Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ef1a30a6 authored by Joël Stemmer's avatar Joël Stemmer Committed by Android (Google) Code Review
Browse files

Merge "Fix formatting of BackupEligibilityRules and test" into main

parents 6266129d c080afdd
Loading
Loading
Loading
Loading
+96 −75
Original line number Original line Diff line number Diff line
@@ -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;


@@ -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));


@@ -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));


@@ -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)
@@ -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,
@@ -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"
@@ -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
@@ -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) {
@@ -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;
@@ -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;
                }
                }


@@ -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
@@ -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)
@@ -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) {
@@ -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:
@@ -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.
@@ -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) {
@@ -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) {