blob: 5dafe077d32e623108e2f4aea6fc9b06cfe1462a [file] [log] [blame]
Sudheer Shankae7361852017-03-07 11:51:46 -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 Shankae7361852017-03-07 11:51:46 -080015 */
16
17package com.android.server.am;
18
19import static org.junit.Assert.assertEquals;
Sudheer Shanka84a48952017-03-08 18:19:01 -080020import static org.junit.Assert.assertTrue;
Sudheer Shankae7361852017-03-07 11:51:46 -080021
22import android.app.ActivityManagerInternal;
Sudheer Shanka84a48952017-03-08 18:19:01 -080023import android.os.SystemClock;
Brett Chabota26eda92018-07-23 13:08:30 -070024
25import androidx.test.filters.MediumTest;
Sudheer Shankae7361852017-03-07 11:51:46 -080026
Sudheer Shankae7361852017-03-07 11:51:46 -080027import org.junit.Before;
28import org.junit.Test;
Sudheer Shanka51ab3ac2017-03-07 15:38:01 -080029import org.mockito.Mock;
30import org.mockito.MockitoAnnotations;
Sudheer Shankae7361852017-03-07 11:51:46 -080031
32/**
33 * Test class for {@link ActivityManagerInternal}.
34 *
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +090035 * Build/Install/Run:
Tadashi G. Takaokad3eb6452018-11-03 18:21:40 -070036 * atest FrameworksServicesTests:ActivityManagerInternalTest
Sudheer Shankae7361852017-03-07 11:51:46 -080037 */
Sudheer Shankae7361852017-03-07 11:51:46 -080038public class ActivityManagerInternalTest {
Sudheer Shanka84a48952017-03-08 18:19:01 -080039 private static final int TEST_UID1 = 111;
40 private static final int TEST_UID2 = 112;
41
42 private static final long TEST_PROC_STATE_SEQ1 = 1111;
43 private static final long TEST_PROC_STATE_SEQ2 = 1112;
44 private static final long TEST_PROC_STATE_SEQ3 = 1113;
45
Sudheer Shanka51ab3ac2017-03-07 15:38:01 -080046 @Mock private ActivityManagerService.Injector mMockInjector;
47
Sudheer Shankae7361852017-03-07 11:51:46 -080048 private ActivityManagerService mAms;
49 private ActivityManagerInternal mAmi;
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +090050
Sudheer Shankae7361852017-03-07 11:51:46 -080051 @Before
52 public void setUp() {
Sudheer Shanka51ab3ac2017-03-07 15:38:01 -080053 MockitoAnnotations.initMocks(this);
54
55 mAms = new ActivityManagerService(mMockInjector);
Sudheer Shankae7361852017-03-07 11:51:46 -080056 mAmi = mAms.new LocalService();
57 }
58
Sudheer Shanka84a48952017-03-08 18:19:01 -080059 @MediumTest
Sudheer Shankae7361852017-03-07 11:51:46 -080060 @Test
Sudheer Shanka84a48952017-03-08 18:19:01 -080061 public void testNotifyNetworkPolicyRulesUpdated() throws Exception {
62 // Check there is no crash when there are no active uid records.
63 mAmi.notifyNetworkPolicyRulesUpdated(TEST_UID1, TEST_PROC_STATE_SEQ1);
Sudheer Shankae7361852017-03-07 11:51:46 -080064
Sudheer Shanka84a48952017-03-08 18:19:01 -080065 // Notify that network policy rules are updated for TEST_UID1 and verify that
66 // UidRecord.lastNetworkUpdateProcStateSeq is updated and any blocked threads are notified.
67 verifyNetworkUpdatedProcStateSeq(
68 TEST_PROC_STATE_SEQ2, // curProcStateSeq
69 TEST_PROC_STATE_SEQ1, // lastNetworkUpdateProcStateSeq
70 TEST_PROC_STATE_SEQ2, // procStateSeq to notify
71 true); // expectNotify
72
73 // Notify that network policy rules are updated for TEST_UID1 with already handled
74 // procStateSeq and verify that there is no notify call.
75 verifyNetworkUpdatedProcStateSeq(
76 TEST_PROC_STATE_SEQ1, // curProcStateSeq
77 TEST_PROC_STATE_SEQ1, // lastNetworkUpdateProcStateSeq
78 TEST_PROC_STATE_SEQ1, // procStateSeq to notify
79 false); // expectNotify
80
81 // Notify that network policy rules are updated for TEST_UID1 with procStateSeq older
82 // than it's UidRecord.curProcStateSeq and verify that there is no notify call.
83 verifyNetworkUpdatedProcStateSeq(
84 TEST_PROC_STATE_SEQ3, // curProcStateSeq
85 TEST_PROC_STATE_SEQ1, // lastNetworkUpdateProcStateSeq
86 TEST_PROC_STATE_SEQ2, // procStateSeq to notify
87 false); // expectNotify
Sudheer Shankae7361852017-03-07 11:51:46 -080088 }
89
Sudheer Shanka84a48952017-03-08 18:19:01 -080090 private void verifyNetworkUpdatedProcStateSeq(long curProcStateSeq,
91 long lastNetworkUpdatedProcStateSeq, long expectedProcStateSeq, boolean expectNotify)
92 throws Exception {
93 final UidRecord record1 = addActiveUidRecord(TEST_UID1, curProcStateSeq,
94 lastNetworkUpdatedProcStateSeq);
95 final UidRecord record2 = addActiveUidRecord(TEST_UID2, curProcStateSeq,
96 lastNetworkUpdatedProcStateSeq);
97
Sudheer Shankaf4923ea2017-03-27 15:36:35 -070098 final CustomThread thread1 = new CustomThread(record1.networkStateLock);
Sudheer Shanka84a48952017-03-08 18:19:01 -080099 thread1.startAndWait("Unexpected state for " + record1);
Sudheer Shankaf4923ea2017-03-27 15:36:35 -0700100 final CustomThread thread2 = new CustomThread(record2.networkStateLock);
Sudheer Shanka84a48952017-03-08 18:19:01 -0800101 thread2.startAndWait("Unexpected state for " + record2);
102
103 mAmi.notifyNetworkPolicyRulesUpdated(TEST_UID1, expectedProcStateSeq);
104 assertEquals(record1 + " should be updated",
105 expectedProcStateSeq, record1.lastNetworkUpdatedProcStateSeq);
106 assertEquals(record2 + " should not be updated",
107 lastNetworkUpdatedProcStateSeq, record2.lastNetworkUpdatedProcStateSeq);
108
109 if (expectNotify) {
110 thread1.assertTerminated("Unexpected state for " + record1);
111 assertTrue("Threads waiting for network should be notified: " + record1,
112 thread1.mNotified);
113 } else {
114 thread1.assertWaiting("Unexpected state for " + record1);
115 thread1.interrupt();
116 }
117 thread2.assertWaiting("Unexpected state for " + record2);
118 thread2.interrupt();
119
Amith Yamasaniaa746442019-01-10 10:09:12 -0800120 mAms.mProcessList.mActiveUids.clear();
Sudheer Shanka84a48952017-03-08 18:19:01 -0800121 }
122
123 private UidRecord addActiveUidRecord(int uid, long curProcStateSeq,
124 long lastNetworkUpdatedProcStateSeq) {
Riddle Hsud7088f82019-01-30 13:04:50 +0800125 final UidRecord record = new UidRecord(uid);
Sudheer Shankae7361852017-03-07 11:51:46 -0800126 record.lastNetworkUpdatedProcStateSeq = lastNetworkUpdatedProcStateSeq;
Sudheer Shanka84a48952017-03-08 18:19:01 -0800127 record.curProcStateSeq = curProcStateSeq;
128 record.waitingForNetwork = true;
Amith Yamasaniaa746442019-01-10 10:09:12 -0800129 mAms.mProcessList.mActiveUids.put(uid, record);
Sudheer Shankae7361852017-03-07 11:51:46 -0800130 return record;
131 }
Sudheer Shanka84a48952017-03-08 18:19:01 -0800132
133 static class CustomThread extends Thread {
134 private static final long WAIT_TIMEOUT_MS = 1000;
135 private static final long WAIT_INTERVAL_MS = 100;
136
137 private final Object mLock;
138 private Runnable mRunnable;
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900139 public boolean mNotified;
Sudheer Shanka84a48952017-03-08 18:19:01 -0800140
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900141 CustomThread(Object lock) {
Sudheer Shanka84a48952017-03-08 18:19:01 -0800142 mLock = lock;
143 }
144
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900145 CustomThread(Object lock, Runnable runnable) {
Sudheer Shanka84a48952017-03-08 18:19:01 -0800146 super(runnable);
147 mLock = lock;
148 mRunnable = runnable;
149 }
150
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900151 @SuppressWarnings("WaitNotInLoop")
Sudheer Shanka84a48952017-03-08 18:19:01 -0800152 @Override
153 public void run() {
154 if (mRunnable != null) {
155 mRunnable.run();
156 } else {
157 synchronized (mLock) {
158 try {
159 mLock.wait();
160 } catch (InterruptedException e) {
Tadashi G. Takaoka74ccec22018-10-23 11:07:13 +0900161 Thread.interrupted();
Sudheer Shanka84a48952017-03-08 18:19:01 -0800162 }
163 }
164 }
165 mNotified = !Thread.interrupted();
166 }
167
168 public void startAndWait(String errMsg) throws Exception {
169 startAndWait(errMsg, false);
170 }
171
172 public void startAndWait(String errMsg, boolean timedWaiting) throws Exception {
173 start();
174 final long endTime = SystemClock.elapsedRealtime() + WAIT_TIMEOUT_MS;
175 final Thread.State stateToReach = timedWaiting
176 ? Thread.State.TIMED_WAITING : Thread.State.WAITING;
177 while (getState() != stateToReach
178 && SystemClock.elapsedRealtime() < endTime) {
179 Thread.sleep(WAIT_INTERVAL_MS);
180 }
181 if (timedWaiting) {
182 assertTimedWaiting(errMsg);
183 } else {
184 assertWaiting(errMsg);
185 }
186 }
187
188 public void assertWaiting(String errMsg) {
189 assertEquals(errMsg, Thread.State.WAITING, getState());
190 }
191
192 public void assertTimedWaiting(String errMsg) {
193 assertEquals(errMsg, Thread.State.TIMED_WAITING, getState());
194 }
195
196 public void assertTerminated(String errMsg) throws Exception {
197 final long endTime = SystemClock.elapsedRealtime() + WAIT_TIMEOUT_MS;
198 while (getState() != Thread.State.TERMINATED
199 && SystemClock.elapsedRealtime() < endTime) {
200 Thread.sleep(WAIT_INTERVAL_MS);
201 }
202 assertEquals(errMsg, Thread.State.TERMINATED, getState());
203 }
204 }
Sudheer Shankae7361852017-03-07 11:51:46 -0800205}