2 * Copyright (C) 2012 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package com.android.server;
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.*;
26 import static org.mockito.Mockito.mock;
28 import android.app.NotificationManager;
29 import android.app.PendingIntent;
30 import android.content.BroadcastReceiver;
31 import android.content.ContentResolver;
32 import android.content.Context;
33 import android.content.ContextWrapper;
34 import android.content.Intent;
35 import android.content.IntentFilter;
36 import android.net.ConnectivityManager;
37 import android.net.ConnectivityManager.NetworkCallback;
38 import android.net.ConnectivityManager.PacketKeepalive;
39 import android.net.ConnectivityManager.PacketKeepaliveCallback;
40 import android.net.INetworkPolicyManager;
41 import android.net.INetworkStatsService;
42 import android.net.IpPrefix;
43 import android.net.LinkAddress;
44 import android.net.LinkProperties;
45 import android.net.Network;
46 import android.net.NetworkAgent;
47 import android.net.NetworkCapabilities;
48 import android.net.NetworkConfig;
49 import android.net.NetworkFactory;
50 import android.net.NetworkInfo;
51 import android.net.NetworkInfo.DetailedState;
52 import android.net.NetworkMisc;
53 import android.net.NetworkRequest;
54 import android.net.RouteInfo;
55 import android.net.metrics.IpConnectivityLog;
56 import android.net.util.AvoidBadWifiTracker;
57 import android.os.ConditionVariable;
58 import android.os.Handler;
59 import android.os.HandlerThread;
60 import android.os.IBinder;
61 import android.os.INetworkManagementService;
62 import android.os.Looper;
63 import android.os.Message;
64 import android.os.MessageQueue;
65 import android.os.Messenger;
66 import android.os.MessageQueue.IdleHandler;
67 import android.os.Process;
68 import android.os.SystemClock;
69 import android.provider.Settings;
70 import android.test.AndroidTestCase;
71 import android.test.FlakyTest;
72 import android.test.mock.MockContentResolver;
73 import android.test.suitebuilder.annotation.LargeTest;
74 import android.test.suitebuilder.annotation.SmallTest;
75 import android.util.Log;
76 import android.util.LogPrinter;
78 import com.android.internal.util.WakeupMessage;
79 import com.android.internal.util.test.BroadcastInterceptingContext;
80 import com.android.internal.util.test.FakeSettingsProvider;
81 import com.android.server.connectivity.NetworkAgentInfo;
82 import com.android.server.connectivity.NetworkMonitor;
83 import com.android.server.connectivity.NetworkMonitor.CaptivePortalProbeResult;
84 import com.android.server.net.NetworkPinner;
86 import java.net.InetAddress;
87 import java.util.ArrayList;
88 import java.util.Arrays;
89 import java.util.Objects;
90 import java.util.concurrent.CountDownLatch;
91 import java.util.concurrent.LinkedBlockingQueue;
92 import java.util.concurrent.TimeUnit;
93 import java.util.concurrent.atomic.AtomicBoolean;
96 * Tests for {@link ConnectivityService}.
98 * Build, install and run with:
99 * runtest frameworks-services -c com.android.server.ConnectivityServiceTest
101 public class ConnectivityServiceTest extends AndroidTestCase {
102 private static final String TAG = "ConnectivityServiceTest";
104 private static final int TIMEOUT_MS = 500;
105 private static final int TEST_LINGER_DELAY_MS = 120;
107 private BroadcastInterceptingContext mServiceContext;
108 private WrappedConnectivityService mService;
109 private WrappedConnectivityManager mCm;
110 private MockNetworkAgent mWiFiNetworkAgent;
111 private MockNetworkAgent mCellNetworkAgent;
112 private MockNetworkAgent mEthernetNetworkAgent;
114 // This class exists to test bindProcessToNetwork and getBoundNetworkForProcess. These methods
115 // do not go through ConnectivityService but talk to netd directly, so they don't automatically
116 // reflect the state of our test ConnectivityService.
117 private class WrappedConnectivityManager extends ConnectivityManager {
118 private Network mFakeBoundNetwork;
120 public synchronized boolean bindProcessToNetwork(Network network) {
121 mFakeBoundNetwork = network;
125 public synchronized Network getBoundNetworkForProcess() {
126 return mFakeBoundNetwork;
129 public WrappedConnectivityManager(Context context, ConnectivityService service) {
130 super(context, service);
134 private class MockContext extends BroadcastInterceptingContext {
135 private final MockContentResolver mContentResolver;
137 MockContext(Context base) {
139 mContentResolver = new MockContentResolver();
140 mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
144 public Object getSystemService(String name) {
145 if (Context.CONNECTIVITY_SERVICE.equals(name)) return mCm;
146 if (Context.NOTIFICATION_SERVICE.equals(name)) return mock(NotificationManager.class);
147 return super.getSystemService(name);
151 public ContentResolver getContentResolver() {
152 return mContentResolver;
157 * A subclass of HandlerThread that allows callers to wait for it to become idle. waitForIdle
158 * will return immediately if the handler is already idle.
160 private class IdleableHandlerThread extends HandlerThread {
161 private IdleHandler mIdleHandler;
163 public IdleableHandlerThread(String name) {
167 public void waitForIdle(int timeoutMs) {
168 final ConditionVariable cv = new ConditionVariable();
169 final MessageQueue queue = getLooper().getQueue();
171 synchronized (queue) {
172 if (queue.isIdle()) {
176 assertNull("BUG: only one idle handler allowed", mIdleHandler);
177 mIdleHandler = new IdleHandler() {
178 public boolean queueIdle() {
179 synchronized (queue) {
182 return false; // Remove the handler.
186 queue.addIdleHandler(mIdleHandler);
189 if (!cv.block(timeoutMs)) {
190 fail("HandlerThread " + getName() +
191 " did not become idle after " + timeoutMs + " ms");
192 queue.removeIdleHandler(mIdleHandler);
197 // Tests that IdleableHandlerThread works as expected.
198 public void testIdleableHandlerThread() {
199 final int attempts = 50; // Causes the test to take about 200ms on bullhead-eng.
201 // Tests that waitForIdle returns immediately if the service is already idle.
202 for (int i = 0; i < attempts; i++) {
203 mService.waitForIdle();
206 // Bring up a network that we can use to send messages to ConnectivityService.
207 ConditionVariable cv = waitForConnectivityBroadcasts(1);
208 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
209 mWiFiNetworkAgent.connect(false);
211 Network n = mWiFiNetworkAgent.getNetwork();
214 // Tests that calling waitForIdle waits for messages to be processed.
215 for (int i = 0; i < attempts; i++) {
216 mWiFiNetworkAgent.setSignalStrength(i);
217 mService.waitForIdle();
218 assertEquals(i, mCm.getNetworkCapabilities(n).getSignalStrength());
222 @FlakyTest(tolerance = 3)
223 public void testNotWaitingForIdleCausesRaceConditions() {
224 // Bring up a network that we can use to send messages to ConnectivityService.
225 ConditionVariable cv = waitForConnectivityBroadcasts(1);
226 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
227 mWiFiNetworkAgent.connect(false);
229 Network n = mWiFiNetworkAgent.getNetwork();
232 // Ensure that not calling waitForIdle causes a race condition.
233 final int attempts = 50; // Causes the test to take about 200ms on bullhead-eng.
234 for (int i = 0; i < attempts; i++) {
235 mWiFiNetworkAgent.setSignalStrength(i);
236 if (i != mCm.getNetworkCapabilities(n).getSignalStrength()) {
237 // We hit a race condition, as expected. Pass the test.
242 // No race? There is a bug in this test.
243 fail("expected race condition at least once in " + attempts + " attempts");
246 private class MockNetworkAgent {
247 private final WrappedNetworkMonitor mWrappedNetworkMonitor;
248 private final NetworkInfo mNetworkInfo;
249 private final NetworkCapabilities mNetworkCapabilities;
250 private final IdleableHandlerThread mHandlerThread;
251 private final ConditionVariable mDisconnected = new ConditionVariable();
252 private final ConditionVariable mNetworkStatusReceived = new ConditionVariable();
253 private final ConditionVariable mPreventReconnectReceived = new ConditionVariable();
255 private NetworkAgent mNetworkAgent;
256 private int mStartKeepaliveError = PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED;
257 private int mStopKeepaliveError = PacketKeepalive.NO_KEEPALIVE;
258 private Integer mExpectedKeepaliveSlot = null;
259 // Contains the redirectUrl from networkStatus(). Before reading, wait for
260 // mNetworkStatusReceived.
261 private String mRedirectUrl;
263 MockNetworkAgent(int transport) {
264 final int type = transportToLegacyType(transport);
265 final String typeName = ConnectivityManager.getNetworkTypeName(type);
266 mNetworkInfo = new NetworkInfo(type, 0, typeName, "Mock");
267 mNetworkCapabilities = new NetworkCapabilities();
268 mNetworkCapabilities.addTransportType(transport);
270 case TRANSPORT_ETHERNET:
276 case TRANSPORT_CELLULAR:
280 throw new UnsupportedOperationException("unimplemented network type");
282 mHandlerThread = new IdleableHandlerThread("Mock-" + typeName);
283 mHandlerThread.start();
284 mNetworkAgent = new NetworkAgent(mHandlerThread.getLooper(), mServiceContext,
285 "Mock-" + typeName, mNetworkInfo, mNetworkCapabilities,
286 new LinkProperties(), mScore, new NetworkMisc()) {
288 public void unwanted() { mDisconnected.open(); }
291 public void startPacketKeepalive(Message msg) {
293 if (mExpectedKeepaliveSlot != null) {
294 assertEquals((int) mExpectedKeepaliveSlot, slot);
296 onPacketKeepaliveEvent(slot, mStartKeepaliveError);
300 public void stopPacketKeepalive(Message msg) {
301 onPacketKeepaliveEvent(msg.arg1, mStopKeepaliveError);
305 public void networkStatus(int status, String redirectUrl) {
306 mRedirectUrl = redirectUrl;
307 mNetworkStatusReceived.open();
311 protected void preventAutomaticReconnect() {
312 mPreventReconnectReceived.open();
315 // Waits for the NetworkAgent to be registered, which includes the creation of the
317 mService.waitForIdle();
318 mWrappedNetworkMonitor = mService.getLastCreatedWrappedNetworkMonitor();
321 public void waitForIdle(int timeoutMs) {
322 mHandlerThread.waitForIdle(timeoutMs);
325 public void waitForIdle() {
326 waitForIdle(TIMEOUT_MS);
329 public void adjustScore(int change) {
331 mNetworkAgent.sendNetworkScore(mScore);
334 public void addCapability(int capability) {
335 mNetworkCapabilities.addCapability(capability);
336 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
339 public void removeCapability(int capability) {
340 mNetworkCapabilities.removeCapability(capability);
341 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
344 public void setSignalStrength(int signalStrength) {
345 mNetworkCapabilities.setSignalStrength(signalStrength);
346 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
349 public void connectWithoutInternet() {
350 mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, null);
351 mNetworkAgent.sendNetworkInfo(mNetworkInfo);
355 * Transition this NetworkAgent to CONNECTED state with NET_CAPABILITY_INTERNET.
356 * @param validated Indicate if network should pretend to be validated.
358 public void connect(boolean validated) {
359 assertEquals("MockNetworkAgents can only be connected once",
360 mNetworkInfo.getDetailedState(), DetailedState.IDLE);
361 assertFalse(mNetworkCapabilities.hasCapability(NET_CAPABILITY_INTERNET));
363 NetworkCallback callback = null;
364 final ConditionVariable validatedCv = new ConditionVariable();
366 mWrappedNetworkMonitor.gen204ProbeResult = 204;
367 NetworkRequest request = new NetworkRequest.Builder()
368 .addTransportType(mNetworkCapabilities.getTransportTypes()[0])
370 callback = new NetworkCallback() {
371 public void onCapabilitiesChanged(Network network,
372 NetworkCapabilities networkCapabilities) {
373 if (network.equals(getNetwork()) &&
374 networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED)) {
379 mCm.registerNetworkCallback(request, callback);
381 addCapability(NET_CAPABILITY_INTERNET);
383 connectWithoutInternet();
386 // Wait for network to validate.
387 waitFor(validatedCv);
388 mWrappedNetworkMonitor.gen204ProbeResult = 500;
391 if (callback != null) mCm.unregisterNetworkCallback(callback);
394 public void connectWithCaptivePortal(String redirectUrl) {
395 mWrappedNetworkMonitor.gen204ProbeResult = 200;
396 mWrappedNetworkMonitor.gen204ProbeRedirectUrl = redirectUrl;
400 public void disconnect() {
401 mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, null);
402 mNetworkAgent.sendNetworkInfo(mNetworkInfo);
405 public Network getNetwork() {
406 return new Network(mNetworkAgent.netId);
409 public ConditionVariable getPreventReconnectReceived() {
410 return mPreventReconnectReceived;
413 public ConditionVariable getDisconnectedCV() {
414 return mDisconnected;
417 public WrappedNetworkMonitor getWrappedNetworkMonitor() {
418 return mWrappedNetworkMonitor;
421 public void sendLinkProperties(LinkProperties lp) {
422 mNetworkAgent.sendLinkProperties(lp);
425 public void setStartKeepaliveError(int error) {
426 mStartKeepaliveError = error;
429 public void setStopKeepaliveError(int error) {
430 mStopKeepaliveError = error;
433 public void setExpectedKeepaliveSlot(Integer slot) {
434 mExpectedKeepaliveSlot = slot;
437 public String waitForRedirectUrl() {
438 assertTrue(mNetworkStatusReceived.block(TIMEOUT_MS));
444 * A NetworkFactory that allows tests to wait until any in-flight NetworkRequest add or remove
445 * operations have been processed. Before ConnectivityService can add or remove any requests,
446 * the factory must be told to expect those operations by calling expectAddRequests or
447 * expectRemoveRequests.
449 private static class MockNetworkFactory extends NetworkFactory {
450 private final ConditionVariable mNetworkStartedCV = new ConditionVariable();
451 private final ConditionVariable mNetworkStoppedCV = new ConditionVariable();
452 private final AtomicBoolean mNetworkStarted = new AtomicBoolean(false);
454 // Used to expect that requests be removed or added on a separate thread, without sleeping.
455 // Callers can call either expectAddRequests() or expectRemoveRequests() exactly once, then
456 // cause some other thread to add or remove requests, then call waitForRequests(). We can
457 // either expect requests to be added or removed, but not both, because CountDownLatch can
458 // only count in one direction.
459 private CountDownLatch mExpectations;
461 // Whether we are currently expecting requests to be added or removed. Valid only if
462 // mExpectations is non-null.
463 private boolean mExpectingAdditions;
465 public MockNetworkFactory(Looper looper, Context context, String logTag,
466 NetworkCapabilities filter) {
467 super(looper, context, logTag, filter);
470 public int getMyRequestCount() {
471 return getRequestCount();
474 protected void startNetwork() {
475 mNetworkStarted.set(true);
476 mNetworkStartedCV.open();
479 protected void stopNetwork() {
480 mNetworkStarted.set(false);
481 mNetworkStoppedCV.open();
484 public boolean getMyStartRequested() {
485 return mNetworkStarted.get();
488 public ConditionVariable getNetworkStartedCV() {
489 mNetworkStartedCV.close();
490 return mNetworkStartedCV;
493 public ConditionVariable getNetworkStoppedCV() {
494 mNetworkStoppedCV.close();
495 return mNetworkStoppedCV;
499 protected void handleAddRequest(NetworkRequest request, int score) {
500 // If we're expecting anything, we must be expecting additions.
501 if (mExpectations != null && !mExpectingAdditions) {
502 fail("Can't add requests while expecting requests to be removed");
506 super.handleAddRequest(request, score);
508 // Reduce the number of request additions we're waiting for.
509 if (mExpectingAdditions) {
510 assertTrue("Added more requests than expected", mExpectations.getCount() > 0);
511 mExpectations.countDown();
516 protected void handleRemoveRequest(NetworkRequest request) {
517 // If we're expecting anything, we must be expecting removals.
518 if (mExpectations != null && mExpectingAdditions) {
519 fail("Can't remove requests while expecting requests to be added");
522 // Remove the request.
523 super.handleRemoveRequest(request);
525 // Reduce the number of request removals we're waiting for.
526 if (!mExpectingAdditions) {
527 assertTrue("Removed more requests than expected", mExpectations.getCount() > 0);
528 mExpectations.countDown();
532 private void assertNoExpectations() {
533 if (mExpectations != null) {
534 fail("Can't add expectation, " + mExpectations.getCount() + " already pending");
538 // Expects that count requests will be added.
539 public void expectAddRequests(final int count) {
540 assertNoExpectations();
541 mExpectingAdditions = true;
542 mExpectations = new CountDownLatch(count);
545 // Expects that count requests will be removed.
546 public void expectRemoveRequests(final int count) {
547 assertNoExpectations();
548 mExpectingAdditions = false;
549 mExpectations = new CountDownLatch(count);
552 // Waits for the expected request additions or removals to happen within a timeout.
553 public void waitForRequests() throws InterruptedException {
554 assertNotNull("Nothing to wait for", mExpectations);
555 mExpectations.await(TIMEOUT_MS, TimeUnit.MILLISECONDS);
556 final long count = mExpectations.getCount();
557 final String msg = count + " requests still not " +
558 (mExpectingAdditions ? "added" : "removed") +
559 " after " + TIMEOUT_MS + " ms";
560 assertEquals(msg, 0, count);
561 mExpectations = null;
564 public void waitForNetworkRequests(final int count) throws InterruptedException {
566 assertEquals(count, getMyRequestCount());
570 private class FakeWakeupMessage extends WakeupMessage {
571 private static final int UNREASONABLY_LONG_WAIT = 1000;
573 public FakeWakeupMessage(Context context, Handler handler, String cmdName, int cmd) {
574 super(context, handler, cmdName, cmd);
577 public FakeWakeupMessage(Context context, Handler handler, String cmdName, int cmd,
578 int arg1, int arg2, Object obj) {
579 super(context, handler, cmdName, cmd, arg1, arg2, obj);
583 public void schedule(long when) {
584 long delayMs = when - SystemClock.elapsedRealtime();
585 if (delayMs < 0) delayMs = 0;
586 if (delayMs > UNREASONABLY_LONG_WAIT) {
587 fail("Attempting to send msg more than " + UNREASONABLY_LONG_WAIT +
588 "ms into the future: " + delayMs);
590 Message msg = mHandler.obtainMessage(mCmd, mArg1, mArg2, mObj);
591 mHandler.sendMessageDelayed(msg, delayMs);
595 public void cancel() {
596 mHandler.removeMessages(mCmd, mObj);
600 public void onAlarm() {
601 throw new AssertionError("Should never happen. Update this fake.");
605 // NetworkMonitor implementation allowing overriding of Internet connectivity probe result.
606 private class WrappedNetworkMonitor extends NetworkMonitor {
607 // HTTP response code fed back to NetworkMonitor for Internet connectivity probe.
608 public int gen204ProbeResult = 500;
609 public String gen204ProbeRedirectUrl = null;
611 public WrappedNetworkMonitor(Context context, Handler handler,
612 NetworkAgentInfo networkAgentInfo, NetworkRequest defaultRequest,
613 IpConnectivityLog log) {
614 super(context, handler, networkAgentInfo, defaultRequest, log);
618 protected CaptivePortalProbeResult isCaptivePortal() {
619 if (!mIsCaptivePortalCheckEnabled) { return new CaptivePortalProbeResult(204); }
620 return new CaptivePortalProbeResult(gen204ProbeResult, gen204ProbeRedirectUrl, null);
624 private class WrappedAvoidBadWifiTracker extends AvoidBadWifiTracker {
625 public boolean configRestrictsAvoidBadWifi;
627 public WrappedAvoidBadWifiTracker(Context c, Handler h, Runnable r) {
632 public boolean configRestrictsAvoidBadWifi() {
633 return configRestrictsAvoidBadWifi;
637 private class WrappedConnectivityService extends ConnectivityService {
638 public WrappedAvoidBadWifiTracker wrappedAvoidBadWifiTracker;
639 private WrappedNetworkMonitor mLastCreatedNetworkMonitor;
641 public WrappedConnectivityService(Context context, INetworkManagementService netManager,
642 INetworkStatsService statsService, INetworkPolicyManager policyManager,
643 IpConnectivityLog log) {
644 super(context, netManager, statsService, policyManager, log);
645 mLingerDelayMs = TEST_LINGER_DELAY_MS;
649 protected HandlerThread createHandlerThread() {
650 return new IdleableHandlerThread("WrappedConnectivityService");
654 protected int getDefaultTcpRwnd() {
655 // Prevent wrapped ConnectivityService from trying to write to SystemProperties.
660 protected int reserveNetId() {
662 final int netId = super.reserveNetId();
664 // Don't overlap test NetIDs with real NetIDs as binding sockets to real networks
665 // can have odd side-effects, like network validations succeeding.
666 final Network[] networks = ConnectivityManager.from(getContext()).getAllNetworks();
667 boolean overlaps = false;
668 for (Network network : networks) {
669 if (netId == network.netId) {
674 if (overlaps) continue;
681 public NetworkMonitor createNetworkMonitor(Context context, Handler handler,
682 NetworkAgentInfo nai, NetworkRequest defaultRequest) {
683 final WrappedNetworkMonitor monitor = new WrappedNetworkMonitor(
684 context, handler, nai, defaultRequest, mock(IpConnectivityLog.class));
685 mLastCreatedNetworkMonitor = monitor;
690 public AvoidBadWifiTracker createAvoidBadWifiTracker(
691 Context c, Handler h, Runnable r) {
692 final WrappedAvoidBadWifiTracker tracker = new WrappedAvoidBadWifiTracker(c, h, r);
696 public WrappedAvoidBadWifiTracker getAvoidBadWifiTracker() {
697 return (WrappedAvoidBadWifiTracker) mAvoidBadWifiTracker;
701 public WakeupMessage makeWakeupMessage(
702 Context context, Handler handler, String cmdName, int cmd, Object obj) {
703 return new FakeWakeupMessage(context, handler, cmdName, cmd, 0, 0, obj);
706 public WrappedNetworkMonitor getLastCreatedWrappedNetworkMonitor() {
707 return mLastCreatedNetworkMonitor;
710 public void waitForIdle(int timeoutMs) {
711 ((IdleableHandlerThread) mHandlerThread).waitForIdle(timeoutMs);
714 public void waitForIdle() {
715 waitForIdle(TIMEOUT_MS);
719 private interface Criteria {
720 public boolean get();
724 * Wait up to 500ms for {@code criteria.get()} to become true, polling.
725 * Fails if 500ms goes by before {@code criteria.get()} to become true.
727 static private void waitFor(Criteria criteria) {
729 while (!criteria.get()) {
731 if (++delays == 10) fail();
736 * Wait up to TIMEOUT_MS for {@code conditionVariable} to open.
737 * Fails if TIMEOUT_MS goes by before {@code conditionVariable} opens.
739 static private void waitFor(ConditionVariable conditionVariable) {
740 assertTrue(conditionVariable.block(TIMEOUT_MS));
744 public void setUp() throws Exception {
747 // InstrumentationTestRunner prepares a looper, but AndroidJUnitRunner does not.
748 // http://b/25897652 .
749 if (Looper.myLooper() == null) {
753 mServiceContext = new MockContext(getContext());
754 mService = new WrappedConnectivityService(mServiceContext,
755 mock(INetworkManagementService.class),
756 mock(INetworkStatsService.class),
757 mock(INetworkPolicyManager.class),
758 mock(IpConnectivityLog.class));
760 mService.systemReady();
761 mCm = new WrappedConnectivityManager(getContext(), mService);
762 mCm.bindProcessToNetwork(null);
764 // Ensure that the default setting for Captive Portals is used for most tests
765 setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_PROMPT);
768 public void tearDown() throws Exception {
769 setMobileDataAlwaysOn(false);
770 if (mCellNetworkAgent != null) { mCellNetworkAgent.disconnect(); }
771 if (mWiFiNetworkAgent != null) { mWiFiNetworkAgent.disconnect(); }
772 mCellNetworkAgent = mWiFiNetworkAgent = null;
776 private int transportToLegacyType(int transport) {
778 case TRANSPORT_ETHERNET:
779 return TYPE_ETHERNET;
782 case TRANSPORT_CELLULAR:
785 throw new IllegalStateException("Unknown transport " + transport);
789 private void verifyActiveNetwork(int transport) {
790 // Test getActiveNetworkInfo()
791 assertNotNull(mCm.getActiveNetworkInfo());
792 assertEquals(transportToLegacyType(transport), mCm.getActiveNetworkInfo().getType());
793 // Test getActiveNetwork()
794 assertNotNull(mCm.getActiveNetwork());
795 assertEquals(mCm.getActiveNetwork(), mCm.getActiveNetworkForUid(Process.myUid()));
798 assertEquals(mCm.getActiveNetwork(), mWiFiNetworkAgent.getNetwork());
800 case TRANSPORT_CELLULAR:
801 assertEquals(mCm.getActiveNetwork(), mCellNetworkAgent.getNetwork());
804 throw new IllegalStateException("Unknown transport" + transport);
806 // Test getNetworkInfo(Network)
807 assertNotNull(mCm.getNetworkInfo(mCm.getActiveNetwork()));
808 assertEquals(transportToLegacyType(transport), mCm.getNetworkInfo(mCm.getActiveNetwork()).getType());
809 // Test getNetworkCapabilities(Network)
810 assertNotNull(mCm.getNetworkCapabilities(mCm.getActiveNetwork()));
811 assertTrue(mCm.getNetworkCapabilities(mCm.getActiveNetwork()).hasTransport(transport));
814 private void verifyNoNetwork() {
815 // Test getActiveNetworkInfo()
816 assertNull(mCm.getActiveNetworkInfo());
817 // Test getActiveNetwork()
818 assertNull(mCm.getActiveNetwork());
819 assertNull(mCm.getActiveNetworkForUid(Process.myUid()));
820 // Test getAllNetworks()
821 assertEquals(0, mCm.getAllNetworks().length);
825 * Return a ConditionVariable that opens when {@code count} numbers of CONNECTIVITY_ACTION
826 * broadcasts are received.
828 private ConditionVariable waitForConnectivityBroadcasts(final int count) {
829 final ConditionVariable cv = new ConditionVariable();
830 mServiceContext.registerReceiver(new BroadcastReceiver() {
831 private int remaining = count;
832 public void onReceive(Context context, Intent intent) {
833 if (--remaining == 0) {
835 mServiceContext.unregisterReceiver(this);
838 }, new IntentFilter(CONNECTIVITY_ACTION));
843 public void testLingering() throws Exception {
845 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
846 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
847 assertNull(mCm.getActiveNetworkInfo());
848 assertNull(mCm.getActiveNetwork());
849 // Test bringing up validated cellular.
850 ConditionVariable cv = waitForConnectivityBroadcasts(1);
851 mCellNetworkAgent.connect(true);
853 verifyActiveNetwork(TRANSPORT_CELLULAR);
854 assertEquals(2, mCm.getAllNetworks().length);
855 assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) ||
856 mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork()));
857 assertTrue(mCm.getAllNetworks()[0].equals(mWiFiNetworkAgent.getNetwork()) ||
858 mCm.getAllNetworks()[1].equals(mWiFiNetworkAgent.getNetwork()));
859 // Test bringing up validated WiFi.
860 cv = waitForConnectivityBroadcasts(2);
861 mWiFiNetworkAgent.connect(true);
863 verifyActiveNetwork(TRANSPORT_WIFI);
864 assertEquals(2, mCm.getAllNetworks().length);
865 assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) ||
866 mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork()));
867 assertTrue(mCm.getAllNetworks()[0].equals(mCellNetworkAgent.getNetwork()) ||
868 mCm.getAllNetworks()[1].equals(mCellNetworkAgent.getNetwork()));
869 // Test cellular linger timeout.
870 waitFor(new Criteria() {
871 public boolean get() { return mCm.getAllNetworks().length == 1; } });
872 verifyActiveNetwork(TRANSPORT_WIFI);
873 assertEquals(1, mCm.getAllNetworks().length);
874 assertEquals(mCm.getAllNetworks()[0], mCm.getActiveNetwork());
875 // Test WiFi disconnect.
876 cv = waitForConnectivityBroadcasts(1);
877 mWiFiNetworkAgent.disconnect();
883 public void testValidatedCellularOutscoresUnvalidatedWiFi() throws Exception {
884 // Test bringing up unvalidated WiFi
885 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
886 ConditionVariable cv = waitForConnectivityBroadcasts(1);
887 mWiFiNetworkAgent.connect(false);
889 verifyActiveNetwork(TRANSPORT_WIFI);
890 // Test bringing up unvalidated cellular
891 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
892 mCellNetworkAgent.connect(false);
893 mService.waitForIdle();
894 verifyActiveNetwork(TRANSPORT_WIFI);
895 // Test cellular disconnect.
896 mCellNetworkAgent.disconnect();
897 mService.waitForIdle();
898 verifyActiveNetwork(TRANSPORT_WIFI);
899 // Test bringing up validated cellular
900 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
901 cv = waitForConnectivityBroadcasts(2);
902 mCellNetworkAgent.connect(true);
904 verifyActiveNetwork(TRANSPORT_CELLULAR);
905 // Test cellular disconnect.
906 cv = waitForConnectivityBroadcasts(2);
907 mCellNetworkAgent.disconnect();
909 verifyActiveNetwork(TRANSPORT_WIFI);
910 // Test WiFi disconnect.
911 cv = waitForConnectivityBroadcasts(1);
912 mWiFiNetworkAgent.disconnect();
918 public void testUnvalidatedWifiOutscoresUnvalidatedCellular() throws Exception {
919 // Test bringing up unvalidated cellular.
920 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
921 ConditionVariable cv = waitForConnectivityBroadcasts(1);
922 mCellNetworkAgent.connect(false);
924 verifyActiveNetwork(TRANSPORT_CELLULAR);
925 // Test bringing up unvalidated WiFi.
926 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
927 cv = waitForConnectivityBroadcasts(2);
928 mWiFiNetworkAgent.connect(false);
930 verifyActiveNetwork(TRANSPORT_WIFI);
931 // Test WiFi disconnect.
932 cv = waitForConnectivityBroadcasts(2);
933 mWiFiNetworkAgent.disconnect();
935 verifyActiveNetwork(TRANSPORT_CELLULAR);
936 // Test cellular disconnect.
937 cv = waitForConnectivityBroadcasts(1);
938 mCellNetworkAgent.disconnect();
944 public void testUnlingeringDoesNotValidate() throws Exception {
945 // Test bringing up unvalidated WiFi.
946 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
947 ConditionVariable cv = waitForConnectivityBroadcasts(1);
948 mWiFiNetworkAgent.connect(false);
950 verifyActiveNetwork(TRANSPORT_WIFI);
951 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
952 NET_CAPABILITY_VALIDATED));
953 // Test bringing up validated cellular.
954 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
955 cv = waitForConnectivityBroadcasts(2);
956 mCellNetworkAgent.connect(true);
958 verifyActiveNetwork(TRANSPORT_CELLULAR);
959 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
960 NET_CAPABILITY_VALIDATED));
961 // Test cellular disconnect.
962 cv = waitForConnectivityBroadcasts(2);
963 mCellNetworkAgent.disconnect();
965 verifyActiveNetwork(TRANSPORT_WIFI);
966 // Unlingering a network should not cause it to be marked as validated.
967 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
968 NET_CAPABILITY_VALIDATED));
972 public void testCellularOutscoresWeakWifi() throws Exception {
973 // Test bringing up validated cellular.
974 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
975 ConditionVariable cv = waitForConnectivityBroadcasts(1);
976 mCellNetworkAgent.connect(true);
978 verifyActiveNetwork(TRANSPORT_CELLULAR);
979 // Test bringing up validated WiFi.
980 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
981 cv = waitForConnectivityBroadcasts(2);
982 mWiFiNetworkAgent.connect(true);
984 verifyActiveNetwork(TRANSPORT_WIFI);
985 // Test WiFi getting really weak.
986 cv = waitForConnectivityBroadcasts(2);
987 mWiFiNetworkAgent.adjustScore(-11);
989 verifyActiveNetwork(TRANSPORT_CELLULAR);
990 // Test WiFi restoring signal strength.
991 cv = waitForConnectivityBroadcasts(2);
992 mWiFiNetworkAgent.adjustScore(11);
994 verifyActiveNetwork(TRANSPORT_WIFI);
998 public void testReapingNetwork() throws Exception {
999 // Test bringing up WiFi without NET_CAPABILITY_INTERNET.
1000 // Expect it to be torn down immediately because it satisfies no requests.
1001 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1002 ConditionVariable cv = mWiFiNetworkAgent.getDisconnectedCV();
1003 mWiFiNetworkAgent.connectWithoutInternet();
1005 // Test bringing up cellular without NET_CAPABILITY_INTERNET.
1006 // Expect it to be torn down immediately because it satisfies no requests.
1007 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1008 cv = mCellNetworkAgent.getDisconnectedCV();
1009 mCellNetworkAgent.connectWithoutInternet();
1011 // Test bringing up validated WiFi.
1012 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1013 cv = waitForConnectivityBroadcasts(1);
1014 mWiFiNetworkAgent.connect(true);
1016 verifyActiveNetwork(TRANSPORT_WIFI);
1017 // Test bringing up unvalidated cellular.
1018 // Expect it to be torn down because it could never be the highest scoring network
1019 // satisfying the default request even if it validated.
1020 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1021 cv = mCellNetworkAgent.getDisconnectedCV();
1022 mCellNetworkAgent.connect(false);
1024 verifyActiveNetwork(TRANSPORT_WIFI);
1025 cv = mWiFiNetworkAgent.getDisconnectedCV();
1026 mWiFiNetworkAgent.disconnect();
1031 public void testCellularFallback() throws Exception {
1032 // Test bringing up validated cellular.
1033 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1034 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1035 mCellNetworkAgent.connect(true);
1037 verifyActiveNetwork(TRANSPORT_CELLULAR);
1038 // Test bringing up validated WiFi.
1039 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1040 cv = waitForConnectivityBroadcasts(2);
1041 mWiFiNetworkAgent.connect(true);
1043 verifyActiveNetwork(TRANSPORT_WIFI);
1044 // Reevaluate WiFi (it'll instantly fail DNS).
1045 cv = waitForConnectivityBroadcasts(2);
1046 assertTrue(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1047 NET_CAPABILITY_VALIDATED));
1048 mCm.reportBadNetwork(mWiFiNetworkAgent.getNetwork());
1049 // Should quickly fall back to Cellular.
1051 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1052 NET_CAPABILITY_VALIDATED));
1053 verifyActiveNetwork(TRANSPORT_CELLULAR);
1054 // Reevaluate cellular (it'll instantly fail DNS).
1055 cv = waitForConnectivityBroadcasts(2);
1056 assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1057 NET_CAPABILITY_VALIDATED));
1058 mCm.reportBadNetwork(mCellNetworkAgent.getNetwork());
1059 // Should quickly fall back to WiFi.
1061 assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1062 NET_CAPABILITY_VALIDATED));
1063 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1064 NET_CAPABILITY_VALIDATED));
1065 verifyActiveNetwork(TRANSPORT_WIFI);
1069 public void testWiFiFallback() throws Exception {
1070 // Test bringing up unvalidated WiFi.
1071 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1072 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1073 mWiFiNetworkAgent.connect(false);
1075 verifyActiveNetwork(TRANSPORT_WIFI);
1076 // Test bringing up validated cellular.
1077 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1078 cv = waitForConnectivityBroadcasts(2);
1079 mCellNetworkAgent.connect(true);
1081 verifyActiveNetwork(TRANSPORT_CELLULAR);
1082 // Reevaluate cellular (it'll instantly fail DNS).
1083 cv = waitForConnectivityBroadcasts(2);
1084 assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1085 NET_CAPABILITY_VALIDATED));
1086 mCm.reportBadNetwork(mCellNetworkAgent.getNetwork());
1087 // Should quickly fall back to WiFi.
1089 assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1090 NET_CAPABILITY_VALIDATED));
1091 verifyActiveNetwork(TRANSPORT_WIFI);
1094 enum CallbackState {
1097 NETWORK_CAPABILITIES,
1104 private static class CallbackInfo {
1105 public final CallbackState state;
1106 public final Network network;
1107 public final Object arg;
1108 public CallbackInfo(CallbackState s, Network n, Object o) {
1109 state = s; network = n; arg = o;
1111 public String toString() {
1112 return String.format("%s (%s)", state, network);
1115 public boolean equals(Object o) {
1116 if (!(o instanceof CallbackInfo)) return false;
1117 // Ignore timeMs, since it's unpredictable.
1118 CallbackInfo other = (CallbackInfo) o;
1119 return (state == other.state) && Objects.equals(network, other.network);
1122 public int hashCode() {
1123 return Objects.hash(state, network);
1128 * Utility NetworkCallback for testing. The caller must explicitly test for all the callbacks
1129 * this class receives, by calling expectCallback() exactly once each time a callback is
1130 * received. assertNoCallback may be called at any time.
1132 private class TestNetworkCallback extends NetworkCallback {
1133 // Chosen to be much less than the linger timeout. This ensures that we can distinguish
1134 // between a LOST callback that arrives immediately and a LOST callback that arrives after
1135 // the linger timeout.
1136 private final static int TIMEOUT_MS = 50;
1138 private final LinkedBlockingQueue<CallbackInfo> mCallbacks = new LinkedBlockingQueue<>();
1140 protected void setLastCallback(CallbackState state, Network network, Object o) {
1141 mCallbacks.offer(new CallbackInfo(state, network, o));
1145 public void onAvailable(Network network) {
1146 setLastCallback(CallbackState.AVAILABLE, network, null);
1150 public void onUnavailable() {
1151 setLastCallback(CallbackState.UNAVAILABLE, null, null);
1155 public void onLosing(Network network, int maxMsToLive) {
1156 setLastCallback(CallbackState.LOSING, network, maxMsToLive /* autoboxed int */);
1160 public void onLost(Network network) {
1161 setLastCallback(CallbackState.LOST, network, null);
1164 CallbackInfo nextCallback(int timeoutMs) {
1165 CallbackInfo cb = null;
1167 cb = mCallbacks.poll(timeoutMs, TimeUnit.MILLISECONDS);
1168 } catch (InterruptedException e) {
1171 // LinkedBlockingQueue.poll() returns null if it timeouts.
1172 fail("Did not receive callback after " + timeoutMs + "ms");
1177 void expectCallback(CallbackState state, MockNetworkAgent mockAgent, int timeoutMs) {
1178 CallbackInfo expected = new CallbackInfo(
1179 state, (mockAgent != null) ? mockAgent.getNetwork() : null, 0);
1180 CallbackInfo actual = nextCallback(timeoutMs);
1181 assertEquals("Unexpected callback:", expected, actual);
1182 if (state == CallbackState.LOSING) {
1183 String msg = String.format(
1184 "Invalid linger time value %d, must be between %d and %d",
1185 actual.arg, 0, TEST_LINGER_DELAY_MS);
1186 int maxMsToLive = (Integer) actual.arg;
1187 assertTrue(msg, 0 <= maxMsToLive && maxMsToLive <= TEST_LINGER_DELAY_MS);
1191 void expectCallback(CallbackState state, MockNetworkAgent mockAgent) {
1192 expectCallback(state, mockAgent, TIMEOUT_MS);
1195 void assertNoCallback() {
1196 mService.waitForIdle();
1197 CallbackInfo c = mCallbacks.peek();
1198 assertNull("Unexpected callback: " + c, c);
1202 // Can't be part of TestNetworkCallback because "cannot be declared static; static methods can
1203 // only be declared in a static or top level type".
1204 static void assertNoCallbacks(TestNetworkCallback ... callbacks) {
1205 for (TestNetworkCallback c : callbacks) {
1206 c.assertNoCallback();
1211 public void testStateChangeNetworkCallbacks() throws Exception {
1212 final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback();
1213 final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
1214 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
1215 final NetworkRequest genericRequest = new NetworkRequest.Builder()
1216 .clearCapabilities().build();
1217 final NetworkRequest wifiRequest = new NetworkRequest.Builder()
1218 .addTransportType(TRANSPORT_WIFI).build();
1219 final NetworkRequest cellRequest = new NetworkRequest.Builder()
1220 .addTransportType(TRANSPORT_CELLULAR).build();
1221 mCm.registerNetworkCallback(genericRequest, genericNetworkCallback);
1222 mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
1223 mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
1225 // Test unvalidated networks
1226 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1227 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1228 mCellNetworkAgent.connect(false);
1229 genericNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1230 cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1231 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1233 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
1235 // This should not trigger spurious onAvailable() callbacks, b/21762680.
1236 mCellNetworkAgent.adjustScore(-1);
1237 mService.waitForIdle();
1238 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
1239 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1241 cv = waitForConnectivityBroadcasts(2);
1242 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1243 mWiFiNetworkAgent.connect(false);
1244 genericNetworkCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1245 wifiNetworkCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1246 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1248 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
1250 cv = waitForConnectivityBroadcasts(2);
1251 mWiFiNetworkAgent.disconnect();
1252 genericNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1253 wifiNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1254 cellNetworkCallback.assertNoCallback();
1256 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
1258 cv = waitForConnectivityBroadcasts(1);
1259 mCellNetworkAgent.disconnect();
1260 genericNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1261 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1263 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
1265 // Test validated networks
1266 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1267 mCellNetworkAgent.connect(true);
1268 genericNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1269 cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1270 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1271 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
1273 // This should not trigger spurious onAvailable() callbacks, b/21762680.
1274 mCellNetworkAgent.adjustScore(-1);
1275 mService.waitForIdle();
1276 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
1277 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1279 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1280 mWiFiNetworkAgent.connect(true);
1281 genericNetworkCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1282 genericNetworkCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
1283 wifiNetworkCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1284 cellNetworkCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
1285 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1286 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
1288 mWiFiNetworkAgent.disconnect();
1289 genericNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1290 wifiNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1291 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
1293 mCellNetworkAgent.disconnect();
1294 genericNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1295 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1296 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
1300 public void testMultipleLingering() {
1301 NetworkRequest request = new NetworkRequest.Builder()
1302 .clearCapabilities().addCapability(NET_CAPABILITY_NOT_METERED)
1304 TestNetworkCallback callback = new TestNetworkCallback();
1305 mCm.registerNetworkCallback(request, callback);
1307 TestNetworkCallback defaultCallback = new TestNetworkCallback();
1308 mCm.registerDefaultNetworkCallback(defaultCallback);
1310 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1311 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1312 mEthernetNetworkAgent = new MockNetworkAgent(TRANSPORT_ETHERNET);
1314 mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
1315 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
1316 mEthernetNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
1318 mCellNetworkAgent.connect(true);
1319 callback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1320 defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1321 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1323 mWiFiNetworkAgent.connect(true);
1324 // We get AVAILABLE on wifi when wifi connects and satisfies our unmetered request.
1325 // We then get LOSING when wifi validates and cell is outscored.
1326 callback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1327 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
1328 defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1329 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1331 mEthernetNetworkAgent.connect(true);
1332 callback.expectCallback(CallbackState.AVAILABLE, mEthernetNetworkAgent);
1333 callback.expectCallback(CallbackState.LOSING, mWiFiNetworkAgent);
1334 defaultCallback.expectCallback(CallbackState.AVAILABLE, mEthernetNetworkAgent);
1335 assertEquals(mEthernetNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1337 mEthernetNetworkAgent.disconnect();
1338 callback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
1339 defaultCallback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
1340 defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1342 for (int i = 0; i < 4; i++) {
1343 MockNetworkAgent oldNetwork, newNetwork;
1345 mWiFiNetworkAgent.adjustScore(-15);
1346 oldNetwork = mWiFiNetworkAgent;
1347 newNetwork = mCellNetworkAgent;
1349 mWiFiNetworkAgent.adjustScore(15);
1350 oldNetwork = mCellNetworkAgent;
1351 newNetwork = mWiFiNetworkAgent;
1354 callback.expectCallback(CallbackState.LOSING, oldNetwork);
1355 // TODO: should we send an AVAILABLE callback to newNetwork, to indicate that it is no
1356 // longer lingering?
1357 defaultCallback.expectCallback(CallbackState.AVAILABLE, newNetwork);
1358 assertEquals(newNetwork.getNetwork(), mCm.getActiveNetwork());
1360 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1362 // Verify that if a network no longer satisfies a request, we send LOST and not LOSING, even
1363 // if the network is still up.
1364 mWiFiNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
1365 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1367 // Wifi no longer satisfies our listen, which is for an unmetered network.
1368 // But because its score is 55, it's still up (and the default network).
1369 defaultCallback.assertNoCallback();
1370 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1372 // Disconnect our test networks.
1373 mWiFiNetworkAgent.disconnect();
1374 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1375 defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1376 mCellNetworkAgent.disconnect();
1377 defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1379 mCm.unregisterNetworkCallback(callback);
1380 mService.waitForIdle();
1382 // Check that a network is only lingered or torn down if it would not satisfy a request even
1384 request = new NetworkRequest.Builder().clearCapabilities().build();
1385 callback = new TestNetworkCallback();
1387 mCm.registerNetworkCallback(request, callback);
1389 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1390 mCellNetworkAgent.connect(false); // Score: 10
1391 callback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1392 defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1393 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1395 // Bring up wifi with a score of 20.
1396 // Cell stays up because it would satisfy the default request if it validated.
1397 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1398 mWiFiNetworkAgent.connect(false); // Score: 20
1399 callback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1400 defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1401 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1403 mWiFiNetworkAgent.disconnect();
1404 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1405 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1406 defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1407 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1409 // Bring up wifi with a score of 70.
1410 // Cell is lingered because it would not satisfy any request, even if it validated.
1411 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1412 mWiFiNetworkAgent.adjustScore(50);
1413 mWiFiNetworkAgent.connect(false); // Score: 70
1414 callback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1415 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
1416 defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1417 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1420 mWiFiNetworkAgent.disconnect();
1421 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1422 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1423 defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1424 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1426 // Bring up wifi, then validate it. Previous versions would immediately tear down cell, but
1427 // it's arguably correct to linger it, since it was the default network before it validated.
1428 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1429 mWiFiNetworkAgent.connect(true);
1430 callback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1431 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
1432 defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1433 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1435 mWiFiNetworkAgent.disconnect();
1436 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1437 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1438 defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1439 mCellNetworkAgent.disconnect();
1440 callback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1441 defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1443 // If a network is lingering, and we add and remove a request from it, resume lingering.
1444 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1445 mCellNetworkAgent.connect(true);
1446 callback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1447 defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1448 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1449 mWiFiNetworkAgent.connect(true);
1450 callback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1451 defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1452 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
1454 NetworkRequest cellRequest = new NetworkRequest.Builder()
1455 .addTransportType(TRANSPORT_CELLULAR).build();
1456 NetworkCallback noopCallback = new NetworkCallback();
1457 mCm.requestNetwork(cellRequest, noopCallback);
1458 // TODO: should this cause an AVAILABLE callback, to indicate that the network is no longer
1460 mCm.unregisterNetworkCallback(noopCallback);
1461 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
1463 // Similar to the above: lingering can start even after the lingered request is removed.
1464 // Disconnect wifi and switch to cell.
1465 mWiFiNetworkAgent.disconnect();
1466 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1467 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1468 defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1470 // Cell is now the default network. Pin it with a cell-specific request.
1471 noopCallback = new NetworkCallback(); // Can't reuse NetworkCallbacks. http://b/20701525
1472 mCm.requestNetwork(cellRequest, noopCallback);
1474 // Now connect wifi, and expect it to become the default network.
1475 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1476 mWiFiNetworkAgent.connect(true);
1477 callback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1478 defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1479 // The default request is lingering on cell, but nothing happens to cell, and we send no
1480 // callbacks for it, because it's kept up by cellRequest.
1481 callback.assertNoCallback();
1482 // Now unregister cellRequest and expect cell to start lingering.
1483 mCm.unregisterNetworkCallback(noopCallback);
1484 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
1486 // Let linger run its course.
1487 callback.assertNoCallback();
1488 callback.expectCallback(CallbackState.LOST, mCellNetworkAgent,
1489 TEST_LINGER_DELAY_MS /* timeoutMs */);
1492 mWiFiNetworkAgent.disconnect();
1493 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1494 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1496 mCm.unregisterNetworkCallback(callback);
1497 mCm.unregisterNetworkCallback(defaultCallback);
1500 private void tryNetworkFactoryRequests(int capability) throws Exception {
1501 // Verify NOT_RESTRICTED is set appropriately
1502 final NetworkCapabilities nc = new NetworkRequest.Builder().addCapability(capability)
1503 .build().networkCapabilities;
1504 if (capability == NET_CAPABILITY_CBS || capability == NET_CAPABILITY_DUN ||
1505 capability == NET_CAPABILITY_EIMS || capability == NET_CAPABILITY_FOTA ||
1506 capability == NET_CAPABILITY_IA || capability == NET_CAPABILITY_IMS ||
1507 capability == NET_CAPABILITY_RCS || capability == NET_CAPABILITY_XCAP) {
1508 assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
1510 assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
1513 NetworkCapabilities filter = new NetworkCapabilities();
1514 filter.addCapability(capability);
1515 final HandlerThread handlerThread = new HandlerThread("testNetworkFactoryRequests");
1516 handlerThread.start();
1517 final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
1518 mServiceContext, "testFactory", filter);
1519 testFactory.setScoreFilter(40);
1520 ConditionVariable cv = testFactory.getNetworkStartedCV();
1521 testFactory.expectAddRequests(1);
1522 testFactory.register();
1523 testFactory.waitForNetworkRequests(1);
1524 int expectedRequestCount = 1;
1525 NetworkCallback networkCallback = null;
1526 // For non-INTERNET capabilities we cannot rely on the default request being present, so
1528 if (capability != NET_CAPABILITY_INTERNET) {
1529 assertFalse(testFactory.getMyStartRequested());
1530 NetworkRequest request = new NetworkRequest.Builder().addCapability(capability).build();
1531 networkCallback = new NetworkCallback();
1532 testFactory.expectAddRequests(1);
1533 mCm.requestNetwork(request, networkCallback);
1534 expectedRequestCount++;
1535 testFactory.waitForNetworkRequests(expectedRequestCount);
1538 assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
1539 assertTrue(testFactory.getMyStartRequested());
1541 // Now bring in a higher scored network.
1542 MockNetworkAgent testAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1543 // Rather than create a validated network which complicates things by registering it's
1544 // own NetworkRequest during startup, just bump up the score to cancel out the
1545 // unvalidated penalty.
1546 testAgent.adjustScore(40);
1547 cv = testFactory.getNetworkStoppedCV();
1549 // When testAgent connects, ConnectivityService will re-send us all current requests with
1550 // the new score. There are expectedRequestCount such requests, and we must wait for all of
1552 testFactory.expectAddRequests(expectedRequestCount);
1553 testAgent.connect(false);
1554 testAgent.addCapability(capability);
1556 testFactory.waitForNetworkRequests(expectedRequestCount);
1557 assertFalse(testFactory.getMyStartRequested());
1559 // Bring in a bunch of requests.
1560 testFactory.expectAddRequests(10);
1561 assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
1562 ConnectivityManager.NetworkCallback[] networkCallbacks =
1563 new ConnectivityManager.NetworkCallback[10];
1564 for (int i = 0; i< networkCallbacks.length; i++) {
1565 networkCallbacks[i] = new ConnectivityManager.NetworkCallback();
1566 NetworkRequest.Builder builder = new NetworkRequest.Builder();
1567 builder.addCapability(capability);
1568 mCm.requestNetwork(builder.build(), networkCallbacks[i]);
1570 testFactory.waitForNetworkRequests(10 + expectedRequestCount);
1571 assertFalse(testFactory.getMyStartRequested());
1573 // Remove the requests.
1574 testFactory.expectRemoveRequests(10);
1575 for (int i = 0; i < networkCallbacks.length; i++) {
1576 mCm.unregisterNetworkCallback(networkCallbacks[i]);
1578 testFactory.waitForNetworkRequests(expectedRequestCount);
1579 assertFalse(testFactory.getMyStartRequested());
1581 // Drop the higher scored network.
1582 cv = testFactory.getNetworkStartedCV();
1583 testAgent.disconnect();
1585 assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
1586 assertTrue(testFactory.getMyStartRequested());
1588 testFactory.unregister();
1589 if (networkCallback != null) mCm.unregisterNetworkCallback(networkCallback);
1590 handlerThread.quit();
1594 public void testNetworkFactoryRequests() throws Exception {
1595 tryNetworkFactoryRequests(NET_CAPABILITY_MMS);
1596 tryNetworkFactoryRequests(NET_CAPABILITY_SUPL);
1597 tryNetworkFactoryRequests(NET_CAPABILITY_DUN);
1598 tryNetworkFactoryRequests(NET_CAPABILITY_FOTA);
1599 tryNetworkFactoryRequests(NET_CAPABILITY_IMS);
1600 tryNetworkFactoryRequests(NET_CAPABILITY_CBS);
1601 tryNetworkFactoryRequests(NET_CAPABILITY_WIFI_P2P);
1602 tryNetworkFactoryRequests(NET_CAPABILITY_IA);
1603 tryNetworkFactoryRequests(NET_CAPABILITY_RCS);
1604 tryNetworkFactoryRequests(NET_CAPABILITY_XCAP);
1605 tryNetworkFactoryRequests(NET_CAPABILITY_EIMS);
1606 tryNetworkFactoryRequests(NET_CAPABILITY_NOT_METERED);
1607 tryNetworkFactoryRequests(NET_CAPABILITY_INTERNET);
1608 tryNetworkFactoryRequests(NET_CAPABILITY_TRUSTED);
1609 tryNetworkFactoryRequests(NET_CAPABILITY_NOT_VPN);
1610 // Skipping VALIDATED and CAPTIVE_PORTAL as they're disallowed.
1614 public void testNoMutableNetworkRequests() throws Exception {
1615 PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, new Intent("a"), 0);
1616 NetworkRequest.Builder builder = new NetworkRequest.Builder();
1617 builder.addCapability(NET_CAPABILITY_VALIDATED);
1619 mCm.requestNetwork(builder.build(), new NetworkCallback());
1621 } catch (IllegalArgumentException expected) {}
1623 mCm.requestNetwork(builder.build(), pendingIntent);
1625 } catch (IllegalArgumentException expected) {}
1626 builder = new NetworkRequest.Builder();
1627 builder.addCapability(NET_CAPABILITY_CAPTIVE_PORTAL);
1629 mCm.requestNetwork(builder.build(), new NetworkCallback());
1631 } catch (IllegalArgumentException expected) {}
1633 mCm.requestNetwork(builder.build(), pendingIntent);
1635 } catch (IllegalArgumentException expected) {}
1639 public void testMMSonWiFi() throws Exception {
1640 // Test bringing up cellular without MMS NetworkRequest gets reaped
1641 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1642 mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS);
1643 ConditionVariable cv = mCellNetworkAgent.getDisconnectedCV();
1644 mCellNetworkAgent.connectWithoutInternet();
1646 waitFor(new Criteria() {
1647 public boolean get() { return mCm.getAllNetworks().length == 0; } });
1649 // Test bringing up validated WiFi.
1650 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1651 cv = waitForConnectivityBroadcasts(1);
1652 mWiFiNetworkAgent.connect(true);
1654 verifyActiveNetwork(TRANSPORT_WIFI);
1655 // Register MMS NetworkRequest
1656 NetworkRequest.Builder builder = new NetworkRequest.Builder();
1657 builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
1658 final TestNetworkCallback networkCallback = new TestNetworkCallback();
1659 mCm.requestNetwork(builder.build(), networkCallback);
1660 // Test bringing up unvalidated cellular with MMS
1661 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1662 mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS);
1663 mCellNetworkAgent.connectWithoutInternet();
1664 networkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1665 verifyActiveNetwork(TRANSPORT_WIFI);
1666 // Test releasing NetworkRequest disconnects cellular with MMS
1667 cv = mCellNetworkAgent.getDisconnectedCV();
1668 mCm.unregisterNetworkCallback(networkCallback);
1670 verifyActiveNetwork(TRANSPORT_WIFI);
1674 public void testMMSonCell() throws Exception {
1675 // Test bringing up cellular without MMS
1676 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1677 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1678 mCellNetworkAgent.connect(false);
1680 verifyActiveNetwork(TRANSPORT_CELLULAR);
1681 // Register MMS NetworkRequest
1682 NetworkRequest.Builder builder = new NetworkRequest.Builder();
1683 builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
1684 final TestNetworkCallback networkCallback = new TestNetworkCallback();
1685 mCm.requestNetwork(builder.build(), networkCallback);
1686 // Test bringing up MMS cellular network
1687 MockNetworkAgent mmsNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1688 mmsNetworkAgent.addCapability(NET_CAPABILITY_MMS);
1689 mmsNetworkAgent.connectWithoutInternet();
1690 networkCallback.expectCallback(CallbackState.AVAILABLE, mmsNetworkAgent);
1691 verifyActiveNetwork(TRANSPORT_CELLULAR);
1692 // Test releasing MMS NetworkRequest does not disconnect main cellular NetworkAgent
1693 cv = mmsNetworkAgent.getDisconnectedCV();
1694 mCm.unregisterNetworkCallback(networkCallback);
1696 verifyActiveNetwork(TRANSPORT_CELLULAR);
1700 public void testCaptivePortal() {
1701 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
1702 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
1703 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
1704 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
1706 final TestNetworkCallback validatedCallback = new TestNetworkCallback();
1707 final NetworkRequest validatedRequest = new NetworkRequest.Builder()
1708 .addCapability(NET_CAPABILITY_VALIDATED).build();
1709 mCm.registerNetworkCallback(validatedRequest, validatedCallback);
1711 // Bring up a network with a captive portal.
1712 // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
1713 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1714 String firstRedirectUrl = "http://example.com/firstPath";
1715 mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl);
1716 captivePortalCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1717 assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), firstRedirectUrl);
1719 // Take down network.
1720 // Expect onLost callback.
1721 mWiFiNetworkAgent.disconnect();
1722 captivePortalCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1724 // Bring up a network with a captive portal.
1725 // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
1726 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1727 String secondRedirectUrl = "http://example.com/secondPath";
1728 mWiFiNetworkAgent.connectWithCaptivePortal(secondRedirectUrl);
1729 captivePortalCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1730 assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), secondRedirectUrl);
1732 // Make captive portal disappear then revalidate.
1733 // Expect onLost callback because network no longer provides NET_CAPABILITY_CAPTIVE_PORTAL.
1734 mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 204;
1735 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
1736 captivePortalCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1738 // Expect NET_CAPABILITY_VALIDATED onAvailable callback.
1739 validatedCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1741 // Break network connectivity.
1742 // Expect NET_CAPABILITY_VALIDATED onLost callback.
1743 mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 500;
1744 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), false);
1745 validatedCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1749 public void testAvoidOrIgnoreCaptivePortals() {
1750 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
1751 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
1752 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
1753 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
1755 final TestNetworkCallback validatedCallback = new TestNetworkCallback();
1756 final NetworkRequest validatedRequest = new NetworkRequest.Builder()
1757 .addCapability(NET_CAPABILITY_VALIDATED).build();
1758 mCm.registerNetworkCallback(validatedRequest, validatedCallback);
1760 setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_AVOID);
1761 // Bring up a network with a captive portal.
1762 // Expect it to fail to connect and not result in any callbacks.
1763 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1764 String firstRedirectUrl = "http://example.com/firstPath";
1766 ConditionVariable disconnectCv = mWiFiNetworkAgent.getDisconnectedCV();
1767 ConditionVariable avoidCv = mWiFiNetworkAgent.getPreventReconnectReceived();
1768 mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl);
1769 waitFor(disconnectCv);
1772 assertNoCallbacks(captivePortalCallback, validatedCallback);
1774 // Now test ignore mode.
1775 setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_IGNORE);
1777 // Bring up a network with a captive portal.
1778 // Since we're ignoring captive portals, the network will validate.
1779 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1780 String secondRedirectUrl = "http://example.com/secondPath";
1781 mWiFiNetworkAgent.connectWithCaptivePortal(secondRedirectUrl);
1783 // Expect NET_CAPABILITY_VALIDATED onAvailable callback.
1784 validatedCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1785 // But there should be no CaptivePortal callback.
1786 captivePortalCallback.assertNoCallback();
1790 public void testInvalidNetworkSpecifier() {
1791 boolean execptionCalled = true;
1794 NetworkRequest.Builder builder = new NetworkRequest.Builder();
1795 builder.setNetworkSpecifier(MATCH_ALL_REQUESTS_NETWORK_SPECIFIER);
1796 execptionCalled = false;
1797 } catch (IllegalArgumentException e) {
1798 // do nothing - should get here
1801 assertTrue("NetworkRequest builder with MATCH_ALL_REQUESTS_NETWORK_SPECIFIER",
1805 NetworkCapabilities networkCapabilities = new NetworkCapabilities();
1806 networkCapabilities.addTransportType(TRANSPORT_WIFI)
1807 .setNetworkSpecifier(NetworkCapabilities.MATCH_ALL_REQUESTS_NETWORK_SPECIFIER);
1808 mService.requestNetwork(networkCapabilities, null, 0, null,
1809 ConnectivityManager.TYPE_WIFI);
1810 execptionCalled = false;
1811 } catch (IllegalArgumentException e) {
1812 // do nothing - should get here
1815 assertTrue("ConnectivityService requestNetwork with MATCH_ALL_REQUESTS_NETWORK_SPECIFIER",
1820 public void testRegisterDefaultNetworkCallback() throws Exception {
1821 final TestNetworkCallback defaultNetworkCallback = new TestNetworkCallback();
1822 mCm.registerDefaultNetworkCallback(defaultNetworkCallback);
1823 defaultNetworkCallback.assertNoCallback();
1825 // Create a TRANSPORT_CELLULAR request to keep the mobile interface up
1826 // whenever Wi-Fi is up. Without this, the mobile network agent is
1827 // reaped before any other activity can take place.
1828 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
1829 final NetworkRequest cellRequest = new NetworkRequest.Builder()
1830 .addTransportType(TRANSPORT_CELLULAR).build();
1831 mCm.requestNetwork(cellRequest, cellNetworkCallback);
1832 cellNetworkCallback.assertNoCallback();
1834 // Bring up cell and expect CALLBACK_AVAILABLE.
1835 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1836 mCellNetworkAgent.connect(true);
1837 cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1838 defaultNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1840 // Bring up wifi and expect CALLBACK_AVAILABLE.
1841 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1842 mWiFiNetworkAgent.connect(true);
1843 cellNetworkCallback.assertNoCallback();
1844 defaultNetworkCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1846 // Bring down cell. Expect no default network callback, since it wasn't the default.
1847 mCellNetworkAgent.disconnect();
1848 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1849 defaultNetworkCallback.assertNoCallback();
1851 // Bring up cell. Expect no default network callback, since it won't be the default.
1852 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1853 mCellNetworkAgent.connect(true);
1854 cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1855 defaultNetworkCallback.assertNoCallback();
1857 // Bring down wifi. Expect the default network callback to notified of LOST wifi
1858 // followed by AVAILABLE cell.
1859 mWiFiNetworkAgent.disconnect();
1860 cellNetworkCallback.assertNoCallback();
1861 defaultNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1862 defaultNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1863 mCellNetworkAgent.disconnect();
1864 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1865 defaultNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1868 private class TestRequestUpdateCallback extends TestNetworkCallback {
1870 public void onCapabilitiesChanged(Network network, NetworkCapabilities netCap) {
1871 setLastCallback(CallbackState.NETWORK_CAPABILITIES, network, netCap);
1875 public void onLinkPropertiesChanged(Network network, LinkProperties linkProp) {
1876 setLastCallback(CallbackState.LINK_PROPERTIES, network, linkProp);
1881 public void testRequestCallbackUpdates() throws Exception {
1882 // File a network request for mobile.
1883 final TestNetworkCallback cellNetworkCallback = new TestRequestUpdateCallback();
1884 final NetworkRequest cellRequest = new NetworkRequest.Builder()
1885 .addTransportType(TRANSPORT_CELLULAR).build();
1886 mCm.requestNetwork(cellRequest, cellNetworkCallback);
1888 // Bring up the mobile network.
1889 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1890 mCellNetworkAgent.connect(true);
1892 // We should get onAvailable().
1893 cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1894 // We should get onCapabilitiesChanged(), when the mobile network successfully validates.
1895 cellNetworkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, mCellNetworkAgent);
1896 cellNetworkCallback.assertNoCallback();
1898 // Update LinkProperties.
1899 final LinkProperties lp = new LinkProperties();
1900 lp.setInterfaceName("foonet_data0");
1901 mCellNetworkAgent.sendLinkProperties(lp);
1902 // We should get onLinkPropertiesChanged().
1903 cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
1904 cellNetworkCallback.assertNoCallback();
1906 // Register a garden variety default network request.
1907 final TestNetworkCallback dfltNetworkCallback = new TestRequestUpdateCallback();
1908 mCm.registerDefaultNetworkCallback(dfltNetworkCallback);
1909 // Only onAvailable() is called; no other information is delivered.
1910 dfltNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1911 dfltNetworkCallback.assertNoCallback();
1913 // Request a NetworkCapabilities update; only the requesting callback is notified.
1914 mCm.requestNetworkCapabilities(dfltNetworkCallback);
1915 dfltNetworkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, mCellNetworkAgent);
1916 cellNetworkCallback.assertNoCallback();
1917 dfltNetworkCallback.assertNoCallback();
1919 // Request a LinkProperties update; only the requesting callback is notified.
1920 mCm.requestLinkProperties(dfltNetworkCallback);
1921 dfltNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
1922 cellNetworkCallback.assertNoCallback();
1923 dfltNetworkCallback.assertNoCallback();
1925 mCm.unregisterNetworkCallback(dfltNetworkCallback);
1926 mCm.unregisterNetworkCallback(cellNetworkCallback);
1929 private void setCaptivePortalMode(int mode) {
1930 ContentResolver cr = mServiceContext.getContentResolver();
1931 Settings.Global.putInt(cr, Settings.Global.CAPTIVE_PORTAL_MODE, mode);
1934 private void setMobileDataAlwaysOn(boolean enable) {
1935 ContentResolver cr = mServiceContext.getContentResolver();
1936 Settings.Global.putInt(cr, Settings.Global.MOBILE_DATA_ALWAYS_ON, enable ? 1 : 0);
1937 mService.updateMobileDataAlwaysOn();
1938 mService.waitForIdle();
1941 private boolean isForegroundNetwork(MockNetworkAgent network) {
1942 NetworkCapabilities nc = mCm.getNetworkCapabilities(network.getNetwork());
1944 return nc.hasCapability(NET_CAPABILITY_FOREGROUND);
1948 public void testBackgroundNetworks() throws Exception {
1949 // Create a background request. We can't do this ourselves because ConnectivityService
1950 // doesn't have an API for it. So just turn on mobile data always on.
1951 setMobileDataAlwaysOn(true);
1952 final NetworkRequest request = new NetworkRequest.Builder().build();
1953 final NetworkRequest fgRequest = new NetworkRequest.Builder()
1954 .addCapability(NET_CAPABILITY_FOREGROUND).build();
1955 final TestNetworkCallback callback = new TestNetworkCallback();
1956 final TestNetworkCallback fgCallback = new TestNetworkCallback();
1957 mCm.registerNetworkCallback(request, callback);
1958 mCm.registerNetworkCallback(fgRequest, fgCallback);
1960 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1961 mCellNetworkAgent.connect(true);
1962 callback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1963 fgCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1964 assertTrue(isForegroundNetwork(mCellNetworkAgent));
1966 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1967 mWiFiNetworkAgent.connect(true);
1969 // When wifi connects, cell lingers.
1970 callback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1971 fgCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1972 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
1973 fgCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
1974 assertTrue(isForegroundNetwork(mCellNetworkAgent));
1975 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
1977 // When lingering is complete, cell is still there but is now in the background.
1978 fgCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent, TEST_LINGER_DELAY_MS);
1979 callback.assertNoCallback();
1980 assertFalse(isForegroundNetwork(mCellNetworkAgent));
1981 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
1983 // File a cell request and check that cell comes into the foreground.
1984 final NetworkRequest cellRequest = new NetworkRequest.Builder()
1985 .addTransportType(TRANSPORT_CELLULAR).build();
1986 final TestNetworkCallback cellCallback = new TestNetworkCallback();
1987 mCm.requestNetwork(cellRequest, cellCallback);
1988 cellCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1989 fgCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1990 callback.assertNoCallback(); // Because the network is already up.
1991 assertTrue(isForegroundNetwork(mCellNetworkAgent));
1992 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
1994 // Release the request. The network immediately goes into the background, since it was not
1996 mCm.unregisterNetworkCallback(cellCallback);
1997 fgCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1998 callback.assertNoCallback();
1999 assertFalse(isForegroundNetwork(mCellNetworkAgent));
2000 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
2002 // Disconnect wifi and check that cell is foreground again.
2003 mWiFiNetworkAgent.disconnect();
2004 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2005 fgCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2006 fgCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
2007 assertTrue(isForegroundNetwork(mCellNetworkAgent));
2009 mCm.unregisterNetworkCallback(callback);
2010 mCm.unregisterNetworkCallback(fgCallback);
2014 public void testRequestBenchmark() throws Exception {
2015 // TODO: turn this unit test into a real benchmarking test.
2016 // Benchmarks connecting and switching performance in the presence of a large number of
2018 // 1. File NUM_REQUESTS requests.
2019 // 2. Have a network connect. Wait for NUM_REQUESTS onAvailable callbacks to fire.
2020 // 3. Have a new network connect and outscore the previous. Wait for NUM_REQUESTS onLosing
2021 // and NUM_REQUESTS onAvailable callbacks to fire.
2022 // See how long it took.
2023 final int NUM_REQUESTS = 90;
2024 final NetworkRequest request = new NetworkRequest.Builder().clearCapabilities().build();
2025 final NetworkCallback[] callbacks = new NetworkCallback[NUM_REQUESTS];
2026 final CountDownLatch availableLatch = new CountDownLatch(NUM_REQUESTS);
2027 final CountDownLatch losingLatch = new CountDownLatch(NUM_REQUESTS);
2029 for (int i = 0; i < NUM_REQUESTS; i++) {
2030 callbacks[i] = new NetworkCallback() {
2031 @Override public void onAvailable(Network n) { availableLatch.countDown(); }
2032 @Override public void onLosing(Network n, int t) { losingLatch.countDown(); }
2036 final int REGISTER_TIME_LIMIT_MS = 180;
2037 assertTimeLimit("Registering callbacks", REGISTER_TIME_LIMIT_MS, () -> {
2038 for (NetworkCallback cb : callbacks) {
2039 mCm.registerNetworkCallback(request, cb);
2043 final int CONNECT_TIME_LIMIT_MS = 40;
2044 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2045 // Don't request that the network validate, because otherwise connect() will block until
2046 // the network gets NET_CAPABILITY_VALIDATED, after all the callbacks below have fired,
2047 // and we won't actually measure anything.
2048 mCellNetworkAgent.connect(false);
2050 long onAvailableDispatchingDuration = durationOf(() -> {
2051 if (!awaitLatch(availableLatch, CONNECT_TIME_LIMIT_MS)) {
2052 fail(String.format("Only dispatched %d/%d onAvailable callbacks in %dms",
2053 NUM_REQUESTS - availableLatch.getCount(), NUM_REQUESTS,
2054 CONNECT_TIME_LIMIT_MS));
2057 Log.d(TAG, String.format("Connect, %d callbacks: %dms, acceptable %dms",
2058 NUM_REQUESTS, onAvailableDispatchingDuration, CONNECT_TIME_LIMIT_MS));
2060 final int SWITCH_TIME_LIMIT_MS = 40;
2061 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2062 // Give wifi a high enough score that we'll linger cell when wifi comes up.
2063 mWiFiNetworkAgent.adjustScore(40);
2064 mWiFiNetworkAgent.connect(false);
2066 long onLostDispatchingDuration = durationOf(() -> {
2067 if (!awaitLatch(losingLatch, SWITCH_TIME_LIMIT_MS)) {
2068 fail(String.format("Only dispatched %d/%d onLosing callbacks in %dms",
2069 NUM_REQUESTS - losingLatch.getCount(), NUM_REQUESTS, SWITCH_TIME_LIMIT_MS));
2072 Log.d(TAG, String.format("Linger, %d callbacks: %dms, acceptable %dms",
2073 NUM_REQUESTS, onLostDispatchingDuration, SWITCH_TIME_LIMIT_MS));
2075 final int UNREGISTER_TIME_LIMIT_MS = 10;
2076 assertTimeLimit("Unregistering callbacks", UNREGISTER_TIME_LIMIT_MS, () -> {
2077 for (NetworkCallback cb : callbacks) {
2078 mCm.unregisterNetworkCallback(cb);
2083 private long durationOf(Runnable fn) {
2084 long startTime = SystemClock.elapsedRealtime();
2086 return SystemClock.elapsedRealtime() - startTime;
2089 private void assertTimeLimit(String descr, long timeLimit, Runnable fn) {
2090 long timeTaken = durationOf(fn);
2091 String msg = String.format("%s: took %dms, limit was %dms", descr, timeTaken, timeLimit);
2093 assertTrue(msg, timeTaken <= timeLimit);
2096 private boolean awaitLatch(CountDownLatch l, long timeoutMs) {
2098 if (l.await(timeoutMs, TimeUnit.MILLISECONDS)) {
2101 } catch (InterruptedException e) {}
2106 public void testMobileDataAlwaysOn() throws Exception {
2107 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
2108 final NetworkRequest cellRequest = new NetworkRequest.Builder()
2109 .addTransportType(TRANSPORT_CELLULAR).build();
2110 mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
2112 final HandlerThread handlerThread = new HandlerThread("MobileDataAlwaysOnFactory");
2113 handlerThread.start();
2114 NetworkCapabilities filter = new NetworkCapabilities()
2115 .addTransportType(TRANSPORT_CELLULAR)
2116 .addCapability(NET_CAPABILITY_INTERNET);
2117 final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
2118 mServiceContext, "testFactory", filter);
2119 testFactory.setScoreFilter(40);
2121 // Register the factory and expect it to start looking for a network.
2122 testFactory.expectAddRequests(1);
2123 testFactory.register();
2124 testFactory.waitForNetworkRequests(1);
2125 assertTrue(testFactory.getMyStartRequested());
2127 // Bring up wifi. The factory stops looking for a network.
2128 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2129 testFactory.expectAddRequests(2); // Because the default request changes score twice.
2130 mWiFiNetworkAgent.connect(true);
2131 testFactory.waitForNetworkRequests(1);
2132 assertFalse(testFactory.getMyStartRequested());
2134 ContentResolver cr = mServiceContext.getContentResolver();
2136 // Turn on mobile data always on. The factory starts looking again.
2137 testFactory.expectAddRequests(1);
2138 setMobileDataAlwaysOn(true);
2139 testFactory.waitForNetworkRequests(2);
2140 assertTrue(testFactory.getMyStartRequested());
2142 // Bring up cell data and check that the factory stops looking.
2143 assertEquals(1, mCm.getAllNetworks().length);
2144 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2145 testFactory.expectAddRequests(2); // Because the cell request changes score twice.
2146 mCellNetworkAgent.connect(true);
2147 cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
2148 testFactory.waitForNetworkRequests(2);
2149 assertFalse(testFactory.getMyStartRequested()); // Because the cell network outscores us.
2151 // Check that cell data stays up.
2152 mService.waitForIdle();
2153 verifyActiveNetwork(TRANSPORT_WIFI);
2154 assertEquals(2, mCm.getAllNetworks().length);
2156 // Turn off mobile data always on and expect the request to disappear...
2157 testFactory.expectRemoveRequests(1);
2158 setMobileDataAlwaysOn(false);
2159 testFactory.waitForNetworkRequests(1);
2161 // ... and cell data to be torn down.
2162 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
2163 assertEquals(1, mCm.getAllNetworks().length);
2165 testFactory.unregister();
2166 mCm.unregisterNetworkCallback(cellNetworkCallback);
2167 handlerThread.quit();
2171 public void testAvoidBadWifiSetting() throws Exception {
2172 final ContentResolver cr = mServiceContext.getContentResolver();
2173 final WrappedAvoidBadWifiTracker tracker = mService.getAvoidBadWifiTracker();
2174 final String settingName = Settings.Global.NETWORK_AVOID_BAD_WIFI;
2176 tracker.configRestrictsAvoidBadWifi = false;
2177 String[] values = new String[] {null, "0", "1"};
2178 for (int i = 0; i < values.length; i++) {
2179 Settings.Global.putInt(cr, settingName, 1);
2180 tracker.reevaluate();
2181 mService.waitForIdle();
2182 String msg = String.format("config=false, setting=%s", values[i]);
2183 assertTrue(msg, mService.avoidBadWifi());
2184 assertFalse(msg, tracker.shouldNotifyWifiUnvalidated());
2187 tracker.configRestrictsAvoidBadWifi = true;
2189 Settings.Global.putInt(cr, settingName, 0);
2190 tracker.reevaluate();
2191 mService.waitForIdle();
2192 assertFalse(mService.avoidBadWifi());
2193 assertFalse(tracker.shouldNotifyWifiUnvalidated());
2195 Settings.Global.putInt(cr, settingName, 1);
2196 tracker.reevaluate();
2197 mService.waitForIdle();
2198 assertTrue(mService.avoidBadWifi());
2199 assertFalse(tracker.shouldNotifyWifiUnvalidated());
2201 Settings.Global.putString(cr, settingName, null);
2202 tracker.reevaluate();
2203 mService.waitForIdle();
2204 assertFalse(mService.avoidBadWifi());
2205 assertTrue(tracker.shouldNotifyWifiUnvalidated());
2209 public void testAvoidBadWifi() throws Exception {
2210 final ContentResolver cr = mServiceContext.getContentResolver();
2211 final WrappedAvoidBadWifiTracker tracker = mService.getAvoidBadWifiTracker();
2213 // Pretend we're on a carrier that restricts switching away from bad wifi.
2214 tracker.configRestrictsAvoidBadWifi = true;
2216 // File a request for cell to ensure it doesn't go down.
2217 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
2218 final NetworkRequest cellRequest = new NetworkRequest.Builder()
2219 .addTransportType(TRANSPORT_CELLULAR).build();
2220 mCm.requestNetwork(cellRequest, cellNetworkCallback);
2222 TestNetworkCallback defaultCallback = new TestNetworkCallback();
2223 mCm.registerDefaultNetworkCallback(defaultCallback);
2225 NetworkRequest validatedWifiRequest = new NetworkRequest.Builder()
2226 .addTransportType(TRANSPORT_WIFI)
2227 .addCapability(NET_CAPABILITY_VALIDATED)
2229 TestNetworkCallback validatedWifiCallback = new TestNetworkCallback();
2230 mCm.registerNetworkCallback(validatedWifiRequest, validatedWifiCallback);
2232 Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 0);
2233 tracker.reevaluate();
2235 // Bring up validated cell.
2236 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2237 mCellNetworkAgent.connect(true);
2238 cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
2239 defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
2240 Network cellNetwork = mCellNetworkAgent.getNetwork();
2242 // Bring up validated wifi.
2243 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2244 mWiFiNetworkAgent.connect(true);
2245 defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
2246 validatedWifiCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
2247 Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
2249 // Fail validation on wifi.
2250 mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 599;
2251 mCm.reportNetworkConnectivity(wifiNetwork, false);
2252 validatedWifiCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2254 // Because avoid bad wifi is off, we don't switch to cellular.
2255 defaultCallback.assertNoCallback();
2256 assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
2257 NET_CAPABILITY_VALIDATED));
2258 assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
2259 NET_CAPABILITY_VALIDATED));
2260 assertEquals(mCm.getActiveNetwork(), wifiNetwork);
2262 // Simulate switching to a carrier that does not restrict avoiding bad wifi, and expect
2263 // that we switch back to cell.
2264 tracker.configRestrictsAvoidBadWifi = false;
2265 tracker.reevaluate();
2266 defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
2267 assertEquals(mCm.getActiveNetwork(), cellNetwork);
2269 // Switch back to a restrictive carrier.
2270 tracker.configRestrictsAvoidBadWifi = true;
2271 tracker.reevaluate();
2272 defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
2273 assertEquals(mCm.getActiveNetwork(), wifiNetwork);
2275 // Simulate the user selecting "switch" on the dialog, and check that we switch to cell.
2276 mCm.setAvoidUnvalidated(wifiNetwork);
2277 defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
2278 assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
2279 NET_CAPABILITY_VALIDATED));
2280 assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
2281 NET_CAPABILITY_VALIDATED));
2282 assertEquals(mCm.getActiveNetwork(), cellNetwork);
2284 // Disconnect and reconnect wifi to clear the one-time switch above.
2285 mWiFiNetworkAgent.disconnect();
2286 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2287 mWiFiNetworkAgent.connect(true);
2288 defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
2289 validatedWifiCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
2290 wifiNetwork = mWiFiNetworkAgent.getNetwork();
2292 // Fail validation on wifi and expect the dialog to appear.
2293 mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 599;
2294 mCm.reportNetworkConnectivity(wifiNetwork, false);
2295 validatedWifiCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2297 // Simulate the user selecting "switch" and checking the don't ask again checkbox.
2298 Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 1);
2299 tracker.reevaluate();
2301 // We now switch to cell.
2302 defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
2303 assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
2304 NET_CAPABILITY_VALIDATED));
2305 assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
2306 NET_CAPABILITY_VALIDATED));
2307 assertEquals(mCm.getActiveNetwork(), cellNetwork);
2309 // Simulate the user turning the cellular fallback setting off and then on.
2310 // We switch to wifi and then to cell.
2311 Settings.Global.putString(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, null);
2312 tracker.reevaluate();
2313 defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
2314 assertEquals(mCm.getActiveNetwork(), wifiNetwork);
2315 Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 1);
2316 tracker.reevaluate();
2317 defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
2318 assertEquals(mCm.getActiveNetwork(), cellNetwork);
2320 // If cell goes down, we switch to wifi.
2321 mCellNetworkAgent.disconnect();
2322 defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
2323 defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
2324 validatedWifiCallback.assertNoCallback();
2326 mCm.unregisterNetworkCallback(cellNetworkCallback);
2327 mCm.unregisterNetworkCallback(validatedWifiCallback);
2328 mCm.unregisterNetworkCallback(defaultCallback);
2332 * Validate that a satisfied network request does not trigger onUnavailable() once the
2333 * time-out period expires.
2336 public void testSatisfiedNetworkRequestDoesNotTriggerOnUnavailable() {
2337 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
2338 NetworkCapabilities.TRANSPORT_WIFI).build();
2339 final TestNetworkCallback networkCallback = new TestNetworkCallback();
2340 mCm.requestNetwork(nr, networkCallback, 10);
2342 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2343 mWiFiNetworkAgent.connect(false);
2344 networkCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
2346 // pass timeout and validate that UNAVAILABLE is not called
2348 networkCallback.assertNoCallback();
2352 * Validate that a satisfied network request followed by a disconnected (lost) network does
2353 * not trigger onUnavailable() once the time-out period expires.
2356 public void testSatisfiedThenLostNetworkRequestDoesNotTriggerOnUnavailable() {
2357 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
2358 NetworkCapabilities.TRANSPORT_WIFI).build();
2359 final TestNetworkCallback networkCallback = new TestNetworkCallback();
2360 mCm.requestNetwork(nr, networkCallback, 500);
2362 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2363 mWiFiNetworkAgent.connect(false);
2364 networkCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
2366 mWiFiNetworkAgent.disconnect();
2367 networkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2369 // pass timeout and validate that UNAVAILABLE is not called
2371 networkCallback.assertNoCallback();
2375 * Validate that when a time-out is specified for a network request the onUnavailable()
2376 * callback is called when time-out expires. Then validate that if network request is
2377 * (somehow) satisfied - the callback isn't called later.
2380 public void testTimedoutNetworkRequest() {
2381 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
2382 NetworkCapabilities.TRANSPORT_WIFI).build();
2383 final TestNetworkCallback networkCallback = new TestNetworkCallback();
2384 mCm.requestNetwork(nr, networkCallback, 10);
2386 // pass timeout and validate that UNAVAILABLE is called
2387 networkCallback.expectCallback(CallbackState.UNAVAILABLE, null);
2389 // create a network satisfying request - validate that request not triggered
2390 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2391 mWiFiNetworkAgent.connect(false);
2392 networkCallback.assertNoCallback();
2396 * Validate that when a network request is unregistered (cancelled) the time-out for that
2397 * request doesn't trigger the onUnavailable() callback.
2400 public void testTimedoutAfterUnregisteredNetworkRequest() {
2401 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
2402 NetworkCapabilities.TRANSPORT_WIFI).build();
2403 final TestNetworkCallback networkCallback = new TestNetworkCallback();
2404 mCm.requestNetwork(nr, networkCallback, 10);
2407 mCm.unregisterNetworkCallback(networkCallback);
2409 // pass timeout and validate that no callbacks
2410 // Note: doesn't validate that nothing called from CS since even if called the CM already
2411 // unregisters the callback and won't pass it through!
2413 networkCallback.assertNoCallback();
2415 // create a network satisfying request - validate that request not triggered
2416 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2417 mWiFiNetworkAgent.connect(false);
2418 networkCallback.assertNoCallback();
2421 private static class TestKeepaliveCallback extends PacketKeepaliveCallback {
2423 public static enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR };
2425 private class CallbackValue {
2426 public CallbackType callbackType;
2429 public CallbackValue(CallbackType type) {
2430 this.callbackType = type;
2431 this.error = PacketKeepalive.SUCCESS;
2432 assertTrue("onError callback must have error", type != CallbackType.ON_ERROR);
2435 public CallbackValue(CallbackType type, int error) {
2436 this.callbackType = type;
2438 assertEquals("error can only be set for onError", type, CallbackType.ON_ERROR);
2442 public boolean equals(Object o) {
2443 return o instanceof CallbackValue &&
2444 this.callbackType == ((CallbackValue) o).callbackType &&
2445 this.error == ((CallbackValue) o).error;
2449 public String toString() {
2450 return String.format("%s(%s, %d)", getClass().getSimpleName(), callbackType, error);
2454 private LinkedBlockingQueue<CallbackValue> mCallbacks = new LinkedBlockingQueue<>();
2457 public void onStarted() {
2458 mCallbacks.add(new CallbackValue(CallbackType.ON_STARTED));
2462 public void onStopped() {
2463 mCallbacks.add(new CallbackValue(CallbackType.ON_STOPPED));
2467 public void onError(int error) {
2468 mCallbacks.add(new CallbackValue(CallbackType.ON_ERROR, error));
2471 private void expectCallback(CallbackValue callbackValue) {
2475 mCallbacks.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
2476 } catch (InterruptedException e) {
2477 fail(callbackValue.callbackType + " callback not seen after " + TIMEOUT_MS + " ms");
2481 public void expectStarted() {
2482 expectCallback(new CallbackValue(CallbackType.ON_STARTED));
2485 public void expectStopped() {
2486 expectCallback(new CallbackValue(CallbackType.ON_STOPPED));
2489 public void expectError(int error) {
2490 expectCallback(new CallbackValue(CallbackType.ON_ERROR, error));
2494 private Network connectKeepaliveNetwork(LinkProperties lp) {
2495 // Ensure the network is disconnected before we do anything.
2496 if (mWiFiNetworkAgent != null) {
2497 assertNull(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()));
2500 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2501 ConditionVariable cv = waitForConnectivityBroadcasts(1);
2502 mWiFiNetworkAgent.connect(true);
2504 verifyActiveNetwork(TRANSPORT_WIFI);
2505 mWiFiNetworkAgent.sendLinkProperties(lp);
2506 mService.waitForIdle();
2507 return mWiFiNetworkAgent.getNetwork();
2510 public void testPacketKeepalives() throws Exception {
2511 InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
2512 InetAddress notMyIPv4 = InetAddress.getByName("192.0.2.35");
2513 InetAddress myIPv6 = InetAddress.getByName("2001:db8::1");
2514 InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8");
2515 InetAddress dstIPv6 = InetAddress.getByName("2001:4860:4860::8888");
2517 LinkProperties lp = new LinkProperties();
2518 lp.setInterfaceName("wlan12");
2519 lp.addLinkAddress(new LinkAddress(myIPv6, 64));
2520 lp.addLinkAddress(new LinkAddress(myIPv4, 25));
2521 lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
2522 lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
2524 Network notMyNet = new Network(61234);
2525 Network myNet = connectKeepaliveNetwork(lp);
2527 TestKeepaliveCallback callback = new TestKeepaliveCallback();
2530 // Attempt to start keepalives with invalid parameters and check for errors.
2531 ka = mCm.startNattKeepalive(notMyNet, 25, callback, myIPv4, 1234, dstIPv4);
2532 callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK);
2534 ka = mCm.startNattKeepalive(myNet, 19, callback, notMyIPv4, 1234, dstIPv4);
2535 callback.expectError(PacketKeepalive.ERROR_INVALID_INTERVAL);
2537 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 1234, dstIPv6);
2538 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
2540 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv6, 1234, dstIPv4);
2541 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
2543 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv6, 1234, dstIPv6);
2544 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS); // NAT-T is IPv4-only.
2546 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 123456, dstIPv4);
2547 callback.expectError(PacketKeepalive.ERROR_INVALID_PORT);
2549 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 123456, dstIPv4);
2550 callback.expectError(PacketKeepalive.ERROR_INVALID_PORT);
2552 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
2553 callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
2555 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
2556 callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
2558 // Check that a started keepalive can be stopped.
2559 mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS);
2560 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
2561 callback.expectStarted();
2562 mWiFiNetworkAgent.setStopKeepaliveError(PacketKeepalive.SUCCESS);
2564 callback.expectStopped();
2566 // Check that deleting the IP address stops the keepalive.
2567 LinkProperties bogusLp = new LinkProperties(lp);
2568 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
2569 callback.expectStarted();
2570 bogusLp.removeLinkAddress(new LinkAddress(myIPv4, 25));
2571 bogusLp.addLinkAddress(new LinkAddress(notMyIPv4, 25));
2572 mWiFiNetworkAgent.sendLinkProperties(bogusLp);
2573 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
2574 mWiFiNetworkAgent.sendLinkProperties(lp);
2576 // Check that a started keepalive is stopped correctly when the network disconnects.
2577 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
2578 callback.expectStarted();
2579 mWiFiNetworkAgent.disconnect();
2580 callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK);
2582 // ... and that stopping it after that has no adverse effects.
2583 assertNull(mCm.getNetworkCapabilities(myNet));
2587 myNet = connectKeepaliveNetwork(lp);
2588 mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS);
2590 // Check things work as expected when the keepalive is stopped and the network disconnects.
2591 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
2592 callback.expectStarted();
2594 mWiFiNetworkAgent.disconnect();
2595 mService.waitForIdle();
2596 callback.expectStopped();
2599 myNet = connectKeepaliveNetwork(lp);
2600 mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS);
2602 // Check that keepalive slots start from 1 and increment. The first one gets slot 1.
2603 mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
2604 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
2605 callback.expectStarted();
2607 // The second one gets slot 2.
2608 mWiFiNetworkAgent.setExpectedKeepaliveSlot(2);
2609 TestKeepaliveCallback callback2 = new TestKeepaliveCallback();
2610 PacketKeepalive ka2 = mCm.startNattKeepalive(myNet, 25, callback2, myIPv4, 6789, dstIPv4);
2611 callback2.expectStarted();
2613 // Now stop the first one and create a third. This also gets slot 1.
2615 callback.expectStopped();
2617 mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
2618 TestKeepaliveCallback callback3 = new TestKeepaliveCallback();
2619 PacketKeepalive ka3 = mCm.startNattKeepalive(myNet, 25, callback3, myIPv4, 9876, dstIPv4);
2620 callback3.expectStarted();
2623 callback2.expectStopped();
2626 callback3.expectStopped();
2630 public void testGetCaptivePortalServerUrl() throws Exception {
2631 String url = mCm.getCaptivePortalServerUrl();
2632 assertEquals("http://connectivitycheck.gstatic.com/generate_204", url);
2635 private static class TestNetworkPinner extends NetworkPinner {
2636 public static boolean awaitPin(int timeoutMs) {
2637 synchronized(sLock) {
2638 if (sNetwork == null) {
2640 sLock.wait(timeoutMs);
2641 } catch (InterruptedException e) {}
2643 return sNetwork != null;
2647 public static boolean awaitUnpin(int timeoutMs) {
2648 synchronized(sLock) {
2649 if (sNetwork != null) {
2651 sLock.wait(timeoutMs);
2652 } catch (InterruptedException e) {}
2654 return sNetwork == null;
2659 private void assertPinnedToWifiWithCellDefault() {
2660 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess());
2661 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2664 private void assertPinnedToWifiWithWifiDefault() {
2665 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess());
2666 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2669 private void assertNotPinnedToWifi() {
2670 assertNull(mCm.getBoundNetworkForProcess());
2671 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2675 public void testNetworkPinner() {
2676 NetworkRequest wifiRequest = new NetworkRequest.Builder()
2677 .addTransportType(TRANSPORT_WIFI)
2679 assertNull(mCm.getBoundNetworkForProcess());
2681 TestNetworkPinner.pin(mServiceContext, wifiRequest);
2682 assertNull(mCm.getBoundNetworkForProcess());
2684 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2685 mCellNetworkAgent.connect(true);
2686 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2687 mWiFiNetworkAgent.connect(false);
2689 // When wi-fi connects, expect to be pinned.
2690 assertTrue(TestNetworkPinner.awaitPin(100));
2691 assertPinnedToWifiWithCellDefault();
2693 // Disconnect and expect the pin to drop.
2694 mWiFiNetworkAgent.disconnect();
2695 assertTrue(TestNetworkPinner.awaitUnpin(100));
2696 assertNotPinnedToWifi();
2698 // Reconnecting does not cause the pin to come back.
2699 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2700 mWiFiNetworkAgent.connect(false);
2701 assertFalse(TestNetworkPinner.awaitPin(100));
2702 assertNotPinnedToWifi();
2704 // Pinning while connected causes the pin to take effect immediately.
2705 TestNetworkPinner.pin(mServiceContext, wifiRequest);
2706 assertTrue(TestNetworkPinner.awaitPin(100));
2707 assertPinnedToWifiWithCellDefault();
2709 // Explicitly unpin and expect to use the default network again.
2710 TestNetworkPinner.unpin();
2711 assertNotPinnedToWifi();
2713 // Disconnect cell and wifi.
2714 ConditionVariable cv = waitForConnectivityBroadcasts(3); // cell down, wifi up, wifi down.
2715 mCellNetworkAgent.disconnect();
2716 mWiFiNetworkAgent.disconnect();
2719 // Pinning takes effect even if the pinned network is the default when the pin is set...
2720 TestNetworkPinner.pin(mServiceContext, wifiRequest);
2721 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2722 mWiFiNetworkAgent.connect(false);
2723 assertTrue(TestNetworkPinner.awaitPin(100));
2724 assertPinnedToWifiWithWifiDefault();
2726 // ... and is maintained even when that network is no longer the default.
2727 cv = waitForConnectivityBroadcasts(1);
2728 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2729 mCellNetworkAgent.connect(true);
2731 assertPinnedToWifiWithCellDefault();
2735 public void testNetworkRequestMaximum() {
2736 final int MAX_REQUESTS = 100;
2737 // Test that the limit is enforced when MAX_REQUESTS simultaneous requests are added.
2738 NetworkRequest networkRequest = new NetworkRequest.Builder().build();
2739 ArrayList<NetworkCallback> networkCallbacks = new ArrayList<NetworkCallback>();
2741 for (int i = 0; i < MAX_REQUESTS; i++) {
2742 NetworkCallback networkCallback = new NetworkCallback();
2743 mCm.requestNetwork(networkRequest, networkCallback);
2744 networkCallbacks.add(networkCallback);
2746 fail("Registering " + MAX_REQUESTS + " NetworkRequests did not throw exception");
2747 } catch (IllegalArgumentException expected) {}
2748 for (NetworkCallback networkCallback : networkCallbacks) {
2749 mCm.unregisterNetworkCallback(networkCallback);
2751 networkCallbacks.clear();
2754 for (int i = 0; i < MAX_REQUESTS; i++) {
2755 NetworkCallback networkCallback = new NetworkCallback();
2756 mCm.registerNetworkCallback(networkRequest, networkCallback);
2757 networkCallbacks.add(networkCallback);
2759 fail("Registering " + MAX_REQUESTS + " NetworkCallbacks did not throw exception");
2760 } catch (IllegalArgumentException expected) {}
2761 for (NetworkCallback networkCallback : networkCallbacks) {
2762 mCm.unregisterNetworkCallback(networkCallback);
2764 networkCallbacks.clear();
2766 ArrayList<PendingIntent> pendingIntents = new ArrayList<PendingIntent>();
2768 for (int i = 0; i < MAX_REQUESTS + 1; i++) {
2769 PendingIntent pendingIntent =
2770 PendingIntent.getBroadcast(mContext, 0, new Intent("a" + i), 0);
2771 mCm.requestNetwork(networkRequest, pendingIntent);
2772 pendingIntents.add(pendingIntent);
2774 fail("Registering " + MAX_REQUESTS +
2775 " PendingIntent NetworkRequests did not throw exception");
2776 } catch (IllegalArgumentException expected) {}
2777 for (PendingIntent pendingIntent : pendingIntents) {
2778 mCm.unregisterNetworkCallback(pendingIntent);
2780 pendingIntents.clear();
2783 for (int i = 0; i < MAX_REQUESTS + 1; i++) {
2784 PendingIntent pendingIntent =
2785 PendingIntent.getBroadcast(mContext, 0, new Intent("a" + i), 0);
2786 mCm.registerNetworkCallback(networkRequest, pendingIntent);
2787 pendingIntents.add(pendingIntent);
2789 fail("Registering " + MAX_REQUESTS +
2790 " PendingIntent NetworkCallbacks did not throw exception");
2791 } catch (IllegalArgumentException expected) {}
2792 for (PendingIntent pendingIntent : pendingIntents) {
2793 mCm.unregisterNetworkCallback(pendingIntent);
2795 pendingIntents.clear();
2796 mService.waitForIdle(5000);
2798 // Test that the limit is not hit when MAX_REQUESTS requests are added and removed.
2799 for (int i = 0; i < MAX_REQUESTS; i++) {
2800 NetworkCallback networkCallback = new NetworkCallback();
2801 mCm.requestNetwork(networkRequest, networkCallback);
2802 mCm.unregisterNetworkCallback(networkCallback);
2804 mService.waitForIdle();
2805 for (int i = 0; i < MAX_REQUESTS; i++) {
2806 NetworkCallback networkCallback = new NetworkCallback();
2807 mCm.registerNetworkCallback(networkRequest, networkCallback);
2808 mCm.unregisterNetworkCallback(networkCallback);
2810 mService.waitForIdle();
2811 for (int i = 0; i < MAX_REQUESTS; i++) {
2812 PendingIntent pendingIntent =
2813 PendingIntent.getBroadcast(mContext, 0, new Intent("b" + i), 0);
2814 mCm.requestNetwork(networkRequest, pendingIntent);
2815 mCm.unregisterNetworkCallback(pendingIntent);
2817 mService.waitForIdle();
2818 for (int i = 0; i < MAX_REQUESTS; i++) {
2819 PendingIntent pendingIntent =
2820 PendingIntent.getBroadcast(mContext, 0, new Intent("c" + i), 0);
2821 mCm.registerNetworkCallback(networkRequest, pendingIntent);
2822 mCm.unregisterNetworkCallback(pendingIntent);
2826 /* test utilities */
2827 static private void sleepFor(int ms) {
2830 } catch (InterruptedException e) {