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.anyBoolean;
27 import static org.mockito.Mockito.anyInt;
28 import static org.mockito.Mockito.eq;
29 import static org.mockito.Mockito.mock;
30 import static org.mockito.Mockito.spy;
31 import static org.mockito.Mockito.when;
33 import android.app.NotificationManager;
34 import android.app.PendingIntent;
35 import android.content.BroadcastReceiver;
36 import android.content.ContentResolver;
37 import android.content.Context;
38 import android.content.ContextWrapper;
39 import android.content.Intent;
40 import android.content.IntentFilter;
41 import android.content.res.Resources;
42 import android.net.CaptivePortal;
43 import android.net.ConnectivityManager;
44 import android.net.ConnectivityManager.NetworkCallback;
45 import android.net.ConnectivityManager.PacketKeepalive;
46 import android.net.ConnectivityManager.PacketKeepaliveCallback;
47 import android.net.INetworkPolicyManager;
48 import android.net.INetworkStatsService;
49 import android.net.IpPrefix;
50 import android.net.LinkAddress;
51 import android.net.LinkProperties;
52 import android.net.MatchAllNetworkSpecifier;
53 import android.net.Network;
54 import android.net.NetworkAgent;
55 import android.net.NetworkCapabilities;
56 import android.net.NetworkConfig;
57 import android.net.NetworkFactory;
58 import android.net.NetworkInfo;
59 import android.net.NetworkInfo.DetailedState;
60 import android.net.NetworkMisc;
61 import android.net.NetworkRequest;
62 import android.net.NetworkSpecifier;
63 import android.net.RouteInfo;
64 import android.net.StringNetworkSpecifier;
65 import android.net.metrics.IpConnectivityLog;
66 import android.net.util.MultinetworkPolicyTracker;
67 import android.os.ConditionVariable;
68 import android.os.Handler;
69 import android.os.HandlerThread;
70 import android.os.IBinder;
71 import android.os.INetworkManagementService;
72 import android.os.Looper;
73 import android.os.Message;
74 import android.os.MessageQueue;
75 import android.os.Messenger;
76 import android.os.MessageQueue.IdleHandler;
77 import android.os.Parcel;
78 import android.os.Parcelable;
79 import android.os.Process;
80 import android.os.SystemClock;
81 import android.os.UserHandle;
82 import android.provider.Settings;
83 import android.test.AndroidTestCase;
84 import android.test.mock.MockContentResolver;
85 import android.test.suitebuilder.annotation.SmallTest;
86 import android.text.TextUtils;
87 import android.util.Log;
88 import android.util.LogPrinter;
90 import com.android.internal.util.WakeupMessage;
91 import com.android.internal.util.test.BroadcastInterceptingContext;
92 import com.android.internal.util.test.FakeSettingsProvider;
93 import com.android.server.connectivity.MockableSystemProperties;
94 import com.android.server.connectivity.NetworkAgentInfo;
95 import com.android.server.connectivity.NetworkMonitor;
96 import com.android.server.connectivity.NetworkMonitor.CaptivePortalProbeResult;
97 import com.android.server.net.NetworkPinner;
98 import com.android.server.net.NetworkPolicyManagerInternal;
100 import org.mockito.Mock;
101 import org.mockito.MockitoAnnotations;
102 import org.mockito.Spy;
104 import java.net.InetAddress;
105 import java.util.ArrayList;
106 import java.util.Arrays;
107 import java.util.Objects;
108 import java.util.concurrent.CountDownLatch;
109 import java.util.concurrent.LinkedBlockingQueue;
110 import java.util.concurrent.TimeUnit;
111 import java.util.concurrent.atomic.AtomicBoolean;
112 import java.util.function.BooleanSupplier;
115 * Tests for {@link ConnectivityService}.
117 * Build, install and run with:
118 * runtest frameworks-services -c com.android.server.ConnectivityServiceTest
120 public class ConnectivityServiceTest extends AndroidTestCase {
121 private static final String TAG = "ConnectivityServiceTest";
123 private static final int TIMEOUT_MS = 500;
124 private static final int TEST_LINGER_DELAY_MS = 120;
126 private MockContext mServiceContext;
127 private WrappedConnectivityService mService;
128 private WrappedConnectivityManager mCm;
129 private MockNetworkAgent mWiFiNetworkAgent;
130 private MockNetworkAgent mCellNetworkAgent;
131 private MockNetworkAgent mEthernetNetworkAgent;
133 // This class exists to test bindProcessToNetwork and getBoundNetworkForProcess. These methods
134 // do not go through ConnectivityService but talk to netd directly, so they don't automatically
135 // reflect the state of our test ConnectivityService.
136 private class WrappedConnectivityManager extends ConnectivityManager {
137 private Network mFakeBoundNetwork;
139 public synchronized boolean bindProcessToNetwork(Network network) {
140 mFakeBoundNetwork = network;
144 public synchronized Network getBoundNetworkForProcess() {
145 return mFakeBoundNetwork;
148 public WrappedConnectivityManager(Context context, ConnectivityService service) {
149 super(context, service);
153 private class MockContext extends BroadcastInterceptingContext {
154 private final MockContentResolver mContentResolver;
156 @Spy private Resources mResources;
157 private final LinkedBlockingQueue<Intent> mStartedActivities = new LinkedBlockingQueue<>();
159 MockContext(Context base) {
162 mResources = spy(base.getResources());
163 when(mResources.getStringArray(com.android.internal.R.array.networkAttributes)).
164 thenReturn(new String[] {
165 "wifi,1,1,1,-1,true",
166 "mobile,0,0,0,-1,true",
167 "mobile_mms,2,0,2,60000,true",
170 mContentResolver = new MockContentResolver();
171 mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
175 public void startActivityAsUser(Intent intent, UserHandle handle) {
176 mStartedActivities.offer(intent);
179 public Intent expectStartActivityIntent(int timeoutMs) {
180 Intent intent = null;
182 intent = mStartedActivities.poll(timeoutMs, TimeUnit.MILLISECONDS);
183 } catch (InterruptedException e) {}
184 assertNotNull("Did not receive sign-in intent after " + timeoutMs + "ms", intent);
188 public void expectNoStartActivityIntent(int timeoutMs) {
190 assertNull("Received unexpected Intent to start activity",
191 mStartedActivities.poll(timeoutMs, TimeUnit.MILLISECONDS));
192 } catch (InterruptedException e) {}
196 public Object getSystemService(String name) {
197 if (Context.CONNECTIVITY_SERVICE.equals(name)) return mCm;
198 if (Context.NOTIFICATION_SERVICE.equals(name)) return mock(NotificationManager.class);
199 return super.getSystemService(name);
203 public ContentResolver getContentResolver() {
204 return mContentResolver;
208 public Resources getResources() {
214 * Block until the given handler becomes idle, or until timeoutMs has passed.
216 private static void waitForIdleHandler(HandlerThread handlerThread, int timeoutMs) {
217 final ConditionVariable cv = new ConditionVariable();
218 final Handler handler = new Handler(handlerThread.getLooper());
219 handler.post(() -> cv.open());
220 if (!cv.block(timeoutMs)) {
221 fail("HandlerThread " + handlerThread.getName() +
222 " did not become idle after " + timeoutMs + " ms");
227 public void testWaitForIdle() {
228 final int attempts = 50; // Causes the test to take about 200ms on bullhead-eng.
230 // Tests that waitForIdle returns immediately if the service is already idle.
231 for (int i = 0; i < attempts; i++) {
232 mService.waitForIdle();
235 // Bring up a network that we can use to send messages to ConnectivityService.
236 ConditionVariable cv = waitForConnectivityBroadcasts(1);
237 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
238 mWiFiNetworkAgent.connect(false);
240 Network n = mWiFiNetworkAgent.getNetwork();
243 // Tests that calling waitForIdle waits for messages to be processed.
244 for (int i = 0; i < attempts; i++) {
245 mWiFiNetworkAgent.setSignalStrength(i);
246 mService.waitForIdle();
247 assertEquals(i, mCm.getNetworkCapabilities(n).getSignalStrength());
251 // This test has an inherent race condition in it, and cannot be enabled for continuous testing
252 // or presubmit tests. It is kept for manual runs and documentation purposes.
253 public void verifyThatNotWaitingForIdleCausesRaceConditions() {
254 // Bring up a network that we can use to send messages to ConnectivityService.
255 ConditionVariable cv = waitForConnectivityBroadcasts(1);
256 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
257 mWiFiNetworkAgent.connect(false);
259 Network n = mWiFiNetworkAgent.getNetwork();
262 // Ensure that not calling waitForIdle causes a race condition.
263 final int attempts = 50; // Causes the test to take about 200ms on bullhead-eng.
264 for (int i = 0; i < attempts; i++) {
265 mWiFiNetworkAgent.setSignalStrength(i);
266 if (i != mCm.getNetworkCapabilities(n).getSignalStrength()) {
267 // We hit a race condition, as expected. Pass the test.
272 // No race? There is a bug in this test.
273 fail("expected race condition at least once in " + attempts + " attempts");
276 private class MockNetworkAgent {
277 private final WrappedNetworkMonitor mWrappedNetworkMonitor;
278 private final NetworkInfo mNetworkInfo;
279 private final NetworkCapabilities mNetworkCapabilities;
280 private final HandlerThread mHandlerThread;
281 private final ConditionVariable mDisconnected = new ConditionVariable();
282 private final ConditionVariable mNetworkStatusReceived = new ConditionVariable();
283 private final ConditionVariable mPreventReconnectReceived = new ConditionVariable();
285 private NetworkAgent mNetworkAgent;
286 private int mStartKeepaliveError = PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED;
287 private int mStopKeepaliveError = PacketKeepalive.NO_KEEPALIVE;
288 private Integer mExpectedKeepaliveSlot = null;
289 // Contains the redirectUrl from networkStatus(). Before reading, wait for
290 // mNetworkStatusReceived.
291 private String mRedirectUrl;
293 MockNetworkAgent(int transport) {
294 final int type = transportToLegacyType(transport);
295 final String typeName = ConnectivityManager.getNetworkTypeName(type);
296 mNetworkInfo = new NetworkInfo(type, 0, typeName, "Mock");
297 mNetworkCapabilities = new NetworkCapabilities();
298 mNetworkCapabilities.addTransportType(transport);
300 case TRANSPORT_ETHERNET:
306 case TRANSPORT_CELLULAR:
310 throw new UnsupportedOperationException("unimplemented network type");
312 mHandlerThread = new HandlerThread("Mock-" + typeName);
313 mHandlerThread.start();
314 mNetworkAgent = new NetworkAgent(mHandlerThread.getLooper(), mServiceContext,
315 "Mock-" + typeName, mNetworkInfo, mNetworkCapabilities,
316 new LinkProperties(), mScore, new NetworkMisc()) {
318 public void unwanted() { mDisconnected.open(); }
321 public void startPacketKeepalive(Message msg) {
323 if (mExpectedKeepaliveSlot != null) {
324 assertEquals((int) mExpectedKeepaliveSlot, slot);
326 onPacketKeepaliveEvent(slot, mStartKeepaliveError);
330 public void stopPacketKeepalive(Message msg) {
331 onPacketKeepaliveEvent(msg.arg1, mStopKeepaliveError);
335 public void networkStatus(int status, String redirectUrl) {
336 mRedirectUrl = redirectUrl;
337 mNetworkStatusReceived.open();
341 protected void preventAutomaticReconnect() {
342 mPreventReconnectReceived.open();
345 // Waits for the NetworkAgent to be registered, which includes the creation of the
347 mService.waitForIdle();
348 mWrappedNetworkMonitor = mService.getLastCreatedWrappedNetworkMonitor();
351 public void waitForIdle(int timeoutMs) {
352 waitForIdleHandler(mHandlerThread, timeoutMs);
355 public void waitForIdle() {
356 waitForIdle(TIMEOUT_MS);
359 public void adjustScore(int change) {
361 mNetworkAgent.sendNetworkScore(mScore);
364 public void addCapability(int capability) {
365 mNetworkCapabilities.addCapability(capability);
366 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
369 public void removeCapability(int capability) {
370 mNetworkCapabilities.removeCapability(capability);
371 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
374 public void setSignalStrength(int signalStrength) {
375 mNetworkCapabilities.setSignalStrength(signalStrength);
376 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
379 public void setNetworkSpecifier(NetworkSpecifier networkSpecifier) {
380 mNetworkCapabilities.setNetworkSpecifier(networkSpecifier);
381 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
384 public void connectWithoutInternet() {
385 mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, null);
386 mNetworkAgent.sendNetworkInfo(mNetworkInfo);
390 * Transition this NetworkAgent to CONNECTED state with NET_CAPABILITY_INTERNET.
391 * @param validated Indicate if network should pretend to be validated.
393 public void connect(boolean validated) {
394 assertEquals("MockNetworkAgents can only be connected once",
395 mNetworkInfo.getDetailedState(), DetailedState.IDLE);
396 assertFalse(mNetworkCapabilities.hasCapability(NET_CAPABILITY_INTERNET));
398 NetworkCallback callback = null;
399 final ConditionVariable validatedCv = new ConditionVariable();
401 mWrappedNetworkMonitor.gen204ProbeResult = 204;
402 NetworkRequest request = new NetworkRequest.Builder()
403 .addTransportType(mNetworkCapabilities.getTransportTypes()[0])
405 callback = new NetworkCallback() {
406 public void onCapabilitiesChanged(Network network,
407 NetworkCapabilities networkCapabilities) {
408 if (network.equals(getNetwork()) &&
409 networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED)) {
414 mCm.registerNetworkCallback(request, callback);
416 addCapability(NET_CAPABILITY_INTERNET);
418 connectWithoutInternet();
421 // Wait for network to validate.
422 waitFor(validatedCv);
423 mWrappedNetworkMonitor.gen204ProbeResult = 500;
426 if (callback != null) mCm.unregisterNetworkCallback(callback);
429 public void connectWithCaptivePortal(String redirectUrl) {
430 mWrappedNetworkMonitor.gen204ProbeResult = 200;
431 mWrappedNetworkMonitor.gen204ProbeRedirectUrl = redirectUrl;
435 public void suspend() {
436 mNetworkInfo.setDetailedState(DetailedState.SUSPENDED, null, null);
437 mNetworkAgent.sendNetworkInfo(mNetworkInfo);
440 public void disconnect() {
441 mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, null);
442 mNetworkAgent.sendNetworkInfo(mNetworkInfo);
445 public Network getNetwork() {
446 return new Network(mNetworkAgent.netId);
449 public ConditionVariable getPreventReconnectReceived() {
450 return mPreventReconnectReceived;
453 public ConditionVariable getDisconnectedCV() {
454 return mDisconnected;
457 public WrappedNetworkMonitor getWrappedNetworkMonitor() {
458 return mWrappedNetworkMonitor;
461 public void sendLinkProperties(LinkProperties lp) {
462 mNetworkAgent.sendLinkProperties(lp);
465 public void setStartKeepaliveError(int error) {
466 mStartKeepaliveError = error;
469 public void setStopKeepaliveError(int error) {
470 mStopKeepaliveError = error;
473 public void setExpectedKeepaliveSlot(Integer slot) {
474 mExpectedKeepaliveSlot = slot;
477 public String waitForRedirectUrl() {
478 assertTrue(mNetworkStatusReceived.block(TIMEOUT_MS));
484 * A NetworkFactory that allows tests to wait until any in-flight NetworkRequest add or remove
485 * operations have been processed. Before ConnectivityService can add or remove any requests,
486 * the factory must be told to expect those operations by calling expectAddRequests or
487 * expectRemoveRequests.
489 private static class MockNetworkFactory extends NetworkFactory {
490 private final ConditionVariable mNetworkStartedCV = new ConditionVariable();
491 private final ConditionVariable mNetworkStoppedCV = new ConditionVariable();
492 private final AtomicBoolean mNetworkStarted = new AtomicBoolean(false);
494 // Used to expect that requests be removed or added on a separate thread, without sleeping.
495 // Callers can call either expectAddRequests() or expectRemoveRequests() exactly once, then
496 // cause some other thread to add or remove requests, then call waitForRequests(). We can
497 // either expect requests to be added or removed, but not both, because CountDownLatch can
498 // only count in one direction.
499 private CountDownLatch mExpectations;
501 // Whether we are currently expecting requests to be added or removed. Valid only if
502 // mExpectations is non-null.
503 private boolean mExpectingAdditions;
505 public MockNetworkFactory(Looper looper, Context context, String logTag,
506 NetworkCapabilities filter) {
507 super(looper, context, logTag, filter);
510 public int getMyRequestCount() {
511 return getRequestCount();
514 protected void startNetwork() {
515 mNetworkStarted.set(true);
516 mNetworkStartedCV.open();
519 protected void stopNetwork() {
520 mNetworkStarted.set(false);
521 mNetworkStoppedCV.open();
524 public boolean getMyStartRequested() {
525 return mNetworkStarted.get();
528 public ConditionVariable getNetworkStartedCV() {
529 mNetworkStartedCV.close();
530 return mNetworkStartedCV;
533 public ConditionVariable getNetworkStoppedCV() {
534 mNetworkStoppedCV.close();
535 return mNetworkStoppedCV;
539 protected void handleAddRequest(NetworkRequest request, int score) {
540 // If we're expecting anything, we must be expecting additions.
541 if (mExpectations != null && !mExpectingAdditions) {
542 fail("Can't add requests while expecting requests to be removed");
546 super.handleAddRequest(request, score);
548 // Reduce the number of request additions we're waiting for.
549 if (mExpectingAdditions) {
550 assertTrue("Added more requests than expected", mExpectations.getCount() > 0);
551 mExpectations.countDown();
556 protected void handleRemoveRequest(NetworkRequest request) {
557 // If we're expecting anything, we must be expecting removals.
558 if (mExpectations != null && mExpectingAdditions) {
559 fail("Can't remove requests while expecting requests to be added");
562 // Remove the request.
563 super.handleRemoveRequest(request);
565 // Reduce the number of request removals we're waiting for.
566 if (!mExpectingAdditions) {
567 assertTrue("Removed more requests than expected", mExpectations.getCount() > 0);
568 mExpectations.countDown();
572 private void assertNoExpectations() {
573 if (mExpectations != null) {
574 fail("Can't add expectation, " + mExpectations.getCount() + " already pending");
578 // Expects that count requests will be added.
579 public void expectAddRequests(final int count) {
580 assertNoExpectations();
581 mExpectingAdditions = true;
582 mExpectations = new CountDownLatch(count);
585 // Expects that count requests will be removed.
586 public void expectRemoveRequests(final int count) {
587 assertNoExpectations();
588 mExpectingAdditions = false;
589 mExpectations = new CountDownLatch(count);
592 // Waits for the expected request additions or removals to happen within a timeout.
593 public void waitForRequests() throws InterruptedException {
594 assertNotNull("Nothing to wait for", mExpectations);
595 mExpectations.await(TIMEOUT_MS, TimeUnit.MILLISECONDS);
596 final long count = mExpectations.getCount();
597 final String msg = count + " requests still not " +
598 (mExpectingAdditions ? "added" : "removed") +
599 " after " + TIMEOUT_MS + " ms";
600 assertEquals(msg, 0, count);
601 mExpectations = null;
604 public void waitForNetworkRequests(final int count) throws InterruptedException {
606 assertEquals(count, getMyRequestCount());
610 private class FakeWakeupMessage extends WakeupMessage {
611 private static final int UNREASONABLY_LONG_WAIT = 1000;
613 public FakeWakeupMessage(Context context, Handler handler, String cmdName, int cmd) {
614 super(context, handler, cmdName, cmd);
617 public FakeWakeupMessage(Context context, Handler handler, String cmdName, int cmd,
618 int arg1, int arg2, Object obj) {
619 super(context, handler, cmdName, cmd, arg1, arg2, obj);
623 public void schedule(long when) {
624 long delayMs = when - SystemClock.elapsedRealtime();
625 if (delayMs < 0) delayMs = 0;
626 if (delayMs > UNREASONABLY_LONG_WAIT) {
627 fail("Attempting to send msg more than " + UNREASONABLY_LONG_WAIT +
628 "ms into the future: " + delayMs);
630 Message msg = mHandler.obtainMessage(mCmd, mArg1, mArg2, mObj);
631 mHandler.sendMessageDelayed(msg, delayMs);
635 public void cancel() {
636 mHandler.removeMessages(mCmd, mObj);
640 public void onAlarm() {
641 throw new AssertionError("Should never happen. Update this fake.");
645 // NetworkMonitor implementation allowing overriding of Internet connectivity probe result.
646 private class WrappedNetworkMonitor extends NetworkMonitor {
647 // HTTP response code fed back to NetworkMonitor for Internet connectivity probe.
648 public int gen204ProbeResult = 500;
649 public String gen204ProbeRedirectUrl = null;
651 public WrappedNetworkMonitor(Context context, Handler handler,
652 NetworkAgentInfo networkAgentInfo, NetworkRequest defaultRequest,
653 IpConnectivityLog log) {
654 super(context, handler, networkAgentInfo, defaultRequest, log);
658 protected CaptivePortalProbeResult isCaptivePortal() {
659 if (!mIsCaptivePortalCheckEnabled) { return new CaptivePortalProbeResult(204); }
660 return new CaptivePortalProbeResult(gen204ProbeResult, gen204ProbeRedirectUrl, null);
664 private class WrappedMultinetworkPolicyTracker extends MultinetworkPolicyTracker {
665 public volatile boolean configRestrictsAvoidBadWifi;
666 public volatile int configMeteredMultipathPreference;
668 public WrappedMultinetworkPolicyTracker(Context c, Handler h, Runnable r) {
673 public boolean configRestrictsAvoidBadWifi() {
674 return configRestrictsAvoidBadWifi;
678 public int configMeteredMultipathPreference() {
679 return configMeteredMultipathPreference;
683 private class WrappedConnectivityService extends ConnectivityService {
684 public WrappedMultinetworkPolicyTracker wrappedMultinetworkPolicyTracker;
685 private WrappedNetworkMonitor mLastCreatedNetworkMonitor;
686 private MockableSystemProperties mSystemProperties;
688 public WrappedConnectivityService(Context context, INetworkManagementService netManager,
689 INetworkStatsService statsService, INetworkPolicyManager policyManager,
690 IpConnectivityLog log) {
691 super(context, netManager, statsService, policyManager, log);
692 mLingerDelayMs = TEST_LINGER_DELAY_MS;
696 protected MockableSystemProperties getSystemProperties() {
697 // Minimal approach to overriding system properties: let most calls fall through to real
698 // device values, and only override ones values that are important to this test.
699 mSystemProperties = spy(new MockableSystemProperties());
700 when(mSystemProperties.getInt("net.tcp.default_init_rwnd", 0)).thenReturn(0);
701 when(mSystemProperties.getBoolean("ro.radio.noril", false)).thenReturn(false);
702 return mSystemProperties;
706 protected int reserveNetId() {
708 final int netId = super.reserveNetId();
710 // Don't overlap test NetIDs with real NetIDs as binding sockets to real networks
711 // can have odd side-effects, like network validations succeeding.
712 final Network[] networks = ConnectivityManager.from(getContext()).getAllNetworks();
713 boolean overlaps = false;
714 for (Network network : networks) {
715 if (netId == network.netId) {
720 if (overlaps) continue;
727 public NetworkMonitor createNetworkMonitor(Context context, Handler handler,
728 NetworkAgentInfo nai, NetworkRequest defaultRequest) {
729 final WrappedNetworkMonitor monitor = new WrappedNetworkMonitor(
730 context, handler, nai, defaultRequest, mock(IpConnectivityLog.class));
731 mLastCreatedNetworkMonitor = monitor;
736 public MultinetworkPolicyTracker createMultinetworkPolicyTracker(
737 Context c, Handler h, Runnable r) {
738 final WrappedMultinetworkPolicyTracker tracker = new WrappedMultinetworkPolicyTracker(c, h, r);
742 public WrappedMultinetworkPolicyTracker getMultinetworkPolicyTracker() {
743 return (WrappedMultinetworkPolicyTracker) mMultinetworkPolicyTracker;
747 public WakeupMessage makeWakeupMessage(
748 Context context, Handler handler, String cmdName, int cmd, Object obj) {
749 return new FakeWakeupMessage(context, handler, cmdName, cmd, 0, 0, obj);
752 public WrappedNetworkMonitor getLastCreatedWrappedNetworkMonitor() {
753 return mLastCreatedNetworkMonitor;
756 public void waitForIdle(int timeoutMs) {
757 waitForIdleHandler(mHandlerThread, timeoutMs);
760 public void waitForIdle() {
761 waitForIdle(TIMEOUT_MS);
766 * Wait up to TIMEOUT_MS for {@code conditionVariable} to open.
767 * Fails if TIMEOUT_MS goes by before {@code conditionVariable} opens.
769 static private void waitFor(ConditionVariable conditionVariable) {
770 assertTrue(conditionVariable.block(TIMEOUT_MS));
774 public void setUp() throws Exception {
777 // InstrumentationTestRunner prepares a looper, but AndroidJUnitRunner does not.
778 // http://b/25897652 .
779 if (Looper.myLooper() == null) {
783 mServiceContext = new MockContext(getContext());
784 LocalServices.removeServiceForTest(NetworkPolicyManagerInternal.class);
785 LocalServices.addService(
786 NetworkPolicyManagerInternal.class, mock(NetworkPolicyManagerInternal.class));
787 mService = new WrappedConnectivityService(mServiceContext,
788 mock(INetworkManagementService.class),
789 mock(INetworkStatsService.class),
790 mock(INetworkPolicyManager.class),
791 mock(IpConnectivityLog.class));
793 mService.systemReady();
794 mCm = new WrappedConnectivityManager(getContext(), mService);
795 mCm.bindProcessToNetwork(null);
797 // Ensure that the default setting for Captive Portals is used for most tests
798 setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_PROMPT);
801 public void tearDown() throws Exception {
802 setMobileDataAlwaysOn(false);
803 if (mCellNetworkAgent != null) { mCellNetworkAgent.disconnect(); }
804 if (mWiFiNetworkAgent != null) { mWiFiNetworkAgent.disconnect(); }
805 mCellNetworkAgent = mWiFiNetworkAgent = null;
809 private int transportToLegacyType(int transport) {
811 case TRANSPORT_ETHERNET:
812 return TYPE_ETHERNET;
815 case TRANSPORT_CELLULAR:
818 throw new IllegalStateException("Unknown transport " + transport);
822 private void verifyActiveNetwork(int transport) {
823 // Test getActiveNetworkInfo()
824 assertNotNull(mCm.getActiveNetworkInfo());
825 assertEquals(transportToLegacyType(transport), mCm.getActiveNetworkInfo().getType());
826 // Test getActiveNetwork()
827 assertNotNull(mCm.getActiveNetwork());
828 assertEquals(mCm.getActiveNetwork(), mCm.getActiveNetworkForUid(Process.myUid()));
831 assertEquals(mCm.getActiveNetwork(), mWiFiNetworkAgent.getNetwork());
833 case TRANSPORT_CELLULAR:
834 assertEquals(mCm.getActiveNetwork(), mCellNetworkAgent.getNetwork());
837 throw new IllegalStateException("Unknown transport" + transport);
839 // Test getNetworkInfo(Network)
840 assertNotNull(mCm.getNetworkInfo(mCm.getActiveNetwork()));
841 assertEquals(transportToLegacyType(transport), mCm.getNetworkInfo(mCm.getActiveNetwork()).getType());
842 // Test getNetworkCapabilities(Network)
843 assertNotNull(mCm.getNetworkCapabilities(mCm.getActiveNetwork()));
844 assertTrue(mCm.getNetworkCapabilities(mCm.getActiveNetwork()).hasTransport(transport));
847 private void verifyNoNetwork() {
848 // Test getActiveNetworkInfo()
849 assertNull(mCm.getActiveNetworkInfo());
850 // Test getActiveNetwork()
851 assertNull(mCm.getActiveNetwork());
852 assertNull(mCm.getActiveNetworkForUid(Process.myUid()));
853 // Test getAllNetworks()
854 assertEquals(0, mCm.getAllNetworks().length);
858 * Return a ConditionVariable that opens when {@code count} numbers of CONNECTIVITY_ACTION
859 * broadcasts are received.
861 private ConditionVariable waitForConnectivityBroadcasts(final int count) {
862 final ConditionVariable cv = new ConditionVariable();
863 mServiceContext.registerReceiver(new BroadcastReceiver() {
864 private int remaining = count;
865 public void onReceive(Context context, Intent intent) {
866 if (--remaining == 0) {
868 mServiceContext.unregisterReceiver(this);
871 }, new IntentFilter(CONNECTIVITY_ACTION));
875 public void testNetworkTypes() {
876 // Ensure that our mocks for the networkAttributes config variable work as expected. If they
877 // don't, then tests that depend on CONNECTIVITY_ACTION broadcasts for these network types
878 // will fail. Failing here is much easier to debug.
879 assertTrue(mCm.isNetworkSupported(TYPE_WIFI));
880 assertTrue(mCm.isNetworkSupported(TYPE_MOBILE));
884 public void testLingering() throws Exception {
886 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
887 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
888 assertNull(mCm.getActiveNetworkInfo());
889 assertNull(mCm.getActiveNetwork());
890 // Test bringing up validated cellular.
891 ConditionVariable cv = waitForConnectivityBroadcasts(1);
892 mCellNetworkAgent.connect(true);
894 verifyActiveNetwork(TRANSPORT_CELLULAR);
895 assertEquals(2, mCm.getAllNetworks().length);
896 assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) ||
897 mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork()));
898 assertTrue(mCm.getAllNetworks()[0].equals(mWiFiNetworkAgent.getNetwork()) ||
899 mCm.getAllNetworks()[1].equals(mWiFiNetworkAgent.getNetwork()));
900 // Test bringing up validated WiFi.
901 cv = waitForConnectivityBroadcasts(2);
902 mWiFiNetworkAgent.connect(true);
904 verifyActiveNetwork(TRANSPORT_WIFI);
905 assertEquals(2, mCm.getAllNetworks().length);
906 assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) ||
907 mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork()));
908 assertTrue(mCm.getAllNetworks()[0].equals(mCellNetworkAgent.getNetwork()) ||
909 mCm.getAllNetworks()[1].equals(mCellNetworkAgent.getNetwork()));
910 // Test cellular linger timeout.
911 waitFor(mCellNetworkAgent.getDisconnectedCV());
912 mService.waitForIdle();
913 assertEquals(1, mCm.getAllNetworks().length);
914 verifyActiveNetwork(TRANSPORT_WIFI);
915 assertEquals(1, mCm.getAllNetworks().length);
916 assertEquals(mCm.getAllNetworks()[0], mCm.getActiveNetwork());
917 // Test WiFi disconnect.
918 cv = waitForConnectivityBroadcasts(1);
919 mWiFiNetworkAgent.disconnect();
925 public void testValidatedCellularOutscoresUnvalidatedWiFi() throws Exception {
926 // Test bringing up unvalidated WiFi
927 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
928 ConditionVariable cv = waitForConnectivityBroadcasts(1);
929 mWiFiNetworkAgent.connect(false);
931 verifyActiveNetwork(TRANSPORT_WIFI);
932 // Test bringing up unvalidated cellular
933 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
934 mCellNetworkAgent.connect(false);
935 mService.waitForIdle();
936 verifyActiveNetwork(TRANSPORT_WIFI);
937 // Test cellular disconnect.
938 mCellNetworkAgent.disconnect();
939 mService.waitForIdle();
940 verifyActiveNetwork(TRANSPORT_WIFI);
941 // Test bringing up validated cellular
942 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
943 cv = waitForConnectivityBroadcasts(2);
944 mCellNetworkAgent.connect(true);
946 verifyActiveNetwork(TRANSPORT_CELLULAR);
947 // Test cellular disconnect.
948 cv = waitForConnectivityBroadcasts(2);
949 mCellNetworkAgent.disconnect();
951 verifyActiveNetwork(TRANSPORT_WIFI);
952 // Test WiFi disconnect.
953 cv = waitForConnectivityBroadcasts(1);
954 mWiFiNetworkAgent.disconnect();
960 public void testUnvalidatedWifiOutscoresUnvalidatedCellular() throws Exception {
961 // Test bringing up unvalidated cellular.
962 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
963 ConditionVariable cv = waitForConnectivityBroadcasts(1);
964 mCellNetworkAgent.connect(false);
966 verifyActiveNetwork(TRANSPORT_CELLULAR);
967 // Test bringing up unvalidated WiFi.
968 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
969 cv = waitForConnectivityBroadcasts(2);
970 mWiFiNetworkAgent.connect(false);
972 verifyActiveNetwork(TRANSPORT_WIFI);
973 // Test WiFi disconnect.
974 cv = waitForConnectivityBroadcasts(2);
975 mWiFiNetworkAgent.disconnect();
977 verifyActiveNetwork(TRANSPORT_CELLULAR);
978 // Test cellular disconnect.
979 cv = waitForConnectivityBroadcasts(1);
980 mCellNetworkAgent.disconnect();
986 public void testUnlingeringDoesNotValidate() throws Exception {
987 // Test bringing up unvalidated WiFi.
988 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
989 ConditionVariable cv = waitForConnectivityBroadcasts(1);
990 mWiFiNetworkAgent.connect(false);
992 verifyActiveNetwork(TRANSPORT_WIFI);
993 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
994 NET_CAPABILITY_VALIDATED));
995 // Test bringing up validated cellular.
996 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
997 cv = waitForConnectivityBroadcasts(2);
998 mCellNetworkAgent.connect(true);
1000 verifyActiveNetwork(TRANSPORT_CELLULAR);
1001 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1002 NET_CAPABILITY_VALIDATED));
1003 // Test cellular disconnect.
1004 cv = waitForConnectivityBroadcasts(2);
1005 mCellNetworkAgent.disconnect();
1007 verifyActiveNetwork(TRANSPORT_WIFI);
1008 // Unlingering a network should not cause it to be marked as validated.
1009 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1010 NET_CAPABILITY_VALIDATED));
1014 public void testCellularOutscoresWeakWifi() throws Exception {
1015 // Test bringing up validated cellular.
1016 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1017 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1018 mCellNetworkAgent.connect(true);
1020 verifyActiveNetwork(TRANSPORT_CELLULAR);
1021 // Test bringing up validated WiFi.
1022 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1023 cv = waitForConnectivityBroadcasts(2);
1024 mWiFiNetworkAgent.connect(true);
1026 verifyActiveNetwork(TRANSPORT_WIFI);
1027 // Test WiFi getting really weak.
1028 cv = waitForConnectivityBroadcasts(2);
1029 mWiFiNetworkAgent.adjustScore(-11);
1031 verifyActiveNetwork(TRANSPORT_CELLULAR);
1032 // Test WiFi restoring signal strength.
1033 cv = waitForConnectivityBroadcasts(2);
1034 mWiFiNetworkAgent.adjustScore(11);
1036 verifyActiveNetwork(TRANSPORT_WIFI);
1040 public void testReapingNetwork() throws Exception {
1041 // Test bringing up WiFi without NET_CAPABILITY_INTERNET.
1042 // Expect it to be torn down immediately because it satisfies no requests.
1043 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1044 ConditionVariable cv = mWiFiNetworkAgent.getDisconnectedCV();
1045 mWiFiNetworkAgent.connectWithoutInternet();
1047 // Test bringing up cellular without NET_CAPABILITY_INTERNET.
1048 // Expect it to be torn down immediately because it satisfies no requests.
1049 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1050 cv = mCellNetworkAgent.getDisconnectedCV();
1051 mCellNetworkAgent.connectWithoutInternet();
1053 // Test bringing up validated WiFi.
1054 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1055 cv = waitForConnectivityBroadcasts(1);
1056 mWiFiNetworkAgent.connect(true);
1058 verifyActiveNetwork(TRANSPORT_WIFI);
1059 // Test bringing up unvalidated cellular.
1060 // Expect it to be torn down because it could never be the highest scoring network
1061 // satisfying the default request even if it validated.
1062 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1063 cv = mCellNetworkAgent.getDisconnectedCV();
1064 mCellNetworkAgent.connect(false);
1066 verifyActiveNetwork(TRANSPORT_WIFI);
1067 cv = mWiFiNetworkAgent.getDisconnectedCV();
1068 mWiFiNetworkAgent.disconnect();
1073 public void testCellularFallback() throws Exception {
1074 // Test bringing up validated cellular.
1075 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1076 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1077 mCellNetworkAgent.connect(true);
1079 verifyActiveNetwork(TRANSPORT_CELLULAR);
1080 // Test bringing up validated WiFi.
1081 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1082 cv = waitForConnectivityBroadcasts(2);
1083 mWiFiNetworkAgent.connect(true);
1085 verifyActiveNetwork(TRANSPORT_WIFI);
1086 // Reevaluate WiFi (it'll instantly fail DNS).
1087 cv = waitForConnectivityBroadcasts(2);
1088 assertTrue(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1089 NET_CAPABILITY_VALIDATED));
1090 mCm.reportBadNetwork(mWiFiNetworkAgent.getNetwork());
1091 // Should quickly fall back to Cellular.
1093 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1094 NET_CAPABILITY_VALIDATED));
1095 verifyActiveNetwork(TRANSPORT_CELLULAR);
1096 // Reevaluate cellular (it'll instantly fail DNS).
1097 cv = waitForConnectivityBroadcasts(2);
1098 assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1099 NET_CAPABILITY_VALIDATED));
1100 mCm.reportBadNetwork(mCellNetworkAgent.getNetwork());
1101 // Should quickly fall back to WiFi.
1103 assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1104 NET_CAPABILITY_VALIDATED));
1105 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1106 NET_CAPABILITY_VALIDATED));
1107 verifyActiveNetwork(TRANSPORT_WIFI);
1111 public void testWiFiFallback() throws Exception {
1112 // Test bringing up unvalidated WiFi.
1113 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1114 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1115 mWiFiNetworkAgent.connect(false);
1117 verifyActiveNetwork(TRANSPORT_WIFI);
1118 // Test bringing up validated cellular.
1119 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1120 cv = waitForConnectivityBroadcasts(2);
1121 mCellNetworkAgent.connect(true);
1123 verifyActiveNetwork(TRANSPORT_CELLULAR);
1124 // Reevaluate cellular (it'll instantly fail DNS).
1125 cv = waitForConnectivityBroadcasts(2);
1126 assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1127 NET_CAPABILITY_VALIDATED));
1128 mCm.reportBadNetwork(mCellNetworkAgent.getNetwork());
1129 // Should quickly fall back to WiFi.
1131 assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1132 NET_CAPABILITY_VALIDATED));
1133 verifyActiveNetwork(TRANSPORT_WIFI);
1136 enum CallbackState {
1139 NETWORK_CAPABILITIES,
1147 private static class CallbackInfo {
1148 public final CallbackState state;
1149 public final Network network;
1150 public final Object arg;
1151 public CallbackInfo(CallbackState s, Network n, Object o) {
1152 state = s; network = n; arg = o;
1154 public String toString() {
1155 return String.format("%s (%s) (%s)", state, network, arg);
1158 public boolean equals(Object o) {
1159 if (!(o instanceof CallbackInfo)) return false;
1160 // Ignore timeMs, since it's unpredictable.
1161 CallbackInfo other = (CallbackInfo) o;
1162 return (state == other.state) && Objects.equals(network, other.network);
1165 public int hashCode() {
1166 return Objects.hash(state, network);
1171 * Utility NetworkCallback for testing. The caller must explicitly test for all the callbacks
1172 * this class receives, by calling expectCallback() exactly once each time a callback is
1173 * received. assertNoCallback may be called at any time.
1175 private class TestNetworkCallback extends NetworkCallback {
1176 // Chosen to be much less than the linger timeout. This ensures that we can distinguish
1177 // between a LOST callback that arrives immediately and a LOST callback that arrives after
1178 // the linger timeout.
1179 private final static int TIMEOUT_MS = 100;
1181 private final LinkedBlockingQueue<CallbackInfo> mCallbacks = new LinkedBlockingQueue<>();
1183 protected void setLastCallback(CallbackState state, Network network, Object o) {
1184 mCallbacks.offer(new CallbackInfo(state, network, o));
1188 public void onAvailable(Network network) {
1189 setLastCallback(CallbackState.AVAILABLE, network, null);
1193 public void onCapabilitiesChanged(Network network, NetworkCapabilities netCap) {
1194 setLastCallback(CallbackState.NETWORK_CAPABILITIES, network, netCap);
1198 public void onLinkPropertiesChanged(Network network, LinkProperties linkProp) {
1199 setLastCallback(CallbackState.LINK_PROPERTIES, network, linkProp);
1203 public void onUnavailable() {
1204 setLastCallback(CallbackState.UNAVAILABLE, null, null);
1208 public void onNetworkSuspended(Network network) {
1209 setLastCallback(CallbackState.SUSPENDED, network, null);
1213 public void onLosing(Network network, int maxMsToLive) {
1214 setLastCallback(CallbackState.LOSING, network, maxMsToLive /* autoboxed int */);
1218 public void onLost(Network network) {
1219 setLastCallback(CallbackState.LOST, network, null);
1222 CallbackInfo nextCallback(int timeoutMs) {
1223 CallbackInfo cb = null;
1225 cb = mCallbacks.poll(timeoutMs, TimeUnit.MILLISECONDS);
1226 } catch (InterruptedException e) {
1229 // LinkedBlockingQueue.poll() returns null if it timeouts.
1230 fail("Did not receive callback after " + timeoutMs + "ms");
1235 CallbackInfo expectCallback(CallbackState state, MockNetworkAgent agent, int timeoutMs) {
1236 final Network expectedNetwork = (agent != null) ? agent.getNetwork() : null;
1237 CallbackInfo expected = new CallbackInfo(state, expectedNetwork, 0);
1238 CallbackInfo actual = nextCallback(timeoutMs);
1239 assertEquals("Unexpected callback:", expected, actual);
1241 if (state == CallbackState.LOSING) {
1242 String msg = String.format(
1243 "Invalid linger time value %d, must be between %d and %d",
1244 actual.arg, 0, TEST_LINGER_DELAY_MS);
1245 int maxMsToLive = (Integer) actual.arg;
1246 assertTrue(msg, 0 <= maxMsToLive && maxMsToLive <= TEST_LINGER_DELAY_MS);
1252 CallbackInfo expectCallback(CallbackState state, MockNetworkAgent agent) {
1253 return expectCallback(state, agent, TIMEOUT_MS);
1256 void expectAvailableCallbacks(MockNetworkAgent agent, boolean expectSuspended, int timeoutMs) {
1257 expectCallback(CallbackState.AVAILABLE, agent, timeoutMs);
1258 if (expectSuspended) {
1259 expectCallback(CallbackState.SUSPENDED, agent, timeoutMs);
1261 expectCallback(CallbackState.NETWORK_CAPABILITIES, agent, timeoutMs);
1262 expectCallback(CallbackState.LINK_PROPERTIES, agent, timeoutMs);
1265 void expectAvailableCallbacks(MockNetworkAgent agent) {
1266 expectAvailableCallbacks(agent, false, TIMEOUT_MS);
1269 void expectAvailableAndSuspendedCallbacks(MockNetworkAgent agent) {
1270 expectAvailableCallbacks(agent, true, TIMEOUT_MS);
1273 void expectAvailableAndValidatedCallbacks(MockNetworkAgent agent) {
1274 expectAvailableCallbacks(agent, false, TIMEOUT_MS);
1275 expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, agent);
1278 void expectCapabilitiesWith(int capability, MockNetworkAgent agent) {
1279 CallbackInfo cbi = expectCallback(CallbackState.NETWORK_CAPABILITIES, agent);
1280 NetworkCapabilities nc = (NetworkCapabilities) cbi.arg;
1281 assertTrue(nc.hasCapability(capability));
1284 void expectCapabilitiesWithout(int capability, MockNetworkAgent agent) {
1285 CallbackInfo cbi = expectCallback(CallbackState.NETWORK_CAPABILITIES, agent);
1286 NetworkCapabilities nc = (NetworkCapabilities) cbi.arg;
1287 assertFalse(nc.hasCapability(capability));
1290 void assertNoCallback() {
1291 mService.waitForIdle();
1292 CallbackInfo c = mCallbacks.peek();
1293 assertNull("Unexpected callback: " + c, c);
1297 // Can't be part of TestNetworkCallback because "cannot be declared static; static methods can
1298 // only be declared in a static or top level type".
1299 static void assertNoCallbacks(TestNetworkCallback ... callbacks) {
1300 for (TestNetworkCallback c : callbacks) {
1301 c.assertNoCallback();
1306 public void testStateChangeNetworkCallbacks() throws Exception {
1307 final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback();
1308 final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
1309 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
1310 final NetworkRequest genericRequest = new NetworkRequest.Builder()
1311 .clearCapabilities().build();
1312 final NetworkRequest wifiRequest = new NetworkRequest.Builder()
1313 .addTransportType(TRANSPORT_WIFI).build();
1314 final NetworkRequest cellRequest = new NetworkRequest.Builder()
1315 .addTransportType(TRANSPORT_CELLULAR).build();
1316 mCm.registerNetworkCallback(genericRequest, genericNetworkCallback);
1317 mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
1318 mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
1320 // Test unvalidated networks
1321 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1322 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1323 mCellNetworkAgent.connect(false);
1324 genericNetworkCallback.expectAvailableCallbacks(mCellNetworkAgent);
1325 cellNetworkCallback.expectAvailableCallbacks(mCellNetworkAgent);
1326 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1328 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
1330 // This should not trigger spurious onAvailable() callbacks, b/21762680.
1331 mCellNetworkAgent.adjustScore(-1);
1332 mService.waitForIdle();
1333 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
1334 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1336 cv = waitForConnectivityBroadcasts(2);
1337 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1338 mWiFiNetworkAgent.connect(false);
1339 genericNetworkCallback.expectAvailableCallbacks(mWiFiNetworkAgent);
1340 wifiNetworkCallback.expectAvailableCallbacks(mWiFiNetworkAgent);
1341 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1343 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
1345 cv = waitForConnectivityBroadcasts(2);
1346 mWiFiNetworkAgent.disconnect();
1347 genericNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1348 wifiNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1349 cellNetworkCallback.assertNoCallback();
1351 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
1353 cv = waitForConnectivityBroadcasts(1);
1354 mCellNetworkAgent.disconnect();
1355 genericNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1356 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1358 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
1360 // Test validated networks
1361 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1362 mCellNetworkAgent.connect(true);
1363 genericNetworkCallback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent);
1364 cellNetworkCallback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent);
1365 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1366 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
1368 // This should not trigger spurious onAvailable() callbacks, b/21762680.
1369 mCellNetworkAgent.adjustScore(-1);
1370 mService.waitForIdle();
1371 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
1372 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1374 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1375 mWiFiNetworkAgent.connect(true);
1376 genericNetworkCallback.expectAvailableCallbacks(mWiFiNetworkAgent);
1377 genericNetworkCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
1378 genericNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
1379 wifiNetworkCallback.expectAvailableAndValidatedCallbacks(mWiFiNetworkAgent);
1380 cellNetworkCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
1381 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1382 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
1384 mWiFiNetworkAgent.disconnect();
1385 genericNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1386 wifiNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1387 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
1389 mCellNetworkAgent.disconnect();
1390 genericNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1391 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1392 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
1396 public void testMultipleLingering() {
1397 NetworkRequest request = new NetworkRequest.Builder()
1398 .clearCapabilities().addCapability(NET_CAPABILITY_NOT_METERED)
1400 TestNetworkCallback callback = new TestNetworkCallback();
1401 mCm.registerNetworkCallback(request, callback);
1403 TestNetworkCallback defaultCallback = new TestNetworkCallback();
1404 mCm.registerDefaultNetworkCallback(defaultCallback);
1406 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1407 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1408 mEthernetNetworkAgent = new MockNetworkAgent(TRANSPORT_ETHERNET);
1410 mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
1411 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
1412 mEthernetNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
1414 mCellNetworkAgent.connect(true);
1415 callback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent);
1416 defaultCallback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent);
1417 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1419 mWiFiNetworkAgent.connect(true);
1420 // We get AVAILABLE on wifi when wifi connects and satisfies our unmetered request.
1421 // We then get LOSING when wifi validates and cell is outscored.
1422 callback.expectAvailableCallbacks(mWiFiNetworkAgent);
1423 // TODO: Investigate sending validated before losing.
1424 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
1425 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
1426 defaultCallback.expectAvailableAndValidatedCallbacks(mWiFiNetworkAgent);
1427 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1429 mEthernetNetworkAgent.connect(true);
1430 callback.expectAvailableCallbacks(mEthernetNetworkAgent);
1431 // TODO: Investigate sending validated before losing.
1432 callback.expectCallback(CallbackState.LOSING, mWiFiNetworkAgent);
1433 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mEthernetNetworkAgent);
1434 defaultCallback.expectAvailableAndValidatedCallbacks(mEthernetNetworkAgent);
1435 assertEquals(mEthernetNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1437 mEthernetNetworkAgent.disconnect();
1438 callback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
1439 defaultCallback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
1440 defaultCallback.expectAvailableCallbacks(mWiFiNetworkAgent);
1442 for (int i = 0; i < 4; i++) {
1443 MockNetworkAgent oldNetwork, newNetwork;
1445 mWiFiNetworkAgent.adjustScore(-15);
1446 oldNetwork = mWiFiNetworkAgent;
1447 newNetwork = mCellNetworkAgent;
1449 mWiFiNetworkAgent.adjustScore(15);
1450 oldNetwork = mCellNetworkAgent;
1451 newNetwork = mWiFiNetworkAgent;
1454 callback.expectCallback(CallbackState.LOSING, oldNetwork);
1455 // TODO: should we send an AVAILABLE callback to newNetwork, to indicate that it is no
1456 // longer lingering?
1457 defaultCallback.expectAvailableCallbacks(newNetwork);
1458 assertEquals(newNetwork.getNetwork(), mCm.getActiveNetwork());
1460 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1462 // Verify that if a network no longer satisfies a request, we send LOST and not LOSING, even
1463 // if the network is still up.
1464 mWiFiNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
1465 // We expect a notification about the capabilities change, and nothing else.
1466 defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_METERED, mWiFiNetworkAgent);
1467 defaultCallback.assertNoCallback();
1468 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1470 // Wifi no longer satisfies our listen, which is for an unmetered network.
1471 // But because its score is 55, it's still up (and the default network).
1472 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1474 // Disconnect our test networks.
1475 mWiFiNetworkAgent.disconnect();
1476 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1477 defaultCallback.expectAvailableCallbacks(mCellNetworkAgent);
1478 mCellNetworkAgent.disconnect();
1479 defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1481 mCm.unregisterNetworkCallback(callback);
1482 mService.waitForIdle();
1484 // Check that a network is only lingered or torn down if it would not satisfy a request even
1486 request = new NetworkRequest.Builder().clearCapabilities().build();
1487 callback = new TestNetworkCallback();
1489 mCm.registerNetworkCallback(request, callback);
1491 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1492 mCellNetworkAgent.connect(false); // Score: 10
1493 callback.expectAvailableCallbacks(mCellNetworkAgent);
1494 defaultCallback.expectAvailableCallbacks(mCellNetworkAgent);
1495 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1497 // Bring up wifi with a score of 20.
1498 // Cell stays up because it would satisfy the default request if it validated.
1499 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1500 mWiFiNetworkAgent.connect(false); // Score: 20
1501 callback.expectAvailableCallbacks(mWiFiNetworkAgent);
1502 defaultCallback.expectAvailableCallbacks(mWiFiNetworkAgent);
1503 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1505 mWiFiNetworkAgent.disconnect();
1506 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1507 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1508 defaultCallback.expectAvailableCallbacks(mCellNetworkAgent);
1509 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1511 // Bring up wifi with a score of 70.
1512 // Cell is lingered because it would not satisfy any request, even if it validated.
1513 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1514 mWiFiNetworkAgent.adjustScore(50);
1515 mWiFiNetworkAgent.connect(false); // Score: 70
1516 callback.expectAvailableCallbacks(mWiFiNetworkAgent);
1517 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
1518 defaultCallback.expectAvailableCallbacks(mWiFiNetworkAgent);
1519 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1522 mWiFiNetworkAgent.disconnect();
1523 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1524 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1525 defaultCallback.expectAvailableCallbacks(mCellNetworkAgent);
1526 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1528 // Bring up wifi, then validate it. Previous versions would immediately tear down cell, but
1529 // it's arguably correct to linger it, since it was the default network before it validated.
1530 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1531 mWiFiNetworkAgent.connect(true);
1532 callback.expectAvailableCallbacks(mWiFiNetworkAgent);
1533 // TODO: Investigate sending validated before losing.
1534 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
1535 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
1536 defaultCallback.expectAvailableAndValidatedCallbacks(mWiFiNetworkAgent);
1537 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1539 mWiFiNetworkAgent.disconnect();
1540 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1541 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1542 defaultCallback.expectAvailableCallbacks(mCellNetworkAgent);
1543 mCellNetworkAgent.disconnect();
1544 callback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1545 defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1547 // If a network is lingering, and we add and remove a request from it, resume lingering.
1548 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1549 mCellNetworkAgent.connect(true);
1550 callback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent);
1551 defaultCallback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent);
1552 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1553 mWiFiNetworkAgent.connect(true);
1554 defaultCallback.expectAvailableAndValidatedCallbacks(mWiFiNetworkAgent);
1555 callback.expectAvailableCallbacks(mWiFiNetworkAgent);
1556 // TODO: Investigate sending validated before losing.
1557 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
1558 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
1560 NetworkRequest cellRequest = new NetworkRequest.Builder()
1561 .addTransportType(TRANSPORT_CELLULAR).build();
1562 NetworkCallback noopCallback = new NetworkCallback();
1563 mCm.requestNetwork(cellRequest, noopCallback);
1564 // TODO: should this cause an AVAILABLE callback, to indicate that the network is no longer
1566 mCm.unregisterNetworkCallback(noopCallback);
1567 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
1569 // Similar to the above: lingering can start even after the lingered request is removed.
1570 // Disconnect wifi and switch to cell.
1571 mWiFiNetworkAgent.disconnect();
1572 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1573 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1574 defaultCallback.expectAvailableCallbacks(mCellNetworkAgent);
1576 // Cell is now the default network. Pin it with a cell-specific request.
1577 noopCallback = new NetworkCallback(); // Can't reuse NetworkCallbacks. http://b/20701525
1578 mCm.requestNetwork(cellRequest, noopCallback);
1580 // Now connect wifi, and expect it to become the default network.
1581 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1582 mWiFiNetworkAgent.connect(true);
1583 callback.expectAvailableAndValidatedCallbacks(mWiFiNetworkAgent);
1584 defaultCallback.expectAvailableAndValidatedCallbacks(mWiFiNetworkAgent);
1585 // The default request is lingering on cell, but nothing happens to cell, and we send no
1586 // callbacks for it, because it's kept up by cellRequest.
1587 callback.assertNoCallback();
1588 // Now unregister cellRequest and expect cell to start lingering.
1589 mCm.unregisterNetworkCallback(noopCallback);
1590 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
1592 // Let linger run its course.
1593 callback.assertNoCallback();
1594 final int lingerTimeoutMs = TEST_LINGER_DELAY_MS + TEST_LINGER_DELAY_MS / 4;
1595 callback.expectCallback(CallbackState.LOST, mCellNetworkAgent, lingerTimeoutMs);
1598 mWiFiNetworkAgent.disconnect();
1599 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1600 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1602 mCm.unregisterNetworkCallback(callback);
1603 mCm.unregisterNetworkCallback(defaultCallback);
1606 private void tryNetworkFactoryRequests(int capability) throws Exception {
1607 // Verify NOT_RESTRICTED is set appropriately
1608 final NetworkCapabilities nc = new NetworkRequest.Builder().addCapability(capability)
1609 .build().networkCapabilities;
1610 if (capability == NET_CAPABILITY_CBS || capability == NET_CAPABILITY_DUN ||
1611 capability == NET_CAPABILITY_EIMS || capability == NET_CAPABILITY_FOTA ||
1612 capability == NET_CAPABILITY_IA || capability == NET_CAPABILITY_IMS ||
1613 capability == NET_CAPABILITY_RCS || capability == NET_CAPABILITY_XCAP) {
1614 assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
1616 assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
1619 NetworkCapabilities filter = new NetworkCapabilities();
1620 filter.addCapability(capability);
1621 final HandlerThread handlerThread = new HandlerThread("testNetworkFactoryRequests");
1622 handlerThread.start();
1623 final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
1624 mServiceContext, "testFactory", filter);
1625 testFactory.setScoreFilter(40);
1626 ConditionVariable cv = testFactory.getNetworkStartedCV();
1627 testFactory.expectAddRequests(1);
1628 testFactory.register();
1629 testFactory.waitForNetworkRequests(1);
1630 int expectedRequestCount = 1;
1631 NetworkCallback networkCallback = null;
1632 // For non-INTERNET capabilities we cannot rely on the default request being present, so
1634 if (capability != NET_CAPABILITY_INTERNET) {
1635 assertFalse(testFactory.getMyStartRequested());
1636 NetworkRequest request = new NetworkRequest.Builder().addCapability(capability).build();
1637 networkCallback = new NetworkCallback();
1638 testFactory.expectAddRequests(1);
1639 mCm.requestNetwork(request, networkCallback);
1640 expectedRequestCount++;
1641 testFactory.waitForNetworkRequests(expectedRequestCount);
1644 assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
1645 assertTrue(testFactory.getMyStartRequested());
1647 // Now bring in a higher scored network.
1648 MockNetworkAgent testAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1649 // Rather than create a validated network which complicates things by registering it's
1650 // own NetworkRequest during startup, just bump up the score to cancel out the
1651 // unvalidated penalty.
1652 testAgent.adjustScore(40);
1653 cv = testFactory.getNetworkStoppedCV();
1655 // When testAgent connects, ConnectivityService will re-send us all current requests with
1656 // the new score. There are expectedRequestCount such requests, and we must wait for all of
1658 testFactory.expectAddRequests(expectedRequestCount);
1659 testAgent.connect(false);
1660 testAgent.addCapability(capability);
1662 testFactory.waitForNetworkRequests(expectedRequestCount);
1663 assertFalse(testFactory.getMyStartRequested());
1665 // Bring in a bunch of requests.
1666 testFactory.expectAddRequests(10);
1667 assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
1668 ConnectivityManager.NetworkCallback[] networkCallbacks =
1669 new ConnectivityManager.NetworkCallback[10];
1670 for (int i = 0; i< networkCallbacks.length; i++) {
1671 networkCallbacks[i] = new ConnectivityManager.NetworkCallback();
1672 NetworkRequest.Builder builder = new NetworkRequest.Builder();
1673 builder.addCapability(capability);
1674 mCm.requestNetwork(builder.build(), networkCallbacks[i]);
1676 testFactory.waitForNetworkRequests(10 + expectedRequestCount);
1677 assertFalse(testFactory.getMyStartRequested());
1679 // Remove the requests.
1680 testFactory.expectRemoveRequests(10);
1681 for (int i = 0; i < networkCallbacks.length; i++) {
1682 mCm.unregisterNetworkCallback(networkCallbacks[i]);
1684 testFactory.waitForNetworkRequests(expectedRequestCount);
1685 assertFalse(testFactory.getMyStartRequested());
1687 // Drop the higher scored network.
1688 cv = testFactory.getNetworkStartedCV();
1689 testAgent.disconnect();
1691 assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
1692 assertTrue(testFactory.getMyStartRequested());
1694 testFactory.unregister();
1695 if (networkCallback != null) mCm.unregisterNetworkCallback(networkCallback);
1696 handlerThread.quit();
1700 public void testNetworkFactoryRequests() throws Exception {
1701 tryNetworkFactoryRequests(NET_CAPABILITY_MMS);
1702 tryNetworkFactoryRequests(NET_CAPABILITY_SUPL);
1703 tryNetworkFactoryRequests(NET_CAPABILITY_DUN);
1704 tryNetworkFactoryRequests(NET_CAPABILITY_FOTA);
1705 tryNetworkFactoryRequests(NET_CAPABILITY_IMS);
1706 tryNetworkFactoryRequests(NET_CAPABILITY_CBS);
1707 tryNetworkFactoryRequests(NET_CAPABILITY_WIFI_P2P);
1708 tryNetworkFactoryRequests(NET_CAPABILITY_IA);
1709 tryNetworkFactoryRequests(NET_CAPABILITY_RCS);
1710 tryNetworkFactoryRequests(NET_CAPABILITY_XCAP);
1711 tryNetworkFactoryRequests(NET_CAPABILITY_EIMS);
1712 tryNetworkFactoryRequests(NET_CAPABILITY_NOT_METERED);
1713 tryNetworkFactoryRequests(NET_CAPABILITY_INTERNET);
1714 tryNetworkFactoryRequests(NET_CAPABILITY_TRUSTED);
1715 tryNetworkFactoryRequests(NET_CAPABILITY_NOT_VPN);
1716 // Skipping VALIDATED and CAPTIVE_PORTAL as they're disallowed.
1720 public void testNoMutableNetworkRequests() throws Exception {
1721 PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, new Intent("a"), 0);
1722 NetworkRequest.Builder builder = new NetworkRequest.Builder();
1723 builder.addCapability(NET_CAPABILITY_VALIDATED);
1725 mCm.requestNetwork(builder.build(), new NetworkCallback());
1727 } catch (IllegalArgumentException expected) {}
1729 mCm.requestNetwork(builder.build(), pendingIntent);
1731 } catch (IllegalArgumentException expected) {}
1732 builder = new NetworkRequest.Builder();
1733 builder.addCapability(NET_CAPABILITY_CAPTIVE_PORTAL);
1735 mCm.requestNetwork(builder.build(), new NetworkCallback());
1737 } catch (IllegalArgumentException expected) {}
1739 mCm.requestNetwork(builder.build(), pendingIntent);
1741 } catch (IllegalArgumentException expected) {}
1745 public void testMMSonWiFi() throws Exception {
1746 // Test bringing up cellular without MMS NetworkRequest gets reaped
1747 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1748 mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS);
1749 ConditionVariable cv = mCellNetworkAgent.getDisconnectedCV();
1750 mCellNetworkAgent.connectWithoutInternet();
1752 mService.waitForIdle();
1753 assertEquals(0, mCm.getAllNetworks().length);
1755 // Test bringing up validated WiFi.
1756 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1757 cv = waitForConnectivityBroadcasts(1);
1758 mWiFiNetworkAgent.connect(true);
1760 verifyActiveNetwork(TRANSPORT_WIFI);
1761 // Register MMS NetworkRequest
1762 NetworkRequest.Builder builder = new NetworkRequest.Builder();
1763 builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
1764 final TestNetworkCallback networkCallback = new TestNetworkCallback();
1765 mCm.requestNetwork(builder.build(), networkCallback);
1766 // Test bringing up unvalidated cellular with MMS
1767 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1768 mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS);
1769 mCellNetworkAgent.connectWithoutInternet();
1770 networkCallback.expectAvailableCallbacks(mCellNetworkAgent);
1771 verifyActiveNetwork(TRANSPORT_WIFI);
1772 // Test releasing NetworkRequest disconnects cellular with MMS
1773 cv = mCellNetworkAgent.getDisconnectedCV();
1774 mCm.unregisterNetworkCallback(networkCallback);
1776 verifyActiveNetwork(TRANSPORT_WIFI);
1780 public void testMMSonCell() throws Exception {
1781 // Test bringing up cellular without MMS
1782 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1783 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1784 mCellNetworkAgent.connect(false);
1786 verifyActiveNetwork(TRANSPORT_CELLULAR);
1787 // Register MMS NetworkRequest
1788 NetworkRequest.Builder builder = new NetworkRequest.Builder();
1789 builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
1790 final TestNetworkCallback networkCallback = new TestNetworkCallback();
1791 mCm.requestNetwork(builder.build(), networkCallback);
1792 // Test bringing up MMS cellular network
1793 MockNetworkAgent mmsNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1794 mmsNetworkAgent.addCapability(NET_CAPABILITY_MMS);
1795 mmsNetworkAgent.connectWithoutInternet();
1796 networkCallback.expectAvailableCallbacks(mmsNetworkAgent);
1797 verifyActiveNetwork(TRANSPORT_CELLULAR);
1798 // Test releasing MMS NetworkRequest does not disconnect main cellular NetworkAgent
1799 cv = mmsNetworkAgent.getDisconnectedCV();
1800 mCm.unregisterNetworkCallback(networkCallback);
1802 verifyActiveNetwork(TRANSPORT_CELLULAR);
1806 public void testCaptivePortal() {
1807 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
1808 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
1809 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
1810 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
1812 final TestNetworkCallback validatedCallback = new TestNetworkCallback();
1813 final NetworkRequest validatedRequest = new NetworkRequest.Builder()
1814 .addCapability(NET_CAPABILITY_VALIDATED).build();
1815 mCm.registerNetworkCallback(validatedRequest, validatedCallback);
1817 // Bring up a network with a captive portal.
1818 // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
1819 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1820 String firstRedirectUrl = "http://example.com/firstPath";
1821 mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl);
1822 captivePortalCallback.expectAvailableCallbacks(mWiFiNetworkAgent);
1823 assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), firstRedirectUrl);
1825 // Take down network.
1826 // Expect onLost callback.
1827 mWiFiNetworkAgent.disconnect();
1828 captivePortalCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1830 // Bring up a network with a captive portal.
1831 // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
1832 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1833 String secondRedirectUrl = "http://example.com/secondPath";
1834 mWiFiNetworkAgent.connectWithCaptivePortal(secondRedirectUrl);
1835 captivePortalCallback.expectAvailableCallbacks(mWiFiNetworkAgent);
1836 assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), secondRedirectUrl);
1838 // Make captive portal disappear then revalidate.
1839 // Expect onLost callback because network no longer provides NET_CAPABILITY_CAPTIVE_PORTAL.
1840 mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 204;
1841 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
1842 captivePortalCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1844 // Expect NET_CAPABILITY_VALIDATED onAvailable callback.
1845 validatedCallback.expectAvailableCallbacks(mWiFiNetworkAgent);
1846 // TODO: Investigate only sending available callbacks.
1847 validatedCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
1849 // Break network connectivity.
1850 // Expect NET_CAPABILITY_VALIDATED onLost callback.
1851 mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 500;
1852 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), false);
1853 validatedCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1857 public void testCaptivePortalApp() {
1858 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
1859 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
1860 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
1861 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
1863 final TestNetworkCallback validatedCallback = new TestNetworkCallback();
1864 final NetworkRequest validatedRequest = new NetworkRequest.Builder()
1865 .addCapability(NET_CAPABILITY_VALIDATED).build();
1866 mCm.registerNetworkCallback(validatedRequest, validatedCallback);
1869 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1870 mWiFiNetworkAgent.connect(true);
1871 validatedCallback.expectAvailableAndValidatedCallbacks(mWiFiNetworkAgent);
1872 Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
1874 // Check that calling startCaptivePortalApp does nothing.
1875 final int fastTimeoutMs = 100;
1876 mCm.startCaptivePortalApp(wifiNetwork);
1877 mServiceContext.expectNoStartActivityIntent(fastTimeoutMs);
1879 // Turn into a captive portal.
1880 mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 302;
1881 mCm.reportNetworkConnectivity(wifiNetwork, false);
1882 captivePortalCallback.expectAvailableCallbacks(mWiFiNetworkAgent);
1883 validatedCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1885 // Check that startCaptivePortalApp sends the expected intent.
1886 mCm.startCaptivePortalApp(wifiNetwork);
1887 Intent intent = mServiceContext.expectStartActivityIntent(TIMEOUT_MS);
1888 assertEquals(ConnectivityManager.ACTION_CAPTIVE_PORTAL_SIGN_IN, intent.getAction());
1889 assertEquals(wifiNetwork, intent.getExtra(ConnectivityManager.EXTRA_NETWORK));
1891 // Have the app report that the captive portal is dismissed, and check that we revalidate.
1892 mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 204;
1893 CaptivePortal c = (CaptivePortal) intent.getExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL);
1894 c.reportCaptivePortalDismissed();
1895 validatedCallback.expectAvailableCallbacks(mWiFiNetworkAgent);
1896 captivePortalCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1898 mCm.unregisterNetworkCallback(validatedCallback);
1899 mCm.unregisterNetworkCallback(captivePortalCallback);
1903 public void testAvoidOrIgnoreCaptivePortals() {
1904 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
1905 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
1906 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
1907 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
1909 final TestNetworkCallback validatedCallback = new TestNetworkCallback();
1910 final NetworkRequest validatedRequest = new NetworkRequest.Builder()
1911 .addCapability(NET_CAPABILITY_VALIDATED).build();
1912 mCm.registerNetworkCallback(validatedRequest, validatedCallback);
1914 setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_AVOID);
1915 // Bring up a network with a captive portal.
1916 // Expect it to fail to connect and not result in any callbacks.
1917 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1918 String firstRedirectUrl = "http://example.com/firstPath";
1920 ConditionVariable disconnectCv = mWiFiNetworkAgent.getDisconnectedCV();
1921 ConditionVariable avoidCv = mWiFiNetworkAgent.getPreventReconnectReceived();
1922 mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl);
1923 waitFor(disconnectCv);
1926 assertNoCallbacks(captivePortalCallback, validatedCallback);
1928 // Now test ignore mode.
1929 setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_IGNORE);
1931 // Bring up a network with a captive portal.
1932 // Since we're ignoring captive portals, the network will validate.
1933 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1934 String secondRedirectUrl = "http://example.com/secondPath";
1935 mWiFiNetworkAgent.connectWithCaptivePortal(secondRedirectUrl);
1937 // Expect NET_CAPABILITY_VALIDATED onAvailable callback.
1938 validatedCallback.expectAvailableCallbacks(mWiFiNetworkAgent);
1939 // But there should be no CaptivePortal callback.
1940 captivePortalCallback.assertNoCallback();
1943 private NetworkRequest.Builder newWifiRequestBuilder() {
1944 return new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI);
1948 public void testNetworkSpecifier() {
1949 NetworkRequest rEmpty1 = newWifiRequestBuilder().build();
1950 NetworkRequest rEmpty2 = newWifiRequestBuilder().setNetworkSpecifier((String) null).build();
1951 NetworkRequest rEmpty3 = newWifiRequestBuilder().setNetworkSpecifier("").build();
1952 NetworkRequest rEmpty4 = newWifiRequestBuilder().setNetworkSpecifier(
1953 (NetworkSpecifier) null).build();
1954 NetworkRequest rFoo = newWifiRequestBuilder().setNetworkSpecifier("foo").build();
1955 NetworkRequest rBar = newWifiRequestBuilder().setNetworkSpecifier(
1956 new StringNetworkSpecifier("bar")).build();
1958 TestNetworkCallback cEmpty1 = new TestNetworkCallback();
1959 TestNetworkCallback cEmpty2 = new TestNetworkCallback();
1960 TestNetworkCallback cEmpty3 = new TestNetworkCallback();
1961 TestNetworkCallback cEmpty4 = new TestNetworkCallback();
1962 TestNetworkCallback cFoo = new TestNetworkCallback();
1963 TestNetworkCallback cBar = new TestNetworkCallback();
1964 TestNetworkCallback[] emptyCallbacks = new TestNetworkCallback[] {
1965 cEmpty1, cEmpty2, cEmpty3 };
1967 mCm.registerNetworkCallback(rEmpty1, cEmpty1);
1968 mCm.registerNetworkCallback(rEmpty2, cEmpty2);
1969 mCm.registerNetworkCallback(rEmpty3, cEmpty3);
1970 mCm.registerNetworkCallback(rEmpty4, cEmpty4);
1971 mCm.registerNetworkCallback(rFoo, cFoo);
1972 mCm.registerNetworkCallback(rBar, cBar);
1974 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1975 mWiFiNetworkAgent.connect(false);
1976 cEmpty1.expectAvailableCallbacks(mWiFiNetworkAgent);
1977 cEmpty2.expectAvailableCallbacks(mWiFiNetworkAgent);
1978 cEmpty3.expectAvailableCallbacks(mWiFiNetworkAgent);
1979 cEmpty4.expectAvailableCallbacks(mWiFiNetworkAgent);
1980 assertNoCallbacks(cFoo, cBar);
1982 mWiFiNetworkAgent.setNetworkSpecifier(new StringNetworkSpecifier("foo"));
1983 cFoo.expectAvailableCallbacks(mWiFiNetworkAgent);
1984 for (TestNetworkCallback c: emptyCallbacks) {
1985 c.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent);
1987 cFoo.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent);
1988 cFoo.assertNoCallback();
1990 mWiFiNetworkAgent.setNetworkSpecifier(new StringNetworkSpecifier("bar"));
1991 cFoo.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1992 cBar.expectAvailableCallbacks(mWiFiNetworkAgent);
1993 for (TestNetworkCallback c: emptyCallbacks) {
1994 c.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent);
1996 cBar.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent);
1997 cBar.assertNoCallback();
1999 mWiFiNetworkAgent.setNetworkSpecifier(null);
2000 cBar.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2001 for (TestNetworkCallback c: emptyCallbacks) {
2002 c.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent);
2005 assertNoCallbacks(cEmpty1, cEmpty2, cEmpty3, cFoo, cBar);
2009 public void testInvalidNetworkSpecifier() {
2011 NetworkRequest.Builder builder = new NetworkRequest.Builder();
2012 builder.setNetworkSpecifier(new MatchAllNetworkSpecifier());
2013 fail("NetworkRequest builder with MatchAllNetworkSpecifier");
2014 } catch (IllegalArgumentException expected) {
2019 NetworkCapabilities networkCapabilities = new NetworkCapabilities();
2020 networkCapabilities.addTransportType(TRANSPORT_WIFI)
2021 .setNetworkSpecifier(new MatchAllNetworkSpecifier());
2022 mService.requestNetwork(networkCapabilities, null, 0, null,
2023 ConnectivityManager.TYPE_WIFI);
2024 fail("ConnectivityService requestNetwork with MatchAllNetworkSpecifier");
2025 } catch (IllegalArgumentException expected) {
2029 class NonParcelableSpecifier extends NetworkSpecifier {
2030 public boolean satisfiedBy(NetworkSpecifier other) { return false; }
2032 class ParcelableSpecifier extends NonParcelableSpecifier implements Parcelable {
2033 @Override public int describeContents() { return 0; }
2034 @Override public void writeToParcel(Parcel p, int flags) {}
2036 NetworkRequest.Builder builder;
2038 builder = new NetworkRequest.Builder().addTransportType(TRANSPORT_ETHERNET);
2040 builder.setNetworkSpecifier(new NonParcelableSpecifier());
2041 Parcel parcelW = Parcel.obtain();
2042 builder.build().writeToParcel(parcelW, 0);
2043 fail("Parceling a non-parcelable specifier did not throw an exception");
2044 } catch (Exception e) {
2048 builder = new NetworkRequest.Builder().addTransportType(TRANSPORT_ETHERNET);
2049 builder.setNetworkSpecifier(new ParcelableSpecifier());
2050 NetworkRequest nr = builder.build();
2054 Parcel parcelW = Parcel.obtain();
2055 nr.writeToParcel(parcelW, 0);
2056 byte[] bytes = parcelW.marshall();
2059 Parcel parcelR = Parcel.obtain();
2060 parcelR.unmarshall(bytes, 0, bytes.length);
2061 parcelR.setDataPosition(0);
2062 NetworkRequest rereadNr = NetworkRequest.CREATOR.createFromParcel(parcelR);
2063 fail("Unparceling a non-framework NetworkSpecifier did not throw an exception");
2064 } catch (Exception e) {
2070 public void testRegisterDefaultNetworkCallback() throws Exception {
2071 final TestNetworkCallback defaultNetworkCallback = new TestNetworkCallback();
2072 mCm.registerDefaultNetworkCallback(defaultNetworkCallback);
2073 defaultNetworkCallback.assertNoCallback();
2075 // Create a TRANSPORT_CELLULAR request to keep the mobile interface up
2076 // whenever Wi-Fi is up. Without this, the mobile network agent is
2077 // reaped before any other activity can take place.
2078 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
2079 final NetworkRequest cellRequest = new NetworkRequest.Builder()
2080 .addTransportType(TRANSPORT_CELLULAR).build();
2081 mCm.requestNetwork(cellRequest, cellNetworkCallback);
2082 cellNetworkCallback.assertNoCallback();
2084 // Bring up cell and expect CALLBACK_AVAILABLE.
2085 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2086 mCellNetworkAgent.connect(true);
2087 cellNetworkCallback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent);
2088 defaultNetworkCallback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent);
2090 // Bring up wifi and expect CALLBACK_AVAILABLE.
2091 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2092 mWiFiNetworkAgent.connect(true);
2093 cellNetworkCallback.assertNoCallback();
2094 defaultNetworkCallback.expectAvailableAndValidatedCallbacks(mWiFiNetworkAgent);
2096 // Bring down cell. Expect no default network callback, since it wasn't the default.
2097 mCellNetworkAgent.disconnect();
2098 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
2099 defaultNetworkCallback.assertNoCallback();
2101 // Bring up cell. Expect no default network callback, since it won't be the default.
2102 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2103 mCellNetworkAgent.connect(true);
2104 cellNetworkCallback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent);
2105 defaultNetworkCallback.assertNoCallback();
2107 // Bring down wifi. Expect the default network callback to notified of LOST wifi
2108 // followed by AVAILABLE cell.
2109 mWiFiNetworkAgent.disconnect();
2110 cellNetworkCallback.assertNoCallback();
2111 defaultNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2112 defaultNetworkCallback.expectAvailableCallbacks(mCellNetworkAgent);
2113 mCellNetworkAgent.disconnect();
2114 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
2115 defaultNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
2119 public void testAdditionalStateCallbacks() throws Exception {
2120 // File a network request for mobile.
2121 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
2122 final NetworkRequest cellRequest = new NetworkRequest.Builder()
2123 .addTransportType(TRANSPORT_CELLULAR).build();
2124 mCm.requestNetwork(cellRequest, cellNetworkCallback);
2126 // Bring up the mobile network.
2127 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2128 mCellNetworkAgent.connect(true);
2130 // We should get onAvailable(), onCapabilitiesChanged(), and
2131 // onLinkPropertiesChanged() in rapid succession. Additionally, we
2132 // should get onCapabilitiesChanged() when the mobile network validates.
2133 cellNetworkCallback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent);
2134 cellNetworkCallback.assertNoCallback();
2136 // Update LinkProperties.
2137 final LinkProperties lp = new LinkProperties();
2138 lp.setInterfaceName("foonet_data0");
2139 mCellNetworkAgent.sendLinkProperties(lp);
2140 // We should get onLinkPropertiesChanged().
2141 cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
2142 cellNetworkCallback.assertNoCallback();
2144 // Suspend the network.
2145 mCellNetworkAgent.suspend();
2146 cellNetworkCallback.expectCallback(CallbackState.SUSPENDED, mCellNetworkAgent);
2147 cellNetworkCallback.assertNoCallback();
2149 // Register a garden variety default network request.
2150 final TestNetworkCallback dfltNetworkCallback = new TestNetworkCallback();
2151 mCm.registerDefaultNetworkCallback(dfltNetworkCallback);
2152 // We should get onAvailable(), onCapabilitiesChanged(), onLinkPropertiesChanged(),
2153 // as well as onNetworkSuspended() in rapid succession.
2154 dfltNetworkCallback.expectAvailableAndSuspendedCallbacks(mCellNetworkAgent);
2155 dfltNetworkCallback.assertNoCallback();
2157 mCm.unregisterNetworkCallback(dfltNetworkCallback);
2158 mCm.unregisterNetworkCallback(cellNetworkCallback);
2161 private void setCaptivePortalMode(int mode) {
2162 ContentResolver cr = mServiceContext.getContentResolver();
2163 Settings.Global.putInt(cr, Settings.Global.CAPTIVE_PORTAL_MODE, mode);
2166 private void setMobileDataAlwaysOn(boolean enable) {
2167 ContentResolver cr = mServiceContext.getContentResolver();
2168 Settings.Global.putInt(cr, Settings.Global.MOBILE_DATA_ALWAYS_ON, enable ? 1 : 0);
2169 mService.updateMobileDataAlwaysOn();
2170 mService.waitForIdle();
2173 private boolean isForegroundNetwork(MockNetworkAgent network) {
2174 NetworkCapabilities nc = mCm.getNetworkCapabilities(network.getNetwork());
2176 return nc.hasCapability(NET_CAPABILITY_FOREGROUND);
2180 public void testBackgroundNetworks() throws Exception {
2181 // Create a background request. We can't do this ourselves because ConnectivityService
2182 // doesn't have an API for it. So just turn on mobile data always on.
2183 setMobileDataAlwaysOn(true);
2184 final NetworkRequest request = new NetworkRequest.Builder().build();
2185 final NetworkRequest fgRequest = new NetworkRequest.Builder()
2186 .addCapability(NET_CAPABILITY_FOREGROUND).build();
2187 final TestNetworkCallback callback = new TestNetworkCallback();
2188 final TestNetworkCallback fgCallback = new TestNetworkCallback();
2189 mCm.registerNetworkCallback(request, callback);
2190 mCm.registerNetworkCallback(fgRequest, fgCallback);
2192 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2193 mCellNetworkAgent.connect(true);
2194 callback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent);
2195 fgCallback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent);
2196 assertTrue(isForegroundNetwork(mCellNetworkAgent));
2198 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2199 mWiFiNetworkAgent.connect(true);
2201 // When wifi connects, cell lingers.
2202 callback.expectAvailableCallbacks(mWiFiNetworkAgent);
2203 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
2204 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
2205 fgCallback.expectAvailableCallbacks(mWiFiNetworkAgent);
2206 fgCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
2207 fgCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
2208 assertTrue(isForegroundNetwork(mCellNetworkAgent));
2209 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
2211 // When lingering is complete, cell is still there but is now in the background.
2212 mService.waitForIdle();
2213 int timeoutMs = TEST_LINGER_DELAY_MS + TEST_LINGER_DELAY_MS / 4;
2214 fgCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent, timeoutMs);
2215 // Expect a network capabilities update sans FOREGROUND.
2216 callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
2217 assertFalse(isForegroundNetwork(mCellNetworkAgent));
2218 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
2220 // File a cell request and check that cell comes into the foreground.
2221 final NetworkRequest cellRequest = new NetworkRequest.Builder()
2222 .addTransportType(TRANSPORT_CELLULAR).build();
2223 final TestNetworkCallback cellCallback = new TestNetworkCallback();
2224 mCm.requestNetwork(cellRequest, cellCallback);
2225 // NOTE: This request causes the network's capabilities to change. This
2226 // is currently delivered before the onAvailable() callbacks.
2228 cellCallback.expectCapabilitiesWith(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
2229 cellCallback.expectAvailableCallbacks(mCellNetworkAgent);
2230 fgCallback.expectAvailableCallbacks(mCellNetworkAgent);
2231 // Expect a network capabilities update with FOREGROUND, because the most recent
2232 // request causes its state to change.
2233 callback.expectCapabilitiesWith(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
2234 assertTrue(isForegroundNetwork(mCellNetworkAgent));
2235 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
2237 // Release the request. The network immediately goes into the background, since it was not
2239 mCm.unregisterNetworkCallback(cellCallback);
2240 fgCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
2241 // Expect a network capabilities update sans FOREGROUND.
2242 callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
2243 assertFalse(isForegroundNetwork(mCellNetworkAgent));
2244 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
2246 // Disconnect wifi and check that cell is foreground again.
2247 mWiFiNetworkAgent.disconnect();
2248 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2249 fgCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2250 fgCallback.expectAvailableCallbacks(mCellNetworkAgent);
2251 assertTrue(isForegroundNetwork(mCellNetworkAgent));
2253 mCm.unregisterNetworkCallback(callback);
2254 mCm.unregisterNetworkCallback(fgCallback);
2258 public void testRequestBenchmark() throws Exception {
2259 // TODO: turn this unit test into a real benchmarking test.
2260 // Benchmarks connecting and switching performance in the presence of a large number of
2262 // 1. File NUM_REQUESTS requests.
2263 // 2. Have a network connect. Wait for NUM_REQUESTS onAvailable callbacks to fire.
2264 // 3. Have a new network connect and outscore the previous. Wait for NUM_REQUESTS onLosing
2265 // and NUM_REQUESTS onAvailable callbacks to fire.
2266 // See how long it took.
2267 final int NUM_REQUESTS = 90;
2268 final NetworkRequest request = new NetworkRequest.Builder().clearCapabilities().build();
2269 final NetworkCallback[] callbacks = new NetworkCallback[NUM_REQUESTS];
2270 final CountDownLatch availableLatch = new CountDownLatch(NUM_REQUESTS);
2271 final CountDownLatch losingLatch = new CountDownLatch(NUM_REQUESTS);
2273 for (int i = 0; i < NUM_REQUESTS; i++) {
2274 callbacks[i] = new NetworkCallback() {
2275 @Override public void onAvailable(Network n) { availableLatch.countDown(); }
2276 @Override public void onLosing(Network n, int t) { losingLatch.countDown(); }
2280 final int REGISTER_TIME_LIMIT_MS = 180;
2281 assertTimeLimit("Registering callbacks", REGISTER_TIME_LIMIT_MS, () -> {
2282 for (NetworkCallback cb : callbacks) {
2283 mCm.registerNetworkCallback(request, cb);
2287 final int CONNECT_TIME_LIMIT_MS = 40;
2288 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2289 // Don't request that the network validate, because otherwise connect() will block until
2290 // the network gets NET_CAPABILITY_VALIDATED, after all the callbacks below have fired,
2291 // and we won't actually measure anything.
2292 mCellNetworkAgent.connect(false);
2294 long onAvailableDispatchingDuration = durationOf(() -> {
2295 if (!awaitLatch(availableLatch, CONNECT_TIME_LIMIT_MS)) {
2296 fail(String.format("Only dispatched %d/%d onAvailable callbacks in %dms",
2297 NUM_REQUESTS - availableLatch.getCount(), NUM_REQUESTS,
2298 CONNECT_TIME_LIMIT_MS));
2301 Log.d(TAG, String.format("Connect, %d callbacks: %dms, acceptable %dms",
2302 NUM_REQUESTS, onAvailableDispatchingDuration, CONNECT_TIME_LIMIT_MS));
2304 final int SWITCH_TIME_LIMIT_MS = 40;
2305 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2306 // Give wifi a high enough score that we'll linger cell when wifi comes up.
2307 mWiFiNetworkAgent.adjustScore(40);
2308 mWiFiNetworkAgent.connect(false);
2310 long onLostDispatchingDuration = durationOf(() -> {
2311 if (!awaitLatch(losingLatch, SWITCH_TIME_LIMIT_MS)) {
2312 fail(String.format("Only dispatched %d/%d onLosing callbacks in %dms",
2313 NUM_REQUESTS - losingLatch.getCount(), NUM_REQUESTS, SWITCH_TIME_LIMIT_MS));
2316 Log.d(TAG, String.format("Linger, %d callbacks: %dms, acceptable %dms",
2317 NUM_REQUESTS, onLostDispatchingDuration, SWITCH_TIME_LIMIT_MS));
2319 final int UNREGISTER_TIME_LIMIT_MS = 10;
2320 assertTimeLimit("Unregistering callbacks", UNREGISTER_TIME_LIMIT_MS, () -> {
2321 for (NetworkCallback cb : callbacks) {
2322 mCm.unregisterNetworkCallback(cb);
2327 private long durationOf(Runnable fn) {
2328 long startTime = SystemClock.elapsedRealtime();
2330 return SystemClock.elapsedRealtime() - startTime;
2333 private void assertTimeLimit(String descr, long timeLimit, Runnable fn) {
2334 long timeTaken = durationOf(fn);
2335 String msg = String.format("%s: took %dms, limit was %dms", descr, timeTaken, timeLimit);
2337 assertTrue(msg, timeTaken <= timeLimit);
2340 private boolean awaitLatch(CountDownLatch l, long timeoutMs) {
2342 if (l.await(timeoutMs, TimeUnit.MILLISECONDS)) {
2345 } catch (InterruptedException e) {}
2350 public void testMobileDataAlwaysOn() throws Exception {
2351 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
2352 final NetworkRequest cellRequest = new NetworkRequest.Builder()
2353 .addTransportType(TRANSPORT_CELLULAR).build();
2354 mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
2356 final HandlerThread handlerThread = new HandlerThread("MobileDataAlwaysOnFactory");
2357 handlerThread.start();
2358 NetworkCapabilities filter = new NetworkCapabilities()
2359 .addTransportType(TRANSPORT_CELLULAR)
2360 .addCapability(NET_CAPABILITY_INTERNET);
2361 final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
2362 mServiceContext, "testFactory", filter);
2363 testFactory.setScoreFilter(40);
2365 // Register the factory and expect it to start looking for a network.
2366 testFactory.expectAddRequests(1);
2367 testFactory.register();
2368 testFactory.waitForNetworkRequests(1);
2369 assertTrue(testFactory.getMyStartRequested());
2371 // Bring up wifi. The factory stops looking for a network.
2372 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2373 testFactory.expectAddRequests(2); // Because the default request changes score twice.
2374 mWiFiNetworkAgent.connect(true);
2375 testFactory.waitForNetworkRequests(1);
2376 assertFalse(testFactory.getMyStartRequested());
2378 ContentResolver cr = mServiceContext.getContentResolver();
2380 // Turn on mobile data always on. The factory starts looking again.
2381 testFactory.expectAddRequests(1);
2382 setMobileDataAlwaysOn(true);
2383 testFactory.waitForNetworkRequests(2);
2384 assertTrue(testFactory.getMyStartRequested());
2386 // Bring up cell data and check that the factory stops looking.
2387 assertEquals(1, mCm.getAllNetworks().length);
2388 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2389 testFactory.expectAddRequests(2); // Because the cell request changes score twice.
2390 mCellNetworkAgent.connect(true);
2391 cellNetworkCallback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent);
2392 testFactory.waitForNetworkRequests(2);
2393 assertFalse(testFactory.getMyStartRequested()); // Because the cell network outscores us.
2395 // Check that cell data stays up.
2396 mService.waitForIdle();
2397 verifyActiveNetwork(TRANSPORT_WIFI);
2398 assertEquals(2, mCm.getAllNetworks().length);
2400 // Turn off mobile data always on and expect the request to disappear...
2401 testFactory.expectRemoveRequests(1);
2402 setMobileDataAlwaysOn(false);
2403 testFactory.waitForNetworkRequests(1);
2405 // ... and cell data to be torn down.
2406 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
2407 assertEquals(1, mCm.getAllNetworks().length);
2409 testFactory.unregister();
2410 mCm.unregisterNetworkCallback(cellNetworkCallback);
2411 handlerThread.quit();
2415 public void testAvoidBadWifiSetting() throws Exception {
2416 final ContentResolver cr = mServiceContext.getContentResolver();
2417 final WrappedMultinetworkPolicyTracker tracker = mService.getMultinetworkPolicyTracker();
2418 final String settingName = Settings.Global.NETWORK_AVOID_BAD_WIFI;
2420 tracker.configRestrictsAvoidBadWifi = false;
2421 String[] values = new String[] {null, "0", "1"};
2422 for (int i = 0; i < values.length; i++) {
2423 Settings.Global.putInt(cr, settingName, 1);
2424 tracker.reevaluate();
2425 mService.waitForIdle();
2426 String msg = String.format("config=false, setting=%s", values[i]);
2427 assertTrue(mService.avoidBadWifi());
2428 assertFalse(msg, tracker.shouldNotifyWifiUnvalidated());
2431 tracker.configRestrictsAvoidBadWifi = true;
2433 Settings.Global.putInt(cr, settingName, 0);
2434 tracker.reevaluate();
2435 mService.waitForIdle();
2436 assertFalse(mService.avoidBadWifi());
2437 assertFalse(tracker.shouldNotifyWifiUnvalidated());
2439 Settings.Global.putInt(cr, settingName, 1);
2440 tracker.reevaluate();
2441 mService.waitForIdle();
2442 assertTrue(mService.avoidBadWifi());
2443 assertFalse(tracker.shouldNotifyWifiUnvalidated());
2445 Settings.Global.putString(cr, settingName, null);
2446 tracker.reevaluate();
2447 mService.waitForIdle();
2448 assertFalse(mService.avoidBadWifi());
2449 assertTrue(tracker.shouldNotifyWifiUnvalidated());
2453 public void testAvoidBadWifi() throws Exception {
2454 final ContentResolver cr = mServiceContext.getContentResolver();
2455 final WrappedMultinetworkPolicyTracker tracker = mService.getMultinetworkPolicyTracker();
2457 // Pretend we're on a carrier that restricts switching away from bad wifi.
2458 tracker.configRestrictsAvoidBadWifi = true;
2460 // File a request for cell to ensure it doesn't go down.
2461 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
2462 final NetworkRequest cellRequest = new NetworkRequest.Builder()
2463 .addTransportType(TRANSPORT_CELLULAR).build();
2464 mCm.requestNetwork(cellRequest, cellNetworkCallback);
2466 TestNetworkCallback defaultCallback = new TestNetworkCallback();
2467 mCm.registerDefaultNetworkCallback(defaultCallback);
2469 NetworkRequest validatedWifiRequest = new NetworkRequest.Builder()
2470 .addTransportType(TRANSPORT_WIFI)
2471 .addCapability(NET_CAPABILITY_VALIDATED)
2473 TestNetworkCallback validatedWifiCallback = new TestNetworkCallback();
2474 mCm.registerNetworkCallback(validatedWifiRequest, validatedWifiCallback);
2476 Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 0);
2477 tracker.reevaluate();
2479 // Bring up validated cell.
2480 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2481 mCellNetworkAgent.connect(true);
2482 cellNetworkCallback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent);
2483 defaultCallback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent);
2484 Network cellNetwork = mCellNetworkAgent.getNetwork();
2486 // Bring up validated wifi.
2487 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2488 mWiFiNetworkAgent.connect(true);
2489 defaultCallback.expectAvailableAndValidatedCallbacks(mWiFiNetworkAgent);
2490 validatedWifiCallback.expectAvailableCallbacks(mWiFiNetworkAgent);
2491 validatedWifiCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
2492 Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
2494 // Fail validation on wifi.
2495 mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 599;
2496 mCm.reportNetworkConnectivity(wifiNetwork, false);
2497 defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
2498 validatedWifiCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2500 // Because avoid bad wifi is off, we don't switch to cellular.
2501 defaultCallback.assertNoCallback();
2502 assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
2503 NET_CAPABILITY_VALIDATED));
2504 assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
2505 NET_CAPABILITY_VALIDATED));
2506 assertEquals(mCm.getActiveNetwork(), wifiNetwork);
2508 // Simulate switching to a carrier that does not restrict avoiding bad wifi, and expect
2509 // that we switch back to cell.
2510 tracker.configRestrictsAvoidBadWifi = false;
2511 tracker.reevaluate();
2512 defaultCallback.expectAvailableCallbacks(mCellNetworkAgent);
2513 assertEquals(mCm.getActiveNetwork(), cellNetwork);
2515 // Switch back to a restrictive carrier.
2516 tracker.configRestrictsAvoidBadWifi = true;
2517 tracker.reevaluate();
2518 defaultCallback.expectAvailableCallbacks(mWiFiNetworkAgent);
2519 assertEquals(mCm.getActiveNetwork(), wifiNetwork);
2521 // Simulate the user selecting "switch" on the dialog, and check that we switch to cell.
2522 mCm.setAvoidUnvalidated(wifiNetwork);
2523 defaultCallback.expectAvailableCallbacks(mCellNetworkAgent);
2524 assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
2525 NET_CAPABILITY_VALIDATED));
2526 assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
2527 NET_CAPABILITY_VALIDATED));
2528 assertEquals(mCm.getActiveNetwork(), cellNetwork);
2530 // Disconnect and reconnect wifi to clear the one-time switch above.
2531 mWiFiNetworkAgent.disconnect();
2532 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2533 mWiFiNetworkAgent.connect(true);
2534 defaultCallback.expectAvailableAndValidatedCallbacks(mWiFiNetworkAgent);
2535 validatedWifiCallback.expectAvailableCallbacks(mWiFiNetworkAgent);
2536 validatedWifiCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
2537 wifiNetwork = mWiFiNetworkAgent.getNetwork();
2539 // Fail validation on wifi and expect the dialog to appear.
2540 mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 599;
2541 mCm.reportNetworkConnectivity(wifiNetwork, false);
2542 defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
2543 validatedWifiCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2545 // Simulate the user selecting "switch" and checking the don't ask again checkbox.
2546 Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 1);
2547 tracker.reevaluate();
2549 // We now switch to cell.
2550 defaultCallback.expectAvailableCallbacks(mCellNetworkAgent);
2551 assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
2552 NET_CAPABILITY_VALIDATED));
2553 assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
2554 NET_CAPABILITY_VALIDATED));
2555 assertEquals(mCm.getActiveNetwork(), cellNetwork);
2557 // Simulate the user turning the cellular fallback setting off and then on.
2558 // We switch to wifi and then to cell.
2559 Settings.Global.putString(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, null);
2560 tracker.reevaluate();
2561 defaultCallback.expectAvailableCallbacks(mWiFiNetworkAgent);
2562 assertEquals(mCm.getActiveNetwork(), wifiNetwork);
2563 Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 1);
2564 tracker.reevaluate();
2565 defaultCallback.expectAvailableCallbacks(mCellNetworkAgent);
2566 assertEquals(mCm.getActiveNetwork(), cellNetwork);
2568 // If cell goes down, we switch to wifi.
2569 mCellNetworkAgent.disconnect();
2570 defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
2571 defaultCallback.expectAvailableCallbacks(mWiFiNetworkAgent);
2572 validatedWifiCallback.assertNoCallback();
2574 mCm.unregisterNetworkCallback(cellNetworkCallback);
2575 mCm.unregisterNetworkCallback(validatedWifiCallback);
2576 mCm.unregisterNetworkCallback(defaultCallback);
2580 public void testMeteredMultipathPreferenceSetting() throws Exception {
2581 final ContentResolver cr = mServiceContext.getContentResolver();
2582 final WrappedMultinetworkPolicyTracker tracker = mService.getMultinetworkPolicyTracker();
2583 final String settingName = Settings.Global.NETWORK_METERED_MULTIPATH_PREFERENCE;
2585 for (int config : Arrays.asList(0, 3, 2)) {
2586 for (String setting: Arrays.asList(null, "0", "2", "1")) {
2587 tracker.configMeteredMultipathPreference = config;
2588 Settings.Global.putString(cr, settingName, setting);
2589 tracker.reevaluate();
2590 mService.waitForIdle();
2592 final int expected = (setting != null) ? Integer.parseInt(setting) : config;
2593 String msg = String.format("config=%d, setting=%s", config, setting);
2594 assertEquals(msg, expected, mCm.getMultipathPreference(null));
2600 * Validate that a satisfied network request does not trigger onUnavailable() once the
2601 * time-out period expires.
2604 public void testSatisfiedNetworkRequestDoesNotTriggerOnUnavailable() {
2605 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
2606 NetworkCapabilities.TRANSPORT_WIFI).build();
2607 final TestNetworkCallback networkCallback = new TestNetworkCallback();
2608 final int timeoutMs = 150;
2609 mCm.requestNetwork(nr, networkCallback, timeoutMs);
2611 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2612 mWiFiNetworkAgent.connect(false);
2613 networkCallback.expectAvailableCallbacks(mWiFiNetworkAgent, false, timeoutMs);
2615 // pass timeout and validate that UNAVAILABLE is not called
2616 networkCallback.assertNoCallback();
2620 * Validate that a satisfied network request followed by a disconnected (lost) network does
2621 * not trigger onUnavailable() once the time-out period expires.
2624 public void testSatisfiedThenLostNetworkRequestDoesNotTriggerOnUnavailable() {
2625 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
2626 NetworkCapabilities.TRANSPORT_WIFI).build();
2627 final TestNetworkCallback networkCallback = new TestNetworkCallback();
2628 final int requestTimeoutMs = 100;
2629 mCm.requestNetwork(nr, networkCallback, requestTimeoutMs);
2631 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2632 mWiFiNetworkAgent.connect(false);
2633 final int assertTimeoutMs = 150;
2634 networkCallback.expectAvailableCallbacks(mWiFiNetworkAgent, false, assertTimeoutMs);
2636 mWiFiNetworkAgent.disconnect();
2637 networkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2639 // pass timeout and validate that UNAVAILABLE is not called
2641 networkCallback.assertNoCallback();
2645 * Validate that when a time-out is specified for a network request the onUnavailable()
2646 * callback is called when time-out expires. Then validate that if network request is
2647 * (somehow) satisfied - the callback isn't called later.
2650 public void testTimedoutNetworkRequest() {
2651 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
2652 NetworkCapabilities.TRANSPORT_WIFI).build();
2653 final TestNetworkCallback networkCallback = new TestNetworkCallback();
2654 final int timeoutMs = 10;
2655 mCm.requestNetwork(nr, networkCallback, timeoutMs);
2657 // pass timeout and validate that UNAVAILABLE is called
2658 networkCallback.expectCallback(CallbackState.UNAVAILABLE, null);
2660 // create a network satisfying request - validate that request not triggered
2661 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2662 mWiFiNetworkAgent.connect(false);
2663 networkCallback.assertNoCallback();
2667 * Validate that when a network request is unregistered (cancelled) the time-out for that
2668 * request doesn't trigger the onUnavailable() callback.
2671 public void testTimedoutAfterUnregisteredNetworkRequest() {
2672 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
2673 NetworkCapabilities.TRANSPORT_WIFI).build();
2674 final TestNetworkCallback networkCallback = new TestNetworkCallback();
2675 final int timeoutMs = 10;
2676 mCm.requestNetwork(nr, networkCallback, timeoutMs);
2679 mCm.unregisterNetworkCallback(networkCallback);
2681 // pass timeout and validate that no callbacks
2682 // Note: doesn't validate that nothing called from CS since even if called the CM already
2683 // unregisters the callback and won't pass it through!
2685 networkCallback.assertNoCallback();
2687 // create a network satisfying request - validate that request not triggered
2688 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2689 mWiFiNetworkAgent.connect(false);
2690 networkCallback.assertNoCallback();
2693 private static class TestKeepaliveCallback extends PacketKeepaliveCallback {
2695 public static enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR };
2697 private class CallbackValue {
2698 public CallbackType callbackType;
2701 public CallbackValue(CallbackType type) {
2702 this.callbackType = type;
2703 this.error = PacketKeepalive.SUCCESS;
2704 assertTrue("onError callback must have error", type != CallbackType.ON_ERROR);
2707 public CallbackValue(CallbackType type, int error) {
2708 this.callbackType = type;
2710 assertEquals("error can only be set for onError", type, CallbackType.ON_ERROR);
2714 public boolean equals(Object o) {
2715 return o instanceof CallbackValue &&
2716 this.callbackType == ((CallbackValue) o).callbackType &&
2717 this.error == ((CallbackValue) o).error;
2721 public String toString() {
2722 return String.format("%s(%s, %d)", getClass().getSimpleName(), callbackType, error);
2726 private LinkedBlockingQueue<CallbackValue> mCallbacks = new LinkedBlockingQueue<>();
2729 public void onStarted() {
2730 mCallbacks.add(new CallbackValue(CallbackType.ON_STARTED));
2734 public void onStopped() {
2735 mCallbacks.add(new CallbackValue(CallbackType.ON_STOPPED));
2739 public void onError(int error) {
2740 mCallbacks.add(new CallbackValue(CallbackType.ON_ERROR, error));
2743 private void expectCallback(CallbackValue callbackValue) {
2747 mCallbacks.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
2748 } catch (InterruptedException e) {
2749 fail(callbackValue.callbackType + " callback not seen after " + TIMEOUT_MS + " ms");
2753 public void expectStarted() {
2754 expectCallback(new CallbackValue(CallbackType.ON_STARTED));
2757 public void expectStopped() {
2758 expectCallback(new CallbackValue(CallbackType.ON_STOPPED));
2761 public void expectError(int error) {
2762 expectCallback(new CallbackValue(CallbackType.ON_ERROR, error));
2766 private Network connectKeepaliveNetwork(LinkProperties lp) {
2767 // Ensure the network is disconnected before we do anything.
2768 if (mWiFiNetworkAgent != null) {
2769 assertNull(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()));
2772 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2773 ConditionVariable cv = waitForConnectivityBroadcasts(1);
2774 mWiFiNetworkAgent.connect(true);
2776 verifyActiveNetwork(TRANSPORT_WIFI);
2777 mWiFiNetworkAgent.sendLinkProperties(lp);
2778 mService.waitForIdle();
2779 return mWiFiNetworkAgent.getNetwork();
2783 public void testPacketKeepalives() throws Exception {
2784 InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
2785 InetAddress notMyIPv4 = InetAddress.getByName("192.0.2.35");
2786 InetAddress myIPv6 = InetAddress.getByName("2001:db8::1");
2787 InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8");
2788 InetAddress dstIPv6 = InetAddress.getByName("2001:4860:4860::8888");
2790 LinkProperties lp = new LinkProperties();
2791 lp.setInterfaceName("wlan12");
2792 lp.addLinkAddress(new LinkAddress(myIPv6, 64));
2793 lp.addLinkAddress(new LinkAddress(myIPv4, 25));
2794 lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
2795 lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
2797 Network notMyNet = new Network(61234);
2798 Network myNet = connectKeepaliveNetwork(lp);
2800 TestKeepaliveCallback callback = new TestKeepaliveCallback();
2803 // Attempt to start keepalives with invalid parameters and check for errors.
2804 ka = mCm.startNattKeepalive(notMyNet, 25, callback, myIPv4, 1234, dstIPv4);
2805 callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK);
2807 ka = mCm.startNattKeepalive(myNet, 19, callback, notMyIPv4, 1234, dstIPv4);
2808 callback.expectError(PacketKeepalive.ERROR_INVALID_INTERVAL);
2810 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 1234, dstIPv6);
2811 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
2813 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv6, 1234, dstIPv4);
2814 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
2816 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv6, 1234, dstIPv6);
2817 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS); // NAT-T is IPv4-only.
2819 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 123456, dstIPv4);
2820 callback.expectError(PacketKeepalive.ERROR_INVALID_PORT);
2822 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 123456, dstIPv4);
2823 callback.expectError(PacketKeepalive.ERROR_INVALID_PORT);
2825 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
2826 callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
2828 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
2829 callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
2831 // Check that a started keepalive can be stopped.
2832 mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS);
2833 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
2834 callback.expectStarted();
2835 mWiFiNetworkAgent.setStopKeepaliveError(PacketKeepalive.SUCCESS);
2837 callback.expectStopped();
2839 // Check that deleting the IP address stops the keepalive.
2840 LinkProperties bogusLp = new LinkProperties(lp);
2841 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
2842 callback.expectStarted();
2843 bogusLp.removeLinkAddress(new LinkAddress(myIPv4, 25));
2844 bogusLp.addLinkAddress(new LinkAddress(notMyIPv4, 25));
2845 mWiFiNetworkAgent.sendLinkProperties(bogusLp);
2846 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
2847 mWiFiNetworkAgent.sendLinkProperties(lp);
2849 // Check that a started keepalive is stopped correctly when the network disconnects.
2850 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
2851 callback.expectStarted();
2852 mWiFiNetworkAgent.disconnect();
2853 waitFor(mWiFiNetworkAgent.getDisconnectedCV());
2854 callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK);
2856 // ... and that stopping it after that has no adverse effects.
2857 mService.waitForIdle();
2858 final Network myNetAlias = myNet;
2859 assertNull(mCm.getNetworkCapabilities(myNetAlias));
2863 myNet = connectKeepaliveNetwork(lp);
2864 mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS);
2866 // Check things work as expected when the keepalive is stopped and the network disconnects.
2867 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
2868 callback.expectStarted();
2870 mWiFiNetworkAgent.disconnect();
2871 waitFor(mWiFiNetworkAgent.getDisconnectedCV());
2872 mService.waitForIdle();
2873 callback.expectStopped();
2876 myNet = connectKeepaliveNetwork(lp);
2877 mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS);
2879 // Check that keepalive slots start from 1 and increment. The first one gets slot 1.
2880 mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
2881 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
2882 callback.expectStarted();
2884 // The second one gets slot 2.
2885 mWiFiNetworkAgent.setExpectedKeepaliveSlot(2);
2886 TestKeepaliveCallback callback2 = new TestKeepaliveCallback();
2887 PacketKeepalive ka2 = mCm.startNattKeepalive(myNet, 25, callback2, myIPv4, 6789, dstIPv4);
2888 callback2.expectStarted();
2890 // Now stop the first one and create a third. This also gets slot 1.
2892 callback.expectStopped();
2894 mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
2895 TestKeepaliveCallback callback3 = new TestKeepaliveCallback();
2896 PacketKeepalive ka3 = mCm.startNattKeepalive(myNet, 25, callback3, myIPv4, 9876, dstIPv4);
2897 callback3.expectStarted();
2900 callback2.expectStopped();
2903 callback3.expectStopped();
2907 public void testGetCaptivePortalServerUrl() throws Exception {
2908 String url = mCm.getCaptivePortalServerUrl();
2909 assertEquals("http://connectivitycheck.gstatic.com/generate_204", url);
2912 private static class TestNetworkPinner extends NetworkPinner {
2913 public static boolean awaitPin(int timeoutMs) {
2914 synchronized(sLock) {
2915 if (sNetwork == null) {
2917 sLock.wait(timeoutMs);
2918 } catch (InterruptedException e) {}
2920 return sNetwork != null;
2924 public static boolean awaitUnpin(int timeoutMs) {
2925 synchronized(sLock) {
2926 if (sNetwork != null) {
2928 sLock.wait(timeoutMs);
2929 } catch (InterruptedException e) {}
2931 return sNetwork == null;
2936 private void assertPinnedToWifiWithCellDefault() {
2937 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess());
2938 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2941 private void assertPinnedToWifiWithWifiDefault() {
2942 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess());
2943 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2946 private void assertNotPinnedToWifi() {
2947 assertNull(mCm.getBoundNetworkForProcess());
2948 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2952 public void testNetworkPinner() {
2953 NetworkRequest wifiRequest = new NetworkRequest.Builder()
2954 .addTransportType(TRANSPORT_WIFI)
2956 assertNull(mCm.getBoundNetworkForProcess());
2958 TestNetworkPinner.pin(mServiceContext, wifiRequest);
2959 assertNull(mCm.getBoundNetworkForProcess());
2961 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2962 mCellNetworkAgent.connect(true);
2963 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2964 mWiFiNetworkAgent.connect(false);
2966 // When wi-fi connects, expect to be pinned.
2967 assertTrue(TestNetworkPinner.awaitPin(100));
2968 assertPinnedToWifiWithCellDefault();
2970 // Disconnect and expect the pin to drop.
2971 mWiFiNetworkAgent.disconnect();
2972 assertTrue(TestNetworkPinner.awaitUnpin(100));
2973 assertNotPinnedToWifi();
2975 // Reconnecting does not cause the pin to come back.
2976 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2977 mWiFiNetworkAgent.connect(false);
2978 assertFalse(TestNetworkPinner.awaitPin(100));
2979 assertNotPinnedToWifi();
2981 // Pinning while connected causes the pin to take effect immediately.
2982 TestNetworkPinner.pin(mServiceContext, wifiRequest);
2983 assertTrue(TestNetworkPinner.awaitPin(100));
2984 assertPinnedToWifiWithCellDefault();
2986 // Explicitly unpin and expect to use the default network again.
2987 TestNetworkPinner.unpin();
2988 assertNotPinnedToWifi();
2990 // Disconnect cell and wifi.
2991 ConditionVariable cv = waitForConnectivityBroadcasts(3); // cell down, wifi up, wifi down.
2992 mCellNetworkAgent.disconnect();
2993 mWiFiNetworkAgent.disconnect();
2996 // Pinning takes effect even if the pinned network is the default when the pin is set...
2997 TestNetworkPinner.pin(mServiceContext, wifiRequest);
2998 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2999 mWiFiNetworkAgent.connect(false);
3000 assertTrue(TestNetworkPinner.awaitPin(100));
3001 assertPinnedToWifiWithWifiDefault();
3003 // ... and is maintained even when that network is no longer the default.
3004 cv = waitForConnectivityBroadcasts(1);
3005 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3006 mCellNetworkAgent.connect(true);
3008 assertPinnedToWifiWithCellDefault();
3012 public void testNetworkRequestMaximum() {
3013 final int MAX_REQUESTS = 100;
3014 // Test that the limit is enforced when MAX_REQUESTS simultaneous requests are added.
3015 NetworkRequest networkRequest = new NetworkRequest.Builder().build();
3016 ArrayList<NetworkCallback> networkCallbacks = new ArrayList<NetworkCallback>();
3018 for (int i = 0; i < MAX_REQUESTS; i++) {
3019 NetworkCallback networkCallback = new NetworkCallback();
3020 mCm.requestNetwork(networkRequest, networkCallback);
3021 networkCallbacks.add(networkCallback);
3023 fail("Registering " + MAX_REQUESTS + " NetworkRequests did not throw exception");
3024 } catch (IllegalArgumentException expected) {}
3025 for (NetworkCallback networkCallback : networkCallbacks) {
3026 mCm.unregisterNetworkCallback(networkCallback);
3028 networkCallbacks.clear();
3031 for (int i = 0; i < MAX_REQUESTS; i++) {
3032 NetworkCallback networkCallback = new NetworkCallback();
3033 mCm.registerNetworkCallback(networkRequest, networkCallback);
3034 networkCallbacks.add(networkCallback);
3036 fail("Registering " + MAX_REQUESTS + " NetworkCallbacks did not throw exception");
3037 } catch (IllegalArgumentException expected) {}
3038 for (NetworkCallback networkCallback : networkCallbacks) {
3039 mCm.unregisterNetworkCallback(networkCallback);
3041 networkCallbacks.clear();
3043 ArrayList<PendingIntent> pendingIntents = new ArrayList<PendingIntent>();
3045 for (int i = 0; i < MAX_REQUESTS + 1; i++) {
3046 PendingIntent pendingIntent =
3047 PendingIntent.getBroadcast(mContext, 0, new Intent("a" + i), 0);
3048 mCm.requestNetwork(networkRequest, pendingIntent);
3049 pendingIntents.add(pendingIntent);
3051 fail("Registering " + MAX_REQUESTS +
3052 " PendingIntent NetworkRequests did not throw exception");
3053 } catch (IllegalArgumentException expected) {}
3054 for (PendingIntent pendingIntent : pendingIntents) {
3055 mCm.unregisterNetworkCallback(pendingIntent);
3057 pendingIntents.clear();
3060 for (int i = 0; i < MAX_REQUESTS + 1; i++) {
3061 PendingIntent pendingIntent =
3062 PendingIntent.getBroadcast(mContext, 0, new Intent("a" + i), 0);
3063 mCm.registerNetworkCallback(networkRequest, pendingIntent);
3064 pendingIntents.add(pendingIntent);
3066 fail("Registering " + MAX_REQUESTS +
3067 " PendingIntent NetworkCallbacks did not throw exception");
3068 } catch (IllegalArgumentException expected) {}
3069 for (PendingIntent pendingIntent : pendingIntents) {
3070 mCm.unregisterNetworkCallback(pendingIntent);
3072 pendingIntents.clear();
3073 mService.waitForIdle(5000);
3075 // Test that the limit is not hit when MAX_REQUESTS requests are added and removed.
3076 for (int i = 0; i < MAX_REQUESTS; i++) {
3077 NetworkCallback networkCallback = new NetworkCallback();
3078 mCm.requestNetwork(networkRequest, networkCallback);
3079 mCm.unregisterNetworkCallback(networkCallback);
3081 mService.waitForIdle();
3082 for (int i = 0; i < MAX_REQUESTS; i++) {
3083 NetworkCallback networkCallback = new NetworkCallback();
3084 mCm.registerNetworkCallback(networkRequest, networkCallback);
3085 mCm.unregisterNetworkCallback(networkCallback);
3087 mService.waitForIdle();
3088 for (int i = 0; i < MAX_REQUESTS; i++) {
3089 PendingIntent pendingIntent =
3090 PendingIntent.getBroadcast(mContext, 0, new Intent("b" + i), 0);
3091 mCm.requestNetwork(networkRequest, pendingIntent);
3092 mCm.unregisterNetworkCallback(pendingIntent);
3094 mService.waitForIdle();
3095 for (int i = 0; i < MAX_REQUESTS; i++) {
3096 PendingIntent pendingIntent =
3097 PendingIntent.getBroadcast(mContext, 0, new Intent("c" + i), 0);
3098 mCm.registerNetworkCallback(networkRequest, pendingIntent);
3099 mCm.unregisterNetworkCallback(pendingIntent);
3103 /* test utilities */
3104 // TODO: eliminate all usages of sleepFor and replace by proper timeouts/waitForIdle.
3105 static private void sleepFor(int ms) {
3108 } catch (InterruptedException e) {