summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java21
-rw-r--r--services/java/com/android/server/BackupManagerService.java60
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;
}