Make B&R active for the main user in headless mode

In this CL we are introducing the concept of a 'default' backup user, for whom backup is activated by default. Basically, if there is a 'main' user on the device, it will be the default user. Otherwise it will be the system user. Note that the main user can be the system user (at least in theory). And if there is a main user that isn't the system user, backup will be deactivated for the system user.

Backup is deactivated by the main user by creating a 'suppress' file for it, just like it worked before for the system user.

There was a previous behavior where if backup was deactivated for the system user, it would be deactivated for every user. I think this was to allow DevicePolicyManager to disable all backups on the device. We maintain this behavior, so if `satBackupService(USER_SYSTEM)` is called, backup will be disabled for ALL users-- even the default user.

To properly test this, mocking a static method was required. This is only possible with extended Mockito, which is enabled in `mockingservicetests` so `BackupManagerServiceTest` is moved there. I also revamped most of the tests in there to be more concise and less... weird (there were a bunch of tests that didn't actually test anything).

Test: BackupManagerServiceTest
Bug: 259850130
Change-Id: Iec8b43d1e3560fe40b70bebfd37db1b2e5b0f9ca
This commit is contained in:
[CSarp Misoglu
2022-12-01 16:13:15 +00:00
committed by Sarp Misoglu
parent 77cbd50bef
commit 5b17f4e564
2 changed files with 343 additions and 220 deletions

View File

@@ -156,6 +156,16 @@ public class BackupManagerService extends IBackupManager.Stub {
}
};
/**
* The user that the backup is activated by default for.
*
* If there is a {@link UserManager#getMainUser()}, this will be that user. If not, it will be
* {@link UserHandle#USER_SYSTEM}.
*
* @see #isBackupActivatedForUser(int)
*/
@UserIdInt private final int mDefaultBackupUserId;
public BackupManagerService(Context context) {
this(context, new SparseArray<>());
}
@@ -175,6 +185,8 @@ public class BackupManagerService extends IBackupManager.Stub {
mTransportWhitelist = (transportWhitelist == null) ? emptySet() : transportWhitelist;
mContext.registerReceiver(
mUserRemovedReceiver, new IntentFilter(Intent.ACTION_USER_REMOVED));
UserHandle mainUser = getUserManager().getMainUser();
mDefaultBackupUserId = mainUser == null ? UserHandle.USER_SYSTEM : mainUser.getIdentifier();
}
// TODO: Remove this when we implement DI by injecting in the construtor.
@@ -183,31 +195,35 @@ public class BackupManagerService extends IBackupManager.Stub {
return mHandler;
}
@VisibleForTesting
protected boolean isBackupDisabled() {
return SystemProperties.getBoolean(BACKUP_DISABLE_PROPERTY, false);
}
@VisibleForTesting
protected int binderGetCallingUserId() {
return Binder.getCallingUserHandle().getIdentifier();
}
@VisibleForTesting
protected int binderGetCallingUid() {
return Binder.getCallingUid();
}
/** Stored in the system user's directory. */
protected File getSuppressFileForSystemUser() {
return new File(UserBackupManagerFiles.getBaseStateDir(UserHandle.USER_SYSTEM),
BACKUP_SUPPRESS_FILENAME);
@VisibleForTesting
protected File getSuppressFileForUser(@UserIdInt int userId) {
return new File(UserBackupManagerFiles.getBaseStateDir(userId), BACKUP_SUPPRESS_FILENAME);
}
/** Stored in the system user's directory and the file is indexed by the user it refers to. */
@VisibleForTesting
protected File getRememberActivatedFileForNonSystemUser(int userId) {
return UserBackupManagerFiles.getStateFileInSystemDir(REMEMBER_ACTIVATED_FILENAME, userId);
}
/** Stored in the system user's directory and the file is indexed by the user it refers to. */
protected File getActivatedFileForNonSystemUser(int userId) {
@VisibleForTesting
protected File getActivatedFileForUser(int userId) {
return UserBackupManagerFiles.getStateFileInSystemDir(BACKUP_ACTIVATED_FILENAME, userId);
}
@@ -249,31 +265,40 @@ public class BackupManagerService extends IBackupManager.Stub {
}
/**
* Deactivates the backup service for user {@code userId}. If this is the system user, it
* creates a suppress file which disables backup for all users. If this is a non-system user, it
* only deactivates backup for that user by deleting its activate file.
* Deactivates the backup service for user {@code userId}.
*
* If this is the system user or the {@link #mDefaultBackupUserId} user, it creates a "suppress"
* file for this user.
*
* Otherwise, it deleties the user's "activated" file.
*
* Note that if backup is deactivated for the system user, it will be deactivated for ALL
* users until it is reactivated for the system user, at which point the per-user activation
* status will be the source of truth.
*/
@GuardedBy("mStateLock")
private void deactivateBackupForUserLocked(int userId) throws IOException {
if (userId == UserHandle.USER_SYSTEM) {
createFile(getSuppressFileForSystemUser());
if (userId == UserHandle.USER_SYSTEM || userId == mDefaultBackupUserId) {
createFile(getSuppressFileForUser(userId));
} else {
deleteFile(getActivatedFileForNonSystemUser(userId));
deleteFile(getActivatedFileForUser(userId));
}
}
/**
* Enables the backup service for user {@code userId}. If this is the system user, it deletes
* the suppress file. If this is a non-system user, it creates the user's activate file. Note,
* deleting the suppress file does not automatically enable backup for non-system users, they
* need their own activate file in order to participate in the service.
* Activates the backup service for user {@code userId}.
*
* If this is the system user or the {@link #mDefaultBackupUserId} user, it deletes its
* "suppress" file.
*
* Otherwise, it creates the user's "activated" file.
*/
@GuardedBy("mStateLock")
private void activateBackupForUserLocked(int userId) throws IOException {
if (userId == UserHandle.USER_SYSTEM) {
deleteFile(getSuppressFileForSystemUser());
if (userId == UserHandle.USER_SYSTEM || userId == mDefaultBackupUserId) {
deleteFile(getSuppressFileForUser(userId));
} else {
createFile(getActivatedFileForNonSystemUser(userId));
createFile(getActivatedFileForUser(userId));
}
}
@@ -286,32 +311,52 @@ public class BackupManagerService extends IBackupManager.Stub {
@Override
public boolean isUserReadyForBackup(int userId) {
enforceCallingPermissionOnUserId(userId, "isUserReadyForBackup()");
return mUserServices.get(UserHandle.USER_SYSTEM) != null
&& mUserServices.get(userId) != null;
return mUserServices.get(userId) != null;
}
/**
* Backup is activated for the system user if the suppress file does not exist. Backup is
* activated for non-system users if the suppress file does not exist AND the user's activated
* file exists.
* If there is a "suppress" file for the system user, backup is inactive for ALL users.
*
* Otherwise, the below logic applies:
*
* For the {@link #mDefaultBackupUserId}, backup is active by default. Backup is only
* deactivated if there exists a "suppress" file for the user, which can be created by calling
* {@link #setBackupServiceActive}.
*
* For non-main users, backup is only active if there exists an "activated" file for the user,
* which can also be created by calling {@link #setBackupServiceActive}.
*/
private boolean isBackupActivatedForUser(int userId) {
if (getSuppressFileForSystemUser().exists()) {
if (getSuppressFileForUser(UserHandle.USER_SYSTEM).exists()) {
return false;
}
return userId == UserHandle.USER_SYSTEM
|| getActivatedFileForNonSystemUser(userId).exists();
boolean isDefaultUser = userId == mDefaultBackupUserId;
// If the default user is not the system user, we are in headless mode and the system user
// doesn't have an actual human user associated with it.
if ((userId == UserHandle.USER_SYSTEM) && !isDefaultUser) {
return false;
}
if (isDefaultUser && getSuppressFileForUser(userId).exists()) {
return false;
}
return isDefaultUser || getActivatedFileForUser(userId).exists();
}
@VisibleForTesting
protected Context getContext() {
return mContext;
}
@VisibleForTesting
protected UserManager getUserManager() {
return mUserManager;
}
@VisibleForTesting
protected void postToHandler(Runnable runnable) {
mHandler.post(runnable);
}
@@ -322,6 +367,7 @@ public class BackupManagerService extends IBackupManager.Stub {
* the handler thread {@link #mHandlerThread} to keep unlock time low since backup is not
* essential for device functioning.
*/
@VisibleForTesting
void onUnlockUser(int userId) {
postToHandler(() -> startServiceForUser(userId));
}
@@ -357,6 +403,7 @@ public class BackupManagerService extends IBackupManager.Stub {
* Starts the backup service for user {@code userId} by registering its instance of {@link
* UserBackupManagerService} with this service and setting enabled state.
*/
@VisibleForTesting
void startServiceForUser(int userId, UserBackupManagerService userBackupManagerService) {
mUserServices.put(userId, userBackupManagerService);

View File

@@ -16,22 +16,28 @@
package com.android.server.backup;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.google.common.truth.Truth.assertThat;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertNull;
import static junit.framework.Assert.assertTrue;
import static junit.framework.Assert.fail;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.Manifest;
import android.annotation.UserIdInt;
import android.app.backup.BackupManager;
@@ -42,6 +48,7 @@ import android.content.Context;
import android.content.pm.PackageManager;
import android.content.pm.UserInfo;
import android.os.ConditionVariable;
import android.os.FileUtils;
import android.os.Process;
import android.os.RemoteException;
import android.os.UserHandle;
@@ -50,9 +57,10 @@ import android.platform.test.annotations.Presubmit;
import android.util.SparseArray;
import androidx.test.InstrumentationRegistry;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import com.android.dx.mockito.inline.extended.ExtendedMockito;
import com.android.server.backup.utils.RandomAccessFileUtils;
import org.junit.After;
@@ -61,11 +69,11 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.MockitoSession;
import org.mockito.quality.Strictness;
import java.io.File;
import java.io.FileDescriptor;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
@@ -76,13 +84,12 @@ import java.util.concurrent.TimeUnit;
public class BackupManagerServiceTest {
private static final ComponentName TRANSPORT_COMPONENT_NAME = new ComponentName("package",
"class");
private static final int NON_USER_SYSTEM = UserHandle.USER_SYSTEM + 1;
private static final int UNSTARTED_NON_USER_SYSTEM = UserHandle.USER_SYSTEM + 2;
private static final int NON_SYSTEM_USER = UserHandle.USER_SYSTEM + 1;
@UserIdInt
private int mUserId;
@Mock
private UserBackupManagerService mUserBackupManagerService;
private UserBackupManagerService mSystemUserBackupManagerService;
@Mock
private UserBackupManagerService mNonSystemUserBackupManagerService;
@Mock
@@ -97,200 +104,177 @@ public class BackupManagerServiceTest {
private FileDescriptor mFileDescriptorStub = new FileDescriptor();
private BackupManagerServiceTestable mService;
private File mTestDir;
private File mSuppressFile;
private static File sTestDir;
private SparseArray<UserBackupManagerService> mUserServices;
private MockitoSession mSession;
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
mSession =
ExtendedMockito.mockitoSession().initMocks(
this)
.strictness(Strictness.LENIENT)
.spyStatic(UserBackupManagerService.class)
.startMocking();
doReturn(mSystemUserBackupManagerService).when(
() -> UserBackupManagerService.createAndInitializeService(
eq(UserHandle.USER_SYSTEM), any(), any(), any()));
doReturn(mNonSystemUserBackupManagerService).when(
() -> UserBackupManagerService.createAndInitializeService(eq(NON_SYSTEM_USER),
any(), any(), any()));
mUserId = UserHandle.USER_SYSTEM;
mUserServices = new SparseArray<>();
mUserServices.append(UserHandle.USER_SYSTEM, mUserBackupManagerService);
mUserServices.append(NON_USER_SYSTEM, mNonSystemUserBackupManagerService);
when(mUserManagerMock.getUserInfo(UserHandle.USER_SYSTEM)).thenReturn(mUserInfoMock);
when(mUserManagerMock.getUserInfo(NON_USER_SYSTEM)).thenReturn(mUserInfoMock);
when(mUserManagerMock.getUserInfo(UNSTARTED_NON_USER_SYSTEM)).thenReturn(mUserInfoMock);
when(mUserManagerMock.getUserInfo(NON_SYSTEM_USER)).thenReturn(mUserInfoMock);
// Null main user means there is no main user on the device.
when(mUserManagerMock.getMainUser()).thenReturn(null);
BackupManagerServiceTestable.sCallingUserId = UserHandle.USER_SYSTEM;
BackupManagerServiceTestable.sCallingUid = Process.SYSTEM_UID;
BackupManagerServiceTestable.sBackupDisabled = false;
BackupManagerServiceTestable.sUserManagerMock = mUserManagerMock;
mTestDir = InstrumentationRegistry.getContext().getFilesDir();
mTestDir.mkdirs();
mSuppressFile = new File(mTestDir, "suppress");
BackupManagerServiceTestable.sSuppressFile = mSuppressFile;
setUpStateFilesForNonSystemUser(NON_USER_SYSTEM);
setUpStateFilesForNonSystemUser(UNSTARTED_NON_USER_SYSTEM);
sTestDir = InstrumentationRegistry.getContext().getFilesDir();
sTestDir.mkdirs();
when(mContextMock.getSystemService(Context.JOB_SCHEDULER_SERVICE))
.thenReturn(mock(JobScheduler.class));
mService = new BackupManagerServiceTestable(mContextMock, mUserServices);
}
private void setUpStateFilesForNonSystemUser(int userId) {
File activatedFile = new File(mTestDir, "activate-" + userId);
BackupManagerServiceTestable.sActivatedFiles.append(userId, activatedFile);
File rememberActivatedFile = new File(mTestDir, "rem-activate-" + userId);
BackupManagerServiceTestable.sRememberActivatedFiles.append(userId, rememberActivatedFile);
simulateUserUnlocked(UserHandle.USER_SYSTEM);
}
@After
public void tearDown() throws Exception {
mSuppressFile.delete();
deleteFiles(BackupManagerServiceTestable.sActivatedFiles);
deleteFiles(BackupManagerServiceTestable.sRememberActivatedFiles);
}
private void deleteFiles(SparseArray<File> files) {
int numFiles = files.size();
for (int i = 0; i < numFiles; i++) {
files.valueAt(i).delete();
}
FileUtils.deleteContentsAndDir(sTestDir);
mSession.finishMocking();
}
@Test
public void testIsBackupServiceActive_whenBackupsNotDisabledAndSuppressFileDoesNotExist() {
assertTrue(mService.isBackupServiceActive(UserHandle.USER_SYSTEM));
public void onUnlockUser_startsUserService() {
mService.setBackupServiceActive(NON_SYSTEM_USER, true);
ConditionVariable unlocked = new ConditionVariable(false);
mService.onUnlockUser(NON_SYSTEM_USER);
mService.getBackupHandler().post(unlocked::open);
unlocked.block();
assertNotNull(mService.getUserService(NON_SYSTEM_USER));
}
@Test
public void testOnUnlockUser_forNonSystemUserWhenBackupsDisabled_doesNotStartUser() {
public void startServiceForUser_backupDisabledGlobally_doesNotStartUserService() {
BackupManagerServiceTestable.sBackupDisabled = true;
BackupManagerServiceTestable service =
new BackupManagerServiceTestable(mContextMock, new SparseArray<>());
ConditionVariable unlocked = new ConditionVariable(false);
service.onUnlockUser(NON_USER_SYSTEM);
service.startServiceForUser(UserHandle.USER_SYSTEM);
service.getBackupHandler().post(unlocked::open);
unlocked.block();
assertNull(service.getUserService(NON_USER_SYSTEM));
}
@Test
public void testOnUnlockUser_forSystemUserWhenBackupsDisabled_doesNotStartUser() {
BackupManagerServiceTestable.sBackupDisabled = true;
BackupManagerServiceTestable service =
new BackupManagerServiceTestable(mContextMock, new SparseArray<>());
ConditionVariable unlocked = new ConditionVariable(false);
service.onUnlockUser(UserHandle.USER_SYSTEM);
service.getBackupHandler().post(unlocked::open);
unlocked.block();
assertNull(service.getUserService(UserHandle.USER_SYSTEM));
}
@Test
public void testOnUnlockUser_whenBackupNotActivated_doesNotStartUser() {
BackupManagerServiceTestable.sBackupDisabled = false;
BackupManagerServiceTestable service =
new BackupManagerServiceTestable(mContextMock, new SparseArray<>());
service.setBackupServiceActive(NON_USER_SYSTEM, false);
ConditionVariable unlocked = new ConditionVariable(false);
public void startServiceForUser_backupNotActiveForUser_doesNotStartUserService() {
mService.setBackupServiceActive(UserHandle.USER_SYSTEM, false);
service.onUnlockUser(NON_USER_SYSTEM);
mService.startServiceForUser(UserHandle.USER_SYSTEM);
service.getBackupHandler().post(unlocked::open);
unlocked.block();
assertNull(service.getUserService(NON_USER_SYSTEM));
assertNull(mService.getUserService(UserHandle.USER_SYSTEM));
}
@Test
public void testIsBackupServiceActive_forSystemUserWhenBackupDisabled_returnsTrue()
throws Exception {
public void startServiceForUser_backupEnabledGloballyAndActiveForUser_startsUserService() {
setMockMainUserAndStartNewBackupManagerService(NON_SYSTEM_USER);
mService.startServiceForUser(NON_SYSTEM_USER);
assertNotNull(mService.getUserService(NON_SYSTEM_USER));
}
@Test
public void isBackupServiceActive_backupDisabledGlobally_returnFalse() {
BackupManagerServiceTestable.sBackupDisabled = true;
BackupManagerService backupManagerService =
BackupManagerService service =
new BackupManagerServiceTestable(mContextMock, mUserServices);
backupManagerService.setBackupServiceActive(UserHandle.USER_SYSTEM, true);
service.setBackupServiceActive(UserHandle.USER_SYSTEM, true);
assertFalse(backupManagerService.isBackupServiceActive(UserHandle.USER_SYSTEM));
assertFalse(service.isBackupServiceActive(UserHandle.USER_SYSTEM));
}
@Test
public void testIsBackupServiceActive_forNonSystemUserWhenBackupDisabled_returnsTrue()
throws Exception {
BackupManagerServiceTestable.sBackupDisabled = true;
BackupManagerService backupManagerService =
new BackupManagerServiceTestable(mContextMock, mUserServices);
backupManagerService.setBackupServiceActive(NON_USER_SYSTEM, true);
assertFalse(backupManagerService.isBackupServiceActive(NON_USER_SYSTEM));
}
@Test
public void isBackupServiceActive_forSystemUser_returnsTrueWhenActivated() throws Exception {
mService.setBackupServiceActive(UserHandle.USER_SYSTEM, true);
assertTrue(mService.isBackupServiceActive(UserHandle.USER_SYSTEM));
}
@Test
public void isBackupServiceActive_forSystemUser_returnsFalseWhenDeactivated() throws Exception {
public void isBackupServiceActive_systemUser_isDefault_deactivated_returnsFalse() {
// If there's no 'main' user on the device, the default user is the system user.
mService.setBackupServiceActive(UserHandle.USER_SYSTEM, false);
assertFalse(mService.isBackupServiceActive(UserHandle.USER_SYSTEM));
}
@Test
public void isBackupServiceActive_forNonSystemUser_returnsFalseWhenSystemUserDeactivated()
throws Exception {
public void isBackupServiceActive_systemUser_isNotDefault_returnsFalse() {
setMockMainUserAndStartNewBackupManagerService(NON_SYSTEM_USER);
assertFalse(mService.isBackupServiceActive(UserHandle.USER_SYSTEM));
}
@Test
public void isBackupServiceActive_systemUser_isDefault_returnsTrue() {
// If there's no 'main' user on the device, the default user is the system user.
assertTrue(mService.isBackupServiceActive(UserHandle.USER_SYSTEM));
}
@Test
public void isBackupServiceActive_nonSystemUser_isDefault_systemUserDeactivated_returnsFalse() {
setMockMainUserAndStartNewBackupManagerService(NON_SYSTEM_USER);
mService.setBackupServiceActive(UserHandle.USER_SYSTEM, false);
mService.setBackupServiceActive(NON_USER_SYSTEM, true);
assertFalse(mService.isBackupServiceActive(NON_USER_SYSTEM));
assertFalse(mService.isBackupServiceActive(NON_SYSTEM_USER));
}
@Test
public void isBackupServiceActive_forNonSystemUser_returnsFalseWhenNonSystemUserDeactivated()
throws Exception {
mService.setBackupServiceActive(UserHandle.USER_SYSTEM, true);
// Don't activate non-system user.
public void isBackupServiceActive_nonSystemUser_isDefault_deactivated_returnsFalse() {
setMockMainUserAndStartNewBackupManagerService(NON_SYSTEM_USER);
mService.setBackupServiceActive(NON_SYSTEM_USER, false);
assertFalse(mService.isBackupServiceActive(NON_USER_SYSTEM));
assertFalse(mService.isBackupServiceActive(NON_SYSTEM_USER));
}
@Test
public void
isBackupServiceActive_forNonSystemUser_returnsTrueWhenSystemAndNonSystemUserActivated()
throws Exception {
mService.setBackupServiceActive(UserHandle.USER_SYSTEM, true);
mService.setBackupServiceActive(NON_USER_SYSTEM, true);
public void isBackupServiceActive_nonSystemUser_isDefault_returnsTrue() {
setMockMainUserAndStartNewBackupManagerService(NON_SYSTEM_USER);
assertTrue(mService.isBackupServiceActive(NON_USER_SYSTEM));
assertTrue(mService.isBackupServiceActive(NON_SYSTEM_USER));
}
@Test
public void
isBackupServiceActive_forUnstartedNonSystemUser_returnsTrueWhenSystemAndUserActivated()
throws Exception {
mService.setBackupServiceActive(UNSTARTED_NON_USER_SYSTEM, true);
assertTrue(mService.isBackupServiceActive(UNSTARTED_NON_USER_SYSTEM));
public void isBackupServiceActive_nonSystemUser_isNotDefault_notActivated_returnsFalse() {
// By default non-system non-default users are not activated.
assertFalse(mService.isBackupServiceActive(NON_SYSTEM_USER));
}
@Test
public void setBackupServiceActive_forSystemUserAndCallerSystemUid_serviceCreated() {
public void isBackupServiceActive_nonSystemUser_isNotDefault_activated_returnsTrue() {
mService.setBackupServiceActive(NON_SYSTEM_USER, true);
assertTrue(mService.isBackupServiceActive(NON_SYSTEM_USER));
}
@Test
public void setBackupServiceActive_forSystemUserAndCallerSystemUid_createsService() {
BackupManagerServiceTestable.sCallingUid = Process.SYSTEM_UID;
mService.setBackupServiceActive(UserHandle.USER_SYSTEM, true);
assertTrue(mService.isBackupServiceActive(UserHandle.USER_SYSTEM));
assertTrue(mService.isUserReadyForBackup(UserHandle.USER_SYSTEM));
}
@Test
public void setBackupServiceActive_forSystemUserAndCallerRootUid_serviceCreated() {
public void setBackupServiceActive_forSystemUserAndCallerRootUid_createsService() {
BackupManagerServiceTestable.sCallingUid = Process.ROOT_UID;
mService.setBackupServiceActive(UserHandle.USER_SYSTEM, true);
assertTrue(mService.isBackupServiceActive(UserHandle.USER_SYSTEM));
assertTrue(mService.isUserReadyForBackup(UserHandle.USER_SYSTEM));
}
@Test
@@ -305,23 +289,25 @@ public class BackupManagerServiceTest {
}
@Test
public void setBackupServiceActive_forManagedProfileAndCallerSystemUid_serviceCreated() {
public void setBackupServiceActive_forManagedProfileAndCallerSystemUid_createsService() {
simulateUserUnlocked(NON_SYSTEM_USER);
when(mUserInfoMock.isManagedProfile()).thenReturn(true);
BackupManagerServiceTestable.sCallingUid = Process.SYSTEM_UID;
mService.setBackupServiceActive(NON_USER_SYSTEM, true);
mService.setBackupServiceActive(NON_SYSTEM_USER, true);
assertTrue(mService.isBackupServiceActive(NON_USER_SYSTEM));
assertTrue(mService.isUserReadyForBackup(NON_SYSTEM_USER));
}
@Test
public void setBackupServiceActive_forManagedProfileAndCallerRootUid_serviceCreated() {
public void setBackupServiceActive_forManagedProfileAndCallerRootUid_createsService() {
simulateUserUnlocked(NON_SYSTEM_USER);
when(mUserInfoMock.isManagedProfile()).thenReturn(true);
BackupManagerServiceTestable.sCallingUid = Process.ROOT_UID;
mService.setBackupServiceActive(NON_USER_SYSTEM, true);
mService.setBackupServiceActive(NON_SYSTEM_USER, true);
assertTrue(mService.isBackupServiceActive(NON_USER_SYSTEM));
assertTrue(mService.isUserReadyForBackup(NON_SYSTEM_USER));
}
@Test
@@ -330,7 +316,7 @@ public class BackupManagerServiceTest {
BackupManagerServiceTestable.sCallingUid = Process.FIRST_APPLICATION_UID;
try {
mService.setBackupServiceActive(NON_USER_SYSTEM, true);
mService.setBackupServiceActive(NON_SYSTEM_USER, true);
fail();
} catch (SecurityException expected) {
}
@@ -343,7 +329,7 @@ public class BackupManagerServiceTest {
.enforceCallingOrSelfPermission(eq(Manifest.permission.BACKUP), anyString());
try {
mService.setBackupServiceActive(NON_USER_SYSTEM, true);
mService.setBackupServiceActive(NON_SYSTEM_USER, true);
fail();
} catch (SecurityException expected) {
}
@@ -357,14 +343,14 @@ public class BackupManagerServiceTest {
eq(Manifest.permission.INTERACT_ACROSS_USERS_FULL), anyString());
try {
mService.setBackupServiceActive(NON_USER_SYSTEM, true);
mService.setBackupServiceActive(NON_SYSTEM_USER, true);
fail();
} catch (SecurityException expected) {
}
}
@Test
public void setBackupServiceActive_backupDisabled_ignored() {
public void setBackupServiceActive_backupDisabledGlobally_ignored() {
BackupManagerServiceTestable.sBackupDisabled = true;
BackupManagerServiceTestable service =
new BackupManagerServiceTestable(mContextMock, mUserServices);
@@ -384,77 +370,139 @@ public class BackupManagerServiceTest {
}
@Test
public void setBackupServiceActive_makeNonActive_alreadyNonActive_ignored() {
mService.setBackupServiceActive(UserHandle.USER_SYSTEM, false);
public void setBackupServiceActive_systemUser_makeActive_deletesSuppressFile() {
mService.setBackupServiceActive(UserHandle.USER_SYSTEM, false);
assertFalse(mService.isBackupServiceActive(UserHandle.USER_SYSTEM));
}
@Test
public void setBackupServiceActive_makeActive_serviceCreatedAndSuppressFileDeleted() {
mService.setBackupServiceActive(UserHandle.USER_SYSTEM, true);
assertTrue(mService.isBackupServiceActive(UserHandle.USER_SYSTEM));
assertFalse(getFakeSuppressFileForUser(UserHandle.USER_SYSTEM).exists());
}
@Test
public void setBackupServiceActive_makeNonActive_serviceDeletedAndSuppressFileCreated()
throws IOException {
assertTrue(mService.isBackupServiceActive(UserHandle.USER_SYSTEM));
public void setBackupServiceActive_systemUser_makeNonActive_createsSuppressFile() {
mService.setBackupServiceActive(UserHandle.USER_SYSTEM, false);
assertFalse(mService.isBackupServiceActive(UserHandle.USER_SYSTEM));
assertTrue(getFakeSuppressFileForUser(UserHandle.USER_SYSTEM).exists());
}
@Test
public void setBackupActive_nonSystemUser_disabledForSystemUser_ignored() {
mService.setBackupServiceActive(UserHandle.USER_SYSTEM, false);
mService.setBackupServiceActive(NON_USER_SYSTEM, true);
public void setBackupServiceActive_systemUser_makeNonActive_stopsUserService() {
assertTrue(mService.isUserReadyForBackup(UserHandle.USER_SYSTEM));
assertFalse(mService.isBackupServiceActive(NON_USER_SYSTEM));
mService.setBackupServiceActive(UserHandle.USER_SYSTEM, false);
assertFalse(mService.isUserReadyForBackup(UserHandle.USER_SYSTEM));
}
@Test
public void setBackupServiceActive_nonSystemUser_isDefault_makeActive_createsService() {
setMockMainUserAndStartNewBackupManagerService(NON_SYSTEM_USER);
simulateUserUnlocked(NON_SYSTEM_USER);
mService.setBackupServiceActive(NON_SYSTEM_USER, false);
mService.setBackupServiceActive(NON_SYSTEM_USER, true);
assertTrue(mService.isUserReadyForBackup(NON_SYSTEM_USER));
}
@Test
public void setBackupServiceActive_nonSystemUser_isDefault_makeActive_deletesSuppressFile() {
setMockMainUserAndStartNewBackupManagerService(NON_SYSTEM_USER);
simulateUserUnlocked(NON_SYSTEM_USER);
mService.setBackupServiceActive(NON_SYSTEM_USER, false);
mService.setBackupServiceActive(NON_SYSTEM_USER, true);
assertFalse(getFakeSuppressFileForUser(NON_SYSTEM_USER).exists());
}
@Test
public void setBackupServiceActive_nonSystemUser_isDefault_makeNonActive_createsSuppressFile() {
setMockMainUserAndStartNewBackupManagerService(NON_SYSTEM_USER);
mService.setBackupServiceActive(NON_SYSTEM_USER, false);
assertTrue(getFakeSuppressFileForUser(NON_SYSTEM_USER).exists());
}
@Test
public void setBackupServiceActive_nonSystemUser_isDefault_makeNonActive_stopsUserService() {
setMockMainUserAndStartNewBackupManagerService(NON_SYSTEM_USER);
simulateUserUnlocked(NON_SYSTEM_USER);
assertTrue(mService.isUserReadyForBackup(NON_SYSTEM_USER));
mService.setBackupServiceActive(NON_SYSTEM_USER, false);
assertFalse(mService.isUserReadyForBackup(NON_SYSTEM_USER));
}
@Test
public void setBackupServiceActive_nonSystemUser_isNotDefault_makeActive_createsService() {
simulateUserUnlocked(NON_SYSTEM_USER);
mService.setBackupServiceActive(NON_SYSTEM_USER, true);
assertTrue(mService.isUserReadyForBackup(NON_SYSTEM_USER));
}
@Test
public void setBackupServiceActive_nonSystemUser_isNotDefault_makeActive_createActivatedFile() {
mService.setBackupServiceActive(NON_SYSTEM_USER, true);
assertTrue(getFakeActivatedFileForUser(NON_SYSTEM_USER).exists());
}
@Test
public void setBackupServiceActive_nonSystemUser_isNotDefault_makeNonActive_stopsUserService() {
simulateUserUnlocked(NON_SYSTEM_USER);
mService.setBackupServiceActive(NON_SYSTEM_USER, true);
mService.setBackupServiceActive(NON_SYSTEM_USER, false);
assertFalse(mService.isUserReadyForBackup(NON_SYSTEM_USER));
}
@Test
public void setBackupServiceActive_nonSystemUser_isNotDefault_makeActive_deleteActivatedFile() {
mService.setBackupServiceActive(NON_SYSTEM_USER, true);
mService.setBackupServiceActive(NON_SYSTEM_USER, false);
assertFalse(getFakeActivatedFileForUser(NON_SYSTEM_USER).exists());
}
@Test
public void setBackupServiceActive_forOneNonSystemUser_doesNotActivateForAllNonSystemUsers() {
int otherUser = NON_USER_SYSTEM + 1;
File activateFile = new File(mTestDir, "activate-" + otherUser);
BackupManagerServiceTestable.sActivatedFiles.append(otherUser, activateFile);
int otherUser = NON_SYSTEM_USER + 1;
mService.setBackupServiceActive(UserHandle.USER_SYSTEM, true);
mService.setBackupServiceActive(NON_USER_SYSTEM, true);
mService.setBackupServiceActive(NON_SYSTEM_USER, true);
assertTrue(mService.isBackupServiceActive(NON_USER_SYSTEM));
assertFalse(mService.isBackupServiceActive(otherUser));
activateFile.delete();
}
@Test
public void setBackupServiceActive_forNonSystemUser_remembersActivated() {
mService.setBackupServiceActive(NON_USER_SYSTEM, true);
mService.setBackupServiceActive(NON_SYSTEM_USER, true);
assertTrue(RandomAccessFileUtils.readBoolean(
BackupManagerServiceTestable.sRememberActivatedFiles.get(NON_USER_SYSTEM), false));
getFakeRememberActivatedFileForUser(NON_SYSTEM_USER), false));
}
@Test
public void setBackupServiceActiveFalse_forNonSystemUser_remembersActivated() {
mService.setBackupServiceActive(NON_USER_SYSTEM, false);
mService.setBackupServiceActive(NON_SYSTEM_USER, false);
assertFalse(RandomAccessFileUtils.readBoolean(
BackupManagerServiceTestable.sRememberActivatedFiles.get(NON_USER_SYSTEM), true));
getFakeRememberActivatedFileForUser(NON_SYSTEM_USER), true));
}
@Test
public void setBackupServiceActiveTwice_forNonSystemUser_remembersLastActivated() {
mService.setBackupServiceActive(NON_USER_SYSTEM, true);
mService.setBackupServiceActive(NON_USER_SYSTEM, false);
mService.setBackupServiceActive(NON_SYSTEM_USER, true);
mService.setBackupServiceActive(NON_SYSTEM_USER, false);
assertFalse(RandomAccessFileUtils.readBoolean(
BackupManagerServiceTestable.sRememberActivatedFiles.get(NON_USER_SYSTEM), true));
getFakeRememberActivatedFileForUser(NON_SYSTEM_USER), true));
}
@Test
@@ -468,6 +516,7 @@ public class BackupManagerServiceTest {
public void onSuccess(String transportName) {
future.completeExceptionally(new AssertionError());
}
@Override
public void onFailure(int reason) {
future.complete(reason);
@@ -488,13 +537,14 @@ public class BackupManagerServiceTest {
}
@Test
public void
selectBackupTransportAsyncForUser_beforeUserUnlockedListenerThrowing_doesNotThrow()
public void selectBackupTransportAsyncForUser_beforeUserUnlockedListenerThrowing_doesNotThrow()
throws Exception {
ISelectBackupTransportCallback.Stub listener =
new ISelectBackupTransportCallback.Stub() {
@Override
public void onSuccess(String transportName) {}
public void onSuccess(String transportName) {
}
@Override
public void onFailure(int reason) throws RemoteException {
throw new RemoteException();
@@ -509,13 +559,13 @@ public class BackupManagerServiceTest {
@Test
public void dump_callerDoesNotHaveDumpPermission_ignored() {
when(mContextMock.checkCallingOrSelfPermission(
android.Manifest.permission.DUMP)).thenReturn(
Manifest.permission.DUMP)).thenReturn(
PackageManager.PERMISSION_DENIED);
mService.dump(mFileDescriptorStub, mPrintWriterMock, new String[0]);
verifyNoMoreInteractions(mUserBackupManagerService);
verifyNoMoreInteractions(mNonSystemUserBackupManagerService);
verify(mSystemUserBackupManagerService, never()).dump(any(), any(), any());
verify(mNonSystemUserBackupManagerService, never()).dump(any(), any(), any());
}
@Test
@@ -526,22 +576,24 @@ public class BackupManagerServiceTest {
mService.dump(mFileDescriptorStub, mPrintWriterMock, new String[0]);
verifyNoMoreInteractions(mUserBackupManagerService);
verifyNoMoreInteractions(mNonSystemUserBackupManagerService);
verify(mSystemUserBackupManagerService, never()).dump(any(), any(), any());
verify(mNonSystemUserBackupManagerService, never()).dump(any(), any(), any());
}
/**
* Test that {@link BackupManagerService#dump()} dumps system user information before non-system
* user information.
* Test that {@link BackupManagerService#dump(FileDescriptor, PrintWriter, String[])} dumps
* system user information before non-system user information.
*/
@Test
public void testDump_systemUserFirst() {
mService.setBackupServiceActive(NON_SYSTEM_USER, true);
simulateUserUnlocked(NON_SYSTEM_USER);
String[] args = new String[0];
mService.dumpWithoutCheckingPermission(mFileDescriptorStub, mPrintWriterMock, args);
InOrder inOrder =
inOrder(mUserBackupManagerService, mNonSystemUserBackupManagerService);
inOrder.verify(mUserBackupManagerService)
inOrder(mSystemUserBackupManagerService, mNonSystemUserBackupManagerService);
inOrder.verify(mSystemUserBackupManagerService)
.dump(mFileDescriptorStub, mPrintWriterMock, args);
inOrder.verify(mNonSystemUserBackupManagerService)
.dump(mFileDescriptorStub, mPrintWriterMock, args);
@@ -550,30 +602,27 @@ public class BackupManagerServiceTest {
@Test
public void testGetUserForAncestralSerialNumber_forSystemUser() {
BackupManagerServiceTestable.sBackupDisabled = false;
BackupManagerService backupManagerService =
new BackupManagerServiceTestable(mContextMock, mUserServices);
simulateUserUnlocked(NON_SYSTEM_USER);
when(mUserManagerMock.getProfileIds(UserHandle.getCallingUserId(), false))
.thenReturn(new int[] {UserHandle.USER_SYSTEM, NON_USER_SYSTEM});
when(mUserBackupManagerService.getAncestralSerialNumber()).thenReturn(11L);
.thenReturn(new int[]{UserHandle.USER_SYSTEM, NON_SYSTEM_USER});
when(mSystemUserBackupManagerService.getAncestralSerialNumber()).thenReturn(11L);
UserHandle user = backupManagerService.getUserForAncestralSerialNumber(11L);
UserHandle user = mService.getUserForAncestralSerialNumber(11L);
assertThat(user).isEqualTo(UserHandle.of(UserHandle.USER_SYSTEM));
}
@Test
public void testGetUserForAncestralSerialNumber_forNonSystemUser() {
BackupManagerServiceTestable.sBackupDisabled = false;
BackupManagerService backupManagerService =
new BackupManagerServiceTestable(mContextMock, mUserServices);
setMockMainUserAndStartNewBackupManagerService(NON_SYSTEM_USER);
simulateUserUnlocked(NON_SYSTEM_USER);
when(mUserManagerMock.getProfileIds(UserHandle.getCallingUserId(), false))
.thenReturn(new int[] {UserHandle.USER_SYSTEM, NON_USER_SYSTEM});
.thenReturn(new int[]{UserHandle.USER_SYSTEM, NON_SYSTEM_USER});
when(mNonSystemUserBackupManagerService.getAncestralSerialNumber()).thenReturn(11L);
UserHandle user = backupManagerService.getUserForAncestralSerialNumber(11L);
UserHandle user = mService.getUserForAncestralSerialNumber(11L);
assertThat(user).isEqualTo(UserHandle.of(NON_USER_SYSTEM));
assertThat(user).isEqualTo(UserHandle.of(NON_SYSTEM_USER));
}
@Test
@@ -581,20 +630,46 @@ public class BackupManagerServiceTest {
BackupManagerServiceTestable.sBackupDisabled = true;
BackupManagerService backupManagerService =
new BackupManagerServiceTestable(mContextMock, mUserServices);
when(mUserBackupManagerService.getAncestralSerialNumber()).thenReturn(11L);
when(mSystemUserBackupManagerService.getAncestralSerialNumber()).thenReturn(11L);
UserHandle user = backupManagerService.getUserForAncestralSerialNumber(11L);
assertThat(user).isNull();
}
/**
* The 'default' user is set in the constructor of {@link BackupManagerService} so we need to
* start a new service after mocking the 'main' user.
*/
private void setMockMainUserAndStartNewBackupManagerService(int userId) {
when(mUserManagerMock.getMainUser()).thenReturn(UserHandle.of(userId));
mService = new BackupManagerServiceTestable(mContextMock, mUserServices);
}
private void simulateUserUnlocked(int userId) {
ConditionVariable unlocked = new ConditionVariable(false);
mService.onUnlockUser(userId);
mService.getBackupHandler().post(unlocked::open);
unlocked.block();
when(mUserManagerMock.isUserUnlocked(userId)).thenReturn(true);
}
private static File getFakeSuppressFileForUser(int userId) {
return new File(sTestDir, "suppress-" + userId);
}
private static File getFakeActivatedFileForUser(int userId) {
return new File(sTestDir, "activated-" + userId);
}
private static File getFakeRememberActivatedFileForUser(int userId) {
return new File(sTestDir, "rememberActivated-" + userId);
}
private static class BackupManagerServiceTestable extends BackupManagerService {
static boolean sBackupDisabled = false;
static int sCallingUserId = -1;
static int sCallingUid = -1;
static File sSuppressFile = null;
static SparseArray<File> sActivatedFiles = new SparseArray<>();
static SparseArray<File> sRememberActivatedFiles = new SparseArray<>();
static UserManager sUserManagerMock = null;
BackupManagerServiceTestable(
@@ -613,20 +688,21 @@ public class BackupManagerServiceTest {
}
@Override
protected File getSuppressFileForSystemUser() {
return sSuppressFile;
protected File getSuppressFileForUser(int userId) {
return getFakeSuppressFileForUser(userId);
}
@Override
protected File getRememberActivatedFileForNonSystemUser(int userId) {
return sRememberActivatedFiles.get(userId);
return getFakeRememberActivatedFileForUser(userId);
}
@Override
protected File getActivatedFileForNonSystemUser(int userId) {
return sActivatedFiles.get(userId);
protected File getActivatedFileForUser(int userId) {
return getFakeActivatedFileForUser(userId);
}
@Override
protected int binderGetCallingUserId() {
return sCallingUserId;
}