+
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 2e405c107cffc..8773f59de1001 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -247,6 +247,19 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
*/
public static final int FLAG_NATIVE_DEBUGGABLE = 1<<21;
+ /**
+ * Value for {@link #flags}: Set to true if the application's backup
+ * agent claims to be able to handle restore data even "from the future,"
+ * i.e. from versions of the application with a versionCode greater than
+ * the one currently installed on the device.
+ *
+ * If android:allowBackup is set to false or no android:backupAgent
+ * is specified, this flag will be ignored.
+ *
+ * {@hide}
+ */
+ public static final int FLAG_RESTORE_ANY_VERSION = 1<<22;
+
/**
* Flags associated with the application. Any combination of
* {@link #FLAG_SYSTEM}, {@link #FLAG_DEBUGGABLE}, {@link #FLAG_HAS_CODE},
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 582356013452e..98aacaacf2f79 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -1369,8 +1369,8 @@ public class PackageParser {
if (allowBackup) {
ai.flags |= ApplicationInfo.FLAG_ALLOW_BACKUP;
- // backupAgent, killAfterRestore, and restoreNeedsApplication are only relevant
- // if backup is possible for the given application.
+ // backupAgent, killAfterRestore, restoreNeedsApplication, and restoreAnyVersion
+ // are only relevant if backup is possible for the given application.
String backupAgent = sa.getNonResourceString(
com.android.internal.R.styleable.AndroidManifestApplication_backupAgent);
if (backupAgent != null) {
@@ -1390,6 +1390,11 @@ public class PackageParser {
false)) {
ai.flags |= ApplicationInfo.FLAG_RESTORE_NEEDS_APPLICATION;
}
+ if (sa.getBoolean(
+ com.android.internal.R.styleable.AndroidManifestApplication_restoreAnyVersion,
+ false)) {
+ ai.flags |= ApplicationInfo.FLAG_RESTORE_ANY_VERSION;
+ }
}
}
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index b3adf49c46113..d66f513a66dc1 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -593,12 +593,15 @@
+ infrastructure. If this attribute is set to false, no backup
+ of the application will ever be performed, even by a full-system backup that
+ would otherwise cause all application data to be saved via adb. The
+ default value of this attribute is true. -->
+ settings have been restored. The default is true,
+ which means to do so. -->
+
+
+
@@ -700,6 +713,7 @@
+
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index b3343375e90f1..5da8e8585f104 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -1231,6 +1231,7 @@
+
diff --git a/services/java/com/android/server/BackupManagerService.java b/services/java/com/android/server/BackupManagerService.java
index f79a02a9166e8..d4b28e20cd8f3 100644
--- a/services/java/com/android/server/BackupManagerService.java
+++ b/services/java/com/android/server/BackupManagerService.java
@@ -1647,11 +1647,22 @@ class BackupManagerService extends IBackupManager.Stub {
}
if (metaInfo.versionCode > packageInfo.versionCode) {
- String message = "Version " + metaInfo.versionCode
- + " > installed version " + packageInfo.versionCode;
- Log.w(TAG, "Package " + packageName + ": " + message);
- EventLog.writeEvent(EventLogTags.RESTORE_AGENT_FAILURE, packageName, message);
- continue;
+ // Data is from a "newer" version of the app than we have currently
+ // installed. If the app has not declared that it is prepared to
+ // handle this case, we do not attempt the restore.
+ if ((packageInfo.applicationInfo.flags
+ & ApplicationInfo.FLAG_RESTORE_ANY_VERSION) == 0) {
+ String message = "Version " + metaInfo.versionCode
+ + " > installed version " + packageInfo.versionCode;
+ Log.w(TAG, "Package " + packageName + ": " + message);
+ EventLog.writeEvent(EventLogTags.RESTORE_AGENT_FAILURE,
+ packageName, message);
+ continue;
+ } else {
+ if (DEBUG) Log.v(TAG, "Version " + metaInfo.versionCode
+ + " > installed " + packageInfo.versionCode
+ + " but restoreAnyVersion");
+ }
}
if (!signaturesMatch(metaInfo.signatures, packageInfo)) {
@@ -1695,8 +1706,10 @@ class BackupManagerService extends IBackupManager.Stub {
// The agent was probably running with a stub Application object,
// which isn't a valid run mode for the main app logic. Shut
// down the app so that next time it's launched, it gets the
- // usual full initialization.
- if ((packageInfo.applicationInfo.flags
+ // usual full initialization. Note that this is only done for
+ // full-system restores: when a single app has requested a restore,
+ // it is explicitly not killed following that operation.
+ if (mTargetPackage == null && (packageInfo.applicationInfo.flags
& ApplicationInfo.FLAG_KILL_AFTER_RESTORE) != 0) {
if (DEBUG) Log.d(TAG, "Restore complete, killing host process of "
+ packageInfo.applicationInfo.processName);