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