Loading core/java/android/provider/Settings.java +18 −0 Original line number Diff line number Diff line Loading @@ -12481,6 +12481,24 @@ public final class Settings { public static void setLocationProviderEnabled(ContentResolver cr, String provider, boolean enabled) { } /** * List of system components that support restore in a V-> U OS downgrade but do not have * RestoreAnyVersion set to true. Value set before system restore. * This setting is not B&Rd * List is stored as a comma-separated string of package names e.g. "a,b,c" * @hide */ public static final String V_TO_U_RESTORE_ALLOWLIST = "v_to_u_restore_allowlist"; /** * List of system components that have RestoreAnyVersion set to true but do not support * restore in a V-> U OS downgrade. Value set before system restore. * This setting is not B&Rd * List is stored as a comma-separated string of package names e.g. "a,b,c" * @hide */ public static final String V_TO_U_RESTORE_DENYLIST = "v_to_u_restore_denylist"; } /** Loading packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java +3 −1 Original line number Diff line number Diff line Loading @@ -807,7 +807,9 @@ public class SettingsBackupTest { Settings.Secure.UI_TRANSLATION_ENABLED, Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_EDGE_HAPTIC_ENABLED, Settings.Secure.DND_CONFIGS_MIGRATED, Settings.Secure.NAVIGATION_MODE_RESTORE); Settings.Secure.NAVIGATION_MODE_RESTORE, Settings.Secure.V_TO_U_RESTORE_ALLOWLIST, Settings.Secure.V_TO_U_RESTORE_DENYLIST); @Test public void systemSettingsBackedUpOrDenied() { Loading services/backup/flags.aconfig +9 −0 Original line number Diff line number Diff line Loading @@ -34,6 +34,15 @@ flag { is_fixed_read_only: true } flag { name: "enable_v_to_u_restore_for_system_components_in_allowlist" namespace: "onboarding" description: "Enables system components to opt in to support restore in V to U downgrade " "scenario without opting in for restoreAnyVersion." bug: "324233962" is_fixed_read_only: true } flag { name: "enable_increase_datatypes_for_agent_logging" namespace: "onboarding" Loading services/backup/java/com/android/server/backup/PackageManagerBackupAgent.java +4 −0 Original line number Diff line number Diff line Loading @@ -177,6 +177,10 @@ public class PackageManagerBackupAgent extends BackupAgent { return mHasMetadata; } public int getSourceSdk() { return mStoredSdkVersion; } public Metadata getRestoredMetadata(String packageName) { if (mRestoredSignatures == null) { Slog.w(TAG, "getRestoredMetadata() before metadata read!"); Loading services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java +128 −53 Original line number Diff line number Diff line Loading @@ -44,6 +44,7 @@ import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.PackageManagerInternal; import android.os.Build; import android.os.Bundle; import android.os.Message; import android.os.ParcelFileDescriptor; Loading @@ -51,6 +52,7 @@ import android.os.Process; import android.os.RemoteException; import android.os.SystemClock; import android.os.UserHandle; import android.provider.Settings; import android.util.EventLog; import android.util.Slog; Loading Loading @@ -82,6 +84,7 @@ import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Objects; import java.util.Set; Loading Loading @@ -158,6 +161,12 @@ public class PerformUnifiedRestoreTask implements BackupRestoreTask { // When finished call listener private final OnTaskFinishedListener mListener; // List of packages that support V-> U downgrade but do not have RestoreAnyVersion set to true. private List<String> mVToUAllowlist; // List of packages that have RestoreAnyVersion set to true but do not support V-> U downgrade. private List<String> mVToUDenylist; // Key/value: bookkeeping about staged data and files for agent access private File mBackupDataName; private File mStageName; Loading @@ -172,7 +181,8 @@ public class PerformUnifiedRestoreTask implements BackupRestoreTask { @VisibleForTesting PerformUnifiedRestoreTask( UserBackupManagerService backupManagerService, TransportConnection transportConnection) { TransportConnection transportConnection, String vToUAllowlist, String vToUDenyList) { mListener = null; mAgentTimeoutParameters = null; mOperationStorage = null; Loading @@ -183,6 +193,8 @@ public class PerformUnifiedRestoreTask implements BackupRestoreTask { mBackupEligibilityRules = null; this.backupManagerService = backupManagerService; mBackupManagerMonitorEventSender = new BackupManagerMonitorEventSender(/* monitor= */ null); mVToUAllowlist = createVToUList(vToUAllowlist); mVToUDenylist = createVToUList(vToUDenyList); } // This task can assume that the wakelock is properly held for it and doesn't have to worry Loading Loading @@ -223,6 +235,18 @@ public class PerformUnifiedRestoreTask implements BackupRestoreTask { backupManagerService.getAgentTimeoutParameters(), "Timeout parameters cannot be null"); mBackupEligibilityRules = backupEligibilityRules; mVToUAllowlist = createVToUList( Settings.Secure.getStringForUser( backupManagerService.getContext().getContentResolver(), Settings.Secure.V_TO_U_RESTORE_ALLOWLIST, mUserId)); mVToUDenylist = createVToUList( Settings.Secure.getStringForUser( backupManagerService.getContext().getContentResolver(), Settings.Secure.V_TO_U_RESTORE_DENYLIST, mUserId)); if (targetPackage != null) { // Single package restore Loading Loading @@ -636,60 +660,29 @@ public class PerformUnifiedRestoreTask implements BackupRestoreTask { // 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 (mIsSystemRestore && isVToUDowngrade(mPmAgent.getSourceSdk(), android.os.Build.VERSION.SDK_INT)) { if (isPackageEligibleForVToURestore(mCurrentPackage)) { Slog.i(TAG, "Package " + pkgName + " is eligible for V to U downgrade scenario"); } else { String message = "Package not eligible for V to U downgrade scenario"; Slog.i(TAG, pkgName + " : " + message); EventLog.writeEvent(EventLogTags.RESTORE_AGENT_FAILURE, pkgName, message); nextState = UnifiedRestoreState.RUNNING_QUEUE; return; } } else { if ((mCurrentPackage.applicationInfo.flags & ApplicationInfo.FLAG_RESTORE_ANY_VERSION) == 0) { String message = "Source version " + metaInfo.versionCode + " > installed version " + mCurrentPackage.getLongVersionCode(); Slog.w(TAG, "Package " + pkgName + ": " + message); Bundle monitoringExtras = mBackupManagerMonitorEventSender.putMonitoringExtra( null, BackupManagerMonitor.EXTRA_LOG_RESTORE_VERSION, metaInfo.versionCode); monitoringExtras = mBackupManagerMonitorEventSender.putMonitoringExtra( monitoringExtras, BackupManagerMonitor.EXTRA_LOG_RESTORE_ANYWAY, false); monitoringExtras = addRestoreOperationTypeToEvent(monitoringExtras); mBackupManagerMonitorEventSender.monitorEvent( BackupManagerMonitor.LOG_EVENT_ID_RESTORE_VERSION_HIGHER, mCurrentPackage, BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY, monitoringExtras); EventLog.writeEvent(EventLogTags.RESTORE_AGENT_FAILURE, pkgName, message); // Downgrade scenario with RestoreAnyVersion flag off logDowngradeScenario(/* isRestoreAnyVersion */ false, metaInfo); nextState = UnifiedRestoreState.RUNNING_QUEUE; return; } else { if (DEBUG) { Slog.v( TAG, "Source version " + metaInfo.versionCode + " > installed version " + mCurrentPackage.getLongVersionCode() + " but restoreAnyVersion"); logDowngradeScenario(/* isRestoreAnyVersion */ true, metaInfo); } Bundle monitoringExtras = mBackupManagerMonitorEventSender.putMonitoringExtra( null, BackupManagerMonitor.EXTRA_LOG_RESTORE_VERSION, metaInfo.versionCode); monitoringExtras = mBackupManagerMonitorEventSender.putMonitoringExtra( monitoringExtras, BackupManagerMonitor.EXTRA_LOG_RESTORE_ANYWAY, true); monitoringExtras = addRestoreOperationTypeToEvent(monitoringExtras); mBackupManagerMonitorEventSender.monitorEvent( BackupManagerMonitor.LOG_EVENT_ID_RESTORE_VERSION_HIGHER, mCurrentPackage, BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY, monitoringExtras); } } Loading Loading @@ -1673,4 +1666,86 @@ public class PerformUnifiedRestoreTask implements BackupRestoreTask { return mBackupManagerMonitorEventSender.putMonitoringExtra( extras, BackupManagerMonitor.EXTRA_LOG_OPERATION_TYPE, RESTORE); } // checks the sdk of the target/source device for a B&R operation. // system components can opt in/out of V->U restore via allowlists. All other apps are // not impacted @SuppressWarnings("AndroidFrameworkCompatChange") @VisibleForTesting protected boolean isVToUDowngrade(int sourceSdk, int targetSdk) { // We assume that if the source sdk is greater than U then the source is V. return Flags.enableVToURestoreForSystemComponentsInAllowlist() && (sourceSdk > Build.VERSION_CODES.UPSIDE_DOWN_CAKE) && (targetSdk == Build.VERSION_CODES.UPSIDE_DOWN_CAKE); } @VisibleForTesting protected List<String> createVToUList(@Nullable String listString) { // The allowlist/denylist is stored as a comma-separated list of package names List<String> list = new ArrayList<>(); if (listString != null) { list = Arrays.asList(listString.split(",")); } return list; } @VisibleForTesting protected boolean isPackageEligibleForVToURestore(PackageInfo mCurrentPackage) { // A package is eligible for V to U downgrade restore if either: // - The package has restoreAnyVersion set to false and is part of the V to U allowlist // (and not in the denylist) // - The package has restoreAnyVersion set to true and is not part of the denylist if (mVToUDenylist.contains(mCurrentPackage.packageName)){ return false; } else if ((mCurrentPackage.applicationInfo.flags & ApplicationInfo.FLAG_RESTORE_ANY_VERSION) == 0) { // package has restoreAnyVersion set to false return mVToUAllowlist.contains(mCurrentPackage.packageName); } else { // package has restoreAnyVersion set to true and is nor in denylist return true; } } private void logDowngradeScenario(boolean isRestoreAnyVersion, Metadata metaInfo) { Bundle monitoringExtras = mBackupManagerMonitorEventSender.putMonitoringExtra( null, BackupManagerMonitor.EXTRA_LOG_RESTORE_VERSION, metaInfo.versionCode); String message; if (isRestoreAnyVersion) { monitoringExtras = mBackupManagerMonitorEventSender.putMonitoringExtra( monitoringExtras, BackupManagerMonitor.EXTRA_LOG_RESTORE_ANYWAY, true); message = "Source version " + metaInfo.versionCode + " > installed version " + mCurrentPackage.getLongVersionCode() + " but restoreAnyVersion"; } else { monitoringExtras = mBackupManagerMonitorEventSender.putMonitoringExtra( monitoringExtras, BackupManagerMonitor.EXTRA_LOG_RESTORE_ANYWAY, false); message = "Source version " + metaInfo.versionCode + " > installed version " + mCurrentPackage.getLongVersionCode(); EventLog.writeEvent(EventLogTags.RESTORE_AGENT_FAILURE, mCurrentPackage.packageName, message); } Slog.i(TAG, "Package " + mCurrentPackage.packageName + ": " + message); monitoringExtras = addRestoreOperationTypeToEvent(monitoringExtras); mBackupManagerMonitorEventSender.monitorEvent( BackupManagerMonitor.LOG_EVENT_ID_RESTORE_VERSION_HIGHER, mCurrentPackage, BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY, monitoringExtras); } } Loading
core/java/android/provider/Settings.java +18 −0 Original line number Diff line number Diff line Loading @@ -12481,6 +12481,24 @@ public final class Settings { public static void setLocationProviderEnabled(ContentResolver cr, String provider, boolean enabled) { } /** * List of system components that support restore in a V-> U OS downgrade but do not have * RestoreAnyVersion set to true. Value set before system restore. * This setting is not B&Rd * List is stored as a comma-separated string of package names e.g. "a,b,c" * @hide */ public static final String V_TO_U_RESTORE_ALLOWLIST = "v_to_u_restore_allowlist"; /** * List of system components that have RestoreAnyVersion set to true but do not support * restore in a V-> U OS downgrade. Value set before system restore. * This setting is not B&Rd * List is stored as a comma-separated string of package names e.g. "a,b,c" * @hide */ public static final String V_TO_U_RESTORE_DENYLIST = "v_to_u_restore_denylist"; } /** Loading
packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java +3 −1 Original line number Diff line number Diff line Loading @@ -807,7 +807,9 @@ public class SettingsBackupTest { Settings.Secure.UI_TRANSLATION_ENABLED, Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_EDGE_HAPTIC_ENABLED, Settings.Secure.DND_CONFIGS_MIGRATED, Settings.Secure.NAVIGATION_MODE_RESTORE); Settings.Secure.NAVIGATION_MODE_RESTORE, Settings.Secure.V_TO_U_RESTORE_ALLOWLIST, Settings.Secure.V_TO_U_RESTORE_DENYLIST); @Test public void systemSettingsBackedUpOrDenied() { Loading
services/backup/flags.aconfig +9 −0 Original line number Diff line number Diff line Loading @@ -34,6 +34,15 @@ flag { is_fixed_read_only: true } flag { name: "enable_v_to_u_restore_for_system_components_in_allowlist" namespace: "onboarding" description: "Enables system components to opt in to support restore in V to U downgrade " "scenario without opting in for restoreAnyVersion." bug: "324233962" is_fixed_read_only: true } flag { name: "enable_increase_datatypes_for_agent_logging" namespace: "onboarding" Loading
services/backup/java/com/android/server/backup/PackageManagerBackupAgent.java +4 −0 Original line number Diff line number Diff line Loading @@ -177,6 +177,10 @@ public class PackageManagerBackupAgent extends BackupAgent { return mHasMetadata; } public int getSourceSdk() { return mStoredSdkVersion; } public Metadata getRestoredMetadata(String packageName) { if (mRestoredSignatures == null) { Slog.w(TAG, "getRestoredMetadata() before metadata read!"); Loading
services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java +128 −53 Original line number Diff line number Diff line Loading @@ -44,6 +44,7 @@ import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.PackageManagerInternal; import android.os.Build; import android.os.Bundle; import android.os.Message; import android.os.ParcelFileDescriptor; Loading @@ -51,6 +52,7 @@ import android.os.Process; import android.os.RemoteException; import android.os.SystemClock; import android.os.UserHandle; import android.provider.Settings; import android.util.EventLog; import android.util.Slog; Loading Loading @@ -82,6 +84,7 @@ import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Objects; import java.util.Set; Loading Loading @@ -158,6 +161,12 @@ public class PerformUnifiedRestoreTask implements BackupRestoreTask { // When finished call listener private final OnTaskFinishedListener mListener; // List of packages that support V-> U downgrade but do not have RestoreAnyVersion set to true. private List<String> mVToUAllowlist; // List of packages that have RestoreAnyVersion set to true but do not support V-> U downgrade. private List<String> mVToUDenylist; // Key/value: bookkeeping about staged data and files for agent access private File mBackupDataName; private File mStageName; Loading @@ -172,7 +181,8 @@ public class PerformUnifiedRestoreTask implements BackupRestoreTask { @VisibleForTesting PerformUnifiedRestoreTask( UserBackupManagerService backupManagerService, TransportConnection transportConnection) { TransportConnection transportConnection, String vToUAllowlist, String vToUDenyList) { mListener = null; mAgentTimeoutParameters = null; mOperationStorage = null; Loading @@ -183,6 +193,8 @@ public class PerformUnifiedRestoreTask implements BackupRestoreTask { mBackupEligibilityRules = null; this.backupManagerService = backupManagerService; mBackupManagerMonitorEventSender = new BackupManagerMonitorEventSender(/* monitor= */ null); mVToUAllowlist = createVToUList(vToUAllowlist); mVToUDenylist = createVToUList(vToUDenyList); } // This task can assume that the wakelock is properly held for it and doesn't have to worry Loading Loading @@ -223,6 +235,18 @@ public class PerformUnifiedRestoreTask implements BackupRestoreTask { backupManagerService.getAgentTimeoutParameters(), "Timeout parameters cannot be null"); mBackupEligibilityRules = backupEligibilityRules; mVToUAllowlist = createVToUList( Settings.Secure.getStringForUser( backupManagerService.getContext().getContentResolver(), Settings.Secure.V_TO_U_RESTORE_ALLOWLIST, mUserId)); mVToUDenylist = createVToUList( Settings.Secure.getStringForUser( backupManagerService.getContext().getContentResolver(), Settings.Secure.V_TO_U_RESTORE_DENYLIST, mUserId)); if (targetPackage != null) { // Single package restore Loading Loading @@ -636,60 +660,29 @@ public class PerformUnifiedRestoreTask implements BackupRestoreTask { // 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 (mIsSystemRestore && isVToUDowngrade(mPmAgent.getSourceSdk(), android.os.Build.VERSION.SDK_INT)) { if (isPackageEligibleForVToURestore(mCurrentPackage)) { Slog.i(TAG, "Package " + pkgName + " is eligible for V to U downgrade scenario"); } else { String message = "Package not eligible for V to U downgrade scenario"; Slog.i(TAG, pkgName + " : " + message); EventLog.writeEvent(EventLogTags.RESTORE_AGENT_FAILURE, pkgName, message); nextState = UnifiedRestoreState.RUNNING_QUEUE; return; } } else { if ((mCurrentPackage.applicationInfo.flags & ApplicationInfo.FLAG_RESTORE_ANY_VERSION) == 0) { String message = "Source version " + metaInfo.versionCode + " > installed version " + mCurrentPackage.getLongVersionCode(); Slog.w(TAG, "Package " + pkgName + ": " + message); Bundle monitoringExtras = mBackupManagerMonitorEventSender.putMonitoringExtra( null, BackupManagerMonitor.EXTRA_LOG_RESTORE_VERSION, metaInfo.versionCode); monitoringExtras = mBackupManagerMonitorEventSender.putMonitoringExtra( monitoringExtras, BackupManagerMonitor.EXTRA_LOG_RESTORE_ANYWAY, false); monitoringExtras = addRestoreOperationTypeToEvent(monitoringExtras); mBackupManagerMonitorEventSender.monitorEvent( BackupManagerMonitor.LOG_EVENT_ID_RESTORE_VERSION_HIGHER, mCurrentPackage, BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY, monitoringExtras); EventLog.writeEvent(EventLogTags.RESTORE_AGENT_FAILURE, pkgName, message); // Downgrade scenario with RestoreAnyVersion flag off logDowngradeScenario(/* isRestoreAnyVersion */ false, metaInfo); nextState = UnifiedRestoreState.RUNNING_QUEUE; return; } else { if (DEBUG) { Slog.v( TAG, "Source version " + metaInfo.versionCode + " > installed version " + mCurrentPackage.getLongVersionCode() + " but restoreAnyVersion"); logDowngradeScenario(/* isRestoreAnyVersion */ true, metaInfo); } Bundle monitoringExtras = mBackupManagerMonitorEventSender.putMonitoringExtra( null, BackupManagerMonitor.EXTRA_LOG_RESTORE_VERSION, metaInfo.versionCode); monitoringExtras = mBackupManagerMonitorEventSender.putMonitoringExtra( monitoringExtras, BackupManagerMonitor.EXTRA_LOG_RESTORE_ANYWAY, true); monitoringExtras = addRestoreOperationTypeToEvent(monitoringExtras); mBackupManagerMonitorEventSender.monitorEvent( BackupManagerMonitor.LOG_EVENT_ID_RESTORE_VERSION_HIGHER, mCurrentPackage, BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY, monitoringExtras); } } Loading Loading @@ -1673,4 +1666,86 @@ public class PerformUnifiedRestoreTask implements BackupRestoreTask { return mBackupManagerMonitorEventSender.putMonitoringExtra( extras, BackupManagerMonitor.EXTRA_LOG_OPERATION_TYPE, RESTORE); } // checks the sdk of the target/source device for a B&R operation. // system components can opt in/out of V->U restore via allowlists. All other apps are // not impacted @SuppressWarnings("AndroidFrameworkCompatChange") @VisibleForTesting protected boolean isVToUDowngrade(int sourceSdk, int targetSdk) { // We assume that if the source sdk is greater than U then the source is V. return Flags.enableVToURestoreForSystemComponentsInAllowlist() && (sourceSdk > Build.VERSION_CODES.UPSIDE_DOWN_CAKE) && (targetSdk == Build.VERSION_CODES.UPSIDE_DOWN_CAKE); } @VisibleForTesting protected List<String> createVToUList(@Nullable String listString) { // The allowlist/denylist is stored as a comma-separated list of package names List<String> list = new ArrayList<>(); if (listString != null) { list = Arrays.asList(listString.split(",")); } return list; } @VisibleForTesting protected boolean isPackageEligibleForVToURestore(PackageInfo mCurrentPackage) { // A package is eligible for V to U downgrade restore if either: // - The package has restoreAnyVersion set to false and is part of the V to U allowlist // (and not in the denylist) // - The package has restoreAnyVersion set to true and is not part of the denylist if (mVToUDenylist.contains(mCurrentPackage.packageName)){ return false; } else if ((mCurrentPackage.applicationInfo.flags & ApplicationInfo.FLAG_RESTORE_ANY_VERSION) == 0) { // package has restoreAnyVersion set to false return mVToUAllowlist.contains(mCurrentPackage.packageName); } else { // package has restoreAnyVersion set to true and is nor in denylist return true; } } private void logDowngradeScenario(boolean isRestoreAnyVersion, Metadata metaInfo) { Bundle monitoringExtras = mBackupManagerMonitorEventSender.putMonitoringExtra( null, BackupManagerMonitor.EXTRA_LOG_RESTORE_VERSION, metaInfo.versionCode); String message; if (isRestoreAnyVersion) { monitoringExtras = mBackupManagerMonitorEventSender.putMonitoringExtra( monitoringExtras, BackupManagerMonitor.EXTRA_LOG_RESTORE_ANYWAY, true); message = "Source version " + metaInfo.versionCode + " > installed version " + mCurrentPackage.getLongVersionCode() + " but restoreAnyVersion"; } else { monitoringExtras = mBackupManagerMonitorEventSender.putMonitoringExtra( monitoringExtras, BackupManagerMonitor.EXTRA_LOG_RESTORE_ANYWAY, false); message = "Source version " + metaInfo.versionCode + " > installed version " + mCurrentPackage.getLongVersionCode(); EventLog.writeEvent(EventLogTags.RESTORE_AGENT_FAILURE, mCurrentPackage.packageName, message); } Slog.i(TAG, "Package " + mCurrentPackage.packageName + ": " + message); monitoringExtras = addRestoreOperationTypeToEvent(monitoringExtras); mBackupManagerMonitorEventSender.monitorEvent( BackupManagerMonitor.LOG_EVENT_ID_RESTORE_VERSION_HIGHER, mCurrentPackage, BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY, monitoringExtras); } }