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