blob: 6fe259e7fc85aad7ed45c049b50fecc8c6e5ec34 [file] [log] [blame]
Sudheer Shanka88c4d1c2017-02-23 16:34:40 -08001/*
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
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +090014 * limitations under the License.
Sudheer Shanka88c4d1c2017-02-23 16:34:40 -080015 */
16
17package com.android.server.am;
18
19import static android.app.ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
20import static android.app.ActivityManager.PROCESS_STATE_CACHED_ACTIVITY;
21import static android.app.ActivityManager.PROCESS_STATE_CACHED_EMPTY;
22import static android.app.ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
23import static android.app.ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND;
24import static android.app.ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND;
25import static android.app.ActivityManager.PROCESS_STATE_LAST_ACTIVITY;
26import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT;
27import static android.app.ActivityManager.PROCESS_STATE_RECEIVER;
28import static android.app.ActivityManager.PROCESS_STATE_SERVICE;
29import static android.app.ActivityManager.PROCESS_STATE_TOP;
30import static android.util.DebugUtils.valueToString;
Brett Chabota26eda92018-07-23 13:08:30 -070031
Charles Chen8d98dd22018-12-26 17:36:54 +080032import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
33
Sudheer Shanka84a48952017-03-08 18:19:01 -080034import static com.android.server.am.ActivityManagerInternalTest.CustomThread;
Sudheer Shanka51ab3ac2017-03-07 15:38:01 -080035import static com.android.server.am.ActivityManagerService.DISPATCH_UIDS_CHANGED_UI_MSG;
36import static com.android.server.am.ActivityManagerService.Injector;
Jing Ji094c3ef2019-08-27 17:02:09 -070037import static com.android.server.am.ProcessList.NETWORK_STATE_BLOCK;
38import static com.android.server.am.ProcessList.NETWORK_STATE_NO_CHANGE;
39import static com.android.server.am.ProcessList.NETWORK_STATE_UNBLOCK;
Sudheer Shanka88c4d1c2017-02-23 16:34:40 -080040
41import static org.junit.Assert.assertEquals;
42import static org.junit.Assert.assertFalse;
Sudheer Shanka4c9afa82017-02-28 19:30:28 -080043import static org.junit.Assert.assertNotEquals;
44import static org.junit.Assert.assertNotNull;
45import static org.junit.Assert.assertNull;
Sudheer Shanka88c4d1c2017-02-23 16:34:40 -080046import static org.junit.Assert.assertTrue;
Sudheer Shanka51ab3ac2017-03-07 15:38:01 -080047import static org.junit.Assert.fail;
Darryl L Johnson11f9a1b2020-04-17 12:32:40 -070048import static org.mockito.Mockito.doReturn;
49import static org.mockito.Mockito.mock;
Sudheer Shanka4c9afa82017-02-28 19:30:28 -080050import static org.mockito.Mockito.verify;
51import static org.mockito.Mockito.verifyNoMoreInteractions;
Sudheer Shanka84a48952017-03-08 18:19:01 -080052import static org.mockito.Mockito.verifyZeroInteractions;
Sudheer Shanka4c9afa82017-02-28 19:30:28 -080053import static org.mockito.Mockito.when;
Sudheer Shanka88c4d1c2017-02-23 16:34:40 -080054
55import android.app.ActivityManager;
Sudheer Shanka4c9afa82017-02-28 19:30:28 -080056import android.app.AppOpsManager;
Sudheer Shanka84a48952017-03-08 18:19:01 -080057import android.app.IApplicationThread;
Sudheer Shanka4c9afa82017-02-28 19:30:28 -080058import android.app.IUidObserver;
Darryl L Johnson11f9a1b2020-04-17 12:32:40 -070059import android.content.ComponentName;
Sudheer Shankadeeb08f2017-03-24 15:53:14 -070060import android.content.Context;
Sudheer Shanka84a48952017-03-08 18:19:01 -080061import android.content.pm.ApplicationInfo;
Sudheer Shankadeeb08f2017-03-24 15:53:14 -070062import android.content.pm.PackageManager;
Darryl L Johnson11f9a1b2020-04-17 12:32:40 -070063import android.content.pm.PackageManagerInternal;
Sudheer Shanka51ab3ac2017-03-07 15:38:01 -080064import android.os.Handler;
65import android.os.HandlerThread;
Sudheer Shanka4c9afa82017-02-28 19:30:28 -080066import android.os.IBinder;
Sudheer Shanka51ab3ac2017-03-07 15:38:01 -080067import android.os.Looper;
68import android.os.Message;
Sudheer Shanka4c9afa82017-02-28 19:30:28 -080069import android.os.Process;
70import android.os.RemoteException;
Sudheer Shanka51ab3ac2017-03-07 15:38:01 -080071import android.os.SystemClock;
Brett Chabota26eda92018-07-23 13:08:30 -070072
Dan Shiebfde332018-10-19 14:25:36 -070073import androidx.test.filters.FlakyTest;
Brett Chabota26eda92018-07-23 13:08:30 -070074import androidx.test.filters.MediumTest;
75import androidx.test.filters.SmallTest;
Sudheer Shanka88c4d1c2017-02-23 16:34:40 -080076
Darryl L Johnson11f9a1b2020-04-17 12:32:40 -070077import com.android.server.LocalServices;
Martijn Coenen01e719b2018-12-05 16:01:38 +010078import com.android.server.am.ProcessList.IsolatedUidRange;
79import com.android.server.am.ProcessList.IsolatedUidRangeAllocator;
Garfield Tanb30145c2019-08-02 17:31:30 -070080import com.android.server.appop.AppOpsService;
Charles Chen8d98dd22018-12-26 17:36:54 +080081import com.android.server.wm.ActivityTaskManagerService;
Sudheer Shanka4c9afa82017-02-28 19:30:28 -080082
Sudheer Shanka51ab3ac2017-03-07 15:38:01 -080083import org.junit.After;
Sudheer Shanka4c9afa82017-02-28 19:30:28 -080084import org.junit.Before;
Darryl L Johnson11f9a1b2020-04-17 12:32:40 -070085import org.junit.BeforeClass;
Garfield Tanb30145c2019-08-02 17:31:30 -070086import org.junit.Rule;
Sudheer Shanka88c4d1c2017-02-23 16:34:40 -080087import org.junit.Test;
Sudheer Shanka4c9afa82017-02-28 19:30:28 -080088import org.mockito.Mock;
89import org.mockito.Mockito;
90import org.mockito.MockitoAnnotations;
Sudheer Shanka88c4d1c2017-02-23 16:34:40 -080091
Sudheer Shanka84a48952017-03-08 18:19:01 -080092import java.io.File;
Sudheer Shanka4c9afa82017-02-28 19:30:28 -080093import java.util.ArrayList;
94import java.util.HashMap;
Sudheer Shanka51ab3ac2017-03-07 15:38:01 -080095import java.util.HashSet;
Sudheer Shanka4c9afa82017-02-28 19:30:28 -080096import java.util.Map;
Sudheer Shanka51ab3ac2017-03-07 15:38:01 -080097import java.util.Set;
Sudheer Shanka88c4d1c2017-02-23 16:34:40 -080098import java.util.function.Function;
99
100/**
101 * Test class for {@link ActivityManagerService}.
102 *
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900103 * Build/Install/Run:
Tadashi G. Takaokad3eb6452018-11-03 18:21:40 -0700104 * atest FrameworksServicesTests:ActivityManagerServiceTest
Sudheer Shanka88c4d1c2017-02-23 16:34:40 -0800105 */
106@SmallTest
Dan Shiebfde332018-10-19 14:25:36 -0700107@FlakyTest(bugId = 113616538)
Sudheer Shanka88c4d1c2017-02-23 16:34:40 -0800108public class ActivityManagerServiceTest {
Sudheer Shanka51ab3ac2017-03-07 15:38:01 -0800109 private static final String TAG = ActivityManagerServiceTest.class.getSimpleName();
110
Sudheer Shankaf4923ea2017-03-27 15:36:35 -0700111 private static final int TEST_UID = 11111;
Sudheer Shanka88c4d1c2017-02-23 16:34:40 -0800112
Sudheer Shanka51ab3ac2017-03-07 15:38:01 -0800113 private static final long TEST_PROC_STATE_SEQ1 = 555;
114 private static final long TEST_PROC_STATE_SEQ2 = 556;
115
116 private static final int[] UID_RECORD_CHANGES = {
117 UidRecord.CHANGE_PROCSTATE,
118 UidRecord.CHANGE_GONE,
Dianne Hackborn3e99f652017-07-05 16:33:56 -0700119 UidRecord.CHANGE_GONE | UidRecord.CHANGE_IDLE,
Sudheer Shanka51ab3ac2017-03-07 15:38:01 -0800120 UidRecord.CHANGE_IDLE,
121 UidRecord.CHANGE_ACTIVE
122 };
123
Darryl L Johnson11f9a1b2020-04-17 12:32:40 -0700124 private static PackageManagerInternal sPackageManagerInternal;
125
126 @BeforeClass
127 public static void setUpOnce() {
128 sPackageManagerInternal = mock(PackageManagerInternal.class);
129 doReturn(new ComponentName("", "")).when(sPackageManagerInternal)
130 .getSystemUiServiceComponent();
131 // Remove stale instance of PackageManagerInternal if there is any
132 LocalServices.removeServiceForTest(PackageManagerInternal.class);
133 LocalServices.addService(PackageManagerInternal.class, sPackageManagerInternal);
134 }
135
Garfield Tanb30145c2019-08-02 17:31:30 -0700136 @Rule public ServiceThreadRule mServiceThreadRule = new ServiceThreadRule();
137
Charles Chen8d98dd22018-12-26 17:36:54 +0800138 private Context mContext = getInstrumentation().getTargetContext();
Sudheer Shanka4c9afa82017-02-28 19:30:28 -0800139 @Mock private AppOpsService mAppOpsService;
Sudheer Shankadeeb08f2017-03-24 15:53:14 -0700140 @Mock private PackageManager mPackageManager;
Sudheer Shanka4c9afa82017-02-28 19:30:28 -0800141
Sudheer Shanka84a48952017-03-08 18:19:01 -0800142 private TestInjector mInjector;
Sudheer Shanka51ab3ac2017-03-07 15:38:01 -0800143 private ActivityManagerService mAms;
144 private HandlerThread mHandlerThread;
145 private TestHandler mHandler;
146
Sudheer Shanka4c9afa82017-02-28 19:30:28 -0800147 @Before
148 public void setUp() {
149 MockitoAnnotations.initMocks(this);
Sudheer Shanka51ab3ac2017-03-07 15:38:01 -0800150
151 mHandlerThread = new HandlerThread(TAG);
152 mHandlerThread.start();
153 mHandler = new TestHandler(mHandlerThread.getLooper());
Sudheer Shanka5269e502019-08-07 16:15:23 -0700154 mInjector = new TestInjector(mContext);
Garfield Tanb30145c2019-08-02 17:31:30 -0700155 mAms = new ActivityManagerService(mInjector, mServiceThreadRule.getThread());
Sudheer Shanka9d3f6682017-04-04 15:27:49 -0700156 mAms.mWaitForNetworkTimeoutMs = 2000;
Charles Chen8d98dd22018-12-26 17:36:54 +0800157 mAms.mActivityTaskManager = new ActivityTaskManagerService(mContext);
158 mAms.mActivityTaskManager.initialize(null, null, mHandler.getLooper());
Sudheer Shanka51ab3ac2017-03-07 15:38:01 -0800159 }
160
161 @After
162 public void tearDown() {
163 mHandlerThread.quit();
Sudheer Shanka4c9afa82017-02-28 19:30:28 -0800164 }
165
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900166 @SuppressWarnings("GuardedBy")
Sudheer Shanka84a48952017-03-08 18:19:01 -0800167 @MediumTest
Sudheer Shanka88c4d1c2017-02-23 16:34:40 -0800168 @Test
Sudheer Shanka84a48952017-03-08 18:19:01 -0800169 public void incrementProcStateSeqAndNotifyAppsLocked() throws Exception {
Sudheer Shanka88c4d1c2017-02-23 16:34:40 -0800170
Sudheer Shankaf4923ea2017-03-27 15:36:35 -0700171 final UidRecord uidRec = addUidRecord(TEST_UID);
172 addUidRecord(TEST_UID + 1);
Sudheer Shanka88c4d1c2017-02-23 16:34:40 -0800173
174 // Uid state is not moving from background to foreground or vice versa.
Sudheer Shanka84a48952017-03-08 18:19:01 -0800175 verifySeqCounterAndInteractions(uidRec,
176 PROCESS_STATE_TOP, // prevState
177 PROCESS_STATE_TOP, // curState
178 0, // expectedGlobalCounter
179 0, // exptectedCurProcStateSeq
180 NETWORK_STATE_NO_CHANGE, // expectedBlockState
181 false); // expectNotify
Sudheer Shanka88c4d1c2017-02-23 16:34:40 -0800182
183 // Uid state is moving from foreground to background.
Sudheer Shanka84a48952017-03-08 18:19:01 -0800184 verifySeqCounterAndInteractions(uidRec,
185 PROCESS_STATE_FOREGROUND_SERVICE, // prevState
186 PROCESS_STATE_SERVICE, // curState
187 1, // expectedGlobalCounter
188 1, // exptectedCurProcStateSeq
189 NETWORK_STATE_UNBLOCK, // expectedBlockState
190 true); // expectNotify
Sudheer Shanka88c4d1c2017-02-23 16:34:40 -0800191
192 // Explicitly setting the seq counter for more verification.
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900193 // @SuppressWarnings("GuardedBy")
Amith Yamasani98a00922018-08-21 12:50:30 -0400194 mAms.mProcessList.mProcStateSeqCounter = 42;
Sudheer Shanka88c4d1c2017-02-23 16:34:40 -0800195
196 // Uid state is not moving from background to foreground or vice versa.
Sudheer Shanka84a48952017-03-08 18:19:01 -0800197 verifySeqCounterAndInteractions(uidRec,
198 PROCESS_STATE_IMPORTANT_BACKGROUND, // prevState
199 PROCESS_STATE_IMPORTANT_FOREGROUND, // curState
200 42, // expectedGlobalCounter
201 1, // exptectedCurProcStateSeq
202 NETWORK_STATE_NO_CHANGE, // expectedBlockState
203 false); // expectNotify
Sudheer Shanka88c4d1c2017-02-23 16:34:40 -0800204
205 // Uid state is moving from background to foreground.
Sudheer Shanka84a48952017-03-08 18:19:01 -0800206 verifySeqCounterAndInteractions(uidRec,
207 PROCESS_STATE_LAST_ACTIVITY, // prevState
208 PROCESS_STATE_TOP, // curState
209 43, // expectedGlobalCounter
210 43, // exptectedCurProcStateSeq
211 NETWORK_STATE_BLOCK, // expectedBlockState
212 false); // expectNotify
213
214 // verify waiting threads are not notified.
215 uidRec.waitingForNetwork = false;
216 // Uid state is moving from foreground to background.
217 verifySeqCounterAndInteractions(uidRec,
218 PROCESS_STATE_FOREGROUND_SERVICE, // prevState
219 PROCESS_STATE_SERVICE, // curState
220 44, // expectedGlobalCounter
221 44, // exptectedCurProcStateSeq
222 NETWORK_STATE_UNBLOCK, // expectedBlockState
223 false); // expectNotify
224
225 // Verify when uid is not restricted, procStateSeq is not incremented.
226 uidRec.waitingForNetwork = true;
227 mInjector.setNetworkRestrictedForUid(false);
228 verifySeqCounterAndInteractions(uidRec,
229 PROCESS_STATE_IMPORTANT_BACKGROUND, // prevState
230 PROCESS_STATE_TOP, // curState
231 44, // expectedGlobalCounter
232 44, // exptectedCurProcStateSeq
233 -1, // expectedBlockState, -1 to verify there are no interactions with main thread.
234 false); // expectNotify
Sudheer Shanka5918c672017-03-21 19:31:37 -0700235
236 // Verify when waitForNetworkTimeout is 0, then procStateSeq is not incremented.
237 mAms.mWaitForNetworkTimeoutMs = 0;
238 mInjector.setNetworkRestrictedForUid(true);
239 verifySeqCounterAndInteractions(uidRec,
240 PROCESS_STATE_TOP, // prevState
241 PROCESS_STATE_IMPORTANT_BACKGROUND, // curState
242 44, // expectedGlobalCounter
243 44, // exptectedCurProcStateSeq
244 -1, // expectedBlockState, -1 to verify there are no interactions with main thread.
245 false); // expectNotify
Sudheer Shankaf4923ea2017-03-27 15:36:35 -0700246
247 // Verify when the uid doesn't have internet permission, then procStateSeq is not
248 // incremented.
249 uidRec.hasInternetPermission = false;
250 mAms.mWaitForNetworkTimeoutMs = 111;
251 mInjector.setNetworkRestrictedForUid(true);
252 verifySeqCounterAndInteractions(uidRec,
253 PROCESS_STATE_CACHED_ACTIVITY, // prevState
254 PROCESS_STATE_FOREGROUND_SERVICE, // curState
255 44, // expectedGlobalCounter
256 44, // exptectedCurProcStateSeq
257 -1, // expectedBlockState, -1 to verify there are no interactions with main thread.
258 false); // expectNotify
259
260 // Verify procStateSeq is not incremented when the uid is not an application, regardless
261 // of the process state.
262 final int notAppUid = 111;
263 final UidRecord uidRec2 = addUidRecord(notAppUid);
264 verifySeqCounterAndInteractions(uidRec2,
265 PROCESS_STATE_CACHED_EMPTY, // prevState
266 PROCESS_STATE_TOP, // curState
267 44, // expectedGlobalCounter
268 0, // exptectedCurProcStateSeq
269 -1, // expectedBlockState, -1 to verify there are no interactions with main thread.
270 false); // expectNotify
271 }
272
273 private UidRecord addUidRecord(int uid) {
Riddle Hsud7088f82019-01-30 13:04:50 +0800274 final UidRecord uidRec = new UidRecord(uid);
Sudheer Shankaf4923ea2017-03-27 15:36:35 -0700275 uidRec.waitingForNetwork = true;
276 uidRec.hasInternetPermission = true;
Amith Yamasaniaa746442019-01-10 10:09:12 -0800277 mAms.mProcessList.mActiveUids.put(uid, uidRec);
Sudheer Shankaf4923ea2017-03-27 15:36:35 -0700278
Darryl L Johnson11f9a1b2020-04-17 12:32:40 -0700279 ApplicationInfo info = new ApplicationInfo();
280 info.packageName = "";
281
282 final ProcessRecord appRec = new ProcessRecord(mAms, info, TAG, uid);
283 appRec.thread = mock(IApplicationThread.class);
Amith Yamasani98a00922018-08-21 12:50:30 -0400284 mAms.mProcessList.mLruProcesses.add(appRec);
Sudheer Shankaf4923ea2017-03-27 15:36:35 -0700285
286 return uidRec;
Sudheer Shanka84a48952017-03-08 18:19:01 -0800287 }
288
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900289 @SuppressWarnings("GuardedBy")
Sudheer Shanka84a48952017-03-08 18:19:01 -0800290 private void verifySeqCounterAndInteractions(UidRecord uidRec, int prevState, int curState,
291 int expectedGlobalCounter, int expectedCurProcStateSeq, int expectedBlockState,
292 boolean expectNotify) throws Exception {
Sudheer Shankaf4923ea2017-03-27 15:36:35 -0700293 CustomThread thread = new CustomThread(uidRec.networkStateLock);
Sudheer Shanka84a48952017-03-08 18:19:01 -0800294 thread.startAndWait("Unexpected state for " + uidRec);
295
296 uidRec.setProcState = prevState;
Wale Ogunwalebff2df42018-10-18 17:09:19 -0700297 uidRec.setCurProcState(curState);
Jing Ji094c3ef2019-08-27 17:02:09 -0700298 mAms.mProcessList.incrementProcStateSeqAndNotifyAppsLocked(mAms.mProcessList.mActiveUids);
Sudheer Shanka84a48952017-03-08 18:19:01 -0800299
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900300 // @SuppressWarnings("GuardedBy")
Amith Yamasani98a00922018-08-21 12:50:30 -0400301 assertEquals(expectedGlobalCounter, mAms.mProcessList.mProcStateSeqCounter);
Sudheer Shanka84a48952017-03-08 18:19:01 -0800302 assertEquals(expectedCurProcStateSeq, uidRec.curProcStateSeq);
303
Amith Yamasani98a00922018-08-21 12:50:30 -0400304 for (int i = mAms.mProcessList.getLruSizeLocked() - 1; i >= 0; --i) {
305 final ProcessRecord app = mAms.mProcessList.mLruProcesses.get(i);
Sudheer Shanka84a48952017-03-08 18:19:01 -0800306 // AMS should notify apps only for block states other than NETWORK_STATE_NO_CHANGE.
307 if (app.uid == uidRec.uid && expectedBlockState == NETWORK_STATE_BLOCK) {
308 verify(app.thread).setNetworkBlockSeq(uidRec.curProcStateSeq);
309 } else {
310 verifyZeroInteractions(app.thread);
311 }
312 Mockito.reset(app.thread);
313 }
314
315 if (expectNotify) {
316 thread.assertTerminated("Unexpected state for " + uidRec);
317 } else {
318 thread.assertWaiting("Unexpected state for " + uidRec);
319 thread.interrupt();
320 }
Sudheer Shanka88c4d1c2017-02-23 16:34:40 -0800321 }
322
Martijn Coenen01e719b2018-12-05 16:01:38 +0100323 private void validateAppZygoteIsolatedUidRange(IsolatedUidRange uidRange) {
324 assertNotNull(uidRange);
325 assertTrue(uidRange.mFirstUid >= Process.FIRST_APP_ZYGOTE_ISOLATED_UID
326 && uidRange.mFirstUid <= Process.LAST_APP_ZYGOTE_ISOLATED_UID);
327 assertTrue(uidRange.mLastUid >= Process.FIRST_APP_ZYGOTE_ISOLATED_UID
328 && uidRange.mLastUid <= Process.LAST_APP_ZYGOTE_ISOLATED_UID);
329 assertTrue(uidRange.mLastUid > uidRange.mFirstUid
330 && ((uidRange.mLastUid - uidRange.mFirstUid + 1)
331 == Process.NUM_UIDS_PER_APP_ZYGOTE));
332 }
333
334 private void verifyUidRangesNoOverlap(IsolatedUidRange uidRange1, IsolatedUidRange uidRange2) {
335 IsolatedUidRange lowRange = uidRange1.mFirstUid <= uidRange2.mFirstUid ? uidRange1 : uidRange2;
336 IsolatedUidRange highRange = lowRange == uidRange1 ? uidRange2 : uidRange1;
337
338 assertTrue(highRange.mFirstUid > lowRange.mLastUid);
339 }
340
341 @Test
342 public void testIsolatedUidRangeAllocator() {
343 final IsolatedUidRangeAllocator allocator = mAms.mProcessList.mAppIsolatedUidRangeAllocator;
344
345 // Create initial range
346 ApplicationInfo appInfo = new ApplicationInfo();
347 appInfo.processName = "com.android.test.app";
348 appInfo.uid = 10000;
Martijn Coenen572ed7f2019-03-28 19:50:44 +0100349 final IsolatedUidRange range = allocator.getOrCreateIsolatedUidRangeLocked(
350 appInfo.processName, appInfo.uid);
Martijn Coenen01e719b2018-12-05 16:01:38 +0100351 validateAppZygoteIsolatedUidRange(range);
352 verifyIsolatedUidAllocator(range);
353
354 // Create a second range
355 ApplicationInfo appInfo2 = new ApplicationInfo();
356 appInfo2.processName = "com.android.test.app2";
357 appInfo2.uid = 10001;
Martijn Coenen572ed7f2019-03-28 19:50:44 +0100358 IsolatedUidRange range2 = allocator.getOrCreateIsolatedUidRangeLocked(
359 appInfo2.processName, appInfo2.uid);
Martijn Coenen01e719b2018-12-05 16:01:38 +0100360 validateAppZygoteIsolatedUidRange(range2);
361 verifyIsolatedUidAllocator(range2);
362
363 // Verify ranges don't overlap
364 verifyUidRangesNoOverlap(range, range2);
365
366 // Free range, reallocate and verify
367 allocator.freeUidRangeLocked(appInfo2);
Martijn Coenen572ed7f2019-03-28 19:50:44 +0100368 range2 = allocator.getOrCreateIsolatedUidRangeLocked(appInfo2.processName, appInfo2.uid);
Martijn Coenen01e719b2018-12-05 16:01:38 +0100369 validateAppZygoteIsolatedUidRange(range2);
370 verifyUidRangesNoOverlap(range, range2);
371 verifyIsolatedUidAllocator(range2);
372
Martijn Coenenc9a0df22019-12-18 07:01:25 +0100373 // Free both
Martijn Coenen01e719b2018-12-05 16:01:38 +0100374 allocator.freeUidRangeLocked(appInfo);
375 allocator.freeUidRangeLocked(appInfo2);
376
Martijn Coenenc9a0df22019-12-18 07:01:25 +0100377 // Verify for a secondary user
378 ApplicationInfo appInfo3 = new ApplicationInfo();
379 appInfo3.processName = "com.android.test.app";
380 appInfo3.uid = 1010000;
381 final IsolatedUidRange range3 = allocator.getOrCreateIsolatedUidRangeLocked(
382 appInfo3.processName, appInfo3.uid);
383 validateAppZygoteIsolatedUidRange(range3);
384 verifyIsolatedUidAllocator(range3);
385
386 allocator.freeUidRangeLocked(appInfo3);
387 // Try to allocate the maximum number of UID ranges
Martijn Coenen01e719b2018-12-05 16:01:38 +0100388 int maxNumUidRanges = (Process.LAST_APP_ZYGOTE_ISOLATED_UID
389 - Process.FIRST_APP_ZYGOTE_ISOLATED_UID + 1) / Process.NUM_UIDS_PER_APP_ZYGOTE;
390 for (int i = 0; i < maxNumUidRanges; i++) {
391 appInfo = new ApplicationInfo();
392 appInfo.uid = 10000 + i;
393 appInfo.processName = "com.android.test.app" + Integer.toString(i);
Martijn Coenen572ed7f2019-03-28 19:50:44 +0100394 IsolatedUidRange uidRange = allocator.getOrCreateIsolatedUidRangeLocked(
395 appInfo.processName, appInfo.uid);
Martijn Coenen01e719b2018-12-05 16:01:38 +0100396 validateAppZygoteIsolatedUidRange(uidRange);
397 verifyIsolatedUidAllocator(uidRange);
398 }
399
400 // Try to allocate another one and make sure it fails
401 appInfo = new ApplicationInfo();
402 appInfo.uid = 9000;
403 appInfo.processName = "com.android.test.app.failed";
Martijn Coenen572ed7f2019-03-28 19:50:44 +0100404 IsolatedUidRange failedRange = allocator.getOrCreateIsolatedUidRangeLocked(
405 appInfo.processName, appInfo.uid);
Martijn Coenen01e719b2018-12-05 16:01:38 +0100406
407 assertNull(failedRange);
408 }
409
410 public void verifyIsolatedUid(ProcessList.IsolatedUidRange range, int uid) {
411 assertTrue(uid >= range.mFirstUid && uid <= range.mLastUid);
412 }
413
414 public void verifyIsolatedUidAllocator(ProcessList.IsolatedUidRange range) {
415 int uid = range.allocateIsolatedUidLocked(0);
416 verifyIsolatedUid(range, uid);
417
418 int uid2 = range.allocateIsolatedUidLocked(0);
419 verifyIsolatedUid(range, uid2);
420 assertTrue(uid2 != uid);
421
422 // Free both
423 range.freeIsolatedUidLocked(uid);
424 range.freeIsolatedUidLocked(uid2);
425
426 // Allocate the entire range
427 for (int i = 0; i < (range.mLastUid - range.mFirstUid + 1); ++i) {
428 uid = range.allocateIsolatedUidLocked(0);
429 verifyIsolatedUid(range, uid);
430 }
431
432 // Ensure the next one fails
433 uid = range.allocateIsolatedUidLocked(0);
434 assertEquals(uid, -1);
435 }
436
437 @Test
438 public void testGlobalIsolatedUidAllocator() {
439 final IsolatedUidRange globalUidRange = mAms.mProcessList.mGlobalIsolatedUids;
440 assertEquals(globalUidRange.mFirstUid, Process.FIRST_ISOLATED_UID);
441 assertEquals(globalUidRange.mLastUid, Process.LAST_ISOLATED_UID);
442 verifyIsolatedUidAllocator(globalUidRange);
443 }
444
Sudheer Shanka88c4d1c2017-02-23 16:34:40 -0800445 @Test
Sudheer Shanka84a48952017-03-08 18:19:01 -0800446 public void testBlockStateForUid() {
Riddle Hsud7088f82019-01-30 13:04:50 +0800447 final UidRecord uidRec = new UidRecord(TEST_UID);
Sudheer Shanka84a48952017-03-08 18:19:01 -0800448 int expectedBlockState;
Sudheer Shanka88c4d1c2017-02-23 16:34:40 -0800449
Sudheer Shanka84a48952017-03-08 18:19:01 -0800450 final String errorTemplate = "Block state should be %s, prevState: %s, curState: %s";
451 Function<Integer, String> errorMsg = (blockState) -> {
Sudheer Shanka88c4d1c2017-02-23 16:34:40 -0800452 return String.format(errorTemplate,
Sudheer Shanka84a48952017-03-08 18:19:01 -0800453 valueToString(ActivityManagerService.class, "NETWORK_STATE_", blockState),
Sudheer Shanka88c4d1c2017-02-23 16:34:40 -0800454 valueToString(ActivityManager.class, "PROCESS_STATE_", uidRec.setProcState),
Wale Ogunwalebff2df42018-10-18 17:09:19 -0700455 valueToString(ActivityManager.class, "PROCESS_STATE_", uidRec.getCurProcState())
456 );
Sudheer Shanka88c4d1c2017-02-23 16:34:40 -0800457 };
458
459 // No change in uid state
460 uidRec.setProcState = PROCESS_STATE_RECEIVER;
Wale Ogunwalebff2df42018-10-18 17:09:19 -0700461 uidRec.setCurProcState(PROCESS_STATE_RECEIVER);
Sudheer Shanka84a48952017-03-08 18:19:01 -0800462 expectedBlockState = NETWORK_STATE_NO_CHANGE;
463 assertEquals(errorMsg.apply(expectedBlockState),
Jing Ji094c3ef2019-08-27 17:02:09 -0700464 expectedBlockState, mAms.mProcessList.getBlockStateForUid(uidRec));
Sudheer Shanka88c4d1c2017-02-23 16:34:40 -0800465
466 // Foreground to foreground
467 uidRec.setProcState = PROCESS_STATE_FOREGROUND_SERVICE;
Wale Ogunwalebff2df42018-10-18 17:09:19 -0700468 uidRec.setCurProcState(PROCESS_STATE_BOUND_FOREGROUND_SERVICE);
Sudheer Shanka84a48952017-03-08 18:19:01 -0800469 expectedBlockState = NETWORK_STATE_NO_CHANGE;
470 assertEquals(errorMsg.apply(expectedBlockState),
Jing Ji094c3ef2019-08-27 17:02:09 -0700471 expectedBlockState, mAms.mProcessList.getBlockStateForUid(uidRec));
Sudheer Shanka88c4d1c2017-02-23 16:34:40 -0800472
473 // Background to background
474 uidRec.setProcState = PROCESS_STATE_CACHED_ACTIVITY;
Wale Ogunwalebff2df42018-10-18 17:09:19 -0700475 uidRec.setCurProcState(PROCESS_STATE_CACHED_EMPTY);
Sudheer Shanka84a48952017-03-08 18:19:01 -0800476 expectedBlockState = NETWORK_STATE_NO_CHANGE;
477 assertEquals(errorMsg.apply(expectedBlockState),
Jing Ji094c3ef2019-08-27 17:02:09 -0700478 expectedBlockState, mAms.mProcessList.getBlockStateForUid(uidRec));
Sudheer Shanka88c4d1c2017-02-23 16:34:40 -0800479
480 // Background to background
481 uidRec.setProcState = PROCESS_STATE_NONEXISTENT;
Wale Ogunwalebff2df42018-10-18 17:09:19 -0700482 uidRec.setCurProcState(PROCESS_STATE_CACHED_ACTIVITY);
Sudheer Shanka84a48952017-03-08 18:19:01 -0800483 expectedBlockState = NETWORK_STATE_NO_CHANGE;
484 assertEquals(errorMsg.apply(expectedBlockState),
Jing Ji094c3ef2019-08-27 17:02:09 -0700485 expectedBlockState, mAms.mProcessList.getBlockStateForUid(uidRec));
Sudheer Shanka88c4d1c2017-02-23 16:34:40 -0800486
487 // Background to foreground
488 uidRec.setProcState = PROCESS_STATE_SERVICE;
Wale Ogunwalebff2df42018-10-18 17:09:19 -0700489 uidRec.setCurProcState(PROCESS_STATE_FOREGROUND_SERVICE);
Sudheer Shanka84a48952017-03-08 18:19:01 -0800490 expectedBlockState = NETWORK_STATE_BLOCK;
491 assertEquals(errorMsg.apply(expectedBlockState),
Jing Ji094c3ef2019-08-27 17:02:09 -0700492 expectedBlockState, mAms.mProcessList.getBlockStateForUid(uidRec));
Sudheer Shanka88c4d1c2017-02-23 16:34:40 -0800493
494 // Foreground to background
495 uidRec.setProcState = PROCESS_STATE_TOP;
Wale Ogunwalebff2df42018-10-18 17:09:19 -0700496 uidRec.setCurProcState(PROCESS_STATE_LAST_ACTIVITY);
Sudheer Shanka84a48952017-03-08 18:19:01 -0800497 expectedBlockState = NETWORK_STATE_UNBLOCK;
498 assertEquals(errorMsg.apply(expectedBlockState),
Jing Ji094c3ef2019-08-27 17:02:09 -0700499 expectedBlockState, mAms.mProcessList.getBlockStateForUid(uidRec));
Sudheer Shanka88c4d1c2017-02-23 16:34:40 -0800500 }
Sudheer Shanka4c9afa82017-02-28 19:30:28 -0800501
502 /**
503 * This test verifies that process state changes are dispatched to observers based on the
504 * changes they wanted to listen (this is specified when registering the observer).
505 */
506 @Test
507 public void testDispatchUids_dispatchNeededChanges() throws RemoteException {
Philip P. Moltmann59076d82019-08-19 15:00:40 -0700508 when(mAppOpsService.noteOperation(AppOpsManager.OP_GET_USAGE_STATS, Process.myUid(), null,
Philip P. Moltmannda554e42019-12-20 11:21:02 -0800509 null, false, null)).thenReturn(AppOpsManager.MODE_ALLOWED);
Sudheer Shanka4c9afa82017-02-28 19:30:28 -0800510
511 final int[] changesToObserve = {
512 ActivityManager.UID_OBSERVER_PROCSTATE,
513 ActivityManager.UID_OBSERVER_GONE,
514 ActivityManager.UID_OBSERVER_IDLE,
515 ActivityManager.UID_OBSERVER_ACTIVE,
516 ActivityManager.UID_OBSERVER_PROCSTATE | ActivityManager.UID_OBSERVER_GONE
517 | ActivityManager.UID_OBSERVER_ACTIVE | ActivityManager.UID_OBSERVER_IDLE
518 };
519 final IUidObserver[] observers = new IUidObserver.Stub[changesToObserve.length];
520 for (int i = 0; i < observers.length; ++i) {
Darryl L Johnson11f9a1b2020-04-17 12:32:40 -0700521 observers[i] = mock(IUidObserver.Stub.class);
Sudheer Shanka4c9afa82017-02-28 19:30:28 -0800522 when(observers[i].asBinder()).thenReturn((IBinder) observers[i]);
Sudheer Shanka51ab3ac2017-03-07 15:38:01 -0800523 mAms.registerUidObserver(observers[i], changesToObserve[i] /* which */,
Sudheer Shanka4c9afa82017-02-28 19:30:28 -0800524 ActivityManager.PROCESS_STATE_UNKNOWN /* cutpoint */, null /* caller */);
525
526 // When we invoke AMS.registerUidObserver, there are some interactions with observers[i]
527 // mock in RemoteCallbackList class. We don't want to test those interactions and
528 // at the same time, we don't want those to interfere with verifyNoMoreInteractions.
529 // So, resetting the mock here.
530 Mockito.reset(observers[i]);
531 }
532
533 // Add pending uid records each corresponding to a different change type UidRecord.CHANGE_*
Sudheer Shanka51ab3ac2017-03-07 15:38:01 -0800534 final int[] changesForPendingUidRecords = UID_RECORD_CHANGES;
535
Sudheer Shanka4c9afa82017-02-28 19:30:28 -0800536 final int[] procStatesForPendingUidRecords = {
537 ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE,
538 ActivityManager.PROCESS_STATE_NONEXISTENT,
539 ActivityManager.PROCESS_STATE_CACHED_EMPTY,
540 ActivityManager.PROCESS_STATE_CACHED_ACTIVITY,
541 ActivityManager.PROCESS_STATE_TOP
542 };
543 final Map<Integer, UidRecord.ChangeItem> changeItems = new HashMap<>();
544 for (int i = 0; i < changesForPendingUidRecords.length; ++i) {
545 final UidRecord.ChangeItem pendingChange = new UidRecord.ChangeItem();
546 pendingChange.change = changesForPendingUidRecords[i];
547 pendingChange.uid = i;
548 pendingChange.processState = procStatesForPendingUidRecords[i];
Sudheer Shanka80255802017-03-04 14:48:53 -0800549 pendingChange.procStateSeq = i;
Sudheer Shanka4c9afa82017-02-28 19:30:28 -0800550 changeItems.put(changesForPendingUidRecords[i], pendingChange);
Sudheer Shanka51ab3ac2017-03-07 15:38:01 -0800551 mAms.mPendingUidChanges.add(pendingChange);
Sudheer Shanka4c9afa82017-02-28 19:30:28 -0800552 }
553
Sudheer Shanka51ab3ac2017-03-07 15:38:01 -0800554 mAms.dispatchUidsChanged();
Sudheer Shanka4c9afa82017-02-28 19:30:28 -0800555 // Verify the required changes have been dispatched to observers.
556 for (int i = 0; i < observers.length; ++i) {
557 final int changeToObserve = changesToObserve[i];
558 final IUidObserver observerToTest = observers[i];
559 if ((changeToObserve & ActivityManager.UID_OBSERVER_IDLE) != 0) {
560 // Observer listens to uid idle changes, so change items corresponding to
561 // UidRecord.CHANGE_IDLE or UidRecord.CHANGE_IDLE_GONE needs to be
562 // delivered to this observer.
563 final int[] changesToVerify = {
564 UidRecord.CHANGE_IDLE,
Dianne Hackborn3e99f652017-07-05 16:33:56 -0700565 UidRecord.CHANGE_GONE | UidRecord.CHANGE_IDLE
Sudheer Shanka4c9afa82017-02-28 19:30:28 -0800566 };
567 verifyObserverReceivedChanges(observerToTest, changesToVerify, changeItems,
568 (observer, changeItem) -> {
569 verify(observer).onUidIdle(changeItem.uid, changeItem.ephemeral);
570 });
571 }
572 if ((changeToObserve & ActivityManager.UID_OBSERVER_ACTIVE) != 0) {
573 // Observer listens to uid active changes, so change items corresponding to
574 // UidRecord.CHANGE_ACTIVE needs to be delivered to this observer.
575 final int[] changesToVerify = { UidRecord.CHANGE_ACTIVE };
576 verifyObserverReceivedChanges(observerToTest, changesToVerify, changeItems,
577 (observer, changeItem) -> {
578 verify(observer).onUidActive(changeItem.uid);
579 });
580 }
581 if ((changeToObserve & ActivityManager.UID_OBSERVER_GONE) != 0) {
582 // Observer listens to uid gone changes, so change items corresponding to
583 // UidRecord.CHANGE_GONE or UidRecord.CHANGE_IDLE_GONE needs to be
584 // delivered to this observer.
585 final int[] changesToVerify = {
586 UidRecord.CHANGE_GONE,
Dianne Hackborn3e99f652017-07-05 16:33:56 -0700587 UidRecord.CHANGE_GONE | UidRecord.CHANGE_IDLE
Sudheer Shanka4c9afa82017-02-28 19:30:28 -0800588 };
589 verifyObserverReceivedChanges(observerToTest, changesToVerify, changeItems,
590 (observer, changeItem) -> {
591 verify(observer).onUidGone(changeItem.uid, changeItem.ephemeral);
592 });
593 }
594 if ((changeToObserve & ActivityManager.UID_OBSERVER_PROCSTATE) != 0) {
595 // Observer listens to uid procState changes, so change items corresponding to
596 // UidRecord.CHANGE_PROCSTATE or UidRecord.CHANGE_IDLE or UidRecord.CHANGE_ACTIVE
597 // needs to be delivered to this observer.
598 final int[] changesToVerify = {
599 UidRecord.CHANGE_PROCSTATE,
600 UidRecord.CHANGE_ACTIVE,
601 UidRecord.CHANGE_IDLE
602 };
603 verifyObserverReceivedChanges(observerToTest, changesToVerify, changeItems,
604 (observer, changeItem) -> {
Sudheer Shanka80255802017-03-04 14:48:53 -0800605 verify(observer).onUidStateChanged(changeItem.uid,
Hui Yu26969322019-08-21 14:56:35 -0700606 changeItem.processState, changeItem.procStateSeq,
607 ActivityManager.PROCESS_CAPABILITY_NONE);
Sudheer Shanka4c9afa82017-02-28 19:30:28 -0800608 });
609 }
610 // Verify there are no other callbacks for this observer.
611 verifyNoMoreInteractions(observerToTest);
612 }
613 }
614
615 private interface ObserverChangesVerifier {
616 void verify(IUidObserver observer, UidRecord.ChangeItem changeItem) throws RemoteException;
617 }
618
619 private void verifyObserverReceivedChanges(IUidObserver observer, int[] changesToVerify,
620 Map<Integer, UidRecord.ChangeItem> changeItems, ObserverChangesVerifier verifier)
621 throws RemoteException {
622 for (int change : changesToVerify) {
623 final UidRecord.ChangeItem changeItem = changeItems.get(change);
624 verifier.verify(observer, changeItem);
625 }
626 }
627
628 /**
629 * This test verifies that process state changes are dispatched to observers only when they
630 * change across the cutpoint (this is specified when registering the observer).
631 */
632 @Test
633 public void testDispatchUidChanges_procStateCutpoint() throws RemoteException {
Darryl L Johnson11f9a1b2020-04-17 12:32:40 -0700634 final IUidObserver observer = mock(IUidObserver.Stub.class);
Sudheer Shanka4c9afa82017-02-28 19:30:28 -0800635
636 when(observer.asBinder()).thenReturn((IBinder) observer);
Sudheer Shanka51ab3ac2017-03-07 15:38:01 -0800637 mAms.registerUidObserver(observer, ActivityManager.UID_OBSERVER_PROCSTATE /* which */,
Sudheer Shanka4c9afa82017-02-28 19:30:28 -0800638 ActivityManager.PROCESS_STATE_SERVICE /* cutpoint */, null /* callingPackage */);
639 // When we invoke AMS.registerUidObserver, there are some interactions with observer
640 // mock in RemoteCallbackList class. We don't want to test those interactions and
641 // at the same time, we don't want those to interfere with verifyNoMoreInteractions.
642 // So, resetting the mock here.
643 Mockito.reset(observer);
644
645 final UidRecord.ChangeItem changeItem = new UidRecord.ChangeItem();
646 changeItem.uid = TEST_UID;
647 changeItem.change = UidRecord.CHANGE_PROCSTATE;
648 changeItem.processState = ActivityManager.PROCESS_STATE_LAST_ACTIVITY;
Sudheer Shanka80255802017-03-04 14:48:53 -0800649 changeItem.procStateSeq = 111;
Sudheer Shanka51ab3ac2017-03-07 15:38:01 -0800650 mAms.mPendingUidChanges.add(changeItem);
651 mAms.dispatchUidsChanged();
Sudheer Shanka4c9afa82017-02-28 19:30:28 -0800652 // First process state message is always delivered regardless of whether the process state
653 // change is above or below the cutpoint (PROCESS_STATE_SERVICE).
654 verify(observer).onUidStateChanged(TEST_UID,
Hui Yu26969322019-08-21 14:56:35 -0700655 changeItem.processState, changeItem.procStateSeq,
656 ActivityManager.PROCESS_CAPABILITY_NONE);
Sudheer Shanka4c9afa82017-02-28 19:30:28 -0800657 verifyNoMoreInteractions(observer);
658
659 changeItem.processState = ActivityManager.PROCESS_STATE_RECEIVER;
Sudheer Shanka51ab3ac2017-03-07 15:38:01 -0800660 mAms.mPendingUidChanges.add(changeItem);
661 mAms.dispatchUidsChanged();
Sudheer Shanka4c9afa82017-02-28 19:30:28 -0800662 // Previous process state change is below cutpoint (PROCESS_STATE_SERVICE) and
663 // the current process state change is also below cutpoint, so no callback will be invoked.
664 verifyNoMoreInteractions(observer);
665
666 changeItem.processState = ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
Sudheer Shanka51ab3ac2017-03-07 15:38:01 -0800667 mAms.mPendingUidChanges.add(changeItem);
668 mAms.dispatchUidsChanged();
Sudheer Shanka4c9afa82017-02-28 19:30:28 -0800669 // Previous process state change is below cutpoint (PROCESS_STATE_SERVICE) and
670 // the current process state change is above cutpoint, so callback will be invoked with the
671 // current process state change.
672 verify(observer).onUidStateChanged(TEST_UID,
Hui Yu26969322019-08-21 14:56:35 -0700673 changeItem.processState, changeItem.procStateSeq,
674 ActivityManager.PROCESS_CAPABILITY_NONE);
Sudheer Shanka4c9afa82017-02-28 19:30:28 -0800675 verifyNoMoreInteractions(observer);
676
677 changeItem.processState = ActivityManager.PROCESS_STATE_TOP;
Sudheer Shanka51ab3ac2017-03-07 15:38:01 -0800678 mAms.mPendingUidChanges.add(changeItem);
679 mAms.dispatchUidsChanged();
Sudheer Shanka4c9afa82017-02-28 19:30:28 -0800680 // Previous process state change is above cutpoint (PROCESS_STATE_SERVICE) and
681 // the current process state change is also above cutpoint, so no callback will be invoked.
682 verifyNoMoreInteractions(observer);
683
684 changeItem.processState = ActivityManager.PROCESS_STATE_CACHED_EMPTY;
Sudheer Shanka51ab3ac2017-03-07 15:38:01 -0800685 mAms.mPendingUidChanges.add(changeItem);
686 mAms.dispatchUidsChanged();
Sudheer Shanka4c9afa82017-02-28 19:30:28 -0800687 // Previous process state change is above cutpoint (PROCESS_STATE_SERVICE) and
688 // the current process state change is below cutpoint, so callback will be invoked with the
689 // current process state change.
Sudheer Shanka80255802017-03-04 14:48:53 -0800690 verify(observer).onUidStateChanged(TEST_UID,
Hui Yu26969322019-08-21 14:56:35 -0700691 changeItem.processState, changeItem.procStateSeq,
692 ActivityManager.PROCESS_CAPABILITY_NONE);
Sudheer Shanka4c9afa82017-02-28 19:30:28 -0800693 verifyNoMoreInteractions(observer);
694 }
695
696 /**
697 * This test verifies that {@link ActivityManagerService#mValidateUids} which is a
698 * part of dumpsys is correctly updated.
699 */
700 @Test
701 public void testDispatchUidChanges_validateUidsUpdated() {
Sudheer Shanka51ab3ac2017-03-07 15:38:01 -0800702 final int[] changesForPendingItems = UID_RECORD_CHANGES;
Sudheer Shanka4c9afa82017-02-28 19:30:28 -0800703
Sudheer Shanka4c9afa82017-02-28 19:30:28 -0800704 final int[] procStatesForPendingItems = {
705 ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE,
706 ActivityManager.PROCESS_STATE_CACHED_EMPTY,
707 ActivityManager.PROCESS_STATE_CACHED_ACTIVITY,
708 ActivityManager.PROCESS_STATE_SERVICE,
709 ActivityManager.PROCESS_STATE_RECEIVER
710 };
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900711 final ArrayList<UidRecord.ChangeItem> pendingItemsForUids =
712 new ArrayList<>(changesForPendingItems.length);
Sudheer Shanka4c9afa82017-02-28 19:30:28 -0800713 for (int i = 0; i < changesForPendingItems.length; ++i) {
714 final UidRecord.ChangeItem item = new UidRecord.ChangeItem();
715 item.uid = i;
716 item.change = changesForPendingItems[i];
717 item.processState = procStatesForPendingItems[i];
718 pendingItemsForUids.add(i, item);
719 }
720
721 // Verify that when there no observers listening to uid state changes, then there will
722 // be no changes to validateUids.
Sudheer Shanka51ab3ac2017-03-07 15:38:01 -0800723 mAms.mPendingUidChanges.addAll(pendingItemsForUids);
724 mAms.dispatchUidsChanged();
Sudheer Shanka4c9afa82017-02-28 19:30:28 -0800725 assertEquals("No observers registered, so validateUids should be empty",
Sudheer Shanka51ab3ac2017-03-07 15:38:01 -0800726 0, mAms.mValidateUids.size());
Sudheer Shanka4c9afa82017-02-28 19:30:28 -0800727
Darryl L Johnson11f9a1b2020-04-17 12:32:40 -0700728 final IUidObserver observer = mock(IUidObserver.Stub.class);
Sudheer Shanka4c9afa82017-02-28 19:30:28 -0800729 when(observer.asBinder()).thenReturn((IBinder) observer);
Sudheer Shanka51ab3ac2017-03-07 15:38:01 -0800730 mAms.registerUidObserver(observer, 0, 0, null);
Sudheer Shanka4c9afa82017-02-28 19:30:28 -0800731 // Verify that when observers are registered, then validateUids is correctly updated.
Sudheer Shanka51ab3ac2017-03-07 15:38:01 -0800732 mAms.mPendingUidChanges.addAll(pendingItemsForUids);
733 mAms.dispatchUidsChanged();
Sudheer Shanka4c9afa82017-02-28 19:30:28 -0800734 for (int i = 0; i < pendingItemsForUids.size(); ++i) {
735 final UidRecord.ChangeItem item = pendingItemsForUids.get(i);
Sudheer Shanka51ab3ac2017-03-07 15:38:01 -0800736 final UidRecord validateUidRecord = mAms.mValidateUids.get(item.uid);
Dianne Hackborn3e99f652017-07-05 16:33:56 -0700737 if ((item.change & UidRecord.CHANGE_GONE) != 0) {
Sudheer Shanka4c9afa82017-02-28 19:30:28 -0800738 assertNull("validateUidRecord should be null since the change is either "
739 + "CHANGE_GONE or CHANGE_GONE_IDLE", validateUidRecord);
740 } else {
741 assertNotNull("validateUidRecord should not be null since the change is neither "
742 + "CHANGE_GONE nor CHANGE_GONE_IDLE", validateUidRecord);
743 assertEquals("processState: " + item.processState + " curProcState: "
Wale Ogunwalebff2df42018-10-18 17:09:19 -0700744 + validateUidRecord.getCurProcState() + " should have been equal",
745 item.processState, validateUidRecord.getCurProcState());
Sudheer Shanka4c9afa82017-02-28 19:30:28 -0800746 assertEquals("processState: " + item.processState + " setProcState: "
Wale Ogunwalebff2df42018-10-18 17:09:19 -0700747 + validateUidRecord.getCurProcState() + " should have been equal",
Sudheer Shanka4c9afa82017-02-28 19:30:28 -0800748 item.processState, validateUidRecord.setProcState);
749 if (item.change == UidRecord.CHANGE_IDLE) {
750 assertTrue("UidRecord.idle should be updated to true for CHANGE_IDLE",
751 validateUidRecord.idle);
752 } else if (item.change == UidRecord.CHANGE_ACTIVE) {
753 assertFalse("UidRecord.idle should be updated to false for CHANGE_ACTIVE",
754 validateUidRecord.idle);
755 }
756 }
757 }
758
759 // Verify that when uid state changes to CHANGE_GONE or CHANGE_GONE_IDLE, then it
760 // will be removed from validateUids.
Amith Yamasaniaa746442019-01-10 10:09:12 -0800761 assertNotEquals("validateUids should not be empty", 0,
762 mAms.mValidateUids.size());
Sudheer Shanka4c9afa82017-02-28 19:30:28 -0800763 for (int i = 0; i < pendingItemsForUids.size(); ++i) {
764 final UidRecord.ChangeItem item = pendingItemsForUids.get(i);
765 // Assign CHANGE_GONE_IDLE to some items and CHANGE_GONE to the others, using even/odd
766 // distribution for this assignment.
Dianne Hackborn3e99f652017-07-05 16:33:56 -0700767 item.change = (i % 2) == 0 ? (UidRecord.CHANGE_GONE | UidRecord.CHANGE_IDLE)
768 : UidRecord.CHANGE_GONE;
Sudheer Shanka4c9afa82017-02-28 19:30:28 -0800769 }
Sudheer Shanka51ab3ac2017-03-07 15:38:01 -0800770 mAms.mPendingUidChanges.addAll(pendingItemsForUids);
771 mAms.dispatchUidsChanged();
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900772 assertEquals("validateUids should be empty, size=" + mAms.mValidateUids.size(),
Sudheer Shanka51ab3ac2017-03-07 15:38:01 -0800773 0, mAms.mValidateUids.size());
774 }
775
776 @Test
777 public void testEnqueueUidChangeLocked_procStateSeqUpdated() {
Riddle Hsud7088f82019-01-30 13:04:50 +0800778 final UidRecord uidRecord = new UidRecord(TEST_UID);
Sudheer Shanka51ab3ac2017-03-07 15:38:01 -0800779 uidRecord.curProcStateSeq = TEST_PROC_STATE_SEQ1;
780
781 // Verify with no pending changes for TEST_UID.
782 verifyLastProcStateSeqUpdated(uidRecord, -1, TEST_PROC_STATE_SEQ1);
783
784 // Add a pending change for TEST_UID and verify enqueueUidChangeLocked still works as
785 // expected.
786 final UidRecord.ChangeItem changeItem = new UidRecord.ChangeItem();
787 uidRecord.pendingChange = changeItem;
788 uidRecord.curProcStateSeq = TEST_PROC_STATE_SEQ2;
789 verifyLastProcStateSeqUpdated(uidRecord, -1, TEST_PROC_STATE_SEQ2);
Sudheer Shankadeeb08f2017-03-24 15:53:14 -0700790 }
Sudheer Shanka51ab3ac2017-03-07 15:38:01 -0800791
Sudheer Shankadeeb08f2017-03-24 15:53:14 -0700792 @Test
793 public void testEnqueueUidChangeLocked_nullUidRecord() {
Sudheer Shanka51ab3ac2017-03-07 15:38:01 -0800794 // Use "null" uidRecord to make sure there is no crash.
Sudheer Shankadeeb08f2017-03-24 15:53:14 -0700795 mAms.enqueueUidChangeLocked(null, TEST_UID, UidRecord.CHANGE_ACTIVE);
Sudheer Shanka51ab3ac2017-03-07 15:38:01 -0800796 }
797
798 private void verifyLastProcStateSeqUpdated(UidRecord uidRecord, int uid, long curProcstateSeq) {
799 // Test enqueueUidChangeLocked with every UidRecord.CHANGE_*
800 for (int i = 0; i < UID_RECORD_CHANGES.length; ++i) {
801 final int changeToDispatch = UID_RECORD_CHANGES[i];
802 // Reset lastProcStateSeqDispatchToObservers after every test.
803 uidRecord.lastDispatchedProcStateSeq = 0;
804 mAms.enqueueUidChangeLocked(uidRecord, uid, changeToDispatch);
805 // Verify there is no effect on curProcStateSeq.
806 assertEquals(curProcstateSeq, uidRecord.curProcStateSeq);
Dianne Hackborn3e99f652017-07-05 16:33:56 -0700807 if ((changeToDispatch & UidRecord.CHANGE_GONE) != 0) {
Sudheer Shanka51ab3ac2017-03-07 15:38:01 -0800808 // Since the change is CHANGE_GONE or CHANGE_GONE_IDLE, verify that
809 // lastProcStateSeqDispatchedToObservers is not updated.
810 assertNotEquals(uidRecord.curProcStateSeq,
811 uidRecord.lastDispatchedProcStateSeq);
812 } else {
813 // Since the change is neither CHANGE_GONE nor CHANGE_GONE_IDLE, verify that
814 // lastProcStateSeqDispatchedToObservers has been updated to curProcStateSeq.
815 assertEquals(uidRecord.curProcStateSeq,
816 uidRecord.lastDispatchedProcStateSeq);
817 }
818 }
819 }
820
821 @MediumTest
822 @Test
823 public void testEnqueueUidChangeLocked_dispatchUidsChanged() {
Riddle Hsud7088f82019-01-30 13:04:50 +0800824 final UidRecord uidRecord = new UidRecord(TEST_UID);
Sudheer Shanka51ab3ac2017-03-07 15:38:01 -0800825 final int expectedProcState = PROCESS_STATE_SERVICE;
826 uidRecord.setProcState = expectedProcState;
827 uidRecord.curProcStateSeq = TEST_PROC_STATE_SEQ1;
828
829 // Test with no pending uid records.
830 for (int i = 0; i < UID_RECORD_CHANGES.length; ++i) {
831 final int changeToDispatch = UID_RECORD_CHANGES[i];
832
833 // Reset the current state
834 mHandler.reset();
835 uidRecord.pendingChange = null;
836 mAms.mPendingUidChanges.clear();
837
838 mAms.enqueueUidChangeLocked(uidRecord, -1, changeToDispatch);
839
840 // Verify that UidRecord.pendingChange is updated correctly.
841 assertNotNull(uidRecord.pendingChange);
842 assertEquals(TEST_UID, uidRecord.pendingChange.uid);
843 assertEquals(expectedProcState, uidRecord.pendingChange.processState);
844 assertEquals(TEST_PROC_STATE_SEQ1, uidRecord.pendingChange.procStateSeq);
845
846 // Verify that DISPATCH_UIDS_CHANGED_UI_MSG is posted to handler.
847 mHandler.waitForMessage(DISPATCH_UIDS_CHANGED_UI_MSG);
848 }
849 }
850
Sudheer Shanka84a48952017-03-08 18:19:01 -0800851 @MediumTest
852 @Test
853 public void testWaitForNetworkStateUpdate() throws Exception {
854 // Check there is no crash when there is no UidRecord for myUid
855 mAms.waitForNetworkStateUpdate(TEST_PROC_STATE_SEQ1);
856
857 // Verify there is no waiting when UidRecord.curProcStateSeq is greater than
858 // the procStateSeq in the request to wait.
859 verifyWaitingForNetworkStateUpdate(
860 TEST_PROC_STATE_SEQ1, // curProcStateSeq
861 TEST_PROC_STATE_SEQ1, // lastDsipatchedProcStateSeq
862 TEST_PROC_STATE_SEQ1 - 4, // lastNetworkUpdatedProcStateSeq
863 TEST_PROC_STATE_SEQ1 - 2, // procStateSeqToWait
864 false); // expectWait
865
866 // Verify there is no waiting when the procStateSeq in the request to wait is
867 // not dispatched to NPMS.
868 verifyWaitingForNetworkStateUpdate(
869 TEST_PROC_STATE_SEQ1, // curProcStateSeq
870 TEST_PROC_STATE_SEQ1 - 1, // lastDsipatchedProcStateSeq
871 TEST_PROC_STATE_SEQ1 - 1, // lastNetworkUpdatedProcStateSeq
872 TEST_PROC_STATE_SEQ1, // procStateSeqToWait
873 false); // expectWait
874
875 // Verify there is not waiting when the procStateSeq in the request already has
876 // an updated network state.
877 verifyWaitingForNetworkStateUpdate(
878 TEST_PROC_STATE_SEQ1, // curProcStateSeq
879 TEST_PROC_STATE_SEQ1, // lastDsipatchedProcStateSeq
880 TEST_PROC_STATE_SEQ1, // lastNetworkUpdatedProcStateSeq
881 TEST_PROC_STATE_SEQ1, // procStateSeqToWait
882 false); // expectWait
883
884 // Verify waiting for network works
885 verifyWaitingForNetworkStateUpdate(
886 TEST_PROC_STATE_SEQ1, // curProcStateSeq
887 TEST_PROC_STATE_SEQ1, // lastDsipatchedProcStateSeq
888 TEST_PROC_STATE_SEQ1 - 1, // lastNetworkUpdatedProcStateSeq
889 TEST_PROC_STATE_SEQ1, // procStateSeqToWait
890 true); // expectWait
891 }
892
893 private void verifyWaitingForNetworkStateUpdate(long curProcStateSeq,
894 long lastDispatchedProcStateSeq, long lastNetworkUpdatedProcStateSeq,
895 final long procStateSeqToWait, boolean expectWait) throws Exception {
Riddle Hsud7088f82019-01-30 13:04:50 +0800896 final UidRecord record = new UidRecord(Process.myUid());
Sudheer Shanka84a48952017-03-08 18:19:01 -0800897 record.curProcStateSeq = curProcStateSeq;
898 record.lastDispatchedProcStateSeq = lastDispatchedProcStateSeq;
899 record.lastNetworkUpdatedProcStateSeq = lastNetworkUpdatedProcStateSeq;
Amith Yamasaniaa746442019-01-10 10:09:12 -0800900 mAms.mProcessList.mActiveUids.put(Process.myUid(), record);
Sudheer Shanka84a48952017-03-08 18:19:01 -0800901
Sudheer Shankaf4923ea2017-03-27 15:36:35 -0700902 CustomThread thread = new CustomThread(record.networkStateLock, new Runnable() {
Sudheer Shanka84a48952017-03-08 18:19:01 -0800903 @Override
904 public void run() {
905 mAms.waitForNetworkStateUpdate(procStateSeqToWait);
906 }
907 });
908 final String errMsg = "Unexpected state for " + record;
909 if (expectWait) {
910 thread.startAndWait(errMsg, true);
911 thread.assertTimedWaiting(errMsg);
Sudheer Shankaf4923ea2017-03-27 15:36:35 -0700912 synchronized (record.networkStateLock) {
913 record.networkStateLock.notifyAll();
Sudheer Shanka84a48952017-03-08 18:19:01 -0800914 }
915 thread.assertTerminated(errMsg);
916 assertTrue(thread.mNotified);
917 assertFalse(record.waitingForNetwork);
918 } else {
919 thread.start();
920 thread.assertTerminated(errMsg);
921 }
922
Amith Yamasaniaa746442019-01-10 10:09:12 -0800923 mAms.mProcessList.mActiveUids.clear();
Sudheer Shanka84a48952017-03-08 18:19:01 -0800924 }
925
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900926 private static class TestHandler extends Handler {
Sudheer Shanka51ab3ac2017-03-07 15:38:01 -0800927 private static final long WAIT_FOR_MSG_TIMEOUT_MS = 4000; // 4 sec
928 private static final long WAIT_FOR_MSG_INTERVAL_MS = 400; // 0.4 sec
929
930 private Set<Integer> mMsgsHandled = new HashSet<>();
931
932 TestHandler(Looper looper) {
933 super(looper);
934 }
935
936 @Override
937 public void handleMessage(Message msg) {
938 mMsgsHandled.add(msg.what);
939 }
940
941 public void waitForMessage(int msg) {
942 final long endTime = System.currentTimeMillis() + WAIT_FOR_MSG_TIMEOUT_MS;
943 while (!mMsgsHandled.contains(msg) && System.currentTimeMillis() < endTime) {
944 SystemClock.sleep(WAIT_FOR_MSG_INTERVAL_MS);
945 }
946 if (!mMsgsHandled.contains(msg)) {
947 fail("Timed out waiting for the message to be handled, msg: " + msg);
948 }
949 }
950
951 public void reset() {
952 mMsgsHandled.clear();
953 }
954 }
955
Sudheer Shanka84a48952017-03-08 18:19:01 -0800956 private class TestInjector extends Injector {
957 private boolean mRestricted = true;
958
Sudheer Shanka5269e502019-08-07 16:15:23 -0700959 TestInjector(Context context) {
960 super(context);
Sudheer Shankadeeb08f2017-03-24 15:53:14 -0700961 }
962
963 @Override
Sudheer Shanka84a48952017-03-08 18:19:01 -0800964 public AppOpsService getAppOpsService(File file, Handler handler) {
Sudheer Shanka51ab3ac2017-03-07 15:38:01 -0800965 return mAppOpsService;
966 }
967
968 @Override
Sudheer Shanka84a48952017-03-08 18:19:01 -0800969 public Handler getUiHandler(ActivityManagerService service) {
Sudheer Shanka51ab3ac2017-03-07 15:38:01 -0800970 return mHandler;
971 }
Sudheer Shanka84a48952017-03-08 18:19:01 -0800972
973 @Override
974 public boolean isNetworkRestrictedForUid(int uid) {
975 return mRestricted;
976 }
977
978 public void setNetworkRestrictedForUid(boolean restricted) {
979 mRestricted = restricted;
980 }
Sudheer Shanka4c9afa82017-02-28 19:30:28 -0800981 }
Dan Shiebfde332018-10-19 14:25:36 -0700982}