• Home
  • 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 android.net;
18 
19 import static android.net.ConnectivityManager.TYPE_NONE;
20 import static android.net.NetworkCapabilities.NET_CAPABILITY_CBS;
21 import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN;
22 import static android.net.NetworkCapabilities.NET_CAPABILITY_FOTA;
23 import static android.net.NetworkCapabilities.NET_CAPABILITY_IMS;
24 import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
25 import static android.net.NetworkCapabilities.NET_CAPABILITY_MMS;
26 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
27 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN;
28 import static android.net.NetworkCapabilities.NET_CAPABILITY_SUPL;
29 import static android.net.NetworkCapabilities.NET_CAPABILITY_TRUSTED;
30 import static android.net.NetworkCapabilities.NET_CAPABILITY_WIFI_P2P;
31 import static android.net.NetworkCapabilities.TRANSPORT_BLUETOOTH;
32 import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
33 import static android.net.NetworkCapabilities.TRANSPORT_ETHERNET;
34 import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
35 import static android.net.NetworkRequest.Type.BACKGROUND_REQUEST;
36 import static android.net.NetworkRequest.Type.REQUEST;
37 import static android.net.NetworkRequest.Type.TRACK_DEFAULT;
38 import static android.net.NetworkRequest.Type.TRACK_SYSTEM_DEFAULT;
39 
40 import static com.android.testutils.MiscAsserts.assertThrows;
41 
42 import static org.junit.Assert.assertFalse;
43 import static org.junit.Assert.assertNotNull;
44 import static org.junit.Assert.assertTrue;
45 import static org.junit.Assert.fail;
46 import static org.mockito.ArgumentMatchers.anyBoolean;
47 import static org.mockito.ArgumentMatchers.eq;
48 import static org.mockito.ArgumentMatchers.nullable;
49 import static org.mockito.Mockito.CALLS_REAL_METHODS;
50 import static org.mockito.Mockito.after;
51 import static org.mockito.Mockito.any;
52 import static org.mockito.Mockito.anyInt;
53 import static org.mockito.Mockito.mock;
54 import static org.mockito.Mockito.never;
55 import static org.mockito.Mockito.reset;
56 import static org.mockito.Mockito.timeout;
57 import static org.mockito.Mockito.times;
58 import static org.mockito.Mockito.verify;
59 import static org.mockito.Mockito.when;
60 
61 import android.app.PendingIntent;
62 import android.content.Context;
63 import android.content.pm.ApplicationInfo;
64 import android.net.ConnectivityManager.NetworkCallback;
65 import android.os.Build.VERSION_CODES;
66 import android.os.Bundle;
67 import android.os.Handler;
68 import android.os.Looper;
69 import android.os.Message;
70 import android.os.Messenger;
71 import android.os.Process;
72 
73 import androidx.test.filters.SmallTest;
74 
75 import com.android.testutils.DevSdkIgnoreRule;
76 import com.android.testutils.DevSdkIgnoreRunner;
77 
78 import org.junit.Before;
79 import org.junit.Test;
80 import org.junit.runner.RunWith;
81 import org.mockito.ArgumentCaptor;
82 import org.mockito.Mock;
83 import org.mockito.MockitoAnnotations;
84 
85 @RunWith(DevSdkIgnoreRunner.class)
86 @SmallTest
87 @DevSdkIgnoreRule.IgnoreUpTo(VERSION_CODES.R)
88 public class ConnectivityManagerTest {
89     private static final int TIMEOUT_MS = 30_000;
90     private static final int SHORT_TIMEOUT_MS = 150;
91 
92     @Mock Context mCtx;
93     @Mock IConnectivityManager mService;
94 
95     @Before
setUp()96     public void setUp() {
97         MockitoAnnotations.initMocks(this);
98     }
99 
verifyNetworkCapabilities( int legacyType, int transportType, int... capabilities)100     static NetworkCapabilities verifyNetworkCapabilities(
101             int legacyType, int transportType, int... capabilities) {
102         final NetworkCapabilities nc = ConnectivityManager.networkCapabilitiesForType(legacyType);
103         assertNotNull(nc);
104         assertTrue(nc.hasTransport(transportType));
105         for (int capability : capabilities) {
106             assertTrue(nc.hasCapability(capability));
107         }
108 
109         return nc;
110     }
111 
verifyUnrestrictedNetworkCapabilities(int legacyType, int transportType)112     static void verifyUnrestrictedNetworkCapabilities(int legacyType, int transportType) {
113         verifyNetworkCapabilities(
114                 legacyType,
115                 transportType,
116                 NET_CAPABILITY_INTERNET,
117                 NET_CAPABILITY_NOT_RESTRICTED,
118                 NET_CAPABILITY_NOT_VPN,
119                 NET_CAPABILITY_TRUSTED);
120     }
121 
verifyRestrictedMobileNetworkCapabilities(int legacyType, int capability)122     static void verifyRestrictedMobileNetworkCapabilities(int legacyType, int capability) {
123         final NetworkCapabilities nc = verifyNetworkCapabilities(
124                 legacyType,
125                 TRANSPORT_CELLULAR,
126                 capability,
127                 NET_CAPABILITY_NOT_VPN,
128                 NET_CAPABILITY_TRUSTED);
129 
130         assertFalse(nc.hasCapability(NET_CAPABILITY_INTERNET));
131         assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
132     }
133 
134     @Test
testNetworkCapabilitiesForTypeMobile()135     public void testNetworkCapabilitiesForTypeMobile() {
136         verifyUnrestrictedNetworkCapabilities(
137                 ConnectivityManager.TYPE_MOBILE, TRANSPORT_CELLULAR);
138     }
139 
140     @Test
testNetworkCapabilitiesForTypeMobileCbs()141     public void testNetworkCapabilitiesForTypeMobileCbs() {
142         verifyRestrictedMobileNetworkCapabilities(
143                 ConnectivityManager.TYPE_MOBILE_CBS, NET_CAPABILITY_CBS);
144     }
145 
146     @Test
testNetworkCapabilitiesForTypeMobileDun()147     public void testNetworkCapabilitiesForTypeMobileDun() {
148         verifyRestrictedMobileNetworkCapabilities(
149                 ConnectivityManager.TYPE_MOBILE_DUN, NET_CAPABILITY_DUN);
150     }
151 
152     @Test
testNetworkCapabilitiesForTypeMobileFota()153     public void testNetworkCapabilitiesForTypeMobileFota() {
154         verifyRestrictedMobileNetworkCapabilities(
155                 ConnectivityManager.TYPE_MOBILE_FOTA, NET_CAPABILITY_FOTA);
156     }
157 
158     @Test
testNetworkCapabilitiesForTypeMobileHipri()159     public void testNetworkCapabilitiesForTypeMobileHipri() {
160         verifyUnrestrictedNetworkCapabilities(
161                 ConnectivityManager.TYPE_MOBILE_HIPRI, TRANSPORT_CELLULAR);
162     }
163 
164     @Test
testNetworkCapabilitiesForTypeMobileIms()165     public void testNetworkCapabilitiesForTypeMobileIms() {
166         verifyRestrictedMobileNetworkCapabilities(
167                 ConnectivityManager.TYPE_MOBILE_IMS, NET_CAPABILITY_IMS);
168     }
169 
170     @Test
testNetworkCapabilitiesForTypeMobileMms()171     public void testNetworkCapabilitiesForTypeMobileMms() {
172         final NetworkCapabilities nc = verifyNetworkCapabilities(
173                 ConnectivityManager.TYPE_MOBILE_MMS,
174                 TRANSPORT_CELLULAR,
175                 NET_CAPABILITY_MMS,
176                 NET_CAPABILITY_NOT_VPN,
177                 NET_CAPABILITY_TRUSTED);
178 
179         assertFalse(nc.hasCapability(NET_CAPABILITY_INTERNET));
180     }
181 
182     @Test
testNetworkCapabilitiesForTypeMobileSupl()183     public void testNetworkCapabilitiesForTypeMobileSupl() {
184         final NetworkCapabilities nc = verifyNetworkCapabilities(
185                 ConnectivityManager.TYPE_MOBILE_SUPL,
186                 TRANSPORT_CELLULAR,
187                 NET_CAPABILITY_SUPL,
188                 NET_CAPABILITY_NOT_VPN,
189                 NET_CAPABILITY_TRUSTED);
190 
191         assertFalse(nc.hasCapability(NET_CAPABILITY_INTERNET));
192     }
193 
194     @Test
testNetworkCapabilitiesForTypeWifi()195     public void testNetworkCapabilitiesForTypeWifi() {
196         verifyUnrestrictedNetworkCapabilities(
197                 ConnectivityManager.TYPE_WIFI, TRANSPORT_WIFI);
198     }
199 
200     @Test
testNetworkCapabilitiesForTypeWifiP2p()201     public void testNetworkCapabilitiesForTypeWifiP2p() {
202         final NetworkCapabilities nc = verifyNetworkCapabilities(
203                 ConnectivityManager.TYPE_WIFI_P2P,
204                 TRANSPORT_WIFI,
205                 NET_CAPABILITY_NOT_RESTRICTED, NET_CAPABILITY_NOT_VPN,
206                 NET_CAPABILITY_TRUSTED, NET_CAPABILITY_WIFI_P2P);
207 
208         assertFalse(nc.hasCapability(NET_CAPABILITY_INTERNET));
209     }
210 
211     @Test
testNetworkCapabilitiesForTypeBluetooth()212     public void testNetworkCapabilitiesForTypeBluetooth() {
213         verifyUnrestrictedNetworkCapabilities(
214                 ConnectivityManager.TYPE_BLUETOOTH, TRANSPORT_BLUETOOTH);
215     }
216 
217     @Test
testNetworkCapabilitiesForTypeEthernet()218     public void testNetworkCapabilitiesForTypeEthernet() {
219         verifyUnrestrictedNetworkCapabilities(
220                 ConnectivityManager.TYPE_ETHERNET, TRANSPORT_ETHERNET);
221     }
222 
223     @Test
testCallbackRelease()224     public void testCallbackRelease() throws Exception {
225         ConnectivityManager manager = new ConnectivityManager(mCtx, mService);
226         NetworkRequest request = makeRequest(1);
227         NetworkCallback callback = mock(ConnectivityManager.NetworkCallback.class,
228                 CALLS_REAL_METHODS);
229         Handler handler = new Handler(Looper.getMainLooper());
230         ArgumentCaptor<Messenger> captor = ArgumentCaptor.forClass(Messenger.class);
231 
232         // register callback
233         when(mService.requestNetwork(anyInt(), any(), anyInt(), captor.capture(), anyInt(), any(),
234                 anyInt(), anyInt(), any(), nullable(String.class))).thenReturn(request);
235         manager.requestNetwork(request, callback, handler);
236 
237         // callback triggers
238         captor.getValue().send(makeMessage(request, ConnectivityManager.CALLBACK_AVAILABLE));
239         verify(callback, timeout(TIMEOUT_MS).times(1)).onAvailable(any(Network.class),
240                 any(NetworkCapabilities.class), any(LinkProperties.class), anyBoolean());
241 
242         // unregister callback
243         manager.unregisterNetworkCallback(callback);
244         verify(mService, times(1)).releaseNetworkRequest(request);
245 
246         // callback does not trigger anymore.
247         captor.getValue().send(makeMessage(request, ConnectivityManager.CALLBACK_LOSING));
248         verify(callback, after(SHORT_TIMEOUT_MS).never()).onLosing(any(), anyInt());
249     }
250 
251     @Test
testCallbackRecycling()252     public void testCallbackRecycling() throws Exception {
253         ConnectivityManager manager = new ConnectivityManager(mCtx, mService);
254         NetworkRequest req1 = makeRequest(1);
255         NetworkRequest req2 = makeRequest(2);
256         NetworkCallback callback = mock(ConnectivityManager.NetworkCallback.class,
257                 CALLS_REAL_METHODS);
258         Handler handler = new Handler(Looper.getMainLooper());
259         ArgumentCaptor<Messenger> captor = ArgumentCaptor.forClass(Messenger.class);
260 
261         // register callback
262         when(mService.requestNetwork(anyInt(), any(), anyInt(), captor.capture(), anyInt(), any(),
263                 anyInt(), anyInt(), any(), nullable(String.class))).thenReturn(req1);
264         manager.requestNetwork(req1, callback, handler);
265 
266         // callback triggers
267         captor.getValue().send(makeMessage(req1, ConnectivityManager.CALLBACK_AVAILABLE));
268         verify(callback, timeout(TIMEOUT_MS).times(1)).onAvailable(any(Network.class),
269                 any(NetworkCapabilities.class), any(LinkProperties.class), anyBoolean());
270 
271         // unregister callback
272         manager.unregisterNetworkCallback(callback);
273         verify(mService, times(1)).releaseNetworkRequest(req1);
274 
275         // callback does not trigger anymore.
276         captor.getValue().send(makeMessage(req1, ConnectivityManager.CALLBACK_LOSING));
277         verify(callback, after(SHORT_TIMEOUT_MS).never()).onLosing(any(), anyInt());
278 
279         // callback can be registered again
280         when(mService.requestNetwork(anyInt(), any(), anyInt(), captor.capture(), anyInt(), any(),
281                 anyInt(), anyInt(), any(), nullable(String.class))).thenReturn(req2);
282         manager.requestNetwork(req2, callback, handler);
283 
284         // callback triggers
285         captor.getValue().send(makeMessage(req2, ConnectivityManager.CALLBACK_LOST));
286         verify(callback, timeout(TIMEOUT_MS).times(1)).onLost(any());
287 
288         // unregister callback
289         manager.unregisterNetworkCallback(callback);
290         verify(mService, times(1)).releaseNetworkRequest(req2);
291     }
292 
293     // TODO: turn on this test when request  callback 1:1 mapping is enforced
294     //@Test
noDoubleCallbackRegistration()295     private void noDoubleCallbackRegistration() throws Exception {
296         ConnectivityManager manager = new ConnectivityManager(mCtx, mService);
297         NetworkRequest request = makeRequest(1);
298         NetworkCallback callback = new ConnectivityManager.NetworkCallback();
299         ApplicationInfo info = new ApplicationInfo();
300         // TODO: update version when starting to enforce 1:1 mapping
301         info.targetSdkVersion = VERSION_CODES.N_MR1 + 1;
302 
303         when(mCtx.getApplicationInfo()).thenReturn(info);
304         when(mService.requestNetwork(anyInt(), any(), anyInt(), any(), anyInt(), any(), anyInt(),
305                 anyInt(), any(), nullable(String.class))).thenReturn(request);
306 
307         Handler handler = new Handler(Looper.getMainLooper());
308         manager.requestNetwork(request, callback, handler);
309 
310         // callback is already registered, reregistration should fail.
311         Class<IllegalArgumentException> wantException = IllegalArgumentException.class;
312         expectThrowable(() -> manager.requestNetwork(request, callback), wantException);
313 
314         manager.unregisterNetworkCallback(callback);
315         verify(mService, times(1)).releaseNetworkRequest(request);
316 
317         // unregistering the callback should make it registrable again.
318         manager.requestNetwork(request, callback);
319     }
320 
321     @Test
testDefaultNetworkActiveListener()322     public void testDefaultNetworkActiveListener() throws Exception {
323         final ConnectivityManager manager = new ConnectivityManager(mCtx, mService);
324         final ConnectivityManager.OnNetworkActiveListener listener =
325                 mock(ConnectivityManager.OnNetworkActiveListener.class);
326         assertThrows(IllegalArgumentException.class,
327                 () -> manager.removeDefaultNetworkActiveListener(listener));
328         manager.addDefaultNetworkActiveListener(listener);
329         verify(mService, times(1)).registerNetworkActivityListener(any());
330         manager.removeDefaultNetworkActiveListener(listener);
331         verify(mService, times(1)).unregisterNetworkActivityListener(any());
332         assertThrows(IllegalArgumentException.class,
333                 () -> manager.removeDefaultNetworkActiveListener(listener));
334     }
335 
336     @Test
testArgumentValidation()337     public void testArgumentValidation() throws Exception {
338         ConnectivityManager manager = new ConnectivityManager(mCtx, mService);
339 
340         NetworkRequest request = mock(NetworkRequest.class);
341         NetworkCallback callback = mock(NetworkCallback.class);
342         Handler handler = mock(Handler.class);
343         NetworkCallback nullCallback = null;
344         PendingIntent nullIntent = null;
345 
346         mustFail(() -> manager.requestNetwork(null, callback));
347         mustFail(() -> manager.requestNetwork(request, nullCallback));
348         mustFail(() -> manager.requestNetwork(request, callback, null));
349         mustFail(() -> manager.requestNetwork(request, callback, -1));
350         mustFail(() -> manager.requestNetwork(request, nullIntent));
351 
352         mustFail(() -> manager.requestBackgroundNetwork(null, callback, handler));
353         mustFail(() -> manager.requestBackgroundNetwork(request, null, handler));
354         mustFail(() -> manager.requestBackgroundNetwork(request, callback, null));
355 
356         mustFail(() -> manager.registerNetworkCallback(null, callback, handler));
357         mustFail(() -> manager.registerNetworkCallback(request, null, handler));
358         mustFail(() -> manager.registerNetworkCallback(request, callback, null));
359         mustFail(() -> manager.registerNetworkCallback(request, nullIntent));
360 
361         mustFail(() -> manager.registerDefaultNetworkCallback(null, handler));
362         mustFail(() -> manager.registerDefaultNetworkCallback(callback, null));
363 
364         mustFail(() -> manager.registerSystemDefaultNetworkCallback(null, handler));
365         mustFail(() -> manager.registerSystemDefaultNetworkCallback(callback, null));
366 
367         mustFail(() -> manager.registerBestMatchingNetworkCallback(null, callback, handler));
368         mustFail(() -> manager.registerBestMatchingNetworkCallback(request, null, handler));
369         mustFail(() -> manager.registerBestMatchingNetworkCallback(request, callback, null));
370 
371         mustFail(() -> manager.unregisterNetworkCallback(nullCallback));
372         mustFail(() -> manager.unregisterNetworkCallback(nullIntent));
373         mustFail(() -> manager.releaseNetworkRequest(nullIntent));
374     }
375 
mustFail(Runnable fn)376     static void mustFail(Runnable fn) {
377         try {
378             fn.run();
379             fail();
380         } catch (Exception expected) {
381         }
382     }
383 
384     @Test
testRequestType()385     public void testRequestType() throws Exception {
386         final String testPkgName = "MyPackage";
387         final String testAttributionTag = "MyTag";
388         final ConnectivityManager manager = new ConnectivityManager(mCtx, mService);
389         when(mCtx.getOpPackageName()).thenReturn(testPkgName);
390         when(mCtx.getAttributionTag()).thenReturn(testAttributionTag);
391         final NetworkRequest request = makeRequest(1);
392         final NetworkCallback callback = new ConnectivityManager.NetworkCallback();
393 
394         manager.requestNetwork(request, callback);
395         verify(mService).requestNetwork(eq(Process.INVALID_UID), eq(request.networkCapabilities),
396                 eq(REQUEST.ordinal()), any(), anyInt(), any(), eq(TYPE_NONE), anyInt(),
397                 eq(testPkgName), eq(testAttributionTag));
398         reset(mService);
399 
400         // Verify that register network callback does not calls requestNetwork at all.
401         manager.registerNetworkCallback(request, callback);
402         verify(mService, never()).requestNetwork(anyInt(), any(), anyInt(), any(), anyInt(), any(),
403                 anyInt(), anyInt(), any(), any());
404         verify(mService).listenForNetwork(eq(request.networkCapabilities), any(), any(), anyInt(),
405                 eq(testPkgName), eq(testAttributionTag));
406         reset(mService);
407 
408         Handler handler = new Handler(ConnectivityThread.getInstanceLooper());
409 
410         manager.registerDefaultNetworkCallback(callback);
411         verify(mService).requestNetwork(eq(Process.INVALID_UID), eq(null),
412                 eq(TRACK_DEFAULT.ordinal()), any(), anyInt(), any(), eq(TYPE_NONE), anyInt(),
413                 eq(testPkgName), eq(testAttributionTag));
414         reset(mService);
415 
416         manager.registerDefaultNetworkCallbackForUid(42, callback, handler);
417         verify(mService).requestNetwork(eq(42), eq(null),
418                 eq(TRACK_DEFAULT.ordinal()), any(), anyInt(), any(), eq(TYPE_NONE), anyInt(),
419                 eq(testPkgName), eq(testAttributionTag));
420 
421         manager.requestBackgroundNetwork(request, callback, handler);
422         verify(mService).requestNetwork(eq(Process.INVALID_UID), eq(request.networkCapabilities),
423                 eq(BACKGROUND_REQUEST.ordinal()), any(), anyInt(), any(), eq(TYPE_NONE), anyInt(),
424                 eq(testPkgName), eq(testAttributionTag));
425         reset(mService);
426 
427         manager.registerSystemDefaultNetworkCallback(callback, handler);
428         verify(mService).requestNetwork(eq(Process.INVALID_UID), eq(null),
429                 eq(TRACK_SYSTEM_DEFAULT.ordinal()), any(), anyInt(), any(), eq(TYPE_NONE), anyInt(),
430                 eq(testPkgName), eq(testAttributionTag));
431         reset(mService);
432     }
433 
makeMessage(NetworkRequest req, int messageType)434     static Message makeMessage(NetworkRequest req, int messageType) {
435         Bundle bundle = new Bundle();
436         bundle.putParcelable(NetworkRequest.class.getSimpleName(), req);
437         // Pass default objects as we don't care which get passed here
438         bundle.putParcelable(Network.class.getSimpleName(), new Network(1));
439         bundle.putParcelable(NetworkCapabilities.class.getSimpleName(), new NetworkCapabilities());
440         bundle.putParcelable(LinkProperties.class.getSimpleName(), new LinkProperties());
441         Message msg = Message.obtain();
442         msg.what = messageType;
443         msg.setData(bundle);
444         return msg;
445     }
446 
makeRequest(int requestId)447     static NetworkRequest makeRequest(int requestId) {
448         NetworkRequest request = new NetworkRequest.Builder().clearCapabilities().build();
449         return new NetworkRequest(request.networkCapabilities, ConnectivityManager.TYPE_NONE,
450                 requestId, NetworkRequest.Type.NONE);
451     }
452 
expectThrowable(Runnable block, Class<? extends Throwable> throwableType)453     static void expectThrowable(Runnable block, Class<? extends Throwable> throwableType) {
454         try {
455             block.run();
456         } catch (Throwable t) {
457             if (t.getClass().equals(throwableType)) {
458                 return;
459             }
460             fail("expected exception of type " + throwableType + ", but was " + t.getClass());
461         }
462         fail("expected exception of type " + throwableType);
463     }
464 }
465