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