1 /* 2 * Copyright (C) 2016 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 android.host.accounts; 17 18 import static org.junit.Assert.fail; 19 20 import com.android.tradefed.device.CollectingOutputReceiver; 21 import com.android.tradefed.device.DeviceNotAvailableException; 22 import com.android.tradefed.device.ITestDevice; 23 import com.android.tradefed.log.LogUtil.CLog; 24 import com.android.tradefed.testtype.IDeviceTest; 25 26 import org.junit.After; 27 import org.junit.Before; 28 29 import java.io.IOException; 30 import java.util.ArrayList; 31 import java.util.concurrent.TimeUnit; 32 33 /** 34 * Base class for multi user tests. 35 */ 36 public class BaseMultiUserTest implements IDeviceTest { 37 38 /** Guest flag value from android/content/pm/UserInfo.java */ 39 private static final int FLAG_GUEST = 0x00000004; 40 41 /** 42 * Feature flag for automotive devices 43 * https://source.android.com/compatibility/android-cdd#2_5_automotive_requirements 44 */ 45 private static final String FEATURE_AUTOMOTIVE = "feature:android.hardware.type.automotive"; 46 private static final String FEATURE_MANAGED_USERS = "android.software.managed_users"; 47 48 /** Whether multi-user is supported. */ 49 protected boolean mSupportsMultiUser; 50 protected boolean mSupportsManagedUsers; 51 protected int mInitialUserId; 52 protected int mPrimaryUserId; 53 54 /** Users we shouldn't delete in the tests. */ 55 private ArrayList<Integer> mFixedUsers; 56 57 private ITestDevice mDevice; 58 59 @Before setUp()60 public void setUp() throws Exception { 61 mSupportsMultiUser = getDevice().getMaxNumberOfUsersSupported() > 1; 62 mSupportsManagedUsers = getDevice().hasFeature(FEATURE_MANAGED_USERS); 63 64 mInitialUserId = getDevice().getCurrentUser(); 65 mPrimaryUserId = getDevice().getPrimaryUserId(); 66 67 // Test should not modify / remove any of the existing users. 68 mFixedUsers = getDevice().listUsers(); 69 } 70 71 @After tearDown()72 public void tearDown() throws Exception { 73 if (getDevice().getCurrentUser() != mInitialUserId) { 74 CLog.w("User changed during test. Switching back to " + mInitialUserId); 75 getDevice().switchUser(mInitialUserId); 76 } 77 // Remove the users created during this test. 78 removeTestUsers(); 79 } 80 81 @Override setDevice(ITestDevice device)82 public void setDevice(ITestDevice device) { 83 mDevice = device; 84 } 85 86 @Override getDevice()87 public ITestDevice getDevice() { 88 return mDevice; 89 } 90 91 /** 92 * @param userId the userId of the parent for this profile 93 * @return the userId of the created user 94 */ createRestrictedProfile(int userId)95 protected int createRestrictedProfile(int userId) 96 throws DeviceNotAvailableException, IllegalStateException { 97 return createUser("--profileOf " + userId + " --restricted"); 98 } 99 100 /** 101 * @param userId the userId of the parent for this profile 102 * @return the userId of the created user 103 */ createProfile(int userId)104 protected int createProfile(int userId) 105 throws DeviceNotAvailableException, IllegalStateException { 106 return createUser("--profileOf " + userId + " --managed"); 107 } 108 109 /** 110 * @return the userid of the created user 111 */ createUser()112 protected int createUser() 113 throws DeviceNotAvailableException, IllegalStateException { 114 return createUser(""); 115 } 116 createUser(String extraParam)117 private int createUser(String extraParam) 118 throws DeviceNotAvailableException, IllegalStateException { 119 final String command = 120 "pm create-user " + extraParam + " TestUser_" + System.currentTimeMillis(); 121 CLog.d("Starting command: " + command); 122 final String output = getDevice().executeShellCommand(command); 123 CLog.d("Output for command " + command + ": " + output); 124 125 if (output.startsWith("Success")) { 126 try { 127 return Integer.parseInt(output.substring(output.lastIndexOf(" ")).trim()); 128 } catch (NumberFormatException e) { 129 throw new IllegalStateException("Failed to parse result: " + output); 130 } 131 } 132 133 throw new IllegalStateException("Failed to create user: " + output); 134 } 135 createGuestUser()136 protected int createGuestUser() throws Exception { 137 return mDevice.createUser( 138 "TestUser_" + System.currentTimeMillis() /* name */, 139 true /* guest */, 140 false /* ephemeral */); 141 } 142 getGuestUser()143 protected int getGuestUser() throws Exception { 144 for (int userId : mDevice.listUsers()) { 145 if ((mDevice.getUserFlags(userId) & FLAG_GUEST) != 0) { 146 return userId; 147 } 148 } 149 return -1; 150 } 151 isAutomotiveDevice()152 protected boolean isAutomotiveDevice() throws Exception { 153 return getDevice().hasFeature(FEATURE_AUTOMOTIVE); 154 } 155 removeTestUsers()156 private void removeTestUsers() throws Exception { 157 for (int userId : getDevice().listUsers()) { 158 if (!mFixedUsers.contains(userId)) { 159 getDevice().removeUser(userId); 160 } 161 } 162 } 163 waitForBroadcastIdle()164 protected void waitForBroadcastIdle() throws DeviceNotAvailableException, IOException { 165 final CollectingOutputReceiver receiver = new CollectingOutputReceiver(); 166 // We allow 8min for the command to complete and 4min for the command to start to 167 // output something. 168 getDevice().executeShellCommand( 169 "am wait-for-broadcast-idle", receiver, 8, 4, TimeUnit.MINUTES, 0); 170 final String output = receiver.getOutput(); 171 if (!output.contains("All broadcast queues are idle!")) { 172 CLog.e("Output from 'am wait-for-broadcast-idle': %s", output); 173 fail("'am wait-for-broadcase-idle' did not complete."); 174 } 175 } 176 } 177