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