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_MOBILE;
21 import static android.net.ConnectivityManager.TYPE_WIFI;
22 import static android.net.ConnectivityManager.getNetworkTypeName;
23 import static android.net.NetworkCapabilities.*;
25 import static org.mockito.Mockito.mock;
27 import android.app.PendingIntent;
28 import android.content.BroadcastReceiver;
29 import android.content.Context;
30 import android.content.ContextWrapper;
31 import android.content.Intent;
32 import android.content.IntentFilter;
33 import android.net.ConnectivityManager;
34 import android.net.ConnectivityManager.NetworkCallback;
35 import android.net.ConnectivityManager.PacketKeepalive;
36 import android.net.ConnectivityManager.PacketKeepaliveCallback;
37 import android.net.INetworkPolicyManager;
38 import android.net.INetworkStatsService;
39 import android.net.IpPrefix;
40 import android.net.LinkAddress;
41 import android.net.LinkProperties;
42 import android.net.Network;
43 import android.net.NetworkAgent;
44 import android.net.NetworkCapabilities;
45 import android.net.NetworkConfig;
46 import android.net.NetworkFactory;
47 import android.net.NetworkInfo;
48 import android.net.NetworkInfo.DetailedState;
49 import android.net.NetworkMisc;
50 import android.net.NetworkRequest;
51 import android.net.RouteInfo;
52 import android.os.ConditionVariable;
53 import android.os.Handler;
54 import android.os.HandlerThread;
55 import android.os.INetworkManagementService;
56 import android.os.Looper;
57 import android.os.Message;
58 import android.os.MessageQueue;
59 import android.os.MessageQueue.IdleHandler;
60 import android.test.AndroidTestCase;
61 import android.test.suitebuilder.annotation.LargeTest;
62 import android.util.Log;
63 import android.util.LogPrinter;
65 import com.android.server.connectivity.NetworkAgentInfo;
66 import com.android.server.connectivity.NetworkMonitor;
68 import java.net.InetAddress;
69 import java.util.concurrent.CountDownLatch;
70 import java.util.concurrent.LinkedBlockingQueue;
71 import java.util.concurrent.TimeUnit;
72 import java.util.concurrent.atomic.AtomicBoolean;
75 * Tests for {@link ConnectivityService}.
77 * Build, install and run with:
78 * runtest frameworks-services -c com.android.server.ConnectivityServiceTest
80 public class ConnectivityServiceTest extends AndroidTestCase {
81 private static final String TAG = "ConnectivityServiceTest";
83 private static final int TIMEOUT_MS = 500;
85 private BroadcastInterceptingContext mServiceContext;
86 private WrappedConnectivityService mService;
87 private ConnectivityManager mCm;
88 private MockNetworkAgent mWiFiNetworkAgent;
89 private MockNetworkAgent mCellNetworkAgent;
91 private class MockContext extends BroadcastInterceptingContext {
92 MockContext(Context base) {
97 public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
98 // PendingIntents sent by the AlarmManager are not intercepted by
99 // BroadcastInterceptingContext so we must really register the receiver.
100 // This shouldn't effect the real NetworkMonitors as the action contains a random token.
101 if (filter.getAction(0).startsWith("android.net.netmon.lingerExpired")) {
102 return getBaseContext().registerReceiver(receiver, filter);
104 return super.registerReceiver(receiver, filter);
109 public Object getSystemService (String name) {
110 if (name == Context.CONNECTIVITY_SERVICE) return mCm;
111 return super.getSystemService(name);
116 * A subclass of HandlerThread that allows callers to wait for it to become idle. waitForIdle
117 * will return immediately if the handler is already idle.
119 private class IdleableHandlerThread extends HandlerThread {
120 private IdleHandler mIdleHandler;
122 public IdleableHandlerThread(String name) {
126 public void waitForIdle(int timeoutMs) {
127 final ConditionVariable cv = new ConditionVariable();
128 final MessageQueue queue = getLooper().getQueue();
130 synchronized (queue) {
131 if (queue.isIdle()) {
135 assertNull("BUG: only one idle handler allowed", mIdleHandler);
136 mIdleHandler = new IdleHandler() {
137 public boolean queueIdle() {
140 return false; // Remove the handler.
143 queue.addIdleHandler(mIdleHandler);
146 if (!cv.block(timeoutMs)) {
147 fail("HandlerThread " + getName() +
148 " did not become idle after " + timeoutMs + " ms");
149 queue.removeIdleHandler(mIdleHandler);
154 // Tests that IdleableHandlerThread works as expected.
155 public void testIdleableHandlerThread() {
156 final int attempts = 50; // Causes the test to take about 200ms on bullhead-eng.
158 // Tests that waitForIdle returns immediately if the service is already idle.
159 for (int i = 0; i < attempts; i++) {
160 mService.waitForIdle();
163 // Bring up a network that we can use to send messages to ConnectivityService.
164 ConditionVariable cv = waitForConnectivityBroadcasts(1);
165 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
166 mWiFiNetworkAgent.connect(false);
168 Network n = mWiFiNetworkAgent.getNetwork();
171 // Tests that calling waitForIdle waits for messages to be processed.
172 for (int i = 0; i < attempts; i++) {
173 mWiFiNetworkAgent.setSignalStrength(i);
174 mService.waitForIdle();
175 assertEquals(i, mCm.getNetworkCapabilities(n).getSignalStrength());
178 // Ensure that not calling waitForIdle causes a race condition.
179 for (int i = 0; i < attempts; i++) {
180 mWiFiNetworkAgent.setSignalStrength(i);
181 if (i != mCm.getNetworkCapabilities(n).getSignalStrength()) {
182 // We hit a race condition, as expected. Pass the test.
187 // No race? There is a bug in this test.
188 fail("expected race condition at least once in " + attempts + " attempts");
191 private class MockNetworkAgent {
192 private final WrappedNetworkMonitor mWrappedNetworkMonitor;
193 private final NetworkInfo mNetworkInfo;
194 private final NetworkCapabilities mNetworkCapabilities;
195 private final IdleableHandlerThread mHandlerThread;
196 private final ConditionVariable mDisconnected = new ConditionVariable();
198 private NetworkAgent mNetworkAgent;
199 private int mStartKeepaliveError = PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED;
200 private int mStopKeepaliveError = PacketKeepalive.NO_KEEPALIVE;
201 private Integer mExpectedKeepaliveSlot = null;
203 MockNetworkAgent(int transport) {
204 final int type = transportToLegacyType(transport);
205 final String typeName = ConnectivityManager.getNetworkTypeName(type);
206 mNetworkInfo = new NetworkInfo(type, 0, typeName, "Mock");
207 mNetworkCapabilities = new NetworkCapabilities();
208 mNetworkCapabilities.addTransportType(transport);
213 case TRANSPORT_CELLULAR:
217 throw new UnsupportedOperationException("unimplemented network type");
219 mHandlerThread = new IdleableHandlerThread("Mock-" + typeName);
220 mHandlerThread.start();
221 mNetworkAgent = new NetworkAgent(mHandlerThread.getLooper(), mServiceContext,
222 "Mock-" + typeName, mNetworkInfo, mNetworkCapabilities,
223 new LinkProperties(), mScore, new NetworkMisc()) {
225 public void unwanted() { mDisconnected.open(); }
228 public void startPacketKeepalive(Message msg) {
230 if (mExpectedKeepaliveSlot != null) {
231 assertEquals((int) mExpectedKeepaliveSlot, slot);
233 onPacketKeepaliveEvent(slot, mStartKeepaliveError);
237 public void stopPacketKeepalive(Message msg) {
238 onPacketKeepaliveEvent(msg.arg1, mStopKeepaliveError);
241 // Waits for the NetworkAgent to be registered, which includes the creation of the
243 mService.waitForIdle();
244 mWrappedNetworkMonitor = mService.getLastCreatedWrappedNetworkMonitor();
247 public void waitForIdle(int timeoutMs) {
248 mHandlerThread.waitForIdle(timeoutMs);
251 public void waitForIdle() {
252 waitForIdle(TIMEOUT_MS);
255 public void adjustScore(int change) {
257 mNetworkAgent.sendNetworkScore(mScore);
260 public void addCapability(int capability) {
261 mNetworkCapabilities.addCapability(capability);
262 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
265 public void setSignalStrength(int signalStrength) {
266 mNetworkCapabilities.setSignalStrength(signalStrength);
267 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
270 public void connectWithoutInternet() {
271 mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, null);
272 mNetworkAgent.sendNetworkInfo(mNetworkInfo);
276 * Transition this NetworkAgent to CONNECTED state with NET_CAPABILITY_INTERNET.
277 * @param validated Indicate if network should pretend to be validated.
279 public void connect(boolean validated) {
280 assertEquals(mNetworkInfo.getDetailedState(), DetailedState.IDLE);
281 assertFalse(mNetworkCapabilities.hasCapability(NET_CAPABILITY_INTERNET));
283 NetworkCallback callback = null;
284 final ConditionVariable validatedCv = new ConditionVariable();
286 mWrappedNetworkMonitor.gen204ProbeResult = 204;
287 NetworkRequest request = new NetworkRequest.Builder()
288 .addTransportType(mNetworkCapabilities.getTransportTypes()[0])
290 callback = new NetworkCallback() {
291 public void onCapabilitiesChanged(Network network,
292 NetworkCapabilities networkCapabilities) {
293 if (network.equals(getNetwork()) &&
294 networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED)) {
299 mCm.registerNetworkCallback(request, callback);
301 addCapability(NET_CAPABILITY_INTERNET);
303 connectWithoutInternet();
306 // Wait for network to validate.
307 waitFor(validatedCv);
308 mWrappedNetworkMonitor.gen204ProbeResult = 500;
311 if (callback != null) mCm.unregisterNetworkCallback(callback);
314 public void connectWithCaptivePortal() {
315 mWrappedNetworkMonitor.gen204ProbeResult = 200;
317 waitFor(new Criteria() { public boolean get() {
318 NetworkCapabilities caps = mCm.getNetworkCapabilities(getNetwork());
319 return caps != null && caps.hasCapability(NET_CAPABILITY_CAPTIVE_PORTAL);} });
320 mWrappedNetworkMonitor.gen204ProbeResult = 500;
323 public void disconnect() {
324 mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, null);
325 mNetworkAgent.sendNetworkInfo(mNetworkInfo);
328 public Network getNetwork() {
329 return new Network(mNetworkAgent.netId);
332 public ConditionVariable getDisconnectedCV() {
333 return mDisconnected;
336 public WrappedNetworkMonitor getWrappedNetworkMonitor() {
337 return mWrappedNetworkMonitor;
340 public void sendLinkProperties(LinkProperties lp) {
341 mNetworkAgent.sendLinkProperties(lp);
344 public void setStartKeepaliveError(int error) {
345 mStartKeepaliveError = error;
348 public void setStopKeepaliveError(int error) {
349 mStopKeepaliveError = error;
352 public void setExpectedKeepaliveSlot(Integer slot) {
353 mExpectedKeepaliveSlot = slot;
358 * A NetworkFactory that allows tests to wait until any in-flight NetworkRequest add or remove
359 * operations have been processed. Before ConnectivityService can add or remove any requests,
360 * the factory must be told to expect those operations by calling expectAddRequests or
361 * expectRemoveRequests.
363 private static class MockNetworkFactory extends NetworkFactory {
364 private final ConditionVariable mNetworkStartedCV = new ConditionVariable();
365 private final ConditionVariable mNetworkStoppedCV = new ConditionVariable();
366 private final AtomicBoolean mNetworkStarted = new AtomicBoolean(false);
368 // Used to expect that requests be removed or added on a separate thread, without sleeping.
369 // Callers can call either expectAddRequests() or expectRemoveRequests() exactly once, then
370 // cause some other thread to add or remove requests, then call waitForRequests(). We can
371 // either expect requests to be added or removed, but not both, because CountDownLatch can
372 // only count in one direction.
373 private CountDownLatch mExpectations;
375 // Whether we are currently expecting requests to be added or removed. Valid only if
376 // mExpectations is non-null.
377 private boolean mExpectingAdditions;
379 public MockNetworkFactory(Looper looper, Context context, String logTag,
380 NetworkCapabilities filter) {
381 super(looper, context, logTag, filter);
384 public int getMyRequestCount() {
385 return getRequestCount();
388 protected void startNetwork() {
389 mNetworkStarted.set(true);
390 mNetworkStartedCV.open();
393 protected void stopNetwork() {
394 mNetworkStarted.set(false);
395 mNetworkStoppedCV.open();
398 public boolean getMyStartRequested() {
399 return mNetworkStarted.get();
402 public ConditionVariable getNetworkStartedCV() {
403 mNetworkStartedCV.close();
404 return mNetworkStartedCV;
407 public ConditionVariable getNetworkStoppedCV() {
408 mNetworkStoppedCV.close();
409 return mNetworkStoppedCV;
413 protected void handleAddRequest(NetworkRequest request, int score) {
414 // If we're expecting anything, we must be expecting additions.
415 if (mExpectations != null && !mExpectingAdditions) {
416 fail("Can't add requests while expecting requests to be removed");
420 super.handleAddRequest(request, score);
422 // Reduce the number of request additions we're waiting for.
423 if (mExpectingAdditions) {
424 assertTrue("Added more requests than expected", mExpectations.getCount() > 0);
425 mExpectations.countDown();
430 protected void handleRemoveRequest(NetworkRequest request) {
431 // If we're expecting anything, we must be expecting removals.
432 if (mExpectations != null && mExpectingAdditions) {
433 fail("Can't remove requests while expecting requests to be added");
436 // Remove the request.
437 super.handleRemoveRequest(request);
439 // Reduce the number of request removals we're waiting for.
440 if (!mExpectingAdditions) {
441 assertTrue("Removed more requests than expected", mExpectations.getCount() > 0);
442 mExpectations.countDown();
446 private void assertNoExpectations() {
447 if (mExpectations != null) {
448 fail("Can't add expectation, " + mExpectations.getCount() + " already pending");
452 // Expects that count requests will be added.
453 public void expectAddRequests(final int count) {
454 assertNoExpectations();
455 mExpectingAdditions = true;
456 mExpectations = new CountDownLatch(count);
459 // Expects that count requests will be removed.
460 public void expectRemoveRequests(final int count) {
461 assertNoExpectations();
462 mExpectingAdditions = false;
463 mExpectations = new CountDownLatch(count);
466 // Waits for the expected request additions or removals to happen within a timeout.
467 public void waitForRequests() throws InterruptedException {
468 assertNotNull("Nothing to wait for", mExpectations);
469 mExpectations.await(TIMEOUT_MS, TimeUnit.MILLISECONDS);
470 final long count = mExpectations.getCount();
471 final String msg = count + " requests still not " +
472 (mExpectingAdditions ? "added" : "removed") +
473 " after " + TIMEOUT_MS + " ms";
474 assertEquals(msg, 0, count);
475 mExpectations = null;
478 public void waitForNetworkRequests(final int count) throws InterruptedException {
480 assertEquals(count, getMyRequestCount());
484 // NetworkMonitor implementation allowing overriding of Internet connectivity probe result.
485 private class WrappedNetworkMonitor extends NetworkMonitor {
486 // HTTP response code fed back to NetworkMonitor for Internet connectivity probe.
487 public int gen204ProbeResult = 500;
489 public WrappedNetworkMonitor(Context context, Handler handler,
490 NetworkAgentInfo networkAgentInfo, NetworkRequest defaultRequest) {
491 super(context, handler, networkAgentInfo, defaultRequest);
495 protected int isCaptivePortal() {
496 return gen204ProbeResult;
500 private class WrappedConnectivityService extends ConnectivityService {
501 private WrappedNetworkMonitor mLastCreatedNetworkMonitor;
503 public WrappedConnectivityService(Context context, INetworkManagementService netManager,
504 INetworkStatsService statsService, INetworkPolicyManager policyManager) {
505 super(context, netManager, statsService, policyManager);
509 protected HandlerThread createHandlerThread() {
510 return new IdleableHandlerThread("WrappedConnectivityService");
514 protected int getDefaultTcpRwnd() {
515 // Prevent wrapped ConnectivityService from trying to write to SystemProperties.
520 protected int reserveNetId() {
522 final int netId = super.reserveNetId();
524 // Don't overlap test NetIDs with real NetIDs as binding sockets to real networks
525 // can have odd side-effects, like network validations succeeding.
526 final Network[] networks = ConnectivityManager.from(getContext()).getAllNetworks();
527 boolean overlaps = false;
528 for (Network network : networks) {
529 if (netId == network.netId) {
534 if (overlaps) continue;
541 public NetworkMonitor createNetworkMonitor(Context context, Handler handler,
542 NetworkAgentInfo nai, NetworkRequest defaultRequest) {
543 final WrappedNetworkMonitor monitor = new WrappedNetworkMonitor(context, handler, nai,
545 mLastCreatedNetworkMonitor = monitor;
549 public WrappedNetworkMonitor getLastCreatedWrappedNetworkMonitor() {
550 return mLastCreatedNetworkMonitor;
553 public void waitForIdle(int timeoutMs) {
554 ((IdleableHandlerThread) mHandlerThread).waitForIdle(timeoutMs);
557 public void waitForIdle() {
558 waitForIdle(TIMEOUT_MS);
563 private interface Criteria {
564 public boolean get();
568 * Wait up to 500ms for {@code criteria.get()} to become true, polling.
569 * Fails if 500ms goes by before {@code criteria.get()} to become true.
571 static private void waitFor(Criteria criteria) {
573 while (!criteria.get()) {
576 } catch (InterruptedException e) {
578 if (++delays == 5) fail();
583 * Wait up to TIMEOUT_MS for {@code conditionVariable} to open.
584 * Fails if TIMEOUT_MS goes by before {@code conditionVariable} opens.
586 static private void waitFor(ConditionVariable conditionVariable) {
587 assertTrue(conditionVariable.block(TIMEOUT_MS));
591 public void setUp() throws Exception {
594 mServiceContext = new MockContext(getContext());
595 mService = new WrappedConnectivityService(mServiceContext,
596 mock(INetworkManagementService.class),
597 mock(INetworkStatsService.class),
598 mock(INetworkPolicyManager.class));
600 mService.systemReady();
601 mCm = new ConnectivityManager(getContext(), mService);
604 private int transportToLegacyType(int transport) {
608 case TRANSPORT_CELLULAR:
611 throw new IllegalStateException("Unknown transport" + transport);
615 private void verifyActiveNetwork(int transport) {
616 // Test getActiveNetworkInfo()
617 assertNotNull(mCm.getActiveNetworkInfo());
618 assertEquals(transportToLegacyType(transport), mCm.getActiveNetworkInfo().getType());
619 // Test getActiveNetwork()
620 assertNotNull(mCm.getActiveNetwork());
623 assertEquals(mCm.getActiveNetwork(), mWiFiNetworkAgent.getNetwork());
625 case TRANSPORT_CELLULAR:
626 assertEquals(mCm.getActiveNetwork(), mCellNetworkAgent.getNetwork());
629 throw new IllegalStateException("Unknown transport" + transport);
631 // Test getNetworkInfo(Network)
632 assertNotNull(mCm.getNetworkInfo(mCm.getActiveNetwork()));
633 assertEquals(transportToLegacyType(transport), mCm.getNetworkInfo(mCm.getActiveNetwork()).getType());
634 // Test getNetworkCapabilities(Network)
635 assertNotNull(mCm.getNetworkCapabilities(mCm.getActiveNetwork()));
636 assertTrue(mCm.getNetworkCapabilities(mCm.getActiveNetwork()).hasTransport(transport));
639 private void verifyNoNetwork() {
640 // Test getActiveNetworkInfo()
641 assertNull(mCm.getActiveNetworkInfo());
642 // Test getActiveNetwork()
643 assertNull(mCm.getActiveNetwork());
644 // Test getAllNetworks()
645 assertEquals(0, mCm.getAllNetworks().length);
649 * Return a ConditionVariable that opens when {@code count} numbers of CONNECTIVITY_ACTION
650 * broadcasts are received.
652 private ConditionVariable waitForConnectivityBroadcasts(final int count) {
653 final ConditionVariable cv = new ConditionVariable();
654 mServiceContext.registerReceiver(new BroadcastReceiver() {
655 private int remaining = count;
656 public void onReceive(Context context, Intent intent) {
657 if (--remaining == 0) {
659 mServiceContext.unregisterReceiver(this);
662 }, new IntentFilter(CONNECTIVITY_ACTION));
667 public void testLingering() throws Exception {
668 // Decrease linger timeout to the minimum allowed by AlarmManagerService.
669 NetworkMonitor.SetDefaultLingerTime(5000);
671 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
672 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
673 assertNull(mCm.getActiveNetworkInfo());
674 assertNull(mCm.getActiveNetwork());
675 // Test bringing up validated cellular.
676 ConditionVariable cv = waitForConnectivityBroadcasts(1);
677 mCellNetworkAgent.connect(true);
679 verifyActiveNetwork(TRANSPORT_CELLULAR);
680 assertEquals(2, mCm.getAllNetworks().length);
681 assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) ||
682 mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork()));
683 assertTrue(mCm.getAllNetworks()[0].equals(mWiFiNetworkAgent.getNetwork()) ||
684 mCm.getAllNetworks()[1].equals(mWiFiNetworkAgent.getNetwork()));
685 // Test bringing up validated WiFi.
686 cv = waitForConnectivityBroadcasts(2);
687 mWiFiNetworkAgent.connect(true);
689 verifyActiveNetwork(TRANSPORT_WIFI);
690 assertEquals(2, mCm.getAllNetworks().length);
691 assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) ||
692 mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork()));
693 assertTrue(mCm.getAllNetworks()[0].equals(mCellNetworkAgent.getNetwork()) ||
694 mCm.getAllNetworks()[1].equals(mCellNetworkAgent.getNetwork()));
695 // Test cellular linger timeout.
698 } catch (InterruptedException e) {
700 verifyActiveNetwork(TRANSPORT_WIFI);
701 assertEquals(1, mCm.getAllNetworks().length);
702 assertEquals(mCm.getAllNetworks()[0], mCm.getActiveNetwork());
703 // Test WiFi disconnect.
704 cv = waitForConnectivityBroadcasts(1);
705 mWiFiNetworkAgent.disconnect();
711 public void testValidatedCellularOutscoresUnvalidatedWiFi() throws Exception {
712 // Test bringing up unvalidated WiFi
713 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
714 ConditionVariable cv = waitForConnectivityBroadcasts(1);
715 mWiFiNetworkAgent.connect(false);
717 verifyActiveNetwork(TRANSPORT_WIFI);
718 // Test bringing up unvalidated cellular
719 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
720 mCellNetworkAgent.connect(false);
721 mService.waitForIdle();
722 verifyActiveNetwork(TRANSPORT_WIFI);
723 // Test cellular disconnect.
724 mCellNetworkAgent.disconnect();
725 mService.waitForIdle();
726 verifyActiveNetwork(TRANSPORT_WIFI);
727 // Test bringing up validated cellular
728 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
729 cv = waitForConnectivityBroadcasts(2);
730 mCellNetworkAgent.connect(true);
732 verifyActiveNetwork(TRANSPORT_CELLULAR);
733 // Test cellular disconnect.
734 cv = waitForConnectivityBroadcasts(2);
735 mCellNetworkAgent.disconnect();
737 verifyActiveNetwork(TRANSPORT_WIFI);
738 // Test WiFi disconnect.
739 cv = waitForConnectivityBroadcasts(1);
740 mWiFiNetworkAgent.disconnect();
746 public void testUnvalidatedWifiOutscoresUnvalidatedCellular() throws Exception {
747 // Test bringing up unvalidated cellular.
748 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
749 ConditionVariable cv = waitForConnectivityBroadcasts(1);
750 mCellNetworkAgent.connect(false);
752 verifyActiveNetwork(TRANSPORT_CELLULAR);
753 // Test bringing up unvalidated WiFi.
754 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
755 cv = waitForConnectivityBroadcasts(2);
756 mWiFiNetworkAgent.connect(false);
758 verifyActiveNetwork(TRANSPORT_WIFI);
759 // Test WiFi disconnect.
760 cv = waitForConnectivityBroadcasts(2);
761 mWiFiNetworkAgent.disconnect();
763 verifyActiveNetwork(TRANSPORT_CELLULAR);
764 // Test cellular disconnect.
765 cv = waitForConnectivityBroadcasts(1);
766 mCellNetworkAgent.disconnect();
772 public void testUnlingeringDoesNotValidate() throws Exception {
773 // Test bringing up unvalidated WiFi.
774 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
775 ConditionVariable cv = waitForConnectivityBroadcasts(1);
776 mWiFiNetworkAgent.connect(false);
778 verifyActiveNetwork(TRANSPORT_WIFI);
779 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
780 NET_CAPABILITY_VALIDATED));
781 // Test bringing up validated cellular.
782 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
783 cv = waitForConnectivityBroadcasts(2);
784 mCellNetworkAgent.connect(true);
786 verifyActiveNetwork(TRANSPORT_CELLULAR);
787 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
788 NET_CAPABILITY_VALIDATED));
789 // Test cellular disconnect.
790 cv = waitForConnectivityBroadcasts(2);
791 mCellNetworkAgent.disconnect();
793 verifyActiveNetwork(TRANSPORT_WIFI);
794 // Unlingering a network should not cause it to be marked as validated.
795 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
796 NET_CAPABILITY_VALIDATED));
800 public void testCellularOutscoresWeakWifi() throws Exception {
801 // Test bringing up validated cellular.
802 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
803 ConditionVariable cv = waitForConnectivityBroadcasts(1);
804 mCellNetworkAgent.connect(true);
806 verifyActiveNetwork(TRANSPORT_CELLULAR);
807 // Test bringing up validated WiFi.
808 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
809 cv = waitForConnectivityBroadcasts(2);
810 mWiFiNetworkAgent.connect(true);
812 verifyActiveNetwork(TRANSPORT_WIFI);
813 // Test WiFi getting really weak.
814 cv = waitForConnectivityBroadcasts(2);
815 mWiFiNetworkAgent.adjustScore(-11);
817 verifyActiveNetwork(TRANSPORT_CELLULAR);
818 // Test WiFi restoring signal strength.
819 cv = waitForConnectivityBroadcasts(2);
820 mWiFiNetworkAgent.adjustScore(11);
822 verifyActiveNetwork(TRANSPORT_WIFI);
823 mCellNetworkAgent.disconnect();
824 mWiFiNetworkAgent.disconnect();
828 public void testReapingNetwork() throws Exception {
829 // Test bringing up WiFi without NET_CAPABILITY_INTERNET.
830 // Expect it to be torn down immediately because it satisfies no requests.
831 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
832 ConditionVariable cv = mWiFiNetworkAgent.getDisconnectedCV();
833 mWiFiNetworkAgent.connectWithoutInternet();
835 // Test bringing up cellular without NET_CAPABILITY_INTERNET.
836 // Expect it to be torn down immediately because it satisfies no requests.
837 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
838 cv = mCellNetworkAgent.getDisconnectedCV();
839 mCellNetworkAgent.connectWithoutInternet();
841 // Test bringing up validated WiFi.
842 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
843 cv = waitForConnectivityBroadcasts(1);
844 mWiFiNetworkAgent.connect(true);
846 verifyActiveNetwork(TRANSPORT_WIFI);
847 // Test bringing up unvalidated cellular.
848 // Expect it to be torn down because it could never be the highest scoring network
849 // satisfying the default request even if it validated.
850 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
851 cv = mCellNetworkAgent.getDisconnectedCV();
852 mCellNetworkAgent.connect(false);
854 verifyActiveNetwork(TRANSPORT_WIFI);
855 cv = mWiFiNetworkAgent.getDisconnectedCV();
856 mWiFiNetworkAgent.disconnect();
861 public void testCellularFallback() throws Exception {
862 // Test bringing up validated cellular.
863 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
864 ConditionVariable cv = waitForConnectivityBroadcasts(1);
865 mCellNetworkAgent.connect(true);
867 verifyActiveNetwork(TRANSPORT_CELLULAR);
868 // Test bringing up validated WiFi.
869 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
870 cv = waitForConnectivityBroadcasts(2);
871 mWiFiNetworkAgent.connect(true);
873 verifyActiveNetwork(TRANSPORT_WIFI);
874 // Reevaluate WiFi (it'll instantly fail DNS).
875 cv = waitForConnectivityBroadcasts(2);
876 assertTrue(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
877 NET_CAPABILITY_VALIDATED));
878 mCm.reportBadNetwork(mWiFiNetworkAgent.getNetwork());
879 // Should quickly fall back to Cellular.
881 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
882 NET_CAPABILITY_VALIDATED));
883 verifyActiveNetwork(TRANSPORT_CELLULAR);
884 // Reevaluate cellular (it'll instantly fail DNS).
885 cv = waitForConnectivityBroadcasts(2);
886 assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
887 NET_CAPABILITY_VALIDATED));
888 mCm.reportBadNetwork(mCellNetworkAgent.getNetwork());
889 // Should quickly fall back to WiFi.
891 assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
892 NET_CAPABILITY_VALIDATED));
893 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
894 NET_CAPABILITY_VALIDATED));
895 verifyActiveNetwork(TRANSPORT_WIFI);
896 mCellNetworkAgent.disconnect();
897 mWiFiNetworkAgent.disconnect();
901 public void testWiFiFallback() throws Exception {
902 // Test bringing up unvalidated WiFi.
903 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
904 ConditionVariable cv = waitForConnectivityBroadcasts(1);
905 mWiFiNetworkAgent.connect(false);
907 verifyActiveNetwork(TRANSPORT_WIFI);
908 // Test bringing up validated cellular.
909 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
910 cv = waitForConnectivityBroadcasts(2);
911 mCellNetworkAgent.connect(true);
913 verifyActiveNetwork(TRANSPORT_CELLULAR);
914 // Reevaluate cellular (it'll instantly fail DNS).
915 cv = waitForConnectivityBroadcasts(2);
916 assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
917 NET_CAPABILITY_VALIDATED));
918 mCm.reportBadNetwork(mCellNetworkAgent.getNetwork());
919 // Should quickly fall back to WiFi.
921 assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
922 NET_CAPABILITY_VALIDATED));
923 verifyActiveNetwork(TRANSPORT_WIFI);
924 mCellNetworkAgent.disconnect();
925 mWiFiNetworkAgent.disconnect();
936 * Utility NetworkCallback for testing. The caller must explicitly test for all the callbacks
937 * this class receives, by calling expectCallback() exactly once each time a callback is
938 * received. assertNoCallback may be called at any time.
940 private class TestNetworkCallback extends NetworkCallback {
941 private final ConditionVariable mConditionVariable = new ConditionVariable();
942 private CallbackState mLastCallback = CallbackState.NONE;
944 public void onAvailable(Network network) {
945 assertEquals(CallbackState.NONE, mLastCallback);
946 mLastCallback = CallbackState.AVAILABLE;
947 mConditionVariable.open();
950 public void onLosing(Network network, int maxMsToLive) {
951 assertEquals(CallbackState.NONE, mLastCallback);
952 mLastCallback = CallbackState.LOSING;
953 mConditionVariable.open();
956 public void onLost(Network network) {
957 assertEquals(CallbackState.NONE, mLastCallback);
958 mLastCallback = CallbackState.LOST;
959 mConditionVariable.open();
962 void expectCallback(CallbackState state) {
963 waitFor(mConditionVariable);
964 assertEquals(state, mLastCallback);
965 mLastCallback = CallbackState.NONE;
966 mConditionVariable.close();
969 void assertNoCallback() {
970 assertEquals(CallbackState.NONE, mLastCallback);
975 public void testStateChangeNetworkCallbacks() throws Exception {
976 final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
977 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
978 final NetworkRequest wifiRequest = new NetworkRequest.Builder()
979 .addTransportType(TRANSPORT_WIFI).build();
980 final NetworkRequest cellRequest = new NetworkRequest.Builder()
981 .addTransportType(TRANSPORT_CELLULAR).build();
982 mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
983 mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
985 // Test unvalidated networks
986 ConditionVariable cv = waitForConnectivityBroadcasts(1);
987 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
988 mCellNetworkAgent.connect(false);
989 cellNetworkCallback.expectCallback(CallbackState.AVAILABLE);
990 wifiNetworkCallback.assertNoCallback();
991 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
994 // This should not trigger spurious onAvailable() callbacks, b/21762680.
995 mCellNetworkAgent.adjustScore(-1);
996 mService.waitForIdle();
997 wifiNetworkCallback.assertNoCallback();
998 cellNetworkCallback.assertNoCallback();
999 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1001 cv = waitForConnectivityBroadcasts(2);
1002 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1003 mWiFiNetworkAgent.connect(false);
1004 wifiNetworkCallback.expectCallback(CallbackState.AVAILABLE);
1005 cellNetworkCallback.assertNoCallback();
1006 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1009 cv = waitForConnectivityBroadcasts(2);
1010 mWiFiNetworkAgent.disconnect();
1011 wifiNetworkCallback.expectCallback(CallbackState.LOST);
1012 cellNetworkCallback.assertNoCallback();
1015 cv = waitForConnectivityBroadcasts(1);
1016 mCellNetworkAgent.disconnect();
1017 cellNetworkCallback.expectCallback(CallbackState.LOST);
1018 wifiNetworkCallback.assertNoCallback();
1021 // Test validated networks
1022 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1023 mCellNetworkAgent.connect(true);
1024 cellNetworkCallback.expectCallback(CallbackState.AVAILABLE);
1025 wifiNetworkCallback.assertNoCallback();
1026 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1028 // This should not trigger spurious onAvailable() callbacks, b/21762680.
1029 mCellNetworkAgent.adjustScore(-1);
1030 mService.waitForIdle();
1031 wifiNetworkCallback.assertNoCallback();
1032 cellNetworkCallback.assertNoCallback();
1033 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1035 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1036 mWiFiNetworkAgent.connect(true);
1037 wifiNetworkCallback.expectCallback(CallbackState.AVAILABLE);
1038 cellNetworkCallback.expectCallback(CallbackState.LOSING);
1039 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1041 mWiFiNetworkAgent.disconnect();
1042 wifiNetworkCallback.expectCallback(CallbackState.LOST);
1043 cellNetworkCallback.assertNoCallback();
1045 mCellNetworkAgent.disconnect();
1046 cellNetworkCallback.expectCallback(CallbackState.LOST);
1047 wifiNetworkCallback.assertNoCallback();
1050 private void tryNetworkFactoryRequests(int capability) throws Exception {
1051 // Verify NOT_RESTRICTED is set appropriately
1052 final NetworkCapabilities nc = new NetworkRequest.Builder().addCapability(capability)
1053 .build().networkCapabilities;
1054 if (capability == NET_CAPABILITY_CBS || capability == NET_CAPABILITY_DUN ||
1055 capability == NET_CAPABILITY_EIMS || capability == NET_CAPABILITY_FOTA ||
1056 capability == NET_CAPABILITY_IA || capability == NET_CAPABILITY_IMS ||
1057 capability == NET_CAPABILITY_RCS || capability == NET_CAPABILITY_XCAP) {
1058 assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
1060 assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
1063 NetworkCapabilities filter = new NetworkCapabilities();
1064 filter.addCapability(capability);
1065 final HandlerThread handlerThread = new HandlerThread("testNetworkFactoryRequests");
1066 handlerThread.start();
1067 final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
1068 mServiceContext, "testFactory", filter);
1069 testFactory.setScoreFilter(40);
1070 ConditionVariable cv = testFactory.getNetworkStartedCV();
1071 testFactory.expectAddRequests(1);
1072 testFactory.register();
1073 testFactory.waitForNetworkRequests(1);
1074 int expectedRequestCount = 1;
1075 NetworkCallback networkCallback = null;
1076 // For non-INTERNET capabilities we cannot rely on the default request being present, so
1078 if (capability != NET_CAPABILITY_INTERNET) {
1079 assertFalse(testFactory.getMyStartRequested());
1080 NetworkRequest request = new NetworkRequest.Builder().addCapability(capability).build();
1081 networkCallback = new NetworkCallback();
1082 testFactory.expectAddRequests(1);
1083 mCm.requestNetwork(request, networkCallback);
1084 expectedRequestCount++;
1085 testFactory.waitForNetworkRequests(expectedRequestCount);
1088 assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
1089 assertTrue(testFactory.getMyStartRequested());
1091 // Now bring in a higher scored network.
1092 MockNetworkAgent testAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1093 // Rather than create a validated network which complicates things by registering it's
1094 // own NetworkRequest during startup, just bump up the score to cancel out the
1095 // unvalidated penalty.
1096 testAgent.adjustScore(40);
1097 cv = testFactory.getNetworkStoppedCV();
1099 // When testAgent connects, ConnectivityService will re-send us all current requests with
1100 // the new score. There are expectedRequestCount such requests, and we must wait for all of
1102 testFactory.expectAddRequests(expectedRequestCount);
1103 testAgent.connect(false);
1104 testAgent.addCapability(capability);
1106 testFactory.waitForNetworkRequests(expectedRequestCount);
1107 assertFalse(testFactory.getMyStartRequested());
1109 // Bring in a bunch of requests.
1110 testFactory.expectAddRequests(10);
1111 assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
1112 ConnectivityManager.NetworkCallback[] networkCallbacks =
1113 new ConnectivityManager.NetworkCallback[10];
1114 for (int i = 0; i< networkCallbacks.length; i++) {
1115 networkCallbacks[i] = new ConnectivityManager.NetworkCallback();
1116 NetworkRequest.Builder builder = new NetworkRequest.Builder();
1117 builder.addCapability(capability);
1118 mCm.requestNetwork(builder.build(), networkCallbacks[i]);
1120 testFactory.waitForNetworkRequests(10 + expectedRequestCount);
1121 assertFalse(testFactory.getMyStartRequested());
1123 // Remove the requests.
1124 testFactory.expectRemoveRequests(10);
1125 for (int i = 0; i < networkCallbacks.length; i++) {
1126 mCm.unregisterNetworkCallback(networkCallbacks[i]);
1128 testFactory.waitForNetworkRequests(expectedRequestCount);
1129 assertFalse(testFactory.getMyStartRequested());
1131 // Drop the higher scored network.
1132 cv = testFactory.getNetworkStartedCV();
1133 testAgent.disconnect();
1135 assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
1136 assertTrue(testFactory.getMyStartRequested());
1138 testFactory.unregister();
1139 if (networkCallback != null) mCm.unregisterNetworkCallback(networkCallback);
1140 handlerThread.quit();
1144 public void testNetworkFactoryRequests() throws Exception {
1145 tryNetworkFactoryRequests(NET_CAPABILITY_MMS);
1146 tryNetworkFactoryRequests(NET_CAPABILITY_SUPL);
1147 tryNetworkFactoryRequests(NET_CAPABILITY_DUN);
1148 tryNetworkFactoryRequests(NET_CAPABILITY_FOTA);
1149 tryNetworkFactoryRequests(NET_CAPABILITY_IMS);
1150 tryNetworkFactoryRequests(NET_CAPABILITY_CBS);
1151 tryNetworkFactoryRequests(NET_CAPABILITY_WIFI_P2P);
1152 tryNetworkFactoryRequests(NET_CAPABILITY_IA);
1153 tryNetworkFactoryRequests(NET_CAPABILITY_RCS);
1154 tryNetworkFactoryRequests(NET_CAPABILITY_XCAP);
1155 tryNetworkFactoryRequests(NET_CAPABILITY_EIMS);
1156 tryNetworkFactoryRequests(NET_CAPABILITY_NOT_METERED);
1157 tryNetworkFactoryRequests(NET_CAPABILITY_INTERNET);
1158 tryNetworkFactoryRequests(NET_CAPABILITY_TRUSTED);
1159 tryNetworkFactoryRequests(NET_CAPABILITY_NOT_VPN);
1160 // Skipping VALIDATED and CAPTIVE_PORTAL as they're disallowed.
1164 public void testNoMutableNetworkRequests() throws Exception {
1165 PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, new Intent("a"), 0);
1166 NetworkRequest.Builder builder = new NetworkRequest.Builder();
1167 builder.addCapability(NET_CAPABILITY_VALIDATED);
1169 mCm.requestNetwork(builder.build(), new NetworkCallback());
1171 } catch (IllegalArgumentException expected) {}
1173 mCm.requestNetwork(builder.build(), pendingIntent);
1175 } catch (IllegalArgumentException expected) {}
1176 builder = new NetworkRequest.Builder();
1177 builder.addCapability(NET_CAPABILITY_CAPTIVE_PORTAL);
1179 mCm.requestNetwork(builder.build(), new NetworkCallback());
1181 } catch (IllegalArgumentException expected) {}
1183 mCm.requestNetwork(builder.build(), pendingIntent);
1185 } catch (IllegalArgumentException expected) {}
1189 public void testMMSonWiFi() throws Exception {
1190 // Test bringing up cellular without MMS NetworkRequest gets reaped
1191 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1192 mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS);
1193 ConditionVariable cv = mCellNetworkAgent.getDisconnectedCV();
1194 mCellNetworkAgent.connectWithoutInternet();
1196 waitFor(new Criteria() {
1197 public boolean get() { return mCm.getAllNetworks().length == 0; } });
1199 // Test bringing up validated WiFi.
1200 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1201 cv = waitForConnectivityBroadcasts(1);
1202 mWiFiNetworkAgent.connect(true);
1204 verifyActiveNetwork(TRANSPORT_WIFI);
1205 // Register MMS NetworkRequest
1206 NetworkRequest.Builder builder = new NetworkRequest.Builder();
1207 builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
1208 final TestNetworkCallback networkCallback = new TestNetworkCallback();
1209 mCm.requestNetwork(builder.build(), networkCallback);
1210 // Test bringing up unvalidated cellular with MMS
1211 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1212 mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS);
1213 mCellNetworkAgent.connectWithoutInternet();
1214 networkCallback.expectCallback(CallbackState.AVAILABLE);
1215 verifyActiveNetwork(TRANSPORT_WIFI);
1216 // Test releasing NetworkRequest disconnects cellular with MMS
1217 cv = mCellNetworkAgent.getDisconnectedCV();
1218 mCm.unregisterNetworkCallback(networkCallback);
1220 verifyActiveNetwork(TRANSPORT_WIFI);
1224 public void testMMSonCell() throws Exception {
1225 // Test bringing up cellular without MMS
1226 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1227 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1228 mCellNetworkAgent.connect(false);
1230 verifyActiveNetwork(TRANSPORT_CELLULAR);
1231 // Register MMS NetworkRequest
1232 NetworkRequest.Builder builder = new NetworkRequest.Builder();
1233 builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
1234 final TestNetworkCallback networkCallback = new TestNetworkCallback();
1235 mCm.requestNetwork(builder.build(), networkCallback);
1236 // Test bringing up MMS cellular network
1237 MockNetworkAgent mmsNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1238 mmsNetworkAgent.addCapability(NET_CAPABILITY_MMS);
1239 mmsNetworkAgent.connectWithoutInternet();
1240 networkCallback.expectCallback(CallbackState.AVAILABLE);
1241 verifyActiveNetwork(TRANSPORT_CELLULAR);
1242 // Test releasing MMS NetworkRequest does not disconnect main cellular NetworkAgent
1243 cv = mmsNetworkAgent.getDisconnectedCV();
1244 mCm.unregisterNetworkCallback(networkCallback);
1246 verifyActiveNetwork(TRANSPORT_CELLULAR);
1250 public void testCaptivePortal() {
1251 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
1252 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
1253 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
1254 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
1256 final TestNetworkCallback validatedCallback = new TestNetworkCallback();
1257 final NetworkRequest validatedRequest = new NetworkRequest.Builder()
1258 .addCapability(NET_CAPABILITY_VALIDATED).build();
1259 mCm.registerNetworkCallback(validatedRequest, validatedCallback);
1261 // Bring up a network with a captive portal.
1262 // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
1263 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1264 mWiFiNetworkAgent.connectWithCaptivePortal();
1265 captivePortalCallback.expectCallback(CallbackState.AVAILABLE);
1267 // Take down network.
1268 // Expect onLost callback.
1269 mWiFiNetworkAgent.disconnect();
1270 captivePortalCallback.expectCallback(CallbackState.LOST);
1272 // Bring up a network with a captive portal.
1273 // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
1274 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1275 mWiFiNetworkAgent.connectWithCaptivePortal();
1276 captivePortalCallback.expectCallback(CallbackState.AVAILABLE);
1278 // Make captive portal disappear then revalidate.
1279 // Expect onLost callback because network no longer provides NET_CAPABILITY_CAPTIVE_PORTAL.
1280 mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 204;
1281 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
1282 captivePortalCallback.expectCallback(CallbackState.LOST);
1284 // Expect NET_CAPABILITY_VALIDATED onAvailable callback.
1285 validatedCallback.expectCallback(CallbackState.AVAILABLE);
1287 // Break network connectivity.
1288 // Expect NET_CAPABILITY_VALIDATED onLost callback.
1289 mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 500;
1290 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), false);
1291 validatedCallback.expectCallback(CallbackState.LOST);
1294 private static class TestKeepaliveCallback extends PacketKeepaliveCallback {
1296 public static enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR };
1298 private class CallbackValue {
1299 public CallbackType callbackType;
1302 public CallbackValue(CallbackType type) {
1303 this.callbackType = type;
1304 this.error = PacketKeepalive.SUCCESS;
1305 assertTrue("onError callback must have error", type != CallbackType.ON_ERROR);
1308 public CallbackValue(CallbackType type, int error) {
1309 this.callbackType = type;
1311 assertEquals("error can only be set for onError", type, CallbackType.ON_ERROR);
1315 public boolean equals(Object o) {
1316 return o instanceof CallbackValue &&
1317 this.callbackType == ((CallbackValue) o).callbackType &&
1318 this.error == ((CallbackValue) o).error;
1322 public String toString() {
1323 return String.format("%s(%s, %d)", getClass().getSimpleName(), callbackType, error);
1327 private LinkedBlockingQueue<CallbackValue> mCallbacks = new LinkedBlockingQueue<>();
1330 public void onStarted() {
1331 mCallbacks.add(new CallbackValue(CallbackType.ON_STARTED));
1335 public void onStopped() {
1336 mCallbacks.add(new CallbackValue(CallbackType.ON_STOPPED));
1340 public void onError(int error) {
1341 mCallbacks.add(new CallbackValue(CallbackType.ON_ERROR, error));
1344 private void expectCallback(CallbackValue callbackValue) {
1348 mCallbacks.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
1349 } catch (InterruptedException e) {
1350 fail(callbackValue.callbackType + " callback not seen after " + TIMEOUT_MS + " ms");
1354 public void expectStarted() {
1355 expectCallback(new CallbackValue(CallbackType.ON_STARTED));
1358 public void expectStopped() {
1359 expectCallback(new CallbackValue(CallbackType.ON_STOPPED));
1362 public void expectError(int error) {
1363 expectCallback(new CallbackValue(CallbackType.ON_ERROR, error));
1367 private Network connectKeepaliveNetwork(LinkProperties lp) {
1368 // Ensure the network is disconnected before we do anything.
1369 if (mWiFiNetworkAgent != null) {
1370 assertNull(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()));
1373 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1374 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1375 mWiFiNetworkAgent.connect(true);
1377 verifyActiveNetwork(TRANSPORT_WIFI);
1378 mWiFiNetworkAgent.sendLinkProperties(lp);
1379 mService.waitForIdle();
1380 return mWiFiNetworkAgent.getNetwork();
1383 public void testPacketKeepalives() throws Exception {
1384 InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
1385 InetAddress notMyIPv4 = InetAddress.getByName("192.0.2.35");
1386 InetAddress myIPv6 = InetAddress.getByName("2001:db8::1");
1387 InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8");
1388 InetAddress dstIPv6 = InetAddress.getByName("2001:4860:4860::8888");
1390 LinkProperties lp = new LinkProperties();
1391 lp.setInterfaceName("wlan12");
1392 lp.addLinkAddress(new LinkAddress(myIPv6, 64));
1393 lp.addLinkAddress(new LinkAddress(myIPv4, 25));
1394 lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
1395 lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
1397 Network notMyNet = new Network(61234);
1398 Network myNet = connectKeepaliveNetwork(lp);
1400 TestKeepaliveCallback callback = new TestKeepaliveCallback();
1403 // Attempt to start keepalives with invalid parameters and check for errors.
1404 ka = mCm.startNattKeepalive(notMyNet, 25, callback, myIPv4, 1234, dstIPv4);
1405 callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK);
1407 ka = mCm.startNattKeepalive(myNet, 19, callback, notMyIPv4, 1234, dstIPv4);
1408 callback.expectError(PacketKeepalive.ERROR_INVALID_INTERVAL);
1410 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 1234, dstIPv6);
1411 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
1413 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv6, 1234, dstIPv4);
1414 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
1416 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv6, 1234, dstIPv6);
1417 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS); // NAT-T is IPv4-only.
1419 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 123456, dstIPv4);
1420 callback.expectError(PacketKeepalive.ERROR_INVALID_PORT);
1422 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 123456, dstIPv4);
1423 callback.expectError(PacketKeepalive.ERROR_INVALID_PORT);
1425 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
1426 callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
1428 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
1429 callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
1431 // Check that a started keepalive can be stopped.
1432 mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS);
1433 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
1434 callback.expectStarted();
1435 mWiFiNetworkAgent.setStopKeepaliveError(PacketKeepalive.SUCCESS);
1437 callback.expectStopped();
1439 // Check that deleting the IP address stops the keepalive.
1440 LinkProperties bogusLp = new LinkProperties(lp);
1441 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
1442 callback.expectStarted();
1443 bogusLp.removeLinkAddress(new LinkAddress(myIPv4, 25));
1444 bogusLp.addLinkAddress(new LinkAddress(notMyIPv4, 25));
1445 mWiFiNetworkAgent.sendLinkProperties(bogusLp);
1446 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
1447 mWiFiNetworkAgent.sendLinkProperties(lp);
1449 // Check that a started keepalive is stopped correctly when the network disconnects.
1450 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
1451 callback.expectStarted();
1452 mWiFiNetworkAgent.disconnect();
1453 callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK);
1455 // ... and that stopping it after that has no adverse effects.
1456 assertNull(mCm.getNetworkCapabilities(myNet));
1460 myNet = connectKeepaliveNetwork(lp);
1461 mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS);
1463 // Check things work as expected when the keepalive is stopped and the network disconnects.
1464 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
1465 callback.expectStarted();
1467 mWiFiNetworkAgent.disconnect();
1468 mService.waitForIdle();
1469 callback.expectStopped();
1472 myNet = connectKeepaliveNetwork(lp);
1473 mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS);
1475 // Check that keepalive slots start from 1 and increment. The first one gets slot 1.
1476 mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
1477 ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
1478 callback.expectStarted();
1480 // The second one gets slot 2.
1481 mWiFiNetworkAgent.setExpectedKeepaliveSlot(2);
1482 TestKeepaliveCallback callback2 = new TestKeepaliveCallback();
1483 PacketKeepalive ka2 = mCm.startNattKeepalive(myNet, 25, callback2, myIPv4, 6789, dstIPv4);
1484 callback2.expectStarted();
1486 // Now stop the first one and create a third. This also gets slot 1.
1488 callback.expectStopped();
1490 mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
1491 TestKeepaliveCallback callback3 = new TestKeepaliveCallback();
1492 PacketKeepalive ka3 = mCm.startNattKeepalive(myNet, 25, callback3, myIPv4, 9876, dstIPv4);
1493 callback3.expectStarted();
1496 callback2.expectStopped();
1499 callback3.expectStopped();