From 702ce6c27cf447fedffe8927497ae41e0c5328b7 Mon Sep 17 00:00:00 2001 From: "[CSarp Misoglu" Date: Fri, 13 Jan 2023 19:11:42 +0000 Subject: [PATCH] Separate allow lists for profile and full non-system users. This change does 2 things - > Separate Backup helper allow lists for profile and full non-system users Due to the work supporting the new headless config (aka 'main' user) we are adding new helpers to the multi-user allowlist in SystemBackupAgent. This allowlist was effectively for work profile so these helpers will start running for profile users as well. Since it might not make sense for all helpers to run for profile user, this CL separates the allowlists. > Separate Backup Eligibility allow lists for profile and full non-system users. Due to the work supporting the new headless config (aka 'main' user) we are adding new packages to the multi-user allowlist in BackupEligibilityRules. This allowlist was effectively for work profile so these packages will start getting backed up for profile users as well. Since it does not make sense for all those packages to be backed up for profile user, this CL separates the allowlists. Bug: 265142782 Test: atest SystemBackupAgentTest Manual by running `adb shell bmgr backupnow android` for a system, profile, and full non-system user and verifying only the correct helpers are added via IntelliJ debugger. atest BackupEligibilityRulesTest Change-Id: I6115d8ef56629293eac0885d9db98da2a5f916bb --- .../backup/UserBackupManagerService.java | 9 +- .../backup/restore/PerformAdbRestoreTask.java | 4 +- .../backup/utils/BackupEligibilityRules.java | 46 ++++-- .../server/backup/utils/RestoreUtils.java | 3 +- .../android/server/backup/utils/SetUtils.java | 37 +++++ .../server/backup/utils/TarBackupReader.java | 6 +- .../com/android/server/backup/SetUtils.java | 37 +++++ .../server/backup/SystemBackupAgent.java | 81 +++++++---- .../keyvalue/KeyValueBackupTaskTest.java | 2 +- .../server/backup/SystemBackupAgentTest.java | 134 ++++++++++++++++++ .../utils/BackupEligibilityRulesTest.java | 99 ++++++++++++- .../backup/utils/TarBackupReaderTest.java | 28 ++-- 12 files changed, 427 insertions(+), 59 deletions(-) create mode 100644 services/backup/java/com/android/server/backup/utils/SetUtils.java create mode 100644 services/core/java/com/android/server/backup/SetUtils.java create mode 100644 services/tests/mockingservicestests/src/com/android/server/backup/SystemBackupAgentTest.java 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);