Fix #2176803 - restores from userdebug to user builds not working

The underlying issue is that ordinarily, the restore mechanism checks the
signature block of the package which uploaded the restore data against the
signature of the package on-device that will be handling the restore.  This is
to ensure that the restore goes to the "same" application as the one that
uploaded it.

However, applications bundled on the system partition as part of the device
build are signed not with a permanent, app-identifying signature, but rather
with the device's signature block, which is different for each kind of device
and potentially between kinds of build for the same device.  That renders the
stored backup data unusable when changing devices / builds / etc.

This change works around the problem by explicitly privileging applications that
reside on the system partition:  they have been built into the device, and so
are trusted to be able to handle data that is marked as coming from its package
name.

Change-Id: I561011bce2b54cff3e695e82e7544b126b6ac31e
diff --git a/services/java/com/android/server/BackupManagerService.java b/services/java/com/android/server/BackupManagerService.java
index 754e6e5..c3b591e 100644
--- a/services/java/com/android/server/BackupManagerService.java
+++ b/services/java/com/android/server/BackupManagerService.java
@@ -1260,9 +1260,20 @@
 
     // ----- Restore handling -----
 
-    private boolean signaturesMatch(Signature[] storedSigs, Signature[] deviceSigs) {
+    private boolean signaturesMatch(Signature[] storedSigs, PackageInfo target) {
+        // If the target resides on the system partition, we allow it to restore
+        // data from the like-named package in a restore set even if the signatures
+        // do not match.  (Unlike general applications, those flashed to the system
+        // partition will be signed with the device's platform certificate, so on
+        // different phones the same system app will have different signatures.)
+        if ((target.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
+            if (DEBUG) Log.v(TAG, "System app " + target.packageName + " - skipping sig check");
+            return true;
+        }
+
         // Allow unsigned apps, but not signed on one device and unsigned on the other
         // !!! TODO: is this the right policy?
+        Signature[] deviceSigs = target.signatures;
         if (DEBUG) Log.v(TAG, "signaturesMatch(): stored=" + storedSigs
                 + " device=" + deviceSigs);
         if ((storedSigs == null || storedSigs.length == 0)
@@ -1465,7 +1476,7 @@
                         continue;
                     }
 
-                    if (!signaturesMatch(metaInfo.signatures, packageInfo.signatures)) {
+                    if (!signaturesMatch(metaInfo.signatures, packageInfo)) {
                         Log.w(TAG, "Signature mismatch restoring " + packageName);
                         EventLog.writeEvent(RESTORE_AGENT_FAILURE_EVENT, packageName,
                                 "Signature mismatch");