• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License
15  */
16 
17 package com.android.server.am;
18 
19 import static org.junit.Assert.assertEquals;
20 import static org.junit.Assert.assertTrue;
21 
22 import android.app.ActivityManagerInternal;
23 import android.os.SystemClock;
24 import android.support.test.filters.MediumTest;
25 import android.support.test.runner.AndroidJUnit4;
26 
27 import org.junit.Before;
28 import org.junit.Test;
29 import org.junit.runner.RunWith;
30 import org.mockito.Mock;
31 import org.mockito.MockitoAnnotations;
32 
33 /**
34  * Test class for {@link ActivityManagerInternal}.
35  *
36  * To run the tests, use
37  *
38  * runtest -c com.android.server.am.ActivityManagerInternalTest frameworks-services
39  *
40  * or the following steps:
41  *
42  * Build: m FrameworksServicesTests
43  * Install: adb install -r \
44  *     ${ANDROID_PRODUCT_OUT}/data/app/FrameworksServicesTests/FrameworksServicesTests.apk
45  * Run: adb shell am instrument -e class com.android.server.am.ActivityManagerInternalTest -w \
46  *     com.android.frameworks.servicestests/android.support.test.runner.AndroidJUnitRunner
47  */
48 @RunWith(AndroidJUnit4.class)
49 public class ActivityManagerInternalTest {
50     private static final int TEST_UID1 = 111;
51     private static final int TEST_UID2 = 112;
52 
53     private static final long TEST_PROC_STATE_SEQ1 = 1111;
54     private static final long TEST_PROC_STATE_SEQ2 = 1112;
55     private static final long TEST_PROC_STATE_SEQ3 = 1113;
56 
57     @Mock private ActivityManagerService.Injector mMockInjector;
58 
59     private ActivityManagerService mAms;
60     private ActivityManagerInternal mAmi;
61     @Before
setUp()62     public void setUp() {
63         MockitoAnnotations.initMocks(this);
64 
65         mAms = new ActivityManagerService(mMockInjector);
66         mAmi = mAms.new LocalService();
67     }
68 
69     @MediumTest
70     @Test
testNotifyNetworkPolicyRulesUpdated()71     public void testNotifyNetworkPolicyRulesUpdated() throws Exception {
72         // Check there is no crash when there are no active uid records.
73         mAmi.notifyNetworkPolicyRulesUpdated(TEST_UID1, TEST_PROC_STATE_SEQ1);
74 
75         // Notify that network policy rules are updated for TEST_UID1 and verify that
76         // UidRecord.lastNetworkUpdateProcStateSeq is updated and any blocked threads are notified.
77         verifyNetworkUpdatedProcStateSeq(
78                 TEST_PROC_STATE_SEQ2, // curProcStateSeq
79                 TEST_PROC_STATE_SEQ1, // lastNetworkUpdateProcStateSeq
80                 TEST_PROC_STATE_SEQ2, // procStateSeq to notify
81                 true); // expectNotify
82 
83         // Notify that network policy rules are updated for TEST_UID1 with already handled
84         // procStateSeq and verify that there is no notify call.
85         verifyNetworkUpdatedProcStateSeq(
86                 TEST_PROC_STATE_SEQ1, // curProcStateSeq
87                 TEST_PROC_STATE_SEQ1, // lastNetworkUpdateProcStateSeq
88                 TEST_PROC_STATE_SEQ1, // procStateSeq to notify
89                 false); // expectNotify
90 
91         // Notify that network policy rules are updated for TEST_UID1 with procStateSeq older
92         // than it's UidRecord.curProcStateSeq and verify that there is no notify call.
93         verifyNetworkUpdatedProcStateSeq(
94                 TEST_PROC_STATE_SEQ3, // curProcStateSeq
95                 TEST_PROC_STATE_SEQ1, // lastNetworkUpdateProcStateSeq
96                 TEST_PROC_STATE_SEQ2, // procStateSeq to notify
97                 false); // expectNotify
98     }
99 
verifyNetworkUpdatedProcStateSeq(long curProcStateSeq, long lastNetworkUpdatedProcStateSeq, long expectedProcStateSeq, boolean expectNotify)100     private void verifyNetworkUpdatedProcStateSeq(long curProcStateSeq,
101             long lastNetworkUpdatedProcStateSeq, long expectedProcStateSeq, boolean expectNotify)
102             throws Exception {
103         final UidRecord record1 = addActiveUidRecord(TEST_UID1, curProcStateSeq,
104                 lastNetworkUpdatedProcStateSeq);
105         final UidRecord record2 = addActiveUidRecord(TEST_UID2, curProcStateSeq,
106                 lastNetworkUpdatedProcStateSeq);
107 
108         final CustomThread thread1 = new CustomThread(record1.networkStateLock);
109         thread1.startAndWait("Unexpected state for " + record1);
110         final CustomThread thread2 = new CustomThread(record2.networkStateLock);
111         thread2.startAndWait("Unexpected state for " + record2);
112 
113         mAmi.notifyNetworkPolicyRulesUpdated(TEST_UID1, expectedProcStateSeq);
114         assertEquals(record1 + " should be updated",
115                 expectedProcStateSeq, record1.lastNetworkUpdatedProcStateSeq);
116         assertEquals(record2 + " should not be updated",
117                 lastNetworkUpdatedProcStateSeq, record2.lastNetworkUpdatedProcStateSeq);
118 
119         if (expectNotify) {
120             thread1.assertTerminated("Unexpected state for " + record1);
121             assertTrue("Threads waiting for network should be notified: " + record1,
122                     thread1.mNotified);
123         } else {
124             thread1.assertWaiting("Unexpected state for " + record1);
125             thread1.interrupt();
126         }
127         thread2.assertWaiting("Unexpected state for " + record2);
128         thread2.interrupt();
129 
130         mAms.mActiveUids.clear();
131     }
132 
addActiveUidRecord(int uid, long curProcStateSeq, long lastNetworkUpdatedProcStateSeq)133     private UidRecord addActiveUidRecord(int uid, long curProcStateSeq,
134             long lastNetworkUpdatedProcStateSeq) {
135         final UidRecord record = new UidRecord(uid);
136         record.lastNetworkUpdatedProcStateSeq = lastNetworkUpdatedProcStateSeq;
137         record.curProcStateSeq = curProcStateSeq;
138         record.waitingForNetwork = true;
139         mAms.mActiveUids.put(uid, record);
140         return record;
141     }
142 
143     static class CustomThread extends Thread {
144         private static final long WAIT_TIMEOUT_MS = 1000;
145         private static final long WAIT_INTERVAL_MS = 100;
146 
147         private final Object mLock;
148         private Runnable mRunnable;
149         boolean mNotified;
150 
CustomThread(Object lock)151         public CustomThread(Object lock) {
152             mLock = lock;
153         }
154 
CustomThread(Object lock, Runnable runnable)155         public CustomThread(Object lock, Runnable runnable) {
156             super(runnable);
157             mLock = lock;
158             mRunnable = runnable;
159         }
160 
161         @Override
run()162         public void run() {
163             if (mRunnable != null) {
164                 mRunnable.run();
165             } else {
166                 synchronized (mLock) {
167                     try {
168                         mLock.wait();
169                     } catch (InterruptedException e) {
170                         Thread.currentThread().interrupted();
171                     }
172                 }
173             }
174             mNotified = !Thread.interrupted();
175         }
176 
startAndWait(String errMsg)177         public void startAndWait(String errMsg) throws Exception {
178             startAndWait(errMsg, false);
179         }
180 
startAndWait(String errMsg, boolean timedWaiting)181         public void startAndWait(String errMsg, boolean timedWaiting) throws Exception {
182             start();
183             final long endTime = SystemClock.elapsedRealtime() + WAIT_TIMEOUT_MS;
184             final Thread.State stateToReach = timedWaiting
185                     ? Thread.State.TIMED_WAITING : Thread.State.WAITING;
186             while (getState() != stateToReach
187                     && SystemClock.elapsedRealtime() < endTime) {
188                 Thread.sleep(WAIT_INTERVAL_MS);
189             }
190             if (timedWaiting) {
191                 assertTimedWaiting(errMsg);
192             } else {
193                 assertWaiting(errMsg);
194             }
195         }
196 
assertWaiting(String errMsg)197         public void assertWaiting(String errMsg) {
198             assertEquals(errMsg, Thread.State.WAITING, getState());
199         }
200 
assertTimedWaiting(String errMsg)201         public void assertTimedWaiting(String errMsg) {
202             assertEquals(errMsg, Thread.State.TIMED_WAITING, getState());
203         }
204 
assertTerminated(String errMsg)205         public void assertTerminated(String errMsg) throws Exception {
206             final long endTime = SystemClock.elapsedRealtime() + WAIT_TIMEOUT_MS;
207             while (getState() != Thread.State.TERMINATED
208                     && SystemClock.elapsedRealtime() < endTime) {
209                 Thread.sleep(WAIT_INTERVAL_MS);
210             }
211             assertEquals(errMsg, Thread.State.TERMINATED, getState());
212         }
213     }
214 }
215