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