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_IMPORTANT_FOREGROUND; 25 import static android.app.ActivityManager.PROCESS_STATE_LAST_ACTIVITY; 26 import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT; 27 import static android.app.ActivityManager.PROCESS_STATE_RECEIVER; 28 import static android.app.ActivityManager.PROCESS_STATE_SERVICE; 29 import static android.app.ActivityManager.PROCESS_STATE_TOP; 30 import static android.util.DebugUtils.valueToString; 31 import static com.android.server.am.ActivityManagerInternalTest.CustomThread; 32 import static com.android.server.am.ActivityManagerService.DISPATCH_UIDS_CHANGED_UI_MSG; 33 import static com.android.server.am.ActivityManagerService.Injector; 34 import static com.android.server.am.ActivityManagerService.NETWORK_STATE_BLOCK; 35 import static com.android.server.am.ActivityManagerService.NETWORK_STATE_NO_CHANGE; 36 import static com.android.server.am.ActivityManagerService.NETWORK_STATE_UNBLOCK; 37 38 import static org.junit.Assert.assertEquals; 39 import static org.junit.Assert.assertFalse; 40 import static org.junit.Assert.assertNotEquals; 41 import static org.junit.Assert.assertNotNull; 42 import static org.junit.Assert.assertNull; 43 import static org.junit.Assert.assertTrue; 44 import static org.junit.Assert.fail; 45 import static org.mockito.Mockito.verify; 46 import static org.mockito.Mockito.verifyNoMoreInteractions; 47 import static org.mockito.Mockito.verifyZeroInteractions; 48 import static org.mockito.Mockito.when; 49 50 import android.app.ActivityManager; 51 import android.app.AppOpsManager; 52 import android.app.IApplicationThread; 53 import android.app.IUidObserver; 54 import android.content.Context; 55 import android.content.pm.ApplicationInfo; 56 import android.content.pm.PackageManager; 57 import android.os.Handler; 58 import android.os.HandlerThread; 59 import android.os.IBinder; 60 import android.os.Looper; 61 import android.os.Message; 62 import android.os.Process; 63 import android.os.RemoteException; 64 import android.os.SystemClock; 65 import android.support.test.filters.MediumTest; 66 import android.support.test.filters.SmallTest; 67 import android.support.test.runner.AndroidJUnit4; 68 69 import com.android.internal.os.BatteryStatsImpl; 70 import com.android.server.AppOpsService; 71 72 import org.junit.After; 73 import org.junit.Before; 74 import org.junit.Test; 75 import org.junit.runner.RunWith; 76 import org.mockito.Mock; 77 import org.mockito.Mockito; 78 import org.mockito.MockitoAnnotations; 79 80 import java.io.File; 81 import java.util.ArrayList; 82 import java.util.HashMap; 83 import java.util.HashSet; 84 import java.util.Map; 85 import java.util.Set; 86 import 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) 105 public 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 setUp()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 = 2000; 141 142 when(mContext.getPackageManager()).thenReturn(mPackageManager); 143 } 144 145 @After tearDown()146 public void tearDown() { 147 mHandlerThread.quit(); 148 } 149 150 @MediumTest 151 @Test incrementProcStateSeqAndNotifyAppsLocked()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 addUidRecord(int uid)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 verifySeqCounterAndInteractions(UidRecord uidRec, int prevState, int curState, int expectedGlobalCounter, int expectedCurProcStateSeq, int expectedBlockState, boolean expectNotify)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 testBlockStateForUid()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 testDispatchUids_dispatchNeededChanges()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 { verify(IUidObserver observer, UidRecord.ChangeItem changeItem)470 void verify(IUidObserver observer, UidRecord.ChangeItem changeItem) throws RemoteException; 471 } 472 verifyObserverReceivedChanges(IUidObserver observer, int[] changesToVerify, Map<Integer, UidRecord.ChangeItem> changeItems, ObserverChangesVerifier verifier)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 testDispatchUidChanges_procStateCutpoint()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 testDispatchUidChanges_validateUidsUpdated()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 testEnqueueUidChangeLocked_procStateSeqUpdated()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 testEnqueueUidChangeLocked_nullUidRecord()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 verifyLastProcStateSeqUpdated(UidRecord uidRecord, int uid, long curProcstateSeq)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 testEnqueueUidChangeLocked_dispatchUidsChanged()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 testWaitForNetworkStateUpdate()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 verifyWaitingForNetworkStateUpdate(long curProcStateSeq, long lastDispatchedProcStateSeq, long lastNetworkUpdatedProcStateSeq, final long procStateSeqToWait, boolean expectWait)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 TestHandler(Looper looper)782 TestHandler(Looper looper) { 783 super(looper); 784 } 785 786 @Override handleMessage(Message msg)787 public void handleMessage(Message msg) { 788 mMsgsHandled.add(msg.what); 789 } 790 waitForMessage(int msg)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 reset()801 public void reset() { 802 mMsgsHandled.clear(); 803 } 804 } 805 806 private class TestInjector extends Injector { 807 private boolean mRestricted = true; 808 809 @Override getContext()810 public Context getContext() { 811 return mContext; 812 } 813 814 @Override getAppOpsService(File file, Handler handler)815 public AppOpsService getAppOpsService(File file, Handler handler) { 816 return mAppOpsService; 817 } 818 819 @Override getUiHandler(ActivityManagerService service)820 public Handler getUiHandler(ActivityManagerService service) { 821 return mHandler; 822 } 823 824 @Override isNetworkRestrictedForUid(int uid)825 public boolean isNetworkRestrictedForUid(int uid) { 826 return mRestricted; 827 } 828 setNetworkRestrictedForUid(boolean restricted)829 public void setNetworkRestrictedForUid(boolean restricted) { 830 mRestricted = restricted; 831 } 832 } 833 }