| // Copyright 2016 The Vanadium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| package main |
| |
| import ( |
| "fmt" |
| "os" |
| "path/filepath" |
| "strconv" |
| |
| "v.io/x/lib/cmdline" |
| ) |
| |
| // TODO(youngseokyoon): add a helper command that wraps "madb exec shell pm list users" to show all available users. |
| var cmdMadbUser = &cmdline.Command{ |
| Children: []*cmdline.Command{cmdMadbUserSet, cmdMadbUserUnset, cmdMadbUserList, cmdMadbUserClearAll}, |
| Name: "user", |
| DontInheritFlags: true, |
| Short: "Manage default user settings for each device", |
| Long: ` |
| Manages default user settings for each device. |
| |
| An Android device can have multiple user accounts, and each user account has a numeric ID associated |
| with it. Certain adb commands accept '--user <user_id>' as a parameter to allow specifying which of |
| the Android user account should be used when running the command. The default behavior when the |
| user ID is not provided varies by the adb command being run. |
| |
| Some madb commands internally run these adb commands which accept the '--user' flag. You can let |
| madb use different user IDs for different devices by storing the default user ID for each device |
| using 'madb user set' command. If the default user ID is not set for a particular device, madb will |
| not provide the '--user' flag to the underlying adb command, and the current user will be used for |
| that device as a result. |
| |
| Below is the list of madb commands which are affected by the default user ID settings: |
| |
| madb clear-data |
| madb install |
| madb start |
| madb stop |
| madb uninstall |
| |
| For more details on how to obtain the user ID from an Android device, see 'madb user help set'. |
| `, |
| } |
| |
| var cmdMadbUserSet = &cmdline.Command{ |
| Runner: subCommandRunnerWithFilepath{runMadbUserSet, getDefaultUserFilePath}, |
| Name: "set", |
| Short: "Set a default user ID to be used for the given device.", |
| Long: ` |
| Sets a default user ID to be used for the specified device, when there are multiple user accounts on |
| a single device. |
| |
| The user IDs can be obtained using the 'adb [<device_serial>] shell pm list users' command. |
| Alternatively, you can use 'madb exec' if you want to specify the device with a nickname. |
| For example, running the following command: |
| |
| madb -n=MyPhone exec shell pm list users |
| |
| will list the available users and their IDs on the MyPhone device. |
| Consider the following example output: |
| |
| [MyPhone] Users: |
| [MyPhone] UserInfo{0:John Doe:13} running |
| [MyPhone] UserInfo{10:Work profile:30} running |
| |
| There are two available users, "John Doe" and "Work profile". Each user is assigned a "user ID", |
| which appears on the left of the user name. In this case, the user ID of "John Doe" is "0", and the |
| user ID of the "Work profile" is "10". |
| |
| To use the "Work profile" as the default user when running madb commands on this device, run the |
| following command: |
| |
| madb user set MyPhone 10 |
| |
| and then madb will use "Work profile" as the default user for device "MyPhone" in any of the |
| subsequence madb commands. |
| `, |
| ArgsName: "<device_serial> <user_id>", |
| ArgsLong: ` |
| <device_serial> is the unique serial number for the device, which can be obtained from 'adb devices'. |
| <user_id> is one of the user IDs obtained from 'adb shell pm list users' command. |
| `, |
| } |
| |
| func runMadbUserSet(env *cmdline.Env, args []string, filename string) error { |
| // Check if the arguments are valid. |
| if len(args) != 2 { |
| return fmt.Errorf("There must be exactly two arguments.") |
| } |
| |
| // TODO(youngseokyoon): make it possible to specify the device using its nickname or index. |
| // Validate the device serial |
| serial := args[0] |
| if !isValidDeviceSerial(serial) { |
| return fmt.Errorf("Not a valid device serial: %v", serial) |
| } |
| |
| // Validate the user ID. |
| userID := args[1] |
| if id, err := strconv.Atoi(userID); err != nil || id < 0 { |
| return fmt.Errorf("Not a valid user ID: %v", userID) |
| } |
| |
| // Get the <device_serial, user_id> mapping. |
| serialUserMap, err := readMapFromFile(filename) |
| if err != nil { |
| return err |
| } |
| |
| // Add the <device_serial, user_id> mapping for the specified device. |
| serialUserMap[serial] = userID |
| return writeMapToFile(serialUserMap, filename) |
| } |
| |
| var cmdMadbUserUnset = &cmdline.Command{ |
| Runner: subCommandRunnerWithFilepath{runMadbUserUnset, getDefaultUserFilePath}, |
| Name: "unset", |
| Short: "Unset the default user ID set by the 'madb user set' command.", |
| Long: ` |
| Unsets the default user ID assigned by the 'madb user set' command for the specified device. |
| |
| Running this command without any device specifiers will unset the default users only for the |
| currently available devices and emulators, while keeping the default user IDs for the other devices. |
| `, |
| ArgsName: "<device_serial>", |
| ArgsLong: ` |
| <device_serial> is the unique serial number for the device, which can be obtained from 'adb devices'. |
| `, |
| } |
| |
| func runMadbUserUnset(env *cmdline.Env, args []string, filename string) error { |
| // Check if the arguments are valid. |
| if len(args) != 1 { |
| return fmt.Errorf("There must be exactly one argument.") |
| } |
| |
| // TODO(youngseokyoon): make it possible to specify the device using its nickname or index. |
| // Validate the device serial |
| serial := args[0] |
| if !isValidDeviceSerial(serial) { |
| return fmt.Errorf("Not a valid device serial: %v", serial) |
| } |
| |
| // Get the <device_serial, user_id> mapping. |
| serialUserMap, err := readMapFromFile(filename) |
| if err != nil { |
| return err |
| } |
| |
| // Delete the <device_serial, user_id> mapping for the specified device. |
| delete(serialUserMap, serial) |
| return writeMapToFile(serialUserMap, filename) |
| } |
| |
| var cmdMadbUserList = &cmdline.Command{ |
| Runner: subCommandRunnerWithFilepath{runMadbUserList, getDefaultUserFilePath}, |
| Name: "list", |
| Short: "List all the existing default user IDs.", |
| Long: ` |
| Lists all the currently stored default user IDs for devices. |
| `, |
| } |
| |
| func runMadbUserList(env *cmdline.Env, args []string, filename string) error { |
| // Get the <device_serial, user_id> mapping. |
| serialUserMap, err := readMapFromFile(filename) |
| if err != nil { |
| return err |
| } |
| |
| // TODO(youngseokyoon): pretty print this. |
| fmt.Println("Device Serial User ID") |
| fmt.Println("========================") |
| |
| for s, u := range serialUserMap { |
| fmt.Printf("%v\t%v\n", s, u) |
| } |
| |
| return nil |
| } |
| |
| var cmdMadbUserClearAll = &cmdline.Command{ |
| Runner: subCommandRunnerWithFilepath{runMadbUserClearAll, getDefaultUserFilePath}, |
| Name: "clear-all", |
| Short: "Clear all the existing default user settings.", |
| Long: ` |
| Clears all the currently stored default user IDs for devices. |
| |
| This command clears the default user IDs regardless of whether the device is currently connected or not. |
| `, |
| } |
| |
| func runMadbUserClearAll(env *cmdline.Env, args []string, filename string) error { |
| return os.Remove(filename) |
| } |
| |
| func getDefaultUserFilePath() (string, error) { |
| configDir, err := getConfigDir() |
| if err != nil { |
| return "", err |
| } |
| |
| return filepath.Join(configDir, "users"), nil |
| } |