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