diff options
-rw-r--r-- | cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java | 21 | ||||
-rw-r--r-- | services/java/com/android/server/BackupManagerService.java | 60 |
2 files changed, 78 insertions, 3 deletions
diff --git a/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java b/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java index 3af80fa..841e3df 100644 --- a/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java +++ b/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java @@ -80,6 +80,14 @@ public final class Bmgr { doRestore(); return; } + + if ("transport".equals(op)) { + doTransport(); + return; + } + + System.err.println("Unknown command"); + showUsage(); } private void doRun() { @@ -113,6 +121,19 @@ public final class Bmgr { } } + private void doTransport() { + try { + int which = Integer.parseInt(nextArg()); + int old = mBmgr.selectBackupTransport(which); + System.out.println("Selected transport " + which + " (formerly " + old + ")"); + } catch (NumberFormatException e) { + showUsage(); + } catch (RemoteException e) { + System.err.println(e.toString()); + System.err.println(BMGR_NOT_RUNNING_ERR); + } + } + private void doList() { String arg = nextArg(); // sets, transports, packages set# if ("transports".equals(arg)) { diff --git a/services/java/com/android/server/BackupManagerService.java b/services/java/com/android/server/BackupManagerService.java index f9a6f5b..6ee8260 100644 --- a/services/java/com/android/server/BackupManagerService.java +++ b/services/java/com/android/server/BackupManagerService.java @@ -31,6 +31,7 @@ import android.content.pm.IPackageDataObserver; import android.content.pm.PackageInfo; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.PackageManager; +import android.content.pm.Signature; import android.net.Uri; import android.os.Binder; import android.os.Bundle; @@ -153,7 +154,9 @@ class BackupManagerService extends IBackupManager.Stub { mJournalDir.mkdirs(); makeJournalLocked(); // okay because no other threads are running yet - // Build our mapping of uid to backup client services + // Build our mapping of uid to backup client services. This implicitly + // schedules a backup pass on the Package Manager metadata the first + // time anything needs to be backed up. synchronized (mBackupParticipants) { addPackageParticipantsLocked(null); } @@ -656,8 +659,15 @@ class BackupManagerService extends IBackupManager.Stub { // Look up the package info & signatures. This is first so that if it // throws an exception, there's no file setup yet that would need to // be unraveled. - PackageInfo packInfo = mPackageManager.getPackageInfo(packageName, + PackageInfo packInfo; + if (packageName.equals(PACKAGE_MANAGER_SENTINEL)) { + // The metadata 'package' is synthetic + packInfo = new PackageInfo(); + packInfo.packageName = packageName; + } else { + packInfo = mPackageManager.getPackageInfo(packageName, PackageManager.GET_SIGNATURES); + } // !!! TODO: get the state file dir from the transport File savedStateName = new File(mStateDir, packageName); @@ -745,6 +755,28 @@ class BackupManagerService extends IBackupManager.Stub { return null; } + private boolean signaturesMatch(Signature[] storedSigs, Signature[] deviceSigs) { + // !!! TODO: this demands that every stored signature match one + // that is present on device, and does not demand the converse. + // Is this this right policy? + int nStored = storedSigs.length; + int nDevice = deviceSigs.length; + + for (int i=0; i < nStored; i++) { + boolean match = false; + for (int j=0; j < nDevice; j++) { + if (storedSigs[i].equals(deviceSigs[j])) { + match = true; + break; + } + } + if (!match) { + return false; + } + } + return true; + } + class PerformRestoreThread extends Thread { private IBackupTransport mTransport; private int mToken; @@ -791,6 +823,13 @@ class BackupManagerService extends IBackupManager.Stub { // !!! TODO: pick out the set for this token mImage = images[0]; + // Pull the Package Manager metadata from the restore set first + PackageManagerBackupAgent pmAgent = new PackageManagerBackupAgent( + mPackageManager, allAgentApps()); + PackageInfo pmApp = new PackageInfo(); + pmApp.packageName = PACKAGE_MANAGER_SENTINEL; + processOneRestore(pmApp, IBackupAgent.Stub.asInterface(pmAgent.onBind())); + // build the set of apps we will attempt to restore PackageInfo[] packages = mTransport.getAppSet(mImage.token); HashSet<PackageInfo> appsToRestore = new HashSet<PackageInfo>(); @@ -798,7 +837,20 @@ class BackupManagerService extends IBackupManager.Stub { // get the real PackageManager idea of the package PackageInfo app = isRestorable(pkg); if (app != null) { - appsToRestore.add(app); + // Validate against the backed-up signature block, too + Signature[] storedSigs + = pmAgent.getRestoredSignatures(app.packageName); + if (storedSigs != null) { + // !!! TODO: check app version here as well + if (signaturesMatch(storedSigs, app.signatures)) { + appsToRestore.add(app); + } else { + Log.w(TAG, "Sig mismatch on restore of " + app.packageName); + } + } else { + Log.i(TAG, "No stored sigs for " + app.packageName + + " so not restoring"); + } } } @@ -1002,6 +1054,7 @@ class BackupManagerService extends IBackupManager.Stub { // Report the currently active transport public int getCurrentTransport() { mContext.enforceCallingPermission("android.permission.BACKUP", "selectBackupTransport"); + Log.v(TAG, "getCurrentTransport() returning " + mTransportId); return mTransportId; } @@ -1011,6 +1064,7 @@ class BackupManagerService extends IBackupManager.Stub { int prevTransport = mTransportId; mTransportId = transportId; + Log.v(TAG, "selectBackupTransport() set " + mTransportId + " returning " + prevTransport); return prevTransport; } |