Merge "[Multi-user] Change BackupManager AIDL to accept userId in methods"
This commit is contained in:
committed by
Android (Google) Code Review
commit
b4815ebf76
@@ -201,7 +201,7 @@ public class Bmgr {
|
||||
|
||||
private void doEnabled(@UserIdInt int userId) {
|
||||
try {
|
||||
boolean isEnabled = mBmgr.isBackupEnabled();
|
||||
boolean isEnabled = mBmgr.isBackupEnabledForUser(userId);
|
||||
System.out.println("Backup Manager currently "
|
||||
+ enableToString(isEnabled));
|
||||
} catch (RemoteException e) {
|
||||
@@ -219,7 +219,7 @@ public class Bmgr {
|
||||
|
||||
try {
|
||||
boolean enable = Boolean.parseBoolean(arg);
|
||||
mBmgr.setBackupEnabled(enable);
|
||||
mBmgr.setBackupEnabledForUser(userId, enable);
|
||||
System.out.println("Backup Manager now " + enableToString(enable));
|
||||
} catch (NumberFormatException e) {
|
||||
showUsage();
|
||||
@@ -232,7 +232,7 @@ public class Bmgr {
|
||||
|
||||
void doRun(@UserIdInt int userId) {
|
||||
try {
|
||||
mBmgr.backupNow();
|
||||
mBmgr.backupNowForUser(userId);
|
||||
} catch (RemoteException e) {
|
||||
System.err.println(e.toString());
|
||||
System.err.println(BMGR_NOT_RUNNING_ERR);
|
||||
@@ -416,7 +416,8 @@ public class Bmgr {
|
||||
(monitorState != Monitor.OFF)
|
||||
? new BackupMonitor(monitorState == Monitor.VERBOSE)
|
||||
: null;
|
||||
int err = mBmgr.requestBackup(
|
||||
int err = mBmgr.requestBackupForUser(
|
||||
userId,
|
||||
packages.toArray(new String[packages.size()]),
|
||||
observer,
|
||||
monitor,
|
||||
@@ -477,7 +478,7 @@ public class Bmgr {
|
||||
String arg = nextArg();
|
||||
if ("backups".equals(arg)) {
|
||||
try {
|
||||
mBmgr.cancelBackups();
|
||||
mBmgr.cancelBackupsForUser(userId);
|
||||
} catch (RemoteException e) {
|
||||
System.err.println(e.toString());
|
||||
System.err.println(BMGR_NOT_RUNNING_ERR);
|
||||
|
||||
@@ -91,6 +91,15 @@ interface IBackupManager {
|
||||
* at some point in the future.
|
||||
*
|
||||
* <p>Callers must hold the android.permission.BACKUP permission to use this method.
|
||||
* If {@code userId} is different from the calling user id, then the caller must hold the
|
||||
* android.permission.INTERACT_ACROSS_USERS_FULL permission.
|
||||
*
|
||||
* @param userId User id for which backup service should be enabled/disabled.
|
||||
*/
|
||||
void setBackupEnabledForUser(int userId, boolean isEnabled);
|
||||
|
||||
/**
|
||||
* {@link android.app.backup.IBackupManager.setBackupEnabledForUser} for the calling user id.
|
||||
*/
|
||||
void setBackupEnabled(boolean isEnabled);
|
||||
|
||||
@@ -120,6 +129,15 @@ interface IBackupManager {
|
||||
* Report whether the backup mechanism is currently enabled.
|
||||
*
|
||||
* <p>Callers must hold the android.permission.BACKUP permission to use this method.
|
||||
* If {@code userId} is different from the calling user id, then the caller must hold the
|
||||
* android.permission.INTERACT_ACROSS_USERS_FULL permission.
|
||||
*
|
||||
* @param userId User id for which the backup service status should be reported.
|
||||
*/
|
||||
boolean isBackupEnabledForUser(int userId);
|
||||
|
||||
/**
|
||||
* {@link android.app.backup.IBackupManager.isBackupEnabledForUser} for the calling user id.
|
||||
*/
|
||||
boolean isBackupEnabled();
|
||||
|
||||
@@ -149,6 +167,15 @@ interface IBackupManager {
|
||||
* method.
|
||||
*
|
||||
* <p>Callers must hold the android.permission.BACKUP permission to use this method.
|
||||
* If {@code userId} is different from the calling user id, then the caller must hold the
|
||||
* android.permission.INTERACT_ACROSS_USERS_FULL permission.
|
||||
*
|
||||
* @param userId User id for which an immediate backup should be scheduled.
|
||||
*/
|
||||
void backupNowForUser(int userId);
|
||||
|
||||
/**
|
||||
* {@link android.app.backup.IBackupManager.backupNowForUser} for the calling user id.
|
||||
*/
|
||||
void backupNow();
|
||||
|
||||
@@ -432,6 +459,12 @@ interface IBackupManager {
|
||||
* <p>If this method returns zero (meaning success), the OS will attempt to backup all provided
|
||||
* packages using the remote transport.
|
||||
*
|
||||
* <p>Callers must hold the android.permission.BACKUP permission to use this method.
|
||||
* If {@code userId} is different from the calling user id, then the caller must hold the
|
||||
* android.permission.INTERACT_ACROSS_USERS_FULL permission.
|
||||
*
|
||||
* @param userId User id for which an immediate backup should be requested.
|
||||
|
||||
* @param observer The {@link BackupObserver} to receive callbacks during the backup
|
||||
* operation.
|
||||
*
|
||||
@@ -442,12 +475,29 @@ interface IBackupManager {
|
||||
*
|
||||
* @return Zero on success; nonzero on error.
|
||||
*/
|
||||
int requestBackupForUser(int userId, in String[] packages, IBackupObserver observer,
|
||||
IBackupManagerMonitor monitor, int flags);
|
||||
|
||||
/**
|
||||
* {@link android.app.backup.IBackupManager.requestBackupForUser} for the calling user id.
|
||||
*/
|
||||
int requestBackup(in String[] packages, IBackupObserver observer, IBackupManagerMonitor monitor,
|
||||
int flags);
|
||||
|
||||
/**
|
||||
* Cancel all running backups. After this call returns, no currently running backups will
|
||||
* interact with the selected transport.
|
||||
*
|
||||
* <p>Callers must hold the android.permission.BACKUP permission to use this method.
|
||||
* If {@code userId} is different from the calling user id, then the caller must hold the
|
||||
* android.permission.INTERACT_ACROSS_USERS_FULL permission.
|
||||
*
|
||||
* @param userId User id for which backups should be cancelled.
|
||||
*/
|
||||
void cancelBackupsForUser(int userId);
|
||||
|
||||
/**
|
||||
* {@link android.app.backup.IBackupManager.cancelBackups} for the calling user id.
|
||||
*/
|
||||
void cancelBackups();
|
||||
}
|
||||
|
||||
@@ -16,7 +16,9 @@
|
||||
|
||||
package com.android.server.backup;
|
||||
|
||||
import android.Manifest;
|
||||
import android.annotation.Nullable;
|
||||
import android.annotation.UserIdInt;
|
||||
import android.app.ActivityManager;
|
||||
import android.app.backup.IBackupManagerMonitor;
|
||||
import android.app.backup.IBackupObserver;
|
||||
@@ -30,6 +32,7 @@ import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.Binder;
|
||||
import android.os.Environment;
|
||||
import android.os.HandlerThread;
|
||||
import android.os.IBinder;
|
||||
@@ -79,6 +82,7 @@ public class BackupManagerService {
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
private final Context mContext;
|
||||
private UserBackupManagerService mUserBackupManagerService;
|
||||
|
||||
/** Instantiate a new instance of {@link BackupManagerService}. */
|
||||
@@ -91,11 +95,26 @@ public class BackupManagerService {
|
||||
transportWhitelist = Collections.emptySet();
|
||||
}
|
||||
|
||||
mContext = context;
|
||||
mUserBackupManagerService =
|
||||
UserBackupManagerService.createAndInitializeService(
|
||||
context, trampoline, backupThread, transportWhitelist);
|
||||
}
|
||||
|
||||
/**
|
||||
* If {@code userId} is different from the calling user id, then the caller must hold the
|
||||
* android.permission.INTERACT_ACROSS_USERS_FULL permission.
|
||||
*
|
||||
* @param userId User id on which the backup operation is being requested.
|
||||
* @param message A message to include in the exception if it is thrown.
|
||||
*/
|
||||
private void enforceCallingPermissionOnUserId(int userId, String message) {
|
||||
if (Binder.getCallingUserHandle().getIdentifier() != userId) {
|
||||
mContext.enforceCallingOrSelfPermission(
|
||||
Manifest.permission.INTERACT_ACROSS_USERS_FULL, message);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(b/118520567): Remove when tests are modified to use per-user instance.
|
||||
@VisibleForTesting
|
||||
void setUserBackupManagerService(UserBackupManagerService userBackupManagerService) {
|
||||
@@ -314,7 +333,8 @@ public class BackupManagerService {
|
||||
// ---------------------------------------------
|
||||
|
||||
/** Enable/disable the backup service. This is user-configurable via backup settings. */
|
||||
public void setBackupEnabled(boolean enable) {
|
||||
public void setBackupEnabled(@UserIdInt int userId, boolean enable) {
|
||||
enforceCallingPermissionOnUserId(userId, "setBackupEnabled");
|
||||
mUserBackupManagerService.setBackupEnabled(enable);
|
||||
}
|
||||
|
||||
@@ -331,7 +351,8 @@ public class BackupManagerService {
|
||||
/**
|
||||
* Return {@code true} if the backup mechanism is currently enabled, else returns {@code false}.
|
||||
*/
|
||||
public boolean isBackupEnabled() {
|
||||
public boolean isBackupEnabled(@UserIdInt int userId) {
|
||||
enforceCallingPermissionOnUserId(userId, "isBackupEnabled");
|
||||
return mUserBackupManagerService.isBackupEnabled();
|
||||
}
|
||||
|
||||
@@ -355,7 +376,8 @@ public class BackupManagerService {
|
||||
* Run a backup pass immediately for any key-value backup applications that have declared that
|
||||
* they have pending updates.
|
||||
*/
|
||||
public void backupNow() {
|
||||
public void backupNow(@UserIdInt int userId) {
|
||||
enforceCallingPermissionOnUserId(userId, "backupNow");
|
||||
mUserBackupManagerService.backupNow();
|
||||
}
|
||||
|
||||
@@ -364,12 +386,18 @@ public class BackupManagerService {
|
||||
* IBackupManagerMonitor} for receiving events during the operation.
|
||||
*/
|
||||
public int requestBackup(
|
||||
String[] packages, IBackupObserver observer, IBackupManagerMonitor monitor, int flags) {
|
||||
@UserIdInt int userId,
|
||||
String[] packages,
|
||||
IBackupObserver observer,
|
||||
IBackupManagerMonitor monitor,
|
||||
int flags) {
|
||||
enforceCallingPermissionOnUserId(userId, "requestBackup");
|
||||
return mUserBackupManagerService.requestBackup(packages, observer, monitor, flags);
|
||||
}
|
||||
|
||||
/** Cancel all running backup operations. */
|
||||
public void cancelBackups() {
|
||||
public void cancelBackups(@UserIdInt int userId) {
|
||||
enforceCallingPermissionOnUserId(userId, "cancelBackups");
|
||||
mUserBackupManagerService.cancelBackups();
|
||||
}
|
||||
|
||||
@@ -533,8 +561,10 @@ public class BackupManagerService {
|
||||
stage.renameTo(enableFile);
|
||||
// will be synced immediately by the try-with-resources call to close()
|
||||
} catch (IOException | RuntimeException e) {
|
||||
Slog.e(TAG, "Unable to record backup enable state; reverting to disabled: "
|
||||
+ e.getMessage());
|
||||
Slog.e(
|
||||
TAG,
|
||||
"Unable to record backup enable state; reverting to disabled: "
|
||||
+ e.getMessage());
|
||||
enableFile.delete();
|
||||
stage.delete();
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ package com.android.server.backup;
|
||||
import static com.android.server.backup.BackupManagerService.TAG;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
import android.annotation.UserIdInt;
|
||||
import android.app.admin.DevicePolicyManager;
|
||||
import android.app.backup.BackupManager;
|
||||
import android.app.backup.IBackupManager;
|
||||
@@ -123,6 +124,10 @@ public class Trampoline extends IBackupManager.Stub {
|
||||
== MULTI_USER_ENABLED;
|
||||
}
|
||||
|
||||
protected int binderGetCallingUserId() {
|
||||
return Binder.getCallingUserHandle().getIdentifier();
|
||||
}
|
||||
|
||||
protected int binderGetCallingUid() {
|
||||
return Binder.getCallingUid();
|
||||
}
|
||||
@@ -319,13 +324,19 @@ public class Trampoline extends IBackupManager.Stub {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBackupEnabled(boolean isEnabled) throws RemoteException {
|
||||
public void setBackupEnabledForUser(@UserIdInt int userId, boolean isEnabled)
|
||||
throws RemoteException {
|
||||
BackupManagerService svc = mService;
|
||||
if (svc != null) {
|
||||
svc.setBackupEnabled(isEnabled);
|
||||
svc.setBackupEnabled(userId, isEnabled);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBackupEnabled(boolean isEnabled) throws RemoteException {
|
||||
setBackupEnabledForUser(binderGetCallingUserId(), isEnabled);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAutoRestore(boolean doAutoRestore) throws RemoteException {
|
||||
BackupManagerService svc = mService;
|
||||
@@ -343,9 +354,14 @@ public class Trampoline extends IBackupManager.Stub {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBackupEnabled() throws RemoteException {
|
||||
public boolean isBackupEnabledForUser(@UserIdInt int userId) throws RemoteException {
|
||||
BackupManagerService svc = mService;
|
||||
return (svc != null) ? svc.isBackupEnabled() : false;
|
||||
return (svc != null) ? svc.isBackupEnabled(userId) : false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBackupEnabled() throws RemoteException {
|
||||
return isBackupEnabledForUser(binderGetCallingUserId());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -361,13 +377,18 @@ public class Trampoline extends IBackupManager.Stub {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void backupNow() throws RemoteException {
|
||||
public void backupNowForUser(@UserIdInt int userId) throws RemoteException {
|
||||
BackupManagerService svc = mService;
|
||||
if (svc != null) {
|
||||
svc.backupNow();
|
||||
svc.backupNow(userId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void backupNow() throws RemoteException {
|
||||
backupNowForUser(binderGetCallingUserId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void adbBackup(ParcelFileDescriptor fd, boolean includeApks, boolean includeObbs,
|
||||
boolean includeShared, boolean doWidgets, boolean allApps,
|
||||
@@ -543,21 +564,33 @@ public class Trampoline extends IBackupManager.Stub {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int requestBackup(String[] packages, IBackupObserver observer,
|
||||
IBackupManagerMonitor monitor, int flags) throws RemoteException {
|
||||
public int requestBackupForUser(@UserIdInt int userId, String[] packages, IBackupObserver
|
||||
observer, IBackupManagerMonitor monitor, int flags) throws RemoteException {
|
||||
BackupManagerService svc = mService;
|
||||
if (svc == null) {
|
||||
return BackupManager.ERROR_BACKUP_NOT_ALLOWED;
|
||||
}
|
||||
return svc.requestBackup(packages, observer, monitor, flags);
|
||||
return svc.requestBackup(userId, packages, observer, monitor, flags);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int requestBackup(String[] packages, IBackupObserver observer,
|
||||
IBackupManagerMonitor monitor, int flags) throws RemoteException {
|
||||
return requestBackupForUser(binderGetCallingUserId(), packages,
|
||||
observer, monitor, flags);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancelBackupsForUser(@UserIdInt int userId) throws RemoteException {
|
||||
BackupManagerService svc = mService;
|
||||
if (svc != null) {
|
||||
svc.cancelBackups(userId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancelBackups() throws RemoteException {
|
||||
BackupManagerService svc = mService;
|
||||
if (svc != null) {
|
||||
svc.cancelBackups();
|
||||
}
|
||||
cancelBackupsForUser(binderGetCallingUserId());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -22,7 +22,10 @@ import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.robolectric.Shadows.shadowOf;
|
||||
import static org.testng.Assert.expectThrows;
|
||||
|
||||
import android.annotation.UserIdInt;
|
||||
import android.app.Application;
|
||||
import android.app.backup.IBackupManagerMonitor;
|
||||
import android.app.backup.IBackupObserver;
|
||||
@@ -32,11 +35,14 @@ import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.IBinder;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
import android.os.UserHandle;
|
||||
import android.platform.test.annotations.Presubmit;
|
||||
|
||||
import com.android.server.backup.testing.BackupManagerServiceTestUtils;
|
||||
import com.android.server.backup.testing.TransportData;
|
||||
import com.android.server.testing.shadows.ShadowBinder;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
@@ -44,6 +50,8 @@ import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
import org.robolectric.annotation.Config;
|
||||
import org.robolectric.shadows.ShadowContextWrapper;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileDescriptor;
|
||||
@@ -51,14 +59,19 @@ import java.io.PrintWriter;
|
||||
|
||||
/** Tests for the user-aware backup/restore system service {@link BackupManagerService}. */
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@Config(shadows = {ShadowBinder.class})
|
||||
@Presubmit
|
||||
public class BackupManagerServiceTest {
|
||||
private static final String TEST_PACKAGE = "package";
|
||||
private static final String TEST_TRANSPORT = "transport";
|
||||
|
||||
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;
|
||||
|
||||
/** Initialize {@link BackupManagerService}. */
|
||||
@Before
|
||||
@@ -67,6 +80,8 @@ public class BackupManagerServiceTest {
|
||||
|
||||
Application application = RuntimeEnvironment.application;
|
||||
mContext = application;
|
||||
mShadowContext = shadowOf(application);
|
||||
mUserId = NON_USER_SYSTEM;
|
||||
mBackupManagerService =
|
||||
new BackupManagerService(
|
||||
application,
|
||||
@@ -75,6 +90,15 @@ public class BackupManagerServiceTest {
|
||||
mBackupManagerService.setUserBackupManagerService(mUserBackupManagerService);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean up and reset state that was created for testing {@link BackupManagerService}
|
||||
* operations.
|
||||
*/
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
ShadowBinder.reset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test verifying that {@link BackupManagerService#MORE_DEBUG} is set to {@code false}.
|
||||
* This is specifically to prevent overloading the logs in production.
|
||||
@@ -274,11 +298,41 @@ public class BackupManagerServiceTest {
|
||||
// ---------------------------------------------
|
||||
// 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
|
||||
public void setBackupEnabled_withoutPermission_throwsSecurityException() {
|
||||
mShadowContext.denyPermissions(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL);
|
||||
|
||||
expectThrows(
|
||||
SecurityException.class,
|
||||
() -> mBackupManagerService.setBackupEnabled(mUserId, 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
|
||||
public void setBackupEnabled_whenCallingUserIsTargetUser_doesntNeedPermission() {
|
||||
ShadowBinder.setCallingUserHandle(UserHandle.of(mUserId));
|
||||
mShadowContext.denyPermissions(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL);
|
||||
|
||||
mBackupManagerService.setBackupEnabled(mUserId, true);
|
||||
|
||||
verify(mUserBackupManagerService).setBackupEnabled(true);
|
||||
}
|
||||
|
||||
|
||||
/** Test that the backup service routes methods correctly to the user that requests it. */
|
||||
@Test
|
||||
public void setBackupEnabled_callsSetBackupEnabledForUser() throws Exception {
|
||||
mBackupManagerService.setBackupEnabled(true);
|
||||
mShadowContext.grantPermissions(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL);
|
||||
|
||||
mBackupManagerService.setBackupEnabled(mUserId, true);
|
||||
|
||||
verify(mUserBackupManagerService).setBackupEnabled(true);
|
||||
}
|
||||
@@ -299,10 +353,25 @@ public class BackupManagerServiceTest {
|
||||
verify(mUserBackupManagerService).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
|
||||
public void testIsBackupEnabled_withoutPermission_throwsSecurityException() {
|
||||
mShadowContext.denyPermissions(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL);
|
||||
|
||||
expectThrows(
|
||||
SecurityException.class,
|
||||
() -> mBackupManagerService.isBackupEnabled(mUserId));
|
||||
}
|
||||
|
||||
/** Test that the backup service routes methods correctly to the user that requests it. */
|
||||
@Test
|
||||
public void testIsBackupEnabled_callsIsBackupEnabledForUser() throws Exception {
|
||||
mBackupManagerService.isBackupEnabled();
|
||||
mShadowContext.grantPermissions(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL);
|
||||
|
||||
mBackupManagerService.isBackupEnabled(mUserId);
|
||||
|
||||
verify(mUserBackupManagerService).isBackupEnabled();
|
||||
}
|
||||
@@ -330,30 +399,81 @@ public class BackupManagerServiceTest {
|
||||
verify(mUserBackupManagerService).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
|
||||
public void testBackupNow_withoutPermission_throwsSecurityException() {
|
||||
mShadowContext.denyPermissions(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL);
|
||||
|
||||
expectThrows(
|
||||
SecurityException.class,
|
||||
() -> mBackupManagerService.backupNow(mUserId));
|
||||
}
|
||||
|
||||
/** Test that the backup service routes methods correctly to the user that requests it. */
|
||||
@Test
|
||||
public void testBackupNow_callsBackupNowForUser() throws Exception {
|
||||
mBackupManagerService.backupNow();
|
||||
mShadowContext.grantPermissions(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL);
|
||||
|
||||
mBackupManagerService.backupNow(mUserId);
|
||||
|
||||
verify(mUserBackupManagerService).backupNow();
|
||||
}
|
||||
|
||||
/** Test that the backup service routes methods correctly to the user that requests it. */
|
||||
/**
|
||||
* 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
|
||||
public void testRequestBackup_callsRequestBackupForUser() throws Exception {
|
||||
public void testRequestBackup_withoutPermission_throwsSecurityException() {
|
||||
mShadowContext.denyPermissions(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL);
|
||||
String[] packages = {TEST_PACKAGE};
|
||||
IBackupObserver observer = mock(IBackupObserver.class);
|
||||
IBackupManagerMonitor monitor = mock(IBackupManagerMonitor.class);
|
||||
|
||||
mBackupManagerService.requestBackup(packages, observer, monitor, /* flags */ 0);
|
||||
expectThrows(
|
||||
SecurityException.class,
|
||||
() -> mBackupManagerService.requestBackup(mUserId, packages, observer, monitor, 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);
|
||||
String[] packages = {TEST_PACKAGE};
|
||||
IBackupObserver observer = mock(IBackupObserver.class);
|
||||
IBackupManagerMonitor monitor = mock(IBackupManagerMonitor.class);
|
||||
|
||||
mBackupManagerService.requestBackup(mUserId, packages, observer, monitor,
|
||||
/* flags */ 0);
|
||||
|
||||
verify(mUserBackupManagerService).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
|
||||
public void testCancelBackups_withoutPermission_throwsSecurityException() {
|
||||
mShadowContext.denyPermissions(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL);
|
||||
|
||||
expectThrows(
|
||||
SecurityException.class,
|
||||
() -> mBackupManagerService.cancelBackups(mUserId));
|
||||
}
|
||||
|
||||
|
||||
/** Test that the backup service routes methods correctly to the user that requests it. */
|
||||
@Test
|
||||
public void testCancelBackups_callsCancelBackupsForUser() throws Exception {
|
||||
mBackupManagerService.cancelBackups();
|
||||
mShadowContext.grantPermissions(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL);
|
||||
|
||||
mBackupManagerService.cancelBackups(mUserId);
|
||||
|
||||
verify(mUserBackupManagerService).cancelBackups();
|
||||
}
|
||||
|
||||
@@ -17,9 +17,11 @@
|
||||
package com.android.server.testing.shadows;
|
||||
|
||||
import android.os.Binder;
|
||||
import android.os.UserHandle;
|
||||
|
||||
import org.robolectric.annotation.Implementation;
|
||||
import org.robolectric.annotation.Implements;
|
||||
import org.robolectric.annotation.Resetter;
|
||||
|
||||
/**
|
||||
* Extends {@link org.robolectric.shadows.ShadowBinder} with {@link Binder#clearCallingIdentity()}
|
||||
@@ -30,6 +32,7 @@ import org.robolectric.annotation.Implements;
|
||||
public class ShadowBinder extends org.robolectric.shadows.ShadowBinder {
|
||||
public static final Integer LOCAL_UID = 1000;
|
||||
private static Integer originalCallingUid;
|
||||
private static UserHandle sCallingUserHandle;
|
||||
|
||||
@Implementation
|
||||
protected static long clearCallingIdentity() {
|
||||
@@ -42,4 +45,30 @@ public class ShadowBinder extends org.robolectric.shadows.ShadowBinder {
|
||||
protected static void restoreCallingIdentity(long token) {
|
||||
setCallingUid(originalCallingUid);
|
||||
}
|
||||
|
||||
public static void setCallingUserHandle(UserHandle userHandle) {
|
||||
sCallingUserHandle = userHandle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shadows {@link Binder#getCallingUserHandle()}. If {@link ShadowBinder#sCallingUserHandle}
|
||||
* is set, return that; otherwise mimic the default implementation.
|
||||
*/
|
||||
@Implementation
|
||||
public static UserHandle getCallingUserHandle() {
|
||||
if (sCallingUserHandle != null) {
|
||||
return sCallingUserHandle;
|
||||
} else {
|
||||
return UserHandle.of(UserHandle.getUserId(getCallingUid()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean up and reset state that was created for testing.
|
||||
*/
|
||||
@Resetter
|
||||
public static void reset() {
|
||||
sCallingUserHandle = null;
|
||||
org.robolectric.shadows.ShadowBinder.reset();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.annotation.UserIdInt;
|
||||
import android.app.backup.BackupManager;
|
||||
import android.app.backup.IBackupManagerMonitor;
|
||||
import android.app.backup.IBackupObserver;
|
||||
@@ -86,8 +87,9 @@ public class TrampolineTest {
|
||||
new ComponentName("package1", "class1"),
|
||||
new ComponentName("package2", "class2")
|
||||
};
|
||||
private final int NON_USER_SYSTEM = UserHandle.USER_SYSTEM + 1;
|
||||
private static final int NON_USER_SYSTEM = UserHandle.USER_SYSTEM + 1;
|
||||
|
||||
@UserIdInt private int mUserId;
|
||||
@Mock private BackupManagerService mBackupManagerServiceMock;
|
||||
@Mock private Context mContextMock;
|
||||
@Mock private File mSuppressFileMock;
|
||||
@@ -110,11 +112,13 @@ public class TrampolineTest {
|
||||
|
||||
TrampolineTestable.sBackupManagerServiceMock = mBackupManagerServiceMock;
|
||||
TrampolineTestable.sSuppressFile = mSuppressFileMock;
|
||||
TrampolineTestable.sCallingUserId = UserHandle.USER_SYSTEM;
|
||||
TrampolineTestable.sCallingUid = Process.SYSTEM_UID;
|
||||
TrampolineTestable.sBackupDisabled = false;
|
||||
|
||||
when(mSuppressFileMock.getParentFile()).thenReturn(mSuppressFileParentMock);
|
||||
|
||||
mUserId = NON_USER_SYSTEM;
|
||||
mTrampoline = new TrampolineTestable(mContextMock);
|
||||
|
||||
mContentResolver = new MockContentResolver();
|
||||
@@ -361,10 +365,22 @@ public class TrampolineTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setBackupEnabled_forwarded() throws RemoteException {
|
||||
public void setBackupEnabledForUser_forwarded() throws RemoteException {
|
||||
mTrampoline.initializeService(UserHandle.USER_SYSTEM);
|
||||
|
||||
mTrampoline.setBackupEnabledForUser(mUserId, true);
|
||||
|
||||
verify(mBackupManagerServiceMock).setBackupEnabled(mUserId, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setBackupEnabled_forwardedToCallingUserId() throws RemoteException {
|
||||
TrampolineTestable.sCallingUserId = mUserId;
|
||||
mTrampoline.initializeService(UserHandle.USER_SYSTEM);
|
||||
|
||||
mTrampoline.setBackupEnabled(true);
|
||||
verify(mBackupManagerServiceMock).setBackupEnabled(true);
|
||||
|
||||
verify(mBackupManagerServiceMock).setBackupEnabled(mUserId, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -400,10 +416,22 @@ public class TrampolineTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isBackupEnabled_forwarded() throws RemoteException {
|
||||
public void isBackupEnabledForUser_forwarded() throws RemoteException {
|
||||
mTrampoline.initializeService(UserHandle.USER_SYSTEM);
|
||||
|
||||
mTrampoline.isBackupEnabledForUser(mUserId);
|
||||
|
||||
verify(mBackupManagerServiceMock).isBackupEnabled(mUserId);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isBackupEnabled_forwardedToCallingUserId() throws RemoteException {
|
||||
TrampolineTestable.sCallingUserId = mUserId;
|
||||
mTrampoline.initializeService(UserHandle.USER_SYSTEM);
|
||||
|
||||
mTrampoline.isBackupEnabled();
|
||||
verify(mBackupManagerServiceMock).isBackupEnabled();
|
||||
|
||||
verify(mBackupManagerServiceMock).isBackupEnabled(mUserId);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -439,10 +467,22 @@ public class TrampolineTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void backupNow_forwarded() throws RemoteException {
|
||||
public void backupNowForUser_forwarded() throws RemoteException {
|
||||
mTrampoline.initializeService(UserHandle.USER_SYSTEM);
|
||||
|
||||
mTrampoline.backupNowForUser(mUserId);
|
||||
|
||||
verify(mBackupManagerServiceMock).backupNow(mUserId);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void backupNow_forwardedToCallingUserId() throws RemoteException {
|
||||
TrampolineTestable.sCallingUserId = mUserId;
|
||||
mTrampoline.initializeService(UserHandle.USER_SYSTEM);
|
||||
|
||||
mTrampoline.backupNow();
|
||||
verify(mBackupManagerServiceMock).backupNow();
|
||||
|
||||
verify(mBackupManagerServiceMock).backupNow(mUserId);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -798,15 +838,28 @@ public class TrampolineTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestBackup_forwarded() throws RemoteException {
|
||||
when(mBackupManagerServiceMock.requestBackup(PACKAGE_NAMES, mBackupObserverMock,
|
||||
mBackupManagerMonitorMock, 123)).thenReturn(456);
|
||||
|
||||
public void requestBackupForUser_forwarded() throws RemoteException {
|
||||
when(mBackupManagerServiceMock.requestBackup(mUserId, PACKAGE_NAMES,
|
||||
mBackupObserverMock, mBackupManagerMonitorMock, 123)).thenReturn(456);
|
||||
mTrampoline.initializeService(UserHandle.USER_SYSTEM);
|
||||
assertEquals(456, mTrampoline.requestBackup(PACKAGE_NAMES, mBackupObserverMock,
|
||||
mBackupManagerMonitorMock, 123));
|
||||
verify(mBackupManagerServiceMock).requestBackup(PACKAGE_NAMES, mBackupObserverMock,
|
||||
mBackupManagerMonitorMock, 123);
|
||||
|
||||
assertEquals(456, mTrampoline.requestBackupForUser(mUserId, PACKAGE_NAMES,
|
||||
mBackupObserverMock, mBackupManagerMonitorMock, 123));
|
||||
verify(mBackupManagerServiceMock).requestBackup(mUserId, PACKAGE_NAMES,
|
||||
mBackupObserverMock, mBackupManagerMonitorMock, 123);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestBackup_forwardedToCallingUserId() throws RemoteException {
|
||||
TrampolineTestable.sCallingUserId = mUserId;
|
||||
when(mBackupManagerServiceMock.requestBackup(NON_USER_SYSTEM, PACKAGE_NAMES,
|
||||
mBackupObserverMock, mBackupManagerMonitorMock, 123)).thenReturn(456);
|
||||
mTrampoline.initializeService(UserHandle.USER_SYSTEM);
|
||||
|
||||
assertEquals(456, mTrampoline.requestBackup(PACKAGE_NAMES,
|
||||
mBackupObserverMock, mBackupManagerMonitorMock, 123));
|
||||
verify(mBackupManagerServiceMock).requestBackup(mUserId, PACKAGE_NAMES,
|
||||
mBackupObserverMock, mBackupManagerMonitorMock, 123);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -816,10 +869,22 @@ public class TrampolineTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void cancelBackups_forwarded() throws RemoteException {
|
||||
public void cancelBackupsForUser_forwarded() throws RemoteException {
|
||||
mTrampoline.initializeService(UserHandle.USER_SYSTEM);
|
||||
|
||||
mTrampoline.cancelBackupsForUser(mUserId);
|
||||
|
||||
verify(mBackupManagerServiceMock).cancelBackups(mUserId);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void cancelBackups_forwardedToCallingUserId() throws RemoteException {
|
||||
TrampolineTestable.sCallingUserId = mUserId;
|
||||
mTrampoline.initializeService(UserHandle.USER_SYSTEM);
|
||||
|
||||
mTrampoline.cancelBackups();
|
||||
verify(mBackupManagerServiceMock).cancelBackups();
|
||||
|
||||
verify(mBackupManagerServiceMock).cancelBackups(mUserId);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -891,6 +956,7 @@ public class TrampolineTest {
|
||||
private static class TrampolineTestable extends Trampoline {
|
||||
static boolean sBackupDisabled = false;
|
||||
static File sSuppressFile = null;
|
||||
static int sCallingUserId = -1;
|
||||
static int sCallingUid = -1;
|
||||
static BackupManagerService sBackupManagerServiceMock = null;
|
||||
private int mCreateServiceCallsCount = 0;
|
||||
@@ -909,6 +975,10 @@ public class TrampolineTest {
|
||||
return sSuppressFile;
|
||||
}
|
||||
|
||||
protected int binderGetCallingUserId() {
|
||||
return sCallingUserId;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int binderGetCallingUid() {
|
||||
return sCallingUid;
|
||||
|
||||
Reference in New Issue
Block a user