1 // Copyright 2012 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 package org.chromium.net; 6 7 import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET; 8 import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; 9 import static android.net.NetworkCapabilities.TRANSPORT_VPN; 10 import static android.net.NetworkCapabilities.TRANSPORT_WIFI; 11 12 import android.annotation.SuppressLint; 13 import android.app.Activity; 14 import android.content.BroadcastReceiver; 15 import android.content.Context; 16 import android.content.ContextWrapper; 17 import android.content.Intent; 18 import android.content.IntentFilter; 19 import android.net.ConnectivityManager; 20 import android.net.ConnectivityManager.NetworkCallback; 21 import android.net.Network; 22 import android.net.NetworkCapabilities; 23 import android.net.NetworkRequest; 24 import android.os.Build; 25 import android.os.Handler; 26 import android.os.Looper; 27 import android.os.StrictMode; 28 import android.telephony.TelephonyManager; 29 30 import androidx.test.InstrumentationRegistry; 31 import androidx.test.filters.MediumTest; 32 33 import org.junit.After; 34 import org.junit.Assert; 35 import org.junit.Before; 36 import org.junit.Test; 37 import org.junit.runner.RunWith; 38 39 import org.chromium.base.ActivityState; 40 import org.chromium.base.ApplicationState; 41 import org.chromium.base.ApplicationStatus; 42 import org.chromium.base.ContextUtils; 43 import org.chromium.base.ThreadUtils; 44 import org.chromium.base.library_loader.LibraryLoader; 45 import org.chromium.base.library_loader.LibraryProcessType; 46 import org.chromium.base.test.BaseJUnit4ClassRunner; 47 import org.chromium.base.test.UiThreadTest; 48 import org.chromium.base.test.util.Feature; 49 import org.chromium.base.test.util.MinAndroidSdkLevel; 50 import org.chromium.net.NetworkChangeNotifierAutoDetect.ConnectivityManagerDelegate; 51 import org.chromium.net.NetworkChangeNotifierAutoDetect.NetworkState; 52 import org.chromium.net.NetworkChangeNotifierAutoDetect.WifiManagerDelegate; 53 import org.chromium.net.test.util.NetworkChangeNotifierTestUtil; 54 55 import java.lang.reflect.Constructor; 56 import java.lang.reflect.InvocationTargetException; 57 import java.util.ArrayList; 58 import java.util.concurrent.Callable; 59 import java.util.concurrent.FutureTask; 60 61 /** 62 * Tests for org.chromium.net.NetworkChangeNotifier. 63 */ 64 @RunWith(BaseJUnit4ClassRunner.class) 65 @SuppressLint("NewApi") 66 public class NetworkChangeNotifierTest { 67 /** 68 * Listens for alerts fired by the NetworkChangeNotifier when network status changes. 69 */ 70 private static class NetworkChangeNotifierTestObserver 71 implements NetworkChangeNotifier.ConnectionTypeObserver { 72 private boolean mReceivedNotification; 73 74 @Override onConnectionTypeChanged(int connectionType)75 public void onConnectionTypeChanged(int connectionType) { 76 mReceivedNotification = true; 77 } 78 hasReceivedNotification()79 public boolean hasReceivedNotification() { 80 return mReceivedNotification; 81 } 82 resetHasReceivedNotification()83 public void resetHasReceivedNotification() { 84 mReceivedNotification = false; 85 } 86 } 87 88 /** 89 * Listens for native notifications of max bandwidth change. 90 */ 91 private static class TestNetworkChangeNotifier extends NetworkChangeNotifier { 92 @Override notifyObserversOfConnectionSubtypeChange(int newConnectionSubtype)93 void notifyObserversOfConnectionSubtypeChange(int newConnectionSubtype) { 94 mReceivedConnectionSubtypeNotification = true; 95 } 96 hasReceivedConnectionSubtypeNotification()97 public boolean hasReceivedConnectionSubtypeNotification() { 98 return mReceivedConnectionSubtypeNotification; 99 } 100 resetHasReceivedConnectionSubtypeNotification()101 public void resetHasReceivedConnectionSubtypeNotification() { 102 mReceivedConnectionSubtypeNotification = false; 103 } 104 105 private boolean mReceivedConnectionSubtypeNotification; 106 } 107 108 private static class Helper { 109 private static final Constructor<Network> sNetworkConstructor; 110 111 static { 112 try { 113 sNetworkConstructor = (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) 114 ? Network.class.getConstructor(Integer.TYPE) 115 : null; 116 } catch (NoSuchMethodException | SecurityException e) { 117 throw new RuntimeException("Unable to get Network constructor", e); 118 } 119 } 120 getCapabilities(int transport)121 static NetworkCapabilities getCapabilities(int transport) { 122 // Create a NetworkRequest with corresponding capabilities 123 NetworkRequest request = new NetworkRequest.Builder() 124 .addCapability(NET_CAPABILITY_INTERNET) 125 .addTransportType(transport) 126 .build(); 127 // Extract the NetworkCapabilities from the NetworkRequest. 128 try { 129 return (NetworkCapabilities) request.getClass() 130 .getDeclaredField("networkCapabilities") 131 .get(request); 132 } catch (NoSuchFieldException | IllegalAccessException e) { 133 return null; 134 } 135 } 136 // Create Network object given a NetID. netIdToNetwork(int netId)137 static Network netIdToNetwork(int netId) { 138 try { 139 return sNetworkConstructor.newInstance(netId); 140 } catch ( 141 InstantiationException | InvocationTargetException | IllegalAccessException e) { 142 throw new IllegalStateException("Trying to create Network when not allowed"); 143 } 144 } 145 } 146 triggerApplicationStateChange( final RegistrationPolicyApplicationStatus policy, final int applicationState)147 private static void triggerApplicationStateChange( 148 final RegistrationPolicyApplicationStatus policy, final int applicationState) { 149 ThreadUtils.runOnUiThreadBlocking(new Runnable() { 150 @Override 151 public void run() { 152 setApplicationHasVisibleActivities( 153 applicationState == ApplicationState.HAS_RUNNING_ACTIVITIES); 154 } 155 }); 156 } 157 158 /** 159 * Mocks out calls to the ConnectivityManager. 160 */ 161 private class MockConnectivityManagerDelegate extends ConnectivityManagerDelegate { 162 // A network we're pretending is currently connected. 163 private class MockNetwork { 164 // Network identifier 165 final int mNetId; 166 // Transport, one of android.net.NetworkCapabilities.TRANSPORT_* 167 final int mTransport; 168 // Is this VPN accessible to the current user? 169 final boolean mVpnAccessible; 170 getCapabilities()171 NetworkCapabilities getCapabilities() { 172 return Helper.getCapabilities(mTransport); 173 } 174 175 /** 176 * @param netId Network identifier 177 * @param transport Transport, one of android.net.NetworkCapabilities.TRANSPORT_* 178 * @param vpnAccessible Is this VPN accessible to the current user? 179 */ MockNetwork(int netId, int transport, boolean vpnAccessible)180 MockNetwork(int netId, int transport, boolean vpnAccessible) { 181 mNetId = netId; 182 mTransport = transport; 183 mVpnAccessible = vpnAccessible; 184 } 185 } 186 187 // List of networks we're pretending are currently connected. 188 private final ArrayList<MockNetwork> mMockNetworks = new ArrayList<>(); 189 190 private boolean mActiveNetworkExists; 191 private int mNetworkType; 192 private int mNetworkSubtype; 193 private boolean mIsMetered; 194 private boolean mIsPrivateDnsActive; 195 private String mPrivateDnsServerName; 196 private NetworkCallback mLastRegisteredNetworkCallback; 197 private NetworkCallback mLastRegisteredDefaultNetworkCallback; 198 199 @Override getNetworkState(WifiManagerDelegate wifiManagerDelegate)200 public NetworkState getNetworkState(WifiManagerDelegate wifiManagerDelegate) { 201 return new NetworkState(mActiveNetworkExists, mNetworkType, mNetworkSubtype, mIsMetered, 202 mNetworkType == ConnectivityManager.TYPE_WIFI 203 ? wifiManagerDelegate.getWifiSsid() 204 : null, 205 mIsPrivateDnsActive, mPrivateDnsServerName); 206 } 207 208 @Override getNetworkCapabilities(Network network)209 protected NetworkCapabilities getNetworkCapabilities(Network network) { 210 int netId = demungeNetId(NetworkChangeNotifierAutoDetect.networkToNetId(network)); 211 for (MockNetwork mockNetwork : mMockNetworks) { 212 if (netId == mockNetwork.mNetId) { 213 return mockNetwork.getCapabilities(); 214 } 215 } 216 return null; 217 } 218 219 @Override vpnAccessible(Network network)220 protected boolean vpnAccessible(Network network) { 221 int netId = demungeNetId(NetworkChangeNotifierAutoDetect.networkToNetId(network)); 222 for (MockNetwork mockNetwork : mMockNetworks) { 223 if (netId == mockNetwork.mNetId) { 224 return mockNetwork.mVpnAccessible; 225 } 226 } 227 return false; 228 } 229 230 @Override getAllNetworksUnfiltered()231 protected Network[] getAllNetworksUnfiltered() { 232 Network[] networks = new Network[mMockNetworks.size()]; 233 for (int i = 0; i < networks.length; i++) { 234 networks[i] = Helper.netIdToNetwork(mMockNetworks.get(i).mNetId); 235 } 236 return networks; 237 } 238 239 // Dummy implementations to avoid NullPointerExceptions in default implementations: 240 241 @Override getDefaultNetwork()242 public Network getDefaultNetwork() { 243 return null; 244 } 245 246 @Override getConnectionType(Network network)247 public int getConnectionType(Network network) { 248 return ConnectionType.CONNECTION_NONE; 249 } 250 251 @Override unregisterNetworkCallback(NetworkCallback networkCallback)252 public void unregisterNetworkCallback(NetworkCallback networkCallback) {} 253 254 // Dummy implementation that also records the last registered callback. 255 @Override registerNetworkCallback( NetworkRequest networkRequest, NetworkCallback networkCallback, Handler handler)256 public void registerNetworkCallback( 257 NetworkRequest networkRequest, NetworkCallback networkCallback, Handler handler) { 258 mLastRegisteredNetworkCallback = networkCallback; 259 } 260 261 // Dummy implementation that also records the last registered callback. 262 @Override registerDefaultNetworkCallback( NetworkCallback networkCallback, Handler handler)263 public void registerDefaultNetworkCallback( 264 NetworkCallback networkCallback, Handler handler) { 265 mLastRegisteredDefaultNetworkCallback = networkCallback; 266 } 267 setActiveNetworkExists(boolean networkExists)268 public void setActiveNetworkExists(boolean networkExists) { 269 mActiveNetworkExists = networkExists; 270 } 271 setNetworkType(int networkType)272 public void setNetworkType(int networkType) { 273 mNetworkType = networkType; 274 } 275 setIsMetered(boolean isMetered)276 public void setIsMetered(boolean isMetered) { 277 mIsMetered = isMetered; 278 } 279 setNetworkSubtype(int networkSubtype)280 public void setNetworkSubtype(int networkSubtype) { 281 mNetworkSubtype = networkSubtype; 282 } 283 setIsPrivateDnsActive(boolean isPrivateDnsActive)284 public void setIsPrivateDnsActive(boolean isPrivateDnsActive) { 285 mIsPrivateDnsActive = isPrivateDnsActive; 286 } 287 setPrivateDnsServerName(String privateDnsServerName)288 public void setPrivateDnsServerName(String privateDnsServerName) { 289 mPrivateDnsServerName = privateDnsServerName; 290 } 291 getLastRegisteredNetworkCallback()292 public NetworkCallback getLastRegisteredNetworkCallback() { 293 return mLastRegisteredNetworkCallback; 294 } 295 getDefaultNetworkCallback()296 public NetworkCallback getDefaultNetworkCallback() { 297 return mLastRegisteredDefaultNetworkCallback; 298 } 299 300 /** 301 * Pretends a network connects. 302 * @param netId Network identifier 303 * @param transport Transport, one of android.net.NetworkCapabilities.TRANSPORT_* 304 * @param vpnAccessible Is this VPN accessible to the current user? 305 */ addNetwork(int netId, int transport, boolean vpnAccessible)306 public void addNetwork(int netId, int transport, boolean vpnAccessible) { 307 mMockNetworks.add(new MockNetwork(netId, transport, vpnAccessible)); 308 mLastRegisteredNetworkCallback.onAvailable(Helper.netIdToNetwork(netId)); 309 } 310 311 /** 312 * Pretends a network disconnects. 313 * @param netId Network identifier 314 */ removeNetwork(int netId)315 public void removeNetwork(int netId) { 316 for (MockNetwork mockNetwork : mMockNetworks) { 317 if (mockNetwork.mNetId == netId) { 318 mMockNetworks.remove(mockNetwork); 319 mLastRegisteredNetworkCallback.onLost(Helper.netIdToNetwork(netId)); 320 break; 321 } 322 } 323 } 324 } 325 326 /** 327 * Mocks out calls to the WifiManager. 328 */ 329 private static class MockWifiManagerDelegate extends WifiManagerDelegate { 330 private String mWifiSSID; 331 332 @Override getWifiSsid()333 public String getWifiSsid() { 334 return mWifiSSID; 335 } 336 setWifiSSID(String wifiSSID)337 public void setWifiSSID(String wifiSSID) { 338 mWifiSSID = wifiSSID; 339 } 340 } 341 demungeNetId(long netId)342 private static int demungeNetId(long netId) { 343 // On Marshmallow, demunge the NetID to undo munging done in Network.getNetworkHandle(). 344 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { 345 netId >>= 32; 346 } 347 // Now that the NetID has been demunged it is a true NetID which means it's only a 16-bit 348 // value (see ConnectivityService.MAX_NET_ID) so it should be safe to cast to int. 349 return (int) netId; 350 } 351 352 // Types of network changes. Each is associated with a NetworkChangeNotifierAutoDetect.Observer 353 // callback, and NONE is provided to indicate no callback observed. 354 private static enum ChangeType { NONE, CONNECT, SOON_TO_DISCONNECT, DISCONNECT, PURGE_LIST } 355 356 // Recorded information about a network change that took place. 357 private static class ChangeInfo { 358 // The type of change. 359 final ChangeType mChangeType; 360 // The network identifier of the network changing. 361 final int mNetId; 362 363 /** 364 * @param changeType the type of change. 365 * @param netId the network identifier of the network changing. 366 */ ChangeInfo(ChangeType changeType, long netId)367 ChangeInfo(ChangeType changeType, long netId) { 368 mChangeType = changeType; 369 mNetId = demungeNetId(netId); 370 } 371 } 372 373 // NetworkChangeNotifierAutoDetect.Observer used to verify proper notifications are sent out. 374 // Notifications come back on UI thread. assertLastChange() called on test thread. 375 private static class TestNetworkChangeNotifierAutoDetectObserver 376 implements NetworkChangeNotifierAutoDetect.Observer { 377 // The list of network changes that have been witnessed. 378 final ArrayList<ChangeInfo> mChanges = new ArrayList<>(); 379 380 @Override onConnectionTypeChanged(int newConnectionType)381 public void onConnectionTypeChanged(int newConnectionType) {} 382 @Override onConnectionCostChanged(int newConnectionCost)383 public void onConnectionCostChanged(int newConnectionCost) {} 384 @Override onConnectionSubtypeChanged(int newConnectionSubtype)385 public void onConnectionSubtypeChanged(int newConnectionSubtype) {} 386 387 @Override onNetworkConnect(long netId, int connectionType)388 public void onNetworkConnect(long netId, int connectionType) { 389 ThreadUtils.assertOnUiThread(); 390 mChanges.add(new ChangeInfo(ChangeType.CONNECT, netId)); 391 } 392 393 @Override onNetworkSoonToDisconnect(long netId)394 public void onNetworkSoonToDisconnect(long netId) { 395 ThreadUtils.assertOnUiThread(); 396 mChanges.add(new ChangeInfo(ChangeType.SOON_TO_DISCONNECT, netId)); 397 } 398 399 @Override onNetworkDisconnect(long netId)400 public void onNetworkDisconnect(long netId) { 401 ThreadUtils.assertOnUiThread(); 402 mChanges.add(new ChangeInfo(ChangeType.DISCONNECT, netId)); 403 } 404 405 @Override purgeActiveNetworkList(long[] activeNetIds)406 public void purgeActiveNetworkList(long[] activeNetIds) { 407 ThreadUtils.assertOnUiThread(); 408 if (activeNetIds.length == 1) { 409 mChanges.add(new ChangeInfo(ChangeType.PURGE_LIST, activeNetIds[0])); 410 } else { 411 mChanges.add(new ChangeInfo(ChangeType.PURGE_LIST, NetId.INVALID)); 412 } 413 } 414 415 // Verify last notification was the expected one. assertLastChange(ChangeType type, int netId)416 public void assertLastChange(ChangeType type, int netId) throws Exception { 417 // Make sure notification processed. 418 NetworkChangeNotifierTestUtil.flushUiThreadTaskQueue(); 419 Assert.assertNotNull(mChanges.get(0)); 420 Assert.assertEquals(type, mChanges.get(0).mChangeType); 421 Assert.assertEquals(netId, mChanges.get(0).mNetId); 422 mChanges.clear(); 423 } 424 } 425 426 // Activity used to send updates to ApplicationStatus to convince ApplicationStatus that the app 427 // is in the foreground or background. Only accessed on the UI thread. 428 private static Activity sActivity; 429 430 // Network.Network(int netId) pointer. 431 private TestNetworkChangeNotifier mNotifier; 432 private NetworkChangeNotifierAutoDetect mReceiver; 433 private MockConnectivityManagerDelegate mConnectivityDelegate; 434 private MockWifiManagerDelegate mWifiDelegate; 435 436 private static enum WatchForChanges { 437 ALWAYS, 438 ONLY_WHEN_APP_IN_FOREGROUND, 439 } 440 441 /** 442 * Helper method to create a notifier and delegates for testing. 443 * @param watchForChanges indicates whether app wants to watch for changes always or only when 444 * it is in the foreground. 445 */ createTestNotifier(WatchForChanges watchForChanges)446 private void createTestNotifier(WatchForChanges watchForChanges) { 447 Context context = new ContextWrapper(InstrumentationRegistry.getInstrumentation() 448 .getTargetContext() 449 .getApplicationContext()) { 450 // Mock out to avoid unintended system interaction. 451 @Override 452 public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter, 453 String permission, Handler scheduler, int flags) { 454 // Should not be used starting with Pie. 455 Assert.assertFalse(Build.VERSION.SDK_INT >= Build.VERSION_CODES.P); 456 return null; 457 } 458 459 @Override 460 public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter, 461 String permission, Handler scheduler) { 462 return registerReceiver(receiver, filter, permission, scheduler, 0); 463 } 464 465 @Override 466 public void unregisterReceiver(BroadcastReceiver receiver) {} 467 468 // Don't allow escaping the mock via the application context. 469 @Override 470 public Context getApplicationContext() { 471 return this; 472 } 473 }; 474 ContextUtils.initApplicationContextForTests(context); 475 mNotifier = new TestNetworkChangeNotifier(); 476 NetworkChangeNotifier.resetInstanceForTests(mNotifier); 477 if (watchForChanges == WatchForChanges.ALWAYS) { 478 NetworkChangeNotifier.registerToReceiveNotificationsAlways(); 479 } else { 480 NetworkChangeNotifier.setAutoDetectConnectivityState(true); 481 } 482 mReceiver = NetworkChangeNotifier.getAutoDetectorForTest(); 483 Assert.assertNotNull(mReceiver); 484 485 mConnectivityDelegate = 486 new MockConnectivityManagerDelegate(); 487 mConnectivityDelegate.setActiveNetworkExists(true); 488 mReceiver.setConnectivityManagerDelegateForTests(mConnectivityDelegate); 489 490 mWifiDelegate = new MockWifiManagerDelegate(); 491 mReceiver.setWifiManagerDelegateForTests(mWifiDelegate); 492 mWifiDelegate.setWifiSSID("foo"); 493 } 494 getCurrentConnectionSubtype()495 private int getCurrentConnectionSubtype() { 496 return mReceiver.getCurrentNetworkState().getConnectionSubtype(); 497 } 498 getCurrentConnectionType()499 private int getCurrentConnectionType() { 500 return mReceiver.getCurrentNetworkState().getConnectionType(); 501 } 502 getCurrentConnectionCost()503 private int getCurrentConnectionCost() { 504 return mReceiver.getCurrentNetworkState().getConnectionCost(); 505 } 506 507 @Before setUp()508 public void setUp() throws Throwable { 509 LibraryLoader.getInstance().setLibraryProcessType(LibraryProcessType.PROCESS_BROWSER); 510 LibraryLoader.getInstance().ensureInitialized(); 511 512 ThreadUtils.runOnUiThreadBlocking(() -> { 513 if (sActivity == null) { 514 sActivity = new Activity(); 515 if (!ApplicationStatus.isInitialized()) { 516 ApplicationStatus.initialize(BaseJUnit4ClassRunner.getApplication()); 517 } 518 ApplicationStatus.onStateChangeForTesting(sActivity, ActivityState.CREATED); 519 } 520 setApplicationHasVisibleActivities(false); 521 createTestNotifier(WatchForChanges.ONLY_WHEN_APP_IN_FOREGROUND); 522 }); 523 } 524 525 @After tearDown()526 public void tearDown() { 527 // Reset the network change notifier. 528 NetworkChangeNotifier.resetInstanceForTests(); 529 } 530 531 /** 532 * Allow tests to simulate the application being foregrounded or backgrounded. 533 */ setApplicationHasVisibleActivities(boolean hasVisibleActivities)534 private static void setApplicationHasVisibleActivities(boolean hasVisibleActivities) { 535 ThreadUtils.assertOnUiThread(); 536 ApplicationStatus.onStateChangeForTesting( 537 sActivity, hasVisibleActivities ? ActivityState.STARTED : ActivityState.STOPPED); 538 } 539 540 /** 541 * Tests that the receiver registers for connectivity 542 * broadcasts during construction when the registration policy dictates. 543 */ 544 @Test 545 @UiThreadTest 546 @MediumTest 547 @Feature({"Android-AppBase"}) testNetworkChangeNotifierRegistersWhenPolicyDictates()548 public void testNetworkChangeNotifierRegistersWhenPolicyDictates() { 549 NetworkChangeNotifierAutoDetect.Observer observer = 550 new TestNetworkChangeNotifierAutoDetectObserver(); 551 552 setApplicationHasVisibleActivities(true); 553 NetworkChangeNotifierAutoDetect receiver = new NetworkChangeNotifierAutoDetect( 554 observer, new RegistrationPolicyApplicationStatus()); 555 556 Assert.assertTrue(receiver.isReceiverRegisteredForTesting()); 557 558 setApplicationHasVisibleActivities(false); 559 receiver = new NetworkChangeNotifierAutoDetect( 560 observer, new RegistrationPolicyApplicationStatus()); 561 562 Assert.assertFalse(receiver.isReceiverRegisteredForTesting()); 563 } 564 565 /** 566 * Tests that the receiver toggles registration for connectivity intents based on activity 567 * state. 568 */ 569 @Test 570 @UiThreadTest 571 @MediumTest 572 @Feature({"Android-AppBase"}) testNetworkChangeNotifierRegistersForIntents()573 public void testNetworkChangeNotifierRegistersForIntents() { 574 RegistrationPolicyApplicationStatus policy = 575 (RegistrationPolicyApplicationStatus) mReceiver.getRegistrationPolicy(); 576 triggerApplicationStateChange(policy, ApplicationState.HAS_RUNNING_ACTIVITIES); 577 Assert.assertTrue(mReceiver.isReceiverRegisteredForTesting()); 578 579 triggerApplicationStateChange(policy, ApplicationState.HAS_PAUSED_ACTIVITIES); 580 Assert.assertFalse(mReceiver.isReceiverRegisteredForTesting()); 581 582 triggerApplicationStateChange(policy, ApplicationState.HAS_RUNNING_ACTIVITIES); 583 Assert.assertTrue(mReceiver.isReceiverRegisteredForTesting()); 584 } 585 586 /** 587 * Tests that getCurrentConnectionCost() returns the correct result. 588 */ 589 @Test 590 @UiThreadTest 591 @MediumTest 592 @Feature({"Android-AppBase"}) testNetworkChangeNotifierConnectionCost()593 public void testNetworkChangeNotifierConnectionCost() { 594 mConnectivityDelegate.setIsMetered(true); 595 Assert.assertEquals(ConnectionCost.METERED, getCurrentConnectionCost()); 596 mConnectivityDelegate.setIsMetered(false); 597 Assert.assertEquals(ConnectionCost.UNMETERED, getCurrentConnectionCost()); 598 } 599 600 /** 601 * Tests that changing the network type changes the connection subtype. 602 */ 603 @Test 604 @UiThreadTest 605 @MediumTest 606 @Feature({"Android-AppBase"}) testNetworkChangeNotifierConnectionSubtypeEthernet()607 public void testNetworkChangeNotifierConnectionSubtypeEthernet() { 608 // Show that for Ethernet the link speed is unknown (+Infinity). 609 mConnectivityDelegate.setNetworkType(ConnectivityManager.TYPE_ETHERNET); 610 Assert.assertEquals(ConnectionType.CONNECTION_ETHERNET, getCurrentConnectionType()); 611 Assert.assertEquals(ConnectionSubtype.SUBTYPE_UNKNOWN, getCurrentConnectionSubtype()); 612 } 613 614 @Test 615 @UiThreadTest 616 @MediumTest 617 @Feature({"Android-AppBase"}) testNetworkChangeNotifierConnectionSubtypeWifi()618 public void testNetworkChangeNotifierConnectionSubtypeWifi() { 619 // Show that for WiFi the link speed is unknown (+Infinity). 620 mConnectivityDelegate.setNetworkType(ConnectivityManager.TYPE_WIFI); 621 Assert.assertEquals(ConnectionType.CONNECTION_WIFI, getCurrentConnectionType()); 622 Assert.assertEquals(ConnectionSubtype.SUBTYPE_UNKNOWN, getCurrentConnectionSubtype()); 623 } 624 625 @Test 626 @UiThreadTest 627 @MediumTest 628 @Feature({"Android-AppBase"}) testNetworkChangeNotifierConnectionSubtypeWiMax()629 public void testNetworkChangeNotifierConnectionSubtypeWiMax() { 630 // Show that for WiMax the link speed is unknown (+Infinity), although the type is 4g. 631 // TODO(jkarlin): Add support for CONNECTION_WIMAX as specified in 632 // http://w3c.github.io/netinfo/. 633 mConnectivityDelegate.setNetworkType(ConnectivityManager.TYPE_WIMAX); 634 Assert.assertEquals(ConnectionType.CONNECTION_4G, getCurrentConnectionType()); 635 Assert.assertEquals(ConnectionSubtype.SUBTYPE_UNKNOWN, getCurrentConnectionSubtype()); 636 } 637 638 @Test 639 @UiThreadTest 640 @MediumTest 641 @Feature({"Android-AppBase"}) testNetworkChangeNotifierConnectionSubtypeBluetooth()642 public void testNetworkChangeNotifierConnectionSubtypeBluetooth() { 643 // Show that for bluetooth the link speed is unknown (+Infinity). 644 mConnectivityDelegate.setNetworkType(ConnectivityManager.TYPE_BLUETOOTH); 645 Assert.assertEquals(ConnectionType.CONNECTION_BLUETOOTH, getCurrentConnectionType()); 646 Assert.assertEquals(ConnectionSubtype.SUBTYPE_UNKNOWN, getCurrentConnectionSubtype()); 647 } 648 649 @Test 650 @UiThreadTest 651 @MediumTest 652 @Feature({"Android-AppBase"}) testNetworkChangeNotifierConnectionSubtypeMobile()653 public void testNetworkChangeNotifierConnectionSubtypeMobile() { 654 // Test that for mobile types the subtype is used to determine the connection subtype. 655 mConnectivityDelegate.setNetworkType(ConnectivityManager.TYPE_MOBILE); 656 mConnectivityDelegate.setNetworkSubtype(TelephonyManager.NETWORK_TYPE_LTE); 657 Assert.assertEquals(ConnectionType.CONNECTION_4G, getCurrentConnectionType()); 658 Assert.assertEquals(ConnectionSubtype.SUBTYPE_LTE, getCurrentConnectionSubtype()); 659 } 660 661 /** 662 * Indicate to NetworkChangeNotifierAutoDetect that a connectivity change has occurred. 663 * Uses same signals that system would use. 664 */ notifyConnectivityChange()665 private void notifyConnectivityChange() { 666 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { 667 mConnectivityDelegate.getDefaultNetworkCallback().onAvailable(null); 668 } else { 669 Intent connectivityIntent = new Intent(ConnectivityManager.CONNECTIVITY_ACTION); 670 mReceiver.onReceive(InstrumentationRegistry.getTargetContext(), connectivityIntent); 671 } 672 } 673 674 /** 675 * Tests that when Chrome gets an intent indicating a change in network connectivity, it sends a 676 * notification to Java observers. 677 */ 678 @Test 679 @UiThreadTest 680 @MediumTest 681 @Feature({"Android-AppBase"}) testNetworkChangeNotifierJavaObservers()682 public void testNetworkChangeNotifierJavaObservers() { 683 mReceiver.register(); 684 // Initialize the NetworkChangeNotifier with a connection. 685 Intent connectivityIntent = new Intent(ConnectivityManager.CONNECTIVITY_ACTION); 686 mReceiver.onReceive(InstrumentationRegistry.getTargetContext(), connectivityIntent); 687 688 // We shouldn't be re-notified if the connection hasn't actually changed. 689 NetworkChangeNotifierTestObserver observer = new NetworkChangeNotifierTestObserver(); 690 NetworkChangeNotifier.addConnectionTypeObserver(observer); 691 notifyConnectivityChange(); 692 Assert.assertFalse(observer.hasReceivedNotification()); 693 694 // We shouldn't be notified if we're connected to non-Wifi and the Wifi SSID changes. 695 mWifiDelegate.setWifiSSID("bar"); 696 notifyConnectivityChange(); 697 Assert.assertFalse(observer.hasReceivedNotification()); 698 // We should be notified when we change to Wifi. 699 mConnectivityDelegate.setNetworkType(ConnectivityManager.TYPE_WIFI); 700 notifyConnectivityChange(); 701 Assert.assertTrue(observer.hasReceivedNotification()); 702 observer.resetHasReceivedNotification(); 703 // We should be notified when the Wifi SSID changes. 704 mWifiDelegate.setWifiSSID("foo"); 705 notifyConnectivityChange(); 706 Assert.assertTrue(observer.hasReceivedNotification()); 707 observer.resetHasReceivedNotification(); 708 // We shouldn't be re-notified if the Wifi SSID hasn't actually changed. 709 notifyConnectivityChange(); 710 Assert.assertFalse(observer.hasReceivedNotification()); 711 712 // We should be notified if use of DNS-over-TLS changes. 713 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { 714 // Verify notification for enabling private DNS. 715 mConnectivityDelegate.setIsPrivateDnsActive(true); 716 mConnectivityDelegate.getDefaultNetworkCallback().onLinkPropertiesChanged(null, null); 717 Assert.assertTrue(observer.hasReceivedNotification()); 718 observer.resetHasReceivedNotification(); 719 // Verify notification for specifying private DNS server. 720 mConnectivityDelegate.setPrivateDnsServerName("dotserver.com"); 721 mConnectivityDelegate.getDefaultNetworkCallback().onLinkPropertiesChanged(null, null); 722 Assert.assertTrue(observer.hasReceivedNotification()); 723 observer.resetHasReceivedNotification(); 724 // Verify no notification for no change. 725 mConnectivityDelegate.getDefaultNetworkCallback().onLinkPropertiesChanged(null, null); 726 Assert.assertFalse(observer.hasReceivedNotification()); 727 // Verify notification for disabling. 728 mConnectivityDelegate.setIsPrivateDnsActive(false); 729 mConnectivityDelegate.getDefaultNetworkCallback().onLinkPropertiesChanged(null, null); 730 Assert.assertTrue(observer.hasReceivedNotification()); 731 observer.resetHasReceivedNotification(); 732 } 733 734 // Mimic that connectivity has been lost and ensure that Chrome notifies our observer. 735 mConnectivityDelegate.setActiveNetworkExists(false); 736 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { 737 mConnectivityDelegate.getDefaultNetworkCallback().onLost(null); 738 } else { 739 mReceiver.onReceive(InstrumentationRegistry.getTargetContext(), connectivityIntent); 740 } 741 Assert.assertTrue(observer.hasReceivedNotification()); 742 743 observer.resetHasReceivedNotification(); 744 // Pretend we got moved to the background. 745 final RegistrationPolicyApplicationStatus policy = 746 (RegistrationPolicyApplicationStatus) mReceiver.getRegistrationPolicy(); 747 triggerApplicationStateChange(policy, ApplicationState.HAS_PAUSED_ACTIVITIES); 748 // Change the state. 749 mConnectivityDelegate.setActiveNetworkExists(true); 750 mConnectivityDelegate.setNetworkType(ConnectivityManager.TYPE_WIFI); 751 // The NetworkChangeNotifierAutoDetect doesn't receive any notification while we are in the 752 // background, but when we get back to the foreground the state changed should be detected 753 // and a notification sent. 754 triggerApplicationStateChange(policy, ApplicationState.HAS_RUNNING_ACTIVITIES); 755 Assert.assertTrue(observer.hasReceivedNotification()); 756 } 757 758 /** 759 * Tests that when Chrome gets an intent indicating a change in max bandwidth, it sends a 760 * notification to Java observers. 761 */ 762 @Test 763 @UiThreadTest 764 @MediumTest 765 @Feature({"Android-AppBase"}) testNetworkChangeNotifierConnectionSubtypeNotifications()766 public void testNetworkChangeNotifierConnectionSubtypeNotifications() { 767 mReceiver.register(); 768 // Initialize the NetworkChangeNotifier with a connection. 769 mConnectivityDelegate.setActiveNetworkExists(true); 770 mConnectivityDelegate.setNetworkType(ConnectivityManager.TYPE_WIFI); 771 Intent connectivityIntent = new Intent(ConnectivityManager.CONNECTIVITY_ACTION); 772 mReceiver.onReceive(InstrumentationRegistry.getTargetContext(), connectivityIntent); 773 Assert.assertTrue(mNotifier.hasReceivedConnectionSubtypeNotification()); 774 mNotifier.resetHasReceivedConnectionSubtypeNotification(); 775 776 // We shouldn't be re-notified if the connection hasn't actually changed. 777 NetworkChangeNotifierTestObserver observer = new NetworkChangeNotifierTestObserver(); 778 NetworkChangeNotifier.addConnectionTypeObserver(observer); 779 mReceiver.onReceive(InstrumentationRegistry.getTargetContext(), connectivityIntent); 780 Assert.assertFalse(mNotifier.hasReceivedConnectionSubtypeNotification()); 781 782 // We should be notified if bandwidth and connection type changed. 783 mConnectivityDelegate.setNetworkType(ConnectivityManager.TYPE_ETHERNET); 784 mReceiver.onReceive(InstrumentationRegistry.getTargetContext(), connectivityIntent); 785 Assert.assertTrue(mNotifier.hasReceivedConnectionSubtypeNotification()); 786 mNotifier.resetHasReceivedConnectionSubtypeNotification(); 787 788 // We should be notified if the connection type changed, but not the bandwidth. 789 // Note that TYPE_ETHERNET and TYPE_BLUETOOTH have the same +INFINITY max bandwidth. 790 // This test will fail if that changes. 791 mConnectivityDelegate.setNetworkType(ConnectivityManager.TYPE_BLUETOOTH); 792 mReceiver.onReceive(InstrumentationRegistry.getTargetContext(), connectivityIntent); 793 Assert.assertTrue(mNotifier.hasReceivedConnectionSubtypeNotification()); 794 } 795 796 /** 797 * Tests that when setting {@code registerToReceiveNotificationsAlways()}, 798 * a NetworkChangeNotifierAutoDetect object is successfully created. 799 */ 800 @Test 801 @UiThreadTest 802 @MediumTest 803 @Feature({"Android-AppBase"}) testCreateNetworkChangeNotifierAlwaysWatchForChanges()804 public void testCreateNetworkChangeNotifierAlwaysWatchForChanges() { 805 createTestNotifier(WatchForChanges.ALWAYS); 806 Assert.assertTrue(mReceiver.isReceiverRegisteredForTesting()); 807 808 // Make sure notifications can be received. 809 NetworkChangeNotifierTestObserver observer = new NetworkChangeNotifierTestObserver(); 810 NetworkChangeNotifier.addConnectionTypeObserver(observer); 811 Intent connectivityIntent = new Intent(ConnectivityManager.CONNECTIVITY_ACTION); 812 mReceiver.onReceive(InstrumentationRegistry.getTargetContext(), connectivityIntent); 813 Assert.assertTrue(observer.hasReceivedNotification()); 814 } 815 816 /** 817 * Tests that ConnectivityManagerDelegate doesn't crash. This test cannot rely on having any 818 * active network connections so it cannot usefully check results, but it can at least check 819 * that the functions don't crash. 820 */ 821 @Test 822 @UiThreadTest 823 @MediumTest 824 @Feature({"Android-AppBase"}) testConnectivityManagerDelegateDoesNotCrash()825 public void testConnectivityManagerDelegateDoesNotCrash() { 826 ConnectivityManagerDelegate delegate = 827 new ConnectivityManagerDelegate(InstrumentationRegistry.getTargetContext()); 828 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { 829 delegate.getNetworkState(null); 830 } else { 831 delegate.getNetworkState( 832 new WifiManagerDelegate(InstrumentationRegistry.getTargetContext())); 833 } 834 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 835 // getConnectionType(Network) doesn't crash upon invalid Network argument. 836 Network invalidNetwork = Helper.netIdToNetwork(NetId.INVALID); 837 Assert.assertEquals( 838 ConnectionType.CONNECTION_NONE, delegate.getConnectionType(invalidNetwork)); 839 840 Network[] networks = delegate.getAllNetworksUnfiltered(); 841 Assert.assertNotNull(networks); 842 if (networks.length >= 1) { 843 delegate.getConnectionType(networks[0]); 844 } 845 delegate.getDefaultNetwork(); 846 NetworkCallback networkCallback = new NetworkCallback(); 847 NetworkRequest networkRequest = new NetworkRequest.Builder().build(); 848 delegate.registerNetworkCallback( 849 networkRequest, networkCallback, new Handler(Looper.myLooper())); 850 delegate.unregisterNetworkCallback(networkCallback); 851 } 852 } 853 854 /** 855 * Tests that NetworkChangeNotifierAutoDetect queryable APIs don't crash. This test cannot rely 856 * on having any active network connections so it cannot usefully check results, but it can at 857 * least check that the functions don't crash. 858 */ 859 @Test 860 @UiThreadTest 861 @MediumTest 862 @Feature({"Android-AppBase"}) testQueryableAPIsDoNotCrash()863 public void testQueryableAPIsDoNotCrash() { 864 NetworkChangeNotifierAutoDetect.Observer observer = 865 new TestNetworkChangeNotifierAutoDetectObserver(); 866 NetworkChangeNotifierAutoDetect ncn = new NetworkChangeNotifierAutoDetect(observer, 867 new RegistrationPolicyAlwaysRegister()); 868 ncn.getNetworksAndTypes(); 869 ncn.getDefaultNetId(); 870 } 871 872 /** 873 * Tests that NetworkChangeNotifierAutoDetect query-able APIs return expected 874 * values from the inserted mock ConnectivityManager. 875 */ 876 @Test 877 @UiThreadTest 878 @MediumTest 879 @Feature({"Android-AppBase"}) testQueryableAPIsReturnExpectedValuesFromMockDelegate()880 public void testQueryableAPIsReturnExpectedValuesFromMockDelegate() { 881 NetworkChangeNotifierAutoDetect.Observer observer = 882 new TestNetworkChangeNotifierAutoDetectObserver(); 883 884 setApplicationHasVisibleActivities(false); 885 NetworkChangeNotifierAutoDetect ncn = new NetworkChangeNotifierAutoDetect( 886 observer, new RegistrationPolicyApplicationStatus()); 887 888 if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { 889 Assert.assertEquals(0, ncn.getNetworksAndTypes().length); 890 Assert.assertEquals(NetId.INVALID, ncn.getDefaultNetId()); 891 return; 892 } 893 894 // Insert a mocked dummy implementation for the ConnectivityDelegate. 895 ncn.setConnectivityManagerDelegateForTests(new ConnectivityManagerDelegate() { 896 public final Network[] mNetworks = 897 new Network[] {Helper.netIdToNetwork(111), Helper.netIdToNetwork(333)}; 898 899 @Override 900 protected Network[] getAllNetworksUnfiltered() { 901 return mNetworks; 902 } 903 904 @Override 905 Network getDefaultNetwork() { 906 return mNetworks[1]; 907 } 908 909 @Override 910 protected NetworkCapabilities getNetworkCapabilities(Network network) { 911 return Helper.getCapabilities(TRANSPORT_WIFI); 912 } 913 914 @Override 915 public int getConnectionType(Network network) { 916 return ConnectionType.CONNECTION_NONE; 917 } 918 }); 919 920 // Verify that the mock delegate connectivity manager is being used 921 // by the network change notifier auto-detector. 922 Assert.assertEquals(333, demungeNetId(ncn.getDefaultNetId())); 923 924 // The api {@link NetworkChangeNotifierAutoDetect#getNetworksAndTypes()} 925 // returns an array of a repeated sequence of: (NetID, ConnectionType). 926 // There are 4 entries in the array, two for each network. 927 Assert.assertEquals(4, ncn.getNetworksAndTypes().length); 928 Assert.assertEquals(111, demungeNetId(ncn.getNetworksAndTypes()[0])); 929 Assert.assertEquals(ConnectionType.CONNECTION_NONE, ncn.getNetworksAndTypes()[1]); 930 Assert.assertEquals(333, demungeNetId(ncn.getNetworksAndTypes()[2])); 931 Assert.assertEquals(ConnectionType.CONNECTION_NONE, ncn.getNetworksAndTypes()[3]); 932 } 933 934 /** 935 * Tests that callbacks are issued to Observers when NetworkChangeNotifierAutoDetect receives 936 * the right signals (via its NetworkCallback). 937 */ 938 @Test 939 @MediumTest 940 @Feature({"Android-AppBase"}) 941 @MinAndroidSdkLevel(Build.VERSION_CODES.LOLLIPOP) testNetworkCallbacks()942 public void testNetworkCallbacks() throws Exception { 943 // Setup NetworkChangeNotifierAutoDetect 944 final TestNetworkChangeNotifierAutoDetectObserver observer = 945 new TestNetworkChangeNotifierAutoDetectObserver(); 946 Callable<NetworkChangeNotifierAutoDetect> callable = 947 new Callable<NetworkChangeNotifierAutoDetect>() { 948 @Override 949 public NetworkChangeNotifierAutoDetect call() { 950 // This call prevents NetworkChangeNotifierAutoDetect from 951 // registering for events right off the bat. We'll delay this 952 // until our MockConnectivityManagerDelegate is first installed 953 // to prevent inadvertent communication with the real 954 // ConnectivityManager. 955 setApplicationHasVisibleActivities(false); 956 return new NetworkChangeNotifierAutoDetect( 957 observer, new RegistrationPolicyApplicationStatus()); 958 } 959 }; 960 FutureTask<NetworkChangeNotifierAutoDetect> task = new FutureTask<>(callable); 961 ThreadUtils.postOnUiThread(task); 962 NetworkChangeNotifierAutoDetect ncn = task.get(); 963 964 // Insert mock ConnectivityDelegate 965 mConnectivityDelegate = new MockConnectivityManagerDelegate(); 966 ncn.setConnectivityManagerDelegateForTests(mConnectivityDelegate); 967 // Now that mock ConnectivityDelegate is inserted, pretend app is foregrounded 968 // so NetworkChangeNotifierAutoDetect will register its NetworkCallback. 969 Assert.assertFalse(ncn.isReceiverRegisteredForTesting()); 970 971 RegistrationPolicyApplicationStatus policy = 972 (RegistrationPolicyApplicationStatus) ncn.getRegistrationPolicy(); 973 triggerApplicationStateChange(policy, ApplicationState.HAS_RUNNING_ACTIVITIES); 974 Assert.assertTrue(ncn.isReceiverRegisteredForTesting()); 975 976 // Find NetworkChangeNotifierAutoDetect's NetworkCallback, which should have been registered 977 // with mConnectivityDelegate. 978 NetworkCallback networkCallback = mConnectivityDelegate.getLastRegisteredNetworkCallback(); 979 Assert.assertNotNull(networkCallback); 980 981 // First thing we'll receive is a purge to initialize any network lists. 982 observer.assertLastChange(ChangeType.PURGE_LIST, NetId.INVALID); 983 984 // Test connected signal is passed along. 985 mConnectivityDelegate.addNetwork(100, TRANSPORT_WIFI, false); 986 observer.assertLastChange(ChangeType.CONNECT, 100); 987 988 // Test soon-to-be-disconnected signal is passed along. 989 networkCallback.onLosing(Helper.netIdToNetwork(100), 30); 990 observer.assertLastChange(ChangeType.SOON_TO_DISCONNECT, 100); 991 992 // Test connected signal is passed along. 993 mConnectivityDelegate.removeNetwork(100); 994 observer.assertLastChange(ChangeType.DISCONNECT, 100); 995 996 // Simulate app backgrounding then foregrounding. 997 Assert.assertTrue(ncn.isReceiverRegisteredForTesting()); 998 triggerApplicationStateChange(policy, ApplicationState.HAS_PAUSED_ACTIVITIES); 999 Assert.assertFalse(ncn.isReceiverRegisteredForTesting()); 1000 triggerApplicationStateChange(policy, ApplicationState.HAS_RUNNING_ACTIVITIES); 1001 Assert.assertTrue(ncn.isReceiverRegisteredForTesting()); 1002 // Verify network list purged. 1003 observer.assertLastChange(ChangeType.PURGE_LIST, NetId.INVALID); 1004 1005 // 1006 // VPN testing 1007 // 1008 1009 // Add a couple normal networks 1010 mConnectivityDelegate.addNetwork(100, TRANSPORT_WIFI, false); 1011 observer.assertLastChange(ChangeType.CONNECT, 100); 1012 mConnectivityDelegate.addNetwork(101, TRANSPORT_CELLULAR, false); 1013 observer.assertLastChange(ChangeType.CONNECT, 101); 1014 1015 // Verify inaccessible VPN is ignored 1016 mConnectivityDelegate.addNetwork(102, TRANSPORT_VPN, false); 1017 NetworkChangeNotifierTestUtil.flushUiThreadTaskQueue(); 1018 Assert.assertEquals(observer.mChanges.size(), 0); 1019 // The disconnect will be ignored in 1020 // NetworkChangeNotifierDelegateAndroid::NotifyOfNetworkDisconnect() because no 1021 // connect event was witnessed, but it will be sent to {@code observer} 1022 mConnectivityDelegate.removeNetwork(102); 1023 observer.assertLastChange(ChangeType.DISCONNECT, 102); 1024 1025 // Verify when an accessible VPN connects, all other network disconnect 1026 mConnectivityDelegate.addNetwork(103, TRANSPORT_VPN, true); 1027 NetworkChangeNotifierTestUtil.flushUiThreadTaskQueue(); 1028 Assert.assertEquals(2, observer.mChanges.size()); 1029 Assert.assertEquals(ChangeType.CONNECT, observer.mChanges.get(0).mChangeType); 1030 Assert.assertEquals(103, observer.mChanges.get(0).mNetId); 1031 Assert.assertEquals(ChangeType.PURGE_LIST, observer.mChanges.get(1).mChangeType); 1032 Assert.assertEquals(103, observer.mChanges.get(1).mNetId); 1033 observer.mChanges.clear(); 1034 1035 // Verify when an accessible VPN disconnects, all other networks reconnect 1036 mConnectivityDelegate.removeNetwork(103); 1037 NetworkChangeNotifierTestUtil.flushUiThreadTaskQueue(); 1038 Assert.assertEquals(3, observer.mChanges.size()); 1039 Assert.assertEquals(ChangeType.DISCONNECT, observer.mChanges.get(0).mChangeType); 1040 Assert.assertEquals(103, observer.mChanges.get(0).mNetId); 1041 Assert.assertEquals(ChangeType.CONNECT, observer.mChanges.get(1).mChangeType); 1042 Assert.assertEquals(100, observer.mChanges.get(1).mNetId); 1043 Assert.assertEquals(ChangeType.CONNECT, observer.mChanges.get(2).mChangeType); 1044 Assert.assertEquals(101, observer.mChanges.get(2).mNetId); 1045 } 1046 1047 /** 1048 * Tests that isOnline() returns the correct result. 1049 */ 1050 @Test 1051 @UiThreadTest 1052 @MediumTest 1053 @Feature({"Android-AppBase"}) testNetworkChangeNotifierIsOnline()1054 public void testNetworkChangeNotifierIsOnline() { 1055 mReceiver.register(); 1056 Intent intent = new Intent(ConnectivityManager.CONNECTIVITY_ACTION); 1057 // For any connection type it should return true. 1058 for (int i = ConnectivityManager.TYPE_MOBILE; i < ConnectivityManager.TYPE_VPN; i++) { 1059 mConnectivityDelegate.setActiveNetworkExists(true); 1060 mConnectivityDelegate.setNetworkType(i); 1061 mReceiver.onReceive(InstrumentationRegistry.getTargetContext(), intent); 1062 Assert.assertTrue(NetworkChangeNotifier.isOnline()); 1063 } 1064 mConnectivityDelegate.setActiveNetworkExists(false); 1065 mReceiver.onReceive(InstrumentationRegistry.getTargetContext(), intent); 1066 Assert.assertFalse(NetworkChangeNotifier.isOnline()); 1067 } 1068 1069 /** 1070 * Regression test for crbug.com/805424 where ConnectivityManagerDelegate.vpnAccessible() was 1071 * found to leak. 1072 */ 1073 @Test 1074 @MediumTest 1075 @MinAndroidSdkLevel(Build.VERSION_CODES.LOLLIPOP) // android.net.Network available in L+. testVpnAccessibleDoesNotLeak()1076 public void testVpnAccessibleDoesNotLeak() { 1077 ConnectivityManagerDelegate connectivityManagerDelegate = new ConnectivityManagerDelegate( 1078 InstrumentationRegistry.getInstrumentation().getTargetContext()); 1079 StrictMode.VmPolicy oldPolicy = StrictMode.getVmPolicy(); 1080 StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder() 1081 .detectLeakedClosableObjects() 1082 .penaltyDeath() 1083 .penaltyLog() 1084 .build()); 1085 try { 1086 // Test non-existent Network (NetIds only go to 65535). 1087 connectivityManagerDelegate.vpnAccessible(Helper.netIdToNetwork(65537)); 1088 // Test existing Networks. 1089 for (Network network : connectivityManagerDelegate.getAllNetworksUnfiltered()) { 1090 connectivityManagerDelegate.vpnAccessible(network); 1091 } 1092 1093 // Run GC and finalizers a few times to pick up leaked closeables 1094 for (int i = 0; i < 10; i++) { 1095 System.gc(); 1096 System.runFinalization(); 1097 } 1098 System.gc(); 1099 System.runFinalization(); 1100 } finally { 1101 StrictMode.setVmPolicy(oldPolicy); 1102 } 1103 } 1104 1105 /** 1106 * Regression test for crbug.com/946531 where ConnectivityManagerDelegate.vpnAccessible() 1107 * triggered StrictMode's untagged socket prohibition. 1108 */ 1109 @Test 1110 @MediumTest 1111 @MinAndroidSdkLevel(Build.VERSION_CODES.O) // detectUntaggedSockets added in Oreo. testVpnAccessibleDoesNotCreateUntaggedSockets()1112 public void testVpnAccessibleDoesNotCreateUntaggedSockets() { 1113 ConnectivityManagerDelegate connectivityManagerDelegate = new ConnectivityManagerDelegate( 1114 InstrumentationRegistry.getInstrumentation().getTargetContext()); 1115 StrictMode.VmPolicy oldPolicy = StrictMode.getVmPolicy(); 1116 StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder() 1117 .detectUntaggedSockets() 1118 .penaltyDeath() 1119 .penaltyLog() 1120 .build()); 1121 try { 1122 // Test non-existent Network (NetIds only go to 65535). 1123 connectivityManagerDelegate.vpnAccessible(Helper.netIdToNetwork(65537)); 1124 // Test existing Networks. 1125 for (Network network : connectivityManagerDelegate.getAllNetworksUnfiltered()) { 1126 connectivityManagerDelegate.vpnAccessible(network); 1127 } 1128 } finally { 1129 StrictMode.setVmPolicy(oldPolicy); 1130 } 1131 } 1132 } 1133