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.TYPE_ETHERNET; 21 import static android.net.ConnectivityManager.TYPE_MOBILE; 22 import static android.net.ConnectivityManager.TYPE_MOBILE_FOTA; 23 import static android.net.ConnectivityManager.TYPE_MOBILE_MMS; 24 import static android.net.ConnectivityManager.TYPE_NONE; 25 import static android.net.ConnectivityManager.TYPE_VPN; 26 import static android.net.ConnectivityManager.TYPE_WIFI; 27 import static android.net.ConnectivityManager.getNetworkTypeName; 28 import static android.net.NetworkCapabilities.*; 29 30 import static com.android.internal.util.TestUtils.waitForIdleHandler; 31 32 import static org.mockito.Mockito.anyBoolean; 33 import static org.mockito.Mockito.anyInt; 34 import static org.mockito.Mockito.eq; 35 import static org.mockito.Mockito.mock; 36 import static org.mockito.Mockito.spy; 37 import static org.mockito.Mockito.when; 38 39 import android.app.NotificationManager; 40 import android.app.PendingIntent; 41 import android.content.BroadcastReceiver; 42 import android.content.ContentResolver; 43 import android.content.Context; 44 import android.content.ContextWrapper; 45 import android.content.Intent; 46 import android.content.IntentFilter; 47 import android.content.res.Resources; 48 import android.net.CaptivePortal; 49 import android.net.ConnectivityManager; 50 import android.net.ConnectivityManager.NetworkCallback; 51 import android.net.ConnectivityManager.PacketKeepalive; 52 import android.net.ConnectivityManager.PacketKeepaliveCallback; 53 import android.net.ConnectivityManager.TooManyRequestsException; 54 import android.net.INetworkPolicyManager; 55 import android.net.INetworkStatsService; 56 import android.net.IpPrefix; 57 import android.net.LinkAddress; 58 import android.net.LinkProperties; 59 import android.net.MatchAllNetworkSpecifier; 60 import android.net.Network; 61 import android.net.NetworkAgent; 62 import android.net.NetworkCapabilities; 63 import android.net.NetworkConfig; 64 import android.net.NetworkFactory; 65 import android.net.NetworkInfo; 66 import android.net.NetworkInfo.DetailedState; 67 import android.net.NetworkMisc; 68 import android.net.NetworkRequest; 69 import android.net.NetworkSpecifier; 70 import android.net.NetworkUtils; 71 import android.net.RouteInfo; 72 import android.net.StringNetworkSpecifier; 73 import android.net.metrics.IpConnectivityLog; 74 import android.net.util.MultinetworkPolicyTracker; 75 import android.os.ConditionVariable; 76 import android.os.Handler; 77 import android.os.HandlerThread; 78 import android.os.IBinder; 79 import android.os.INetworkManagementService; 80 import android.os.Looper; 81 import android.os.Message; 82 import android.os.MessageQueue; 83 import android.os.Messenger; 84 import android.os.MessageQueue.IdleHandler; 85 import android.os.Parcel; 86 import android.os.Parcelable; 87 import android.os.Process; 88 import android.os.SystemClock; 89 import android.os.UserHandle; 90 import android.provider.Settings; 91 import android.test.AndroidTestCase; 92 import android.test.mock.MockContentResolver; 93 import android.test.suitebuilder.annotation.SmallTest; 94 import android.text.TextUtils; 95 import android.util.ArraySet; 96 import android.util.Log; 97 import android.util.LogPrinter; 98 99 import com.android.internal.util.WakeupMessage; 100 import com.android.internal.util.test.BroadcastInterceptingContext; 101 import com.android.internal.util.test.FakeSettingsProvider; 102 import com.android.server.connectivity.MockableSystemProperties; 103 import com.android.server.connectivity.NetworkAgentInfo; 104 import com.android.server.connectivity.NetworkMonitor; 105 import com.android.server.connectivity.NetworkMonitor.CaptivePortalProbeResult; 106 import com.android.server.connectivity.Vpn; 107 import com.android.server.net.NetworkPinner; 108 import com.android.server.net.NetworkPolicyManagerInternal; 109 110 import org.junit.Ignore; 111 import org.mockito.Mock; 112 import org.mockito.MockitoAnnotations; 113 import org.mockito.Spy; 114 115 import java.net.InetAddress; 116 import java.util.ArrayList; 117 import java.util.Arrays; 118 import java.util.Collection; 119 import java.util.List; 120 import java.util.Objects; 121 import java.util.Set; 122 import java.util.concurrent.CountDownLatch; 123 import java.util.concurrent.LinkedBlockingQueue; 124 import java.util.concurrent.TimeUnit; 125 import java.util.concurrent.atomic.AtomicBoolean; 126 import java.util.function.BooleanSupplier; 127 import java.util.function.Predicate; 128 129 /** 130 * Tests for {@link ConnectivityService}. 131 * 132 * Build, install and run with: 133 * runtest frameworks-net -c com.android.server.ConnectivityServiceTest 134 */ 135 public class ConnectivityServiceTest extends AndroidTestCase { 136 private static final String TAG = "ConnectivityServiceTest"; 137 138 private static final int TIMEOUT_MS = 500; 139 private static final int TEST_LINGER_DELAY_MS = 120; 140 141 private MockContext mServiceContext; 142 private WrappedConnectivityService mService; 143 private WrappedConnectivityManager mCm; 144 private MockNetworkAgent mWiFiNetworkAgent; 145 private MockNetworkAgent mCellNetworkAgent; 146 private MockNetworkAgent mEthernetNetworkAgent; 147 148 // This class exists to test bindProcessToNetwork and getBoundNetworkForProcess. These methods 149 // do not go through ConnectivityService but talk to netd directly, so they don't automatically 150 // reflect the state of our test ConnectivityService. 151 private class WrappedConnectivityManager extends ConnectivityManager { 152 private Network mFakeBoundNetwork; 153 bindProcessToNetwork(Network network)154 public synchronized boolean bindProcessToNetwork(Network network) { 155 mFakeBoundNetwork = network; 156 return true; 157 } 158 getBoundNetworkForProcess()159 public synchronized Network getBoundNetworkForProcess() { 160 return mFakeBoundNetwork; 161 } 162 WrappedConnectivityManager(Context context, ConnectivityService service)163 public WrappedConnectivityManager(Context context, ConnectivityService service) { 164 super(context, service); 165 } 166 } 167 168 private class MockContext extends BroadcastInterceptingContext { 169 private final MockContentResolver mContentResolver; 170 171 @Spy private Resources mResources; 172 private final LinkedBlockingQueue<Intent> mStartedActivities = new LinkedBlockingQueue<>(); 173 MockContext(Context base)174 MockContext(Context base) { 175 super(base); 176 177 mResources = spy(base.getResources()); 178 when(mResources.getStringArray(com.android.internal.R.array.networkAttributes)). 179 thenReturn(new String[] { 180 "wifi,1,1,1,-1,true", 181 "mobile,0,0,0,-1,true", 182 "mobile_mms,2,0,2,60000,true", 183 }); 184 185 mContentResolver = new MockContentResolver(); 186 mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider()); 187 } 188 189 @Override startActivityAsUser(Intent intent, UserHandle handle)190 public void startActivityAsUser(Intent intent, UserHandle handle) { 191 mStartedActivities.offer(intent); 192 } 193 expectStartActivityIntent(int timeoutMs)194 public Intent expectStartActivityIntent(int timeoutMs) { 195 Intent intent = null; 196 try { 197 intent = mStartedActivities.poll(timeoutMs, TimeUnit.MILLISECONDS); 198 } catch (InterruptedException e) {} 199 assertNotNull("Did not receive sign-in intent after " + timeoutMs + "ms", intent); 200 return intent; 201 } 202 expectNoStartActivityIntent(int timeoutMs)203 public void expectNoStartActivityIntent(int timeoutMs) { 204 try { 205 assertNull("Received unexpected Intent to start activity", 206 mStartedActivities.poll(timeoutMs, TimeUnit.MILLISECONDS)); 207 } catch (InterruptedException e) {} 208 } 209 210 @Override getSystemService(String name)211 public Object getSystemService(String name) { 212 if (Context.CONNECTIVITY_SERVICE.equals(name)) return mCm; 213 if (Context.NOTIFICATION_SERVICE.equals(name)) return mock(NotificationManager.class); 214 return super.getSystemService(name); 215 } 216 217 @Override getContentResolver()218 public ContentResolver getContentResolver() { 219 return mContentResolver; 220 } 221 222 @Override getResources()223 public Resources getResources() { 224 return mResources; 225 } 226 } 227 waitForIdle(int timeoutMsAsInt)228 public void waitForIdle(int timeoutMsAsInt) { 229 long timeoutMs = timeoutMsAsInt; 230 waitForIdleHandler(mService.mHandlerThread, timeoutMs); 231 waitForIdle(mCellNetworkAgent, timeoutMs); 232 waitForIdle(mWiFiNetworkAgent, timeoutMs); 233 waitForIdle(mEthernetNetworkAgent, timeoutMs); 234 waitForIdleHandler(mService.mHandlerThread, timeoutMs); 235 } 236 waitForIdle(MockNetworkAgent agent, long timeoutMs)237 public void waitForIdle(MockNetworkAgent agent, long timeoutMs) { 238 if (agent == null) { 239 return; 240 } 241 waitForIdleHandler(agent.mHandlerThread, timeoutMs); 242 } 243 waitForIdle()244 private void waitForIdle() { 245 waitForIdle(TIMEOUT_MS); 246 } 247 248 @SmallTest testWaitForIdle()249 public void testWaitForIdle() { 250 final int attempts = 50; // Causes the test to take about 200ms on bullhead-eng. 251 252 // Tests that waitForIdle returns immediately if the service is already idle. 253 for (int i = 0; i < attempts; i++) { 254 waitForIdle(); 255 } 256 257 // Bring up a network that we can use to send messages to ConnectivityService. 258 ConditionVariable cv = waitForConnectivityBroadcasts(1); 259 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 260 mWiFiNetworkAgent.connect(false); 261 waitFor(cv); 262 Network n = mWiFiNetworkAgent.getNetwork(); 263 assertNotNull(n); 264 265 // Tests that calling waitForIdle waits for messages to be processed. 266 for (int i = 0; i < attempts; i++) { 267 mWiFiNetworkAgent.setSignalStrength(i); 268 waitForIdle(); 269 assertEquals(i, mCm.getNetworkCapabilities(n).getSignalStrength()); 270 } 271 } 272 273 // This test has an inherent race condition in it, and cannot be enabled for continuous testing 274 // or presubmit tests. It is kept for manual runs and documentation purposes. verifyThatNotWaitingForIdleCausesRaceConditions()275 public void verifyThatNotWaitingForIdleCausesRaceConditions() { 276 // Bring up a network that we can use to send messages to ConnectivityService. 277 ConditionVariable cv = waitForConnectivityBroadcasts(1); 278 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 279 mWiFiNetworkAgent.connect(false); 280 waitFor(cv); 281 Network n = mWiFiNetworkAgent.getNetwork(); 282 assertNotNull(n); 283 284 // Ensure that not calling waitForIdle causes a race condition. 285 final int attempts = 50; // Causes the test to take about 200ms on bullhead-eng. 286 for (int i = 0; i < attempts; i++) { 287 mWiFiNetworkAgent.setSignalStrength(i); 288 if (i != mCm.getNetworkCapabilities(n).getSignalStrength()) { 289 // We hit a race condition, as expected. Pass the test. 290 return; 291 } 292 } 293 294 // No race? There is a bug in this test. 295 fail("expected race condition at least once in " + attempts + " attempts"); 296 } 297 298 private class MockNetworkAgent { 299 private final WrappedNetworkMonitor mWrappedNetworkMonitor; 300 private final NetworkInfo mNetworkInfo; 301 private final NetworkCapabilities mNetworkCapabilities; 302 private final HandlerThread mHandlerThread; 303 private final ConditionVariable mDisconnected = new ConditionVariable(); 304 private final ConditionVariable mNetworkStatusReceived = new ConditionVariable(); 305 private final ConditionVariable mPreventReconnectReceived = new ConditionVariable(); 306 private int mScore; 307 private NetworkAgent mNetworkAgent; 308 private int mStartKeepaliveError = PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED; 309 private int mStopKeepaliveError = PacketKeepalive.NO_KEEPALIVE; 310 private Integer mExpectedKeepaliveSlot = null; 311 // Contains the redirectUrl from networkStatus(). Before reading, wait for 312 // mNetworkStatusReceived. 313 private String mRedirectUrl; 314 MockNetworkAgent(int transport)315 MockNetworkAgent(int transport) { 316 this(transport, new LinkProperties()); 317 } 318 MockNetworkAgent(int transport, LinkProperties linkProperties)319 MockNetworkAgent(int transport, LinkProperties linkProperties) { 320 final int type = transportToLegacyType(transport); 321 final String typeName = ConnectivityManager.getNetworkTypeName(type); 322 mNetworkInfo = new NetworkInfo(type, 0, typeName, "Mock"); 323 mNetworkCapabilities = new NetworkCapabilities(); 324 mNetworkCapabilities.addTransportType(transport); 325 switch (transport) { 326 case TRANSPORT_ETHERNET: 327 mScore = 70; 328 break; 329 case TRANSPORT_WIFI: 330 mScore = 60; 331 break; 332 case TRANSPORT_CELLULAR: 333 mScore = 50; 334 break; 335 case TRANSPORT_WIFI_AWARE: 336 mScore = 20; 337 break; 338 case TRANSPORT_VPN: 339 mScore = 0; 340 break; 341 default: 342 throw new UnsupportedOperationException("unimplemented network type"); 343 } 344 mHandlerThread = new HandlerThread("Mock-" + typeName); 345 mHandlerThread.start(); 346 mNetworkAgent = new NetworkAgent(mHandlerThread.getLooper(), mServiceContext, 347 "Mock-" + typeName, mNetworkInfo, mNetworkCapabilities, 348 linkProperties, mScore, new NetworkMisc()) { 349 @Override 350 public void unwanted() { mDisconnected.open(); } 351 352 @Override 353 public void startPacketKeepalive(Message msg) { 354 int slot = msg.arg1; 355 if (mExpectedKeepaliveSlot != null) { 356 assertEquals((int) mExpectedKeepaliveSlot, slot); 357 } 358 onPacketKeepaliveEvent(slot, mStartKeepaliveError); 359 } 360 361 @Override 362 public void stopPacketKeepalive(Message msg) { 363 onPacketKeepaliveEvent(msg.arg1, mStopKeepaliveError); 364 } 365 366 @Override 367 public void networkStatus(int status, String redirectUrl) { 368 mRedirectUrl = redirectUrl; 369 mNetworkStatusReceived.open(); 370 } 371 372 @Override 373 protected void preventAutomaticReconnect() { 374 mPreventReconnectReceived.open(); 375 } 376 }; 377 // Waits for the NetworkAgent to be registered, which includes the creation of the 378 // NetworkMonitor. 379 waitForIdle(); 380 mWrappedNetworkMonitor = mService.getLastCreatedWrappedNetworkMonitor(); 381 } 382 adjustScore(int change)383 public void adjustScore(int change) { 384 mScore += change; 385 mNetworkAgent.sendNetworkScore(mScore); 386 } 387 explicitlySelected(boolean acceptUnvalidated)388 public void explicitlySelected(boolean acceptUnvalidated) { 389 mNetworkAgent.explicitlySelected(acceptUnvalidated); 390 } 391 addCapability(int capability)392 public void addCapability(int capability) { 393 mNetworkCapabilities.addCapability(capability); 394 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities); 395 } 396 removeCapability(int capability)397 public void removeCapability(int capability) { 398 mNetworkCapabilities.removeCapability(capability); 399 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities); 400 } 401 setSignalStrength(int signalStrength)402 public void setSignalStrength(int signalStrength) { 403 mNetworkCapabilities.setSignalStrength(signalStrength); 404 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities); 405 } 406 setNetworkSpecifier(NetworkSpecifier networkSpecifier)407 public void setNetworkSpecifier(NetworkSpecifier networkSpecifier) { 408 mNetworkCapabilities.setNetworkSpecifier(networkSpecifier); 409 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities); 410 } 411 connectWithoutInternet()412 public void connectWithoutInternet() { 413 mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, null); 414 mNetworkAgent.sendNetworkInfo(mNetworkInfo); 415 } 416 417 /** 418 * Transition this NetworkAgent to CONNECTED state with NET_CAPABILITY_INTERNET. 419 * @param validated Indicate if network should pretend to be validated. 420 */ connect(boolean validated)421 public void connect(boolean validated) { 422 connect(validated, true); 423 } 424 425 /** 426 * Transition this NetworkAgent to CONNECTED state. 427 * @param validated Indicate if network should pretend to be validated. 428 * @param hasInternet Indicate if network should pretend to have NET_CAPABILITY_INTERNET. 429 */ connect(boolean validated, boolean hasInternet)430 public void connect(boolean validated, boolean hasInternet) { 431 assertEquals("MockNetworkAgents can only be connected once", 432 mNetworkInfo.getDetailedState(), DetailedState.IDLE); 433 assertFalse(mNetworkCapabilities.hasCapability(NET_CAPABILITY_INTERNET)); 434 435 NetworkCallback callback = null; 436 final ConditionVariable validatedCv = new ConditionVariable(); 437 if (validated) { 438 mWrappedNetworkMonitor.gen204ProbeResult = 204; 439 NetworkRequest request = new NetworkRequest.Builder() 440 .addTransportType(mNetworkCapabilities.getTransportTypes()[0]) 441 .build(); 442 callback = new NetworkCallback() { 443 public void onCapabilitiesChanged(Network network, 444 NetworkCapabilities networkCapabilities) { 445 if (network.equals(getNetwork()) && 446 networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED)) { 447 validatedCv.open(); 448 } 449 } 450 }; 451 mCm.registerNetworkCallback(request, callback); 452 } 453 if (hasInternet) { 454 addCapability(NET_CAPABILITY_INTERNET); 455 } 456 457 connectWithoutInternet(); 458 459 if (validated) { 460 // Wait for network to validate. 461 waitFor(validatedCv); 462 mWrappedNetworkMonitor.gen204ProbeResult = 500; 463 } 464 465 if (callback != null) mCm.unregisterNetworkCallback(callback); 466 } 467 connectWithCaptivePortal(String redirectUrl)468 public void connectWithCaptivePortal(String redirectUrl) { 469 mWrappedNetworkMonitor.gen204ProbeResult = 200; 470 mWrappedNetworkMonitor.gen204ProbeRedirectUrl = redirectUrl; 471 connect(false); 472 } 473 suspend()474 public void suspend() { 475 mNetworkInfo.setDetailedState(DetailedState.SUSPENDED, null, null); 476 mNetworkAgent.sendNetworkInfo(mNetworkInfo); 477 } 478 disconnect()479 public void disconnect() { 480 mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, null); 481 mNetworkAgent.sendNetworkInfo(mNetworkInfo); 482 } 483 getNetwork()484 public Network getNetwork() { 485 return new Network(mNetworkAgent.netId); 486 } 487 getPreventReconnectReceived()488 public ConditionVariable getPreventReconnectReceived() { 489 return mPreventReconnectReceived; 490 } 491 getDisconnectedCV()492 public ConditionVariable getDisconnectedCV() { 493 return mDisconnected; 494 } 495 getWrappedNetworkMonitor()496 public WrappedNetworkMonitor getWrappedNetworkMonitor() { 497 return mWrappedNetworkMonitor; 498 } 499 sendLinkProperties(LinkProperties lp)500 public void sendLinkProperties(LinkProperties lp) { 501 mNetworkAgent.sendLinkProperties(lp); 502 } 503 setStartKeepaliveError(int error)504 public void setStartKeepaliveError(int error) { 505 mStartKeepaliveError = error; 506 } 507 setStopKeepaliveError(int error)508 public void setStopKeepaliveError(int error) { 509 mStopKeepaliveError = error; 510 } 511 setExpectedKeepaliveSlot(Integer slot)512 public void setExpectedKeepaliveSlot(Integer slot) { 513 mExpectedKeepaliveSlot = slot; 514 } 515 waitForRedirectUrl()516 public String waitForRedirectUrl() { 517 assertTrue(mNetworkStatusReceived.block(TIMEOUT_MS)); 518 return mRedirectUrl; 519 } 520 } 521 522 /** 523 * A NetworkFactory that allows tests to wait until any in-flight NetworkRequest add or remove 524 * operations have been processed. Before ConnectivityService can add or remove any requests, 525 * the factory must be told to expect those operations by calling expectAddRequests or 526 * expectRemoveRequests. 527 */ 528 private static class MockNetworkFactory extends NetworkFactory { 529 private final ConditionVariable mNetworkStartedCV = new ConditionVariable(); 530 private final ConditionVariable mNetworkStoppedCV = new ConditionVariable(); 531 private final AtomicBoolean mNetworkStarted = new AtomicBoolean(false); 532 533 // Used to expect that requests be removed or added on a separate thread, without sleeping. 534 // Callers can call either expectAddRequests() or expectRemoveRequests() exactly once, then 535 // cause some other thread to add or remove requests, then call waitForRequests(). We can 536 // either expect requests to be added or removed, but not both, because CountDownLatch can 537 // only count in one direction. 538 private CountDownLatch mExpectations; 539 540 // Whether we are currently expecting requests to be added or removed. Valid only if 541 // mExpectations is non-null. 542 private boolean mExpectingAdditions; 543 MockNetworkFactory(Looper looper, Context context, String logTag, NetworkCapabilities filter)544 public MockNetworkFactory(Looper looper, Context context, String logTag, 545 NetworkCapabilities filter) { 546 super(looper, context, logTag, filter); 547 } 548 getMyRequestCount()549 public int getMyRequestCount() { 550 return getRequestCount(); 551 } 552 startNetwork()553 protected void startNetwork() { 554 mNetworkStarted.set(true); 555 mNetworkStartedCV.open(); 556 } 557 stopNetwork()558 protected void stopNetwork() { 559 mNetworkStarted.set(false); 560 mNetworkStoppedCV.open(); 561 } 562 getMyStartRequested()563 public boolean getMyStartRequested() { 564 return mNetworkStarted.get(); 565 } 566 getNetworkStartedCV()567 public ConditionVariable getNetworkStartedCV() { 568 mNetworkStartedCV.close(); 569 return mNetworkStartedCV; 570 } 571 getNetworkStoppedCV()572 public ConditionVariable getNetworkStoppedCV() { 573 mNetworkStoppedCV.close(); 574 return mNetworkStoppedCV; 575 } 576 577 @Override handleAddRequest(NetworkRequest request, int score)578 protected void handleAddRequest(NetworkRequest request, int score) { 579 // If we're expecting anything, we must be expecting additions. 580 if (mExpectations != null && !mExpectingAdditions) { 581 fail("Can't add requests while expecting requests to be removed"); 582 } 583 584 // Add the request. 585 super.handleAddRequest(request, score); 586 587 // Reduce the number of request additions we're waiting for. 588 if (mExpectingAdditions) { 589 assertTrue("Added more requests than expected", mExpectations.getCount() > 0); 590 mExpectations.countDown(); 591 } 592 } 593 594 @Override handleRemoveRequest(NetworkRequest request)595 protected void handleRemoveRequest(NetworkRequest request) { 596 // If we're expecting anything, we must be expecting removals. 597 if (mExpectations != null && mExpectingAdditions) { 598 fail("Can't remove requests while expecting requests to be added"); 599 } 600 601 // Remove the request. 602 super.handleRemoveRequest(request); 603 604 // Reduce the number of request removals we're waiting for. 605 if (!mExpectingAdditions) { 606 assertTrue("Removed more requests than expected", mExpectations.getCount() > 0); 607 mExpectations.countDown(); 608 } 609 } 610 assertNoExpectations()611 private void assertNoExpectations() { 612 if (mExpectations != null) { 613 fail("Can't add expectation, " + mExpectations.getCount() + " already pending"); 614 } 615 } 616 617 // Expects that count requests will be added. expectAddRequests(final int count)618 public void expectAddRequests(final int count) { 619 assertNoExpectations(); 620 mExpectingAdditions = true; 621 mExpectations = new CountDownLatch(count); 622 } 623 624 // Expects that count requests will be removed. expectRemoveRequests(final int count)625 public void expectRemoveRequests(final int count) { 626 assertNoExpectations(); 627 mExpectingAdditions = false; 628 mExpectations = new CountDownLatch(count); 629 } 630 631 // Waits for the expected request additions or removals to happen within a timeout. waitForRequests()632 public void waitForRequests() throws InterruptedException { 633 assertNotNull("Nothing to wait for", mExpectations); 634 mExpectations.await(TIMEOUT_MS, TimeUnit.MILLISECONDS); 635 final long count = mExpectations.getCount(); 636 final String msg = count + " requests still not " + 637 (mExpectingAdditions ? "added" : "removed") + 638 " after " + TIMEOUT_MS + " ms"; 639 assertEquals(msg, 0, count); 640 mExpectations = null; 641 } 642 waitForNetworkRequests(final int count)643 public void waitForNetworkRequests(final int count) throws InterruptedException { 644 waitForRequests(); 645 assertEquals(count, getMyRequestCount()); 646 } 647 } 648 649 private class FakeWakeupMessage extends WakeupMessage { 650 private static final int UNREASONABLY_LONG_WAIT = 1000; 651 FakeWakeupMessage(Context context, Handler handler, String cmdName, int cmd)652 public FakeWakeupMessage(Context context, Handler handler, String cmdName, int cmd) { 653 super(context, handler, cmdName, cmd); 654 } 655 FakeWakeupMessage(Context context, Handler handler, String cmdName, int cmd, int arg1, int arg2, Object obj)656 public FakeWakeupMessage(Context context, Handler handler, String cmdName, int cmd, 657 int arg1, int arg2, Object obj) { 658 super(context, handler, cmdName, cmd, arg1, arg2, obj); 659 } 660 661 @Override schedule(long when)662 public void schedule(long when) { 663 long delayMs = when - SystemClock.elapsedRealtime(); 664 if (delayMs < 0) delayMs = 0; 665 if (delayMs > UNREASONABLY_LONG_WAIT) { 666 fail("Attempting to send msg more than " + UNREASONABLY_LONG_WAIT + 667 "ms into the future: " + delayMs); 668 } 669 Message msg = mHandler.obtainMessage(mCmd, mArg1, mArg2, mObj); 670 mHandler.sendMessageDelayed(msg, delayMs); 671 } 672 673 @Override cancel()674 public void cancel() { 675 mHandler.removeMessages(mCmd, mObj); 676 } 677 678 @Override onAlarm()679 public void onAlarm() { 680 throw new AssertionError("Should never happen. Update this fake."); 681 } 682 } 683 684 // NetworkMonitor implementation allowing overriding of Internet connectivity probe result. 685 private class WrappedNetworkMonitor extends NetworkMonitor { 686 // HTTP response code fed back to NetworkMonitor for Internet connectivity probe. 687 public int gen204ProbeResult = 500; 688 public String gen204ProbeRedirectUrl = null; 689 WrappedNetworkMonitor(Context context, Handler handler, NetworkAgentInfo networkAgentInfo, NetworkRequest defaultRequest, IpConnectivityLog log)690 public WrappedNetworkMonitor(Context context, Handler handler, 691 NetworkAgentInfo networkAgentInfo, NetworkRequest defaultRequest, 692 IpConnectivityLog log) { 693 super(context, handler, networkAgentInfo, defaultRequest, log); 694 } 695 696 @Override isCaptivePortal()697 protected CaptivePortalProbeResult isCaptivePortal() { 698 if (!mIsCaptivePortalCheckEnabled) { return new CaptivePortalProbeResult(204); } 699 return new CaptivePortalProbeResult(gen204ProbeResult, gen204ProbeRedirectUrl, null); 700 } 701 } 702 703 private class WrappedMultinetworkPolicyTracker extends MultinetworkPolicyTracker { 704 public volatile boolean configRestrictsAvoidBadWifi; 705 public volatile int configMeteredMultipathPreference; 706 WrappedMultinetworkPolicyTracker(Context c, Handler h, Runnable r)707 public WrappedMultinetworkPolicyTracker(Context c, Handler h, Runnable r) { 708 super(c, h, r); 709 } 710 711 @Override configRestrictsAvoidBadWifi()712 public boolean configRestrictsAvoidBadWifi() { 713 return configRestrictsAvoidBadWifi; 714 } 715 716 @Override configMeteredMultipathPreference()717 public int configMeteredMultipathPreference() { 718 return configMeteredMultipathPreference; 719 } 720 } 721 722 private class WrappedConnectivityService extends ConnectivityService { 723 public WrappedMultinetworkPolicyTracker wrappedMultinetworkPolicyTracker; 724 private WrappedNetworkMonitor mLastCreatedNetworkMonitor; 725 private MockableSystemProperties mSystemProperties; 726 WrappedConnectivityService(Context context, INetworkManagementService netManager, INetworkStatsService statsService, INetworkPolicyManager policyManager, IpConnectivityLog log)727 public WrappedConnectivityService(Context context, INetworkManagementService netManager, 728 INetworkStatsService statsService, INetworkPolicyManager policyManager, 729 IpConnectivityLog log) { 730 super(context, netManager, statsService, policyManager, log); 731 mLingerDelayMs = TEST_LINGER_DELAY_MS; 732 } 733 734 @Override getSystemProperties()735 protected MockableSystemProperties getSystemProperties() { 736 // Minimal approach to overriding system properties: let most calls fall through to real 737 // device values, and only override ones values that are important to this test. 738 mSystemProperties = spy(new MockableSystemProperties()); 739 when(mSystemProperties.getInt("net.tcp.default_init_rwnd", 0)).thenReturn(0); 740 when(mSystemProperties.getBoolean("ro.radio.noril", false)).thenReturn(false); 741 return mSystemProperties; 742 } 743 744 @Override reserveNetId()745 protected int reserveNetId() { 746 while (true) { 747 final int netId = super.reserveNetId(); 748 749 // Don't overlap test NetIDs with real NetIDs as binding sockets to real networks 750 // can have odd side-effects, like network validations succeeding. 751 final Network[] networks = ConnectivityManager.from(getContext()).getAllNetworks(); 752 boolean overlaps = false; 753 for (Network network : networks) { 754 if (netId == network.netId) { 755 overlaps = true; 756 break; 757 } 758 } 759 if (overlaps) continue; 760 761 return netId; 762 } 763 } 764 765 @Override createNetworkMonitor(Context context, Handler handler, NetworkAgentInfo nai, NetworkRequest defaultRequest)766 public NetworkMonitor createNetworkMonitor(Context context, Handler handler, 767 NetworkAgentInfo nai, NetworkRequest defaultRequest) { 768 final WrappedNetworkMonitor monitor = new WrappedNetworkMonitor( 769 context, handler, nai, defaultRequest, mock(IpConnectivityLog.class)); 770 mLastCreatedNetworkMonitor = monitor; 771 return monitor; 772 } 773 774 @Override createMultinetworkPolicyTracker( Context c, Handler h, Runnable r)775 public MultinetworkPolicyTracker createMultinetworkPolicyTracker( 776 Context c, Handler h, Runnable r) { 777 final WrappedMultinetworkPolicyTracker tracker = new WrappedMultinetworkPolicyTracker(c, h, r); 778 return tracker; 779 } 780 getMultinetworkPolicyTracker()781 public WrappedMultinetworkPolicyTracker getMultinetworkPolicyTracker() { 782 return (WrappedMultinetworkPolicyTracker) mMultinetworkPolicyTracker; 783 } 784 785 @Override makeWakeupMessage( Context context, Handler handler, String cmdName, int cmd, Object obj)786 public WakeupMessage makeWakeupMessage( 787 Context context, Handler handler, String cmdName, int cmd, Object obj) { 788 return new FakeWakeupMessage(context, handler, cmdName, cmd, 0, 0, obj); 789 } 790 791 @Override hasService(String name)792 public boolean hasService(String name) { 793 // Currenty, the only relevant service that ConnectivityService checks for is 794 // ETHERNET_SERVICE. 795 return Context.ETHERNET_SERVICE.equals(name); 796 } 797 getLastCreatedWrappedNetworkMonitor()798 public WrappedNetworkMonitor getLastCreatedWrappedNetworkMonitor() { 799 return mLastCreatedNetworkMonitor; 800 } 801 waitForIdle(int timeoutMs)802 public void waitForIdle(int timeoutMs) { 803 waitForIdleHandler(mHandlerThread, timeoutMs); 804 } 805 waitForIdle()806 public void waitForIdle() { 807 waitForIdle(TIMEOUT_MS); 808 } 809 } 810 811 /** 812 * Wait up to TIMEOUT_MS for {@code conditionVariable} to open. 813 * Fails if TIMEOUT_MS goes by before {@code conditionVariable} opens. 814 */ waitFor(ConditionVariable conditionVariable)815 static private void waitFor(ConditionVariable conditionVariable) { 816 if (conditionVariable.block(TIMEOUT_MS)) { 817 return; 818 } 819 fail("ConditionVariable was blocked for more than " + TIMEOUT_MS + "ms"); 820 } 821 822 @Override setUp()823 public void setUp() throws Exception { 824 super.setUp(); 825 826 // InstrumentationTestRunner prepares a looper, but AndroidJUnitRunner does not. 827 // http://b/25897652 . 828 if (Looper.myLooper() == null) { 829 Looper.prepare(); 830 } 831 832 mServiceContext = new MockContext(getContext()); 833 LocalServices.removeServiceForTest(NetworkPolicyManagerInternal.class); 834 LocalServices.addService( 835 NetworkPolicyManagerInternal.class, mock(NetworkPolicyManagerInternal.class)); 836 mService = new WrappedConnectivityService(mServiceContext, 837 mock(INetworkManagementService.class), 838 mock(INetworkStatsService.class), 839 mock(INetworkPolicyManager.class), 840 mock(IpConnectivityLog.class)); 841 842 mService.systemReady(); 843 mCm = new WrappedConnectivityManager(getContext(), mService); 844 mCm.bindProcessToNetwork(null); 845 846 // Ensure that the default setting for Captive Portals is used for most tests 847 setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_PROMPT); 848 setMobileDataAlwaysOn(false); 849 } 850 tearDown()851 public void tearDown() throws Exception { 852 setMobileDataAlwaysOn(false); 853 if (mCellNetworkAgent != null) { 854 mCellNetworkAgent.disconnect(); 855 mCellNetworkAgent = null; 856 } 857 if (mWiFiNetworkAgent != null) { 858 mWiFiNetworkAgent.disconnect(); 859 mWiFiNetworkAgent = null; 860 } 861 if (mEthernetNetworkAgent != null) { 862 mEthernetNetworkAgent.disconnect(); 863 mEthernetNetworkAgent = null; 864 } 865 super.tearDown(); 866 } 867 transportToLegacyType(int transport)868 private static int transportToLegacyType(int transport) { 869 switch (transport) { 870 case TRANSPORT_ETHERNET: 871 return TYPE_ETHERNET; 872 case TRANSPORT_WIFI: 873 return TYPE_WIFI; 874 case TRANSPORT_CELLULAR: 875 return TYPE_MOBILE; 876 case TRANSPORT_VPN: 877 return TYPE_VPN; 878 default: 879 return TYPE_NONE; 880 } 881 } 882 verifyActiveNetwork(int transport)883 private void verifyActiveNetwork(int transport) { 884 // Test getActiveNetworkInfo() 885 assertNotNull(mCm.getActiveNetworkInfo()); 886 assertEquals(transportToLegacyType(transport), mCm.getActiveNetworkInfo().getType()); 887 // Test getActiveNetwork() 888 assertNotNull(mCm.getActiveNetwork()); 889 assertEquals(mCm.getActiveNetwork(), mCm.getActiveNetworkForUid(Process.myUid())); 890 if (!NetworkCapabilities.isValidTransport(transport)) { 891 throw new IllegalStateException("Unknown transport " + transport); 892 } 893 switch (transport) { 894 case TRANSPORT_WIFI: 895 assertEquals(mCm.getActiveNetwork(), mWiFiNetworkAgent.getNetwork()); 896 break; 897 case TRANSPORT_CELLULAR: 898 assertEquals(mCm.getActiveNetwork(), mCellNetworkAgent.getNetwork()); 899 break; 900 default: 901 break; 902 } 903 // Test getNetworkInfo(Network) 904 assertNotNull(mCm.getNetworkInfo(mCm.getActiveNetwork())); 905 assertEquals(transportToLegacyType(transport), 906 mCm.getNetworkInfo(mCm.getActiveNetwork()).getType()); 907 // Test getNetworkCapabilities(Network) 908 assertNotNull(mCm.getNetworkCapabilities(mCm.getActiveNetwork())); 909 assertTrue(mCm.getNetworkCapabilities(mCm.getActiveNetwork()).hasTransport(transport)); 910 } 911 verifyNoNetwork()912 private void verifyNoNetwork() { 913 waitForIdle(); 914 // Test getActiveNetworkInfo() 915 assertNull(mCm.getActiveNetworkInfo()); 916 // Test getActiveNetwork() 917 assertNull(mCm.getActiveNetwork()); 918 assertNull(mCm.getActiveNetworkForUid(Process.myUid())); 919 // Test getAllNetworks() 920 assertEmpty(mCm.getAllNetworks()); 921 } 922 923 /** 924 * Return a ConditionVariable that opens when {@code count} numbers of CONNECTIVITY_ACTION 925 * broadcasts are received. 926 */ waitForConnectivityBroadcasts(final int count)927 private ConditionVariable waitForConnectivityBroadcasts(final int count) { 928 final ConditionVariable cv = new ConditionVariable(); 929 mServiceContext.registerReceiver(new BroadcastReceiver() { 930 private int remaining = count; 931 public void onReceive(Context context, Intent intent) { 932 if (--remaining == 0) { 933 cv.open(); 934 mServiceContext.unregisterReceiver(this); 935 } 936 } 937 }, new IntentFilter(CONNECTIVITY_ACTION)); 938 return cv; 939 } 940 testNetworkTypes()941 public void testNetworkTypes() { 942 // Ensure that our mocks for the networkAttributes config variable work as expected. If they 943 // don't, then tests that depend on CONNECTIVITY_ACTION broadcasts for these network types 944 // will fail. Failing here is much easier to debug. 945 assertTrue(mCm.isNetworkSupported(TYPE_WIFI)); 946 assertTrue(mCm.isNetworkSupported(TYPE_MOBILE)); 947 assertTrue(mCm.isNetworkSupported(TYPE_MOBILE_MMS)); 948 assertFalse(mCm.isNetworkSupported(TYPE_MOBILE_FOTA)); 949 950 // Check that TYPE_ETHERNET is supported. Unlike the asserts above, which only validate our 951 // mocks, this assert exercises the ConnectivityService code path that ensures that 952 // TYPE_ETHERNET is supported if the ethernet service is running. 953 assertTrue(mCm.isNetworkSupported(TYPE_ETHERNET)); 954 } 955 956 @SmallTest testLingering()957 public void testLingering() throws Exception { 958 verifyNoNetwork(); 959 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); 960 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 961 assertNull(mCm.getActiveNetworkInfo()); 962 assertNull(mCm.getActiveNetwork()); 963 // Test bringing up validated cellular. 964 ConditionVariable cv = waitForConnectivityBroadcasts(1); 965 mCellNetworkAgent.connect(true); 966 waitFor(cv); 967 verifyActiveNetwork(TRANSPORT_CELLULAR); 968 assertLength(2, mCm.getAllNetworks()); 969 assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) || 970 mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork())); 971 assertTrue(mCm.getAllNetworks()[0].equals(mWiFiNetworkAgent.getNetwork()) || 972 mCm.getAllNetworks()[1].equals(mWiFiNetworkAgent.getNetwork())); 973 // Test bringing up validated WiFi. 974 cv = waitForConnectivityBroadcasts(2); 975 mWiFiNetworkAgent.connect(true); 976 waitFor(cv); 977 verifyActiveNetwork(TRANSPORT_WIFI); 978 assertLength(2, mCm.getAllNetworks()); 979 assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) || 980 mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork())); 981 assertTrue(mCm.getAllNetworks()[0].equals(mCellNetworkAgent.getNetwork()) || 982 mCm.getAllNetworks()[1].equals(mCellNetworkAgent.getNetwork())); 983 // Test cellular linger timeout. 984 waitFor(mCellNetworkAgent.getDisconnectedCV()); 985 waitForIdle(); 986 assertLength(1, mCm.getAllNetworks()); 987 verifyActiveNetwork(TRANSPORT_WIFI); 988 assertLength(1, mCm.getAllNetworks()); 989 assertEquals(mCm.getAllNetworks()[0], mCm.getActiveNetwork()); 990 // Test WiFi disconnect. 991 cv = waitForConnectivityBroadcasts(1); 992 mWiFiNetworkAgent.disconnect(); 993 waitFor(cv); 994 verifyNoNetwork(); 995 } 996 997 @SmallTest testValidatedCellularOutscoresUnvalidatedWiFi()998 public void testValidatedCellularOutscoresUnvalidatedWiFi() throws Exception { 999 // Test bringing up unvalidated WiFi 1000 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 1001 ConditionVariable cv = waitForConnectivityBroadcasts(1); 1002 mWiFiNetworkAgent.connect(false); 1003 waitFor(cv); 1004 verifyActiveNetwork(TRANSPORT_WIFI); 1005 // Test bringing up unvalidated cellular 1006 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); 1007 mCellNetworkAgent.connect(false); 1008 waitForIdle(); 1009 verifyActiveNetwork(TRANSPORT_WIFI); 1010 // Test cellular disconnect. 1011 mCellNetworkAgent.disconnect(); 1012 waitForIdle(); 1013 verifyActiveNetwork(TRANSPORT_WIFI); 1014 // Test bringing up validated cellular 1015 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); 1016 cv = waitForConnectivityBroadcasts(2); 1017 mCellNetworkAgent.connect(true); 1018 waitFor(cv); 1019 verifyActiveNetwork(TRANSPORT_CELLULAR); 1020 // Test cellular disconnect. 1021 cv = waitForConnectivityBroadcasts(2); 1022 mCellNetworkAgent.disconnect(); 1023 waitFor(cv); 1024 verifyActiveNetwork(TRANSPORT_WIFI); 1025 // Test WiFi disconnect. 1026 cv = waitForConnectivityBroadcasts(1); 1027 mWiFiNetworkAgent.disconnect(); 1028 waitFor(cv); 1029 verifyNoNetwork(); 1030 } 1031 1032 @SmallTest testUnvalidatedWifiOutscoresUnvalidatedCellular()1033 public void testUnvalidatedWifiOutscoresUnvalidatedCellular() throws Exception { 1034 // Test bringing up unvalidated cellular. 1035 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); 1036 ConditionVariable cv = waitForConnectivityBroadcasts(1); 1037 mCellNetworkAgent.connect(false); 1038 waitFor(cv); 1039 verifyActiveNetwork(TRANSPORT_CELLULAR); 1040 // Test bringing up unvalidated WiFi. 1041 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 1042 cv = waitForConnectivityBroadcasts(2); 1043 mWiFiNetworkAgent.connect(false); 1044 waitFor(cv); 1045 verifyActiveNetwork(TRANSPORT_WIFI); 1046 // Test WiFi disconnect. 1047 cv = waitForConnectivityBroadcasts(2); 1048 mWiFiNetworkAgent.disconnect(); 1049 waitFor(cv); 1050 verifyActiveNetwork(TRANSPORT_CELLULAR); 1051 // Test cellular disconnect. 1052 cv = waitForConnectivityBroadcasts(1); 1053 mCellNetworkAgent.disconnect(); 1054 waitFor(cv); 1055 verifyNoNetwork(); 1056 } 1057 1058 @SmallTest testUnlingeringDoesNotValidate()1059 public void testUnlingeringDoesNotValidate() throws Exception { 1060 // Test bringing up unvalidated WiFi. 1061 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 1062 ConditionVariable cv = waitForConnectivityBroadcasts(1); 1063 mWiFiNetworkAgent.connect(false); 1064 waitFor(cv); 1065 verifyActiveNetwork(TRANSPORT_WIFI); 1066 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability( 1067 NET_CAPABILITY_VALIDATED)); 1068 // Test bringing up validated cellular. 1069 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); 1070 cv = waitForConnectivityBroadcasts(2); 1071 mCellNetworkAgent.connect(true); 1072 waitFor(cv); 1073 verifyActiveNetwork(TRANSPORT_CELLULAR); 1074 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability( 1075 NET_CAPABILITY_VALIDATED)); 1076 // Test cellular disconnect. 1077 cv = waitForConnectivityBroadcasts(2); 1078 mCellNetworkAgent.disconnect(); 1079 waitFor(cv); 1080 verifyActiveNetwork(TRANSPORT_WIFI); 1081 // Unlingering a network should not cause it to be marked as validated. 1082 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability( 1083 NET_CAPABILITY_VALIDATED)); 1084 } 1085 1086 @SmallTest testCellularOutscoresWeakWifi()1087 public void testCellularOutscoresWeakWifi() throws Exception { 1088 // Test bringing up validated cellular. 1089 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); 1090 ConditionVariable cv = waitForConnectivityBroadcasts(1); 1091 mCellNetworkAgent.connect(true); 1092 waitFor(cv); 1093 verifyActiveNetwork(TRANSPORT_CELLULAR); 1094 // Test bringing up validated WiFi. 1095 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 1096 cv = waitForConnectivityBroadcasts(2); 1097 mWiFiNetworkAgent.connect(true); 1098 waitFor(cv); 1099 verifyActiveNetwork(TRANSPORT_WIFI); 1100 // Test WiFi getting really weak. 1101 cv = waitForConnectivityBroadcasts(2); 1102 mWiFiNetworkAgent.adjustScore(-11); 1103 waitFor(cv); 1104 verifyActiveNetwork(TRANSPORT_CELLULAR); 1105 // Test WiFi restoring signal strength. 1106 cv = waitForConnectivityBroadcasts(2); 1107 mWiFiNetworkAgent.adjustScore(11); 1108 waitFor(cv); 1109 verifyActiveNetwork(TRANSPORT_WIFI); 1110 } 1111 1112 @SmallTest testReapingNetwork()1113 public void testReapingNetwork() throws Exception { 1114 // Test bringing up WiFi without NET_CAPABILITY_INTERNET. 1115 // Expect it to be torn down immediately because it satisfies no requests. 1116 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 1117 ConditionVariable cv = mWiFiNetworkAgent.getDisconnectedCV(); 1118 mWiFiNetworkAgent.connectWithoutInternet(); 1119 waitFor(cv); 1120 // Test bringing up cellular without NET_CAPABILITY_INTERNET. 1121 // Expect it to be torn down immediately because it satisfies no requests. 1122 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 1123 cv = mCellNetworkAgent.getDisconnectedCV(); 1124 mCellNetworkAgent.connectWithoutInternet(); 1125 waitFor(cv); 1126 // Test bringing up validated WiFi. 1127 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 1128 cv = waitForConnectivityBroadcasts(1); 1129 mWiFiNetworkAgent.connect(true); 1130 waitFor(cv); 1131 verifyActiveNetwork(TRANSPORT_WIFI); 1132 // Test bringing up unvalidated cellular. 1133 // Expect it to be torn down because it could never be the highest scoring network 1134 // satisfying the default request even if it validated. 1135 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); 1136 cv = mCellNetworkAgent.getDisconnectedCV(); 1137 mCellNetworkAgent.connect(false); 1138 waitFor(cv); 1139 verifyActiveNetwork(TRANSPORT_WIFI); 1140 cv = mWiFiNetworkAgent.getDisconnectedCV(); 1141 mWiFiNetworkAgent.disconnect(); 1142 waitFor(cv); 1143 } 1144 1145 @SmallTest testCellularFallback()1146 public void testCellularFallback() throws Exception { 1147 // Test bringing up validated cellular. 1148 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); 1149 ConditionVariable cv = waitForConnectivityBroadcasts(1); 1150 mCellNetworkAgent.connect(true); 1151 waitFor(cv); 1152 verifyActiveNetwork(TRANSPORT_CELLULAR); 1153 // Test bringing up validated WiFi. 1154 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 1155 cv = waitForConnectivityBroadcasts(2); 1156 mWiFiNetworkAgent.connect(true); 1157 waitFor(cv); 1158 verifyActiveNetwork(TRANSPORT_WIFI); 1159 // Reevaluate WiFi (it'll instantly fail DNS). 1160 cv = waitForConnectivityBroadcasts(2); 1161 assertTrue(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability( 1162 NET_CAPABILITY_VALIDATED)); 1163 mCm.reportBadNetwork(mWiFiNetworkAgent.getNetwork()); 1164 // Should quickly fall back to Cellular. 1165 waitFor(cv); 1166 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability( 1167 NET_CAPABILITY_VALIDATED)); 1168 verifyActiveNetwork(TRANSPORT_CELLULAR); 1169 // Reevaluate cellular (it'll instantly fail DNS). 1170 cv = waitForConnectivityBroadcasts(2); 1171 assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability( 1172 NET_CAPABILITY_VALIDATED)); 1173 mCm.reportBadNetwork(mCellNetworkAgent.getNetwork()); 1174 // Should quickly fall back to WiFi. 1175 waitFor(cv); 1176 assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability( 1177 NET_CAPABILITY_VALIDATED)); 1178 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability( 1179 NET_CAPABILITY_VALIDATED)); 1180 verifyActiveNetwork(TRANSPORT_WIFI); 1181 } 1182 1183 @SmallTest testWiFiFallback()1184 public void testWiFiFallback() throws Exception { 1185 // Test bringing up unvalidated WiFi. 1186 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 1187 ConditionVariable cv = waitForConnectivityBroadcasts(1); 1188 mWiFiNetworkAgent.connect(false); 1189 waitFor(cv); 1190 verifyActiveNetwork(TRANSPORT_WIFI); 1191 // Test bringing up validated cellular. 1192 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); 1193 cv = waitForConnectivityBroadcasts(2); 1194 mCellNetworkAgent.connect(true); 1195 waitFor(cv); 1196 verifyActiveNetwork(TRANSPORT_CELLULAR); 1197 // Reevaluate cellular (it'll instantly fail DNS). 1198 cv = waitForConnectivityBroadcasts(2); 1199 assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability( 1200 NET_CAPABILITY_VALIDATED)); 1201 mCm.reportBadNetwork(mCellNetworkAgent.getNetwork()); 1202 // Should quickly fall back to WiFi. 1203 waitFor(cv); 1204 assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability( 1205 NET_CAPABILITY_VALIDATED)); 1206 verifyActiveNetwork(TRANSPORT_WIFI); 1207 } 1208 1209 enum CallbackState { 1210 NONE, 1211 AVAILABLE, 1212 NETWORK_CAPABILITIES, 1213 LINK_PROPERTIES, 1214 SUSPENDED, 1215 LOSING, 1216 LOST, 1217 UNAVAILABLE 1218 } 1219 1220 private static class CallbackInfo { 1221 public final CallbackState state; 1222 public final Network network; 1223 public final Object arg; CallbackInfo(CallbackState s, Network n, Object o)1224 public CallbackInfo(CallbackState s, Network n, Object o) { 1225 state = s; network = n; arg = o; 1226 } toString()1227 public String toString() { 1228 return String.format("%s (%s) (%s)", state, network, arg); 1229 } 1230 @Override equals(Object o)1231 public boolean equals(Object o) { 1232 if (!(o instanceof CallbackInfo)) return false; 1233 // Ignore timeMs, since it's unpredictable. 1234 CallbackInfo other = (CallbackInfo) o; 1235 return (state == other.state) && Objects.equals(network, other.network); 1236 } 1237 @Override hashCode()1238 public int hashCode() { 1239 return Objects.hash(state, network); 1240 } 1241 } 1242 1243 /** 1244 * Utility NetworkCallback for testing. The caller must explicitly test for all the callbacks 1245 * this class receives, by calling expectCallback() exactly once each time a callback is 1246 * received. assertNoCallback may be called at any time. 1247 */ 1248 private class TestNetworkCallback extends NetworkCallback { 1249 // Chosen to be much less than the linger timeout. This ensures that we can distinguish 1250 // between a LOST callback that arrives immediately and a LOST callback that arrives after 1251 // the linger timeout. 1252 private final static int TIMEOUT_MS = 100; 1253 1254 private final LinkedBlockingQueue<CallbackInfo> mCallbacks = new LinkedBlockingQueue<>(); 1255 setLastCallback(CallbackState state, Network network, Object o)1256 protected void setLastCallback(CallbackState state, Network network, Object o) { 1257 mCallbacks.offer(new CallbackInfo(state, network, o)); 1258 } 1259 1260 @Override onAvailable(Network network)1261 public void onAvailable(Network network) { 1262 setLastCallback(CallbackState.AVAILABLE, network, null); 1263 } 1264 1265 @Override onCapabilitiesChanged(Network network, NetworkCapabilities netCap)1266 public void onCapabilitiesChanged(Network network, NetworkCapabilities netCap) { 1267 setLastCallback(CallbackState.NETWORK_CAPABILITIES, network, netCap); 1268 } 1269 1270 @Override onLinkPropertiesChanged(Network network, LinkProperties linkProp)1271 public void onLinkPropertiesChanged(Network network, LinkProperties linkProp) { 1272 setLastCallback(CallbackState.LINK_PROPERTIES, network, linkProp); 1273 } 1274 1275 @Override onUnavailable()1276 public void onUnavailable() { 1277 setLastCallback(CallbackState.UNAVAILABLE, null, null); 1278 } 1279 1280 @Override onNetworkSuspended(Network network)1281 public void onNetworkSuspended(Network network) { 1282 setLastCallback(CallbackState.SUSPENDED, network, null); 1283 } 1284 1285 @Override onLosing(Network network, int maxMsToLive)1286 public void onLosing(Network network, int maxMsToLive) { 1287 setLastCallback(CallbackState.LOSING, network, maxMsToLive /* autoboxed int */); 1288 } 1289 1290 @Override onLost(Network network)1291 public void onLost(Network network) { 1292 setLastCallback(CallbackState.LOST, network, null); 1293 } 1294 nextCallback(int timeoutMs)1295 CallbackInfo nextCallback(int timeoutMs) { 1296 CallbackInfo cb = null; 1297 try { 1298 cb = mCallbacks.poll(timeoutMs, TimeUnit.MILLISECONDS); 1299 } catch (InterruptedException e) { 1300 } 1301 if (cb == null) { 1302 // LinkedBlockingQueue.poll() returns null if it timeouts. 1303 fail("Did not receive callback after " + timeoutMs + "ms"); 1304 } 1305 return cb; 1306 } 1307 expectCallback(CallbackState state, MockNetworkAgent agent, int timeoutMs)1308 CallbackInfo expectCallback(CallbackState state, MockNetworkAgent agent, int timeoutMs) { 1309 final Network expectedNetwork = (agent != null) ? agent.getNetwork() : null; 1310 CallbackInfo expected = new CallbackInfo(state, expectedNetwork, 0); 1311 CallbackInfo actual = nextCallback(timeoutMs); 1312 assertEquals("Unexpected callback:", expected, actual); 1313 1314 if (state == CallbackState.LOSING) { 1315 String msg = String.format( 1316 "Invalid linger time value %d, must be between %d and %d", 1317 actual.arg, 0, TEST_LINGER_DELAY_MS); 1318 int maxMsToLive = (Integer) actual.arg; 1319 assertTrue(msg, 0 <= maxMsToLive && maxMsToLive <= TEST_LINGER_DELAY_MS); 1320 } 1321 1322 return actual; 1323 } 1324 expectCallback(CallbackState state, MockNetworkAgent agent)1325 CallbackInfo expectCallback(CallbackState state, MockNetworkAgent agent) { 1326 return expectCallback(state, agent, TIMEOUT_MS); 1327 } 1328 expectCallbackLike(Predicate<CallbackInfo> fn)1329 CallbackInfo expectCallbackLike(Predicate<CallbackInfo> fn) { 1330 return expectCallbackLike(fn, TIMEOUT_MS); 1331 } 1332 expectCallbackLike(Predicate<CallbackInfo> fn, int timeoutMs)1333 CallbackInfo expectCallbackLike(Predicate<CallbackInfo> fn, int timeoutMs) { 1334 int timeLeft = timeoutMs; 1335 while (timeLeft > 0) { 1336 long start = SystemClock.elapsedRealtime(); 1337 CallbackInfo info = nextCallback(timeLeft); 1338 if (fn.test(info)) { 1339 return info; 1340 } 1341 timeLeft -= (SystemClock.elapsedRealtime() - start); 1342 } 1343 fail("Did not receive expected callback after " + timeoutMs + "ms"); 1344 return null; 1345 } 1346 expectAvailableCallbacks( MockNetworkAgent agent, boolean expectSuspended, int timeoutMs)1347 void expectAvailableCallbacks( 1348 MockNetworkAgent agent, boolean expectSuspended, int timeoutMs) { 1349 expectCallback(CallbackState.AVAILABLE, agent, timeoutMs); 1350 if (expectSuspended) { 1351 expectCallback(CallbackState.SUSPENDED, agent, timeoutMs); 1352 } 1353 expectCallback(CallbackState.NETWORK_CAPABILITIES, agent, timeoutMs); 1354 expectCallback(CallbackState.LINK_PROPERTIES, agent, timeoutMs); 1355 } 1356 expectAvailableCallbacks(MockNetworkAgent agent)1357 void expectAvailableCallbacks(MockNetworkAgent agent) { 1358 expectAvailableCallbacks(agent, false, TIMEOUT_MS); 1359 } 1360 expectAvailableAndSuspendedCallbacks(MockNetworkAgent agent)1361 void expectAvailableAndSuspendedCallbacks(MockNetworkAgent agent) { 1362 expectAvailableCallbacks(agent, true, TIMEOUT_MS); 1363 } 1364 expectAvailableAndValidatedCallbacks(MockNetworkAgent agent)1365 void expectAvailableAndValidatedCallbacks(MockNetworkAgent agent) { 1366 expectAvailableCallbacks(agent, false, TIMEOUT_MS); 1367 expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, agent); 1368 } 1369 expectCapabilitiesWith(int capability, MockNetworkAgent agent)1370 void expectCapabilitiesWith(int capability, MockNetworkAgent agent) { 1371 CallbackInfo cbi = expectCallback(CallbackState.NETWORK_CAPABILITIES, agent); 1372 NetworkCapabilities nc = (NetworkCapabilities) cbi.arg; 1373 assertTrue(nc.hasCapability(capability)); 1374 } 1375 expectCapabilitiesWithout(int capability, MockNetworkAgent agent)1376 void expectCapabilitiesWithout(int capability, MockNetworkAgent agent) { 1377 CallbackInfo cbi = expectCallback(CallbackState.NETWORK_CAPABILITIES, agent); 1378 NetworkCapabilities nc = (NetworkCapabilities) cbi.arg; 1379 assertFalse(nc.hasCapability(capability)); 1380 } 1381 assertNoCallback()1382 void assertNoCallback() { 1383 waitForIdle(); 1384 CallbackInfo c = mCallbacks.peek(); 1385 assertNull("Unexpected callback: " + c, c); 1386 } 1387 } 1388 1389 // Can't be part of TestNetworkCallback because "cannot be declared static; static methods can 1390 // only be declared in a static or top level type". assertNoCallbacks(TestNetworkCallback .... callbacks)1391 static void assertNoCallbacks(TestNetworkCallback ... callbacks) { 1392 for (TestNetworkCallback c : callbacks) { 1393 c.assertNoCallback(); 1394 } 1395 } 1396 1397 @SmallTest testStateChangeNetworkCallbacks()1398 public void testStateChangeNetworkCallbacks() throws Exception { 1399 final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback(); 1400 final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback(); 1401 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback(); 1402 final NetworkRequest genericRequest = new NetworkRequest.Builder() 1403 .clearCapabilities().build(); 1404 final NetworkRequest wifiRequest = new NetworkRequest.Builder() 1405 .addTransportType(TRANSPORT_WIFI).build(); 1406 final NetworkRequest cellRequest = new NetworkRequest.Builder() 1407 .addTransportType(TRANSPORT_CELLULAR).build(); 1408 mCm.registerNetworkCallback(genericRequest, genericNetworkCallback); 1409 mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback); 1410 mCm.registerNetworkCallback(cellRequest, cellNetworkCallback); 1411 1412 // Test unvalidated networks 1413 ConditionVariable cv = waitForConnectivityBroadcasts(1); 1414 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); 1415 mCellNetworkAgent.connect(false); 1416 genericNetworkCallback.expectAvailableCallbacks(mCellNetworkAgent); 1417 cellNetworkCallback.expectAvailableCallbacks(mCellNetworkAgent); 1418 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 1419 waitFor(cv); 1420 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback); 1421 1422 // This should not trigger spurious onAvailable() callbacks, b/21762680. 1423 mCellNetworkAgent.adjustScore(-1); 1424 waitForIdle(); 1425 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback); 1426 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 1427 1428 cv = waitForConnectivityBroadcasts(2); 1429 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 1430 mWiFiNetworkAgent.connect(false); 1431 genericNetworkCallback.expectAvailableCallbacks(mWiFiNetworkAgent); 1432 wifiNetworkCallback.expectAvailableCallbacks(mWiFiNetworkAgent); 1433 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 1434 waitFor(cv); 1435 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback); 1436 1437 cv = waitForConnectivityBroadcasts(2); 1438 mWiFiNetworkAgent.disconnect(); 1439 genericNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); 1440 wifiNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); 1441 cellNetworkCallback.assertNoCallback(); 1442 waitFor(cv); 1443 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback); 1444 1445 cv = waitForConnectivityBroadcasts(1); 1446 mCellNetworkAgent.disconnect(); 1447 genericNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent); 1448 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent); 1449 waitFor(cv); 1450 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback); 1451 1452 // Test validated networks 1453 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); 1454 mCellNetworkAgent.connect(true); 1455 genericNetworkCallback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent); 1456 cellNetworkCallback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent); 1457 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 1458 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback); 1459 1460 // This should not trigger spurious onAvailable() callbacks, b/21762680. 1461 mCellNetworkAgent.adjustScore(-1); 1462 waitForIdle(); 1463 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback); 1464 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 1465 1466 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 1467 mWiFiNetworkAgent.connect(true); 1468 genericNetworkCallback.expectAvailableCallbacks(mWiFiNetworkAgent); 1469 genericNetworkCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent); 1470 genericNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent); 1471 wifiNetworkCallback.expectAvailableAndValidatedCallbacks(mWiFiNetworkAgent); 1472 cellNetworkCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent); 1473 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 1474 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback); 1475 1476 mWiFiNetworkAgent.disconnect(); 1477 genericNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); 1478 wifiNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); 1479 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback); 1480 1481 mCellNetworkAgent.disconnect(); 1482 genericNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent); 1483 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent); 1484 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback); 1485 } 1486 1487 @SmallTest testMultipleLingering()1488 public void testMultipleLingering() { 1489 NetworkRequest request = new NetworkRequest.Builder() 1490 .clearCapabilities().addCapability(NET_CAPABILITY_NOT_METERED) 1491 .build(); 1492 TestNetworkCallback callback = new TestNetworkCallback(); 1493 mCm.registerNetworkCallback(request, callback); 1494 1495 TestNetworkCallback defaultCallback = new TestNetworkCallback(); 1496 mCm.registerDefaultNetworkCallback(defaultCallback); 1497 1498 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); 1499 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 1500 mEthernetNetworkAgent = new MockNetworkAgent(TRANSPORT_ETHERNET); 1501 1502 mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED); 1503 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED); 1504 mEthernetNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED); 1505 1506 mCellNetworkAgent.connect(true); 1507 callback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent); 1508 defaultCallback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent); 1509 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 1510 1511 mWiFiNetworkAgent.connect(true); 1512 // We get AVAILABLE on wifi when wifi connects and satisfies our unmetered request. 1513 // We then get LOSING when wifi validates and cell is outscored. 1514 callback.expectAvailableCallbacks(mWiFiNetworkAgent); 1515 // TODO: Investigate sending validated before losing. 1516 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent); 1517 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent); 1518 defaultCallback.expectAvailableAndValidatedCallbacks(mWiFiNetworkAgent); 1519 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 1520 1521 mEthernetNetworkAgent.connect(true); 1522 callback.expectAvailableCallbacks(mEthernetNetworkAgent); 1523 // TODO: Investigate sending validated before losing. 1524 callback.expectCallback(CallbackState.LOSING, mWiFiNetworkAgent); 1525 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mEthernetNetworkAgent); 1526 defaultCallback.expectAvailableAndValidatedCallbacks(mEthernetNetworkAgent); 1527 assertEquals(mEthernetNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 1528 1529 mEthernetNetworkAgent.disconnect(); 1530 callback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent); 1531 defaultCallback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent); 1532 defaultCallback.expectAvailableCallbacks(mWiFiNetworkAgent); 1533 1534 for (int i = 0; i < 4; i++) { 1535 MockNetworkAgent oldNetwork, newNetwork; 1536 if (i % 2 == 0) { 1537 mWiFiNetworkAgent.adjustScore(-15); 1538 oldNetwork = mWiFiNetworkAgent; 1539 newNetwork = mCellNetworkAgent; 1540 } else { 1541 mWiFiNetworkAgent.adjustScore(15); 1542 oldNetwork = mCellNetworkAgent; 1543 newNetwork = mWiFiNetworkAgent; 1544 1545 } 1546 callback.expectCallback(CallbackState.LOSING, oldNetwork); 1547 // TODO: should we send an AVAILABLE callback to newNetwork, to indicate that it is no 1548 // longer lingering? 1549 defaultCallback.expectAvailableCallbacks(newNetwork); 1550 assertEquals(newNetwork.getNetwork(), mCm.getActiveNetwork()); 1551 } 1552 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 1553 1554 // Verify that if a network no longer satisfies a request, we send LOST and not LOSING, even 1555 // if the network is still up. 1556 mWiFiNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED); 1557 // We expect a notification about the capabilities change, and nothing else. 1558 defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_METERED, mWiFiNetworkAgent); 1559 defaultCallback.assertNoCallback(); 1560 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); 1561 1562 // Wifi no longer satisfies our listen, which is for an unmetered network. 1563 // But because its score is 55, it's still up (and the default network). 1564 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 1565 1566 // Disconnect our test networks. 1567 mWiFiNetworkAgent.disconnect(); 1568 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); 1569 defaultCallback.expectAvailableCallbacks(mCellNetworkAgent); 1570 mCellNetworkAgent.disconnect(); 1571 defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent); 1572 1573 mCm.unregisterNetworkCallback(callback); 1574 waitForIdle(); 1575 1576 // Check that a network is only lingered or torn down if it would not satisfy a request even 1577 // if it validated. 1578 request = new NetworkRequest.Builder().clearCapabilities().build(); 1579 callback = new TestNetworkCallback(); 1580 1581 mCm.registerNetworkCallback(request, callback); 1582 1583 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); 1584 mCellNetworkAgent.connect(false); // Score: 10 1585 callback.expectAvailableCallbacks(mCellNetworkAgent); 1586 defaultCallback.expectAvailableCallbacks(mCellNetworkAgent); 1587 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 1588 1589 // Bring up wifi with a score of 20. 1590 // Cell stays up because it would satisfy the default request if it validated. 1591 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 1592 mWiFiNetworkAgent.connect(false); // Score: 20 1593 callback.expectAvailableCallbacks(mWiFiNetworkAgent); 1594 defaultCallback.expectAvailableCallbacks(mWiFiNetworkAgent); 1595 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 1596 1597 mWiFiNetworkAgent.disconnect(); 1598 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); 1599 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); 1600 defaultCallback.expectAvailableCallbacks(mCellNetworkAgent); 1601 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 1602 1603 // Bring up wifi with a score of 70. 1604 // Cell is lingered because it would not satisfy any request, even if it validated. 1605 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 1606 mWiFiNetworkAgent.adjustScore(50); 1607 mWiFiNetworkAgent.connect(false); // Score: 70 1608 callback.expectAvailableCallbacks(mWiFiNetworkAgent); 1609 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent); 1610 defaultCallback.expectAvailableCallbacks(mWiFiNetworkAgent); 1611 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 1612 1613 // Tear down wifi. 1614 mWiFiNetworkAgent.disconnect(); 1615 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); 1616 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); 1617 defaultCallback.expectAvailableCallbacks(mCellNetworkAgent); 1618 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 1619 1620 // Bring up wifi, then validate it. Previous versions would immediately tear down cell, but 1621 // it's arguably correct to linger it, since it was the default network before it validated. 1622 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 1623 mWiFiNetworkAgent.connect(true); 1624 callback.expectAvailableCallbacks(mWiFiNetworkAgent); 1625 // TODO: Investigate sending validated before losing. 1626 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent); 1627 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent); 1628 defaultCallback.expectAvailableAndValidatedCallbacks(mWiFiNetworkAgent); 1629 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 1630 1631 mWiFiNetworkAgent.disconnect(); 1632 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); 1633 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); 1634 defaultCallback.expectAvailableCallbacks(mCellNetworkAgent); 1635 mCellNetworkAgent.disconnect(); 1636 callback.expectCallback(CallbackState.LOST, mCellNetworkAgent); 1637 defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent); 1638 1639 // If a network is lingering, and we add and remove a request from it, resume lingering. 1640 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); 1641 mCellNetworkAgent.connect(true); 1642 callback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent); 1643 defaultCallback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent); 1644 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 1645 mWiFiNetworkAgent.connect(true); 1646 defaultCallback.expectAvailableAndValidatedCallbacks(mWiFiNetworkAgent); 1647 callback.expectAvailableCallbacks(mWiFiNetworkAgent); 1648 // TODO: Investigate sending validated before losing. 1649 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent); 1650 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent); 1651 1652 NetworkRequest cellRequest = new NetworkRequest.Builder() 1653 .addTransportType(TRANSPORT_CELLULAR).build(); 1654 NetworkCallback noopCallback = new NetworkCallback(); 1655 mCm.requestNetwork(cellRequest, noopCallback); 1656 // TODO: should this cause an AVAILABLE callback, to indicate that the network is no longer 1657 // lingering? 1658 mCm.unregisterNetworkCallback(noopCallback); 1659 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent); 1660 1661 // Similar to the above: lingering can start even after the lingered request is removed. 1662 // Disconnect wifi and switch to cell. 1663 mWiFiNetworkAgent.disconnect(); 1664 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); 1665 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); 1666 defaultCallback.expectAvailableCallbacks(mCellNetworkAgent); 1667 1668 // Cell is now the default network. Pin it with a cell-specific request. 1669 noopCallback = new NetworkCallback(); // Can't reuse NetworkCallbacks. http://b/20701525 1670 mCm.requestNetwork(cellRequest, noopCallback); 1671 1672 // Now connect wifi, and expect it to become the default network. 1673 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 1674 mWiFiNetworkAgent.connect(true); 1675 callback.expectAvailableAndValidatedCallbacks(mWiFiNetworkAgent); 1676 defaultCallback.expectAvailableAndValidatedCallbacks(mWiFiNetworkAgent); 1677 // The default request is lingering on cell, but nothing happens to cell, and we send no 1678 // callbacks for it, because it's kept up by cellRequest. 1679 callback.assertNoCallback(); 1680 // Now unregister cellRequest and expect cell to start lingering. 1681 mCm.unregisterNetworkCallback(noopCallback); 1682 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent); 1683 1684 // Let linger run its course. 1685 callback.assertNoCallback(); 1686 final int lingerTimeoutMs = TEST_LINGER_DELAY_MS + TEST_LINGER_DELAY_MS / 4; 1687 callback.expectCallback(CallbackState.LOST, mCellNetworkAgent, lingerTimeoutMs); 1688 1689 // Register a TRACK_DEFAULT request and check that it does not affect lingering. 1690 TestNetworkCallback trackDefaultCallback = new TestNetworkCallback(); 1691 mCm.registerDefaultNetworkCallback(trackDefaultCallback); 1692 trackDefaultCallback.expectAvailableCallbacks(mWiFiNetworkAgent); 1693 mEthernetNetworkAgent = new MockNetworkAgent(TRANSPORT_ETHERNET); 1694 mEthernetNetworkAgent.connect(true); 1695 callback.expectAvailableCallbacks(mEthernetNetworkAgent); 1696 callback.expectCallback(CallbackState.LOSING, mWiFiNetworkAgent); 1697 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mEthernetNetworkAgent); 1698 trackDefaultCallback.expectAvailableAndValidatedCallbacks(mEthernetNetworkAgent); 1699 defaultCallback.expectAvailableAndValidatedCallbacks(mEthernetNetworkAgent); 1700 1701 // Let linger run its course. 1702 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent, lingerTimeoutMs); 1703 1704 // Clean up. 1705 mEthernetNetworkAgent.disconnect(); 1706 callback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent); 1707 defaultCallback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent); 1708 trackDefaultCallback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent); 1709 1710 mCm.unregisterNetworkCallback(callback); 1711 mCm.unregisterNetworkCallback(defaultCallback); 1712 mCm.unregisterNetworkCallback(trackDefaultCallback); 1713 } 1714 1715 @SmallTest testExplicitlySelected()1716 public void testExplicitlySelected() { 1717 NetworkRequest request = new NetworkRequest.Builder() 1718 .clearCapabilities().addCapability(NET_CAPABILITY_INTERNET) 1719 .build(); 1720 TestNetworkCallback callback = new TestNetworkCallback(); 1721 mCm.registerNetworkCallback(request, callback); 1722 1723 // Bring up validated cell. 1724 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); 1725 mCellNetworkAgent.connect(true); 1726 callback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent); 1727 1728 // Bring up unvalidated wifi with explicitlySelected=true. 1729 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 1730 mWiFiNetworkAgent.explicitlySelected(false); 1731 mWiFiNetworkAgent.connect(false); 1732 callback.expectAvailableCallbacks(mWiFiNetworkAgent); 1733 1734 // Cell Remains the default. 1735 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 1736 1737 // Lower wifi's score to below than cell, and check that it doesn't disconnect because 1738 // it's explicitly selected. 1739 mWiFiNetworkAgent.adjustScore(-40); 1740 mWiFiNetworkAgent.adjustScore(40); 1741 callback.assertNoCallback(); 1742 1743 // If the user chooses yes on the "No Internet access, stay connected?" dialog, we switch to 1744 // wifi even though it's unvalidated. 1745 mCm.setAcceptUnvalidated(mWiFiNetworkAgent.getNetwork(), true, false); 1746 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent); 1747 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 1748 1749 // Disconnect wifi, and then reconnect, again with explicitlySelected=true. 1750 mWiFiNetworkAgent.disconnect(); 1751 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); 1752 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 1753 mWiFiNetworkAgent.explicitlySelected(false); 1754 mWiFiNetworkAgent.connect(false); 1755 callback.expectAvailableCallbacks(mWiFiNetworkAgent); 1756 1757 // If the user chooses no on the "No Internet access, stay connected?" dialog, we ask the 1758 // network to disconnect. 1759 mCm.setAcceptUnvalidated(mWiFiNetworkAgent.getNetwork(), false, false); 1760 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); 1761 1762 // Reconnect, again with explicitlySelected=true, but this time validate. 1763 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 1764 mWiFiNetworkAgent.explicitlySelected(false); 1765 mWiFiNetworkAgent.connect(true); 1766 callback.expectAvailableCallbacks(mWiFiNetworkAgent); 1767 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent); 1768 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent); 1769 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 1770 1771 // BUG: the network will no longer linger, even though it's validated and outscored. 1772 // TODO: fix this. 1773 mEthernetNetworkAgent = new MockNetworkAgent(TRANSPORT_ETHERNET); 1774 mEthernetNetworkAgent.connect(true); 1775 callback.expectAvailableAndValidatedCallbacks(mEthernetNetworkAgent); 1776 assertEquals(mEthernetNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 1777 callback.assertNoCallback(); 1778 1779 // Clean up. 1780 mWiFiNetworkAgent.disconnect(); 1781 mCellNetworkAgent.disconnect(); 1782 mEthernetNetworkAgent.disconnect(); 1783 1784 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); 1785 callback.expectCallback(CallbackState.LOST, mCellNetworkAgent); 1786 callback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent); 1787 } 1788 tryNetworkFactoryRequests(int capability)1789 private void tryNetworkFactoryRequests(int capability) throws Exception { 1790 // Verify NOT_RESTRICTED is set appropriately 1791 final NetworkCapabilities nc = new NetworkRequest.Builder().addCapability(capability) 1792 .build().networkCapabilities; 1793 if (capability == NET_CAPABILITY_CBS || capability == NET_CAPABILITY_DUN || 1794 capability == NET_CAPABILITY_EIMS || capability == NET_CAPABILITY_FOTA || 1795 capability == NET_CAPABILITY_IA || capability == NET_CAPABILITY_IMS || 1796 capability == NET_CAPABILITY_RCS || capability == NET_CAPABILITY_XCAP) { 1797 assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)); 1798 } else { 1799 assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)); 1800 } 1801 1802 NetworkCapabilities filter = new NetworkCapabilities(); 1803 filter.addCapability(capability); 1804 final HandlerThread handlerThread = new HandlerThread("testNetworkFactoryRequests"); 1805 handlerThread.start(); 1806 final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(), 1807 mServiceContext, "testFactory", filter); 1808 testFactory.setScoreFilter(40); 1809 ConditionVariable cv = testFactory.getNetworkStartedCV(); 1810 testFactory.expectAddRequests(1); 1811 testFactory.register(); 1812 testFactory.waitForNetworkRequests(1); 1813 int expectedRequestCount = 1; 1814 NetworkCallback networkCallback = null; 1815 // For non-INTERNET capabilities we cannot rely on the default request being present, so 1816 // add one. 1817 if (capability != NET_CAPABILITY_INTERNET) { 1818 assertFalse(testFactory.getMyStartRequested()); 1819 NetworkRequest request = new NetworkRequest.Builder().addCapability(capability).build(); 1820 networkCallback = new NetworkCallback(); 1821 testFactory.expectAddRequests(1); 1822 mCm.requestNetwork(request, networkCallback); 1823 expectedRequestCount++; 1824 testFactory.waitForNetworkRequests(expectedRequestCount); 1825 } 1826 waitFor(cv); 1827 assertEquals(expectedRequestCount, testFactory.getMyRequestCount()); 1828 assertTrue(testFactory.getMyStartRequested()); 1829 1830 // Now bring in a higher scored network. 1831 MockNetworkAgent testAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); 1832 // Rather than create a validated network which complicates things by registering it's 1833 // own NetworkRequest during startup, just bump up the score to cancel out the 1834 // unvalidated penalty. 1835 testAgent.adjustScore(40); 1836 cv = testFactory.getNetworkStoppedCV(); 1837 1838 // When testAgent connects, ConnectivityService will re-send us all current requests with 1839 // the new score. There are expectedRequestCount such requests, and we must wait for all of 1840 // them. 1841 testFactory.expectAddRequests(expectedRequestCount); 1842 testAgent.connect(false); 1843 testAgent.addCapability(capability); 1844 waitFor(cv); 1845 testFactory.waitForNetworkRequests(expectedRequestCount); 1846 assertFalse(testFactory.getMyStartRequested()); 1847 1848 // Bring in a bunch of requests. 1849 testFactory.expectAddRequests(10); 1850 assertEquals(expectedRequestCount, testFactory.getMyRequestCount()); 1851 ConnectivityManager.NetworkCallback[] networkCallbacks = 1852 new ConnectivityManager.NetworkCallback[10]; 1853 for (int i = 0; i< networkCallbacks.length; i++) { 1854 networkCallbacks[i] = new ConnectivityManager.NetworkCallback(); 1855 NetworkRequest.Builder builder = new NetworkRequest.Builder(); 1856 builder.addCapability(capability); 1857 mCm.requestNetwork(builder.build(), networkCallbacks[i]); 1858 } 1859 testFactory.waitForNetworkRequests(10 + expectedRequestCount); 1860 assertFalse(testFactory.getMyStartRequested()); 1861 1862 // Remove the requests. 1863 testFactory.expectRemoveRequests(10); 1864 for (int i = 0; i < networkCallbacks.length; i++) { 1865 mCm.unregisterNetworkCallback(networkCallbacks[i]); 1866 } 1867 testFactory.waitForNetworkRequests(expectedRequestCount); 1868 assertFalse(testFactory.getMyStartRequested()); 1869 1870 // Drop the higher scored network. 1871 cv = testFactory.getNetworkStartedCV(); 1872 testAgent.disconnect(); 1873 waitFor(cv); 1874 assertEquals(expectedRequestCount, testFactory.getMyRequestCount()); 1875 assertTrue(testFactory.getMyStartRequested()); 1876 1877 testFactory.unregister(); 1878 if (networkCallback != null) mCm.unregisterNetworkCallback(networkCallback); 1879 handlerThread.quit(); 1880 } 1881 1882 @SmallTest testNetworkFactoryRequests()1883 public void testNetworkFactoryRequests() throws Exception { 1884 tryNetworkFactoryRequests(NET_CAPABILITY_MMS); 1885 tryNetworkFactoryRequests(NET_CAPABILITY_SUPL); 1886 tryNetworkFactoryRequests(NET_CAPABILITY_DUN); 1887 tryNetworkFactoryRequests(NET_CAPABILITY_FOTA); 1888 tryNetworkFactoryRequests(NET_CAPABILITY_IMS); 1889 tryNetworkFactoryRequests(NET_CAPABILITY_CBS); 1890 tryNetworkFactoryRequests(NET_CAPABILITY_WIFI_P2P); 1891 tryNetworkFactoryRequests(NET_CAPABILITY_IA); 1892 tryNetworkFactoryRequests(NET_CAPABILITY_RCS); 1893 tryNetworkFactoryRequests(NET_CAPABILITY_XCAP); 1894 tryNetworkFactoryRequests(NET_CAPABILITY_EIMS); 1895 tryNetworkFactoryRequests(NET_CAPABILITY_NOT_METERED); 1896 tryNetworkFactoryRequests(NET_CAPABILITY_INTERNET); 1897 tryNetworkFactoryRequests(NET_CAPABILITY_TRUSTED); 1898 tryNetworkFactoryRequests(NET_CAPABILITY_NOT_VPN); 1899 // Skipping VALIDATED and CAPTIVE_PORTAL as they're disallowed. 1900 } 1901 1902 @SmallTest testNoMutableNetworkRequests()1903 public void testNoMutableNetworkRequests() throws Exception { 1904 PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, new Intent("a"), 0); 1905 NetworkRequest request1 = new NetworkRequest.Builder() 1906 .addCapability(NET_CAPABILITY_VALIDATED) 1907 .build(); 1908 NetworkRequest request2 = new NetworkRequest.Builder() 1909 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL) 1910 .build(); 1911 1912 Class<IllegalArgumentException> expected = IllegalArgumentException.class; 1913 assertException(() -> { mCm.requestNetwork(request1, new NetworkCallback()); }, expected); 1914 assertException(() -> { mCm.requestNetwork(request1, pendingIntent); }, expected); 1915 assertException(() -> { mCm.requestNetwork(request2, new NetworkCallback()); }, expected); 1916 assertException(() -> { mCm.requestNetwork(request2, pendingIntent); }, expected); 1917 } 1918 1919 @SmallTest testMMSonWiFi()1920 public void testMMSonWiFi() throws Exception { 1921 // Test bringing up cellular without MMS NetworkRequest gets reaped 1922 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); 1923 mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS); 1924 ConditionVariable cv = mCellNetworkAgent.getDisconnectedCV(); 1925 mCellNetworkAgent.connectWithoutInternet(); 1926 waitFor(cv); 1927 waitForIdle(); 1928 assertEmpty(mCm.getAllNetworks()); 1929 verifyNoNetwork(); 1930 1931 // Test bringing up validated WiFi. 1932 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 1933 cv = waitForConnectivityBroadcasts(1); 1934 mWiFiNetworkAgent.connect(true); 1935 waitFor(cv); 1936 verifyActiveNetwork(TRANSPORT_WIFI); 1937 1938 // Register MMS NetworkRequest 1939 NetworkRequest.Builder builder = new NetworkRequest.Builder(); 1940 builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS); 1941 final TestNetworkCallback networkCallback = new TestNetworkCallback(); 1942 mCm.requestNetwork(builder.build(), networkCallback); 1943 1944 // Test bringing up unvalidated cellular with MMS 1945 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); 1946 mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS); 1947 mCellNetworkAgent.connectWithoutInternet(); 1948 networkCallback.expectAvailableCallbacks(mCellNetworkAgent); 1949 verifyActiveNetwork(TRANSPORT_WIFI); 1950 1951 // Test releasing NetworkRequest disconnects cellular with MMS 1952 cv = mCellNetworkAgent.getDisconnectedCV(); 1953 mCm.unregisterNetworkCallback(networkCallback); 1954 waitFor(cv); 1955 verifyActiveNetwork(TRANSPORT_WIFI); 1956 } 1957 1958 @SmallTest testMMSonCell()1959 public void testMMSonCell() throws Exception { 1960 // Test bringing up cellular without MMS 1961 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); 1962 ConditionVariable cv = waitForConnectivityBroadcasts(1); 1963 mCellNetworkAgent.connect(false); 1964 waitFor(cv); 1965 verifyActiveNetwork(TRANSPORT_CELLULAR); 1966 1967 // Register MMS NetworkRequest 1968 NetworkRequest.Builder builder = new NetworkRequest.Builder(); 1969 builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS); 1970 final TestNetworkCallback networkCallback = new TestNetworkCallback(); 1971 mCm.requestNetwork(builder.build(), networkCallback); 1972 1973 // Test bringing up MMS cellular network 1974 MockNetworkAgent mmsNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); 1975 mmsNetworkAgent.addCapability(NET_CAPABILITY_MMS); 1976 mmsNetworkAgent.connectWithoutInternet(); 1977 networkCallback.expectAvailableCallbacks(mmsNetworkAgent); 1978 verifyActiveNetwork(TRANSPORT_CELLULAR); 1979 1980 // Test releasing MMS NetworkRequest does not disconnect main cellular NetworkAgent 1981 cv = mmsNetworkAgent.getDisconnectedCV(); 1982 mCm.unregisterNetworkCallback(networkCallback); 1983 waitFor(cv); 1984 verifyActiveNetwork(TRANSPORT_CELLULAR); 1985 } 1986 1987 @SmallTest testCaptivePortal()1988 public void testCaptivePortal() { 1989 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback(); 1990 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder() 1991 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build(); 1992 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback); 1993 1994 final TestNetworkCallback validatedCallback = new TestNetworkCallback(); 1995 final NetworkRequest validatedRequest = new NetworkRequest.Builder() 1996 .addCapability(NET_CAPABILITY_VALIDATED).build(); 1997 mCm.registerNetworkCallback(validatedRequest, validatedCallback); 1998 1999 // Bring up a network with a captive portal. 2000 // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL. 2001 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 2002 String firstRedirectUrl = "http://example.com/firstPath"; 2003 mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl); 2004 captivePortalCallback.expectAvailableCallbacks(mWiFiNetworkAgent); 2005 assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), firstRedirectUrl); 2006 2007 // Take down network. 2008 // Expect onLost callback. 2009 mWiFiNetworkAgent.disconnect(); 2010 captivePortalCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); 2011 2012 // Bring up a network with a captive portal. 2013 // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL. 2014 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 2015 String secondRedirectUrl = "http://example.com/secondPath"; 2016 mWiFiNetworkAgent.connectWithCaptivePortal(secondRedirectUrl); 2017 captivePortalCallback.expectAvailableCallbacks(mWiFiNetworkAgent); 2018 assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), secondRedirectUrl); 2019 2020 // Make captive portal disappear then revalidate. 2021 // Expect onLost callback because network no longer provides NET_CAPABILITY_CAPTIVE_PORTAL. 2022 mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 204; 2023 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true); 2024 captivePortalCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); 2025 2026 // Expect NET_CAPABILITY_VALIDATED onAvailable callback. 2027 validatedCallback.expectAvailableCallbacks(mWiFiNetworkAgent); 2028 // TODO: Investigate only sending available callbacks. 2029 validatedCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent); 2030 2031 // Break network connectivity. 2032 // Expect NET_CAPABILITY_VALIDATED onLost callback. 2033 mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 500; 2034 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), false); 2035 validatedCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); 2036 } 2037 2038 @SmallTest testCaptivePortalApp()2039 public void testCaptivePortalApp() { 2040 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback(); 2041 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder() 2042 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build(); 2043 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback); 2044 2045 final TestNetworkCallback validatedCallback = new TestNetworkCallback(); 2046 final NetworkRequest validatedRequest = new NetworkRequest.Builder() 2047 .addCapability(NET_CAPABILITY_VALIDATED).build(); 2048 mCm.registerNetworkCallback(validatedRequest, validatedCallback); 2049 2050 // Bring up wifi. 2051 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 2052 mWiFiNetworkAgent.connect(true); 2053 validatedCallback.expectAvailableAndValidatedCallbacks(mWiFiNetworkAgent); 2054 Network wifiNetwork = mWiFiNetworkAgent.getNetwork(); 2055 2056 // Check that calling startCaptivePortalApp does nothing. 2057 final int fastTimeoutMs = 100; 2058 mCm.startCaptivePortalApp(wifiNetwork); 2059 mServiceContext.expectNoStartActivityIntent(fastTimeoutMs); 2060 2061 // Turn into a captive portal. 2062 mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 302; 2063 mCm.reportNetworkConnectivity(wifiNetwork, false); 2064 captivePortalCallback.expectAvailableCallbacks(mWiFiNetworkAgent); 2065 validatedCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); 2066 2067 // Check that startCaptivePortalApp sends the expected intent. 2068 mCm.startCaptivePortalApp(wifiNetwork); 2069 Intent intent = mServiceContext.expectStartActivityIntent(TIMEOUT_MS); 2070 assertEquals(ConnectivityManager.ACTION_CAPTIVE_PORTAL_SIGN_IN, intent.getAction()); 2071 assertEquals(wifiNetwork, intent.getExtra(ConnectivityManager.EXTRA_NETWORK)); 2072 2073 // Have the app report that the captive portal is dismissed, and check that we revalidate. 2074 mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 204; 2075 CaptivePortal c = (CaptivePortal) intent.getExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL); 2076 c.reportCaptivePortalDismissed(); 2077 validatedCallback.expectAvailableCallbacks(mWiFiNetworkAgent); 2078 captivePortalCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); 2079 2080 mCm.unregisterNetworkCallback(validatedCallback); 2081 mCm.unregisterNetworkCallback(captivePortalCallback); 2082 } 2083 2084 @SmallTest testAvoidOrIgnoreCaptivePortals()2085 public void testAvoidOrIgnoreCaptivePortals() { 2086 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback(); 2087 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder() 2088 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build(); 2089 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback); 2090 2091 final TestNetworkCallback validatedCallback = new TestNetworkCallback(); 2092 final NetworkRequest validatedRequest = new NetworkRequest.Builder() 2093 .addCapability(NET_CAPABILITY_VALIDATED).build(); 2094 mCm.registerNetworkCallback(validatedRequest, validatedCallback); 2095 2096 setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_AVOID); 2097 // Bring up a network with a captive portal. 2098 // Expect it to fail to connect and not result in any callbacks. 2099 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 2100 String firstRedirectUrl = "http://example.com/firstPath"; 2101 2102 ConditionVariable disconnectCv = mWiFiNetworkAgent.getDisconnectedCV(); 2103 ConditionVariable avoidCv = mWiFiNetworkAgent.getPreventReconnectReceived(); 2104 mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl); 2105 waitFor(disconnectCv); 2106 waitFor(avoidCv); 2107 2108 assertNoCallbacks(captivePortalCallback, validatedCallback); 2109 2110 // Now test ignore mode. 2111 setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_IGNORE); 2112 2113 // Bring up a network with a captive portal. 2114 // Since we're ignoring captive portals, the network will validate. 2115 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 2116 String secondRedirectUrl = "http://example.com/secondPath"; 2117 mWiFiNetworkAgent.connectWithCaptivePortal(secondRedirectUrl); 2118 2119 // Expect NET_CAPABILITY_VALIDATED onAvailable callback. 2120 validatedCallback.expectAvailableCallbacks(mWiFiNetworkAgent); 2121 // But there should be no CaptivePortal callback. 2122 captivePortalCallback.assertNoCallback(); 2123 } 2124 newWifiRequestBuilder()2125 private NetworkRequest.Builder newWifiRequestBuilder() { 2126 return new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI); 2127 } 2128 2129 @SmallTest testNetworkSpecifier()2130 public void testNetworkSpecifier() { 2131 NetworkRequest rEmpty1 = newWifiRequestBuilder().build(); 2132 NetworkRequest rEmpty2 = newWifiRequestBuilder().setNetworkSpecifier((String) null).build(); 2133 NetworkRequest rEmpty3 = newWifiRequestBuilder().setNetworkSpecifier("").build(); 2134 NetworkRequest rEmpty4 = newWifiRequestBuilder().setNetworkSpecifier( 2135 (NetworkSpecifier) null).build(); 2136 NetworkRequest rFoo = newWifiRequestBuilder().setNetworkSpecifier("foo").build(); 2137 NetworkRequest rBar = newWifiRequestBuilder().setNetworkSpecifier( 2138 new StringNetworkSpecifier("bar")).build(); 2139 2140 TestNetworkCallback cEmpty1 = new TestNetworkCallback(); 2141 TestNetworkCallback cEmpty2 = new TestNetworkCallback(); 2142 TestNetworkCallback cEmpty3 = new TestNetworkCallback(); 2143 TestNetworkCallback cEmpty4 = new TestNetworkCallback(); 2144 TestNetworkCallback cFoo = new TestNetworkCallback(); 2145 TestNetworkCallback cBar = new TestNetworkCallback(); 2146 TestNetworkCallback[] emptyCallbacks = new TestNetworkCallback[] { 2147 cEmpty1, cEmpty2, cEmpty3 }; 2148 2149 mCm.registerNetworkCallback(rEmpty1, cEmpty1); 2150 mCm.registerNetworkCallback(rEmpty2, cEmpty2); 2151 mCm.registerNetworkCallback(rEmpty3, cEmpty3); 2152 mCm.registerNetworkCallback(rEmpty4, cEmpty4); 2153 mCm.registerNetworkCallback(rFoo, cFoo); 2154 mCm.registerNetworkCallback(rBar, cBar); 2155 2156 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 2157 mWiFiNetworkAgent.connect(false); 2158 cEmpty1.expectAvailableCallbacks(mWiFiNetworkAgent); 2159 cEmpty2.expectAvailableCallbacks(mWiFiNetworkAgent); 2160 cEmpty3.expectAvailableCallbacks(mWiFiNetworkAgent); 2161 cEmpty4.expectAvailableCallbacks(mWiFiNetworkAgent); 2162 assertNoCallbacks(cFoo, cBar); 2163 2164 mWiFiNetworkAgent.setNetworkSpecifier(new StringNetworkSpecifier("foo")); 2165 cFoo.expectAvailableCallbacks(mWiFiNetworkAgent); 2166 for (TestNetworkCallback c: emptyCallbacks) { 2167 c.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent); 2168 } 2169 cFoo.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent); 2170 cFoo.assertNoCallback(); 2171 2172 mWiFiNetworkAgent.setNetworkSpecifier(new StringNetworkSpecifier("bar")); 2173 cFoo.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); 2174 cBar.expectAvailableCallbacks(mWiFiNetworkAgent); 2175 for (TestNetworkCallback c: emptyCallbacks) { 2176 c.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent); 2177 } 2178 cBar.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent); 2179 cBar.assertNoCallback(); 2180 2181 mWiFiNetworkAgent.setNetworkSpecifier(null); 2182 cBar.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); 2183 for (TestNetworkCallback c: emptyCallbacks) { 2184 c.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent); 2185 } 2186 2187 assertNoCallbacks(cEmpty1, cEmpty2, cEmpty3, cFoo, cBar); 2188 } 2189 2190 @SmallTest testInvalidNetworkSpecifier()2191 public void testInvalidNetworkSpecifier() { 2192 try { 2193 NetworkRequest.Builder builder = new NetworkRequest.Builder(); 2194 builder.setNetworkSpecifier(new MatchAllNetworkSpecifier()); 2195 fail("NetworkRequest builder with MatchAllNetworkSpecifier"); 2196 } catch (IllegalArgumentException expected) { 2197 // expected 2198 } 2199 2200 try { 2201 NetworkCapabilities networkCapabilities = new NetworkCapabilities(); 2202 networkCapabilities.addTransportType(TRANSPORT_WIFI) 2203 .setNetworkSpecifier(new MatchAllNetworkSpecifier()); 2204 mService.requestNetwork(networkCapabilities, null, 0, null, 2205 ConnectivityManager.TYPE_WIFI); 2206 fail("ConnectivityService requestNetwork with MatchAllNetworkSpecifier"); 2207 } catch (IllegalArgumentException expected) { 2208 // expected 2209 } 2210 2211 class NonParcelableSpecifier extends NetworkSpecifier { 2212 public boolean satisfiedBy(NetworkSpecifier other) { return false; } 2213 }; 2214 class ParcelableSpecifier extends NonParcelableSpecifier implements Parcelable { 2215 @Override public int describeContents() { return 0; } 2216 @Override public void writeToParcel(Parcel p, int flags) {} 2217 } 2218 NetworkRequest.Builder builder; 2219 2220 builder = new NetworkRequest.Builder().addTransportType(TRANSPORT_ETHERNET); 2221 try { 2222 builder.setNetworkSpecifier(new NonParcelableSpecifier()); 2223 Parcel parcelW = Parcel.obtain(); 2224 builder.build().writeToParcel(parcelW, 0); 2225 fail("Parceling a non-parcelable specifier did not throw an exception"); 2226 } catch (Exception e) { 2227 // expected 2228 } 2229 2230 builder = new NetworkRequest.Builder().addTransportType(TRANSPORT_ETHERNET); 2231 builder.setNetworkSpecifier(new ParcelableSpecifier()); 2232 NetworkRequest nr = builder.build(); 2233 assertNotNull(nr); 2234 2235 try { 2236 Parcel parcelW = Parcel.obtain(); 2237 nr.writeToParcel(parcelW, 0); 2238 byte[] bytes = parcelW.marshall(); 2239 parcelW.recycle(); 2240 2241 Parcel parcelR = Parcel.obtain(); 2242 parcelR.unmarshall(bytes, 0, bytes.length); 2243 parcelR.setDataPosition(0); 2244 NetworkRequest rereadNr = NetworkRequest.CREATOR.createFromParcel(parcelR); 2245 fail("Unparceling a non-framework NetworkSpecifier did not throw an exception"); 2246 } catch (Exception e) { 2247 // expected 2248 } 2249 } 2250 2251 @SmallTest testNetworkSpecifierUidSpoofSecurityException()2252 public void testNetworkSpecifierUidSpoofSecurityException() { 2253 class UidAwareNetworkSpecifier extends NetworkSpecifier implements Parcelable { 2254 @Override 2255 public boolean satisfiedBy(NetworkSpecifier other) { 2256 return true; 2257 } 2258 2259 @Override 2260 public void assertValidFromUid(int requestorUid) { 2261 throw new SecurityException("failure"); 2262 } 2263 2264 @Override 2265 public int describeContents() { return 0; } 2266 @Override 2267 public void writeToParcel(Parcel dest, int flags) {} 2268 } 2269 2270 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 2271 mWiFiNetworkAgent.connect(false); 2272 2273 UidAwareNetworkSpecifier networkSpecifier = new UidAwareNetworkSpecifier(); 2274 NetworkRequest networkRequest = newWifiRequestBuilder().setNetworkSpecifier( 2275 networkSpecifier).build(); 2276 TestNetworkCallback networkCallback = new TestNetworkCallback(); 2277 try { 2278 mCm.requestNetwork(networkRequest, networkCallback); 2279 fail("Network request with spoofed UID did not throw a SecurityException"); 2280 } catch (SecurityException e) { 2281 // expected 2282 } 2283 } 2284 2285 @SmallTest testRegisterDefaultNetworkCallback()2286 public void testRegisterDefaultNetworkCallback() throws Exception { 2287 final TestNetworkCallback defaultNetworkCallback = new TestNetworkCallback(); 2288 mCm.registerDefaultNetworkCallback(defaultNetworkCallback); 2289 defaultNetworkCallback.assertNoCallback(); 2290 2291 // Create a TRANSPORT_CELLULAR request to keep the mobile interface up 2292 // whenever Wi-Fi is up. Without this, the mobile network agent is 2293 // reaped before any other activity can take place. 2294 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback(); 2295 final NetworkRequest cellRequest = new NetworkRequest.Builder() 2296 .addTransportType(TRANSPORT_CELLULAR).build(); 2297 mCm.requestNetwork(cellRequest, cellNetworkCallback); 2298 cellNetworkCallback.assertNoCallback(); 2299 2300 // Bring up cell and expect CALLBACK_AVAILABLE. 2301 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); 2302 mCellNetworkAgent.connect(true); 2303 cellNetworkCallback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent); 2304 defaultNetworkCallback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent); 2305 2306 // Bring up wifi and expect CALLBACK_AVAILABLE. 2307 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 2308 mWiFiNetworkAgent.connect(true); 2309 cellNetworkCallback.assertNoCallback(); 2310 defaultNetworkCallback.expectAvailableAndValidatedCallbacks(mWiFiNetworkAgent); 2311 2312 // Bring down cell. Expect no default network callback, since it wasn't the default. 2313 mCellNetworkAgent.disconnect(); 2314 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent); 2315 defaultNetworkCallback.assertNoCallback(); 2316 2317 // Bring up cell. Expect no default network callback, since it won't be the default. 2318 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); 2319 mCellNetworkAgent.connect(true); 2320 cellNetworkCallback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent); 2321 defaultNetworkCallback.assertNoCallback(); 2322 2323 // Bring down wifi. Expect the default network callback to notified of LOST wifi 2324 // followed by AVAILABLE cell. 2325 mWiFiNetworkAgent.disconnect(); 2326 cellNetworkCallback.assertNoCallback(); 2327 defaultNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); 2328 defaultNetworkCallback.expectAvailableCallbacks(mCellNetworkAgent); 2329 mCellNetworkAgent.disconnect(); 2330 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent); 2331 defaultNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent); 2332 } 2333 2334 @SmallTest testAdditionalStateCallbacks()2335 public void testAdditionalStateCallbacks() throws Exception { 2336 // File a network request for mobile. 2337 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback(); 2338 final NetworkRequest cellRequest = new NetworkRequest.Builder() 2339 .addTransportType(TRANSPORT_CELLULAR).build(); 2340 mCm.requestNetwork(cellRequest, cellNetworkCallback); 2341 2342 // Bring up the mobile network. 2343 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); 2344 mCellNetworkAgent.connect(true); 2345 2346 // We should get onAvailable(), onCapabilitiesChanged(), and 2347 // onLinkPropertiesChanged() in rapid succession. Additionally, we 2348 // should get onCapabilitiesChanged() when the mobile network validates. 2349 cellNetworkCallback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent); 2350 cellNetworkCallback.assertNoCallback(); 2351 2352 // Update LinkProperties. 2353 final LinkProperties lp = new LinkProperties(); 2354 lp.setInterfaceName("foonet_data0"); 2355 mCellNetworkAgent.sendLinkProperties(lp); 2356 // We should get onLinkPropertiesChanged(). 2357 cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent); 2358 cellNetworkCallback.assertNoCallback(); 2359 2360 // Suspend the network. 2361 mCellNetworkAgent.suspend(); 2362 cellNetworkCallback.expectCallback(CallbackState.SUSPENDED, mCellNetworkAgent); 2363 cellNetworkCallback.assertNoCallback(); 2364 2365 // Register a garden variety default network request. 2366 final TestNetworkCallback dfltNetworkCallback = new TestNetworkCallback(); 2367 mCm.registerDefaultNetworkCallback(dfltNetworkCallback); 2368 // We should get onAvailable(), onCapabilitiesChanged(), onLinkPropertiesChanged(), 2369 // as well as onNetworkSuspended() in rapid succession. 2370 dfltNetworkCallback.expectAvailableAndSuspendedCallbacks(mCellNetworkAgent); 2371 dfltNetworkCallback.assertNoCallback(); 2372 2373 mCm.unregisterNetworkCallback(dfltNetworkCallback); 2374 mCm.unregisterNetworkCallback(cellNetworkCallback); 2375 } 2376 setCaptivePortalMode(int mode)2377 private void setCaptivePortalMode(int mode) { 2378 ContentResolver cr = mServiceContext.getContentResolver(); 2379 Settings.Global.putInt(cr, Settings.Global.CAPTIVE_PORTAL_MODE, mode); 2380 } 2381 setMobileDataAlwaysOn(boolean enable)2382 private void setMobileDataAlwaysOn(boolean enable) { 2383 ContentResolver cr = mServiceContext.getContentResolver(); 2384 Settings.Global.putInt(cr, Settings.Global.MOBILE_DATA_ALWAYS_ON, enable ? 1 : 0); 2385 mService.updateMobileDataAlwaysOn(); 2386 waitForIdle(); 2387 } 2388 isForegroundNetwork(MockNetworkAgent network)2389 private boolean isForegroundNetwork(MockNetworkAgent network) { 2390 NetworkCapabilities nc = mCm.getNetworkCapabilities(network.getNetwork()); 2391 assertNotNull(nc); 2392 return nc.hasCapability(NET_CAPABILITY_FOREGROUND); 2393 } 2394 2395 @SmallTest testBackgroundNetworks()2396 public void testBackgroundNetworks() throws Exception { 2397 // Create a background request. We can't do this ourselves because ConnectivityService 2398 // doesn't have an API for it. So just turn on mobile data always on. 2399 setMobileDataAlwaysOn(true); 2400 final NetworkRequest request = new NetworkRequest.Builder().build(); 2401 final NetworkRequest fgRequest = new NetworkRequest.Builder() 2402 .addCapability(NET_CAPABILITY_FOREGROUND).build(); 2403 final TestNetworkCallback callback = new TestNetworkCallback(); 2404 final TestNetworkCallback fgCallback = new TestNetworkCallback(); 2405 mCm.registerNetworkCallback(request, callback); 2406 mCm.registerNetworkCallback(fgRequest, fgCallback); 2407 2408 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); 2409 mCellNetworkAgent.connect(true); 2410 callback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent); 2411 fgCallback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent); 2412 assertTrue(isForegroundNetwork(mCellNetworkAgent)); 2413 2414 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 2415 mWiFiNetworkAgent.connect(true); 2416 2417 // When wifi connects, cell lingers. 2418 callback.expectAvailableCallbacks(mWiFiNetworkAgent); 2419 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent); 2420 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent); 2421 fgCallback.expectAvailableCallbacks(mWiFiNetworkAgent); 2422 fgCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent); 2423 fgCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent); 2424 assertTrue(isForegroundNetwork(mCellNetworkAgent)); 2425 assertTrue(isForegroundNetwork(mWiFiNetworkAgent)); 2426 2427 // When lingering is complete, cell is still there but is now in the background. 2428 waitForIdle(); 2429 int timeoutMs = TEST_LINGER_DELAY_MS + TEST_LINGER_DELAY_MS / 4; 2430 fgCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent, timeoutMs); 2431 // Expect a network capabilities update sans FOREGROUND. 2432 callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent); 2433 assertFalse(isForegroundNetwork(mCellNetworkAgent)); 2434 assertTrue(isForegroundNetwork(mWiFiNetworkAgent)); 2435 2436 // File a cell request and check that cell comes into the foreground. 2437 final NetworkRequest cellRequest = new NetworkRequest.Builder() 2438 .addTransportType(TRANSPORT_CELLULAR).build(); 2439 final TestNetworkCallback cellCallback = new TestNetworkCallback(); 2440 mCm.requestNetwork(cellRequest, cellCallback); 2441 // NOTE: This request causes the network's capabilities to change. This 2442 // is currently delivered before the onAvailable() callbacks. 2443 // TODO: Fix this. 2444 cellCallback.expectCapabilitiesWith(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent); 2445 cellCallback.expectAvailableCallbacks(mCellNetworkAgent); 2446 fgCallback.expectAvailableCallbacks(mCellNetworkAgent); 2447 // Expect a network capabilities update with FOREGROUND, because the most recent 2448 // request causes its state to change. 2449 callback.expectCapabilitiesWith(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent); 2450 assertTrue(isForegroundNetwork(mCellNetworkAgent)); 2451 assertTrue(isForegroundNetwork(mWiFiNetworkAgent)); 2452 2453 // Release the request. The network immediately goes into the background, since it was not 2454 // lingering. 2455 mCm.unregisterNetworkCallback(cellCallback); 2456 fgCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent); 2457 // Expect a network capabilities update sans FOREGROUND. 2458 callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent); 2459 assertFalse(isForegroundNetwork(mCellNetworkAgent)); 2460 assertTrue(isForegroundNetwork(mWiFiNetworkAgent)); 2461 2462 // Disconnect wifi and check that cell is foreground again. 2463 mWiFiNetworkAgent.disconnect(); 2464 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); 2465 fgCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); 2466 fgCallback.expectAvailableCallbacks(mCellNetworkAgent); 2467 assertTrue(isForegroundNetwork(mCellNetworkAgent)); 2468 2469 mCm.unregisterNetworkCallback(callback); 2470 mCm.unregisterNetworkCallback(fgCallback); 2471 } 2472 2473 @Ignore // This test has instrinsic chances of spurious failures: ignore for continuous testing. benchmarkRequestRegistrationAndCallbackDispatch()2474 public void benchmarkRequestRegistrationAndCallbackDispatch() throws Exception { 2475 // TODO: turn this unit test into a real benchmarking test. 2476 // Benchmarks connecting and switching performance in the presence of a large number of 2477 // NetworkRequests. 2478 // 1. File NUM_REQUESTS requests. 2479 // 2. Have a network connect. Wait for NUM_REQUESTS onAvailable callbacks to fire. 2480 // 3. Have a new network connect and outscore the previous. Wait for NUM_REQUESTS onLosing 2481 // and NUM_REQUESTS onAvailable callbacks to fire. 2482 // See how long it took. 2483 final int NUM_REQUESTS = 90; 2484 final int REGISTER_TIME_LIMIT_MS = 200; 2485 final int CONNECT_TIME_LIMIT_MS = 60; 2486 final int SWITCH_TIME_LIMIT_MS = 60; 2487 final int UNREGISTER_TIME_LIMIT_MS = 20; 2488 2489 final NetworkRequest request = new NetworkRequest.Builder().clearCapabilities().build(); 2490 final NetworkCallback[] callbacks = new NetworkCallback[NUM_REQUESTS]; 2491 final CountDownLatch availableLatch = new CountDownLatch(NUM_REQUESTS); 2492 final CountDownLatch losingLatch = new CountDownLatch(NUM_REQUESTS); 2493 2494 for (int i = 0; i < NUM_REQUESTS; i++) { 2495 callbacks[i] = new NetworkCallback() { 2496 @Override public void onAvailable(Network n) { availableLatch.countDown(); } 2497 @Override public void onLosing(Network n, int t) { losingLatch.countDown(); } 2498 }; 2499 } 2500 2501 assertTimeLimit("Registering callbacks", REGISTER_TIME_LIMIT_MS, () -> { 2502 for (NetworkCallback cb : callbacks) { 2503 mCm.registerNetworkCallback(request, cb); 2504 } 2505 }); 2506 2507 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); 2508 // Don't request that the network validate, because otherwise connect() will block until 2509 // the network gets NET_CAPABILITY_VALIDATED, after all the callbacks below have fired, 2510 // and we won't actually measure anything. 2511 mCellNetworkAgent.connect(false); 2512 2513 long onAvailableDispatchingDuration = durationOf(() -> { 2514 awaitLatch(availableLatch, 10 * CONNECT_TIME_LIMIT_MS); 2515 }); 2516 Log.d(TAG, String.format("Dispatched %d of %d onAvailable callbacks in %dms", 2517 NUM_REQUESTS - availableLatch.getCount(), NUM_REQUESTS, 2518 onAvailableDispatchingDuration)); 2519 assertTrue(String.format("Dispatching %d onAvailable callbacks in %dms, expected %dms", 2520 NUM_REQUESTS, onAvailableDispatchingDuration, CONNECT_TIME_LIMIT_MS), 2521 onAvailableDispatchingDuration <= CONNECT_TIME_LIMIT_MS); 2522 2523 // Give wifi a high enough score that we'll linger cell when wifi comes up. 2524 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 2525 mWiFiNetworkAgent.adjustScore(40); 2526 mWiFiNetworkAgent.connect(false); 2527 2528 long onLostDispatchingDuration = durationOf(() -> { 2529 awaitLatch(losingLatch, 10 * SWITCH_TIME_LIMIT_MS); 2530 }); 2531 Log.d(TAG, String.format("Dispatched %d of %d onLosing callbacks in %dms", 2532 NUM_REQUESTS - losingLatch.getCount(), NUM_REQUESTS, onLostDispatchingDuration)); 2533 assertTrue(String.format("Dispatching %d onLosing callbacks in %dms, expected %dms", 2534 NUM_REQUESTS, onLostDispatchingDuration, SWITCH_TIME_LIMIT_MS), 2535 onLostDispatchingDuration <= SWITCH_TIME_LIMIT_MS); 2536 2537 assertTimeLimit("Unregistering callbacks", UNREGISTER_TIME_LIMIT_MS, () -> { 2538 for (NetworkCallback cb : callbacks) { 2539 mCm.unregisterNetworkCallback(cb); 2540 } 2541 }); 2542 } 2543 durationOf(Runnable fn)2544 private long durationOf(Runnable fn) { 2545 long startTime = SystemClock.elapsedRealtime(); 2546 fn.run(); 2547 return SystemClock.elapsedRealtime() - startTime; 2548 } 2549 assertTimeLimit(String descr, long timeLimit, Runnable fn)2550 private void assertTimeLimit(String descr, long timeLimit, Runnable fn) { 2551 long timeTaken = durationOf(fn); 2552 String msg = String.format("%s: took %dms, limit was %dms", descr, timeTaken, timeLimit); 2553 Log.d(TAG, msg); 2554 assertTrue(msg, timeTaken <= timeLimit); 2555 } 2556 awaitLatch(CountDownLatch l, long timeoutMs)2557 private boolean awaitLatch(CountDownLatch l, long timeoutMs) { 2558 try { 2559 return l.await(timeoutMs, TimeUnit.MILLISECONDS); 2560 } catch (InterruptedException e) {} 2561 return false; 2562 } 2563 2564 @SmallTest testMobileDataAlwaysOn()2565 public void testMobileDataAlwaysOn() throws Exception { 2566 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback(); 2567 final NetworkRequest cellRequest = new NetworkRequest.Builder() 2568 .addTransportType(TRANSPORT_CELLULAR).build(); 2569 mCm.registerNetworkCallback(cellRequest, cellNetworkCallback); 2570 2571 final HandlerThread handlerThread = new HandlerThread("MobileDataAlwaysOnFactory"); 2572 handlerThread.start(); 2573 NetworkCapabilities filter = new NetworkCapabilities() 2574 .addTransportType(TRANSPORT_CELLULAR) 2575 .addCapability(NET_CAPABILITY_INTERNET); 2576 final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(), 2577 mServiceContext, "testFactory", filter); 2578 testFactory.setScoreFilter(40); 2579 2580 // Register the factory and expect it to start looking for a network. 2581 testFactory.expectAddRequests(1); 2582 testFactory.register(); 2583 testFactory.waitForNetworkRequests(1); 2584 assertTrue(testFactory.getMyStartRequested()); 2585 2586 // Bring up wifi. The factory stops looking for a network. 2587 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 2588 testFactory.expectAddRequests(2); // Because the default request changes score twice. 2589 mWiFiNetworkAgent.connect(true); 2590 testFactory.waitForNetworkRequests(1); 2591 assertFalse(testFactory.getMyStartRequested()); 2592 2593 ContentResolver cr = mServiceContext.getContentResolver(); 2594 2595 // Turn on mobile data always on. The factory starts looking again. 2596 testFactory.expectAddRequests(1); 2597 setMobileDataAlwaysOn(true); 2598 testFactory.waitForNetworkRequests(2); 2599 assertTrue(testFactory.getMyStartRequested()); 2600 2601 // Bring up cell data and check that the factory stops looking. 2602 assertLength(1, mCm.getAllNetworks()); 2603 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); 2604 testFactory.expectAddRequests(2); // Because the cell request changes score twice. 2605 mCellNetworkAgent.connect(true); 2606 cellNetworkCallback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent); 2607 testFactory.waitForNetworkRequests(2); 2608 assertFalse(testFactory.getMyStartRequested()); // Because the cell network outscores us. 2609 2610 // Check that cell data stays up. 2611 waitForIdle(); 2612 verifyActiveNetwork(TRANSPORT_WIFI); 2613 assertLength(2, mCm.getAllNetworks()); 2614 2615 // Turn off mobile data always on and expect the request to disappear... 2616 testFactory.expectRemoveRequests(1); 2617 setMobileDataAlwaysOn(false); 2618 testFactory.waitForNetworkRequests(1); 2619 2620 // ... and cell data to be torn down. 2621 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent); 2622 assertLength(1, mCm.getAllNetworks()); 2623 2624 testFactory.unregister(); 2625 mCm.unregisterNetworkCallback(cellNetworkCallback); 2626 handlerThread.quit(); 2627 } 2628 2629 @SmallTest testAvoidBadWifiSetting()2630 public void testAvoidBadWifiSetting() throws Exception { 2631 final ContentResolver cr = mServiceContext.getContentResolver(); 2632 final WrappedMultinetworkPolicyTracker tracker = mService.getMultinetworkPolicyTracker(); 2633 final String settingName = Settings.Global.NETWORK_AVOID_BAD_WIFI; 2634 2635 tracker.configRestrictsAvoidBadWifi = false; 2636 String[] values = new String[] {null, "0", "1"}; 2637 for (int i = 0; i < values.length; i++) { 2638 Settings.Global.putInt(cr, settingName, 1); 2639 tracker.reevaluate(); 2640 waitForIdle(); 2641 String msg = String.format("config=false, setting=%s", values[i]); 2642 assertTrue(mService.avoidBadWifi()); 2643 assertFalse(msg, tracker.shouldNotifyWifiUnvalidated()); 2644 } 2645 2646 tracker.configRestrictsAvoidBadWifi = true; 2647 2648 Settings.Global.putInt(cr, settingName, 0); 2649 tracker.reevaluate(); 2650 waitForIdle(); 2651 assertFalse(mService.avoidBadWifi()); 2652 assertFalse(tracker.shouldNotifyWifiUnvalidated()); 2653 2654 Settings.Global.putInt(cr, settingName, 1); 2655 tracker.reevaluate(); 2656 waitForIdle(); 2657 assertTrue(mService.avoidBadWifi()); 2658 assertFalse(tracker.shouldNotifyWifiUnvalidated()); 2659 2660 Settings.Global.putString(cr, settingName, null); 2661 tracker.reevaluate(); 2662 waitForIdle(); 2663 assertFalse(mService.avoidBadWifi()); 2664 assertTrue(tracker.shouldNotifyWifiUnvalidated()); 2665 } 2666 2667 @SmallTest testAvoidBadWifi()2668 public void testAvoidBadWifi() throws Exception { 2669 final ContentResolver cr = mServiceContext.getContentResolver(); 2670 final WrappedMultinetworkPolicyTracker tracker = mService.getMultinetworkPolicyTracker(); 2671 2672 // Pretend we're on a carrier that restricts switching away from bad wifi. 2673 tracker.configRestrictsAvoidBadWifi = true; 2674 2675 // File a request for cell to ensure it doesn't go down. 2676 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback(); 2677 final NetworkRequest cellRequest = new NetworkRequest.Builder() 2678 .addTransportType(TRANSPORT_CELLULAR).build(); 2679 mCm.requestNetwork(cellRequest, cellNetworkCallback); 2680 2681 TestNetworkCallback defaultCallback = new TestNetworkCallback(); 2682 mCm.registerDefaultNetworkCallback(defaultCallback); 2683 2684 NetworkRequest validatedWifiRequest = new NetworkRequest.Builder() 2685 .addTransportType(TRANSPORT_WIFI) 2686 .addCapability(NET_CAPABILITY_VALIDATED) 2687 .build(); 2688 TestNetworkCallback validatedWifiCallback = new TestNetworkCallback(); 2689 mCm.registerNetworkCallback(validatedWifiRequest, validatedWifiCallback); 2690 2691 Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 0); 2692 tracker.reevaluate(); 2693 2694 // Bring up validated cell. 2695 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); 2696 mCellNetworkAgent.connect(true); 2697 cellNetworkCallback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent); 2698 defaultCallback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent); 2699 Network cellNetwork = mCellNetworkAgent.getNetwork(); 2700 2701 // Bring up validated wifi. 2702 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 2703 mWiFiNetworkAgent.connect(true); 2704 defaultCallback.expectAvailableAndValidatedCallbacks(mWiFiNetworkAgent); 2705 validatedWifiCallback.expectAvailableCallbacks(mWiFiNetworkAgent); 2706 validatedWifiCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent); 2707 Network wifiNetwork = mWiFiNetworkAgent.getNetwork(); 2708 2709 // Fail validation on wifi. 2710 mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 599; 2711 mCm.reportNetworkConnectivity(wifiNetwork, false); 2712 defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent); 2713 validatedWifiCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); 2714 2715 // Because avoid bad wifi is off, we don't switch to cellular. 2716 defaultCallback.assertNoCallback(); 2717 assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability( 2718 NET_CAPABILITY_VALIDATED)); 2719 assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability( 2720 NET_CAPABILITY_VALIDATED)); 2721 assertEquals(mCm.getActiveNetwork(), wifiNetwork); 2722 2723 // Simulate switching to a carrier that does not restrict avoiding bad wifi, and expect 2724 // that we switch back to cell. 2725 tracker.configRestrictsAvoidBadWifi = false; 2726 tracker.reevaluate(); 2727 defaultCallback.expectAvailableCallbacks(mCellNetworkAgent); 2728 assertEquals(mCm.getActiveNetwork(), cellNetwork); 2729 2730 // Switch back to a restrictive carrier. 2731 tracker.configRestrictsAvoidBadWifi = true; 2732 tracker.reevaluate(); 2733 defaultCallback.expectAvailableCallbacks(mWiFiNetworkAgent); 2734 assertEquals(mCm.getActiveNetwork(), wifiNetwork); 2735 2736 // Simulate the user selecting "switch" on the dialog, and check that we switch to cell. 2737 mCm.setAvoidUnvalidated(wifiNetwork); 2738 defaultCallback.expectAvailableCallbacks(mCellNetworkAgent); 2739 assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability( 2740 NET_CAPABILITY_VALIDATED)); 2741 assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability( 2742 NET_CAPABILITY_VALIDATED)); 2743 assertEquals(mCm.getActiveNetwork(), cellNetwork); 2744 2745 // Disconnect and reconnect wifi to clear the one-time switch above. 2746 mWiFiNetworkAgent.disconnect(); 2747 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 2748 mWiFiNetworkAgent.connect(true); 2749 defaultCallback.expectAvailableAndValidatedCallbacks(mWiFiNetworkAgent); 2750 validatedWifiCallback.expectAvailableCallbacks(mWiFiNetworkAgent); 2751 validatedWifiCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent); 2752 wifiNetwork = mWiFiNetworkAgent.getNetwork(); 2753 2754 // Fail validation on wifi and expect the dialog to appear. 2755 mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 599; 2756 mCm.reportNetworkConnectivity(wifiNetwork, false); 2757 defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent); 2758 validatedWifiCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); 2759 2760 // Simulate the user selecting "switch" and checking the don't ask again checkbox. 2761 Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 1); 2762 tracker.reevaluate(); 2763 2764 // We now switch to cell. 2765 defaultCallback.expectAvailableCallbacks(mCellNetworkAgent); 2766 assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability( 2767 NET_CAPABILITY_VALIDATED)); 2768 assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability( 2769 NET_CAPABILITY_VALIDATED)); 2770 assertEquals(mCm.getActiveNetwork(), cellNetwork); 2771 2772 // Simulate the user turning the cellular fallback setting off and then on. 2773 // We switch to wifi and then to cell. 2774 Settings.Global.putString(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, null); 2775 tracker.reevaluate(); 2776 defaultCallback.expectAvailableCallbacks(mWiFiNetworkAgent); 2777 assertEquals(mCm.getActiveNetwork(), wifiNetwork); 2778 Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 1); 2779 tracker.reevaluate(); 2780 defaultCallback.expectAvailableCallbacks(mCellNetworkAgent); 2781 assertEquals(mCm.getActiveNetwork(), cellNetwork); 2782 2783 // If cell goes down, we switch to wifi. 2784 mCellNetworkAgent.disconnect(); 2785 defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent); 2786 defaultCallback.expectAvailableCallbacks(mWiFiNetworkAgent); 2787 validatedWifiCallback.assertNoCallback(); 2788 2789 mCm.unregisterNetworkCallback(cellNetworkCallback); 2790 mCm.unregisterNetworkCallback(validatedWifiCallback); 2791 mCm.unregisterNetworkCallback(defaultCallback); 2792 } 2793 2794 @SmallTest testMeteredMultipathPreferenceSetting()2795 public void testMeteredMultipathPreferenceSetting() throws Exception { 2796 final ContentResolver cr = mServiceContext.getContentResolver(); 2797 final WrappedMultinetworkPolicyTracker tracker = mService.getMultinetworkPolicyTracker(); 2798 final String settingName = Settings.Global.NETWORK_METERED_MULTIPATH_PREFERENCE; 2799 2800 for (int config : Arrays.asList(0, 3, 2)) { 2801 for (String setting: Arrays.asList(null, "0", "2", "1")) { 2802 tracker.configMeteredMultipathPreference = config; 2803 Settings.Global.putString(cr, settingName, setting); 2804 tracker.reevaluate(); 2805 waitForIdle(); 2806 2807 final int expected = (setting != null) ? Integer.parseInt(setting) : config; 2808 String msg = String.format("config=%d, setting=%s", config, setting); 2809 assertEquals(msg, expected, mCm.getMultipathPreference(null)); 2810 } 2811 } 2812 } 2813 2814 /** 2815 * Validate that a satisfied network request does not trigger onUnavailable() once the 2816 * time-out period expires. 2817 */ 2818 @SmallTest testSatisfiedNetworkRequestDoesNotTriggerOnUnavailable()2819 public void testSatisfiedNetworkRequestDoesNotTriggerOnUnavailable() { 2820 NetworkRequest nr = new NetworkRequest.Builder().addTransportType( 2821 NetworkCapabilities.TRANSPORT_WIFI).build(); 2822 final TestNetworkCallback networkCallback = new TestNetworkCallback(); 2823 final int timeoutMs = 150; 2824 mCm.requestNetwork(nr, networkCallback, timeoutMs); 2825 2826 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 2827 mWiFiNetworkAgent.connect(false); 2828 networkCallback.expectAvailableCallbacks(mWiFiNetworkAgent, false, timeoutMs); 2829 2830 // pass timeout and validate that UNAVAILABLE is not called 2831 networkCallback.assertNoCallback(); 2832 } 2833 2834 /** 2835 * Validate that a satisfied network request followed by a disconnected (lost) network does 2836 * not trigger onUnavailable() once the time-out period expires. 2837 */ 2838 @SmallTest testSatisfiedThenLostNetworkRequestDoesNotTriggerOnUnavailable()2839 public void testSatisfiedThenLostNetworkRequestDoesNotTriggerOnUnavailable() { 2840 NetworkRequest nr = new NetworkRequest.Builder().addTransportType( 2841 NetworkCapabilities.TRANSPORT_WIFI).build(); 2842 final TestNetworkCallback networkCallback = new TestNetworkCallback(); 2843 final int requestTimeoutMs = 50; 2844 mCm.requestNetwork(nr, networkCallback, requestTimeoutMs); 2845 2846 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 2847 mWiFiNetworkAgent.connect(false); 2848 final int assertTimeoutMs = 100; 2849 networkCallback.expectAvailableCallbacks(mWiFiNetworkAgent, false, assertTimeoutMs); 2850 mWiFiNetworkAgent.disconnect(); 2851 networkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); 2852 2853 // Validate that UNAVAILABLE is not called 2854 networkCallback.assertNoCallback(); 2855 } 2856 2857 /** 2858 * Validate that when a time-out is specified for a network request the onUnavailable() 2859 * callback is called when time-out expires. Then validate that if network request is 2860 * (somehow) satisfied - the callback isn't called later. 2861 */ 2862 @SmallTest testTimedoutNetworkRequest()2863 public void testTimedoutNetworkRequest() { 2864 NetworkRequest nr = new NetworkRequest.Builder().addTransportType( 2865 NetworkCapabilities.TRANSPORT_WIFI).build(); 2866 final TestNetworkCallback networkCallback = new TestNetworkCallback(); 2867 final int timeoutMs = 10; 2868 mCm.requestNetwork(nr, networkCallback, timeoutMs); 2869 2870 // pass timeout and validate that UNAVAILABLE is called 2871 networkCallback.expectCallback(CallbackState.UNAVAILABLE, null); 2872 2873 // create a network satisfying request - validate that request not triggered 2874 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 2875 mWiFiNetworkAgent.connect(false); 2876 networkCallback.assertNoCallback(); 2877 } 2878 2879 /** 2880 * Validate that when a network request is unregistered (cancelled), no posterior event can 2881 * trigger the callback. 2882 */ 2883 @SmallTest testNoCallbackAfterUnregisteredNetworkRequest()2884 public void testNoCallbackAfterUnregisteredNetworkRequest() { 2885 NetworkRequest nr = new NetworkRequest.Builder().addTransportType( 2886 NetworkCapabilities.TRANSPORT_WIFI).build(); 2887 final TestNetworkCallback networkCallback = new TestNetworkCallback(); 2888 final int timeoutMs = 10; 2889 2890 mCm.requestNetwork(nr, networkCallback, timeoutMs); 2891 mCm.unregisterNetworkCallback(networkCallback); 2892 // Regardless of the timeout, unregistering the callback in ConnectivityManager ensures 2893 // that this callback will not be called. 2894 networkCallback.assertNoCallback(); 2895 2896 // create a network satisfying request - validate that request not triggered 2897 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 2898 mWiFiNetworkAgent.connect(false); 2899 networkCallback.assertNoCallback(); 2900 } 2901 2902 private static class TestKeepaliveCallback extends PacketKeepaliveCallback { 2903 2904 public static enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR }; 2905 2906 private class CallbackValue { 2907 public CallbackType callbackType; 2908 public int error; 2909 CallbackValue(CallbackType type)2910 public CallbackValue(CallbackType type) { 2911 this.callbackType = type; 2912 this.error = PacketKeepalive.SUCCESS; 2913 assertTrue("onError callback must have error", type != CallbackType.ON_ERROR); 2914 } 2915 CallbackValue(CallbackType type, int error)2916 public CallbackValue(CallbackType type, int error) { 2917 this.callbackType = type; 2918 this.error = error; 2919 assertEquals("error can only be set for onError", type, CallbackType.ON_ERROR); 2920 } 2921 2922 @Override equals(Object o)2923 public boolean equals(Object o) { 2924 return o instanceof CallbackValue && 2925 this.callbackType == ((CallbackValue) o).callbackType && 2926 this.error == ((CallbackValue) o).error; 2927 } 2928 2929 @Override toString()2930 public String toString() { 2931 return String.format("%s(%s, %d)", getClass().getSimpleName(), callbackType, error); 2932 } 2933 } 2934 2935 private LinkedBlockingQueue<CallbackValue> mCallbacks = new LinkedBlockingQueue<>(); 2936 2937 @Override onStarted()2938 public void onStarted() { 2939 mCallbacks.add(new CallbackValue(CallbackType.ON_STARTED)); 2940 } 2941 2942 @Override onStopped()2943 public void onStopped() { 2944 mCallbacks.add(new CallbackValue(CallbackType.ON_STOPPED)); 2945 } 2946 2947 @Override onError(int error)2948 public void onError(int error) { 2949 mCallbacks.add(new CallbackValue(CallbackType.ON_ERROR, error)); 2950 } 2951 expectCallback(CallbackValue callbackValue)2952 private void expectCallback(CallbackValue callbackValue) { 2953 try { 2954 assertEquals( 2955 callbackValue, 2956 mCallbacks.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS)); 2957 } catch (InterruptedException e) { 2958 fail(callbackValue.callbackType + " callback not seen after " + TIMEOUT_MS + " ms"); 2959 } 2960 } 2961 expectStarted()2962 public void expectStarted() { 2963 expectCallback(new CallbackValue(CallbackType.ON_STARTED)); 2964 } 2965 expectStopped()2966 public void expectStopped() { 2967 expectCallback(new CallbackValue(CallbackType.ON_STOPPED)); 2968 } 2969 expectError(int error)2970 public void expectError(int error) { 2971 expectCallback(new CallbackValue(CallbackType.ON_ERROR, error)); 2972 } 2973 } 2974 connectKeepaliveNetwork(LinkProperties lp)2975 private Network connectKeepaliveNetwork(LinkProperties lp) { 2976 // Ensure the network is disconnected before we do anything. 2977 if (mWiFiNetworkAgent != null) { 2978 assertNull(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork())); 2979 } 2980 2981 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 2982 ConditionVariable cv = waitForConnectivityBroadcasts(1); 2983 mWiFiNetworkAgent.connect(true); 2984 waitFor(cv); 2985 verifyActiveNetwork(TRANSPORT_WIFI); 2986 mWiFiNetworkAgent.sendLinkProperties(lp); 2987 waitForIdle(); 2988 return mWiFiNetworkAgent.getNetwork(); 2989 } 2990 2991 @SmallTest testPacketKeepalives()2992 public void testPacketKeepalives() throws Exception { 2993 InetAddress myIPv4 = InetAddress.getByName("192.0.2.129"); 2994 InetAddress notMyIPv4 = InetAddress.getByName("192.0.2.35"); 2995 InetAddress myIPv6 = InetAddress.getByName("2001:db8::1"); 2996 InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8"); 2997 InetAddress dstIPv6 = InetAddress.getByName("2001:4860:4860::8888"); 2998 2999 LinkProperties lp = new LinkProperties(); 3000 lp.setInterfaceName("wlan12"); 3001 lp.addLinkAddress(new LinkAddress(myIPv6, 64)); 3002 lp.addLinkAddress(new LinkAddress(myIPv4, 25)); 3003 lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234"))); 3004 lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254"))); 3005 3006 Network notMyNet = new Network(61234); 3007 Network myNet = connectKeepaliveNetwork(lp); 3008 3009 TestKeepaliveCallback callback = new TestKeepaliveCallback(); 3010 PacketKeepalive ka; 3011 3012 // Attempt to start keepalives with invalid parameters and check for errors. 3013 ka = mCm.startNattKeepalive(notMyNet, 25, callback, myIPv4, 1234, dstIPv4); 3014 callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK); 3015 3016 ka = mCm.startNattKeepalive(myNet, 19, callback, notMyIPv4, 1234, dstIPv4); 3017 callback.expectError(PacketKeepalive.ERROR_INVALID_INTERVAL); 3018 3019 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 1234, dstIPv6); 3020 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS); 3021 3022 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv6, 1234, dstIPv4); 3023 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS); 3024 3025 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv6, 1234, dstIPv6); 3026 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS); // NAT-T is IPv4-only. 3027 3028 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 123456, dstIPv4); 3029 callback.expectError(PacketKeepalive.ERROR_INVALID_PORT); 3030 3031 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 123456, dstIPv4); 3032 callback.expectError(PacketKeepalive.ERROR_INVALID_PORT); 3033 3034 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4); 3035 callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED); 3036 3037 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4); 3038 callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED); 3039 3040 // Check that a started keepalive can be stopped. 3041 mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS); 3042 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4); 3043 callback.expectStarted(); 3044 mWiFiNetworkAgent.setStopKeepaliveError(PacketKeepalive.SUCCESS); 3045 ka.stop(); 3046 callback.expectStopped(); 3047 3048 // Check that deleting the IP address stops the keepalive. 3049 LinkProperties bogusLp = new LinkProperties(lp); 3050 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4); 3051 callback.expectStarted(); 3052 bogusLp.removeLinkAddress(new LinkAddress(myIPv4, 25)); 3053 bogusLp.addLinkAddress(new LinkAddress(notMyIPv4, 25)); 3054 mWiFiNetworkAgent.sendLinkProperties(bogusLp); 3055 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS); 3056 mWiFiNetworkAgent.sendLinkProperties(lp); 3057 3058 // Check that a started keepalive is stopped correctly when the network disconnects. 3059 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4); 3060 callback.expectStarted(); 3061 mWiFiNetworkAgent.disconnect(); 3062 waitFor(mWiFiNetworkAgent.getDisconnectedCV()); 3063 callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK); 3064 3065 // ... and that stopping it after that has no adverse effects. 3066 waitForIdle(); 3067 final Network myNetAlias = myNet; 3068 assertNull(mCm.getNetworkCapabilities(myNetAlias)); 3069 ka.stop(); 3070 3071 // Reconnect. 3072 myNet = connectKeepaliveNetwork(lp); 3073 mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS); 3074 3075 // Check things work as expected when the keepalive is stopped and the network disconnects. 3076 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4); 3077 callback.expectStarted(); 3078 ka.stop(); 3079 mWiFiNetworkAgent.disconnect(); 3080 waitFor(mWiFiNetworkAgent.getDisconnectedCV()); 3081 waitForIdle(); 3082 callback.expectStopped(); 3083 3084 // Reconnect. 3085 myNet = connectKeepaliveNetwork(lp); 3086 mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS); 3087 3088 // Check that keepalive slots start from 1 and increment. The first one gets slot 1. 3089 mWiFiNetworkAgent.setExpectedKeepaliveSlot(1); 3090 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4); 3091 callback.expectStarted(); 3092 3093 // The second one gets slot 2. 3094 mWiFiNetworkAgent.setExpectedKeepaliveSlot(2); 3095 TestKeepaliveCallback callback2 = new TestKeepaliveCallback(); 3096 PacketKeepalive ka2 = mCm.startNattKeepalive(myNet, 25, callback2, myIPv4, 6789, dstIPv4); 3097 callback2.expectStarted(); 3098 3099 // Now stop the first one and create a third. This also gets slot 1. 3100 ka.stop(); 3101 callback.expectStopped(); 3102 3103 mWiFiNetworkAgent.setExpectedKeepaliveSlot(1); 3104 TestKeepaliveCallback callback3 = new TestKeepaliveCallback(); 3105 PacketKeepalive ka3 = mCm.startNattKeepalive(myNet, 25, callback3, myIPv4, 9876, dstIPv4); 3106 callback3.expectStarted(); 3107 3108 ka2.stop(); 3109 callback2.expectStopped(); 3110 3111 ka3.stop(); 3112 callback3.expectStopped(); 3113 } 3114 3115 @SmallTest testGetCaptivePortalServerUrl()3116 public void testGetCaptivePortalServerUrl() throws Exception { 3117 String url = mCm.getCaptivePortalServerUrl(); 3118 assertEquals("http://connectivitycheck.gstatic.com/generate_204", url); 3119 } 3120 3121 private static class TestNetworkPinner extends NetworkPinner { awaitPin(int timeoutMs)3122 public static boolean awaitPin(int timeoutMs) { 3123 synchronized(sLock) { 3124 if (sNetwork == null) { 3125 try { 3126 sLock.wait(timeoutMs); 3127 } catch (InterruptedException e) {} 3128 } 3129 return sNetwork != null; 3130 } 3131 } 3132 awaitUnpin(int timeoutMs)3133 public static boolean awaitUnpin(int timeoutMs) { 3134 synchronized(sLock) { 3135 if (sNetwork != null) { 3136 try { 3137 sLock.wait(timeoutMs); 3138 } catch (InterruptedException e) {} 3139 } 3140 return sNetwork == null; 3141 } 3142 } 3143 } 3144 assertPinnedToWifiWithCellDefault()3145 private void assertPinnedToWifiWithCellDefault() { 3146 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess()); 3147 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 3148 } 3149 assertPinnedToWifiWithWifiDefault()3150 private void assertPinnedToWifiWithWifiDefault() { 3151 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess()); 3152 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 3153 } 3154 assertNotPinnedToWifi()3155 private void assertNotPinnedToWifi() { 3156 assertNull(mCm.getBoundNetworkForProcess()); 3157 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 3158 } 3159 3160 @SmallTest testNetworkPinner()3161 public void testNetworkPinner() { 3162 NetworkRequest wifiRequest = new NetworkRequest.Builder() 3163 .addTransportType(TRANSPORT_WIFI) 3164 .build(); 3165 assertNull(mCm.getBoundNetworkForProcess()); 3166 3167 TestNetworkPinner.pin(mServiceContext, wifiRequest); 3168 assertNull(mCm.getBoundNetworkForProcess()); 3169 3170 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); 3171 mCellNetworkAgent.connect(true); 3172 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 3173 mWiFiNetworkAgent.connect(false); 3174 3175 // When wi-fi connects, expect to be pinned. 3176 assertTrue(TestNetworkPinner.awaitPin(100)); 3177 assertPinnedToWifiWithCellDefault(); 3178 3179 // Disconnect and expect the pin to drop. 3180 mWiFiNetworkAgent.disconnect(); 3181 assertTrue(TestNetworkPinner.awaitUnpin(100)); 3182 assertNotPinnedToWifi(); 3183 3184 // Reconnecting does not cause the pin to come back. 3185 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 3186 mWiFiNetworkAgent.connect(false); 3187 assertFalse(TestNetworkPinner.awaitPin(100)); 3188 assertNotPinnedToWifi(); 3189 3190 // Pinning while connected causes the pin to take effect immediately. 3191 TestNetworkPinner.pin(mServiceContext, wifiRequest); 3192 assertTrue(TestNetworkPinner.awaitPin(100)); 3193 assertPinnedToWifiWithCellDefault(); 3194 3195 // Explicitly unpin and expect to use the default network again. 3196 TestNetworkPinner.unpin(); 3197 assertNotPinnedToWifi(); 3198 3199 // Disconnect cell and wifi. 3200 ConditionVariable cv = waitForConnectivityBroadcasts(3); // cell down, wifi up, wifi down. 3201 mCellNetworkAgent.disconnect(); 3202 mWiFiNetworkAgent.disconnect(); 3203 waitFor(cv); 3204 3205 // Pinning takes effect even if the pinned network is the default when the pin is set... 3206 TestNetworkPinner.pin(mServiceContext, wifiRequest); 3207 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 3208 mWiFiNetworkAgent.connect(false); 3209 assertTrue(TestNetworkPinner.awaitPin(100)); 3210 assertPinnedToWifiWithWifiDefault(); 3211 3212 // ... and is maintained even when that network is no longer the default. 3213 cv = waitForConnectivityBroadcasts(1); 3214 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 3215 mCellNetworkAgent.connect(true); 3216 waitFor(cv); 3217 assertPinnedToWifiWithCellDefault(); 3218 } 3219 3220 @SmallTest testNetworkRequestMaximum()3221 public void testNetworkRequestMaximum() { 3222 final int MAX_REQUESTS = 100; 3223 // Test that the limit is enforced when MAX_REQUESTS simultaneous requests are added. 3224 NetworkRequest networkRequest = new NetworkRequest.Builder().build(); 3225 ArrayList<NetworkCallback> networkCallbacks = new ArrayList<NetworkCallback>(); 3226 try { 3227 for (int i = 0; i < MAX_REQUESTS; i++) { 3228 NetworkCallback networkCallback = new NetworkCallback(); 3229 mCm.requestNetwork(networkRequest, networkCallback); 3230 networkCallbacks.add(networkCallback); 3231 } 3232 fail("Registering " + MAX_REQUESTS + " NetworkRequests did not throw exception"); 3233 } catch (TooManyRequestsException expected) {} 3234 for (NetworkCallback networkCallback : networkCallbacks) { 3235 mCm.unregisterNetworkCallback(networkCallback); 3236 } 3237 networkCallbacks.clear(); 3238 3239 try { 3240 for (int i = 0; i < MAX_REQUESTS; i++) { 3241 NetworkCallback networkCallback = new NetworkCallback(); 3242 mCm.registerNetworkCallback(networkRequest, networkCallback); 3243 networkCallbacks.add(networkCallback); 3244 } 3245 fail("Registering " + MAX_REQUESTS + " NetworkCallbacks did not throw exception"); 3246 } catch (TooManyRequestsException expected) {} 3247 for (NetworkCallback networkCallback : networkCallbacks) { 3248 mCm.unregisterNetworkCallback(networkCallback); 3249 } 3250 networkCallbacks.clear(); 3251 3252 ArrayList<PendingIntent> pendingIntents = new ArrayList<PendingIntent>(); 3253 try { 3254 for (int i = 0; i < MAX_REQUESTS + 1; i++) { 3255 PendingIntent pendingIntent = 3256 PendingIntent.getBroadcast(mContext, 0, new Intent("a" + i), 0); 3257 mCm.requestNetwork(networkRequest, pendingIntent); 3258 pendingIntents.add(pendingIntent); 3259 } 3260 fail("Registering " + MAX_REQUESTS + 3261 " PendingIntent NetworkRequests did not throw exception"); 3262 } catch (TooManyRequestsException expected) {} 3263 for (PendingIntent pendingIntent : pendingIntents) { 3264 mCm.unregisterNetworkCallback(pendingIntent); 3265 } 3266 pendingIntents.clear(); 3267 3268 try { 3269 for (int i = 0; i < MAX_REQUESTS + 1; i++) { 3270 PendingIntent pendingIntent = 3271 PendingIntent.getBroadcast(mContext, 0, new Intent("a" + i), 0); 3272 mCm.registerNetworkCallback(networkRequest, pendingIntent); 3273 pendingIntents.add(pendingIntent); 3274 } 3275 fail("Registering " + MAX_REQUESTS + 3276 " PendingIntent NetworkCallbacks did not throw exception"); 3277 } catch (TooManyRequestsException expected) {} 3278 for (PendingIntent pendingIntent : pendingIntents) { 3279 mCm.unregisterNetworkCallback(pendingIntent); 3280 } 3281 pendingIntents.clear(); 3282 waitForIdle(5000); 3283 3284 // Test that the limit is not hit when MAX_REQUESTS requests are added and removed. 3285 for (int i = 0; i < MAX_REQUESTS; i++) { 3286 NetworkCallback networkCallback = new NetworkCallback(); 3287 mCm.requestNetwork(networkRequest, networkCallback); 3288 mCm.unregisterNetworkCallback(networkCallback); 3289 } 3290 waitForIdle(); 3291 for (int i = 0; i < MAX_REQUESTS; i++) { 3292 NetworkCallback networkCallback = new NetworkCallback(); 3293 mCm.registerNetworkCallback(networkRequest, networkCallback); 3294 mCm.unregisterNetworkCallback(networkCallback); 3295 } 3296 waitForIdle(); 3297 for (int i = 0; i < MAX_REQUESTS; i++) { 3298 PendingIntent pendingIntent = 3299 PendingIntent.getBroadcast(mContext, 0, new Intent("b" + i), 0); 3300 mCm.requestNetwork(networkRequest, pendingIntent); 3301 mCm.unregisterNetworkCallback(pendingIntent); 3302 } 3303 waitForIdle(); 3304 for (int i = 0; i < MAX_REQUESTS; i++) { 3305 PendingIntent pendingIntent = 3306 PendingIntent.getBroadcast(mContext, 0, new Intent("c" + i), 0); 3307 mCm.registerNetworkCallback(networkRequest, pendingIntent); 3308 mCm.unregisterNetworkCallback(pendingIntent); 3309 } 3310 } 3311 3312 @SmallTest testNetworkInfoOfTypeNone()3313 public void testNetworkInfoOfTypeNone() { 3314 ConditionVariable broadcastCV = waitForConnectivityBroadcasts(1); 3315 3316 verifyNoNetwork(); 3317 MockNetworkAgent wifiAware = new MockNetworkAgent(TRANSPORT_WIFI_AWARE); 3318 assertNull(mCm.getActiveNetworkInfo()); 3319 3320 Network[] allNetworks = mCm.getAllNetworks(); 3321 assertLength(1, allNetworks); 3322 Network network = allNetworks[0]; 3323 NetworkCapabilities capabilities = mCm.getNetworkCapabilities(network); 3324 assertTrue(capabilities.hasTransport(TRANSPORT_WIFI_AWARE)); 3325 3326 final NetworkRequest request = 3327 new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI_AWARE).build(); 3328 final TestNetworkCallback callback = new TestNetworkCallback(); 3329 mCm.registerNetworkCallback(request, callback); 3330 3331 // Bring up wifi aware network. 3332 wifiAware.connect(false, false); 3333 callback.expectAvailableCallbacks(wifiAware); 3334 3335 assertNull(mCm.getActiveNetworkInfo()); 3336 assertNull(mCm.getActiveNetwork()); 3337 // TODO: getAllNetworkInfo is dirty and returns a non-empty array right from the start 3338 // of this test. Fix it and uncomment the assert below. 3339 //assertEmpty(mCm.getAllNetworkInfo()); 3340 3341 // Disconnect wifi aware network. 3342 wifiAware.disconnect(); 3343 callback.expectCallbackLike((info) -> info.state == CallbackState.LOST, TIMEOUT_MS); 3344 mCm.unregisterNetworkCallback(callback); 3345 3346 verifyNoNetwork(); 3347 if (broadcastCV.block(10)) { 3348 fail("expected no broadcast, but got CONNECTIVITY_ACTION broadcast"); 3349 } 3350 } 3351 3352 @SmallTest testDeprecatedAndUnsupportedOperations()3353 public void testDeprecatedAndUnsupportedOperations() throws Exception { 3354 final int TYPE_NONE = ConnectivityManager.TYPE_NONE; 3355 assertNull(mCm.getNetworkInfo(TYPE_NONE)); 3356 assertNull(mCm.getNetworkForType(TYPE_NONE)); 3357 assertNull(mCm.getLinkProperties(TYPE_NONE)); 3358 assertFalse(mCm.isNetworkSupported(TYPE_NONE)); 3359 3360 assertException(() -> { mCm.networkCapabilitiesForType(TYPE_NONE); }, 3361 IllegalArgumentException.class); 3362 3363 Class<UnsupportedOperationException> unsupported = UnsupportedOperationException.class; 3364 assertException(() -> { mCm.startUsingNetworkFeature(TYPE_WIFI, ""); }, unsupported); 3365 assertException(() -> { mCm.stopUsingNetworkFeature(TYPE_WIFI, ""); }, unsupported); 3366 // TODO: let test context have configuration application target sdk version 3367 // and test that pre-M requesting for TYPE_NONE sends back APN_REQUEST_FAILED 3368 assertException(() -> { mCm.startUsingNetworkFeature(TYPE_NONE, ""); }, unsupported); 3369 assertException(() -> { mCm.stopUsingNetworkFeature(TYPE_NONE, ""); }, unsupported); 3370 assertException(() -> { mCm.requestRouteToHostAddress(TYPE_NONE, null); }, unsupported); 3371 } 3372 3373 @SmallTest testLinkPropertiesEnsuresDirectlyConnectedRoutes()3374 public void testLinkPropertiesEnsuresDirectlyConnectedRoutes() { 3375 final NetworkRequest networkRequest = new NetworkRequest.Builder() 3376 .addTransportType(TRANSPORT_WIFI).build(); 3377 final TestNetworkCallback networkCallback = new TestNetworkCallback(); 3378 mCm.registerNetworkCallback(networkRequest, networkCallback); 3379 3380 LinkProperties lp = new LinkProperties(); 3381 lp.setInterfaceName("wlan0"); 3382 LinkAddress myIpv4Address = new LinkAddress("192.168.12.3/24"); 3383 RouteInfo myIpv4DefaultRoute = new RouteInfo((IpPrefix) null, 3384 NetworkUtils.numericToInetAddress("192.168.12.1"), lp.getInterfaceName()); 3385 lp.addLinkAddress(myIpv4Address); 3386 lp.addRoute(myIpv4DefaultRoute); 3387 3388 // Verify direct routes are added when network agent is first registered in 3389 // ConnectivityService. 3390 MockNetworkAgent networkAgent = new MockNetworkAgent(TRANSPORT_WIFI, lp); 3391 networkAgent.connect(true); 3392 networkCallback.expectCallback(CallbackState.AVAILABLE, networkAgent); 3393 networkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, networkAgent); 3394 CallbackInfo cbi = networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, 3395 networkAgent); 3396 networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, networkAgent); 3397 networkCallback.assertNoCallback(); 3398 checkDirectlyConnectedRoutes(cbi.arg, Arrays.asList(myIpv4Address), 3399 Arrays.asList(myIpv4DefaultRoute)); 3400 checkDirectlyConnectedRoutes(mCm.getLinkProperties(networkAgent.getNetwork()), 3401 Arrays.asList(myIpv4Address), Arrays.asList(myIpv4DefaultRoute)); 3402 3403 // Verify direct routes are added during subsequent link properties updates. 3404 LinkProperties newLp = new LinkProperties(lp); 3405 LinkAddress myIpv6Address1 = new LinkAddress("fe80::cafe/64"); 3406 LinkAddress myIpv6Address2 = new LinkAddress("2001:db8::2/64"); 3407 newLp.addLinkAddress(myIpv6Address1); 3408 newLp.addLinkAddress(myIpv6Address2); 3409 networkAgent.sendLinkProperties(newLp); 3410 cbi = networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, networkAgent); 3411 networkCallback.assertNoCallback(); 3412 checkDirectlyConnectedRoutes(cbi.arg, 3413 Arrays.asList(myIpv4Address, myIpv6Address1, myIpv6Address2), 3414 Arrays.asList(myIpv4DefaultRoute)); 3415 mCm.unregisterNetworkCallback(networkCallback); 3416 } 3417 checkDirectlyConnectedRoutes(Object callbackObj, Collection<LinkAddress> linkAddresses, Collection<RouteInfo> otherRoutes)3418 private void checkDirectlyConnectedRoutes(Object callbackObj, 3419 Collection<LinkAddress> linkAddresses, Collection<RouteInfo> otherRoutes) { 3420 assertTrue(callbackObj instanceof LinkProperties); 3421 LinkProperties lp = (LinkProperties) callbackObj; 3422 3423 Set<RouteInfo> expectedRoutes = new ArraySet<>(); 3424 expectedRoutes.addAll(otherRoutes); 3425 for (LinkAddress address : linkAddresses) { 3426 RouteInfo localRoute = new RouteInfo(address, null, lp.getInterfaceName()); 3427 // Duplicates in linkAddresses are considered failures 3428 assertTrue(expectedRoutes.add(localRoute)); 3429 } 3430 List<RouteInfo> observedRoutes = lp.getRoutes(); 3431 assertEquals(expectedRoutes.size(), observedRoutes.size()); 3432 assertTrue(observedRoutes.containsAll(expectedRoutes)); 3433 } 3434 assertEmpty(T[] ts)3435 private static <T> void assertEmpty(T[] ts) { 3436 int length = ts.length; 3437 assertEquals("expected empty array, but length was " + length, 0, length); 3438 } 3439 assertLength(int expected, T[] got)3440 private static <T> void assertLength(int expected, T[] got) { 3441 int length = got.length; 3442 assertEquals(String.format("expected array of length %s, but length was %s for %s", 3443 expected, length, Arrays.toString(got)), expected, length); 3444 } 3445 assertException(Runnable block, Class<T> expected)3446 private static <T> void assertException(Runnable block, Class<T> expected) { 3447 try { 3448 block.run(); 3449 fail("Expected exception of type " + expected); 3450 } catch (Exception got) { 3451 if (!got.getClass().equals(expected)) { 3452 fail("Expected exception of type " + expected + " but got " + got); 3453 } 3454 return; 3455 } 3456 } 3457 3458 @SmallTest testVpnNetworkMetered()3459 public void testVpnNetworkMetered() { 3460 final TestNetworkCallback callback = new TestNetworkCallback(); 3461 mCm.registerDefaultNetworkCallback(callback); 3462 3463 final NetworkRequest cellRequest = new NetworkRequest.Builder() 3464 .addTransportType(TRANSPORT_CELLULAR).build(); 3465 final TestNetworkCallback cellCallback = new TestNetworkCallback(); 3466 mCm.registerNetworkCallback(cellRequest, cellCallback); 3467 3468 // Setup cellular 3469 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); 3470 mCellNetworkAgent.connect(true); 3471 callback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent); 3472 cellCallback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent); 3473 verifyActiveNetwork(TRANSPORT_CELLULAR); 3474 3475 // Verify meteredness of cellular 3476 assertTrue(mCm.isActiveNetworkMetered()); 3477 3478 // Setup Wifi 3479 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 3480 mWiFiNetworkAgent.connect(true); 3481 callback.expectAvailableAndValidatedCallbacks(mWiFiNetworkAgent); 3482 cellCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent); 3483 verifyActiveNetwork(TRANSPORT_WIFI); 3484 3485 // Verify meteredness of WiFi 3486 assertTrue(mCm.isActiveNetworkMetered()); 3487 3488 // Verify that setting unmetered on Wifi changes ActiveNetworkMetered 3489 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED); 3490 callback.expectCapabilitiesWith(NET_CAPABILITY_NOT_METERED, mWiFiNetworkAgent); 3491 assertFalse(mCm.isActiveNetworkMetered()); 3492 3493 // Setup VPN 3494 final MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN); 3495 vpnNetworkAgent.connect(true); 3496 3497 Vpn mockVpn = mock(Vpn.class); 3498 when(mockVpn.appliesToUid(anyInt())).thenReturn(true); 3499 when(mockVpn.getNetId()).thenReturn(vpnNetworkAgent.getNetwork().netId); 3500 3501 Vpn oldVpn = mService.getVpn(UserHandle.myUserId()); 3502 mService.setVpn(UserHandle.myUserId(), mockVpn); 3503 assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 3504 3505 // Verify meteredness of VPN on default network 3506 when(mockVpn.getUnderlyingNetworks()).thenReturn(null); 3507 assertFalse(mCm.isActiveNetworkMetered()); 3508 assertFalse(mCm.isActiveNetworkMeteredForUid(Process.myUid())); 3509 3510 // Verify meteredness of VPN on unmetered wifi 3511 when(mockVpn.getUnderlyingNetworks()) 3512 .thenReturn(new Network[] {mWiFiNetworkAgent.getNetwork()}); 3513 assertFalse(mCm.isActiveNetworkMetered()); 3514 assertFalse(mCm.isActiveNetworkMeteredForUid(Process.myUid())); 3515 3516 // Set WiFi as metered, then check to see that it has been updated on the VPN 3517 mWiFiNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED); 3518 callback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_METERED, mWiFiNetworkAgent); 3519 assertTrue(mCm.isActiveNetworkMetered()); 3520 assertTrue(mCm.isActiveNetworkMeteredForUid(Process.myUid())); 3521 3522 // Switch to cellular 3523 when(mockVpn.getUnderlyingNetworks()) 3524 .thenReturn(new Network[] {mCellNetworkAgent.getNetwork()}); 3525 assertTrue(mCm.isActiveNetworkMetered()); 3526 assertTrue(mCm.isActiveNetworkMeteredForUid(Process.myUid())); 3527 3528 // Test unmetered cellular 3529 mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED); 3530 cellCallback.expectCapabilitiesWith(NET_CAPABILITY_NOT_METERED, mCellNetworkAgent); 3531 assertFalse(mCm.isActiveNetworkMetered()); 3532 assertFalse(mCm.isActiveNetworkMeteredForUid(Process.myUid())); 3533 3534 mService.setVpn(UserHandle.myUserId(), oldVpn); 3535 mCm.unregisterNetworkCallback(callback); 3536 } 3537 } 3538