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