diff options
Diffstat (limited to 'services/java/com/android/server/BackupManagerService.java')
-rw-r--r-- | services/java/com/android/server/BackupManagerService.java | 181 |
1 files changed, 154 insertions, 27 deletions
diff --git a/services/java/com/android/server/BackupManagerService.java b/services/java/com/android/server/BackupManagerService.java index 3aa1239..786f2fa 100644 --- a/services/java/com/android/server/BackupManagerService.java +++ b/services/java/com/android/server/BackupManagerService.java @@ -23,6 +23,7 @@ import android.app.IActivityManager; import android.app.IApplicationThread; import android.app.IBackupAgent; import android.app.PendingIntent; +import android.app.backup.BackupAgent; import android.app.backup.BackupDataOutput; import android.app.backup.FullBackup; import android.app.backup.RestoreSet; @@ -64,6 +65,7 @@ import android.os.SystemClock; import android.os.WorkSource; import android.provider.Settings; import android.util.EventLog; +import android.util.Log; import android.util.Slog; import android.util.SparseArray; import android.util.SparseIntArray; @@ -222,6 +224,7 @@ class BackupManagerService extends IBackupManager.Stub { public PackageInfo pkgInfo; public int pmToken; // in post-install restore, the PM's token for this transaction public boolean needFullBackup; + public String[] filterSet; RestoreParams(IBackupTransport _transport, IRestoreObserver _obs, long _token, PackageInfo _pkg, int _pmToken, boolean _needFullBackup) { @@ -231,6 +234,7 @@ class BackupManagerService extends IBackupManager.Stub { pkgInfo = _pkg; pmToken = _pmToken; needFullBackup = _needFullBackup; + filterSet = null; } RestoreParams(IBackupTransport _transport, IRestoreObserver _obs, long _token, @@ -241,6 +245,18 @@ class BackupManagerService extends IBackupManager.Stub { pkgInfo = null; pmToken = 0; needFullBackup = _needFullBackup; + filterSet = null; + } + + RestoreParams(IBackupTransport _transport, IRestoreObserver _obs, long _token, + String[] _filterSet, boolean _needFullBackup) { + transport = _transport; + observer = _obs; + token = _token; + pkgInfo = null; + pmToken = 0; + needFullBackup = _needFullBackup; + filterSet = _filterSet; } } @@ -402,7 +418,7 @@ class BackupManagerService extends IBackupManager.Stub { Slog.d(TAG, "MSG_RUN_RESTORE observer=" + params.observer); (new PerformRestoreTask(params.transport, params.observer, params.token, params.pkgInfo, params.pmToken, - params.needFullBackup)).run(); + params.needFullBackup, params.filterSet)).run(); break; } @@ -1587,8 +1603,7 @@ class BackupManagerService extends IBackupManager.Stub { // Initiate the target's backup pass prepareOperationTimeout(token, TIMEOUT_BACKUP_INTERVAL); - agent.doBackup(savedState, backupData, newState, false, - token, mBackupManagerBinder); + agent.doBackup(savedState, backupData, newState, token, mBackupManagerBinder); boolean success = waitUntilOperationComplete(token); if (!success) { @@ -1764,30 +1779,31 @@ class BackupManagerService extends IBackupManager.Stub { if (agent != null) { try { ApplicationInfo app = pkg.applicationInfo; - boolean sendApk = mIncludeApks + final boolean sendApk = mIncludeApks && ((app.flags & ApplicationInfo.FLAG_FORWARD_LOCK) == 0) && ((app.flags & ApplicationInfo.FLAG_SYSTEM) == 0 || (app.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0); sendOnBackupPackage(pkg.packageName); - { - BackupDataOutput output = new BackupDataOutput( - mOutputFile.getFileDescriptor()); + BackupDataOutput output = new BackupDataOutput( + mOutputFile.getFileDescriptor()); - if (DEBUG) Slog.d(TAG, "Writing manifest for " + pkg.packageName); - writeAppManifest(pkg, mManifestFile, sendApk); - FullBackup.backupToTar(pkg.packageName, null, null, - mFilesDir.getAbsolutePath(), - mManifestFile.getAbsolutePath(), - output); + if (DEBUG) Slog.d(TAG, "Writing manifest for " + pkg.packageName); + writeAppManifest(pkg, mManifestFile, sendApk); + FullBackup.backupToTar(pkg.packageName, null, null, + mFilesDir.getAbsolutePath(), + mManifestFile.getAbsolutePath(), + output); + + if (sendApk) { + writeApkToBackup(pkg, output); } - if (DEBUG) Slog.d(TAG, "Calling doBackup()"); + if (DEBUG) Slog.d(TAG, "Calling doFullBackup()"); final int token = generateToken(); prepareOperationTimeout(token, TIMEOUT_FULL_BACKUP_INTERVAL); - agent.doBackup(null, mOutputFile, null, sendApk, - token, mBackupManagerBinder); + agent.doFullBackup(mOutputFile, token, mBackupManagerBinder); if (!waitUntilOperationComplete(token)) { Slog.e(TAG, "Full backup failed on package " + pkg.packageName); } else { @@ -1802,6 +1818,29 @@ class BackupManagerService extends IBackupManager.Stub { tearDown(pkg); } + private void writeApkToBackup(PackageInfo pkg, BackupDataOutput output) { + // Forward-locked apps, system-bundled .apks, etc are filtered out before we get here + final String appSourceDir = pkg.applicationInfo.sourceDir; + final String apkDir = new File(appSourceDir).getParent(); + FullBackup.backupToTar(pkg.packageName, FullBackup.APK_TREE_TOKEN, null, + apkDir, appSourceDir, output); + + // Save associated .obb content if it exists and we did save the apk + // check for .obb and save those too + final File obbDir = Environment.getExternalStorageAppObbDirectory(pkg.packageName); + if (obbDir != null) { + if (DEBUG) Log.i(TAG, "obb dir: " + obbDir.getAbsolutePath()); + File[] obbFiles = obbDir.listFiles(); + if (obbFiles != null) { + final String obbDirName = obbDir.getAbsolutePath(); + for (File obb : obbFiles) { + FullBackup.backupToTar(pkg.packageName, FullBackup.OBB_TREE_TOKEN, null, + obbDirName, obb.getAbsolutePath(), output); + } + } + } + } + private void backupSharedStorage() throws RemoteException { PackageInfo pkg = null; try { @@ -1813,7 +1852,7 @@ class BackupManagerService extends IBackupManager.Stub { final int token = generateToken(); prepareOperationTimeout(token, TIMEOUT_SHARED_BACKUP_INTERVAL); - agent.doBackup(null, mOutputFile, null, false, token, mBackupManagerBinder); + agent.doFullBackup(mOutputFile, token, mBackupManagerBinder); if (!waitUntilOperationComplete(token)) { Slog.e(TAG, "Full backup failed on shared storage"); } else { @@ -1933,7 +1972,7 @@ class BackupManagerService extends IBackupManager.Stub { static class FileMetadata { String packageName; // name of the owning app String installerPackageName; // name of the market-type app that installed the owner - int type; // e.g. FullBackup.TYPE_DIRECTORY + int type; // e.g. BackupAgent.TYPE_DIRECTORY String domain; // e.g. FullBackup.DATABASE_TREE_TOKEN String path; // subpath within the semantic domain long mode; // e.g. 0666 (actually int) @@ -2182,15 +2221,15 @@ class BackupManagerService extends IBackupManager.Stub { // If we haven't sent any data to this app yet, we probably // need to clear it first. Check that. if (!mClearedPackages.contains(pkg)) { - // apps with their own full backup agents are + // apps with their own backup agents are // responsible for coherently managing a full // restore. - if (mTargetApp.fullBackupAgentName == null) { + if (mTargetApp.backupAgentName == null) { if (DEBUG) Slog.d(TAG, "Clearing app data preparatory to full restore"); clearApplicationDataSynchronous(pkg); } else { - if (DEBUG) Slog.d(TAG, "full backup agent (" - + mTargetApp.fullBackupAgentName + ") => no clear"); + if (DEBUG) Slog.d(TAG, "backup agent (" + + mTargetApp.backupAgentName + ") => no clear"); } mClearedPackages.add(pkg); } else { @@ -2686,7 +2725,7 @@ class BackupManagerService extends IBackupManager.Stub { StringBuilder b = new StringBuilder(128); // mode string - b.append((info.type == FullBackup.TYPE_DIRECTORY) ? 'd' : '-'); + b.append((info.type == BackupAgent.TYPE_DIRECTORY) ? 'd' : '-'); b.append(((info.mode & 0400) != 0) ? 'r' : '-'); b.append(((info.mode & 0200) != 0) ? 'w' : '-'); b.append(((info.mode & 0100) != 0) ? 'x' : '-'); @@ -2746,9 +2785,9 @@ class BackupManagerService extends IBackupManager.Stub { } switch (typeChar) { - case '0': info.type = FullBackup.TYPE_FILE; break; + case '0': info.type = BackupAgent.TYPE_FILE; break; case '5': { - info.type = FullBackup.TYPE_DIRECTORY; + info.type = BackupAgent.TYPE_DIRECTORY; if (info.size != 0) { Slog.w(TAG, "Directory entry with nonzero size in header"); info.size = 0; @@ -2995,6 +3034,7 @@ class BackupManagerService extends IBackupManager.Stub { private File mStateDir; private int mPmToken; private boolean mNeedFullBackup; + private HashSet<String> mFilterSet; class RestoreRequest { public PackageInfo app; @@ -3008,7 +3048,7 @@ class BackupManagerService extends IBackupManager.Stub { PerformRestoreTask(IBackupTransport transport, IRestoreObserver observer, long restoreSetToken, PackageInfo targetPackage, int pmToken, - boolean needFullBackup) { + boolean needFullBackup, String[] filterSet) { mTransport = transport; mObserver = observer; mToken = restoreSetToken; @@ -3016,6 +3056,15 @@ class BackupManagerService extends IBackupManager.Stub { mPmToken = pmToken; mNeedFullBackup = needFullBackup; + if (filterSet != null) { + mFilterSet = new HashSet<String>(); + for (String pkg : filterSet) { + mFilterSet.add(pkg); + } + } else { + mFilterSet = null; + } + try { mStateDir = new File(mBaseStateDir, transport.transportDirName()); } catch (RemoteException e) { @@ -3027,7 +3076,8 @@ class BackupManagerService extends IBackupManager.Stub { long startRealtime = SystemClock.elapsedRealtime(); if (DEBUG) Slog.v(TAG, "Beginning restore process mTransport=" + mTransport + " mObserver=" + mObserver + " mToken=" + Long.toHexString(mToken) - + " mTargetPackage=" + mTargetPackage + " mPmToken=" + mPmToken); + + " mTargetPackage=" + mTargetPackage + " mFilterSet=" + mFilterSet + + " mPmToken=" + mPmToken); PackageManagerBackupAgent pmAgent = null; int error = -1; // assume error @@ -3046,6 +3096,22 @@ class BackupManagerService extends IBackupManager.Stub { List<PackageInfo> agentPackages = allAgentPackages(); if (mTargetPackage == null) { + // if there's a filter set, strip out anything that isn't + // present before proceeding + if (mFilterSet != null) { + for (int i = agentPackages.size() - 1; i >= 0; i--) { + final PackageInfo pkg = agentPackages.get(i); + if (! mFilterSet.contains(pkg.packageName)) { + agentPackages.remove(i); + } + } + if (DEBUG) { + Slog.i(TAG, "Post-filter package set for restore:"); + for (PackageInfo p : agentPackages) { + Slog.i(TAG, " " + p); + } + } + } restorePackages.addAll(agentPackages); } else { // Just one package to attempt restore of @@ -4241,6 +4307,67 @@ class BackupManagerService extends IBackupManager.Stub { return -1; } + public synchronized int restoreSome(long token, IRestoreObserver observer, + String[] packages) { + mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP, + "performRestore"); + + if (DEBUG) { + StringBuilder b = new StringBuilder(128); + b.append("restoreSome token="); + b.append(Long.toHexString(token)); + b.append(" observer="); + b.append(observer.toString()); + b.append(" packages="); + if (packages == null) { + b.append("null"); + } else { + b.append('{'); + boolean first = true; + for (String s : packages) { + if (!first) { + b.append(", "); + } else first = false; + b.append(s); + } + b.append('}'); + } + Slog.d(TAG, b.toString()); + } + + if (mEnded) { + throw new IllegalStateException("Restore session already ended"); + } + + if (mRestoreTransport == null || mRestoreSets == null) { + Slog.e(TAG, "Ignoring restoreAll() with no restore set"); + return -1; + } + + if (mPackageName != null) { + Slog.e(TAG, "Ignoring restoreAll() on single-package session"); + return -1; + } + + synchronized (mQueueLock) { + for (int i = 0; i < mRestoreSets.length; i++) { + if (token == mRestoreSets[i].token) { + long oldId = Binder.clearCallingIdentity(); + mWakelock.acquire(); + Message msg = mBackupHandler.obtainMessage(MSG_RUN_RESTORE); + msg.obj = new RestoreParams(mRestoreTransport, observer, token, + packages, true); + mBackupHandler.sendMessage(msg); + Binder.restoreCallingIdentity(oldId); + return 0; + } + } + } + + Slog.w(TAG, "Restore token " + Long.toHexString(token) + " not found"); + return -1; + } + public synchronized int restorePackage(String packageName, IRestoreObserver observer) { if (DEBUG) Slog.v(TAG, "restorePackage pkg=" + packageName + " obs=" + observer); |