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