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