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.INetworkManagementService; 56import android.os.Looper; 57import android.os.Message; 58import android.os.MessageQueue; 59import android.os.MessageQueue.IdleHandler; 60import android.test.AndroidTestCase; 61import android.test.suitebuilder.annotation.LargeTest; 62import android.util.Log; 63import android.util.LogPrinter; 64 65import com.android.server.connectivity.NetworkAgentInfo; 66import com.android.server.connectivity.NetworkMonitor; 67 68import java.net.InetAddress; 69import java.util.concurrent.CountDownLatch; 70import java.util.concurrent.LinkedBlockingQueue; 71import java.util.concurrent.TimeUnit; 72import java.util.concurrent.atomic.AtomicBoolean; 73 74/** 75 * Tests for {@link ConnectivityService}. 76 * 77 * Build, install and run with: 78 * runtest frameworks-services -c com.android.server.ConnectivityServiceTest 79 */ 80public class ConnectivityServiceTest extends AndroidTestCase { 81 private static final String TAG = "ConnectivityServiceTest"; 82 83 private static final int TIMEOUT_MS = 500; 84 85 private BroadcastInterceptingContext mServiceContext; 86 private WrappedConnectivityService mService; 87 private ConnectivityManager mCm; 88 private MockNetworkAgent mWiFiNetworkAgent; 89 private MockNetworkAgent mCellNetworkAgent; 90 91 private class MockContext extends BroadcastInterceptingContext { 92 MockContext(Context base) { 93 super(base); 94 } 95 96 @Override 97 public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) { 98 // PendingIntents sent by the AlarmManager are not intercepted by 99 // BroadcastInterceptingContext so we must really register the receiver. 100 // This shouldn't effect the real NetworkMonitors as the action contains a random token. 101 if (filter.getAction(0).startsWith("android.net.netmon.lingerExpired")) { 102 return getBaseContext().registerReceiver(receiver, filter); 103 } else { 104 return super.registerReceiver(receiver, filter); 105 } 106 } 107 108 @Override 109 public Object getSystemService (String name) { 110 if (name == Context.CONNECTIVITY_SERVICE) return mCm; 111 return super.getSystemService(name); 112 } 113 } 114 115 /** 116 * A subclass of HandlerThread that allows callers to wait for it to become idle. waitForIdle 117 * will return immediately if the handler is already idle. 118 */ 119 private class IdleableHandlerThread extends HandlerThread { 120 private IdleHandler mIdleHandler; 121 122 public IdleableHandlerThread(String name) { 123 super(name); 124 } 125 126 public void waitForIdle(int timeoutMs) { 127 final ConditionVariable cv = new ConditionVariable(); 128 final MessageQueue queue = getLooper().getQueue(); 129 130 synchronized (queue) { 131 if (queue.isIdle()) { 132 return; 133 } 134 135 assertNull("BUG: only one idle handler allowed", mIdleHandler); 136 mIdleHandler = new IdleHandler() { 137 public boolean queueIdle() { 138 cv.open(); 139 mIdleHandler = null; 140 return false; // Remove the handler. 141 } 142 }; 143 queue.addIdleHandler(mIdleHandler); 144 } 145 146 if (!cv.block(timeoutMs)) { 147 fail("HandlerThread " + getName() + 148 " did not become idle after " + timeoutMs + " ms"); 149 queue.removeIdleHandler(mIdleHandler); 150 } 151 } 152 } 153 154 // Tests that IdleableHandlerThread works as expected. 155 public void testIdleableHandlerThread() { 156 final int attempts = 50; // Causes the test to take about 200ms on bullhead-eng. 157 158 // Tests that waitForIdle returns immediately if the service is already idle. 159 for (int i = 0; i < attempts; i++) { 160 mService.waitForIdle(); 161 } 162 163 // Bring up a network that we can use to send messages to ConnectivityService. 164 ConditionVariable cv = waitForConnectivityBroadcasts(1); 165 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 166 mWiFiNetworkAgent.connect(false); 167 waitFor(cv); 168 Network n = mWiFiNetworkAgent.getNetwork(); 169 assertNotNull(n); 170 171 // Tests that calling waitForIdle waits for messages to be processed. 172 for (int i = 0; i < attempts; i++) { 173 mWiFiNetworkAgent.setSignalStrength(i); 174 mService.waitForIdle(); 175 assertEquals(i, mCm.getNetworkCapabilities(n).getSignalStrength()); 176 } 177 178 // Ensure that not calling waitForIdle causes a race condition. 179 for (int i = 0; i < attempts; i++) { 180 mWiFiNetworkAgent.setSignalStrength(i); 181 if (i != mCm.getNetworkCapabilities(n).getSignalStrength()) { 182 // We hit a race condition, as expected. Pass the test. 183 return; 184 } 185 } 186 187 // No race? There is a bug in this test. 188 fail("expected race condition at least once in " + attempts + " attempts"); 189 } 190 191 private class MockNetworkAgent { 192 private final WrappedNetworkMonitor mWrappedNetworkMonitor; 193 private final NetworkInfo mNetworkInfo; 194 private final NetworkCapabilities mNetworkCapabilities; 195 private final IdleableHandlerThread mHandlerThread; 196 private final ConditionVariable mDisconnected = new ConditionVariable(); 197 private int mScore; 198 private NetworkAgent mNetworkAgent; 199 private int mStartKeepaliveError = PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED; 200 private int mStopKeepaliveError = PacketKeepalive.NO_KEEPALIVE; 201 private Integer mExpectedKeepaliveSlot = null; 202 203 MockNetworkAgent(int transport) { 204 final int type = transportToLegacyType(transport); 205 final String typeName = ConnectivityManager.getNetworkTypeName(type); 206 mNetworkInfo = new NetworkInfo(type, 0, typeName, "Mock"); 207 mNetworkCapabilities = new NetworkCapabilities(); 208 mNetworkCapabilities.addTransportType(transport); 209 switch (transport) { 210 case TRANSPORT_WIFI: 211 mScore = 60; 212 break; 213 case TRANSPORT_CELLULAR: 214 mScore = 50; 215 break; 216 default: 217 throw new UnsupportedOperationException("unimplemented network type"); 218 } 219 mHandlerThread = new IdleableHandlerThread("Mock-" + typeName); 220 mHandlerThread.start(); 221 mNetworkAgent = new NetworkAgent(mHandlerThread.getLooper(), mServiceContext, 222 "Mock-" + typeName, mNetworkInfo, mNetworkCapabilities, 223 new LinkProperties(), mScore, new NetworkMisc()) { 224 @Override 225 public void unwanted() { mDisconnected.open(); } 226 227 @Override 228 public void startPacketKeepalive(Message msg) { 229 int slot = msg.arg1; 230 if (mExpectedKeepaliveSlot != null) { 231 assertEquals((int) mExpectedKeepaliveSlot, slot); 232 } 233 onPacketKeepaliveEvent(slot, mStartKeepaliveError); 234 } 235 236 @Override 237 public void stopPacketKeepalive(Message msg) { 238 onPacketKeepaliveEvent(msg.arg1, mStopKeepaliveError); 239 } 240 }; 241 // Waits for the NetworkAgent to be registered, which includes the creation of the 242 // NetworkMonitor. 243 mService.waitForIdle(); 244 mWrappedNetworkMonitor = mService.getLastCreatedWrappedNetworkMonitor(); 245 } 246 247 public void waitForIdle(int timeoutMs) { 248 mHandlerThread.waitForIdle(timeoutMs); 249 } 250 251 public void waitForIdle() { 252 waitForIdle(TIMEOUT_MS); 253 } 254 255 public void adjustScore(int change) { 256 mScore += change; 257 mNetworkAgent.sendNetworkScore(mScore); 258 } 259 260 public void addCapability(int capability) { 261 mNetworkCapabilities.addCapability(capability); 262 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities); 263 } 264 265 public void setSignalStrength(int signalStrength) { 266 mNetworkCapabilities.setSignalStrength(signalStrength); 267 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities); 268 } 269 270 public void connectWithoutInternet() { 271 mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, null); 272 mNetworkAgent.sendNetworkInfo(mNetworkInfo); 273 } 274 275 /** 276 * Transition this NetworkAgent to CONNECTED state with NET_CAPABILITY_INTERNET. 277 * @param validated Indicate if network should pretend to be validated. 278 */ 279 public void connect(boolean validated) { 280 assertEquals(mNetworkInfo.getDetailedState(), DetailedState.IDLE); 281 assertFalse(mNetworkCapabilities.hasCapability(NET_CAPABILITY_INTERNET)); 282 283 NetworkCallback callback = null; 284 final ConditionVariable validatedCv = new ConditionVariable(); 285 if (validated) { 286 mWrappedNetworkMonitor.gen204ProbeResult = 204; 287 NetworkRequest request = new NetworkRequest.Builder() 288 .addTransportType(mNetworkCapabilities.getTransportTypes()[0]) 289 .build(); 290 callback = new NetworkCallback() { 291 public void onCapabilitiesChanged(Network network, 292 NetworkCapabilities networkCapabilities) { 293 if (network.equals(getNetwork()) && 294 networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED)) { 295 validatedCv.open(); 296 } 297 } 298 }; 299 mCm.registerNetworkCallback(request, callback); 300 } 301 addCapability(NET_CAPABILITY_INTERNET); 302 303 connectWithoutInternet(); 304 305 if (validated) { 306 // Wait for network to validate. 307 waitFor(validatedCv); 308 mWrappedNetworkMonitor.gen204ProbeResult = 500; 309 } 310 311 if (callback != null) mCm.unregisterNetworkCallback(callback); 312 } 313 314 public void connectWithCaptivePortal() { 315 mWrappedNetworkMonitor.gen204ProbeResult = 200; 316 connect(false); 317 waitFor(new Criteria() { public boolean get() { 318 NetworkCapabilities caps = mCm.getNetworkCapabilities(getNetwork()); 319 return caps != null && caps.hasCapability(NET_CAPABILITY_CAPTIVE_PORTAL);} }); 320 mWrappedNetworkMonitor.gen204ProbeResult = 500; 321 } 322 323 public void disconnect() { 324 mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, null); 325 mNetworkAgent.sendNetworkInfo(mNetworkInfo); 326 } 327 328 public Network getNetwork() { 329 return new Network(mNetworkAgent.netId); 330 } 331 332 public ConditionVariable getDisconnectedCV() { 333 return mDisconnected; 334 } 335 336 public WrappedNetworkMonitor getWrappedNetworkMonitor() { 337 return mWrappedNetworkMonitor; 338 } 339 340 public void sendLinkProperties(LinkProperties lp) { 341 mNetworkAgent.sendLinkProperties(lp); 342 } 343 344 public void setStartKeepaliveError(int error) { 345 mStartKeepaliveError = error; 346 } 347 348 public void setStopKeepaliveError(int error) { 349 mStopKeepaliveError = error; 350 } 351 352 public void setExpectedKeepaliveSlot(Integer slot) { 353 mExpectedKeepaliveSlot = slot; 354 } 355 } 356 357 /** 358 * A NetworkFactory that allows tests to wait until any in-flight NetworkRequest add or remove 359 * operations have been processed. Before ConnectivityService can add or remove any requests, 360 * the factory must be told to expect those operations by calling expectAddRequests or 361 * expectRemoveRequests. 362 */ 363 private static class MockNetworkFactory extends NetworkFactory { 364 private final ConditionVariable mNetworkStartedCV = new ConditionVariable(); 365 private final ConditionVariable mNetworkStoppedCV = new ConditionVariable(); 366 private final AtomicBoolean mNetworkStarted = new AtomicBoolean(false); 367 368 // Used to expect that requests be removed or added on a separate thread, without sleeping. 369 // Callers can call either expectAddRequests() or expectRemoveRequests() exactly once, then 370 // cause some other thread to add or remove requests, then call waitForRequests(). We can 371 // either expect requests to be added or removed, but not both, because CountDownLatch can 372 // only count in one direction. 373 private CountDownLatch mExpectations; 374 375 // Whether we are currently expecting requests to be added or removed. Valid only if 376 // mExpectations is non-null. 377 private boolean mExpectingAdditions; 378 379 public MockNetworkFactory(Looper looper, Context context, String logTag, 380 NetworkCapabilities filter) { 381 super(looper, context, logTag, filter); 382 } 383 384 public int getMyRequestCount() { 385 return getRequestCount(); 386 } 387 388 protected void startNetwork() { 389 mNetworkStarted.set(true); 390 mNetworkStartedCV.open(); 391 } 392 393 protected void stopNetwork() { 394 mNetworkStarted.set(false); 395 mNetworkStoppedCV.open(); 396 } 397 398 public boolean getMyStartRequested() { 399 return mNetworkStarted.get(); 400 } 401 402 public ConditionVariable getNetworkStartedCV() { 403 mNetworkStartedCV.close(); 404 return mNetworkStartedCV; 405 } 406 407 public ConditionVariable getNetworkStoppedCV() { 408 mNetworkStoppedCV.close(); 409 return mNetworkStoppedCV; 410 } 411 412 @Override 413 protected void handleAddRequest(NetworkRequest request, int score) { 414 // If we're expecting anything, we must be expecting additions. 415 if (mExpectations != null && !mExpectingAdditions) { 416 fail("Can't add requests while expecting requests to be removed"); 417 } 418 419 // Add the request. 420 super.handleAddRequest(request, score); 421 422 // Reduce the number of request additions we're waiting for. 423 if (mExpectingAdditions) { 424 assertTrue("Added more requests than expected", mExpectations.getCount() > 0); 425 mExpectations.countDown(); 426 } 427 } 428 429 @Override 430 protected void handleRemoveRequest(NetworkRequest request) { 431 // If we're expecting anything, we must be expecting removals. 432 if (mExpectations != null && mExpectingAdditions) { 433 fail("Can't remove requests while expecting requests to be added"); 434 } 435 436 // Remove the request. 437 super.handleRemoveRequest(request); 438 439 // Reduce the number of request removals we're waiting for. 440 if (!mExpectingAdditions) { 441 assertTrue("Removed more requests than expected", mExpectations.getCount() > 0); 442 mExpectations.countDown(); 443 } 444 } 445 446 private void assertNoExpectations() { 447 if (mExpectations != null) { 448 fail("Can't add expectation, " + mExpectations.getCount() + " already pending"); 449 } 450 } 451 452 // Expects that count requests will be added. 453 public void expectAddRequests(final int count) { 454 assertNoExpectations(); 455 mExpectingAdditions = true; 456 mExpectations = new CountDownLatch(count); 457 } 458 459 // Expects that count requests will be removed. 460 public void expectRemoveRequests(final int count) { 461 assertNoExpectations(); 462 mExpectingAdditions = false; 463 mExpectations = new CountDownLatch(count); 464 } 465 466 // Waits for the expected request additions or removals to happen within a timeout. 467 public void waitForRequests() throws InterruptedException { 468 assertNotNull("Nothing to wait for", mExpectations); 469 mExpectations.await(TIMEOUT_MS, TimeUnit.MILLISECONDS); 470 final long count = mExpectations.getCount(); 471 final String msg = count + " requests still not " + 472 (mExpectingAdditions ? "added" : "removed") + 473 " after " + TIMEOUT_MS + " ms"; 474 assertEquals(msg, 0, count); 475 mExpectations = null; 476 } 477 478 public void waitForNetworkRequests(final int count) throws InterruptedException { 479 waitForRequests(); 480 assertEquals(count, getMyRequestCount()); 481 } 482 } 483 484 // NetworkMonitor implementation allowing overriding of Internet connectivity probe result. 485 private class WrappedNetworkMonitor extends NetworkMonitor { 486 // HTTP response code fed back to NetworkMonitor for Internet connectivity probe. 487 public int gen204ProbeResult = 500; 488 489 public WrappedNetworkMonitor(Context context, Handler handler, 490 NetworkAgentInfo networkAgentInfo, NetworkRequest defaultRequest) { 491 super(context, handler, networkAgentInfo, defaultRequest); 492 } 493 494 @Override 495 protected int isCaptivePortal() { 496 return gen204ProbeResult; 497 } 498 } 499 500 private class WrappedConnectivityService extends ConnectivityService { 501 private WrappedNetworkMonitor mLastCreatedNetworkMonitor; 502 503 public WrappedConnectivityService(Context context, INetworkManagementService netManager, 504 INetworkStatsService statsService, INetworkPolicyManager policyManager) { 505 super(context, netManager, statsService, policyManager); 506 } 507 508 @Override 509 protected HandlerThread createHandlerThread() { 510 return new IdleableHandlerThread("WrappedConnectivityService"); 511 } 512 513 @Override 514 protected int getDefaultTcpRwnd() { 515 // Prevent wrapped ConnectivityService from trying to write to SystemProperties. 516 return 0; 517 } 518 519 @Override 520 protected int reserveNetId() { 521 while (true) { 522 final int netId = super.reserveNetId(); 523 524 // Don't overlap test NetIDs with real NetIDs as binding sockets to real networks 525 // can have odd side-effects, like network validations succeeding. 526 final Network[] networks = ConnectivityManager.from(getContext()).getAllNetworks(); 527 boolean overlaps = false; 528 for (Network network : networks) { 529 if (netId == network.netId) { 530 overlaps = true; 531 break; 532 } 533 } 534 if (overlaps) continue; 535 536 return netId; 537 } 538 } 539 540 @Override 541 public NetworkMonitor createNetworkMonitor(Context context, Handler handler, 542 NetworkAgentInfo nai, NetworkRequest defaultRequest) { 543 final WrappedNetworkMonitor monitor = new WrappedNetworkMonitor(context, handler, nai, 544 defaultRequest); 545 mLastCreatedNetworkMonitor = monitor; 546 return monitor; 547 } 548 549 public WrappedNetworkMonitor getLastCreatedWrappedNetworkMonitor() { 550 return mLastCreatedNetworkMonitor; 551 } 552 553 public void waitForIdle(int timeoutMs) { 554 ((IdleableHandlerThread) mHandlerThread).waitForIdle(timeoutMs); 555 } 556 557 public void waitForIdle() { 558 waitForIdle(TIMEOUT_MS); 559 } 560 561 } 562 563 private interface Criteria { 564 public boolean get(); 565 } 566 567 /** 568 * Wait up to 500ms for {@code criteria.get()} to become true, polling. 569 * Fails if 500ms goes by before {@code criteria.get()} to become true. 570 */ 571 static private void waitFor(Criteria criteria) { 572 int delays = 0; 573 while (!criteria.get()) { 574 try { 575 Thread.sleep(100); 576 } catch (InterruptedException e) { 577 } 578 if (++delays == 5) fail(); 579 } 580 } 581 582 /** 583 * Wait up to TIMEOUT_MS for {@code conditionVariable} to open. 584 * Fails if TIMEOUT_MS goes by before {@code conditionVariable} opens. 585 */ 586 static private void waitFor(ConditionVariable conditionVariable) { 587 assertTrue(conditionVariable.block(TIMEOUT_MS)); 588 } 589 590 @Override 591 public void setUp() throws Exception { 592 super.setUp(); 593 594 mServiceContext = new MockContext(getContext()); 595 mService = new WrappedConnectivityService(mServiceContext, 596 mock(INetworkManagementService.class), 597 mock(INetworkStatsService.class), 598 mock(INetworkPolicyManager.class)); 599 600 mService.systemReady(); 601 mCm = new ConnectivityManager(getContext(), mService); 602 } 603 604 private int transportToLegacyType(int transport) { 605 switch (transport) { 606 case TRANSPORT_WIFI: 607 return TYPE_WIFI; 608 case TRANSPORT_CELLULAR: 609 return TYPE_MOBILE; 610 default: 611 throw new IllegalStateException("Unknown transport" + transport); 612 } 613 } 614 615 private void verifyActiveNetwork(int transport) { 616 // Test getActiveNetworkInfo() 617 assertNotNull(mCm.getActiveNetworkInfo()); 618 assertEquals(transportToLegacyType(transport), mCm.getActiveNetworkInfo().getType()); 619 // Test getActiveNetwork() 620 assertNotNull(mCm.getActiveNetwork()); 621 switch (transport) { 622 case TRANSPORT_WIFI: 623 assertEquals(mCm.getActiveNetwork(), mWiFiNetworkAgent.getNetwork()); 624 break; 625 case TRANSPORT_CELLULAR: 626 assertEquals(mCm.getActiveNetwork(), mCellNetworkAgent.getNetwork()); 627 break; 628 default: 629 throw new IllegalStateException("Unknown transport" + transport); 630 } 631 // Test getNetworkInfo(Network) 632 assertNotNull(mCm.getNetworkInfo(mCm.getActiveNetwork())); 633 assertEquals(transportToLegacyType(transport), mCm.getNetworkInfo(mCm.getActiveNetwork()).getType()); 634 // Test getNetworkCapabilities(Network) 635 assertNotNull(mCm.getNetworkCapabilities(mCm.getActiveNetwork())); 636 assertTrue(mCm.getNetworkCapabilities(mCm.getActiveNetwork()).hasTransport(transport)); 637 } 638 639 private void verifyNoNetwork() { 640 // Test getActiveNetworkInfo() 641 assertNull(mCm.getActiveNetworkInfo()); 642 // Test getActiveNetwork() 643 assertNull(mCm.getActiveNetwork()); 644 // Test getAllNetworks() 645 assertEquals(0, mCm.getAllNetworks().length); 646 } 647 648 /** 649 * Return a ConditionVariable that opens when {@code count} numbers of CONNECTIVITY_ACTION 650 * broadcasts are received. 651 */ 652 private ConditionVariable waitForConnectivityBroadcasts(final int count) { 653 final ConditionVariable cv = new ConditionVariable(); 654 mServiceContext.registerReceiver(new BroadcastReceiver() { 655 private int remaining = count; 656 public void onReceive(Context context, Intent intent) { 657 if (--remaining == 0) { 658 cv.open(); 659 mServiceContext.unregisterReceiver(this); 660 } 661 } 662 }, new IntentFilter(CONNECTIVITY_ACTION)); 663 return cv; 664 } 665 666 @LargeTest 667 public void testLingering() throws Exception { 668 // Decrease linger timeout to the minimum allowed by AlarmManagerService. 669 NetworkMonitor.SetDefaultLingerTime(5000); 670 verifyNoNetwork(); 671 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); 672 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 673 assertNull(mCm.getActiveNetworkInfo()); 674 assertNull(mCm.getActiveNetwork()); 675 // Test bringing up validated cellular. 676 ConditionVariable cv = waitForConnectivityBroadcasts(1); 677 mCellNetworkAgent.connect(true); 678 waitFor(cv); 679 verifyActiveNetwork(TRANSPORT_CELLULAR); 680 assertEquals(2, mCm.getAllNetworks().length); 681 assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) || 682 mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork())); 683 assertTrue(mCm.getAllNetworks()[0].equals(mWiFiNetworkAgent.getNetwork()) || 684 mCm.getAllNetworks()[1].equals(mWiFiNetworkAgent.getNetwork())); 685 // Test bringing up validated WiFi. 686 cv = waitForConnectivityBroadcasts(2); 687 mWiFiNetworkAgent.connect(true); 688 waitFor(cv); 689 verifyActiveNetwork(TRANSPORT_WIFI); 690 assertEquals(2, mCm.getAllNetworks().length); 691 assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) || 692 mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork())); 693 assertTrue(mCm.getAllNetworks()[0].equals(mCellNetworkAgent.getNetwork()) || 694 mCm.getAllNetworks()[1].equals(mCellNetworkAgent.getNetwork())); 695 // Test cellular linger timeout. 696 try { 697 Thread.sleep(6000); 698 } catch (InterruptedException e) { 699 } 700 verifyActiveNetwork(TRANSPORT_WIFI); 701 assertEquals(1, mCm.getAllNetworks().length); 702 assertEquals(mCm.getAllNetworks()[0], mCm.getActiveNetwork()); 703 // Test WiFi disconnect. 704 cv = waitForConnectivityBroadcasts(1); 705 mWiFiNetworkAgent.disconnect(); 706 waitFor(cv); 707 verifyNoNetwork(); 708 } 709 710 @LargeTest 711 public void testValidatedCellularOutscoresUnvalidatedWiFi() throws Exception { 712 // Test bringing up unvalidated WiFi 713 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 714 ConditionVariable cv = waitForConnectivityBroadcasts(1); 715 mWiFiNetworkAgent.connect(false); 716 waitFor(cv); 717 verifyActiveNetwork(TRANSPORT_WIFI); 718 // Test bringing up unvalidated cellular 719 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); 720 mCellNetworkAgent.connect(false); 721 mService.waitForIdle(); 722 verifyActiveNetwork(TRANSPORT_WIFI); 723 // Test cellular disconnect. 724 mCellNetworkAgent.disconnect(); 725 mService.waitForIdle(); 726 verifyActiveNetwork(TRANSPORT_WIFI); 727 // Test bringing up validated cellular 728 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); 729 cv = waitForConnectivityBroadcasts(2); 730 mCellNetworkAgent.connect(true); 731 waitFor(cv); 732 verifyActiveNetwork(TRANSPORT_CELLULAR); 733 // Test cellular disconnect. 734 cv = waitForConnectivityBroadcasts(2); 735 mCellNetworkAgent.disconnect(); 736 waitFor(cv); 737 verifyActiveNetwork(TRANSPORT_WIFI); 738 // Test WiFi disconnect. 739 cv = waitForConnectivityBroadcasts(1); 740 mWiFiNetworkAgent.disconnect(); 741 waitFor(cv); 742 verifyNoNetwork(); 743 } 744 745 @LargeTest 746 public void testUnvalidatedWifiOutscoresUnvalidatedCellular() throws Exception { 747 // Test bringing up unvalidated cellular. 748 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); 749 ConditionVariable cv = waitForConnectivityBroadcasts(1); 750 mCellNetworkAgent.connect(false); 751 waitFor(cv); 752 verifyActiveNetwork(TRANSPORT_CELLULAR); 753 // Test bringing up unvalidated WiFi. 754 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 755 cv = waitForConnectivityBroadcasts(2); 756 mWiFiNetworkAgent.connect(false); 757 waitFor(cv); 758 verifyActiveNetwork(TRANSPORT_WIFI); 759 // Test WiFi disconnect. 760 cv = waitForConnectivityBroadcasts(2); 761 mWiFiNetworkAgent.disconnect(); 762 waitFor(cv); 763 verifyActiveNetwork(TRANSPORT_CELLULAR); 764 // Test cellular disconnect. 765 cv = waitForConnectivityBroadcasts(1); 766 mCellNetworkAgent.disconnect(); 767 waitFor(cv); 768 verifyNoNetwork(); 769 } 770 771 @LargeTest 772 public void testUnlingeringDoesNotValidate() throws Exception { 773 // Test bringing up unvalidated WiFi. 774 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 775 ConditionVariable cv = waitForConnectivityBroadcasts(1); 776 mWiFiNetworkAgent.connect(false); 777 waitFor(cv); 778 verifyActiveNetwork(TRANSPORT_WIFI); 779 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability( 780 NET_CAPABILITY_VALIDATED)); 781 // Test bringing up validated cellular. 782 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); 783 cv = waitForConnectivityBroadcasts(2); 784 mCellNetworkAgent.connect(true); 785 waitFor(cv); 786 verifyActiveNetwork(TRANSPORT_CELLULAR); 787 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability( 788 NET_CAPABILITY_VALIDATED)); 789 // Test cellular disconnect. 790 cv = waitForConnectivityBroadcasts(2); 791 mCellNetworkAgent.disconnect(); 792 waitFor(cv); 793 verifyActiveNetwork(TRANSPORT_WIFI); 794 // Unlingering a network should not cause it to be marked as validated. 795 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability( 796 NET_CAPABILITY_VALIDATED)); 797 } 798 799 @LargeTest 800 public void testCellularOutscoresWeakWifi() throws Exception { 801 // Test bringing up validated cellular. 802 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); 803 ConditionVariable cv = waitForConnectivityBroadcasts(1); 804 mCellNetworkAgent.connect(true); 805 waitFor(cv); 806 verifyActiveNetwork(TRANSPORT_CELLULAR); 807 // Test bringing up validated WiFi. 808 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 809 cv = waitForConnectivityBroadcasts(2); 810 mWiFiNetworkAgent.connect(true); 811 waitFor(cv); 812 verifyActiveNetwork(TRANSPORT_WIFI); 813 // Test WiFi getting really weak. 814 cv = waitForConnectivityBroadcasts(2); 815 mWiFiNetworkAgent.adjustScore(-11); 816 waitFor(cv); 817 verifyActiveNetwork(TRANSPORT_CELLULAR); 818 // Test WiFi restoring signal strength. 819 cv = waitForConnectivityBroadcasts(2); 820 mWiFiNetworkAgent.adjustScore(11); 821 waitFor(cv); 822 verifyActiveNetwork(TRANSPORT_WIFI); 823 mCellNetworkAgent.disconnect(); 824 mWiFiNetworkAgent.disconnect(); 825 } 826 827 @LargeTest 828 public void testReapingNetwork() throws Exception { 829 // Test bringing up WiFi without NET_CAPABILITY_INTERNET. 830 // Expect it to be torn down immediately because it satisfies no requests. 831 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 832 ConditionVariable cv = mWiFiNetworkAgent.getDisconnectedCV(); 833 mWiFiNetworkAgent.connectWithoutInternet(); 834 waitFor(cv); 835 // Test bringing up cellular without NET_CAPABILITY_INTERNET. 836 // Expect it to be torn down immediately because it satisfies no requests. 837 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 838 cv = mCellNetworkAgent.getDisconnectedCV(); 839 mCellNetworkAgent.connectWithoutInternet(); 840 waitFor(cv); 841 // Test bringing up validated WiFi. 842 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 843 cv = waitForConnectivityBroadcasts(1); 844 mWiFiNetworkAgent.connect(true); 845 waitFor(cv); 846 verifyActiveNetwork(TRANSPORT_WIFI); 847 // Test bringing up unvalidated cellular. 848 // Expect it to be torn down because it could never be the highest scoring network 849 // satisfying the default request even if it validated. 850 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); 851 cv = mCellNetworkAgent.getDisconnectedCV(); 852 mCellNetworkAgent.connect(false); 853 waitFor(cv); 854 verifyActiveNetwork(TRANSPORT_WIFI); 855 cv = mWiFiNetworkAgent.getDisconnectedCV(); 856 mWiFiNetworkAgent.disconnect(); 857 waitFor(cv); 858 } 859 860 @LargeTest 861 public void testCellularFallback() throws Exception { 862 // Test bringing up validated cellular. 863 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); 864 ConditionVariable cv = waitForConnectivityBroadcasts(1); 865 mCellNetworkAgent.connect(true); 866 waitFor(cv); 867 verifyActiveNetwork(TRANSPORT_CELLULAR); 868 // Test bringing up validated WiFi. 869 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 870 cv = waitForConnectivityBroadcasts(2); 871 mWiFiNetworkAgent.connect(true); 872 waitFor(cv); 873 verifyActiveNetwork(TRANSPORT_WIFI); 874 // Reevaluate WiFi (it'll instantly fail DNS). 875 cv = waitForConnectivityBroadcasts(2); 876 assertTrue(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability( 877 NET_CAPABILITY_VALIDATED)); 878 mCm.reportBadNetwork(mWiFiNetworkAgent.getNetwork()); 879 // Should quickly fall back to Cellular. 880 waitFor(cv); 881 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability( 882 NET_CAPABILITY_VALIDATED)); 883 verifyActiveNetwork(TRANSPORT_CELLULAR); 884 // Reevaluate cellular (it'll instantly fail DNS). 885 cv = waitForConnectivityBroadcasts(2); 886 assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability( 887 NET_CAPABILITY_VALIDATED)); 888 mCm.reportBadNetwork(mCellNetworkAgent.getNetwork()); 889 // Should quickly fall back to WiFi. 890 waitFor(cv); 891 assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability( 892 NET_CAPABILITY_VALIDATED)); 893 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability( 894 NET_CAPABILITY_VALIDATED)); 895 verifyActiveNetwork(TRANSPORT_WIFI); 896 mCellNetworkAgent.disconnect(); 897 mWiFiNetworkAgent.disconnect(); 898 } 899 900 @LargeTest 901 public void testWiFiFallback() throws Exception { 902 // Test bringing up unvalidated WiFi. 903 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 904 ConditionVariable cv = waitForConnectivityBroadcasts(1); 905 mWiFiNetworkAgent.connect(false); 906 waitFor(cv); 907 verifyActiveNetwork(TRANSPORT_WIFI); 908 // Test bringing up validated cellular. 909 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); 910 cv = waitForConnectivityBroadcasts(2); 911 mCellNetworkAgent.connect(true); 912 waitFor(cv); 913 verifyActiveNetwork(TRANSPORT_CELLULAR); 914 // Reevaluate cellular (it'll instantly fail DNS). 915 cv = waitForConnectivityBroadcasts(2); 916 assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability( 917 NET_CAPABILITY_VALIDATED)); 918 mCm.reportBadNetwork(mCellNetworkAgent.getNetwork()); 919 // Should quickly fall back to WiFi. 920 waitFor(cv); 921 assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability( 922 NET_CAPABILITY_VALIDATED)); 923 verifyActiveNetwork(TRANSPORT_WIFI); 924 mCellNetworkAgent.disconnect(); 925 mWiFiNetworkAgent.disconnect(); 926 } 927 928 enum CallbackState { 929 NONE, 930 AVAILABLE, 931 LOSING, 932 LOST 933 } 934 935 /** 936 * Utility NetworkCallback for testing. The caller must explicitly test for all the callbacks 937 * this class receives, by calling expectCallback() exactly once each time a callback is 938 * received. assertNoCallback may be called at any time. 939 */ 940 private class TestNetworkCallback extends NetworkCallback { 941 private final ConditionVariable mConditionVariable = new ConditionVariable(); 942 private CallbackState mLastCallback = CallbackState.NONE; 943 944 public void onAvailable(Network network) { 945 assertEquals(CallbackState.NONE, mLastCallback); 946 mLastCallback = CallbackState.AVAILABLE; 947 mConditionVariable.open(); 948 } 949 950 public void onLosing(Network network, int maxMsToLive) { 951 assertEquals(CallbackState.NONE, mLastCallback); 952 mLastCallback = CallbackState.LOSING; 953 mConditionVariable.open(); 954 } 955 956 public void onLost(Network network) { 957 assertEquals(CallbackState.NONE, mLastCallback); 958 mLastCallback = CallbackState.LOST; 959 mConditionVariable.open(); 960 } 961 962 void expectCallback(CallbackState state) { 963 waitFor(mConditionVariable); 964 assertEquals(state, mLastCallback); 965 mLastCallback = CallbackState.NONE; 966 mConditionVariable.close(); 967 } 968 969 void assertNoCallback() { 970 assertEquals(CallbackState.NONE, mLastCallback); 971 } 972 } 973 974 @LargeTest 975 public void testStateChangeNetworkCallbacks() throws Exception { 976 final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback(); 977 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback(); 978 final NetworkRequest wifiRequest = new NetworkRequest.Builder() 979 .addTransportType(TRANSPORT_WIFI).build(); 980 final NetworkRequest cellRequest = new NetworkRequest.Builder() 981 .addTransportType(TRANSPORT_CELLULAR).build(); 982 mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback); 983 mCm.registerNetworkCallback(cellRequest, cellNetworkCallback); 984 985 // Test unvalidated networks 986 ConditionVariable cv = waitForConnectivityBroadcasts(1); 987 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); 988 mCellNetworkAgent.connect(false); 989 cellNetworkCallback.expectCallback(CallbackState.AVAILABLE); 990 wifiNetworkCallback.assertNoCallback(); 991 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 992 waitFor(cv); 993 994 // This should not trigger spurious onAvailable() callbacks, b/21762680. 995 mCellNetworkAgent.adjustScore(-1); 996 mService.waitForIdle(); 997 wifiNetworkCallback.assertNoCallback(); 998 cellNetworkCallback.assertNoCallback(); 999 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 1000 1001 cv = waitForConnectivityBroadcasts(2); 1002 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 1003 mWiFiNetworkAgent.connect(false); 1004 wifiNetworkCallback.expectCallback(CallbackState.AVAILABLE); 1005 cellNetworkCallback.assertNoCallback(); 1006 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 1007 waitFor(cv); 1008 1009 cv = waitForConnectivityBroadcasts(2); 1010 mWiFiNetworkAgent.disconnect(); 1011 wifiNetworkCallback.expectCallback(CallbackState.LOST); 1012 cellNetworkCallback.assertNoCallback(); 1013 waitFor(cv); 1014 1015 cv = waitForConnectivityBroadcasts(1); 1016 mCellNetworkAgent.disconnect(); 1017 cellNetworkCallback.expectCallback(CallbackState.LOST); 1018 wifiNetworkCallback.assertNoCallback(); 1019 waitFor(cv); 1020 1021 // Test validated networks 1022 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); 1023 mCellNetworkAgent.connect(true); 1024 cellNetworkCallback.expectCallback(CallbackState.AVAILABLE); 1025 wifiNetworkCallback.assertNoCallback(); 1026 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 1027 1028 // This should not trigger spurious onAvailable() callbacks, b/21762680. 1029 mCellNetworkAgent.adjustScore(-1); 1030 mService.waitForIdle(); 1031 wifiNetworkCallback.assertNoCallback(); 1032 cellNetworkCallback.assertNoCallback(); 1033 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 1034 1035 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 1036 mWiFiNetworkAgent.connect(true); 1037 wifiNetworkCallback.expectCallback(CallbackState.AVAILABLE); 1038 cellNetworkCallback.expectCallback(CallbackState.LOSING); 1039 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 1040 1041 mWiFiNetworkAgent.disconnect(); 1042 wifiNetworkCallback.expectCallback(CallbackState.LOST); 1043 cellNetworkCallback.assertNoCallback(); 1044 1045 mCellNetworkAgent.disconnect(); 1046 cellNetworkCallback.expectCallback(CallbackState.LOST); 1047 wifiNetworkCallback.assertNoCallback(); 1048 } 1049 1050 private void tryNetworkFactoryRequests(int capability) throws Exception { 1051 // Verify NOT_RESTRICTED is set appropriately 1052 final NetworkCapabilities nc = new NetworkRequest.Builder().addCapability(capability) 1053 .build().networkCapabilities; 1054 if (capability == NET_CAPABILITY_CBS || capability == NET_CAPABILITY_DUN || 1055 capability == NET_CAPABILITY_EIMS || capability == NET_CAPABILITY_FOTA || 1056 capability == NET_CAPABILITY_IA || capability == NET_CAPABILITY_IMS || 1057 capability == NET_CAPABILITY_RCS || capability == NET_CAPABILITY_XCAP) { 1058 assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)); 1059 } else { 1060 assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)); 1061 } 1062 1063 NetworkCapabilities filter = new NetworkCapabilities(); 1064 filter.addCapability(capability); 1065 final HandlerThread handlerThread = new HandlerThread("testNetworkFactoryRequests"); 1066 handlerThread.start(); 1067 final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(), 1068 mServiceContext, "testFactory", filter); 1069 testFactory.setScoreFilter(40); 1070 ConditionVariable cv = testFactory.getNetworkStartedCV(); 1071 testFactory.expectAddRequests(1); 1072 testFactory.register(); 1073 testFactory.waitForNetworkRequests(1); 1074 int expectedRequestCount = 1; 1075 NetworkCallback networkCallback = null; 1076 // For non-INTERNET capabilities we cannot rely on the default request being present, so 1077 // add one. 1078 if (capability != NET_CAPABILITY_INTERNET) { 1079 assertFalse(testFactory.getMyStartRequested()); 1080 NetworkRequest request = new NetworkRequest.Builder().addCapability(capability).build(); 1081 networkCallback = new NetworkCallback(); 1082 testFactory.expectAddRequests(1); 1083 mCm.requestNetwork(request, networkCallback); 1084 expectedRequestCount++; 1085 testFactory.waitForNetworkRequests(expectedRequestCount); 1086 } 1087 waitFor(cv); 1088 assertEquals(expectedRequestCount, testFactory.getMyRequestCount()); 1089 assertTrue(testFactory.getMyStartRequested()); 1090 1091 // Now bring in a higher scored network. 1092 MockNetworkAgent testAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); 1093 // Rather than create a validated network which complicates things by registering it's 1094 // own NetworkRequest during startup, just bump up the score to cancel out the 1095 // unvalidated penalty. 1096 testAgent.adjustScore(40); 1097 cv = testFactory.getNetworkStoppedCV(); 1098 1099 // When testAgent connects, ConnectivityService will re-send us all current requests with 1100 // the new score. There are expectedRequestCount such requests, and we must wait for all of 1101 // them. 1102 testFactory.expectAddRequests(expectedRequestCount); 1103 testAgent.connect(false); 1104 testAgent.addCapability(capability); 1105 waitFor(cv); 1106 testFactory.waitForNetworkRequests(expectedRequestCount); 1107 assertFalse(testFactory.getMyStartRequested()); 1108 1109 // Bring in a bunch of requests. 1110 testFactory.expectAddRequests(10); 1111 assertEquals(expectedRequestCount, testFactory.getMyRequestCount()); 1112 ConnectivityManager.NetworkCallback[] networkCallbacks = 1113 new ConnectivityManager.NetworkCallback[10]; 1114 for (int i = 0; i< networkCallbacks.length; i++) { 1115 networkCallbacks[i] = new ConnectivityManager.NetworkCallback(); 1116 NetworkRequest.Builder builder = new NetworkRequest.Builder(); 1117 builder.addCapability(capability); 1118 mCm.requestNetwork(builder.build(), networkCallbacks[i]); 1119 } 1120 testFactory.waitForNetworkRequests(10 + expectedRequestCount); 1121 assertFalse(testFactory.getMyStartRequested()); 1122 1123 // Remove the requests. 1124 testFactory.expectRemoveRequests(10); 1125 for (int i = 0; i < networkCallbacks.length; i++) { 1126 mCm.unregisterNetworkCallback(networkCallbacks[i]); 1127 } 1128 testFactory.waitForNetworkRequests(expectedRequestCount); 1129 assertFalse(testFactory.getMyStartRequested()); 1130 1131 // Drop the higher scored network. 1132 cv = testFactory.getNetworkStartedCV(); 1133 testAgent.disconnect(); 1134 waitFor(cv); 1135 assertEquals(expectedRequestCount, testFactory.getMyRequestCount()); 1136 assertTrue(testFactory.getMyStartRequested()); 1137 1138 testFactory.unregister(); 1139 if (networkCallback != null) mCm.unregisterNetworkCallback(networkCallback); 1140 handlerThread.quit(); 1141 } 1142 1143 @LargeTest 1144 public void testNetworkFactoryRequests() throws Exception { 1145 tryNetworkFactoryRequests(NET_CAPABILITY_MMS); 1146 tryNetworkFactoryRequests(NET_CAPABILITY_SUPL); 1147 tryNetworkFactoryRequests(NET_CAPABILITY_DUN); 1148 tryNetworkFactoryRequests(NET_CAPABILITY_FOTA); 1149 tryNetworkFactoryRequests(NET_CAPABILITY_IMS); 1150 tryNetworkFactoryRequests(NET_CAPABILITY_CBS); 1151 tryNetworkFactoryRequests(NET_CAPABILITY_WIFI_P2P); 1152 tryNetworkFactoryRequests(NET_CAPABILITY_IA); 1153 tryNetworkFactoryRequests(NET_CAPABILITY_RCS); 1154 tryNetworkFactoryRequests(NET_CAPABILITY_XCAP); 1155 tryNetworkFactoryRequests(NET_CAPABILITY_EIMS); 1156 tryNetworkFactoryRequests(NET_CAPABILITY_NOT_METERED); 1157 tryNetworkFactoryRequests(NET_CAPABILITY_INTERNET); 1158 tryNetworkFactoryRequests(NET_CAPABILITY_TRUSTED); 1159 tryNetworkFactoryRequests(NET_CAPABILITY_NOT_VPN); 1160 // Skipping VALIDATED and CAPTIVE_PORTAL as they're disallowed. 1161 } 1162 1163 @LargeTest 1164 public void testNoMutableNetworkRequests() throws Exception { 1165 PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, new Intent("a"), 0); 1166 NetworkRequest.Builder builder = new NetworkRequest.Builder(); 1167 builder.addCapability(NET_CAPABILITY_VALIDATED); 1168 try { 1169 mCm.requestNetwork(builder.build(), new NetworkCallback()); 1170 fail(); 1171 } catch (IllegalArgumentException expected) {} 1172 try { 1173 mCm.requestNetwork(builder.build(), pendingIntent); 1174 fail(); 1175 } catch (IllegalArgumentException expected) {} 1176 builder = new NetworkRequest.Builder(); 1177 builder.addCapability(NET_CAPABILITY_CAPTIVE_PORTAL); 1178 try { 1179 mCm.requestNetwork(builder.build(), new NetworkCallback()); 1180 fail(); 1181 } catch (IllegalArgumentException expected) {} 1182 try { 1183 mCm.requestNetwork(builder.build(), pendingIntent); 1184 fail(); 1185 } catch (IllegalArgumentException expected) {} 1186 } 1187 1188 @LargeTest 1189 public void testMMSonWiFi() throws Exception { 1190 // Test bringing up cellular without MMS NetworkRequest gets reaped 1191 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); 1192 mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS); 1193 ConditionVariable cv = mCellNetworkAgent.getDisconnectedCV(); 1194 mCellNetworkAgent.connectWithoutInternet(); 1195 waitFor(cv); 1196 waitFor(new Criteria() { 1197 public boolean get() { return mCm.getAllNetworks().length == 0; } }); 1198 verifyNoNetwork(); 1199 // Test bringing up validated WiFi. 1200 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 1201 cv = waitForConnectivityBroadcasts(1); 1202 mWiFiNetworkAgent.connect(true); 1203 waitFor(cv); 1204 verifyActiveNetwork(TRANSPORT_WIFI); 1205 // Register MMS NetworkRequest 1206 NetworkRequest.Builder builder = new NetworkRequest.Builder(); 1207 builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS); 1208 final TestNetworkCallback networkCallback = new TestNetworkCallback(); 1209 mCm.requestNetwork(builder.build(), networkCallback); 1210 // Test bringing up unvalidated cellular with MMS 1211 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); 1212 mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS); 1213 mCellNetworkAgent.connectWithoutInternet(); 1214 networkCallback.expectCallback(CallbackState.AVAILABLE); 1215 verifyActiveNetwork(TRANSPORT_WIFI); 1216 // Test releasing NetworkRequest disconnects cellular with MMS 1217 cv = mCellNetworkAgent.getDisconnectedCV(); 1218 mCm.unregisterNetworkCallback(networkCallback); 1219 waitFor(cv); 1220 verifyActiveNetwork(TRANSPORT_WIFI); 1221 } 1222 1223 @LargeTest 1224 public void testMMSonCell() throws Exception { 1225 // Test bringing up cellular without MMS 1226 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); 1227 ConditionVariable cv = waitForConnectivityBroadcasts(1); 1228 mCellNetworkAgent.connect(false); 1229 waitFor(cv); 1230 verifyActiveNetwork(TRANSPORT_CELLULAR); 1231 // Register MMS NetworkRequest 1232 NetworkRequest.Builder builder = new NetworkRequest.Builder(); 1233 builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS); 1234 final TestNetworkCallback networkCallback = new TestNetworkCallback(); 1235 mCm.requestNetwork(builder.build(), networkCallback); 1236 // Test bringing up MMS cellular network 1237 MockNetworkAgent mmsNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); 1238 mmsNetworkAgent.addCapability(NET_CAPABILITY_MMS); 1239 mmsNetworkAgent.connectWithoutInternet(); 1240 networkCallback.expectCallback(CallbackState.AVAILABLE); 1241 verifyActiveNetwork(TRANSPORT_CELLULAR); 1242 // Test releasing MMS NetworkRequest does not disconnect main cellular NetworkAgent 1243 cv = mmsNetworkAgent.getDisconnectedCV(); 1244 mCm.unregisterNetworkCallback(networkCallback); 1245 waitFor(cv); 1246 verifyActiveNetwork(TRANSPORT_CELLULAR); 1247 } 1248 1249 @LargeTest 1250 public void testCaptivePortal() { 1251 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback(); 1252 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder() 1253 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build(); 1254 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback); 1255 1256 final TestNetworkCallback validatedCallback = new TestNetworkCallback(); 1257 final NetworkRequest validatedRequest = new NetworkRequest.Builder() 1258 .addCapability(NET_CAPABILITY_VALIDATED).build(); 1259 mCm.registerNetworkCallback(validatedRequest, validatedCallback); 1260 1261 // Bring up a network with a captive portal. 1262 // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL. 1263 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 1264 mWiFiNetworkAgent.connectWithCaptivePortal(); 1265 captivePortalCallback.expectCallback(CallbackState.AVAILABLE); 1266 1267 // Take down network. 1268 // Expect onLost callback. 1269 mWiFiNetworkAgent.disconnect(); 1270 captivePortalCallback.expectCallback(CallbackState.LOST); 1271 1272 // Bring up a network with a captive portal. 1273 // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL. 1274 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 1275 mWiFiNetworkAgent.connectWithCaptivePortal(); 1276 captivePortalCallback.expectCallback(CallbackState.AVAILABLE); 1277 1278 // Make captive portal disappear then revalidate. 1279 // Expect onLost callback because network no longer provides NET_CAPABILITY_CAPTIVE_PORTAL. 1280 mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 204; 1281 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true); 1282 captivePortalCallback.expectCallback(CallbackState.LOST); 1283 1284 // Expect NET_CAPABILITY_VALIDATED onAvailable callback. 1285 validatedCallback.expectCallback(CallbackState.AVAILABLE); 1286 1287 // Break network connectivity. 1288 // Expect NET_CAPABILITY_VALIDATED onLost callback. 1289 mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 500; 1290 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), false); 1291 validatedCallback.expectCallback(CallbackState.LOST); 1292 } 1293 1294 private static class TestKeepaliveCallback extends PacketKeepaliveCallback { 1295 1296 public static enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR }; 1297 1298 private class CallbackValue { 1299 public CallbackType callbackType; 1300 public int error; 1301 1302 public CallbackValue(CallbackType type) { 1303 this.callbackType = type; 1304 this.error = PacketKeepalive.SUCCESS; 1305 assertTrue("onError callback must have error", type != CallbackType.ON_ERROR); 1306 } 1307 1308 public CallbackValue(CallbackType type, int error) { 1309 this.callbackType = type; 1310 this.error = error; 1311 assertEquals("error can only be set for onError", type, CallbackType.ON_ERROR); 1312 } 1313 1314 @Override 1315 public boolean equals(Object o) { 1316 return o instanceof CallbackValue && 1317 this.callbackType == ((CallbackValue) o).callbackType && 1318 this.error == ((CallbackValue) o).error; 1319 } 1320 1321 @Override 1322 public String toString() { 1323 return String.format("%s(%s, %d)", getClass().getSimpleName(), callbackType, error); 1324 } 1325 } 1326 1327 private LinkedBlockingQueue<CallbackValue> mCallbacks = new LinkedBlockingQueue<>(); 1328 1329 @Override 1330 public void onStarted() { 1331 mCallbacks.add(new CallbackValue(CallbackType.ON_STARTED)); 1332 } 1333 1334 @Override 1335 public void onStopped() { 1336 mCallbacks.add(new CallbackValue(CallbackType.ON_STOPPED)); 1337 } 1338 1339 @Override 1340 public void onError(int error) { 1341 mCallbacks.add(new CallbackValue(CallbackType.ON_ERROR, error)); 1342 } 1343 1344 private void expectCallback(CallbackValue callbackValue) { 1345 try { 1346 assertEquals( 1347 callbackValue, 1348 mCallbacks.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS)); 1349 } catch (InterruptedException e) { 1350 fail(callbackValue.callbackType + " callback not seen after " + TIMEOUT_MS + " ms"); 1351 } 1352 } 1353 1354 public void expectStarted() { 1355 expectCallback(new CallbackValue(CallbackType.ON_STARTED)); 1356 } 1357 1358 public void expectStopped() { 1359 expectCallback(new CallbackValue(CallbackType.ON_STOPPED)); 1360 } 1361 1362 public void expectError(int error) { 1363 expectCallback(new CallbackValue(CallbackType.ON_ERROR, error)); 1364 } 1365 } 1366 1367 private Network connectKeepaliveNetwork(LinkProperties lp) { 1368 // Ensure the network is disconnected before we do anything. 1369 if (mWiFiNetworkAgent != null) { 1370 assertNull(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork())); 1371 } 1372 1373 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); 1374 ConditionVariable cv = waitForConnectivityBroadcasts(1); 1375 mWiFiNetworkAgent.connect(true); 1376 waitFor(cv); 1377 verifyActiveNetwork(TRANSPORT_WIFI); 1378 mWiFiNetworkAgent.sendLinkProperties(lp); 1379 mService.waitForIdle(); 1380 return mWiFiNetworkAgent.getNetwork(); 1381 } 1382 1383 public void testPacketKeepalives() throws Exception { 1384 InetAddress myIPv4 = InetAddress.getByName("192.0.2.129"); 1385 InetAddress notMyIPv4 = InetAddress.getByName("192.0.2.35"); 1386 InetAddress myIPv6 = InetAddress.getByName("2001:db8::1"); 1387 InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8"); 1388 InetAddress dstIPv6 = InetAddress.getByName("2001:4860:4860::8888"); 1389 1390 LinkProperties lp = new LinkProperties(); 1391 lp.setInterfaceName("wlan12"); 1392 lp.addLinkAddress(new LinkAddress(myIPv6, 64)); 1393 lp.addLinkAddress(new LinkAddress(myIPv4, 25)); 1394 lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234"))); 1395 lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254"))); 1396 1397 Network notMyNet = new Network(61234); 1398 Network myNet = connectKeepaliveNetwork(lp); 1399 1400 TestKeepaliveCallback callback = new TestKeepaliveCallback(); 1401 PacketKeepalive ka; 1402 1403 // Attempt to start keepalives with invalid parameters and check for errors. 1404 ka = mCm.startNattKeepalive(notMyNet, 25, callback, myIPv4, 1234, dstIPv4); 1405 callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK); 1406 1407 ka = mCm.startNattKeepalive(myNet, 19, callback, notMyIPv4, 1234, dstIPv4); 1408 callback.expectError(PacketKeepalive.ERROR_INVALID_INTERVAL); 1409 1410 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 1234, dstIPv6); 1411 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS); 1412 1413 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv6, 1234, dstIPv4); 1414 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS); 1415 1416 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv6, 1234, dstIPv6); 1417 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS); // NAT-T is IPv4-only. 1418 1419 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 123456, dstIPv4); 1420 callback.expectError(PacketKeepalive.ERROR_INVALID_PORT); 1421 1422 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 123456, dstIPv4); 1423 callback.expectError(PacketKeepalive.ERROR_INVALID_PORT); 1424 1425 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4); 1426 callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED); 1427 1428 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4); 1429 callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED); 1430 1431 // Check that a started keepalive can be stopped. 1432 mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS); 1433 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4); 1434 callback.expectStarted(); 1435 mWiFiNetworkAgent.setStopKeepaliveError(PacketKeepalive.SUCCESS); 1436 ka.stop(); 1437 callback.expectStopped(); 1438 1439 // Check that deleting the IP address stops the keepalive. 1440 LinkProperties bogusLp = new LinkProperties(lp); 1441 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4); 1442 callback.expectStarted(); 1443 bogusLp.removeLinkAddress(new LinkAddress(myIPv4, 25)); 1444 bogusLp.addLinkAddress(new LinkAddress(notMyIPv4, 25)); 1445 mWiFiNetworkAgent.sendLinkProperties(bogusLp); 1446 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS); 1447 mWiFiNetworkAgent.sendLinkProperties(lp); 1448 1449 // Check that a started keepalive is stopped correctly when the network disconnects. 1450 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4); 1451 callback.expectStarted(); 1452 mWiFiNetworkAgent.disconnect(); 1453 callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK); 1454 1455 // ... and that stopping it after that has no adverse effects. 1456 assertNull(mCm.getNetworkCapabilities(myNet)); 1457 ka.stop(); 1458 1459 // Reconnect. 1460 myNet = connectKeepaliveNetwork(lp); 1461 mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS); 1462 1463 // Check things work as expected when the keepalive is stopped and the network disconnects. 1464 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4); 1465 callback.expectStarted(); 1466 ka.stop(); 1467 mWiFiNetworkAgent.disconnect(); 1468 mService.waitForIdle(); 1469 callback.expectStopped(); 1470 1471 // Reconnect. 1472 myNet = connectKeepaliveNetwork(lp); 1473 mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS); 1474 1475 // Check that keepalive slots start from 1 and increment. The first one gets slot 1. 1476 mWiFiNetworkAgent.setExpectedKeepaliveSlot(1); 1477 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4); 1478 callback.expectStarted(); 1479 1480 // The second one gets slot 2. 1481 mWiFiNetworkAgent.setExpectedKeepaliveSlot(2); 1482 TestKeepaliveCallback callback2 = new TestKeepaliveCallback(); 1483 PacketKeepalive ka2 = mCm.startNattKeepalive(myNet, 25, callback2, myIPv4, 6789, dstIPv4); 1484 callback2.expectStarted(); 1485 1486 // Now stop the first one and create a third. This also gets slot 1. 1487 ka.stop(); 1488 callback.expectStopped(); 1489 1490 mWiFiNetworkAgent.setExpectedKeepaliveSlot(1); 1491 TestKeepaliveCallback callback3 = new TestKeepaliveCallback(); 1492 PacketKeepalive ka3 = mCm.startNattKeepalive(myNet, 25, callback3, myIPv4, 9876, dstIPv4); 1493 callback3.expectStarted(); 1494 1495 ka2.stop(); 1496 callback2.expectStopped(); 1497 1498 ka3.stop(); 1499 callback3.expectStopped(); 1500 } 1501} 1502