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