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 20 import static org.mockito.ArgumentMatchers.anyBoolean; 21 import static org.mockito.Matchers.anyString; 22 import static org.mockito.Mockito.when; 23 24 import android.annotation.NonNull; 25 import android.annotation.Nullable; 26 import android.annotation.UserIdInt; 27 import android.app.ActivityManager; 28 import android.car.test.util.UserTestingHelper; 29 import android.car.test.util.UserTestingHelper.UserInfoBuilder; 30 import android.content.Context; 31 import android.content.pm.PackageManager; 32 import android.content.pm.UserInfo; 33 import android.content.pm.UserInfo.UserInfoFlag; 34 import android.os.IBinder; 35 import android.os.IInterface; 36 import android.os.ServiceManager; 37 import android.os.UserHandle; 38 import android.os.UserManager; 39 40 import com.android.internal.infra.AndroidFuture; 41 42 import java.util.Arrays; 43 import java.util.List; 44 import java.util.Objects; 45 import java.util.concurrent.ExecutionException; 46 import java.util.concurrent.TimeUnit; 47 import java.util.concurrent.TimeoutException; 48 import java.util.stream.Collectors; 49 50 /** 51 * Provides common Mockito calls for core Android classes. 52 */ 53 public final class AndroidMockitoHelper { 54 55 private static final long ASYNC_TIMEOUT_MS = 500; 56 57 /** 58 * Mocks a call to {@link ActivityManager#getCurrentUser()}. 59 * 60 * <p><b>Note: </b>it must be made inside a 61 * {@link com.android.dx.mockito.inline.extended.StaticMockitoSession} built with 62 * {@code spyStatic(ActivityManager.class)}. 63 * 64 * @param userId result of such call 65 */ mockAmGetCurrentUser(@serIdInt int userId)66 public static void mockAmGetCurrentUser(@UserIdInt int userId) { 67 doReturn(userId).when(() -> ActivityManager.getCurrentUser()); 68 } 69 70 /** 71 * Mocks a call to {@link UserManager#isHeadlessSystemUserMode()}. 72 * 73 * <p><b>Note: </b>it must be made inside a 74 * {@linkcom.android.dx.mockito.inline.extended.StaticMockitoSession} built with 75 * {@code spyStatic(UserManager.class)}. 76 * 77 * @param mode result of such call 78 */ mockUmIsHeadlessSystemUserMode(boolean mode)79 public static void mockUmIsHeadlessSystemUserMode(boolean mode) { 80 doReturn(mode).when(() -> UserManager.isHeadlessSystemUserMode()); 81 } 82 83 /** 84 * Mocks {@code UserManager#getUserInfo(userId)} to return a {@link UserInfo} with the given 85 * {@code flags}. 86 */ 87 @NonNull mockUmGetUserInfo(@onNull UserManager um, @UserIdInt int userId, @UserInfoFlag int flags)88 public static UserInfo mockUmGetUserInfo(@NonNull UserManager um, @UserIdInt int userId, 89 @UserInfoFlag int flags) { 90 Objects.requireNonNull(um); 91 UserInfo user = new UserTestingHelper.UserInfoBuilder(userId).setFlags(flags).build(); 92 mockUmGetUserInfo(um, user); 93 return user; 94 } 95 96 /** 97 * Mocks {@code UserManager.getUserInfo(userId)} to return the given {@link UserInfo}. 98 */ 99 @NonNull mockUmGetUserInfo(@onNull UserManager um, @NonNull UserInfo user)100 public static void mockUmGetUserInfo(@NonNull UserManager um, @NonNull UserInfo user) { 101 when(um.getUserInfo(user.id)).thenReturn(user); 102 } 103 104 /** 105 * Mocks {@code UserManager#getUserInfo(userId)} when the {@code userId} is the system user's. 106 */ 107 @NonNull mockUmGetSystemUser(@onNull UserManager um)108 public static void mockUmGetSystemUser(@NonNull UserManager um) { 109 UserInfo user = new UserTestingHelper.UserInfoBuilder(UserHandle.USER_SYSTEM) 110 .setFlags(UserInfo.FLAG_SYSTEM).build(); 111 when(um.getUserInfo(UserHandle.USER_SYSTEM)).thenReturn(user); 112 } 113 114 /** 115 * Mocks {@code UserManager#getUsers()}, {@code UserManager#getUsers(excludeDying)}, and 116 * {@code UserManager#getUsers(excludePartial, excludeDying, excludeDying)} to return the given 117 * users. 118 */ mockUmGetUsers(@onNull UserManager um, @NonNull UserInfo... users)119 public static void mockUmGetUsers(@NonNull UserManager um, @NonNull UserInfo... users) { 120 Objects.requireNonNull(um); 121 List<UserInfo> testUsers = Arrays.stream(users).collect(Collectors.toList()); 122 when(um.getUsers()).thenReturn(testUsers); 123 when(um.getUsers(anyBoolean())).thenReturn(testUsers); 124 when(um.getUsers(anyBoolean(), anyBoolean(), anyBoolean())).thenReturn(testUsers); 125 } 126 127 /** 128 * Mocks {@code UserManager#getUsers()}, {@code UserManager#getUsers(excludeDying)}, and 129 * {@code UserManager#getUsers(excludePartial, excludeDying, excludeDying)} to return simple 130 * users with the given ids. 131 */ mockUmGetUsers(@onNull UserManager um, @NonNull @UserIdInt int... userIds)132 public static void mockUmGetUsers(@NonNull UserManager um, @NonNull @UserIdInt int... userIds) { 133 List<UserInfo> users = UserTestingHelper.newUsers(userIds); 134 when(um.getUsers()).thenReturn(users); 135 when(um.getUsers(anyBoolean())).thenReturn(users); 136 when(um.getUsers(anyBoolean(), anyBoolean(), anyBoolean())).thenReturn(users); 137 } 138 139 /** 140 * Mocks a call to {@code UserManager#getUsers()}, which includes dying users. 141 */ mockUmGetAllUsers(@onNull UserManager um, @NonNull List<UserInfo> userInfos)142 public static void mockUmGetAllUsers(@NonNull UserManager um, 143 @NonNull List<UserInfo> userInfos) { 144 when(um.getUsers()).thenReturn(userInfos); 145 } 146 147 /** 148 * Mocks {@code UserManager#getUsers()}, {@code UserManager#getUsers(excludeDying)}, and 149 * {@code UserManager#getUsers(excludePartial, excludeDying, excludeDying)} to return given 150 * userInfos. 151 */ mockUmGetUsers(@onNull UserManager um, @NonNull List<UserInfo> userInfos)152 public static void mockUmGetUsers(@NonNull UserManager um, @NonNull List<UserInfo> userInfos) { 153 when(um.getUsers()).thenReturn(userInfos); 154 when(um.getUsers(anyBoolean())).thenReturn(userInfos); 155 when(um.getUsers(anyBoolean(), anyBoolean(), anyBoolean())).thenReturn(userInfos); 156 } 157 158 /** 159 * Mocks a call to {@code UserManager#isUserRunning(userId)}. 160 */ mockUmIsUserRunning(@onNull UserManager um, @UserIdInt int userId, boolean isRunning)161 public static void mockUmIsUserRunning(@NonNull UserManager um, @UserIdInt int userId, 162 boolean isRunning) { 163 when(um.isUserRunning(userId)).thenReturn(isRunning); 164 } 165 166 /** 167 * Mocks a successful call to {@code UserManager#createUser(String, String, int)}, returning 168 * a user with the passed arguments. 169 */ 170 @NonNull mockUmCreateUser(@onNull UserManager um, @Nullable String name, @NonNull String userType, @UserInfoFlag int flags, @UserIdInt int userId)171 public static UserInfo mockUmCreateUser(@NonNull UserManager um, @Nullable String name, 172 @NonNull String userType, @UserInfoFlag int flags, @UserIdInt int userId) { 173 UserInfo userInfo = new UserInfoBuilder(userId) 174 .setName(name) 175 .setType(userType) 176 .setFlags(flags) 177 .build(); 178 when(um.createUser(name, userType, flags)).thenReturn(userInfo); 179 return userInfo; 180 } 181 182 /** 183 * Mocks a call to {@code UserManager#createUser(String, String, int)} that throws the given 184 * runtime exception. 185 */ 186 @NonNull mockUmCreateUser(@onNull UserManager um, @Nullable String name, @NonNull String userType, @UserInfoFlag int flags, @NonNull RuntimeException e)187 public static void mockUmCreateUser(@NonNull UserManager um, @Nullable String name, 188 @NonNull String userType, @UserInfoFlag int flags, @NonNull RuntimeException e) { 189 when(um.createUser(name, userType, flags)).thenThrow(e); 190 } 191 192 /** 193 * Mocks a call to {@link ServiceManager#getService(name)}. 194 * 195 * <p><b>Note: </b>it must be made inside a 196 * {@link com.android.dx.mockito.inline.extended.StaticMockitoSession} built with 197 * {@code spyStatic(ServiceManager.class)}. 198 * 199 * @param name interface name of the service 200 * @param binder result of such call 201 */ mockSmGetService(@onNull String name, @NonNull IBinder binder)202 public static void mockSmGetService(@NonNull String name, @NonNull IBinder binder) { 203 doReturn(binder).when(() -> ServiceManager.getService(name)); 204 } 205 206 /** 207 * Returns mocked binder implementation from the given interface name. 208 * 209 * <p><b>Note: </b>it must be made inside a 210 * {@link com.android.dx.mockito.inline.extended.StaticMockitoSession} built with 211 * {@code spyStatic(ServiceManager.class)}. 212 * 213 * @param name interface name of the service 214 * @param binder mocked return of ServiceManager.getService 215 * @param service binder implementation 216 */ mockQueryService(@onNull String name, @NonNull IBinder binder, @NonNull T service)217 public static <T extends IInterface> void mockQueryService(@NonNull String name, 218 @NonNull IBinder binder, @NonNull T service) { 219 doReturn(binder).when(() -> ServiceManager.getService(name)); 220 when(binder.queryLocalInterface(anyString())).thenReturn(service); 221 } 222 223 /** 224 * Mocks a call to {@link Context#getSystemService(Class)}. 225 */ mockContextGetService(@onNull Context context, @NonNull Class<T> serviceClass, @NonNull T service)226 public static <T> void mockContextGetService(@NonNull Context context, 227 @NonNull Class<T> serviceClass, @NonNull T service) { 228 when(context.getSystemService(serviceClass)).thenReturn(service); 229 if (serviceClass.equals(PackageManager.class)) { 230 when(context.getPackageManager()).thenReturn(PackageManager.class.cast(service)); 231 } 232 } 233 234 /** 235 * Gets the result of a future, or throw a {@link IllegalStateException} if it times out after 236 * {@value #ASYNC_TIMEOUT_MS} ms. 237 */ 238 @NonNull getResult(@onNull AndroidFuture<T> future)239 public static <T> T getResult(@NonNull AndroidFuture<T> future) 240 throws InterruptedException, ExecutionException { 241 return getResult(future, ASYNC_TIMEOUT_MS); 242 } 243 244 /** 245 * Gets the result of a future, or throw a {@link IllegalStateException} if it times out. 246 */ 247 @NonNull getResult(@onNull AndroidFuture<T> future, long timeoutMs)248 public static <T> T getResult(@NonNull AndroidFuture<T> future, long timeoutMs) 249 throws InterruptedException, ExecutionException { 250 try { 251 return future.get(timeoutMs, TimeUnit.MILLISECONDS); 252 } catch (TimeoutException e) { 253 throw new IllegalStateException("not called in " + ASYNC_TIMEOUT_MS + "ms", e); 254 } 255 } 256 AndroidMockitoHelper()257 private AndroidMockitoHelper() { 258 throw new UnsupportedOperationException("contains only static methods"); 259 } 260 } 261