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