ActivityManagerServiceTest.java revision f4923ea0b25edb6e6ca6804ed4c66f57a8ec29c2
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 17package com.android.server.am; 18 19import static android.app.ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE; 20import static android.app.ActivityManager.PROCESS_STATE_CACHED_ACTIVITY; 21import static android.app.ActivityManager.PROCESS_STATE_CACHED_EMPTY; 22import static android.app.ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE; 23import static android.app.ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND; 24import static android.app.ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND; 25import static android.app.ActivityManager.PROCESS_STATE_LAST_ACTIVITY; 26import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT; 27import static android.app.ActivityManager.PROCESS_STATE_RECEIVER; 28import static android.app.ActivityManager.PROCESS_STATE_SERVICE; 29import static android.app.ActivityManager.PROCESS_STATE_TOP; 30import static android.util.DebugUtils.valueToString; 31import static com.android.server.am.ActivityManagerInternalTest.CustomThread; 32import static com.android.server.am.ActivityManagerService.DISPATCH_UIDS_CHANGED_UI_MSG; 33import static com.android.server.am.ActivityManagerService.Injector; 34import static com.android.server.am.ActivityManagerService.NETWORK_STATE_BLOCK; 35import static com.android.server.am.ActivityManagerService.NETWORK_STATE_NO_CHANGE; 36import static com.android.server.am.ActivityManagerService.NETWORK_STATE_UNBLOCK; 37 38import static org.junit.Assert.assertEquals; 39import static org.junit.Assert.assertFalse; 40import static org.junit.Assert.assertNotEquals; 41import static org.junit.Assert.assertNotNull; 42import static org.junit.Assert.assertNull; 43import static org.junit.Assert.assertTrue; 44import static org.junit.Assert.fail; 45import static org.mockito.Mockito.verify; 46import static org.mockito.Mockito.verifyNoMoreInteractions; 47import static org.mockito.Mockito.verifyZeroInteractions; 48import static org.mockito.Mockito.when; 49 50import android.app.ActivityManager; 51import android.app.AppOpsManager; 52import android.app.IApplicationThread; 53import android.app.IUidObserver; 54import android.content.Context; 55import android.content.pm.ApplicationInfo; 56import android.content.pm.PackageManager; 57import android.os.Handler; 58import android.os.HandlerThread; 59import android.os.IBinder; 60import android.os.Looper; 61import android.os.Message; 62import android.os.Process; 63import android.os.RemoteException; 64import android.os.SystemClock; 65import android.support.test.filters.MediumTest; 66import android.support.test.filters.SmallTest; 67import android.support.test.runner.AndroidJUnit4; 68 69import com.android.internal.os.BatteryStatsImpl; 70import com.android.server.AppOpsService; 71 72import org.junit.After; 73import org.junit.Before; 74import org.junit.Test; 75import org.junit.runner.RunWith; 76import org.mockito.Mock; 77import org.mockito.Mockito; 78import org.mockito.MockitoAnnotations; 79 80import java.io.File; 81import java.util.ArrayList; 82import java.util.HashMap; 83import java.util.HashSet; 84import java.util.Map; 85import java.util.Set; 86import java.util.function.Function; 87 88/** 89 * Test class for {@link ActivityManagerService}. 90 * 91 * To run the tests, use 92 * 93 * runtest -c com.android.server.am.ActivityManagerServiceTest frameworks-services 94 * 95 * or the following steps: 96 * 97 * Build: m FrameworksServicesTests 98 * Install: adb install -r \ 99 * ${ANDROID_PRODUCT_OUT}/data/app/FrameworksServicesTests/FrameworksServicesTests.apk 100 * Run: adb shell am instrument -e class com.android.server.am.ActivityManagerServiceTest -w \ 101 * com.android.frameworks.servicestests/android.support.test.runner.AndroidJUnitRunner 102 */ 103@SmallTest 104@RunWith(AndroidJUnit4.class) 105public class ActivityManagerServiceTest { 106 private static final String TAG = ActivityManagerServiceTest.class.getSimpleName(); 107 108 private static final int TEST_UID = 11111; 109 110 private static final long TEST_PROC_STATE_SEQ1 = 555; 111 private static final long TEST_PROC_STATE_SEQ2 = 556; 112 113 private static final int[] UID_RECORD_CHANGES = { 114 UidRecord.CHANGE_PROCSTATE, 115 UidRecord.CHANGE_GONE, 116 UidRecord.CHANGE_GONE_IDLE, 117 UidRecord.CHANGE_IDLE, 118 UidRecord.CHANGE_ACTIVE 119 }; 120 121 @Mock private Context mContext; 122 @Mock private AppOpsService mAppOpsService; 123 @Mock private PackageManager mPackageManager; 124 @Mock private BatteryStatsImpl mBatteryStatsImpl; 125 126 private TestInjector mInjector; 127 private ActivityManagerService mAms; 128 private HandlerThread mHandlerThread; 129 private TestHandler mHandler; 130 131 @Before 132 public void setUp() { 133 MockitoAnnotations.initMocks(this); 134 135 mHandlerThread = new HandlerThread(TAG); 136 mHandlerThread.start(); 137 mHandler = new TestHandler(mHandlerThread.getLooper()); 138 mInjector = new TestInjector(); 139 mAms = new ActivityManagerService(mInjector); 140 mAms.mWaitForNetworkTimeoutMs = 100; 141 142 when(mContext.getPackageManager()).thenReturn(mPackageManager); 143 } 144 145 @After 146 public void tearDown() { 147 mHandlerThread.quit(); 148 } 149 150 @MediumTest 151 @Test 152 public void incrementProcStateSeqAndNotifyAppsLocked() throws Exception { 153 154 final UidRecord uidRec = addUidRecord(TEST_UID); 155 addUidRecord(TEST_UID + 1); 156 157 // Uid state is not moving from background to foreground or vice versa. 158 verifySeqCounterAndInteractions(uidRec, 159 PROCESS_STATE_TOP, // prevState 160 PROCESS_STATE_TOP, // curState 161 0, // expectedGlobalCounter 162 0, // exptectedCurProcStateSeq 163 NETWORK_STATE_NO_CHANGE, // expectedBlockState 164 false); // expectNotify 165 166 // Uid state is moving from foreground to background. 167 verifySeqCounterAndInteractions(uidRec, 168 PROCESS_STATE_FOREGROUND_SERVICE, // prevState 169 PROCESS_STATE_SERVICE, // curState 170 1, // expectedGlobalCounter 171 1, // exptectedCurProcStateSeq 172 NETWORK_STATE_UNBLOCK, // expectedBlockState 173 true); // expectNotify 174 175 // Explicitly setting the seq counter for more verification. 176 mAms.mProcStateSeqCounter = 42; 177 178 // Uid state is not moving from background to foreground or vice versa. 179 verifySeqCounterAndInteractions(uidRec, 180 PROCESS_STATE_IMPORTANT_BACKGROUND, // prevState 181 PROCESS_STATE_IMPORTANT_FOREGROUND, // curState 182 42, // expectedGlobalCounter 183 1, // exptectedCurProcStateSeq 184 NETWORK_STATE_NO_CHANGE, // expectedBlockState 185 false); // expectNotify 186 187 // Uid state is moving from background to foreground. 188 verifySeqCounterAndInteractions(uidRec, 189 PROCESS_STATE_LAST_ACTIVITY, // prevState 190 PROCESS_STATE_TOP, // curState 191 43, // expectedGlobalCounter 192 43, // exptectedCurProcStateSeq 193 NETWORK_STATE_BLOCK, // expectedBlockState 194 false); // expectNotify 195 196 // verify waiting threads are not notified. 197 uidRec.waitingForNetwork = false; 198 // Uid state is moving from foreground to background. 199 verifySeqCounterAndInteractions(uidRec, 200 PROCESS_STATE_FOREGROUND_SERVICE, // prevState 201 PROCESS_STATE_SERVICE, // curState 202 44, // expectedGlobalCounter 203 44, // exptectedCurProcStateSeq 204 NETWORK_STATE_UNBLOCK, // expectedBlockState 205 false); // expectNotify 206 207 // Verify when uid is not restricted, procStateSeq is not incremented. 208 uidRec.waitingForNetwork = true; 209 mInjector.setNetworkRestrictedForUid(false); 210 verifySeqCounterAndInteractions(uidRec, 211 PROCESS_STATE_IMPORTANT_BACKGROUND, // prevState 212 PROCESS_STATE_TOP, // curState 213 44, // expectedGlobalCounter 214 44, // exptectedCurProcStateSeq 215 -1, // expectedBlockState, -1 to verify there are no interactions with main thread. 216 false); // expectNotify 217 218 // Verify when waitForNetworkTimeout is 0, then procStateSeq is not incremented. 219 mAms.mWaitForNetworkTimeoutMs = 0; 220 mInjector.setNetworkRestrictedForUid(true); 221 verifySeqCounterAndInteractions(uidRec, 222 PROCESS_STATE_TOP, // prevState 223 PROCESS_STATE_IMPORTANT_BACKGROUND, // curState 224 44, // expectedGlobalCounter 225 44, // exptectedCurProcStateSeq 226 -1, // expectedBlockState, -1 to verify there are no interactions with main thread. 227 false); // expectNotify 228 229 // Verify when the uid doesn't have internet permission, then procStateSeq is not 230 // incremented. 231 uidRec.hasInternetPermission = false; 232 mAms.mWaitForNetworkTimeoutMs = 111; 233 mInjector.setNetworkRestrictedForUid(true); 234 verifySeqCounterAndInteractions(uidRec, 235 PROCESS_STATE_CACHED_ACTIVITY, // prevState 236 PROCESS_STATE_FOREGROUND_SERVICE, // curState 237 44, // expectedGlobalCounter 238 44, // exptectedCurProcStateSeq 239 -1, // expectedBlockState, -1 to verify there are no interactions with main thread. 240 false); // expectNotify 241 242 // Verify procStateSeq is not incremented when the uid is not an application, regardless 243 // of the process state. 244 final int notAppUid = 111; 245 final UidRecord uidRec2 = addUidRecord(notAppUid); 246 verifySeqCounterAndInteractions(uidRec2, 247 PROCESS_STATE_CACHED_EMPTY, // prevState 248 PROCESS_STATE_TOP, // curState 249 44, // expectedGlobalCounter 250 0, // exptectedCurProcStateSeq 251 -1, // expectedBlockState, -1 to verify there are no interactions with main thread. 252 false); // expectNotify 253 } 254 255 private UidRecord addUidRecord(int uid) { 256 final UidRecord uidRec = new UidRecord(uid); 257 uidRec.waitingForNetwork = true; 258 uidRec.hasInternetPermission = true; 259 mAms.mActiveUids.put(uid, uidRec); 260 261 final ProcessRecord appRec = new ProcessRecord(mBatteryStatsImpl, 262 new ApplicationInfo(), TAG, uid); 263 appRec.thread = Mockito.mock(IApplicationThread.class); 264 mAms.mLruProcesses.add(appRec); 265 266 return uidRec; 267 } 268 269 private void verifySeqCounterAndInteractions(UidRecord uidRec, int prevState, int curState, 270 int expectedGlobalCounter, int expectedCurProcStateSeq, int expectedBlockState, 271 boolean expectNotify) throws Exception { 272 CustomThread thread = new CustomThread(uidRec.networkStateLock); 273 thread.startAndWait("Unexpected state for " + uidRec); 274 275 uidRec.setProcState = prevState; 276 uidRec.curProcState = curState; 277 mAms.incrementProcStateSeqAndNotifyAppsLocked(); 278 279 assertEquals(expectedGlobalCounter, mAms.mProcStateSeqCounter); 280 assertEquals(expectedCurProcStateSeq, uidRec.curProcStateSeq); 281 282 for (int i = mAms.mLruProcesses.size() - 1; i >= 0; --i) { 283 final ProcessRecord app = mAms.mLruProcesses.get(i); 284 // AMS should notify apps only for block states other than NETWORK_STATE_NO_CHANGE. 285 if (app.uid == uidRec.uid && expectedBlockState == NETWORK_STATE_BLOCK) { 286 verify(app.thread).setNetworkBlockSeq(uidRec.curProcStateSeq); 287 } else { 288 verifyZeroInteractions(app.thread); 289 } 290 Mockito.reset(app.thread); 291 } 292 293 if (expectNotify) { 294 thread.assertTerminated("Unexpected state for " + uidRec); 295 } else { 296 thread.assertWaiting("Unexpected state for " + uidRec); 297 thread.interrupt(); 298 } 299 } 300 301 @Test 302 public void testBlockStateForUid() { 303 final UidRecord uidRec = new UidRecord(TEST_UID); 304 int expectedBlockState; 305 306 final String errorTemplate = "Block state should be %s, prevState: %s, curState: %s"; 307 Function<Integer, String> errorMsg = (blockState) -> { 308 return String.format(errorTemplate, 309 valueToString(ActivityManagerService.class, "NETWORK_STATE_", blockState), 310 valueToString(ActivityManager.class, "PROCESS_STATE_", uidRec.setProcState), 311 valueToString(ActivityManager.class, "PROCESS_STATE_", uidRec.curProcState)); 312 }; 313 314 // No change in uid state 315 uidRec.setProcState = PROCESS_STATE_RECEIVER; 316 uidRec.curProcState = PROCESS_STATE_RECEIVER; 317 expectedBlockState = NETWORK_STATE_NO_CHANGE; 318 assertEquals(errorMsg.apply(expectedBlockState), 319 expectedBlockState, mAms.getBlockStateForUid(uidRec)); 320 321 // Foreground to foreground 322 uidRec.setProcState = PROCESS_STATE_FOREGROUND_SERVICE; 323 uidRec.curProcState = PROCESS_STATE_BOUND_FOREGROUND_SERVICE; 324 expectedBlockState = NETWORK_STATE_NO_CHANGE; 325 assertEquals(errorMsg.apply(expectedBlockState), 326 expectedBlockState, mAms.getBlockStateForUid(uidRec)); 327 328 // Background to background 329 uidRec.setProcState = PROCESS_STATE_CACHED_ACTIVITY; 330 uidRec.curProcState = PROCESS_STATE_CACHED_EMPTY; 331 expectedBlockState = NETWORK_STATE_NO_CHANGE; 332 assertEquals(errorMsg.apply(expectedBlockState), 333 expectedBlockState, mAms.getBlockStateForUid(uidRec)); 334 335 // Background to background 336 uidRec.setProcState = PROCESS_STATE_NONEXISTENT; 337 uidRec.curProcState = PROCESS_STATE_CACHED_ACTIVITY; 338 expectedBlockState = NETWORK_STATE_NO_CHANGE; 339 assertEquals(errorMsg.apply(expectedBlockState), 340 expectedBlockState, mAms.getBlockStateForUid(uidRec)); 341 342 // Background to foreground 343 uidRec.setProcState = PROCESS_STATE_SERVICE; 344 uidRec.curProcState = PROCESS_STATE_FOREGROUND_SERVICE; 345 expectedBlockState = NETWORK_STATE_BLOCK; 346 assertEquals(errorMsg.apply(expectedBlockState), 347 expectedBlockState, mAms.getBlockStateForUid(uidRec)); 348 349 // Foreground to background 350 uidRec.setProcState = PROCESS_STATE_TOP; 351 uidRec.curProcState = PROCESS_STATE_LAST_ACTIVITY; 352 expectedBlockState = NETWORK_STATE_UNBLOCK; 353 assertEquals(errorMsg.apply(expectedBlockState), 354 expectedBlockState, mAms.getBlockStateForUid(uidRec)); 355 } 356 357 /** 358 * This test verifies that process state changes are dispatched to observers based on the 359 * changes they wanted to listen (this is specified when registering the observer). 360 */ 361 @Test 362 public void testDispatchUids_dispatchNeededChanges() throws RemoteException { 363 when(mAppOpsService.checkOperation(AppOpsManager.OP_GET_USAGE_STATS, Process.myUid(), null)) 364 .thenReturn(AppOpsManager.MODE_ALLOWED); 365 366 final int[] changesToObserve = { 367 ActivityManager.UID_OBSERVER_PROCSTATE, 368 ActivityManager.UID_OBSERVER_GONE, 369 ActivityManager.UID_OBSERVER_IDLE, 370 ActivityManager.UID_OBSERVER_ACTIVE, 371 ActivityManager.UID_OBSERVER_PROCSTATE | ActivityManager.UID_OBSERVER_GONE 372 | ActivityManager.UID_OBSERVER_ACTIVE | ActivityManager.UID_OBSERVER_IDLE 373 }; 374 final IUidObserver[] observers = new IUidObserver.Stub[changesToObserve.length]; 375 for (int i = 0; i < observers.length; ++i) { 376 observers[i] = Mockito.mock(IUidObserver.Stub.class); 377 when(observers[i].asBinder()).thenReturn((IBinder) observers[i]); 378 mAms.registerUidObserver(observers[i], changesToObserve[i] /* which */, 379 ActivityManager.PROCESS_STATE_UNKNOWN /* cutpoint */, null /* caller */); 380 381 // When we invoke AMS.registerUidObserver, there are some interactions with observers[i] 382 // mock in RemoteCallbackList class. We don't want to test those interactions and 383 // at the same time, we don't want those to interfere with verifyNoMoreInteractions. 384 // So, resetting the mock here. 385 Mockito.reset(observers[i]); 386 } 387 388 // Add pending uid records each corresponding to a different change type UidRecord.CHANGE_* 389 final int[] changesForPendingUidRecords = UID_RECORD_CHANGES; 390 391 final int[] procStatesForPendingUidRecords = { 392 ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE, 393 ActivityManager.PROCESS_STATE_NONEXISTENT, 394 ActivityManager.PROCESS_STATE_CACHED_EMPTY, 395 ActivityManager.PROCESS_STATE_CACHED_ACTIVITY, 396 ActivityManager.PROCESS_STATE_TOP 397 }; 398 final Map<Integer, UidRecord.ChangeItem> changeItems = new HashMap<>(); 399 for (int i = 0; i < changesForPendingUidRecords.length; ++i) { 400 final UidRecord.ChangeItem pendingChange = new UidRecord.ChangeItem(); 401 pendingChange.change = changesForPendingUidRecords[i]; 402 pendingChange.uid = i; 403 pendingChange.processState = procStatesForPendingUidRecords[i]; 404 pendingChange.procStateSeq = i; 405 changeItems.put(changesForPendingUidRecords[i], pendingChange); 406 mAms.mPendingUidChanges.add(pendingChange); 407 } 408 409 mAms.dispatchUidsChanged(); 410 // Verify the required changes have been dispatched to observers. 411 for (int i = 0; i < observers.length; ++i) { 412 final int changeToObserve = changesToObserve[i]; 413 final IUidObserver observerToTest = observers[i]; 414 if ((changeToObserve & ActivityManager.UID_OBSERVER_IDLE) != 0) { 415 // Observer listens to uid idle changes, so change items corresponding to 416 // UidRecord.CHANGE_IDLE or UidRecord.CHANGE_IDLE_GONE needs to be 417 // delivered to this observer. 418 final int[] changesToVerify = { 419 UidRecord.CHANGE_IDLE, 420 UidRecord.CHANGE_GONE_IDLE 421 }; 422 verifyObserverReceivedChanges(observerToTest, changesToVerify, changeItems, 423 (observer, changeItem) -> { 424 verify(observer).onUidIdle(changeItem.uid, changeItem.ephemeral); 425 }); 426 } 427 if ((changeToObserve & ActivityManager.UID_OBSERVER_ACTIVE) != 0) { 428 // Observer listens to uid active changes, so change items corresponding to 429 // UidRecord.CHANGE_ACTIVE needs to be delivered to this observer. 430 final int[] changesToVerify = { UidRecord.CHANGE_ACTIVE }; 431 verifyObserverReceivedChanges(observerToTest, changesToVerify, changeItems, 432 (observer, changeItem) -> { 433 verify(observer).onUidActive(changeItem.uid); 434 }); 435 } 436 if ((changeToObserve & ActivityManager.UID_OBSERVER_GONE) != 0) { 437 // Observer listens to uid gone changes, so change items corresponding to 438 // UidRecord.CHANGE_GONE or UidRecord.CHANGE_IDLE_GONE needs to be 439 // delivered to this observer. 440 final int[] changesToVerify = { 441 UidRecord.CHANGE_GONE, 442 UidRecord.CHANGE_GONE_IDLE 443 }; 444 verifyObserverReceivedChanges(observerToTest, changesToVerify, changeItems, 445 (observer, changeItem) -> { 446 verify(observer).onUidGone(changeItem.uid, changeItem.ephemeral); 447 }); 448 } 449 if ((changeToObserve & ActivityManager.UID_OBSERVER_PROCSTATE) != 0) { 450 // Observer listens to uid procState changes, so change items corresponding to 451 // UidRecord.CHANGE_PROCSTATE or UidRecord.CHANGE_IDLE or UidRecord.CHANGE_ACTIVE 452 // needs to be delivered to this observer. 453 final int[] changesToVerify = { 454 UidRecord.CHANGE_PROCSTATE, 455 UidRecord.CHANGE_ACTIVE, 456 UidRecord.CHANGE_IDLE 457 }; 458 verifyObserverReceivedChanges(observerToTest, changesToVerify, changeItems, 459 (observer, changeItem) -> { 460 verify(observer).onUidStateChanged(changeItem.uid, 461 changeItem.processState, changeItem.procStateSeq); 462 }); 463 } 464 // Verify there are no other callbacks for this observer. 465 verifyNoMoreInteractions(observerToTest); 466 } 467 } 468 469 private interface ObserverChangesVerifier { 470 void verify(IUidObserver observer, UidRecord.ChangeItem changeItem) throws RemoteException; 471 } 472 473 private void verifyObserverReceivedChanges(IUidObserver observer, int[] changesToVerify, 474 Map<Integer, UidRecord.ChangeItem> changeItems, ObserverChangesVerifier verifier) 475 throws RemoteException { 476 for (int change : changesToVerify) { 477 final UidRecord.ChangeItem changeItem = changeItems.get(change); 478 verifier.verify(observer, changeItem); 479 } 480 } 481 482 /** 483 * This test verifies that process state changes are dispatched to observers only when they 484 * change across the cutpoint (this is specified when registering the observer). 485 */ 486 @Test 487 public void testDispatchUidChanges_procStateCutpoint() throws RemoteException { 488 final IUidObserver observer = Mockito.mock(IUidObserver.Stub.class); 489 490 when(observer.asBinder()).thenReturn((IBinder) observer); 491 mAms.registerUidObserver(observer, ActivityManager.UID_OBSERVER_PROCSTATE /* which */, 492 ActivityManager.PROCESS_STATE_SERVICE /* cutpoint */, null /* callingPackage */); 493 // When we invoke AMS.registerUidObserver, there are some interactions with observer 494 // mock in RemoteCallbackList class. We don't want to test those interactions and 495 // at the same time, we don't want those to interfere with verifyNoMoreInteractions. 496 // So, resetting the mock here. 497 Mockito.reset(observer); 498 499 final UidRecord.ChangeItem changeItem = new UidRecord.ChangeItem(); 500 changeItem.uid = TEST_UID; 501 changeItem.change = UidRecord.CHANGE_PROCSTATE; 502 changeItem.processState = ActivityManager.PROCESS_STATE_LAST_ACTIVITY; 503 changeItem.procStateSeq = 111; 504 mAms.mPendingUidChanges.add(changeItem); 505 mAms.dispatchUidsChanged(); 506 // First process state message is always delivered regardless of whether the process state 507 // change is above or below the cutpoint (PROCESS_STATE_SERVICE). 508 verify(observer).onUidStateChanged(TEST_UID, 509 changeItem.processState, changeItem.procStateSeq); 510 verifyNoMoreInteractions(observer); 511 512 changeItem.processState = ActivityManager.PROCESS_STATE_RECEIVER; 513 mAms.mPendingUidChanges.add(changeItem); 514 mAms.dispatchUidsChanged(); 515 // Previous process state change is below cutpoint (PROCESS_STATE_SERVICE) and 516 // the current process state change is also below cutpoint, so no callback will be invoked. 517 verifyNoMoreInteractions(observer); 518 519 changeItem.processState = ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE; 520 mAms.mPendingUidChanges.add(changeItem); 521 mAms.dispatchUidsChanged(); 522 // Previous process state change is below cutpoint (PROCESS_STATE_SERVICE) and 523 // the current process state change is above cutpoint, so callback will be invoked with the 524 // current process state change. 525 verify(observer).onUidStateChanged(TEST_UID, 526 changeItem.processState, changeItem.procStateSeq); 527 verifyNoMoreInteractions(observer); 528 529 changeItem.processState = ActivityManager.PROCESS_STATE_TOP; 530 mAms.mPendingUidChanges.add(changeItem); 531 mAms.dispatchUidsChanged(); 532 // Previous process state change is above cutpoint (PROCESS_STATE_SERVICE) and 533 // the current process state change is also above cutpoint, so no callback will be invoked. 534 verifyNoMoreInteractions(observer); 535 536 changeItem.processState = ActivityManager.PROCESS_STATE_CACHED_EMPTY; 537 mAms.mPendingUidChanges.add(changeItem); 538 mAms.dispatchUidsChanged(); 539 // Previous process state change is above cutpoint (PROCESS_STATE_SERVICE) and 540 // the current process state change is below cutpoint, so callback will be invoked with the 541 // current process state change. 542 verify(observer).onUidStateChanged(TEST_UID, 543 changeItem.processState, changeItem.procStateSeq); 544 verifyNoMoreInteractions(observer); 545 } 546 547 /** 548 * This test verifies that {@link ActivityManagerService#mValidateUids} which is a 549 * part of dumpsys is correctly updated. 550 */ 551 @Test 552 public void testDispatchUidChanges_validateUidsUpdated() { 553 final int[] changesForPendingItems = UID_RECORD_CHANGES; 554 555 final int[] procStatesForPendingItems = { 556 ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE, 557 ActivityManager.PROCESS_STATE_CACHED_EMPTY, 558 ActivityManager.PROCESS_STATE_CACHED_ACTIVITY, 559 ActivityManager.PROCESS_STATE_SERVICE, 560 ActivityManager.PROCESS_STATE_RECEIVER 561 }; 562 final ArrayList<UidRecord.ChangeItem> pendingItemsForUids 563 = new ArrayList<>(changesForPendingItems.length); 564 for (int i = 0; i < changesForPendingItems.length; ++i) { 565 final UidRecord.ChangeItem item = new UidRecord.ChangeItem(); 566 item.uid = i; 567 item.change = changesForPendingItems[i]; 568 item.processState = procStatesForPendingItems[i]; 569 pendingItemsForUids.add(i, item); 570 } 571 572 // Verify that when there no observers listening to uid state changes, then there will 573 // be no changes to validateUids. 574 mAms.mPendingUidChanges.addAll(pendingItemsForUids); 575 mAms.dispatchUidsChanged(); 576 assertEquals("No observers registered, so validateUids should be empty", 577 0, mAms.mValidateUids.size()); 578 579 final IUidObserver observer = Mockito.mock(IUidObserver.Stub.class); 580 when(observer.asBinder()).thenReturn((IBinder) observer); 581 mAms.registerUidObserver(observer, 0, 0, null); 582 // Verify that when observers are registered, then validateUids is correctly updated. 583 mAms.mPendingUidChanges.addAll(pendingItemsForUids); 584 mAms.dispatchUidsChanged(); 585 for (int i = 0; i < pendingItemsForUids.size(); ++i) { 586 final UidRecord.ChangeItem item = pendingItemsForUids.get(i); 587 final UidRecord validateUidRecord = mAms.mValidateUids.get(item.uid); 588 if (item.change == UidRecord.CHANGE_GONE || item.change == UidRecord.CHANGE_GONE_IDLE) { 589 assertNull("validateUidRecord should be null since the change is either " 590 + "CHANGE_GONE or CHANGE_GONE_IDLE", validateUidRecord); 591 } else { 592 assertNotNull("validateUidRecord should not be null since the change is neither " 593 + "CHANGE_GONE nor CHANGE_GONE_IDLE", validateUidRecord); 594 assertEquals("processState: " + item.processState + " curProcState: " 595 + validateUidRecord.curProcState + " should have been equal", 596 item.processState, validateUidRecord.curProcState); 597 assertEquals("processState: " + item.processState + " setProcState: " 598 + validateUidRecord.curProcState + " should have been equal", 599 item.processState, validateUidRecord.setProcState); 600 if (item.change == UidRecord.CHANGE_IDLE) { 601 assertTrue("UidRecord.idle should be updated to true for CHANGE_IDLE", 602 validateUidRecord.idle); 603 } else if (item.change == UidRecord.CHANGE_ACTIVE) { 604 assertFalse("UidRecord.idle should be updated to false for CHANGE_ACTIVE", 605 validateUidRecord.idle); 606 } 607 } 608 } 609 610 // Verify that when uid state changes to CHANGE_GONE or CHANGE_GONE_IDLE, then it 611 // will be removed from validateUids. 612 assertNotEquals("validateUids should not be empty", 0, mAms.mValidateUids.size()); 613 for (int i = 0; i < pendingItemsForUids.size(); ++i) { 614 final UidRecord.ChangeItem item = pendingItemsForUids.get(i); 615 // Assign CHANGE_GONE_IDLE to some items and CHANGE_GONE to the others, using even/odd 616 // distribution for this assignment. 617 item.change = (i % 2) == 0 ? UidRecord.CHANGE_GONE_IDLE : UidRecord.CHANGE_GONE; 618 } 619 mAms.mPendingUidChanges.addAll(pendingItemsForUids); 620 mAms.dispatchUidsChanged(); 621 assertEquals("validateUids should be empty, validateUids: " + mAms.mValidateUids, 622 0, mAms.mValidateUids.size()); 623 } 624 625 @Test 626 public void testEnqueueUidChangeLocked_procStateSeqUpdated() { 627 final UidRecord uidRecord = new UidRecord(TEST_UID); 628 uidRecord.curProcStateSeq = TEST_PROC_STATE_SEQ1; 629 630 // Verify with no pending changes for TEST_UID. 631 verifyLastProcStateSeqUpdated(uidRecord, -1, TEST_PROC_STATE_SEQ1); 632 633 // Add a pending change for TEST_UID and verify enqueueUidChangeLocked still works as 634 // expected. 635 final UidRecord.ChangeItem changeItem = new UidRecord.ChangeItem(); 636 uidRecord.pendingChange = changeItem; 637 uidRecord.curProcStateSeq = TEST_PROC_STATE_SEQ2; 638 verifyLastProcStateSeqUpdated(uidRecord, -1, TEST_PROC_STATE_SEQ2); 639 } 640 641 @Test 642 public void testEnqueueUidChangeLocked_nullUidRecord() { 643 // Use "null" uidRecord to make sure there is no crash. 644 mAms.enqueueUidChangeLocked(null, TEST_UID, UidRecord.CHANGE_ACTIVE); 645 } 646 647 private void verifyLastProcStateSeqUpdated(UidRecord uidRecord, int uid, long curProcstateSeq) { 648 // Test enqueueUidChangeLocked with every UidRecord.CHANGE_* 649 for (int i = 0; i < UID_RECORD_CHANGES.length; ++i) { 650 final int changeToDispatch = UID_RECORD_CHANGES[i]; 651 // Reset lastProcStateSeqDispatchToObservers after every test. 652 uidRecord.lastDispatchedProcStateSeq = 0; 653 mAms.enqueueUidChangeLocked(uidRecord, uid, changeToDispatch); 654 // Verify there is no effect on curProcStateSeq. 655 assertEquals(curProcstateSeq, uidRecord.curProcStateSeq); 656 if (changeToDispatch == UidRecord.CHANGE_GONE 657 || changeToDispatch == UidRecord.CHANGE_GONE_IDLE) { 658 // Since the change is CHANGE_GONE or CHANGE_GONE_IDLE, verify that 659 // lastProcStateSeqDispatchedToObservers is not updated. 660 assertNotEquals(uidRecord.curProcStateSeq, 661 uidRecord.lastDispatchedProcStateSeq); 662 } else { 663 // Since the change is neither CHANGE_GONE nor CHANGE_GONE_IDLE, verify that 664 // lastProcStateSeqDispatchedToObservers has been updated to curProcStateSeq. 665 assertEquals(uidRecord.curProcStateSeq, 666 uidRecord.lastDispatchedProcStateSeq); 667 } 668 } 669 } 670 671 @MediumTest 672 @Test 673 public void testEnqueueUidChangeLocked_dispatchUidsChanged() { 674 final UidRecord uidRecord = new UidRecord(TEST_UID); 675 final int expectedProcState = PROCESS_STATE_SERVICE; 676 uidRecord.setProcState = expectedProcState; 677 uidRecord.curProcStateSeq = TEST_PROC_STATE_SEQ1; 678 679 // Test with no pending uid records. 680 for (int i = 0; i < UID_RECORD_CHANGES.length; ++i) { 681 final int changeToDispatch = UID_RECORD_CHANGES[i]; 682 683 // Reset the current state 684 mHandler.reset(); 685 uidRecord.pendingChange = null; 686 mAms.mPendingUidChanges.clear(); 687 688 mAms.enqueueUidChangeLocked(uidRecord, -1, changeToDispatch); 689 690 // Verify that UidRecord.pendingChange is updated correctly. 691 assertNotNull(uidRecord.pendingChange); 692 assertEquals(TEST_UID, uidRecord.pendingChange.uid); 693 assertEquals(expectedProcState, uidRecord.pendingChange.processState); 694 assertEquals(TEST_PROC_STATE_SEQ1, uidRecord.pendingChange.procStateSeq); 695 696 // Verify that DISPATCH_UIDS_CHANGED_UI_MSG is posted to handler. 697 mHandler.waitForMessage(DISPATCH_UIDS_CHANGED_UI_MSG); 698 } 699 } 700 701 @MediumTest 702 @Test 703 public void testWaitForNetworkStateUpdate() throws Exception { 704 // Check there is no crash when there is no UidRecord for myUid 705 mAms.waitForNetworkStateUpdate(TEST_PROC_STATE_SEQ1); 706 707 // Verify there is no waiting when UidRecord.curProcStateSeq is greater than 708 // the procStateSeq in the request to wait. 709 verifyWaitingForNetworkStateUpdate( 710 TEST_PROC_STATE_SEQ1, // curProcStateSeq 711 TEST_PROC_STATE_SEQ1, // lastDsipatchedProcStateSeq 712 TEST_PROC_STATE_SEQ1 - 4, // lastNetworkUpdatedProcStateSeq 713 TEST_PROC_STATE_SEQ1 - 2, // procStateSeqToWait 714 false); // expectWait 715 716 // Verify there is no waiting when the procStateSeq in the request to wait is 717 // not dispatched to NPMS. 718 verifyWaitingForNetworkStateUpdate( 719 TEST_PROC_STATE_SEQ1, // curProcStateSeq 720 TEST_PROC_STATE_SEQ1 - 1, // lastDsipatchedProcStateSeq 721 TEST_PROC_STATE_SEQ1 - 1, // lastNetworkUpdatedProcStateSeq 722 TEST_PROC_STATE_SEQ1, // procStateSeqToWait 723 false); // expectWait 724 725 // Verify there is not waiting when the procStateSeq in the request already has 726 // an updated network state. 727 verifyWaitingForNetworkStateUpdate( 728 TEST_PROC_STATE_SEQ1, // curProcStateSeq 729 TEST_PROC_STATE_SEQ1, // lastDsipatchedProcStateSeq 730 TEST_PROC_STATE_SEQ1, // lastNetworkUpdatedProcStateSeq 731 TEST_PROC_STATE_SEQ1, // procStateSeqToWait 732 false); // expectWait 733 734 // Verify waiting for network works 735 verifyWaitingForNetworkStateUpdate( 736 TEST_PROC_STATE_SEQ1, // curProcStateSeq 737 TEST_PROC_STATE_SEQ1, // lastDsipatchedProcStateSeq 738 TEST_PROC_STATE_SEQ1 - 1, // lastNetworkUpdatedProcStateSeq 739 TEST_PROC_STATE_SEQ1, // procStateSeqToWait 740 true); // expectWait 741 } 742 743 private void verifyWaitingForNetworkStateUpdate(long curProcStateSeq, 744 long lastDispatchedProcStateSeq, long lastNetworkUpdatedProcStateSeq, 745 final long procStateSeqToWait, boolean expectWait) throws Exception { 746 final UidRecord record = new UidRecord(Process.myUid()); 747 record.curProcStateSeq = curProcStateSeq; 748 record.lastDispatchedProcStateSeq = lastDispatchedProcStateSeq; 749 record.lastNetworkUpdatedProcStateSeq = lastNetworkUpdatedProcStateSeq; 750 mAms.mActiveUids.put(Process.myUid(), record); 751 752 CustomThread thread = new CustomThread(record.networkStateLock, new Runnable() { 753 @Override 754 public void run() { 755 mAms.waitForNetworkStateUpdate(procStateSeqToWait); 756 } 757 }); 758 final String errMsg = "Unexpected state for " + record; 759 if (expectWait) { 760 thread.startAndWait(errMsg, true); 761 thread.assertTimedWaiting(errMsg); 762 synchronized (record.networkStateLock) { 763 record.networkStateLock.notifyAll(); 764 } 765 thread.assertTerminated(errMsg); 766 assertTrue(thread.mNotified); 767 assertFalse(record.waitingForNetwork); 768 } else { 769 thread.start(); 770 thread.assertTerminated(errMsg); 771 } 772 773 mAms.mActiveUids.clear(); 774 } 775 776 private class TestHandler extends Handler { 777 private static final long WAIT_FOR_MSG_TIMEOUT_MS = 4000; // 4 sec 778 private static final long WAIT_FOR_MSG_INTERVAL_MS = 400; // 0.4 sec 779 780 private Set<Integer> mMsgsHandled = new HashSet<>(); 781 782 TestHandler(Looper looper) { 783 super(looper); 784 } 785 786 @Override 787 public void handleMessage(Message msg) { 788 mMsgsHandled.add(msg.what); 789 } 790 791 public void waitForMessage(int msg) { 792 final long endTime = System.currentTimeMillis() + WAIT_FOR_MSG_TIMEOUT_MS; 793 while (!mMsgsHandled.contains(msg) && System.currentTimeMillis() < endTime) { 794 SystemClock.sleep(WAIT_FOR_MSG_INTERVAL_MS); 795 } 796 if (!mMsgsHandled.contains(msg)) { 797 fail("Timed out waiting for the message to be handled, msg: " + msg); 798 } 799 } 800 801 public void reset() { 802 mMsgsHandled.clear(); 803 } 804 } 805 806 private class TestInjector extends Injector { 807 private boolean mRestricted = true; 808 809 @Override 810 public Context getContext() { 811 return mContext; 812 } 813 814 @Override 815 public AppOpsService getAppOpsService(File file, Handler handler) { 816 return mAppOpsService; 817 } 818 819 @Override 820 public Handler getUiHandler(ActivityManagerService service) { 821 return mHandler; 822 } 823 824 @Override 825 public boolean isNetworkRestrictedForUid(int uid) { 826 return mRestricted; 827 } 828 829 public void setNetworkRestrictedForUid(boolean restricted) { 830 mRestricted = restricted; 831 } 832 } 833}