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.mock.MockContentResolver;
72 import android.test.suitebuilder.annotation.LargeTest;
73 import android.test.suitebuilder.annotation.SmallTest;
74 import android.util.Log;
75 import android.util.LogPrinter;
77 import com.android.internal.util.FakeSettingsProvider;
78 import com.android.internal.util.WakeupMessage;
79 import com.android.server.connectivity.NetworkAgentInfo;
80 import com.android.server.connectivity.NetworkMonitor;
81 import com.android.server.connectivity.NetworkMonitor.CaptivePortalProbeResult;
82 import com.android.server.net.NetworkPinner;
84 import java.net.InetAddress;
85 import java.util.ArrayList;
86 import java.util.Arrays;
87 import java.util.Objects;
88 import java.util.concurrent.CountDownLatch;
89 import java.util.concurrent.LinkedBlockingQueue;
90 import java.util.concurrent.TimeUnit;
91 import java.util.concurrent.atomic.AtomicBoolean;
94 * Tests for {@link ConnectivityService}.
96 * Build, install and run with:
97 * runtest frameworks-services -c com.android.server.ConnectivityServiceTest
99 public class ConnectivityServiceTest extends AndroidTestCase {
100 private static final String TAG = "ConnectivityServiceTest";
102 private static final int TIMEOUT_MS = 500;
103 private static final int TEST_LINGER_DELAY_MS = 120;
105 private BroadcastInterceptingContext mServiceContext;
106 private WrappedConnectivityService mService;
107 private WrappedConnectivityManager mCm;
108 private MockNetworkAgent mWiFiNetworkAgent;
109 private MockNetworkAgent mCellNetworkAgent;
110 private MockNetworkAgent mEthernetNetworkAgent;
112 // This class exists to test bindProcessToNetwork and getBoundNetworkForProcess. These methods
113 // do not go through ConnectivityService but talk to netd directly, so they don't automatically
114 // reflect the state of our test ConnectivityService.
115 private class WrappedConnectivityManager extends ConnectivityManager {
116 private Network mFakeBoundNetwork;
118 public synchronized boolean bindProcessToNetwork(Network network) {
119 mFakeBoundNetwork = network;
123 public synchronized Network getBoundNetworkForProcess() {
124 return mFakeBoundNetwork;
127 public WrappedConnectivityManager(Context context, ConnectivityService service) {
128 super(context, service);
132 private class MockContext extends BroadcastInterceptingContext {
133 private final MockContentResolver mContentResolver;
135 MockContext(Context base) {
137 mContentResolver = new MockContentResolver();
138 mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
142 public Object getSystemService(String name) {
143 if (Context.CONNECTIVITY_SERVICE.equals(name)) return mCm;
144 if (Context.NOTIFICATION_SERVICE.equals(name)) return mock(NotificationManager.class);
145 return super.getSystemService(name);
149 public ContentResolver getContentResolver() {
150 return mContentResolver;
155 * A subclass of HandlerThread that allows callers to wait for it to become idle. waitForIdle
156 * will return immediately if the handler is already idle.
158 private class IdleableHandlerThread extends HandlerThread {
159 private IdleHandler mIdleHandler;
161 public IdleableHandlerThread(String name) {
165 public void waitForIdle(int timeoutMs) {
166 final ConditionVariable cv = new ConditionVariable();
167 final MessageQueue queue = getLooper().getQueue();
169 synchronized (queue) {
170 if (queue.isIdle()) {
174 assertNull("BUG: only one idle handler allowed", mIdleHandler);
175 mIdleHandler = new IdleHandler() {
176 public boolean queueIdle() {
177 synchronized (queue) {
180 return false; // Remove the handler.
184 queue.addIdleHandler(mIdleHandler);
187 if (!cv.block(timeoutMs)) {
188 fail("HandlerThread " + getName() +
189 " did not become idle after " + timeoutMs + " ms");
190 queue.removeIdleHandler(mIdleHandler);
195 // Tests that IdleableHandlerThread works as expected.
196 public void testIdleableHandlerThread() {
197 final int attempts = 50; // Causes the test to take about 200ms on bullhead-eng.
199 // Tests that waitForIdle returns immediately if the service is already idle.
200 for (int i = 0; i < attempts; i++) {
201 mService.waitForIdle();
204 // Bring up a network that we can use to send messages to ConnectivityService.
205 ConditionVariable cv = waitForConnectivityBroadcasts(1);
206 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
207 mWiFiNetworkAgent.connect(false);
209 Network n = mWiFiNetworkAgent.getNetwork();
212 // Tests that calling waitForIdle waits for messages to be processed.
213 for (int i = 0; i < attempts; i++) {
214 mWiFiNetworkAgent.setSignalStrength(i);
215 mService.waitForIdle();
216 assertEquals(i, mCm.getNetworkCapabilities(n).getSignalStrength());
219 // Ensure that not calling waitForIdle causes a race condition.
220 for (int i = 0; i < attempts; i++) {
221 mWiFiNetworkAgent.setSignalStrength(i);
222 if (i != mCm.getNetworkCapabilities(n).getSignalStrength()) {
223 // We hit a race condition, as expected. Pass the test.
228 // No race? There is a bug in this test.
229 fail("expected race condition at least once in " + attempts + " attempts");
232 private class MockNetworkAgent {
233 private final WrappedNetworkMonitor mWrappedNetworkMonitor;
234 private final NetworkInfo mNetworkInfo;
235 private final NetworkCapabilities mNetworkCapabilities;
236 private final IdleableHandlerThread mHandlerThread;
237 private final ConditionVariable mDisconnected = new ConditionVariable();
238 private final ConditionVariable mNetworkStatusReceived = new ConditionVariable();
239 private final ConditionVariable mPreventReconnectReceived = new ConditionVariable();
241 private NetworkAgent mNetworkAgent;
242 private int mStartKeepaliveError = PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED;
243 private int mStopKeepaliveError = PacketKeepalive.NO_KEEPALIVE;
244 private Integer mExpectedKeepaliveSlot = null;
245 // Contains the redirectUrl from networkStatus(). Before reading, wait for
246 // mNetworkStatusReceived.
247 private String mRedirectUrl;
249 MockNetworkAgent(int transport) {
250 final int type = transportToLegacyType(transport);
251 final String typeName = ConnectivityManager.getNetworkTypeName(type);
252 mNetworkInfo = new NetworkInfo(type, 0, typeName, "Mock");
253 mNetworkCapabilities = new NetworkCapabilities();
254 mNetworkCapabilities.addTransportType(transport);
256 case TRANSPORT_ETHERNET:
262 case TRANSPORT_CELLULAR:
266 throw new UnsupportedOperationException("unimplemented network type");
268 mHandlerThread = new IdleableHandlerThread("Mock-" + typeName);
269 mHandlerThread.start();
270 mNetworkAgent = new NetworkAgent(mHandlerThread.getLooper(), mServiceContext,
271 "Mock-" + typeName, mNetworkInfo, mNetworkCapabilities,
272 new LinkProperties(), mScore, new NetworkMisc()) {
274 public void unwanted() { mDisconnected.open(); }
277 public void startPacketKeepalive(Message msg) {
279 if (mExpectedKeepaliveSlot != null) {
280 assertEquals((int) mExpectedKeepaliveSlot, slot);
282 onPacketKeepaliveEvent(slot, mStartKeepaliveError);
286 public void stopPacketKeepalive(Message msg) {
287 onPacketKeepaliveEvent(msg.arg1, mStopKeepaliveError);
291 public void networkStatus(int status, String redirectUrl) {
292 mRedirectUrl = redirectUrl;
293 mNetworkStatusReceived.open();
297 protected void preventAutomaticReconnect() {
298 mPreventReconnectReceived.open();
301 // Waits for the NetworkAgent to be registered, which includes the creation of the
303 mService.waitForIdle();
304 mWrappedNetworkMonitor = mService.getLastCreatedWrappedNetworkMonitor();
307 public void waitForIdle(int timeoutMs) {
308 mHandlerThread.waitForIdle(timeoutMs);
311 public void waitForIdle() {
312 waitForIdle(TIMEOUT_MS);
315 public void adjustScore(int change) {
317 mNetworkAgent.sendNetworkScore(mScore);
320 public void addCapability(int capability) {
321 mNetworkCapabilities.addCapability(capability);
322 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
325 public void removeCapability(int capability) {
326 mNetworkCapabilities.removeCapability(capability);
327 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
330 public void setSignalStrength(int signalStrength) {
331 mNetworkCapabilities.setSignalStrength(signalStrength);
332 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
335 public void connectWithoutInternet() {
336 mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, null);
337 mNetworkAgent.sendNetworkInfo(mNetworkInfo);
341 * Transition this NetworkAgent to CONNECTED state with NET_CAPABILITY_INTERNET.
342 * @param validated Indicate if network should pretend to be validated.
344 public void connect(boolean validated) {
345 assertEquals("MockNetworkAgents can only be connected once",
346 mNetworkInfo.getDetailedState(), DetailedState.IDLE);
347 assertFalse(mNetworkCapabilities.hasCapability(NET_CAPABILITY_INTERNET));
349 NetworkCallback callback = null;
350 final ConditionVariable validatedCv = new ConditionVariable();
352 mWrappedNetworkMonitor.gen204ProbeResult = 204;
353 NetworkRequest request = new NetworkRequest.Builder()
354 .addTransportType(mNetworkCapabilities.getTransportTypes()[0])
356 callback = new NetworkCallback() {
357 public void onCapabilitiesChanged(Network network,
358 NetworkCapabilities networkCapabilities) {
359 if (network.equals(getNetwork()) &&
360 networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED)) {
365 mCm.registerNetworkCallback(request, callback);
367 addCapability(NET_CAPABILITY_INTERNET);
369 connectWithoutInternet();
372 // Wait for network to validate.
373 waitFor(validatedCv);
374 mWrappedNetworkMonitor.gen204ProbeResult = 500;
377 if (callback != null) mCm.unregisterNetworkCallback(callback);
380 public void connectWithCaptivePortal(String redirectUrl) {
381 mWrappedNetworkMonitor.gen204ProbeResult = 200;
382 mWrappedNetworkMonitor.gen204ProbeRedirectUrl = redirectUrl;
386 public void disconnect() {
387 mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, null);
388 mNetworkAgent.sendNetworkInfo(mNetworkInfo);
391 public Network getNetwork() {
392 return new Network(mNetworkAgent.netId);
395 public ConditionVariable getPreventReconnectReceived() {
396 return mPreventReconnectReceived;
399 public ConditionVariable getDisconnectedCV() {
400 return mDisconnected;
403 public WrappedNetworkMonitor getWrappedNetworkMonitor() {
404 return mWrappedNetworkMonitor;
407 public void sendLinkProperties(LinkProperties lp) {
408 mNetworkAgent.sendLinkProperties(lp);
411 public void setStartKeepaliveError(int error) {
412 mStartKeepaliveError = error;
415 public void setStopKeepaliveError(int error) {
416 mStopKeepaliveError = error;
419 public void setExpectedKeepaliveSlot(Integer slot) {
420 mExpectedKeepaliveSlot = slot;
423 public String waitForRedirectUrl() {
424 assertTrue(mNetworkStatusReceived.block(TIMEOUT_MS));
430 * A NetworkFactory that allows tests to wait until any in-flight NetworkRequest add or remove
431 * operations have been processed. Before ConnectivityService can add or remove any requests,
432 * the factory must be told to expect those operations by calling expectAddRequests or
433 * expectRemoveRequests.
435 private static class MockNetworkFactory extends NetworkFactory {
436 private final ConditionVariable mNetworkStartedCV = new ConditionVariable();
437 private final ConditionVariable mNetworkStoppedCV = new ConditionVariable();
438 private final AtomicBoolean mNetworkStarted = new AtomicBoolean(false);
440 // Used to expect that requests be removed or added on a separate thread, without sleeping.
441 // Callers can call either expectAddRequests() or expectRemoveRequests() exactly once, then
442 // cause some other thread to add or remove requests, then call waitForRequests(). We can
443 // either expect requests to be added or removed, but not both, because CountDownLatch can
444 // only count in one direction.
445 private CountDownLatch mExpectations;
447 // Whether we are currently expecting requests to be added or removed. Valid only if
448 // mExpectations is non-null.
449 private boolean mExpectingAdditions;
451 public MockNetworkFactory(Looper looper, Context context, String logTag,
452 NetworkCapabilities filter) {
453 super(looper, context, logTag, filter);
456 public int getMyRequestCount() {
457 return getRequestCount();
460 protected void startNetwork() {
461 mNetworkStarted.set(true);
462 mNetworkStartedCV.open();
465 protected void stopNetwork() {
466 mNetworkStarted.set(false);
467 mNetworkStoppedCV.open();
470 public boolean getMyStartRequested() {
471 return mNetworkStarted.get();
474 public ConditionVariable getNetworkStartedCV() {
475 mNetworkStartedCV.close();
476 return mNetworkStartedCV;
479 public ConditionVariable getNetworkStoppedCV() {
480 mNetworkStoppedCV.close();
481 return mNetworkStoppedCV;
485 protected void handleAddRequest(NetworkRequest request, int score) {
486 // If we're expecting anything, we must be expecting additions.
487 if (mExpectations != null && !mExpectingAdditions) {
488 fail("Can't add requests while expecting requests to be removed");
492 super.handleAddRequest(request, score);
494 // Reduce the number of request additions we're waiting for.
495 if (mExpectingAdditions) {
496 assertTrue("Added more requests than expected", mExpectations.getCount() > 0);
497 mExpectations.countDown();
502 protected void handleRemoveRequest(NetworkRequest request) {
503 // If we're expecting anything, we must be expecting removals.
504 if (mExpectations != null && mExpectingAdditions) {
505 fail("Can't remove requests while expecting requests to be added");
508 // Remove the request.
509 super.handleRemoveRequest(request);
511 // Reduce the number of request removals we're waiting for.
512 if (!mExpectingAdditions) {
513 assertTrue("Removed more requests than expected", mExpectations.getCount() > 0);
514 mExpectations.countDown();
518 private void assertNoExpectations() {
519 if (mExpectations != null) {
520 fail("Can't add expectation, " + mExpectations.getCount() + " already pending");
524 // Expects that count requests will be added.
525 public void expectAddRequests(final int count) {
526 assertNoExpectations();
527 mExpectingAdditions = true;
528 mExpectations = new CountDownLatch(count);
531 // Expects that count requests will be removed.
532 public void expectRemoveRequests(final int count) {
533 assertNoExpectations();
534 mExpectingAdditions = false;
535 mExpectations = new CountDownLatch(count);
538 // Waits for the expected request additions or removals to happen within a timeout.
539 public void waitForRequests() throws InterruptedException {
540 assertNotNull("Nothing to wait for", mExpectations);
541 mExpectations.await(TIMEOUT_MS, TimeUnit.MILLISECONDS);
542 final long count = mExpectations.getCount();
543 final String msg = count + " requests still not " +
544 (mExpectingAdditions ? "added" : "removed") +
545 " after " + TIMEOUT_MS + " ms";
546 assertEquals(msg, 0, count);
547 mExpectations = null;
550 public void waitForNetworkRequests(final int count) throws InterruptedException {
552 assertEquals(count, getMyRequestCount());
556 private class FakeWakeupMessage extends WakeupMessage {
557 private static final int UNREASONABLY_LONG_WAIT = 1000;
559 public FakeWakeupMessage(Context context, Handler handler, String cmdName, int cmd) {
560 super(context, handler, cmdName, cmd);
563 public FakeWakeupMessage(Context context, Handler handler, String cmdName, int cmd,
564 int arg1, int arg2, Object obj) {
565 super(context, handler, cmdName, cmd, arg1, arg2, obj);
569 public void schedule(long when) {
570 long delayMs = when - SystemClock.elapsedRealtime();
571 if (delayMs < 0) delayMs = 0;
572 if (delayMs > UNREASONABLY_LONG_WAIT) {
573 fail("Attempting to send msg more than " + UNREASONABLY_LONG_WAIT +
574 "ms into the future: " + delayMs);
576 Message msg = mHandler.obtainMessage(mCmd, mArg1, mArg2, mObj);
577 mHandler.sendMessageDelayed(msg, delayMs);
581 public void cancel() {
582 mHandler.removeMessages(mCmd, mObj);
586 public void onAlarm() {
587 throw new AssertionError("Should never happen. Update this fake.");
591 // NetworkMonitor implementation allowing overriding of Internet connectivity probe result.
592 private class WrappedNetworkMonitor extends NetworkMonitor {
593 // HTTP response code fed back to NetworkMonitor for Internet connectivity probe.
594 public int gen204ProbeResult = 500;
595 public String gen204ProbeRedirectUrl = null;
597 public WrappedNetworkMonitor(Context context, Handler handler,
598 NetworkAgentInfo networkAgentInfo, NetworkRequest defaultRequest,
599 IpConnectivityLog log) {
600 super(context, handler, networkAgentInfo, defaultRequest, log);
604 protected CaptivePortalProbeResult isCaptivePortal() {
605 if (!mIsCaptivePortalCheckEnabled) { return new CaptivePortalProbeResult(204); }
606 return new CaptivePortalProbeResult(gen204ProbeResult, gen204ProbeRedirectUrl, null);
610 private class WrappedAvoidBadWifiTracker extends AvoidBadWifiTracker {
611 public boolean configRestrictsAvoidBadWifi;
613 public WrappedAvoidBadWifiTracker(Context c, Handler h, Runnable r) {
618 public boolean configRestrictsAvoidBadWifi() {
619 return configRestrictsAvoidBadWifi;
623 private class WrappedConnectivityService extends ConnectivityService {
624 public WrappedAvoidBadWifiTracker wrappedAvoidBadWifiTracker;
625 private WrappedNetworkMonitor mLastCreatedNetworkMonitor;
627 public WrappedConnectivityService(Context context, INetworkManagementService netManager,
628 INetworkStatsService statsService, INetworkPolicyManager policyManager,
629 IpConnectivityLog log) {
630 super(context, netManager, statsService, policyManager, log);
631 mLingerDelayMs = TEST_LINGER_DELAY_MS;
635 protected HandlerThread createHandlerThread() {
636 return new IdleableHandlerThread("WrappedConnectivityService");
640 protected int getDefaultTcpRwnd() {
641 // Prevent wrapped ConnectivityService from trying to write to SystemProperties.
646 protected int reserveNetId() {
648 final int netId = super.reserveNetId();
650 // Don't overlap test NetIDs with real NetIDs as binding sockets to real networks
651 // can have odd side-effects, like network validations succeeding.
652 final Network[] networks = ConnectivityManager.from(getContext()).getAllNetworks();
653 boolean overlaps = false;
654 for (Network network : networks) {
655 if (netId == network.netId) {
660 if (overlaps) continue;
667 public NetworkMonitor createNetworkMonitor(Context context, Handler handler,
668 NetworkAgentInfo nai, NetworkRequest defaultRequest) {
669 final WrappedNetworkMonitor monitor = new WrappedNetworkMonitor(
670 context, handler, nai, defaultRequest, mock(IpConnectivityLog.class));
671 mLastCreatedNetworkMonitor = monitor;
676 public AvoidBadWifiTracker createAvoidBadWifiTracker(
677 Context c, Handler h, Runnable r) {
678 final WrappedAvoidBadWifiTracker tracker = new WrappedAvoidBadWifiTracker(c, h, r);
682 public WrappedAvoidBadWifiTracker getAvoidBadWifiTracker() {
683 return (WrappedAvoidBadWifiTracker) mAvoidBadWifiTracker;
687 public WakeupMessage makeWakeupMessage(
688 Context context, Handler handler, String cmdName, int cmd, Object obj) {
689 return new FakeWakeupMessage(context, handler, cmdName, cmd, 0, 0, obj);
692 public WrappedNetworkMonitor getLastCreatedWrappedNetworkMonitor() {
693 return mLastCreatedNetworkMonitor;
696 public void waitForIdle(int timeoutMs) {
697 ((IdleableHandlerThread) mHandlerThread).waitForIdle(timeoutMs);
700 public void waitForIdle() {
701 waitForIdle(TIMEOUT_MS);
705 private interface Criteria {
706 public boolean get();
710 * Wait up to 500ms for {@code criteria.get()} to become true, polling.
711 * Fails if 500ms goes by before {@code criteria.get()} to become true.
713 static private void waitFor(Criteria criteria) {
715 while (!criteria.get()) {
718 } catch (InterruptedException e) {
720 if (++delays == 10) fail();
725 * Wait up to TIMEOUT_MS for {@code conditionVariable} to open.
726 * Fails if TIMEOUT_MS goes by before {@code conditionVariable} opens.
728 static private void waitFor(ConditionVariable conditionVariable) {
729 assertTrue(conditionVariable.block(TIMEOUT_MS));
733 public void setUp() throws Exception {
736 // InstrumentationTestRunner prepares a looper, but AndroidJUnitRunner does not.
737 // http://b/25897652 .
738 if (Looper.myLooper() == null) {
742 mServiceContext = new MockContext(getContext());
743 mService = new WrappedConnectivityService(mServiceContext,
744 mock(INetworkManagementService.class),
745 mock(INetworkStatsService.class),
746 mock(INetworkPolicyManager.class),
747 mock(IpConnectivityLog.class));
749 mService.systemReady();
750 mCm = new WrappedConnectivityManager(getContext(), mService);
751 mCm.bindProcessToNetwork(null);
753 // Ensure that the default setting for Captive Portals is used for most tests
754 setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_PROMPT);
757 public void tearDown() throws Exception {
758 setMobileDataAlwaysOn(false);
759 if (mCellNetworkAgent != null) { mCellNetworkAgent.disconnect(); }
760 if (mWiFiNetworkAgent != null) { mWiFiNetworkAgent.disconnect(); }
761 mCellNetworkAgent = mWiFiNetworkAgent = null;
765 private int transportToLegacyType(int transport) {
767 case TRANSPORT_ETHERNET:
768 return TYPE_ETHERNET;
771 case TRANSPORT_CELLULAR:
774 throw new IllegalStateException("Unknown transport " + transport);
778 private void verifyActiveNetwork(int transport) {
779 // Test getActiveNetworkInfo()
780 assertNotNull(mCm.getActiveNetworkInfo());
781 assertEquals(transportToLegacyType(transport), mCm.getActiveNetworkInfo().getType());
782 // Test getActiveNetwork()
783 assertNotNull(mCm.getActiveNetwork());
784 assertEquals(mCm.getActiveNetwork(), mCm.getActiveNetworkForUid(Process.myUid()));
787 assertEquals(mCm.getActiveNetwork(), mWiFiNetworkAgent.getNetwork());
789 case TRANSPORT_CELLULAR:
790 assertEquals(mCm.getActiveNetwork(), mCellNetworkAgent.getNetwork());
793 throw new IllegalStateException("Unknown transport" + transport);
795 // Test getNetworkInfo(Network)
796 assertNotNull(mCm.getNetworkInfo(mCm.getActiveNetwork()));
797 assertEquals(transportToLegacyType(transport), mCm.getNetworkInfo(mCm.getActiveNetwork()).getType());
798 // Test getNetworkCapabilities(Network)
799 assertNotNull(mCm.getNetworkCapabilities(mCm.getActiveNetwork()));
800 assertTrue(mCm.getNetworkCapabilities(mCm.getActiveNetwork()).hasTransport(transport));
803 private void verifyNoNetwork() {
804 // Test getActiveNetworkInfo()
805 assertNull(mCm.getActiveNetworkInfo());
806 // Test getActiveNetwork()
807 assertNull(mCm.getActiveNetwork());
808 assertNull(mCm.getActiveNetworkForUid(Process.myUid()));
809 // Test getAllNetworks()
810 assertEquals(0, mCm.getAllNetworks().length);
814 * Return a ConditionVariable that opens when {@code count} numbers of CONNECTIVITY_ACTION
815 * broadcasts are received.
817 private ConditionVariable waitForConnectivityBroadcasts(final int count) {
818 final ConditionVariable cv = new ConditionVariable();
819 mServiceContext.registerReceiver(new BroadcastReceiver() {
820 private int remaining = count;
821 public void onReceive(Context context, Intent intent) {
822 if (--remaining == 0) {
824 mServiceContext.unregisterReceiver(this);
827 }, new IntentFilter(CONNECTIVITY_ACTION));
832 public void testLingering() throws Exception {
834 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
835 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
836 assertNull(mCm.getActiveNetworkInfo());
837 assertNull(mCm.getActiveNetwork());
838 // Test bringing up validated cellular.
839 ConditionVariable cv = waitForConnectivityBroadcasts(1);
840 mCellNetworkAgent.connect(true);
842 verifyActiveNetwork(TRANSPORT_CELLULAR);
843 assertEquals(2, mCm.getAllNetworks().length);
844 assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) ||
845 mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork()));
846 assertTrue(mCm.getAllNetworks()[0].equals(mWiFiNetworkAgent.getNetwork()) ||
847 mCm.getAllNetworks()[1].equals(mWiFiNetworkAgent.getNetwork()));
848 // Test bringing up validated WiFi.
849 cv = waitForConnectivityBroadcasts(2);
850 mWiFiNetworkAgent.connect(true);
852 verifyActiveNetwork(TRANSPORT_WIFI);
853 assertEquals(2, mCm.getAllNetworks().length);
854 assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) ||
855 mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork()));
856 assertTrue(mCm.getAllNetworks()[0].equals(mCellNetworkAgent.getNetwork()) ||
857 mCm.getAllNetworks()[1].equals(mCellNetworkAgent.getNetwork()));
858 // Test cellular linger timeout.
859 waitFor(new Criteria() {
860 public boolean get() { return mCm.getAllNetworks().length == 1; } });
861 verifyActiveNetwork(TRANSPORT_WIFI);
862 assertEquals(1, mCm.getAllNetworks().length);
863 assertEquals(mCm.getAllNetworks()[0], mCm.getActiveNetwork());
864 // Test WiFi disconnect.
865 cv = waitForConnectivityBroadcasts(1);
866 mWiFiNetworkAgent.disconnect();
872 public void testValidatedCellularOutscoresUnvalidatedWiFi() throws Exception {
873 // Test bringing up unvalidated WiFi
874 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
875 ConditionVariable cv = waitForConnectivityBroadcasts(1);
876 mWiFiNetworkAgent.connect(false);
878 verifyActiveNetwork(TRANSPORT_WIFI);
879 // Test bringing up unvalidated cellular
880 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
881 mCellNetworkAgent.connect(false);
882 mService.waitForIdle();
883 verifyActiveNetwork(TRANSPORT_WIFI);
884 // Test cellular disconnect.
885 mCellNetworkAgent.disconnect();
886 mService.waitForIdle();
887 verifyActiveNetwork(TRANSPORT_WIFI);
888 // Test bringing up validated cellular
889 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
890 cv = waitForConnectivityBroadcasts(2);
891 mCellNetworkAgent.connect(true);
893 verifyActiveNetwork(TRANSPORT_CELLULAR);
894 // Test cellular disconnect.
895 cv = waitForConnectivityBroadcasts(2);
896 mCellNetworkAgent.disconnect();
898 verifyActiveNetwork(TRANSPORT_WIFI);
899 // Test WiFi disconnect.
900 cv = waitForConnectivityBroadcasts(1);
901 mWiFiNetworkAgent.disconnect();
907 public void testUnvalidatedWifiOutscoresUnvalidatedCellular() throws Exception {
908 // Test bringing up unvalidated cellular.
909 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
910 ConditionVariable cv = waitForConnectivityBroadcasts(1);
911 mCellNetworkAgent.connect(false);
913 verifyActiveNetwork(TRANSPORT_CELLULAR);
914 // Test bringing up unvalidated WiFi.
915 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
916 cv = waitForConnectivityBroadcasts(2);
917 mWiFiNetworkAgent.connect(false);
919 verifyActiveNetwork(TRANSPORT_WIFI);
920 // Test WiFi disconnect.
921 cv = waitForConnectivityBroadcasts(2);
922 mWiFiNetworkAgent.disconnect();
924 verifyActiveNetwork(TRANSPORT_CELLULAR);
925 // Test cellular disconnect.
926 cv = waitForConnectivityBroadcasts(1);
927 mCellNetworkAgent.disconnect();
933 public void testUnlingeringDoesNotValidate() throws Exception {
934 // Test bringing up unvalidated WiFi.
935 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
936 ConditionVariable cv = waitForConnectivityBroadcasts(1);
937 mWiFiNetworkAgent.connect(false);
939 verifyActiveNetwork(TRANSPORT_WIFI);
940 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
941 NET_CAPABILITY_VALIDATED));
942 // Test bringing up validated cellular.
943 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
944 cv = waitForConnectivityBroadcasts(2);
945 mCellNetworkAgent.connect(true);
947 verifyActiveNetwork(TRANSPORT_CELLULAR);
948 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
949 NET_CAPABILITY_VALIDATED));
950 // Test cellular disconnect.
951 cv = waitForConnectivityBroadcasts(2);
952 mCellNetworkAgent.disconnect();
954 verifyActiveNetwork(TRANSPORT_WIFI);
955 // Unlingering a network should not cause it to be marked as validated.
956 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
957 NET_CAPABILITY_VALIDATED));
961 public void testCellularOutscoresWeakWifi() throws Exception {
962 // Test bringing up validated cellular.
963 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
964 ConditionVariable cv = waitForConnectivityBroadcasts(1);
965 mCellNetworkAgent.connect(true);
967 verifyActiveNetwork(TRANSPORT_CELLULAR);
968 // Test bringing up validated WiFi.
969 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
970 cv = waitForConnectivityBroadcasts(2);
971 mWiFiNetworkAgent.connect(true);
973 verifyActiveNetwork(TRANSPORT_WIFI);
974 // Test WiFi getting really weak.
975 cv = waitForConnectivityBroadcasts(2);
976 mWiFiNetworkAgent.adjustScore(-11);
978 verifyActiveNetwork(TRANSPORT_CELLULAR);
979 // Test WiFi restoring signal strength.
980 cv = waitForConnectivityBroadcasts(2);
981 mWiFiNetworkAgent.adjustScore(11);
983 verifyActiveNetwork(TRANSPORT_WIFI);
987 public void testReapingNetwork() throws Exception {
988 // Test bringing up WiFi without NET_CAPABILITY_INTERNET.
989 // Expect it to be torn down immediately because it satisfies no requests.
990 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
991 ConditionVariable cv = mWiFiNetworkAgent.getDisconnectedCV();
992 mWiFiNetworkAgent.connectWithoutInternet();
994 // Test bringing up cellular without NET_CAPABILITY_INTERNET.
995 // Expect it to be torn down immediately because it satisfies no requests.
996 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
997 cv = mCellNetworkAgent.getDisconnectedCV();
998 mCellNetworkAgent.connectWithoutInternet();
1000 // Test bringing up validated WiFi.
1001 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1002 cv = waitForConnectivityBroadcasts(1);
1003 mWiFiNetworkAgent.connect(true);
1005 verifyActiveNetwork(TRANSPORT_WIFI);
1006 // Test bringing up unvalidated cellular.
1007 // Expect it to be torn down because it could never be the highest scoring network
1008 // satisfying the default request even if it validated.
1009 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1010 cv = mCellNetworkAgent.getDisconnectedCV();
1011 mCellNetworkAgent.connect(false);
1013 verifyActiveNetwork(TRANSPORT_WIFI);
1014 cv = mWiFiNetworkAgent.getDisconnectedCV();
1015 mWiFiNetworkAgent.disconnect();
1020 public void testCellularFallback() throws Exception {
1021 // Test bringing up validated cellular.
1022 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1023 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1024 mCellNetworkAgent.connect(true);
1026 verifyActiveNetwork(TRANSPORT_CELLULAR);
1027 // Test bringing up validated WiFi.
1028 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1029 cv = waitForConnectivityBroadcasts(2);
1030 mWiFiNetworkAgent.connect(true);
1032 verifyActiveNetwork(TRANSPORT_WIFI);
1033 // Reevaluate WiFi (it'll instantly fail DNS).
1034 cv = waitForConnectivityBroadcasts(2);
1035 assertTrue(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1036 NET_CAPABILITY_VALIDATED));
1037 mCm.reportBadNetwork(mWiFiNetworkAgent.getNetwork());
1038 // Should quickly fall back to Cellular.
1040 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1041 NET_CAPABILITY_VALIDATED));
1042 verifyActiveNetwork(TRANSPORT_CELLULAR);
1043 // Reevaluate cellular (it'll instantly fail DNS).
1044 cv = waitForConnectivityBroadcasts(2);
1045 assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1046 NET_CAPABILITY_VALIDATED));
1047 mCm.reportBadNetwork(mCellNetworkAgent.getNetwork());
1048 // Should quickly fall back to WiFi.
1050 assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1051 NET_CAPABILITY_VALIDATED));
1052 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1053 NET_CAPABILITY_VALIDATED));
1054 verifyActiveNetwork(TRANSPORT_WIFI);
1058 public void testWiFiFallback() throws Exception {
1059 // Test bringing up unvalidated WiFi.
1060 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1061 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1062 mWiFiNetworkAgent.connect(false);
1064 verifyActiveNetwork(TRANSPORT_WIFI);
1065 // Test bringing up validated cellular.
1066 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1067 cv = waitForConnectivityBroadcasts(2);
1068 mCellNetworkAgent.connect(true);
1070 verifyActiveNetwork(TRANSPORT_CELLULAR);
1071 // Reevaluate cellular (it'll instantly fail DNS).
1072 cv = waitForConnectivityBroadcasts(2);
1073 assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1074 NET_CAPABILITY_VALIDATED));
1075 mCm.reportBadNetwork(mCellNetworkAgent.getNetwork());
1076 // Should quickly fall back to WiFi.
1078 assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1079 NET_CAPABILITY_VALIDATED));
1080 verifyActiveNetwork(TRANSPORT_WIFI);
1083 enum CallbackState {
1086 NETWORK_CAPABILITIES,
1093 * Utility NetworkCallback for testing. The caller must explicitly test for all the callbacks
1094 * this class receives, by calling expectCallback() exactly once each time a callback is
1095 * received. assertNoCallback may be called at any time.
1097 private class TestNetworkCallback extends NetworkCallback {
1098 // Chosen to be much less than the linger timeout. This ensures that we can distinguish
1099 // between a LOST callback that arrives immediately and a LOST callback that arrives after
1100 // the linger timeout.
1101 private final static int TIMEOUT_MS = 50;
1103 private class CallbackInfo {
1104 public final CallbackState state;
1105 public final Network network;
1107 public CallbackInfo(CallbackState s, Network n, Object o) {
1108 state = s; network = n; arg = o;
1110 public String toString() { return String.format("%s (%s)", state, network); }
1111 public boolean equals(Object o) {
1112 if (!(o instanceof CallbackInfo)) return false;
1113 // Ignore timeMs, since it's unpredictable.
1114 CallbackInfo other = (CallbackInfo) o;
1115 return state == other.state && Objects.equals(network, other.network);
1118 private final LinkedBlockingQueue<CallbackInfo> mCallbacks = new LinkedBlockingQueue<>();
1120 protected void setLastCallback(CallbackState state, Network network, Object o) {
1121 mCallbacks.offer(new CallbackInfo(state, network, o));
1125 public void onAvailable(Network network) {
1126 setLastCallback(CallbackState.AVAILABLE, network, null);
1130 public void onLosing(Network network, int maxMsToLive) {
1131 setLastCallback(CallbackState.LOSING, network, maxMsToLive /* autoboxed int */);
1135 public void onLost(Network network) {
1136 setLastCallback(CallbackState.LOST, network, null);
1139 void expectCallback(CallbackState state, MockNetworkAgent mockAgent, int timeoutMs) {
1140 CallbackInfo expected = new CallbackInfo(
1141 state, (mockAgent != null) ? mockAgent.getNetwork() : null, 0);
1142 CallbackInfo actual;
1144 actual = mCallbacks.poll(timeoutMs, TimeUnit.MILLISECONDS);
1145 assertEquals("Unexpected callback:", expected, actual);
1146 } catch (InterruptedException e) {
1147 fail("Did not receive expected " + expected + " after " + TIMEOUT_MS + "ms");
1148 actual = null; // Or the compiler can't tell it's never used uninitialized.
1150 if (state == CallbackState.LOSING) {
1151 String msg = String.format(
1152 "Invalid linger time value %d, must be between %d and %d",
1153 actual.arg, 0, TEST_LINGER_DELAY_MS);
1154 int maxMsToLive = (Integer) actual.arg;
1155 assertTrue(msg, 0 <= maxMsToLive && maxMsToLive <= TEST_LINGER_DELAY_MS);
1159 void expectCallback(CallbackState state, MockNetworkAgent mockAgent) {
1160 expectCallback(state, mockAgent, TIMEOUT_MS);
1163 void assertNoCallback() {
1164 mService.waitForIdle();
1165 CallbackInfo c = mCallbacks.peek();
1166 assertNull("Unexpected callback: " + c, c);
1170 // Can't be part of TestNetworkCallback because "cannot be declared static; static methods can
1171 // only be declared in a static or top level type".
1172 static void assertNoCallbacks(TestNetworkCallback ... callbacks) {
1173 for (TestNetworkCallback c : callbacks) {
1174 c.assertNoCallback();
1179 public void testStateChangeNetworkCallbacks() throws Exception {
1180 final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback();
1181 final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
1182 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
1183 final NetworkRequest genericRequest = new NetworkRequest.Builder()
1184 .clearCapabilities().build();
1185 final NetworkRequest wifiRequest = new NetworkRequest.Builder()
1186 .addTransportType(TRANSPORT_WIFI).build();
1187 final NetworkRequest cellRequest = new NetworkRequest.Builder()
1188 .addTransportType(TRANSPORT_CELLULAR).build();
1189 mCm.registerNetworkCallback(genericRequest, genericNetworkCallback);
1190 mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
1191 mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
1193 // Test unvalidated networks
1194 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1195 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1196 mCellNetworkAgent.connect(false);
1197 genericNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1198 cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1199 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1201 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
1203 // This should not trigger spurious onAvailable() callbacks, b/21762680.
1204 mCellNetworkAgent.adjustScore(-1);
1205 mService.waitForIdle();
1206 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
1207 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1209 cv = waitForConnectivityBroadcasts(2);
1210 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1211 mWiFiNetworkAgent.connect(false);
1212 genericNetworkCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1213 wifiNetworkCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1214 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1216 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
1218 cv = waitForConnectivityBroadcasts(2);
1219 mWiFiNetworkAgent.disconnect();
1220 genericNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1221 wifiNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1222 cellNetworkCallback.assertNoCallback();
1224 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
1226 cv = waitForConnectivityBroadcasts(1);
1227 mCellNetworkAgent.disconnect();
1228 genericNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1229 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1231 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
1233 // Test validated networks
1234 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1235 mCellNetworkAgent.connect(true);
1236 genericNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1237 cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1238 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1239 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
1241 // This should not trigger spurious onAvailable() callbacks, b/21762680.
1242 mCellNetworkAgent.adjustScore(-1);
1243 mService.waitForIdle();
1244 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
1245 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1247 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1248 mWiFiNetworkAgent.connect(true);
1249 genericNetworkCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1250 genericNetworkCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
1251 wifiNetworkCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1252 cellNetworkCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
1253 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1254 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
1256 mWiFiNetworkAgent.disconnect();
1257 genericNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1258 wifiNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1259 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
1261 mCellNetworkAgent.disconnect();
1262 genericNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1263 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1264 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
1268 public void testMultipleLingering() {
1269 NetworkRequest request = new NetworkRequest.Builder()
1270 .clearCapabilities().addCapability(NET_CAPABILITY_NOT_METERED)
1272 TestNetworkCallback callback = new TestNetworkCallback();
1273 mCm.registerNetworkCallback(request, callback);
1275 TestNetworkCallback defaultCallback = new TestNetworkCallback();
1276 mCm.registerDefaultNetworkCallback(defaultCallback);
1278 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1279 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1280 mEthernetNetworkAgent = new MockNetworkAgent(TRANSPORT_ETHERNET);
1282 mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
1283 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
1284 mEthernetNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
1286 mCellNetworkAgent.connect(true);
1287 callback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1288 defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1289 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1291 mWiFiNetworkAgent.connect(true);
1292 // We get AVAILABLE on wifi when wifi connects and satisfies our unmetered request.
1293 // We then get LOSING when wifi validates and cell is outscored.
1294 callback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1295 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
1296 defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1297 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1299 mEthernetNetworkAgent.connect(true);
1300 callback.expectCallback(CallbackState.AVAILABLE, mEthernetNetworkAgent);
1301 callback.expectCallback(CallbackState.LOSING, mWiFiNetworkAgent);
1302 defaultCallback.expectCallback(CallbackState.AVAILABLE, mEthernetNetworkAgent);
1303 assertEquals(mEthernetNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1305 mEthernetNetworkAgent.disconnect();
1306 callback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
1307 defaultCallback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
1308 defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1310 for (int i = 0; i < 4; i++) {
1311 MockNetworkAgent oldNetwork, newNetwork;
1313 mWiFiNetworkAgent.adjustScore(-15);
1314 oldNetwork = mWiFiNetworkAgent;
1315 newNetwork = mCellNetworkAgent;
1317 mWiFiNetworkAgent.adjustScore(15);
1318 oldNetwork = mCellNetworkAgent;
1319 newNetwork = mWiFiNetworkAgent;
1322 callback.expectCallback(CallbackState.LOSING, oldNetwork);
1323 // TODO: should we send an AVAILABLE callback to newNetwork, to indicate that it is no
1324 // longer lingering?
1325 defaultCallback.expectCallback(CallbackState.AVAILABLE, newNetwork);
1326 assertEquals(newNetwork.getNetwork(), mCm.getActiveNetwork());
1328 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1330 // Verify that if a network no longer satisfies a request, we send LOST and not LOSING, even
1331 // if the network is still up.
1332 mWiFiNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
1333 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1335 // Wifi no longer satisfies our listen, which is for an unmetered network.
1336 // But because its score is 55, it's still up (and the default network).
1337 defaultCallback.assertNoCallback();
1338 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1340 // Disconnect our test networks.
1341 mWiFiNetworkAgent.disconnect();
1342 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1343 defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1344 mCellNetworkAgent.disconnect();
1345 defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1347 mCm.unregisterNetworkCallback(callback);
1348 mService.waitForIdle();
1350 // Check that a network is only lingered or torn down if it would not satisfy a request even
1352 request = new NetworkRequest.Builder().clearCapabilities().build();
1353 callback = new TestNetworkCallback();
1355 mCm.registerNetworkCallback(request, callback);
1357 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1358 mCellNetworkAgent.connect(false); // Score: 10
1359 callback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1360 defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1361 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1363 // Bring up wifi with a score of 20.
1364 // Cell stays up because it would satisfy the default request if it validated.
1365 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1366 mWiFiNetworkAgent.connect(false); // Score: 20
1367 callback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1368 defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1369 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1371 mWiFiNetworkAgent.disconnect();
1372 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1373 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1374 defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1375 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1377 // Bring up wifi with a score of 70.
1378 // Cell is lingered because it would not satisfy any request, even if it validated.
1379 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1380 mWiFiNetworkAgent.adjustScore(50);
1381 mWiFiNetworkAgent.connect(false); // Score: 70
1382 callback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1383 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
1384 defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1385 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1388 mWiFiNetworkAgent.disconnect();
1389 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1390 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1391 defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1392 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1394 // Bring up wifi, then validate it. Previous versions would immediately tear down cell, but
1395 // it's arguably correct to linger it, since it was the default network before it validated.
1396 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1397 mWiFiNetworkAgent.connect(true);
1398 callback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1399 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
1400 defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1401 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1403 mWiFiNetworkAgent.disconnect();
1404 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1405 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1406 defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1407 mCellNetworkAgent.disconnect();
1408 callback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1409 defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1411 // If a network is lingering, and we add and remove a request from it, resume lingering.
1412 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1413 mCellNetworkAgent.connect(true);
1414 callback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1415 defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1416 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1417 mWiFiNetworkAgent.connect(true);
1418 callback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1419 defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1420 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
1422 NetworkRequest cellRequest = new NetworkRequest.Builder()
1423 .addTransportType(TRANSPORT_CELLULAR).build();
1424 NetworkCallback noopCallback = new NetworkCallback();
1425 mCm.requestNetwork(cellRequest, noopCallback);
1426 // TODO: should this cause an AVAILABLE callback, to indicate that the network is no longer
1428 mCm.unregisterNetworkCallback(noopCallback);
1429 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
1431 // Similar to the above: lingering can start even after the lingered request is removed.
1432 // Disconnect wifi and switch to cell.
1433 mWiFiNetworkAgent.disconnect();
1434 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1435 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1436 defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1438 // Cell is now the default network. Pin it with a cell-specific request.
1439 noopCallback = new NetworkCallback(); // Can't reuse NetworkCallbacks. http://b/20701525
1440 mCm.requestNetwork(cellRequest, noopCallback);
1442 // Now connect wifi, and expect it to become the default network.
1443 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1444 mWiFiNetworkAgent.connect(true);
1445 callback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1446 defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1447 // The default request is lingering on cell, but nothing happens to cell, and we send no
1448 // callbacks for it, because it's kept up by cellRequest.
1449 callback.assertNoCallback();
1450 // Now unregister cellRequest and expect cell to start lingering.
1451 mCm.unregisterNetworkCallback(noopCallback);
1452 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
1454 // Let linger run its course.
1455 callback.assertNoCallback();
1456 callback.expectCallback(CallbackState.LOST, mCellNetworkAgent,
1457 TEST_LINGER_DELAY_MS /* timeoutMs */);
1460 mWiFiNetworkAgent.disconnect();
1461 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1462 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1464 mCm.unregisterNetworkCallback(callback);
1465 mCm.unregisterNetworkCallback(defaultCallback);
1468 private void tryNetworkFactoryRequests(int capability) throws Exception {
1469 // Verify NOT_RESTRICTED is set appropriately
1470 final NetworkCapabilities nc = new NetworkRequest.Builder().addCapability(capability)
1471 .build().networkCapabilities;
1472 if (capability == NET_CAPABILITY_CBS || capability == NET_CAPABILITY_DUN ||
1473 capability == NET_CAPABILITY_EIMS || capability == NET_CAPABILITY_FOTA ||
1474 capability == NET_CAPABILITY_IA || capability == NET_CAPABILITY_IMS ||
1475 capability == NET_CAPABILITY_RCS || capability == NET_CAPABILITY_XCAP) {
1476 assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
1478 assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
1481 NetworkCapabilities filter = new NetworkCapabilities();
1482 filter.addCapability(capability);
1483 final HandlerThread handlerThread = new HandlerThread("testNetworkFactoryRequests");
1484 handlerThread.start();
1485 final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
1486 mServiceContext, "testFactory", filter);
1487 testFactory.setScoreFilter(40);
1488 ConditionVariable cv = testFactory.getNetworkStartedCV();
1489 testFactory.expectAddRequests(1);
1490 testFactory.register();
1491 testFactory.waitForNetworkRequests(1);
1492 int expectedRequestCount = 1;
1493 NetworkCallback networkCallback = null;
1494 // For non-INTERNET capabilities we cannot rely on the default request being present, so
1496 if (capability != NET_CAPABILITY_INTERNET) {
1497 assertFalse(testFactory.getMyStartRequested());
1498 NetworkRequest request = new NetworkRequest.Builder().addCapability(capability).build();
1499 networkCallback = new NetworkCallback();
1500 testFactory.expectAddRequests(1);
1501 mCm.requestNetwork(request, networkCallback);
1502 expectedRequestCount++;
1503 testFactory.waitForNetworkRequests(expectedRequestCount);
1506 assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
1507 assertTrue(testFactory.getMyStartRequested());
1509 // Now bring in a higher scored network.
1510 MockNetworkAgent testAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1511 // Rather than create a validated network which complicates things by registering it's
1512 // own NetworkRequest during startup, just bump up the score to cancel out the
1513 // unvalidated penalty.
1514 testAgent.adjustScore(40);
1515 cv = testFactory.getNetworkStoppedCV();
1517 // When testAgent connects, ConnectivityService will re-send us all current requests with
1518 // the new score. There are expectedRequestCount such requests, and we must wait for all of
1520 testFactory.expectAddRequests(expectedRequestCount);
1521 testAgent.connect(false);
1522 testAgent.addCapability(capability);
1524 testFactory.waitForNetworkRequests(expectedRequestCount);
1525 assertFalse(testFactory.getMyStartRequested());
1527 // Bring in a bunch of requests.
1528 testFactory.expectAddRequests(10);
1529 assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
1530 ConnectivityManager.NetworkCallback[] networkCallbacks =
1531 new ConnectivityManager.NetworkCallback[10];
1532 for (int i = 0; i< networkCallbacks.length; i++) {
1533 networkCallbacks[i] = new ConnectivityManager.NetworkCallback();
1534 NetworkRequest.Builder builder = new NetworkRequest.Builder();
1535 builder.addCapability(capability);
1536 mCm.requestNetwork(builder.build(), networkCallbacks[i]);
1538 testFactory.waitForNetworkRequests(10 + expectedRequestCount);
1539 assertFalse(testFactory.getMyStartRequested());
1541 // Remove the requests.
1542 testFactory.expectRemoveRequests(10);
1543 for (int i = 0; i < networkCallbacks.length; i++) {
1544 mCm.unregisterNetworkCallback(networkCallbacks[i]);
1546 testFactory.waitForNetworkRequests(expectedRequestCount);
1547 assertFalse(testFactory.getMyStartRequested());
1549 // Drop the higher scored network.
1550 cv = testFactory.getNetworkStartedCV();
1551 testAgent.disconnect();
1553 assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
1554 assertTrue(testFactory.getMyStartRequested());
1556 testFactory.unregister();
1557 if (networkCallback != null) mCm.unregisterNetworkCallback(networkCallback);
1558 handlerThread.quit();
1562 public void testNetworkFactoryRequests() throws Exception {
1563 tryNetworkFactoryRequests(NET_CAPABILITY_MMS);
1564 tryNetworkFactoryRequests(NET_CAPABILITY_SUPL);
1565 tryNetworkFactoryRequests(NET_CAPABILITY_DUN);
1566 tryNetworkFactoryRequests(NET_CAPABILITY_FOTA);
1567 tryNetworkFactoryRequests(NET_CAPABILITY_IMS);
1568 tryNetworkFactoryRequests(NET_CAPABILITY_CBS);
1569 tryNetworkFactoryRequests(NET_CAPABILITY_WIFI_P2P);
1570 tryNetworkFactoryRequests(NET_CAPABILITY_IA);
1571 tryNetworkFactoryRequests(NET_CAPABILITY_RCS);
1572 tryNetworkFactoryRequests(NET_CAPABILITY_XCAP);
1573 tryNetworkFactoryRequests(NET_CAPABILITY_EIMS);
1574 tryNetworkFactoryRequests(NET_CAPABILITY_NOT_METERED);
1575 tryNetworkFactoryRequests(NET_CAPABILITY_INTERNET);
1576 tryNetworkFactoryRequests(NET_CAPABILITY_TRUSTED);
1577 tryNetworkFactoryRequests(NET_CAPABILITY_NOT_VPN);
1578 // Skipping VALIDATED and CAPTIVE_PORTAL as they're disallowed.
1582 public void testNoMutableNetworkRequests() throws Exception {
1583 PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, new Intent("a"), 0);
1584 NetworkRequest.Builder builder = new NetworkRequest.Builder();
1585 builder.addCapability(NET_CAPABILITY_VALIDATED);
1587 mCm.requestNetwork(builder.build(), new NetworkCallback());
1589 } catch (IllegalArgumentException expected) {}
1591 mCm.requestNetwork(builder.build(), pendingIntent);
1593 } catch (IllegalArgumentException expected) {}
1594 builder = new NetworkRequest.Builder();
1595 builder.addCapability(NET_CAPABILITY_CAPTIVE_PORTAL);
1597 mCm.requestNetwork(builder.build(), new NetworkCallback());
1599 } catch (IllegalArgumentException expected) {}
1601 mCm.requestNetwork(builder.build(), pendingIntent);
1603 } catch (IllegalArgumentException expected) {}
1607 public void testMMSonWiFi() throws Exception {
1608 // Test bringing up cellular without MMS NetworkRequest gets reaped
1609 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1610 mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS);
1611 ConditionVariable cv = mCellNetworkAgent.getDisconnectedCV();
1612 mCellNetworkAgent.connectWithoutInternet();
1614 waitFor(new Criteria() {
1615 public boolean get() { return mCm.getAllNetworks().length == 0; } });
1617 // Test bringing up validated WiFi.
1618 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1619 cv = waitForConnectivityBroadcasts(1);
1620 mWiFiNetworkAgent.connect(true);
1622 verifyActiveNetwork(TRANSPORT_WIFI);
1623 // Register MMS NetworkRequest
1624 NetworkRequest.Builder builder = new NetworkRequest.Builder();
1625 builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
1626 final TestNetworkCallback networkCallback = new TestNetworkCallback();
1627 mCm.requestNetwork(builder.build(), networkCallback);
1628 // Test bringing up unvalidated cellular with MMS
1629 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1630 mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS);
1631 mCellNetworkAgent.connectWithoutInternet();
1632 networkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1633 verifyActiveNetwork(TRANSPORT_WIFI);
1634 // Test releasing NetworkRequest disconnects cellular with MMS
1635 cv = mCellNetworkAgent.getDisconnectedCV();
1636 mCm.unregisterNetworkCallback(networkCallback);
1638 verifyActiveNetwork(TRANSPORT_WIFI);
1642 public void testMMSonCell() throws Exception {
1643 // Test bringing up cellular without MMS
1644 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1645 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1646 mCellNetworkAgent.connect(false);
1648 verifyActiveNetwork(TRANSPORT_CELLULAR);
1649 // Register MMS NetworkRequest
1650 NetworkRequest.Builder builder = new NetworkRequest.Builder();
1651 builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
1652 final TestNetworkCallback networkCallback = new TestNetworkCallback();
1653 mCm.requestNetwork(builder.build(), networkCallback);
1654 // Test bringing up MMS cellular network
1655 MockNetworkAgent mmsNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1656 mmsNetworkAgent.addCapability(NET_CAPABILITY_MMS);
1657 mmsNetworkAgent.connectWithoutInternet();
1658 networkCallback.expectCallback(CallbackState.AVAILABLE, mmsNetworkAgent);
1659 verifyActiveNetwork(TRANSPORT_CELLULAR);
1660 // Test releasing MMS NetworkRequest does not disconnect main cellular NetworkAgent
1661 cv = mmsNetworkAgent.getDisconnectedCV();
1662 mCm.unregisterNetworkCallback(networkCallback);
1664 verifyActiveNetwork(TRANSPORT_CELLULAR);
1668 public void testCaptivePortal() {
1669 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
1670 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
1671 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
1672 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
1674 final TestNetworkCallback validatedCallback = new TestNetworkCallback();
1675 final NetworkRequest validatedRequest = new NetworkRequest.Builder()
1676 .addCapability(NET_CAPABILITY_VALIDATED).build();
1677 mCm.registerNetworkCallback(validatedRequest, validatedCallback);
1679 // Bring up a network with a captive portal.
1680 // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
1681 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1682 String firstRedirectUrl = "http://example.com/firstPath";
1683 mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl);
1684 captivePortalCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1685 assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), firstRedirectUrl);
1687 // Take down network.
1688 // Expect onLost callback.
1689 mWiFiNetworkAgent.disconnect();
1690 captivePortalCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1692 // Bring up a network with a captive portal.
1693 // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
1694 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1695 String secondRedirectUrl = "http://example.com/secondPath";
1696 mWiFiNetworkAgent.connectWithCaptivePortal(secondRedirectUrl);
1697 captivePortalCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1698 assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), secondRedirectUrl);
1700 // Make captive portal disappear then revalidate.
1701 // Expect onLost callback because network no longer provides NET_CAPABILITY_CAPTIVE_PORTAL.
1702 mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 204;
1703 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
1704 captivePortalCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1706 // Expect NET_CAPABILITY_VALIDATED onAvailable callback.
1707 validatedCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1709 // Break network connectivity.
1710 // Expect NET_CAPABILITY_VALIDATED onLost callback.
1711 mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 500;
1712 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), false);
1713 validatedCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1717 public void testAvoidOrIgnoreCaptivePortals() {
1718 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
1719 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
1720 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
1721 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
1723 final TestNetworkCallback validatedCallback = new TestNetworkCallback();
1724 final NetworkRequest validatedRequest = new NetworkRequest.Builder()
1725 .addCapability(NET_CAPABILITY_VALIDATED).build();
1726 mCm.registerNetworkCallback(validatedRequest, validatedCallback);
1728 setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_AVOID);
1729 // Bring up a network with a captive portal.
1730 // Expect it to fail to connect and not result in any callbacks.
1731 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1732 String firstRedirectUrl = "http://example.com/firstPath";
1734 ConditionVariable disconnectCv = mWiFiNetworkAgent.getDisconnectedCV();
1735 ConditionVariable avoidCv = mWiFiNetworkAgent.getPreventReconnectReceived();
1736 mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl);
1737 waitFor(disconnectCv);
1740 assertNoCallbacks(captivePortalCallback, validatedCallback);
1742 // Now test ignore mode.
1743 setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_IGNORE);
1745 // Bring up a network with a captive portal.
1746 // Since we're ignoring captive portals, the network will validate.
1747 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1748 String secondRedirectUrl = "http://example.com/secondPath";
1749 mWiFiNetworkAgent.connectWithCaptivePortal(secondRedirectUrl);
1751 // Expect NET_CAPABILITY_VALIDATED onAvailable callback.
1752 validatedCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1753 // But there should be no CaptivePortal callback.
1754 captivePortalCallback.assertNoCallback();
1758 public void testInvalidNetworkSpecifier() {
1759 boolean execptionCalled = true;
1762 NetworkRequest.Builder builder = new NetworkRequest.Builder();
1763 builder.setNetworkSpecifier(MATCH_ALL_REQUESTS_NETWORK_SPECIFIER);
1764 execptionCalled = false;
1765 } catch (IllegalArgumentException e) {
1766 // do nothing - should get here
1769 assertTrue("NetworkRequest builder with MATCH_ALL_REQUESTS_NETWORK_SPECIFIER",
1773 NetworkCapabilities networkCapabilities = new NetworkCapabilities();
1774 networkCapabilities.addTransportType(TRANSPORT_WIFI)
1775 .setNetworkSpecifier(NetworkCapabilities.MATCH_ALL_REQUESTS_NETWORK_SPECIFIER);
1776 mService.requestNetwork(networkCapabilities, null, 0, null,
1777 ConnectivityManager.TYPE_WIFI);
1778 execptionCalled = false;
1779 } catch (IllegalArgumentException e) {
1780 // do nothing - should get here
1783 assertTrue("ConnectivityService requestNetwork with MATCH_ALL_REQUESTS_NETWORK_SPECIFIER",
1788 public void testRegisterDefaultNetworkCallback() throws Exception {
1789 final TestNetworkCallback defaultNetworkCallback = new TestNetworkCallback();
1790 mCm.registerDefaultNetworkCallback(defaultNetworkCallback);
1791 defaultNetworkCallback.assertNoCallback();
1793 // Create a TRANSPORT_CELLULAR request to keep the mobile interface up
1794 // whenever Wi-Fi is up. Without this, the mobile network agent is
1795 // reaped before any other activity can take place.
1796 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
1797 final NetworkRequest cellRequest = new NetworkRequest.Builder()
1798 .addTransportType(TRANSPORT_CELLULAR).build();
1799 mCm.requestNetwork(cellRequest, cellNetworkCallback);
1800 cellNetworkCallback.assertNoCallback();
1802 // Bring up cell and expect CALLBACK_AVAILABLE.
1803 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1804 mCellNetworkAgent.connect(true);
1805 cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1806 defaultNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1808 // Bring up wifi and expect CALLBACK_AVAILABLE.
1809 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1810 mWiFiNetworkAgent.connect(true);
1811 cellNetworkCallback.assertNoCallback();
1812 defaultNetworkCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1814 // Bring down cell. Expect no default network callback, since it wasn't the default.
1815 mCellNetworkAgent.disconnect();
1816 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1817 defaultNetworkCallback.assertNoCallback();
1819 // Bring up cell. Expect no default network callback, since it won't be the default.
1820 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1821 mCellNetworkAgent.connect(true);
1822 cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1823 defaultNetworkCallback.assertNoCallback();
1825 // Bring down wifi. Expect the default network callback to notified of LOST wifi
1826 // followed by AVAILABLE cell.
1827 mWiFiNetworkAgent.disconnect();
1828 cellNetworkCallback.assertNoCallback();
1829 defaultNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1830 defaultNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1831 mCellNetworkAgent.disconnect();
1832 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1833 defaultNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1836 private class TestRequestUpdateCallback extends TestNetworkCallback {
1838 public void onCapabilitiesChanged(Network network, NetworkCapabilities netCap) {
1839 setLastCallback(CallbackState.NETWORK_CAPABILITIES, network, netCap);
1843 public void onLinkPropertiesChanged(Network network, LinkProperties linkProp) {
1844 setLastCallback(CallbackState.LINK_PROPERTIES, network, linkProp);
1849 public void testRequestCallbackUpdates() throws Exception {
1850 // File a network request for mobile.
1851 final TestNetworkCallback cellNetworkCallback = new TestRequestUpdateCallback();
1852 final NetworkRequest cellRequest = new NetworkRequest.Builder()
1853 .addTransportType(TRANSPORT_CELLULAR).build();
1854 mCm.requestNetwork(cellRequest, cellNetworkCallback);
1856 // Bring up the mobile network.
1857 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1858 mCellNetworkAgent.connect(true);
1860 // We should get onAvailable().
1861 cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1862 // We should get onCapabilitiesChanged(), when the mobile network successfully validates.
1863 cellNetworkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, mCellNetworkAgent);
1864 cellNetworkCallback.assertNoCallback();
1866 // Update LinkProperties.
1867 final LinkProperties lp = new LinkProperties();
1868 lp.setInterfaceName("foonet_data0");
1869 mCellNetworkAgent.sendLinkProperties(lp);
1870 // We should get onLinkPropertiesChanged().
1871 cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
1872 cellNetworkCallback.assertNoCallback();
1874 // Register a garden variety default network request.
1875 final TestNetworkCallback dfltNetworkCallback = new TestRequestUpdateCallback();
1876 mCm.registerDefaultNetworkCallback(dfltNetworkCallback);
1877 // Only onAvailable() is called; no other information is delivered.
1878 dfltNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1879 dfltNetworkCallback.assertNoCallback();
1881 // Request a NetworkCapabilities update; only the requesting callback is notified.
1882 mCm.requestNetworkCapabilities(dfltNetworkCallback);
1883 dfltNetworkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, mCellNetworkAgent);
1884 cellNetworkCallback.assertNoCallback();
1885 dfltNetworkCallback.assertNoCallback();
1887 // Request a LinkProperties update; only the requesting callback is notified.
1888 mCm.requestLinkProperties(dfltNetworkCallback);
1889 dfltNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
1890 cellNetworkCallback.assertNoCallback();
1891 dfltNetworkCallback.assertNoCallback();
1893 mCm.unregisterNetworkCallback(dfltNetworkCallback);
1894 mCm.unregisterNetworkCallback(cellNetworkCallback);
1897 private void setCaptivePortalMode(int mode) {
1898 ContentResolver cr = mServiceContext.getContentResolver();
1899 Settings.Global.putInt(cr, Settings.Global.CAPTIVE_PORTAL_MODE, mode);
1902 private void setMobileDataAlwaysOn(boolean enable) {
1903 ContentResolver cr = mServiceContext.getContentResolver();
1904 Settings.Global.putInt(cr, Settings.Global.MOBILE_DATA_ALWAYS_ON, enable ? 1 : 0);
1905 mService.updateMobileDataAlwaysOn();
1906 mService.waitForIdle();
1909 private boolean isForegroundNetwork(MockNetworkAgent network) {
1910 NetworkCapabilities nc = mCm.getNetworkCapabilities(network.getNetwork());
1912 return nc.hasCapability(NET_CAPABILITY_FOREGROUND);
1916 public void testBackgroundNetworks() throws Exception {
1917 // Create a background request. We can't do this ourselves because ConnectivityService
1918 // doesn't have an API for it. So just turn on mobile data always on.
1919 setMobileDataAlwaysOn(true);
1920 final NetworkRequest request = new NetworkRequest.Builder().build();
1921 final NetworkRequest fgRequest = new NetworkRequest.Builder()
1922 .addCapability(NET_CAPABILITY_FOREGROUND).build();
1923 final TestNetworkCallback callback = new TestNetworkCallback();
1924 final TestNetworkCallback fgCallback = new TestNetworkCallback();
1925 mCm.registerNetworkCallback(request, callback);
1926 mCm.registerNetworkCallback(fgRequest, fgCallback);
1928 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1929 mCellNetworkAgent.connect(true);
1930 callback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1931 fgCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1932 assertTrue(isForegroundNetwork(mCellNetworkAgent));
1934 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1935 mWiFiNetworkAgent.connect(true);
1937 // When wifi connects, cell lingers.
1938 callback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1939 fgCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1940 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
1941 fgCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
1942 assertTrue(isForegroundNetwork(mCellNetworkAgent));
1943 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
1945 // When lingering is complete, cell is still there but is now in the background.
1946 fgCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent, TEST_LINGER_DELAY_MS);
1947 callback.assertNoCallback();
1948 assertFalse(isForegroundNetwork(mCellNetworkAgent));
1949 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
1951 // File a cell request and check that cell comes into the foreground.
1952 final NetworkRequest cellRequest = new NetworkRequest.Builder()
1953 .addTransportType(TRANSPORT_CELLULAR).build();
1954 final TestNetworkCallback cellCallback = new TestNetworkCallback();
1955 mCm.requestNetwork(cellRequest, cellCallback);
1956 cellCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1957 fgCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1958 callback.assertNoCallback(); // Because the network is already up.
1959 assertTrue(isForegroundNetwork(mCellNetworkAgent));
1960 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
1962 // Release the request. The network immediately goes into the background, since it was not
1964 mCm.unregisterNetworkCallback(cellCallback);
1965 fgCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1966 callback.assertNoCallback();
1967 assertFalse(isForegroundNetwork(mCellNetworkAgent));
1968 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
1970 // Disconnect wifi and check that cell is foreground again.
1971 mWiFiNetworkAgent.disconnect();
1972 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1973 fgCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1974 fgCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1975 assertTrue(isForegroundNetwork(mCellNetworkAgent));
1977 mCm.unregisterNetworkCallback(callback);
1978 mCm.unregisterNetworkCallback(fgCallback);
1982 public void testRequestBenchmark() throws Exception {
1983 // Benchmarks connecting and switching performance in the presence of a large number of
1985 // 1. File NUM_REQUESTS requests.
1986 // 2. Have a network connect. Wait for NUM_REQUESTS onAvailable callbacks to fire.
1987 // 3. Have a new network connect and outscore the previous. Wait for NUM_REQUESTS onLosing
1988 // and NUM_REQUESTS onAvailable callbacks to fire.
1989 // See how long it took.
1990 final int NUM_REQUESTS = 90;
1991 final NetworkRequest request = new NetworkRequest.Builder().clearCapabilities().build();
1992 final NetworkCallback[] callbacks = new NetworkCallback[NUM_REQUESTS];
1993 final CountDownLatch availableLatch = new CountDownLatch(NUM_REQUESTS);
1994 final CountDownLatch losingLatch = new CountDownLatch(NUM_REQUESTS);
1996 final int REGISTER_TIME_LIMIT_MS = 100;
1997 long startTime = System.currentTimeMillis();
1998 for (int i = 0; i < NUM_REQUESTS; i++) {
1999 callbacks[i] = new NetworkCallback() {
2000 @Override public void onAvailable(Network n) { availableLatch.countDown(); }
2001 @Override public void onLosing(Network n, int t) { losingLatch.countDown(); }
2003 mCm.registerNetworkCallback(request, callbacks[i]);
2005 long timeTaken = System.currentTimeMillis() - startTime;
2006 String msg = String.format("Register %d callbacks: %dms, acceptable %dms",
2007 NUM_REQUESTS, timeTaken, REGISTER_TIME_LIMIT_MS);
2009 assertTrue(msg, timeTaken < REGISTER_TIME_LIMIT_MS);
2011 final int CONNECT_TIME_LIMIT_MS = 30;
2012 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2013 // Don't request that the network validate, because otherwise connect() will block until
2014 // the network gets NET_CAPABILITY_VALIDATED, after all the callbacks below have fired,
2015 // and we won't actually measure anything.
2016 mCellNetworkAgent.connect(false);
2017 startTime = System.currentTimeMillis();
2018 if (!availableLatch.await(CONNECT_TIME_LIMIT_MS, TimeUnit.MILLISECONDS)) {
2019 fail(String.format("Only dispatched %d/%d onAvailable callbacks in %dms",
2020 NUM_REQUESTS - availableLatch.getCount(), NUM_REQUESTS,
2021 CONNECT_TIME_LIMIT_MS));
2023 timeTaken = System.currentTimeMillis() - startTime;
2024 Log.d(TAG, String.format("Connect, %d callbacks: %dms, acceptable %dms",
2025 NUM_REQUESTS, timeTaken, CONNECT_TIME_LIMIT_MS));
2027 final int SWITCH_TIME_LIMIT_MS = 30;
2028 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2029 // Give wifi a high enough score that we'll linger cell when wifi comes up.
2030 mWiFiNetworkAgent.adjustScore(40);
2031 mWiFiNetworkAgent.connect(false);
2032 startTime = System.currentTimeMillis();
2033 if (!losingLatch.await(SWITCH_TIME_LIMIT_MS, TimeUnit.MILLISECONDS)) {
2034 fail(String.format("Only dispatched %d/%d onLosing callbacks in %dms",
2035 NUM_REQUESTS - losingLatch.getCount(), NUM_REQUESTS, SWITCH_TIME_LIMIT_MS));
2037 timeTaken = System.currentTimeMillis() - startTime;
2038 Log.d(TAG, String.format("Linger, %d callbacks: %dms, acceptable %dms",
2039 NUM_REQUESTS, timeTaken, SWITCH_TIME_LIMIT_MS));
2041 final int UNREGISTER_TIME_LIMIT_MS = 10;
2042 startTime = System.currentTimeMillis();
2043 for (int i = 0; i < NUM_REQUESTS; i++) {
2044 mCm.unregisterNetworkCallback(callbacks[i]);
2046 timeTaken = System.currentTimeMillis() - startTime;
2047 msg = String.format("Unregister %d callbacks: %dms, acceptable %dms",
2048 NUM_REQUESTS, timeTaken, UNREGISTER_TIME_LIMIT_MS);
2050 assertTrue(msg, timeTaken < UNREGISTER_TIME_LIMIT_MS);
2054 public void testMobileDataAlwaysOn() throws Exception {
2055 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
2056 final NetworkRequest cellRequest = new NetworkRequest.Builder()
2057 .addTransportType(TRANSPORT_CELLULAR).build();
2058 mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
2060 final HandlerThread handlerThread = new HandlerThread("MobileDataAlwaysOnFactory");
2061 handlerThread.start();
2062 NetworkCapabilities filter = new NetworkCapabilities()
2063 .addTransportType(TRANSPORT_CELLULAR)
2064 .addCapability(NET_CAPABILITY_INTERNET);
2065 final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
2066 mServiceContext, "testFactory", filter);
2067 testFactory.setScoreFilter(40);
2069 // Register the factory and expect it to start looking for a network.
2070 testFactory.expectAddRequests(1);
2071 testFactory.register();
2072 testFactory.waitForNetworkRequests(1);
2073 assertTrue(testFactory.getMyStartRequested());
2075 // Bring up wifi. The factory stops looking for a network.
2076 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2077 testFactory.expectAddRequests(2); // Because the default request changes score twice.
2078 mWiFiNetworkAgent.connect(true);
2079 testFactory.waitForNetworkRequests(1);
2080 assertFalse(testFactory.getMyStartRequested());
2082 ContentResolver cr = mServiceContext.getContentResolver();
2084 // Turn on mobile data always on. The factory starts looking again.
2085 testFactory.expectAddRequests(1);
2086 setMobileDataAlwaysOn(true);
2087 testFactory.waitForNetworkRequests(2);
2088 assertTrue(testFactory.getMyStartRequested());
2090 // Bring up cell data and check that the factory stops looking.
2091 assertEquals(1, mCm.getAllNetworks().length);
2092 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2093 testFactory.expectAddRequests(2); // Because the cell request changes score twice.
2094 mCellNetworkAgent.connect(true);
2095 cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
2096 testFactory.waitForNetworkRequests(2);
2097 assertFalse(testFactory.getMyStartRequested()); // Because the cell network outscores us.
2099 // Check that cell data stays up.
2100 mService.waitForIdle();
2101 verifyActiveNetwork(TRANSPORT_WIFI);
2102 assertEquals(2, mCm.getAllNetworks().length);
2104 // Turn off mobile data always on and expect the request to disappear...
2105 testFactory.expectRemoveRequests(1);
2106 setMobileDataAlwaysOn(false);
2107 testFactory.waitForNetworkRequests(1);
2109 // ... and cell data to be torn down.
2110 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
2111 assertEquals(1, mCm.getAllNetworks().length);
2113 testFactory.unregister();
2114 mCm.unregisterNetworkCallback(cellNetworkCallback);
2115 handlerThread.quit();
2119 public void testAvoidBadWifiSetting() throws Exception {
2120 final ContentResolver cr = mServiceContext.getContentResolver();
2121 final WrappedAvoidBadWifiTracker tracker = mService.getAvoidBadWifiTracker();
2122 final String settingName = Settings.Global.NETWORK_AVOID_BAD_WIFI;
2124 tracker.configRestrictsAvoidBadWifi = false;
2125 String[] values = new String[] {null, "0", "1"};
2126 for (int i = 0; i < values.length; i++) {
2127 Settings.Global.putInt(cr, settingName, 1);
2128 tracker.reevaluate();
2129 mService.waitForIdle();
2130 String msg = String.format("config=false, setting=%s", values[i]);
2131 assertTrue(msg, mService.avoidBadWifi());
2132 assertFalse(msg, tracker.shouldNotifyWifiUnvalidated());
2135 tracker.configRestrictsAvoidBadWifi = true;
2137 Settings.Global.putInt(cr, settingName, 0);
2138 tracker.reevaluate();
2139 mService.waitForIdle();
2140 assertFalse(mService.avoidBadWifi());
2141 assertFalse(tracker.shouldNotifyWifiUnvalidated());
2143 Settings.Global.putInt(cr, settingName, 1);
2144 tracker.reevaluate();
2145 mService.waitForIdle();
2146 assertTrue(mService.avoidBadWifi());
2147 assertFalse(tracker.shouldNotifyWifiUnvalidated());
2149 Settings.Global.putString(cr, settingName, null);
2150 tracker.reevaluate();
2151 mService.waitForIdle();
2152 assertFalse(mService.avoidBadWifi());
2153 assertTrue(tracker.shouldNotifyWifiUnvalidated());
2157 public void testAvoidBadWifi() throws Exception {
2158 final ContentResolver cr = mServiceContext.getContentResolver();
2159 final WrappedAvoidBadWifiTracker tracker = mService.getAvoidBadWifiTracker();
2161 // Pretend we're on a carrier that restricts switching away from bad wifi.
2162 tracker.configRestrictsAvoidBadWifi = true;
2164 // File a request for cell to ensure it doesn't go down.
2165 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
2166 final NetworkRequest cellRequest = new NetworkRequest.Builder()
2167 .addTransportType(TRANSPORT_CELLULAR).build();
2168 mCm.requestNetwork(cellRequest, cellNetworkCallback);
2170 TestNetworkCallback defaultCallback = new TestNetworkCallback();
2171 mCm.registerDefaultNetworkCallback(defaultCallback);
2173 NetworkRequest validatedWifiRequest = new NetworkRequest.Builder()
2174 .addTransportType(TRANSPORT_WIFI)
2175 .addCapability(NET_CAPABILITY_VALIDATED)
2177 TestNetworkCallback validatedWifiCallback = new TestNetworkCallback();
2178 mCm.registerNetworkCallback(validatedWifiRequest, validatedWifiCallback);
2180 Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 0);
2181 tracker.reevaluate();
2183 // Bring up validated cell.
2184 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2185 mCellNetworkAgent.connect(true);
2186 cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
2187 defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
2188 Network cellNetwork = mCellNetworkAgent.getNetwork();
2190 // Bring up validated wifi.
2191 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2192 mWiFiNetworkAgent.connect(true);
2193 defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
2194 validatedWifiCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
2195 Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
2197 // Fail validation on wifi.
2198 mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 599;
2199 mCm.reportNetworkConnectivity(wifiNetwork, false);
2200 validatedWifiCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2202 // Because avoid bad wifi is off, we don't switch to cellular.
2203 defaultCallback.assertNoCallback();
2204 assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
2205 NET_CAPABILITY_VALIDATED));
2206 assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
2207 NET_CAPABILITY_VALIDATED));
2208 assertEquals(mCm.getActiveNetwork(), wifiNetwork);
2210 // Simulate switching to a carrier that does not restrict avoiding bad wifi, and expect
2211 // that we switch back to cell.
2212 tracker.configRestrictsAvoidBadWifi = false;
2213 tracker.reevaluate();
2214 defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
2215 assertEquals(mCm.getActiveNetwork(), cellNetwork);
2217 // Switch back to a restrictive carrier.
2218 tracker.configRestrictsAvoidBadWifi = true;
2219 tracker.reevaluate();
2220 defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
2221 assertEquals(mCm.getActiveNetwork(), wifiNetwork);
2223 // Simulate the user selecting "switch" on the dialog, and check that we switch to cell.
2224 mCm.setAvoidUnvalidated(wifiNetwork);
2225 defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
2226 assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
2227 NET_CAPABILITY_VALIDATED));
2228 assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
2229 NET_CAPABILITY_VALIDATED));
2230 assertEquals(mCm.getActiveNetwork(), cellNetwork);
2232 // Disconnect and reconnect wifi to clear the one-time switch above.
2233 mWiFiNetworkAgent.disconnect();
2234 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2235 mWiFiNetworkAgent.connect(true);
2236 defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
2237 validatedWifiCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
2238 wifiNetwork = mWiFiNetworkAgent.getNetwork();
2240 // Fail validation on wifi and expect the dialog to appear.
2241 mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 599;
2242 mCm.reportNetworkConnectivity(wifiNetwork, false);
2243 validatedWifiCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2245 // Simulate the user selecting "switch" and checking the don't ask again checkbox.
2246 Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 1);
2247 tracker.reevaluate();
2249 // We now switch to cell.
2250 defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
2251 assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
2252 NET_CAPABILITY_VALIDATED));
2253 assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
2254 NET_CAPABILITY_VALIDATED));
2255 assertEquals(mCm.getActiveNetwork(), cellNetwork);
2257 // Simulate the user turning the cellular fallback setting off and then on.
2258 // We switch to wifi and then to cell.
2259 Settings.Global.putString(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, null);
2260 tracker.reevaluate();
2261 defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
2262 assertEquals(mCm.getActiveNetwork(), wifiNetwork);
2263 Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 1);
2264 tracker.reevaluate();
2265 defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
2266 assertEquals(mCm.getActiveNetwork(), cellNetwork);
2268 // If cell goes down, we switch to wifi.
2269 mCellNetworkAgent.disconnect();
2270 defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
2271 defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
2272 validatedWifiCallback.assertNoCallback();
2274 mCm.unregisterNetworkCallback(cellNetworkCallback);
2275 mCm.unregisterNetworkCallback(validatedWifiCallback);
2276 mCm.unregisterNetworkCallback(defaultCallback);
2279 private static class TestKeepaliveCallback extends PacketKeepaliveCallback {
2281 public static enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR };
2283 private class CallbackValue {
2284 public CallbackType callbackType;
2287 public CallbackValue(CallbackType type) {
2288 this.callbackType = type;
2289 this.error = PacketKeepalive.SUCCESS;
2290 assertTrue("onError callback must have error", type != CallbackType.ON_ERROR);
2293 public CallbackValue(CallbackType type, int error) {
2294 this.callbackType = type;
2296 assertEquals("error can only be set for onError", type, CallbackType.ON_ERROR);
2300 public boolean equals(Object o) {
2301 return o instanceof CallbackValue &&
2302 this.callbackType == ((CallbackValue) o).callbackType &&
2303 this.error == ((CallbackValue) o).error;
2307 public String toString() {
2308 return String.format("%s(%s, %d)", getClass().getSimpleName(), callbackType, error);
2312 private LinkedBlockingQueue<CallbackValue> mCallbacks = new LinkedBlockingQueue<>();
2315 public void onStarted() {
2316 mCallbacks.add(new CallbackValue(CallbackType.ON_STARTED));
2320 public void onStopped() {
2321 mCallbacks.add(new CallbackValue(CallbackType.ON_STOPPED));
2325 public void onError(int error) {
2326 mCallbacks.add(new CallbackValue(CallbackType.ON_ERROR, error));
2329 private void expectCallback(CallbackValue callbackValue) {
2333 mCallbacks.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
2334 } catch (InterruptedException e) {
2335 fail(callbackValue.callbackType + " callback not seen after " + TIMEOUT_MS + " ms");
2339 public void expectStarted() {
2340 expectCallback(new CallbackValue(CallbackType.ON_STARTED));
2343 public void expectStopped() {
2344 expectCallback(new CallbackValue(CallbackType.ON_STOPPED));
2347 public void expectError(int error) {
2348 expectCallback(new CallbackValue(CallbackType.ON_ERROR, error));
2352 private Network connectKeepaliveNetwork(LinkProperties lp) {
2353 // Ensure the network is disconnected before we do anything.
2354 if (mWiFiNetworkAgent != null) {
2355 assertNull(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()));
2358 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2359 ConditionVariable cv = waitForConnectivityBroadcasts(1);
2360 mWiFiNetworkAgent.connect(true);
2362 verifyActiveNetwork(TRANSPORT_WIFI);
2363 mWiFiNetworkAgent.sendLinkProperties(lp);
2364 mService.waitForIdle();
2365 return mWiFiNetworkAgent.getNetwork();
2368 public void testPacketKeepalives() throws Exception {
2369 InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
2370 InetAddress notMyIPv4 = InetAddress.getByName("192.0.2.35");
2371 InetAddress myIPv6 = InetAddress.getByName("2001:db8::1");
2372 InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8");
2373 InetAddress dstIPv6 = InetAddress.getByName("2001:4860:4860::8888");
2375 LinkProperties lp = new LinkProperties();
2376 lp.setInterfaceName("wlan12");
2377 lp.addLinkAddress(new LinkAddress(myIPv6, 64));
2378 lp.addLinkAddress(new LinkAddress(myIPv4, 25));
2379 lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
2380 lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
2382 Network notMyNet = new Network(61234);
2383 Network myNet = connectKeepaliveNetwork(lp);
2385 TestKeepaliveCallback callback = new TestKeepaliveCallback();
2388 // Attempt to start keepalives with invalid parameters and check for errors.
2389 ka = mCm.startNattKeepalive(notMyNet, 25, callback, myIPv4, 1234, dstIPv4);
2390 callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK);
2392 ka = mCm.startNattKeepalive(myNet, 19, callback, notMyIPv4, 1234, dstIPv4);
2393 callback.expectError(PacketKeepalive.ERROR_INVALID_INTERVAL);
2395 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 1234, dstIPv6);
2396 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
2398 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv6, 1234, dstIPv4);
2399 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
2401 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv6, 1234, dstIPv6);
2402 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS); // NAT-T is IPv4-only.
2404 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 123456, dstIPv4);
2405 callback.expectError(PacketKeepalive.ERROR_INVALID_PORT);
2407 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 123456, dstIPv4);
2408 callback.expectError(PacketKeepalive.ERROR_INVALID_PORT);
2410 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
2411 callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
2413 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
2414 callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
2416 // Check that a started keepalive can be stopped.
2417 mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS);
2418 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
2419 callback.expectStarted();
2420 mWiFiNetworkAgent.setStopKeepaliveError(PacketKeepalive.SUCCESS);
2422 callback.expectStopped();
2424 // Check that deleting the IP address stops the keepalive.
2425 LinkProperties bogusLp = new LinkProperties(lp);
2426 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
2427 callback.expectStarted();
2428 bogusLp.removeLinkAddress(new LinkAddress(myIPv4, 25));
2429 bogusLp.addLinkAddress(new LinkAddress(notMyIPv4, 25));
2430 mWiFiNetworkAgent.sendLinkProperties(bogusLp);
2431 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
2432 mWiFiNetworkAgent.sendLinkProperties(lp);
2434 // Check that a started keepalive is stopped correctly when the network disconnects.
2435 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
2436 callback.expectStarted();
2437 mWiFiNetworkAgent.disconnect();
2438 callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK);
2440 // ... and that stopping it after that has no adverse effects.
2441 assertNull(mCm.getNetworkCapabilities(myNet));
2445 myNet = connectKeepaliveNetwork(lp);
2446 mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS);
2448 // Check things work as expected when the keepalive is stopped and the network disconnects.
2449 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
2450 callback.expectStarted();
2452 mWiFiNetworkAgent.disconnect();
2453 mService.waitForIdle();
2454 callback.expectStopped();
2457 myNet = connectKeepaliveNetwork(lp);
2458 mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS);
2460 // Check that keepalive slots start from 1 and increment. The first one gets slot 1.
2461 mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
2462 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
2463 callback.expectStarted();
2465 // The second one gets slot 2.
2466 mWiFiNetworkAgent.setExpectedKeepaliveSlot(2);
2467 TestKeepaliveCallback callback2 = new TestKeepaliveCallback();
2468 PacketKeepalive ka2 = mCm.startNattKeepalive(myNet, 25, callback2, myIPv4, 6789, dstIPv4);
2469 callback2.expectStarted();
2471 // Now stop the first one and create a third. This also gets slot 1.
2473 callback.expectStopped();
2475 mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
2476 TestKeepaliveCallback callback3 = new TestKeepaliveCallback();
2477 PacketKeepalive ka3 = mCm.startNattKeepalive(myNet, 25, callback3, myIPv4, 9876, dstIPv4);
2478 callback3.expectStarted();
2481 callback2.expectStopped();
2484 callback3.expectStopped();
2488 public void testGetCaptivePortalServerUrl() throws Exception {
2489 String url = mCm.getCaptivePortalServerUrl();
2490 assertEquals("http://connectivitycheck.gstatic.com/generate_204", url);
2493 private static class TestNetworkPinner extends NetworkPinner {
2494 public static boolean awaitPin(int timeoutMs) {
2495 synchronized(sLock) {
2496 if (sNetwork == null) {
2498 sLock.wait(timeoutMs);
2499 } catch (InterruptedException e) {}
2501 return sNetwork != null;
2505 public static boolean awaitUnpin(int timeoutMs) {
2506 synchronized(sLock) {
2507 if (sNetwork != null) {
2509 sLock.wait(timeoutMs);
2510 } catch (InterruptedException e) {}
2512 return sNetwork == null;
2517 private void assertPinnedToWifiWithCellDefault() {
2518 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess());
2519 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2522 private void assertPinnedToWifiWithWifiDefault() {
2523 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess());
2524 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2527 private void assertNotPinnedToWifi() {
2528 assertNull(mCm.getBoundNetworkForProcess());
2529 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2533 public void testNetworkPinner() {
2534 NetworkRequest wifiRequest = new NetworkRequest.Builder()
2535 .addTransportType(TRANSPORT_WIFI)
2537 assertNull(mCm.getBoundNetworkForProcess());
2539 TestNetworkPinner.pin(mServiceContext, wifiRequest);
2540 assertNull(mCm.getBoundNetworkForProcess());
2542 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2543 mCellNetworkAgent.connect(true);
2544 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2545 mWiFiNetworkAgent.connect(false);
2547 // When wi-fi connects, expect to be pinned.
2548 assertTrue(TestNetworkPinner.awaitPin(100));
2549 assertPinnedToWifiWithCellDefault();
2551 // Disconnect and expect the pin to drop.
2552 mWiFiNetworkAgent.disconnect();
2553 assertTrue(TestNetworkPinner.awaitUnpin(100));
2554 assertNotPinnedToWifi();
2556 // Reconnecting does not cause the pin to come back.
2557 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2558 mWiFiNetworkAgent.connect(false);
2559 assertFalse(TestNetworkPinner.awaitPin(100));
2560 assertNotPinnedToWifi();
2562 // Pinning while connected causes the pin to take effect immediately.
2563 TestNetworkPinner.pin(mServiceContext, wifiRequest);
2564 assertTrue(TestNetworkPinner.awaitPin(100));
2565 assertPinnedToWifiWithCellDefault();
2567 // Explicitly unpin and expect to use the default network again.
2568 TestNetworkPinner.unpin();
2569 assertNotPinnedToWifi();
2571 // Disconnect cell and wifi.
2572 ConditionVariable cv = waitForConnectivityBroadcasts(3); // cell down, wifi up, wifi down.
2573 mCellNetworkAgent.disconnect();
2574 mWiFiNetworkAgent.disconnect();
2577 // Pinning takes effect even if the pinned network is the default when the pin is set...
2578 TestNetworkPinner.pin(mServiceContext, wifiRequest);
2579 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2580 mWiFiNetworkAgent.connect(false);
2581 assertTrue(TestNetworkPinner.awaitPin(100));
2582 assertPinnedToWifiWithWifiDefault();
2584 // ... and is maintained even when that network is no longer the default.
2585 cv = waitForConnectivityBroadcasts(1);
2586 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2587 mCellNetworkAgent.connect(true);
2589 assertPinnedToWifiWithCellDefault();
2593 public void testNetworkRequestMaximum() {
2594 final int MAX_REQUESTS = 100;
2595 // Test that the limit is enforced when MAX_REQUESTS simultaneous requests are added.
2596 NetworkRequest networkRequest = new NetworkRequest.Builder().build();
2597 ArrayList<NetworkCallback> networkCallbacks = new ArrayList<NetworkCallback>();
2599 for (int i = 0; i < MAX_REQUESTS; i++) {
2600 NetworkCallback networkCallback = new NetworkCallback();
2601 mCm.requestNetwork(networkRequest, networkCallback);
2602 networkCallbacks.add(networkCallback);
2604 fail("Registering " + MAX_REQUESTS + " NetworkRequests did not throw exception");
2605 } catch (IllegalArgumentException expected) {}
2606 for (NetworkCallback networkCallback : networkCallbacks) {
2607 mCm.unregisterNetworkCallback(networkCallback);
2609 networkCallbacks.clear();
2612 for (int i = 0; i < MAX_REQUESTS; i++) {
2613 NetworkCallback networkCallback = new NetworkCallback();
2614 mCm.registerNetworkCallback(networkRequest, networkCallback);
2615 networkCallbacks.add(networkCallback);
2617 fail("Registering " + MAX_REQUESTS + " NetworkCallbacks did not throw exception");
2618 } catch (IllegalArgumentException expected) {}
2619 for (NetworkCallback networkCallback : networkCallbacks) {
2620 mCm.unregisterNetworkCallback(networkCallback);
2622 networkCallbacks.clear();
2624 ArrayList<PendingIntent> pendingIntents = new ArrayList<PendingIntent>();
2626 for (int i = 0; i < MAX_REQUESTS + 1; i++) {
2627 PendingIntent pendingIntent =
2628 PendingIntent.getBroadcast(mContext, 0, new Intent("a" + i), 0);
2629 mCm.requestNetwork(networkRequest, pendingIntent);
2630 pendingIntents.add(pendingIntent);
2632 fail("Registering " + MAX_REQUESTS +
2633 " PendingIntent NetworkRequests did not throw exception");
2634 } catch (IllegalArgumentException expected) {}
2635 for (PendingIntent pendingIntent : pendingIntents) {
2636 mCm.unregisterNetworkCallback(pendingIntent);
2638 pendingIntents.clear();
2641 for (int i = 0; i < MAX_REQUESTS + 1; i++) {
2642 PendingIntent pendingIntent =
2643 PendingIntent.getBroadcast(mContext, 0, new Intent("a" + i), 0);
2644 mCm.registerNetworkCallback(networkRequest, pendingIntent);
2645 pendingIntents.add(pendingIntent);
2647 fail("Registering " + MAX_REQUESTS +
2648 " PendingIntent NetworkCallbacks did not throw exception");
2649 } catch (IllegalArgumentException expected) {}
2650 for (PendingIntent pendingIntent : pendingIntents) {
2651 mCm.unregisterNetworkCallback(pendingIntent);
2653 pendingIntents.clear();
2654 mService.waitForIdle(5000);
2656 // Test that the limit is not hit when MAX_REQUESTS requests are added and removed.
2657 for (int i = 0; i < MAX_REQUESTS; i++) {
2658 NetworkCallback networkCallback = new NetworkCallback();
2659 mCm.requestNetwork(networkRequest, networkCallback);
2660 mCm.unregisterNetworkCallback(networkCallback);
2662 mService.waitForIdle();
2663 for (int i = 0; i < MAX_REQUESTS; i++) {
2664 NetworkCallback networkCallback = new NetworkCallback();
2665 mCm.registerNetworkCallback(networkRequest, networkCallback);
2666 mCm.unregisterNetworkCallback(networkCallback);
2668 mService.waitForIdle();
2669 for (int i = 0; i < MAX_REQUESTS; i++) {
2670 PendingIntent pendingIntent =
2671 PendingIntent.getBroadcast(mContext, 0, new Intent("b" + i), 0);
2672 mCm.requestNetwork(networkRequest, pendingIntent);
2673 mCm.unregisterNetworkCallback(pendingIntent);
2675 mService.waitForIdle();
2676 for (int i = 0; i < MAX_REQUESTS; i++) {
2677 PendingIntent pendingIntent =
2678 PendingIntent.getBroadcast(mContext, 0, new Intent("c" + i), 0);
2679 mCm.registerNetworkCallback(networkRequest, pendingIntent);
2680 mCm.unregisterNetworkCallback(pendingIntent);