blob: 9bb392a23d5604a5b62023b1cc1c16d78828f109 [file] [log] [blame]
Erik Kline885a9092017-01-16 16:27:22 +09001/*
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
17package com.android.server.connectivity.tethering;
18
Erik Klinedd8e8912017-01-18 16:08:06 +090019import static android.net.ConnectivityManager.TYPE_MOBILE_DUN;
20import static android.net.ConnectivityManager.TYPE_MOBILE_HIPRI;
Erik Kline885a9092017-01-16 16:27:22 +090021import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN;
22import static org.junit.Assert.assertEquals;
23import static org.junit.Assert.assertFalse;
24import static org.junit.Assert.assertTrue;
Erik Kline35eee132017-01-17 15:06:35 +090025import static org.junit.Assert.fail;
Erik Kline7462f462017-01-23 19:05:28 +090026import static org.mockito.Mockito.any;
27import static org.mockito.Mockito.anyInt;
Erik Kline292b65a2017-05-12 16:52:48 +090028import static org.mockito.Mockito.anyString;
Erik Kline885a9092017-01-16 16:27:22 +090029import static org.mockito.Mockito.reset;
Erik Kline7462f462017-01-23 19:05:28 +090030import static org.mockito.Mockito.spy;
31import static org.mockito.Mockito.times;
32import static org.mockito.Mockito.verify;
33import static org.mockito.Mockito.verifyNoMoreInteractions;
Erik Kline292b65a2017-05-12 16:52:48 +090034import static org.mockito.Mockito.when;
Erik Kline885a9092017-01-16 16:27:22 +090035
36import android.content.Context;
Erik Klineb583b032017-02-22 12:58:24 +090037import android.os.Handler;
38import android.os.Message;
Erik Kline885a9092017-01-16 16:27:22 +090039import android.net.ConnectivityManager;
40import android.net.ConnectivityManager.NetworkCallback;
41import android.net.IConnectivityManager;
42import android.net.Network;
43import android.net.NetworkCapabilities;
44import android.net.NetworkRequest;
Erik Kline292b65a2017-05-12 16:52:48 +090045import android.net.util.SharedLog;
Erik Kline885a9092017-01-16 16:27:22 +090046
47import android.support.test.filters.SmallTest;
48import android.support.test.runner.AndroidJUnit4;
49
Erik Klineb583b032017-02-22 12:58:24 +090050import com.android.internal.util.State;
51import com.android.internal.util.StateMachine;
52
53import org.junit.After;
Erik Kline885a9092017-01-16 16:27:22 +090054import org.junit.Before;
55import org.junit.runner.RunWith;
56import org.junit.Test;
57import org.mockito.Mock;
Erik Kline7462f462017-01-23 19:05:28 +090058import org.mockito.Mockito;
Erik Kline885a9092017-01-16 16:27:22 +090059import org.mockito.MockitoAnnotations;
60
Erik Klineb583b032017-02-22 12:58:24 +090061import java.util.ArrayList;
Erik Kline885a9092017-01-16 16:27:22 +090062import java.util.HashMap;
63import java.util.HashSet;
64import java.util.Map;
65import java.util.Set;
66
67
68@RunWith(AndroidJUnit4.class)
69@SmallTest
70public class UpstreamNetworkMonitorTest {
71 private static final int EVENT_UNM_UPDATE = 1;
72
73 @Mock private Context mContext;
74 @Mock private IConnectivityManager mCS;
Erik Kline292b65a2017-05-12 16:52:48 +090075 @Mock private SharedLog mLog;
Erik Kline885a9092017-01-16 16:27:22 +090076
Erik Klineb583b032017-02-22 12:58:24 +090077 private TestStateMachine mSM;
Erik Kline885a9092017-01-16 16:27:22 +090078 private TestConnectivityManager mCM;
79 private UpstreamNetworkMonitor mUNM;
80
81 @Before public void setUp() throws Exception {
82 MockitoAnnotations.initMocks(this);
83 reset(mContext);
84 reset(mCS);
Erik Kline292b65a2017-05-12 16:52:48 +090085 reset(mLog);
86 when(mLog.forSubComponent(anyString())).thenReturn(mLog);
Erik Kline885a9092017-01-16 16:27:22 +090087
Erik Kline7462f462017-01-23 19:05:28 +090088 mCM = spy(new TestConnectivityManager(mContext, mCS));
Erik Klineb583b032017-02-22 12:58:24 +090089 mSM = new TestStateMachine();
Erik Kline292b65a2017-05-12 16:52:48 +090090 mUNM = new UpstreamNetworkMonitor(mSM, EVENT_UNM_UPDATE, (ConnectivityManager) mCM, mLog);
Erik Klineb583b032017-02-22 12:58:24 +090091 }
92
93 @After public void tearDown() throws Exception {
94 if (mSM != null) {
95 mSM.quit();
96 mSM = null;
97 }
Erik Kline885a9092017-01-16 16:27:22 +090098 }
99
100 @Test
101 public void testDoesNothingBeforeStarted() {
Erik Kline35eee132017-01-17 15:06:35 +0900102 assertTrue(mCM.hasNoCallbacks());
103 assertFalse(mUNM.mobileNetworkRequested());
104
105 mUNM.updateMobileRequiresDun(true);
106 assertTrue(mCM.hasNoCallbacks());
107 mUNM.updateMobileRequiresDun(false);
108 assertTrue(mCM.hasNoCallbacks());
Erik Kline885a9092017-01-16 16:27:22 +0900109 }
110
111 @Test
112 public void testDefaultNetworkIsTracked() throws Exception {
113 assertEquals(0, mCM.trackingDefault.size());
114
115 mUNM.start();
116 assertEquals(1, mCM.trackingDefault.size());
117
118 mUNM.stop();
Erik Kline35eee132017-01-17 15:06:35 +0900119 assertTrue(mCM.hasNoCallbacks());
Erik Kline885a9092017-01-16 16:27:22 +0900120 }
121
122 @Test
Erik Klined2ec3912017-01-25 00:53:04 +0900123 public void testListensForAllNetworks() throws Exception {
Erik Kline885a9092017-01-16 16:27:22 +0900124 assertTrue(mCM.listening.isEmpty());
125
126 mUNM.start();
127 assertFalse(mCM.listening.isEmpty());
Erik Klined2ec3912017-01-25 00:53:04 +0900128 assertTrue(mCM.isListeningForAll());
Erik Kline885a9092017-01-16 16:27:22 +0900129
130 mUNM.stop();
Erik Kline35eee132017-01-17 15:06:35 +0900131 assertTrue(mCM.hasNoCallbacks());
Erik Kline885a9092017-01-16 16:27:22 +0900132 }
133
134 @Test
Erik Kline35eee132017-01-17 15:06:35 +0900135 public void testRequestsMobileNetwork() throws Exception {
Erik Kline885a9092017-01-16 16:27:22 +0900136 assertFalse(mUNM.mobileNetworkRequested());
137 assertEquals(0, mCM.requested.size());
138
139 mUNM.start();
140 assertFalse(mUNM.mobileNetworkRequested());
141 assertEquals(0, mCM.requested.size());
142
Erik Klineefdd3f4c2017-01-20 16:31:29 +0900143 mUNM.updateMobileRequiresDun(false);
Erik Kline885a9092017-01-16 16:27:22 +0900144 assertFalse(mUNM.mobileNetworkRequested());
145 assertEquals(0, mCM.requested.size());
146
147 mUNM.registerMobileNetworkRequest();
148 assertTrue(mUNM.mobileNetworkRequested());
Erik Kline973c7df2017-01-23 15:55:16 +0900149 assertUpstreamTypeRequested(TYPE_MOBILE_HIPRI);
Erik Kline885a9092017-01-16 16:27:22 +0900150 assertFalse(mCM.isDunRequested());
151
152 mUNM.stop();
153 assertFalse(mUNM.mobileNetworkRequested());
Erik Kline35eee132017-01-17 15:06:35 +0900154 assertTrue(mCM.hasNoCallbacks());
Erik Kline885a9092017-01-16 16:27:22 +0900155 }
156
157 @Test
Erik Kline7462f462017-01-23 19:05:28 +0900158 public void testDuplicateMobileRequestsIgnored() throws Exception {
159 assertFalse(mUNM.mobileNetworkRequested());
160 assertEquals(0, mCM.requested.size());
161
162 mUNM.start();
163 verify(mCM, Mockito.times(1)).registerNetworkCallback(
Erik Klineb583b032017-02-22 12:58:24 +0900164 any(NetworkRequest.class), any(NetworkCallback.class), any(Handler.class));
165 verify(mCM, Mockito.times(1)).registerDefaultNetworkCallback(
166 any(NetworkCallback.class), any(Handler.class));
Erik Kline7462f462017-01-23 19:05:28 +0900167 assertFalse(mUNM.mobileNetworkRequested());
168 assertEquals(0, mCM.requested.size());
169
170 mUNM.updateMobileRequiresDun(true);
171 mUNM.registerMobileNetworkRequest();
172 verify(mCM, Mockito.times(1)).requestNetwork(
Erik Klineb583b032017-02-22 12:58:24 +0900173 any(NetworkRequest.class), any(NetworkCallback.class), anyInt(), anyInt(),
174 any(Handler.class));
Erik Kline7462f462017-01-23 19:05:28 +0900175
176 assertTrue(mUNM.mobileNetworkRequested());
177 assertUpstreamTypeRequested(TYPE_MOBILE_DUN);
178 assertTrue(mCM.isDunRequested());
179
180 // Try a few things that must not result in any state change.
181 mUNM.registerMobileNetworkRequest();
182 mUNM.updateMobileRequiresDun(true);
183 mUNM.registerMobileNetworkRequest();
184
185 assertTrue(mUNM.mobileNetworkRequested());
186 assertUpstreamTypeRequested(TYPE_MOBILE_DUN);
187 assertTrue(mCM.isDunRequested());
188
189 mUNM.stop();
190 verify(mCM, times(3)).unregisterNetworkCallback(any(NetworkCallback.class));
191
192 verifyNoMoreInteractions(mCM);
193 }
194
195 @Test
Erik Kline35eee132017-01-17 15:06:35 +0900196 public void testRequestsDunNetwork() throws Exception {
Erik Kline885a9092017-01-16 16:27:22 +0900197 assertFalse(mUNM.mobileNetworkRequested());
198 assertEquals(0, mCM.requested.size());
199
200 mUNM.start();
201 assertFalse(mUNM.mobileNetworkRequested());
202 assertEquals(0, mCM.requested.size());
203
Erik Klineefdd3f4c2017-01-20 16:31:29 +0900204 mUNM.updateMobileRequiresDun(true);
Erik Kline885a9092017-01-16 16:27:22 +0900205 assertFalse(mUNM.mobileNetworkRequested());
206 assertEquals(0, mCM.requested.size());
207
208 mUNM.registerMobileNetworkRequest();
209 assertTrue(mUNM.mobileNetworkRequested());
Erik Kline973c7df2017-01-23 15:55:16 +0900210 assertUpstreamTypeRequested(TYPE_MOBILE_DUN);
Erik Kline885a9092017-01-16 16:27:22 +0900211 assertTrue(mCM.isDunRequested());
212
213 mUNM.stop();
214 assertFalse(mUNM.mobileNetworkRequested());
Erik Kline35eee132017-01-17 15:06:35 +0900215 assertTrue(mCM.hasNoCallbacks());
Erik Kline885a9092017-01-16 16:27:22 +0900216 }
217
Erik Kline973c7df2017-01-23 15:55:16 +0900218 @Test
Erik Kline7462f462017-01-23 19:05:28 +0900219 public void testUpdateMobileRequiresDun() throws Exception {
Erik Kline973c7df2017-01-23 15:55:16 +0900220 mUNM.start();
221
222 // Test going from no-DUN to DUN correctly re-registers callbacks.
223 mUNM.updateMobileRequiresDun(false);
224 mUNM.registerMobileNetworkRequest();
225 assertTrue(mUNM.mobileNetworkRequested());
226 assertUpstreamTypeRequested(TYPE_MOBILE_HIPRI);
227 assertFalse(mCM.isDunRequested());
228 mUNM.updateMobileRequiresDun(true);
229 assertTrue(mUNM.mobileNetworkRequested());
230 assertUpstreamTypeRequested(TYPE_MOBILE_DUN);
231 assertTrue(mCM.isDunRequested());
232
233 // Test going from DUN to no-DUN correctly re-registers callbacks.
234 mUNM.updateMobileRequiresDun(false);
235 assertTrue(mUNM.mobileNetworkRequested());
236 assertUpstreamTypeRequested(TYPE_MOBILE_HIPRI);
237 assertFalse(mCM.isDunRequested());
238
239 mUNM.stop();
240 assertFalse(mUNM.mobileNetworkRequested());
241 }
242
243 private void assertUpstreamTypeRequested(int upstreamType) throws Exception {
244 assertEquals(1, mCM.requested.size());
245 assertEquals(1, mCM.legacyTypeMap.size());
246 assertEquals(Integer.valueOf(upstreamType),
247 mCM.legacyTypeMap.values().iterator().next());
248 }
249
Erik Kline7462f462017-01-23 19:05:28 +0900250 public static class TestConnectivityManager extends ConnectivityManager {
Erik Klineb583b032017-02-22 12:58:24 +0900251 public Map<NetworkCallback, Handler> allCallbacks = new HashMap<>();
Erik Kline885a9092017-01-16 16:27:22 +0900252 public Set<NetworkCallback> trackingDefault = new HashSet<>();
253 public Map<NetworkCallback, NetworkRequest> listening = new HashMap<>();
254 public Map<NetworkCallback, NetworkRequest> requested = new HashMap<>();
Erik Klinedd8e8912017-01-18 16:08:06 +0900255 public Map<NetworkCallback, Integer> legacyTypeMap = new HashMap<>();
Erik Kline885a9092017-01-16 16:27:22 +0900256
257 public TestConnectivityManager(Context ctx, IConnectivityManager svc) {
258 super(ctx, svc);
259 }
260
Erik Kline35eee132017-01-17 15:06:35 +0900261 boolean hasNoCallbacks() {
Erik Klineb583b032017-02-22 12:58:24 +0900262 return allCallbacks.isEmpty() &&
263 trackingDefault.isEmpty() &&
Erik Kline885a9092017-01-16 16:27:22 +0900264 listening.isEmpty() &&
Erik Klinedd8e8912017-01-18 16:08:06 +0900265 requested.isEmpty() &&
266 legacyTypeMap.isEmpty();
Erik Kline885a9092017-01-16 16:27:22 +0900267 }
268
Erik Klined2ec3912017-01-25 00:53:04 +0900269 boolean isListeningForAll() {
270 final NetworkCapabilities empty = new NetworkCapabilities();
271 empty.clearAll();
272
Erik Kline885a9092017-01-16 16:27:22 +0900273 for (NetworkRequest req : listening.values()) {
Erik Klined2ec3912017-01-25 00:53:04 +0900274 if (req.networkCapabilities.equalRequestableCapabilities(empty)) {
Erik Kline885a9092017-01-16 16:27:22 +0900275 return true;
276 }
277 }
278 return false;
279 }
280
281 boolean isDunRequested() {
282 for (NetworkRequest req : requested.values()) {
283 if (req.networkCapabilities.hasCapability(NET_CAPABILITY_DUN)) {
284 return true;
285 }
286 }
287 return false;
288 }
289
290 @Override
Erik Klineb583b032017-02-22 12:58:24 +0900291 public void requestNetwork(NetworkRequest req, NetworkCallback cb, Handler h) {
292 assertFalse(allCallbacks.containsKey(cb));
293 allCallbacks.put(cb, h);
Erik Kline885a9092017-01-16 16:27:22 +0900294 assertFalse(requested.containsKey(cb));
295 requested.put(cb, req);
296 }
297
298 @Override
Erik Klineb583b032017-02-22 12:58:24 +0900299 public void requestNetwork(NetworkRequest req, NetworkCallback cb) {
300 fail("Should never be called.");
301 }
302
303 @Override
Erik Klinedd8e8912017-01-18 16:08:06 +0900304 public void requestNetwork(NetworkRequest req, NetworkCallback cb,
Erik Klineb583b032017-02-22 12:58:24 +0900305 int timeoutMs, int legacyType, Handler h) {
306 assertFalse(allCallbacks.containsKey(cb));
307 allCallbacks.put(cb, h);
Erik Klinedd8e8912017-01-18 16:08:06 +0900308 assertFalse(requested.containsKey(cb));
309 requested.put(cb, req);
310 assertFalse(legacyTypeMap.containsKey(cb));
311 if (legacyType != ConnectivityManager.TYPE_NONE) {
312 legacyTypeMap.put(cb, legacyType);
313 }
314 }
315
316 @Override
Erik Klineb583b032017-02-22 12:58:24 +0900317 public void registerNetworkCallback(NetworkRequest req, NetworkCallback cb, Handler h) {
318 assertFalse(allCallbacks.containsKey(cb));
319 allCallbacks.put(cb, h);
Erik Kline885a9092017-01-16 16:27:22 +0900320 assertFalse(listening.containsKey(cb));
321 listening.put(cb, req);
322 }
323
324 @Override
Erik Klineb583b032017-02-22 12:58:24 +0900325 public void registerNetworkCallback(NetworkRequest req, NetworkCallback cb) {
326 fail("Should never be called.");
327 }
328
329 @Override
330 public void registerDefaultNetworkCallback(NetworkCallback cb, Handler h) {
331 assertFalse(allCallbacks.containsKey(cb));
332 allCallbacks.put(cb, h);
Erik Kline885a9092017-01-16 16:27:22 +0900333 assertFalse(trackingDefault.contains(cb));
334 trackingDefault.add(cb);
335 }
336
337 @Override
Erik Klineb583b032017-02-22 12:58:24 +0900338 public void registerDefaultNetworkCallback(NetworkCallback cb) {
339 fail("Should never be called.");
340 }
341
342 @Override
Erik Kline885a9092017-01-16 16:27:22 +0900343 public void unregisterNetworkCallback(NetworkCallback cb) {
344 if (trackingDefault.contains(cb)) {
345 trackingDefault.remove(cb);
346 } else if (listening.containsKey(cb)) {
347 listening.remove(cb);
348 } else if (requested.containsKey(cb)) {
349 requested.remove(cb);
Erik Klinedd8e8912017-01-18 16:08:06 +0900350 legacyTypeMap.remove(cb);
Erik Kline35eee132017-01-17 15:06:35 +0900351 } else {
352 fail("Unexpected callback removed");
Erik Kline885a9092017-01-16 16:27:22 +0900353 }
Erik Klineb583b032017-02-22 12:58:24 +0900354 allCallbacks.remove(cb);
Erik Kline885a9092017-01-16 16:27:22 +0900355
Erik Klineb583b032017-02-22 12:58:24 +0900356 assertFalse(allCallbacks.containsKey(cb));
Erik Kline885a9092017-01-16 16:27:22 +0900357 assertFalse(trackingDefault.contains(cb));
358 assertFalse(listening.containsKey(cb));
359 assertFalse(requested.containsKey(cb));
360 }
361 }
Erik Klineb583b032017-02-22 12:58:24 +0900362
363 public static class TestStateMachine extends StateMachine {
364 public final ArrayList<Message> messages = new ArrayList<>();
365 private final State mLoggingState = new LoggingState();
366
367 class LoggingState extends State {
368 @Override public void enter() { messages.clear(); }
369
370 @Override public void exit() { messages.clear(); }
371
372 @Override public boolean processMessage(Message msg) {
373 messages.add(msg);
374 return true;
375 }
376 }
377
378 public TestStateMachine() {
379 super("UpstreamNetworkMonitor.TestStateMachine");
380 addState(mLoggingState);
381 setInitialState(mLoggingState);
382 super.start();
383 }
384 }
Erik Kline885a9092017-01-16 16:27:22 +0900385}