1/* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.server; 18 19import static android.net.ConnectivityManager.CONNECTIVITY_ACTION; 20import static android.net.ConnectivityManager.TYPE_MOBILE; 21import static android.net.ConnectivityManager.TYPE_WIFI; 22import static android.net.ConnectivityManager.getNetworkTypeName; 23import static android.net.NetworkCapabilities.*; 24 25import static org.mockito.Mockito.mock; 26 27import android.app.PendingIntent; 28import android.content.BroadcastReceiver; 29import android.content.Context; 30import android.content.ContextWrapper; 31import android.content.Intent; 32import android.content.IntentFilter; 33import android.net.ConnectivityManager; 34import android.net.ConnectivityManager.NetworkCallback; 35import android.net.ConnectivityManager.PacketKeepalive; 36import android.net.ConnectivityManager.PacketKeepaliveCallback; 37import android.net.INetworkPolicyManager; 38import android.net.INetworkStatsService; 39import android.net.IpPrefix; 40import android.net.LinkAddress; 41import android.net.LinkProperties; 42import android.net.Network; 43import android.net.NetworkAgent; 44import android.net.NetworkCapabilities; 45import android.net.NetworkConfig; 46import android.net.NetworkFactory; 47import android.net.NetworkInfo; 48import android.net.NetworkInfo.DetailedState; 49import android.net.NetworkMisc; 50import android.net.NetworkRequest; 51import android.net.RouteInfo; 52import android.os.ConditionVariable; 53import android.os.Handler; 54import android.os.HandlerThread; 55import android.os.IBinder; 56import android.os.INetworkManagementService; 57import android.os.Looper; 58import android.os.Message; 59import android.os.MessageQueue; 60import android.os.Messenger; 61import android.os.MessageQueue.IdleHandler; 62import android.os.Process; 63import android.os.SystemClock; 64import android.test.AndroidTestCase; 65import android.test.suitebuilder.annotation.LargeTest; 66import android.test.suitebuilder.annotation.SmallTest; 67import android.util.Log; 68import android.util.LogPrinter; 69 70import com.android.internal.util.WakeupMessage; 71import com.android.server.connectivity.NetworkAgentInfo; 72import com.android.server.connectivity.NetworkMonitor; 73import com.android.server.connectivity.NetworkMonitor.CaptivePortalProbeResult; 74import com.android.server.net.NetworkPinner; 75 76import java.net.InetAddress; 77import java.util.ArrayList; 78import java.util.concurrent.CountDownLatch; 79import java.util.concurrent.LinkedBlockingQueue; 80import java.util.concurrent.TimeUnit; 81import java.util.concurrent.atomic.AtomicBoolean; 82 83/** 84 * Tests for {@link ConnectivityService}. 85 * 86 * Build, install and run with: 87 * runtest frameworks-services -c com.android.server.ConnectivityServiceTest 88 */ 89public class ConnectivityServiceTest extends AndroidTestCase { 90 private static final String TAG = "ConnectivityServiceTest"; 91 92 private static final int TIMEOUT_MS = 500; 93 94 private BroadcastInterceptingContext mServiceContext; 95 private WrappedConnectivityService mService; 96 private WrappedConnectivityManager mCm; 97 private MockNetworkAgent mWiFiNetworkAgent; 98 private MockNetworkAgent mCellNetworkAgent; 99 100 // This class exists to test bindProcessToNetwork and getBoundNetworkForProcess. These methods 101 // do not go through ConnectivityService but talk to netd directly, so they don't automatically 102 // reflect the state of our test ConnectivityService. 103 private class WrappedConnectivityManager extends ConnectivityManager { 104 private Network mFakeBoundNetwork; 105 106 public synchronized boolean bindProcessToNetwork(Network network) { 107 mFakeBoundNetwork = network; 108 return true; 109 } 110 111 public synchronized Network getBoundNetworkForProcess() { 112 return mFakeBoundNetwork; 113 } 114 115 public WrappedConnectivityManager(Context context, ConnectivityService service) { 116 super(context, service); 117 } 118 } 119 120 private class MockContext extends BroadcastInterceptingContext { 121 MockContext(Context base) { 122 super(base); 123 } 124 125 @Override 126 public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) { 127 // PendingIntents sent by the AlarmManager are not intercepted by 128 // BroadcastInterceptingContext so we must really register the receiver. 129 // This shouldn't effect the real NetworkMonitors as the action contains a random token. 130 if (filter.getAction(0).startsWith("android.net.netmon.lingerExpired")) { 131 return getBaseContext().registerReceiver(receiver, filter); 132 } else { 133 return super.registerReceiver(receiver, filter); 134 } 135 } 136 137 @Override 138 public Object getSystemService (String name) { 139 if (name == Context.CONNECTIVITY_SERVICE) return mCm; 140 return super.getSystemService(name); 141 } 142 } 143 144 /** 145 * A subclass of HandlerThread that allows callers to wait for it to become idle. waitForIdle 146 * will return immediately if the handler is already idle. 147 */ 148 private class IdleableHandlerThread extends HandlerThread { 149 private IdleHandler mIdleHandler; 150 151 public IdleableHandlerThread(String name) { 152 super(name); 153 } 154 155 public void waitForIdle(int timeoutMs) { 156 final ConditionVariable cv = new ConditionVariable(); 157 final MessageQueue queue = getLooper().getQueue(); 158 159 synchronized (queue) { 160 if (queue.isIdle()) { 161 return; 162 } 163 164 assertNull("BUG: only one idle handler allowed", mIdleHandler); 165 mIdleHandler = new IdleHandler() { 166 public boolean queueIdle() { 167 synchronized (queue) { 168 cv.open(); 169 mIdleHandler = null; 170 return false; // Remove the handler. 171 } 172 } 173 }; 174 queue.addIdleHandler(mIdleHandler); 175 } 176 177 if (!cv.block(timeoutMs)) { 178 fail("HandlerThread " + getName() + 179 " did not become idle after " + timeoutMs + " ms"); 180 queue.removeIdleHandler(mIdleHandler); 181 } 182 } 183 } 184 185 // Tests that IdleableHandlerThread works as expected. 186 public void testIdleableHandlerThread() { 187 final int attempts = 50; // Causes the test to take about 200ms on bullhead-eng. 188 189 // Tests that waitForIdle returns immediately if the service is already idle. 190 for (int i = 0; i < attempts; i++) { 191 mService.waitForIdle(); 192 } 193 194 // Bring up a network that we can use to send messages to ConnectivityService. 195 ConditionVariable cv = waitForConnectivityBroadcasts(1); 196 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 197 mWiFiNetworkAgent.connect(false); 198 waitFor(cv); 199 Network n = mWiFiNetworkAgent.getNetwork(); 200 assertNotNull(n); 201 202 // Tests that calling waitForIdle waits for messages to be processed. 203 for (int i = 0; i < attempts; i++) { 204 mWiFiNetworkAgent.setSignalStrength(i); 205 mService.waitForIdle(); 206 assertEquals(i, mCm.getNetworkCapabilities(n).getSignalStrength()); 207 } 208 209 // Ensure that not calling waitForIdle causes a race condition. 210 for (int i = 0; i < attempts; i++) { 211 mWiFiNetworkAgent.setSignalStrength(i); 212 if (i != mCm.getNetworkCapabilities(n).getSignalStrength()) { 213 // We hit a race condition, as expected. Pass the test. 214 return; 215 } 216 } 217 218 // No race? There is a bug in this test. 219 fail("expected race condition at least once in " + attempts + " attempts"); 220 } 221 222 private class MockNetworkAgent { 223 private final WrappedNetworkMonitor mWrappedNetworkMonitor; 224 private final NetworkInfo mNetworkInfo; 225 private final NetworkCapabilities mNetworkCapabilities; 226 private final IdleableHandlerThread mHandlerThread; 227 private final ConditionVariable mDisconnected = new ConditionVariable(); 228 private final ConditionVariable mNetworkStatusReceived = new ConditionVariable(); 229 private int mScore; 230 private NetworkAgent mNetworkAgent; 231 private int mStartKeepaliveError = PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED; 232 private int mStopKeepaliveError = PacketKeepalive.NO_KEEPALIVE; 233 private Integer mExpectedKeepaliveSlot = null; 234 // Contains the redirectUrl from networkStatus(). Before reading, wait for 235 // mNetworkStatusReceived. 236 private String mRedirectUrl; 237 238 MockNetworkAgent(int transport) { 239 final int type = transportToLegacyType(transport); 240 final String typeName = ConnectivityManager.getNetworkTypeName(type); 241 mNetworkInfo = new NetworkInfo(type, 0, typeName, "Mock"); 242 mNetworkCapabilities = new NetworkCapabilities(); 243 mNetworkCapabilities.addTransportType(transport); 244 switch (transport) { 245 case TRANSPORT_WIFI: 246 mScore = 60; 247 break; 248 case TRANSPORT_CELLULAR: 249 mScore = 50; 250 break; 251 default: 252 throw new UnsupportedOperationException("unimplemented network type"); 253 } 254 mHandlerThread = new IdleableHandlerThread("Mock-" + typeName); 255 mHandlerThread.start(); 256 mNetworkAgent = new NetworkAgent(mHandlerThread.getLooper(), mServiceContext, 257 "Mock-" + typeName, mNetworkInfo, mNetworkCapabilities, 258 new LinkProperties(), mScore, new NetworkMisc()) { 259 @Override 260 public void unwanted() { mDisconnected.open(); } 261 262 @Override 263 public void startPacketKeepalive(Message msg) { 264 int slot = msg.arg1; 265 if (mExpectedKeepaliveSlot != null) { 266 assertEquals((int) mExpectedKeepaliveSlot, slot); 267 } 268 onPacketKeepaliveEvent(slot, mStartKeepaliveError); 269 } 270 271 @Override 272 public void stopPacketKeepalive(Message msg) { 273 onPacketKeepaliveEvent(msg.arg1, mStopKeepaliveError); 274 } 275 276 @Override 277 public void networkStatus(int status, String redirectUrl) { 278 mRedirectUrl = redirectUrl; 279 mNetworkStatusReceived.open(); 280 } 281 }; 282 // Waits for the NetworkAgent to be registered, which includes the creation of the 283 // NetworkMonitor. 284 mService.waitForIdle(); 285 mWrappedNetworkMonitor = mService.getLastCreatedWrappedNetworkMonitor(); 286 } 287 288 public void waitForIdle(int timeoutMs) { 289 mHandlerThread.waitForIdle(timeoutMs); 290 } 291 292 public void waitForIdle() { 293 waitForIdle(TIMEOUT_MS); 294 } 295 296 public void adjustScore(int change) { 297 mScore += change; 298 mNetworkAgent.sendNetworkScore(mScore); 299 } 300 301 public void addCapability(int capability) { 302 mNetworkCapabilities.addCapability(capability); 303 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities); 304 } 305 306 public void setSignalStrength(int signalStrength) { 307 mNetworkCapabilities.setSignalStrength(signalStrength); 308 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities); 309 } 310 311 public void connectWithoutInternet() { 312 mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, null); 313 mNetworkAgent.sendNetworkInfo(mNetworkInfo); 314 } 315 316 /** 317 * Transition this NetworkAgent to CONNECTED state with NET_CAPABILITY_INTERNET. 318 * @param validated Indicate if network should pretend to be validated. 319 */ 320 public void connect(boolean validated) { 321 assertEquals(mNetworkInfo.getDetailedState(), DetailedState.IDLE); 322 assertFalse(mNetworkCapabilities.hasCapability(NET_CAPABILITY_INTERNET)); 323 324 NetworkCallback callback = null; 325 final ConditionVariable validatedCv = new ConditionVariable(); 326 if (validated) { 327 mWrappedNetworkMonitor.gen204ProbeResult = 204; 328 NetworkRequest request = new NetworkRequest.Builder() 329 .addTransportType(mNetworkCapabilities.getTransportTypes()[0]) 330 .build(); 331 callback = new NetworkCallback() { 332 public void onCapabilitiesChanged(Network network, 333 NetworkCapabilities networkCapabilities) { 334 if (network.equals(getNetwork()) && 335 networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED)) { 336 validatedCv.open(); 337 } 338 } 339 }; 340 mCm.registerNetworkCallback(request, callback); 341 } 342 addCapability(NET_CAPABILITY_INTERNET); 343 344 connectWithoutInternet(); 345 346 if (validated) { 347 // Wait for network to validate. 348 waitFor(validatedCv); 349 mWrappedNetworkMonitor.gen204ProbeResult = 500; 350 } 351 352 if (callback != null) mCm.unregisterNetworkCallback(callback); 353 } 354 355 public void connectWithCaptivePortal(String redirectUrl) { 356 mWrappedNetworkMonitor.gen204ProbeResult = 200; 357 mWrappedNetworkMonitor.gen204ProbeRedirectUrl = redirectUrl; 358 connect(false); 359 waitFor(new Criteria() { public boolean get() { 360 NetworkCapabilities caps = mCm.getNetworkCapabilities(getNetwork()); 361 return caps != null && caps.hasCapability(NET_CAPABILITY_CAPTIVE_PORTAL);} }); 362 mWrappedNetworkMonitor.gen204ProbeResult = 500; 363 mWrappedNetworkMonitor.gen204ProbeRedirectUrl = null; 364 } 365 366 public void disconnect() { 367 mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, null); 368 mNetworkAgent.sendNetworkInfo(mNetworkInfo); 369 } 370 371 public Network getNetwork() { 372 return new Network(mNetworkAgent.netId); 373 } 374 375 public ConditionVariable getDisconnectedCV() { 376 return mDisconnected; 377 } 378 379 public WrappedNetworkMonitor getWrappedNetworkMonitor() { 380 return mWrappedNetworkMonitor; 381 } 382 383 public void sendLinkProperties(LinkProperties lp) { 384 mNetworkAgent.sendLinkProperties(lp); 385 } 386 387 public void setStartKeepaliveError(int error) { 388 mStartKeepaliveError = error; 389 } 390 391 public void setStopKeepaliveError(int error) { 392 mStopKeepaliveError = error; 393 } 394 395 public void setExpectedKeepaliveSlot(Integer slot) { 396 mExpectedKeepaliveSlot = slot; 397 } 398 399 public String waitForRedirectUrl() { 400 assertTrue(mNetworkStatusReceived.block(TIMEOUT_MS)); 401 return mRedirectUrl; 402 } 403 } 404 405 /** 406 * A NetworkFactory that allows tests to wait until any in-flight NetworkRequest add or remove 407 * operations have been processed. Before ConnectivityService can add or remove any requests, 408 * the factory must be told to expect those operations by calling expectAddRequests or 409 * expectRemoveRequests. 410 */ 411 private static class MockNetworkFactory extends NetworkFactory { 412 private final ConditionVariable mNetworkStartedCV = new ConditionVariable(); 413 private final ConditionVariable mNetworkStoppedCV = new ConditionVariable(); 414 private final AtomicBoolean mNetworkStarted = new AtomicBoolean(false); 415 416 // Used to expect that requests be removed or added on a separate thread, without sleeping. 417 // Callers can call either expectAddRequests() or expectRemoveRequests() exactly once, then 418 // cause some other thread to add or remove requests, then call waitForRequests(). We can 419 // either expect requests to be added or removed, but not both, because CountDownLatch can 420 // only count in one direction. 421 private CountDownLatch mExpectations; 422 423 // Whether we are currently expecting requests to be added or removed. Valid only if 424 // mExpectations is non-null. 425 private boolean mExpectingAdditions; 426 427 public MockNetworkFactory(Looper looper, Context context, String logTag, 428 NetworkCapabilities filter) { 429 super(looper, context, logTag, filter); 430 } 431 432 public int getMyRequestCount() { 433 return getRequestCount(); 434 } 435 436 protected void startNetwork() { 437 mNetworkStarted.set(true); 438 mNetworkStartedCV.open(); 439 } 440 441 protected void stopNetwork() { 442 mNetworkStarted.set(false); 443 mNetworkStoppedCV.open(); 444 } 445 446 public boolean getMyStartRequested() { 447 return mNetworkStarted.get(); 448 } 449 450 public ConditionVariable getNetworkStartedCV() { 451 mNetworkStartedCV.close(); 452 return mNetworkStartedCV; 453 } 454 455 public ConditionVariable getNetworkStoppedCV() { 456 mNetworkStoppedCV.close(); 457 return mNetworkStoppedCV; 458 } 459 460 @Override 461 protected void handleAddRequest(NetworkRequest request, int score) { 462 // If we're expecting anything, we must be expecting additions. 463 if (mExpectations != null && !mExpectingAdditions) { 464 fail("Can't add requests while expecting requests to be removed"); 465 } 466 467 // Add the request. 468 super.handleAddRequest(request, score); 469 470 // Reduce the number of request additions we're waiting for. 471 if (mExpectingAdditions) { 472 assertTrue("Added more requests than expected", mExpectations.getCount() > 0); 473 mExpectations.countDown(); 474 } 475 } 476 477 @Override 478 protected void handleRemoveRequest(NetworkRequest request) { 479 // If we're expecting anything, we must be expecting removals. 480 if (mExpectations != null && mExpectingAdditions) { 481 fail("Can't remove requests while expecting requests to be added"); 482 } 483 484 // Remove the request. 485 super.handleRemoveRequest(request); 486 487 // Reduce the number of request removals we're waiting for. 488 if (!mExpectingAdditions) { 489 assertTrue("Removed more requests than expected", mExpectations.getCount() > 0); 490 mExpectations.countDown(); 491 } 492 } 493 494 private void assertNoExpectations() { 495 if (mExpectations != null) { 496 fail("Can't add expectation, " + mExpectations.getCount() + " already pending"); 497 } 498 } 499 500 // Expects that count requests will be added. 501 public void expectAddRequests(final int count) { 502 assertNoExpectations(); 503 mExpectingAdditions = true; 504 mExpectations = new CountDownLatch(count); 505 } 506 507 // Expects that count requests will be removed. 508 public void expectRemoveRequests(final int count) { 509 assertNoExpectations(); 510 mExpectingAdditions = false; 511 mExpectations = new CountDownLatch(count); 512 } 513 514 // Waits for the expected request additions or removals to happen within a timeout. 515 public void waitForRequests() throws InterruptedException { 516 assertNotNull("Nothing to wait for", mExpectations); 517 mExpectations.await(TIMEOUT_MS, TimeUnit.MILLISECONDS); 518 final long count = mExpectations.getCount(); 519 final String msg = count + " requests still not " + 520 (mExpectingAdditions ? "added" : "removed") + 521 " after " + TIMEOUT_MS + " ms"; 522 assertEquals(msg, 0, count); 523 mExpectations = null; 524 } 525 526 public void waitForNetworkRequests(final int count) throws InterruptedException { 527 waitForRequests(); 528 assertEquals(count, getMyRequestCount()); 529 } 530 } 531 532 private class FakeWakeupMessage extends WakeupMessage { 533 private static final int UNREASONABLY_LONG_WAIT = 1000; 534 535 public FakeWakeupMessage(Context context, Handler handler, String cmdName, int cmd) { 536 super(context, handler, cmdName, cmd); 537 } 538 539 @Override 540 public void schedule(long when) { 541 long delayMs = when - SystemClock.elapsedRealtime(); 542 if (delayMs < 0) delayMs = 0; 543 if (delayMs > UNREASONABLY_LONG_WAIT) { 544 fail("Attempting to send msg more than " + UNREASONABLY_LONG_WAIT + 545 "ms into the future: " + delayMs); 546 } 547 mHandler.sendEmptyMessageDelayed(mCmd, delayMs); 548 } 549 550 @Override 551 public void cancel() { 552 mHandler.removeMessages(mCmd); 553 } 554 555 @Override 556 public void onAlarm() { 557 throw new AssertionError("Should never happen. Update this fake."); 558 } 559 } 560 561 // NetworkMonitor implementation allowing overriding of Internet connectivity probe result. 562 private class WrappedNetworkMonitor extends NetworkMonitor { 563 // HTTP response code fed back to NetworkMonitor for Internet connectivity probe. 564 public int gen204ProbeResult = 500; 565 public String gen204ProbeRedirectUrl = null; 566 567 public WrappedNetworkMonitor(Context context, Handler handler, 568 NetworkAgentInfo networkAgentInfo, NetworkRequest defaultRequest) { 569 super(context, handler, networkAgentInfo, defaultRequest); 570 } 571 572 @Override 573 protected CaptivePortalProbeResult isCaptivePortal() { 574 return new CaptivePortalProbeResult(gen204ProbeResult, gen204ProbeRedirectUrl); 575 } 576 577 @Override 578 protected WakeupMessage makeWakeupMessage( 579 Context context, Handler handler, String cmdName, int cmd) { 580 return new FakeWakeupMessage(context, handler, cmdName, cmd); 581 } 582 } 583 584 private class WrappedConnectivityService extends ConnectivityService { 585 private WrappedNetworkMonitor mLastCreatedNetworkMonitor; 586 587 public WrappedConnectivityService(Context context, INetworkManagementService netManager, 588 INetworkStatsService statsService, INetworkPolicyManager policyManager) { 589 super(context, netManager, statsService, policyManager); 590 } 591 592 @Override 593 protected HandlerThread createHandlerThread() { 594 return new IdleableHandlerThread("WrappedConnectivityService"); 595 } 596 597 @Override 598 protected int getDefaultTcpRwnd() { 599 // Prevent wrapped ConnectivityService from trying to write to SystemProperties. 600 return 0; 601 } 602 603 @Override 604 protected int reserveNetId() { 605 while (true) { 606 final int netId = super.reserveNetId(); 607 608 // Don't overlap test NetIDs with real NetIDs as binding sockets to real networks 609 // can have odd side-effects, like network validations succeeding. 610 final Network[] networks = ConnectivityManager.from(getContext()).getAllNetworks(); 611 boolean overlaps = false; 612 for (Network network : networks) { 613 if (netId == network.netId) { 614 overlaps = true; 615 break; 616 } 617 } 618 if (overlaps) continue; 619 620 return netId; 621 } 622 } 623 624 @Override 625 public NetworkMonitor createNetworkMonitor(Context context, Handler handler, 626 NetworkAgentInfo nai, NetworkRequest defaultRequest) { 627 final WrappedNetworkMonitor monitor = new WrappedNetworkMonitor(context, handler, nai, 628 defaultRequest); 629 mLastCreatedNetworkMonitor = monitor; 630 return monitor; 631 } 632 633 public WrappedNetworkMonitor getLastCreatedWrappedNetworkMonitor() { 634 return mLastCreatedNetworkMonitor; 635 } 636 637 public void waitForIdle(int timeoutMs) { 638 ((IdleableHandlerThread) mHandlerThread).waitForIdle(timeoutMs); 639 } 640 641 public void waitForIdle() { 642 waitForIdle(TIMEOUT_MS); 643 } 644 645 } 646 647 private interface Criteria { 648 public boolean get(); 649 } 650 651 /** 652 * Wait up to 500ms for {@code criteria.get()} to become true, polling. 653 * Fails if 500ms goes by before {@code criteria.get()} to become true. 654 */ 655 static private void waitFor(Criteria criteria) { 656 int delays = 0; 657 while (!criteria.get()) { 658 try { 659 Thread.sleep(50); 660 } catch (InterruptedException e) { 661 } 662 if (++delays == 10) fail(); 663 } 664 } 665 666 /** 667 * Wait up to TIMEOUT_MS for {@code conditionVariable} to open. 668 * Fails if TIMEOUT_MS goes by before {@code conditionVariable} opens. 669 */ 670 static private void waitFor(ConditionVariable conditionVariable) { 671 assertTrue(conditionVariable.block(TIMEOUT_MS)); 672 } 673 674 @Override 675 public void setUp() throws Exception { 676 super.setUp(); 677 678 NetworkMonitor.SetDefaultLingerTime(120); 679 680 // InstrumentationTestRunner prepares a looper, but AndroidJUnitRunner does not. 681 // http://b/25897652 . 682 if (Looper.myLooper() == null) { 683 Looper.prepare(); 684 } 685 686 mServiceContext = new MockContext(getContext()); 687 mService = new WrappedConnectivityService(mServiceContext, 688 mock(INetworkManagementService.class), 689 mock(INetworkStatsService.class), 690 mock(INetworkPolicyManager.class)); 691 692 mService.systemReady(); 693 mCm = new WrappedConnectivityManager(getContext(), mService); 694 mCm.bindProcessToNetwork(null); 695 } 696 697 private int transportToLegacyType(int transport) { 698 switch (transport) { 699 case TRANSPORT_WIFI: 700 return TYPE_WIFI; 701 case TRANSPORT_CELLULAR: 702 return TYPE_MOBILE; 703 default: 704 throw new IllegalStateException("Unknown transport" + transport); 705 } 706 } 707 708 private void verifyActiveNetwork(int transport) { 709 // Test getActiveNetworkInfo() 710 assertNotNull(mCm.getActiveNetworkInfo()); 711 assertEquals(transportToLegacyType(transport), mCm.getActiveNetworkInfo().getType()); 712 // Test getActiveNetwork() 713 assertNotNull(mCm.getActiveNetwork()); 714 assertEquals(mCm.getActiveNetwork(), mCm.getActiveNetworkForUid(Process.myUid())); 715 switch (transport) { 716 case TRANSPORT_WIFI: 717 assertEquals(mCm.getActiveNetwork(), mWiFiNetworkAgent.getNetwork()); 718 break; 719 case TRANSPORT_CELLULAR: 720 assertEquals(mCm.getActiveNetwork(), mCellNetworkAgent.getNetwork()); 721 break; 722 default: 723 throw new IllegalStateException("Unknown transport" + transport); 724 } 725 // Test getNetworkInfo(Network) 726 assertNotNull(mCm.getNetworkInfo(mCm.getActiveNetwork())); 727 assertEquals(transportToLegacyType(transport), mCm.getNetworkInfo(mCm.getActiveNetwork()).getType()); 728 // Test getNetworkCapabilities(Network) 729 assertNotNull(mCm.getNetworkCapabilities(mCm.getActiveNetwork())); 730 assertTrue(mCm.getNetworkCapabilities(mCm.getActiveNetwork()).hasTransport(transport)); 731 } 732 733 private void verifyNoNetwork() { 734 // Test getActiveNetworkInfo() 735 assertNull(mCm.getActiveNetworkInfo()); 736 // Test getActiveNetwork() 737 assertNull(mCm.getActiveNetwork()); 738 assertNull(mCm.getActiveNetworkForUid(Process.myUid())); 739 // Test getAllNetworks() 740 assertEquals(0, mCm.getAllNetworks().length); 741 } 742 743 /** 744 * Return a ConditionVariable that opens when {@code count} numbers of CONNECTIVITY_ACTION 745 * broadcasts are received. 746 */ 747 private ConditionVariable waitForConnectivityBroadcasts(final int count) { 748 final ConditionVariable cv = new ConditionVariable(); 749 mServiceContext.registerReceiver(new BroadcastReceiver() { 750 private int remaining = count; 751 public void onReceive(Context context, Intent intent) { 752 if (--remaining == 0) { 753 cv.open(); 754 mServiceContext.unregisterReceiver(this); 755 } 756 } 757 }, new IntentFilter(CONNECTIVITY_ACTION)); 758 return cv; 759 } 760 761 @LargeTest 762 public void testLingering() throws Exception { 763 verifyNoNetwork(); 764 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); 765 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 766 assertNull(mCm.getActiveNetworkInfo()); 767 assertNull(mCm.getActiveNetwork()); 768 // Test bringing up validated cellular. 769 ConditionVariable cv = waitForConnectivityBroadcasts(1); 770 mCellNetworkAgent.connect(true); 771 waitFor(cv); 772 verifyActiveNetwork(TRANSPORT_CELLULAR); 773 assertEquals(2, mCm.getAllNetworks().length); 774 assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) || 775 mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork())); 776 assertTrue(mCm.getAllNetworks()[0].equals(mWiFiNetworkAgent.getNetwork()) || 777 mCm.getAllNetworks()[1].equals(mWiFiNetworkAgent.getNetwork())); 778 // Test bringing up validated WiFi. 779 cv = waitForConnectivityBroadcasts(2); 780 mWiFiNetworkAgent.connect(true); 781 waitFor(cv); 782 verifyActiveNetwork(TRANSPORT_WIFI); 783 assertEquals(2, mCm.getAllNetworks().length); 784 assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) || 785 mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork())); 786 assertTrue(mCm.getAllNetworks()[0].equals(mCellNetworkAgent.getNetwork()) || 787 mCm.getAllNetworks()[1].equals(mCellNetworkAgent.getNetwork())); 788 // Test cellular linger timeout. 789 waitFor(new Criteria() { 790 public boolean get() { return mCm.getAllNetworks().length == 1; } }); 791 verifyActiveNetwork(TRANSPORT_WIFI); 792 assertEquals(1, mCm.getAllNetworks().length); 793 assertEquals(mCm.getAllNetworks()[0], mCm.getActiveNetwork()); 794 // Test WiFi disconnect. 795 cv = waitForConnectivityBroadcasts(1); 796 mWiFiNetworkAgent.disconnect(); 797 waitFor(cv); 798 verifyNoNetwork(); 799 } 800 801 @LargeTest 802 public void testValidatedCellularOutscoresUnvalidatedWiFi() throws Exception { 803 // Test bringing up unvalidated WiFi 804 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 805 ConditionVariable cv = waitForConnectivityBroadcasts(1); 806 mWiFiNetworkAgent.connect(false); 807 waitFor(cv); 808 verifyActiveNetwork(TRANSPORT_WIFI); 809 // Test bringing up unvalidated cellular 810 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); 811 mCellNetworkAgent.connect(false); 812 mService.waitForIdle(); 813 verifyActiveNetwork(TRANSPORT_WIFI); 814 // Test cellular disconnect. 815 mCellNetworkAgent.disconnect(); 816 mService.waitForIdle(); 817 verifyActiveNetwork(TRANSPORT_WIFI); 818 // Test bringing up validated cellular 819 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); 820 cv = waitForConnectivityBroadcasts(2); 821 mCellNetworkAgent.connect(true); 822 waitFor(cv); 823 verifyActiveNetwork(TRANSPORT_CELLULAR); 824 // Test cellular disconnect. 825 cv = waitForConnectivityBroadcasts(2); 826 mCellNetworkAgent.disconnect(); 827 waitFor(cv); 828 verifyActiveNetwork(TRANSPORT_WIFI); 829 // Test WiFi disconnect. 830 cv = waitForConnectivityBroadcasts(1); 831 mWiFiNetworkAgent.disconnect(); 832 waitFor(cv); 833 verifyNoNetwork(); 834 } 835 836 @LargeTest 837 public void testUnvalidatedWifiOutscoresUnvalidatedCellular() throws Exception { 838 // Test bringing up unvalidated cellular. 839 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); 840 ConditionVariable cv = waitForConnectivityBroadcasts(1); 841 mCellNetworkAgent.connect(false); 842 waitFor(cv); 843 verifyActiveNetwork(TRANSPORT_CELLULAR); 844 // Test bringing up unvalidated WiFi. 845 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 846 cv = waitForConnectivityBroadcasts(2); 847 mWiFiNetworkAgent.connect(false); 848 waitFor(cv); 849 verifyActiveNetwork(TRANSPORT_WIFI); 850 // Test WiFi disconnect. 851 cv = waitForConnectivityBroadcasts(2); 852 mWiFiNetworkAgent.disconnect(); 853 waitFor(cv); 854 verifyActiveNetwork(TRANSPORT_CELLULAR); 855 // Test cellular disconnect. 856 cv = waitForConnectivityBroadcasts(1); 857 mCellNetworkAgent.disconnect(); 858 waitFor(cv); 859 verifyNoNetwork(); 860 } 861 862 @LargeTest 863 public void testUnlingeringDoesNotValidate() throws Exception { 864 // Test bringing up unvalidated WiFi. 865 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 866 ConditionVariable cv = waitForConnectivityBroadcasts(1); 867 mWiFiNetworkAgent.connect(false); 868 waitFor(cv); 869 verifyActiveNetwork(TRANSPORT_WIFI); 870 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability( 871 NET_CAPABILITY_VALIDATED)); 872 // Test bringing up validated cellular. 873 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); 874 cv = waitForConnectivityBroadcasts(2); 875 mCellNetworkAgent.connect(true); 876 waitFor(cv); 877 verifyActiveNetwork(TRANSPORT_CELLULAR); 878 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability( 879 NET_CAPABILITY_VALIDATED)); 880 // Test cellular disconnect. 881 cv = waitForConnectivityBroadcasts(2); 882 mCellNetworkAgent.disconnect(); 883 waitFor(cv); 884 verifyActiveNetwork(TRANSPORT_WIFI); 885 // Unlingering a network should not cause it to be marked as validated. 886 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability( 887 NET_CAPABILITY_VALIDATED)); 888 } 889 890 @LargeTest 891 public void testCellularOutscoresWeakWifi() throws Exception { 892 // Test bringing up validated cellular. 893 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); 894 ConditionVariable cv = waitForConnectivityBroadcasts(1); 895 mCellNetworkAgent.connect(true); 896 waitFor(cv); 897 verifyActiveNetwork(TRANSPORT_CELLULAR); 898 // Test bringing up validated WiFi. 899 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 900 cv = waitForConnectivityBroadcasts(2); 901 mWiFiNetworkAgent.connect(true); 902 waitFor(cv); 903 verifyActiveNetwork(TRANSPORT_WIFI); 904 // Test WiFi getting really weak. 905 cv = waitForConnectivityBroadcasts(2); 906 mWiFiNetworkAgent.adjustScore(-11); 907 waitFor(cv); 908 verifyActiveNetwork(TRANSPORT_CELLULAR); 909 // Test WiFi restoring signal strength. 910 cv = waitForConnectivityBroadcasts(2); 911 mWiFiNetworkAgent.adjustScore(11); 912 waitFor(cv); 913 verifyActiveNetwork(TRANSPORT_WIFI); 914 mCellNetworkAgent.disconnect(); 915 mWiFiNetworkAgent.disconnect(); 916 } 917 918 @LargeTest 919 public void testReapingNetwork() throws Exception { 920 // Test bringing up WiFi without NET_CAPABILITY_INTERNET. 921 // Expect it to be torn down immediately because it satisfies no requests. 922 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 923 ConditionVariable cv = mWiFiNetworkAgent.getDisconnectedCV(); 924 mWiFiNetworkAgent.connectWithoutInternet(); 925 waitFor(cv); 926 // Test bringing up cellular without NET_CAPABILITY_INTERNET. 927 // Expect it to be torn down immediately because it satisfies no requests. 928 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 929 cv = mCellNetworkAgent.getDisconnectedCV(); 930 mCellNetworkAgent.connectWithoutInternet(); 931 waitFor(cv); 932 // Test bringing up validated WiFi. 933 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 934 cv = waitForConnectivityBroadcasts(1); 935 mWiFiNetworkAgent.connect(true); 936 waitFor(cv); 937 verifyActiveNetwork(TRANSPORT_WIFI); 938 // Test bringing up unvalidated cellular. 939 // Expect it to be torn down because it could never be the highest scoring network 940 // satisfying the default request even if it validated. 941 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); 942 cv = mCellNetworkAgent.getDisconnectedCV(); 943 mCellNetworkAgent.connect(false); 944 waitFor(cv); 945 verifyActiveNetwork(TRANSPORT_WIFI); 946 cv = mWiFiNetworkAgent.getDisconnectedCV(); 947 mWiFiNetworkAgent.disconnect(); 948 waitFor(cv); 949 } 950 951 @LargeTest 952 public void testCellularFallback() throws Exception { 953 // Test bringing up validated cellular. 954 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); 955 ConditionVariable cv = waitForConnectivityBroadcasts(1); 956 mCellNetworkAgent.connect(true); 957 waitFor(cv); 958 verifyActiveNetwork(TRANSPORT_CELLULAR); 959 // Test bringing up validated WiFi. 960 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 961 cv = waitForConnectivityBroadcasts(2); 962 mWiFiNetworkAgent.connect(true); 963 waitFor(cv); 964 verifyActiveNetwork(TRANSPORT_WIFI); 965 // Reevaluate WiFi (it'll instantly fail DNS). 966 cv = waitForConnectivityBroadcasts(2); 967 assertTrue(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability( 968 NET_CAPABILITY_VALIDATED)); 969 mCm.reportBadNetwork(mWiFiNetworkAgent.getNetwork()); 970 // Should quickly fall back to Cellular. 971 waitFor(cv); 972 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability( 973 NET_CAPABILITY_VALIDATED)); 974 verifyActiveNetwork(TRANSPORT_CELLULAR); 975 // Reevaluate cellular (it'll instantly fail DNS). 976 cv = waitForConnectivityBroadcasts(2); 977 assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability( 978 NET_CAPABILITY_VALIDATED)); 979 mCm.reportBadNetwork(mCellNetworkAgent.getNetwork()); 980 // Should quickly fall back to WiFi. 981 waitFor(cv); 982 assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability( 983 NET_CAPABILITY_VALIDATED)); 984 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability( 985 NET_CAPABILITY_VALIDATED)); 986 verifyActiveNetwork(TRANSPORT_WIFI); 987 mCellNetworkAgent.disconnect(); 988 mWiFiNetworkAgent.disconnect(); 989 } 990 991 @LargeTest 992 public void testWiFiFallback() throws Exception { 993 // Test bringing up unvalidated WiFi. 994 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 995 ConditionVariable cv = waitForConnectivityBroadcasts(1); 996 mWiFiNetworkAgent.connect(false); 997 waitFor(cv); 998 verifyActiveNetwork(TRANSPORT_WIFI); 999 // Test bringing up validated cellular. 1000 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); 1001 cv = waitForConnectivityBroadcasts(2); 1002 mCellNetworkAgent.connect(true); 1003 waitFor(cv); 1004 verifyActiveNetwork(TRANSPORT_CELLULAR); 1005 // Reevaluate cellular (it'll instantly fail DNS). 1006 cv = waitForConnectivityBroadcasts(2); 1007 assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability( 1008 NET_CAPABILITY_VALIDATED)); 1009 mCm.reportBadNetwork(mCellNetworkAgent.getNetwork()); 1010 // Should quickly fall back to WiFi. 1011 waitFor(cv); 1012 assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability( 1013 NET_CAPABILITY_VALIDATED)); 1014 verifyActiveNetwork(TRANSPORT_WIFI); 1015 mCellNetworkAgent.disconnect(); 1016 mWiFiNetworkAgent.disconnect(); 1017 } 1018 1019 enum CallbackState { 1020 NONE, 1021 AVAILABLE, 1022 LOSING, 1023 LOST 1024 } 1025 1026 /** 1027 * Utility NetworkCallback for testing. The caller must explicitly test for all the callbacks 1028 * this class receives, by calling expectCallback() exactly once each time a callback is 1029 * received. assertNoCallback may be called at any time. 1030 */ 1031 private class TestNetworkCallback extends NetworkCallback { 1032 private final ConditionVariable mConditionVariable = new ConditionVariable(); 1033 private CallbackState mLastCallback = CallbackState.NONE; 1034 private Network mLastNetwork; 1035 1036 public void onAvailable(Network network) { 1037 assertEquals(CallbackState.NONE, mLastCallback); 1038 mLastCallback = CallbackState.AVAILABLE; 1039 mLastNetwork = network; 1040 mConditionVariable.open(); 1041 } 1042 1043 public void onLosing(Network network, int maxMsToLive) { 1044 assertEquals(CallbackState.NONE, mLastCallback); 1045 mLastCallback = CallbackState.LOSING; 1046 mLastNetwork = network; 1047 mConditionVariable.open(); 1048 } 1049 1050 public void onLost(Network network) { 1051 assertEquals(CallbackState.NONE, mLastCallback); 1052 mLastCallback = CallbackState.LOST; 1053 mLastNetwork = network; 1054 mConditionVariable.open(); 1055 } 1056 1057 void expectCallback(CallbackState state) { 1058 expectCallback(state, null); 1059 } 1060 1061 void expectCallback(CallbackState state, MockNetworkAgent mockAgent) { 1062 waitFor(mConditionVariable); 1063 assertEquals(state, mLastCallback); 1064 if (mockAgent != null) { 1065 assertEquals(mockAgent.getNetwork(), mLastNetwork); 1066 } 1067 mLastCallback = CallbackState.NONE; 1068 mLastNetwork = null; 1069 mConditionVariable.close(); 1070 } 1071 1072 void assertNoCallback() { 1073 assertEquals(CallbackState.NONE, mLastCallback); 1074 } 1075 } 1076 1077 @LargeTest 1078 public void testStateChangeNetworkCallbacks() throws Exception { 1079 final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback(); 1080 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback(); 1081 final NetworkRequest wifiRequest = new NetworkRequest.Builder() 1082 .addTransportType(TRANSPORT_WIFI).build(); 1083 final NetworkRequest cellRequest = new NetworkRequest.Builder() 1084 .addTransportType(TRANSPORT_CELLULAR).build(); 1085 mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback); 1086 mCm.registerNetworkCallback(cellRequest, cellNetworkCallback); 1087 1088 // Test unvalidated networks 1089 ConditionVariable cv = waitForConnectivityBroadcasts(1); 1090 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); 1091 mCellNetworkAgent.connect(false); 1092 cellNetworkCallback.expectCallback(CallbackState.AVAILABLE); 1093 wifiNetworkCallback.assertNoCallback(); 1094 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 1095 waitFor(cv); 1096 1097 // This should not trigger spurious onAvailable() callbacks, b/21762680. 1098 mCellNetworkAgent.adjustScore(-1); 1099 mService.waitForIdle(); 1100 wifiNetworkCallback.assertNoCallback(); 1101 cellNetworkCallback.assertNoCallback(); 1102 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 1103 1104 cv = waitForConnectivityBroadcasts(2); 1105 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 1106 mWiFiNetworkAgent.connect(false); 1107 wifiNetworkCallback.expectCallback(CallbackState.AVAILABLE); 1108 cellNetworkCallback.assertNoCallback(); 1109 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 1110 waitFor(cv); 1111 1112 cv = waitForConnectivityBroadcasts(2); 1113 mWiFiNetworkAgent.disconnect(); 1114 wifiNetworkCallback.expectCallback(CallbackState.LOST); 1115 cellNetworkCallback.assertNoCallback(); 1116 waitFor(cv); 1117 1118 cv = waitForConnectivityBroadcasts(1); 1119 mCellNetworkAgent.disconnect(); 1120 cellNetworkCallback.expectCallback(CallbackState.LOST); 1121 wifiNetworkCallback.assertNoCallback(); 1122 waitFor(cv); 1123 1124 // Test validated networks 1125 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); 1126 mCellNetworkAgent.connect(true); 1127 cellNetworkCallback.expectCallback(CallbackState.AVAILABLE); 1128 wifiNetworkCallback.assertNoCallback(); 1129 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 1130 1131 // This should not trigger spurious onAvailable() callbacks, b/21762680. 1132 mCellNetworkAgent.adjustScore(-1); 1133 mService.waitForIdle(); 1134 wifiNetworkCallback.assertNoCallback(); 1135 cellNetworkCallback.assertNoCallback(); 1136 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 1137 1138 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 1139 mWiFiNetworkAgent.connect(true); 1140 wifiNetworkCallback.expectCallback(CallbackState.AVAILABLE); 1141 cellNetworkCallback.expectCallback(CallbackState.LOSING); 1142 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 1143 1144 mWiFiNetworkAgent.disconnect(); 1145 wifiNetworkCallback.expectCallback(CallbackState.LOST); 1146 cellNetworkCallback.assertNoCallback(); 1147 1148 mCellNetworkAgent.disconnect(); 1149 cellNetworkCallback.expectCallback(CallbackState.LOST); 1150 wifiNetworkCallback.assertNoCallback(); 1151 } 1152 1153 private void tryNetworkFactoryRequests(int capability) throws Exception { 1154 // Verify NOT_RESTRICTED is set appropriately 1155 final NetworkCapabilities nc = new NetworkRequest.Builder().addCapability(capability) 1156 .build().networkCapabilities; 1157 if (capability == NET_CAPABILITY_CBS || capability == NET_CAPABILITY_DUN || 1158 capability == NET_CAPABILITY_EIMS || capability == NET_CAPABILITY_FOTA || 1159 capability == NET_CAPABILITY_IA || capability == NET_CAPABILITY_IMS || 1160 capability == NET_CAPABILITY_RCS || capability == NET_CAPABILITY_XCAP) { 1161 assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)); 1162 } else { 1163 assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)); 1164 } 1165 1166 NetworkCapabilities filter = new NetworkCapabilities(); 1167 filter.addCapability(capability); 1168 final HandlerThread handlerThread = new HandlerThread("testNetworkFactoryRequests"); 1169 handlerThread.start(); 1170 final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(), 1171 mServiceContext, "testFactory", filter); 1172 testFactory.setScoreFilter(40); 1173 ConditionVariable cv = testFactory.getNetworkStartedCV(); 1174 testFactory.expectAddRequests(1); 1175 testFactory.register(); 1176 testFactory.waitForNetworkRequests(1); 1177 int expectedRequestCount = 1; 1178 NetworkCallback networkCallback = null; 1179 // For non-INTERNET capabilities we cannot rely on the default request being present, so 1180 // add one. 1181 if (capability != NET_CAPABILITY_INTERNET) { 1182 assertFalse(testFactory.getMyStartRequested()); 1183 NetworkRequest request = new NetworkRequest.Builder().addCapability(capability).build(); 1184 networkCallback = new NetworkCallback(); 1185 testFactory.expectAddRequests(1); 1186 mCm.requestNetwork(request, networkCallback); 1187 expectedRequestCount++; 1188 testFactory.waitForNetworkRequests(expectedRequestCount); 1189 } 1190 waitFor(cv); 1191 assertEquals(expectedRequestCount, testFactory.getMyRequestCount()); 1192 assertTrue(testFactory.getMyStartRequested()); 1193 1194 // Now bring in a higher scored network. 1195 MockNetworkAgent testAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); 1196 // Rather than create a validated network which complicates things by registering it's 1197 // own NetworkRequest during startup, just bump up the score to cancel out the 1198 // unvalidated penalty. 1199 testAgent.adjustScore(40); 1200 cv = testFactory.getNetworkStoppedCV(); 1201 1202 // When testAgent connects, ConnectivityService will re-send us all current requests with 1203 // the new score. There are expectedRequestCount such requests, and we must wait for all of 1204 // them. 1205 testFactory.expectAddRequests(expectedRequestCount); 1206 testAgent.connect(false); 1207 testAgent.addCapability(capability); 1208 waitFor(cv); 1209 testFactory.waitForNetworkRequests(expectedRequestCount); 1210 assertFalse(testFactory.getMyStartRequested()); 1211 1212 // Bring in a bunch of requests. 1213 testFactory.expectAddRequests(10); 1214 assertEquals(expectedRequestCount, testFactory.getMyRequestCount()); 1215 ConnectivityManager.NetworkCallback[] networkCallbacks = 1216 new ConnectivityManager.NetworkCallback[10]; 1217 for (int i = 0; i< networkCallbacks.length; i++) { 1218 networkCallbacks[i] = new ConnectivityManager.NetworkCallback(); 1219 NetworkRequest.Builder builder = new NetworkRequest.Builder(); 1220 builder.addCapability(capability); 1221 mCm.requestNetwork(builder.build(), networkCallbacks[i]); 1222 } 1223 testFactory.waitForNetworkRequests(10 + expectedRequestCount); 1224 assertFalse(testFactory.getMyStartRequested()); 1225 1226 // Remove the requests. 1227 testFactory.expectRemoveRequests(10); 1228 for (int i = 0; i < networkCallbacks.length; i++) { 1229 mCm.unregisterNetworkCallback(networkCallbacks[i]); 1230 } 1231 testFactory.waitForNetworkRequests(expectedRequestCount); 1232 assertFalse(testFactory.getMyStartRequested()); 1233 1234 // Drop the higher scored network. 1235 cv = testFactory.getNetworkStartedCV(); 1236 testAgent.disconnect(); 1237 waitFor(cv); 1238 assertEquals(expectedRequestCount, testFactory.getMyRequestCount()); 1239 assertTrue(testFactory.getMyStartRequested()); 1240 1241 testFactory.unregister(); 1242 if (networkCallback != null) mCm.unregisterNetworkCallback(networkCallback); 1243 handlerThread.quit(); 1244 } 1245 1246 @LargeTest 1247 public void testNetworkFactoryRequests() throws Exception { 1248 tryNetworkFactoryRequests(NET_CAPABILITY_MMS); 1249 tryNetworkFactoryRequests(NET_CAPABILITY_SUPL); 1250 tryNetworkFactoryRequests(NET_CAPABILITY_DUN); 1251 tryNetworkFactoryRequests(NET_CAPABILITY_FOTA); 1252 tryNetworkFactoryRequests(NET_CAPABILITY_IMS); 1253 tryNetworkFactoryRequests(NET_CAPABILITY_CBS); 1254 tryNetworkFactoryRequests(NET_CAPABILITY_WIFI_P2P); 1255 tryNetworkFactoryRequests(NET_CAPABILITY_IA); 1256 tryNetworkFactoryRequests(NET_CAPABILITY_RCS); 1257 tryNetworkFactoryRequests(NET_CAPABILITY_XCAP); 1258 tryNetworkFactoryRequests(NET_CAPABILITY_EIMS); 1259 tryNetworkFactoryRequests(NET_CAPABILITY_NOT_METERED); 1260 tryNetworkFactoryRequests(NET_CAPABILITY_INTERNET); 1261 tryNetworkFactoryRequests(NET_CAPABILITY_TRUSTED); 1262 tryNetworkFactoryRequests(NET_CAPABILITY_NOT_VPN); 1263 // Skipping VALIDATED and CAPTIVE_PORTAL as they're disallowed. 1264 } 1265 1266 @LargeTest 1267 public void testNoMutableNetworkRequests() throws Exception { 1268 PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, new Intent("a"), 0); 1269 NetworkRequest.Builder builder = new NetworkRequest.Builder(); 1270 builder.addCapability(NET_CAPABILITY_VALIDATED); 1271 try { 1272 mCm.requestNetwork(builder.build(), new NetworkCallback()); 1273 fail(); 1274 } catch (IllegalArgumentException expected) {} 1275 try { 1276 mCm.requestNetwork(builder.build(), pendingIntent); 1277 fail(); 1278 } catch (IllegalArgumentException expected) {} 1279 builder = new NetworkRequest.Builder(); 1280 builder.addCapability(NET_CAPABILITY_CAPTIVE_PORTAL); 1281 try { 1282 mCm.requestNetwork(builder.build(), new NetworkCallback()); 1283 fail(); 1284 } catch (IllegalArgumentException expected) {} 1285 try { 1286 mCm.requestNetwork(builder.build(), pendingIntent); 1287 fail(); 1288 } catch (IllegalArgumentException expected) {} 1289 } 1290 1291 @LargeTest 1292 public void testMMSonWiFi() throws Exception { 1293 // Test bringing up cellular without MMS NetworkRequest gets reaped 1294 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); 1295 mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS); 1296 ConditionVariable cv = mCellNetworkAgent.getDisconnectedCV(); 1297 mCellNetworkAgent.connectWithoutInternet(); 1298 waitFor(cv); 1299 waitFor(new Criteria() { 1300 public boolean get() { return mCm.getAllNetworks().length == 0; } }); 1301 verifyNoNetwork(); 1302 // Test bringing up validated WiFi. 1303 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 1304 cv = waitForConnectivityBroadcasts(1); 1305 mWiFiNetworkAgent.connect(true); 1306 waitFor(cv); 1307 verifyActiveNetwork(TRANSPORT_WIFI); 1308 // Register MMS NetworkRequest 1309 NetworkRequest.Builder builder = new NetworkRequest.Builder(); 1310 builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS); 1311 final TestNetworkCallback networkCallback = new TestNetworkCallback(); 1312 mCm.requestNetwork(builder.build(), networkCallback); 1313 // Test bringing up unvalidated cellular with MMS 1314 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); 1315 mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS); 1316 mCellNetworkAgent.connectWithoutInternet(); 1317 networkCallback.expectCallback(CallbackState.AVAILABLE); 1318 verifyActiveNetwork(TRANSPORT_WIFI); 1319 // Test releasing NetworkRequest disconnects cellular with MMS 1320 cv = mCellNetworkAgent.getDisconnectedCV(); 1321 mCm.unregisterNetworkCallback(networkCallback); 1322 waitFor(cv); 1323 verifyActiveNetwork(TRANSPORT_WIFI); 1324 } 1325 1326 @LargeTest 1327 public void testMMSonCell() throws Exception { 1328 // Test bringing up cellular without MMS 1329 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); 1330 ConditionVariable cv = waitForConnectivityBroadcasts(1); 1331 mCellNetworkAgent.connect(false); 1332 waitFor(cv); 1333 verifyActiveNetwork(TRANSPORT_CELLULAR); 1334 // Register MMS NetworkRequest 1335 NetworkRequest.Builder builder = new NetworkRequest.Builder(); 1336 builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS); 1337 final TestNetworkCallback networkCallback = new TestNetworkCallback(); 1338 mCm.requestNetwork(builder.build(), networkCallback); 1339 // Test bringing up MMS cellular network 1340 MockNetworkAgent mmsNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); 1341 mmsNetworkAgent.addCapability(NET_CAPABILITY_MMS); 1342 mmsNetworkAgent.connectWithoutInternet(); 1343 networkCallback.expectCallback(CallbackState.AVAILABLE); 1344 verifyActiveNetwork(TRANSPORT_CELLULAR); 1345 // Test releasing MMS NetworkRequest does not disconnect main cellular NetworkAgent 1346 cv = mmsNetworkAgent.getDisconnectedCV(); 1347 mCm.unregisterNetworkCallback(networkCallback); 1348 waitFor(cv); 1349 verifyActiveNetwork(TRANSPORT_CELLULAR); 1350 } 1351 1352 @LargeTest 1353 public void testCaptivePortal() { 1354 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback(); 1355 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder() 1356 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build(); 1357 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback); 1358 1359 final TestNetworkCallback validatedCallback = new TestNetworkCallback(); 1360 final NetworkRequest validatedRequest = new NetworkRequest.Builder() 1361 .addCapability(NET_CAPABILITY_VALIDATED).build(); 1362 mCm.registerNetworkCallback(validatedRequest, validatedCallback); 1363 1364 // Bring up a network with a captive portal. 1365 // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL. 1366 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 1367 String firstRedirectUrl = "http://example.com/firstPath"; 1368 mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl); 1369 captivePortalCallback.expectCallback(CallbackState.AVAILABLE); 1370 assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), firstRedirectUrl); 1371 1372 // Take down network. 1373 // Expect onLost callback. 1374 mWiFiNetworkAgent.disconnect(); 1375 captivePortalCallback.expectCallback(CallbackState.LOST); 1376 1377 // Bring up a network with a captive portal. 1378 // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL. 1379 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 1380 String secondRedirectUrl = "http://example.com/secondPath"; 1381 mWiFiNetworkAgent.connectWithCaptivePortal(secondRedirectUrl); 1382 captivePortalCallback.expectCallback(CallbackState.AVAILABLE); 1383 assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), secondRedirectUrl); 1384 1385 // Make captive portal disappear then revalidate. 1386 // Expect onLost callback because network no longer provides NET_CAPABILITY_CAPTIVE_PORTAL. 1387 mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 204; 1388 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true); 1389 captivePortalCallback.expectCallback(CallbackState.LOST); 1390 1391 // Expect NET_CAPABILITY_VALIDATED onAvailable callback. 1392 validatedCallback.expectCallback(CallbackState.AVAILABLE); 1393 1394 // Break network connectivity. 1395 // Expect NET_CAPABILITY_VALIDATED onLost callback. 1396 mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 500; 1397 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), false); 1398 validatedCallback.expectCallback(CallbackState.LOST); 1399 } 1400 1401 @SmallTest 1402 public void testInvalidNetworkSpecifier() { 1403 boolean execptionCalled = true; 1404 1405 try { 1406 NetworkRequest.Builder builder = new NetworkRequest.Builder(); 1407 builder.setNetworkSpecifier(MATCH_ALL_REQUESTS_NETWORK_SPECIFIER); 1408 execptionCalled = false; 1409 } catch (IllegalArgumentException e) { 1410 // do nothing - should get here 1411 } 1412 1413 assertTrue("NetworkReqeuest builder with MATCH_ALL_REQUESTS_NETWORK_SPECIFIER", 1414 execptionCalled); 1415 1416 try { 1417 NetworkCapabilities networkCapabilities = new NetworkCapabilities(); 1418 networkCapabilities.addTransportType(TRANSPORT_WIFI) 1419 .setNetworkSpecifier(NetworkCapabilities.MATCH_ALL_REQUESTS_NETWORK_SPECIFIER); 1420 mService.requestNetwork(networkCapabilities, null, 0, null, 1421 ConnectivityManager.TYPE_WIFI); 1422 execptionCalled = false; 1423 } catch (IllegalArgumentException e) { 1424 // do nothing - should get here 1425 } 1426 1427 assertTrue("ConnectivityService requestNetwork with MATCH_ALL_REQUESTS_NETWORK_SPECIFIER", 1428 execptionCalled); 1429 } 1430 1431 @LargeTest 1432 public void testRegisterDefaultNetworkCallback() throws Exception { 1433 final TestNetworkCallback defaultNetworkCallback = new TestNetworkCallback(); 1434 mCm.registerDefaultNetworkCallback(defaultNetworkCallback); 1435 defaultNetworkCallback.assertNoCallback(); 1436 1437 // Create a TRANSPORT_CELLULAR request to keep the mobile interface up 1438 // whenever Wi-Fi is up. Without this, the mobile network agent is 1439 // reaped before any other activity can take place. 1440 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback(); 1441 final NetworkRequest cellRequest = new NetworkRequest.Builder() 1442 .addTransportType(TRANSPORT_CELLULAR).build(); 1443 mCm.requestNetwork(cellRequest, cellNetworkCallback); 1444 cellNetworkCallback.assertNoCallback(); 1445 1446 // Bring up cell and expect CALLBACK_AVAILABLE. 1447 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); 1448 mCellNetworkAgent.connect(true); 1449 cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent); 1450 defaultNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent); 1451 1452 // Bring up wifi and expect CALLBACK_AVAILABLE. 1453 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 1454 mWiFiNetworkAgent.connect(true); 1455 cellNetworkCallback.assertNoCallback(); 1456 defaultNetworkCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent); 1457 1458 // Bring down cell. Expect no default network callback, since it wasn't the default. 1459 mCellNetworkAgent.disconnect(); 1460 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent); 1461 defaultNetworkCallback.assertNoCallback(); 1462 1463 // Bring up cell. Expect no default network callback, since it won't be the default. 1464 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); 1465 mCellNetworkAgent.connect(true); 1466 cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent); 1467 defaultNetworkCallback.assertNoCallback(); 1468 1469 // Bring down wifi. Expect the default network callback to notified of LOST wifi 1470 // followed by AVAILABLE cell. 1471 mWiFiNetworkAgent.disconnect(); 1472 cellNetworkCallback.assertNoCallback(); 1473 defaultNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); 1474 defaultNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent); 1475 mCellNetworkAgent.disconnect(); 1476 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent); 1477 defaultNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent); 1478 } 1479 1480 private static class TestKeepaliveCallback extends PacketKeepaliveCallback { 1481 1482 public static enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR }; 1483 1484 private class CallbackValue { 1485 public CallbackType callbackType; 1486 public int error; 1487 1488 public CallbackValue(CallbackType type) { 1489 this.callbackType = type; 1490 this.error = PacketKeepalive.SUCCESS; 1491 assertTrue("onError callback must have error", type != CallbackType.ON_ERROR); 1492 } 1493 1494 public CallbackValue(CallbackType type, int error) { 1495 this.callbackType = type; 1496 this.error = error; 1497 assertEquals("error can only be set for onError", type, CallbackType.ON_ERROR); 1498 } 1499 1500 @Override 1501 public boolean equals(Object o) { 1502 return o instanceof CallbackValue && 1503 this.callbackType == ((CallbackValue) o).callbackType && 1504 this.error == ((CallbackValue) o).error; 1505 } 1506 1507 @Override 1508 public String toString() { 1509 return String.format("%s(%s, %d)", getClass().getSimpleName(), callbackType, error); 1510 } 1511 } 1512 1513 private LinkedBlockingQueue<CallbackValue> mCallbacks = new LinkedBlockingQueue<>(); 1514 1515 @Override 1516 public void onStarted() { 1517 mCallbacks.add(new CallbackValue(CallbackType.ON_STARTED)); 1518 } 1519 1520 @Override 1521 public void onStopped() { 1522 mCallbacks.add(new CallbackValue(CallbackType.ON_STOPPED)); 1523 } 1524 1525 @Override 1526 public void onError(int error) { 1527 mCallbacks.add(new CallbackValue(CallbackType.ON_ERROR, error)); 1528 } 1529 1530 private void expectCallback(CallbackValue callbackValue) { 1531 try { 1532 assertEquals( 1533 callbackValue, 1534 mCallbacks.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS)); 1535 } catch (InterruptedException e) { 1536 fail(callbackValue.callbackType + " callback not seen after " + TIMEOUT_MS + " ms"); 1537 } 1538 } 1539 1540 public void expectStarted() { 1541 expectCallback(new CallbackValue(CallbackType.ON_STARTED)); 1542 } 1543 1544 public void expectStopped() { 1545 expectCallback(new CallbackValue(CallbackType.ON_STOPPED)); 1546 } 1547 1548 public void expectError(int error) { 1549 expectCallback(new CallbackValue(CallbackType.ON_ERROR, error)); 1550 } 1551 } 1552 1553 private Network connectKeepaliveNetwork(LinkProperties lp) { 1554 // Ensure the network is disconnected before we do anything. 1555 if (mWiFiNetworkAgent != null) { 1556 assertNull(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork())); 1557 } 1558 1559 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 1560 ConditionVariable cv = waitForConnectivityBroadcasts(1); 1561 mWiFiNetworkAgent.connect(true); 1562 waitFor(cv); 1563 verifyActiveNetwork(TRANSPORT_WIFI); 1564 mWiFiNetworkAgent.sendLinkProperties(lp); 1565 mService.waitForIdle(); 1566 return mWiFiNetworkAgent.getNetwork(); 1567 } 1568 1569 public void testPacketKeepalives() throws Exception { 1570 InetAddress myIPv4 = InetAddress.getByName("192.0.2.129"); 1571 InetAddress notMyIPv4 = InetAddress.getByName("192.0.2.35"); 1572 InetAddress myIPv6 = InetAddress.getByName("2001:db8::1"); 1573 InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8"); 1574 InetAddress dstIPv6 = InetAddress.getByName("2001:4860:4860::8888"); 1575 1576 LinkProperties lp = new LinkProperties(); 1577 lp.setInterfaceName("wlan12"); 1578 lp.addLinkAddress(new LinkAddress(myIPv6, 64)); 1579 lp.addLinkAddress(new LinkAddress(myIPv4, 25)); 1580 lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234"))); 1581 lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254"))); 1582 1583 Network notMyNet = new Network(61234); 1584 Network myNet = connectKeepaliveNetwork(lp); 1585 1586 TestKeepaliveCallback callback = new TestKeepaliveCallback(); 1587 PacketKeepalive ka; 1588 1589 // Attempt to start keepalives with invalid parameters and check for errors. 1590 ka = mCm.startNattKeepalive(notMyNet, 25, callback, myIPv4, 1234, dstIPv4); 1591 callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK); 1592 1593 ka = mCm.startNattKeepalive(myNet, 19, callback, notMyIPv4, 1234, dstIPv4); 1594 callback.expectError(PacketKeepalive.ERROR_INVALID_INTERVAL); 1595 1596 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 1234, dstIPv6); 1597 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS); 1598 1599 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv6, 1234, dstIPv4); 1600 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS); 1601 1602 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv6, 1234, dstIPv6); 1603 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS); // NAT-T is IPv4-only. 1604 1605 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 123456, dstIPv4); 1606 callback.expectError(PacketKeepalive.ERROR_INVALID_PORT); 1607 1608 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 123456, dstIPv4); 1609 callback.expectError(PacketKeepalive.ERROR_INVALID_PORT); 1610 1611 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4); 1612 callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED); 1613 1614 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4); 1615 callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED); 1616 1617 // Check that a started keepalive can be stopped. 1618 mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS); 1619 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4); 1620 callback.expectStarted(); 1621 mWiFiNetworkAgent.setStopKeepaliveError(PacketKeepalive.SUCCESS); 1622 ka.stop(); 1623 callback.expectStopped(); 1624 1625 // Check that deleting the IP address stops the keepalive. 1626 LinkProperties bogusLp = new LinkProperties(lp); 1627 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4); 1628 callback.expectStarted(); 1629 bogusLp.removeLinkAddress(new LinkAddress(myIPv4, 25)); 1630 bogusLp.addLinkAddress(new LinkAddress(notMyIPv4, 25)); 1631 mWiFiNetworkAgent.sendLinkProperties(bogusLp); 1632 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS); 1633 mWiFiNetworkAgent.sendLinkProperties(lp); 1634 1635 // Check that a started keepalive is stopped correctly when the network disconnects. 1636 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4); 1637 callback.expectStarted(); 1638 mWiFiNetworkAgent.disconnect(); 1639 callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK); 1640 1641 // ... and that stopping it after that has no adverse effects. 1642 assertNull(mCm.getNetworkCapabilities(myNet)); 1643 ka.stop(); 1644 1645 // Reconnect. 1646 myNet = connectKeepaliveNetwork(lp); 1647 mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS); 1648 1649 // Check things work as expected when the keepalive is stopped and the network disconnects. 1650 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4); 1651 callback.expectStarted(); 1652 ka.stop(); 1653 mWiFiNetworkAgent.disconnect(); 1654 mService.waitForIdle(); 1655 callback.expectStopped(); 1656 1657 // Reconnect. 1658 myNet = connectKeepaliveNetwork(lp); 1659 mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS); 1660 1661 // Check that keepalive slots start from 1 and increment. The first one gets slot 1. 1662 mWiFiNetworkAgent.setExpectedKeepaliveSlot(1); 1663 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4); 1664 callback.expectStarted(); 1665 1666 // The second one gets slot 2. 1667 mWiFiNetworkAgent.setExpectedKeepaliveSlot(2); 1668 TestKeepaliveCallback callback2 = new TestKeepaliveCallback(); 1669 PacketKeepalive ka2 = mCm.startNattKeepalive(myNet, 25, callback2, myIPv4, 6789, dstIPv4); 1670 callback2.expectStarted(); 1671 1672 // Now stop the first one and create a third. This also gets slot 1. 1673 ka.stop(); 1674 callback.expectStopped(); 1675 1676 mWiFiNetworkAgent.setExpectedKeepaliveSlot(1); 1677 TestKeepaliveCallback callback3 = new TestKeepaliveCallback(); 1678 PacketKeepalive ka3 = mCm.startNattKeepalive(myNet, 25, callback3, myIPv4, 9876, dstIPv4); 1679 callback3.expectStarted(); 1680 1681 ka2.stop(); 1682 callback2.expectStopped(); 1683 1684 ka3.stop(); 1685 callback3.expectStopped(); 1686 } 1687 1688 @SmallTest 1689 public void testGetCaptivePortalServerUrl() throws Exception { 1690 String url = mCm.getCaptivePortalServerUrl(); 1691 assertEquals("http://connectivitycheck.gstatic.com/generate_204", url); 1692 } 1693 1694 private static class TestNetworkPinner extends NetworkPinner { 1695 public static boolean awaitPin(int timeoutMs) { 1696 synchronized(sLock) { 1697 if (sNetwork == null) { 1698 try { 1699 sLock.wait(timeoutMs); 1700 } catch (InterruptedException e) {} 1701 } 1702 return sNetwork != null; 1703 } 1704 } 1705 1706 public static boolean awaitUnpin(int timeoutMs) { 1707 synchronized(sLock) { 1708 if (sNetwork != null) { 1709 try { 1710 sLock.wait(timeoutMs); 1711 } catch (InterruptedException e) {} 1712 } 1713 return sNetwork == null; 1714 } 1715 } 1716 } 1717 1718 private void assertPinnedToWifiWithCellDefault() { 1719 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess()); 1720 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 1721 } 1722 1723 private void assertPinnedToWifiWithWifiDefault() { 1724 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess()); 1725 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 1726 } 1727 1728 private void assertNotPinnedToWifi() { 1729 assertNull(mCm.getBoundNetworkForProcess()); 1730 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 1731 } 1732 1733 @SmallTest 1734 public void testNetworkPinner() { 1735 NetworkRequest wifiRequest = new NetworkRequest.Builder() 1736 .addTransportType(TRANSPORT_WIFI) 1737 .build(); 1738 assertNull(mCm.getBoundNetworkForProcess()); 1739 1740 TestNetworkPinner.pin(mServiceContext, wifiRequest); 1741 assertNull(mCm.getBoundNetworkForProcess()); 1742 1743 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); 1744 mCellNetworkAgent.connect(true); 1745 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 1746 mWiFiNetworkAgent.connect(false); 1747 1748 // When wi-fi connects, expect to be pinned. 1749 assertTrue(TestNetworkPinner.awaitPin(100)); 1750 assertPinnedToWifiWithCellDefault(); 1751 1752 // Disconnect and expect the pin to drop. 1753 mWiFiNetworkAgent.disconnect(); 1754 assertTrue(TestNetworkPinner.awaitUnpin(100)); 1755 assertNotPinnedToWifi(); 1756 1757 // Reconnecting does not cause the pin to come back. 1758 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 1759 mWiFiNetworkAgent.connect(false); 1760 assertFalse(TestNetworkPinner.awaitPin(100)); 1761 assertNotPinnedToWifi(); 1762 1763 // Pinning while connected causes the pin to take effect immediately. 1764 TestNetworkPinner.pin(mServiceContext, wifiRequest); 1765 assertTrue(TestNetworkPinner.awaitPin(100)); 1766 assertPinnedToWifiWithCellDefault(); 1767 1768 // Explicitly unpin and expect to use the default network again. 1769 TestNetworkPinner.unpin(); 1770 assertNotPinnedToWifi(); 1771 1772 // Disconnect cell and wifi. 1773 ConditionVariable cv = waitForConnectivityBroadcasts(3); // cell down, wifi up, wifi down. 1774 mCellNetworkAgent.disconnect(); 1775 mWiFiNetworkAgent.disconnect(); 1776 waitFor(cv); 1777 1778 // Pinning takes effect even if the pinned network is the default when the pin is set... 1779 TestNetworkPinner.pin(mServiceContext, wifiRequest); 1780 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 1781 mWiFiNetworkAgent.connect(false); 1782 assertTrue(TestNetworkPinner.awaitPin(100)); 1783 assertPinnedToWifiWithWifiDefault(); 1784 1785 // ... and is maintained even when that network is no longer the default. 1786 cv = waitForConnectivityBroadcasts(1); 1787 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 1788 mCellNetworkAgent.connect(true); 1789 waitFor(cv); 1790 assertPinnedToWifiWithCellDefault(); 1791 } 1792 1793 @SmallTest 1794 public void testNetworkRequestMaximum() { 1795 final int MAX_REQUESTS = 100; 1796 // Test that the limit is enforced when MAX_REQUESTS simultaneous requests are added. 1797 NetworkRequest networkRequest = new NetworkRequest.Builder().build(); 1798 ArrayList<NetworkCallback> networkCallbacks = new ArrayList<NetworkCallback>(); 1799 try { 1800 for (int i = 0; i < MAX_REQUESTS; i++) { 1801 NetworkCallback networkCallback = new NetworkCallback(); 1802 mCm.requestNetwork(networkRequest, networkCallback); 1803 networkCallbacks.add(networkCallback); 1804 } 1805 fail("Registering " + MAX_REQUESTS + " NetworkRequests did not throw exception"); 1806 } catch (IllegalArgumentException expected) {} 1807 for (NetworkCallback networkCallback : networkCallbacks) { 1808 mCm.unregisterNetworkCallback(networkCallback); 1809 } 1810 networkCallbacks.clear(); 1811 1812 try { 1813 for (int i = 0; i < MAX_REQUESTS; i++) { 1814 NetworkCallback networkCallback = new NetworkCallback(); 1815 mCm.registerNetworkCallback(networkRequest, networkCallback); 1816 networkCallbacks.add(networkCallback); 1817 } 1818 fail("Registering " + MAX_REQUESTS + " NetworkCallbacks did not throw exception"); 1819 } catch (IllegalArgumentException expected) {} 1820 for (NetworkCallback networkCallback : networkCallbacks) { 1821 mCm.unregisterNetworkCallback(networkCallback); 1822 } 1823 networkCallbacks.clear(); 1824 1825 ArrayList<PendingIntent> pendingIntents = new ArrayList<PendingIntent>(); 1826 try { 1827 for (int i = 0; i < MAX_REQUESTS + 1; i++) { 1828 PendingIntent pendingIntent = 1829 PendingIntent.getBroadcast(mContext, 0, new Intent("a" + i), 0); 1830 mCm.requestNetwork(networkRequest, pendingIntent); 1831 pendingIntents.add(pendingIntent); 1832 } 1833 fail("Registering " + MAX_REQUESTS + 1834 " PendingIntent NetworkRequests did not throw exception"); 1835 } catch (IllegalArgumentException expected) {} 1836 for (PendingIntent pendingIntent : pendingIntents) { 1837 mCm.unregisterNetworkCallback(pendingIntent); 1838 } 1839 pendingIntents.clear(); 1840 1841 try { 1842 for (int i = 0; i < MAX_REQUESTS + 1; i++) { 1843 PendingIntent pendingIntent = 1844 PendingIntent.getBroadcast(mContext, 0, new Intent("a" + i), 0); 1845 mCm.registerNetworkCallback(networkRequest, pendingIntent); 1846 pendingIntents.add(pendingIntent); 1847 } 1848 fail("Registering " + MAX_REQUESTS + 1849 " PendingIntent NetworkCallbacks did not throw exception"); 1850 } catch (IllegalArgumentException expected) {} 1851 for (PendingIntent pendingIntent : pendingIntents) { 1852 mCm.unregisterNetworkCallback(pendingIntent); 1853 } 1854 pendingIntents.clear(); 1855 mService.waitForIdle(5000); 1856 1857 // Test that the limit is not hit when MAX_REQUESTS requests are added and removed. 1858 for (int i = 0; i < MAX_REQUESTS; i++) { 1859 NetworkCallback networkCallback = new NetworkCallback(); 1860 mCm.requestNetwork(networkRequest, networkCallback); 1861 mCm.unregisterNetworkCallback(networkCallback); 1862 } 1863 mService.waitForIdle(); 1864 for (int i = 0; i < MAX_REQUESTS; i++) { 1865 NetworkCallback networkCallback = new NetworkCallback(); 1866 mCm.registerNetworkCallback(networkRequest, networkCallback); 1867 mCm.unregisterNetworkCallback(networkCallback); 1868 } 1869 mService.waitForIdle(); 1870 for (int i = 0; i < MAX_REQUESTS; i++) { 1871 PendingIntent pendingIntent = 1872 PendingIntent.getBroadcast(mContext, 0, new Intent("b" + i), 0); 1873 mCm.requestNetwork(networkRequest, pendingIntent); 1874 mCm.unregisterNetworkCallback(pendingIntent); 1875 } 1876 mService.waitForIdle(); 1877 for (int i = 0; i < MAX_REQUESTS; i++) { 1878 PendingIntent pendingIntent = 1879 PendingIntent.getBroadcast(mContext, 0, new Intent("c" + i), 0); 1880 mCm.registerNetworkCallback(networkRequest, pendingIntent); 1881 mCm.unregisterNetworkCallback(pendingIntent); 1882 } 1883 } 1884} 1885