1 /* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server; 18 19 import static android.net.ConnectivityManager.CONNECTIVITY_ACTION; 20 import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OFF; 21 import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OPPORTUNISTIC; 22 import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_PROVIDER_HOSTNAME; 23 import static android.net.ConnectivityManager.TYPE_ETHERNET; 24 import static android.net.ConnectivityManager.TYPE_MOBILE; 25 import static android.net.ConnectivityManager.TYPE_MOBILE_FOTA; 26 import static android.net.ConnectivityManager.TYPE_MOBILE_MMS; 27 import static android.net.ConnectivityManager.TYPE_NONE; 28 import static android.net.ConnectivityManager.TYPE_WIFI; 29 import static android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL; 30 import static android.net.NetworkCapabilities.NET_CAPABILITY_CBS; 31 import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN; 32 import static android.net.NetworkCapabilities.NET_CAPABILITY_EIMS; 33 import static android.net.NetworkCapabilities.NET_CAPABILITY_FOREGROUND; 34 import static android.net.NetworkCapabilities.NET_CAPABILITY_FOTA; 35 import static android.net.NetworkCapabilities.NET_CAPABILITY_IA; 36 import static android.net.NetworkCapabilities.NET_CAPABILITY_IMS; 37 import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET; 38 import static android.net.NetworkCapabilities.NET_CAPABILITY_MMS; 39 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED; 40 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED; 41 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED; 42 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN; 43 import static android.net.NetworkCapabilities.NET_CAPABILITY_RCS; 44 import static android.net.NetworkCapabilities.NET_CAPABILITY_SUPL; 45 import static android.net.NetworkCapabilities.NET_CAPABILITY_TRUSTED; 46 import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED; 47 import static android.net.NetworkCapabilities.NET_CAPABILITY_WIFI_P2P; 48 import static android.net.NetworkCapabilities.NET_CAPABILITY_XCAP; 49 import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; 50 import static android.net.NetworkCapabilities.TRANSPORT_ETHERNET; 51 import static android.net.NetworkCapabilities.TRANSPORT_VPN; 52 import static android.net.NetworkCapabilities.TRANSPORT_WIFI; 53 import static android.net.NetworkCapabilities.TRANSPORT_WIFI_AWARE; 54 55 import static com.android.internal.util.TestUtils.waitForIdleHandler; 56 import static com.android.internal.util.TestUtils.waitForIdleLooper; 57 58 import static org.junit.Assert.assertEquals; 59 import static org.junit.Assert.assertFalse; 60 import static org.junit.Assert.assertNotNull; 61 import static org.junit.Assert.assertNull; 62 import static org.junit.Assert.assertTrue; 63 import static org.junit.Assert.fail; 64 import static org.mockito.Matchers.anyBoolean; 65 import static org.mockito.Matchers.anyInt; 66 import static org.mockito.Matchers.anyString; 67 import static org.mockito.Mockito.any; 68 import static org.mockito.Mockito.atLeastOnce; 69 import static org.mockito.Mockito.eq; 70 import static org.mockito.Mockito.mock; 71 import static org.mockito.Mockito.never; 72 import static org.mockito.Mockito.reset; 73 import static org.mockito.Mockito.spy; 74 import static org.mockito.Mockito.times; 75 import static org.mockito.Mockito.verify; 76 import static org.mockito.Mockito.verifyNoMoreInteractions; 77 import static org.mockito.Mockito.when; 78 79 80 import android.app.NotificationManager; 81 import android.app.PendingIntent; 82 import android.content.BroadcastReceiver; 83 import android.content.ContentResolver; 84 import android.content.Context; 85 import android.content.Intent; 86 import android.content.IntentFilter; 87 import android.content.pm.UserInfo; 88 import android.content.res.Resources; 89 import android.net.CaptivePortal; 90 import android.net.ConnectivityManager; 91 import android.net.ConnectivityManager.NetworkCallback; 92 import android.net.ConnectivityManager.PacketKeepalive; 93 import android.net.ConnectivityManager.PacketKeepaliveCallback; 94 import android.net.ConnectivityManager.TooManyRequestsException; 95 import android.net.ConnectivityThread; 96 import android.net.INetworkPolicyManager; 97 import android.net.INetworkStatsService; 98 import android.net.IpPrefix; 99 import android.net.LinkAddress; 100 import android.net.LinkProperties; 101 import android.net.MatchAllNetworkSpecifier; 102 import android.net.Network; 103 import android.net.NetworkAgent; 104 import android.net.NetworkCapabilities; 105 import android.net.NetworkFactory; 106 import android.net.NetworkInfo; 107 import android.net.NetworkInfo.DetailedState; 108 import android.net.NetworkMisc; 109 import android.net.NetworkRequest; 110 import android.net.NetworkSpecifier; 111 import android.net.NetworkUtils; 112 import android.net.RouteInfo; 113 import android.net.StringNetworkSpecifier; 114 import android.net.UidRange; 115 import android.net.VpnService; 116 import android.net.captiveportal.CaptivePortalProbeResult; 117 import android.net.metrics.IpConnectivityLog; 118 import android.net.util.MultinetworkPolicyTracker; 119 import android.os.ConditionVariable; 120 import android.os.Handler; 121 import android.os.HandlerThread; 122 import android.os.INetworkManagementService; 123 import android.os.Looper; 124 import android.os.Message; 125 import android.os.Parcel; 126 import android.os.Parcelable; 127 import android.os.Process; 128 import android.os.SystemClock; 129 import android.os.UserHandle; 130 import android.provider.Settings; 131 import android.support.test.InstrumentationRegistry; 132 import android.support.test.filters.SmallTest; 133 import android.support.test.runner.AndroidJUnit4; 134 import android.test.mock.MockContentResolver; 135 import android.util.ArraySet; 136 import android.util.Log; 137 138 import com.android.internal.net.VpnConfig; 139 import com.android.internal.util.ArrayUtils; 140 import com.android.internal.util.WakeupMessage; 141 import com.android.internal.util.test.BroadcastInterceptingContext; 142 import com.android.internal.util.test.FakeSettingsProvider; 143 import com.android.server.connectivity.ConnectivityConstants; 144 import com.android.server.connectivity.DefaultNetworkMetrics; 145 import com.android.server.connectivity.DnsManager; 146 import com.android.server.connectivity.IpConnectivityMetrics; 147 import com.android.server.connectivity.MockableSystemProperties; 148 import com.android.server.connectivity.NetworkAgentInfo; 149 import com.android.server.connectivity.NetworkMonitor; 150 import com.android.server.connectivity.Vpn; 151 import com.android.server.net.NetworkPinner; 152 import com.android.server.net.NetworkPolicyManagerInternal; 153 154 import org.junit.After; 155 import org.junit.Before; 156 import org.junit.Ignore; 157 import org.junit.Test; 158 import org.junit.runner.RunWith; 159 import org.mockito.ArgumentCaptor; 160 import org.mockito.Mock; 161 import org.mockito.MockitoAnnotations; 162 import org.mockito.Spy; 163 164 import java.net.InetAddress; 165 import java.util.ArrayList; 166 import java.util.Arrays; 167 import java.util.Collection; 168 import java.util.HashSet; 169 import java.util.List; 170 import java.util.Objects; 171 import java.util.Set; 172 import java.util.concurrent.CountDownLatch; 173 import java.util.concurrent.LinkedBlockingQueue; 174 import java.util.concurrent.TimeUnit; 175 import java.util.concurrent.atomic.AtomicBoolean; 176 import java.util.function.Predicate; 177 178 179 /** 180 * Tests for {@link ConnectivityService}. 181 * 182 * Build, install and run with: 183 * runtest frameworks-net -c com.android.server.ConnectivityServiceTest 184 */ 185 @RunWith(AndroidJUnit4.class) 186 @SmallTest 187 public class ConnectivityServiceTest { 188 private static final String TAG = "ConnectivityServiceTest"; 189 190 private static final int TIMEOUT_MS = 500; 191 private static final int TEST_LINGER_DELAY_MS = 120; 192 193 private static final String MOBILE_IFNAME = "test_rmnet_data0"; 194 private static final String WIFI_IFNAME = "test_wlan0"; 195 196 private MockContext mServiceContext; 197 private WrappedConnectivityService mService; 198 private WrappedConnectivityManager mCm; 199 private MockNetworkAgent mWiFiNetworkAgent; 200 private MockNetworkAgent mCellNetworkAgent; 201 private MockNetworkAgent mEthernetNetworkAgent; 202 private MockVpn mMockVpn; 203 private Context mContext; 204 205 @Mock IpConnectivityMetrics.Logger mMetricsService; 206 @Mock DefaultNetworkMetrics mDefaultNetworkMetrics; 207 @Mock INetworkManagementService mNetworkManagementService; 208 @Mock INetworkStatsService mStatsService; 209 210 private ArgumentCaptor<String[]> mStringArrayCaptor = ArgumentCaptor.forClass(String[].class); 211 212 // This class exists to test bindProcessToNetwork and getBoundNetworkForProcess. These methods 213 // do not go through ConnectivityService but talk to netd directly, so they don't automatically 214 // reflect the state of our test ConnectivityService. 215 private class WrappedConnectivityManager extends ConnectivityManager { 216 private Network mFakeBoundNetwork; 217 218 public synchronized boolean bindProcessToNetwork(Network network) { 219 mFakeBoundNetwork = network; 220 return true; 221 } 222 223 public synchronized Network getBoundNetworkForProcess() { 224 return mFakeBoundNetwork; 225 } 226 227 public WrappedConnectivityManager(Context context, ConnectivityService service) { 228 super(context, service); 229 } 230 } 231 232 private class MockContext extends BroadcastInterceptingContext { 233 private final MockContentResolver mContentResolver; 234 235 @Spy private Resources mResources; 236 private final LinkedBlockingQueue<Intent> mStartedActivities = new LinkedBlockingQueue<>(); 237 238 MockContext(Context base) { 239 super(base); 240 241 mResources = spy(base.getResources()); 242 when(mResources.getStringArray(com.android.internal.R.array.networkAttributes)). 243 thenReturn(new String[] { 244 "wifi,1,1,1,-1,true", 245 "mobile,0,0,0,-1,true", 246 "mobile_mms,2,0,2,60000,true", 247 }); 248 249 mContentResolver = new MockContentResolver(); 250 mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider()); 251 } 252 253 @Override 254 public void startActivityAsUser(Intent intent, UserHandle handle) { 255 mStartedActivities.offer(intent); 256 } 257 258 public Intent expectStartActivityIntent(int timeoutMs) { 259 Intent intent = null; 260 try { 261 intent = mStartedActivities.poll(timeoutMs, TimeUnit.MILLISECONDS); 262 } catch (InterruptedException e) {} 263 assertNotNull("Did not receive sign-in intent after " + timeoutMs + "ms", intent); 264 return intent; 265 } 266 267 public void expectNoStartActivityIntent(int timeoutMs) { 268 try { 269 assertNull("Received unexpected Intent to start activity", 270 mStartedActivities.poll(timeoutMs, TimeUnit.MILLISECONDS)); 271 } catch (InterruptedException e) {} 272 } 273 274 @Override 275 public Object getSystemService(String name) { 276 if (Context.CONNECTIVITY_SERVICE.equals(name)) return mCm; 277 if (Context.NOTIFICATION_SERVICE.equals(name)) return mock(NotificationManager.class); 278 return super.getSystemService(name); 279 } 280 281 @Override 282 public ContentResolver getContentResolver() { 283 return mContentResolver; 284 } 285 286 @Override 287 public Resources getResources() { 288 return mResources; 289 } 290 } 291 292 public void waitForIdle(int timeoutMsAsInt) { 293 long timeoutMs = timeoutMsAsInt; 294 waitForIdleHandler(mService.mHandlerThread, timeoutMs); 295 waitForIdle(mCellNetworkAgent, timeoutMs); 296 waitForIdle(mWiFiNetworkAgent, timeoutMs); 297 waitForIdle(mEthernetNetworkAgent, timeoutMs); 298 waitForIdleHandler(mService.mHandlerThread, timeoutMs); 299 waitForIdleLooper(ConnectivityThread.getInstanceLooper(), timeoutMs); 300 } 301 302 public void waitForIdle(MockNetworkAgent agent, long timeoutMs) { 303 if (agent == null) { 304 return; 305 } 306 waitForIdleHandler(agent.mHandlerThread, timeoutMs); 307 } 308 309 private void waitForIdle() { 310 waitForIdle(TIMEOUT_MS); 311 } 312 313 @Test 314 public void testWaitForIdle() { 315 final int attempts = 50; // Causes the test to take about 200ms on bullhead-eng. 316 317 // Tests that waitForIdle returns immediately if the service is already idle. 318 for (int i = 0; i < attempts; i++) { 319 waitForIdle(); 320 } 321 322 // Bring up a network that we can use to send messages to ConnectivityService. 323 ConditionVariable cv = waitForConnectivityBroadcasts(1); 324 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 325 mWiFiNetworkAgent.connect(false); 326 waitFor(cv); 327 Network n = mWiFiNetworkAgent.getNetwork(); 328 assertNotNull(n); 329 330 // Tests that calling waitForIdle waits for messages to be processed. 331 for (int i = 0; i < attempts; i++) { 332 mWiFiNetworkAgent.setSignalStrength(i); 333 waitForIdle(); 334 assertEquals(i, mCm.getNetworkCapabilities(n).getSignalStrength()); 335 } 336 } 337 338 // This test has an inherent race condition in it, and cannot be enabled for continuous testing 339 // or presubmit tests. It is kept for manual runs and documentation purposes. 340 @Ignore 341 public void verifyThatNotWaitingForIdleCausesRaceConditions() { 342 // Bring up a network that we can use to send messages to ConnectivityService. 343 ConditionVariable cv = waitForConnectivityBroadcasts(1); 344 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 345 mWiFiNetworkAgent.connect(false); 346 waitFor(cv); 347 Network n = mWiFiNetworkAgent.getNetwork(); 348 assertNotNull(n); 349 350 // Ensure that not calling waitForIdle causes a race condition. 351 final int attempts = 50; // Causes the test to take about 200ms on bullhead-eng. 352 for (int i = 0; i < attempts; i++) { 353 mWiFiNetworkAgent.setSignalStrength(i); 354 if (i != mCm.getNetworkCapabilities(n).getSignalStrength()) { 355 // We hit a race condition, as expected. Pass the test. 356 return; 357 } 358 } 359 360 // No race? There is a bug in this test. 361 fail("expected race condition at least once in " + attempts + " attempts"); 362 } 363 364 private class MockNetworkAgent { 365 private final WrappedNetworkMonitor mWrappedNetworkMonitor; 366 private final NetworkInfo mNetworkInfo; 367 private final NetworkCapabilities mNetworkCapabilities; 368 private final HandlerThread mHandlerThread; 369 private final ConditionVariable mDisconnected = new ConditionVariable(); 370 private final ConditionVariable mNetworkStatusReceived = new ConditionVariable(); 371 private final ConditionVariable mPreventReconnectReceived = new ConditionVariable(); 372 private int mScore; 373 private NetworkAgent mNetworkAgent; 374 private int mStartKeepaliveError = PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED; 375 private int mStopKeepaliveError = PacketKeepalive.NO_KEEPALIVE; 376 private Integer mExpectedKeepaliveSlot = null; 377 // Contains the redirectUrl from networkStatus(). Before reading, wait for 378 // mNetworkStatusReceived. 379 private String mRedirectUrl; 380 381 MockNetworkAgent(int transport) { 382 this(transport, new LinkProperties()); 383 } 384 385 MockNetworkAgent(int transport, LinkProperties linkProperties) { 386 final int type = transportToLegacyType(transport); 387 final String typeName = ConnectivityManager.getNetworkTypeName(transport); 388 mNetworkInfo = new NetworkInfo(type, 0, typeName, "Mock"); 389 mNetworkCapabilities = new NetworkCapabilities(); 390 mNetworkCapabilities.addTransportType(transport); 391 switch (transport) { 392 case TRANSPORT_ETHERNET: 393 mScore = 70; 394 break; 395 case TRANSPORT_WIFI: 396 mScore = 60; 397 break; 398 case TRANSPORT_CELLULAR: 399 mScore = 50; 400 break; 401 case TRANSPORT_WIFI_AWARE: 402 mScore = 20; 403 break; 404 case TRANSPORT_VPN: 405 mNetworkCapabilities.removeCapability(NET_CAPABILITY_NOT_VPN); 406 mScore = ConnectivityConstants.VPN_DEFAULT_SCORE; 407 break; 408 default: 409 throw new UnsupportedOperationException("unimplemented network type"); 410 } 411 mHandlerThread = new HandlerThread("Mock-" + typeName); 412 mHandlerThread.start(); 413 mNetworkAgent = new NetworkAgent(mHandlerThread.getLooper(), mServiceContext, 414 "Mock-" + typeName, mNetworkInfo, mNetworkCapabilities, 415 linkProperties, mScore, new NetworkMisc()) { 416 @Override 417 public void unwanted() { mDisconnected.open(); } 418 419 @Override 420 public void startPacketKeepalive(Message msg) { 421 int slot = msg.arg1; 422 if (mExpectedKeepaliveSlot != null) { 423 assertEquals((int) mExpectedKeepaliveSlot, slot); 424 } 425 onPacketKeepaliveEvent(slot, mStartKeepaliveError); 426 } 427 428 @Override 429 public void stopPacketKeepalive(Message msg) { 430 onPacketKeepaliveEvent(msg.arg1, mStopKeepaliveError); 431 } 432 433 @Override 434 public void networkStatus(int status, String redirectUrl) { 435 mRedirectUrl = redirectUrl; 436 mNetworkStatusReceived.open(); 437 } 438 439 @Override 440 protected void preventAutomaticReconnect() { 441 mPreventReconnectReceived.open(); 442 } 443 }; 444 // Waits for the NetworkAgent to be registered, which includes the creation of the 445 // NetworkMonitor. 446 waitForIdle(); 447 mWrappedNetworkMonitor = mService.getLastCreatedWrappedNetworkMonitor(); 448 } 449 450 public void adjustScore(int change) { 451 mScore += change; 452 mNetworkAgent.sendNetworkScore(mScore); 453 } 454 455 public void explicitlySelected(boolean acceptUnvalidated) { 456 mNetworkAgent.explicitlySelected(acceptUnvalidated); 457 } 458 459 public void addCapability(int capability) { 460 mNetworkCapabilities.addCapability(capability); 461 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities); 462 } 463 464 public void removeCapability(int capability) { 465 mNetworkCapabilities.removeCapability(capability); 466 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities); 467 } 468 469 public void setUids(Set<UidRange> uids) { 470 mNetworkCapabilities.setUids(uids); 471 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities); 472 } 473 474 public void setSignalStrength(int signalStrength) { 475 mNetworkCapabilities.setSignalStrength(signalStrength); 476 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities); 477 } 478 479 public void setNetworkSpecifier(NetworkSpecifier networkSpecifier) { 480 mNetworkCapabilities.setNetworkSpecifier(networkSpecifier); 481 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities); 482 } 483 484 public void setNetworkCapabilities(NetworkCapabilities nc, 485 boolean sendToConnectivityService) { 486 mNetworkCapabilities.set(nc); 487 if (sendToConnectivityService) { 488 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities); 489 } 490 } 491 492 public void connectWithoutInternet() { 493 mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, null); 494 mNetworkAgent.sendNetworkInfo(mNetworkInfo); 495 } 496 497 /** 498 * Transition this NetworkAgent to CONNECTED state with NET_CAPABILITY_INTERNET. 499 * @param validated Indicate if network should pretend to be validated. 500 */ 501 public void connect(boolean validated) { 502 connect(validated, true); 503 } 504 505 /** 506 * Transition this NetworkAgent to CONNECTED state. 507 * @param validated Indicate if network should pretend to be validated. 508 * @param hasInternet Indicate if network should pretend to have NET_CAPABILITY_INTERNET. 509 */ 510 public void connect(boolean validated, boolean hasInternet) { 511 assertEquals("MockNetworkAgents can only be connected once", 512 mNetworkInfo.getDetailedState(), DetailedState.IDLE); 513 assertFalse(mNetworkCapabilities.hasCapability(NET_CAPABILITY_INTERNET)); 514 515 NetworkCallback callback = null; 516 final ConditionVariable validatedCv = new ConditionVariable(); 517 if (validated) { 518 mWrappedNetworkMonitor.gen204ProbeResult = 204; 519 NetworkRequest request = new NetworkRequest.Builder() 520 .addTransportType(mNetworkCapabilities.getTransportTypes()[0]) 521 .clearCapabilities() 522 .build(); 523 callback = new NetworkCallback() { 524 public void onCapabilitiesChanged(Network network, 525 NetworkCapabilities networkCapabilities) { 526 if (network.equals(getNetwork()) && 527 networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED)) { 528 validatedCv.open(); 529 } 530 } 531 }; 532 mCm.registerNetworkCallback(request, callback); 533 } 534 if (hasInternet) { 535 addCapability(NET_CAPABILITY_INTERNET); 536 } 537 538 connectWithoutInternet(); 539 540 if (validated) { 541 // Wait for network to validate. 542 waitFor(validatedCv); 543 mWrappedNetworkMonitor.gen204ProbeResult = 500; 544 } 545 546 if (callback != null) mCm.unregisterNetworkCallback(callback); 547 } 548 549 public void connectWithCaptivePortal(String redirectUrl) { 550 mWrappedNetworkMonitor.gen204ProbeResult = 200; 551 mWrappedNetworkMonitor.gen204ProbeRedirectUrl = redirectUrl; 552 connect(false); 553 } 554 555 public void suspend() { 556 mNetworkInfo.setDetailedState(DetailedState.SUSPENDED, null, null); 557 mNetworkAgent.sendNetworkInfo(mNetworkInfo); 558 } 559 560 public void resume() { 561 mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, null); 562 mNetworkAgent.sendNetworkInfo(mNetworkInfo); 563 } 564 565 public void disconnect() { 566 mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, null); 567 mNetworkAgent.sendNetworkInfo(mNetworkInfo); 568 } 569 570 public Network getNetwork() { 571 return new Network(mNetworkAgent.netId); 572 } 573 574 public ConditionVariable getPreventReconnectReceived() { 575 return mPreventReconnectReceived; 576 } 577 578 public ConditionVariable getDisconnectedCV() { 579 return mDisconnected; 580 } 581 582 public WrappedNetworkMonitor getWrappedNetworkMonitor() { 583 return mWrappedNetworkMonitor; 584 } 585 586 public void sendLinkProperties(LinkProperties lp) { 587 mNetworkAgent.sendLinkProperties(lp); 588 } 589 590 public void setStartKeepaliveError(int error) { 591 mStartKeepaliveError = error; 592 } 593 594 public void setStopKeepaliveError(int error) { 595 mStopKeepaliveError = error; 596 } 597 598 public void setExpectedKeepaliveSlot(Integer slot) { 599 mExpectedKeepaliveSlot = slot; 600 } 601 602 public String waitForRedirectUrl() { 603 assertTrue(mNetworkStatusReceived.block(TIMEOUT_MS)); 604 return mRedirectUrl; 605 } 606 607 public NetworkAgent getNetworkAgent() { 608 return mNetworkAgent; 609 } 610 611 public NetworkCapabilities getNetworkCapabilities() { 612 return mNetworkCapabilities; 613 } 614 } 615 616 /** 617 * A NetworkFactory that allows tests to wait until any in-flight NetworkRequest add or remove 618 * operations have been processed. Before ConnectivityService can add or remove any requests, 619 * the factory must be told to expect those operations by calling expectAddRequests or 620 * expectRemoveRequests. 621 */ 622 private static class MockNetworkFactory extends NetworkFactory { 623 private final ConditionVariable mNetworkStartedCV = new ConditionVariable(); 624 private final ConditionVariable mNetworkStoppedCV = new ConditionVariable(); 625 private final AtomicBoolean mNetworkStarted = new AtomicBoolean(false); 626 627 // Used to expect that requests be removed or added on a separate thread, without sleeping. 628 // Callers can call either expectAddRequests() or expectRemoveRequests() exactly once, then 629 // cause some other thread to add or remove requests, then call waitForRequests(). We can 630 // either expect requests to be added or removed, but not both, because CountDownLatch can 631 // only count in one direction. 632 private CountDownLatch mExpectations; 633 634 // Whether we are currently expecting requests to be added or removed. Valid only if 635 // mExpectations is non-null. 636 private boolean mExpectingAdditions; 637 638 public MockNetworkFactory(Looper looper, Context context, String logTag, 639 NetworkCapabilities filter) { 640 super(looper, context, logTag, filter); 641 } 642 643 public int getMyRequestCount() { 644 return getRequestCount(); 645 } 646 647 protected void startNetwork() { 648 mNetworkStarted.set(true); 649 mNetworkStartedCV.open(); 650 } 651 652 protected void stopNetwork() { 653 mNetworkStarted.set(false); 654 mNetworkStoppedCV.open(); 655 } 656 657 public boolean getMyStartRequested() { 658 return mNetworkStarted.get(); 659 } 660 661 public ConditionVariable getNetworkStartedCV() { 662 mNetworkStartedCV.close(); 663 return mNetworkStartedCV; 664 } 665 666 public ConditionVariable getNetworkStoppedCV() { 667 mNetworkStoppedCV.close(); 668 return mNetworkStoppedCV; 669 } 670 671 @Override 672 protected void handleAddRequest(NetworkRequest request, int score) { 673 // If we're expecting anything, we must be expecting additions. 674 if (mExpectations != null && !mExpectingAdditions) { 675 fail("Can't add requests while expecting requests to be removed"); 676 } 677 678 // Add the request. 679 super.handleAddRequest(request, score); 680 681 // Reduce the number of request additions we're waiting for. 682 if (mExpectingAdditions) { 683 assertTrue("Added more requests than expected", mExpectations.getCount() > 0); 684 mExpectations.countDown(); 685 } 686 } 687 688 @Override 689 protected void handleRemoveRequest(NetworkRequest request) { 690 // If we're expecting anything, we must be expecting removals. 691 if (mExpectations != null && mExpectingAdditions) { 692 fail("Can't remove requests while expecting requests to be added"); 693 } 694 695 // Remove the request. 696 super.handleRemoveRequest(request); 697 698 // Reduce the number of request removals we're waiting for. 699 if (!mExpectingAdditions) { 700 assertTrue("Removed more requests than expected", mExpectations.getCount() > 0); 701 mExpectations.countDown(); 702 } 703 } 704 705 private void assertNoExpectations() { 706 if (mExpectations != null) { 707 fail("Can't add expectation, " + mExpectations.getCount() + " already pending"); 708 } 709 } 710 711 // Expects that count requests will be added. 712 public void expectAddRequests(final int count) { 713 assertNoExpectations(); 714 mExpectingAdditions = true; 715 mExpectations = new CountDownLatch(count); 716 } 717 718 // Expects that count requests will be removed. 719 public void expectRemoveRequests(final int count) { 720 assertNoExpectations(); 721 mExpectingAdditions = false; 722 mExpectations = new CountDownLatch(count); 723 } 724 725 // Waits for the expected request additions or removals to happen within a timeout. 726 public void waitForRequests() throws InterruptedException { 727 assertNotNull("Nothing to wait for", mExpectations); 728 mExpectations.await(TIMEOUT_MS, TimeUnit.MILLISECONDS); 729 final long count = mExpectations.getCount(); 730 final String msg = count + " requests still not " + 731 (mExpectingAdditions ? "added" : "removed") + 732 " after " + TIMEOUT_MS + " ms"; 733 assertEquals(msg, 0, count); 734 mExpectations = null; 735 } 736 737 public void waitForNetworkRequests(final int count) throws InterruptedException { 738 waitForRequests(); 739 assertEquals(count, getMyRequestCount()); 740 } 741 } 742 743 private static Looper startHandlerThreadAndReturnLooper() { 744 final HandlerThread handlerThread = new HandlerThread("MockVpnThread"); 745 handlerThread.start(); 746 return handlerThread.getLooper(); 747 } 748 749 private class MockVpn extends Vpn { 750 // TODO : the interactions between this mock and the mock network agent are too 751 // hard to get right at this moment, because it's unclear in which case which 752 // target needs to get a method call or both, and in what order. It's because 753 // MockNetworkAgent wants to manage its own NetworkCapabilities, but the Vpn 754 // parent class of MockVpn agent wants that responsibility. 755 // That being said inside the test it should be possible to make the interactions 756 // harder to get wrong with precise speccing, judicious comments, helper methods 757 // and a few sprinkled assertions. 758 759 private boolean mConnected = false; 760 // Careful ! This is different from mNetworkAgent, because MockNetworkAgent does 761 // not inherit from NetworkAgent. 762 private MockNetworkAgent mMockNetworkAgent; 763 764 public MockVpn(int userId) { 765 super(startHandlerThreadAndReturnLooper(), mServiceContext, mNetworkManagementService, 766 userId); 767 } 768 769 public void setNetworkAgent(MockNetworkAgent agent) { 770 waitForIdle(agent, TIMEOUT_MS); 771 mMockNetworkAgent = agent; 772 mNetworkAgent = agent.getNetworkAgent(); 773 mNetworkCapabilities.set(agent.getNetworkCapabilities()); 774 } 775 776 public void setUids(Set<UidRange> uids) { 777 mNetworkCapabilities.setUids(uids); 778 updateCapabilities(); 779 } 780 781 @Override 782 public int getNetId() { 783 return mMockNetworkAgent.getNetwork().netId; 784 } 785 786 @Override 787 public boolean appliesToUid(int uid) { 788 return mConnected; // Trickery to simplify testing. 789 } 790 791 @Override 792 protected boolean isCallerEstablishedOwnerLocked() { 793 return mConnected; // Similar trickery 794 } 795 796 public void connect() { 797 mNetworkCapabilities.set(mMockNetworkAgent.getNetworkCapabilities()); 798 mConnected = true; 799 mConfig = new VpnConfig(); 800 } 801 802 @Override 803 public void updateCapabilities() { 804 if (!mConnected) return; 805 super.updateCapabilities(); 806 // Because super.updateCapabilities will update the capabilities of the agent but not 807 // the mock agent, the mock agent needs to know about them. 808 copyCapabilitiesToNetworkAgent(); 809 } 810 811 private void copyCapabilitiesToNetworkAgent() { 812 if (null != mMockNetworkAgent) { 813 mMockNetworkAgent.setNetworkCapabilities(mNetworkCapabilities, 814 false /* sendToConnectivityService */); 815 } 816 } 817 818 public void disconnect() { 819 mConnected = false; 820 mConfig = null; 821 } 822 } 823 824 private class FakeWakeupMessage extends WakeupMessage { 825 private static final int UNREASONABLY_LONG_WAIT = 1000; 826 827 public FakeWakeupMessage(Context context, Handler handler, String cmdName, int cmd) { 828 super(context, handler, cmdName, cmd); 829 } 830 831 public FakeWakeupMessage(Context context, Handler handler, String cmdName, int cmd, 832 int arg1, int arg2, Object obj) { 833 super(context, handler, cmdName, cmd, arg1, arg2, obj); 834 } 835 836 @Override 837 public void schedule(long when) { 838 long delayMs = when - SystemClock.elapsedRealtime(); 839 if (delayMs < 0) delayMs = 0; 840 if (delayMs > UNREASONABLY_LONG_WAIT) { 841 fail("Attempting to send msg more than " + UNREASONABLY_LONG_WAIT + 842 "ms into the future: " + delayMs); 843 } 844 Message msg = mHandler.obtainMessage(mCmd, mArg1, mArg2, mObj); 845 mHandler.sendMessageDelayed(msg, delayMs); 846 } 847 848 @Override 849 public void cancel() { 850 mHandler.removeMessages(mCmd, mObj); 851 } 852 853 @Override 854 public void onAlarm() { 855 throw new AssertionError("Should never happen. Update this fake."); 856 } 857 } 858 859 // NetworkMonitor implementation allowing overriding of Internet connectivity probe result. 860 private class WrappedNetworkMonitor extends NetworkMonitor { 861 public final Handler connectivityHandler; 862 // HTTP response code fed back to NetworkMonitor for Internet connectivity probe. 863 public int gen204ProbeResult = 500; 864 public String gen204ProbeRedirectUrl = null; 865 866 public WrappedNetworkMonitor(Context context, Handler handler, 867 NetworkAgentInfo networkAgentInfo, NetworkRequest defaultRequest, 868 IpConnectivityLog log) { 869 super(context, handler, networkAgentInfo, defaultRequest, log, 870 NetworkMonitor.NetworkMonitorSettings.DEFAULT); 871 connectivityHandler = handler; 872 } 873 874 @Override 875 protected CaptivePortalProbeResult isCaptivePortal() { 876 if (!mIsCaptivePortalCheckEnabled) { return new CaptivePortalProbeResult(204); } 877 return new CaptivePortalProbeResult(gen204ProbeResult, gen204ProbeRedirectUrl, null); 878 } 879 } 880 881 private class WrappedMultinetworkPolicyTracker extends MultinetworkPolicyTracker { 882 public volatile boolean configRestrictsAvoidBadWifi; 883 public volatile int configMeteredMultipathPreference; 884 885 public WrappedMultinetworkPolicyTracker(Context c, Handler h, Runnable r) { 886 super(c, h, r); 887 } 888 889 @Override 890 public boolean configRestrictsAvoidBadWifi() { 891 return configRestrictsAvoidBadWifi; 892 } 893 894 @Override 895 public int configMeteredMultipathPreference() { 896 return configMeteredMultipathPreference; 897 } 898 } 899 900 private class WrappedConnectivityService extends ConnectivityService { 901 public WrappedMultinetworkPolicyTracker wrappedMultinetworkPolicyTracker; 902 private WrappedNetworkMonitor mLastCreatedNetworkMonitor; 903 private MockableSystemProperties mSystemProperties; 904 905 public WrappedConnectivityService(Context context, INetworkManagementService netManager, 906 INetworkStatsService statsService, INetworkPolicyManager policyManager, 907 IpConnectivityLog log) { 908 super(context, netManager, statsService, policyManager, log); 909 mLingerDelayMs = TEST_LINGER_DELAY_MS; 910 } 911 912 @Override 913 protected MockableSystemProperties getSystemProperties() { 914 // Minimal approach to overriding system properties: let most calls fall through to real 915 // device values, and only override ones values that are important to this test. 916 mSystemProperties = spy(new MockableSystemProperties()); 917 when(mSystemProperties.getInt("net.tcp.default_init_rwnd", 0)).thenReturn(0); 918 when(mSystemProperties.getBoolean("ro.radio.noril", false)).thenReturn(false); 919 return mSystemProperties; 920 } 921 922 @Override 923 protected int reserveNetId() { 924 while (true) { 925 final int netId = super.reserveNetId(); 926 927 // Don't overlap test NetIDs with real NetIDs as binding sockets to real networks 928 // can have odd side-effects, like network validations succeeding. 929 Context context = InstrumentationRegistry.getContext(); 930 final Network[] networks = ConnectivityManager.from(context).getAllNetworks(); 931 boolean overlaps = false; 932 for (Network network : networks) { 933 if (netId == network.netId) { 934 overlaps = true; 935 break; 936 } 937 } 938 if (overlaps) continue; 939 940 return netId; 941 } 942 } 943 944 @Override 945 public NetworkMonitor createNetworkMonitor(Context context, Handler handler, 946 NetworkAgentInfo nai, NetworkRequest defaultRequest) { 947 final WrappedNetworkMonitor monitor = new WrappedNetworkMonitor( 948 context, handler, nai, defaultRequest, mock(IpConnectivityLog.class)); 949 mLastCreatedNetworkMonitor = monitor; 950 return monitor; 951 } 952 953 @Override 954 public MultinetworkPolicyTracker createMultinetworkPolicyTracker( 955 Context c, Handler h, Runnable r) { 956 final WrappedMultinetworkPolicyTracker tracker = new WrappedMultinetworkPolicyTracker(c, h, r); 957 return tracker; 958 } 959 960 public WrappedMultinetworkPolicyTracker getMultinetworkPolicyTracker() { 961 return (WrappedMultinetworkPolicyTracker) mMultinetworkPolicyTracker; 962 } 963 964 @Override 965 public WakeupMessage makeWakeupMessage( 966 Context context, Handler handler, String cmdName, int cmd, Object obj) { 967 return new FakeWakeupMessage(context, handler, cmdName, cmd, 0, 0, obj); 968 } 969 970 @Override 971 public boolean hasService(String name) { 972 // Currenty, the only relevant service that ConnectivityService checks for is 973 // ETHERNET_SERVICE. 974 return Context.ETHERNET_SERVICE.equals(name); 975 } 976 977 @Override 978 protected IpConnectivityMetrics.Logger metricsLogger() { 979 return mMetricsService; 980 } 981 982 @Override 983 protected void registerNetdEventCallback() { 984 } 985 986 public WrappedNetworkMonitor getLastCreatedWrappedNetworkMonitor() { 987 return mLastCreatedNetworkMonitor; 988 } 989 990 public void mockVpn(int uid) { 991 synchronized (mVpns) { 992 int userId = UserHandle.getUserId(uid); 993 mMockVpn = new MockVpn(userId); 994 // This has no effect unless the VPN is actually connected, because things like 995 // getActiveNetworkForUidInternal call getNetworkAgentInfoForNetId on the VPN 996 // netId, and check if that network is actually connected. 997 mVpns.put(userId, mMockVpn); 998 } 999 } 1000 1001 public void waitForIdle(int timeoutMs) { 1002 waitForIdleHandler(mHandlerThread, timeoutMs); 1003 } 1004 1005 public void waitForIdle() { 1006 waitForIdle(TIMEOUT_MS); 1007 } 1008 } 1009 1010 /** 1011 * Wait up to TIMEOUT_MS for {@code conditionVariable} to open. 1012 * Fails if TIMEOUT_MS goes by before {@code conditionVariable} opens. 1013 */ 1014 static private void waitFor(ConditionVariable conditionVariable) { 1015 if (conditionVariable.block(TIMEOUT_MS)) { 1016 return; 1017 } 1018 fail("ConditionVariable was blocked for more than " + TIMEOUT_MS + "ms"); 1019 } 1020 1021 @Before 1022 public void setUp() throws Exception { 1023 mContext = InstrumentationRegistry.getContext(); 1024 1025 MockitoAnnotations.initMocks(this); 1026 when(mMetricsService.defaultNetworkMetrics()).thenReturn(mDefaultNetworkMetrics); 1027 1028 // InstrumentationTestRunner prepares a looper, but AndroidJUnitRunner does not. 1029 // http://b/25897652 . 1030 if (Looper.myLooper() == null) { 1031 Looper.prepare(); 1032 } 1033 1034 mServiceContext = new MockContext(InstrumentationRegistry.getContext()); 1035 LocalServices.removeServiceForTest(NetworkPolicyManagerInternal.class); 1036 LocalServices.addService( 1037 NetworkPolicyManagerInternal.class, mock(NetworkPolicyManagerInternal.class)); 1038 mService = new WrappedConnectivityService(mServiceContext, 1039 mNetworkManagementService, 1040 mStatsService, 1041 mock(INetworkPolicyManager.class), 1042 mock(IpConnectivityLog.class)); 1043 1044 // Create local CM before sending system ready so that we can answer 1045 // getSystemService() correctly. 1046 mCm = new WrappedConnectivityManager(InstrumentationRegistry.getContext(), mService); 1047 mService.systemReady(); 1048 mService.mockVpn(Process.myUid()); 1049 mCm.bindProcessToNetwork(null); 1050 1051 // Ensure that the default setting for Captive Portals is used for most tests 1052 setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_PROMPT); 1053 setMobileDataAlwaysOn(false); 1054 setPrivateDnsSettings(PRIVATE_DNS_MODE_OFF, "ignored.example.com"); 1055 } 1056 1057 @After 1058 public void tearDown() throws Exception { 1059 setMobileDataAlwaysOn(false); 1060 if (mCellNetworkAgent != null) { 1061 mCellNetworkAgent.disconnect(); 1062 mCellNetworkAgent = null; 1063 } 1064 if (mWiFiNetworkAgent != null) { 1065 mWiFiNetworkAgent.disconnect(); 1066 mWiFiNetworkAgent = null; 1067 } 1068 if (mEthernetNetworkAgent != null) { 1069 mEthernetNetworkAgent.disconnect(); 1070 mEthernetNetworkAgent = null; 1071 } 1072 } 1073 1074 private static int transportToLegacyType(int transport) { 1075 switch (transport) { 1076 case TRANSPORT_ETHERNET: 1077 return TYPE_ETHERNET; 1078 case TRANSPORT_WIFI: 1079 return TYPE_WIFI; 1080 case TRANSPORT_CELLULAR: 1081 return TYPE_MOBILE; 1082 default: 1083 return TYPE_NONE; 1084 } 1085 } 1086 1087 private void verifyActiveNetwork(int transport) { 1088 // Test getActiveNetworkInfo() 1089 assertNotNull(mCm.getActiveNetworkInfo()); 1090 assertEquals(transportToLegacyType(transport), mCm.getActiveNetworkInfo().getType()); 1091 // Test getActiveNetwork() 1092 assertNotNull(mCm.getActiveNetwork()); 1093 assertEquals(mCm.getActiveNetwork(), mCm.getActiveNetworkForUid(Process.myUid())); 1094 if (!NetworkCapabilities.isValidTransport(transport)) { 1095 throw new IllegalStateException("Unknown transport " + transport); 1096 } 1097 switch (transport) { 1098 case TRANSPORT_WIFI: 1099 assertEquals(mCm.getActiveNetwork(), mWiFiNetworkAgent.getNetwork()); 1100 break; 1101 case TRANSPORT_CELLULAR: 1102 assertEquals(mCm.getActiveNetwork(), mCellNetworkAgent.getNetwork()); 1103 break; 1104 default: 1105 break; 1106 } 1107 // Test getNetworkInfo(Network) 1108 assertNotNull(mCm.getNetworkInfo(mCm.getActiveNetwork())); 1109 assertEquals(transportToLegacyType(transport), 1110 mCm.getNetworkInfo(mCm.getActiveNetwork()).getType()); 1111 // Test getNetworkCapabilities(Network) 1112 assertNotNull(mCm.getNetworkCapabilities(mCm.getActiveNetwork())); 1113 assertTrue(mCm.getNetworkCapabilities(mCm.getActiveNetwork()).hasTransport(transport)); 1114 } 1115 1116 private void verifyNoNetwork() { 1117 waitForIdle(); 1118 // Test getActiveNetworkInfo() 1119 assertNull(mCm.getActiveNetworkInfo()); 1120 // Test getActiveNetwork() 1121 assertNull(mCm.getActiveNetwork()); 1122 assertNull(mCm.getActiveNetworkForUid(Process.myUid())); 1123 // Test getAllNetworks() 1124 assertEmpty(mCm.getAllNetworks()); 1125 } 1126 1127 /** 1128 * Return a ConditionVariable that opens when {@code count} numbers of CONNECTIVITY_ACTION 1129 * broadcasts are received. 1130 */ 1131 private ConditionVariable waitForConnectivityBroadcasts(final int count) { 1132 final ConditionVariable cv = new ConditionVariable(); 1133 mServiceContext.registerReceiver(new BroadcastReceiver() { 1134 private int remaining = count; 1135 public void onReceive(Context context, Intent intent) { 1136 if (--remaining == 0) { 1137 cv.open(); 1138 mServiceContext.unregisterReceiver(this); 1139 } 1140 } 1141 }, new IntentFilter(CONNECTIVITY_ACTION)); 1142 return cv; 1143 } 1144 1145 @Test 1146 public void testNetworkTypes() { 1147 // Ensure that our mocks for the networkAttributes config variable work as expected. If they 1148 // don't, then tests that depend on CONNECTIVITY_ACTION broadcasts for these network types 1149 // will fail. Failing here is much easier to debug. 1150 assertTrue(mCm.isNetworkSupported(TYPE_WIFI)); 1151 assertTrue(mCm.isNetworkSupported(TYPE_MOBILE)); 1152 assertTrue(mCm.isNetworkSupported(TYPE_MOBILE_MMS)); 1153 assertFalse(mCm.isNetworkSupported(TYPE_MOBILE_FOTA)); 1154 1155 // Check that TYPE_ETHERNET is supported. Unlike the asserts above, which only validate our 1156 // mocks, this assert exercises the ConnectivityService code path that ensures that 1157 // TYPE_ETHERNET is supported if the ethernet service is running. 1158 assertTrue(mCm.isNetworkSupported(TYPE_ETHERNET)); 1159 } 1160 1161 @Test 1162 public void testLingering() throws Exception { 1163 verifyNoNetwork(); 1164 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); 1165 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 1166 assertNull(mCm.getActiveNetworkInfo()); 1167 assertNull(mCm.getActiveNetwork()); 1168 // Test bringing up validated cellular. 1169 ConditionVariable cv = waitForConnectivityBroadcasts(1); 1170 mCellNetworkAgent.connect(true); 1171 waitFor(cv); 1172 verifyActiveNetwork(TRANSPORT_CELLULAR); 1173 assertLength(2, mCm.getAllNetworks()); 1174 assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) || 1175 mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork())); 1176 assertTrue(mCm.getAllNetworks()[0].equals(mWiFiNetworkAgent.getNetwork()) || 1177 mCm.getAllNetworks()[1].equals(mWiFiNetworkAgent.getNetwork())); 1178 // Test bringing up validated WiFi. 1179 cv = waitForConnectivityBroadcasts(2); 1180 mWiFiNetworkAgent.connect(true); 1181 waitFor(cv); 1182 verifyActiveNetwork(TRANSPORT_WIFI); 1183 assertLength(2, mCm.getAllNetworks()); 1184 assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) || 1185 mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork())); 1186 assertTrue(mCm.getAllNetworks()[0].equals(mCellNetworkAgent.getNetwork()) || 1187 mCm.getAllNetworks()[1].equals(mCellNetworkAgent.getNetwork())); 1188 // Test cellular linger timeout. 1189 waitFor(mCellNetworkAgent.getDisconnectedCV()); 1190 waitForIdle(); 1191 assertLength(1, mCm.getAllNetworks()); 1192 verifyActiveNetwork(TRANSPORT_WIFI); 1193 assertLength(1, mCm.getAllNetworks()); 1194 assertEquals(mCm.getAllNetworks()[0], mCm.getActiveNetwork()); 1195 // Test WiFi disconnect. 1196 cv = waitForConnectivityBroadcasts(1); 1197 mWiFiNetworkAgent.disconnect(); 1198 waitFor(cv); 1199 verifyNoNetwork(); 1200 } 1201 1202 @Test 1203 public void testValidatedCellularOutscoresUnvalidatedWiFi() throws Exception { 1204 // Test bringing up unvalidated WiFi 1205 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 1206 ConditionVariable cv = waitForConnectivityBroadcasts(1); 1207 mWiFiNetworkAgent.connect(false); 1208 waitFor(cv); 1209 verifyActiveNetwork(TRANSPORT_WIFI); 1210 // Test bringing up unvalidated cellular 1211 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); 1212 mCellNetworkAgent.connect(false); 1213 waitForIdle(); 1214 verifyActiveNetwork(TRANSPORT_WIFI); 1215 // Test cellular disconnect. 1216 mCellNetworkAgent.disconnect(); 1217 waitForIdle(); 1218 verifyActiveNetwork(TRANSPORT_WIFI); 1219 // Test bringing up validated cellular 1220 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); 1221 cv = waitForConnectivityBroadcasts(2); 1222 mCellNetworkAgent.connect(true); 1223 waitFor(cv); 1224 verifyActiveNetwork(TRANSPORT_CELLULAR); 1225 // Test cellular disconnect. 1226 cv = waitForConnectivityBroadcasts(2); 1227 mCellNetworkAgent.disconnect(); 1228 waitFor(cv); 1229 verifyActiveNetwork(TRANSPORT_WIFI); 1230 // Test WiFi disconnect. 1231 cv = waitForConnectivityBroadcasts(1); 1232 mWiFiNetworkAgent.disconnect(); 1233 waitFor(cv); 1234 verifyNoNetwork(); 1235 } 1236 1237 @Test 1238 public void testUnvalidatedWifiOutscoresUnvalidatedCellular() throws Exception { 1239 // Test bringing up unvalidated cellular. 1240 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); 1241 ConditionVariable cv = waitForConnectivityBroadcasts(1); 1242 mCellNetworkAgent.connect(false); 1243 waitFor(cv); 1244 verifyActiveNetwork(TRANSPORT_CELLULAR); 1245 // Test bringing up unvalidated WiFi. 1246 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 1247 cv = waitForConnectivityBroadcasts(2); 1248 mWiFiNetworkAgent.connect(false); 1249 waitFor(cv); 1250 verifyActiveNetwork(TRANSPORT_WIFI); 1251 // Test WiFi disconnect. 1252 cv = waitForConnectivityBroadcasts(2); 1253 mWiFiNetworkAgent.disconnect(); 1254 waitFor(cv); 1255 verifyActiveNetwork(TRANSPORT_CELLULAR); 1256 // Test cellular disconnect. 1257 cv = waitForConnectivityBroadcasts(1); 1258 mCellNetworkAgent.disconnect(); 1259 waitFor(cv); 1260 verifyNoNetwork(); 1261 } 1262 1263 @Test 1264 public void testUnlingeringDoesNotValidate() throws Exception { 1265 // Test bringing up unvalidated WiFi. 1266 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 1267 ConditionVariable cv = waitForConnectivityBroadcasts(1); 1268 mWiFiNetworkAgent.connect(false); 1269 waitFor(cv); 1270 verifyActiveNetwork(TRANSPORT_WIFI); 1271 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability( 1272 NET_CAPABILITY_VALIDATED)); 1273 // Test bringing up validated cellular. 1274 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); 1275 cv = waitForConnectivityBroadcasts(2); 1276 mCellNetworkAgent.connect(true); 1277 waitFor(cv); 1278 verifyActiveNetwork(TRANSPORT_CELLULAR); 1279 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability( 1280 NET_CAPABILITY_VALIDATED)); 1281 // Test cellular disconnect. 1282 cv = waitForConnectivityBroadcasts(2); 1283 mCellNetworkAgent.disconnect(); 1284 waitFor(cv); 1285 verifyActiveNetwork(TRANSPORT_WIFI); 1286 // Unlingering a network should not cause it to be marked as validated. 1287 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability( 1288 NET_CAPABILITY_VALIDATED)); 1289 } 1290 1291 @Test 1292 public void testCellularOutscoresWeakWifi() throws Exception { 1293 // Test bringing up validated cellular. 1294 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); 1295 ConditionVariable cv = waitForConnectivityBroadcasts(1); 1296 mCellNetworkAgent.connect(true); 1297 waitFor(cv); 1298 verifyActiveNetwork(TRANSPORT_CELLULAR); 1299 // Test bringing up validated WiFi. 1300 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 1301 cv = waitForConnectivityBroadcasts(2); 1302 mWiFiNetworkAgent.connect(true); 1303 waitFor(cv); 1304 verifyActiveNetwork(TRANSPORT_WIFI); 1305 // Test WiFi getting really weak. 1306 cv = waitForConnectivityBroadcasts(2); 1307 mWiFiNetworkAgent.adjustScore(-11); 1308 waitFor(cv); 1309 verifyActiveNetwork(TRANSPORT_CELLULAR); 1310 // Test WiFi restoring signal strength. 1311 cv = waitForConnectivityBroadcasts(2); 1312 mWiFiNetworkAgent.adjustScore(11); 1313 waitFor(cv); 1314 verifyActiveNetwork(TRANSPORT_WIFI); 1315 } 1316 1317 @Test 1318 public void testReapingNetwork() throws Exception { 1319 // Test bringing up WiFi without NET_CAPABILITY_INTERNET. 1320 // Expect it to be torn down immediately because it satisfies no requests. 1321 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 1322 ConditionVariable cv = mWiFiNetworkAgent.getDisconnectedCV(); 1323 mWiFiNetworkAgent.connectWithoutInternet(); 1324 waitFor(cv); 1325 // Test bringing up cellular without NET_CAPABILITY_INTERNET. 1326 // Expect it to be torn down immediately because it satisfies no requests. 1327 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 1328 cv = mCellNetworkAgent.getDisconnectedCV(); 1329 mCellNetworkAgent.connectWithoutInternet(); 1330 waitFor(cv); 1331 // Test bringing up validated WiFi. 1332 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 1333 cv = waitForConnectivityBroadcasts(1); 1334 mWiFiNetworkAgent.connect(true); 1335 waitFor(cv); 1336 verifyActiveNetwork(TRANSPORT_WIFI); 1337 // Test bringing up unvalidated cellular. 1338 // Expect it to be torn down because it could never be the highest scoring network 1339 // satisfying the default request even if it validated. 1340 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); 1341 cv = mCellNetworkAgent.getDisconnectedCV(); 1342 mCellNetworkAgent.connect(false); 1343 waitFor(cv); 1344 verifyActiveNetwork(TRANSPORT_WIFI); 1345 cv = mWiFiNetworkAgent.getDisconnectedCV(); 1346 mWiFiNetworkAgent.disconnect(); 1347 waitFor(cv); 1348 } 1349 1350 @Test 1351 public void testCellularFallback() throws Exception { 1352 // Test bringing up validated cellular. 1353 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); 1354 ConditionVariable cv = waitForConnectivityBroadcasts(1); 1355 mCellNetworkAgent.connect(true); 1356 waitFor(cv); 1357 verifyActiveNetwork(TRANSPORT_CELLULAR); 1358 // Test bringing up validated WiFi. 1359 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 1360 cv = waitForConnectivityBroadcasts(2); 1361 mWiFiNetworkAgent.connect(true); 1362 waitFor(cv); 1363 verifyActiveNetwork(TRANSPORT_WIFI); 1364 // Reevaluate WiFi (it'll instantly fail DNS). 1365 cv = waitForConnectivityBroadcasts(2); 1366 assertTrue(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability( 1367 NET_CAPABILITY_VALIDATED)); 1368 mCm.reportBadNetwork(mWiFiNetworkAgent.getNetwork()); 1369 // Should quickly fall back to Cellular. 1370 waitFor(cv); 1371 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability( 1372 NET_CAPABILITY_VALIDATED)); 1373 verifyActiveNetwork(TRANSPORT_CELLULAR); 1374 // Reevaluate cellular (it'll instantly fail DNS). 1375 cv = waitForConnectivityBroadcasts(2); 1376 assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability( 1377 NET_CAPABILITY_VALIDATED)); 1378 mCm.reportBadNetwork(mCellNetworkAgent.getNetwork()); 1379 // Should quickly fall back to WiFi. 1380 waitFor(cv); 1381 assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability( 1382 NET_CAPABILITY_VALIDATED)); 1383 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability( 1384 NET_CAPABILITY_VALIDATED)); 1385 verifyActiveNetwork(TRANSPORT_WIFI); 1386 } 1387 1388 @Test 1389 public void testWiFiFallback() throws Exception { 1390 // Test bringing up unvalidated WiFi. 1391 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 1392 ConditionVariable cv = waitForConnectivityBroadcasts(1); 1393 mWiFiNetworkAgent.connect(false); 1394 waitFor(cv); 1395 verifyActiveNetwork(TRANSPORT_WIFI); 1396 // Test bringing up validated cellular. 1397 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); 1398 cv = waitForConnectivityBroadcasts(2); 1399 mCellNetworkAgent.connect(true); 1400 waitFor(cv); 1401 verifyActiveNetwork(TRANSPORT_CELLULAR); 1402 // Reevaluate cellular (it'll instantly fail DNS). 1403 cv = waitForConnectivityBroadcasts(2); 1404 assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability( 1405 NET_CAPABILITY_VALIDATED)); 1406 mCm.reportBadNetwork(mCellNetworkAgent.getNetwork()); 1407 // Should quickly fall back to WiFi. 1408 waitFor(cv); 1409 assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability( 1410 NET_CAPABILITY_VALIDATED)); 1411 verifyActiveNetwork(TRANSPORT_WIFI); 1412 } 1413 1414 enum CallbackState { 1415 NONE, 1416 AVAILABLE, 1417 NETWORK_CAPABILITIES, 1418 LINK_PROPERTIES, 1419 SUSPENDED, 1420 RESUMED, 1421 LOSING, 1422 LOST, 1423 UNAVAILABLE 1424 } 1425 1426 private static class CallbackInfo { 1427 public final CallbackState state; 1428 public final Network network; 1429 public final Object arg; 1430 public CallbackInfo(CallbackState s, Network n, Object o) { 1431 state = s; network = n; arg = o; 1432 } 1433 public String toString() { 1434 return String.format("%s (%s) (%s)", state, network, arg); 1435 } 1436 @Override 1437 public boolean equals(Object o) { 1438 if (!(o instanceof CallbackInfo)) return false; 1439 // Ignore timeMs, since it's unpredictable. 1440 CallbackInfo other = (CallbackInfo) o; 1441 return (state == other.state) && Objects.equals(network, other.network); 1442 } 1443 @Override 1444 public int hashCode() { 1445 return Objects.hash(state, network); 1446 } 1447 } 1448 1449 /** 1450 * Utility NetworkCallback for testing. The caller must explicitly test for all the callbacks 1451 * this class receives, by calling expectCallback() exactly once each time a callback is 1452 * received. assertNoCallback may be called at any time. 1453 */ 1454 private class TestNetworkCallback extends NetworkCallback { 1455 // Chosen to be much less than the linger timeout. This ensures that we can distinguish 1456 // between a LOST callback that arrives immediately and a LOST callback that arrives after 1457 // the linger timeout. 1458 private final static int TIMEOUT_MS = 100; 1459 1460 private final LinkedBlockingQueue<CallbackInfo> mCallbacks = new LinkedBlockingQueue<>(); 1461 private Network mLastAvailableNetwork; 1462 1463 protected void setLastCallback(CallbackState state, Network network, Object o) { 1464 mCallbacks.offer(new CallbackInfo(state, network, o)); 1465 } 1466 1467 @Override 1468 public void onAvailable(Network network) { 1469 mLastAvailableNetwork = network; 1470 setLastCallback(CallbackState.AVAILABLE, network, null); 1471 } 1472 1473 @Override 1474 public void onCapabilitiesChanged(Network network, NetworkCapabilities netCap) { 1475 setLastCallback(CallbackState.NETWORK_CAPABILITIES, network, netCap); 1476 } 1477 1478 @Override 1479 public void onLinkPropertiesChanged(Network network, LinkProperties linkProp) { 1480 setLastCallback(CallbackState.LINK_PROPERTIES, network, linkProp); 1481 } 1482 1483 @Override 1484 public void onUnavailable() { 1485 setLastCallback(CallbackState.UNAVAILABLE, null, null); 1486 } 1487 1488 @Override 1489 public void onNetworkSuspended(Network network) { 1490 setLastCallback(CallbackState.SUSPENDED, network, null); 1491 } 1492 1493 @Override 1494 public void onNetworkResumed(Network network) { 1495 setLastCallback(CallbackState.RESUMED, network, null); 1496 } 1497 1498 @Override 1499 public void onLosing(Network network, int maxMsToLive) { 1500 setLastCallback(CallbackState.LOSING, network, maxMsToLive /* autoboxed int */); 1501 } 1502 1503 @Override 1504 public void onLost(Network network) { 1505 mLastAvailableNetwork = null; 1506 setLastCallback(CallbackState.LOST, network, null); 1507 } 1508 1509 public Network getLastAvailableNetwork() { 1510 return mLastAvailableNetwork; 1511 } 1512 1513 CallbackInfo nextCallback(int timeoutMs) { 1514 CallbackInfo cb = null; 1515 try { 1516 cb = mCallbacks.poll(timeoutMs, TimeUnit.MILLISECONDS); 1517 } catch (InterruptedException e) { 1518 } 1519 if (cb == null) { 1520 // LinkedBlockingQueue.poll() returns null if it timeouts. 1521 fail("Did not receive callback after " + timeoutMs + "ms"); 1522 } 1523 return cb; 1524 } 1525 1526 CallbackInfo expectCallback(CallbackState state, MockNetworkAgent agent, int timeoutMs) { 1527 final Network expectedNetwork = (agent != null) ? agent.getNetwork() : null; 1528 CallbackInfo expected = new CallbackInfo(state, expectedNetwork, 0); 1529 CallbackInfo actual = nextCallback(timeoutMs); 1530 assertEquals("Unexpected callback:", expected, actual); 1531 1532 if (state == CallbackState.LOSING) { 1533 String msg = String.format( 1534 "Invalid linger time value %d, must be between %d and %d", 1535 actual.arg, 0, TEST_LINGER_DELAY_MS); 1536 int maxMsToLive = (Integer) actual.arg; 1537 assertTrue(msg, 0 <= maxMsToLive && maxMsToLive <= TEST_LINGER_DELAY_MS); 1538 } 1539 1540 return actual; 1541 } 1542 1543 CallbackInfo expectCallback(CallbackState state, MockNetworkAgent agent) { 1544 return expectCallback(state, agent, TIMEOUT_MS); 1545 } 1546 1547 CallbackInfo expectCallbackLike(Predicate<CallbackInfo> fn) { 1548 return expectCallbackLike(fn, TIMEOUT_MS); 1549 } 1550 1551 CallbackInfo expectCallbackLike(Predicate<CallbackInfo> fn, int timeoutMs) { 1552 int timeLeft = timeoutMs; 1553 while (timeLeft > 0) { 1554 long start = SystemClock.elapsedRealtime(); 1555 CallbackInfo info = nextCallback(timeLeft); 1556 if (fn.test(info)) { 1557 return info; 1558 } 1559 timeLeft -= (SystemClock.elapsedRealtime() - start); 1560 } 1561 fail("Did not receive expected callback after " + timeoutMs + "ms"); 1562 return null; 1563 } 1564 1565 // Expects onAvailable and the callbacks that follow it. These are: 1566 // - onSuspended, iff the network was suspended when the callbacks fire. 1567 // - onCapabilitiesChanged. 1568 // - onLinkPropertiesChanged. 1569 // 1570 // @param agent the network to expect the callbacks on. 1571 // @param expectSuspended whether to expect a SUSPENDED callback. 1572 // @param expectValidated the expected value of the VALIDATED capability in the 1573 // onCapabilitiesChanged callback. 1574 // @param timeoutMs how long to wait for the callbacks. 1575 void expectAvailableCallbacks(MockNetworkAgent agent, boolean expectSuspended, 1576 boolean expectValidated, int timeoutMs) { 1577 expectCallback(CallbackState.AVAILABLE, agent, timeoutMs); 1578 if (expectSuspended) { 1579 expectCallback(CallbackState.SUSPENDED, agent, timeoutMs); 1580 } 1581 if (expectValidated) { 1582 expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, agent, timeoutMs); 1583 } else { 1584 expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, agent, timeoutMs); 1585 } 1586 expectCallback(CallbackState.LINK_PROPERTIES, agent, timeoutMs); 1587 } 1588 1589 // Expects the available callbacks (validated), plus onSuspended. 1590 void expectAvailableAndSuspendedCallbacks(MockNetworkAgent agent, boolean expectValidated) { 1591 expectAvailableCallbacks(agent, true, expectValidated, TIMEOUT_MS); 1592 } 1593 1594 void expectAvailableCallbacksValidated(MockNetworkAgent agent) { 1595 expectAvailableCallbacks(agent, false, true, TIMEOUT_MS); 1596 } 1597 1598 void expectAvailableCallbacksUnvalidated(MockNetworkAgent agent) { 1599 expectAvailableCallbacks(agent, false, false, TIMEOUT_MS); 1600 } 1601 1602 // Expects the available callbacks (where the onCapabilitiesChanged must contain the 1603 // VALIDATED capability), plus another onCapabilitiesChanged which is identical to the 1604 // one we just sent. 1605 // TODO: this is likely a bug. Fix it and remove this method. 1606 void expectAvailableDoubleValidatedCallbacks(MockNetworkAgent agent) { 1607 expectCallback(CallbackState.AVAILABLE, agent, TIMEOUT_MS); 1608 NetworkCapabilities nc1 = expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, agent); 1609 expectCallback(CallbackState.LINK_PROPERTIES, agent, TIMEOUT_MS); 1610 NetworkCapabilities nc2 = expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, agent); 1611 assertEquals(nc1, nc2); 1612 } 1613 1614 // Expects the available callbacks where the onCapabilitiesChanged must not have validated, 1615 // then expects another onCapabilitiesChanged that has the validated bit set. This is used 1616 // when a network connects and satisfies a callback, and then immediately validates. 1617 void expectAvailableThenValidatedCallbacks(MockNetworkAgent agent) { 1618 expectAvailableCallbacksUnvalidated(agent); 1619 expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, agent); 1620 } 1621 1622 NetworkCapabilities expectCapabilitiesWith(int capability, MockNetworkAgent agent) { 1623 return expectCapabilitiesWith(capability, agent, TIMEOUT_MS); 1624 } 1625 1626 NetworkCapabilities expectCapabilitiesWith(int capability, MockNetworkAgent agent, 1627 int timeoutMs) { 1628 CallbackInfo cbi = expectCallback(CallbackState.NETWORK_CAPABILITIES, agent, timeoutMs); 1629 NetworkCapabilities nc = (NetworkCapabilities) cbi.arg; 1630 assertTrue(nc.hasCapability(capability)); 1631 return nc; 1632 } 1633 1634 NetworkCapabilities expectCapabilitiesWithout(int capability, MockNetworkAgent agent) { 1635 return expectCapabilitiesWithout(capability, agent, TIMEOUT_MS); 1636 } 1637 1638 NetworkCapabilities expectCapabilitiesWithout(int capability, MockNetworkAgent agent, 1639 int timeoutMs) { 1640 CallbackInfo cbi = expectCallback(CallbackState.NETWORK_CAPABILITIES, agent, timeoutMs); 1641 NetworkCapabilities nc = (NetworkCapabilities) cbi.arg; 1642 assertFalse(nc.hasCapability(capability)); 1643 return nc; 1644 } 1645 1646 void expectCapabilitiesLike(Predicate<NetworkCapabilities> fn, MockNetworkAgent agent) { 1647 CallbackInfo cbi = expectCallback(CallbackState.NETWORK_CAPABILITIES, agent); 1648 assertTrue("Received capabilities don't match expectations : " + cbi.arg, 1649 fn.test((NetworkCapabilities) cbi.arg)); 1650 } 1651 1652 void assertNoCallback() { 1653 waitForIdle(); 1654 CallbackInfo c = mCallbacks.peek(); 1655 assertNull("Unexpected callback: " + c, c); 1656 } 1657 } 1658 1659 // Can't be part of TestNetworkCallback because "cannot be declared static; static methods can 1660 // only be declared in a static or top level type". 1661 static void assertNoCallbacks(TestNetworkCallback ... callbacks) { 1662 for (TestNetworkCallback c : callbacks) { 1663 c.assertNoCallback(); 1664 } 1665 } 1666 1667 @Test 1668 public void testStateChangeNetworkCallbacks() throws Exception { 1669 final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback(); 1670 final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback(); 1671 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback(); 1672 final NetworkRequest genericRequest = new NetworkRequest.Builder() 1673 .clearCapabilities().build(); 1674 final NetworkRequest wifiRequest = new NetworkRequest.Builder() 1675 .addTransportType(TRANSPORT_WIFI).build(); 1676 final NetworkRequest cellRequest = new NetworkRequest.Builder() 1677 .addTransportType(TRANSPORT_CELLULAR).build(); 1678 mCm.registerNetworkCallback(genericRequest, genericNetworkCallback); 1679 mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback); 1680 mCm.registerNetworkCallback(cellRequest, cellNetworkCallback); 1681 1682 // Test unvalidated networks 1683 ConditionVariable cv = waitForConnectivityBroadcasts(1); 1684 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); 1685 mCellNetworkAgent.connect(false); 1686 genericNetworkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent); 1687 cellNetworkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent); 1688 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 1689 waitFor(cv); 1690 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback); 1691 1692 // This should not trigger spurious onAvailable() callbacks, b/21762680. 1693 mCellNetworkAgent.adjustScore(-1); 1694 waitForIdle(); 1695 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback); 1696 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 1697 1698 cv = waitForConnectivityBroadcasts(2); 1699 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 1700 mWiFiNetworkAgent.connect(false); 1701 genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); 1702 wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); 1703 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 1704 waitFor(cv); 1705 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback); 1706 1707 cv = waitForConnectivityBroadcasts(2); 1708 mWiFiNetworkAgent.disconnect(); 1709 genericNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); 1710 wifiNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); 1711 cellNetworkCallback.assertNoCallback(); 1712 waitFor(cv); 1713 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback); 1714 1715 cv = waitForConnectivityBroadcasts(1); 1716 mCellNetworkAgent.disconnect(); 1717 genericNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent); 1718 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent); 1719 waitFor(cv); 1720 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback); 1721 1722 // Test validated networks 1723 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); 1724 mCellNetworkAgent.connect(true); 1725 genericNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); 1726 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); 1727 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 1728 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback); 1729 1730 // This should not trigger spurious onAvailable() callbacks, b/21762680. 1731 mCellNetworkAgent.adjustScore(-1); 1732 waitForIdle(); 1733 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback); 1734 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 1735 1736 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 1737 mWiFiNetworkAgent.connect(true); 1738 genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); 1739 genericNetworkCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent); 1740 genericNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent); 1741 wifiNetworkCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent); 1742 cellNetworkCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent); 1743 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 1744 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback); 1745 1746 mWiFiNetworkAgent.disconnect(); 1747 genericNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); 1748 wifiNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); 1749 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback); 1750 1751 mCellNetworkAgent.disconnect(); 1752 genericNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent); 1753 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent); 1754 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback); 1755 } 1756 1757 @Test 1758 public void testMultipleLingering() { 1759 NetworkRequest request = new NetworkRequest.Builder() 1760 .clearCapabilities().addCapability(NET_CAPABILITY_NOT_METERED) 1761 .build(); 1762 TestNetworkCallback callback = new TestNetworkCallback(); 1763 mCm.registerNetworkCallback(request, callback); 1764 1765 TestNetworkCallback defaultCallback = new TestNetworkCallback(); 1766 mCm.registerDefaultNetworkCallback(defaultCallback); 1767 1768 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); 1769 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 1770 mEthernetNetworkAgent = new MockNetworkAgent(TRANSPORT_ETHERNET); 1771 1772 mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED); 1773 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED); 1774 mEthernetNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED); 1775 1776 mCellNetworkAgent.connect(true); 1777 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); 1778 defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); 1779 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 1780 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); 1781 1782 mWiFiNetworkAgent.connect(true); 1783 // We get AVAILABLE on wifi when wifi connects and satisfies our unmetered request. 1784 // We then get LOSING when wifi validates and cell is outscored. 1785 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); 1786 // TODO: Investigate sending validated before losing. 1787 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent); 1788 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent); 1789 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent); 1790 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 1791 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); 1792 1793 mEthernetNetworkAgent.connect(true); 1794 callback.expectAvailableCallbacksUnvalidated(mEthernetNetworkAgent); 1795 // TODO: Investigate sending validated before losing. 1796 callback.expectCallback(CallbackState.LOSING, mWiFiNetworkAgent); 1797 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mEthernetNetworkAgent); 1798 defaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent); 1799 assertEquals(mEthernetNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 1800 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); 1801 1802 mEthernetNetworkAgent.disconnect(); 1803 callback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent); 1804 defaultCallback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent); 1805 defaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent); 1806 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); 1807 1808 for (int i = 0; i < 4; i++) { 1809 MockNetworkAgent oldNetwork, newNetwork; 1810 if (i % 2 == 0) { 1811 mWiFiNetworkAgent.adjustScore(-15); 1812 oldNetwork = mWiFiNetworkAgent; 1813 newNetwork = mCellNetworkAgent; 1814 } else { 1815 mWiFiNetworkAgent.adjustScore(15); 1816 oldNetwork = mCellNetworkAgent; 1817 newNetwork = mWiFiNetworkAgent; 1818 1819 } 1820 callback.expectCallback(CallbackState.LOSING, oldNetwork); 1821 // TODO: should we send an AVAILABLE callback to newNetwork, to indicate that it is no 1822 // longer lingering? 1823 defaultCallback.expectAvailableCallbacksValidated(newNetwork); 1824 assertEquals(newNetwork.getNetwork(), mCm.getActiveNetwork()); 1825 } 1826 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 1827 1828 // Verify that if a network no longer satisfies a request, we send LOST and not LOSING, even 1829 // if the network is still up. 1830 mWiFiNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED); 1831 // We expect a notification about the capabilities change, and nothing else. 1832 defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_METERED, mWiFiNetworkAgent); 1833 defaultCallback.assertNoCallback(); 1834 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); 1835 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); 1836 1837 // Wifi no longer satisfies our listen, which is for an unmetered network. 1838 // But because its score is 55, it's still up (and the default network). 1839 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 1840 1841 // Disconnect our test networks. 1842 mWiFiNetworkAgent.disconnect(); 1843 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); 1844 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent); 1845 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); 1846 mCellNetworkAgent.disconnect(); 1847 defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent); 1848 waitForIdle(); 1849 assertEquals(null, mCm.getActiveNetwork()); 1850 1851 mCm.unregisterNetworkCallback(callback); 1852 waitForIdle(); 1853 1854 // Check that a network is only lingered or torn down if it would not satisfy a request even 1855 // if it validated. 1856 request = new NetworkRequest.Builder().clearCapabilities().build(); 1857 callback = new TestNetworkCallback(); 1858 1859 mCm.registerNetworkCallback(request, callback); 1860 1861 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); 1862 mCellNetworkAgent.connect(false); // Score: 10 1863 callback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent); 1864 defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent); 1865 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 1866 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); 1867 1868 // Bring up wifi with a score of 20. 1869 // Cell stays up because it would satisfy the default request if it validated. 1870 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 1871 mWiFiNetworkAgent.connect(false); // Score: 20 1872 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); 1873 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); 1874 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 1875 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); 1876 1877 mWiFiNetworkAgent.disconnect(); 1878 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); 1879 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); 1880 defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent); 1881 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 1882 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); 1883 1884 // Bring up wifi with a score of 70. 1885 // Cell is lingered because it would not satisfy any request, even if it validated. 1886 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 1887 mWiFiNetworkAgent.adjustScore(50); 1888 mWiFiNetworkAgent.connect(false); // Score: 70 1889 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); 1890 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent); 1891 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); 1892 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 1893 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); 1894 1895 // Tear down wifi. 1896 mWiFiNetworkAgent.disconnect(); 1897 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); 1898 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); 1899 defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent); 1900 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 1901 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); 1902 1903 // Bring up wifi, then validate it. Previous versions would immediately tear down cell, but 1904 // it's arguably correct to linger it, since it was the default network before it validated. 1905 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 1906 mWiFiNetworkAgent.connect(true); 1907 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); 1908 // TODO: Investigate sending validated before losing. 1909 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent); 1910 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent); 1911 defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent); 1912 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 1913 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); 1914 1915 mWiFiNetworkAgent.disconnect(); 1916 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); 1917 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); 1918 defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent); 1919 mCellNetworkAgent.disconnect(); 1920 callback.expectCallback(CallbackState.LOST, mCellNetworkAgent); 1921 defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent); 1922 waitForIdle(); 1923 assertEquals(null, mCm.getActiveNetwork()); 1924 1925 // If a network is lingering, and we add and remove a request from it, resume lingering. 1926 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); 1927 mCellNetworkAgent.connect(true); 1928 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); 1929 defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); 1930 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); 1931 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 1932 mWiFiNetworkAgent.connect(true); 1933 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent); 1934 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); 1935 // TODO: Investigate sending validated before losing. 1936 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent); 1937 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent); 1938 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); 1939 1940 NetworkRequest cellRequest = new NetworkRequest.Builder() 1941 .addTransportType(TRANSPORT_CELLULAR).build(); 1942 NetworkCallback noopCallback = new NetworkCallback(); 1943 mCm.requestNetwork(cellRequest, noopCallback); 1944 // TODO: should this cause an AVAILABLE callback, to indicate that the network is no longer 1945 // lingering? 1946 mCm.unregisterNetworkCallback(noopCallback); 1947 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent); 1948 1949 // Similar to the above: lingering can start even after the lingered request is removed. 1950 // Disconnect wifi and switch to cell. 1951 mWiFiNetworkAgent.disconnect(); 1952 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); 1953 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); 1954 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent); 1955 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); 1956 1957 // Cell is now the default network. Pin it with a cell-specific request. 1958 noopCallback = new NetworkCallback(); // Can't reuse NetworkCallbacks. http://b/20701525 1959 mCm.requestNetwork(cellRequest, noopCallback); 1960 1961 // Now connect wifi, and expect it to become the default network. 1962 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 1963 mWiFiNetworkAgent.connect(true); 1964 callback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent); 1965 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent); 1966 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); 1967 // The default request is lingering on cell, but nothing happens to cell, and we send no 1968 // callbacks for it, because it's kept up by cellRequest. 1969 callback.assertNoCallback(); 1970 // Now unregister cellRequest and expect cell to start lingering. 1971 mCm.unregisterNetworkCallback(noopCallback); 1972 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent); 1973 1974 // Let linger run its course. 1975 callback.assertNoCallback(); 1976 final int lingerTimeoutMs = TEST_LINGER_DELAY_MS + TEST_LINGER_DELAY_MS / 4; 1977 callback.expectCallback(CallbackState.LOST, mCellNetworkAgent, lingerTimeoutMs); 1978 1979 // Register a TRACK_DEFAULT request and check that it does not affect lingering. 1980 TestNetworkCallback trackDefaultCallback = new TestNetworkCallback(); 1981 mCm.registerDefaultNetworkCallback(trackDefaultCallback); 1982 trackDefaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent); 1983 mEthernetNetworkAgent = new MockNetworkAgent(TRANSPORT_ETHERNET); 1984 mEthernetNetworkAgent.connect(true); 1985 callback.expectAvailableCallbacksUnvalidated(mEthernetNetworkAgent); 1986 callback.expectCallback(CallbackState.LOSING, mWiFiNetworkAgent); 1987 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mEthernetNetworkAgent); 1988 trackDefaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent); 1989 defaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent); 1990 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); 1991 1992 // Let linger run its course. 1993 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent, lingerTimeoutMs); 1994 1995 // Clean up. 1996 mEthernetNetworkAgent.disconnect(); 1997 callback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent); 1998 defaultCallback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent); 1999 trackDefaultCallback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent); 2000 2001 mCm.unregisterNetworkCallback(callback); 2002 mCm.unregisterNetworkCallback(defaultCallback); 2003 mCm.unregisterNetworkCallback(trackDefaultCallback); 2004 } 2005 2006 @Test 2007 public void testNetworkGoesIntoBackgroundAfterLinger() { 2008 setMobileDataAlwaysOn(true); 2009 NetworkRequest request = new NetworkRequest.Builder() 2010 .clearCapabilities() 2011 .build(); 2012 TestNetworkCallback callback = new TestNetworkCallback(); 2013 mCm.registerNetworkCallback(request, callback); 2014 2015 TestNetworkCallback defaultCallback = new TestNetworkCallback(); 2016 mCm.registerDefaultNetworkCallback(defaultCallback); 2017 2018 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); 2019 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 2020 2021 mCellNetworkAgent.connect(true); 2022 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); 2023 defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); 2024 2025 // Wifi comes up and cell lingers. 2026 mWiFiNetworkAgent.connect(true); 2027 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent); 2028 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); 2029 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent); 2030 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent); 2031 2032 // File a request for cellular, then release it. 2033 NetworkRequest cellRequest = new NetworkRequest.Builder() 2034 .addTransportType(TRANSPORT_CELLULAR).build(); 2035 NetworkCallback noopCallback = new NetworkCallback(); 2036 mCm.requestNetwork(cellRequest, noopCallback); 2037 mCm.unregisterNetworkCallback(noopCallback); 2038 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent); 2039 2040 // Let linger run its course. 2041 callback.assertNoCallback(); 2042 final int lingerTimeoutMs = TEST_LINGER_DELAY_MS + TEST_LINGER_DELAY_MS / 4; 2043 callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent, 2044 lingerTimeoutMs); 2045 2046 // Clean up. 2047 mCm.unregisterNetworkCallback(defaultCallback); 2048 mCm.unregisterNetworkCallback(callback); 2049 } 2050 2051 @Test 2052 public void testExplicitlySelected() { 2053 NetworkRequest request = new NetworkRequest.Builder() 2054 .clearCapabilities().addCapability(NET_CAPABILITY_INTERNET) 2055 .build(); 2056 TestNetworkCallback callback = new TestNetworkCallback(); 2057 mCm.registerNetworkCallback(request, callback); 2058 2059 // Bring up validated cell. 2060 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); 2061 mCellNetworkAgent.connect(true); 2062 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); 2063 2064 // Bring up unvalidated wifi with explicitlySelected=true. 2065 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 2066 mWiFiNetworkAgent.explicitlySelected(false); 2067 mWiFiNetworkAgent.connect(false); 2068 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); 2069 2070 // Cell Remains the default. 2071 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 2072 2073 // Lower wifi's score to below than cell, and check that it doesn't disconnect because 2074 // it's explicitly selected. 2075 mWiFiNetworkAgent.adjustScore(-40); 2076 mWiFiNetworkAgent.adjustScore(40); 2077 callback.assertNoCallback(); 2078 2079 // If the user chooses yes on the "No Internet access, stay connected?" dialog, we switch to 2080 // wifi even though it's unvalidated. 2081 mCm.setAcceptUnvalidated(mWiFiNetworkAgent.getNetwork(), true, false); 2082 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent); 2083 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 2084 2085 // Disconnect wifi, and then reconnect, again with explicitlySelected=true. 2086 mWiFiNetworkAgent.disconnect(); 2087 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); 2088 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 2089 mWiFiNetworkAgent.explicitlySelected(false); 2090 mWiFiNetworkAgent.connect(false); 2091 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); 2092 2093 // If the user chooses no on the "No Internet access, stay connected?" dialog, we ask the 2094 // network to disconnect. 2095 mCm.setAcceptUnvalidated(mWiFiNetworkAgent.getNetwork(), false, false); 2096 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); 2097 2098 // Reconnect, again with explicitlySelected=true, but this time validate. 2099 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 2100 mWiFiNetworkAgent.explicitlySelected(false); 2101 mWiFiNetworkAgent.connect(true); 2102 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); 2103 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent); 2104 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent); 2105 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 2106 2107 // BUG: the network will no longer linger, even though it's validated and outscored. 2108 // TODO: fix this. 2109 mEthernetNetworkAgent = new MockNetworkAgent(TRANSPORT_ETHERNET); 2110 mEthernetNetworkAgent.connect(true); 2111 callback.expectAvailableThenValidatedCallbacks(mEthernetNetworkAgent); 2112 assertEquals(mEthernetNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 2113 callback.assertNoCallback(); 2114 2115 // Clean up. 2116 mWiFiNetworkAgent.disconnect(); 2117 mCellNetworkAgent.disconnect(); 2118 mEthernetNetworkAgent.disconnect(); 2119 2120 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); 2121 callback.expectCallback(CallbackState.LOST, mCellNetworkAgent); 2122 callback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent); 2123 } 2124 2125 private void tryNetworkFactoryRequests(int capability) throws Exception { 2126 // Verify NOT_RESTRICTED is set appropriately 2127 final NetworkCapabilities nc = new NetworkRequest.Builder().addCapability(capability) 2128 .build().networkCapabilities; 2129 if (capability == NET_CAPABILITY_CBS || capability == NET_CAPABILITY_DUN || 2130 capability == NET_CAPABILITY_EIMS || capability == NET_CAPABILITY_FOTA || 2131 capability == NET_CAPABILITY_IA || capability == NET_CAPABILITY_IMS || 2132 capability == NET_CAPABILITY_RCS || capability == NET_CAPABILITY_XCAP) { 2133 assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)); 2134 } else { 2135 assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)); 2136 } 2137 2138 NetworkCapabilities filter = new NetworkCapabilities(); 2139 filter.addCapability(capability); 2140 final HandlerThread handlerThread = new HandlerThread("testNetworkFactoryRequests"); 2141 handlerThread.start(); 2142 final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(), 2143 mServiceContext, "testFactory", filter); 2144 testFactory.setScoreFilter(40); 2145 ConditionVariable cv = testFactory.getNetworkStartedCV(); 2146 testFactory.expectAddRequests(1); 2147 testFactory.register(); 2148 testFactory.waitForNetworkRequests(1); 2149 int expectedRequestCount = 1; 2150 NetworkCallback networkCallback = null; 2151 // For non-INTERNET capabilities we cannot rely on the default request being present, so 2152 // add one. 2153 if (capability != NET_CAPABILITY_INTERNET) { 2154 assertFalse(testFactory.getMyStartRequested()); 2155 NetworkRequest request = new NetworkRequest.Builder().addCapability(capability).build(); 2156 networkCallback = new NetworkCallback(); 2157 testFactory.expectAddRequests(1); 2158 mCm.requestNetwork(request, networkCallback); 2159 expectedRequestCount++; 2160 testFactory.waitForNetworkRequests(expectedRequestCount); 2161 } 2162 waitFor(cv); 2163 assertEquals(expectedRequestCount, testFactory.getMyRequestCount()); 2164 assertTrue(testFactory.getMyStartRequested()); 2165 2166 // Now bring in a higher scored network. 2167 MockNetworkAgent testAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); 2168 // Rather than create a validated network which complicates things by registering it's 2169 // own NetworkRequest during startup, just bump up the score to cancel out the 2170 // unvalidated penalty. 2171 testAgent.adjustScore(40); 2172 cv = testFactory.getNetworkStoppedCV(); 2173 2174 // When testAgent connects, ConnectivityService will re-send us all current requests with 2175 // the new score. There are expectedRequestCount such requests, and we must wait for all of 2176 // them. 2177 testFactory.expectAddRequests(expectedRequestCount); 2178 testAgent.connect(false); 2179 testAgent.addCapability(capability); 2180 waitFor(cv); 2181 testFactory.waitForNetworkRequests(expectedRequestCount); 2182 assertFalse(testFactory.getMyStartRequested()); 2183 2184 // Bring in a bunch of requests. 2185 testFactory.expectAddRequests(10); 2186 assertEquals(expectedRequestCount, testFactory.getMyRequestCount()); 2187 ConnectivityManager.NetworkCallback[] networkCallbacks = 2188 new ConnectivityManager.NetworkCallback[10]; 2189 for (int i = 0; i< networkCallbacks.length; i++) { 2190 networkCallbacks[i] = new ConnectivityManager.NetworkCallback(); 2191 NetworkRequest.Builder builder = new NetworkRequest.Builder(); 2192 builder.addCapability(capability); 2193 mCm.requestNetwork(builder.build(), networkCallbacks[i]); 2194 } 2195 testFactory.waitForNetworkRequests(10 + expectedRequestCount); 2196 assertFalse(testFactory.getMyStartRequested()); 2197 2198 // Remove the requests. 2199 testFactory.expectRemoveRequests(10); 2200 for (int i = 0; i < networkCallbacks.length; i++) { 2201 mCm.unregisterNetworkCallback(networkCallbacks[i]); 2202 } 2203 testFactory.waitForNetworkRequests(expectedRequestCount); 2204 assertFalse(testFactory.getMyStartRequested()); 2205 2206 // Drop the higher scored network. 2207 cv = testFactory.getNetworkStartedCV(); 2208 testAgent.disconnect(); 2209 waitFor(cv); 2210 assertEquals(expectedRequestCount, testFactory.getMyRequestCount()); 2211 assertTrue(testFactory.getMyStartRequested()); 2212 2213 testFactory.unregister(); 2214 if (networkCallback != null) mCm.unregisterNetworkCallback(networkCallback); 2215 handlerThread.quit(); 2216 } 2217 2218 @Test 2219 public void testNetworkFactoryRequests() throws Exception { 2220 tryNetworkFactoryRequests(NET_CAPABILITY_MMS); 2221 tryNetworkFactoryRequests(NET_CAPABILITY_SUPL); 2222 tryNetworkFactoryRequests(NET_CAPABILITY_DUN); 2223 tryNetworkFactoryRequests(NET_CAPABILITY_FOTA); 2224 tryNetworkFactoryRequests(NET_CAPABILITY_IMS); 2225 tryNetworkFactoryRequests(NET_CAPABILITY_CBS); 2226 tryNetworkFactoryRequests(NET_CAPABILITY_WIFI_P2P); 2227 tryNetworkFactoryRequests(NET_CAPABILITY_IA); 2228 tryNetworkFactoryRequests(NET_CAPABILITY_RCS); 2229 tryNetworkFactoryRequests(NET_CAPABILITY_XCAP); 2230 tryNetworkFactoryRequests(NET_CAPABILITY_EIMS); 2231 tryNetworkFactoryRequests(NET_CAPABILITY_NOT_METERED); 2232 tryNetworkFactoryRequests(NET_CAPABILITY_INTERNET); 2233 tryNetworkFactoryRequests(NET_CAPABILITY_TRUSTED); 2234 tryNetworkFactoryRequests(NET_CAPABILITY_NOT_VPN); 2235 // Skipping VALIDATED and CAPTIVE_PORTAL as they're disallowed. 2236 } 2237 2238 @Test 2239 public void testNoMutableNetworkRequests() throws Exception { 2240 PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, new Intent("a"), 0); 2241 NetworkRequest request1 = new NetworkRequest.Builder() 2242 .addCapability(NET_CAPABILITY_VALIDATED) 2243 .build(); 2244 NetworkRequest request2 = new NetworkRequest.Builder() 2245 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL) 2246 .build(); 2247 2248 Class<IllegalArgumentException> expected = IllegalArgumentException.class; 2249 assertException(() -> { mCm.requestNetwork(request1, new NetworkCallback()); }, expected); 2250 assertException(() -> { mCm.requestNetwork(request1, pendingIntent); }, expected); 2251 assertException(() -> { mCm.requestNetwork(request2, new NetworkCallback()); }, expected); 2252 assertException(() -> { mCm.requestNetwork(request2, pendingIntent); }, expected); 2253 } 2254 2255 @Test 2256 public void testMMSonWiFi() throws Exception { 2257 // Test bringing up cellular without MMS NetworkRequest gets reaped 2258 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); 2259 mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS); 2260 ConditionVariable cv = mCellNetworkAgent.getDisconnectedCV(); 2261 mCellNetworkAgent.connectWithoutInternet(); 2262 waitFor(cv); 2263 waitForIdle(); 2264 assertEmpty(mCm.getAllNetworks()); 2265 verifyNoNetwork(); 2266 2267 // Test bringing up validated WiFi. 2268 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 2269 cv = waitForConnectivityBroadcasts(1); 2270 mWiFiNetworkAgent.connect(true); 2271 waitFor(cv); 2272 verifyActiveNetwork(TRANSPORT_WIFI); 2273 2274 // Register MMS NetworkRequest 2275 NetworkRequest.Builder builder = new NetworkRequest.Builder(); 2276 builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS); 2277 final TestNetworkCallback networkCallback = new TestNetworkCallback(); 2278 mCm.requestNetwork(builder.build(), networkCallback); 2279 2280 // Test bringing up unvalidated cellular with MMS 2281 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); 2282 mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS); 2283 mCellNetworkAgent.connectWithoutInternet(); 2284 networkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent); 2285 verifyActiveNetwork(TRANSPORT_WIFI); 2286 2287 // Test releasing NetworkRequest disconnects cellular with MMS 2288 cv = mCellNetworkAgent.getDisconnectedCV(); 2289 mCm.unregisterNetworkCallback(networkCallback); 2290 waitFor(cv); 2291 verifyActiveNetwork(TRANSPORT_WIFI); 2292 } 2293 2294 @Test 2295 public void testMMSonCell() throws Exception { 2296 // Test bringing up cellular without MMS 2297 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); 2298 ConditionVariable cv = waitForConnectivityBroadcasts(1); 2299 mCellNetworkAgent.connect(false); 2300 waitFor(cv); 2301 verifyActiveNetwork(TRANSPORT_CELLULAR); 2302 2303 // Register MMS NetworkRequest 2304 NetworkRequest.Builder builder = new NetworkRequest.Builder(); 2305 builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS); 2306 final TestNetworkCallback networkCallback = new TestNetworkCallback(); 2307 mCm.requestNetwork(builder.build(), networkCallback); 2308 2309 // Test bringing up MMS cellular network 2310 MockNetworkAgent mmsNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); 2311 mmsNetworkAgent.addCapability(NET_CAPABILITY_MMS); 2312 mmsNetworkAgent.connectWithoutInternet(); 2313 networkCallback.expectAvailableCallbacksUnvalidated(mmsNetworkAgent); 2314 verifyActiveNetwork(TRANSPORT_CELLULAR); 2315 2316 // Test releasing MMS NetworkRequest does not disconnect main cellular NetworkAgent 2317 cv = mmsNetworkAgent.getDisconnectedCV(); 2318 mCm.unregisterNetworkCallback(networkCallback); 2319 waitFor(cv); 2320 verifyActiveNetwork(TRANSPORT_CELLULAR); 2321 } 2322 2323 @Test 2324 public void testCaptivePortal() { 2325 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback(); 2326 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder() 2327 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build(); 2328 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback); 2329 2330 final TestNetworkCallback validatedCallback = new TestNetworkCallback(); 2331 final NetworkRequest validatedRequest = new NetworkRequest.Builder() 2332 .addCapability(NET_CAPABILITY_VALIDATED).build(); 2333 mCm.registerNetworkCallback(validatedRequest, validatedCallback); 2334 2335 // Bring up a network with a captive portal. 2336 // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL. 2337 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 2338 String firstRedirectUrl = "http://example.com/firstPath"; 2339 mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl); 2340 captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); 2341 assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), firstRedirectUrl); 2342 2343 // Take down network. 2344 // Expect onLost callback. 2345 mWiFiNetworkAgent.disconnect(); 2346 captivePortalCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); 2347 2348 // Bring up a network with a captive portal. 2349 // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL. 2350 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 2351 String secondRedirectUrl = "http://example.com/secondPath"; 2352 mWiFiNetworkAgent.connectWithCaptivePortal(secondRedirectUrl); 2353 captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); 2354 assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), secondRedirectUrl); 2355 2356 // Make captive portal disappear then revalidate. 2357 // Expect onLost callback because network no longer provides NET_CAPABILITY_CAPTIVE_PORTAL. 2358 mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 204; 2359 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true); 2360 captivePortalCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); 2361 2362 // Expect NET_CAPABILITY_VALIDATED onAvailable callback. 2363 validatedCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent); 2364 2365 // Break network connectivity. 2366 // Expect NET_CAPABILITY_VALIDATED onLost callback. 2367 mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 500; 2368 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), false); 2369 validatedCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); 2370 } 2371 2372 @Test 2373 public void testCaptivePortalApp() { 2374 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback(); 2375 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder() 2376 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build(); 2377 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback); 2378 2379 final TestNetworkCallback validatedCallback = new TestNetworkCallback(); 2380 final NetworkRequest validatedRequest = new NetworkRequest.Builder() 2381 .addCapability(NET_CAPABILITY_VALIDATED).build(); 2382 mCm.registerNetworkCallback(validatedRequest, validatedCallback); 2383 2384 // Bring up wifi. 2385 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 2386 mWiFiNetworkAgent.connect(true); 2387 validatedCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent); 2388 Network wifiNetwork = mWiFiNetworkAgent.getNetwork(); 2389 2390 // Check that calling startCaptivePortalApp does nothing. 2391 final int fastTimeoutMs = 100; 2392 mCm.startCaptivePortalApp(wifiNetwork); 2393 mServiceContext.expectNoStartActivityIntent(fastTimeoutMs); 2394 2395 // Turn into a captive portal. 2396 mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 302; 2397 mCm.reportNetworkConnectivity(wifiNetwork, false); 2398 captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); 2399 validatedCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); 2400 2401 // Check that startCaptivePortalApp sends the expected intent. 2402 mCm.startCaptivePortalApp(wifiNetwork); 2403 Intent intent = mServiceContext.expectStartActivityIntent(TIMEOUT_MS); 2404 assertEquals(ConnectivityManager.ACTION_CAPTIVE_PORTAL_SIGN_IN, intent.getAction()); 2405 assertEquals(wifiNetwork, intent.getExtra(ConnectivityManager.EXTRA_NETWORK)); 2406 2407 // Have the app report that the captive portal is dismissed, and check that we revalidate. 2408 mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 204; 2409 CaptivePortal c = (CaptivePortal) intent.getExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL); 2410 c.reportCaptivePortalDismissed(); 2411 validatedCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent); 2412 captivePortalCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); 2413 2414 mCm.unregisterNetworkCallback(validatedCallback); 2415 mCm.unregisterNetworkCallback(captivePortalCallback); 2416 } 2417 2418 @Test 2419 public void testAvoidOrIgnoreCaptivePortals() { 2420 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback(); 2421 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder() 2422 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build(); 2423 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback); 2424 2425 final TestNetworkCallback validatedCallback = new TestNetworkCallback(); 2426 final NetworkRequest validatedRequest = new NetworkRequest.Builder() 2427 .addCapability(NET_CAPABILITY_VALIDATED).build(); 2428 mCm.registerNetworkCallback(validatedRequest, validatedCallback); 2429 2430 setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_AVOID); 2431 // Bring up a network with a captive portal. 2432 // Expect it to fail to connect and not result in any callbacks. 2433 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 2434 String firstRedirectUrl = "http://example.com/firstPath"; 2435 2436 ConditionVariable disconnectCv = mWiFiNetworkAgent.getDisconnectedCV(); 2437 ConditionVariable avoidCv = mWiFiNetworkAgent.getPreventReconnectReceived(); 2438 mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl); 2439 waitFor(disconnectCv); 2440 waitFor(avoidCv); 2441 2442 assertNoCallbacks(captivePortalCallback, validatedCallback); 2443 2444 // Now test ignore mode. 2445 setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_IGNORE); 2446 2447 // Bring up a network with a captive portal. 2448 // Since we're ignoring captive portals, the network will validate. 2449 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 2450 String secondRedirectUrl = "http://example.com/secondPath"; 2451 mWiFiNetworkAgent.connectWithCaptivePortal(secondRedirectUrl); 2452 2453 // Expect NET_CAPABILITY_VALIDATED onAvailable callback. 2454 validatedCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent); 2455 // But there should be no CaptivePortal callback. 2456 captivePortalCallback.assertNoCallback(); 2457 } 2458 2459 private NetworkRequest.Builder newWifiRequestBuilder() { 2460 return new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI); 2461 } 2462 2463 @Test 2464 public void testNetworkSpecifier() { 2465 NetworkRequest rEmpty1 = newWifiRequestBuilder().build(); 2466 NetworkRequest rEmpty2 = newWifiRequestBuilder().setNetworkSpecifier((String) null).build(); 2467 NetworkRequest rEmpty3 = newWifiRequestBuilder().setNetworkSpecifier("").build(); 2468 NetworkRequest rEmpty4 = newWifiRequestBuilder().setNetworkSpecifier( 2469 (NetworkSpecifier) null).build(); 2470 NetworkRequest rFoo = newWifiRequestBuilder().setNetworkSpecifier("foo").build(); 2471 NetworkRequest rBar = newWifiRequestBuilder().setNetworkSpecifier( 2472 new StringNetworkSpecifier("bar")).build(); 2473 2474 TestNetworkCallback cEmpty1 = new TestNetworkCallback(); 2475 TestNetworkCallback cEmpty2 = new TestNetworkCallback(); 2476 TestNetworkCallback cEmpty3 = new TestNetworkCallback(); 2477 TestNetworkCallback cEmpty4 = new TestNetworkCallback(); 2478 TestNetworkCallback cFoo = new TestNetworkCallback(); 2479 TestNetworkCallback cBar = new TestNetworkCallback(); 2480 TestNetworkCallback[] emptyCallbacks = new TestNetworkCallback[] { 2481 cEmpty1, cEmpty2, cEmpty3 }; 2482 2483 mCm.registerNetworkCallback(rEmpty1, cEmpty1); 2484 mCm.registerNetworkCallback(rEmpty2, cEmpty2); 2485 mCm.registerNetworkCallback(rEmpty3, cEmpty3); 2486 mCm.registerNetworkCallback(rEmpty4, cEmpty4); 2487 mCm.registerNetworkCallback(rFoo, cFoo); 2488 mCm.registerNetworkCallback(rBar, cBar); 2489 2490 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 2491 mWiFiNetworkAgent.connect(false); 2492 cEmpty1.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); 2493 cEmpty2.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); 2494 cEmpty3.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); 2495 cEmpty4.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); 2496 assertNoCallbacks(cFoo, cBar); 2497 2498 mWiFiNetworkAgent.setNetworkSpecifier(new StringNetworkSpecifier("foo")); 2499 cFoo.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); 2500 for (TestNetworkCallback c: emptyCallbacks) { 2501 c.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent); 2502 } 2503 cFoo.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent); 2504 cFoo.assertNoCallback(); 2505 2506 mWiFiNetworkAgent.setNetworkSpecifier(new StringNetworkSpecifier("bar")); 2507 cFoo.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); 2508 cBar.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); 2509 for (TestNetworkCallback c: emptyCallbacks) { 2510 c.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent); 2511 } 2512 cBar.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent); 2513 cBar.assertNoCallback(); 2514 2515 mWiFiNetworkAgent.setNetworkSpecifier(null); 2516 cBar.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); 2517 for (TestNetworkCallback c: emptyCallbacks) { 2518 c.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent); 2519 } 2520 2521 assertNoCallbacks(cEmpty1, cEmpty2, cEmpty3, cFoo, cBar); 2522 } 2523 2524 @Test 2525 public void testInvalidNetworkSpecifier() { 2526 try { 2527 NetworkRequest.Builder builder = new NetworkRequest.Builder(); 2528 builder.setNetworkSpecifier(new MatchAllNetworkSpecifier()); 2529 fail("NetworkRequest builder with MatchAllNetworkSpecifier"); 2530 } catch (IllegalArgumentException expected) { 2531 // expected 2532 } 2533 2534 try { 2535 NetworkCapabilities networkCapabilities = new NetworkCapabilities(); 2536 networkCapabilities.addTransportType(TRANSPORT_WIFI) 2537 .setNetworkSpecifier(new MatchAllNetworkSpecifier()); 2538 mService.requestNetwork(networkCapabilities, null, 0, null, 2539 ConnectivityManager.TYPE_WIFI); 2540 fail("ConnectivityService requestNetwork with MatchAllNetworkSpecifier"); 2541 } catch (IllegalArgumentException expected) { 2542 // expected 2543 } 2544 2545 class NonParcelableSpecifier extends NetworkSpecifier { 2546 public boolean satisfiedBy(NetworkSpecifier other) { return false; } 2547 }; 2548 class ParcelableSpecifier extends NonParcelableSpecifier implements Parcelable { 2549 @Override public int describeContents() { return 0; } 2550 @Override public void writeToParcel(Parcel p, int flags) {} 2551 } 2552 NetworkRequest.Builder builder; 2553 2554 builder = new NetworkRequest.Builder().addTransportType(TRANSPORT_ETHERNET); 2555 try { 2556 builder.setNetworkSpecifier(new NonParcelableSpecifier()); 2557 Parcel parcelW = Parcel.obtain(); 2558 builder.build().writeToParcel(parcelW, 0); 2559 fail("Parceling a non-parcelable specifier did not throw an exception"); 2560 } catch (Exception e) { 2561 // expected 2562 } 2563 2564 builder = new NetworkRequest.Builder().addTransportType(TRANSPORT_ETHERNET); 2565 builder.setNetworkSpecifier(new ParcelableSpecifier()); 2566 NetworkRequest nr = builder.build(); 2567 assertNotNull(nr); 2568 2569 try { 2570 Parcel parcelW = Parcel.obtain(); 2571 nr.writeToParcel(parcelW, 0); 2572 byte[] bytes = parcelW.marshall(); 2573 parcelW.recycle(); 2574 2575 Parcel parcelR = Parcel.obtain(); 2576 parcelR.unmarshall(bytes, 0, bytes.length); 2577 parcelR.setDataPosition(0); 2578 NetworkRequest rereadNr = NetworkRequest.CREATOR.createFromParcel(parcelR); 2579 fail("Unparceling a non-framework NetworkSpecifier did not throw an exception"); 2580 } catch (Exception e) { 2581 // expected 2582 } 2583 } 2584 2585 @Test 2586 public void testNetworkSpecifierUidSpoofSecurityException() { 2587 class UidAwareNetworkSpecifier extends NetworkSpecifier implements Parcelable { 2588 @Override 2589 public boolean satisfiedBy(NetworkSpecifier other) { 2590 return true; 2591 } 2592 2593 @Override 2594 public void assertValidFromUid(int requestorUid) { 2595 throw new SecurityException("failure"); 2596 } 2597 2598 @Override 2599 public int describeContents() { return 0; } 2600 @Override 2601 public void writeToParcel(Parcel dest, int flags) {} 2602 } 2603 2604 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 2605 mWiFiNetworkAgent.connect(false); 2606 2607 UidAwareNetworkSpecifier networkSpecifier = new UidAwareNetworkSpecifier(); 2608 NetworkRequest networkRequest = newWifiRequestBuilder().setNetworkSpecifier( 2609 networkSpecifier).build(); 2610 TestNetworkCallback networkCallback = new TestNetworkCallback(); 2611 try { 2612 mCm.requestNetwork(networkRequest, networkCallback); 2613 fail("Network request with spoofed UID did not throw a SecurityException"); 2614 } catch (SecurityException e) { 2615 // expected 2616 } 2617 } 2618 2619 @Test 2620 public void testRegisterDefaultNetworkCallback() throws Exception { 2621 final TestNetworkCallback defaultNetworkCallback = new TestNetworkCallback(); 2622 mCm.registerDefaultNetworkCallback(defaultNetworkCallback); 2623 defaultNetworkCallback.assertNoCallback(); 2624 2625 // Create a TRANSPORT_CELLULAR request to keep the mobile interface up 2626 // whenever Wi-Fi is up. Without this, the mobile network agent is 2627 // reaped before any other activity can take place. 2628 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback(); 2629 final NetworkRequest cellRequest = new NetworkRequest.Builder() 2630 .addTransportType(TRANSPORT_CELLULAR).build(); 2631 mCm.requestNetwork(cellRequest, cellNetworkCallback); 2632 cellNetworkCallback.assertNoCallback(); 2633 2634 // Bring up cell and expect CALLBACK_AVAILABLE. 2635 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); 2636 mCellNetworkAgent.connect(true); 2637 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); 2638 defaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); 2639 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); 2640 2641 // Bring up wifi and expect CALLBACK_AVAILABLE. 2642 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 2643 mWiFiNetworkAgent.connect(true); 2644 cellNetworkCallback.assertNoCallback(); 2645 defaultNetworkCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent); 2646 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); 2647 2648 // Bring down cell. Expect no default network callback, since it wasn't the default. 2649 mCellNetworkAgent.disconnect(); 2650 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent); 2651 defaultNetworkCallback.assertNoCallback(); 2652 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); 2653 2654 // Bring up cell. Expect no default network callback, since it won't be the default. 2655 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); 2656 mCellNetworkAgent.connect(true); 2657 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); 2658 defaultNetworkCallback.assertNoCallback(); 2659 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); 2660 2661 // Bring down wifi. Expect the default network callback to notified of LOST wifi 2662 // followed by AVAILABLE cell. 2663 mWiFiNetworkAgent.disconnect(); 2664 cellNetworkCallback.assertNoCallback(); 2665 defaultNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); 2666 defaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent); 2667 mCellNetworkAgent.disconnect(); 2668 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent); 2669 defaultNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent); 2670 waitForIdle(); 2671 assertEquals(null, mCm.getActiveNetwork()); 2672 2673 final int uid = Process.myUid(); 2674 final MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN); 2675 final ArraySet<UidRange> ranges = new ArraySet<>(); 2676 ranges.add(new UidRange(uid, uid)); 2677 mMockVpn.setNetworkAgent(vpnNetworkAgent); 2678 mMockVpn.setUids(ranges); 2679 vpnNetworkAgent.connect(true); 2680 mMockVpn.connect(); 2681 defaultNetworkCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent); 2682 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); 2683 2684 vpnNetworkAgent.disconnect(); 2685 defaultNetworkCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent); 2686 waitForIdle(); 2687 assertEquals(null, mCm.getActiveNetwork()); 2688 } 2689 2690 @Test 2691 public void testAdditionalStateCallbacks() throws Exception { 2692 // File a network request for mobile. 2693 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback(); 2694 final NetworkRequest cellRequest = new NetworkRequest.Builder() 2695 .addTransportType(TRANSPORT_CELLULAR).build(); 2696 mCm.requestNetwork(cellRequest, cellNetworkCallback); 2697 2698 // Bring up the mobile network. 2699 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); 2700 mCellNetworkAgent.connect(true); 2701 2702 // We should get onAvailable(), onCapabilitiesChanged(), and 2703 // onLinkPropertiesChanged() in rapid succession. Additionally, we 2704 // should get onCapabilitiesChanged() when the mobile network validates. 2705 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); 2706 cellNetworkCallback.assertNoCallback(); 2707 2708 // Update LinkProperties. 2709 final LinkProperties lp = new LinkProperties(); 2710 lp.setInterfaceName("foonet_data0"); 2711 mCellNetworkAgent.sendLinkProperties(lp); 2712 // We should get onLinkPropertiesChanged(). 2713 cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent); 2714 cellNetworkCallback.assertNoCallback(); 2715 2716 // Suspend the network. 2717 mCellNetworkAgent.suspend(); 2718 cellNetworkCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_SUSPENDED, 2719 mCellNetworkAgent); 2720 cellNetworkCallback.expectCallback(CallbackState.SUSPENDED, mCellNetworkAgent); 2721 cellNetworkCallback.assertNoCallback(); 2722 2723 // Register a garden variety default network request. 2724 TestNetworkCallback dfltNetworkCallback = new TestNetworkCallback(); 2725 mCm.registerDefaultNetworkCallback(dfltNetworkCallback); 2726 // We should get onAvailable(), onCapabilitiesChanged(), onLinkPropertiesChanged(), 2727 // as well as onNetworkSuspended() in rapid succession. 2728 dfltNetworkCallback.expectAvailableAndSuspendedCallbacks(mCellNetworkAgent, true); 2729 dfltNetworkCallback.assertNoCallback(); 2730 mCm.unregisterNetworkCallback(dfltNetworkCallback); 2731 2732 mCellNetworkAgent.resume(); 2733 cellNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_NOT_SUSPENDED, 2734 mCellNetworkAgent); 2735 cellNetworkCallback.expectCallback(CallbackState.RESUMED, mCellNetworkAgent); 2736 cellNetworkCallback.assertNoCallback(); 2737 2738 dfltNetworkCallback = new TestNetworkCallback(); 2739 mCm.registerDefaultNetworkCallback(dfltNetworkCallback); 2740 // This time onNetworkSuspended should not be called. 2741 dfltNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent); 2742 dfltNetworkCallback.assertNoCallback(); 2743 2744 mCm.unregisterNetworkCallback(dfltNetworkCallback); 2745 mCm.unregisterNetworkCallback(cellNetworkCallback); 2746 } 2747 2748 private void setCaptivePortalMode(int mode) { 2749 ContentResolver cr = mServiceContext.getContentResolver(); 2750 Settings.Global.putInt(cr, Settings.Global.CAPTIVE_PORTAL_MODE, mode); 2751 } 2752 2753 private void setMobileDataAlwaysOn(boolean enable) { 2754 ContentResolver cr = mServiceContext.getContentResolver(); 2755 Settings.Global.putInt(cr, Settings.Global.MOBILE_DATA_ALWAYS_ON, enable ? 1 : 0); 2756 mService.updateMobileDataAlwaysOn(); 2757 waitForIdle(); 2758 } 2759 2760 private void setPrivateDnsSettings(String mode, String specifier) { 2761 final ContentResolver cr = mServiceContext.getContentResolver(); 2762 Settings.Global.putString(cr, Settings.Global.PRIVATE_DNS_MODE, mode); 2763 Settings.Global.putString(cr, Settings.Global.PRIVATE_DNS_SPECIFIER, specifier); 2764 mService.updatePrivateDnsSettings(); 2765 waitForIdle(); 2766 } 2767 2768 private boolean isForegroundNetwork(MockNetworkAgent network) { 2769 NetworkCapabilities nc = mCm.getNetworkCapabilities(network.getNetwork()); 2770 assertNotNull(nc); 2771 return nc.hasCapability(NET_CAPABILITY_FOREGROUND); 2772 } 2773 2774 @Test 2775 public void testBackgroundNetworks() throws Exception { 2776 // Create a background request. We can't do this ourselves because ConnectivityService 2777 // doesn't have an API for it. So just turn on mobile data always on. 2778 setMobileDataAlwaysOn(true); 2779 final NetworkRequest request = new NetworkRequest.Builder().build(); 2780 final NetworkRequest fgRequest = new NetworkRequest.Builder() 2781 .addCapability(NET_CAPABILITY_FOREGROUND).build(); 2782 final TestNetworkCallback callback = new TestNetworkCallback(); 2783 final TestNetworkCallback fgCallback = new TestNetworkCallback(); 2784 mCm.registerNetworkCallback(request, callback); 2785 mCm.registerNetworkCallback(fgRequest, fgCallback); 2786 2787 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); 2788 mCellNetworkAgent.connect(true); 2789 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); 2790 fgCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); 2791 assertTrue(isForegroundNetwork(mCellNetworkAgent)); 2792 2793 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 2794 mWiFiNetworkAgent.connect(true); 2795 2796 // When wifi connects, cell lingers. 2797 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); 2798 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent); 2799 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent); 2800 fgCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); 2801 fgCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent); 2802 fgCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent); 2803 assertTrue(isForegroundNetwork(mCellNetworkAgent)); 2804 assertTrue(isForegroundNetwork(mWiFiNetworkAgent)); 2805 2806 // When lingering is complete, cell is still there but is now in the background. 2807 waitForIdle(); 2808 int timeoutMs = TEST_LINGER_DELAY_MS + TEST_LINGER_DELAY_MS / 4; 2809 fgCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent, timeoutMs); 2810 // Expect a network capabilities update sans FOREGROUND. 2811 callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent); 2812 assertFalse(isForegroundNetwork(mCellNetworkAgent)); 2813 assertTrue(isForegroundNetwork(mWiFiNetworkAgent)); 2814 2815 // File a cell request and check that cell comes into the foreground. 2816 final NetworkRequest cellRequest = new NetworkRequest.Builder() 2817 .addTransportType(TRANSPORT_CELLULAR).build(); 2818 final TestNetworkCallback cellCallback = new TestNetworkCallback(); 2819 mCm.requestNetwork(cellRequest, cellCallback); 2820 // NOTE: This request causes the network's capabilities to change. This 2821 // is currently delivered before the onAvailable() callbacks. 2822 // TODO: Fix this. 2823 cellCallback.expectCapabilitiesWith(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent); 2824 cellCallback.expectAvailableCallbacksValidated(mCellNetworkAgent); 2825 fgCallback.expectAvailableCallbacksValidated(mCellNetworkAgent); 2826 // Expect a network capabilities update with FOREGROUND, because the most recent 2827 // request causes its state to change. 2828 callback.expectCapabilitiesWith(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent); 2829 assertTrue(isForegroundNetwork(mCellNetworkAgent)); 2830 assertTrue(isForegroundNetwork(mWiFiNetworkAgent)); 2831 2832 // Release the request. The network immediately goes into the background, since it was not 2833 // lingering. 2834 mCm.unregisterNetworkCallback(cellCallback); 2835 fgCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent); 2836 // Expect a network capabilities update sans FOREGROUND. 2837 callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent); 2838 assertFalse(isForegroundNetwork(mCellNetworkAgent)); 2839 assertTrue(isForegroundNetwork(mWiFiNetworkAgent)); 2840 2841 // Disconnect wifi and check that cell is foreground again. 2842 mWiFiNetworkAgent.disconnect(); 2843 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); 2844 fgCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); 2845 fgCallback.expectAvailableCallbacksValidated(mCellNetworkAgent); 2846 assertTrue(isForegroundNetwork(mCellNetworkAgent)); 2847 2848 mCm.unregisterNetworkCallback(callback); 2849 mCm.unregisterNetworkCallback(fgCallback); 2850 } 2851 2852 @Ignore // This test has instrinsic chances of spurious failures: ignore for continuous testing. 2853 public void benchmarkRequestRegistrationAndCallbackDispatch() throws Exception { 2854 // TODO: turn this unit test into a real benchmarking test. 2855 // Benchmarks connecting and switching performance in the presence of a large number of 2856 // NetworkRequests. 2857 // 1. File NUM_REQUESTS requests. 2858 // 2. Have a network connect. Wait for NUM_REQUESTS onAvailable callbacks to fire. 2859 // 3. Have a new network connect and outscore the previous. Wait for NUM_REQUESTS onLosing 2860 // and NUM_REQUESTS onAvailable callbacks to fire. 2861 // See how long it took. 2862 final int NUM_REQUESTS = 90; 2863 final int REGISTER_TIME_LIMIT_MS = 200; 2864 final int CONNECT_TIME_LIMIT_MS = 60; 2865 final int SWITCH_TIME_LIMIT_MS = 60; 2866 final int UNREGISTER_TIME_LIMIT_MS = 20; 2867 2868 final NetworkRequest request = new NetworkRequest.Builder().clearCapabilities().build(); 2869 final NetworkCallback[] callbacks = new NetworkCallback[NUM_REQUESTS]; 2870 final CountDownLatch availableLatch = new CountDownLatch(NUM_REQUESTS); 2871 final CountDownLatch losingLatch = new CountDownLatch(NUM_REQUESTS); 2872 2873 for (int i = 0; i < NUM_REQUESTS; i++) { 2874 callbacks[i] = new NetworkCallback() { 2875 @Override public void onAvailable(Network n) { availableLatch.countDown(); } 2876 @Override public void onLosing(Network n, int t) { losingLatch.countDown(); } 2877 }; 2878 } 2879 2880 assertTimeLimit("Registering callbacks", REGISTER_TIME_LIMIT_MS, () -> { 2881 for (NetworkCallback cb : callbacks) { 2882 mCm.registerNetworkCallback(request, cb); 2883 } 2884 }); 2885 2886 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); 2887 // Don't request that the network validate, because otherwise connect() will block until 2888 // the network gets NET_CAPABILITY_VALIDATED, after all the callbacks below have fired, 2889 // and we won't actually measure anything. 2890 mCellNetworkAgent.connect(false); 2891 2892 long onAvailableDispatchingDuration = durationOf(() -> { 2893 awaitLatch(availableLatch, 10 * CONNECT_TIME_LIMIT_MS); 2894 }); 2895 Log.d(TAG, String.format("Dispatched %d of %d onAvailable callbacks in %dms", 2896 NUM_REQUESTS - availableLatch.getCount(), NUM_REQUESTS, 2897 onAvailableDispatchingDuration)); 2898 assertTrue(String.format("Dispatching %d onAvailable callbacks in %dms, expected %dms", 2899 NUM_REQUESTS, onAvailableDispatchingDuration, CONNECT_TIME_LIMIT_MS), 2900 onAvailableDispatchingDuration <= CONNECT_TIME_LIMIT_MS); 2901 2902 // Give wifi a high enough score that we'll linger cell when wifi comes up. 2903 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 2904 mWiFiNetworkAgent.adjustScore(40); 2905 mWiFiNetworkAgent.connect(false); 2906 2907 long onLostDispatchingDuration = durationOf(() -> { 2908 awaitLatch(losingLatch, 10 * SWITCH_TIME_LIMIT_MS); 2909 }); 2910 Log.d(TAG, String.format("Dispatched %d of %d onLosing callbacks in %dms", 2911 NUM_REQUESTS - losingLatch.getCount(), NUM_REQUESTS, onLostDispatchingDuration)); 2912 assertTrue(String.format("Dispatching %d onLosing callbacks in %dms, expected %dms", 2913 NUM_REQUESTS, onLostDispatchingDuration, SWITCH_TIME_LIMIT_MS), 2914 onLostDispatchingDuration <= SWITCH_TIME_LIMIT_MS); 2915 2916 assertTimeLimit("Unregistering callbacks", UNREGISTER_TIME_LIMIT_MS, () -> { 2917 for (NetworkCallback cb : callbacks) { 2918 mCm.unregisterNetworkCallback(cb); 2919 } 2920 }); 2921 } 2922 2923 private long durationOf(Runnable fn) { 2924 long startTime = SystemClock.elapsedRealtime(); 2925 fn.run(); 2926 return SystemClock.elapsedRealtime() - startTime; 2927 } 2928 2929 private void assertTimeLimit(String descr, long timeLimit, Runnable fn) { 2930 long timeTaken = durationOf(fn); 2931 String msg = String.format("%s: took %dms, limit was %dms", descr, timeTaken, timeLimit); 2932 Log.d(TAG, msg); 2933 assertTrue(msg, timeTaken <= timeLimit); 2934 } 2935 2936 private boolean awaitLatch(CountDownLatch l, long timeoutMs) { 2937 try { 2938 return l.await(timeoutMs, TimeUnit.MILLISECONDS); 2939 } catch (InterruptedException e) {} 2940 return false; 2941 } 2942 2943 @Test 2944 public void testMobileDataAlwaysOn() throws Exception { 2945 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback(); 2946 final NetworkRequest cellRequest = new NetworkRequest.Builder() 2947 .addTransportType(TRANSPORT_CELLULAR).build(); 2948 mCm.registerNetworkCallback(cellRequest, cellNetworkCallback); 2949 2950 final HandlerThread handlerThread = new HandlerThread("MobileDataAlwaysOnFactory"); 2951 handlerThread.start(); 2952 NetworkCapabilities filter = new NetworkCapabilities() 2953 .addTransportType(TRANSPORT_CELLULAR) 2954 .addCapability(NET_CAPABILITY_INTERNET); 2955 final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(), 2956 mServiceContext, "testFactory", filter); 2957 testFactory.setScoreFilter(40); 2958 2959 // Register the factory and expect it to start looking for a network. 2960 testFactory.expectAddRequests(1); 2961 testFactory.register(); 2962 testFactory.waitForNetworkRequests(1); 2963 assertTrue(testFactory.getMyStartRequested()); 2964 2965 // Bring up wifi. The factory stops looking for a network. 2966 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 2967 testFactory.expectAddRequests(2); // Because the default request changes score twice. 2968 mWiFiNetworkAgent.connect(true); 2969 testFactory.waitForNetworkRequests(1); 2970 assertFalse(testFactory.getMyStartRequested()); 2971 2972 ContentResolver cr = mServiceContext.getContentResolver(); 2973 2974 // Turn on mobile data always on. The factory starts looking again. 2975 testFactory.expectAddRequests(1); 2976 setMobileDataAlwaysOn(true); 2977 testFactory.waitForNetworkRequests(2); 2978 assertTrue(testFactory.getMyStartRequested()); 2979 2980 // Bring up cell data and check that the factory stops looking. 2981 assertLength(1, mCm.getAllNetworks()); 2982 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); 2983 testFactory.expectAddRequests(2); // Because the cell request changes score twice. 2984 mCellNetworkAgent.connect(true); 2985 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); 2986 testFactory.waitForNetworkRequests(2); 2987 assertFalse(testFactory.getMyStartRequested()); // Because the cell network outscores us. 2988 2989 // Check that cell data stays up. 2990 waitForIdle(); 2991 verifyActiveNetwork(TRANSPORT_WIFI); 2992 assertLength(2, mCm.getAllNetworks()); 2993 2994 // Turn off mobile data always on and expect the request to disappear... 2995 testFactory.expectRemoveRequests(1); 2996 setMobileDataAlwaysOn(false); 2997 testFactory.waitForNetworkRequests(1); 2998 2999 // ... and cell data to be torn down. 3000 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent); 3001 assertLength(1, mCm.getAllNetworks()); 3002 3003 testFactory.unregister(); 3004 mCm.unregisterNetworkCallback(cellNetworkCallback); 3005 handlerThread.quit(); 3006 } 3007 3008 @Test 3009 public void testAvoidBadWifiSetting() throws Exception { 3010 final ContentResolver cr = mServiceContext.getContentResolver(); 3011 final WrappedMultinetworkPolicyTracker tracker = mService.getMultinetworkPolicyTracker(); 3012 final String settingName = Settings.Global.NETWORK_AVOID_BAD_WIFI; 3013 3014 tracker.configRestrictsAvoidBadWifi = false; 3015 String[] values = new String[] {null, "0", "1"}; 3016 for (int i = 0; i < values.length; i++) { 3017 Settings.Global.putInt(cr, settingName, 1); 3018 tracker.reevaluate(); 3019 waitForIdle(); 3020 String msg = String.format("config=false, setting=%s", values[i]); 3021 assertTrue(mService.avoidBadWifi()); 3022 assertFalse(msg, tracker.shouldNotifyWifiUnvalidated()); 3023 } 3024 3025 tracker.configRestrictsAvoidBadWifi = true; 3026 3027 Settings.Global.putInt(cr, settingName, 0); 3028 tracker.reevaluate(); 3029 waitForIdle(); 3030 assertFalse(mService.avoidBadWifi()); 3031 assertFalse(tracker.shouldNotifyWifiUnvalidated()); 3032 3033 Settings.Global.putInt(cr, settingName, 1); 3034 tracker.reevaluate(); 3035 waitForIdle(); 3036 assertTrue(mService.avoidBadWifi()); 3037 assertFalse(tracker.shouldNotifyWifiUnvalidated()); 3038 3039 Settings.Global.putString(cr, settingName, null); 3040 tracker.reevaluate(); 3041 waitForIdle(); 3042 assertFalse(mService.avoidBadWifi()); 3043 assertTrue(tracker.shouldNotifyWifiUnvalidated()); 3044 } 3045 3046 @Test 3047 public void testAvoidBadWifi() throws Exception { 3048 final ContentResolver cr = mServiceContext.getContentResolver(); 3049 final WrappedMultinetworkPolicyTracker tracker = mService.getMultinetworkPolicyTracker(); 3050 3051 // Pretend we're on a carrier that restricts switching away from bad wifi. 3052 tracker.configRestrictsAvoidBadWifi = true; 3053 3054 // File a request for cell to ensure it doesn't go down. 3055 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback(); 3056 final NetworkRequest cellRequest = new NetworkRequest.Builder() 3057 .addTransportType(TRANSPORT_CELLULAR).build(); 3058 mCm.requestNetwork(cellRequest, cellNetworkCallback); 3059 3060 TestNetworkCallback defaultCallback = new TestNetworkCallback(); 3061 mCm.registerDefaultNetworkCallback(defaultCallback); 3062 3063 NetworkRequest validatedWifiRequest = new NetworkRequest.Builder() 3064 .addTransportType(TRANSPORT_WIFI) 3065 .addCapability(NET_CAPABILITY_VALIDATED) 3066 .build(); 3067 TestNetworkCallback validatedWifiCallback = new TestNetworkCallback(); 3068 mCm.registerNetworkCallback(validatedWifiRequest, validatedWifiCallback); 3069 3070 Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 0); 3071 tracker.reevaluate(); 3072 3073 // Bring up validated cell. 3074 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); 3075 mCellNetworkAgent.connect(true); 3076 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); 3077 defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); 3078 Network cellNetwork = mCellNetworkAgent.getNetwork(); 3079 3080 // Bring up validated wifi. 3081 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 3082 mWiFiNetworkAgent.connect(true); 3083 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent); 3084 validatedWifiCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent); 3085 Network wifiNetwork = mWiFiNetworkAgent.getNetwork(); 3086 3087 // Fail validation on wifi. 3088 mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 599; 3089 mCm.reportNetworkConnectivity(wifiNetwork, false); 3090 defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent); 3091 validatedWifiCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); 3092 3093 // Because avoid bad wifi is off, we don't switch to cellular. 3094 defaultCallback.assertNoCallback(); 3095 assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability( 3096 NET_CAPABILITY_VALIDATED)); 3097 assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability( 3098 NET_CAPABILITY_VALIDATED)); 3099 assertEquals(mCm.getActiveNetwork(), wifiNetwork); 3100 3101 // Simulate switching to a carrier that does not restrict avoiding bad wifi, and expect 3102 // that we switch back to cell. 3103 tracker.configRestrictsAvoidBadWifi = false; 3104 tracker.reevaluate(); 3105 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent); 3106 assertEquals(mCm.getActiveNetwork(), cellNetwork); 3107 3108 // Switch back to a restrictive carrier. 3109 tracker.configRestrictsAvoidBadWifi = true; 3110 tracker.reevaluate(); 3111 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); 3112 assertEquals(mCm.getActiveNetwork(), wifiNetwork); 3113 3114 // Simulate the user selecting "switch" on the dialog, and check that we switch to cell. 3115 mCm.setAvoidUnvalidated(wifiNetwork); 3116 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent); 3117 assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability( 3118 NET_CAPABILITY_VALIDATED)); 3119 assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability( 3120 NET_CAPABILITY_VALIDATED)); 3121 assertEquals(mCm.getActiveNetwork(), cellNetwork); 3122 3123 // Disconnect and reconnect wifi to clear the one-time switch above. 3124 mWiFiNetworkAgent.disconnect(); 3125 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 3126 mWiFiNetworkAgent.connect(true); 3127 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent); 3128 validatedWifiCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent); 3129 wifiNetwork = mWiFiNetworkAgent.getNetwork(); 3130 3131 // Fail validation on wifi and expect the dialog to appear. 3132 mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 599; 3133 mCm.reportNetworkConnectivity(wifiNetwork, false); 3134 defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent); 3135 validatedWifiCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); 3136 3137 // Simulate the user selecting "switch" and checking the don't ask again checkbox. 3138 Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 1); 3139 tracker.reevaluate(); 3140 3141 // We now switch to cell. 3142 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent); 3143 assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability( 3144 NET_CAPABILITY_VALIDATED)); 3145 assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability( 3146 NET_CAPABILITY_VALIDATED)); 3147 assertEquals(mCm.getActiveNetwork(), cellNetwork); 3148 3149 // Simulate the user turning the cellular fallback setting off and then on. 3150 // We switch to wifi and then to cell. 3151 Settings.Global.putString(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, null); 3152 tracker.reevaluate(); 3153 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); 3154 assertEquals(mCm.getActiveNetwork(), wifiNetwork); 3155 Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 1); 3156 tracker.reevaluate(); 3157 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent); 3158 assertEquals(mCm.getActiveNetwork(), cellNetwork); 3159 3160 // If cell goes down, we switch to wifi. 3161 mCellNetworkAgent.disconnect(); 3162 defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent); 3163 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); 3164 validatedWifiCallback.assertNoCallback(); 3165 3166 mCm.unregisterNetworkCallback(cellNetworkCallback); 3167 mCm.unregisterNetworkCallback(validatedWifiCallback); 3168 mCm.unregisterNetworkCallback(defaultCallback); 3169 } 3170 3171 @Test 3172 public void testMeteredMultipathPreferenceSetting() throws Exception { 3173 final ContentResolver cr = mServiceContext.getContentResolver(); 3174 final WrappedMultinetworkPolicyTracker tracker = mService.getMultinetworkPolicyTracker(); 3175 final String settingName = Settings.Global.NETWORK_METERED_MULTIPATH_PREFERENCE; 3176 3177 for (int config : Arrays.asList(0, 3, 2)) { 3178 for (String setting: Arrays.asList(null, "0", "2", "1")) { 3179 tracker.configMeteredMultipathPreference = config; 3180 Settings.Global.putString(cr, settingName, setting); 3181 tracker.reevaluate(); 3182 waitForIdle(); 3183 3184 final int expected = (setting != null) ? Integer.parseInt(setting) : config; 3185 String msg = String.format("config=%d, setting=%s", config, setting); 3186 assertEquals(msg, expected, mCm.getMultipathPreference(null)); 3187 } 3188 } 3189 } 3190 3191 /** 3192 * Validate that a satisfied network request does not trigger onUnavailable() once the 3193 * time-out period expires. 3194 */ 3195 @Test 3196 public void testSatisfiedNetworkRequestDoesNotTriggerOnUnavailable() { 3197 NetworkRequest nr = new NetworkRequest.Builder().addTransportType( 3198 NetworkCapabilities.TRANSPORT_WIFI).build(); 3199 final TestNetworkCallback networkCallback = new TestNetworkCallback(); 3200 final int timeoutMs = 150; 3201 mCm.requestNetwork(nr, networkCallback, timeoutMs); 3202 3203 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 3204 mWiFiNetworkAgent.connect(false); 3205 networkCallback.expectAvailableCallbacks(mWiFiNetworkAgent, false, false, timeoutMs); 3206 3207 // pass timeout and validate that UNAVAILABLE is not called 3208 networkCallback.assertNoCallback(); 3209 } 3210 3211 /** 3212 * Validate that a satisfied network request followed by a disconnected (lost) network does 3213 * not trigger onUnavailable() once the time-out period expires. 3214 */ 3215 @Test 3216 public void testSatisfiedThenLostNetworkRequestDoesNotTriggerOnUnavailable() { 3217 NetworkRequest nr = new NetworkRequest.Builder().addTransportType( 3218 NetworkCapabilities.TRANSPORT_WIFI).build(); 3219 final TestNetworkCallback networkCallback = new TestNetworkCallback(); 3220 final int requestTimeoutMs = 50; 3221 mCm.requestNetwork(nr, networkCallback, requestTimeoutMs); 3222 3223 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 3224 mWiFiNetworkAgent.connect(false); 3225 final int assertTimeoutMs = 100; 3226 networkCallback.expectAvailableCallbacks(mWiFiNetworkAgent, false, false, assertTimeoutMs); 3227 mWiFiNetworkAgent.disconnect(); 3228 networkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); 3229 3230 // Validate that UNAVAILABLE is not called 3231 networkCallback.assertNoCallback(); 3232 } 3233 3234 /** 3235 * Validate that when a time-out is specified for a network request the onUnavailable() 3236 * callback is called when time-out expires. Then validate that if network request is 3237 * (somehow) satisfied - the callback isn't called later. 3238 */ 3239 @Test 3240 public void testTimedoutNetworkRequest() { 3241 NetworkRequest nr = new NetworkRequest.Builder().addTransportType( 3242 NetworkCapabilities.TRANSPORT_WIFI).build(); 3243 final TestNetworkCallback networkCallback = new TestNetworkCallback(); 3244 final int timeoutMs = 10; 3245 mCm.requestNetwork(nr, networkCallback, timeoutMs); 3246 3247 // pass timeout and validate that UNAVAILABLE is called 3248 networkCallback.expectCallback(CallbackState.UNAVAILABLE, null); 3249 3250 // create a network satisfying request - validate that request not triggered 3251 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 3252 mWiFiNetworkAgent.connect(false); 3253 networkCallback.assertNoCallback(); 3254 } 3255 3256 /** 3257 * Validate that when a network request is unregistered (cancelled), no posterior event can 3258 * trigger the callback. 3259 */ 3260 @Test 3261 public void testNoCallbackAfterUnregisteredNetworkRequest() { 3262 NetworkRequest nr = new NetworkRequest.Builder().addTransportType( 3263 NetworkCapabilities.TRANSPORT_WIFI).build(); 3264 final TestNetworkCallback networkCallback = new TestNetworkCallback(); 3265 final int timeoutMs = 10; 3266 3267 mCm.requestNetwork(nr, networkCallback, timeoutMs); 3268 mCm.unregisterNetworkCallback(networkCallback); 3269 // Regardless of the timeout, unregistering the callback in ConnectivityManager ensures 3270 // that this callback will not be called. 3271 networkCallback.assertNoCallback(); 3272 3273 // create a network satisfying request - validate that request not triggered 3274 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 3275 mWiFiNetworkAgent.connect(false); 3276 networkCallback.assertNoCallback(); 3277 } 3278 3279 private static class TestKeepaliveCallback extends PacketKeepaliveCallback { 3280 3281 public static enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR }; 3282 3283 private class CallbackValue { 3284 public CallbackType callbackType; 3285 public int error; 3286 3287 public CallbackValue(CallbackType type) { 3288 this.callbackType = type; 3289 this.error = PacketKeepalive.SUCCESS; 3290 assertTrue("onError callback must have error", type != CallbackType.ON_ERROR); 3291 } 3292 3293 public CallbackValue(CallbackType type, int error) { 3294 this.callbackType = type; 3295 this.error = error; 3296 assertEquals("error can only be set for onError", type, CallbackType.ON_ERROR); 3297 } 3298 3299 @Override 3300 public boolean equals(Object o) { 3301 return o instanceof CallbackValue && 3302 this.callbackType == ((CallbackValue) o).callbackType && 3303 this.error == ((CallbackValue) o).error; 3304 } 3305 3306 @Override 3307 public String toString() { 3308 return String.format("%s(%s, %d)", getClass().getSimpleName(), callbackType, error); 3309 } 3310 } 3311 3312 private LinkedBlockingQueue<CallbackValue> mCallbacks = new LinkedBlockingQueue<>(); 3313 3314 @Override 3315 public void onStarted() { 3316 mCallbacks.add(new CallbackValue(CallbackType.ON_STARTED)); 3317 } 3318 3319 @Override 3320 public void onStopped() { 3321 mCallbacks.add(new CallbackValue(CallbackType.ON_STOPPED)); 3322 } 3323 3324 @Override 3325 public void onError(int error) { 3326 mCallbacks.add(new CallbackValue(CallbackType.ON_ERROR, error)); 3327 } 3328 3329 private void expectCallback(CallbackValue callbackValue) { 3330 try { 3331 assertEquals( 3332 callbackValue, 3333 mCallbacks.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS)); 3334 } catch (InterruptedException e) { 3335 fail(callbackValue.callbackType + " callback not seen after " + TIMEOUT_MS + " ms"); 3336 } 3337 } 3338 3339 public void expectStarted() { 3340 expectCallback(new CallbackValue(CallbackType.ON_STARTED)); 3341 } 3342 3343 public void expectStopped() { 3344 expectCallback(new CallbackValue(CallbackType.ON_STOPPED)); 3345 } 3346 3347 public void expectError(int error) { 3348 expectCallback(new CallbackValue(CallbackType.ON_ERROR, error)); 3349 } 3350 } 3351 3352 private Network connectKeepaliveNetwork(LinkProperties lp) { 3353 // Ensure the network is disconnected before we do anything. 3354 if (mWiFiNetworkAgent != null) { 3355 assertNull(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork())); 3356 } 3357 3358 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 3359 ConditionVariable cv = waitForConnectivityBroadcasts(1); 3360 mWiFiNetworkAgent.connect(true); 3361 waitFor(cv); 3362 verifyActiveNetwork(TRANSPORT_WIFI); 3363 mWiFiNetworkAgent.sendLinkProperties(lp); 3364 waitForIdle(); 3365 return mWiFiNetworkAgent.getNetwork(); 3366 } 3367 3368 @Test 3369 public void testPacketKeepalives() throws Exception { 3370 InetAddress myIPv4 = InetAddress.getByName("192.0.2.129"); 3371 InetAddress notMyIPv4 = InetAddress.getByName("192.0.2.35"); 3372 InetAddress myIPv6 = InetAddress.getByName("2001:db8::1"); 3373 InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8"); 3374 InetAddress dstIPv6 = InetAddress.getByName("2001:4860:4860::8888"); 3375 3376 final int validKaInterval = 15; 3377 final int invalidKaInterval = 9; 3378 3379 LinkProperties lp = new LinkProperties(); 3380 lp.setInterfaceName("wlan12"); 3381 lp.addLinkAddress(new LinkAddress(myIPv6, 64)); 3382 lp.addLinkAddress(new LinkAddress(myIPv4, 25)); 3383 lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234"))); 3384 lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254"))); 3385 3386 Network notMyNet = new Network(61234); 3387 Network myNet = connectKeepaliveNetwork(lp); 3388 3389 TestKeepaliveCallback callback = new TestKeepaliveCallback(); 3390 PacketKeepalive ka; 3391 3392 // Attempt to start keepalives with invalid parameters and check for errors. 3393 ka = mCm.startNattKeepalive(notMyNet, validKaInterval, callback, myIPv4, 1234, dstIPv4); 3394 callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK); 3395 3396 ka = mCm.startNattKeepalive(myNet, invalidKaInterval, callback, myIPv4, 1234, dstIPv4); 3397 callback.expectError(PacketKeepalive.ERROR_INVALID_INTERVAL); 3398 3399 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 1234, dstIPv6); 3400 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS); 3401 3402 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv6, 1234, dstIPv4); 3403 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS); 3404 3405 // NAT-T is only supported for IPv4. 3406 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv6, 1234, dstIPv6); 3407 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS); 3408 3409 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 123456, dstIPv4); 3410 callback.expectError(PacketKeepalive.ERROR_INVALID_PORT); 3411 3412 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 123456, dstIPv4); 3413 callback.expectError(PacketKeepalive.ERROR_INVALID_PORT); 3414 3415 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4); 3416 callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED); 3417 3418 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4); 3419 callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED); 3420 3421 // Check that a started keepalive can be stopped. 3422 mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS); 3423 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4); 3424 callback.expectStarted(); 3425 mWiFiNetworkAgent.setStopKeepaliveError(PacketKeepalive.SUCCESS); 3426 ka.stop(); 3427 callback.expectStopped(); 3428 3429 // Check that deleting the IP address stops the keepalive. 3430 LinkProperties bogusLp = new LinkProperties(lp); 3431 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4); 3432 callback.expectStarted(); 3433 bogusLp.removeLinkAddress(new LinkAddress(myIPv4, 25)); 3434 bogusLp.addLinkAddress(new LinkAddress(notMyIPv4, 25)); 3435 mWiFiNetworkAgent.sendLinkProperties(bogusLp); 3436 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS); 3437 mWiFiNetworkAgent.sendLinkProperties(lp); 3438 3439 // Check that a started keepalive is stopped correctly when the network disconnects. 3440 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4); 3441 callback.expectStarted(); 3442 mWiFiNetworkAgent.disconnect(); 3443 waitFor(mWiFiNetworkAgent.getDisconnectedCV()); 3444 callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK); 3445 3446 // ... and that stopping it after that has no adverse effects. 3447 waitForIdle(); 3448 final Network myNetAlias = myNet; 3449 assertNull(mCm.getNetworkCapabilities(myNetAlias)); 3450 ka.stop(); 3451 3452 // Reconnect. 3453 myNet = connectKeepaliveNetwork(lp); 3454 mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS); 3455 3456 // Check things work as expected when the keepalive is stopped and the network disconnects. 3457 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4); 3458 callback.expectStarted(); 3459 ka.stop(); 3460 mWiFiNetworkAgent.disconnect(); 3461 waitFor(mWiFiNetworkAgent.getDisconnectedCV()); 3462 waitForIdle(); 3463 callback.expectStopped(); 3464 3465 // Reconnect. 3466 myNet = connectKeepaliveNetwork(lp); 3467 mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS); 3468 3469 // Check that keepalive slots start from 1 and increment. The first one gets slot 1. 3470 mWiFiNetworkAgent.setExpectedKeepaliveSlot(1); 3471 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4); 3472 callback.expectStarted(); 3473 3474 // The second one gets slot 2. 3475 mWiFiNetworkAgent.setExpectedKeepaliveSlot(2); 3476 TestKeepaliveCallback callback2 = new TestKeepaliveCallback(); 3477 PacketKeepalive ka2 = mCm.startNattKeepalive( 3478 myNet, validKaInterval, callback2, myIPv4, 6789, dstIPv4); 3479 callback2.expectStarted(); 3480 3481 // Now stop the first one and create a third. This also gets slot 1. 3482 ka.stop(); 3483 callback.expectStopped(); 3484 3485 mWiFiNetworkAgent.setExpectedKeepaliveSlot(1); 3486 TestKeepaliveCallback callback3 = new TestKeepaliveCallback(); 3487 PacketKeepalive ka3 = mCm.startNattKeepalive( 3488 myNet, validKaInterval, callback3, myIPv4, 9876, dstIPv4); 3489 callback3.expectStarted(); 3490 3491 ka2.stop(); 3492 callback2.expectStopped(); 3493 3494 ka3.stop(); 3495 callback3.expectStopped(); 3496 } 3497 3498 @Test 3499 public void testGetCaptivePortalServerUrl() throws Exception { 3500 String url = mCm.getCaptivePortalServerUrl(); 3501 assertEquals("http://connectivitycheck.gstatic.com/generate_204", url); 3502 } 3503 3504 private static class TestNetworkPinner extends NetworkPinner { 3505 public static boolean awaitPin(int timeoutMs) { 3506 synchronized(sLock) { 3507 if (sNetwork == null) { 3508 try { 3509 sLock.wait(timeoutMs); 3510 } catch (InterruptedException e) {} 3511 } 3512 return sNetwork != null; 3513 } 3514 } 3515 3516 public static boolean awaitUnpin(int timeoutMs) { 3517 synchronized(sLock) { 3518 if (sNetwork != null) { 3519 try { 3520 sLock.wait(timeoutMs); 3521 } catch (InterruptedException e) {} 3522 } 3523 return sNetwork == null; 3524 } 3525 } 3526 } 3527 3528 private void assertPinnedToWifiWithCellDefault() { 3529 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess()); 3530 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 3531 } 3532 3533 private void assertPinnedToWifiWithWifiDefault() { 3534 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess()); 3535 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 3536 } 3537 3538 private void assertNotPinnedToWifi() { 3539 assertNull(mCm.getBoundNetworkForProcess()); 3540 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 3541 } 3542 3543 @Test 3544 public void testNetworkPinner() { 3545 NetworkRequest wifiRequest = new NetworkRequest.Builder() 3546 .addTransportType(TRANSPORT_WIFI) 3547 .build(); 3548 assertNull(mCm.getBoundNetworkForProcess()); 3549 3550 TestNetworkPinner.pin(mServiceContext, wifiRequest); 3551 assertNull(mCm.getBoundNetworkForProcess()); 3552 3553 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); 3554 mCellNetworkAgent.connect(true); 3555 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 3556 mWiFiNetworkAgent.connect(false); 3557 3558 // When wi-fi connects, expect to be pinned. 3559 assertTrue(TestNetworkPinner.awaitPin(100)); 3560 assertPinnedToWifiWithCellDefault(); 3561 3562 // Disconnect and expect the pin to drop. 3563 mWiFiNetworkAgent.disconnect(); 3564 assertTrue(TestNetworkPinner.awaitUnpin(100)); 3565 assertNotPinnedToWifi(); 3566 3567 // Reconnecting does not cause the pin to come back. 3568 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 3569 mWiFiNetworkAgent.connect(false); 3570 assertFalse(TestNetworkPinner.awaitPin(100)); 3571 assertNotPinnedToWifi(); 3572 3573 // Pinning while connected causes the pin to take effect immediately. 3574 TestNetworkPinner.pin(mServiceContext, wifiRequest); 3575 assertTrue(TestNetworkPinner.awaitPin(100)); 3576 assertPinnedToWifiWithCellDefault(); 3577 3578 // Explicitly unpin and expect to use the default network again. 3579 TestNetworkPinner.unpin(); 3580 assertNotPinnedToWifi(); 3581 3582 // Disconnect cell and wifi. 3583 ConditionVariable cv = waitForConnectivityBroadcasts(3); // cell down, wifi up, wifi down. 3584 mCellNetworkAgent.disconnect(); 3585 mWiFiNetworkAgent.disconnect(); 3586 waitFor(cv); 3587 3588 // Pinning takes effect even if the pinned network is the default when the pin is set... 3589 TestNetworkPinner.pin(mServiceContext, wifiRequest); 3590 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 3591 mWiFiNetworkAgent.connect(false); 3592 assertTrue(TestNetworkPinner.awaitPin(100)); 3593 assertPinnedToWifiWithWifiDefault(); 3594 3595 // ... and is maintained even when that network is no longer the default. 3596 cv = waitForConnectivityBroadcasts(1); 3597 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 3598 mCellNetworkAgent.connect(true); 3599 waitFor(cv); 3600 assertPinnedToWifiWithCellDefault(); 3601 } 3602 3603 @Test 3604 public void testNetworkCallbackMaximum() { 3605 // We can only have 99 callbacks, because MultipathPolicyTracker is 3606 // already one of them. 3607 final int MAX_REQUESTS = 99; 3608 final int CALLBACKS = 89; 3609 final int INTENTS = 10; 3610 assertEquals(MAX_REQUESTS, CALLBACKS + INTENTS); 3611 3612 NetworkRequest networkRequest = new NetworkRequest.Builder().build(); 3613 ArrayList<Object> registered = new ArrayList<>(); 3614 3615 int j = 0; 3616 while (j++ < CALLBACKS / 2) { 3617 NetworkCallback cb = new NetworkCallback(); 3618 mCm.requestNetwork(networkRequest, cb); 3619 registered.add(cb); 3620 } 3621 while (j++ < CALLBACKS) { 3622 NetworkCallback cb = new NetworkCallback(); 3623 mCm.registerNetworkCallback(networkRequest, cb); 3624 registered.add(cb); 3625 } 3626 j = 0; 3627 while (j++ < INTENTS / 2) { 3628 PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, new Intent("a" + j), 0); 3629 mCm.requestNetwork(networkRequest, pi); 3630 registered.add(pi); 3631 } 3632 while (j++ < INTENTS) { 3633 PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, new Intent("b" + j), 0); 3634 mCm.registerNetworkCallback(networkRequest, pi); 3635 registered.add(pi); 3636 } 3637 3638 // Test that the limit is enforced when MAX_REQUESTS simultaneous requests are added. 3639 try { 3640 mCm.requestNetwork(networkRequest, new NetworkCallback()); 3641 fail("Registering " + MAX_REQUESTS + " network requests did not throw exception"); 3642 } catch (TooManyRequestsException expected) {} 3643 try { 3644 mCm.registerNetworkCallback(networkRequest, new NetworkCallback()); 3645 fail("Registering " + MAX_REQUESTS + " network callbacks did not throw exception"); 3646 } catch (TooManyRequestsException expected) {} 3647 try { 3648 mCm.requestNetwork(networkRequest, 3649 PendingIntent.getBroadcast(mContext, 0, new Intent("c"), 0)); 3650 fail("Registering " + MAX_REQUESTS + " PendingIntent requests did not throw exception"); 3651 } catch (TooManyRequestsException expected) {} 3652 try { 3653 mCm.registerNetworkCallback(networkRequest, 3654 PendingIntent.getBroadcast(mContext, 0, new Intent("d"), 0)); 3655 fail("Registering " + MAX_REQUESTS 3656 + " PendingIntent callbacks did not throw exception"); 3657 } catch (TooManyRequestsException expected) {} 3658 3659 for (Object o : registered) { 3660 if (o instanceof NetworkCallback) { 3661 mCm.unregisterNetworkCallback((NetworkCallback)o); 3662 } 3663 if (o instanceof PendingIntent) { 3664 mCm.unregisterNetworkCallback((PendingIntent)o); 3665 } 3666 } 3667 waitForIdle(); 3668 3669 // Test that the limit is not hit when MAX_REQUESTS requests are added and removed. 3670 for (int i = 0; i < MAX_REQUESTS; i++) { 3671 NetworkCallback networkCallback = new NetworkCallback(); 3672 mCm.requestNetwork(networkRequest, networkCallback); 3673 mCm.unregisterNetworkCallback(networkCallback); 3674 } 3675 waitForIdle(); 3676 3677 for (int i = 0; i < MAX_REQUESTS; i++) { 3678 NetworkCallback networkCallback = new NetworkCallback(); 3679 mCm.registerNetworkCallback(networkRequest, networkCallback); 3680 mCm.unregisterNetworkCallback(networkCallback); 3681 } 3682 waitForIdle(); 3683 3684 for (int i = 0; i < MAX_REQUESTS; i++) { 3685 PendingIntent pendingIntent = 3686 PendingIntent.getBroadcast(mContext, 0, new Intent("e" + i), 0); 3687 mCm.requestNetwork(networkRequest, pendingIntent); 3688 mCm.unregisterNetworkCallback(pendingIntent); 3689 } 3690 waitForIdle(); 3691 3692 for (int i = 0; i < MAX_REQUESTS; i++) { 3693 PendingIntent pendingIntent = 3694 PendingIntent.getBroadcast(mContext, 0, new Intent("f" + i), 0); 3695 mCm.registerNetworkCallback(networkRequest, pendingIntent); 3696 mCm.unregisterNetworkCallback(pendingIntent); 3697 } 3698 } 3699 3700 @Test 3701 public void testNetworkInfoOfTypeNone() { 3702 ConditionVariable broadcastCV = waitForConnectivityBroadcasts(1); 3703 3704 verifyNoNetwork(); 3705 MockNetworkAgent wifiAware = new MockNetworkAgent(TRANSPORT_WIFI_AWARE); 3706 assertNull(mCm.getActiveNetworkInfo()); 3707 3708 Network[] allNetworks = mCm.getAllNetworks(); 3709 assertLength(1, allNetworks); 3710 Network network = allNetworks[0]; 3711 NetworkCapabilities capabilities = mCm.getNetworkCapabilities(network); 3712 assertTrue(capabilities.hasTransport(TRANSPORT_WIFI_AWARE)); 3713 3714 final NetworkRequest request = 3715 new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI_AWARE).build(); 3716 final TestNetworkCallback callback = new TestNetworkCallback(); 3717 mCm.registerNetworkCallback(request, callback); 3718 3719 // Bring up wifi aware network. 3720 wifiAware.connect(false, false); 3721 callback.expectAvailableCallbacksUnvalidated(wifiAware); 3722 3723 assertNull(mCm.getActiveNetworkInfo()); 3724 assertNull(mCm.getActiveNetwork()); 3725 // TODO: getAllNetworkInfo is dirty and returns a non-empty array right from the start 3726 // of this test. Fix it and uncomment the assert below. 3727 //assertEmpty(mCm.getAllNetworkInfo()); 3728 3729 // Disconnect wifi aware network. 3730 wifiAware.disconnect(); 3731 callback.expectCallbackLike((info) -> info.state == CallbackState.LOST, TIMEOUT_MS); 3732 mCm.unregisterNetworkCallback(callback); 3733 3734 verifyNoNetwork(); 3735 if (broadcastCV.block(10)) { 3736 fail("expected no broadcast, but got CONNECTIVITY_ACTION broadcast"); 3737 } 3738 } 3739 3740 @Test 3741 public void testDeprecatedAndUnsupportedOperations() throws Exception { 3742 final int TYPE_NONE = ConnectivityManager.TYPE_NONE; 3743 assertNull(mCm.getNetworkInfo(TYPE_NONE)); 3744 assertNull(mCm.getNetworkForType(TYPE_NONE)); 3745 assertNull(mCm.getLinkProperties(TYPE_NONE)); 3746 assertFalse(mCm.isNetworkSupported(TYPE_NONE)); 3747 3748 assertException(() -> { mCm.networkCapabilitiesForType(TYPE_NONE); }, 3749 IllegalArgumentException.class); 3750 3751 Class<UnsupportedOperationException> unsupported = UnsupportedOperationException.class; 3752 assertException(() -> { mCm.startUsingNetworkFeature(TYPE_WIFI, ""); }, unsupported); 3753 assertException(() -> { mCm.stopUsingNetworkFeature(TYPE_WIFI, ""); }, unsupported); 3754 // TODO: let test context have configuration application target sdk version 3755 // and test that pre-M requesting for TYPE_NONE sends back APN_REQUEST_FAILED 3756 assertException(() -> { mCm.startUsingNetworkFeature(TYPE_NONE, ""); }, unsupported); 3757 assertException(() -> { mCm.stopUsingNetworkFeature(TYPE_NONE, ""); }, unsupported); 3758 assertException(() -> { mCm.requestRouteToHostAddress(TYPE_NONE, null); }, unsupported); 3759 } 3760 3761 @Test 3762 public void testLinkPropertiesEnsuresDirectlyConnectedRoutes() { 3763 final NetworkRequest networkRequest = new NetworkRequest.Builder() 3764 .addTransportType(TRANSPORT_WIFI).build(); 3765 final TestNetworkCallback networkCallback = new TestNetworkCallback(); 3766 mCm.registerNetworkCallback(networkRequest, networkCallback); 3767 3768 LinkProperties lp = new LinkProperties(); 3769 lp.setInterfaceName(WIFI_IFNAME); 3770 LinkAddress myIpv4Address = new LinkAddress("192.168.12.3/24"); 3771 RouteInfo myIpv4DefaultRoute = new RouteInfo((IpPrefix) null, 3772 NetworkUtils.numericToInetAddress("192.168.12.1"), lp.getInterfaceName()); 3773 lp.addLinkAddress(myIpv4Address); 3774 lp.addRoute(myIpv4DefaultRoute); 3775 3776 // Verify direct routes are added when network agent is first registered in 3777 // ConnectivityService. 3778 MockNetworkAgent networkAgent = new MockNetworkAgent(TRANSPORT_WIFI, lp); 3779 networkAgent.connect(true); 3780 networkCallback.expectCallback(CallbackState.AVAILABLE, networkAgent); 3781 networkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, networkAgent); 3782 CallbackInfo cbi = networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, 3783 networkAgent); 3784 networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, networkAgent); 3785 networkCallback.assertNoCallback(); 3786 checkDirectlyConnectedRoutes(cbi.arg, Arrays.asList(myIpv4Address), 3787 Arrays.asList(myIpv4DefaultRoute)); 3788 checkDirectlyConnectedRoutes(mCm.getLinkProperties(networkAgent.getNetwork()), 3789 Arrays.asList(myIpv4Address), Arrays.asList(myIpv4DefaultRoute)); 3790 3791 // Verify direct routes are added during subsequent link properties updates. 3792 LinkProperties newLp = new LinkProperties(lp); 3793 LinkAddress myIpv6Address1 = new LinkAddress("fe80::cafe/64"); 3794 LinkAddress myIpv6Address2 = new LinkAddress("2001:db8::2/64"); 3795 newLp.addLinkAddress(myIpv6Address1); 3796 newLp.addLinkAddress(myIpv6Address2); 3797 networkAgent.sendLinkProperties(newLp); 3798 cbi = networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, networkAgent); 3799 networkCallback.assertNoCallback(); 3800 checkDirectlyConnectedRoutes(cbi.arg, 3801 Arrays.asList(myIpv4Address, myIpv6Address1, myIpv6Address2), 3802 Arrays.asList(myIpv4DefaultRoute)); 3803 mCm.unregisterNetworkCallback(networkCallback); 3804 } 3805 3806 @Test 3807 public void testStatsIfacesChanged() throws Exception { 3808 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); 3809 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 3810 3811 Network[] onlyCell = new Network[]{mCellNetworkAgent.getNetwork()}; 3812 Network[] onlyWifi = new Network[]{mWiFiNetworkAgent.getNetwork()}; 3813 3814 // Simple connection should have updated ifaces 3815 mCellNetworkAgent.connect(false); 3816 waitForIdle(); 3817 verify(mStatsService, atLeastOnce()).forceUpdateIfaces(onlyCell); 3818 reset(mStatsService); 3819 3820 // Default network switch should update ifaces. 3821 mWiFiNetworkAgent.connect(false); 3822 waitForIdle(); 3823 verify(mStatsService, atLeastOnce()).forceUpdateIfaces(onlyWifi); 3824 reset(mStatsService); 3825 3826 // Disconnect should update ifaces. 3827 mWiFiNetworkAgent.disconnect(); 3828 waitForIdle(); 3829 verify(mStatsService, atLeastOnce()).forceUpdateIfaces(onlyCell); 3830 reset(mStatsService); 3831 3832 // Metered change should update ifaces 3833 mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED); 3834 waitForIdle(); 3835 verify(mStatsService, atLeastOnce()).forceUpdateIfaces(onlyCell); 3836 reset(mStatsService); 3837 3838 mCellNetworkAgent.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED); 3839 waitForIdle(); 3840 verify(mStatsService, atLeastOnce()).forceUpdateIfaces(onlyCell); 3841 reset(mStatsService); 3842 3843 // Captive portal change shouldn't update ifaces 3844 mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL); 3845 waitForIdle(); 3846 verify(mStatsService, never()).forceUpdateIfaces(onlyCell); 3847 reset(mStatsService); 3848 3849 // Roaming change should update ifaces 3850 mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING); 3851 waitForIdle(); 3852 verify(mStatsService, atLeastOnce()).forceUpdateIfaces(onlyCell); 3853 reset(mStatsService); 3854 } 3855 3856 @Test 3857 public void testBasicDnsConfigurationPushed() throws Exception { 3858 setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com"); 3859 ArgumentCaptor<String[]> tlsServers = ArgumentCaptor.forClass(String[].class); 3860 3861 // Clear any interactions that occur as a result of CS starting up. 3862 reset(mNetworkManagementService); 3863 3864 final String[] EMPTY_STRING_ARRAY = new String[0]; 3865 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); 3866 waitForIdle(); 3867 verify(mNetworkManagementService, never()).setDnsConfigurationForNetwork( 3868 anyInt(), eq(EMPTY_STRING_ARRAY), any(), any(), eq(""), eq(EMPTY_STRING_ARRAY)); 3869 verifyNoMoreInteractions(mNetworkManagementService); 3870 3871 final LinkProperties cellLp = new LinkProperties(); 3872 cellLp.setInterfaceName(MOBILE_IFNAME); 3873 // Add IPv4 and IPv6 default routes, because DNS-over-TLS code does 3874 // "is-reachable" testing in order to not program netd with unreachable 3875 // nameservers that it might try repeated to validate. 3876 cellLp.addLinkAddress(new LinkAddress("192.0.2.4/24")); 3877 cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("192.0.2.4"), 3878 MOBILE_IFNAME)); 3879 cellLp.addLinkAddress(new LinkAddress("2001:db8:1::1/64")); 3880 cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("2001:db8:1::1"), 3881 MOBILE_IFNAME)); 3882 mCellNetworkAgent.sendLinkProperties(cellLp); 3883 mCellNetworkAgent.connect(false); 3884 waitForIdle(); 3885 // CS tells netd about the empty DNS config for this network. 3886 verify(mNetworkManagementService, atLeastOnce()).setDnsConfigurationForNetwork( 3887 anyInt(), eq(EMPTY_STRING_ARRAY), any(), any(), eq(""), eq(EMPTY_STRING_ARRAY)); 3888 reset(mNetworkManagementService); 3889 3890 cellLp.addDnsServer(InetAddress.getByName("2001:db8::1")); 3891 mCellNetworkAgent.sendLinkProperties(cellLp); 3892 waitForIdle(); 3893 verify(mNetworkManagementService, atLeastOnce()).setDnsConfigurationForNetwork( 3894 anyInt(), mStringArrayCaptor.capture(), any(), any(), 3895 eq(""), tlsServers.capture()); 3896 assertEquals(1, mStringArrayCaptor.getValue().length); 3897 assertTrue(ArrayUtils.contains(mStringArrayCaptor.getValue(), "2001:db8::1")); 3898 // Opportunistic mode. 3899 assertTrue(ArrayUtils.contains(tlsServers.getValue(), "2001:db8::1")); 3900 reset(mNetworkManagementService); 3901 3902 cellLp.addDnsServer(InetAddress.getByName("192.0.2.1")); 3903 mCellNetworkAgent.sendLinkProperties(cellLp); 3904 waitForIdle(); 3905 verify(mNetworkManagementService, atLeastOnce()).setDnsConfigurationForNetwork( 3906 anyInt(), mStringArrayCaptor.capture(), any(), any(), 3907 eq(""), tlsServers.capture()); 3908 assertEquals(2, mStringArrayCaptor.getValue().length); 3909 assertTrue(ArrayUtils.containsAll(mStringArrayCaptor.getValue(), 3910 new String[]{"2001:db8::1", "192.0.2.1"})); 3911 // Opportunistic mode. 3912 assertEquals(2, tlsServers.getValue().length); 3913 assertTrue(ArrayUtils.containsAll(tlsServers.getValue(), 3914 new String[]{"2001:db8::1", "192.0.2.1"})); 3915 reset(mNetworkManagementService); 3916 3917 final String TLS_SPECIFIER = "tls.example.com"; 3918 final String TLS_SERVER6 = "2001:db8:53::53"; 3919 final InetAddress[] TLS_IPS = new InetAddress[]{ InetAddress.getByName(TLS_SERVER6) }; 3920 final String[] TLS_SERVERS = new String[]{ TLS_SERVER6 }; 3921 final Handler h = mCellNetworkAgent.getWrappedNetworkMonitor().connectivityHandler; 3922 h.sendMessage(h.obtainMessage( 3923 NetworkMonitor.EVENT_PRIVATE_DNS_CONFIG_RESOLVED, 0, 3924 mCellNetworkAgent.getNetwork().netId, 3925 new DnsManager.PrivateDnsConfig(TLS_SPECIFIER, TLS_IPS))); 3926 waitForIdle(); 3927 verify(mNetworkManagementService, atLeastOnce()).setDnsConfigurationForNetwork( 3928 anyInt(), mStringArrayCaptor.capture(), any(), any(), 3929 eq(TLS_SPECIFIER), eq(TLS_SERVERS)); 3930 assertEquals(2, mStringArrayCaptor.getValue().length); 3931 assertTrue(ArrayUtils.containsAll(mStringArrayCaptor.getValue(), 3932 new String[]{"2001:db8::1", "192.0.2.1"})); 3933 reset(mNetworkManagementService); 3934 } 3935 3936 @Test 3937 public void testPrivateDnsSettingsChange() throws Exception { 3938 final String[] EMPTY_STRING_ARRAY = new String[0]; 3939 ArgumentCaptor<String[]> tlsServers = ArgumentCaptor.forClass(String[].class); 3940 3941 // Clear any interactions that occur as a result of CS starting up. 3942 reset(mNetworkManagementService); 3943 3944 // The default on Android is opportunistic mode ("Automatic"). 3945 setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com"); 3946 3947 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback(); 3948 final NetworkRequest cellRequest = new NetworkRequest.Builder() 3949 .addTransportType(TRANSPORT_CELLULAR).build(); 3950 mCm.requestNetwork(cellRequest, cellNetworkCallback); 3951 3952 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); 3953 waitForIdle(); 3954 // CS tells netd about the empty DNS config for this network. 3955 verify(mNetworkManagementService, never()).setDnsConfigurationForNetwork( 3956 anyInt(), eq(EMPTY_STRING_ARRAY), any(), any(), eq(""), eq(EMPTY_STRING_ARRAY)); 3957 verifyNoMoreInteractions(mNetworkManagementService); 3958 3959 final LinkProperties cellLp = new LinkProperties(); 3960 cellLp.setInterfaceName(MOBILE_IFNAME); 3961 // Add IPv4 and IPv6 default routes, because DNS-over-TLS code does 3962 // "is-reachable" testing in order to not program netd with unreachable 3963 // nameservers that it might try repeated to validate. 3964 cellLp.addLinkAddress(new LinkAddress("192.0.2.4/24")); 3965 cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("192.0.2.4"), 3966 MOBILE_IFNAME)); 3967 cellLp.addLinkAddress(new LinkAddress("2001:db8:1::1/64")); 3968 cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("2001:db8:1::1"), 3969 MOBILE_IFNAME)); 3970 cellLp.addDnsServer(InetAddress.getByName("2001:db8::1")); 3971 cellLp.addDnsServer(InetAddress.getByName("192.0.2.1")); 3972 3973 mCellNetworkAgent.sendLinkProperties(cellLp); 3974 mCellNetworkAgent.connect(false); 3975 waitForIdle(); 3976 verify(mNetworkManagementService, atLeastOnce()).setDnsConfigurationForNetwork( 3977 anyInt(), mStringArrayCaptor.capture(), any(), any(), 3978 eq(""), tlsServers.capture()); 3979 assertEquals(2, mStringArrayCaptor.getValue().length); 3980 assertTrue(ArrayUtils.containsAll(mStringArrayCaptor.getValue(), 3981 new String[]{"2001:db8::1", "192.0.2.1"})); 3982 // Opportunistic mode. 3983 assertEquals(2, tlsServers.getValue().length); 3984 assertTrue(ArrayUtils.containsAll(tlsServers.getValue(), 3985 new String[]{"2001:db8::1", "192.0.2.1"})); 3986 reset(mNetworkManagementService); 3987 cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent); 3988 cellNetworkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, 3989 mCellNetworkAgent); 3990 CallbackInfo cbi = cellNetworkCallback.expectCallback( 3991 CallbackState.LINK_PROPERTIES, mCellNetworkAgent); 3992 cellNetworkCallback.assertNoCallback(); 3993 assertFalse(((LinkProperties)cbi.arg).isPrivateDnsActive()); 3994 assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName()); 3995 3996 setPrivateDnsSettings(PRIVATE_DNS_MODE_OFF, "ignored.example.com"); 3997 verify(mNetworkManagementService, times(1)).setDnsConfigurationForNetwork( 3998 anyInt(), mStringArrayCaptor.capture(), any(), any(), 3999 eq(""), eq(EMPTY_STRING_ARRAY)); 4000 assertEquals(2, mStringArrayCaptor.getValue().length); 4001 assertTrue(ArrayUtils.containsAll(mStringArrayCaptor.getValue(), 4002 new String[]{"2001:db8::1", "192.0.2.1"})); 4003 reset(mNetworkManagementService); 4004 cellNetworkCallback.assertNoCallback(); 4005 4006 setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com"); 4007 verify(mNetworkManagementService, atLeastOnce()).setDnsConfigurationForNetwork( 4008 anyInt(), mStringArrayCaptor.capture(), any(), any(), 4009 eq(""), tlsServers.capture()); 4010 assertEquals(2, mStringArrayCaptor.getValue().length); 4011 assertTrue(ArrayUtils.containsAll(mStringArrayCaptor.getValue(), 4012 new String[]{"2001:db8::1", "192.0.2.1"})); 4013 assertEquals(2, tlsServers.getValue().length); 4014 assertTrue(ArrayUtils.containsAll(tlsServers.getValue(), 4015 new String[]{"2001:db8::1", "192.0.2.1"})); 4016 reset(mNetworkManagementService); 4017 cellNetworkCallback.assertNoCallback(); 4018 4019 setPrivateDnsSettings(PRIVATE_DNS_MODE_PROVIDER_HOSTNAME, "strict.example.com"); 4020 // Can't test dns configuration for strict mode without properly mocking 4021 // out the DNS lookups, but can test that LinkProperties is updated. 4022 cbi = cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES, 4023 mCellNetworkAgent); 4024 cellNetworkCallback.assertNoCallback(); 4025 assertTrue(((LinkProperties)cbi.arg).isPrivateDnsActive()); 4026 assertEquals("strict.example.com", ((LinkProperties)cbi.arg).getPrivateDnsServerName()); 4027 } 4028 4029 @Test 4030 public void testLinkPropertiesWithPrivateDnsValidationEvents() throws Exception { 4031 // The default on Android is opportunistic mode ("Automatic"). 4032 setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com"); 4033 4034 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback(); 4035 final NetworkRequest cellRequest = new NetworkRequest.Builder() 4036 .addTransportType(TRANSPORT_CELLULAR).build(); 4037 mCm.requestNetwork(cellRequest, cellNetworkCallback); 4038 4039 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); 4040 waitForIdle(); 4041 LinkProperties lp = new LinkProperties(); 4042 mCellNetworkAgent.sendLinkProperties(lp); 4043 mCellNetworkAgent.connect(false); 4044 waitForIdle(); 4045 cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent); 4046 cellNetworkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, 4047 mCellNetworkAgent); 4048 CallbackInfo cbi = cellNetworkCallback.expectCallback( 4049 CallbackState.LINK_PROPERTIES, mCellNetworkAgent); 4050 cellNetworkCallback.assertNoCallback(); 4051 assertFalse(((LinkProperties)cbi.arg).isPrivateDnsActive()); 4052 assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName()); 4053 Set<InetAddress> dnsServers = new HashSet<>(); 4054 checkDnsServers(cbi.arg, dnsServers); 4055 4056 // Send a validation event for a server that is not part of the current 4057 // resolver config. The validation event should be ignored. 4058 mService.mNetdEventCallback.onPrivateDnsValidationEvent( 4059 mCellNetworkAgent.getNetwork().netId, "", "145.100.185.18", true); 4060 cellNetworkCallback.assertNoCallback(); 4061 4062 // Add a dns server to the LinkProperties. 4063 LinkProperties lp2 = new LinkProperties(lp); 4064 lp2.addDnsServer(InetAddress.getByName("145.100.185.16")); 4065 mCellNetworkAgent.sendLinkProperties(lp2); 4066 cbi = cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES, 4067 mCellNetworkAgent); 4068 cellNetworkCallback.assertNoCallback(); 4069 assertFalse(((LinkProperties)cbi.arg).isPrivateDnsActive()); 4070 assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName()); 4071 dnsServers.add(InetAddress.getByName("145.100.185.16")); 4072 checkDnsServers(cbi.arg, dnsServers); 4073 4074 // Send a validation event containing a hostname that is not part of 4075 // the current resolver config. The validation event should be ignored. 4076 mService.mNetdEventCallback.onPrivateDnsValidationEvent( 4077 mCellNetworkAgent.getNetwork().netId, "145.100.185.16", "hostname", true); 4078 cellNetworkCallback.assertNoCallback(); 4079 4080 // Send a validation event where validation failed. 4081 mService.mNetdEventCallback.onPrivateDnsValidationEvent( 4082 mCellNetworkAgent.getNetwork().netId, "145.100.185.16", "", false); 4083 cellNetworkCallback.assertNoCallback(); 4084 4085 // Send a validation event where validation succeeded for a server in 4086 // the current resolver config. A LinkProperties callback with updated 4087 // private dns fields should be sent. 4088 mService.mNetdEventCallback.onPrivateDnsValidationEvent( 4089 mCellNetworkAgent.getNetwork().netId, "145.100.185.16", "", true); 4090 cbi = cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES, 4091 mCellNetworkAgent); 4092 cellNetworkCallback.assertNoCallback(); 4093 assertTrue(((LinkProperties)cbi.arg).isPrivateDnsActive()); 4094 assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName()); 4095 checkDnsServers(cbi.arg, dnsServers); 4096 4097 // The private dns fields in LinkProperties should be preserved when 4098 // the network agent sends unrelated changes. 4099 LinkProperties lp3 = new LinkProperties(lp2); 4100 lp3.setMtu(1300); 4101 mCellNetworkAgent.sendLinkProperties(lp3); 4102 cbi = cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES, 4103 mCellNetworkAgent); 4104 cellNetworkCallback.assertNoCallback(); 4105 assertTrue(((LinkProperties)cbi.arg).isPrivateDnsActive()); 4106 assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName()); 4107 checkDnsServers(cbi.arg, dnsServers); 4108 assertEquals(1300, ((LinkProperties)cbi.arg).getMtu()); 4109 4110 // Removing the only validated server should affect the private dns 4111 // fields in LinkProperties. 4112 LinkProperties lp4 = new LinkProperties(lp3); 4113 lp4.removeDnsServer(InetAddress.getByName("145.100.185.16")); 4114 mCellNetworkAgent.sendLinkProperties(lp4); 4115 cbi = cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES, 4116 mCellNetworkAgent); 4117 cellNetworkCallback.assertNoCallback(); 4118 assertFalse(((LinkProperties)cbi.arg).isPrivateDnsActive()); 4119 assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName()); 4120 dnsServers.remove(InetAddress.getByName("145.100.185.16")); 4121 checkDnsServers(cbi.arg, dnsServers); 4122 assertEquals(1300, ((LinkProperties)cbi.arg).getMtu()); 4123 } 4124 4125 private void checkDirectlyConnectedRoutes(Object callbackObj, 4126 Collection<LinkAddress> linkAddresses, Collection<RouteInfo> otherRoutes) { 4127 assertTrue(callbackObj instanceof LinkProperties); 4128 LinkProperties lp = (LinkProperties) callbackObj; 4129 4130 Set<RouteInfo> expectedRoutes = new ArraySet<>(); 4131 expectedRoutes.addAll(otherRoutes); 4132 for (LinkAddress address : linkAddresses) { 4133 RouteInfo localRoute = new RouteInfo(address, null, lp.getInterfaceName()); 4134 // Duplicates in linkAddresses are considered failures 4135 assertTrue(expectedRoutes.add(localRoute)); 4136 } 4137 List<RouteInfo> observedRoutes = lp.getRoutes(); 4138 assertEquals(expectedRoutes.size(), observedRoutes.size()); 4139 assertTrue(observedRoutes.containsAll(expectedRoutes)); 4140 } 4141 4142 private static void checkDnsServers(Object callbackObj, Set<InetAddress> dnsServers) { 4143 assertTrue(callbackObj instanceof LinkProperties); 4144 LinkProperties lp = (LinkProperties) callbackObj; 4145 assertEquals(dnsServers.size(), lp.getDnsServers().size()); 4146 assertTrue(lp.getDnsServers().containsAll(dnsServers)); 4147 } 4148 4149 private static <T> void assertEmpty(T[] ts) { 4150 int length = ts.length; 4151 assertEquals("expected empty array, but length was " + length, 0, length); 4152 } 4153 4154 private static <T> void assertLength(int expected, T[] got) { 4155 int length = got.length; 4156 assertEquals(String.format("expected array of length %s, but length was %s for %s", 4157 expected, length, Arrays.toString(got)), expected, length); 4158 } 4159 4160 private static <T> void assertException(Runnable block, Class<T> expected) { 4161 try { 4162 block.run(); 4163 fail("Expected exception of type " + expected); 4164 } catch (Exception got) { 4165 if (!got.getClass().equals(expected)) { 4166 fail("Expected exception of type " + expected + " but got " + got); 4167 } 4168 return; 4169 } 4170 } 4171 4172 @Test 4173 public void testVpnNetworkActive() { 4174 final int uid = Process.myUid(); 4175 4176 final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback(); 4177 final TestNetworkCallback genericNotVpnNetworkCallback = new TestNetworkCallback(); 4178 final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback(); 4179 final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback(); 4180 final TestNetworkCallback defaultCallback = new TestNetworkCallback(); 4181 final NetworkRequest genericNotVpnRequest = new NetworkRequest.Builder().build(); 4182 final NetworkRequest genericRequest = new NetworkRequest.Builder() 4183 .removeCapability(NET_CAPABILITY_NOT_VPN).build(); 4184 final NetworkRequest wifiRequest = new NetworkRequest.Builder() 4185 .addTransportType(TRANSPORT_WIFI).build(); 4186 final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder() 4187 .removeCapability(NET_CAPABILITY_NOT_VPN) 4188 .addTransportType(TRANSPORT_VPN).build(); 4189 mCm.registerNetworkCallback(genericRequest, genericNetworkCallback); 4190 mCm.registerNetworkCallback(genericNotVpnRequest, genericNotVpnNetworkCallback); 4191 mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback); 4192 mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback); 4193 mCm.registerDefaultNetworkCallback(defaultCallback); 4194 defaultCallback.assertNoCallback(); 4195 4196 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 4197 mWiFiNetworkAgent.connect(false); 4198 4199 genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); 4200 genericNotVpnNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); 4201 wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); 4202 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); 4203 vpnNetworkCallback.assertNoCallback(); 4204 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); 4205 4206 final MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN); 4207 final ArraySet<UidRange> ranges = new ArraySet<>(); 4208 ranges.add(new UidRange(uid, uid)); 4209 mMockVpn.setNetworkAgent(vpnNetworkAgent); 4210 mMockVpn.setUids(ranges); 4211 vpnNetworkAgent.connect(false); 4212 mMockVpn.connect(); 4213 4214 genericNetworkCallback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent); 4215 genericNotVpnNetworkCallback.assertNoCallback(); 4216 wifiNetworkCallback.assertNoCallback(); 4217 vpnNetworkCallback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent); 4218 defaultCallback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent); 4219 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); 4220 4221 genericNetworkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, vpnNetworkAgent); 4222 genericNotVpnNetworkCallback.assertNoCallback(); 4223 vpnNetworkCallback.expectCapabilitiesLike(nc -> null == nc.getUids(), vpnNetworkAgent); 4224 defaultCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, vpnNetworkAgent); 4225 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); 4226 4227 ranges.clear(); 4228 vpnNetworkAgent.setUids(ranges); 4229 4230 genericNetworkCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent); 4231 genericNotVpnNetworkCallback.assertNoCallback(); 4232 wifiNetworkCallback.assertNoCallback(); 4233 vpnNetworkCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent); 4234 4235 // TODO : The default network callback should actually get a LOST call here (also see the 4236 // comment below for AVAILABLE). This is because ConnectivityService does not look at UID 4237 // ranges at all when determining whether a network should be rematched. In practice, VPNs 4238 // can't currently update their UIDs without disconnecting, so this does not matter too 4239 // much, but that is the reason the test here has to check for an update to the 4240 // capabilities instead of the expected LOST then AVAILABLE. 4241 defaultCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, vpnNetworkAgent); 4242 4243 ranges.add(new UidRange(uid, uid)); 4244 mMockVpn.setUids(ranges); 4245 4246 genericNetworkCallback.expectAvailableCallbacksValidated(vpnNetworkAgent); 4247 genericNotVpnNetworkCallback.assertNoCallback(); 4248 wifiNetworkCallback.assertNoCallback(); 4249 vpnNetworkCallback.expectAvailableCallbacksValidated(vpnNetworkAgent); 4250 // TODO : Here like above, AVAILABLE would be correct, but because this can't actually 4251 // happen outside of the test, ConnectivityService does not rematch callbacks. 4252 defaultCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, vpnNetworkAgent); 4253 4254 mWiFiNetworkAgent.disconnect(); 4255 4256 genericNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); 4257 genericNotVpnNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); 4258 wifiNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); 4259 vpnNetworkCallback.assertNoCallback(); 4260 defaultCallback.assertNoCallback(); 4261 4262 vpnNetworkAgent.disconnect(); 4263 4264 genericNetworkCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent); 4265 genericNotVpnNetworkCallback.assertNoCallback(); 4266 wifiNetworkCallback.assertNoCallback(); 4267 vpnNetworkCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent); 4268 defaultCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent); 4269 assertEquals(null, mCm.getActiveNetwork()); 4270 4271 mCm.unregisterNetworkCallback(genericNetworkCallback); 4272 mCm.unregisterNetworkCallback(wifiNetworkCallback); 4273 mCm.unregisterNetworkCallback(vpnNetworkCallback); 4274 mCm.unregisterNetworkCallback(defaultCallback); 4275 } 4276 4277 @Test 4278 public void testVpnWithAndWithoutInternet() { 4279 final int uid = Process.myUid(); 4280 4281 final TestNetworkCallback defaultCallback = new TestNetworkCallback(); 4282 mCm.registerDefaultNetworkCallback(defaultCallback); 4283 defaultCallback.assertNoCallback(); 4284 4285 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 4286 mWiFiNetworkAgent.connect(true); 4287 4288 defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent); 4289 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); 4290 4291 MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN); 4292 final ArraySet<UidRange> ranges = new ArraySet<>(); 4293 ranges.add(new UidRange(uid, uid)); 4294 mMockVpn.setNetworkAgent(vpnNetworkAgent); 4295 mMockVpn.setUids(ranges); 4296 vpnNetworkAgent.connect(true /* validated */, false /* hasInternet */); 4297 mMockVpn.connect(); 4298 4299 defaultCallback.assertNoCallback(); 4300 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); 4301 4302 vpnNetworkAgent.disconnect(); 4303 defaultCallback.assertNoCallback(); 4304 4305 vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN); 4306 mMockVpn.setNetworkAgent(vpnNetworkAgent); 4307 mMockVpn.setUids(ranges); 4308 vpnNetworkAgent.connect(true /* validated */, true /* hasInternet */); 4309 mMockVpn.connect(); 4310 defaultCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent); 4311 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); 4312 4313 vpnNetworkAgent.disconnect(); 4314 defaultCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent); 4315 defaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent); 4316 4317 vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN); 4318 ranges.clear(); 4319 mMockVpn.setNetworkAgent(vpnNetworkAgent); 4320 mMockVpn.setUids(ranges); 4321 vpnNetworkAgent.connect(false /* validated */, true /* hasInternet */); 4322 mMockVpn.connect(); 4323 defaultCallback.assertNoCallback(); 4324 4325 mCm.unregisterNetworkCallback(defaultCallback); 4326 } 4327 4328 @Test 4329 public void testVpnSetUnderlyingNetworks() { 4330 final int uid = Process.myUid(); 4331 4332 final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback(); 4333 final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder() 4334 .removeCapability(NET_CAPABILITY_NOT_VPN) 4335 .addTransportType(TRANSPORT_VPN) 4336 .build(); 4337 NetworkCapabilities nc; 4338 mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback); 4339 vpnNetworkCallback.assertNoCallback(); 4340 4341 final MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN); 4342 final ArraySet<UidRange> ranges = new ArraySet<>(); 4343 ranges.add(new UidRange(uid, uid)); 4344 mMockVpn.setNetworkAgent(vpnNetworkAgent); 4345 mMockVpn.connect(); 4346 mMockVpn.setUids(ranges); 4347 vpnNetworkAgent.connect(true /* validated */, false /* hasInternet */); 4348 4349 vpnNetworkCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent); 4350 nc = mCm.getNetworkCapabilities(vpnNetworkAgent.getNetwork()); 4351 assertTrue(nc.hasTransport(TRANSPORT_VPN)); 4352 assertFalse(nc.hasTransport(TRANSPORT_CELLULAR)); 4353 assertFalse(nc.hasTransport(TRANSPORT_WIFI)); 4354 // For safety reasons a VPN without underlying networks is considered metered. 4355 assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED)); 4356 4357 // Connect cell and use it as an underlying network. 4358 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); 4359 mCellNetworkAgent.connect(true); 4360 4361 mService.setUnderlyingNetworksForVpn( 4362 new Network[] { mCellNetworkAgent.getNetwork() }); 4363 4364 vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN) 4365 && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI) 4366 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED), 4367 vpnNetworkAgent); 4368 4369 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 4370 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED); 4371 mWiFiNetworkAgent.connect(true); 4372 4373 mService.setUnderlyingNetworksForVpn( 4374 new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() }); 4375 4376 vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN) 4377 && caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI) 4378 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED), 4379 vpnNetworkAgent); 4380 4381 // Don't disconnect, but note the VPN is not using wifi any more. 4382 mService.setUnderlyingNetworksForVpn( 4383 new Network[] { mCellNetworkAgent.getNetwork() }); 4384 4385 vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN) 4386 && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI) 4387 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED), 4388 vpnNetworkAgent); 4389 4390 // Use Wifi but not cell. Note the VPN is now unmetered. 4391 mService.setUnderlyingNetworksForVpn( 4392 new Network[] { mWiFiNetworkAgent.getNetwork() }); 4393 4394 vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN) 4395 && !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI) 4396 && caps.hasCapability(NET_CAPABILITY_NOT_METERED), 4397 vpnNetworkAgent); 4398 4399 // Use both again. 4400 mService.setUnderlyingNetworksForVpn( 4401 new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() }); 4402 4403 vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN) 4404 && caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI) 4405 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED), 4406 vpnNetworkAgent); 4407 4408 // Disconnect cell. Receive update without even removing the dead network from the 4409 // underlying networks it's dead anyway. Not metered any more. 4410 mCellNetworkAgent.disconnect(); 4411 vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN) 4412 && !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI) 4413 && caps.hasCapability(NET_CAPABILITY_NOT_METERED), 4414 vpnNetworkAgent); 4415 4416 // Disconnect wifi too. No underlying networks means this is now metered. 4417 mWiFiNetworkAgent.disconnect(); 4418 vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN) 4419 && !caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI) 4420 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED), 4421 vpnNetworkAgent); 4422 4423 mMockVpn.disconnect(); 4424 } 4425 } 4426