1 /* 2 * Copyright (C) 2020 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.car.test.mocks; 17 18 import static android.car.test.mocks.CarArgumentMatchers.isUserHandle; 19 20 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; 21 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doThrow; 22 23 import static com.google.common.truth.Truth.assertWithMessage; 24 25 import static org.mockito.ArgumentMatchers.anyString; 26 import static org.mockito.ArgumentMatchers.argThat; 27 import static org.mockito.Mockito.when; 28 29 import android.annotation.NonNull; 30 import android.annotation.Nullable; 31 import android.annotation.UserIdInt; 32 import android.app.Activity; 33 import android.app.ActivityManager; 34 import android.app.admin.DevicePolicyManager; 35 import android.car.Car; 36 import android.car.CarVersion; 37 import android.car.PlatformVersion; 38 import android.car.builtin.app.ActivityManagerHelper; 39 import android.car.builtin.os.UserManagerHelper; 40 import android.car.test.util.UserTestingHelper; 41 import android.car.test.util.Visitor; 42 import android.content.Context; 43 import android.content.pm.PackageManager; 44 import android.content.pm.PackageManager.PermissionResult; 45 import android.content.pm.UserInfo; 46 import android.content.pm.UserInfo.UserInfoFlag; 47 import android.os.Binder; 48 import android.os.Handler; 49 import android.os.IBinder; 50 import android.os.IInterface; 51 import android.os.Looper; 52 import android.os.NewUserRequest; 53 import android.os.NewUserResponse; 54 import android.os.ServiceManager; 55 import android.os.UserHandle; 56 import android.os.UserManager; 57 import android.os.UserManager.RemoveResult; 58 import android.os.UserManager.UserSwitchabilityResult; 59 import android.util.Log; 60 61 import org.mockito.ArgumentMatcher; 62 63 import java.util.Arrays; 64 import java.util.List; 65 import java.util.Objects; 66 import java.util.Set; 67 import java.util.concurrent.Callable; 68 import java.util.concurrent.CountDownLatch; 69 import java.util.concurrent.atomic.AtomicReference; 70 import java.util.stream.Collectors; 71 72 /** 73 * Provides common Mockito calls for core Android classes. 74 */ 75 public final class AndroidMockitoHelper { 76 77 private static final String TAG = AndroidMockitoHelper.class.getSimpleName(); 78 79 /** 80 * Mocks a call to {@link ActivityManager#getCurrentUser()}. 81 * 82 * <p><b>Note: </b>it must be made inside a 83 * {@link com.android.dx.mockito.inline.extended.StaticMockitoSession} built with 84 * {@code spyStatic(ActivityManager.class)}. 85 * 86 * @param userId result of such call 87 */ mockAmGetCurrentUser(@serIdInt int userId)88 public static void mockAmGetCurrentUser(@UserIdInt int userId) { 89 doReturn(userId).when(() -> ActivityManager.getCurrentUser()); 90 } 91 92 /** 93 * Mocks a call to {@link ActivityManager#switchUser(UserHandle)}. 94 */ mockAmSwitchUser(ActivityManager am, UserHandle user, boolean result)95 public static void mockAmSwitchUser(ActivityManager am, UserHandle user, 96 boolean result) { 97 when(am.switchUser(user)).thenReturn(result); 98 } 99 100 /** 101 * Mocks a call to {@link ActivityManagerHelper#startUserInBackground(int)}. 102 * 103 * * <p><b>Note: </b>it must be made inside a 104 * * {@link com.android.dx.mockito.inline.extended.StaticMockitoSession} built with 105 * * {@code spyStatic(ActivityManagerHelper.class)}. 106 */ mockAmStartUserInBackground(@serIdInt int userId, boolean result)107 public static void mockAmStartUserInBackground(@UserIdInt int userId, boolean result) 108 throws Exception { 109 doReturn(result).when(() -> ActivityManagerHelper.startUserInBackground(userId)); 110 } 111 112 /** 113 * Mocks a call to {@link ActivityManagerHelper#startUserInBackgroundVisibleOnDisplay(int, int)} 114 * 115 * * <p><b>Note: </b>it must be made inside a 116 * * {@link com.android.dx.mockito.inline.extended.StaticMockitoSession} built with 117 * * {@code spyStatic(ActivityManagerHelper.class)}. 118 */ mockAmStartUserInBackgroundVisibleOnDisplay( @serIdInt int userId, int displayId, boolean result)119 public static void mockAmStartUserInBackgroundVisibleOnDisplay( 120 @UserIdInt int userId, int displayId, boolean result) throws Exception { 121 doReturn(result).when(() 122 -> ActivityManagerHelper.startUserInBackgroundVisibleOnDisplay(userId, displayId)); 123 } 124 125 /** 126 * Mocks a call to {@link ActivityManagerHelper#stopUser(int, boolean)}. 127 * 128 * * <p><b>Note: </b>it must be made inside a 129 * * {@link com.android.dx.mockito.inline.extended.StaticMockitoSession} built with 130 * * {@code spyStatic(ActivityManagerHelper.class)}. 131 */ mockForceStopUser(@serIdInt int userId, int result)132 public static void mockForceStopUser(@UserIdInt int userId, int result) throws Exception { 133 doReturn(result) 134 .when(() -> ActivityManagerHelper.stopUser(userId, /* force= */ true)); 135 } 136 137 /** 138 * Mocks a throwing call to {@link ActivityManagerHelper#stopUser(int, boolean)}. 139 * 140 * * <p><b>Note: </b>it must be made inside a 141 * * {@link com.android.dx.mockito.inline.extended.StaticMockitoSession} built with 142 * * {@code spyStatic(ActivityManagerHelper.class)}. 143 */ mockForceStopUserThrows(@serIdInt int userId, Throwable throwable)144 public static void mockForceStopUserThrows(@UserIdInt int userId, Throwable throwable) 145 throws Exception { 146 doThrow(throwable).when(() -> ActivityManagerHelper.stopUser(userId, /* force= */ true)); 147 } 148 149 /** 150 * Mocks a call to {@link ActivityManagerHelper#stopUserWithDelayedLocking(int, boolean)}. 151 * 152 * * <p><b>Note: </b>it must be made inside a 153 * * {@link com.android.dx.mockito.inline.extended.StaticMockitoSession} built with 154 * * {@code spyStatic(ActivityManagerHelper.class)}. 155 */ mockStopUserWithDelayedLocking(@serIdInt int userId, int result)156 public static void mockStopUserWithDelayedLocking(@UserIdInt int userId, int result) 157 throws Exception { 158 doReturn(result) 159 .when(() -> ActivityManagerHelper.stopUserWithDelayedLocking( 160 userId, /* force= */ true)); 161 } 162 163 /** 164 * Mocks a throwing call to 165 * {@link ActivityManagerHelper#stopUserWithDelayedLocking(int, boolean)}. 166 * 167 * * <p><b>Note: </b>it must be made inside a 168 * * {@link com.android.dx.mockito.inline.extended.StaticMockitoSession} built with 169 * * {@code spyStatic(ActivityManagerHelper.class)}. 170 */ mockStopUserWithDelayedLockingThrows(@serIdInt int userId, Throwable throwable)171 public static void mockStopUserWithDelayedLockingThrows(@UserIdInt int userId, 172 Throwable throwable) throws Exception { 173 doThrow(throwable).when(() -> ActivityManagerHelper.stopUserWithDelayedLocking( 174 userId, /* force= */ true)); 175 } 176 177 /** 178 * Mocks a call to {@link DevicePolicyManager#logoutUser()}. 179 */ mockDpmLogoutUser(DevicePolicyManager dpm, int result)180 public static void mockDpmLogoutUser(DevicePolicyManager dpm, int result) { 181 when(dpm.logoutUser()).thenReturn(result); 182 } 183 184 /** 185 * Mocks a successful call to {@code UserManager#createUser(NewUserRequest)} 186 */ mockUmCreateUser(UserManager um, @Nullable String name, String userType, @UserInfoFlag int flags, UserHandle user)187 public static void mockUmCreateUser(UserManager um, @Nullable String name, String userType, 188 @UserInfoFlag int flags, UserHandle user) { 189 NewUserResponse response = new NewUserResponse(user, UserManager.USER_OPERATION_SUCCESS); 190 when(um.createUser(isNewUserRequest(name, userType, flags))).thenReturn(response); 191 } 192 193 /** 194 * Mocks a call to {@code UserManager#createUser(NewUserRequest)} that returns the given 195 * response. 196 */ mockUmCreateUser(UserManager um, @Nullable String name, String userType, @UserInfoFlag int flags, NewUserResponse response)197 public static void mockUmCreateUser(UserManager um, @Nullable String name, String userType, 198 @UserInfoFlag int flags, NewUserResponse response) { 199 when(um.createUser(isNewUserRequest(name, userType, flags))).thenReturn(response); 200 } 201 202 /** 203 * Mocks a call to {@code UserManager#createUser(NewUserRequest)} that throws the given 204 * runtime exception. 205 */ mockUmCreateUser(UserManager um, @Nullable String name, String userType, @UserInfoFlag int flags, RuntimeException e)206 public static void mockUmCreateUser(UserManager um, @Nullable String name, String userType, 207 @UserInfoFlag int flags, RuntimeException e) { 208 when(um.createUser(isNewUserRequest(name, userType, flags))).thenThrow(e); 209 } 210 211 /** 212 * Mocks a successful call to {@code UserManager#createUser(NewUserRequest)} 213 */ mockUmCreateGuest(UserManager um, @Nullable String name, @UserIdInt int userId)214 public static void mockUmCreateGuest(UserManager um, @Nullable String name, 215 @UserIdInt int userId) { 216 NewUserResponse response = new NewUserResponse(UserHandle.of(userId), 217 UserManager.USER_OPERATION_SUCCESS); 218 when(um.createUser( 219 isNewUserRequest(name, UserManager.USER_TYPE_FULL_GUEST, /* flags= */ 0))) 220 .thenReturn(response); 221 } 222 223 @NonNull isNewUserRequest(@ullable String name, String userType, @UserInfoFlag int flags)224 private static NewUserRequest isNewUserRequest(@Nullable String name, 225 String userType, @UserInfoFlag int flags) { 226 return argThat(new NewUserRequestMatcher(name, userType, flags)); 227 } 228 229 /** 230 * Mocks a call to {@link UserManager#isHeadlessSystemUserMode()}. 231 * 232 * <p><b>Note: </b>it must be made inside a 233 * {@linkcom.android.dx.mockito.inline.extended.StaticMockitoSession} built with 234 * {@code spyStatic(UserManager.class)}. 235 * 236 * @param mode result of such call 237 */ mockUmIsHeadlessSystemUserMode(boolean mode)238 public static void mockUmIsHeadlessSystemUserMode(boolean mode) { 239 doReturn(mode).when(() -> UserManager.isHeadlessSystemUserMode()); 240 } 241 242 /** 243 * Mocks {@code UserManager#getUserInfo(userId)} to return a {@link UserInfo} with the given 244 * {@code flags}. 245 */ 246 @NonNull mockUmGetUserInfo(UserManager um, @UserIdInt int userId, @UserInfoFlag int flags)247 public static UserInfo mockUmGetUserInfo(UserManager um, @UserIdInt int userId, 248 @UserInfoFlag int flags) { 249 Objects.requireNonNull(um); 250 UserInfo user = new UserTestingHelper.UserInfoBuilder(userId).setFlags(flags).build(); 251 mockUmGetUserInfo(um, user); 252 return user; 253 } 254 255 /** 256 * Mocks {@code UserManager.getUserInfo(userId)} to return the given {@link UserInfo}. 257 */ 258 @NonNull mockUmGetUserInfo(UserManager um, UserInfo user)259 public static void mockUmGetUserInfo(UserManager um, UserInfo user) { 260 when(um.getUserInfo(user.id)).thenReturn(user); 261 } 262 263 /** 264 * Mocks {@code UserManager#getUserInfo(userId)} when the {@code userId} is the system user's. 265 */ 266 @NonNull mockUmGetSystemUser(UserManager um)267 public static void mockUmGetSystemUser(UserManager um) { 268 UserInfo user = new UserTestingHelper.UserInfoBuilder(UserHandle.USER_SYSTEM) 269 .setFlags(UserInfo.FLAG_SYSTEM).build(); 270 when(um.getUserInfo(UserHandle.USER_SYSTEM)).thenReturn(user); 271 } 272 273 /** 274 * Mocks {@link UserManager#getAliveUsers()} to return the given users. 275 */ mockUmGetAliveUsers(UserManager um, UserInfo... users)276 public static void mockUmGetAliveUsers(UserManager um, UserInfo... users) { 277 Objects.requireNonNull(um); 278 when(um.getAliveUsers()).thenReturn(UserTestingHelper.toList(users)); 279 } 280 281 /** 282 * Mocks {@link UserManager#getAliveUsers()} to return the simple users with the given ids. 283 */ mockUmGetAliveUsers(UserManager um, @UserIdInt int... userIds)284 public static void mockUmGetAliveUsers(UserManager um, 285 @UserIdInt int... userIds) { 286 mockUmGetUserHandles(um, true, userIds); 287 List<UserInfo> users = UserTestingHelper.newUsers(userIds); 288 when(um.getAliveUsers()).thenReturn(users); 289 } 290 291 /** 292 * Mocks {@link UserManager#getUserHandles(boolean)} to return the given users. 293 */ mockUmGetUserHandles(UserManager um, boolean excludeDying, UserHandle... users)294 public static void mockUmGetUserHandles(UserManager um, boolean excludeDying, 295 UserHandle... users) { 296 Objects.requireNonNull(users); 297 mockUmGetUserHandles(um, excludeDying, UserTestingHelper.toList(users)); 298 } 299 300 /** 301 * Mocks {@link UserManager#getUserHandles(boolean)} to return the given users. 302 */ mockUmGetUserHandles(UserManager um, boolean excludeDying, List<UserHandle> users)303 public static void mockUmGetUserHandles(UserManager um, boolean excludeDying, 304 List<UserHandle> users) { 305 Objects.requireNonNull(um); 306 Objects.requireNonNull(users); 307 when(um.getUserHandles(excludeDying)).thenReturn(users); 308 } 309 310 /** 311 * Mocks {@link UserManager#getUserHandles(boolean)} to return the given users. 312 */ mockUmGetUserHandles(UserManager um, boolean excludeDying, int... userIds)313 public static void mockUmGetUserHandles(UserManager um, boolean excludeDying, 314 int... userIds) { 315 mockUmGetUserHandles(um, excludeDying, UserTestingHelper.newUserHandles(userIds)); 316 } 317 318 /** Mocks a call to {@link UserManager#getUserHandles(boolean)}. */ mockUmGetAllUsers(UserManager um, UserHandle... users)319 public static void mockUmGetAllUsers(UserManager um, UserHandle... users) { 320 mockUmGetUserHandles(um, /* excludeDying= */ false, users); 321 } 322 323 /** 324 * Mocks a call to {@code UserManager#isUserRunning(userId)}. 325 */ mockUmIsUserRunning(UserManager um, @UserIdInt int userId, boolean isRunning)326 public static void mockUmIsUserRunning(UserManager um, @UserIdInt int userId, 327 boolean isRunning) { 328 when(um.isUserRunning(userId)).thenReturn(isRunning); 329 when(um.isUserRunning(UserHandle.of(userId))).thenReturn(isRunning); 330 } 331 332 /** 333 * Mocks a call to {@code UserManager#isUserUnlockingOrUnlocked()}. 334 */ mockUmIsUserUnlockingOrUnlocked(UserManager um, @UserIdInt int userId, boolean value)335 public static void mockUmIsUserUnlockingOrUnlocked(UserManager um, @UserIdInt int userId, 336 boolean value) { 337 when(um.isUserUnlockingOrUnlocked(isUserHandle(userId))).thenReturn(value); 338 when(um.isUserUnlockingOrUnlocked(userId)).thenReturn(value); 339 } 340 341 /** 342 * Mocks a successful call to {@code UserManager#removeUserWhenPossible(UserHandle, boolean)}, 343 * and notifies {@code listener} when it's called. 344 */ mockUmRemoveUserWhenPossible(UserManager um, UserInfo user, boolean overrideDevicePolicy, @RemoveResult int result, @Nullable Visitor<UserInfo> listener)345 public static void mockUmRemoveUserWhenPossible(UserManager um, 346 UserInfo user, boolean overrideDevicePolicy, @RemoveResult int result, 347 @Nullable Visitor<UserInfo> listener) { 348 when(um.removeUserWhenPossible(user.getUserHandle(), overrideDevicePolicy)) 349 .thenAnswer((inv) -> { 350 if (listener != null) { 351 Log.v(TAG, "mockUmRemoveUserWhenPossible(" + user + "): notifying " 352 + listener); 353 listener.visit(user); 354 } 355 return result; 356 }); 357 } 358 359 /** 360 * Mocks a successful call to {@code UserManager#removeUserWhenPossible(UserHandle, boolean)}, 361 * and notifies {@code listener} when it's called. 362 */ mockUmRemoveUserWhenPossible(UserManager um, UserHandle user, boolean overrideDevicePolicy, @RemoveResult int result, @Nullable Visitor<UserHandle> listener)363 public static void mockUmRemoveUserWhenPossible(UserManager um, 364 UserHandle user, boolean overrideDevicePolicy, @RemoveResult int result, 365 @Nullable Visitor<UserHandle> listener) { 366 when(um.removeUserWhenPossible(user, overrideDevicePolicy)).thenAnswer((inv) -> { 367 if (listener != null) { 368 Log.v(TAG, "mockUmRemoveUserWhenPossible(" + user + "): notifying " + listener); 369 listener.visit(user); 370 } 371 return result; 372 }); 373 } 374 375 /** 376 * Mocks a call to {@code UserManager#hasUserRestrictionForUser(String, UserHandle)} that 377 * returns {@code value}. 378 */ mockUmHasUserRestrictionForUser(UserManager um, UserHandle user, String restrictionKey, boolean value)379 public static void mockUmHasUserRestrictionForUser(UserManager um, 380 UserHandle user, String restrictionKey, boolean value) { 381 when(um.hasUserRestrictionForUser(restrictionKey, user)).thenReturn(value); 382 } 383 384 /** 385 * Mocks a call to {@code UserManager#getUserSwitchability(int)} that 386 * returns {@code result}. 387 */ mockUmGetUserSwitchability(UserManager um, @UserSwitchabilityResult int result)388 public static void mockUmGetUserSwitchability(UserManager um, 389 @UserSwitchabilityResult int result) { 390 when(um.getUserSwitchability()).thenReturn(result); 391 } 392 393 /** 394 * Mocks a call to {@code UserManager#getVisibleUsers()} that 395 * returns {@link UserHandle UserHandles} with the given {@code userIds}. 396 */ mockUmGetVisibleUsers(UserManager um, @UserIdInt int...userIds)397 public static void mockUmGetVisibleUsers(UserManager um, @UserIdInt int...userIds) { 398 Set<UserHandle> users = Arrays.stream(userIds).mapToObj(u -> UserHandle.of(u)) 399 .collect(Collectors.toSet()); 400 Log.v(TAG, "mockUmGetVisibleUsers(" + Arrays.toString(userIds) + ": returning " 401 + users); 402 when(um.getVisibleUsers()).thenReturn(users); 403 } 404 405 /** 406 * Mocks a call to {@code UserManager#isUserVisible()} that returns {@code isVisible}. 407 */ mockUmIsUserVisible(UserManager um, boolean isVisible)408 public static void mockUmIsUserVisible(UserManager um, boolean isVisible) { 409 when(um.isUserVisible()).thenReturn(isVisible); 410 } 411 412 /** 413 * Mocks a call to {@code UserManager#isVisibleBackgroundUsersSupported()} that returns 414 * {@code isVisibleBackgroundUsersSupported}. 415 */ mockUmIsVisibleBackgroundUsersSupported(UserManager um, boolean isVisibleBackgroundUsersSupported)416 public static void mockUmIsVisibleBackgroundUsersSupported(UserManager um, 417 boolean isVisibleBackgroundUsersSupported) { 418 when(um.isVisibleBackgroundUsersSupported()).thenReturn( 419 isVisibleBackgroundUsersSupported); 420 } 421 422 /** 423 * Mocks a call to {@code UserManager#isVisibleBackgroundUsersOnDefaultDisplaySupported()} that 424 * returns {@code isVisibleBackgroundUsersOnDefaultDisplaySupported}. 425 */ mockUmIsVisibleBackgroundUsersOnDefaultDisplaySupported(UserManager um, boolean supported)426 public static void mockUmIsVisibleBackgroundUsersOnDefaultDisplaySupported(UserManager um, 427 boolean supported) { 428 when(um.isVisibleBackgroundUsersOnDefaultDisplaySupported()).thenReturn(supported); 429 } 430 431 /** 432 * Mocks a call to {@link ServiceManager#getService(name)}. 433 * 434 * <p><b>Note: </b>it must be made inside a 435 * {@link com.android.dx.mockito.inline.extended.StaticMockitoSession} built with 436 * {@code spyStatic(ServiceManager.class)}. 437 * 438 * @param name interface name of the service 439 * @param binder result of such call 440 */ mockSmGetService(String name, IBinder binder)441 public static void mockSmGetService(String name, IBinder binder) { 442 doReturn(binder).when(() -> ServiceManager.getService(name)); 443 } 444 445 /** 446 * Returns mocked binder implementation from the given interface name. 447 * 448 * <p><b>Note: </b>it must be made inside a 449 * {@link com.android.dx.mockito.inline.extended.StaticMockitoSession} built with 450 * {@code spyStatic(ServiceManager.class)}. 451 * 452 * @param name interface name of the service 453 * @param binder mocked return of ServiceManager.getService 454 * @param service binder implementation 455 */ mockQueryService(String name, IBinder binder, T service)456 public static <T extends IInterface> void mockQueryService(String name, 457 IBinder binder, T service) { 458 doReturn(binder).when(() -> ServiceManager.getService(name)); 459 doReturn(binder).when(() -> ServiceManager.checkService(name)); 460 when(binder.queryLocalInterface(anyString())).thenReturn(service); 461 } 462 463 /** 464 * Mocks a call to {@link Binder#getCallingUserHandle()}. 465 * 466 * <p><b>Note: </b>it must be made inside a 467 * {@link com.android.dx.mockito.inline.extended.StaticMockitoSession} built with 468 * {@code spyStatic(Binder.class)}. 469 * 470 * @param userId identifier of the {@link UserHandle} that will be returned. 471 */ mockBinderGetCallingUserHandle(@serIdInt int userId)472 public static void mockBinderGetCallingUserHandle(@UserIdInt int userId) { 473 doReturn(UserHandle.of(userId)).when(() -> Binder.getCallingUserHandle()); 474 } 475 476 /** 477 * Mocks a call to {@link Car#getCarVersion()} 478 */ mockCarGetCarVersion(CarVersion version)479 public static void mockCarGetCarVersion(CarVersion version) { 480 Log.d(TAG, "mockCarGetCarVersion(): " + version); 481 doReturn(version).when(() -> Car.getCarVersion()); 482 } 483 484 /** 485 * Mocks a call to {@link Car#getPlatformVersion()} 486 */ mockCarGetPlatformVersion(PlatformVersion version)487 public static void mockCarGetPlatformVersion(PlatformVersion version) { 488 Log.d(TAG, "mockCarGetPlatformVersion(): " + version); 489 doReturn(version).when(() -> Car.getPlatformVersion()); 490 } 491 492 /** 493 * Mocks a call to {@link Car#isApiVersionAtLeast()} 494 */ mockCarIsApiVersionAtLeast(int major, int minor, boolean isIt)495 public static void mockCarIsApiVersionAtLeast(int major, int minor, boolean isIt) { 496 Log.d(TAG, "mockCarIsApiVersionAtLeast(" + major + ", " + minor + "): " + isIt); 497 doReturn(isIt).when(() -> Car.isApiVersionAtLeast(major, minor)); 498 } 499 500 /** 501 * Mocks a call to {@link Context#getSystemService(Class)}. 502 */ mockContextGetService(Context context, Class<T> serviceClass, T service)503 public static <T> void mockContextGetService(Context context, 504 Class<T> serviceClass, T service) { 505 when(context.getSystemService(serviceClass)).thenReturn(service); 506 if (serviceClass.equals(PackageManager.class)) { 507 when(context.getPackageManager()).thenReturn(PackageManager.class.cast(service)); 508 } 509 } 510 511 /** 512 * Mocks a call to {@link Context#checkCallingOrSelfPermission(String)} 513 */ mockContextCheckCallingOrSelfPermission(Context context, String permission, @PermissionResult int permissionResults)514 public static void mockContextCheckCallingOrSelfPermission(Context context, 515 String permission, @PermissionResult int permissionResults) { 516 when(context.checkCallingOrSelfPermission(permission)).thenReturn(permissionResults); 517 } 518 519 /** 520 * Mock a call to {@link Context#createContextAsUser(UserHandle, int)}} 521 */ mockContextCreateContextAsUser(Context context, Context userContext, @UserIdInt int userId)522 public static void mockContextCreateContextAsUser(Context context, Context userContext, 523 @UserIdInt int userId) { 524 when(context.createContextAsUser(UserHandle.of(userId), /* flags= */ 0)).thenReturn( 525 userContext); 526 } 527 528 // TODO(b/192307581): add unit tests 529 /** 530 * Returns the result of the giving {@code callable} in the main thread, preparing the 531 * {@link Looper} if needed and using a default timeout. 532 */ syncCallOnMainThread(Callable<T> c)533 public static <T> T syncCallOnMainThread(Callable<T> c) throws Exception { 534 return syncCallOnMainThread(JavaMockitoHelper.ASYNC_TIMEOUT_MS, c); 535 } 536 537 // TODO(b/192307581): add unit tests 538 /** 539 * Returns the result of the giving {@code callable} in the main thread, preparing the 540 * {@link Looper} if needed. 541 */ syncCallOnMainThread(long timeoutMs, Callable<T> callable)542 public static <T> T syncCallOnMainThread(long timeoutMs, Callable<T> callable) 543 throws Exception { 544 boolean quitLooper = false; 545 Looper looper = Looper.getMainLooper(); 546 if (looper == null) { 547 Log.i(TAG, "preparing main looper"); 548 Looper.prepareMainLooper(); 549 looper = Looper.getMainLooper(); 550 assertWithMessage("Looper.getMainLooper()").that(looper).isNotNull(); 551 quitLooper = true; 552 } 553 Log.i(TAG, "looper: " + looper); 554 AtomicReference<Exception> exception = new AtomicReference<>(); 555 AtomicReference<T> ref = new AtomicReference<>(); 556 try { 557 Handler handler = new Handler(looper); 558 CountDownLatch latch = new CountDownLatch(1); 559 handler.post(() -> { 560 T result = null; 561 try { 562 result = callable.call(); 563 } catch (Exception e) { 564 exception.set(e); 565 } 566 ref.set(result); 567 latch.countDown(); 568 }); 569 JavaMockitoHelper.await(latch, timeoutMs); 570 Exception e = exception.get(); 571 if (e != null) throw e; 572 return ref.get(); 573 } finally { 574 if (quitLooper) { 575 Log.i(TAG, "quitting looper: " + looper); 576 looper.quitSafely(); 577 } 578 } 579 } 580 581 // TODO(b/192307581): add unit tests 582 /** 583 * Runs the giving {@code runnable} in the activity's UI thread, using a default timeout. 584 */ syncRunOnUiThread(Activity activity, Runnable runnable)585 public static void syncRunOnUiThread(Activity activity, Runnable runnable) throws Exception { 586 syncRunOnUiThread(JavaMockitoHelper.ASYNC_TIMEOUT_MS, activity, runnable); 587 } 588 589 // TODO(b/192307581): add unit tests 590 /** 591 * Runs the giving {@code runnable} in the activity's UI thread. 592 */ syncRunOnUiThread(long timeoutMs, Activity activity, Runnable runnable)593 public static void syncRunOnUiThread(long timeoutMs, Activity activity, Runnable runnable) 594 throws Exception { 595 CountDownLatch latch = new CountDownLatch(1); 596 activity.runOnUiThread(() -> { 597 runnable.run(); 598 latch.countDown(); 599 }); 600 JavaMockitoHelper.await(latch, timeoutMs); 601 } 602 AndroidMockitoHelper()603 private AndroidMockitoHelper() { 604 throw new UnsupportedOperationException("contains only static methods"); 605 } 606 607 static final class NewUserRequestMatcher implements 608 ArgumentMatcher<NewUserRequest> { 609 610 private final String mName; 611 private final String mUserType; 612 private final int mFlags; 613 NewUserRequestMatcher(String name, String userType, int flags)614 NewUserRequestMatcher(String name, String userType, int flags) { 615 mName = name; 616 mUserType = userType; 617 mFlags = flags; 618 } 619 620 @Override matches(NewUserRequest request)621 public boolean matches(NewUserRequest request) { 622 if (request.isAdmin() 623 && ((mFlags & UserManagerHelper.FLAG_ADMIN) != UserManagerHelper.FLAG_ADMIN)) { 624 return false; 625 } 626 if (request.isEphemeral() && ((mFlags 627 & UserManagerHelper.FLAG_EPHEMERAL) != UserManagerHelper.FLAG_EPHEMERAL)) { 628 return false; 629 } 630 631 return request.getUserType().equals(mUserType) 632 && Objects.equals(request.getName(), mName); 633 } 634 } 635 } 636