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