Merge "Separate allow lists for profile and full non-system users."
This commit is contained in:
committed by
Android (Google) Code Review
commit
e728ab566c
@@ -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'. */
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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<String> 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<String> 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<String> 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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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 <T> Set<T> union(Set<T> set1, Set<T> set2) {
|
||||
Set<T> unionSet = new HashSet<>(set1);
|
||||
unionSet.addAll(set2);
|
||||
return unionSet;
|
||||
}
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
37
services/core/java/com/android/server/backup/SetUtils.java
Normal file
37
services/core/java/com/android/server/backup/SetUtils.java
Normal file
@@ -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 <T> Set<T> union(Set<T> set1, Set<T> set2) {
|
||||
Set<T> unionSet = new HashSet<>(set1);
|
||||
unionSet.addAll(set2);
|
||||
return unionSet;
|
||||
}
|
||||
}
|
||||
@@ -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<String> 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<String> 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<String> 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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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<String> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<Bundle> 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<Bundle> 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<Bundle> 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<Bundle> 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<Bundle> 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<Bundle> 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<Bundle> 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<Bundle> 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<Bundle> 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<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
|
||||
|
||||
Reference in New Issue
Block a user