1 /* 2 * Copyright (C) 2018 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 17 package com.android.car; 18 19 import static com.google.common.truth.Truth.assertThat; 20 21 import static org.mockito.Mockito.verify; 22 import static org.mockito.Mockito.when; 23 24 import android.app.ActivityManager; 25 import android.car.user.CarUserManagerHelper; 26 import android.content.BroadcastReceiver; 27 import android.content.Context; 28 import android.content.Intent; 29 import android.content.IntentFilter; 30 import android.content.pm.UserInfo; 31 import android.graphics.Bitmap; 32 import android.graphics.drawable.Drawable; 33 import android.os.Handler; 34 import android.os.SystemProperties; 35 import android.os.UserHandle; 36 import android.os.UserManager; 37 import android.support.test.InstrumentationRegistry; 38 import android.support.test.runner.AndroidJUnit4; 39 40 import org.junit.Before; 41 import org.junit.Test; 42 import org.junit.runner.RunWith; 43 import org.mockito.ArgumentCaptor; 44 import org.mockito.Mock; 45 import org.mockito.MockitoAnnotations; 46 47 import java.util.ArrayList; 48 import java.util.List; 49 50 /** 51 * This class contains unit tests for the {@link CarUserManagerHelper}. 52 * It tests that {@link CarUserManagerHelper} does the right thing for user management flows. 53 * 54 * The following mocks are used: 55 * 1. {@link Context} provides system services and resources. 56 * 2. {@link UserManager} provides dummy users and user info. 57 * 3. {@link ActivityManager} provides dummy current process user. 58 * 4. {@link CarUserManagerHelper.OnUsersUpdateListener} registers a listener for user updates. 59 */ 60 @RunWith(AndroidJUnit4.class) 61 public class CarUserManagerHelperTest { 62 @Mock 63 private Context mContext; 64 @Mock 65 private UserManager mUserManager; 66 @Mock 67 private ActivityManager mActivityManager; 68 @Mock 69 private CarUserManagerHelper.OnUsersUpdateListener mTestListener; 70 71 private CarUserManagerHelper mHelper; 72 private UserInfo mCurrentProcessUser; 73 private UserInfo mSystemUser; 74 private String mGuestUserName = "testGuest"; 75 private String mTestUserName = "testUser"; 76 77 @Before 78 public void setUpMocksAndVariables() throws Exception { 79 MockitoAnnotations.initMocks(this); 80 when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager); 81 when(mContext.getSystemService(Context.ACTIVITY_SERVICE)).thenReturn(mActivityManager); 82 when(mContext.getResources()) 83 .thenReturn(InstrumentationRegistry.getTargetContext().getResources()); 84 when(mContext.getApplicationContext()).thenReturn(mContext); 85 mHelper = new CarUserManagerHelper(mContext); 86 87 mCurrentProcessUser = createUserInfoForId(UserHandle.myUserId()); 88 mSystemUser = createUserInfoForId(UserHandle.USER_SYSTEM); 89 when(mUserManager.getUserInfo(UserHandle.myUserId())).thenReturn(mCurrentProcessUser); 90 } 91 92 @Test 93 public void checkIsSystemUser() { 94 UserInfo testInfo = new UserInfo(); 95 96 testInfo.id = UserHandle.USER_SYSTEM; 97 assertThat(mHelper.isSystemUser(testInfo)).isTrue(); 98 99 testInfo.id = UserHandle.USER_SYSTEM + 2; // Make it different than system id. 100 assertThat(mHelper.isSystemUser(testInfo)).isFalse(); 101 } 102 103 // System user will not be returned when calling get all users. 104 @Test 105 public void testHeadlessUser0GetAllUsers_NotReturnSystemUser() { 106 SystemProperties.set("android.car.systemuser.headless", "true"); 107 UserInfo otherUser1 = createUserInfoForId(10); 108 UserInfo otherUser2 = createUserInfoForId(11); 109 UserInfo otherUser3 = createUserInfoForId(12); 110 111 List<UserInfo> testUsers = new ArrayList<>(); 112 testUsers.add(mSystemUser); 113 testUsers.add(otherUser1); 114 testUsers.add(otherUser2); 115 testUsers.add(otherUser3); 116 117 when(mUserManager.getUsers(true)).thenReturn(testUsers); 118 119 // Should return 3 users that don't have SYSTEM USER id. 120 assertThat(mHelper.getAllUsers()).hasSize(3); 121 assertThat(mHelper.getAllUsers()) 122 .containsExactly(otherUser1, otherUser2, otherUser3); 123 } 124 125 @Test 126 public void testHeadlessUser0GetAllUsersWithActiveForegroundUser_NotReturnSystemUser() { 127 SystemProperties.set("android.car.systemuser.headless", "true"); 128 mCurrentProcessUser = createUserInfoForId(10); 129 130 UserInfo otherUser1 = createUserInfoForId(11); 131 UserInfo otherUser2 = createUserInfoForId(12); 132 UserInfo otherUser3 = createUserInfoForId(13); 133 134 List<UserInfo> testUsers = new ArrayList<>(); 135 testUsers.add(mSystemUser); 136 testUsers.add(mCurrentProcessUser); 137 testUsers.add(otherUser1); 138 testUsers.add(otherUser2); 139 testUsers.add(otherUser3); 140 141 when(mUserManager.getUsers(true)).thenReturn(testUsers); 142 143 assertThat(mHelper.getAllUsers().size()).isEqualTo(4); 144 assertThat(mHelper.getAllUsers()) 145 .containsExactly(mCurrentProcessUser, otherUser1, otherUser2, otherUser3); 146 } 147 148 @Test 149 public void testGetAllSwitchableUsers() { 150 UserInfo user1 = createUserInfoForId(10); 151 UserInfo user2 = createUserInfoForId(11); 152 UserInfo user3 = createUserInfoForId(12); 153 154 List<UserInfo> testUsers = new ArrayList<>(); 155 testUsers.add(mSystemUser); 156 testUsers.add(user1); 157 testUsers.add(user2); 158 testUsers.add(user3); 159 160 when(mUserManager.getUsers(true)).thenReturn(new ArrayList<>(testUsers)); 161 162 // Should return all 3 non-system users. 163 assertThat(mHelper.getAllUsers().size()) 164 .isEqualTo(3); 165 166 when(mUserManager.getUserInfo(UserHandle.myUserId())).thenReturn(user1); 167 // Should return user 10, 11 and 12. 168 assertThat(mHelper.getAllSwitchableUsers().size()) 169 .isEqualTo(3); 170 assertThat(mHelper.getAllSwitchableUsers()).contains(user1); 171 assertThat(mHelper.getAllSwitchableUsers()).contains(user2); 172 assertThat(mHelper.getAllSwitchableUsers()).contains(user3); 173 } 174 175 // Get all users for headless user 0 model should exclude system user by default. 176 @Test 177 public void testHeadlessUser0GetAllSwitchableUsers() { 178 SystemProperties.set("android.car.systemuser.headless", "true"); 179 UserInfo user1 = createUserInfoForId(10); 180 UserInfo user2 = createUserInfoForId(11); 181 UserInfo user3 = createUserInfoForId(12); 182 183 List<UserInfo> testUsers = new ArrayList<>(); 184 testUsers.add(mSystemUser); 185 testUsers.add(user1); 186 testUsers.add(user2); 187 testUsers.add(user3); 188 189 when(mUserManager.getUsers(true)).thenReturn(new ArrayList<>(testUsers)); 190 191 // Should return all 3 non-system users. 192 assertThat(mHelper.getAllUsers()).hasSize(3); 193 194 when(mUserManager.getUserInfo(UserHandle.myUserId())).thenReturn(user1); 195 // Should return user 10, 11 and 12. 196 assertThat(mHelper.getAllSwitchableUsers()).containsExactly(user1, user2, user3); 197 } 198 199 @Test 200 public void testUserCanBeRemoved() { 201 UserInfo testInfo = new UserInfo(); 202 203 // System user cannot be removed. 204 testInfo.id = UserHandle.USER_SYSTEM; 205 assertThat(mHelper.canUserBeRemoved(testInfo)).isFalse(); 206 207 testInfo.id = UserHandle.USER_SYSTEM + 2; // Make it different than system id. 208 assertThat(mHelper.canUserBeRemoved(testInfo)).isTrue(); 209 } 210 211 @Test 212 public void testCurrentProcessCanAddUsers() { 213 when(mUserManager.hasUserRestriction(UserManager.DISALLOW_ADD_USER)).thenReturn(false); 214 assertThat(mHelper.canCurrentProcessAddUsers()).isTrue(); 215 216 when(mUserManager.hasUserRestriction(UserManager.DISALLOW_ADD_USER)).thenReturn(true); 217 assertThat(mHelper.canCurrentProcessAddUsers()).isFalse(); 218 } 219 220 @Test 221 public void testCurrentProcessCanRemoveUsers() { 222 when(mUserManager.hasUserRestriction(UserManager.DISALLOW_REMOVE_USER)).thenReturn(false); 223 assertThat(mHelper.canCurrentProcessRemoveUsers()).isTrue(); 224 225 when(mUserManager.hasUserRestriction(UserManager.DISALLOW_REMOVE_USER)).thenReturn(true); 226 assertThat(mHelper.canCurrentProcessRemoveUsers()).isFalse(); 227 } 228 229 @Test 230 public void testCurrentProcessCanSwitchUsers() { 231 when(mUserManager.hasUserRestriction(UserManager.DISALLOW_USER_SWITCH)).thenReturn(false); 232 assertThat(mHelper.canCurrentProcessSwitchUsers()).isTrue(); 233 234 when(mUserManager.hasUserRestriction(UserManager.DISALLOW_USER_SWITCH)).thenReturn(true); 235 assertThat(mHelper.canCurrentProcessSwitchUsers()).isFalse(); 236 } 237 238 @Test 239 public void testCurrentGuestProcessCannotModifyAccounts() { 240 assertThat(mHelper.canCurrentProcessModifyAccounts()).isTrue(); 241 242 when(mUserManager.isGuestUser()).thenReturn(true); 243 assertThat(mHelper.canCurrentProcessModifyAccounts()).isFalse(); 244 } 245 246 @Test 247 public void testCurrentDemoProcessCannotModifyAccounts() { 248 assertThat(mHelper.canCurrentProcessModifyAccounts()).isTrue(); 249 250 when(mUserManager.isDemoUser()).thenReturn(true); 251 assertThat(mHelper.canCurrentProcessModifyAccounts()).isFalse(); 252 } 253 254 @Test 255 public void testCurrentDisallowModifyAccountsProcessIsEnforced() { 256 assertThat(mHelper.canCurrentProcessModifyAccounts()).isTrue(); 257 258 when(mUserManager.hasUserRestriction(UserManager.DISALLOW_MODIFY_ACCOUNTS)) 259 .thenReturn(true); 260 assertThat(mHelper.canCurrentProcessModifyAccounts()).isFalse(); 261 } 262 263 @Test 264 public void testCreateNewAdminUser() { 265 // Verify createUser on UserManager gets called. 266 mHelper.createNewAdminUser(mTestUserName); 267 verify(mUserManager).createUser(mTestUserName, UserInfo.FLAG_ADMIN); 268 269 when(mUserManager.createUser(mTestUserName, UserInfo.FLAG_ADMIN)).thenReturn(null); 270 assertThat(mHelper.createNewAdminUser(mTestUserName)).isNull(); 271 272 UserInfo newUser = new UserInfo(); 273 newUser.name = mTestUserName; 274 when(mUserManager.createUser(mTestUserName, UserInfo.FLAG_ADMIN)).thenReturn(newUser); 275 assertThat(mHelper.createNewAdminUser(mTestUserName)).isEqualTo(newUser); 276 } 277 278 @Test 279 public void testCreateNewNonAdminUser() { 280 // Verify createUser on UserManager gets called. 281 mHelper.createNewNonAdminUser(mTestUserName); 282 verify(mUserManager).createUser(mTestUserName, 0); 283 284 when(mUserManager.createUser(mTestUserName, 0)).thenReturn(null); 285 assertThat(mHelper.createNewNonAdminUser(mTestUserName)).isNull(); 286 287 UserInfo newUser = new UserInfo(); 288 newUser.name = mTestUserName; 289 when(mUserManager.createUser(mTestUserName, 0)).thenReturn(newUser); 290 assertThat(mHelper.createNewNonAdminUser(mTestUserName)).isEqualTo(newUser); 291 } 292 293 @Test 294 public void testRemoveUser() { 295 // Cannot remove system user. 296 assertThat(mHelper.removeUser(mSystemUser, mGuestUserName)).isFalse(); 297 298 // Removing non-current, non-system user, simply calls removeUser. 299 UserInfo userToRemove = createUserInfoForId(mCurrentProcessUser.id + 2); 300 301 mHelper.removeUser(userToRemove, mGuestUserName); 302 verify(mUserManager).removeUser(mCurrentProcessUser.id + 2); 303 } 304 305 @Test 306 public void testSwitchToGuest() { 307 mHelper.startNewGuestSession(mGuestUserName); 308 verify(mUserManager).createGuest(mContext, mGuestUserName); 309 310 UserInfo guestInfo = new UserInfo(21, mGuestUserName, UserInfo.FLAG_GUEST); 311 when(mUserManager.createGuest(mContext, mGuestUserName)).thenReturn(guestInfo); 312 mHelper.startNewGuestSession(mGuestUserName); 313 verify(mActivityManager).switchUser(21); 314 } 315 316 @Test 317 public void testGetUserIcon() { 318 mHelper.getUserIcon(mCurrentProcessUser); 319 verify(mUserManager).getUserIcon(mCurrentProcessUser.id); 320 } 321 322 @Test 323 public void testScaleUserIcon() { 324 Bitmap fakeIcon = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888); 325 Drawable scaledIcon = mHelper.scaleUserIcon(fakeIcon, 300); 326 assertThat(scaledIcon.getIntrinsicWidth()).isEqualTo(300); 327 assertThat(scaledIcon.getIntrinsicHeight()).isEqualTo(300); 328 } 329 330 @Test 331 public void testSetUserName() { 332 UserInfo testInfo = createUserInfoForId(mCurrentProcessUser.id + 3); 333 String newName = "New Test Name"; 334 mHelper.setUserName(testInfo, newName); 335 verify(mUserManager).setUserName(mCurrentProcessUser.id + 3, newName); 336 } 337 338 @Test 339 public void testRegisterUserChangeReceiver() { 340 mHelper.registerOnUsersUpdateListener(mTestListener); 341 342 ArgumentCaptor<BroadcastReceiver> receiverCaptor = 343 ArgumentCaptor.forClass(BroadcastReceiver.class); 344 ArgumentCaptor<UserHandle> handleCaptor = ArgumentCaptor.forClass(UserHandle.class); 345 ArgumentCaptor<IntentFilter> filterCaptor = ArgumentCaptor.forClass(IntentFilter.class); 346 ArgumentCaptor<String> permissionCaptor = ArgumentCaptor.forClass(String.class); 347 ArgumentCaptor<Handler> handlerCaptor = ArgumentCaptor.forClass(Handler.class); 348 349 verify(mContext).registerReceiverAsUser( 350 receiverCaptor.capture(), 351 handleCaptor.capture(), 352 filterCaptor.capture(), 353 permissionCaptor.capture(), 354 handlerCaptor.capture()); 355 356 // Verify we're listening to Intents from ALL users. 357 assertThat(handleCaptor.getValue()).isEqualTo(UserHandle.ALL); 358 359 // Verify the presence of each intent in the filter. 360 // Verify the exact number of filters. Every time a new intent is added, this test should 361 // get updated. 362 assertThat(filterCaptor.getValue().countActions()).isEqualTo(6); 363 assertThat(filterCaptor.getValue().hasAction(Intent.ACTION_USER_REMOVED)).isTrue(); 364 assertThat(filterCaptor.getValue().hasAction(Intent.ACTION_USER_ADDED)).isTrue(); 365 assertThat(filterCaptor.getValue().hasAction(Intent.ACTION_USER_INFO_CHANGED)).isTrue(); 366 assertThat(filterCaptor.getValue().hasAction(Intent.ACTION_USER_SWITCHED)).isTrue(); 367 assertThat(filterCaptor.getValue().hasAction(Intent.ACTION_USER_STOPPED)).isTrue(); 368 assertThat(filterCaptor.getValue().hasAction(Intent.ACTION_USER_UNLOCKED)).isTrue(); 369 370 // Verify that calling the receiver calls the listener. 371 receiverCaptor.getValue().onReceive(mContext, new Intent()); 372 verify(mTestListener).onUsersUpdate(); 373 374 assertThat(permissionCaptor.getValue()).isNull(); 375 assertThat(handlerCaptor.getValue()).isNull(); 376 377 // Unregister the receiver. 378 mHelper.unregisterOnUsersUpdateListener(); 379 verify(mContext).unregisterReceiver(receiverCaptor.getValue()); 380 } 381 382 private UserInfo createUserInfoForId(int id) { 383 UserInfo userInfo = new UserInfo(); 384 userInfo.id = id; 385 return userInfo; 386 } 387 } 388