diff --git a/services/backup/java/com/android/server/backup/UserBackupManagerService.java b/services/backup/java/com/android/server/backup/UserBackupManagerService.java index 998c9c2278db4..7261709d7b8d6 100644 --- a/services/backup/java/com/android/server/backup/UserBackupManagerService.java +++ b/services/backup/java/com/android/server/backup/UserBackupManagerService.java @@ -551,7 +551,7 @@ public class UserBackupManagerService { mPackageManagerBinder = AppGlobals.getPackageManager(); mActivityManager = ActivityManager.getService(); mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class); - mScheduledBackupEligibility = getEligibilityRules(mPackageManager, userId, + mScheduledBackupEligibility = getEligibilityRules(mPackageManager, userId, mContext, BackupDestination.CLOUD); mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); @@ -4118,13 +4118,14 @@ public class UserBackupManagerService { public BackupEligibilityRules getEligibilityRulesForOperation( @BackupDestination int backupDestination) { - return getEligibilityRules(mPackageManager, mUserId, backupDestination); + return getEligibilityRules(mPackageManager, mUserId, mContext, backupDestination); } private static BackupEligibilityRules getEligibilityRules(PackageManager packageManager, - int userId, @BackupDestination int backupDestination) { + int userId, Context context, @BackupDestination int backupDestination) { return new BackupEligibilityRules(packageManager, - LocalServices.getService(PackageManagerInternal.class), userId, backupDestination); + LocalServices.getService(PackageManagerInternal.class), userId, context, + backupDestination); } /** Prints service state for 'dumpsys backup'. */ diff --git a/services/backup/java/com/android/server/backup/restore/PerformAdbRestoreTask.java b/services/backup/java/com/android/server/backup/restore/PerformAdbRestoreTask.java index 515a172721096..2374dee7755e2 100644 --- a/services/backup/java/com/android/server/backup/restore/PerformAdbRestoreTask.java +++ b/services/backup/java/com/android/server/backup/restore/PerformAdbRestoreTask.java @@ -112,7 +112,9 @@ public class PerformAdbRestoreTask implements Runnable { BackupEligibilityRules eligibilityRules = new BackupEligibilityRules( mBackupManagerService.getPackageManager(), LocalServices.getService(PackageManagerInternal.class), - mBackupManagerService.getUserId(), BackupDestination.ADB_BACKUP); + mBackupManagerService.getUserId(), + mBackupManagerService.getContext(), + BackupDestination.ADB_BACKUP); FullRestoreEngine mEngine = new FullRestoreEngine(mBackupManagerService, mOperationStorage, null, mObserver, null, null, true, 0 /*unused*/, true, eligibilityRules); diff --git a/services/backup/java/com/android/server/backup/utils/BackupEligibilityRules.java b/services/backup/java/com/android/server/backup/utils/BackupEligibilityRules.java index 2ee9174961364..7c47f1e477b61 100644 --- a/services/backup/java/com/android/server/backup/utils/BackupEligibilityRules.java +++ b/services/backup/java/com/android/server/backup/utils/BackupEligibilityRules.java @@ -31,6 +31,7 @@ import android.app.compat.CompatChanges; import android.compat.annotation.ChangeId; import android.compat.annotation.EnabledSince; import android.compat.annotation.Overridable; +import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; @@ -39,10 +40,12 @@ import android.content.pm.Signature; import android.content.pm.SigningInfo; import android.os.Build; import android.os.UserHandle; +import android.os.UserManager; import android.util.Slog; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.ArrayUtils; +import com.android.server.backup.SetUtils; import com.android.server.backup.transport.BackupTransportClient; import com.android.server.backup.transport.TransportConnection; @@ -56,13 +59,26 @@ import java.util.Set; */ public class BackupEligibilityRules { private static final boolean DEBUG = false; - // List of system packages that are eligible for backup in non-system users. - private static final Set systemPackagesAllowedForAllUsers = Sets.newArraySet( - PACKAGE_MANAGER_SENTINEL, PLATFORM_PACKAGE_NAME, WALLPAPER_PACKAGE, SETTINGS_PACKAGE); + + /** + * List of system packages that are eligible for backup in "profile" users (such as work + * profile). See {@link UserManager#isProfile()}. This is a subset of {@link + * #systemPackagesAllowedForNonSystemUsers} + */ + private static final Set 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 systemPackagesAllowedForNonSystemUsers = SetUtils.union( + systemPackagesAllowedForProfileUser, + Sets.newArraySet(WALLPAPER_PACKAGE, SETTINGS_PACKAGE)); private final PackageManager mPackageManager; private final PackageManagerInternal mPackageManagerInternal; private final int mUserId; + private boolean mIsProfileUser = false; @BackupDestination private final int mBackupDestination; /** @@ -85,19 +101,23 @@ public class BackupEligibilityRules { public static BackupEligibilityRules forBackup(PackageManager packageManager, PackageManagerInternal packageManagerInternal, - int userId) { - return new BackupEligibilityRules(packageManager, packageManagerInternal, userId, + int userId, + Context context) { + return new BackupEligibilityRules(packageManager, packageManagerInternal, userId, context, BackupDestination.CLOUD); } public BackupEligibilityRules(PackageManager packageManager, PackageManagerInternal packageManagerInternal, int userId, + Context context, @BackupDestination int backupDestination) { mPackageManager = packageManager; mPackageManagerInternal = packageManagerInternal; mUserId = userId; mBackupDestination = backupDestination; + UserManager userManager = context.getSystemService(UserManager.class); + mIsProfileUser = userManager.isProfile(); } /** @@ -125,11 +145,17 @@ 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 on a package that is not explicitly - // allowed. - if (mUserId != UserHandle.USER_SYSTEM - && !systemPackagesAllowedForAllUsers.contains(app.packageName)) { - return false; + // 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)) { + return false; + } + if (!mIsProfileUser && !systemPackagesAllowedForNonSystemUsers.contains( + app.packageName)) { + return false; + } } // or do not supply their own backup agent diff --git a/services/backup/java/com/android/server/backup/utils/RestoreUtils.java b/services/backup/java/com/android/server/backup/utils/RestoreUtils.java index 8e8bac435503b..0accb9fadd041 100644 --- a/services/backup/java/com/android/server/backup/utils/RestoreUtils.java +++ b/services/backup/java/com/android/server/backup/utils/RestoreUtils.java @@ -160,7 +160,8 @@ public class RestoreUtils { PackageManagerInternal pmi = LocalServices.getService( PackageManagerInternal.class); BackupEligibilityRules eligibilityRules = - BackupEligibilityRules.forBackup(packageManager, pmi, userId); + BackupEligibilityRules.forBackup(packageManager, pmi, userId, + context); if (eligibilityRules.signaturesMatch(sigs, pkg)) { // If this is a system-uid app without a declared backup agent, // don't restore any of the file data. diff --git a/services/backup/java/com/android/server/backup/utils/SetUtils.java b/services/backup/java/com/android/server/backup/utils/SetUtils.java new file mode 100644 index 0000000000000..ecd628fcaa974 --- /dev/null +++ b/services/backup/java/com/android/server/backup/utils/SetUtils.java @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.backup.utils; + +import java.util.HashSet; +import java.util.Set; + +/** + * Helper class containing common operation on {@link java.util.Set}. + */ +public final class SetUtils { + // Statics only + private SetUtils() {} + + /** + * Returns union of two sets. + */ + public static Set union(Set set1, Set set2) { + Set unionSet = new HashSet<>(set1); + unionSet.addAll(set2); + return unionSet; + } +} diff --git a/services/backup/java/com/android/server/backup/utils/TarBackupReader.java b/services/backup/java/com/android/server/backup/utils/TarBackupReader.java index 6963248734a3f..71ca8ca246046 100644 --- a/services/backup/java/com/android/server/backup/utils/TarBackupReader.java +++ b/services/backup/java/com/android/server/backup/utils/TarBackupReader.java @@ -47,6 +47,7 @@ import android.app.backup.BackupAgent; import android.app.backup.BackupManagerMonitor; import android.app.backup.FullBackup; import android.app.backup.IBackupManagerMonitor; +import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; @@ -384,13 +385,14 @@ public class TarBackupReader { * @param info - file metadata. * @param signatures - array of signatures parsed from backup file. * @param userId - ID of the user for which restore is performed. + * @param context - Context instance. * @return a restore policy constant. */ public RestorePolicy chooseRestorePolicy(PackageManager packageManager, boolean allowApks, FileMetadata info, Signature[] signatures, - PackageManagerInternal pmi, int userId) { + PackageManagerInternal pmi, int userId, Context context) { return chooseRestorePolicy(packageManager, allowApks, info, signatures, pmi, userId, - BackupEligibilityRules.forBackup(packageManager, pmi, userId)); + BackupEligibilityRules.forBackup(packageManager, pmi, userId, context)); } /** diff --git a/services/core/java/com/android/server/backup/SetUtils.java b/services/core/java/com/android/server/backup/SetUtils.java new file mode 100644 index 0000000000000..ae70e199cf5a7 --- /dev/null +++ b/services/core/java/com/android/server/backup/SetUtils.java @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.backup; + +import java.util.HashSet; +import java.util.Set; + +/** + * Helper class containing common operation on {@link java.util.Set}. + */ +public final class SetUtils { + // Statics only + private SetUtils() {} + + /** + * Returns union of two sets. + */ + public static Set union(Set set1, Set set2) { + Set unionSet = new HashSet<>(set1); + unionSet.addAll(set2); + return unionSet; + } +} diff --git a/services/core/java/com/android/server/backup/SystemBackupAgent.java b/services/core/java/com/android/server/backup/SystemBackupAgent.java index c0ea56169c15d..224e34da8d7e1 100644 --- a/services/core/java/com/android/server/backup/SystemBackupAgent.java +++ b/services/core/java/com/android/server/backup/SystemBackupAgent.java @@ -30,6 +30,7 @@ import android.os.ParcelFileDescriptor; import android.os.RemoteException; import android.os.ServiceManager; import android.os.UserHandle; +import android.os.UserManager; import android.util.Slog; import com.google.android.collect.Sets; @@ -84,30 +85,50 @@ public class SystemBackupAgent extends BackupAgentHelper { // Use old keys to keep legacy data compatibility and avoid writing two wallpapers private static final String WALLPAPER_IMAGE_KEY = WallpaperBackupHelper.WALLPAPER_IMAGE_KEY; - private static final Set sEligibleForMultiUser = Sets.newArraySet( - PERMISSION_HELPER, NOTIFICATION_HELPER, SYNC_SETTINGS_HELPER, APP_LOCALES_HELPER, - ACCOUNT_MANAGER_HELPER, USAGE_STATS_HELPER, PREFERRED_HELPER, SHORTCUT_MANAGER_HELPER - ); + /** + * Helpers that are enabled for "profile" users (such as work profile). See {@link + * UserManager#isProfile()}. This is a subset of {@link #sEligibleHelpersForNonSystemUser}. + */ + private static final Set sEligibleHelpersForProfileUser = + Sets.newArraySet( + PERMISSION_HELPER, + NOTIFICATION_HELPER, + SYNC_SETTINGS_HELPER, + APP_LOCALES_HELPER); + + /** Helpers that are enabled for full, non-system users. */ + private static final Set sEligibleHelpersForNonSystemUser = + SetUtils.union(sEligibleHelpersForProfileUser, + Sets.newArraySet(ACCOUNT_MANAGER_HELPER, USAGE_STATS_HELPER, PREFERRED_HELPER, + SHORTCUT_MANAGER_HELPER)); private int mUserId = UserHandle.USER_SYSTEM; + private boolean mIsProfileUser = false; @Override public void onCreate(UserHandle user, @BackupDestination int backupDestination) { super.onCreate(user, backupDestination); mUserId = user.getIdentifier(); + if (mUserId != UserHandle.USER_SYSTEM) { + Context context = createContextAsUser(user, /* flags= */ 0); + UserManager userManager = context.getSystemService(UserManager.class); + mIsProfileUser = userManager.isProfile(); + } - addHelper(SYNC_SETTINGS_HELPER, new AccountSyncSettingsBackupHelper(this, mUserId)); - addHelper(PREFERRED_HELPER, new PreferredActivityBackupHelper(mUserId)); - addHelper(NOTIFICATION_HELPER, new NotificationBackupHelper(mUserId)); - addHelper(PERMISSION_HELPER, new PermissionBackupHelper(mUserId)); - addHelper(USAGE_STATS_HELPER, new UsageStatsBackupHelper(mUserId)); - addHelper(SHORTCUT_MANAGER_HELPER, new ShortcutBackupHelper(mUserId)); - addHelper(ACCOUNT_MANAGER_HELPER, new AccountManagerBackupHelper(mUserId)); - addHelper(SLICES_HELPER, new SliceBackupHelper(this)); - addHelper(PEOPLE_HELPER, new PeopleBackupHelper(mUserId)); - addHelper(APP_LOCALES_HELPER, new AppSpecificLocalesBackupHelper(mUserId)); - addHelper(APP_GENDER_HELPER, new AppGrammaticalGenderBackupHelper(mUserId)); + addHelperIfEligibleForUser( + SYNC_SETTINGS_HELPER, new AccountSyncSettingsBackupHelper(this, mUserId)); + addHelperIfEligibleForUser(PREFERRED_HELPER, new PreferredActivityBackupHelper(mUserId)); + addHelperIfEligibleForUser(NOTIFICATION_HELPER, new NotificationBackupHelper(mUserId)); + addHelperIfEligibleForUser(PERMISSION_HELPER, new PermissionBackupHelper(mUserId)); + addHelperIfEligibleForUser(USAGE_STATS_HELPER, new UsageStatsBackupHelper(mUserId)); + addHelperIfEligibleForUser(SHORTCUT_MANAGER_HELPER, new ShortcutBackupHelper(mUserId)); + addHelperIfEligibleForUser(ACCOUNT_MANAGER_HELPER, new AccountManagerBackupHelper(mUserId)); + addHelperIfEligibleForUser(SLICES_HELPER, new SliceBackupHelper(this)); + addHelperIfEligibleForUser(PEOPLE_HELPER, new PeopleBackupHelper(mUserId)); + addHelperIfEligibleForUser(APP_LOCALES_HELPER, new AppSpecificLocalesBackupHelper(mUserId)); + addHelperIfEligibleForUser(APP_GENDER_HELPER, + new AppGrammaticalGenderBackupHelper(mUserId)); } @Override @@ -131,15 +152,6 @@ public class SystemBackupAgent extends BackupAgentHelper { super.onRestore(data, appVersionCode, newState); } - @Override - public void addHelper(String keyPrefix, BackupHelper helper) { - if (mUserId != UserHandle.USER_SYSTEM && !sEligibleForMultiUser.contains(keyPrefix)) { - return; - } - - super.addHelper(keyPrefix, helper); - } - /** * Support for 'adb restore' of legacy archives */ @@ -190,4 +202,25 @@ public class SystemBackupAgent extends BackupAgentHelper { } } } + + private void addHelperIfEligibleForUser(String keyPrefix, BackupHelper helper) { + if (isHelperEligibleForUser(keyPrefix)) { + addHelper(keyPrefix, helper); + } + } + + private boolean isHelperEligibleForUser(String keyPrefix) { + // All helpers are eligible for the system user. + if (mUserId == UserHandle.USER_SYSTEM) { + return true; + } + + // Profile users (such as work profile) have their own allow list. + if (mIsProfileUser) { + return sEligibleHelpersForProfileUser.contains(keyPrefix); + } + + // Full, non-system users have their own allow list. + return sEligibleHelpersForNonSystemUser.contains(keyPrefix); + } } diff --git a/services/robotests/backup/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java b/services/robotests/backup/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java index 1abcf38baff97..bfbc0f50f67ad 100644 --- a/services/robotests/backup/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java +++ b/services/robotests/backup/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java @@ -267,7 +267,7 @@ public class KeyValueBackupTaskTest { LocalServices.removeServiceForTest(PackageManagerInternal.class); LocalServices.addService(PackageManagerInternal.class, mPackageManagerInternal); mBackupEligibilityRules = new BackupEligibilityRules(mPackageManager, - LocalServices.getService(PackageManagerInternal.class), USER_ID, + LocalServices.getService(PackageManagerInternal.class), USER_ID, mContext, BACKUP_DESTINATION); } diff --git a/services/tests/mockingservicestests/src/com/android/server/backup/SystemBackupAgentTest.java b/services/tests/mockingservicestests/src/com/android/server/backup/SystemBackupAgentTest.java new file mode 100644 index 0000000000000..327fc194fc4ff --- /dev/null +++ b/services/tests/mockingservicestests/src/com/android/server/backup/SystemBackupAgentTest.java @@ -0,0 +1,134 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.backup; + +import static com.google.common.truth.Truth.assertThat; + +import android.annotation.NonNull; +import android.app.backup.BackupHelper; +import android.content.Context; +import android.os.UserHandle; +import android.os.UserManager; +import android.platform.test.annotations.Presubmit; +import android.util.ArraySet; + +import static org.mockito.Mockito.when; + +import androidx.test.ext.junit.runners.AndroidJUnit4; +import androidx.test.filters.SmallTest; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import java.util.Set; + +@SmallTest +@Presubmit +@RunWith(AndroidJUnit4.class) +public class SystemBackupAgentTest { + private static final int NON_SYSTEM_USER_ID = 10; + + private TestableSystemBackupAgent mSystemBackupAgent; + + @Mock private Context mContextMock; + @Mock private UserManager mUserManagerMock; + + @Before + public void setUp() throws Exception { + MockitoAnnotations.initMocks(this); + mSystemBackupAgent = new TestableSystemBackupAgent(); + when(mContextMock.getSystemService(UserManager.class)).thenReturn(mUserManagerMock); + } + + @Test + public void onCreate_systemUser_addsAllHelpers() { + UserHandle userHandle = new UserHandle(UserHandle.USER_SYSTEM); + when(mUserManagerMock.isProfile()).thenReturn(false); + + mSystemBackupAgent.onCreate(userHandle, /* backupDestination= */ 0); + + assertThat(mSystemBackupAgent.mAddedHelpers) + .containsExactly( + "account_sync_settings", + "preferred_activities", + "notifications", + "permissions", + "usage_stats", + "shortcut_manager", + "account_manager", + "slices", + "people", + "app_locales", + "app_gender"); + } + + @Test + public void onCreate_profileUser_addsProfileEligibleHelpers() { + UserHandle userHandle = new UserHandle(NON_SYSTEM_USER_ID); + when(mUserManagerMock.isProfile()).thenReturn(true); + + mSystemBackupAgent.onCreate(userHandle, /* backupDestination= */ 0); + + assertThat(mSystemBackupAgent.mAddedHelpers) + .containsExactly( + "account_sync_settings", + "notifications", + "permissions", + "app_locales"); + } + + @Test + public void onCreate_nonSystemUser_addsNonSystemEligibleHelpers() { + UserHandle userHandle = new UserHandle(NON_SYSTEM_USER_ID); + when(mUserManagerMock.isProfile()).thenReturn(false); + + mSystemBackupAgent.onCreate(userHandle, /* backupDestination= */ 0); + + assertThat(mSystemBackupAgent.mAddedHelpers) + .containsExactly( + "account_sync_settings", + "preferred_activities", + "notifications", + "permissions", + "app_locales", + "account_manager", + "usage_stats", + "shortcut_manager"); + } + + private class TestableSystemBackupAgent extends SystemBackupAgent { + final Set mAddedHelpers = new ArraySet<>(); + + @Override + public void addHelper(String keyPrefix, BackupHelper helper) { + mAddedHelpers.add(keyPrefix); + } + + @Override + public Context createContextAsUser(UserHandle user, @CreatePackageOptions int flags) { + return mContextMock; + } + + @Override + public Object getSystemService(@ServiceName @NonNull String name) { + return null; + } + } +} diff --git a/services/tests/mockingservicestests/src/com/android/server/backup/utils/BackupEligibilityRulesTest.java b/services/tests/mockingservicestests/src/com/android/server/backup/utils/BackupEligibilityRulesTest.java index 6093f4b204d21..030665537c38e 100644 --- a/services/tests/mockingservicestests/src/com/android/server/backup/utils/BackupEligibilityRulesTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/backup/utils/BackupEligibilityRulesTest.java @@ -25,6 +25,7 @@ import static org.mockito.Mockito.when; import android.app.backup.BackupAnnotations.BackupDestination; import android.compat.testing.PlatformCompatChangeRule; +import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; @@ -35,6 +36,7 @@ import android.content.pm.SigningDetails; import android.content.pm.SigningInfo; import android.os.Process; import android.os.UserHandle; +import android.os.UserManager; import android.platform.test.annotations.Presubmit; import androidx.test.filters.SmallTest; @@ -64,11 +66,17 @@ 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 = 10; @Rule public TestRule compatChangeRule = new PlatformCompatChangeRule(); @Mock private PackageManagerInternal mMockPackageManagerInternal; - @Mock private PackageManager mPackageManager; + @Mock + private PackageManager mPackageManager; + @Mock + private Context mContext; + @Mock + private UserManager mUserManager; private BackupEligibilityRules mBackupEligibilityRules; private int mUserId; @@ -78,6 +86,7 @@ public class BackupEligibilityRulesTest { MockitoAnnotations.initMocks(this); mUserId = UserHandle.USER_SYSTEM; + mockContextForFullUser(); mBackupEligibilityRules = getBackupEligibilityRules(BackupDestination.CLOUD); } @@ -94,6 +103,70 @@ public class BackupEligibilityRulesTest { assertThat(isEligible).isFalse(); } + @Test + public void appIsEligibleForBackup_systemUid_nonSystemUser_notAllowedPackage_returnsFalse() + throws Exception { + setUpForNonSystemUser(); + + ApplicationInfo applicationInfo = new ApplicationInfo(); + applicationInfo.flags |= ApplicationInfo.FLAG_ALLOW_BACKUP; + applicationInfo.uid = Process.SYSTEM_UID; + applicationInfo.backupAgentName = CUSTOM_BACKUP_AGENT_NAME; + applicationInfo.packageName = TEST_PACKAGE_NAME; + + boolean isEligible = mBackupEligibilityRules.appIsEligibleForBackup(applicationInfo); + + assertThat(isEligible).isFalse(); + } + + @Test + public void appIsEligibleForBackup_systemUid_nonSystemUser_allowedPackage_returnsTrue() + throws Exception { + setUpForNonSystemUser(); + + ApplicationInfo applicationInfo = new ApplicationInfo(); + applicationInfo.flags |= ApplicationInfo.FLAG_ALLOW_BACKUP; + applicationInfo.uid = Process.SYSTEM_UID; + applicationInfo.backupAgentName = CUSTOM_BACKUP_AGENT_NAME; + applicationInfo.packageName = UserBackupManagerService.WALLPAPER_PACKAGE; + + boolean isEligible = mBackupEligibilityRules.appIsEligibleForBackup(applicationInfo); + + assertThat(isEligible).isTrue(); + } + + @Test + public void appIsEligibleForBackup_systemUid_profileUser_notAllowedPackage_returnsFalse() + throws Exception { + setUpForProfileUser(); + + ApplicationInfo applicationInfo = new ApplicationInfo(); + applicationInfo.flags |= ApplicationInfo.FLAG_ALLOW_BACKUP; + applicationInfo.uid = Process.SYSTEM_UID; + applicationInfo.backupAgentName = CUSTOM_BACKUP_AGENT_NAME; + applicationInfo.packageName = TEST_PACKAGE_NAME; + + boolean isEligible = mBackupEligibilityRules.appIsEligibleForBackup(applicationInfo); + + assertThat(isEligible).isFalse(); + } + + @Test + public void appIsEligibleForBackup_systemUid_profileUser_allowedPackage_returnsTrue() + throws Exception { + setUpForProfileUser(); + + ApplicationInfo applicationInfo = new ApplicationInfo(); + applicationInfo.flags |= ApplicationInfo.FLAG_ALLOW_BACKUP; + applicationInfo.uid = Process.SYSTEM_UID; + applicationInfo.backupAgentName = CUSTOM_BACKUP_AGENT_NAME; + applicationInfo.packageName = UserBackupManagerService.PACKAGE_MANAGER_SENTINEL; + + boolean isEligible = mBackupEligibilityRules.appIsEligibleForBackup(applicationInfo); + + assertThat(isEligible).isTrue(); + } + @Test public void appIsEligibleForBackup_systemAppWithoutCustomBackupAgent_returnsFalse() throws Exception { @@ -790,7 +863,7 @@ public class BackupEligibilityRulesTest { private BackupEligibilityRules getBackupEligibilityRules( @BackupDestination int backupDestination) { return new BackupEligibilityRules(mPackageManager, mMockPackageManagerInternal, mUserId, - backupDestination); + mContext, backupDestination); } private static Signature generateSignature(byte i) { @@ -813,4 +886,26 @@ public class BackupEligibilityRulesTest { return new Property(PackageManager.PROPERTY_ALLOW_ADB_BACKUP, allowAdbBackup, TEST_PACKAGE_NAME, /* className */ ""); } + + private void setUpForNonSystemUser() { + mUserId = NON_SYSTEM_USER; + mockContextForFullUser(); + mBackupEligibilityRules = getBackupEligibilityRules(BackupDestination.CLOUD); + } + + private void setUpForProfileUser() { + mUserId = NON_SYSTEM_USER; + mockContextForProfile(); + mBackupEligibilityRules = getBackupEligibilityRules(BackupDestination.CLOUD); + } + + private void mockContextForProfile() { + when(mUserManager.isProfile()).thenReturn(true); + when(mContext.getSystemService(UserManager.class)).thenReturn(mUserManager); + } + + private void mockContextForFullUser() { + when(mUserManager.isProfile()).thenReturn(false); + when(mContext.getSystemService(UserManager.class)).thenReturn(mUserManager); + } } diff --git a/services/tests/mockingservicestests/src/com/android/server/backup/utils/TarBackupReaderTest.java b/services/tests/mockingservicestests/src/com/android/server/backup/utils/TarBackupReaderTest.java index 30c69758495c7..33995653870e6 100644 --- a/services/tests/mockingservicestests/src/com/android/server/backup/utils/TarBackupReaderTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/backup/utils/TarBackupReaderTest.java @@ -149,7 +149,7 @@ public class TarBackupReaderTest { fileMetadata); RestorePolicy restorePolicy = tarBackupReader.chooseRestorePolicy( mPackageManagerStub, false /* allowApks */, fileMetadata, signatures, - mMockPackageManagerInternal, mUserId); + mMockPackageManagerInternal, mUserId, mContext); assertThat(restorePolicy).isEqualTo(RestorePolicy.IGNORE); assertThat(fileMetadata.packageName).isEqualTo(TEST_PACKAGE_NAME); @@ -163,7 +163,7 @@ public class TarBackupReaderTest { fileMetadata); restorePolicy = tarBackupReader.chooseRestorePolicy( mPackageManagerStub, false /* allowApks */, fileMetadata, signatures, - mMockPackageManagerInternal, mUserId); + mMockPackageManagerInternal, mUserId, mContext); assertThat(restorePolicy).isEqualTo(RestorePolicy.IGNORE); assertThat(fileMetadata.packageName).isEqualTo(TEST_PACKAGE_NAME); @@ -226,7 +226,7 @@ public class TarBackupReaderTest { RestorePolicy policy = tarBackupReader.chooseRestorePolicy(mPackageManagerStub, true /* allowApks */, new FileMetadata(), null /* signatures */, - mMockPackageManagerInternal, mUserId); + mMockPackageManagerInternal, mUserId, mContext); assertThat(policy).isEqualTo(RestorePolicy.IGNORE); verifyZeroInteractions(mBackupManagerMonitorMock); @@ -247,7 +247,7 @@ public class TarBackupReaderTest { RestorePolicy policy = tarBackupReader.chooseRestorePolicy(mPackageManagerStub, true /* allowApks */, info, new Signature[0] /* signatures */, - mMockPackageManagerInternal, mUserId); + mMockPackageManagerInternal, mUserId, mContext); assertThat(policy).isEqualTo(RestorePolicy.ACCEPT_IF_APK); ArgumentCaptor bundleCaptor = ArgumentCaptor.forClass(Bundle.class); @@ -272,7 +272,7 @@ public class TarBackupReaderTest { RestorePolicy policy = tarBackupReader.chooseRestorePolicy(mPackageManagerStub, true /* allowApks */, info, new Signature[0] /* signatures */, - mMockPackageManagerInternal, mUserId); + mMockPackageManagerInternal, mUserId, mContext); assertThat(policy).isEqualTo(RestorePolicy.ACCEPT_IF_APK); ArgumentCaptor bundleCaptor = ArgumentCaptor.forClass(Bundle.class); @@ -298,7 +298,7 @@ public class TarBackupReaderTest { RestorePolicy policy = tarBackupReader.chooseRestorePolicy(mPackageManagerStub, false /* allowApks */, new FileMetadata(), new Signature[0] /* signatures */, - mMockPackageManagerInternal, mUserId); + mMockPackageManagerInternal, mUserId, mContext); assertThat(policy).isEqualTo(RestorePolicy.IGNORE); ArgumentCaptor bundleCaptor = ArgumentCaptor.forClass(Bundle.class); @@ -323,7 +323,7 @@ public class TarBackupReaderTest { RestorePolicy policy = tarBackupReader.chooseRestorePolicy(mPackageManagerStub, false /* allowApks */, new FileMetadata(), new Signature[0] /* signatures */, - mMockPackageManagerInternal, mUserId); + mMockPackageManagerInternal, mUserId, mContext); assertThat(policy).isEqualTo(RestorePolicy.IGNORE); ArgumentCaptor bundleCaptor = ArgumentCaptor.forClass(Bundle.class); @@ -350,7 +350,7 @@ public class TarBackupReaderTest { RestorePolicy policy = tarBackupReader.chooseRestorePolicy(mPackageManagerStub, false /* allowApks */, new FileMetadata(), new Signature[0] /* signatures */, - mMockPackageManagerInternal, mUserId); + mMockPackageManagerInternal, mUserId, mContext); assertThat(policy).isEqualTo(RestorePolicy.IGNORE); ArgumentCaptor bundleCaptor = ArgumentCaptor.forClass(Bundle.class); @@ -385,7 +385,7 @@ public class TarBackupReaderTest { RestorePolicy policy = tarBackupReader.chooseRestorePolicy(mPackageManagerStub, false /* allowApks */, new FileMetadata(), signatures, - mMockPackageManagerInternal, mUserId); + mMockPackageManagerInternal, mUserId, mContext); assertThat(policy).isEqualTo(RestorePolicy.IGNORE); ArgumentCaptor bundleCaptor = ArgumentCaptor.forClass(Bundle.class); @@ -424,7 +424,7 @@ public class TarBackupReaderTest { packageInfo.packageName); RestorePolicy policy = tarBackupReader.chooseRestorePolicy(mPackageManagerStub, false /* allowApks */, new FileMetadata(), signatures, - mMockPackageManagerInternal, mUserId); + mMockPackageManagerInternal, mUserId, mContext); assertThat(policy).isEqualTo(RestorePolicy.ACCEPT); ArgumentCaptor bundleCaptor = ArgumentCaptor.forClass(Bundle.class); @@ -462,7 +462,7 @@ public class TarBackupReaderTest { packageInfo.packageName); RestorePolicy policy = tarBackupReader.chooseRestorePolicy(mPackageManagerStub, false /* allowApks */, new FileMetadata(), signatures, - mMockPackageManagerInternal, mUserId); + mMockPackageManagerInternal, mUserId, mContext); assertThat(policy).isEqualTo(RestorePolicy.ACCEPT); ArgumentCaptor bundleCaptor = ArgumentCaptor.forClass(Bundle.class); @@ -504,7 +504,7 @@ public class TarBackupReaderTest { packageInfo.packageName); RestorePolicy policy = tarBackupReader.chooseRestorePolicy(mPackageManagerStub, false /* allowApks */, info, signatures, mMockPackageManagerInternal, - mUserId); + mUserId, mContext); assertThat(policy).isEqualTo(RestorePolicy.ACCEPT); ArgumentCaptor bundleCaptor = ArgumentCaptor.forClass(Bundle.class); @@ -548,7 +548,7 @@ public class TarBackupReaderTest { packageInfo.packageName); RestorePolicy policy = tarBackupReader.chooseRestorePolicy(mPackageManagerStub, true /* allowApks */, info, signatures, mMockPackageManagerInternal, - mUserId); + mUserId, mContext); assertThat(policy).isEqualTo(RestorePolicy.ACCEPT_IF_APK); verifyNoMoreInteractions(mBackupManagerMonitorMock); @@ -588,7 +588,7 @@ public class TarBackupReaderTest { packageInfo.packageName); RestorePolicy policy = tarBackupReader.chooseRestorePolicy(mPackageManagerStub, false /* allowApks */, info, signatures, mMockPackageManagerInternal, - mUserId); + mUserId, mContext); assertThat(policy).isEqualTo(RestorePolicy.IGNORE); ArgumentCaptor bundleCaptor = ArgumentCaptor.forClass(Bundle.class);