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