• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.android.tradefed.util;
17 
18 import com.android.tradefed.device.DeviceNotAvailableException;
19 import com.android.tradefed.device.ITestDevice;
20 import com.android.tradefed.log.LogUtil.CLog;
21 
22 public class UserUtil {
23     // From the UserInfo class.
24     public static final int FLAG_PRIMARY = 0x00000001;
25     public static final int FLAG_GUEST = 0x00000004;
26     public static final int FLAG_RESTRICTED = 0x00000008;
27     public static final int FLAG_MANAGED_PROFILE = 0x00000020;
28     public static final int USER_SYSTEM = 0;
29 
30     public static final int FLAGS_NOT_SECONDARY =
31             FLAG_PRIMARY | FLAG_MANAGED_PROFILE | FLAG_GUEST | FLAG_RESTRICTED;
32 
33     /** Thrown if a user switch could not happen. */
34     public static class UserSwitchFailedException extends Exception {
UserSwitchFailedException(String message)35         public UserSwitchFailedException(String message) {
36             super(message);
37         }
38     }
39 
40     /** Thrown if a user switch could not happen because the secondary user could not be found. */
41     public static class SecondaryUserNotFoundException extends UserSwitchFailedException {
SecondaryUserNotFoundException()42         public SecondaryUserNotFoundException() {
43             super("Secondary User Not Found");
44         }
45     }
46 
47     /** Parameters that specify which user to run the test module as. */
48     public enum UserType {
49         // TODO:(b/123077733) Add support for guest
50 
51         /** current foreground user of the device */
52         CURRENT,
53         /** user flagged as primary on the device; most often primary = system user = user 0 */
54         PRIMARY,
55         /** system user = user 0 */
56         SYSTEM,
57         /** secondary user, i.e. non-primary and non-system. */
58         SECONDARY,
59     }
60 
61     /**
62      * Attempt to switch to a user type.
63      *
64      * @returns true if successful, false if not.
65      */
switchToUserType(ITestDevice device, UserType userType)66     public static void switchToUserType(ITestDevice device, UserType userType)
67             throws DeviceNotAvailableException, UserSwitchFailedException {
68         switch (userType) {
69             case CURRENT:
70                 return; // do nothing
71             case SYSTEM:
72                 switchUser(device, USER_SYSTEM);
73                 return;
74             case PRIMARY:
75                 switchUser(device, device.getPrimaryUserId());
76                 return;
77             case SECONDARY:
78                 switchToSecondaryUser(device);
79                 return;
80             default:
81                 throw new RuntimeException("userType case not covered: " + userType);
82         }
83     }
84 
85     /**
86      * Attempt to switch to a secondary user, creating one if necessary.
87      *
88      * @returns true if successful, false if not.
89      */
switchToSecondaryUser(ITestDevice device)90     private static void switchToSecondaryUser(ITestDevice device)
91             throws DeviceNotAvailableException, UserSwitchFailedException {
92         int currentUser = device.getCurrentUser();
93         if (device.isUserSecondary(currentUser)) {
94             CLog.d("currentUser is already secondary, no action.");
95             return;
96         }
97 
98         int secondary = findExistingSecondary(device);
99         if (secondary <= 0) {
100             throw new SecondaryUserNotFoundException();
101         }
102 
103         switchUser(device, secondary);
104     }
105 
switchUser(ITestDevice device, int userId)106     private static void switchUser(ITestDevice device, int userId)
107             throws DeviceNotAvailableException, UserSwitchFailedException {
108         if (!device.switchUser(userId)) {
109             throw new UserSwitchFailedException("Failed to switch to user " + userId);
110         }
111     }
112 
113     /**
114      * Finds an arbitrary secondary user and returns the userId.
115      *
116      * <p>TODO: evaluate if a more comprehensive API is needed for this or not.
117      *
118      * @return id of the secondary user or -1 if one could not be found.
119      * @throws DeviceNotAvailableException
120      */
findExistingSecondary(ITestDevice device)121     private static int findExistingSecondary(ITestDevice device)
122             throws DeviceNotAvailableException {
123         for (int userId : device.listUsers()) {
124             if (device.isUserSecondary(userId)) {
125                 return userId;
126             }
127         }
128         // Returns a negative id if we couldn't find a proper existing secondary user.
129         return -1;
130     }
131 }
132