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