diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java index 79afe8e4de72e..302e3ffa5200c 100644 --- a/services/backup/java/com/android/server/backup/BackupManagerService.java +++ b/services/backup/java/com/android/server/backup/BackupManagerService.java @@ -49,6 +49,7 @@ import android.util.SparseArray; import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.util.DumpUtils; import com.android.server.SystemConfig; import com.android.server.SystemService; @@ -71,6 +72,9 @@ public class BackupManagerService { public static final boolean MORE_DEBUG = false; public static final boolean DEBUG_SCHEDULING = true; + @VisibleForTesting + static final String DUMP_RUNNING_USERS_MESSAGE = "Backup Manager is running for users:"; + // The published binder is a singleton Trampoline object that calls through to the proper code. // This indirection lets us turn down the heavy implementation object on the fly without // disturbing binders that have been cached elsewhere in the system. @@ -849,6 +853,23 @@ public void acknowledgeAdbBackupOrRestore( /** Prints service state for 'dumpsys backup'. */ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { + if (!DumpUtils.checkDumpAndUsageStatsPermission(mContext, TAG, pw)) { + return; + } + + if (args != null) { + for (String arg : args) { + if ("users".equals(arg.toLowerCase())) { + pw.print(DUMP_RUNNING_USERS_MESSAGE); + for (int i = 0; i < mServiceUsers.size(); i++) { + pw.print(" " + mServiceUsers.keyAt(i)); + } + pw.println(); + return; + } + } + } + UserBackupManagerService userBackupManagerService = getServiceForUserIfCallerHasPermission(UserHandle.USER_SYSTEM, "dump()"); diff --git a/services/backup/java/com/android/server/backup/UserBackupManagerService.java b/services/backup/java/com/android/server/backup/UserBackupManagerService.java index 32a814468f128..c0af99c305422 100644 --- a/services/backup/java/com/android/server/backup/UserBackupManagerService.java +++ b/services/backup/java/com/android/server/backup/UserBackupManagerService.java @@ -101,7 +101,6 @@ import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.backup.IBackupTransport; -import com.android.internal.util.DumpUtils; import com.android.internal.util.Preconditions; import com.android.server.AppWidgetBackupBridge; import com.android.server.EventLogTags; @@ -3470,8 +3469,6 @@ public String[] filterAppsEligibleForBackup(String[] packages) { /** Prints service state for 'dumpsys backup'. */ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - if (!DumpUtils.checkDumpAndUsageStatsPermission(mContext, TAG, pw)) return; - long identityToken = Binder.clearCallingIdentity(); try { if (args != null) { @@ -3480,6 +3477,8 @@ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 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)) { dumpAgents(pw); diff --git a/services/robotests/backup/src/com/android/server/backup/BackupManagerServiceTest.java b/services/robotests/backup/src/com/android/server/backup/BackupManagerServiceTest.java index 37909c3022d47..0cb21d0140540 100644 --- a/services/robotests/backup/src/com/android/server/backup/BackupManagerServiceTest.java +++ b/services/robotests/backup/src/com/android/server/backup/BackupManagerServiceTest.java @@ -17,7 +17,9 @@ package com.android.server.backup; import static android.Manifest.permission.BACKUP; +import static android.Manifest.permission.DUMP; import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL; +import static android.Manifest.permission.PACKAGE_USAGE_STATS; import static com.android.server.backup.testing.BackupManagerServiceTestUtils.startBackupThread; import static com.android.server.backup.testing.TransportData.backupTransport; @@ -64,6 +66,7 @@ import java.io.FileDescriptor; import java.io.IOException; import java.io.PrintWriter; +import java.io.StringWriter; /** Tests for the user-aware backup/restore system service {@link BackupManagerService}. */ @RunWith(RobolectricTestRunner.class) @@ -1515,6 +1518,8 @@ public void testAcknowledgeAdbBackupOrRestore_onUnknownUser_doesNotPropagateCall /** Test that the backup service routes methods correctly to the user that requests it. */ @Test public void testDump_onRegisteredUser_callsMethodForUser() throws Exception { + grantDumpPermissions(); + BackupManagerService backupManagerService = createServiceAndRegisterUser(UserHandle.USER_SYSTEM, mUserOneService); File testFile = createTestFile(); @@ -1530,6 +1535,8 @@ public void testDump_onRegisteredUser_callsMethodForUser() throws Exception { /** Test that the backup service does not route methods for non-registered users. */ @Test public void testDump_onUnknownUser_doesNotPropagateCall() throws Exception { + grantDumpPermissions(); + BackupManagerService backupManagerService = createService(); File testFile = createTestFile(); FileDescriptor fileDescriptor = new FileDescriptor(); @@ -1541,6 +1548,31 @@ public void testDump_onUnknownUser_doesNotPropagateCall() throws Exception { verify(mUserOneService, never()).dump(fileDescriptor, printWriter, args); } + /** Test that 'dumpsys backup users' dumps the list of users registered in backup service*/ + @Test + public void testDump_users_dumpsListOfRegisteredUsers() { + grantDumpPermissions(); + + BackupManagerService backupManagerService = createServiceAndRegisterUser(mUserOneId, + mUserOneService); + StringWriter out = new StringWriter(); + PrintWriter writer = new PrintWriter(out); + String[] args = {"users"}; + + backupManagerService.dump(null, writer, args); + + writer.flush(); + assertEquals( + String.format("%s %d\n", BackupManagerService.DUMP_RUNNING_USERS_MESSAGE, + mUserOneId), + out.toString()); + } + + private void grantDumpPermissions() { + mShadowContext.grantPermissions(DUMP); + mShadowContext.grantPermissions(PACKAGE_USAGE_STATS); + } + private File createTestFile() throws IOException { File testFile = new File(mContext.getFilesDir(), "test"); testFile.createNewFile();