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