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 17 package com.android.server.am; 18 19 import static android.app.ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE; 20 import static android.app.ActivityManager.PROCESS_STATE_CACHED_ACTIVITY; 21 import static android.app.ActivityManager.PROCESS_STATE_CACHED_EMPTY; 22 import static android.app.ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE; 23 import static android.app.ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND; 24 import static android.app.ActivityManager.PROCESS_STATE_LAST_ACTIVITY; 25 import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT; 26 import static android.app.ActivityManager.PROCESS_STATE_RECEIVER; 27 import static android.app.ActivityManager.PROCESS_STATE_SERVICE; 28 import static android.app.ActivityManager.PROCESS_STATE_TOP; 29 import static android.app.ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND; 30 import static android.app.ActivityManager.PROCESS_STATE_UNKNOWN; 31 import static android.util.DebugUtils.valueToString; 32 33 import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; 34 35 import static com.android.server.am.ActivityManagerInternalTest.CustomThread; 36 import static com.android.server.am.ActivityManagerService.Injector; 37 import static com.android.server.am.ProcessList.NETWORK_STATE_BLOCK; 38 import static com.android.server.am.ProcessList.NETWORK_STATE_NO_CHANGE; 39 import static com.android.server.am.ProcessList.NETWORK_STATE_UNBLOCK; 40 41 import static com.google.common.truth.Truth.assertThat; 42 import static com.google.common.truth.Truth.assertWithMessage; 43 44 import static org.junit.Assert.assertEquals; 45 import static org.junit.Assert.assertFalse; 46 import static org.junit.Assert.assertNotEquals; 47 import static org.junit.Assert.assertNotNull; 48 import static org.junit.Assert.assertNull; 49 import static org.junit.Assert.assertThrows; 50 import static org.junit.Assert.assertTrue; 51 import static org.junit.Assert.fail; 52 import static org.mockito.ArgumentMatchers.any; 53 import static org.mockito.ArgumentMatchers.anyBoolean; 54 import static org.mockito.ArgumentMatchers.anyInt; 55 import static org.mockito.ArgumentMatchers.eq; 56 import static org.mockito.ArgumentMatchers.nullable; 57 import static org.mockito.Mockito.doAnswer; 58 import static org.mockito.Mockito.doReturn; 59 import static org.mockito.Mockito.mock; 60 import static org.mockito.Mockito.verify; 61 import static org.mockito.Mockito.verifyNoMoreInteractions; 62 import static org.mockito.Mockito.verifyZeroInteractions; 63 import static org.mockito.Mockito.when; 64 65 import android.Manifest; 66 import android.app.ActivityManager; 67 import android.app.AppOpsManager; 68 import android.app.BroadcastOptions; 69 import android.app.IApplicationThread; 70 import android.app.IUidObserver; 71 import android.app.SyncNotedAppOp; 72 import android.content.ComponentName; 73 import android.content.Context; 74 import android.content.Intent; 75 import android.content.pm.ApplicationInfo; 76 import android.content.pm.PackageManagerInternal; 77 import android.os.Bundle; 78 import android.os.Handler; 79 import android.os.HandlerThread; 80 import android.os.IBinder; 81 import android.os.IProgressListener; 82 import android.os.Looper; 83 import android.os.Message; 84 import android.os.Process; 85 import android.os.RemoteException; 86 import android.os.SystemClock; 87 import android.platform.test.annotations.Presubmit; 88 import android.provider.DeviceConfig; 89 import android.util.IntArray; 90 import android.util.Log; 91 import android.util.Pair; 92 93 import androidx.test.filters.MediumTest; 94 import androidx.test.filters.SmallTest; 95 import androidx.test.platform.app.InstrumentationRegistry; 96 97 import com.android.dx.mockito.inline.extended.ExtendedMockito; 98 import com.android.server.LocalServices; 99 import com.android.server.am.ActivityManagerService.StickyBroadcast; 100 import com.android.server.am.ProcessList.IsolatedUidRange; 101 import com.android.server.am.ProcessList.IsolatedUidRangeAllocator; 102 import com.android.server.am.UidObserverController.ChangeRecord; 103 import com.android.server.appop.AppOpsService; 104 import com.android.server.wm.ActivityTaskManagerService; 105 106 import org.junit.After; 107 import org.junit.AfterClass; 108 import org.junit.Before; 109 import org.junit.BeforeClass; 110 import org.junit.Rule; 111 import org.junit.Test; 112 import org.mockito.Mock; 113 import org.mockito.Mockito; 114 import org.mockito.MockitoAnnotations; 115 import org.mockito.MockitoSession; 116 117 import java.io.File; 118 import java.util.ArrayList; 119 import java.util.Arrays; 120 import java.util.HashMap; 121 import java.util.HashSet; 122 import java.util.List; 123 import java.util.Map; 124 import java.util.Objects; 125 import java.util.Set; 126 import java.util.function.Function; 127 128 /** 129 * Test class for {@link ActivityManagerService}. 130 * 131 * Build/Install/Run: 132 * atest FrameworksServicesTests:ActivityManagerServiceTest 133 */ 134 @Presubmit 135 @SmallTest 136 public class ActivityManagerServiceTest { 137 private static final String TAG = ActivityManagerServiceTest.class.getSimpleName(); 138 139 private static final int TEST_USER = 11; 140 141 private static final String TEST_ACTION1 = "com.android.server.am.TEST_ACTION1"; 142 private static final String TEST_ACTION2 = "com.android.server.am.TEST_ACTION2"; 143 private static final String TEST_ACTION3 = "com.android.server.am.TEST_ACTION3"; 144 145 private static final String TEST_EXTRA_KEY1 = "com.android.server.am.TEST_EXTRA_KEY1"; 146 private static final String TEST_EXTRA_VALUE1 = "com.android.server.am.TEST_EXTRA_VALUE1"; 147 private static final String PROPERTY_APPLY_SDK_SANDBOX_NEXT_RESTRICTIONS = 148 "apply_sdk_sandbox_next_restrictions"; 149 private static final String APPLY_SDK_SANDBOX_NEXT_RESTRICTIONS = ":isSdkSandboxNext"; 150 private static final int TEST_UID = 11111; 151 private static final int USER_ID = 666; 152 153 private static final long TEST_PROC_STATE_SEQ1 = 555; 154 private static final long TEST_PROC_STATE_SEQ2 = 556; 155 156 private static final int[] UID_RECORD_CHANGES = { 157 UidRecord.CHANGE_PROCSTATE, 158 UidRecord.CHANGE_GONE, 159 UidRecord.CHANGE_GONE | UidRecord.CHANGE_IDLE, 160 UidRecord.CHANGE_IDLE, 161 UidRecord.CHANGE_ACTIVE, 162 UidRecord.CHANGE_CAPABILITY, 163 }; 164 165 private static PackageManagerInternal sPackageManagerInternal; 166 private static ProcessList.ProcessListSettingsListener sProcessListSettingsListener; 167 168 @BeforeClass setUpOnce()169 public static void setUpOnce() { 170 sPackageManagerInternal = mock(PackageManagerInternal.class); 171 doReturn(new ComponentName("", "")).when(sPackageManagerInternal) 172 .getSystemUiServiceComponent(); 173 LocalServices.addService(PackageManagerInternal.class, sPackageManagerInternal); 174 } 175 176 @AfterClass tearDownOnce()177 public static void tearDownOnce() { 178 LocalServices.removeServiceForTest(PackageManagerInternal.class); 179 } 180 181 @Rule 182 public final ApplicationExitInfoTest.ServiceThreadRule 183 mServiceThreadRule = new ApplicationExitInfoTest.ServiceThreadRule(); 184 185 private Context mContext = getInstrumentation().getTargetContext(); 186 187 @Mock private AppOpsService mAppOpsService; 188 @Mock private UserController mUserController; 189 190 private TestInjector mInjector; 191 private ActivityManagerService mAms; 192 private HandlerThread mHandlerThread; 193 private TestHandler mHandler; 194 @Before setUp()195 public void setUp() { 196 MockitoAnnotations.initMocks(this); 197 198 mHandlerThread = new HandlerThread(TAG); 199 mHandlerThread.start(); 200 mHandler = new TestHandler(mHandlerThread.getLooper()); 201 mInjector = new TestInjector(mContext); 202 doAnswer(invocation -> { 203 final int userId = invocation.getArgument(2); 204 return userId; 205 }).when(mUserController).handleIncomingUser(anyInt(), anyInt(), anyInt(), anyBoolean(), 206 anyInt(), any(), any()); 207 doReturn(true).when(mUserController).isUserOrItsParentRunning(anyInt()); 208 mAms = new ActivityManagerService(mInjector, mServiceThreadRule.getThread(), 209 mUserController); 210 mAms.mConstants.mNetworkAccessTimeoutMs = 2000; 211 mAms.mActivityTaskManager = new ActivityTaskManagerService(mContext); 212 mAms.mActivityTaskManager.initialize(null, null, mHandler.getLooper()); 213 mHandler.setRunnablesToIgnore( 214 List.of(mAms.mUidObserverController.getDispatchRunnableForTest())); 215 216 // Required for updating DeviceConfig. 217 InstrumentationRegistry.getInstrumentation() 218 .getUiAutomation() 219 .adoptShellPermissionIdentity( 220 Manifest.permission.READ_DEVICE_CONFIG, 221 Manifest.permission.WRITE_DEVICE_CONFIG); 222 sProcessListSettingsListener = mAms.mProcessList.getProcessListSettingsListener(); 223 assertThat(sProcessListSettingsListener).isNotNull(); 224 } 225 mockNoteOperation()226 private void mockNoteOperation() { 227 SyncNotedAppOp allowed = new SyncNotedAppOp(AppOpsManager.MODE_ALLOWED, 228 AppOpsManager.OP_GET_USAGE_STATS, null, mContext.getPackageName()); 229 when(mAppOpsService.noteOperation(eq(AppOpsManager.OP_GET_USAGE_STATS), eq(Process.myUid()), 230 nullable(String.class), nullable(String.class), any(Boolean.class), 231 nullable(String.class), any(Boolean.class))).thenReturn(allowed); 232 } 233 234 @After tearDown()235 public void tearDown() { 236 mHandlerThread.quit(); 237 InstrumentationRegistry.getInstrumentation() 238 .getUiAutomation() 239 .dropShellPermissionIdentity(); 240 if (sProcessListSettingsListener != null) { 241 sProcessListSettingsListener.unregisterObserver(); 242 } 243 } 244 245 @SuppressWarnings("GuardedBy") 246 @MediumTest 247 @Test incrementProcStateSeqAndNotifyAppsLocked()248 public void incrementProcStateSeqAndNotifyAppsLocked() throws Exception { 249 250 final UidRecord uidRec = addUidRecord(TEST_UID); 251 addUidRecord(TEST_UID + 1); 252 253 // Uid state is not moving from background to foreground or vice versa. 254 verifySeqCounterAndInteractions(uidRec, 255 PROCESS_STATE_TOP, // prevState 256 PROCESS_STATE_TOP, // curState 257 NETWORK_STATE_NO_CHANGE, // expectedBlockState 258 false); // expectNotify 259 260 // Uid state is moving from foreground to background. 261 verifySeqCounterAndInteractions(uidRec, 262 PROCESS_STATE_FOREGROUND_SERVICE, // prevState 263 PROCESS_STATE_SERVICE, // curState 264 NETWORK_STATE_UNBLOCK, // expectedBlockState 265 true); // expectNotify 266 267 // Explicitly setting the seq counter for more verification. 268 // @SuppressWarnings("GuardedBy") 269 mAms.mProcessList.mProcStateSeqCounter = 42; 270 271 // Uid state is not moving from background to foreground or vice versa. 272 verifySeqCounterAndInteractions(uidRec, 273 PROCESS_STATE_TRANSIENT_BACKGROUND, // prevState 274 PROCESS_STATE_IMPORTANT_BACKGROUND, // curState 275 NETWORK_STATE_NO_CHANGE, // expectedBlockState 276 false); // expectNotify 277 278 // Uid state is moving from background to foreground. 279 verifySeqCounterAndInteractions(uidRec, 280 PROCESS_STATE_LAST_ACTIVITY, // prevState 281 PROCESS_STATE_TOP, // curState 282 NETWORK_STATE_BLOCK, // expectedBlockState 283 false); // expectNotify 284 285 // verify waiting threads are not notified. 286 uidRec.procStateSeqWaitingForNetwork = 0; 287 // Uid state is moving from foreground to background. 288 verifySeqCounterAndInteractions(uidRec, 289 PROCESS_STATE_FOREGROUND_SERVICE, // prevState 290 PROCESS_STATE_SERVICE, // curState 291 NETWORK_STATE_UNBLOCK, // expectedBlockState 292 false); // expectNotify 293 } 294 295 @SuppressWarnings("GuardedBy") 296 @SmallTest 297 @Test defaultSdkSandboxNextRestrictions()298 public void defaultSdkSandboxNextRestrictions() throws Exception { 299 sProcessListSettingsListener.onPropertiesChanged( 300 new DeviceConfig.Properties( 301 DeviceConfig.NAMESPACE_ADSERVICES, 302 Map.of(PROPERTY_APPLY_SDK_SANDBOX_NEXT_RESTRICTIONS, ""))); 303 assertThat( 304 sProcessListSettingsListener.applySdkSandboxRestrictionsNext()) 305 .isFalse(); 306 } 307 308 @SuppressWarnings("GuardedBy") 309 @SmallTest 310 @Test doNotApplySdkSandboxNextRestrictions()311 public void doNotApplySdkSandboxNextRestrictions() throws Exception { 312 MockitoSession mockitoSession = 313 ExtendedMockito.mockitoSession().spyStatic(Process.class).startMocking(); 314 try { 315 sProcessListSettingsListener.onPropertiesChanged( 316 new DeviceConfig.Properties( 317 DeviceConfig.NAMESPACE_ADSERVICES, 318 Map.of(PROPERTY_APPLY_SDK_SANDBOX_NEXT_RESTRICTIONS, "false"))); 319 assertThat( 320 sProcessListSettingsListener.applySdkSandboxRestrictionsNext()) 321 .isFalse(); 322 ExtendedMockito.doReturn(true).when(() -> Process.isSdkSandboxUid(anyInt())); 323 ApplicationInfo info = new ApplicationInfo(); 324 info.packageName = "com.android.sdksandbox"; 325 info.seInfo = "default:targetSdkVersion=34:complete"; 326 final ProcessRecord appRec = new ProcessRecord( 327 mAms, info, TAG, Process.FIRST_SDK_SANDBOX_UID, 328 /* sdkSandboxClientPackageName= */ "com.example.client", 329 /* definingUid= */ 0, /* definingProcessName= */ ""); 330 assertThat(mAms.mProcessList.updateSeInfo(appRec)).doesNotContain( 331 APPLY_SDK_SANDBOX_NEXT_RESTRICTIONS); 332 } finally { 333 mockitoSession.finishMocking(); 334 } 335 } 336 @SuppressWarnings("GuardedBy") 337 @SmallTest 338 @Test applySdkSandboxNextRestrictions()339 public void applySdkSandboxNextRestrictions() throws Exception { 340 MockitoSession mockitoSession = 341 ExtendedMockito.mockitoSession().spyStatic(Process.class).startMocking(); 342 try { 343 sProcessListSettingsListener.onPropertiesChanged( 344 new DeviceConfig.Properties( 345 DeviceConfig.NAMESPACE_ADSERVICES, 346 Map.of(PROPERTY_APPLY_SDK_SANDBOX_NEXT_RESTRICTIONS, "true"))); 347 assertThat( 348 sProcessListSettingsListener.applySdkSandboxRestrictionsNext()) 349 .isTrue(); 350 ExtendedMockito.doReturn(true).when(() -> Process.isSdkSandboxUid(anyInt())); 351 ApplicationInfo info = new ApplicationInfo(); 352 info.packageName = "com.android.sdksandbox"; 353 info.seInfo = "default:targetSdkVersion=34:complete"; 354 final ProcessRecord appRec = new ProcessRecord( 355 mAms, info, TAG, Process.FIRST_SDK_SANDBOX_UID, 356 /* sdkSandboxClientPackageName= */ "com.example.client", 357 /* definingUid= */ 0, /* definingProcessName= */ ""); 358 assertThat(mAms.mProcessList.updateSeInfo(appRec)).contains( 359 APPLY_SDK_SANDBOX_NEXT_RESTRICTIONS); 360 } finally { 361 mockitoSession.finishMocking(); 362 } 363 } 364 365 addUidRecord(int uid)366 private UidRecord addUidRecord(int uid) { 367 final UidRecord uidRec = new UidRecord(uid, mAms); 368 uidRec.procStateSeqWaitingForNetwork = 1; 369 uidRec.hasInternetPermission = true; 370 mAms.mProcessList.mActiveUids.put(uid, uidRec); 371 372 ApplicationInfo info = new ApplicationInfo(); 373 info.packageName = ""; 374 375 final ProcessRecord appRec = new ProcessRecord(mAms, info, TAG, uid); 376 final ProcessStatsService tracker = new ProcessStatsService(mAms, mContext.getCacheDir()); 377 appRec.makeActive(mock(IApplicationThread.class), tracker); 378 mAms.mProcessList.getLruProcessesLSP().add(appRec); 379 380 return uidRec; 381 } 382 383 @SuppressWarnings("GuardedBy") verifySeqCounterAndInteractions(UidRecord uidRec, int prevState, int curState, int expectedBlockState, boolean expectNotify)384 private void verifySeqCounterAndInteractions(UidRecord uidRec, int prevState, int curState, 385 int expectedBlockState, boolean expectNotify) throws Exception { 386 CustomThread thread = new CustomThread(uidRec.networkStateLock); 387 thread.startAndWait("Unexpected state for " + uidRec); 388 389 uidRec.setSetProcState(prevState); 390 uidRec.setCurProcState(curState); 391 final long beforeProcStateSeq = mAms.mProcessList.mProcStateSeqCounter; 392 393 mAms.mProcessList.incrementProcStateSeqAndNotifyAppsLOSP(mAms.mProcessList.mActiveUids); 394 395 final long afterProcStateSeq = beforeProcStateSeq 396 + mAms.mProcessList.mActiveUids.size(); 397 assertEquals("beforeProcStateSeq=" + beforeProcStateSeq 398 + ",activeUids.size=" + mAms.mProcessList.mActiveUids.size(), 399 afterProcStateSeq, mAms.mProcessList.mProcStateSeqCounter); 400 assertTrue("beforeProcStateSeq=" + beforeProcStateSeq 401 + ",afterProcStateSeq=" + afterProcStateSeq 402 + ",uidCurProcStateSeq=" + uidRec.curProcStateSeq, 403 uidRec.curProcStateSeq > beforeProcStateSeq 404 && uidRec.curProcStateSeq <= afterProcStateSeq); 405 406 for (int i = mAms.mProcessList.getLruSizeLOSP() - 1; i >= 0; --i) { 407 final ProcessRecord app = mAms.mProcessList.getLruProcessesLOSP().get(i); 408 // AMS should notify apps only for block states other than NETWORK_STATE_NO_CHANGE. 409 if (app.uid == uidRec.getUid() && expectedBlockState == NETWORK_STATE_BLOCK) { 410 verify(app.getThread()).setNetworkBlockSeq(uidRec.curProcStateSeq); 411 } else { 412 verifyZeroInteractions(app.getThread()); 413 } 414 Mockito.reset(app.getThread()); 415 } 416 417 if (expectNotify) { 418 thread.assertTerminated("Unexpected state for " + uidRec); 419 } else { 420 thread.assertWaiting("Unexpected state for " + uidRec); 421 thread.interrupt(); 422 } 423 } 424 validateAppZygoteIsolatedUidRange(IsolatedUidRange uidRange)425 private void validateAppZygoteIsolatedUidRange(IsolatedUidRange uidRange) { 426 assertNotNull(uidRange); 427 assertTrue(uidRange.mFirstUid >= Process.FIRST_APP_ZYGOTE_ISOLATED_UID 428 && uidRange.mFirstUid <= Process.LAST_APP_ZYGOTE_ISOLATED_UID); 429 assertTrue(uidRange.mLastUid >= Process.FIRST_APP_ZYGOTE_ISOLATED_UID 430 && uidRange.mLastUid <= Process.LAST_APP_ZYGOTE_ISOLATED_UID); 431 assertTrue(uidRange.mLastUid > uidRange.mFirstUid 432 && ((uidRange.mLastUid - uidRange.mFirstUid + 1) 433 == Process.NUM_UIDS_PER_APP_ZYGOTE)); 434 } 435 verifyUidRangesNoOverlap(IsolatedUidRange uidRange1, IsolatedUidRange uidRange2)436 private void verifyUidRangesNoOverlap(IsolatedUidRange uidRange1, IsolatedUidRange uidRange2) { 437 IsolatedUidRange lowRange = uidRange1.mFirstUid <= uidRange2.mFirstUid 438 ? uidRange1 : uidRange2; 439 IsolatedUidRange highRange = lowRange == uidRange1 ? uidRange2 : uidRange1; 440 441 assertTrue(highRange.mFirstUid > lowRange.mLastUid); 442 } 443 444 @Test testIsolatedUidRangeAllocator()445 public void testIsolatedUidRangeAllocator() { 446 final IsolatedUidRangeAllocator allocator = mAms.mProcessList.mAppIsolatedUidRangeAllocator; 447 448 // Create initial range 449 ApplicationInfo appInfo = new ApplicationInfo(); 450 appInfo.processName = "com.android.test.app"; 451 appInfo.uid = 10000; 452 final IsolatedUidRange range = allocator.getOrCreateIsolatedUidRangeLocked( 453 appInfo.processName, appInfo.uid); 454 validateAppZygoteIsolatedUidRange(range); 455 verifyIsolatedUidAllocator(range); 456 457 // Create a second range 458 ApplicationInfo appInfo2 = new ApplicationInfo(); 459 appInfo2.processName = "com.android.test.app2"; 460 appInfo2.uid = 10001; 461 IsolatedUidRange range2 = allocator.getOrCreateIsolatedUidRangeLocked( 462 appInfo2.processName, appInfo2.uid); 463 validateAppZygoteIsolatedUidRange(range2); 464 verifyIsolatedUidAllocator(range2); 465 466 // Verify ranges don't overlap 467 verifyUidRangesNoOverlap(range, range2); 468 469 // Free range, reallocate and verify 470 allocator.freeUidRangeLocked(appInfo2); 471 range2 = allocator.getOrCreateIsolatedUidRangeLocked(appInfo2.processName, appInfo2.uid); 472 validateAppZygoteIsolatedUidRange(range2); 473 verifyUidRangesNoOverlap(range, range2); 474 verifyIsolatedUidAllocator(range2); 475 476 // Free both 477 allocator.freeUidRangeLocked(appInfo); 478 allocator.freeUidRangeLocked(appInfo2); 479 480 // Verify for a secondary user 481 ApplicationInfo appInfo3 = new ApplicationInfo(); 482 appInfo3.processName = "com.android.test.app"; 483 appInfo3.uid = 1010000; 484 final IsolatedUidRange range3 = allocator.getOrCreateIsolatedUidRangeLocked( 485 appInfo3.processName, appInfo3.uid); 486 validateAppZygoteIsolatedUidRange(range3); 487 verifyIsolatedUidAllocator(range3); 488 489 allocator.freeUidRangeLocked(appInfo3); 490 // Try to allocate the maximum number of UID ranges 491 int maxNumUidRanges = (Process.LAST_APP_ZYGOTE_ISOLATED_UID 492 - Process.FIRST_APP_ZYGOTE_ISOLATED_UID + 1) / Process.NUM_UIDS_PER_APP_ZYGOTE; 493 for (int i = 0; i < maxNumUidRanges; i++) { 494 appInfo = new ApplicationInfo(); 495 appInfo.uid = 10000 + i; 496 appInfo.processName = "com.android.test.app" + Integer.toString(i); 497 IsolatedUidRange uidRange = allocator.getOrCreateIsolatedUidRangeLocked( 498 appInfo.processName, appInfo.uid); 499 validateAppZygoteIsolatedUidRange(uidRange); 500 verifyIsolatedUidAllocator(uidRange); 501 } 502 503 // Try to allocate another one and make sure it fails 504 appInfo = new ApplicationInfo(); 505 appInfo.uid = 9000; 506 appInfo.processName = "com.android.test.app.failed"; 507 IsolatedUidRange failedRange = allocator.getOrCreateIsolatedUidRangeLocked( 508 appInfo.processName, appInfo.uid); 509 510 assertNull(failedRange); 511 } 512 verifyIsolatedUid(ProcessList.IsolatedUidRange range, int uid)513 public void verifyIsolatedUid(ProcessList.IsolatedUidRange range, int uid) { 514 assertTrue(uid >= range.mFirstUid && uid <= range.mLastUid); 515 } 516 verifyIsolatedUidAllocator(ProcessList.IsolatedUidRange range)517 public void verifyIsolatedUidAllocator(ProcessList.IsolatedUidRange range) { 518 int uid = range.allocateIsolatedUidLocked(0); 519 verifyIsolatedUid(range, uid); 520 521 int uid2 = range.allocateIsolatedUidLocked(0); 522 verifyIsolatedUid(range, uid2); 523 assertTrue(uid2 != uid); 524 525 // Free both 526 range.freeIsolatedUidLocked(uid); 527 range.freeIsolatedUidLocked(uid2); 528 529 // Allocate the entire range 530 for (int i = 0; i < (range.mLastUid - range.mFirstUid + 1); ++i) { 531 uid = range.allocateIsolatedUidLocked(0); 532 verifyIsolatedUid(range, uid); 533 } 534 535 // Ensure the next one fails 536 uid = range.allocateIsolatedUidLocked(0); 537 assertEquals(uid, -1); 538 } 539 540 @Test testGlobalIsolatedUidAllocator()541 public void testGlobalIsolatedUidAllocator() { 542 final IsolatedUidRange globalUidRange = mAms.mProcessList.mGlobalIsolatedUids; 543 assertEquals(globalUidRange.mFirstUid, Process.FIRST_ISOLATED_UID); 544 assertEquals(globalUidRange.mLastUid, Process.LAST_ISOLATED_UID); 545 verifyIsolatedUidAllocator(globalUidRange); 546 } 547 548 @Test testBlockStateForUid()549 public void testBlockStateForUid() { 550 final UidRecord uidRec = new UidRecord(TEST_UID, mAms); 551 int expectedBlockState; 552 553 final String errorTemplate = "Block state should be %s, prevState: %s, curState: %s"; 554 Function<Integer, String> errorMsg = (blockState) -> { 555 return String.format(errorTemplate, 556 valueToString(ActivityManagerService.class, "NETWORK_STATE_", blockState), 557 valueToString(ActivityManager.class, "PROCESS_STATE_", 558 uidRec.getSetProcState()), 559 valueToString(ActivityManager.class, "PROCESS_STATE_", uidRec.getCurProcState()) 560 ); 561 }; 562 563 // No change in uid state 564 uidRec.setSetProcState(PROCESS_STATE_RECEIVER); 565 uidRec.setCurProcState(PROCESS_STATE_RECEIVER); 566 expectedBlockState = NETWORK_STATE_NO_CHANGE; 567 assertEquals(errorMsg.apply(expectedBlockState), 568 expectedBlockState, mAms.mProcessList.getBlockStateForUid(uidRec)); 569 570 // Foreground to foreground 571 uidRec.setSetProcState(PROCESS_STATE_FOREGROUND_SERVICE); 572 uidRec.setCurProcState(PROCESS_STATE_BOUND_FOREGROUND_SERVICE); 573 expectedBlockState = NETWORK_STATE_NO_CHANGE; 574 assertEquals(errorMsg.apply(expectedBlockState), 575 expectedBlockState, mAms.mProcessList.getBlockStateForUid(uidRec)); 576 577 // Background to background 578 uidRec.setSetProcState(PROCESS_STATE_CACHED_ACTIVITY); 579 uidRec.setCurProcState(PROCESS_STATE_CACHED_EMPTY); 580 expectedBlockState = NETWORK_STATE_NO_CHANGE; 581 assertEquals(errorMsg.apply(expectedBlockState), 582 expectedBlockState, mAms.mProcessList.getBlockStateForUid(uidRec)); 583 584 // Background to background 585 uidRec.setSetProcState(PROCESS_STATE_NONEXISTENT); 586 uidRec.setCurProcState(PROCESS_STATE_CACHED_ACTIVITY); 587 expectedBlockState = NETWORK_STATE_NO_CHANGE; 588 assertEquals(errorMsg.apply(expectedBlockState), 589 expectedBlockState, mAms.mProcessList.getBlockStateForUid(uidRec)); 590 591 // Background to foreground 592 uidRec.setSetProcState(PROCESS_STATE_SERVICE); 593 uidRec.setCurProcState(PROCESS_STATE_FOREGROUND_SERVICE); 594 expectedBlockState = NETWORK_STATE_BLOCK; 595 assertEquals(errorMsg.apply(expectedBlockState), 596 expectedBlockState, mAms.mProcessList.getBlockStateForUid(uidRec)); 597 598 // Foreground to background 599 uidRec.setSetProcState(PROCESS_STATE_TOP); 600 uidRec.setCurProcState(PROCESS_STATE_LAST_ACTIVITY); 601 expectedBlockState = NETWORK_STATE_UNBLOCK; 602 assertEquals(errorMsg.apply(expectedBlockState), 603 expectedBlockState, mAms.mProcessList.getBlockStateForUid(uidRec)); 604 } 605 606 /** 607 * This test verifies that process state changes are dispatched to observers based on the 608 * changes they wanted to listen (this is specified when registering the observer). 609 */ 610 @Test testDispatchUids_dispatchNeededChanges()611 public void testDispatchUids_dispatchNeededChanges() throws RemoteException { 612 mockNoteOperation(); 613 614 final int[] changesToObserve = { 615 ActivityManager.UID_OBSERVER_PROCSTATE, 616 ActivityManager.UID_OBSERVER_GONE, 617 ActivityManager.UID_OBSERVER_IDLE, 618 ActivityManager.UID_OBSERVER_ACTIVE, 619 ActivityManager.UID_OBSERVER_CAPABILITY, 620 ActivityManager.UID_OBSERVER_PROCSTATE | ActivityManager.UID_OBSERVER_GONE 621 | ActivityManager.UID_OBSERVER_ACTIVE | ActivityManager.UID_OBSERVER_IDLE 622 | ActivityManager.UID_OBSERVER_CAPABILITY 623 }; 624 final IUidObserver[] observers = new IUidObserver.Stub[changesToObserve.length]; 625 for (int i = 0; i < observers.length; ++i) { 626 observers[i] = mock(IUidObserver.Stub.class); 627 when(observers[i].asBinder()).thenReturn((IBinder) observers[i]); 628 mAms.registerUidObserver(observers[i], changesToObserve[i] /* which */, 629 ActivityManager.PROCESS_STATE_UNKNOWN /* cutpoint */, null /* caller */); 630 631 // When we invoke AMS.registerUidObserver, there are some interactions with observers[i] 632 // mock in RemoteCallbackList class. We don't want to test those interactions and 633 // at the same time, we don't want those to interfere with verifyNoMoreInteractions. 634 // So, resetting the mock here. 635 Mockito.reset(observers[i]); 636 } 637 638 // Add pending uid records each corresponding to a different change type UidRecord.CHANGE_* 639 final int[] changesForPendingUidRecords = UID_RECORD_CHANGES; 640 641 final int[] procStatesForPendingUidRecords = { 642 ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE, 643 ActivityManager.PROCESS_STATE_NONEXISTENT, 644 ActivityManager.PROCESS_STATE_CACHED_EMPTY, 645 ActivityManager.PROCESS_STATE_CACHED_ACTIVITY, 646 ActivityManager.PROCESS_STATE_TOP, 647 ActivityManager.PROCESS_STATE_TOP, 648 }; 649 final int[] capabilitiesForPendingUidRecords = { 650 ActivityManager.PROCESS_CAPABILITY_ALL, 651 ActivityManager.PROCESS_CAPABILITY_NONE, 652 ActivityManager.PROCESS_CAPABILITY_NONE, 653 ActivityManager.PROCESS_CAPABILITY_NONE, 654 ActivityManager.PROCESS_CAPABILITY_NONE, 655 ActivityManager.PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK, 656 }; 657 final Map<Integer, ChangeRecord> changeItems = new HashMap<>(); 658 for (int i = 0; i < changesForPendingUidRecords.length; ++i) { 659 final ChangeRecord pendingChange = new ChangeRecord(); 660 pendingChange.change = changesForPendingUidRecords[i]; 661 pendingChange.uid = i; 662 pendingChange.procState = procStatesForPendingUidRecords[i]; 663 pendingChange.procStateSeq = i; 664 pendingChange.capability = capabilitiesForPendingUidRecords[i]; 665 changeItems.put(changesForPendingUidRecords[i], pendingChange); 666 addPendingUidChange(pendingChange); 667 } 668 669 mAms.mUidObserverController.dispatchUidsChanged(); 670 // Verify the required changes have been dispatched to observers. 671 for (int i = 0; i < observers.length; ++i) { 672 final int changeToObserve = changesToObserve[i]; 673 final IUidObserver observerToTest = observers[i]; 674 if ((changeToObserve & ActivityManager.UID_OBSERVER_IDLE) != 0) { 675 // Observer listens to uid idle changes, so change items corresponding to 676 // UidRecord.CHANGE_IDLE or UidRecord.CHANGE_IDLE_GONE needs to be 677 // delivered to this observer. 678 final int[] changesToVerify = { 679 UidRecord.CHANGE_IDLE, 680 UidRecord.CHANGE_GONE | UidRecord.CHANGE_IDLE 681 }; 682 verifyObserverReceivedChanges(observerToTest, changesToVerify, changeItems, 683 (observer, changeItem) -> { 684 verify(observer).onUidIdle(changeItem.uid, changeItem.ephemeral); 685 }); 686 } 687 if ((changeToObserve & ActivityManager.UID_OBSERVER_ACTIVE) != 0) { 688 // Observer listens to uid active changes, so change items corresponding to 689 // UidRecord.CHANGE_ACTIVE needs to be delivered to this observer. 690 final int[] changesToVerify = { UidRecord.CHANGE_ACTIVE }; 691 verifyObserverReceivedChanges(observerToTest, changesToVerify, changeItems, 692 (observer, changeItem) -> { 693 verify(observer).onUidActive(changeItem.uid); 694 }); 695 } 696 if ((changeToObserve & ActivityManager.UID_OBSERVER_GONE) != 0) { 697 // Observer listens to uid gone changes, so change items corresponding to 698 // UidRecord.CHANGE_GONE or UidRecord.CHANGE_IDLE_GONE needs to be 699 // delivered to this observer. 700 final int[] changesToVerify = { 701 UidRecord.CHANGE_GONE, 702 UidRecord.CHANGE_GONE | UidRecord.CHANGE_IDLE 703 }; 704 verifyObserverReceivedChanges(observerToTest, changesToVerify, changeItems, 705 (observer, changeItem) -> { 706 verify(observer).onUidGone(changeItem.uid, changeItem.ephemeral); 707 }); 708 } 709 if ((changeToObserve & ActivityManager.UID_OBSERVER_PROCSTATE) != 0 710 || (changeToObserve & ActivityManager.UID_OBSERVER_CAPABILITY) != 0) { 711 // Observer listens to uid procState changes, so change items corresponding to 712 // UidRecord.CHANGE_PROCSTATE or UidRecord.CHANGE_IDLE or UidRecord.CHANGE_ACTIVE 713 // needs to be delivered to this observer. 714 final IntArray changesToVerify = new IntArray(); 715 if ((changeToObserve & ActivityManager.UID_OBSERVER_PROCSTATE) == 0) { 716 changesToVerify.add(UidRecord.CHANGE_CAPABILITY); 717 } else { 718 changesToVerify.add(UidRecord.CHANGE_PROCSTATE); 719 changesToVerify.add(UidRecord.CHANGE_ACTIVE); 720 changesToVerify.add(UidRecord.CHANGE_IDLE); 721 changesToVerify.add(UidRecord.CHANGE_CAPABILITY); 722 } 723 verifyObserverReceivedChanges(observerToTest, changesToVerify.toArray(), 724 changeItems, 725 (observer, changeItem) -> { 726 verify(observer).onUidStateChanged(changeItem.uid, 727 changeItem.procState, changeItem.procStateSeq, 728 changeItem.capability); 729 }); 730 } 731 // Verify there are no other callbacks for this observer. 732 verifyNoMoreInteractions(observerToTest); 733 } 734 } 735 736 @Test testBroadcastStickyIntent()737 public void testBroadcastStickyIntent() { 738 final Intent intent1 = new Intent(TEST_ACTION1); 739 final Intent intent2 = new Intent(TEST_ACTION2) 740 .putExtra(TEST_EXTRA_KEY1, TEST_EXTRA_VALUE1); 741 final Intent intent3 = new Intent(TEST_ACTION3); 742 final BroadcastOptions options = BroadcastOptions.makeWithDeferUntilActive(true); 743 744 broadcastIntent(intent1, null, true); 745 assertStickyBroadcasts(mAms.getStickyBroadcasts(TEST_ACTION1, TEST_USER), 746 StickyBroadcast.create(intent1, false, Process.myUid(), PROCESS_STATE_UNKNOWN)); 747 assertNull(mAms.getStickyBroadcasts(TEST_ACTION2, TEST_USER)); 748 assertNull(mAms.getStickyBroadcasts(TEST_ACTION3, TEST_USER)); 749 750 broadcastIntent(intent2, options.toBundle(), true); 751 assertStickyBroadcasts(mAms.getStickyBroadcasts(TEST_ACTION1, TEST_USER), 752 StickyBroadcast.create(intent1, false, Process.myUid(), PROCESS_STATE_UNKNOWN)); 753 assertStickyBroadcasts(mAms.getStickyBroadcasts(TEST_ACTION2, TEST_USER), 754 StickyBroadcast.create(intent2, true, Process.myUid(), PROCESS_STATE_UNKNOWN)); 755 assertNull(mAms.getStickyBroadcasts(TEST_ACTION3, TEST_USER)); 756 757 broadcastIntent(intent3, null, true); 758 assertStickyBroadcasts(mAms.getStickyBroadcasts(TEST_ACTION1, TEST_USER), 759 StickyBroadcast.create(intent1, false, Process.myUid(), PROCESS_STATE_UNKNOWN)); 760 assertStickyBroadcasts(mAms.getStickyBroadcasts(TEST_ACTION2, TEST_USER), 761 StickyBroadcast.create(intent2, true, Process.myUid(), PROCESS_STATE_UNKNOWN)); 762 assertStickyBroadcasts(mAms.getStickyBroadcasts(TEST_ACTION3, TEST_USER), 763 StickyBroadcast.create(intent3, false, Process.myUid(), PROCESS_STATE_UNKNOWN)); 764 } 765 766 @SuppressWarnings("GuardedBy") broadcastIntent(Intent intent, Bundle options, boolean sticky)767 private void broadcastIntent(Intent intent, Bundle options, boolean sticky) { 768 final int res = mAms.broadcastIntentLocked(null, null, null, intent, null, null, 0, 769 null, null, null, null, null, 0, options, false, sticky, 770 Process.myPid(), Process.myUid(), Process.myUid(), Process.myPid(), TEST_USER); 771 assertEquals(ActivityManager.BROADCAST_SUCCESS, res); 772 } 773 assertStickyBroadcasts(ArrayList<StickyBroadcast> actualBroadcasts, StickyBroadcast... expectedBroadcasts)774 private void assertStickyBroadcasts(ArrayList<StickyBroadcast> actualBroadcasts, 775 StickyBroadcast... expectedBroadcasts) { 776 final String errMsg = "Expected: " + Arrays.toString(expectedBroadcasts) 777 + "; Actual: " + Arrays.toString(actualBroadcasts.toArray()); 778 assertEquals(errMsg, expectedBroadcasts.length, actualBroadcasts.size()); 779 for (int i = 0; i < expectedBroadcasts.length; ++i) { 780 final StickyBroadcast expected = expectedBroadcasts[i]; 781 final StickyBroadcast actual = actualBroadcasts.get(i); 782 assertTrue(errMsg, areEquals(expected, actual)); 783 } 784 } 785 areEquals(StickyBroadcast a, StickyBroadcast b)786 private boolean areEquals(StickyBroadcast a, StickyBroadcast b) { 787 if (!Objects.equals(a.intent.getAction(), b.intent.getAction())) { 788 return false; 789 } 790 if (!Bundle.kindofEquals(a.intent.getExtras(), b.intent.getExtras())) { 791 return false; 792 } 793 if (a.deferUntilActive != b.deferUntilActive) { 794 return false; 795 } 796 if (a.originalCallingUid != b.originalCallingUid) { 797 return false; 798 } 799 return true; 800 } 801 802 private interface ObserverChangesVerifier { verify(IUidObserver observer, ChangeRecord changeItem)803 void verify(IUidObserver observer, ChangeRecord changeItem) throws RemoteException; 804 } 805 verifyObserverReceivedChanges(IUidObserver observer, int[] changesToVerify, Map<Integer, ChangeRecord> changeItems, ObserverChangesVerifier verifier)806 private void verifyObserverReceivedChanges(IUidObserver observer, int[] changesToVerify, 807 Map<Integer, ChangeRecord> changeItems, ObserverChangesVerifier verifier) 808 throws RemoteException { 809 for (int change : changesToVerify) { 810 final ChangeRecord changeItem = changeItems.get(change); 811 verifier.verify(observer, changeItem); 812 } 813 } 814 815 /** 816 * This test verifies that process state changes are dispatched to observers only when they 817 * change across the cutpoint (this is specified when registering the observer). 818 */ 819 @Test testDispatchUidChanges_procStateCutpoint()820 public void testDispatchUidChanges_procStateCutpoint() throws RemoteException { 821 mockNoteOperation(); 822 823 final IUidObserver observer = mock(IUidObserver.Stub.class); 824 825 when(observer.asBinder()).thenReturn((IBinder) observer); 826 mAms.registerUidObserver(observer, ActivityManager.UID_OBSERVER_PROCSTATE /* which */, 827 ActivityManager.PROCESS_STATE_SERVICE /* cutpoint */, null /* callingPackage */); 828 // When we invoke AMS.registerUidObserver, there are some interactions with observer 829 // mock in RemoteCallbackList class. We don't want to test those interactions and 830 // at the same time, we don't want those to interfere with verifyNoMoreInteractions. 831 // So, resetting the mock here. 832 Mockito.reset(observer); 833 834 final ChangeRecord changeItem = new ChangeRecord(); 835 changeItem.uid = TEST_UID; 836 changeItem.change = UidRecord.CHANGE_PROCSTATE; 837 changeItem.procState = ActivityManager.PROCESS_STATE_LAST_ACTIVITY; 838 changeItem.procStateSeq = 111; 839 addPendingUidChange(changeItem); 840 mAms.mUidObserverController.dispatchUidsChanged(); 841 // First process state message is always delivered regardless of whether the process state 842 // change is above or below the cutpoint (PROCESS_STATE_SERVICE). 843 verify(observer).onUidStateChanged(TEST_UID, 844 changeItem.procState, changeItem.procStateSeq, 845 ActivityManager.PROCESS_CAPABILITY_NONE); 846 verifyNoMoreInteractions(observer); 847 848 changeItem.procState = ActivityManager.PROCESS_STATE_RECEIVER; 849 addPendingUidChange(changeItem); 850 mAms.mUidObserverController.dispatchUidsChanged(); 851 // Previous process state change is below cutpoint (PROCESS_STATE_SERVICE) and 852 // the current process state change is also below cutpoint, so no callback will be invoked. 853 verifyNoMoreInteractions(observer); 854 855 changeItem.procState = ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE; 856 addPendingUidChange(changeItem); 857 mAms.mUidObserverController.dispatchUidsChanged(); 858 // Previous process state change is below cutpoint (PROCESS_STATE_SERVICE) and 859 // the current process state change is above cutpoint, so callback will be invoked with the 860 // current process state change. 861 verify(observer).onUidStateChanged(TEST_UID, 862 changeItem.procState, changeItem.procStateSeq, 863 ActivityManager.PROCESS_CAPABILITY_NONE); 864 verifyNoMoreInteractions(observer); 865 866 changeItem.procState = ActivityManager.PROCESS_STATE_TOP; 867 addPendingUidChange(changeItem); 868 mAms.mUidObserverController.dispatchUidsChanged(); 869 // Previous process state change is above cutpoint (PROCESS_STATE_SERVICE) and 870 // the current process state change is also above cutpoint, so no callback will be invoked. 871 verifyNoMoreInteractions(observer); 872 873 changeItem.procState = ActivityManager.PROCESS_STATE_CACHED_EMPTY; 874 addPendingUidChange(changeItem); 875 mAms.mUidObserverController.dispatchUidsChanged(); 876 // Previous process state change is above cutpoint (PROCESS_STATE_SERVICE) and 877 // the current process state change is below cutpoint, so callback will be invoked with the 878 // current process state change. 879 verify(observer).onUidStateChanged(TEST_UID, 880 changeItem.procState, changeItem.procStateSeq, 881 ActivityManager.PROCESS_CAPABILITY_NONE); 882 verifyNoMoreInteractions(observer); 883 } 884 885 /** 886 * This test verifies that {@link UidObserverController#getValidateUidsForTest()} which is a 887 * part of dumpsys is correctly updated. 888 */ 889 @Test testDispatchUidChanges_validateUidsUpdated()890 public void testDispatchUidChanges_validateUidsUpdated() { 891 mockNoteOperation(); 892 893 final int[] changesForPendingItems = UID_RECORD_CHANGES; 894 895 final int[] procStatesForPendingItems = { 896 ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE, 897 ActivityManager.PROCESS_STATE_CACHED_EMPTY, 898 ActivityManager.PROCESS_STATE_CACHED_ACTIVITY, 899 ActivityManager.PROCESS_STATE_SERVICE, 900 ActivityManager.PROCESS_STATE_RECEIVER, 901 }; 902 final ArrayList<ChangeRecord> pendingItemsForUids = 903 new ArrayList<>(procStatesForPendingItems.length); 904 for (int i = 0; i < procStatesForPendingItems.length; ++i) { 905 final ChangeRecord item = new ChangeRecord(); 906 item.uid = i; 907 item.change = changesForPendingItems[i]; 908 item.procState = procStatesForPendingItems[i]; 909 pendingItemsForUids.add(i, item); 910 } 911 912 // Verify that when there no observers listening to uid state changes, then there will 913 // be no changes to validateUids. 914 addPendingUidChanges(pendingItemsForUids); 915 mAms.mUidObserverController.dispatchUidsChanged(); 916 assertEquals("No observers registered, so validateUids should be empty", 917 0, mAms.mUidObserverController.getValidateUidsForTest().size()); 918 919 final IUidObserver observer = mock(IUidObserver.Stub.class); 920 when(observer.asBinder()).thenReturn((IBinder) observer); 921 mAms.registerUidObserver(observer, 0, 0, null); 922 // Verify that when observers are registered, then validateUids is correctly updated. 923 addPendingUidChanges(pendingItemsForUids); 924 mAms.mUidObserverController.dispatchUidsChanged(); 925 for (int i = 0; i < pendingItemsForUids.size(); ++i) { 926 final ChangeRecord item = pendingItemsForUids.get(i); 927 final UidRecord validateUidRecord = 928 mAms.mUidObserverController.getValidateUidsForTest().get(item.uid); 929 if ((item.change & UidRecord.CHANGE_GONE) != 0) { 930 assertNull("validateUidRecord should be null since the change is either " 931 + "CHANGE_GONE or CHANGE_GONE_IDLE", validateUidRecord); 932 } else { 933 assertNotNull("validateUidRecord should not be null since the change is neither " 934 + "CHANGE_GONE nor CHANGE_GONE_IDLE", validateUidRecord); 935 assertEquals("processState: " + item.procState + " curProcState: " 936 + validateUidRecord.getCurProcState() + " should have been equal", 937 item.procState, validateUidRecord.getCurProcState()); 938 assertEquals("processState: " + item.procState + " setProcState: " 939 + validateUidRecord.getCurProcState() + " should have been equal", 940 item.procState, validateUidRecord.getSetProcState()); 941 if (item.change == UidRecord.CHANGE_IDLE) { 942 assertTrue("UidRecord.idle should be updated to true for CHANGE_IDLE", 943 validateUidRecord.isIdle()); 944 } else if (item.change == UidRecord.CHANGE_ACTIVE) { 945 assertFalse("UidRecord.idle should be updated to false for CHANGE_ACTIVE", 946 validateUidRecord.isIdle()); 947 } 948 } 949 } 950 951 // Verify that when uid state changes to CHANGE_GONE or CHANGE_GONE_IDLE, then it 952 // will be removed from validateUids. 953 assertNotEquals("validateUids should not be empty", 0, 954 mAms.mUidObserverController.getValidateUidsForTest().size()); 955 for (int i = 0; i < pendingItemsForUids.size(); ++i) { 956 final ChangeRecord item = pendingItemsForUids.get(i); 957 // Assign CHANGE_GONE_IDLE to some items and CHANGE_GONE to the others, using even/odd 958 // distribution for this assignment. 959 item.change = (i % 2) == 0 ? (UidRecord.CHANGE_GONE | UidRecord.CHANGE_IDLE) 960 : UidRecord.CHANGE_GONE; 961 } 962 addPendingUidChanges(pendingItemsForUids); 963 mAms.mUidObserverController.dispatchUidsChanged(); 964 assertEquals("validateUids should be empty, size=" 965 + mAms.mUidObserverController.getValidateUidsForTest().size(), 966 0, mAms.mUidObserverController.getValidateUidsForTest().size()); 967 } 968 969 @Test testEnqueueUidChangeLocked_nullUidRecord()970 public void testEnqueueUidChangeLocked_nullUidRecord() { 971 // Use "null" uidRecord to make sure there is no crash. 972 mAms.enqueueUidChangeLocked(null, TEST_UID, UidRecord.CHANGE_ACTIVE); 973 } 974 975 @MediumTest 976 @Test testEnqueueUidChangeLocked_dispatchUidsChanged()977 public void testEnqueueUidChangeLocked_dispatchUidsChanged() { 978 final UidRecord uidRecord = new UidRecord(TEST_UID, mAms); 979 final int expectedProcState = PROCESS_STATE_SERVICE; 980 uidRecord.setSetProcState(expectedProcState); 981 uidRecord.curProcStateSeq = TEST_PROC_STATE_SEQ1; 982 983 // Test with no pending uid records. 984 for (int i = 0; i < UID_RECORD_CHANGES.length; ++i) { 985 final int changeToDispatch = UID_RECORD_CHANGES[i]; 986 987 // Reset the current state 988 mHandler.reset(); 989 clearPendingUidChanges(); 990 uidRecord.pendingChange.isPending = false; 991 992 mAms.enqueueUidChangeLocked(uidRecord, -1, changeToDispatch); 993 994 // Verify that pendingChange is updated correctly. 995 final ChangeRecord pendingChange = uidRecord.pendingChange; 996 assertTrue(pendingChange.isPending); 997 assertEquals(TEST_UID, pendingChange.uid); 998 assertEquals(expectedProcState, pendingChange.procState); 999 assertEquals(TEST_PROC_STATE_SEQ1, pendingChange.procStateSeq); 1000 1001 // TODO: Verify that DISPATCH_UIDS_CHANGED_UI_MSG is posted to handler. 1002 } 1003 } 1004 1005 @MediumTest 1006 @Test testWaitForNetworkStateUpdate()1007 public void testWaitForNetworkStateUpdate() throws Exception { 1008 // Check there is no crash when there is no UidRecord for myUid 1009 mAms.waitForNetworkStateUpdate(TEST_PROC_STATE_SEQ1); 1010 1011 // Verify there is not waiting when the procStateSeq in the request already has 1012 // an updated network state. 1013 verifyWaitingForNetworkStateUpdate( 1014 TEST_PROC_STATE_SEQ1, // curProcStateSeq 1015 TEST_PROC_STATE_SEQ1, // lastNetworkUpdatedProcStateSeq 1016 TEST_PROC_STATE_SEQ1, // procStateSeqToWait 1017 false); // expectWait 1018 1019 // Verify waiting for network works 1020 verifyWaitingForNetworkStateUpdate( 1021 TEST_PROC_STATE_SEQ1, // curProcStateSeq 1022 TEST_PROC_STATE_SEQ1 - 1, // lastNetworkUpdatedProcStateSeq 1023 TEST_PROC_STATE_SEQ1, // procStateSeqToWait 1024 true); // expectWait 1025 } 1026 1027 @Test testGetDisplayIdsForStartingBackgroundUsers()1028 public void testGetDisplayIdsForStartingBackgroundUsers() { 1029 mInjector.secondaryDisplayIdsForStartingBackgroundUsers = new int[]{4, 8, 15, 16, 23, 42}; 1030 1031 int [] displayIds = mAms.getDisplayIdsForStartingVisibleBackgroundUsers(); 1032 1033 assertWithMessage("mAms.getDisplayIdsForStartingVisibleBackgroundUsers()") 1034 .that(displayIds).asList().containsExactly(4, 8, 15, 16, 23, 42); 1035 } 1036 1037 @Test testStartUserInBackgroundVisibleOnDisplay_invalidDisplay()1038 public void testStartUserInBackgroundVisibleOnDisplay_invalidDisplay() { 1039 mInjector.secondaryDisplayIdsForStartingBackgroundUsers = new int[]{4, 8, 15, 16, 23, 42}; 1040 1041 assertThrows(IllegalArgumentException.class, 1042 () -> mAms.startUserInBackgroundVisibleOnDisplay(USER_ID, 666, 1043 /* unlockProgressListener= */ null)); 1044 1045 assertWithMessage("UserController.startUserOnSecondaryDisplay() calls") 1046 .that(mInjector.usersStartedOnSecondaryDisplays).isEmpty(); 1047 } 1048 1049 @Test testStartUserInBackgroundVisibleOnDisplay_validDisplay_failed()1050 public void testStartUserInBackgroundVisibleOnDisplay_validDisplay_failed() { 1051 mInjector.secondaryDisplayIdsForStartingBackgroundUsers = new int[]{ 4, 8, 15, 16, 23, 42 }; 1052 mInjector.returnValueForstartUserOnSecondaryDisplay = false; 1053 1054 boolean started = mAms.startUserInBackgroundVisibleOnDisplay(USER_ID, 42, 1055 /* unlockProgressListener= */ null); 1056 Log.v(TAG, "Started: " + started); 1057 1058 assertWithMessage("mAms.startUserInBackgroundOnDisplay(%s, 42)", USER_ID) 1059 .that(started).isFalse(); 1060 assertWithMessage("UserController.startUserOnSecondaryDisplay() calls") 1061 .that(mInjector.usersStartedOnSecondaryDisplays) 1062 .containsExactly(new Pair<>(USER_ID, 42)); 1063 } 1064 1065 @Test testStartUserInBackgroundVisibleOnDisplay_validDisplay_success()1066 public void testStartUserInBackgroundVisibleOnDisplay_validDisplay_success() { 1067 mInjector.secondaryDisplayIdsForStartingBackgroundUsers = new int[]{ 4, 8, 15, 16, 23, 42 }; 1068 mInjector.returnValueForstartUserOnSecondaryDisplay = true; 1069 1070 boolean started = mAms.startUserInBackgroundVisibleOnDisplay(USER_ID, 42, 1071 /* unlockProgressListener= */ null); 1072 Log.v(TAG, "Started: " + started); 1073 1074 assertWithMessage("mAms.startUserInBackgroundOnDisplay(%s, 42)", USER_ID) 1075 .that(started).isTrue(); 1076 assertWithMessage("UserController.startUserOnDisplay() calls") 1077 .that(mInjector.usersStartedOnSecondaryDisplays) 1078 .containsExactly(new Pair<>(USER_ID, 42)); 1079 } 1080 verifyWaitingForNetworkStateUpdate(long curProcStateSeq, long lastNetworkUpdatedProcStateSeq, final long procStateSeqToWait, boolean expectWait)1081 private void verifyWaitingForNetworkStateUpdate(long curProcStateSeq, 1082 long lastNetworkUpdatedProcStateSeq, 1083 final long procStateSeqToWait, boolean expectWait) throws Exception { 1084 final UidRecord record = new UidRecord(Process.myUid(), mAms); 1085 record.curProcStateSeq = curProcStateSeq; 1086 record.lastNetworkUpdatedProcStateSeq = lastNetworkUpdatedProcStateSeq; 1087 mAms.mProcessList.mActiveUids.put(Process.myUid(), record); 1088 1089 CustomThread thread = new CustomThread(record.networkStateLock, new Runnable() { 1090 @Override 1091 public void run() { 1092 mAms.waitForNetworkStateUpdate(procStateSeqToWait); 1093 } 1094 }); 1095 final String errMsg = "Unexpected state for " + record; 1096 if (expectWait) { 1097 thread.startAndWait(errMsg, true); 1098 thread.assertTimedWaiting(errMsg); 1099 synchronized (record.networkStateLock) { 1100 record.networkStateLock.notifyAll(); 1101 } 1102 thread.assertTerminated(errMsg); 1103 assertTrue(thread.mNotified); 1104 assertEquals(0, record.procStateSeqWaitingForNetwork); 1105 } else { 1106 thread.start(); 1107 thread.assertTerminated(errMsg); 1108 } 1109 1110 mAms.mProcessList.mActiveUids.clear(); 1111 } 1112 addPendingUidChange(ChangeRecord record)1113 private void addPendingUidChange(ChangeRecord record) { 1114 mAms.mUidObserverController.getPendingUidChangesForTest().add(record); 1115 } 1116 addPendingUidChanges(ArrayList<ChangeRecord> changes)1117 private void addPendingUidChanges(ArrayList<ChangeRecord> changes) { 1118 final ArrayList<ChangeRecord> pendingChanges = 1119 mAms.mUidObserverController.getPendingUidChangesForTest(); 1120 for (int i = 0; i < changes.size(); ++i) { 1121 final ChangeRecord record = changes.get(i); 1122 pendingChanges.add(record); 1123 } 1124 } 1125 clearPendingUidChanges()1126 private void clearPendingUidChanges() { 1127 mAms.mUidObserverController.getPendingUidChangesForTest().clear(); 1128 } 1129 1130 private static class TestHandler extends Handler { 1131 private static final long WAIT_FOR_MSG_TIMEOUT_MS = 4000; // 4 sec 1132 private static final long WAIT_FOR_MSG_INTERVAL_MS = 400; // 0.4 sec 1133 1134 private final Set<Integer> mMsgsHandled = new HashSet<>(); 1135 private final List<Runnable> mRunnablesToIgnore = new ArrayList<>(); 1136 TestHandler(Looper looper)1137 TestHandler(Looper looper) { 1138 super(looper); 1139 } 1140 1141 @Override dispatchMessage(Message msg)1142 public void dispatchMessage(Message msg) { 1143 if (msg.getCallback() != null && mRunnablesToIgnore.contains(msg.getCallback())) { 1144 return; 1145 } 1146 super.dispatchMessage(msg); 1147 } 1148 1149 @Override handleMessage(Message msg)1150 public void handleMessage(Message msg) { 1151 mMsgsHandled.add(msg.what); 1152 } 1153 waitForMessage(int msg)1154 public void waitForMessage(int msg) { 1155 final long endTime = System.currentTimeMillis() + WAIT_FOR_MSG_TIMEOUT_MS; 1156 while (!mMsgsHandled.contains(msg) && System.currentTimeMillis() < endTime) { 1157 SystemClock.sleep(WAIT_FOR_MSG_INTERVAL_MS); 1158 } 1159 if (!mMsgsHandled.contains(msg)) { 1160 fail("Timed out waiting for the message to be handled, msg: " + msg); 1161 } 1162 } 1163 setRunnablesToIgnore(List<Runnable> runnables)1164 public void setRunnablesToIgnore(List<Runnable> runnables) { 1165 mRunnablesToIgnore.clear(); 1166 mRunnablesToIgnore.addAll(runnables); 1167 } 1168 reset()1169 public void reset() { 1170 mMsgsHandled.clear(); 1171 } 1172 } 1173 1174 private class TestInjector extends Injector { 1175 public boolean restricted = true; 1176 public int[] secondaryDisplayIdsForStartingBackgroundUsers; 1177 1178 public boolean returnValueForstartUserOnSecondaryDisplay; 1179 public List<Pair<Integer, Integer>> usersStartedOnSecondaryDisplays = new ArrayList<>(); 1180 TestInjector(Context context)1181 TestInjector(Context context) { 1182 super(context); 1183 } 1184 1185 @Override getAppOpsService(File recentAccessesFile, File storageFile, Handler handler)1186 public AppOpsService getAppOpsService(File recentAccessesFile, File storageFile, 1187 Handler handler) { 1188 return mAppOpsService; 1189 } 1190 1191 @Override getUiHandler(ActivityManagerService service)1192 public Handler getUiHandler(ActivityManagerService service) { 1193 return mHandler; 1194 } 1195 1196 @Override isNetworkRestrictedForUid(int uid)1197 public boolean isNetworkRestrictedForUid(int uid) { 1198 return restricted; 1199 } 1200 1201 @Override getDisplayIdsForStartingVisibleBackgroundUsers()1202 public int[] getDisplayIdsForStartingVisibleBackgroundUsers() { 1203 return secondaryDisplayIdsForStartingBackgroundUsers; 1204 } 1205 1206 @Override startUserInBackgroundVisibleOnDisplay(int userId, int displayId, IProgressListener unlockProgressListener)1207 public boolean startUserInBackgroundVisibleOnDisplay(int userId, int displayId, 1208 IProgressListener unlockProgressListener) { 1209 usersStartedOnSecondaryDisplays.add(new Pair<>(userId, displayId)); 1210 return returnValueForstartUserOnSecondaryDisplay; 1211 } 1212 } 1213 } 1214