Loading services/backup/java/com/android/server/backup/utils/BackupEligibilityRules.java +96 −75 Original line number Diff line number Diff line Loading @@ -57,9 +57,7 @@ import com.google.android.collect.Sets; import java.util.Arrays; import java.util.Set; /** * Utility methods wrapping operations on ApplicationInfo and PackageInfo. */ /** Utility methods wrapping operations on ApplicationInfo and PackageInfo. */ public class BackupEligibilityRules { private static final boolean DEBUG = false; Loading @@ -71,10 +69,9 @@ public class BackupEligibilityRules { private static final Set<String> systemPackagesAllowedForProfileUser = Sets.newArraySet(PACKAGE_MANAGER_SENTINEL, PLATFORM_PACKAGE_NAME); /** * List of system packages that are eligible for backup in non-system users. */ private static final Set<String> systemPackagesAllowedForNonSystemUsers = SetUtils.union( /** List of system packages that are eligible for backup in non-system users. */ private static final Set<String> systemPackagesAllowedForNonSystemUsers = SetUtils.union( systemPackagesAllowedForProfileUser, Sets.newArraySet(WALLPAPER_PACKAGE, SETTINGS_PACKAGE)); Loading @@ -82,7 +79,8 @@ public class BackupEligibilityRules { * List of system packages that are eligible for backup for the main user in Headless System * User Mode (HSUM). In HSUM, certain packages are only backed up for the main user. */ private static final Set<String> systemPackagesAllowedForHsumMainUser = SetUtils.union( private static final Set<String> systemPackagesAllowedForHsumMainUser = SetUtils.union( systemPackagesAllowedForNonSystemUsers, Sets.newArraySet(TELEPHONY_PROVIDER_PACKAGE)); Loading @@ -94,9 +92,9 @@ public class BackupEligibilityRules { private final boolean mSkipRestoreForLaunchedApps; /** * When this change is enabled, {@code adb backup} is automatically turned on for apps * running as debuggable ({@code android:debuggable} set to {@code true}) and unavailable to * any other apps. * When this change is enabled, {@code adb backup} is automatically turned on for apps running * as debuggable ({@code android:debuggable} set to {@code true}) and unavailable to any other * apps. */ @ChangeId @EnabledSince(targetSdkVersion = Build.VERSION_CODES.S) Loading @@ -111,24 +109,33 @@ public class BackupEligibilityRules { @EnabledSince(targetSdkVersion = Build.VERSION_CODES.S) static final long IGNORE_ALLOW_BACKUP_IN_D2D = 183147249L; public static BackupEligibilityRules forBackup(PackageManager packageManager, /** Create eligibility rules to check backup eligibility. */ public static BackupEligibilityRules forBackup( PackageManager packageManager, PackageManagerInternal packageManagerInternal, int userId, Context context) { return new BackupEligibilityRules(packageManager, packageManagerInternal, userId, context, BackupDestination.CLOUD); return new BackupEligibilityRules( packageManager, packageManagerInternal, userId, context, BackupDestination.CLOUD); } public BackupEligibilityRules(PackageManager packageManager, public BackupEligibilityRules( PackageManager packageManager, PackageManagerInternal packageManagerInternal, int userId, Context context, @BackupDestination int backupDestination) { this(packageManager, packageManagerInternal, userId, context, backupDestination, this( packageManager, packageManagerInternal, userId, context, backupDestination, /* skipRestoreForLaunchedApps */ false); } public BackupEligibilityRules(PackageManager packageManager, public BackupEligibilityRules( PackageManager packageManager, PackageManagerInternal packageManagerInternal, int userId, Context context, Loading @@ -145,8 +152,8 @@ public class BackupEligibilityRules { /** * Returns whether app is eligible for backup. * * High level policy: apps are generally ineligible for backup if certain conditions apply. The * conditions are: * <p>High level policy: apps are generally ineligible for backup if certain conditions apply. * The conditions are: * * <ol> * <li>their manifest states android:allowBackup="false" Loading @@ -157,7 +164,7 @@ public class BackupEligibilityRules { * These eligibility conditions are also checked before restore, in case the backup happened on * a device / from the version of the app where these rules were not enforced. * * However, the above eligibility rules are ignored for non-system apps in in case of * <p>However, the above eligibility rules are ignored for non-system apps in case of * device-to-device migration, see {@link BackupDestination}. */ @VisibleForTesting Loading Loading @@ -196,9 +203,9 @@ public class BackupEligibilityRules { } /** * Checks if a given system package is allowed for backup for the current user. * True for system user ({@link android.os.UserHandle#USER_SYSTEM}); for others, * eligibility depends on user type (profile, HSUM main, etc.) and specific allowlists. * Checks if a given system package is allowed for backup for the current user. True for system * user ({@link android.os.UserHandle#USER_SYSTEM}); for others, eligibility depends on user * type (profile, HSUM main, etc.) and specific allowlists. */ @SuppressWarnings("AndroidFrameworkRequiresPermission") private boolean isSystemPackageAllowedForCurrentUser(String packageName) { Loading Loading @@ -237,8 +244,12 @@ public class BackupEligibilityRules { // Backup / restore of all non-system apps is force allowed during // device-to-device migration. boolean isSystemApp = (app.flags & ApplicationInfo.FLAG_SYSTEM) != 0; boolean ignoreAllowBackup = !isSystemApp && CompatChanges.isChangeEnabled( IGNORE_ALLOW_BACKUP_IN_D2D, app.packageName, UserHandle.of(mUserId)); boolean ignoreAllowBackup = !isSystemApp && CompatChanges.isChangeEnabled( IGNORE_ALLOW_BACKUP_IN_D2D, app.packageName, UserHandle.of(mUserId)); return ignoreAllowBackup || allowBackup; case BackupDestination.ADB_BACKUP: String packageName = app.packageName; Loading @@ -247,8 +258,8 @@ public class BackupEligibilityRules { return false; } if (!CompatChanges.isChangeEnabled(RESTRICT_ADB_BACKUP, packageName, UserHandle.of(mUserId))) { if (!CompatChanges.isChangeEnabled( RESTRICT_ADB_BACKUP, packageName, UserHandle.of(mUserId))) { return allowBackup; } Loading @@ -263,12 +274,15 @@ public class BackupEligibilityRules { boolean isDebuggable = (app.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0; if (UserHandle.isCore(app.uid) || isPrivileged) { try { return mPackageManager.getPropertyAsUser( PackageManager.PROPERTY_ALLOW_ADB_BACKUP, packageName, null /* className */, mUserId).getBoolean(); return mPackageManager .getPropertyAsUser( PackageManager.PROPERTY_ALLOW_ADB_BACKUP, packageName, null /* className */, mUserId) .getBoolean(); } catch (PackageManager.NameNotFoundException e) { Slog.w(TAG, "Failed to read allowAdbBackup property for + " + packageName); Slog.w(TAG, "Failed to read allowAdbBackup property for + " + packageName); // This temporarily falls back to the legacy allowBackup flag to // avoid breaking existing users of adb backup. Once they're able to use Loading @@ -290,20 +304,21 @@ public class BackupEligibilityRules { /** * Returns whether an app is eligible for backup at runtime. That is, the app has to: * * <ol> * <li>Return true for {@link #appIsEligibleForBackup(ApplicationInfo, int)} * <li>Return false for {@link #appIsStopped(ApplicationInfo)} * <li>Return false for {@link #appIsDisabled(ApplicationInfo, int)} * <li>Be eligible for the transport via * {@link BackupTransport#isAppEligibleForBackup(PackageInfo, boolean)} * <li>Be eligible for the transport via {@link * BackupTransport#isAppEligibleForBackup(PackageInfo, boolean)} * </ol> */ public boolean appIsRunningAndEligibleForBackupWithTransport( @Nullable TransportConnection transportConnection, String packageName) { @Nullable TransportConnection transportConnection, String packageName) { try { PackageInfo packageInfo = mPackageManager.getPackageInfoAsUser(packageName, PackageManager.GET_SIGNING_CERTIFICATES, mUserId); PackageInfo packageInfo = mPackageManager.getPackageInfoAsUser( packageName, PackageManager.GET_SIGNING_CERTIFICATES, mUserId); ApplicationInfo applicationInfo = packageInfo.applicationInfo; if (!appIsEligibleForBackup(applicationInfo) || appIsStopped(applicationInfo) Loading Loading @@ -332,7 +347,7 @@ public class BackupEligibilityRules { * Determine if data restore should be run for the given package. * * <p>This is used in combination with {@link #appIsEligibleForBackup(ApplicationInfo)} that * checks whether the backup being restored should have happened in the first place.</p> * checks whether the backup being restored should have happened in the first place. */ public boolean isAppEligibleForRestore(ApplicationInfo app) { if (!mSkipRestoreForLaunchedApps) { Loading @@ -351,10 +366,9 @@ public class BackupEligibilityRules { /** Avoid backups of 'disabled' apps. */ @VisibleForTesting boolean appIsDisabled( ApplicationInfo app) { int enabledSetting = mPackageManagerInternal.getApplicationEnabledState(app.packageName, mUserId); boolean appIsDisabled(ApplicationInfo app) { int enabledSetting = mPackageManagerInternal.getApplicationEnabledState(app.packageName, mUserId); switch (enabledSetting) { case PackageManager.COMPONENT_ENABLED_STATE_DISABLED: Loading @@ -374,6 +388,7 @@ public class BackupEligibilityRules { * newly-installing ones). * * <p>Reasons for such state: * * <ul> * <li>The app has been force-stopped. * <li>The app has been cleared. Loading Loading @@ -418,12 +433,12 @@ public class BackupEligibilityRules { * <li>Target contains all signatures in source, and nothing more * </ul> * * or if both source and target have exactly one signature, and they don't match, we check * if the app was ever signed with source signature (i.e. app has rotated key) * Note: key rotation is only supported for apps ever signed with one key, and those apps will * not be allowed to be signed by more certificates in the future * or if both source and target have exactly one signature, and they don't match, we check if * the app was ever signed with source signature (i.e. app has rotated key) Note: key rotation * is only supported for apps ever signed with one key, and those apps will not be allowed to be * signed by more certificates in the future * * Note that if {@param target} is null we return false. * <p>Note that if {@param target} is null we return false. */ public boolean signaturesMatch(Signature[] storedSigs, PackageInfo target) { if (target == null || target.packageName == null) { Loading @@ -449,13 +464,19 @@ public class BackupEligibilityRules { SigningInfo signingInfo = target.signingInfo; if (signingInfo == null) { Slog.w(TAG, "signingInfo is empty, app was either unsigned or the flag" + " PackageManager#GET_SIGNING_CERTIFICATES was not specified"); Slog.w( TAG, "signingInfo is empty, app was either unsigned or the flag" + " PackageManager#GET_SIGNING_CERTIFICATES was not specified"); return false; } Slog.d(TAG, "signaturesMatch(): stored=" + Arrays.toString(storedSigs) + " device=" + Arrays.toString(signingInfo.getApkContentsSigners())); Slog.d( TAG, "signaturesMatch(): stored=" + Arrays.toString(storedSigs) + " device=" + Arrays.toString(signingInfo.getApkContentsSigners())); final int nStored = storedSigs.length; if (nStored == 1) { Loading services/tests/mockingservicestests/src/com/android/server/backup/utils/BackupEligibilityRulesTest.java +212 −137 File changed.Preview size limit exceeded, changes collapsed. Show changes Loading
services/backup/java/com/android/server/backup/utils/BackupEligibilityRules.java +96 −75 Original line number Diff line number Diff line Loading @@ -57,9 +57,7 @@ import com.google.android.collect.Sets; import java.util.Arrays; import java.util.Set; /** * Utility methods wrapping operations on ApplicationInfo and PackageInfo. */ /** Utility methods wrapping operations on ApplicationInfo and PackageInfo. */ public class BackupEligibilityRules { private static final boolean DEBUG = false; Loading @@ -71,10 +69,9 @@ public class BackupEligibilityRules { private static final Set<String> systemPackagesAllowedForProfileUser = Sets.newArraySet(PACKAGE_MANAGER_SENTINEL, PLATFORM_PACKAGE_NAME); /** * List of system packages that are eligible for backup in non-system users. */ private static final Set<String> systemPackagesAllowedForNonSystemUsers = SetUtils.union( /** List of system packages that are eligible for backup in non-system users. */ private static final Set<String> systemPackagesAllowedForNonSystemUsers = SetUtils.union( systemPackagesAllowedForProfileUser, Sets.newArraySet(WALLPAPER_PACKAGE, SETTINGS_PACKAGE)); Loading @@ -82,7 +79,8 @@ public class BackupEligibilityRules { * List of system packages that are eligible for backup for the main user in Headless System * User Mode (HSUM). In HSUM, certain packages are only backed up for the main user. */ private static final Set<String> systemPackagesAllowedForHsumMainUser = SetUtils.union( private static final Set<String> systemPackagesAllowedForHsumMainUser = SetUtils.union( systemPackagesAllowedForNonSystemUsers, Sets.newArraySet(TELEPHONY_PROVIDER_PACKAGE)); Loading @@ -94,9 +92,9 @@ public class BackupEligibilityRules { private final boolean mSkipRestoreForLaunchedApps; /** * When this change is enabled, {@code adb backup} is automatically turned on for apps * running as debuggable ({@code android:debuggable} set to {@code true}) and unavailable to * any other apps. * When this change is enabled, {@code adb backup} is automatically turned on for apps running * as debuggable ({@code android:debuggable} set to {@code true}) and unavailable to any other * apps. */ @ChangeId @EnabledSince(targetSdkVersion = Build.VERSION_CODES.S) Loading @@ -111,24 +109,33 @@ public class BackupEligibilityRules { @EnabledSince(targetSdkVersion = Build.VERSION_CODES.S) static final long IGNORE_ALLOW_BACKUP_IN_D2D = 183147249L; public static BackupEligibilityRules forBackup(PackageManager packageManager, /** Create eligibility rules to check backup eligibility. */ public static BackupEligibilityRules forBackup( PackageManager packageManager, PackageManagerInternal packageManagerInternal, int userId, Context context) { return new BackupEligibilityRules(packageManager, packageManagerInternal, userId, context, BackupDestination.CLOUD); return new BackupEligibilityRules( packageManager, packageManagerInternal, userId, context, BackupDestination.CLOUD); } public BackupEligibilityRules(PackageManager packageManager, public BackupEligibilityRules( PackageManager packageManager, PackageManagerInternal packageManagerInternal, int userId, Context context, @BackupDestination int backupDestination) { this(packageManager, packageManagerInternal, userId, context, backupDestination, this( packageManager, packageManagerInternal, userId, context, backupDestination, /* skipRestoreForLaunchedApps */ false); } public BackupEligibilityRules(PackageManager packageManager, public BackupEligibilityRules( PackageManager packageManager, PackageManagerInternal packageManagerInternal, int userId, Context context, Loading @@ -145,8 +152,8 @@ public class BackupEligibilityRules { /** * Returns whether app is eligible for backup. * * High level policy: apps are generally ineligible for backup if certain conditions apply. The * conditions are: * <p>High level policy: apps are generally ineligible for backup if certain conditions apply. * The conditions are: * * <ol> * <li>their manifest states android:allowBackup="false" Loading @@ -157,7 +164,7 @@ public class BackupEligibilityRules { * These eligibility conditions are also checked before restore, in case the backup happened on * a device / from the version of the app where these rules were not enforced. * * However, the above eligibility rules are ignored for non-system apps in in case of * <p>However, the above eligibility rules are ignored for non-system apps in case of * device-to-device migration, see {@link BackupDestination}. */ @VisibleForTesting Loading Loading @@ -196,9 +203,9 @@ public class BackupEligibilityRules { } /** * Checks if a given system package is allowed for backup for the current user. * True for system user ({@link android.os.UserHandle#USER_SYSTEM}); for others, * eligibility depends on user type (profile, HSUM main, etc.) and specific allowlists. * Checks if a given system package is allowed for backup for the current user. True for system * user ({@link android.os.UserHandle#USER_SYSTEM}); for others, eligibility depends on user * type (profile, HSUM main, etc.) and specific allowlists. */ @SuppressWarnings("AndroidFrameworkRequiresPermission") private boolean isSystemPackageAllowedForCurrentUser(String packageName) { Loading Loading @@ -237,8 +244,12 @@ public class BackupEligibilityRules { // Backup / restore of all non-system apps is force allowed during // device-to-device migration. boolean isSystemApp = (app.flags & ApplicationInfo.FLAG_SYSTEM) != 0; boolean ignoreAllowBackup = !isSystemApp && CompatChanges.isChangeEnabled( IGNORE_ALLOW_BACKUP_IN_D2D, app.packageName, UserHandle.of(mUserId)); boolean ignoreAllowBackup = !isSystemApp && CompatChanges.isChangeEnabled( IGNORE_ALLOW_BACKUP_IN_D2D, app.packageName, UserHandle.of(mUserId)); return ignoreAllowBackup || allowBackup; case BackupDestination.ADB_BACKUP: String packageName = app.packageName; Loading @@ -247,8 +258,8 @@ public class BackupEligibilityRules { return false; } if (!CompatChanges.isChangeEnabled(RESTRICT_ADB_BACKUP, packageName, UserHandle.of(mUserId))) { if (!CompatChanges.isChangeEnabled( RESTRICT_ADB_BACKUP, packageName, UserHandle.of(mUserId))) { return allowBackup; } Loading @@ -263,12 +274,15 @@ public class BackupEligibilityRules { boolean isDebuggable = (app.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0; if (UserHandle.isCore(app.uid) || isPrivileged) { try { return mPackageManager.getPropertyAsUser( PackageManager.PROPERTY_ALLOW_ADB_BACKUP, packageName, null /* className */, mUserId).getBoolean(); return mPackageManager .getPropertyAsUser( PackageManager.PROPERTY_ALLOW_ADB_BACKUP, packageName, null /* className */, mUserId) .getBoolean(); } catch (PackageManager.NameNotFoundException e) { Slog.w(TAG, "Failed to read allowAdbBackup property for + " + packageName); Slog.w(TAG, "Failed to read allowAdbBackup property for + " + packageName); // This temporarily falls back to the legacy allowBackup flag to // avoid breaking existing users of adb backup. Once they're able to use Loading @@ -290,20 +304,21 @@ public class BackupEligibilityRules { /** * Returns whether an app is eligible for backup at runtime. That is, the app has to: * * <ol> * <li>Return true for {@link #appIsEligibleForBackup(ApplicationInfo, int)} * <li>Return false for {@link #appIsStopped(ApplicationInfo)} * <li>Return false for {@link #appIsDisabled(ApplicationInfo, int)} * <li>Be eligible for the transport via * {@link BackupTransport#isAppEligibleForBackup(PackageInfo, boolean)} * <li>Be eligible for the transport via {@link * BackupTransport#isAppEligibleForBackup(PackageInfo, boolean)} * </ol> */ public boolean appIsRunningAndEligibleForBackupWithTransport( @Nullable TransportConnection transportConnection, String packageName) { @Nullable TransportConnection transportConnection, String packageName) { try { PackageInfo packageInfo = mPackageManager.getPackageInfoAsUser(packageName, PackageManager.GET_SIGNING_CERTIFICATES, mUserId); PackageInfo packageInfo = mPackageManager.getPackageInfoAsUser( packageName, PackageManager.GET_SIGNING_CERTIFICATES, mUserId); ApplicationInfo applicationInfo = packageInfo.applicationInfo; if (!appIsEligibleForBackup(applicationInfo) || appIsStopped(applicationInfo) Loading Loading @@ -332,7 +347,7 @@ public class BackupEligibilityRules { * Determine if data restore should be run for the given package. * * <p>This is used in combination with {@link #appIsEligibleForBackup(ApplicationInfo)} that * checks whether the backup being restored should have happened in the first place.</p> * checks whether the backup being restored should have happened in the first place. */ public boolean isAppEligibleForRestore(ApplicationInfo app) { if (!mSkipRestoreForLaunchedApps) { Loading @@ -351,10 +366,9 @@ public class BackupEligibilityRules { /** Avoid backups of 'disabled' apps. */ @VisibleForTesting boolean appIsDisabled( ApplicationInfo app) { int enabledSetting = mPackageManagerInternal.getApplicationEnabledState(app.packageName, mUserId); boolean appIsDisabled(ApplicationInfo app) { int enabledSetting = mPackageManagerInternal.getApplicationEnabledState(app.packageName, mUserId); switch (enabledSetting) { case PackageManager.COMPONENT_ENABLED_STATE_DISABLED: Loading @@ -374,6 +388,7 @@ public class BackupEligibilityRules { * newly-installing ones). * * <p>Reasons for such state: * * <ul> * <li>The app has been force-stopped. * <li>The app has been cleared. Loading Loading @@ -418,12 +433,12 @@ public class BackupEligibilityRules { * <li>Target contains all signatures in source, and nothing more * </ul> * * or if both source and target have exactly one signature, and they don't match, we check * if the app was ever signed with source signature (i.e. app has rotated key) * Note: key rotation is only supported for apps ever signed with one key, and those apps will * not be allowed to be signed by more certificates in the future * or if both source and target have exactly one signature, and they don't match, we check if * the app was ever signed with source signature (i.e. app has rotated key) Note: key rotation * is only supported for apps ever signed with one key, and those apps will not be allowed to be * signed by more certificates in the future * * Note that if {@param target} is null we return false. * <p>Note that if {@param target} is null we return false. */ public boolean signaturesMatch(Signature[] storedSigs, PackageInfo target) { if (target == null || target.packageName == null) { Loading @@ -449,13 +464,19 @@ public class BackupEligibilityRules { SigningInfo signingInfo = target.signingInfo; if (signingInfo == null) { Slog.w(TAG, "signingInfo is empty, app was either unsigned or the flag" + " PackageManager#GET_SIGNING_CERTIFICATES was not specified"); Slog.w( TAG, "signingInfo is empty, app was either unsigned or the flag" + " PackageManager#GET_SIGNING_CERTIFICATES was not specified"); return false; } Slog.d(TAG, "signaturesMatch(): stored=" + Arrays.toString(storedSigs) + " device=" + Arrays.toString(signingInfo.getApkContentsSigners())); Slog.d( TAG, "signaturesMatch(): stored=" + Arrays.toString(storedSigs) + " device=" + Arrays.toString(signingInfo.getApkContentsSigners())); final int nStored = storedSigs.length; if (nStored == 1) { Loading
services/tests/mockingservicestests/src/com/android/server/backup/utils/BackupEligibilityRulesTest.java +212 −137 File changed.Preview size limit exceeded, changes collapsed. Show changes