Merge changes from topic "br-cts-hsum" into udc-dev
* changes: Modifying Backup code to support HSUM mode. Improve `dumpsys backup`
This commit is contained in:
committed by
Android (Google) Code Review
commit
82a2b5e93c
@@ -253,7 +253,7 @@ public class Bmgr {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
boolean enable = Boolean.parseBoolean(arg);
|
boolean enable = Boolean.parseBoolean(arg);
|
||||||
mBmgr.setAutoRestore(enable);
|
mBmgr.setAutoRestoreForUser(userId, enable);
|
||||||
System.out.println(
|
System.out.println(
|
||||||
"Auto restore is now "
|
"Auto restore is now "
|
||||||
+ (enable ? "enabled" : "disabled")
|
+ (enable ? "enabled" : "disabled")
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ public final class Backup {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void run(String[] args) {
|
public void run(String[] args) {
|
||||||
|
Log.d(TAG, "Called run() with args: " + String.join(" ", args));
|
||||||
if (mBackupManager == null) {
|
if (mBackupManager == null) {
|
||||||
Log.e(TAG, "Can't obtain Backup Manager binder");
|
Log.e(TAG, "Can't obtain Backup Manager binder");
|
||||||
return;
|
return;
|
||||||
@@ -70,6 +71,8 @@ public final class Backup {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Log.d(TAG, "UserId : " + userId);
|
||||||
|
|
||||||
String arg = nextArg();
|
String arg = nextArg();
|
||||||
if (arg.equals("backup")) {
|
if (arg.equals("backup")) {
|
||||||
doBackup(OsConstants.STDOUT_FILENO, userId);
|
doBackup(OsConstants.STDOUT_FILENO, userId);
|
||||||
|
|||||||
@@ -813,7 +813,7 @@ public class BackupManagerService extends IBackupManager.Stub {
|
|||||||
}
|
}
|
||||||
UserBackupManagerService userBackupManagerService =
|
UserBackupManagerService userBackupManagerService =
|
||||||
getServiceForUserIfCallerHasPermission(
|
getServiceForUserIfCallerHasPermission(
|
||||||
UserHandle.USER_SYSTEM, "hasBackupPassword()");
|
userId, "hasBackupPassword()");
|
||||||
|
|
||||||
return userBackupManagerService != null && userBackupManagerService.hasBackupPassword();
|
return userBackupManagerService != null && userBackupManagerService.hasBackupPassword();
|
||||||
}
|
}
|
||||||
@@ -1515,41 +1515,73 @@ public class BackupManagerService extends IBackupManager.Stub {
|
|||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
void dumpWithoutCheckingPermission(FileDescriptor fd, PrintWriter pw, String[] args) {
|
void dumpWithoutCheckingPermission(FileDescriptor fd, PrintWriter pw, String[] args) {
|
||||||
int userId = binderGetCallingUserId();
|
int argIndex = 0;
|
||||||
if (!isUserReadyForBackup(userId)) {
|
|
||||||
pw.println("Inactive");
|
String op = nextArg(args, argIndex);
|
||||||
|
argIndex++;
|
||||||
|
|
||||||
|
if ("--help".equals(op)) {
|
||||||
|
showDumpUsage(pw);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if ("users".equals(op)) {
|
||||||
if (args != null) {
|
pw.print(DUMP_RUNNING_USERS_MESSAGE);
|
||||||
for (String arg : args) {
|
for (int i = 0; i < mUserServices.size(); i++) {
|
||||||
if ("-h".equals(arg)) {
|
UserBackupManagerService userBackupManagerService =
|
||||||
pw.println("'dumpsys backup' optional arguments:");
|
getServiceForUserIfCallerHasPermission(mUserServices.keyAt(i),
|
||||||
pw.println(" -h : this help text");
|
"dump()");
|
||||||
pw.println(" a[gents] : dump information about defined backup agents");
|
if (userBackupManagerService != null) {
|
||||||
pw.println(" transportclients : dump information about transport clients");
|
pw.print(" " + userBackupManagerService.getUserId());
|
||||||
pw.println(" transportstats : dump transport statts");
|
|
||||||
pw.println(" users : dump the list of users for which backup service "
|
|
||||||
+ "is running");
|
|
||||||
return;
|
|
||||||
} else if ("users".equals(arg.toLowerCase())) {
|
|
||||||
pw.print(DUMP_RUNNING_USERS_MESSAGE);
|
|
||||||
for (int i = 0; i < mUserServices.size(); i++) {
|
|
||||||
pw.print(" " + mUserServices.keyAt(i));
|
|
||||||
}
|
|
||||||
pw.println();
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pw.println();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
if ("--user".equals(op)) {
|
||||||
for (int i = 0; i < mUserServices.size(); i++) {
|
String userArg = nextArg(args, argIndex);
|
||||||
|
argIndex++;
|
||||||
|
if (userArg == null) {
|
||||||
|
showDumpUsage(pw);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int userId = UserHandle.parseUserArg(userArg);
|
||||||
UserBackupManagerService userBackupManagerService =
|
UserBackupManagerService userBackupManagerService =
|
||||||
getServiceForUserIfCallerHasPermission(mUserServices.keyAt(i), "dump()");
|
getServiceForUserIfCallerHasPermission(userId, "dump()");
|
||||||
if (userBackupManagerService != null) {
|
if (userBackupManagerService != null) {
|
||||||
userBackupManagerService.dump(fd, pw, args);
|
userBackupManagerService.dump(fd, pw, args);
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
if (op == null || "agents".startsWith(op) || "transportclients".equals(op)
|
||||||
|
|| "transportstats".equals(op)) {
|
||||||
|
for (int i = 0; i < mUserServices.size(); i++) {
|
||||||
|
UserBackupManagerService userBackupManagerService =
|
||||||
|
getServiceForUserIfCallerHasPermission(mUserServices.keyAt(i), "dump()");
|
||||||
|
if (userBackupManagerService != null) {
|
||||||
|
userBackupManagerService.dump(fd, pw, args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
showDumpUsage(pw);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String nextArg(String[] args, int argIndex) {
|
||||||
|
if (argIndex >= args.length) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return args[argIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void showDumpUsage(PrintWriter pw) {
|
||||||
|
pw.println("'dumpsys backup' optional arguments:");
|
||||||
|
pw.println(" --help : this help text");
|
||||||
|
pw.println(" a[gents] : dump information about defined backup agents");
|
||||||
|
pw.println(" transportclients : dump information about transport clients");
|
||||||
|
pw.println(" transportstats : dump transport stats");
|
||||||
|
pw.println(" users : dump the list of users for which backup service is running");
|
||||||
|
pw.println(" --user <userId> : dump information for user userId");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1654,7 +1686,7 @@ public class BackupManagerService extends IBackupManager.Stub {
|
|||||||
* @param message A message to include in the exception if it is thrown.
|
* @param message A message to include in the exception if it is thrown.
|
||||||
*/
|
*/
|
||||||
void enforceCallingPermissionOnUserId(@UserIdInt int userId, String message) {
|
void enforceCallingPermissionOnUserId(@UserIdInt int userId, String message) {
|
||||||
if (Binder.getCallingUserHandle().getIdentifier() != userId) {
|
if (binderGetCallingUserId() != userId) {
|
||||||
mContext.enforceCallingOrSelfPermission(
|
mContext.enforceCallingOrSelfPermission(
|
||||||
Manifest.permission.INTERACT_ACROSS_USERS_FULL, message);
|
Manifest.permission.INTERACT_ACROSS_USERS_FULL, message);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2797,11 +2797,6 @@ public class UserBackupManagerService {
|
|||||||
boolean includeSystem, boolean compress, boolean doKeyValue, String[] pkgList) {
|
boolean includeSystem, boolean compress, boolean doKeyValue, String[] pkgList) {
|
||||||
mContext.enforceCallingPermission(android.Manifest.permission.BACKUP, "adbBackup");
|
mContext.enforceCallingPermission(android.Manifest.permission.BACKUP, "adbBackup");
|
||||||
|
|
||||||
final int callingUserHandle = UserHandle.getCallingUserId();
|
|
||||||
if (callingUserHandle != UserHandle.USER_SYSTEM) {
|
|
||||||
throw new IllegalStateException("Backup supported only for the device owner");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate
|
// Validate
|
||||||
if (!doAllApps) {
|
if (!doAllApps) {
|
||||||
if (!includeShared) {
|
if (!includeShared) {
|
||||||
@@ -2972,11 +2967,6 @@ public class UserBackupManagerService {
|
|||||||
public void adbRestore(ParcelFileDescriptor fd) {
|
public void adbRestore(ParcelFileDescriptor fd) {
|
||||||
mContext.enforceCallingPermission(android.Manifest.permission.BACKUP, "adbRestore");
|
mContext.enforceCallingPermission(android.Manifest.permission.BACKUP, "adbRestore");
|
||||||
|
|
||||||
final int callingUserHandle = UserHandle.getCallingUserId();
|
|
||||||
if (callingUserHandle != UserHandle.USER_SYSTEM) {
|
|
||||||
throw new IllegalStateException("Restore supported only for the device owner");
|
|
||||||
}
|
|
||||||
|
|
||||||
final long oldId = Binder.clearCallingIdentity();
|
final long oldId = Binder.clearCallingIdentity();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -3085,7 +3075,7 @@ public class UserBackupManagerService {
|
|||||||
"com.android.backupconfirm.BackupRestoreConfirmation");
|
"com.android.backupconfirm.BackupRestoreConfirmation");
|
||||||
confIntent.putExtra(FullBackup.CONF_TOKEN_INTENT_EXTRA, token);
|
confIntent.putExtra(FullBackup.CONF_TOKEN_INTENT_EXTRA, token);
|
||||||
confIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
|
confIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
|
||||||
mContext.startActivityAsUser(confIntent, UserHandle.SYSTEM);
|
mContext.startActivityAsUser(confIntent, UserHandle.of(mUserId));
|
||||||
} catch (ActivityNotFoundException e) {
|
} catch (ActivityNotFoundException e) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ import static org.mockito.Mockito.mock;
|
|||||||
import static org.mockito.Mockito.never;
|
import static org.mockito.Mockito.never;
|
||||||
import static org.mockito.Mockito.spy;
|
import static org.mockito.Mockito.spy;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
import static org.robolectric.Shadows.shadowOf;
|
import static org.robolectric.Shadows.shadowOf;
|
||||||
import static org.testng.Assert.expectThrows;
|
import static org.testng.Assert.expectThrows;
|
||||||
|
|
||||||
@@ -118,6 +119,10 @@ public class BackupManagerServiceRoboTest {
|
|||||||
mShadowUserManager.addUser(mUserOneId, "mUserOneId", 0);
|
mShadowUserManager.addUser(mUserOneId, "mUserOneId", 0);
|
||||||
mShadowUserManager.addUser(mUserTwoId, "mUserTwoId", 0);
|
mShadowUserManager.addUser(mUserTwoId, "mUserTwoId", 0);
|
||||||
|
|
||||||
|
when(mUserSystemService.getUserId()).thenReturn(UserHandle.USER_SYSTEM);
|
||||||
|
when(mUserOneService.getUserId()).thenReturn(mUserOneId);
|
||||||
|
when(mUserTwoService.getUserId()).thenReturn(mUserTwoId);
|
||||||
|
|
||||||
mShadowContext.grantPermissions(BACKUP);
|
mShadowContext.grantPermissions(BACKUP);
|
||||||
mShadowContext.grantPermissions(INTERACT_ACROSS_USERS_FULL);
|
mShadowContext.grantPermissions(INTERACT_ACROSS_USERS_FULL);
|
||||||
|
|
||||||
@@ -1469,9 +1474,9 @@ public class BackupManagerServiceRoboTest {
|
|||||||
File testFile = createTestFile();
|
File testFile = createTestFile();
|
||||||
FileDescriptor fileDescriptor = new FileDescriptor();
|
FileDescriptor fileDescriptor = new FileDescriptor();
|
||||||
PrintWriter printWriter = new PrintWriter(testFile);
|
PrintWriter printWriter = new PrintWriter(testFile);
|
||||||
String[] args = {"1", "2"};
|
|
||||||
ShadowBinder.setCallingUserHandle(UserHandle.of(UserHandle.USER_SYSTEM));
|
ShadowBinder.setCallingUserHandle(UserHandle.of(UserHandle.USER_SYSTEM));
|
||||||
|
|
||||||
|
String[] args = {"--user", "0"};
|
||||||
backupManagerService.dump(fileDescriptor, printWriter, args);
|
backupManagerService.dump(fileDescriptor, printWriter, args);
|
||||||
|
|
||||||
verify(mUserSystemService).dump(fileDescriptor, printWriter, args);
|
verify(mUserSystemService).dump(fileDescriptor, printWriter, args);
|
||||||
@@ -1485,8 +1490,8 @@ public class BackupManagerServiceRoboTest {
|
|||||||
File testFile = createTestFile();
|
File testFile = createTestFile();
|
||||||
FileDescriptor fileDescriptor = new FileDescriptor();
|
FileDescriptor fileDescriptor = new FileDescriptor();
|
||||||
PrintWriter printWriter = new PrintWriter(testFile);
|
PrintWriter printWriter = new PrintWriter(testFile);
|
||||||
String[] args = {"1", "2"};
|
|
||||||
|
|
||||||
|
String[] args = {"--user", "10"};
|
||||||
backupManagerService.dump(fileDescriptor, printWriter, args);
|
backupManagerService.dump(fileDescriptor, printWriter, args);
|
||||||
|
|
||||||
verify(mUserOneService, never()).dump(fileDescriptor, printWriter, args);
|
verify(mUserOneService, never()).dump(fileDescriptor, printWriter, args);
|
||||||
|
|||||||
@@ -63,6 +63,7 @@ import com.android.server.SystemService;
|
|||||||
import com.android.server.backup.utils.RandomAccessFileUtils;
|
import com.android.server.backup.utils.RandomAccessFileUtils;
|
||||||
|
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
|
import org.junit.Assert;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
@@ -615,6 +616,53 @@ public class BackupManagerServiceTest {
|
|||||||
verify(mNonSystemUserBackupManagerService, never()).dump(any(), any(), any());
|
verify(mNonSystemUserBackupManagerService, never()).dump(any(), any(), any());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDumpForOneUser_callerDoesNotHaveInteractAcrossUsersFullPermission_ignored() {
|
||||||
|
createBackupManagerServiceAndUnlockSystemUser();
|
||||||
|
mService.setBackupServiceActive(NON_SYSTEM_USER, true);
|
||||||
|
simulateUserUnlocked(NON_SYSTEM_USER);
|
||||||
|
|
||||||
|
doThrow(new SecurityException())
|
||||||
|
.when(mContextMock)
|
||||||
|
.enforceCallingOrSelfPermission(
|
||||||
|
eq(Manifest.permission.INTERACT_ACROSS_USERS_FULL), anyString());
|
||||||
|
|
||||||
|
String[] args = new String[]{"--user", Integer.toString(NON_SYSTEM_USER)};
|
||||||
|
Assert.assertThrows(SecurityException.class,
|
||||||
|
() -> mService.dumpWithoutCheckingPermission(mFileDescriptorStub, mPrintWriterMock,
|
||||||
|
args));
|
||||||
|
|
||||||
|
verify(mNonSystemUserBackupManagerService, never()).dump(any(), any(), any());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void
|
||||||
|
testDumpForOneUser_callerHasInteractAcrossUsersFullPermission_dumpsOnlySpecifiedUser() {
|
||||||
|
createBackupManagerServiceAndUnlockSystemUser();
|
||||||
|
mService.setBackupServiceActive(NON_SYSTEM_USER, true);
|
||||||
|
simulateUserUnlocked(NON_SYSTEM_USER);
|
||||||
|
|
||||||
|
String[] args = new String[]{"--user", Integer.toString(UserHandle.USER_SYSTEM)};
|
||||||
|
mService.dumpWithoutCheckingPermission(mFileDescriptorStub, mPrintWriterMock, args);
|
||||||
|
|
||||||
|
verify(mSystemUserBackupManagerService).dump(any(), any(), any());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDumpForAllUsers_callerHasInteractAcrossUsersFullPermission_dumpsAllUsers() {
|
||||||
|
createBackupManagerServiceAndUnlockSystemUser();
|
||||||
|
mService.setBackupServiceActive(NON_SYSTEM_USER, true);
|
||||||
|
simulateUserUnlocked(NON_SYSTEM_USER);
|
||||||
|
|
||||||
|
String[] args = new String[]{"users"};
|
||||||
|
mService.dumpWithoutCheckingPermission(mFileDescriptorStub, mPrintWriterMock, args);
|
||||||
|
|
||||||
|
// Check that dump() invocations are not called on user's Backup service,
|
||||||
|
// as 'dumpsys backup users' only list users for whom Backup service is running.
|
||||||
|
verify(mSystemUserBackupManagerService, never()).dump(any(), any(), any());
|
||||||
|
verify(mNonSystemUserBackupManagerService, never()).dump(any(), any(), any());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test that {@link BackupManagerService#dump(FileDescriptor, PrintWriter, String[])} dumps
|
* Test that {@link BackupManagerService#dump(FileDescriptor, PrintWriter, String[])} dumps
|
||||||
* system user information before non-system user information.
|
* system user information before non-system user information.
|
||||||
|
|||||||
Reference in New Issue
Block a user