diff --git a/api/current.xml b/api/current.xml index 3af1426b99681..031506b558e84 100644 --- a/api/current.xml +++ b/api/current.xml @@ -6785,6 +6785,17 @@ visibility="public" > + + - + 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);