/* * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.car.test.mocks; import static android.car.test.mocks.CarArgumentMatchers.isUserHandle; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doThrow; import static com.google.common.truth.Truth.assertWithMessage; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.Mockito.when; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.UserIdInt; import android.app.Activity; import android.app.ActivityManager; import android.app.admin.DevicePolicyManager; import android.car.Car; import android.car.CarVersion; import android.car.PlatformVersion; import android.car.builtin.app.ActivityManagerHelper; import android.car.builtin.os.UserManagerHelper; import android.car.test.util.UserTestingHelper; import android.car.test.util.Visitor; import android.content.Context; import android.content.pm.PackageManager; import android.content.pm.PackageManager.PermissionResult; import android.content.pm.UserInfo; import android.content.pm.UserInfo.UserInfoFlag; import android.os.Binder; import android.os.Handler; import android.os.IBinder; import android.os.IInterface; import android.os.Looper; import android.os.NewUserRequest; import android.os.NewUserResponse; import android.os.ServiceManager; import android.os.UserHandle; import android.os.UserManager; import android.os.UserManager.RemoveResult; import android.os.UserManager.UserSwitchabilityResult; import android.util.Log; import org.mockito.ArgumentMatcher; import java.util.Arrays; import java.util.List; import java.util.Objects; import java.util.Set; import java.util.concurrent.Callable; import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicReference; import java.util.stream.Collectors; /** * Provides common Mockito calls for core Android classes. */ public final class AndroidMockitoHelper { private static final String TAG = AndroidMockitoHelper.class.getSimpleName(); /** * Mocks a call to {@link ActivityManager#getCurrentUser()}. * *
Note: it must be made inside a * {@link com.android.dx.mockito.inline.extended.StaticMockitoSession} built with * {@code spyStatic(ActivityManager.class)}. * * @param userId result of such call */ public static void mockAmGetCurrentUser(@UserIdInt int userId) { doReturn(userId).when(() -> ActivityManager.getCurrentUser()); } /** * Mocks a call to {@link ActivityManager#switchUser(UserHandle)}. */ public static void mockAmSwitchUser(ActivityManager am, UserHandle user, boolean result) { when(am.switchUser(user)).thenReturn(result); } /** * Mocks a call to {@link ActivityManagerHelper#startUserInBackground(int)}. * * *
Note: it must be made inside a * * {@link com.android.dx.mockito.inline.extended.StaticMockitoSession} built with * * {@code spyStatic(ActivityManagerHelper.class)}. */ public static void mockAmStartUserInBackground(@UserIdInt int userId, boolean result) throws Exception { doReturn(result).when(() -> ActivityManagerHelper.startUserInBackground(userId)); } /** * Mocks a call to {@link ActivityManagerHelper#startUserInBackgroundVisibleOnDisplay(int, int)} * * *
Note: it must be made inside a * * {@link com.android.dx.mockito.inline.extended.StaticMockitoSession} built with * * {@code spyStatic(ActivityManagerHelper.class)}. */ public static void mockAmStartUserInBackgroundVisibleOnDisplay( @UserIdInt int userId, int displayId, boolean result) throws Exception { doReturn(result).when(() -> ActivityManagerHelper.startUserInBackgroundVisibleOnDisplay(userId, displayId)); } /** * Mocks a call to {@link ActivityManagerHelper#stopUser(int, boolean)}. * * *
Note: it must be made inside a * * {@link com.android.dx.mockito.inline.extended.StaticMockitoSession} built with * * {@code spyStatic(ActivityManagerHelper.class)}. */ public static void mockForceStopUser(@UserIdInt int userId, int result) throws Exception { doReturn(result) .when(() -> ActivityManagerHelper.stopUser(userId, /* force= */ true)); } /** * Mocks a throwing call to {@link ActivityManagerHelper#stopUser(int, boolean)}. * * *
Note: it must be made inside a * * {@link com.android.dx.mockito.inline.extended.StaticMockitoSession} built with * * {@code spyStatic(ActivityManagerHelper.class)}. */ public static void mockForceStopUserThrows(@UserIdInt int userId, Throwable throwable) throws Exception { doThrow(throwable).when(() -> ActivityManagerHelper.stopUser(userId, /* force= */ true)); } /** * Mocks a call to {@link ActivityManagerHelper#stopUserWithDelayedLocking(int, boolean)}. * * *
Note: it must be made inside a * * {@link com.android.dx.mockito.inline.extended.StaticMockitoSession} built with * * {@code spyStatic(ActivityManagerHelper.class)}. */ public static void mockStopUserWithDelayedLocking(@UserIdInt int userId, int result) throws Exception { doReturn(result) .when(() -> ActivityManagerHelper.stopUserWithDelayedLocking( userId, /* force= */ true)); } /** * Mocks a throwing call to * {@link ActivityManagerHelper#stopUserWithDelayedLocking(int, boolean)}. * * *
Note: it must be made inside a * * {@link com.android.dx.mockito.inline.extended.StaticMockitoSession} built with * * {@code spyStatic(ActivityManagerHelper.class)}. */ public static void mockStopUserWithDelayedLockingThrows(@UserIdInt int userId, Throwable throwable) throws Exception { doThrow(throwable).when(() -> ActivityManagerHelper.stopUserWithDelayedLocking( userId, /* force= */ true)); } /** * Mocks a call to {@link DevicePolicyManager#logoutUser()}. */ public static void mockDpmLogoutUser(DevicePolicyManager dpm, int result) { when(dpm.logoutUser()).thenReturn(result); } /** * Mocks a successful call to {@code UserManager#createUser(NewUserRequest)} */ public static void mockUmCreateUser(UserManager um, @Nullable String name, String userType, @UserInfoFlag int flags, UserHandle user) { NewUserResponse response = new NewUserResponse(user, UserManager.USER_OPERATION_SUCCESS); when(um.createUser(isNewUserRequest(name, userType, flags))).thenReturn(response); } /** * Mocks a call to {@code UserManager#createUser(NewUserRequest)} that returns the given * response. */ public static void mockUmCreateUser(UserManager um, @Nullable String name, String userType, @UserInfoFlag int flags, NewUserResponse response) { when(um.createUser(isNewUserRequest(name, userType, flags))).thenReturn(response); } /** * Mocks a call to {@code UserManager#createUser(NewUserRequest)} that throws the given * runtime exception. */ public static void mockUmCreateUser(UserManager um, @Nullable String name, String userType, @UserInfoFlag int flags, RuntimeException e) { when(um.createUser(isNewUserRequest(name, userType, flags))).thenThrow(e); } /** * Mocks a successful call to {@code UserManager#createUser(NewUserRequest)} */ public static void mockUmCreateGuest(UserManager um, @Nullable String name, @UserIdInt int userId) { NewUserResponse response = new NewUserResponse(UserHandle.of(userId), UserManager.USER_OPERATION_SUCCESS); when(um.createUser( isNewUserRequest(name, UserManager.USER_TYPE_FULL_GUEST, /* flags= */ 0))) .thenReturn(response); } @NonNull private static NewUserRequest isNewUserRequest(@Nullable String name, String userType, @UserInfoFlag int flags) { return argThat(new NewUserRequestMatcher(name, userType, flags)); } /** * Mocks a call to {@link UserManager#isHeadlessSystemUserMode()}. * *
Note: it must be made inside a
* {@linkcom.android.dx.mockito.inline.extended.StaticMockitoSession} built with
* {@code spyStatic(UserManager.class)}.
*
* @param mode result of such call
*/
public static void mockUmIsHeadlessSystemUserMode(boolean mode) {
doReturn(mode).when(() -> UserManager.isHeadlessSystemUserMode());
}
/**
* Mocks {@code UserManager#getUserInfo(userId)} to return a {@link UserInfo} with the given
* {@code flags}.
*/
@NonNull
public static UserInfo mockUmGetUserInfo(UserManager um, @UserIdInt int userId,
@UserInfoFlag int flags) {
Objects.requireNonNull(um);
UserInfo user = new UserTestingHelper.UserInfoBuilder(userId).setFlags(flags).build();
mockUmGetUserInfo(um, user);
return user;
}
/**
* Mocks {@code UserManager.getUserInfo(userId)} to return the given {@link UserInfo}.
*/
@NonNull
public static void mockUmGetUserInfo(UserManager um, UserInfo user) {
when(um.getUserInfo(user.id)).thenReturn(user);
}
/**
* Mocks {@code UserManager#getUserInfo(userId)} when the {@code userId} is the system user's.
*/
@NonNull
public static void mockUmGetSystemUser(UserManager um) {
UserInfo user = new UserTestingHelper.UserInfoBuilder(UserHandle.USER_SYSTEM)
.setFlags(UserInfo.FLAG_SYSTEM).build();
when(um.getUserInfo(UserHandle.USER_SYSTEM)).thenReturn(user);
}
/**
* Mocks {@link UserManager#getAliveUsers()} to return the given users.
*/
public static void mockUmGetAliveUsers(UserManager um, UserInfo... users) {
Objects.requireNonNull(um);
when(um.getAliveUsers()).thenReturn(UserTestingHelper.toList(users));
}
/**
* Mocks {@link UserManager#getAliveUsers()} to return the simple users with the given ids.
*/
public static void mockUmGetAliveUsers(UserManager um,
@UserIdInt int... userIds) {
mockUmGetUserHandles(um, true, userIds);
List Note: it must be made inside a
* {@link com.android.dx.mockito.inline.extended.StaticMockitoSession} built with
* {@code spyStatic(ServiceManager.class)}.
*
* @param name interface name of the service
* @param binder result of such call
*/
public static void mockSmGetService(String name, IBinder binder) {
doReturn(binder).when(() -> ServiceManager.getService(name));
}
/**
* Returns mocked binder implementation from the given interface name.
*
* Note: it must be made inside a
* {@link com.android.dx.mockito.inline.extended.StaticMockitoSession} built with
* {@code spyStatic(ServiceManager.class)}.
*
* @param name interface name of the service
* @param binder mocked return of ServiceManager.getService
* @param service binder implementation
*/
public static Note: it must be made inside a
* {@link com.android.dx.mockito.inline.extended.StaticMockitoSession} built with
* {@code spyStatic(Binder.class)}.
*
* @param userId identifier of the {@link UserHandle} that will be returned.
*/
public static void mockBinderGetCallingUserHandle(@UserIdInt int userId) {
doReturn(UserHandle.of(userId)).when(() -> Binder.getCallingUserHandle());
}
/**
* Mocks a call to {@link Car#getCarVersion()}
*/
public static void mockCarGetCarVersion(CarVersion version) {
Log.d(TAG, "mockCarGetCarVersion(): " + version);
doReturn(version).when(() -> Car.getCarVersion());
}
/**
* Mocks a call to {@link Car#getPlatformVersion()}
*/
public static void mockCarGetPlatformVersion(PlatformVersion version) {
Log.d(TAG, "mockCarGetPlatformVersion(): " + version);
doReturn(version).when(() -> Car.getPlatformVersion());
}
/**
* Mocks a call to {@link Car#isApiVersionAtLeast()}
*/
public static void mockCarIsApiVersionAtLeast(int major, int minor, boolean isIt) {
Log.d(TAG, "mockCarIsApiVersionAtLeast(" + major + ", " + minor + "): " + isIt);
doReturn(isIt).when(() -> Car.isApiVersionAtLeast(major, minor));
}
/**
* Mocks a call to {@link Context#getSystemService(Class)}.
*/
public static