Backup participants must now hold the BACKUP_DATA permission

Packages that do not use android.permission.BACKUP_DATA will neither be backed
up nor restored.  That permission is currently signature-only.  In the future if
access to the backup/restore infrastructure is made available to arbitrary 3rd
party applications, the permission checks (and indeed, the permission itself)
can simply be removed.
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index cf85af5..d55f188 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1046,6 +1046,13 @@
         android:description="@string/permdesc_backup"
         android:protectionLevel="signatureOrSystem" />
 
+    <!-- Allows an application to participate in the backup and restore process
+         @hide -->
+    <permission android:name="android.permission.BACKUP_DATA"
+        android:label="@string/permlab_backup_data"
+        android:description="@string/permdesc_backup_data"
+        android:protectionLevel="signatureOrSystem" />
+
     <!-- Allows an application to tell the AppWidget service which application
          can access AppWidget's data.  The normal user flow is that a user
          picks an AppWidget to go into a particular host, thereby giving that
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 68f2070..815b767 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -552,6 +552,11 @@
     <string name="permdesc_backup">Allows the application to control the system's backup and restore mechanism.  Not for use by normal applications.</string>
 
     <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permlab_backup_data">back up and restore the application's data</string>
+    <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permdesc_backup_data">Allows the application to participate in the system's backup and restore mechanism.</string>
+
+    <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permlab_internalSystemWindow">display unauthorized windows</string>
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permdesc_internalSystemWindow">Allows the creation of
diff --git a/packages/SettingsProvider/AndroidManifest.xml b/packages/SettingsProvider/AndroidManifest.xml
index d84572b..af0a1bd 100644
--- a/packages/SettingsProvider/AndroidManifest.xml
+++ b/packages/SettingsProvider/AndroidManifest.xml
@@ -2,6 +2,8 @@
         package="com.android.providers.settings"
         android:sharedUserId="android.uid.system">
 
+    <uses-permission android:name="android.permission.BACKUP_DATA" />
+
     <application android:allowClearUserData="false"
                  android:label="@string/app_label"
                  android:process="system"
diff --git a/services/java/com/android/server/BackupManagerService.java b/services/java/com/android/server/BackupManagerService.java
index 36dca7d..4eed7fe 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.ApplicationInfo;
 import android.content.pm.IPackageDataObserver;
 import android.content.pm.PackageInfo;
+import android.content.pm.PermissionInfo;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.PackageManager;
 import android.content.pm.Signature;
@@ -642,9 +643,12 @@
         List<PackageInfo> packages = mPackageManager.getInstalledPackages(flags);
         int N = packages.size();
         for (int a = N-1; a >= 0; a--) {
-            ApplicationInfo app = packages.get(a).applicationInfo;
+            PackageInfo pkg = packages.get(a);
+            ApplicationInfo app = pkg.applicationInfo;
             if (((app.flags&ApplicationInfo.FLAG_ALLOW_BACKUP) == 0)
-                    || app.backupAgentName == null) {
+                    || app.backupAgentName == null
+                    || (mPackageManager.checkPermission(android.Manifest.permission.BACKUP_DATA,
+                            pkg.packageName) != PackageManager.PERMISSION_GRANTED)) {
                 packages.remove(a);
             }
         }
@@ -899,6 +903,15 @@
             for (BackupRequest request : mQueue) {
                 Log.d(TAG, "starting agent for backup of " + request);
 
+                // Don't run backup, even if requested, if the target app does not have
+                // the requisite permission
+                if (mPackageManager.checkPermission(android.Manifest.permission.BACKUP_DATA,
+                        request.appInfo.packageName) != PackageManager.PERMISSION_GRANTED) {
+                    Log.w(TAG, "Skipping backup of unprivileged package "
+                            + request.appInfo.packageName);
+                    continue;
+                }
+
                 IBackupAgent agent = null;
                 int mode = (request.fullBackup)
                         ? IApplicationThread.BACKUP_MODE_FULL
@@ -1287,6 +1300,12 @@
 
             if (DEBUG) Log.d(TAG, "processOneRestore packageName=" + packageName);
 
+            // Don't restore to unprivileged packages
+            if (mPackageManager.checkPermission(android.Manifest.permission.BACKUP_DATA,
+                    packageName) != PackageManager.PERMISSION_GRANTED) {
+                Log.d(TAG, "Skipping restore of unprivileged package " + packageName);
+            }
+
             // !!! TODO: get the dirs from the transport
             File backupDataName = new File(mDataDir, packageName + ".restore");
             File newStateName = new File(mStateDir, packageName + ".new");
diff --git a/tests/backup/AndroidManifest.xml b/tests/backup/AndroidManifest.xml
index 3778742..d992627 100644
--- a/tests/backup/AndroidManifest.xml
+++ b/tests/backup/AndroidManifest.xml
@@ -1,5 +1,6 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
         package="com.android.backuptest">
+    <uses-permission android:name="android.permission.BACKUP_DATA" />
     <application android:backupAgent="BackupTestAgent">
         <activity android:name="BackupTestActivity" android:label="_BackupTest">
             <intent-filter>