diff options
4 files changed, 1301 insertions, 315 deletions
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java index 2cbab492a605..a533640b526b 100644 --- a/services/backup/java/com/android/server/backup/BackupManagerService.java +++ b/services/backup/java/com/android/server/backup/BackupManagerService.java @@ -16,10 +16,13 @@ package com.android.server.backup; +import static com.android.internal.util.Preconditions.checkNotNull; + import android.Manifest; import android.annotation.Nullable; import android.annotation.UserIdInt; import android.app.ActivityManager; +import android.app.backup.BackupManager; import android.app.backup.IBackupManagerMonitor; import android.app.backup.IBackupObserver; import android.app.backup.IFullBackupRestoreObserver; @@ -41,6 +44,7 @@ import android.os.RemoteException; import android.os.Trace; import android.os.UserHandle; import android.util.Slog; +import android.util.SparseArray; import com.android.internal.annotations.VisibleForTesting; import com.android.server.SystemConfig; @@ -83,22 +87,27 @@ public class BackupManagerService { } private final Context mContext; - private UserBackupManagerService mUserBackupManagerService; + private final Trampoline mTrampoline; + private final HandlerThread mBackupThread; + + // Keeps track of all unlocked users registered with this service. Indexed by user id. + private final SparseArray<UserBackupManagerService> mServiceUsers = new SparseArray<>(); + + private Set<ComponentName> mTransportWhitelist; /** Instantiate a new instance of {@link BackupManagerService}. */ public BackupManagerService( Context context, Trampoline trampoline, HandlerThread backupThread) { - // Set up our transport options and initialize the default transport + mContext = checkNotNull(context); + mTrampoline = checkNotNull(trampoline); + mBackupThread = checkNotNull(backupThread); + + // Set up our transport options. SystemConfig systemConfig = SystemConfig.getInstance(); - Set<ComponentName> transportWhitelist = systemConfig.getBackupTransportWhitelist(); - if (transportWhitelist == null) { - transportWhitelist = Collections.emptySet(); + mTransportWhitelist = systemConfig.getBackupTransportWhitelist(); + if (mTransportWhitelist == null) { + mTransportWhitelist = Collections.emptySet(); } - - mContext = context; - mUserBackupManagerService = - UserBackupManagerService.createAndInitializeService( - context, trampoline, backupThread, transportWhitelist); } /** @@ -115,12 +124,6 @@ public class BackupManagerService { } } - // TODO(b/118520567): Remove when tests are modified to use per-user instance. - @VisibleForTesting - void setUserBackupManagerService(UserBackupManagerService userBackupManagerService) { - mUserBackupManagerService = userBackupManagerService; - } - /** * Called through Trampoline from {@link Lifecycle#onUnlockUser(int)}. We run the heavy work on * a background thread to keep the unlock time down. @@ -139,9 +142,42 @@ public class BackupManagerService { * Starts the backup service for user {@code userId} by creating a new instance of {@link * UserBackupManagerService} and registering it with this service. */ - // TODO(b/120212806): Add UserBackupManagerService initialization logic. - void startServiceForUser(int userId) { - // Intentionally empty. + @VisibleForTesting + protected void startServiceForUser(int userId) { + UserBackupManagerService userBackupManagerService = + UserBackupManagerService.createAndInitializeService( + mContext, mTrampoline, mBackupThread, mTransportWhitelist); + startServiceForUser(userId, userBackupManagerService); + } + + /** + * Starts the backup service for user {@code userId} by registering its instance of {@link + * UserBackupManagerService} with this service. + */ + void startServiceForUser(int userId, UserBackupManagerService userBackupManagerService) { + mServiceUsers.put(userId, userBackupManagerService); + } + + SparseArray<UserBackupManagerService> getServiceUsers() { + return mServiceUsers; + } + + /** + * Returns the {@link UserBackupManagerService} instance for the specified user {@code userId}. + * If the user is not registered with the service (either the user is locked or not eligible for + * the backup service) then return {@code null}. + * + * @param userId The id of the user to retrieve its instance of {@link + * UserBackupManagerService}. + * @param caller A {@link String} identifying the caller for logging purposes. + */ + @Nullable + private UserBackupManagerService getServiceForUser(@UserIdInt int userId, String caller) { + UserBackupManagerService userBackupManagerService = mServiceUsers.get(userId); + if (userBackupManagerService == null) { + Slog.w(TAG, "Called " + caller + " for unknown user: " + userId); + } + return userBackupManagerService; } /* @@ -149,7 +185,7 @@ public class BackupManagerService { * They delegate to the appropriate per-user instance of UserBackupManagerService to perform the * action on the passed in user. Currently this is a straight redirection (see TODO). */ - // TODO (b/118520567): Take in user id and call per-user instance of UserBackupManagerService. + // TODO (b/118520567): Stop hardcoding system user when we pass in user id as a parameter // --------------------------------------------- // BACKUP AGENT OPERATIONS @@ -161,7 +197,12 @@ public class BackupManagerService { * backup. */ public void dataChanged(String packageName) { - mUserBackupManagerService.dataChanged(packageName); + UserBackupManagerService userBackupManagerService = + getServiceForUser(UserHandle.USER_SYSTEM, "dataChanged()"); + + if (userBackupManagerService != null) { + userBackupManagerService.dataChanged(packageName); + } } /** @@ -169,7 +210,12 @@ public class BackupManagerService { * {@link ActivityManager}. */ public void agentConnected(String packageName, IBinder agentBinder) { - mUserBackupManagerService.agentConnected(packageName, agentBinder); + UserBackupManagerService userBackupManagerService = + getServiceForUser(UserHandle.USER_SYSTEM, "agentConnected()"); + + if (userBackupManagerService != null) { + userBackupManagerService.agentConnected(packageName, agentBinder); + } } /** @@ -177,7 +223,12 @@ public class BackupManagerService { * called from the {@link ActivityManager}. */ public void agentDisconnected(String packageName) { - mUserBackupManagerService.agentDisconnected(packageName); + UserBackupManagerService userBackupManagerService = + getServiceForUser(UserHandle.USER_SYSTEM, "agentDisconnected()"); + + if (userBackupManagerService != null) { + userBackupManagerService.agentDisconnected(packageName); + } } /** @@ -185,7 +236,12 @@ public class BackupManagerService { * outstanding asynchronous backup/restore operation. */ public void opComplete(int token, long result) { - mUserBackupManagerService.opComplete(token, result); + UserBackupManagerService userBackupManagerService = + getServiceForUser(UserHandle.USER_SYSTEM, "opComplete()"); + + if (userBackupManagerService != null) { + userBackupManagerService.opComplete(token, result); + } } // --------------------------------------------- @@ -194,7 +250,12 @@ public class BackupManagerService { /** Run an initialize operation for the given transports {@code transportNames}. */ public void initializeTransports(String[] transportNames, IBackupObserver observer) { - mUserBackupManagerService.initializeTransports(transportNames, observer); + UserBackupManagerService userBackupManagerService = + getServiceForUser(UserHandle.USER_SYSTEM, "initializeTransports()"); + + if (userBackupManagerService != null) { + userBackupManagerService.initializeTransports(transportNames, observer); + } } /** @@ -202,35 +263,70 @@ public class BackupManagerService { * transportName}. */ public void clearBackupData(String transportName, String packageName) { - mUserBackupManagerService.clearBackupData(transportName, packageName); + UserBackupManagerService userBackupManagerService = + getServiceForUser(UserHandle.USER_SYSTEM, "clearBackupData()"); + + if (userBackupManagerService != null) { + userBackupManagerService.clearBackupData(transportName, packageName); + } } /** Return the name of the currently active transport. */ + @Nullable public String getCurrentTransport() { - return mUserBackupManagerService.getCurrentTransport(); + UserBackupManagerService userBackupManagerService = + getServiceForUser(UserHandle.USER_SYSTEM, "getCurrentTransport()"); + + return userBackupManagerService == null + ? null + : userBackupManagerService.getCurrentTransport(); } /** * Returns the {@link ComponentName} of the host service of the selected transport or {@code * null} if no transport selected or if the transport selected is not registered. */ + @Nullable public ComponentName getCurrentTransportComponent() { - return mUserBackupManagerService.getCurrentTransportComponent(); + UserBackupManagerService userBackupManagerService = + getServiceForUser(UserHandle.USER_SYSTEM, "getCurrentTransportComponent()"); + + return userBackupManagerService == null + ? null + : userBackupManagerService.getCurrentTransportComponent(); } /** Report all known, available backup transports by name. */ + @Nullable public String[] listAllTransports() { - return mUserBackupManagerService.listAllTransports(); + UserBackupManagerService userBackupManagerService = + getServiceForUser(UserHandle.USER_SYSTEM, "listAllTransports()"); + + return userBackupManagerService == null + ? null + : userBackupManagerService.listAllTransports(); } /** Report all known, available backup transports by {@link ComponentName}. */ + @Nullable public ComponentName[] listAllTransportComponents() { - return mUserBackupManagerService.listAllTransportComponents(); + UserBackupManagerService userBackupManagerService = + getServiceForUser(UserHandle.USER_SYSTEM, "listAllTransportComponents()"); + + return userBackupManagerService == null + ? null + : userBackupManagerService.listAllTransportComponents(); } /** Report all system whitelisted transports. */ + @Nullable public String[] getTransportWhitelist() { - return mUserBackupManagerService.getTransportWhitelist(); + UserBackupManagerService userBackupManagerService = + getServiceForUser(UserHandle.USER_SYSTEM, "getTransportWhitelist()"); + + return userBackupManagerService == null + ? null + : userBackupManagerService.getTransportWhitelist(); } /** @@ -263,13 +359,18 @@ public class BackupManagerService { String currentDestinationString, @Nullable Intent dataManagementIntent, String dataManagementLabel) { - mUserBackupManagerService.updateTransportAttributes( - transportComponent, - name, - configurationIntent, - currentDestinationString, - dataManagementIntent, - dataManagementLabel); + UserBackupManagerService userBackupManagerService = + getServiceForUser(UserHandle.USER_SYSTEM, "updateTransportAttributes()"); + + if (userBackupManagerService != null) { + userBackupManagerService.updateTransportAttributes( + transportComponent, + name, + configurationIntent, + currentDestinationString, + dataManagementIntent, + dataManagementLabel); + } } /** @@ -281,7 +382,12 @@ public class BackupManagerService { @Deprecated @Nullable public String selectBackupTransport(String transportName) { - return mUserBackupManagerService.selectBackupTransport(transportName); + UserBackupManagerService userBackupManagerService = + getServiceForUser(UserHandle.USER_SYSTEM, "selectBackupTransport()"); + + return userBackupManagerService == null + ? null + : userBackupManagerService.selectBackupTransport(transportName); } /** @@ -290,7 +396,12 @@ public class BackupManagerService { */ public void selectBackupTransportAsync( ComponentName transportComponent, ISelectBackupTransportCallback listener) { - mUserBackupManagerService.selectBackupTransportAsync(transportComponent, listener); + UserBackupManagerService userBackupManagerService = + getServiceForUser(UserHandle.USER_SYSTEM, "selectBackupTransportAsync()"); + + if (userBackupManagerService != null) { + userBackupManagerService.selectBackupTransportAsync(transportComponent, listener); + } } /** @@ -298,8 +409,14 @@ public class BackupManagerService { * available transports, or if the transport does not supply any configuration UI, the method * returns {@code null}. */ + @Nullable public Intent getConfigurationIntent(String transportName) { - return mUserBackupManagerService.getConfigurationIntent(transportName); + UserBackupManagerService userBackupManagerService = + getServiceForUser(UserHandle.USER_SYSTEM, "getConfigurationIntent()"); + + return userBackupManagerService == null + ? null + : userBackupManagerService.getConfigurationIntent(transportName); } /** @@ -311,21 +428,39 @@ public class BackupManagerService { * @param transportName The name of the registered transport. * @return The current destination string or null if the transport is not registered. */ + @Nullable public String getDestinationString(String transportName) { - return mUserBackupManagerService.getDestinationString(transportName); + UserBackupManagerService userBackupManagerService = + getServiceForUser(UserHandle.USER_SYSTEM, "getDestinationString()"); + + return userBackupManagerService == null + ? null + : userBackupManagerService.getDestinationString(transportName); } /** Supply the manage-data intent for the given transport. */ + @Nullable public Intent getDataManagementIntent(String transportName) { - return mUserBackupManagerService.getDataManagementIntent(transportName); + UserBackupManagerService userBackupManagerService = + getServiceForUser(UserHandle.USER_SYSTEM, "getDataManagementIntent()"); + + return userBackupManagerService == null + ? null + : userBackupManagerService.getDataManagementIntent(transportName); } /** * Supply the menu label for affordances that fire the manage-data intent for the given * transport. */ + @Nullable public String getDataManagementLabel(String transportName) { - return mUserBackupManagerService.getDataManagementLabel(transportName); + UserBackupManagerService userBackupManagerService = + getServiceForUser(UserHandle.USER_SYSTEM, "getDataManagementLabel()"); + + return userBackupManagerService == null + ? null + : userBackupManagerService.getDataManagementLabel(transportName); } // --------------------------------------------- @@ -335,17 +470,32 @@ public class BackupManagerService { /** Enable/disable the backup service. This is user-configurable via backup settings. */ public void setBackupEnabled(@UserIdInt int userId, boolean enable) { enforceCallingPermissionOnUserId(userId, "setBackupEnabled"); - mUserBackupManagerService.setBackupEnabled(enable); + UserBackupManagerService userBackupManagerService = + getServiceForUser(userId, "setBackupEnabled()"); + + if (userBackupManagerService != null) { + userBackupManagerService.setBackupEnabled(enable); + } } /** Enable/disable automatic restore of app data at install time. */ public void setAutoRestore(boolean autoRestore) { - mUserBackupManagerService.setAutoRestore(autoRestore); + UserBackupManagerService userBackupManagerService = + getServiceForUser(UserHandle.USER_SYSTEM, "setAutoRestore()"); + + if (userBackupManagerService != null) { + userBackupManagerService.setAutoRestore(autoRestore); + } } /** Mark the backup service as having been provisioned (device has gone through SUW). */ public void setBackupProvisioned(boolean provisioned) { - mUserBackupManagerService.setBackupProvisioned(provisioned); + UserBackupManagerService userBackupManagerService = + getServiceForUser(UserHandle.USER_SYSTEM, "setBackupProvisioned()"); + + if (userBackupManagerService != null) { + userBackupManagerService.setBackupProvisioned(provisioned); + } } /** @@ -353,7 +503,10 @@ public class BackupManagerService { */ public boolean isBackupEnabled(@UserIdInt int userId) { enforceCallingPermissionOnUserId(userId, "isBackupEnabled"); - return mUserBackupManagerService.isBackupEnabled(); + UserBackupManagerService userBackupManagerService = + getServiceForUser(userId, "isBackupEnabled()"); + + return userBackupManagerService != null && userBackupManagerService.isBackupEnabled(); } // --------------------------------------------- @@ -362,14 +515,24 @@ public class BackupManagerService { /** Checks if the given package {@code packageName} is eligible for backup. */ public boolean isAppEligibleForBackup(String packageName) { - return mUserBackupManagerService.isAppEligibleForBackup(packageName); + UserBackupManagerService userBackupManagerService = + getServiceForUser(UserHandle.USER_SYSTEM, "isAppEligibleForBackup()"); + + return userBackupManagerService != null + && userBackupManagerService.isAppEligibleForBackup(packageName); } /** * Returns from the inputted packages {@code packages}, the ones that are eligible for backup. */ + @Nullable public String[] filterAppsEligibleForBackup(String[] packages) { - return mUserBackupManagerService.filterAppsEligibleForBackup(packages); + UserBackupManagerService userBackupManagerService = + getServiceForUser(UserHandle.USER_SYSTEM, "filterAppsEligibleForBackup()"); + + return userBackupManagerService == null + ? null + : userBackupManagerService.filterAppsEligibleForBackup(packages); } /** @@ -378,7 +541,12 @@ public class BackupManagerService { */ public void backupNow(@UserIdInt int userId) { enforceCallingPermissionOnUserId(userId, "backupNow"); - mUserBackupManagerService.backupNow(); + UserBackupManagerService userBackupManagerService = + getServiceForUser(userId, "backupNow()"); + + if (userBackupManagerService != null) { + userBackupManagerService.backupNow(); + } } /** @@ -392,13 +560,23 @@ public class BackupManagerService { IBackupManagerMonitor monitor, int flags) { enforceCallingPermissionOnUserId(userId, "requestBackup"); - return mUserBackupManagerService.requestBackup(packages, observer, monitor, flags); + UserBackupManagerService userBackupManagerService = + getServiceForUser(userId, "requestBackup()"); + + return userBackupManagerService == null + ? BackupManager.ERROR_BACKUP_NOT_ALLOWED + : userBackupManagerService.requestBackup(packages, observer, monitor, flags); } /** Cancel all running backup operations. */ public void cancelBackups(@UserIdInt int userId) { enforceCallingPermissionOnUserId(userId, "cancelBackups"); - mUserBackupManagerService.cancelBackups(); + UserBackupManagerService userBackupManagerService = + getServiceForUser(userId, "cancelBackups()"); + + if (userBackupManagerService != null) { + userBackupManagerService.cancelBackups(); + } } /** @@ -410,7 +588,11 @@ public class BackupManagerService { * return value to the callback {@link JobService#onStartJob(JobParameters)}. */ public boolean beginFullBackup(FullBackupJob scheduledJob) { - return mUserBackupManagerService.beginFullBackup(scheduledJob); + UserBackupManagerService userBackupManagerService = + getServiceForUser(UserHandle.USER_SYSTEM, "beginFullBackup()"); + + return userBackupManagerService != null + && userBackupManagerService.beginFullBackup(scheduledJob); } /** @@ -418,14 +600,24 @@ public class BackupManagerService { * longer met for running the full backup job. */ public void endFullBackup() { - mUserBackupManagerService.endFullBackup(); + UserBackupManagerService userBackupManagerService = + getServiceForUser(UserHandle.USER_SYSTEM, "endFullBackup()"); + + if (userBackupManagerService != null) { + userBackupManagerService.endFullBackup(); + } } /** * Run a full backup pass for the given packages {@code packageNames}. Used by 'adb shell bmgr'. */ public void fullTransportBackup(String[] packageNames) { - mUserBackupManagerService.fullTransportBackup(packageNames); + UserBackupManagerService userBackupManagerService = + getServiceForUser(UserHandle.USER_SYSTEM, "fullTransportBackup()"); + + if (userBackupManagerService != null) { + userBackupManagerService.fullTransportBackup(packageNames); + } } // --------------------------------------------- @@ -437,15 +629,26 @@ public class BackupManagerService { * called from the {@link PackageManager}. */ public void restoreAtInstall(String packageName, int token) { - mUserBackupManagerService.restoreAtInstall(packageName, token); + UserBackupManagerService userBackupManagerService = + getServiceForUser(UserHandle.USER_SYSTEM, "restoreAtInstall()"); + + if (userBackupManagerService != null) { + userBackupManagerService.restoreAtInstall(packageName, token); + } } /** * Begin a restore for the specified package {@code packageName} using the specified transport * {@code transportName}. */ + @Nullable public IRestoreSession beginRestoreSession(String packageName, String transportName) { - return mUserBackupManagerService.beginRestoreSession(packageName, transportName); + UserBackupManagerService userBackupManagerService = + getServiceForUser(UserHandle.USER_SYSTEM, "beginRestoreSession()"); + + return userBackupManagerService == null + ? null + : userBackupManagerService.beginRestoreSession(packageName, transportName); } /** @@ -453,7 +656,12 @@ public class BackupManagerService { * the active set if possible, else the ancestral one. Returns zero if none available. */ public long getAvailableRestoreToken(String packageName) { - return mUserBackupManagerService.getAvailableRestoreToken(packageName); + UserBackupManagerService userBackupManagerService = + getServiceForUser(UserHandle.USER_SYSTEM, "getAvailableRestoreToken()"); + + return userBackupManagerService == null + ? 0 + : userBackupManagerService.getAvailableRestoreToken(packageName); } // --------------------------------------------- @@ -462,12 +670,19 @@ public class BackupManagerService { /** Sets the backup password used when running adb backup. */ public boolean setBackupPassword(String currentPassword, String newPassword) { - return mUserBackupManagerService.setBackupPassword(currentPassword, newPassword); + UserBackupManagerService userBackupManagerService = + getServiceForUser(UserHandle.USER_SYSTEM, "setBackupPassword()"); + + return userBackupManagerService != null + && userBackupManagerService.setBackupPassword(currentPassword, newPassword); } /** Returns {@code true} if adb backup was run with a password, else returns {@code false}. */ public boolean hasBackupPassword() { - return mUserBackupManagerService.hasBackupPassword(); + UserBackupManagerService userBackupManagerService = + getServiceForUser(UserHandle.USER_SYSTEM, "hasBackupPassword()"); + + return userBackupManagerService != null && userBackupManagerService.hasBackupPassword(); } /** @@ -489,18 +704,22 @@ public class BackupManagerService { boolean doKeyValue, String[] packageNames) { enforceCallingPermissionOnUserId(userId, "adbBackup"); - - mUserBackupManagerService.adbBackup( - fd, - includeApks, - includeObbs, - includeShared, - doWidgets, - doAllApps, - includeSystem, - doCompress, - doKeyValue, - packageNames); + UserBackupManagerService userBackupManagerService = + getServiceForUser(userId, "adbBackup()"); + + if (userBackupManagerService != null) { + userBackupManagerService.adbBackup( + fd, + includeApks, + includeObbs, + includeShared, + doWidgets, + doAllApps, + includeSystem, + doCompress, + doKeyValue, + packageNames); + } } /** @@ -510,8 +729,12 @@ public class BackupManagerService { */ public void adbRestore(@UserIdInt int userId, ParcelFileDescriptor fd) { enforceCallingPermissionOnUserId(userId, "setBackupEnabled"); + UserBackupManagerService userBackupManagerService = + getServiceForUser(userId, "adbRestore()"); - mUserBackupManagerService.adbRestore(fd); + if (userBackupManagerService != null) { + userBackupManagerService.adbRestore(fd); + } } /** @@ -524,8 +747,13 @@ public class BackupManagerService { String currentPassword, String encryptionPassword, IFullBackupRestoreObserver observer) { - mUserBackupManagerService.acknowledgeAdbBackupOrRestore( - token, allow, currentPassword, encryptionPassword, observer); + UserBackupManagerService userBackupManagerService = + getServiceForUser(UserHandle.USER_SYSTEM, "acknowledgeAdbBackupOrRestore()"); + + if (userBackupManagerService != null) { + userBackupManagerService.acknowledgeAdbBackupOrRestore( + token, allow, currentPassword, encryptionPassword, observer); + } } // --------------------------------------------- @@ -534,7 +762,12 @@ public class BackupManagerService { /** Prints service state for 'dumpsys backup'. */ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - mUserBackupManagerService.dump(fd, pw, args); + UserBackupManagerService userBackupManagerService = + getServiceForUser(UserHandle.USER_SYSTEM, "dump()"); + + if (userBackupManagerService != null) { + userBackupManagerService.dump(fd, pw, args); + } } private static boolean readBackupEnableState(int userId) { @@ -592,7 +825,7 @@ public class BackupManagerService { if (userId == UserHandle.USER_SYSTEM) { sInstance.initializeServiceAndUnlockSystemUser(); } else { - sInstance.startServiceForUser(userId); + sInstance.unlockUser(userId); } } } diff --git a/services/backup/java/com/android/server/backup/Trampoline.java b/services/backup/java/com/android/server/backup/Trampoline.java index 4acd5c494ac7..59b72f9262b6 100644 --- a/services/backup/java/com/android/server/backup/Trampoline.java +++ b/services/backup/java/com/android/server/backup/Trampoline.java @@ -116,7 +116,7 @@ public class Trampoline extends IBackupManager.Stub { return SystemProperties.getBoolean(BACKUP_DISABLE_PROPERTY, false); } - protected boolean isMultiUserEnabled() { + private boolean isMultiUserEnabled() { return Settings.Global.getInt( mContext.getContentResolver(), Settings.Global.BACKUP_MULTI_USER_ENABLED, @@ -145,6 +145,10 @@ public class Trampoline extends IBackupManager.Stub { return new BackupManagerService(mContext, this, mHandlerThread); } + protected void postToHandler(Runnable runnable) { + mHandler.post(runnable); + } + /** * Initialize {@link BackupManagerService} if the backup service is not disabled. Only the * system user can initialize the service. @@ -174,14 +178,18 @@ public class Trampoline extends IBackupManager.Stub { * to initialize {@link BackupManagerService} and set backup state for the system user. */ void initializeServiceAndUnlockSystemUser() { - mHandler.post( + postToHandler( () -> { + // Initialize the backup service. Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "backup init"); initializeService(UserHandle.USER_SYSTEM); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); + // Start the service for the system user. BackupManagerService service = mService; if (service != null) { + Slog.i(TAG, "Starting service for system user"); + service.startServiceForUser(UserHandle.USER_SYSTEM); Slog.i(TAG, "Unlocking system user"); service.unlockSystemUser(); } @@ -195,20 +203,21 @@ public class Trampoline extends IBackupManager.Stub { */ // TODO(b/120212806): Consolidate service start for system and non-system users when system // user-only logic is removed. - void startServiceForUser(int userId) { + void unlockUser(int userId) { if (!isMultiUserEnabled()) { Slog.i(TAG, "Multi-user disabled, cannot start service for user: " + userId); return; } - mHandler.post( - () -> { - BackupManagerService service = mService; - if (service != null) { - Slog.i(TAG, "Starting service for user: " + userId); - service.startServiceForUser(userId); - } - }); + postToHandler(() -> startServiceForUser(userId)); + } + + private void startServiceForUser(int userId) { + BackupManagerService service = mService; + if (service != null) { + Slog.i(TAG, "Starting service for user: " + userId); + service.startServiceForUser(userId); + } } /** @@ -242,6 +251,7 @@ public class Trampoline extends IBackupManager.Stub { if (makeActive) { mService = createBackupManagerService(); mSuppressFile.delete(); + startServiceForUser(userId); } else { mService = null; try { diff --git a/services/robotests/src/com/android/server/backup/BackupManagerServiceTest.java b/services/robotests/src/com/android/server/backup/BackupManagerServiceTest.java index 58bce1cdfbf1..83f66c5258b2 100644 --- a/services/robotests/src/com/android/server/backup/BackupManagerServiceTest.java +++ b/services/robotests/src/com/android/server/backup/BackupManagerServiceTest.java @@ -16,11 +16,15 @@ package com.android.server.backup; +import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL; + +import static com.android.server.backup.testing.BackupManagerServiceTestUtils.startBackupThread; import static com.android.server.backup.testing.TransportData.backupTransport; import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.robolectric.Shadows.shadowOf; import static org.testng.Assert.expectThrows; @@ -37,8 +41,8 @@ import android.os.IBinder; import android.os.ParcelFileDescriptor; import android.os.UserHandle; import android.platform.test.annotations.Presubmit; +import android.util.SparseArray; -import com.android.server.backup.testing.BackupManagerServiceTestUtils; import com.android.server.backup.testing.TransportData; import com.android.server.testing.shadows.ShadowBinder; @@ -64,16 +68,14 @@ import java.io.PrintWriter; public class BackupManagerServiceTest { private static final String TEST_PACKAGE = "package"; private static final String TEST_TRANSPORT = "transport"; - private static final String[] ADB_TEST_PACKAGES = {TEST_PACKAGE}; - private static final int NON_USER_SYSTEM = UserHandle.USER_SYSTEM + 1; - private ShadowContextWrapper mShadowContext; - @Mock private UserBackupManagerService mUserBackupManagerService; - private BackupManagerService mBackupManagerService; private Context mContext; - @UserIdInt private int mUserId; + @UserIdInt private int mUserOneId; + @UserIdInt private int mUserTwoId; + @Mock private UserBackupManagerService mUserOneService; + @Mock private UserBackupManagerService mUserTwoService; /** Initialize {@link BackupManagerService}. */ @Before @@ -83,13 +85,11 @@ public class BackupManagerServiceTest { Application application = RuntimeEnvironment.application; mContext = application; mShadowContext = shadowOf(application); - mUserId = NON_USER_SYSTEM; - mBackupManagerService = - new BackupManagerService( - application, - new Trampoline(application), - BackupManagerServiceTestUtils.startBackupThread(null)); - mBackupManagerService.setUserBackupManagerService(mUserBackupManagerService); + + // TODO(b/120212806): Hardcoding system user for now since most methods in BMS don't yet + // take an user parameter (and instead hardcode the system user). + mUserOneId = UserHandle.USER_SYSTEM; + mUserTwoId = mUserOneId + 1; } /** @@ -102,8 +102,8 @@ public class BackupManagerServiceTest { } /** - * Test verifying that {@link BackupManagerService#MORE_DEBUG} is set to {@code false}. - * This is specifically to prevent overloading the logs in production. + * Test verifying that {@link BackupManagerService#MORE_DEBUG} is set to {@code false}. This is + * specifically to prevent overloading the logs in production. */ @Test public void testMoreDebug_isFalse() throws Exception { @@ -112,9 +112,73 @@ public class BackupManagerServiceTest { assertThat(moreDebug).isFalse(); } - // TODO(b/118520567): Change the following tests to use the per-user instance of - // UserBackupManagerService once it's implemented. Currently these tests only test the straight - // forward redirection. + /** Test that the constructor does not create {@link UserBackupManagerService} instances. */ + @Test + public void testConstructor_doesNotRegisterUsers() throws Exception { + BackupManagerService backupManagerService = createService(); + + assertThat(backupManagerService.getServiceUsers().size()).isEqualTo(0); + } + + /** Test that the constructor handles {@code null} parameters. */ + @Test + public void testConstructor_withNullContext_throws() throws Exception { + expectThrows( + NullPointerException.class, + () -> + new BackupManagerService( + /* context */ null, + new Trampoline(mContext), + startBackupThread(null))); + } + + /** Test that the constructor handles {@code null} parameters. */ + @Test + public void testConstructor_withNullTrampoline_throws() throws Exception { + expectThrows( + NullPointerException.class, + () -> + new BackupManagerService( + mContext, /* trampoline */ null, startBackupThread(null))); + } + + /** Test that the constructor handles {@code null} parameters. */ + @Test + public void testConstructor_withNullBackupThread_throws() throws Exception { + expectThrows( + NullPointerException.class, + () -> + new BackupManagerService( + mContext, new Trampoline(mContext), /* backupThread */ null)); + } + + /** Test that the service registers users. */ + @Test + public void testStartServiceForUser_registersUser() throws Exception { + BackupManagerService backupManagerService = createService(); + + backupManagerService.startServiceForUser(mUserOneId); + + SparseArray<UserBackupManagerService> serviceUsers = backupManagerService.getServiceUsers(); + assertThat(serviceUsers.size()).isEqualTo(1); + assertThat(serviceUsers.get(mUserOneId)).isNotNull(); + } + + /** Test that the service registers users. */ + @Test + public void testStartServiceForUser_withServiceInstance_registersUser() throws Exception { + BackupManagerService backupManagerService = createService(); + + backupManagerService.startServiceForUser(mUserOneId, mUserOneService); + + SparseArray<UserBackupManagerService> serviceUsers = backupManagerService.getServiceUsers(); + assertThat(serviceUsers.size()).isEqualTo(1); + assertThat(serviceUsers.get(mUserOneId)).isEqualTo(mUserOneService); + } + + // TODO(b/120212806): When BMS methods take in a user parameter, modify unknown user tests to + // check that that we don't call the method on another registered user. Currently these tests + // have no registered users since we hardcode the system user in BMS. // --------------------------------------------- // Backup agent tests @@ -122,36 +186,88 @@ public class BackupManagerServiceTest { /** Test that the backup service routes methods correctly to the user that requests it. */ @Test - public void testDataChanged_callsDataChangedForUser() throws Exception { - mBackupManagerService.dataChanged(TEST_PACKAGE); + public void testDataChanged_onRegisteredUser_callsMethodForUser() throws Exception { + BackupManagerService backupManagerService = + createServiceAndRegisterUser(mUserOneId, mUserOneService); - verify(mUserBackupManagerService).dataChanged(TEST_PACKAGE); + backupManagerService.dataChanged(TEST_PACKAGE); + + verify(mUserOneService).dataChanged(TEST_PACKAGE); + } + + /** Test that the backup service does not route methods for non-registered users. */ + @Test + public void testDataChanged_onUnknownUser_doesNotPropagateCall() throws Exception { + BackupManagerService backupManagerService = createService(); + + backupManagerService.dataChanged(TEST_PACKAGE); + + verify(mUserOneService, never()).dataChanged(TEST_PACKAGE); } /** Test that the backup service routes methods correctly to the user that requests it. */ @Test - public void testAgentConnected_callsAgentConnectedForUser() throws Exception { + public void testAgentConnected_onRegisteredUser_callsMethodForUser() throws Exception { + BackupManagerService backupManagerService = + createServiceAndRegisterUser(mUserOneId, mUserOneService); IBinder agentBinder = mock(IBinder.class); - mBackupManagerService.agentConnected(TEST_PACKAGE, agentBinder); + backupManagerService.agentConnected(TEST_PACKAGE, agentBinder); - verify(mUserBackupManagerService).agentConnected(TEST_PACKAGE, agentBinder); + verify(mUserOneService).agentConnected(TEST_PACKAGE, agentBinder); + } + + /** Test that the backup service does not route methods for non-registered users. */ + @Test + public void testAgentConnected_onUnknownUser_doesNotPropagateCall() throws Exception { + BackupManagerService backupManagerService = createService(); + IBinder agentBinder = mock(IBinder.class); + + backupManagerService.agentConnected(TEST_PACKAGE, agentBinder); + + verify(mUserOneService, never()).agentConnected(TEST_PACKAGE, agentBinder); } /** Test that the backup service routes methods correctly to the user that requests it. */ @Test - public void testAgentDisconnected_callsAgentDisconnectedForUser() throws Exception { - mBackupManagerService.agentDisconnected(TEST_PACKAGE); + public void testAgentDisconnected_onRegisteredUser_callsMethodForUser() throws Exception { + BackupManagerService backupManagerService = + createServiceAndRegisterUser(mUserOneId, mUserOneService); + + backupManagerService.agentDisconnected(TEST_PACKAGE); + + verify(mUserOneService).agentDisconnected(TEST_PACKAGE); + } + + /** Test that the backup service does not route methods for non-registered users. */ + @Test + public void testAgentDisconnected_onUnknownUser_doesNotPropagateCall() throws Exception { + BackupManagerService backupManagerService = createService(); - verify(mUserBackupManagerService).agentDisconnected(TEST_PACKAGE); + backupManagerService.agentDisconnected(TEST_PACKAGE); + + verify(mUserOneService, never()).agentDisconnected(TEST_PACKAGE); } /** Test that the backup service routes methods correctly to the user that requests it. */ @Test - public void testOpComplete_callsOpCompleteForUser() throws Exception { - mBackupManagerService.opComplete(/* token */ 0, /* result */ 0L); + public void testOpComplete_onRegisteredUser_callsMethodForUser() throws Exception { + BackupManagerService backupManagerService = + createServiceAndRegisterUser(mUserOneId, mUserOneService); + + backupManagerService.opComplete(/* token */ 0, /* result */ 0L); + + verify(mUserOneService).opComplete(/* token */ 0, /* result */ 0L); + } + + /** Test that the backup service does not route methods for non-registered users. */ + @Test + public void testOpComplete_onUnknownUser_doesNotPropagateCall() throws Exception { + BackupManagerService backupManagerService = createService(); - verify(mUserBackupManagerService).opComplete(/* token */ 0, /* result */ 0L); + backupManagerService.opComplete(/* token */ 0, /* result */ 0L); + + verify(mUserOneService, never()).opComplete(/* token */ 0, /* result */ 0L); } // --------------------------------------------- @@ -160,73 +276,168 @@ public class BackupManagerServiceTest { /** Test that the backup service routes methods correctly to the user that requests it. */ @Test - public void testInitializeTransports_callsInitializeTransportsForUser() throws Exception { + public void testInitializeTransports_onRegisteredUser_callsMethodForUser() throws Exception { + BackupManagerService backupManagerService = + createServiceAndRegisterUser(mUserOneId, mUserOneService); + String[] transports = {TEST_TRANSPORT}; + + backupManagerService.initializeTransports(transports, /* observer */ null); + + verify(mUserOneService).initializeTransports(transports, /* observer */ null); + } + + /** Test that the backup service does not route methods for non-registered users. */ + @Test + public void testInitializeTransports_onUnknownUser_doesNotPropagateCall() throws Exception { + BackupManagerService backupManagerService = createService(); String[] transports = {TEST_TRANSPORT}; - mBackupManagerService.initializeTransports(transports, /* observer */ null); + backupManagerService.initializeTransports(transports, /* observer */ null); - verify(mUserBackupManagerService).initializeTransports(transports, /* observer */ null); + verify(mUserOneService, never()).initializeTransports(transports, /* observer */ null); } /** Test that the backup service routes methods correctly to the user that requests it. */ @Test - public void testClearBackupData_callsClearBackupDataForUser() throws Exception { - mBackupManagerService.clearBackupData(TEST_TRANSPORT, TEST_PACKAGE); + public void testClearBackupData_onRegisteredUser_callsMethodForUser() throws Exception { + BackupManagerService backupManagerService = + createServiceAndRegisterUser(mUserOneId, mUserOneService); + + backupManagerService.clearBackupData(TEST_TRANSPORT, TEST_PACKAGE); + + verify(mUserOneService).clearBackupData(TEST_TRANSPORT, TEST_PACKAGE); + } + + /** Test that the backup service does not route methods for non-registered users. */ + @Test + public void testClearBackupData_onUnknownUser_doesNotPropagateCall() throws Exception { + BackupManagerService backupManagerService = createService(); - verify(mUserBackupManagerService).clearBackupData(TEST_TRANSPORT, TEST_PACKAGE); + backupManagerService.clearBackupData(TEST_TRANSPORT, TEST_PACKAGE); + + verify(mUserOneService, never()).clearBackupData(TEST_TRANSPORT, TEST_PACKAGE); } /** Test that the backup service routes methods correctly to the user that requests it. */ @Test - public void testGetCurrentTransport_callsGetCurrentTransportForUser() throws Exception { - mBackupManagerService.getCurrentTransport(); + public void testGetCurrentTransport_onRegisteredUser_callsMethodForUser() throws Exception { + BackupManagerService backupManagerService = + createServiceAndRegisterUser(mUserOneId, mUserOneService); + + backupManagerService.getCurrentTransport(); - verify(mUserBackupManagerService).getCurrentTransport(); + verify(mUserOneService).getCurrentTransport(); + } + + /** Test that the backup service does not route methods for non-registered users. */ + @Test + public void testGetCurrentTransport_onUnknownUser_doesNotPropagateCall() throws Exception { + BackupManagerService backupManagerService = createService(); + + backupManagerService.getCurrentTransport(); + + verify(mUserOneService, never()).getCurrentTransport(); } /** Test that the backup service routes methods correctly to the user that requests it. */ @Test - public void testGetCurrentTransportComponent_callsGetCurrentTransportComponentForUser() + public void testGetCurrentTransportComponent_onRegisteredUser_callsMethodForUser() + throws Exception { + BackupManagerService backupManagerService = + createServiceAndRegisterUser(mUserOneId, mUserOneService); + + backupManagerService.getCurrentTransportComponent(); + + verify(mUserOneService).getCurrentTransportComponent(); + } + + /** Test that the backup service does not route methods for non-registered users. */ + @Test + public void testGetCurrentTransportComponent_onUnknownUser_doesNotPropagateCall() throws Exception { - mBackupManagerService.getCurrentTransportComponent(); + BackupManagerService backupManagerService = createService(); + + backupManagerService.getCurrentTransportComponent(); - verify(mUserBackupManagerService).getCurrentTransportComponent(); + verify(mUserOneService, never()).getCurrentTransportComponent(); } /** Test that the backup service routes methods correctly to the user that requests it. */ @Test - public void testListAllTransports_callsListAllTransportsForUser() throws Exception { - mBackupManagerService.listAllTransports(); + public void testListAllTransports_onRegisteredUser_callsMethodForUser() throws Exception { + BackupManagerService backupManagerService = + createServiceAndRegisterUser(mUserOneId, mUserOneService); + + backupManagerService.listAllTransports(); - verify(mUserBackupManagerService).listAllTransports(); + verify(mUserOneService).listAllTransports(); + } + + /** Test that the backup service does not route methods for non-registered users. */ + @Test + public void testListAllTransports_onUnknownUser_doesNotPropagateCall() throws Exception { + BackupManagerService backupManagerService = createService(); + + backupManagerService.listAllTransports(); + + verify(mUserOneService, never()).listAllTransports(); } /** Test that the backup service routes methods correctly to the user that requests it. */ @Test - public void testListAllTransportComponents_callsListAllTransportComponentsForUser() + public void testListAllTransportComponents_onRegisteredUser_callsMethodForUser() throws Exception { - mBackupManagerService.listAllTransportComponents(); + BackupManagerService backupManagerService = + createServiceAndRegisterUser(mUserOneId, mUserOneService); + + backupManagerService.listAllTransportComponents(); - verify(mUserBackupManagerService).listAllTransportComponents(); + verify(mUserOneService).listAllTransportComponents(); + } + + /** Test that the backup service does not route methods for non-registered users. */ + @Test + public void testListAllTransportComponents_onUnknownUser_doesNotPropagateCall() + throws Exception { + BackupManagerService backupManagerService = createService(); + + backupManagerService.listAllTransportComponents(); + + verify(mUserOneService, never()).listAllTransportComponents(); } /** Test that the backup service routes methods correctly to the user that requests it. */ @Test - public void testGetTransportWhitelist_callsGetTransportWhitelistForUser() throws Exception { - mBackupManagerService.getTransportWhitelist(); + public void testGetTransportWhitelist_onRegisteredUser_callsMethodForUser() throws Exception { + BackupManagerService backupManagerService = + createServiceAndRegisterUser(mUserOneId, mUserOneService); + + backupManagerService.getTransportWhitelist(); + + verify(mUserOneService).getTransportWhitelist(); + } + + /** Test that the backup service does not route methods for non-registered users. */ + @Test + public void testGetTransportWhitelist_onUnknownUser_doesNotPropagateCall() throws Exception { + BackupManagerService backupManagerService = createService(); - verify(mUserBackupManagerService).getTransportWhitelist(); + backupManagerService.getTransportWhitelist(); + + verify(mUserOneService, never()).getTransportWhitelist(); } /** Test that the backup service routes methods correctly to the user that requests it. */ @Test - public void testUpdateTransportAttributes_callsUpdateTransportAttributesForUser() + public void testUpdateTransportAttributes_onRegisteredUser_callsMethodForUser() throws Exception { + BackupManagerService backupManagerService = + createServiceAndRegisterUser(mUserOneId, mUserOneService); TransportData transport = backupTransport(); Intent configurationIntent = new Intent(); Intent dataManagementIntent = new Intent(); - mBackupManagerService.updateTransportAttributes( + backupManagerService.updateTransportAttributes( transport.getTransportComponent(), transport.transportName, configurationIntent, @@ -234,7 +445,34 @@ public class BackupManagerServiceTest { dataManagementIntent, "dataManagementLabel"); - verify(mUserBackupManagerService) + verify(mUserOneService) + .updateTransportAttributes( + transport.getTransportComponent(), + transport.transportName, + configurationIntent, + "currentDestinationString", + dataManagementIntent, + "dataManagementLabel"); + } + + /** Test that the backup service does not route methods for non-registered users. */ + @Test + public void testUpdateTransportAttributes_onUnknownUser_doesNotPropagateCall() + throws Exception { + BackupManagerService backupManagerService = createService(); + TransportData transport = backupTransport(); + Intent configurationIntent = new Intent(); + Intent dataManagementIntent = new Intent(); + + backupManagerService.updateTransportAttributes( + transport.getTransportComponent(), + transport.transportName, + configurationIntent, + "currentDestinationString", + dataManagementIntent, + "dataManagementLabel"); + + verify(mUserOneService, never()) .updateTransportAttributes( transport.getTransportComponent(), transport.transportName, @@ -246,136 +484,292 @@ public class BackupManagerServiceTest { /** Test that the backup service routes methods correctly to the user that requests it. */ @Test - public void testSelectBackupTransport_callsSelectBackupTransportForUser() throws Exception { - mBackupManagerService.selectBackupTransport(TEST_TRANSPORT); + public void testSelectBackupTransport_onRegisteredUser_callsMethodForUser() throws Exception { + BackupManagerService backupManagerService = + createServiceAndRegisterUser(mUserOneId, mUserOneService); + + backupManagerService.selectBackupTransport(TEST_TRANSPORT); + + verify(mUserOneService).selectBackupTransport(TEST_TRANSPORT); + } + + /** Test that the backup service does not route methods for non-registered users. */ + @Test + public void testSelectBackupTransport_onUnknownUser_doesNotPropagateCall() throws Exception { + BackupManagerService backupManagerService = createService(); + + backupManagerService.selectBackupTransport(TEST_TRANSPORT); - verify(mUserBackupManagerService).selectBackupTransport(TEST_TRANSPORT); + verify(mUserOneService, never()).selectBackupTransport(TEST_TRANSPORT); } /** Test that the backup service routes methods correctly to the user that requests it. */ @Test - public void testSelectTransportAsync_callsSelectTransportAsyncForUser() throws Exception { + public void testSelectTransportAsync_onRegisteredUser_callsMethodForUser() throws Exception { + BackupManagerService backupManagerService = + createServiceAndRegisterUser(mUserOneId, mUserOneService); TransportData transport = backupTransport(); ISelectBackupTransportCallback callback = mock(ISelectBackupTransportCallback.class); - mBackupManagerService.selectBackupTransportAsync( + backupManagerService.selectBackupTransportAsync( transport.getTransportComponent(), callback); - verify(mUserBackupManagerService) + verify(mUserOneService) + .selectBackupTransportAsync(transport.getTransportComponent(), callback); + } + + /** Test that the backup service does not route methods for non-registered users. */ + @Test + public void testSelectBackupTransportAsync_onUnknownUser_doesNotPropagateCall() + throws Exception { + BackupManagerService backupManagerService = createService(); + TransportData transport = backupTransport(); + ISelectBackupTransportCallback callback = mock(ISelectBackupTransportCallback.class); + + backupManagerService.selectBackupTransportAsync( + transport.getTransportComponent(), callback); + + verify(mUserOneService, never()) .selectBackupTransportAsync(transport.getTransportComponent(), callback); } /** Test that the backup service routes methods correctly to the user that requests it. */ @Test - public void testGetConfigurationIntent_callsGetConfigurationIntentForUser() throws Exception { - mBackupManagerService.getConfigurationIntent(TEST_TRANSPORT); + public void testGetConfigurationIntent_onRegisteredUser_callsMethodForUser() throws Exception { + BackupManagerService backupManagerService = + createServiceAndRegisterUser(mUserOneId, mUserOneService); - verify(mUserBackupManagerService).getConfigurationIntent(TEST_TRANSPORT); + backupManagerService.getConfigurationIntent(TEST_TRANSPORT); + + verify(mUserOneService).getConfigurationIntent(TEST_TRANSPORT); + } + + /** Test that the backup service does not route methods for non-registered users. */ + @Test + public void testGetConfigurationIntent_onUnknownUser_doesNotPropagateCall() throws Exception { + BackupManagerService backupManagerService = createService(); + + backupManagerService.getConfigurationIntent(TEST_TRANSPORT); + + verify(mUserOneService, never()).getConfigurationIntent(TEST_TRANSPORT); } /** Test that the backup service routes methods correctly to the user that requests it. */ @Test - public void testGetDestinationString_callsGetDestinationStringForUser() throws Exception { - mBackupManagerService.getDestinationString(TEST_TRANSPORT); + public void testGetDestinationString_onRegisteredUser_callsMethodForUser() throws Exception { + BackupManagerService backupManagerService = + createServiceAndRegisterUser(mUserOneId, mUserOneService); + + backupManagerService.getDestinationString(TEST_TRANSPORT); + + verify(mUserOneService).getDestinationString(TEST_TRANSPORT); + } + + /** Test that the backup service does not route methods for non-registered users. */ + @Test + public void testGetDestinationString_onUnknownUser_doesNotPropagateCall() throws Exception { + BackupManagerService backupManagerService = createService(); - verify(mUserBackupManagerService).getDestinationString(TEST_TRANSPORT); + backupManagerService.getDestinationString(TEST_TRANSPORT); + + verify(mUserOneService, never()).getDestinationString(TEST_TRANSPORT); } /** Test that the backup service routes methods correctly to the user that requests it. */ @Test - public void testGetDataManagementIntent_callsGetDataManagementIntentForUser() throws Exception { - mBackupManagerService.getDataManagementIntent(TEST_TRANSPORT); + public void testGetDataManagementIntent_onRegisteredUser_callsMethodForUser() throws Exception { + BackupManagerService backupManagerService = + createServiceAndRegisterUser(mUserOneId, mUserOneService); + + backupManagerService.getDataManagementIntent(TEST_TRANSPORT); - verify(mUserBackupManagerService).getDataManagementIntent(TEST_TRANSPORT); + verify(mUserOneService).getDataManagementIntent(TEST_TRANSPORT); + } + + /** Test that the backup service does not route methods for non-registered users. */ + @Test + public void testGetDataManagementIntent_onUnknownUser_doesNotPropagateCall() throws Exception { + BackupManagerService backupManagerService = createService(); + + backupManagerService.getDataManagementIntent(TEST_TRANSPORT); + + verify(mUserOneService, never()).getDataManagementIntent(TEST_TRANSPORT); } /** Test that the backup service routes methods correctly to the user that requests it. */ @Test - public void testGetDataManagementLabel_callsGetDataManagementLabelForUser() throws Exception { - mBackupManagerService.getDataManagementLabel(TEST_TRANSPORT); + public void testGetDataManagementLabel_onRegisteredUser_callsMethodForUser() throws Exception { + BackupManagerService backupManagerService = + createServiceAndRegisterUser(mUserOneId, mUserOneService); + + backupManagerService.getDataManagementLabel(TEST_TRANSPORT); - verify(mUserBackupManagerService).getDataManagementLabel(TEST_TRANSPORT); + verify(mUserOneService).getDataManagementLabel(TEST_TRANSPORT); + } + + /** Test that the backup service does not route methods for non-registered users. */ + @Test + public void testGetDataManagementLabel_onUnknownUser_doesNotPropagateCall() throws Exception { + BackupManagerService backupManagerService = createService(); + + backupManagerService.getDataManagementLabel(TEST_TRANSPORT); + + verify(mUserOneService, never()).getDataManagementLabel(TEST_TRANSPORT); } // --------------------------------------------- // Settings tests // --------------------------------------------- + /** - * Test verifying that {@link BackupManagerService#setBackupEnabled(int, boolean)} throws a - * {@link SecurityException} if the caller does not have INTERACT_ACROSS_USERS_FULL permission. + * Test that the backup services throws a {@link SecurityException} if the caller does not have + * INTERACT_ACROSS_USERS_FULL permission and passes a different user id. */ @Test - public void setBackupEnabled_withoutPermission_throwsSecurityException() { - mShadowContext.denyPermissions(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL); + public void testSetBackupEnabled_withoutPermission_throwsSecurityExceptionForNonCallingUser() { + BackupManagerService backupManagerService = + createServiceAndRegisterUser(mUserOneId, mUserOneService); + setCallerAndGrantInteractUserPermission(mUserOneId, /* shouldGrantPermission */ false); expectThrows( SecurityException.class, - () -> mBackupManagerService.setBackupEnabled(mUserId, true)); + () -> backupManagerService.setBackupEnabled(mUserTwoId, true)); } /** - * Test verifying that {@link BackupManagerService#setBackupEnabled(int, boolean)} does not - * require the caller to have INTERACT_ACROSS_USERS_FULL permission when the calling user id is - * the same as the target user id. + * Test that the backup service does not throw a {@link SecurityException} if the caller has + * INTERACT_ACROSS_USERS_FULL permission and passes a different user id. */ @Test - public void setBackupEnabled_whenCallingUserIsTargetUser_doesntNeedPermission() { - ShadowBinder.setCallingUserHandle(UserHandle.of(mUserId)); - mShadowContext.denyPermissions(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL); + public void testSetBackupEnabled_withPermission_propagatesForNonCallingUser() { + BackupManagerService backupManagerService = + createServiceAndRegisterUser(mUserOneId, mUserOneService); + backupManagerService.startServiceForUser(mUserTwoId, mUserTwoService); + setCallerAndGrantInteractUserPermission(mUserOneId, /* shouldGrantPermission */ true); - mBackupManagerService.setBackupEnabled(mUserId, true); + backupManagerService.setBackupEnabled(mUserTwoId, true); - verify(mUserBackupManagerService).setBackupEnabled(true); + verify(mUserTwoService).setBackupEnabled(true); } - /** Test that the backup service routes methods correctly to the user that requests it. */ @Test - public void setBackupEnabled_callsSetBackupEnabledForUser() throws Exception { - mShadowContext.grantPermissions(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL); + public void testSetBackupEnabled_onRegisteredUser_callsMethodForUser() throws Exception { + BackupManagerService backupManagerService = + createServiceAndRegisterUser(mUserOneId, mUserOneService); + setCallerAndGrantInteractUserPermission(mUserOneId, /* shouldGrantPermission */ false); + + backupManagerService.setBackupEnabled(mUserOneId, true); + + verify(mUserOneService).setBackupEnabled(true); + } + + /** Test that the backup service does not route methods for non-registered users. */ + @Test + public void testSetBackupEnabled_onUnknownUser_doesNotPropagateCall() throws Exception { + BackupManagerService backupManagerService = + createServiceAndRegisterUser(mUserOneId, mUserOneService); + setCallerAndGrantInteractUserPermission(mUserTwoId, /* shouldGrantPermission */ false); - mBackupManagerService.setBackupEnabled(mUserId, true); + backupManagerService.setBackupEnabled(mUserTwoId, true); - verify(mUserBackupManagerService).setBackupEnabled(true); + verify(mUserOneService, never()).setBackupEnabled(true); } /** Test that the backup service routes methods correctly to the user that requests it. */ @Test - public void setAutoRestore_callsSetAutoRestoreForUser() throws Exception { - mBackupManagerService.setAutoRestore(true); + public void testSetAutoRestore_onRegisteredUser_callsMethodForUser() throws Exception { + BackupManagerService backupManagerService = + createServiceAndRegisterUser(mUserOneId, mUserOneService); + + backupManagerService.setAutoRestore(true); + + verify(mUserOneService).setAutoRestore(true); + } + + /** Test that the backup service does not route methods for non-registered users. */ + @Test + public void testSetAutoRestore_onUnknownUser_doesNotPropagateCall() throws Exception { + BackupManagerService backupManagerService = createService(); + + backupManagerService.setAutoRestore(true); - verify(mUserBackupManagerService).setAutoRestore(true); + verify(mUserOneService, never()).setAutoRestore(true); } /** Test that the backup service routes methods correctly to the user that requests it. */ @Test - public void testSetBackupProvisioned_callsSetBackupProvisionedForUser() throws Exception { - mBackupManagerService.setBackupProvisioned(true); + public void testSetBackupProvisioned_onRegisteredUser_callsMethodForUser() throws Exception { + BackupManagerService backupManagerService = + createServiceAndRegisterUser(mUserOneId, mUserOneService); - verify(mUserBackupManagerService).setBackupProvisioned(true); + backupManagerService.setBackupProvisioned(true); + + verify(mUserOneService).setBackupProvisioned(true); + } + + /** Test that the backup service does not route methods for non-registered users. */ + @Test + public void testSetBackupProvisioned_onUnknownUser_doesNotPropagateCall() throws Exception { + BackupManagerService backupManagerService = createService(); + + backupManagerService.setBackupProvisioned(true); + + verify(mUserOneService, never()).setBackupProvisioned(true); } /** - * Test verifying that {@link BackupManagerService#isBackupEnabled(int)} throws a - * {@link SecurityException} if the caller does not have INTERACT_ACROSS_USERS_FULL permission. + * Test that the backup services throws a {@link SecurityException} if the caller does not have + * INTERACT_ACROSS_USERS_FULL permission and passes a different user id. */ @Test - public void testIsBackupEnabled_withoutPermission_throwsSecurityException() { - mShadowContext.denyPermissions(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL); + public void testIsBackupEnabled_withoutPermission_throwsSecurityExceptionForNonCallingUser() { + BackupManagerService backupManagerService = + createServiceAndRegisterUser(mUserOneId, mUserOneService); + setCallerAndGrantInteractUserPermission(mUserOneId, /* shouldGrantPermission */ false); expectThrows( - SecurityException.class, - () -> mBackupManagerService.isBackupEnabled(mUserId)); + SecurityException.class, () -> backupManagerService.isBackupEnabled(mUserTwoId)); + } + + /** + * Test that the backup service does not throw a {@link SecurityException} if the caller has + * INTERACT_ACROSS_USERS_FULL permission and passes a different user id. + */ + @Test + public void testIsBackupEnabled_withPermission_propagatesForNonCallingUser() { + BackupManagerService backupManagerService = + createServiceAndRegisterUser(mUserOneId, mUserOneService); + backupManagerService.startServiceForUser(mUserTwoId, mUserTwoService); + setCallerAndGrantInteractUserPermission(mUserOneId, /* shouldGrantPermission */ true); + + backupManagerService.isBackupEnabled(mUserTwoId); + + verify(mUserTwoService).isBackupEnabled(); } /** Test that the backup service routes methods correctly to the user that requests it. */ @Test - public void testIsBackupEnabled_callsIsBackupEnabledForUser() throws Exception { - mShadowContext.grantPermissions(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL); + public void testIsBackupEnabled_onRegisteredUser_callsMethodForUser() throws Exception { + BackupManagerService backupManagerService = + createServiceAndRegisterUser(mUserOneId, mUserOneService); + setCallerAndGrantInteractUserPermission(mUserOneId, /* shouldGrantPermission */ false); + + backupManagerService.isBackupEnabled(mUserOneId); + + verify(mUserOneService).isBackupEnabled(); + } + + /** Test that the backup service does not route methods for non-registered users. */ + @Test + public void testIsBackupEnabled_onUnknownUser_doesNotPropagateCall() throws Exception { + BackupManagerService backupManagerService = + createServiceAndRegisterUser(mUserOneId, mUserOneService); + setCallerAndGrantInteractUserPermission(mUserTwoId, /* shouldGrantPermission */ false); - mBackupManagerService.isBackupEnabled(mUserId); + backupManagerService.isBackupEnabled(mUserTwoId); - verify(mUserBackupManagerService).isBackupEnabled(); + verify(mUserOneService, never()).isBackupEnabled(); } // --------------------------------------------- @@ -384,128 +778,290 @@ public class BackupManagerServiceTest { /** Test that the backup service routes methods correctly to the user that requests it. */ @Test - public void testIsAppEligibleForBackup_callsIsAppEligibleForBackupForUser() throws Exception { - mBackupManagerService.isAppEligibleForBackup(TEST_PACKAGE); + public void testIsAppEligibleForBackup_onRegisteredUser_callsMethodForUser() throws Exception { + BackupManagerService backupManagerService = + createServiceAndRegisterUser(mUserOneId, mUserOneService); + + backupManagerService.isAppEligibleForBackup(TEST_PACKAGE); + + verify(mUserOneService).isAppEligibleForBackup(TEST_PACKAGE); + } + + /** Test that the backup service does not route methods for non-registered users. */ + @Test + public void testIsAppEligibleForBackup_onUnknownUser_doesNotPropagateCall() throws Exception { + BackupManagerService backupManagerService = createService(); + + backupManagerService.isAppEligibleForBackup(TEST_PACKAGE); - verify(mUserBackupManagerService).isAppEligibleForBackup(TEST_PACKAGE); + verify(mUserOneService, never()).isAppEligibleForBackup(TEST_PACKAGE); } /** Test that the backup service routes methods correctly to the user that requests it. */ @Test - public void testFilterAppsEligibleForBackup_callsFilterAppsEligibleForBackupForUser() + public void testFilterAppsEligibleForBackup_onRegisteredUser_callsMethodForUser() + throws Exception { + BackupManagerService backupManagerService = + createServiceAndRegisterUser(mUserOneId, mUserOneService); + String[] packages = {TEST_PACKAGE}; + + backupManagerService.filterAppsEligibleForBackup(packages); + + verify(mUserOneService).filterAppsEligibleForBackup(packages); + } + + /** Test that the backup service does not route methods for non-registered users. */ + @Test + public void testFilterAppsEligibleForBackup_onUnknownUser_doesNotPropagateCall() throws Exception { + BackupManagerService backupManagerService = createService(); String[] packages = {TEST_PACKAGE}; - mBackupManagerService.filterAppsEligibleForBackup(packages); + backupManagerService.filterAppsEligibleForBackup(packages); - verify(mUserBackupManagerService).filterAppsEligibleForBackup(packages); + verify(mUserOneService, never()).filterAppsEligibleForBackup(packages); } /** - * Test verifying that {@link BackupManagerService#backupNow(int)} throws a - * {@link SecurityException} if the caller does not have INTERACT_ACROSS_USERS_FULL permission. + * Test verifying that {@link BackupManagerService#backupNow(int)} throws a {@link + * SecurityException} if the caller does not have INTERACT_ACROSS_USERS_FULL permission. */ @Test - public void testBackupNow_withoutPermission_throwsSecurityException() { - mShadowContext.denyPermissions(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL); + public void testBackupNow_withoutPermission_throwsSecurityExceptionForNonCallingUser() { + BackupManagerService backupManagerService = + createServiceAndRegisterUser(mUserOneId, mUserOneService); + setCallerAndGrantInteractUserPermission(mUserOneId, /* shouldGrantPermission */ false); - expectThrows( - SecurityException.class, - () -> mBackupManagerService.backupNow(mUserId)); + expectThrows(SecurityException.class, () -> backupManagerService.backupNow(mUserTwoId)); + } + + /** + * Test that the backup service does not throw a {@link SecurityException} if the caller has + * INTERACT_ACROSS_USERS_FULL permission and passes a different user id. + */ + @Test + public void testBackupNow_withPermission_propagatesForNonCallingUser() { + BackupManagerService backupManagerService = + createServiceAndRegisterUser(mUserOneId, mUserOneService); + backupManagerService.startServiceForUser(mUserTwoId, mUserTwoService); + setCallerAndGrantInteractUserPermission(mUserOneId, /* shouldGrantPermission */ true); + + backupManagerService.backupNow(mUserTwoId); + + verify(mUserTwoService).backupNow(); } /** Test that the backup service routes methods correctly to the user that requests it. */ @Test - public void testBackupNow_callsBackupNowForUser() throws Exception { - mShadowContext.grantPermissions(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL); + public void testBackupNow_onRegisteredUser_callsMethodForUser() throws Exception { + BackupManagerService backupManagerService = + createServiceAndRegisterUser(mUserOneId, mUserOneService); + setCallerAndGrantInteractUserPermission(mUserOneId, /* shouldGrantPermission */ false); - mBackupManagerService.backupNow(mUserId); + backupManagerService.backupNow(mUserOneId); - verify(mUserBackupManagerService).backupNow(); + verify(mUserOneService).backupNow(); + } + + /** Test that the backup service does not route methods for non-registered users. */ + @Test + public void testBackupNow_onUnknownUser_doesNotPropagateCall() throws Exception { + BackupManagerService backupManagerService = + createServiceAndRegisterUser(mUserOneId, mUserOneService); + setCallerAndGrantInteractUserPermission(mUserTwoId, /* shouldGrantPermission */ false); + + backupManagerService.backupNow(mUserTwoId); + + verify(mUserOneService, never()).backupNow(); } /** - * Test verifying that {@link BackupManagerService#requestBackup(int, String[], IBackupObserver, - * IBackupManagerMonitor, int)} throws a {@link SecurityException} if the caller does not have - * INTERACT_ACROSS_USERS_FULL permission. + * Test that the backup services throws a {@link SecurityException} if the caller does not have + * INTERACT_ACROSS_USERS_FULL permission and passes a different user id. */ @Test - public void testRequestBackup_withoutPermission_throwsSecurityException() { - mShadowContext.denyPermissions(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL); + public void testRequestBackup_withoutPermission_throwsSecurityExceptionForNonCallingUser() { + BackupManagerService backupManagerService = + createServiceAndRegisterUser(mUserOneId, mUserOneService); + setCallerAndGrantInteractUserPermission(mUserOneId, /* shouldGrantPermission */ false); String[] packages = {TEST_PACKAGE}; IBackupObserver observer = mock(IBackupObserver.class); IBackupManagerMonitor monitor = mock(IBackupManagerMonitor.class); expectThrows( SecurityException.class, - () -> mBackupManagerService.requestBackup(mUserId, packages, observer, monitor, 0)); + () -> + backupManagerService.requestBackup( + mUserTwoId, packages, observer, monitor, 0)); } + /** + * Test that the backup service does not throw a {@link SecurityException} if the caller has + * INTERACT_ACROSS_USERS_FULL permission and passes a different user id. + */ + @Test + public void testRequestBackup_withPermission_propagatesForNonCallingUser() { + BackupManagerService backupManagerService = + createServiceAndRegisterUser(mUserOneId, mUserOneService); + backupManagerService.startServiceForUser(mUserTwoId, mUserTwoService); + String[] packages = {TEST_PACKAGE}; + IBackupObserver observer = mock(IBackupObserver.class); + IBackupManagerMonitor monitor = mock(IBackupManagerMonitor.class); + setCallerAndGrantInteractUserPermission(mUserOneId, /* shouldGrantPermission */ true); + + backupManagerService.requestBackup(mUserTwoId, packages, observer, monitor, /* flags */ 0); + + verify(mUserTwoService).requestBackup(packages, observer, monitor, /* flags */ 0); + } + + /** Test that the backup service routes methods correctly to the user that requests it. */ + @Test + public void testRequestBackup_onRegisteredUser_callsMethodForUser() throws Exception { + BackupManagerService backupManagerService = + createServiceAndRegisterUser(mUserOneId, mUserOneService); + String[] packages = {TEST_PACKAGE}; + IBackupObserver observer = mock(IBackupObserver.class); + IBackupManagerMonitor monitor = mock(IBackupManagerMonitor.class); + setCallerAndGrantInteractUserPermission(mUserOneId, /* shouldGrantPermission */ false); + + backupManagerService.requestBackup(mUserOneId, packages, observer, monitor, /* flags */ 0); + + verify(mUserOneService).requestBackup(packages, observer, monitor, /* flags */ 0); + } /** Test that the backup service routes methods correctly to the user that requests it. */ @Test - public void testRequestBackup_callsRequestBackupForUser() throws Exception { - mShadowContext.grantPermissions(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL); + public void testRequestBackup_onUnknownUser_doesNotPropagateCall() throws Exception { + BackupManagerService backupManagerService = + createServiceAndRegisterUser(mUserOneId, mUserOneService); String[] packages = {TEST_PACKAGE}; IBackupObserver observer = mock(IBackupObserver.class); IBackupManagerMonitor monitor = mock(IBackupManagerMonitor.class); + setCallerAndGrantInteractUserPermission(mUserTwoId, /* shouldGrantPermission */ false); - mBackupManagerService.requestBackup(mUserId, packages, observer, monitor, - /* flags */ 0); + backupManagerService.requestBackup(mUserTwoId, packages, observer, monitor, /* flags */ 0); - verify(mUserBackupManagerService).requestBackup(packages, observer, monitor, /* flags */ 0); + verify(mUserOneService, never()).requestBackup(packages, observer, monitor, /* flags */ 0); } /** - * Test verifying that {@link BackupManagerService#cancelBackups(int)} throws a - * {@link SecurityException} if the caller does not have INTERACT_ACROSS_USERS_FULL permission. + * Test verifying that {@link BackupManagerService#cancelBackups(int)} throws a {@link + * SecurityException} if the caller does not have INTERACT_ACROSS_USERS_FULL permission. */ @Test - public void testCancelBackups_withoutPermission_throwsSecurityException() { - mShadowContext.denyPermissions(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL); + public void testCancelBackups_withoutPermission_throwsSecurityExceptionForNonCallingUser() { + BackupManagerService backupManagerService = + createServiceAndRegisterUser(mUserOneId, mUserOneService); + setCallerAndGrantInteractUserPermission(mUserOneId, /* shouldGrantPermission */ false); - expectThrows( - SecurityException.class, - () -> mBackupManagerService.cancelBackups(mUserId)); + expectThrows(SecurityException.class, () -> backupManagerService.cancelBackups(mUserTwoId)); } + /** + * Test that the backup service does not throw a {@link SecurityException} if the caller has + * INTERACT_ACROSS_USERS_FULL permission and passes a different user id. + */ + @Test + public void testCancelBackups_withPermission_propagatesForNonCallingUser() { + BackupManagerService backupManagerService = + createServiceAndRegisterUser(mUserOneId, mUserOneService); + backupManagerService.startServiceForUser(mUserTwoId, mUserTwoService); + setCallerAndGrantInteractUserPermission(mUserOneId, /* shouldGrantPermission */ true); + + backupManagerService.cancelBackups(mUserTwoId); + + verify(mUserTwoService).cancelBackups(); + } /** Test that the backup service routes methods correctly to the user that requests it. */ @Test - public void testCancelBackups_callsCancelBackupsForUser() throws Exception { - mShadowContext.grantPermissions(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL); + public void testCancelBackups_onRegisteredUser_callsMethodForUser() throws Exception { + BackupManagerService backupManagerService = + createServiceAndRegisterUser(mUserOneId, mUserOneService); + setCallerAndGrantInteractUserPermission(mUserOneId, /* shouldGrantPermission */ false); + + backupManagerService.cancelBackups(mUserOneId); + + verify(mUserOneService).cancelBackups(); + } + + /** Test that the backup service does not route methods for non-registered users. */ + @Test + public void testCancelBackups_onUnknownUser_doesNotPropagateCall() throws Exception { + BackupManagerService backupManagerService = + createServiceAndRegisterUser(mUserOneId, mUserOneService); + setCallerAndGrantInteractUserPermission(mUserTwoId, /* shouldGrantPermission */ false); - mBackupManagerService.cancelBackups(mUserId); + backupManagerService.cancelBackups(mUserTwoId); - verify(mUserBackupManagerService).cancelBackups(); + verify(mUserOneService, never()).cancelBackups(); } /** Test that the backup service routes methods correctly to the user that requests it. */ @Test - public void testBeginFullBackup_callsBeginFullBackupForUser() throws Exception { + public void testBeginFullBackup_onRegisteredUser_callsMethodForUser() throws Exception { + BackupManagerService backupManagerService = + createServiceAndRegisterUser(mUserOneId, mUserOneService); FullBackupJob job = new FullBackupJob(); - mBackupManagerService.beginFullBackup(job); + backupManagerService.beginFullBackup(job); - verify(mUserBackupManagerService).beginFullBackup(job); + verify(mUserOneService).beginFullBackup(job); + } + + /** Test that the backup service does not route methods for non-registered users. */ + @Test + public void testBeginFullBackup_onUnknownUser_doesNotPropagateCall() throws Exception { + BackupManagerService backupManagerService = createService(); + FullBackupJob job = new FullBackupJob(); + + backupManagerService.beginFullBackup(job); + + verify(mUserOneService, never()).beginFullBackup(job); } /** Test that the backup service routes methods correctly to the user that requests it. */ @Test - public void testEndFullBackup_callsEndFullBackupForUser() throws Exception { - mBackupManagerService.endFullBackup(); + public void testEndFullBackup_onRegisteredUser_callsMethodForUser() throws Exception { + BackupManagerService backupManagerService = + createServiceAndRegisterUser(mUserOneId, mUserOneService); + + backupManagerService.endFullBackup(); + + verify(mUserOneService).endFullBackup(); + } + + /** Test that the backup service does not route methods for non-registered users. */ + @Test + public void testEndFullBackup_onUnknownUser_doesNotPropagateCall() throws Exception { + BackupManagerService backupManagerService = createService(); + + backupManagerService.endFullBackup(); - verify(mUserBackupManagerService).endFullBackup(); + verify(mUserOneService, never()).endFullBackup(); } /** Test that the backup service routes methods correctly to the user that requests it. */ @Test - public void testFullTransportBackup_callsFullTransportBackupForUser() throws Exception { + public void testFullTransportBackup_onRegisteredUser_callsMethodForUser() throws Exception { + BackupManagerService backupManagerService = + createServiceAndRegisterUser(mUserOneId, mUserOneService); String[] packages = {TEST_PACKAGE}; - mBackupManagerService.fullTransportBackup(packages); + backupManagerService.fullTransportBackup(packages); - verify(mUserBackupManagerService).fullTransportBackup(packages); + verify(mUserOneService).fullTransportBackup(packages); + } + + /** Test that the backup service does not route methods for non-registered users. */ + @Test + public void testFullTransportBackup_onUnknownUser_doesNotPropagateCall() throws Exception { + BackupManagerService backupManagerService = createService(); + String[] packages = {TEST_PACKAGE}; + + backupManagerService.fullTransportBackup(packages); + + verify(mUserOneService, never()).fullTransportBackup(packages); } // --------------------------------------------- @@ -514,27 +1070,66 @@ public class BackupManagerServiceTest { /** Test that the backup service routes methods correctly to the user that requests it. */ @Test - public void testRestoreAtInstall_callsRestoreAtInstallForUser() throws Exception { - mBackupManagerService.restoreAtInstall(TEST_PACKAGE, /* token */ 0); + public void testRestoreAtInstall_onRegisteredUser_callsMethodForUser() throws Exception { + BackupManagerService backupManagerService = + createServiceAndRegisterUser(mUserOneId, mUserOneService); + + backupManagerService.restoreAtInstall(TEST_PACKAGE, /* token */ 0); - verify(mUserBackupManagerService).restoreAtInstall(TEST_PACKAGE, /* token */ 0); + verify(mUserOneService).restoreAtInstall(TEST_PACKAGE, /* token */ 0); + } + + /** Test that the backup service does not route methods for non-registered users. */ + @Test + public void testRestoreAtInstall_onUnknownUser_doesNotPropagateCall() throws Exception { + BackupManagerService backupManagerService = createService(); + + backupManagerService.restoreAtInstall(TEST_PACKAGE, /* token */ 0); + + verify(mUserOneService, never()).restoreAtInstall(TEST_PACKAGE, /* token */ 0); } /** Test that the backup service routes methods correctly to the user that requests it. */ @Test - public void testBeginRestoreSession_callsBeginRestoreSessionForUser() throws Exception { - mBackupManagerService.beginRestoreSession(TEST_PACKAGE, TEST_TRANSPORT); + public void testBeginRestoreSession_onRegisteredUser_callsMethodForUser() throws Exception { + BackupManagerService backupManagerService = + createServiceAndRegisterUser(mUserOneId, mUserOneService); + + backupManagerService.beginRestoreSession(TEST_PACKAGE, TEST_TRANSPORT); - verify(mUserBackupManagerService).beginRestoreSession(TEST_PACKAGE, TEST_TRANSPORT); + verify(mUserOneService).beginRestoreSession(TEST_PACKAGE, TEST_TRANSPORT); + } + + /** Test that the backup service does not route methods for non-registered users. */ + @Test + public void testBeginRestoreSession_onUnknownUser_doesNotPropagateCall() throws Exception { + BackupManagerService backupManagerService = createService(); + + backupManagerService.beginRestoreSession(TEST_PACKAGE, TEST_TRANSPORT); + + verify(mUserOneService, never()).beginRestoreSession(TEST_PACKAGE, TEST_TRANSPORT); } /** Test that the backup service routes methods correctly to the user that requests it. */ @Test - public void testGetAvailableRestoreToken_callsGetAvailableRestoreTokenForUser() + public void testGetAvailableRestoreToken_onRegisteredUser_callsMethodForUser() throws Exception { - mBackupManagerService.getAvailableRestoreToken(TEST_PACKAGE); + BackupManagerService backupManagerService = + createServiceAndRegisterUser(mUserOneId, mUserOneService); + + backupManagerService.getAvailableRestoreToken(TEST_PACKAGE); + + verify(mUserOneService).getAvailableRestoreToken(TEST_PACKAGE); + } - verify(mUserBackupManagerService).getAvailableRestoreToken(TEST_PACKAGE); + /** Test that the backup service does not route methods for non-registered users. */ + @Test + public void testGetAvailableRestoreToken_onUnknownUser_doesNotPropagateCall() throws Exception { + BackupManagerService backupManagerService = createService(); + + backupManagerService.getAvailableRestoreToken(TEST_PACKAGE); + + verify(mUserOneService, never()).getAvailableRestoreToken(TEST_PACKAGE); } // --------------------------------------------- @@ -543,33 +1138,61 @@ public class BackupManagerServiceTest { /** Test that the backup service routes methods correctly to the user that requests it. */ @Test - public void testSetBackupPassword_callsSetBackupPasswordForUser() throws Exception { - mBackupManagerService.setBackupPassword("currentPassword", "newPassword"); + public void testSetBackupPassword_onRegisteredUser_callsMethodForUser() throws Exception { + BackupManagerService backupManagerService = + createServiceAndRegisterUser(mUserOneId, mUserOneService); + + backupManagerService.setBackupPassword("currentPassword", "newPassword"); + + verify(mUserOneService).setBackupPassword("currentPassword", "newPassword"); + } + + /** Test that the backup service does not route methods for non-registered users. */ + @Test + public void testSetBackupPassword_onUnknownUser_doesNotPropagateCall() throws Exception { + BackupManagerService backupManagerService = createService(); + + backupManagerService.setBackupPassword("currentPassword", "newPassword"); - verify(mUserBackupManagerService).setBackupPassword("currentPassword", "newPassword"); + verify(mUserOneService, never()).setBackupPassword("currentPassword", "newPassword"); } /** Test that the backup service routes methods correctly to the user that requests it. */ @Test - public void testHasBackupPassword_callsHasBackupPasswordForUser() throws Exception { - mBackupManagerService.hasBackupPassword(); + public void testHasBackupPassword_onRegisteredUser_callsMethodForUser() throws Exception { + BackupManagerService backupManagerService = + createServiceAndRegisterUser(mUserOneId, mUserOneService); + + backupManagerService.hasBackupPassword(); + + verify(mUserOneService).hasBackupPassword(); + } + + /** Test that the backup service does not route methods for non-registered users. */ + @Test + public void testHasBackupPassword_onUnknownUser_doesNotPropagateCall() throws Exception { + BackupManagerService backupManagerService = createService(); + + backupManagerService.hasBackupPassword(); - verify(mUserBackupManagerService).hasBackupPassword(); + verify(mUserOneService, never()).hasBackupPassword(); } /** - * Test verifying that {@link BackupManagerService#adbBackup(ParcelFileDescriptor, int, boolean, - * boolean, boolean, boolean, boolean, boolean, boolean, boolean, String[])} throws a - * {@link SecurityException} if the caller does not have INTERACT_ACROSS_USERS_FULL permission. + * Test that the backup services throws a {@link SecurityException} if the caller does not have + * INTERACT_ACROSS_USERS_FULL permission and passes a different user id. */ @Test - public void testAdbBackup_withoutPermission_throwsSecurityException() { - mShadowContext.denyPermissions(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL); + public void testAdbBackup_withoutPermission_throwsSecurityExceptionForNonCallingUser() { + BackupManagerService backupManagerService = + createServiceAndRegisterUser(mUserOneId, mUserOneService); + setCallerAndGrantInteractUserPermission(mUserOneId, /* shouldGrantPermission */ false); - expectThrows(SecurityException.class, + expectThrows( + SecurityException.class, () -> - mBackupManagerService.adbBackup( - /* userId */ mUserId, + backupManagerService.adbBackup( + mUserTwoId, /* parcelFileDescriptor*/ null, /* includeApks */ true, /* includeObbs */ true, @@ -580,24 +1203,22 @@ public class BackupManagerServiceTest { /* doCompress */ true, /* doKeyValue */ true, null)); - } /** - * Test verifying that {@link BackupManagerService#adbBackup(ParcelFileDescriptor, int, boolean, - * boolean, boolean, boolean, boolean, boolean, boolean, boolean, String[])} does not require - * the caller to have INTERACT_ACROSS_USERS_FULL permission when the calling user id is the - * same as the target user id. + * Test that the backup service does not throw a {@link SecurityException} if the caller has + * INTERACT_ACROSS_USERS_FULL permission and passes a different user id. */ @Test - public void testAdbBackup_whenCallingUserIsTargetUser_doesntNeedPermission() throws Exception { - ShadowBinder.setCallingUserHandle(UserHandle.of(mUserId)); - mShadowContext.denyPermissions(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL); - + public void testAdbBackup_withPermission_propagatesForNonCallingUser() throws Exception { + BackupManagerService backupManagerService = + createServiceAndRegisterUser(mUserOneId, mUserOneService); + backupManagerService.startServiceForUser(mUserTwoId, mUserTwoService); ParcelFileDescriptor parcelFileDescriptor = getFileDescriptorForAdbTest(); + setCallerAndGrantInteractUserPermission(mUserOneId, /* shouldGrantPermission */ true); - mBackupManagerService.adbBackup( - /* userId */ mUserId, + backupManagerService.adbBackup( + mUserTwoId, parcelFileDescriptor, /* includeApks */ true, /* includeObbs */ true, @@ -609,7 +1230,7 @@ public class BackupManagerServiceTest { /* doKeyValue */ true, ADB_TEST_PACKAGES); - verify(mUserBackupManagerService) + verify(mUserTwoService) .adbBackup( parcelFileDescriptor, /* includeApks */ true, @@ -625,13 +1246,49 @@ public class BackupManagerServiceTest { /** Test that the backup service routes methods correctly to the user that requests it. */ @Test - public void testAdbBackup_callsAdbBackupForUser() throws Exception { - mShadowContext.grantPermissions(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL); + public void testAdbBackup_onRegisteredUser_callsMethodForUser() throws Exception { + BackupManagerService backupManagerService = + createServiceAndRegisterUser(mUserOneId, mUserOneService); + ParcelFileDescriptor parcelFileDescriptor = getFileDescriptorForAdbTest(); + setCallerAndGrantInteractUserPermission(mUserOneId, /* shouldGrantPermission */ false); + backupManagerService.adbBackup( + mUserOneId, + parcelFileDescriptor, + /* includeApks */ true, + /* includeObbs */ true, + /* includeShared */ true, + /* doWidgets */ true, + /* doAllApps */ true, + /* includeSystem */ true, + /* doCompress */ true, + /* doKeyValue */ true, + ADB_TEST_PACKAGES); + + verify(mUserOneService) + .adbBackup( + parcelFileDescriptor, + /* includeApks */ true, + /* includeObbs */ true, + /* includeShared */ true, + /* doWidgets */ true, + /* doAllApps */ true, + /* includeSystem */ true, + /* doCompress */ true, + /* doKeyValue */ true, + ADB_TEST_PACKAGES); + } + + /** Test that the backup service does not route methods for non-registered users. */ + @Test + public void testAdbBackup_onUnknownUser_doesNotPropagateCall() throws Exception { + BackupManagerService backupManagerService = + createServiceAndRegisterUser(mUserOneId, mUserOneService); ParcelFileDescriptor parcelFileDescriptor = getFileDescriptorForAdbTest(); + setCallerAndGrantInteractUserPermission(mUserTwoId, /* shouldGrantPermission */ false); - mBackupManagerService.adbBackup( - /* userId */ mUserId, + backupManagerService.adbBackup( + mUserTwoId, parcelFileDescriptor, /* includeApks */ true, /* includeObbs */ true, @@ -643,7 +1300,7 @@ public class BackupManagerServiceTest { /* doKeyValue */ true, ADB_TEST_PACKAGES); - verify(mUserBackupManagerService) + verify(mUserOneService, never()) .adbBackup( parcelFileDescriptor, /* includeApks */ true, @@ -658,58 +1315,93 @@ public class BackupManagerServiceTest { } /** - * Test verifying that {@link BackupManagerService#adbRestore(ParcelFileDescriptor, int)} throws - * a {@link SecurityException} if the caller does not have INTERACT_ACROSS_USERS_FULL - * permission. + * Test that the backup services throws a {@link SecurityException} if the caller does not have + * INTERACT_ACROSS_USERS_FULL permission and passes a different user id. */ @Test - public void testAdbRestore_withoutPermission_throwsSecurityException() { - mShadowContext.denyPermissions(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL); - - expectThrows(SecurityException.class, - () -> mBackupManagerService.adbRestore(mUserId, null)); + public void testAdbRestore_withoutPermission_throwsSecurityExceptionForNonCallingUser() { + BackupManagerService backupManagerService = + createServiceAndRegisterUser(mUserOneId, mUserOneService); + setCallerAndGrantInteractUserPermission(mUserOneId, /* shouldGrantPermission */ false); + expectThrows( + SecurityException.class, () -> backupManagerService.adbRestore(mUserTwoId, null)); } /** - * Test verifying that {@link BackupManagerService#adbRestore(ParcelFileDescriptor, int)} does - * not require the caller to have INTERACT_ACROSS_USERS_FULL permission when the calling user id - * is the same as the target user id. + * Test that the backup service does not throw a {@link SecurityException} if the caller has + * INTERACT_ACROSS_USERS_FULL permission and passes a different user id. */ @Test - public void testAdbRestore_whenCallingUserIsTargetUser_doesntNeedPermission() throws Exception { - ShadowBinder.setCallingUserHandle(UserHandle.of(mUserId)); - mShadowContext.denyPermissions(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL); - + public void testAdbRestore_withPermission_propagatesForNonCallingUser() throws Exception { + BackupManagerService backupManagerService = + createServiceAndRegisterUser(mUserOneId, mUserOneService); + backupManagerService.startServiceForUser(mUserTwoId, mUserTwoService); ParcelFileDescriptor parcelFileDescriptor = getFileDescriptorForAdbTest(); + setCallerAndGrantInteractUserPermission(mUserOneId, /* shouldGrantPermission */ true); - mBackupManagerService.adbRestore(mUserId, parcelFileDescriptor); + backupManagerService.adbRestore(mUserTwoId, parcelFileDescriptor); - verify(mUserBackupManagerService).adbRestore(parcelFileDescriptor); + verify(mUserTwoService).adbRestore(parcelFileDescriptor); } /** Test that the backup service routes methods correctly to the user that requests it. */ @Test - public void testAdbRestore_callsAdbRestoreForUser() throws Exception { - mShadowContext.grantPermissions(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL); + public void testAdbRestore_onRegisteredUser_callsMethodForUser() throws Exception { + BackupManagerService backupManagerService = + createServiceAndRegisterUser(mUserOneId, mUserOneService); + ParcelFileDescriptor parcelFileDescriptor = getFileDescriptorForAdbTest(); + setCallerAndGrantInteractUserPermission(mUserOneId, /* shouldGrantPermission */ false); + + backupManagerService.adbRestore(mUserOneId, parcelFileDescriptor); + + verify(mUserOneService).adbRestore(parcelFileDescriptor); + } + /** Test that the backup service does not route methods for non-registered users. */ + @Test + public void testAdbRestore_onUnknownUser_doesNotPropagateCall() throws Exception { + BackupManagerService backupManagerService = + createServiceAndRegisterUser(mUserOneId, mUserOneService); ParcelFileDescriptor parcelFileDescriptor = getFileDescriptorForAdbTest(); + setCallerAndGrantInteractUserPermission(mUserTwoId, /* shouldGrantPermission */ false); - mBackupManagerService.adbRestore(mUserId, parcelFileDescriptor); + backupManagerService.adbRestore(mUserTwoId, parcelFileDescriptor); - verify(mUserBackupManagerService).adbRestore(parcelFileDescriptor); + verify(mUserOneService, never()).adbRestore(parcelFileDescriptor); } /** Test that the backup service routes methods correctly to the user that requests it. */ @Test - public void testAcknowledgeAdbBackupOrRestore_callsAcknowledgeAdbBackupOrRestoreForUser() + public void testAcknowledgeAdbBackupOrRestore_onRegisteredUser_callsMethodForUser() + throws Exception { + BackupManagerService backupManagerService = + createServiceAndRegisterUser(mUserOneId, mUserOneService); + IFullBackupRestoreObserver observer = mock(IFullBackupRestoreObserver.class); + + backupManagerService.acknowledgeAdbBackupOrRestore( + /* token */ 0, /* allow */ true, "currentPassword", "encryptionPassword", observer); + + verify(mUserOneService) + .acknowledgeAdbBackupOrRestore( + /* token */ 0, + /* allow */ true, + "currentPassword", + "encryptionPassword", + observer); + } + + /** Test that the backup service does not route methods for non-registered users. */ + @Test + public void testAcknowledgeAdbBackupOrRestore_onUnknownUser_doesNotPropagateCall() throws Exception { + BackupManagerService backupManagerService = createService(); IFullBackupRestoreObserver observer = mock(IFullBackupRestoreObserver.class); - mBackupManagerService.acknowledgeAdbBackupOrRestore( + backupManagerService.acknowledgeAdbBackupOrRestore( /* token */ 0, /* allow */ true, "currentPassword", "encryptionPassword", observer); - verify(mUserBackupManagerService) + verify(mUserOneService, never()) .acknowledgeAdbBackupOrRestore( /* token */ 0, /* allow */ true, @@ -724,16 +1416,60 @@ public class BackupManagerServiceTest { /** Test that the backup service routes methods correctly to the user that requests it. */ @Test - public void testDump_callsDumpForUser() throws Exception { + public void testDump_onRegisteredUser_callsMethodForUser() throws Exception { + BackupManagerService backupManagerService = + createServiceAndRegisterUser(mUserOneId, mUserOneService); File testFile = new File(mContext.getFilesDir(), "test"); testFile.createNewFile(); FileDescriptor fileDescriptor = new FileDescriptor(); PrintWriter printWriter = new PrintWriter(testFile); String[] args = {"1", "2"}; - mBackupManagerService.dump(fileDescriptor, printWriter, args); + backupManagerService.dump(fileDescriptor, printWriter, args); + + verify(mUserOneService).dump(fileDescriptor, printWriter, args); + } - verify(mUserBackupManagerService).dump(fileDescriptor, printWriter, args); + /** Test that the backup service does not route methods for non-registered users. */ + @Test + public void testDump_onUnknownUser_doesNotPropagateCall() throws Exception { + BackupManagerService backupManagerService = createService(); + File testFile = new File(mContext.getFilesDir(), "test"); + testFile.createNewFile(); + FileDescriptor fileDescriptor = new FileDescriptor(); + PrintWriter printWriter = new PrintWriter(testFile); + String[] args = {"1", "2"}; + + backupManagerService.dump(fileDescriptor, printWriter, args); + + verify(mUserOneService, never()).dump(fileDescriptor, printWriter, args); + } + + private BackupManagerService createService() { + return new BackupManagerService( + mContext, new Trampoline(mContext), startBackupThread(null)); + } + + private BackupManagerService createServiceAndRegisterUser( + int userId, UserBackupManagerService userBackupManagerService) { + BackupManagerService backupManagerService = createService(); + backupManagerService.startServiceForUser(userId, userBackupManagerService); + return backupManagerService; + } + + /** + * Sets the calling user to {@code userId} and grants the permission INTERACT_ACROSS_USERS_FULL + * to the caller if {@code shouldGrantPermission} is {@code true}, else it denies the + * permission. + */ + private void setCallerAndGrantInteractUserPermission( + @UserIdInt int userId, boolean shouldGrantPermission) { + ShadowBinder.setCallingUserHandle(UserHandle.of(userId)); + if (shouldGrantPermission) { + mShadowContext.grantPermissions(INTERACT_ACROSS_USERS_FULL); + } else { + mShadowContext.denyPermissions(INTERACT_ACROSS_USERS_FULL); + } } private ParcelFileDescriptor getFileDescriptorForAdbTest() throws Exception { diff --git a/services/tests/servicestests/src/com/android/server/backup/TrampolineTest.java b/services/tests/servicestests/src/com/android/server/backup/TrampolineTest.java index d7a398e50a66..ff31435162b1 100644 --- a/services/tests/servicestests/src/com/android/server/backup/TrampolineTest.java +++ b/services/tests/servicestests/src/com/android/server/backup/TrampolineTest.java @@ -132,19 +132,21 @@ public class TrampolineTest { } @Test - public void startServiceForUser_whenMultiUserSettingDisabled_isIgnored() { + public void unlockUser_whenMultiUserSettingDisabled_isIgnoredForNonSystemUser() { Settings.Global.putInt(mContentResolver, Settings.Global.BACKUP_MULTI_USER_ENABLED, 0); + mTrampoline.initializeService(UserHandle.USER_SYSTEM); - mTrampoline.startServiceForUser(10); + mTrampoline.unlockUser(10); verify(mBackupManagerServiceMock, never()).startServiceForUser(10); } @Test - public void startServiceForUser_whenMultiUserSettingEnabled_callsBackupManagerService() { + public void unlockUser_whenMultiUserSettingEnabled_callsBackupManagerServiceForNonSystemUser() { Settings.Global.putInt(mContentResolver, Settings.Global.BACKUP_MULTI_USER_ENABLED, 1); + mTrampoline.initializeService(UserHandle.USER_SYSTEM); - mTrampoline.startServiceForUser(10); + mTrampoline.unlockUser(10); verify(mBackupManagerServiceMock).startServiceForUser(10); } @@ -989,6 +991,11 @@ public class TrampolineTest { return sBackupManagerServiceMock; } + @Override + protected void postToHandler(Runnable runnable) { + runnable.run(); + } + int getCreateServiceCallsCount() { return mCreateServiceCallsCount; } |