Loading services/backup/java/com/android/server/backup/BackupManagerService.java +21 −6 Original line number Diff line number Diff line Loading @@ -1452,6 +1452,11 @@ public class BackupManagerService extends IBackupManager.Stub { if (!DumpUtils.checkDumpAndUsageStatsPermission(mContext, TAG, pw)) { return; } dumpWithoutCheckingPermission(fd, pw, args); } @VisibleForTesting void dumpWithoutCheckingPermission(FileDescriptor fd, PrintWriter pw, String[] args) { int userId = binderGetCallingUserId(); if (!isUserReadyForBackup(userId)) { pw.println("Inactive"); Loading @@ -1460,7 +1465,16 @@ public class BackupManagerService extends IBackupManager.Stub { if (args != null) { for (String arg : args) { if ("users".equals(arg.toLowerCase())) { if ("-h".equals(arg)) { pw.println("'dumpsys backup' optional arguments:"); pw.println(" -h : 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 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)); Loading @@ -1471,13 +1485,14 @@ public class BackupManagerService extends IBackupManager.Stub { } } for (int i = 0; i < mUserServices.size(); i++) { UserBackupManagerService userBackupManagerService = getServiceForUserIfCallerHasPermission(UserHandle.USER_SYSTEM, "dump()"); getServiceForUserIfCallerHasPermission(mUserServices.keyAt(i), "dump()"); if (userBackupManagerService != null) { userBackupManagerService.dump(fd, pw, args); } } } /** * Used by the {@link JobScheduler} to run a full backup when conditions are right. The model we Loading services/backup/java/com/android/server/backup/UserBackupManagerService.java +14 −19 Original line number Diff line number Diff line Loading @@ -3545,14 +3545,7 @@ public class UserBackupManagerService { try { if (args != null) { for (String arg : args) { if ("-h".equals(arg)) { pw.println("'dumpsys backup' optional arguments:"); pw.println(" -h : this help text"); pw.println(" a[gents] : dump information about defined backup agents"); pw.println(" users : dump the list of users for which backup service " + "is running"); return; } else if ("agents".startsWith(arg)) { if ("agents".startsWith(arg)) { dumpAgents(pw); return; } else if ("transportclients".equals(arg.toLowerCase())) { Loading Loading @@ -3583,8 +3576,10 @@ public class UserBackupManagerService { } private void dumpInternal(PrintWriter pw) { // Add prefix for only non-system users so that system user dumpsys is the same as before String userPrefix = mUserId == UserHandle.USER_SYSTEM ? "" : "User " + mUserId + ":"; synchronized (mQueueLock) { pw.println("Backup Manager is " + (mEnabled ? "enabled" : "disabled") pw.println(userPrefix + "Backup Manager is " + (mEnabled ? "enabled" : "disabled") + " / " + (!mSetupComplete ? "not " : "") + "setup complete / " + (this.mPendingInits.size() == 0 ? "not " : "") + "pending init"); pw.println("Auto-restore is " + (mAutoRestore ? "enabled" : "disabled")); Loading @@ -3594,13 +3589,13 @@ public class UserBackupManagerService { + " (now = " + System.currentTimeMillis() + ')'); pw.println(" next scheduled: " + KeyValueBackupJob.nextScheduled(mUserId)); pw.println("Transport whitelist:"); pw.println(userPrefix + "Transport whitelist:"); for (ComponentName transport : mTransportManager.getTransportWhitelist()) { pw.print(" "); pw.println(transport.flattenToShortString()); } pw.println("Available transports:"); pw.println(userPrefix + "Available transports:"); final String[] transports = listAllTransports(); if (transports != null) { for (String t : transports) { Loading @@ -3626,18 +3621,18 @@ public class UserBackupManagerService { mTransportManager.dumpTransportClients(pw); pw.println("Pending init: " + mPendingInits.size()); pw.println(userPrefix + "Pending init: " + mPendingInits.size()); for (String s : mPendingInits) { pw.println(" " + s); } pw.print("Ancestral: "); pw.print(userPrefix + "Ancestral: "); pw.println(Long.toHexString(mAncestralToken)); pw.print("Current: "); pw.print(userPrefix + "Current: "); pw.println(Long.toHexString(mCurrentToken)); int numPackages = mBackupParticipants.size(); pw.println("Participants:"); pw.println(userPrefix + "Participants:"); for (int i = 0; i < numPackages; i++) { int uid = mBackupParticipants.keyAt(i); pw.print(" uid: "); Loading @@ -3648,7 +3643,7 @@ public class UserBackupManagerService { } } pw.println("Ancestral packages: " pw.println(userPrefix + "Ancestral packages: " + (mAncestralPackages == null ? "none" : mAncestralPackages.size())); if (mAncestralPackages != null) { for (String pkg : mAncestralPackages) { Loading @@ -3657,17 +3652,17 @@ public class UserBackupManagerService { } Set<String> processedPackages = mProcessedPackagesJournal.getPackagesCopy(); pw.println("Ever backed up: " + processedPackages.size()); pw.println(userPrefix + "Ever backed up: " + processedPackages.size()); for (String pkg : processedPackages) { pw.println(" " + pkg); } pw.println("Pending key/value backup: " + mPendingBackups.size()); pw.println(userPrefix + "Pending key/value backup: " + mPendingBackups.size()); for (BackupRequest req : mPendingBackups.values()) { pw.println(" " + req); } pw.println("Full backup queue:" + mFullBackupQueue.size()); pw.println(userPrefix + "Full backup queue:" + mFullBackupQueue.size()); for (FullBackupEntry entry : mFullBackupQueue) { pw.print(" "); pw.print(entry.lastBackup); Loading services/robotests/backup/src/com/android/server/backup/UserBackupManagerServiceTest.java +40 −1 Original line number Diff line number Diff line Loading @@ -81,7 +81,10 @@ import org.robolectric.shadows.ShadowLooper; import org.robolectric.shadows.ShadowPackageManager; import java.io.File; import java.io.FileDescriptor; import java.io.IOException; import java.io.PrintWriter; import java.io.StringWriter; import java.util.List; /** Loading Loading @@ -1238,13 +1241,49 @@ public class UserBackupManagerServiceTest { assertThat(service.getAncestralSerialNumber()).isEqualTo(testSerialNumber2); } /** * Test that {@link UserBackupManagerService#dump()} for system user does not prefix dump with * "User 0:". */ @Test public void testDump_forSystemUser_DoesNotHaveUserPrefix() throws Exception { mShadowContext.grantPermissions(android.Manifest.permission.BACKUP); UserBackupManagerService service = BackupManagerServiceTestUtils.createUserBackupManagerServiceAndRunTasks( UserHandle.USER_SYSTEM, mContext, mBackupThread, mBaseStateDir, mDataDir, mTransportManager); StringWriter dump = new StringWriter(); service.dump(new FileDescriptor(), new PrintWriter(dump), new String[0]); assertThat(dump.toString()).startsWith("Backup Manager is "); } /** * Test that {@link UserBackupManagerService#dump()} for non-system user prefixes dump with * "User <userid>:". */ @Test public void testDump_forNonSystemUser_HasUserPrefix() throws Exception { mShadowContext.grantPermissions(android.Manifest.permission.BACKUP); UserBackupManagerService service = createUserBackupManagerServiceAndRunTasks(); StringWriter dump = new StringWriter(); service.dump(new FileDescriptor(), new PrintWriter(dump), new String[0]); assertThat(dump.toString()).startsWith("User " + USER_ID + ":" + "Backup Manager is "); } private File createTestFile() throws IOException { File testFile = new File(mContext.getFilesDir(), "test"); testFile.createNewFile(); return testFile; } /** * We can't mock the void method {@link #schedule(Context, long, BackupManagerConstants)} so we * extend {@link ShadowKeyValueBackupJob} and throw an exception at the end of the method. Loading services/tests/servicestests/src/com/android/server/backup/BackupManagerServiceTest.java +25 −1 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ import static junit.framework.Assert.fail; 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.when; Loading Loading @@ -59,6 +60,7 @@ import org.junit.Before; import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.InOrder; import org.mockito.Mock; import org.mockito.MockitoAnnotations; Loading @@ -83,6 +85,8 @@ public class BackupManagerServiceTest { @Mock private UserBackupManagerService mUserBackupManagerService; @Mock private UserBackupManagerService mNonSystemUserBackupManagerService; @Mock private Context mContextMock; @Mock private PrintWriter mPrintWriterMock; Loading @@ -105,7 +109,7 @@ public class BackupManagerServiceTest { mUserServices = new SparseArray<>(); mUserServices.append(UserHandle.USER_SYSTEM, mUserBackupManagerService); mUserServices.append(NON_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); Loading Loading @@ -512,6 +516,26 @@ public class BackupManagerServiceTest { mService.dump(mFileDescriptorStub, mPrintWriterMock, new String[0]); verifyNoMoreInteractions(mUserBackupManagerService); verifyNoMoreInteractions(mNonSystemUserBackupManagerService); } /** * Test that {@link BackupManagerService#dump()} dumps system user information before non-system * user information. */ @Test public void testDump_systemUserFirst() { String[] args = new String[0]; mService.dumpWithoutCheckingPermission(mFileDescriptorStub, mPrintWriterMock, args); InOrder inOrder = inOrder(mUserBackupManagerService, mNonSystemUserBackupManagerService); inOrder.verify(mUserBackupManagerService) .dump(mFileDescriptorStub, mPrintWriterMock, args); inOrder.verify(mNonSystemUserBackupManagerService) .dump(mFileDescriptorStub, mPrintWriterMock, args); inOrder.verifyNoMoreInteractions(); } @Test Loading Loading
services/backup/java/com/android/server/backup/BackupManagerService.java +21 −6 Original line number Diff line number Diff line Loading @@ -1452,6 +1452,11 @@ public class BackupManagerService extends IBackupManager.Stub { if (!DumpUtils.checkDumpAndUsageStatsPermission(mContext, TAG, pw)) { return; } dumpWithoutCheckingPermission(fd, pw, args); } @VisibleForTesting void dumpWithoutCheckingPermission(FileDescriptor fd, PrintWriter pw, String[] args) { int userId = binderGetCallingUserId(); if (!isUserReadyForBackup(userId)) { pw.println("Inactive"); Loading @@ -1460,7 +1465,16 @@ public class BackupManagerService extends IBackupManager.Stub { if (args != null) { for (String arg : args) { if ("users".equals(arg.toLowerCase())) { if ("-h".equals(arg)) { pw.println("'dumpsys backup' optional arguments:"); pw.println(" -h : 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 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)); Loading @@ -1471,13 +1485,14 @@ public class BackupManagerService extends IBackupManager.Stub { } } for (int i = 0; i < mUserServices.size(); i++) { UserBackupManagerService userBackupManagerService = getServiceForUserIfCallerHasPermission(UserHandle.USER_SYSTEM, "dump()"); getServiceForUserIfCallerHasPermission(mUserServices.keyAt(i), "dump()"); if (userBackupManagerService != null) { userBackupManagerService.dump(fd, pw, args); } } } /** * Used by the {@link JobScheduler} to run a full backup when conditions are right. The model we Loading
services/backup/java/com/android/server/backup/UserBackupManagerService.java +14 −19 Original line number Diff line number Diff line Loading @@ -3545,14 +3545,7 @@ public class UserBackupManagerService { try { if (args != null) { for (String arg : args) { if ("-h".equals(arg)) { pw.println("'dumpsys backup' optional arguments:"); pw.println(" -h : this help text"); pw.println(" a[gents] : dump information about defined backup agents"); pw.println(" users : dump the list of users for which backup service " + "is running"); return; } else if ("agents".startsWith(arg)) { if ("agents".startsWith(arg)) { dumpAgents(pw); return; } else if ("transportclients".equals(arg.toLowerCase())) { Loading Loading @@ -3583,8 +3576,10 @@ public class UserBackupManagerService { } private void dumpInternal(PrintWriter pw) { // Add prefix for only non-system users so that system user dumpsys is the same as before String userPrefix = mUserId == UserHandle.USER_SYSTEM ? "" : "User " + mUserId + ":"; synchronized (mQueueLock) { pw.println("Backup Manager is " + (mEnabled ? "enabled" : "disabled") pw.println(userPrefix + "Backup Manager is " + (mEnabled ? "enabled" : "disabled") + " / " + (!mSetupComplete ? "not " : "") + "setup complete / " + (this.mPendingInits.size() == 0 ? "not " : "") + "pending init"); pw.println("Auto-restore is " + (mAutoRestore ? "enabled" : "disabled")); Loading @@ -3594,13 +3589,13 @@ public class UserBackupManagerService { + " (now = " + System.currentTimeMillis() + ')'); pw.println(" next scheduled: " + KeyValueBackupJob.nextScheduled(mUserId)); pw.println("Transport whitelist:"); pw.println(userPrefix + "Transport whitelist:"); for (ComponentName transport : mTransportManager.getTransportWhitelist()) { pw.print(" "); pw.println(transport.flattenToShortString()); } pw.println("Available transports:"); pw.println(userPrefix + "Available transports:"); final String[] transports = listAllTransports(); if (transports != null) { for (String t : transports) { Loading @@ -3626,18 +3621,18 @@ public class UserBackupManagerService { mTransportManager.dumpTransportClients(pw); pw.println("Pending init: " + mPendingInits.size()); pw.println(userPrefix + "Pending init: " + mPendingInits.size()); for (String s : mPendingInits) { pw.println(" " + s); } pw.print("Ancestral: "); pw.print(userPrefix + "Ancestral: "); pw.println(Long.toHexString(mAncestralToken)); pw.print("Current: "); pw.print(userPrefix + "Current: "); pw.println(Long.toHexString(mCurrentToken)); int numPackages = mBackupParticipants.size(); pw.println("Participants:"); pw.println(userPrefix + "Participants:"); for (int i = 0; i < numPackages; i++) { int uid = mBackupParticipants.keyAt(i); pw.print(" uid: "); Loading @@ -3648,7 +3643,7 @@ public class UserBackupManagerService { } } pw.println("Ancestral packages: " pw.println(userPrefix + "Ancestral packages: " + (mAncestralPackages == null ? "none" : mAncestralPackages.size())); if (mAncestralPackages != null) { for (String pkg : mAncestralPackages) { Loading @@ -3657,17 +3652,17 @@ public class UserBackupManagerService { } Set<String> processedPackages = mProcessedPackagesJournal.getPackagesCopy(); pw.println("Ever backed up: " + processedPackages.size()); pw.println(userPrefix + "Ever backed up: " + processedPackages.size()); for (String pkg : processedPackages) { pw.println(" " + pkg); } pw.println("Pending key/value backup: " + mPendingBackups.size()); pw.println(userPrefix + "Pending key/value backup: " + mPendingBackups.size()); for (BackupRequest req : mPendingBackups.values()) { pw.println(" " + req); } pw.println("Full backup queue:" + mFullBackupQueue.size()); pw.println(userPrefix + "Full backup queue:" + mFullBackupQueue.size()); for (FullBackupEntry entry : mFullBackupQueue) { pw.print(" "); pw.print(entry.lastBackup); Loading
services/robotests/backup/src/com/android/server/backup/UserBackupManagerServiceTest.java +40 −1 Original line number Diff line number Diff line Loading @@ -81,7 +81,10 @@ import org.robolectric.shadows.ShadowLooper; import org.robolectric.shadows.ShadowPackageManager; import java.io.File; import java.io.FileDescriptor; import java.io.IOException; import java.io.PrintWriter; import java.io.StringWriter; import java.util.List; /** Loading Loading @@ -1238,13 +1241,49 @@ public class UserBackupManagerServiceTest { assertThat(service.getAncestralSerialNumber()).isEqualTo(testSerialNumber2); } /** * Test that {@link UserBackupManagerService#dump()} for system user does not prefix dump with * "User 0:". */ @Test public void testDump_forSystemUser_DoesNotHaveUserPrefix() throws Exception { mShadowContext.grantPermissions(android.Manifest.permission.BACKUP); UserBackupManagerService service = BackupManagerServiceTestUtils.createUserBackupManagerServiceAndRunTasks( UserHandle.USER_SYSTEM, mContext, mBackupThread, mBaseStateDir, mDataDir, mTransportManager); StringWriter dump = new StringWriter(); service.dump(new FileDescriptor(), new PrintWriter(dump), new String[0]); assertThat(dump.toString()).startsWith("Backup Manager is "); } /** * Test that {@link UserBackupManagerService#dump()} for non-system user prefixes dump with * "User <userid>:". */ @Test public void testDump_forNonSystemUser_HasUserPrefix() throws Exception { mShadowContext.grantPermissions(android.Manifest.permission.BACKUP); UserBackupManagerService service = createUserBackupManagerServiceAndRunTasks(); StringWriter dump = new StringWriter(); service.dump(new FileDescriptor(), new PrintWriter(dump), new String[0]); assertThat(dump.toString()).startsWith("User " + USER_ID + ":" + "Backup Manager is "); } private File createTestFile() throws IOException { File testFile = new File(mContext.getFilesDir(), "test"); testFile.createNewFile(); return testFile; } /** * We can't mock the void method {@link #schedule(Context, long, BackupManagerConstants)} so we * extend {@link ShadowKeyValueBackupJob} and throw an exception at the end of the method. Loading
services/tests/servicestests/src/com/android/server/backup/BackupManagerServiceTest.java +25 −1 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ import static junit.framework.Assert.fail; 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.when; Loading Loading @@ -59,6 +60,7 @@ import org.junit.Before; import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.InOrder; import org.mockito.Mock; import org.mockito.MockitoAnnotations; Loading @@ -83,6 +85,8 @@ public class BackupManagerServiceTest { @Mock private UserBackupManagerService mUserBackupManagerService; @Mock private UserBackupManagerService mNonSystemUserBackupManagerService; @Mock private Context mContextMock; @Mock private PrintWriter mPrintWriterMock; Loading @@ -105,7 +109,7 @@ public class BackupManagerServiceTest { mUserServices = new SparseArray<>(); mUserServices.append(UserHandle.USER_SYSTEM, mUserBackupManagerService); mUserServices.append(NON_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); Loading Loading @@ -512,6 +516,26 @@ public class BackupManagerServiceTest { mService.dump(mFileDescriptorStub, mPrintWriterMock, new String[0]); verifyNoMoreInteractions(mUserBackupManagerService); verifyNoMoreInteractions(mNonSystemUserBackupManagerService); } /** * Test that {@link BackupManagerService#dump()} dumps system user information before non-system * user information. */ @Test public void testDump_systemUserFirst() { String[] args = new String[0]; mService.dumpWithoutCheckingPermission(mFileDescriptorStub, mPrintWriterMock, args); InOrder inOrder = inOrder(mUserBackupManagerService, mNonSystemUserBackupManagerService); inOrder.verify(mUserBackupManagerService) .dump(mFileDescriptorStub, mPrintWriterMock, args); inOrder.verify(mNonSystemUserBackupManagerService) .dump(mFileDescriptorStub, mPrintWriterMock, args); inOrder.verifyNoMoreInteractions(); } @Test Loading