Merge "add option --user to Bmgr.java"
diff --git a/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java b/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java
index a826ec7..3723fce 100644
--- a/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java
+++ b/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java
@@ -17,6 +17,7 @@
 package com.android.commands.bmgr;
 
 import android.annotation.IntDef;
+import android.annotation.UserIdInt;
 import android.app.backup.BackupManager;
 import android.app.backup.BackupManagerMonitor;
 import android.app.backup.BackupProgress;
@@ -29,6 +30,7 @@
 import android.app.backup.ISelectBackupTransportCallback;
 import android.app.backup.RestoreSet;
 import android.content.ComponentName;
+import android.content.Context;
 import android.content.pm.IPackageManager;
 import android.content.pm.PackageInfo;
 import android.os.Bundle;
@@ -37,8 +39,10 @@
 import android.os.SystemClock;
 import android.os.UserHandle;
 import android.util.ArraySet;
+import android.util.Slog;
 
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -49,20 +53,34 @@
 import java.util.Set;
 import java.util.concurrent.CountDownLatch;
 
-public final class Bmgr {
-    IBackupManager mBmgr;
-    IRestoreSession mRestore;
+/**
+ * Adb shell command for {@link android.app.backup.IBackupManager}.
+ */
+public class Bmgr {
+    public static final String TAG = "Bmgr";
 
-    static final String BMGR_NOT_RUNNING_ERR =
+    private final IBackupManager mBmgr;
+    private IRestoreSession mRestore;
+
+    private static final String BMGR_NOT_RUNNING_ERR =
             "Error: Could not access the Backup Manager.  Is the system running?";
-    static final String TRANSPORT_NOT_RUNNING_ERR =
+    private static final String TRANSPORT_NOT_RUNNING_ERR =
             "Error: Could not access the backup transport.  Is the system running?";
-    static final String PM_NOT_RUNNING_ERR =
+    private static final String PM_NOT_RUNNING_ERR =
             "Error: Could not access the Package Manager.  Is the system running?";
 
     private String[] mArgs;
     private int mNextArg;
 
+    @VisibleForTesting
+    Bmgr(IBackupManager bmgr) {
+        mBmgr = bmgr;
+    }
+
+    Bmgr() {
+        mBmgr = IBackupManager.Stub.asInterface(ServiceManager.getService(Context.BACKUP_SERVICE));
+    }
+
     public static void main(String[] args) {
         try {
             new Bmgr().run(args);
@@ -78,71 +96,73 @@
             return;
         }
 
-        if (!isBmgrActive()) {
+        mArgs = args;
+        mNextArg = 0;
+        int userId = parseUserId();
+        String op = nextArg();
+        Slog.v(TAG, "Running " + op + " for user:" + userId);
+
+        if (!isBmgrActive(userId)) {
             return;
         }
 
-        mArgs = args;
-        String op = args[0];
-        mNextArg = 1;
-
         if ("enabled".equals(op)) {
-            doEnabled();
+            doEnabled(userId);
             return;
         }
 
         if ("enable".equals(op)) {
-            doEnable();
+            doEnable(userId);
             return;
         }
 
         if ("run".equals(op)) {
-            doRun();
+            doRun(userId);
             return;
         }
 
         if ("backup".equals(op)) {
-            doBackup();
+            doBackup(userId);
             return;
         }
 
         if ("init".equals(op)) {
-            doInit();
+            doInit(userId);
             return;
         }
 
         if ("list".equals(op)) {
-            doList();
+            doList(userId);
             return;
         }
 
         if ("restore".equals(op)) {
-            doRestore();
+            doRestore(userId);
             return;
         }
 
         if ("transport".equals(op)) {
-            doTransport();
+            doTransport(userId);
             return;
         }
 
         if ("wipe".equals(op)) {
-            doWipe();
+            doWipe(userId);
             return;
         }
 
         if ("fullbackup".equals(op)) {
-            doFullTransportBackup();
+            doFullTransportBackup(userId);
             return;
         }
 
         if ("backupnow".equals(op)) {
-            doBackupNow();
+            doBackupNow(userId);
             return;
         }
 
         if ("cancel".equals(op)) {
-            doCancel();
+            doCancel(userId);
             return;
         }
 
@@ -155,15 +175,14 @@
         showUsage();
     }
 
-    private boolean isBmgrActive() {
-        mBmgr = IBackupManager.Stub.asInterface(ServiceManager.getService("backup"));
+    boolean isBmgrActive(@UserIdInt int userId) {
         if (mBmgr == null) {
             System.err.println(BMGR_NOT_RUNNING_ERR);
             return false;
         }
 
         try {
-            if (!mBmgr.isBackupServiceActive(UserHandle.USER_SYSTEM)) {
+            if (!mBmgr.isBackupServiceActive(userId)) {
                 System.err.println(BMGR_NOT_RUNNING_ERR);
                 return false;
             }
@@ -180,7 +199,7 @@
         return enabled ? "enabled" : "disabled";
     }
 
-    private void doEnabled() {
+    private void doEnabled(@UserIdInt int userId) {
         try {
             boolean isEnabled = mBmgr.isBackupEnabled();
             System.out.println("Backup Manager currently "
@@ -191,7 +210,7 @@
         }
     }
 
-    private void doEnable() {
+    private void doEnable(@UserIdInt int userId) {
         String arg = nextArg();
         if (arg == null) {
             showUsage();
@@ -211,7 +230,7 @@
         }
     }
 
-    private void doRun() {
+    void doRun(@UserIdInt int userId) {
         try {
             mBmgr.backupNow();
         } catch (RemoteException e) {
@@ -220,7 +239,7 @@
         }
     }
 
-    private void doBackup() {
+    private void doBackup(@UserIdInt int userId) {
         String pkg = nextArg();
         if (pkg == null) {
             showUsage();
@@ -235,7 +254,7 @@
         }
     }
 
-    private void doFullTransportBackup() {
+    private void doFullTransportBackup(@UserIdInt int userId) {
         System.out.println("Performing full transport backup");
 
         String pkg;
@@ -354,8 +373,8 @@
         }
     }
 
-    private void backupNowAllPackages(boolean nonIncrementalBackup, @Monitor int monitorState) {
-        int userId = UserHandle.USER_SYSTEM;
+    private void backupNowAllPackages(@UserIdInt int userId, boolean nonIncrementalBackup,
+            @Monitor int monitorState) {
         IPackageManager mPm =
                 IPackageManager.Stub.asInterface(ServiceManager.getService("package"));
         if (mPm == null) {
@@ -379,11 +398,13 @@
                 System.err.println(e.toString());
                 System.err.println(BMGR_NOT_RUNNING_ERR);
             }
-            backupNowPackages(Arrays.asList(filteredPackages), nonIncrementalBackup, monitorState);
+            backupNowPackages(userId, Arrays.asList(filteredPackages), nonIncrementalBackup,
+                    monitorState);
         }
     }
 
     private void backupNowPackages(
+            @UserIdInt int userId,
             List<String> packages, boolean nonIncrementalBackup, @Monitor int monitorState) {
         int flags = 0;
         if (nonIncrementalBackup) {
@@ -412,7 +433,7 @@
         }
     }
 
-    private void doBackupNow() {
+    private void doBackupNow(@UserIdInt int userId) {
         String pkg;
         boolean backupAll = false;
         boolean nonIncrementalBackup = false;
@@ -439,20 +460,20 @@
             if (allPkgs.size() == 0) {
                 System.out.println("Running " + (nonIncrementalBackup ? "non-" : "") +
                         "incremental backup for all packages.");
-                backupNowAllPackages(nonIncrementalBackup, monitor);
+                backupNowAllPackages(userId, nonIncrementalBackup, monitor);
             } else {
                 System.err.println("Provide only '--all' flag or list of packages.");
             }
         } else if (allPkgs.size() > 0) {
             System.out.println("Running " + (nonIncrementalBackup ? "non-" : "") +
                     "incremental backup for " + allPkgs.size() +" requested packages.");
-            backupNowPackages(allPkgs, nonIncrementalBackup, monitor);
+            backupNowPackages(userId, allPkgs, nonIncrementalBackup, monitor);
         } else {
             System.err.println("Provide '--all' flag or list of packages.");
         }
     }
 
-    private void doCancel() {
+    private void doCancel(@UserIdInt int userId) {
         String arg = nextArg();
         if ("backups".equals(arg)) {
             try {
@@ -467,7 +488,7 @@
         System.err.println("Unknown command.");
     }
 
-    private void doTransport() {
+    private void doTransport(@UserIdInt int userId) {
         try {
             String which = nextArg();
             if (which == null) {
@@ -531,7 +552,7 @@
         }
     }
 
-    private void doWipe() {
+    private void doWipe(@UserIdInt int userId) {
         String transport = nextArg();
         if (transport == null) {
             showUsage();
@@ -563,7 +584,7 @@
         }
     }
 
-    private void doInit() {
+    private void doInit(@UserIdInt int userId) {
         ArraySet<String> transports = new ArraySet<>();
         String transport;
         while ((transport = nextArg()) != null) {
@@ -586,7 +607,7 @@
         }
     }
 
-    private void doList() {
+    private void doList(@UserIdInt int userId) {
         String arg = nextArg();     // sets, transports, packages set#
         if ("transports".equals(arg)) {
             doListTransports();
@@ -603,8 +624,6 @@
 
             if ("sets".equals(arg)) {
                 doListRestoreSets();
-            } else if ("transports".equals(arg)) {
-                doListTransports();
             }
 
             mRestore.endRestoreSession();
@@ -717,7 +736,7 @@
         }
     }
 
-    private void doRestore() {
+    private void doRestore(@UserIdInt int userId) {
         String arg = nextArg();
         if (arg == null) {
             showUsage();
@@ -830,8 +849,18 @@
         return arg;
     }
 
+    private int parseUserId() {
+        String arg = nextArg();
+        if ("--user".equals(arg)) {
+            return UserHandle.parseUserArg(nextArg());
+        } else {
+            mNextArg--;
+            return UserHandle.USER_SYSTEM;
+        }
+    }
+
     private static void showUsage() {
-        System.err.println("usage: bmgr [backup|restore|list|transport|run]");
+        System.err.println("usage: bmgr [--user <userId>] [backup|restore|list|transport|run]");
         System.err.println("       bmgr backup PACKAGE");
         System.err.println("       bmgr enable BOOL");
         System.err.println("       bmgr enabled");
@@ -847,6 +876,10 @@
         System.err.println("       bmgr cancel backups");
         System.err.println("       bmgr init TRANSPORT...");
         System.err.println("");
+        System.err.println("The '--user' option specifies the user on which the operation is run.");
+        System.err.println("It must be the first argument before the operation.");
+        System.err.println("The default value is 0 which is the system user.");
+        System.err.println("");
         System.err.println("The 'backup' command schedules a backup pass for the named package.");
         System.err.println("Note that the backup pass will effectively be a no-op if the package");
         System.err.println("does not actually have changed data to store.");
diff --git a/services/robotests/Android.mk b/services/robotests/Android.mk
index 565152c..6f10ed5 100644
--- a/services/robotests/Android.mk
+++ b/services/robotests/Android.mk
@@ -26,6 +26,7 @@
 LOCAL_PRIVILEGED_MODULE := true
 
 LOCAL_STATIC_JAVA_LIBRARIES := \
+    bmgrlib \
     services.backup \
     services.core \
     services.net
diff --git a/services/robotests/src/com/android/commands/bmgr/BmgrTest.java b/services/robotests/src/com/android/commands/bmgr/BmgrTest.java
new file mode 100644
index 0000000..1705f5b
--- /dev/null
+++ b/services/robotests/src/com/android/commands/bmgr/BmgrTest.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.commands.bmgr;
+
+import static org.mockito.Mockito.verify;
+
+import android.app.backup.IBackupManager;
+import android.os.UserHandle;
+import android.platform.test.annotations.Presubmit;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+
+/** Unit tests for {@link com.android.commands.bmgr.Bmgr}. */
+@RunWith(RobolectricTestRunner.class)
+@Presubmit
+public class BmgrTest {
+    @Mock private IBackupManager mBackupManager;
+    private Bmgr mBmgr;
+
+    /** Common setup run before each test method. */
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+        mBmgr = new Bmgr(mBackupManager);
+    }
+
+    /**
+     * Test that bmgr uses the default user {@link UserHandle.USER_SYSTEM} if no user is specified.
+     */
+    @Test
+    public void testRun_whenUserNotSpecified_callsBackupManagerAsSystemUser() throws Exception {
+        mBmgr.run(new String[] {"run"});
+
+        verify(mBackupManager).isBackupServiceActive(UserHandle.USER_SYSTEM);
+    }
+
+    /** Test that bmgr uses the specified user if an user is specified. */
+    @Test
+    public void testRun_whenUserSpecified_callsBackupManagerAsSpecifiedUser() throws Exception {
+        mBmgr.run(new String[] {"--user", "10"});
+
+        verify(mBackupManager).isBackupServiceActive(10);
+    }
+}