diff options
-rw-r--r-- | Android.mk | 1 | ||||
-rw-r--r-- | cmds/bu/src/com/android/commands/bu/Backup.java | 28 | ||||
-rw-r--r-- | core/java/android/app/backup/BackupAgent.java | 1 | ||||
-rw-r--r-- | core/java/android/app/backup/FullBackup.java | 2 | ||||
-rw-r--r-- | core/java/android/app/backup/IBackupManager.aidl | 7 | ||||
-rw-r--r-- | core/java/com/android/internal/backup/IObbBackupService.aidl | 45 | ||||
-rw-r--r-- | libs/androidfw/BackupHelpers.cpp | 2 | ||||
-rw-r--r-- | packages/SharedStorageBackup/AndroidManifest.xml | 7 | ||||
-rw-r--r-- | packages/SharedStorageBackup/proguard.flags | 1 | ||||
-rw-r--r-- | packages/SharedStorageBackup/src/com/android/sharedstoragebackup/ObbBackupService.java | 151 | ||||
-rw-r--r-- | services/java/com/android/server/BackupManagerService.java | 235 |
11 files changed, 417 insertions, 63 deletions
@@ -180,6 +180,7 @@ LOCAL_SRC_FILES += \ core/java/com/android/internal/appwidget/IAppWidgetService.aidl \ core/java/com/android/internal/appwidget/IAppWidgetHost.aidl \ core/java/com/android/internal/backup/IBackupTransport.aidl \ + core/java/com/android/internal/backup/IObbBackupService.aidl \ core/java/com/android/internal/policy/IFaceLockCallback.aidl \ core/java/com/android/internal/policy/IFaceLockInterface.aidl \ core/java/com/android/internal/os/IDropBoxManagerService.aidl \ diff --git a/cmds/bu/src/com/android/commands/bu/Backup.java b/cmds/bu/src/com/android/commands/bu/Backup.java index 046ccca..73fd660 100644 --- a/cmds/bu/src/com/android/commands/bu/Backup.java +++ b/cmds/bu/src/com/android/commands/bu/Backup.java @@ -22,6 +22,7 @@ import android.os.RemoteException; import android.os.ServiceManager; import android.util.Log; +import java.io.IOException; import java.util.ArrayList; public final class Backup { @@ -64,6 +65,7 @@ public final class Backup { private void doFullBackup(int socketFd) { ArrayList<String> packages = new ArrayList<String>(); boolean saveApks = false; + boolean saveObbs = false; boolean saveShared = false; boolean doEverything = false; boolean allIncludesSystem = true; @@ -75,6 +77,10 @@ public final class Backup { saveApks = true; } else if ("-noapk".equals(arg)) { saveApks = false; + } else if ("-obb".equals(arg)) { + saveObbs = true; + } else if ("-noobb".equals(arg)) { + saveObbs = false; } else if ("-shared".equals(arg)) { saveShared = true; } else if ("-noshared".equals(arg)) { @@ -104,23 +110,37 @@ public final class Backup { return; } + ParcelFileDescriptor fd = null; try { - ParcelFileDescriptor fd = ParcelFileDescriptor.adoptFd(socketFd); + fd = ParcelFileDescriptor.adoptFd(socketFd); String[] packArray = new String[packages.size()]; - mBackupManager.fullBackup(fd, saveApks, saveShared, doEverything, allIncludesSystem, - packages.toArray(packArray)); + mBackupManager.fullBackup(fd, saveApks, saveObbs, saveShared, doEverything, + allIncludesSystem, packages.toArray(packArray)); } catch (RemoteException e) { Log.e(TAG, "Unable to invoke backup manager for backup"); + } finally { + if (fd != null) { + try { + fd.close(); + } catch (IOException e) {} + } } } private void doFullRestore(int socketFd) { // No arguments to restore + ParcelFileDescriptor fd = null; try { - ParcelFileDescriptor fd = ParcelFileDescriptor.adoptFd(socketFd); + fd = ParcelFileDescriptor.adoptFd(socketFd); mBackupManager.fullRestore(fd); } catch (RemoteException e) { Log.e(TAG, "Unable to invoke backup manager for restore"); + } finally { + if (fd != null) { + try { + fd.close(); + } catch (IOException e) {} + } } } diff --git a/core/java/android/app/backup/BackupAgent.java b/core/java/android/app/backup/BackupAgent.java index 44aa06f..3425765 100644 --- a/core/java/android/app/backup/BackupAgent.java +++ b/core/java/android/app/backup/BackupAgent.java @@ -472,6 +472,7 @@ public abstract class BackupAgent extends ContextWrapper { File efLocation = getExternalFilesDir(null); if (efLocation != null) { basePath = getExternalFilesDir(null).getCanonicalPath(); + mode = -1; // < 0 is a token to skip attempting a chmod() } } } else { diff --git a/core/java/android/app/backup/FullBackup.java b/core/java/android/app/backup/FullBackup.java index 2fe08f3..cb0737e 100644 --- a/core/java/android/app/backup/FullBackup.java +++ b/core/java/android/app/backup/FullBackup.java @@ -89,7 +89,7 @@ public class FullBackup { * last modification time of the output file. if the {@code mode} parameter is * negative then this parameter will be ignored. * @param outFile Location within the filesystem to place the data. This must point - * to a location that is writeable by the caller, prefereably using an absolute path. + * to a location that is writeable by the caller, preferably using an absolute path. * @throws IOException */ static public void restoreFile(ParcelFileDescriptor data, diff --git a/core/java/android/app/backup/IBackupManager.aidl b/core/java/android/app/backup/IBackupManager.aidl index acdd0b5..bb4f5f1 100644 --- a/core/java/android/app/backup/IBackupManager.aidl +++ b/core/java/android/app/backup/IBackupManager.aidl @@ -152,6 +152,8 @@ interface IBackupManager { * @param fd The file descriptor to which a 'tar' file stream is to be written * @param includeApks If <code>true</code>, the resulting tar stream will include the * application .apk files themselves as well as their data. + * @param includeObbs If <code>true</code>, the resulting tar stream will include any + * application expansion (OBB) files themselves belonging to each application. * @param includeShared If <code>true</code>, the resulting tar stream will include * the contents of the device's shared storage (SD card or equivalent). * @param allApps If <code>true</code>, the resulting tar stream will include all @@ -164,8 +166,9 @@ interface IBackupManager { * @param packageNames The package names of the apps whose data (and optionally .apk files) * are to be backed up. The <code>allApps</code> parameter supersedes this. */ - void fullBackup(in ParcelFileDescriptor fd, boolean includeApks, boolean includeShared, - boolean allApps, boolean allIncludesSystem, in String[] packageNames); + void fullBackup(in ParcelFileDescriptor fd, boolean includeApks, boolean includeObbs, + boolean includeShared, boolean allApps, boolean allIncludesSystem, + in String[] packageNames); /** * Restore device content from the data stream passed through the given socket. The diff --git a/core/java/com/android/internal/backup/IObbBackupService.aidl b/core/java/com/android/internal/backup/IObbBackupService.aidl new file mode 100644 index 0000000..426dbc4 --- /dev/null +++ b/core/java/com/android/internal/backup/IObbBackupService.aidl @@ -0,0 +1,45 @@ +/* + * Copyright 2013, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.internal.backup; + +import android.app.backup.IBackupManager; +import android.os.ParcelFileDescriptor; + +/** + * Interface for the Backup Manager Service to communicate with a helper service that + * handles local (whole-file) backup & restore of OBB content on behalf of applications. + * This can't be done within the Backup Manager Service itself because of the restrictions + * on system-user access to external storage, and can't be left to the apps because even + * apps that do not have permission to access external storage in the usual way can still + * use OBBs. + * + * {@hide} + */ +oneway interface IObbBackupService { + /* + * Back up a package's OBB directory tree + */ + void backupObbs(in String packageName, in ParcelFileDescriptor data, + int token, in IBackupManager callbackBinder); + + /* + * Restore an OBB file for the given package from the incoming stream + */ + void restoreObbFile(in String pkgName, in ParcelFileDescriptor data, + long fileSize, int type, in String path, long mode, long mtime, + int token, in IBackupManager callbackBinder); +} diff --git a/libs/androidfw/BackupHelpers.cpp b/libs/androidfw/BackupHelpers.cpp index dcf41b7..b8d3f48 100644 --- a/libs/androidfw/BackupHelpers.cpp +++ b/libs/androidfw/BackupHelpers.cpp @@ -553,7 +553,7 @@ int write_tarfile(const String8& packageName, const String8& domain, if (buf == NULL) { ALOGE("Out of mem allocating transfer buffer"); err = ENOMEM; - goto cleanup; + goto done; } // Magic fields for the ustar file format diff --git a/packages/SharedStorageBackup/AndroidManifest.xml b/packages/SharedStorageBackup/AndroidManifest.xml index fc21df3..b8df88e 100644 --- a/packages/SharedStorageBackup/AndroidManifest.xml +++ b/packages/SharedStorageBackup/AndroidManifest.xml @@ -24,5 +24,12 @@ <application android:allowClearUserData="false" android:permission="android.permission.CONFIRM_FULL_BACKUP" android:backupAgent="SharedStorageAgent" > + + <service android:name=".ObbBackupService" + android:enabled="true" + android:exported="true"> + </service> + </application> + </manifest> diff --git a/packages/SharedStorageBackup/proguard.flags b/packages/SharedStorageBackup/proguard.flags index f43cb81..6a66a47 100644 --- a/packages/SharedStorageBackup/proguard.flags +++ b/packages/SharedStorageBackup/proguard.flags @@ -1 +1,2 @@ -keep class com.android.sharedstoragebackup.SharedStorageAgent +-keep class com.android.sharedstoragebackup.ObbBackupService diff --git a/packages/SharedStorageBackup/src/com/android/sharedstoragebackup/ObbBackupService.java b/packages/SharedStorageBackup/src/com/android/sharedstoragebackup/ObbBackupService.java new file mode 100644 index 0000000..7ebe096 --- /dev/null +++ b/packages/SharedStorageBackup/src/com/android/sharedstoragebackup/ObbBackupService.java @@ -0,0 +1,151 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.sharedstoragebackup; + +import android.app.Service; +import android.app.backup.BackupDataOutput; +import android.app.backup.FullBackup; +import android.app.backup.IBackupManager; +import android.content.Intent; +import android.os.Environment; +import android.os.IBinder; +import android.os.ParcelFileDescriptor; +import android.os.RemoteException; +import android.util.Log; + +import java.io.File; +import java.io.FileDescriptor; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.ArrayList; + +import com.android.internal.backup.IObbBackupService; + +/** + * Service that the Backup Manager Services delegates OBB backup/restore operations to, + * because those require accessing external storage. + * + * {@hide} + */ +public class ObbBackupService extends Service { + static final String TAG = "ObbBackupService"; + static final boolean DEBUG = true; + + /** + * IObbBackupService interface implementation + */ + IObbBackupService mService = new IObbBackupService.Stub() { + /* + * Back up a package's OBB directory tree + */ + @Override + public void backupObbs(String packageName, ParcelFileDescriptor data, + int token, IBackupManager callbackBinder) { + final FileDescriptor outFd = data.getFileDescriptor(); + try { + File obbDir = Environment.getExternalStorageAppObbDirectory(packageName); + if (obbDir != null) { + if (obbDir.exists()) { + ArrayList<File> obbList = allFileContents(obbDir); + if (obbList != null) { + // okay, there's at least something there + if (DEBUG) { + Log.i(TAG, obbList.size() + " files to back up"); + } + final String rootPath = obbDir.getCanonicalPath(); + final BackupDataOutput out = new BackupDataOutput(outFd); + for (File f : obbList) { + final String filePath = f.getCanonicalPath(); + if (DEBUG) { + Log.i(TAG, "storing: " + filePath); + } + FullBackup.backupToTar(packageName, FullBackup.OBB_TREE_TOKEN, null, + rootPath, filePath, out); + } + } + } + } + } catch (IOException e) { + Log.w(TAG, "Exception backing up OBBs for " + packageName, e); + } finally { + // Send the EOD marker indicating that there is no more data + try { + FileOutputStream out = new FileOutputStream(outFd); + byte[] buf = new byte[4]; + out.write(buf); + } catch (IOException e) { + Log.e(TAG, "Unable to finalize obb backup stream!"); + } + + try { + callbackBinder.opComplete(token); + } catch (RemoteException e) { + } + } + } + + /* + * Restore an OBB file for the given package from the incoming stream + */ + @Override + public void restoreObbFile(String packageName, ParcelFileDescriptor data, + long fileSize, int type, String path, long mode, long mtime, + int token, IBackupManager callbackBinder) { + try { + File outFile = Environment.getExternalStorageAppObbDirectory(packageName); + if (outFile != null) { + outFile = new File(outFile, path); + } + // outFile is null here if we couldn't get access to external storage, + // in which case restoreFile() will discard the data cleanly and let + // us proceed with the next file segment in the stream. We pass -1 + // for the file mode to suppress attempts to chmod() on shared storage. + FullBackup.restoreFile(data, fileSize, type, -1, mtime, outFile); + } catch (IOException e) { + Log.i(TAG, "Exception restoring OBB " + path, e); + } finally { + try { + callbackBinder.opComplete(token); + } catch (RemoteException e) { + } + } + } + + ArrayList<File> allFileContents(File rootDir) { + final ArrayList<File> files = new ArrayList<File>(); + final ArrayList<File> dirs = new ArrayList<File>(); + + dirs.add(rootDir); + while (!dirs.isEmpty()) { + File dir = dirs.remove(0); + File[] contents = dir.listFiles(); + if (contents != null) { + for (File f : contents) { + if (f.isDirectory()) dirs.add(f); + else if (f.isFile()) files.add(f); + } + } + } + return files; + } + }; + + @Override + public IBinder onBind(Intent intent) { + return mService.asBinder(); + } +} diff --git a/services/java/com/android/server/BackupManagerService.java b/services/java/com/android/server/BackupManagerService.java index 401a25f..328b503 100644 --- a/services/java/com/android/server/BackupManagerService.java +++ b/services/java/com/android/server/BackupManagerService.java @@ -78,6 +78,7 @@ import android.util.StringBuilderPrinter; import com.android.internal.backup.BackupConstants; import com.android.internal.backup.IBackupTransport; +import com.android.internal.backup.IObbBackupService; import com.android.internal.backup.LocalTransport; import com.android.server.PackageManagerBackupAgent.Metadata; @@ -363,15 +364,17 @@ class BackupManagerService extends IBackupManager.Stub { class FullBackupParams extends FullParams { public boolean includeApks; + public boolean includeObbs; public boolean includeShared; public boolean allApps; public boolean includeSystem; public String[] packages; - FullBackupParams(ParcelFileDescriptor output, boolean saveApks, boolean saveShared, - boolean doAllApps, boolean doSystem, String[] pkgList) { + FullBackupParams(ParcelFileDescriptor output, boolean saveApks, boolean saveObbs, + boolean saveShared, boolean doAllApps, boolean doSystem, String[] pkgList) { fd = output; includeApks = saveApks; + includeObbs = saveObbs; includeShared = saveShared; allApps = doAllApps; includeSystem = doSystem; @@ -550,7 +553,7 @@ class BackupManagerService extends IBackupManager.Stub { // similar to normal backup/restore. FullBackupParams params = (FullBackupParams)msg.obj; PerformFullBackupTask task = new PerformFullBackupTask(params.fd, - params.observer, params.includeApks, + params.observer, params.includeApks, params.includeObbs, params.includeShared, params.curPassword, params.encryptPassword, params.allApps, params.includeSystem, params.packages, params.latch); (new Thread(task)).start(); @@ -2306,13 +2309,132 @@ class BackupManagerService extends IBackupManager.Stub { } - // ----- Full backup to a file/socket ----- + // ----- Full backup/restore to a file/socket ----- - class PerformFullBackupTask implements Runnable { + abstract class ObbServiceClient { + public IObbBackupService mObbService; + public void setObbBinder(IObbBackupService binder) { + mObbService = binder; + } + } + + class FullBackupObbConnection implements ServiceConnection { + volatile IObbBackupService mService; + + FullBackupObbConnection() { + mService = null; + } + + public void establish() { + if (DEBUG) Slog.i(TAG, "Initiating bind of OBB service on " + this); + Intent obbIntent = new Intent().setComponent(new ComponentName( + "com.android.sharedstoragebackup", + "com.android.sharedstoragebackup.ObbBackupService")); + BackupManagerService.this.mContext.bindService( + obbIntent, this, Context.BIND_AUTO_CREATE); + } + + public void tearDown() { + BackupManagerService.this.mContext.unbindService(this); + } + + public boolean backupObbs(PackageInfo pkg, OutputStream out) { + boolean success = false; + waitForConnection(); + + ParcelFileDescriptor[] pipes = null; + try { + pipes = ParcelFileDescriptor.createPipe(); + int token = generateToken(); + prepareOperationTimeout(token, TIMEOUT_FULL_BACKUP_INTERVAL, null); + mService.backupObbs(pkg.packageName, pipes[1], token, mBackupManagerBinder); + routeSocketDataToOutput(pipes[0], out); + success = waitUntilOperationComplete(token); + } catch (Exception e) { + Slog.w(TAG, "Unable to back up OBBs for " + pkg, e); + } finally { + try { + out.flush(); + if (pipes != null) { + if (pipes[0] != null) pipes[0].close(); + if (pipes[1] != null) pipes[1].close(); + } + } catch (IOException e) { + Slog.w(TAG, "I/O error closing down OBB backup", e); + } + } + return success; + } + + public void restoreObbFile(String pkgName, ParcelFileDescriptor data, + long fileSize, int type, String path, long mode, long mtime, + int token, IBackupManager callbackBinder) { + waitForConnection(); + + try { + mService.restoreObbFile(pkgName, data, fileSize, type, path, mode, mtime, + token, callbackBinder); + } catch (Exception e) { + Slog.w(TAG, "Unable to restore OBBs for " + pkgName, e); + } + } + + private void waitForConnection() { + synchronized (this) { + while (mService == null) { + if (DEBUG) Slog.i(TAG, "...waiting for OBB service binding..."); + try { + this.wait(); + } catch (InterruptedException e) { /* never interrupted */ } + } + if (DEBUG) Slog.i(TAG, "Connected to OBB service; continuing"); + } + } + + @Override + public void onServiceConnected(ComponentName name, IBinder service) { + synchronized (this) { + mService = IObbBackupService.Stub.asInterface(service); + if (DEBUG) Slog.i(TAG, "OBB service connection " + mService + + " connected on " + this); + this.notifyAll(); + } + } + + @Override + public void onServiceDisconnected(ComponentName name) { + synchronized (this) { + mService = null; + if (DEBUG) Slog.i(TAG, "OBB service connection disconnected on " + this); + this.notifyAll(); + } + } + + } + + private void routeSocketDataToOutput(ParcelFileDescriptor inPipe, OutputStream out) + throws IOException { + FileInputStream raw = new FileInputStream(inPipe.getFileDescriptor()); + DataInputStream in = new DataInputStream(raw); + + byte[] buffer = new byte[32 * 1024]; + int chunkTotal; + while ((chunkTotal = in.readInt()) > 0) { + while (chunkTotal > 0) { + int toRead = (chunkTotal > buffer.length) ? buffer.length : chunkTotal; + int nRead = in.read(buffer, 0, toRead); + out.write(buffer, 0, nRead); + chunkTotal -= nRead; + } + } + } + + class PerformFullBackupTask extends ObbServiceClient implements Runnable { ParcelFileDescriptor mOutputFile; DeflaterOutputStream mDeflater; IFullBackupRestoreObserver mObserver; boolean mIncludeApks; + boolean mIncludeObbs; boolean mIncludeShared; boolean mAllApps; final boolean mIncludeSystem; @@ -2322,6 +2444,7 @@ class BackupManagerService extends IBackupManager.Stub { AtomicBoolean mLatchObject; File mFilesDir; File mManifestFile; + class FullBackupRunner implements Runnable { PackageInfo mPackage; @@ -2377,12 +2500,13 @@ class BackupManagerService extends IBackupManager.Stub { } PerformFullBackupTask(ParcelFileDescriptor fd, IFullBackupRestoreObserver observer, - boolean includeApks, boolean includeShared, String curPassword, - String encryptPassword, boolean doAllApps, boolean doSystem, String[] packages, - AtomicBoolean latch) { + boolean includeApks, boolean includeObbs, boolean includeShared, + String curPassword, String encryptPassword, boolean doAllApps, + boolean doSystem, String[] packages, AtomicBoolean latch) { mOutputFile = fd; mObserver = observer; mIncludeApks = includeApks; + mIncludeObbs = includeObbs; mIncludeShared = includeShared; mAllApps = doAllApps; mIncludeSystem = doSystem; @@ -2405,9 +2529,12 @@ class BackupManagerService extends IBackupManager.Stub { @Override public void run() { + Slog.i(TAG, "--- Performing full-dataset backup ---"); + List<PackageInfo> packagesToBackup = new ArrayList<PackageInfo>(); + FullBackupObbConnection obbConnection = new FullBackupObbConnection(); + obbConnection.establish(); // we'll want this later - Slog.i(TAG, "--- Performing full-dataset backup ---"); sendStartBackup(); // doAllApps supersedes the package set if any @@ -2557,6 +2684,15 @@ class BackupManagerService extends IBackupManager.Stub { for (int i = 0; i < N; i++) { pkg = packagesToBackup.get(i); backupOnePackage(pkg, out); + + // after the app's agent runs to handle its private filesystem + // contents, back up any OBB content it has on its behalf. + if (mIncludeObbs) { + boolean obbOkay = obbConnection.backupObbs(pkg, out); + if (!obbOkay) { + throw new RuntimeException("Failure writing OBB stack for " + pkg); + } + } } // Done! @@ -2581,6 +2717,7 @@ class BackupManagerService extends IBackupManager.Stub { mLatchObject.notifyAll(); } sendEndBackup(); + obbConnection.tearDown(); if (DEBUG) Slog.d(TAG, "Full backup pass complete."); mWakelock.release(); } @@ -2688,20 +2825,7 @@ class BackupManagerService extends IBackupManager.Stub { // Now pull data from the app and stuff it into the compressor try { - FileInputStream raw = new FileInputStream(pipes[0].getFileDescriptor()); - DataInputStream in = new DataInputStream(raw); - - byte[] buffer = new byte[16 * 1024]; - int chunkTotal; - while ((chunkTotal = in.readInt()) > 0) { - while (chunkTotal > 0) { - int toRead = (chunkTotal > buffer.length) - ? buffer.length : chunkTotal; - int nRead = in.read(buffer, 0, toRead); - out.write(buffer, 0, nRead); - chunkTotal -= nRead; - } - } + routeSocketDataToOutput(pipes[0], out); } catch (IOException e) { Slog.i(TAG, "Caught exception reading from agent", e); } @@ -2900,7 +3024,7 @@ class BackupManagerService extends IBackupManager.Stub { ACCEPT_IF_APK } - class PerformFullRestoreTask implements Runnable { + class PerformFullRestoreTask extends ObbServiceClient implements Runnable { ParcelFileDescriptor mInputFile; String mCurrentPassword; String mDecryptPassword; @@ -2909,6 +3033,7 @@ class BackupManagerService extends IBackupManager.Stub { IBackupAgent mAgent; String mAgentPackage; ApplicationInfo mTargetApp; + FullBackupObbConnection mObbConnection = null; ParcelFileDescriptor[] mPipes = null; long mBytes; @@ -2937,6 +3062,7 @@ class BackupManagerService extends IBackupManager.Stub { mAgent = null; mAgentPackage = null; mTargetApp = null; + mObbConnection = new FullBackupObbConnection(); // Which packages we've already wiped data on. We prepopulate this // with a whitelist of packages known to be unclearable. @@ -2980,6 +3106,7 @@ class BackupManagerService extends IBackupManager.Stub { @Override public void run() { Slog.i(TAG, "--- Performing full-dataset restore ---"); + mObbConnection.establish(); sendStartRestore(); // Are we able to restore shared-storage data? @@ -3067,6 +3194,7 @@ class BackupManagerService extends IBackupManager.Stub { mLatchObject.set(true); mLatchObject.notifyAll(); } + mObbConnection.tearDown(); sendEndRestore(); Slog.d(TAG, "Full restore pass complete."); mWakelock.release(); @@ -3319,22 +3447,30 @@ class BackupManagerService extends IBackupManager.Stub { long toCopy = info.size; final int token = generateToken(); try { - if (DEBUG) Slog.d(TAG, "Invoking agent to restore file " - + info.path); prepareOperationTimeout(token, TIMEOUT_FULL_BACKUP_INTERVAL, null); - // fire up the app's agent listening on the socket. If - // the agent is running in the system process we can't - // just invoke it asynchronously, so we provide a thread - // for it here. - if (mTargetApp.processName.equals("system")) { - Slog.d(TAG, "system process agent - spinning a thread"); - RestoreFileRunnable runner = new RestoreFileRunnable( - mAgent, info, mPipes[0], token); - new Thread(runner).start(); + if (info.domain.equals(FullBackup.OBB_TREE_TOKEN)) { + if (DEBUG) Slog.d(TAG, "Restoring OBB file for " + pkg + + " : " + info.path); + mObbConnection.restoreObbFile(pkg, mPipes[0], + info.size, info.type, info.path, info.mode, + info.mtime, token, mBackupManagerBinder); } else { - mAgent.doRestoreFile(mPipes[0], info.size, info.type, - info.domain, info.path, info.mode, info.mtime, - token, mBackupManagerBinder); + if (DEBUG) Slog.d(TAG, "Invoking agent to restore file " + + info.path); + // fire up the app's agent listening on the socket. If + // the agent is running in the system process we can't + // just invoke it asynchronously, so we provide a thread + // for it here. + if (mTargetApp.processName.equals("system")) { + Slog.d(TAG, "system process agent - spinning a thread"); + RestoreFileRunnable runner = new RestoreFileRunnable( + mAgent, info, mPipes[0], token); + new Thread(runner).start(); + } else { + mAgent.doRestoreFile(mPipes[0], info.size, info.type, + info.domain, info.path, info.mode, info.mtime, + token, mBackupManagerBinder); + } } } catch (IOException e) { // couldn't dup the socket for a process-local restore @@ -3342,7 +3478,7 @@ class BackupManagerService extends IBackupManager.Stub { agentSuccess = false; okay = false; } catch (RemoteException e) { - // whoops, remote agent went away. We'll eat the content + // whoops, remote entity went away. We'll eat the content // ourselves, then, and not copy it over. Slog.e(TAG, "Agent crashed during full restore"); agentSuccess = false; @@ -3891,18 +4027,6 @@ class BackupManagerService extends IBackupManager.Stub { slash = info.path.indexOf('/'); if (slash < 0) throw new IOException("Illegal semantic path in non-manifest " + info.path); info.domain = info.path.substring(0, slash); - // validate that it's one of the domains we understand - if (!info.domain.equals(FullBackup.APK_TREE_TOKEN) - && !info.domain.equals(FullBackup.DATA_TREE_TOKEN) - && !info.domain.equals(FullBackup.DATABASE_TREE_TOKEN) - && !info.domain.equals(FullBackup.ROOT_TREE_TOKEN) - && !info.domain.equals(FullBackup.SHAREDPREFS_TREE_TOKEN) - && !info.domain.equals(FullBackup.MANAGED_EXTERNAL_TREE_TOKEN) - && !info.domain.equals(FullBackup.OBB_TREE_TOKEN) - && !info.domain.equals(FullBackup.CACHE_TREE_TOKEN)) { - throw new IOException("Unrecognized domain " + info.domain); - } - info.path = info.path.substring(slash + 1); } } @@ -4989,7 +5113,8 @@ class BackupManagerService extends IBackupManager.Stub { // Run a *full* backup pass for the given package, writing the resulting data stream // to the supplied file descriptor. This method is synchronous and does not return // to the caller until the backup has been completed. - public void fullBackup(ParcelFileDescriptor fd, boolean includeApks, boolean includeShared, + public void fullBackup(ParcelFileDescriptor fd, boolean includeApks, + boolean includeObbs, boolean includeShared, boolean doAllApps, boolean includeSystem, String[] pkgList) { mContext.enforceCallingPermission(android.Manifest.permission.BACKUP, "fullBackup"); @@ -5020,12 +5145,12 @@ class BackupManagerService extends IBackupManager.Stub { } if (DEBUG) Slog.v(TAG, "Requesting full backup: apks=" + includeApks - + " shared=" + includeShared + " all=" + doAllApps + + " obb=" + includeObbs + " shared=" + includeShared + " all=" + doAllApps + " pkgs=" + pkgList); Slog.i(TAG, "Beginning full backup..."); - FullBackupParams params = new FullBackupParams(fd, includeApks, includeShared, - doAllApps, includeSystem, pkgList); + FullBackupParams params = new FullBackupParams(fd, includeApks, includeObbs, + includeShared, doAllApps, includeSystem, pkgList); final int token = generateToken(); synchronized (mFullConfirmations) { mFullConfirmations.put(token, params); |