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