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