1 /* 2 * Copyright (C) 2017 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 com.android.server.devicepolicy; 17 18 import static org.mockito.ArgumentMatchers.anyBoolean; 19 import static org.mockito.ArgumentMatchers.anyInt; 20 import static org.mockito.ArgumentMatchers.eq; 21 import static org.mockito.Mockito.RETURNS_DEEP_STUBS; 22 import static org.mockito.Mockito.mock; 23 import static org.mockito.Mockito.spy; 24 import static org.mockito.Mockito.when; 25 26 import android.accounts.Account; 27 import android.accounts.AccountManager; 28 import android.app.AlarmManager; 29 import android.app.IActivityManager; 30 import android.app.NotificationManager; 31 import android.app.backup.IBackupManager; 32 import android.content.BroadcastReceiver; 33 import android.content.Context; 34 import android.content.Intent; 35 import android.content.IntentFilter; 36 import android.content.pm.IPackageManager; 37 import android.content.pm.PackageManager; 38 import android.content.pm.PackageManagerInternal; 39 import android.content.pm.UserInfo; 40 import android.media.IAudioService; 41 import android.net.IIpConnectivityMetrics; 42 import android.net.wifi.WifiManager; 43 import android.os.Handler; 44 import android.os.PowerManager; 45 import android.os.PowerManagerInternal; 46 import android.os.UserHandle; 47 import android.os.UserManager; 48 import android.os.UserManagerInternal; 49 import android.provider.Settings; 50 import android.security.KeyChain; 51 import android.telephony.TelephonyManager; 52 import android.test.mock.MockContentResolver; 53 import android.util.ArrayMap; 54 import android.util.Pair; 55 import android.view.IWindowManager; 56 57 import com.android.internal.util.test.FakeSettingsProvider; 58 import com.android.internal.widget.LockPatternUtils; 59 60 import java.io.File; 61 import java.io.IOException; 62 import java.util.ArrayList; 63 import java.util.List; 64 import java.util.Map; 65 import java.util.concurrent.atomic.AtomicReference; 66 67 /** 68 * System services mocks and some other data that are shared by all contexts during the test. 69 */ 70 public class MockSystemServices { 71 public final File systemUserDataDir; 72 public final EnvironmentForMock environment; 73 public final SystemPropertiesForMock systemProperties; 74 public final UserManager userManager; 75 public final UserManagerInternal userManagerInternal; 76 public final PackageManagerInternal packageManagerInternal; 77 public final UserManagerForMock userManagerForMock; 78 public final PowerManagerForMock powerManager; 79 public final PowerManagerInternal powerManagerInternal; 80 public final RecoverySystemForMock recoverySystem; 81 public final NotificationManager notificationManager; 82 public final IIpConnectivityMetrics iipConnectivityMetrics; 83 public final IWindowManager iwindowManager; 84 public final IActivityManager iactivityManager; 85 public final IPackageManager ipackageManager; 86 public final IBackupManager ibackupManager; 87 public final IAudioService iaudioService; 88 public final LockPatternUtils lockPatternUtils; 89 public final StorageManagerForMock storageManager; 90 public final WifiManager wifiManager; 91 public final SettingsForMock settings; 92 public final MockContentResolver contentResolver; 93 public final TelephonyManager telephonyManager; 94 public final AccountManager accountManager; 95 public final AlarmManager alarmManager; 96 public final KeyChain.KeyChainConnection keyChainConnection; 97 /** Note this is a partial mock, not a real mock. */ 98 public final PackageManager packageManager; 99 public final BuildMock buildMock = new BuildMock(); 100 public final File dataDir; 101 102 public MockSystemServices(Context realContext, String name) { 103 dataDir = new File(realContext.getCacheDir(), name); 104 DpmTestUtils.clearDir(dataDir); 105 106 environment = mock(EnvironmentForMock.class); 107 systemProperties = mock(SystemPropertiesForMock.class); 108 userManager = mock(UserManager.class); 109 userManagerInternal = mock(UserManagerInternal.class); 110 userManagerForMock = mock(UserManagerForMock.class); 111 packageManagerInternal = mock(PackageManagerInternal.class); 112 powerManager = mock(PowerManagerForMock.class); 113 powerManagerInternal = mock(PowerManagerInternal.class); 114 recoverySystem = mock(RecoverySystemForMock.class); 115 notificationManager = mock(NotificationManager.class); 116 iipConnectivityMetrics = mock(IIpConnectivityMetrics.class); 117 iwindowManager = mock(IWindowManager.class); 118 iactivityManager = mock(IActivityManager.class); 119 ipackageManager = mock(IPackageManager.class); 120 ibackupManager = mock(IBackupManager.class); 121 iaudioService = mock(IAudioService.class); 122 lockPatternUtils = mock(LockPatternUtils.class); 123 storageManager = mock(StorageManagerForMock.class); 124 wifiManager = mock(WifiManager.class); 125 settings = mock(SettingsForMock.class); 126 telephonyManager = mock(TelephonyManager.class); 127 accountManager = mock(AccountManager.class); 128 alarmManager = mock(AlarmManager.class); 129 keyChainConnection = mock(KeyChain.KeyChainConnection.class, RETURNS_DEEP_STUBS); 130 131 // Package manager is huge, so we use a partial mock instead. 132 packageManager = spy(realContext.getPackageManager()); 133 134 contentResolver = new MockContentResolver(); 135 contentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider()); 136 137 // Add the system user with a fake profile group already set up (this can happen in the real 138 // world if a managed profile is added and then removed). 139 systemUserDataDir = 140 addUser(UserHandle.USER_SYSTEM, UserInfo.FLAG_PRIMARY, UserHandle.USER_SYSTEM); 141 142 // System user is always running. 143 setUserRunning(UserHandle.USER_SYSTEM, true); 144 } 145 146 /** Optional mapping of other user contexts for {@link #createPackageContextAsUser} to return */ 147 private final Map<Pair<UserHandle, String>, Context> userPackageContexts = new ArrayMap<>(); 148 149 private final ArrayList<UserInfo> mUserInfos = new ArrayList<>(); 150 151 private final List<BroadcastReceiverRegistration> mBroadcastReceivers = new ArrayList<>(); 152 153 public void registerReceiver( 154 BroadcastReceiver receiver, IntentFilter filter, Handler scheduler) { 155 mBroadcastReceivers.add(new BroadcastReceiverRegistration(receiver, filter, scheduler)); 156 } 157 158 public void unregisterReceiver(BroadcastReceiver receiver) { 159 mBroadcastReceivers.removeIf(r -> r.receiver == receiver); 160 } 161 162 public File addUser(int userId, int flags) { 163 return addUser(userId, flags, UserInfo.NO_PROFILE_GROUP_ID); 164 } 165 166 public File addUser(int userId, int flags, int profileGroupId) { 167 // Set up (default) UserInfo for CALLER_USER_HANDLE. 168 final UserInfo uh = new UserInfo(userId, "user" + userId, flags); 169 uh.profileGroupId = profileGroupId; 170 when(userManager.getUserInfo(eq(userId))).thenReturn(uh); 171 172 mUserInfos.add(uh); 173 when(userManager.getUsers()).thenReturn(mUserInfos); 174 when(userManager.getUsers(anyBoolean())).thenReturn(mUserInfos); 175 when(userManager.isUserRunning(eq(new UserHandle(userId)))).thenReturn(true); 176 when(userManager.getUserInfo(anyInt())).thenAnswer( 177 invocation -> { 178 final int userId1 = (int) invocation.getArguments()[0]; 179 return getUserInfo(userId1); 180 } 181 ); 182 when(userManager.getProfiles(anyInt())).thenAnswer( 183 invocation -> { 184 final int userId12 = (int) invocation.getArguments()[0]; 185 return getProfiles(userId12); 186 } 187 ); 188 when(userManager.getProfileIdsWithDisabled(anyInt())).thenAnswer( 189 invocation -> { 190 final int userId13 = (int) invocation.getArguments()[0]; 191 List<UserInfo> profiles = getProfiles(userId13); 192 return profiles.stream() 193 .mapToInt(profile -> profile.id) 194 .toArray(); 195 } 196 ); 197 when(accountManager.getAccountsAsUser(anyInt())).thenReturn(new Account[0]); 198 199 // Create a data directory. 200 final File dir = new File(dataDir, "users/" + userId); 201 DpmTestUtils.clearDir(dir); 202 203 when(environment.getUserSystemDirectory(eq(userId))).thenReturn(dir); 204 return dir; 205 } 206 207 public void removeUser(int userId) { 208 for (int i = 0; i < mUserInfos.size(); i++) { 209 if (mUserInfos.get(i).id == userId) { 210 mUserInfos.remove(i); 211 break; 212 } 213 } 214 when(userManager.getUserInfo(eq(userId))).thenReturn(null); 215 216 when(userManager.isUserRunning(eq(new UserHandle(userId)))).thenReturn(false); 217 } 218 219 private UserInfo getUserInfo(int userId) { 220 for (final UserInfo ui : mUserInfos) { 221 if (ui.id == userId) { 222 return ui; 223 } 224 } 225 return null; 226 } 227 228 private List<UserInfo> getProfiles(int userId) { 229 final ArrayList<UserInfo> ret = new ArrayList<>(); 230 UserInfo parent = null; 231 for (final UserInfo ui : mUserInfos) { 232 if (ui.id == userId) { 233 parent = ui; 234 break; 235 } 236 } 237 if (parent == null) { 238 return ret; 239 } 240 for (final UserInfo ui : mUserInfos) { 241 if (ui == parent 242 || ui.profileGroupId != UserInfo.NO_PROFILE_GROUP_ID 243 && ui.profileGroupId == parent.profileGroupId) { 244 ret.add(ui); 245 } 246 } 247 return ret; 248 } 249 250 /** 251 * Add multiple users at once. They'll all have flag 0. 252 */ 253 public void addUsers(int... userIds) { 254 for (final int userId : userIds) { 255 addUser(userId, 0); 256 } 257 } 258 259 public void setUserRunning(int userId, boolean isRunning) { 260 when(userManager.isUserRunning(MockUtils.checkUserHandle(userId))) 261 .thenReturn(isRunning); 262 } 263 264 public void injectBroadcast(Context context, final Intent intent, int userId) { 265 //final int userId = UserHandle.getUserId(binder.getCallingUid()); 266 for (final BroadcastReceiverRegistration receiver : mBroadcastReceivers) { 267 receiver.sendBroadcastIfApplicable(context, userId, intent); 268 } 269 } 270 271 public void rethrowBackgroundBroadcastExceptions() throws Exception { 272 for (final BroadcastReceiverRegistration receiver : mBroadcastReceivers) { 273 final Exception e = receiver.backgroundException.getAndSet(null); 274 if (e != null) { 275 throw e; 276 } 277 } 278 } 279 280 public void addPackageContext(UserHandle user, Context context) { 281 if (context.getPackageName() == null) { 282 throw new NullPointerException("getPackageName() == null"); 283 } 284 userPackageContexts.put(new Pair<>(user, context.getPackageName()), context); 285 } 286 287 public Context createPackageContextAsUser(String packageName, int flags, UserHandle user) 288 throws PackageManager.NameNotFoundException { 289 final Pair<UserHandle, String> key = new Pair<>(user, packageName); 290 if (userPackageContexts.containsKey(key)) { 291 return userPackageContexts.get(key); 292 } 293 throw new UnsupportedOperationException("No package " + packageName + " for user " + user); 294 } 295 296 297 public static class EnvironmentForMock { 298 public File getUserSystemDirectory(int userId) { 299 return null; 300 } 301 } 302 303 public static class BuildMock { 304 public boolean isDebuggable = true; 305 } 306 307 public static class PowerManagerForMock { 308 public PowerManager.WakeLock newWakeLock(int levelAndFlags, String tag) { 309 return null; 310 } 311 312 public void goToSleep(long time, int reason, int flags) { 313 } 314 315 public void reboot(String reason) { 316 } 317 } 318 319 public static class RecoverySystemForMock { 320 public void rebootWipeUserData(boolean shutdown, String reason, boolean force, 321 boolean wipeEuicc) throws IOException { 322 } 323 } 324 325 public static class SystemPropertiesForMock { 326 public boolean getBoolean(String key, boolean def) { 327 return false; 328 } 329 330 public long getLong(String key, long def) { 331 return 0; 332 } 333 334 public String get(String key, String def) { 335 return null; 336 } 337 338 public String get(String key) { 339 return null; 340 } 341 342 public void set(String key, String value) { 343 } 344 } 345 346 public static class UserManagerForMock { 347 public boolean isSplitSystemUser() { 348 return false; 349 } 350 } 351 352 public static class SettingsForMock { 353 public int settingsSecureGetIntForUser(String name, int def, int userHandle) { 354 return 0; 355 } 356 357 public String settingsSecureGetStringForUser(String name, int userHandle) { 358 return null; 359 } 360 361 public void settingsSecurePutIntForUser(String name, int value, int userHandle) { 362 } 363 364 public void settingsSecurePutStringForUser(String name, String value, int userHandle) { 365 } 366 367 public void settingsGlobalPutStringForUser(String name, String value, int userHandle) { 368 } 369 370 public void settingsSecurePutInt(String name, int value) { 371 } 372 373 public void settingsGlobalPutInt(String name, int value) { 374 } 375 376 public void settingsSecurePutString(String name, String value) { 377 } 378 379 public void settingsGlobalPutString(String name, String value) { 380 } 381 382 public int settingsGlobalGetInt(String name, int value) { 383 return 0; 384 } 385 386 public String settingsGlobalGetString(String name) { 387 return ""; 388 } 389 390 public void securityLogSetLoggingEnabledProperty(boolean enabled) { 391 } 392 393 public boolean securityLogGetLoggingEnabledProperty() { 394 return false; 395 } 396 397 public boolean securityLogIsLoggingEnabled() { 398 return false; 399 } 400 } 401 402 public static class StorageManagerForMock { 403 public boolean isFileBasedEncryptionEnabled() { 404 return false; 405 } 406 407 public boolean isNonDefaultBlockEncrypted() { 408 return false; 409 } 410 411 public boolean isEncrypted() { 412 return false; 413 } 414 415 public boolean isEncryptable() { 416 return false; 417 } 418 } 419 420 // We have to keep track of broadcast receivers registered for a given intent ourselves as the 421 // DPM unit tests mock out the package manager and PackageManager.queryBroadcastReceivers() does 422 // not work. 423 private static class BroadcastReceiverRegistration { 424 public final BroadcastReceiver receiver; 425 public final IntentFilter filter; 426 public final Handler scheduler; 427 428 // Exceptions thrown in a background thread kill the whole test. Save them instead. 429 public final AtomicReference<Exception> backgroundException = new AtomicReference<>(); 430 431 public BroadcastReceiverRegistration(BroadcastReceiver receiver, IntentFilter filter, 432 Handler scheduler) { 433 this.receiver = receiver; 434 this.filter = filter; 435 this.scheduler = scheduler; 436 } 437 438 public void sendBroadcastIfApplicable(Context context, int userId, Intent intent) { 439 final BroadcastReceiver.PendingResult result = new BroadcastReceiver.PendingResult( 440 0 /* resultCode */, null /* resultData */, null /* resultExtras */, 441 0 /* type */, false /* ordered */, false /* sticky */, null /* token */, userId, 442 0 /* flags */); 443 if (filter.match(null, intent, false, "DpmMockContext") > 0) { 444 final Runnable send = () -> { 445 receiver.setPendingResult(result); 446 receiver.onReceive(context, intent); 447 }; 448 if (scheduler != null) { 449 scheduler.post(() -> { 450 try { 451 send.run(); 452 } catch (Exception e) { 453 backgroundException.compareAndSet(null, e); 454 } 455 }); 456 } else { 457 send.run(); 458 } 459 } 460 } 461 } 462 } 463