ActivityManagerServiceTest.java revision 4c9afa87d09a9b6abecbddc956343a70363f0c5f
188c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka/*
288c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka * Copyright (C) 2017 The Android Open Source Project
388c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka *
488c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka * Licensed under the Apache License, Version 2.0 (the "License");
588c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka * you may not use this file except in compliance with the License.
688c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka * You may obtain a copy of the License at
788c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka *
888c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka *      http://www.apache.org/licenses/LICENSE-2.0
988c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka *
1088c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka * Unless required by applicable law or agreed to in writing, software
1188c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka * distributed under the License is distributed on an "AS IS" BASIS,
1288c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1388c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka * See the License for the specific language governing permissions and
1488c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka * limitations under the License
1588c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka */
1688c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka
1788c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shankapackage com.android.server.am;
1888c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka
1988c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shankaimport static android.app.ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
2088c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shankaimport static android.app.ActivityManager.PROCESS_STATE_CACHED_ACTIVITY;
2188c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shankaimport static android.app.ActivityManager.PROCESS_STATE_CACHED_EMPTY;
2288c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shankaimport static android.app.ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
2388c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shankaimport static android.app.ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND;
2488c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shankaimport static android.app.ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND;
2588c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shankaimport static android.app.ActivityManager.PROCESS_STATE_LAST_ACTIVITY;
2688c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shankaimport static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT;
2788c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shankaimport static android.app.ActivityManager.PROCESS_STATE_RECEIVER;
2888c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shankaimport static android.app.ActivityManager.PROCESS_STATE_SERVICE;
2988c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shankaimport static android.app.ActivityManager.PROCESS_STATE_TOP;
3088c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shankaimport static android.util.DebugUtils.valueToString;
3188c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka
3288c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shankaimport static org.junit.Assert.assertEquals;
3388c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shankaimport static org.junit.Assert.assertFalse;
344c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shankaimport static org.junit.Assert.assertNotEquals;
354c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shankaimport static org.junit.Assert.assertNotNull;
364c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shankaimport static org.junit.Assert.assertNull;
3788c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shankaimport static org.junit.Assert.assertTrue;
384c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shankaimport static org.mockito.Mockito.verify;
394c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shankaimport static org.mockito.Mockito.verifyNoMoreInteractions;
404c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shankaimport static org.mockito.Mockito.when;
4188c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka
4288c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shankaimport android.app.ActivityManager;
434c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shankaimport android.app.AppOpsManager;
444c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shankaimport android.app.IUidObserver;
454c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shankaimport android.os.IBinder;
464c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shankaimport android.os.Process;
474c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shankaimport android.os.RemoteException;
4888c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shankaimport android.support.test.filters.SmallTest;
4988c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shankaimport android.support.test.runner.AndroidJUnit4;
5088c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka
514c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shankaimport com.android.server.AppOpsService;
524c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka
534c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shankaimport org.junit.Before;
5488c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shankaimport org.junit.Test;
5588c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shankaimport org.junit.runner.RunWith;
564c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shankaimport org.mockito.Mock;
574c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shankaimport org.mockito.Mockito;
584c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shankaimport org.mockito.MockitoAnnotations;
5988c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka
604c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shankaimport java.util.ArrayList;
614c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shankaimport java.util.HashMap;
624c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shankaimport java.util.Map;
6388c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shankaimport java.util.function.Function;
6488c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka
6588c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka/**
6688c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka * Test class for {@link ActivityManagerService}.
6788c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka *
6888c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka * To run the tests, use
6988c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka *
7088c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka * runtest -c com.android.server.am.ActivityManagerServiceTest frameworks-services
7188c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka *
7288c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka * or the following steps:
7388c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka *
7488c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka * Build: m FrameworksServicesTests
7588c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka * Install: adb install -r \
7688c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka *     ${ANDROID_PRODUCT_OUT}/data/app/FrameworksServicesTests/FrameworksServicesTests.apk
7788c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka * Run: adb shell am instrument -e class com.android.server.am.ActivityManagerServiceTest -w \
7888c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka *     com.android.frameworks.servicestests/android.support.test.runner.AndroidJUnitRunner
7988c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka */
8088c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka@SmallTest
8188c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka@RunWith(AndroidJUnit4.class)
8288c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shankapublic class ActivityManagerServiceTest {
8388c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka    private static final int TEST_UID = 111;
8488c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka
854c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka    @Mock private AppOpsService mAppOpsService;
864c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka
874c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka    @Before
884c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka    public void setUp() {
894c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        MockitoAnnotations.initMocks(this);
904c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka    }
914c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka
9288c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka    @Test
9388c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka    public void testIncrementProcStateSeqIfNeeded() {
944c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        final ActivityManagerService ams = new ActivityManagerService(mAppOpsService);
9588c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka        final UidRecord uidRec = new UidRecord(TEST_UID);
9688c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka
9788c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka        assertEquals("Initially global seq counter should be 0", 0, ams.mProcStateSeqCounter);
9888c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka        assertEquals("Initially seq counter in uidRecord should be 0", 0, uidRec.curProcStateSeq);
9988c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka
10088c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka        // Uid state is not moving from background to foreground or vice versa.
10188c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka        uidRec.setProcState = PROCESS_STATE_TOP;
10288c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka        uidRec.curProcState = PROCESS_STATE_TOP;
10388c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka        ams.incrementProcStateSeqIfNeeded(uidRec);
10488c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka        assertEquals(0, ams.mProcStateSeqCounter);
10588c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka        assertEquals(0, uidRec.curProcStateSeq);
10688c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka
10788c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka        // Uid state is moving from foreground to background.
10888c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka        uidRec.curProcState = PROCESS_STATE_FOREGROUND_SERVICE;
10988c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka        uidRec.setProcState = PROCESS_STATE_SERVICE;
11088c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka        ams.incrementProcStateSeqIfNeeded(uidRec);
11188c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka        assertEquals(1, ams.mProcStateSeqCounter);
11288c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka        assertEquals(1, uidRec.curProcStateSeq);
11388c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka
11488c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka        // Explicitly setting the seq counter for more verification.
11588c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka        ams.mProcStateSeqCounter = 42;
11688c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka
11788c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka        // Uid state is not moving from background to foreground or vice versa.
11888c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka        uidRec.setProcState = PROCESS_STATE_IMPORTANT_BACKGROUND;
11988c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka        uidRec.curProcState = PROCESS_STATE_IMPORTANT_FOREGROUND;
12088c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka        ams.incrementProcStateSeqIfNeeded(uidRec);
12188c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka        assertEquals(42, ams.mProcStateSeqCounter);
12288c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka        assertEquals(1, uidRec.curProcStateSeq);
12388c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka
12488c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka        // Uid state is moving from background to foreground.
12588c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka        uidRec.setProcState = PROCESS_STATE_LAST_ACTIVITY;
12688c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka        uidRec.curProcState = PROCESS_STATE_TOP;
12788c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka        ams.incrementProcStateSeqIfNeeded(uidRec);
12888c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka        assertEquals(43, ams.mProcStateSeqCounter);
12988c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka        assertEquals(43, uidRec.curProcStateSeq);
13088c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka    }
13188c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka
13288c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka    @Test
13388c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka    public void testShouldIncrementProcStateSeq() {
1344c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        final ActivityManagerService ams = new ActivityManagerService(mAppOpsService);
13588c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka        final UidRecord uidRec = new UidRecord(TEST_UID);
13688c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka
13788c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka        final String error1 = "Seq should be incremented: prevState: %s, curState: %s";
13888c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka        final String error2 = "Seq should not be incremented: prevState: %s, curState: %s";
13988c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka        Function<String, String> errorMsg = errorTemplate -> {
14088c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka            return String.format(errorTemplate,
14188c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka                    valueToString(ActivityManager.class, "PROCESS_STATE_", uidRec.setProcState),
14288c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka                    valueToString(ActivityManager.class, "PROCESS_STATE_", uidRec.curProcState));
14388c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka        };
14488c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka
14588c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka        // No change in uid state
14688c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka        uidRec.setProcState = PROCESS_STATE_RECEIVER;
14788c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka        uidRec.curProcState = PROCESS_STATE_RECEIVER;
14888c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka        assertFalse(errorMsg.apply(error2), ams.shouldIncrementProcStateSeq(uidRec));
14988c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka
15088c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka        // Foreground to foreground
15188c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka        uidRec.setProcState = PROCESS_STATE_FOREGROUND_SERVICE;
15288c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka        uidRec.curProcState = PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
15388c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka        assertFalse(errorMsg.apply(error2), ams.shouldIncrementProcStateSeq(uidRec));
15488c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka
15588c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka        // Background to background
15688c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka        uidRec.setProcState = PROCESS_STATE_CACHED_ACTIVITY;
15788c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka        uidRec.curProcState = PROCESS_STATE_CACHED_EMPTY;
15888c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka        assertFalse(errorMsg.apply(error2), ams.shouldIncrementProcStateSeq(uidRec));
15988c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka
16088c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka        // Background to background
16188c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka        uidRec.setProcState = PROCESS_STATE_NONEXISTENT;
16288c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka        uidRec.curProcState = PROCESS_STATE_CACHED_ACTIVITY;
16388c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka        assertFalse(errorMsg.apply(error2), ams.shouldIncrementProcStateSeq(uidRec));
16488c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka
16588c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka        // Background to foreground
16688c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka        uidRec.setProcState = PROCESS_STATE_SERVICE;
16788c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka        uidRec.curProcState = PROCESS_STATE_FOREGROUND_SERVICE;
16888c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka        assertTrue(errorMsg.apply(error1), ams.shouldIncrementProcStateSeq(uidRec));
16988c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka
17088c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka        // Foreground to background
17188c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka        uidRec.setProcState = PROCESS_STATE_TOP;
17288c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka        uidRec.curProcState = PROCESS_STATE_LAST_ACTIVITY;
17388c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka        assertTrue(errorMsg.apply(error1), ams.shouldIncrementProcStateSeq(uidRec));
17488c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka    }
1754c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka
1764c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka    /**
1774c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka     * This test verifies that process state changes are dispatched to observers based on the
1784c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka     * changes they wanted to listen (this is specified when registering the observer).
1794c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka     */
1804c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka    @Test
1814c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka    public void testDispatchUids_dispatchNeededChanges() throws RemoteException {
1824c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        final ActivityManagerService ams = new ActivityManagerService(mAppOpsService);
1834c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        when(mAppOpsService.checkOperation(AppOpsManager.OP_GET_USAGE_STATS, Process.myUid(), null))
1844c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka                .thenReturn(AppOpsManager.MODE_ALLOWED);
1854c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka
1864c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        final int[] changesToObserve = {
1874c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka            ActivityManager.UID_OBSERVER_PROCSTATE,
1884c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka            ActivityManager.UID_OBSERVER_GONE,
1894c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka            ActivityManager.UID_OBSERVER_IDLE,
1904c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka            ActivityManager.UID_OBSERVER_ACTIVE,
1914c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka            ActivityManager.UID_OBSERVER_PROCSTATE | ActivityManager.UID_OBSERVER_GONE
1924c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka                    | ActivityManager.UID_OBSERVER_ACTIVE | ActivityManager.UID_OBSERVER_IDLE
1934c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        };
1944c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        final IUidObserver[] observers = new IUidObserver.Stub[changesToObserve.length];
1954c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        for (int i = 0; i < observers.length; ++i) {
1964c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka            observers[i] = Mockito.mock(IUidObserver.Stub.class);
1974c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka            when(observers[i].asBinder()).thenReturn((IBinder) observers[i]);
1984c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka            ams.registerUidObserver(observers[i], changesToObserve[i] /* which */,
1994c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka                    ActivityManager.PROCESS_STATE_UNKNOWN /* cutpoint */, null /* caller */);
2004c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka
2014c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka            // When we invoke AMS.registerUidObserver, there are some interactions with observers[i]
2024c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka            // mock in RemoteCallbackList class. We don't want to test those interactions and
2034c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka            // at the same time, we don't want those to interfere with verifyNoMoreInteractions.
2044c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka            // So, resetting the mock here.
2054c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka            Mockito.reset(observers[i]);
2064c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        }
2074c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka
2084c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        // Add pending uid records each corresponding to a different change type UidRecord.CHANGE_*
2094c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        final int[] changesForPendingUidRecords = {
2104c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka            UidRecord.CHANGE_PROCSTATE,
2114c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka            UidRecord.CHANGE_GONE,
2124c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka            UidRecord.CHANGE_GONE_IDLE,
2134c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka            UidRecord.CHANGE_IDLE,
2144c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka            UidRecord.CHANGE_ACTIVE
2154c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        };
2164c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        final int[] procStatesForPendingUidRecords = {
2174c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka            ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE,
2184c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka            ActivityManager.PROCESS_STATE_NONEXISTENT,
2194c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka            ActivityManager.PROCESS_STATE_CACHED_EMPTY,
2204c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka            ActivityManager.PROCESS_STATE_CACHED_ACTIVITY,
2214c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka            ActivityManager.PROCESS_STATE_TOP
2224c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        };
2234c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        final Map<Integer, UidRecord.ChangeItem> changeItems = new HashMap<>();
2244c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        for (int i = 0; i < changesForPendingUidRecords.length; ++i) {
2254c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka            final UidRecord.ChangeItem pendingChange = new UidRecord.ChangeItem();
2264c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka            pendingChange.change = changesForPendingUidRecords[i];
2274c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka            pendingChange.uid = i;
2284c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka            pendingChange.processState = procStatesForPendingUidRecords[i];
2294c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka            changeItems.put(changesForPendingUidRecords[i], pendingChange);
2304c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka            ams.mPendingUidChanges.add(pendingChange);
2314c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        }
2324c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka
2334c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        ams.dispatchUidsChanged();
2344c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        // Verify the required changes have been dispatched to observers.
2354c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        for (int i = 0; i < observers.length; ++i) {
2364c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka            final int changeToObserve = changesToObserve[i];
2374c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka            final IUidObserver observerToTest = observers[i];
2384c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka            if ((changeToObserve & ActivityManager.UID_OBSERVER_IDLE) != 0) {
2394c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka                // Observer listens to uid idle changes, so change items corresponding to
2404c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka                // UidRecord.CHANGE_IDLE or UidRecord.CHANGE_IDLE_GONE needs to be
2414c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka                // delivered to this observer.
2424c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka                final int[] changesToVerify = {
2434c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka                    UidRecord.CHANGE_IDLE,
2444c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka                    UidRecord.CHANGE_GONE_IDLE
2454c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka                };
2464c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka                verifyObserverReceivedChanges(observerToTest, changesToVerify, changeItems,
2474c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka                        (observer, changeItem) -> {
2484c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka                            verify(observer).onUidIdle(changeItem.uid, changeItem.ephemeral);
2494c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka                        });
2504c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka            }
2514c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka            if ((changeToObserve & ActivityManager.UID_OBSERVER_ACTIVE) != 0) {
2524c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka                // Observer listens to uid active changes, so change items corresponding to
2534c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka                // UidRecord.CHANGE_ACTIVE needs to be delivered to this observer.
2544c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka                final int[] changesToVerify = { UidRecord.CHANGE_ACTIVE };
2554c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka                verifyObserverReceivedChanges(observerToTest, changesToVerify, changeItems,
2564c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka                        (observer, changeItem) -> {
2574c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka                            verify(observer).onUidActive(changeItem.uid);
2584c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka                        });
2594c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka            }
2604c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka            if ((changeToObserve & ActivityManager.UID_OBSERVER_GONE) != 0) {
2614c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka                // Observer listens to uid gone changes, so change items corresponding to
2624c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka                // UidRecord.CHANGE_GONE or UidRecord.CHANGE_IDLE_GONE needs to be
2634c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka                // delivered to this observer.
2644c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka                final int[] changesToVerify = {
2654c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka                        UidRecord.CHANGE_GONE,
2664c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka                        UidRecord.CHANGE_GONE_IDLE
2674c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka                };
2684c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka                verifyObserverReceivedChanges(observerToTest, changesToVerify, changeItems,
2694c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka                        (observer, changeItem) -> {
2704c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka                            verify(observer).onUidGone(changeItem.uid, changeItem.ephemeral);
2714c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka                        });
2724c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka            }
2734c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka            if ((changeToObserve & ActivityManager.UID_OBSERVER_PROCSTATE) != 0) {
2744c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka                // Observer listens to uid procState changes, so change items corresponding to
2754c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka                // UidRecord.CHANGE_PROCSTATE or UidRecord.CHANGE_IDLE or UidRecord.CHANGE_ACTIVE
2764c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka                // needs to be delivered to this observer.
2774c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka                final int[] changesToVerify = {
2784c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka                        UidRecord.CHANGE_PROCSTATE,
2794c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka                        UidRecord.CHANGE_ACTIVE,
2804c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka                        UidRecord.CHANGE_IDLE
2814c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka                };
2824c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka                verifyObserverReceivedChanges(observerToTest, changesToVerify, changeItems,
2834c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka                        (observer, changeItem) -> {
2844c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka                            verify(observer).onUidStateChanged(
2854c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka                                    changeItem.uid, changeItem.processState);
2864c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka                        });
2874c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka            }
2884c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka            // Verify there are no other callbacks for this observer.
2894c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka            verifyNoMoreInteractions(observerToTest);
2904c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        }
2914c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka    }
2924c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka
2934c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka    private interface ObserverChangesVerifier {
2944c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        void verify(IUidObserver observer, UidRecord.ChangeItem changeItem) throws RemoteException;
2954c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka    }
2964c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka
2974c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka    private void verifyObserverReceivedChanges(IUidObserver observer, int[] changesToVerify,
2984c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka            Map<Integer, UidRecord.ChangeItem> changeItems, ObserverChangesVerifier verifier)
2994c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka            throws RemoteException {
3004c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        for (int change : changesToVerify) {
3014c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka            final UidRecord.ChangeItem changeItem = changeItems.get(change);
3024c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka            verifier.verify(observer, changeItem);
3034c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        }
3044c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka    }
3054c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka
3064c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka    /**
3074c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka     * This test verifies that process state changes are dispatched to observers only when they
3084c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka     * change across the cutpoint (this is specified when registering the observer).
3094c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka     */
3104c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka    @Test
3114c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka    public void testDispatchUidChanges_procStateCutpoint() throws RemoteException {
3124c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        final ActivityManagerService ams = new ActivityManagerService(mAppOpsService);
3134c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        final IUidObserver observer = Mockito.mock(IUidObserver.Stub.class);
3144c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka
3154c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        when(observer.asBinder()).thenReturn((IBinder) observer);
3164c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        ams.registerUidObserver(observer, ActivityManager.UID_OBSERVER_PROCSTATE /* which */,
3174c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka                ActivityManager.PROCESS_STATE_SERVICE /* cutpoint */, null /* callingPackage */);
3184c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        // When we invoke AMS.registerUidObserver, there are some interactions with observer
3194c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        // mock in RemoteCallbackList class. We don't want to test those interactions and
3204c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        // at the same time, we don't want those to interfere with verifyNoMoreInteractions.
3214c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        // So, resetting the mock here.
3224c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        Mockito.reset(observer);
3234c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka
3244c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        final UidRecord.ChangeItem changeItem = new UidRecord.ChangeItem();
3254c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        changeItem.uid = TEST_UID;
3264c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        changeItem.change = UidRecord.CHANGE_PROCSTATE;
3274c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        changeItem.processState = ActivityManager.PROCESS_STATE_LAST_ACTIVITY;
3284c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        ams.mPendingUidChanges.add(changeItem);
3294c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        ams.dispatchUidsChanged();
3304c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        // First process state message is always delivered regardless of whether the process state
3314c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        // change is above or below the cutpoint (PROCESS_STATE_SERVICE).
3324c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        verify(observer).onUidStateChanged(TEST_UID,
3334c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka                ActivityManager.PROCESS_STATE_LAST_ACTIVITY);
3344c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        verifyNoMoreInteractions(observer);
3354c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka
3364c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        changeItem.processState = ActivityManager.PROCESS_STATE_RECEIVER;
3374c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        ams.mPendingUidChanges.add(changeItem);
3384c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        ams.dispatchUidsChanged();
3394c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        // Previous process state change is below cutpoint (PROCESS_STATE_SERVICE) and
3404c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        // the current process state change is also below cutpoint, so no callback will be invoked.
3414c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        verifyNoMoreInteractions(observer);
3424c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka
3434c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        changeItem.processState = ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
3444c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        ams.mPendingUidChanges.add(changeItem);
3454c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        ams.dispatchUidsChanged();
3464c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        // Previous process state change is below cutpoint (PROCESS_STATE_SERVICE) and
3474c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        // the current process state change is above cutpoint, so callback will be invoked with the
3484c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        // current process state change.
3494c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        verify(observer).onUidStateChanged(TEST_UID,
3504c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka                ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE);
3514c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        verifyNoMoreInteractions(observer);
3524c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka
3534c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        changeItem.processState = ActivityManager.PROCESS_STATE_TOP;
3544c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        ams.mPendingUidChanges.add(changeItem);
3554c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        ams.dispatchUidsChanged();
3564c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        // Previous process state change is above cutpoint (PROCESS_STATE_SERVICE) and
3574c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        // the current process state change is also above cutpoint, so no callback will be invoked.
3584c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        verifyNoMoreInteractions(observer);
3594c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka
3604c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        changeItem.processState = ActivityManager.PROCESS_STATE_CACHED_EMPTY;
3614c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        ams.mPendingUidChanges.add(changeItem);
3624c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        ams.dispatchUidsChanged();
3634c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        // Previous process state change is above cutpoint (PROCESS_STATE_SERVICE) and
3644c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        // the current process state change is below cutpoint, so callback will be invoked with the
3654c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        // current process state change.
3664c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        verify(observer).onUidStateChanged(TEST_UID, ActivityManager.PROCESS_STATE_CACHED_EMPTY);
3674c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        verifyNoMoreInteractions(observer);
3684c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka    }
3694c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka
3704c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka    /**
3714c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka     * This test verifies that {@link ActivityManagerService#mValidateUids} which is a
3724c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka     * part of dumpsys is correctly updated.
3734c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka     */
3744c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka    @Test
3754c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka    public void testDispatchUidChanges_validateUidsUpdated() {
3764c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        final ActivityManagerService ams = new ActivityManagerService(mAppOpsService);
3774c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka
3784c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        final int[] changesForPendingItems = {
3794c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka            UidRecord.CHANGE_PROCSTATE,
3804c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka            UidRecord.CHANGE_GONE,
3814c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka            UidRecord.CHANGE_GONE_IDLE,
3824c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka            UidRecord.CHANGE_IDLE,
3834c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka            UidRecord.CHANGE_ACTIVE
3844c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        };
3854c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        final int[] procStatesForPendingItems = {
3864c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka            ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE,
3874c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka            ActivityManager.PROCESS_STATE_CACHED_EMPTY,
3884c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka            ActivityManager.PROCESS_STATE_CACHED_ACTIVITY,
3894c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka            ActivityManager.PROCESS_STATE_SERVICE,
3904c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka            ActivityManager.PROCESS_STATE_RECEIVER
3914c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        };
3924c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        final ArrayList<UidRecord.ChangeItem> pendingItemsForUids
3934c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka                = new ArrayList<>(changesForPendingItems.length);
3944c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        for (int i = 0; i < changesForPendingItems.length; ++i) {
3954c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka            final UidRecord.ChangeItem item = new UidRecord.ChangeItem();
3964c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka            item.uid = i;
3974c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka            item.change = changesForPendingItems[i];
3984c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka            item.processState = procStatesForPendingItems[i];
3994c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka            pendingItemsForUids.add(i, item);
4004c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        }
4014c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka
4024c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        // Verify that when there no observers listening to uid state changes, then there will
4034c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        // be no changes to validateUids.
4044c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        ams.mPendingUidChanges.addAll(pendingItemsForUids);
4054c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        ams.dispatchUidsChanged();
4064c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        assertEquals("No observers registered, so validateUids should be empty",
4074c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka                0, ams.mValidateUids.size());
4084c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka
4094c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        final IUidObserver observer = Mockito.mock(IUidObserver.Stub.class);
4104c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        when(observer.asBinder()).thenReturn((IBinder) observer);
4114c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        ams.registerUidObserver(observer, 0, 0, null);
4124c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        // Verify that when observers are registered, then validateUids is correctly updated.
4134c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        ams.mPendingUidChanges.addAll(pendingItemsForUids);
4144c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        ams.dispatchUidsChanged();
4154c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        for (int i = 0; i < pendingItemsForUids.size(); ++i) {
4164c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka            final UidRecord.ChangeItem item = pendingItemsForUids.get(i);
4174c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka            final UidRecord validateUidRecord = ams.mValidateUids.get(item.uid);
4184c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka            if (item.change == UidRecord.CHANGE_GONE || item.change == UidRecord.CHANGE_GONE_IDLE) {
4194c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka                assertNull("validateUidRecord should be null since the change is either "
4204c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka                        + "CHANGE_GONE or CHANGE_GONE_IDLE", validateUidRecord);
4214c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka            } else {
4224c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka                assertNotNull("validateUidRecord should not be null since the change is neither "
4234c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka                        + "CHANGE_GONE nor CHANGE_GONE_IDLE", validateUidRecord);
4244c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka                assertEquals("processState: " + item.processState + " curProcState: "
4254c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka                        + validateUidRecord.curProcState + " should have been equal",
4264c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka                        item.processState, validateUidRecord.curProcState);
4274c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka                assertEquals("processState: " + item.processState + " setProcState: "
4284c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka                        + validateUidRecord.curProcState + " should have been equal",
4294c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka                        item.processState, validateUidRecord.setProcState);
4304c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka                if (item.change == UidRecord.CHANGE_IDLE) {
4314c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka                    assertTrue("UidRecord.idle should be updated to true for CHANGE_IDLE",
4324c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka                            validateUidRecord.idle);
4334c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka                } else if (item.change == UidRecord.CHANGE_ACTIVE) {
4344c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka                    assertFalse("UidRecord.idle should be updated to false for CHANGE_ACTIVE",
4354c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka                            validateUidRecord.idle);
4364c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka                }
4374c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka            }
4384c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        }
4394c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka
4404c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        // Verify that when uid state changes to CHANGE_GONE or CHANGE_GONE_IDLE, then it
4414c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        // will be removed from validateUids.
4424c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        assertNotEquals("validateUids should not be empty", 0, ams.mValidateUids.size());
4434c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        for (int i = 0; i < pendingItemsForUids.size(); ++i) {
4444c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka            final UidRecord.ChangeItem item = pendingItemsForUids.get(i);
4454c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka            // Assign CHANGE_GONE_IDLE to some items and CHANGE_GONE to the others, using even/odd
4464c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka            // distribution for this assignment.
4474c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka            item.change = (i % 2) == 0 ? UidRecord.CHANGE_GONE_IDLE : UidRecord.CHANGE_GONE;
4484c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        }
4494c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        ams.mPendingUidChanges.addAll(pendingItemsForUids);
4504c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        ams.dispatchUidsChanged();
4514c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka        assertEquals("validateUids should be empty, validateUids: " + ams.mValidateUids,
4524c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka                0, ams.mValidateUids.size());
4534c9afa87d09a9b6abecbddc956343a70363f0c5fSudheer Shanka    }
45488c4d1ce97f5fa3859dd1854d4a82305e68a2b0eSudheer Shanka}