Loading services/backup/java/com/android/server/backup/utils/BackupEligibilityRules.java +41 −20 Original line number Diff line number Diff line Loading @@ -76,16 +76,18 @@ public class BackupEligibilityRules { systemPackagesAllowedForProfileUser, Sets.newArraySet(WALLPAPER_PACKAGE, SETTINGS_PACKAGE)); static { if (UserManager.isHeadlessSystemUserMode()) { systemPackagesAllowedForNonSystemUsers.add(TELEPHONY_PROVIDER_PACKAGE); } } /** * 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( systemPackagesAllowedForNonSystemUsers, Sets.newArraySet(TELEPHONY_PROVIDER_PACKAGE)); private final PackageManager mPackageManager; private final PackageManagerInternal mPackageManagerInternal; private final UserManager mUserManager; private final int mUserId; private boolean mIsProfileUser = false; @BackupDestination private final int mBackupDestination; private final boolean mSkipRestoreForLaunchedApps; Loading Loading @@ -134,8 +136,7 @@ public class BackupEligibilityRules { mPackageManagerInternal = packageManagerInternal; mUserId = userId; mBackupDestination = backupDestination; UserManager userManager = context.getSystemService(UserManager.class); mIsProfileUser = userManager.isProfile(); mUserManager = context.getSystemService(UserManager.class); mSkipRestoreForLaunchedApps = skipRestoreForLaunchedApps; } Loading Loading @@ -167,20 +168,13 @@ public class BackupEligibilityRules { // 2. they run as a system-level uid if (UserHandle.isCore(app.uid)) { // and the backup is happening for a non-system user or profile on a package that is // not explicitly allowed. if (mUserId != UserHandle.USER_SYSTEM) { if (mIsProfileUser && !systemPackagesAllowedForProfileUser.contains( app.packageName)) { // System apps are additionally checked: // ...if not allowed for the current user (governed by user-specific allowlists) if (!isSystemPackageAllowedForCurrentUser(app.packageName)) { return false; } if (!mIsProfileUser && !systemPackagesAllowedForNonSystemUsers.contains( app.packageName)) { return false; } } // or do not supply their own backup agent // ...or do not supply their own backup agent if (app.backupAgentName == null) { return false; } Loading @@ -199,6 +193,33 @@ public class BackupEligibilityRules { return !appIsDisabled(app); } /** * 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) { if (mUserId == UserHandle.USER_SYSTEM) { return true; } if (mUserManager.isProfile()) { return systemPackagesAllowedForProfileUser.contains(packageName); } // In Headless System User Mode, certain packages are only backed up for the main user. if (UserManager.isHeadlessSystemUserMode()) { UserHandle mainUser = mUserManager.getMainUser(); if (mainUser != null && mainUser.getIdentifier() == mUserId) { return systemPackagesAllowedForHsumMainUser.contains(packageName); } } // Default allowlist for other non-system users (including non-main users in HSUM). return systemPackagesAllowedForNonSystemUsers.contains(packageName); } /** * Check if this app allows backup. Apps can opt out of backup by stating * android:allowBackup="false" in their manifest. However, this flag is ignored for non-system Loading services/tests/mockingservicestests/src/com/android/server/backup/utils/BackupEligibilityRulesTest.java +61 −3 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ package com.android.server.backup.utils; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.eq; Loading @@ -42,6 +44,7 @@ import android.platform.test.annotations.Presubmit; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; import com.android.modules.utils.testing.ExtendedMockitoRule; import com.android.server.backup.UserBackupManagerService; import libcore.junit.util.compat.CoreCompatChangeRule.DisableCompatChanges; Loading @@ -53,7 +56,7 @@ import org.junit.Test; import org.junit.rules.TestRule; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.mockito.quality.Strictness; @SmallTest @Presubmit Loading @@ -66,10 +69,16 @@ public class BackupEligibilityRulesTest { private static final Signature SIGNATURE_2 = generateSignature((byte) 2); private static final Signature SIGNATURE_3 = generateSignature((byte) 3); private static final Signature SIGNATURE_4 = generateSignature((byte) 4); private static final int NON_SYSTEM_USER_ID = 10; private static final UserHandle NON_SYSTEM_USER = UserHandle.of(NON_SYSTEM_USER_ID); @Rule public TestRule compatChangeRule = new PlatformCompatChangeRule(); @Rule public final ExtendedMockitoRule extendedMockitoRule = new ExtendedMockitoRule.Builder(this) .setStrictness(Strictness.LENIENT).spyStatic(UserManager.class).build(); @Mock private PackageManagerInternal mMockPackageManagerInternal; @Mock private PackageManager mPackageManager; @Mock private Context mContext; Loading @@ -80,9 +89,8 @@ public class BackupEligibilityRulesTest { @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); mUserId = UserHandle.USER_SYSTEM; mockHeadlessSystemUserMode(false); mockContextForFullUser(); mBackupEligibilityRules = getBackupEligibilityRules(BackupDestination.CLOUD); } Loading @@ -100,6 +108,7 @@ public class BackupEligibilityRulesTest { @Test public void appIsEligibleForBackup_systemUid_nonSystemUser_notAllowedPackage_returnsFalse() throws Exception { mockHeadlessSystemUserMode(false); setUpForNonSystemUser(); ApplicationInfo applicationInfo = Loading @@ -113,6 +122,7 @@ public class BackupEligibilityRulesTest { @Test public void appIsEligibleForBackup_systemUid_nonSystemUser_allowedPackage_returnsTrue() throws Exception { mockHeadlessSystemUserMode(false); setUpForNonSystemUser(); ApplicationInfo applicationInfo = getApplicationInfo( Loading @@ -124,6 +134,50 @@ public class BackupEligibilityRulesTest { assertThat(isEligible).isTrue(); } @Test public void appIsEligibleForBackup_systemUid_hsumMainUser_telephonyPackage_returnsTrue() throws Exception { mockHeadlessSystemUserMode(true); // Current user is the main user. when(mUserManager.getMainUser()).thenReturn(NON_SYSTEM_USER); mUserId = NON_SYSTEM_USER_ID; mockContextForFullUser(); mBackupEligibilityRules = getBackupEligibilityRules(BackupDestination.CLOUD); ApplicationInfo applicationInfo = getApplicationInfo( Process.SYSTEM_UID, ApplicationInfo.FLAG_ALLOW_BACKUP, CUSTOM_BACKUP_AGENT_NAME, UserBackupManagerService.TELEPHONY_PROVIDER_PACKAGE); boolean isEligible = mBackupEligibilityRules.appIsEligibleForBackup(applicationInfo); // Telephony package is allowed for the main user in HSUM. assertThat(isEligible).isTrue(); } @Test public void appIsEligibleForBackup_systemUid_hsumNonMainUser_telephonyPackage_returnsFalse() throws Exception { mockHeadlessSystemUserMode(true); // Current user is a non-main user. when(mUserManager.getMainUser()).thenReturn(NON_SYSTEM_USER); mUserId = NON_SYSTEM_USER_ID + 1; mockContextForFullUser(); mBackupEligibilityRules = getBackupEligibilityRules(BackupDestination.CLOUD); ApplicationInfo applicationInfo = getApplicationInfo( Process.SYSTEM_UID, ApplicationInfo.FLAG_ALLOW_BACKUP, CUSTOM_BACKUP_AGENT_NAME, UserBackupManagerService.TELEPHONY_PROVIDER_PACKAGE); boolean isEligible = mBackupEligibilityRules.appIsEligibleForBackup(applicationInfo); // Telephony package is not allowed for non-main users in HSUM. assertThat(isEligible).isFalse(); } @Test public void appIsEligibleForBackup_systemUid_profileUser_notAllowedPackage_returnsFalse() throws Exception { Loading Loading @@ -865,6 +919,10 @@ public class BackupEligibilityRulesTest { backupDestination, skipRestoreForLaunchedApps); } private static void mockHeadlessSystemUserMode(boolean isHeadless) { doReturn(isHeadless).when(UserManager::isHeadlessSystemUserMode); } private static Signature generateSignature(byte i) { byte[] signatureBytes = new byte[256]; signatureBytes[0] = i; Loading Loading
services/backup/java/com/android/server/backup/utils/BackupEligibilityRules.java +41 −20 Original line number Diff line number Diff line Loading @@ -76,16 +76,18 @@ public class BackupEligibilityRules { systemPackagesAllowedForProfileUser, Sets.newArraySet(WALLPAPER_PACKAGE, SETTINGS_PACKAGE)); static { if (UserManager.isHeadlessSystemUserMode()) { systemPackagesAllowedForNonSystemUsers.add(TELEPHONY_PROVIDER_PACKAGE); } } /** * 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( systemPackagesAllowedForNonSystemUsers, Sets.newArraySet(TELEPHONY_PROVIDER_PACKAGE)); private final PackageManager mPackageManager; private final PackageManagerInternal mPackageManagerInternal; private final UserManager mUserManager; private final int mUserId; private boolean mIsProfileUser = false; @BackupDestination private final int mBackupDestination; private final boolean mSkipRestoreForLaunchedApps; Loading Loading @@ -134,8 +136,7 @@ public class BackupEligibilityRules { mPackageManagerInternal = packageManagerInternal; mUserId = userId; mBackupDestination = backupDestination; UserManager userManager = context.getSystemService(UserManager.class); mIsProfileUser = userManager.isProfile(); mUserManager = context.getSystemService(UserManager.class); mSkipRestoreForLaunchedApps = skipRestoreForLaunchedApps; } Loading Loading @@ -167,20 +168,13 @@ public class BackupEligibilityRules { // 2. they run as a system-level uid if (UserHandle.isCore(app.uid)) { // and the backup is happening for a non-system user or profile on a package that is // not explicitly allowed. if (mUserId != UserHandle.USER_SYSTEM) { if (mIsProfileUser && !systemPackagesAllowedForProfileUser.contains( app.packageName)) { // System apps are additionally checked: // ...if not allowed for the current user (governed by user-specific allowlists) if (!isSystemPackageAllowedForCurrentUser(app.packageName)) { return false; } if (!mIsProfileUser && !systemPackagesAllowedForNonSystemUsers.contains( app.packageName)) { return false; } } // or do not supply their own backup agent // ...or do not supply their own backup agent if (app.backupAgentName == null) { return false; } Loading @@ -199,6 +193,33 @@ public class BackupEligibilityRules { return !appIsDisabled(app); } /** * 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) { if (mUserId == UserHandle.USER_SYSTEM) { return true; } if (mUserManager.isProfile()) { return systemPackagesAllowedForProfileUser.contains(packageName); } // In Headless System User Mode, certain packages are only backed up for the main user. if (UserManager.isHeadlessSystemUserMode()) { UserHandle mainUser = mUserManager.getMainUser(); if (mainUser != null && mainUser.getIdentifier() == mUserId) { return systemPackagesAllowedForHsumMainUser.contains(packageName); } } // Default allowlist for other non-system users (including non-main users in HSUM). return systemPackagesAllowedForNonSystemUsers.contains(packageName); } /** * Check if this app allows backup. Apps can opt out of backup by stating * android:allowBackup="false" in their manifest. However, this flag is ignored for non-system Loading
services/tests/mockingservicestests/src/com/android/server/backup/utils/BackupEligibilityRulesTest.java +61 −3 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ package com.android.server.backup.utils; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.eq; Loading @@ -42,6 +44,7 @@ import android.platform.test.annotations.Presubmit; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; import com.android.modules.utils.testing.ExtendedMockitoRule; import com.android.server.backup.UserBackupManagerService; import libcore.junit.util.compat.CoreCompatChangeRule.DisableCompatChanges; Loading @@ -53,7 +56,7 @@ import org.junit.Test; import org.junit.rules.TestRule; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.mockito.quality.Strictness; @SmallTest @Presubmit Loading @@ -66,10 +69,16 @@ public class BackupEligibilityRulesTest { private static final Signature SIGNATURE_2 = generateSignature((byte) 2); private static final Signature SIGNATURE_3 = generateSignature((byte) 3); private static final Signature SIGNATURE_4 = generateSignature((byte) 4); private static final int NON_SYSTEM_USER_ID = 10; private static final UserHandle NON_SYSTEM_USER = UserHandle.of(NON_SYSTEM_USER_ID); @Rule public TestRule compatChangeRule = new PlatformCompatChangeRule(); @Rule public final ExtendedMockitoRule extendedMockitoRule = new ExtendedMockitoRule.Builder(this) .setStrictness(Strictness.LENIENT).spyStatic(UserManager.class).build(); @Mock private PackageManagerInternal mMockPackageManagerInternal; @Mock private PackageManager mPackageManager; @Mock private Context mContext; Loading @@ -80,9 +89,8 @@ public class BackupEligibilityRulesTest { @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); mUserId = UserHandle.USER_SYSTEM; mockHeadlessSystemUserMode(false); mockContextForFullUser(); mBackupEligibilityRules = getBackupEligibilityRules(BackupDestination.CLOUD); } Loading @@ -100,6 +108,7 @@ public class BackupEligibilityRulesTest { @Test public void appIsEligibleForBackup_systemUid_nonSystemUser_notAllowedPackage_returnsFalse() throws Exception { mockHeadlessSystemUserMode(false); setUpForNonSystemUser(); ApplicationInfo applicationInfo = Loading @@ -113,6 +122,7 @@ public class BackupEligibilityRulesTest { @Test public void appIsEligibleForBackup_systemUid_nonSystemUser_allowedPackage_returnsTrue() throws Exception { mockHeadlessSystemUserMode(false); setUpForNonSystemUser(); ApplicationInfo applicationInfo = getApplicationInfo( Loading @@ -124,6 +134,50 @@ public class BackupEligibilityRulesTest { assertThat(isEligible).isTrue(); } @Test public void appIsEligibleForBackup_systemUid_hsumMainUser_telephonyPackage_returnsTrue() throws Exception { mockHeadlessSystemUserMode(true); // Current user is the main user. when(mUserManager.getMainUser()).thenReturn(NON_SYSTEM_USER); mUserId = NON_SYSTEM_USER_ID; mockContextForFullUser(); mBackupEligibilityRules = getBackupEligibilityRules(BackupDestination.CLOUD); ApplicationInfo applicationInfo = getApplicationInfo( Process.SYSTEM_UID, ApplicationInfo.FLAG_ALLOW_BACKUP, CUSTOM_BACKUP_AGENT_NAME, UserBackupManagerService.TELEPHONY_PROVIDER_PACKAGE); boolean isEligible = mBackupEligibilityRules.appIsEligibleForBackup(applicationInfo); // Telephony package is allowed for the main user in HSUM. assertThat(isEligible).isTrue(); } @Test public void appIsEligibleForBackup_systemUid_hsumNonMainUser_telephonyPackage_returnsFalse() throws Exception { mockHeadlessSystemUserMode(true); // Current user is a non-main user. when(mUserManager.getMainUser()).thenReturn(NON_SYSTEM_USER); mUserId = NON_SYSTEM_USER_ID + 1; mockContextForFullUser(); mBackupEligibilityRules = getBackupEligibilityRules(BackupDestination.CLOUD); ApplicationInfo applicationInfo = getApplicationInfo( Process.SYSTEM_UID, ApplicationInfo.FLAG_ALLOW_BACKUP, CUSTOM_BACKUP_AGENT_NAME, UserBackupManagerService.TELEPHONY_PROVIDER_PACKAGE); boolean isEligible = mBackupEligibilityRules.appIsEligibleForBackup(applicationInfo); // Telephony package is not allowed for non-main users in HSUM. assertThat(isEligible).isFalse(); } @Test public void appIsEligibleForBackup_systemUid_profileUser_notAllowedPackage_returnsFalse() throws Exception { Loading Loading @@ -865,6 +919,10 @@ public class BackupEligibilityRulesTest { backupDestination, skipRestoreForLaunchedApps); } private static void mockHeadlessSystemUserMode(boolean isHeadless) { doReturn(isHeadless).when(UserManager::isHeadlessSystemUserMode); } private static Signature generateSignature(byte i) { byte[] signatureBytes = new byte[256]; signatureBytes[0] = i; Loading