ConnectivityServiceTest.java revision cf4c2c637268b1a2979e20a8b5644916777a02a4
1/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server;
18
19import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
20import static android.net.ConnectivityManager.TYPE_MOBILE;
21import static android.net.ConnectivityManager.TYPE_WIFI;
22import static android.net.ConnectivityManager.getNetworkTypeName;
23import static android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL;
24import static android.net.NetworkCapabilities.NET_CAPABILITY_CBS;
25import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN;
26import static android.net.NetworkCapabilities.NET_CAPABILITY_EIMS;
27import static android.net.NetworkCapabilities.NET_CAPABILITY_FOTA;
28import static android.net.NetworkCapabilities.NET_CAPABILITY_IA;
29import static android.net.NetworkCapabilities.NET_CAPABILITY_IMS;
30import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
31import static android.net.NetworkCapabilities.NET_CAPABILITY_MMS;
32import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
33import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
34import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN;
35import static android.net.NetworkCapabilities.NET_CAPABILITY_RCS;
36import static android.net.NetworkCapabilities.NET_CAPABILITY_SUPL;
37import static android.net.NetworkCapabilities.NET_CAPABILITY_TRUSTED;
38import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
39import static android.net.NetworkCapabilities.NET_CAPABILITY_WIFI_P2P;
40import static android.net.NetworkCapabilities.NET_CAPABILITY_XCAP;
41import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
42import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
43import static org.mockito.Matchers.anyInt;
44import static org.mockito.Matchers.eq;
45import static org.mockito.Matchers.isA;
46import static org.mockito.Mockito.doNothing;
47import static org.mockito.Mockito.doReturn;
48import static org.mockito.Mockito.doThrow;
49import static org.mockito.Mockito.mock;
50import static org.mockito.Mockito.reset;
51import static org.mockito.Mockito.verify;
52
53import android.app.PendingIntent;
54import android.content.BroadcastReceiver;
55import android.content.Context;
56import android.content.ContextWrapper;
57import android.content.Intent;
58import android.content.IntentFilter;
59import android.net.ConnectivityManager;
60import android.net.ConnectivityManager.NetworkCallback;
61import android.net.INetworkPolicyManager;
62import android.net.INetworkStatsService;
63import android.net.LinkProperties;
64import android.net.Network;
65import android.net.NetworkAgent;
66import android.net.NetworkCapabilities;
67import android.net.NetworkConfig;
68import android.net.NetworkFactory;
69import android.net.NetworkInfo;
70import android.net.NetworkInfo.DetailedState;
71import android.net.NetworkMisc;
72import android.net.NetworkRequest;
73import android.net.RouteInfo;
74import android.os.ConditionVariable;
75import android.os.Handler;
76import android.os.HandlerThread;
77import android.os.Looper;
78import android.os.INetworkManagementService;
79import android.test.AndroidTestCase;
80import android.test.suitebuilder.annotation.LargeTest;
81import android.util.Log;
82import android.util.LogPrinter;
83
84import com.android.server.connectivity.NetworkAgentInfo;
85import com.android.server.connectivity.NetworkMonitor;
86
87import org.mockito.ArgumentCaptor;
88
89import java.net.InetAddress;
90import java.util.concurrent.Future;
91import java.util.concurrent.atomic.AtomicBoolean;
92
93/**
94 * Tests for {@link ConnectivityService}.
95 *
96 * Build, install and run with:
97 *  runtest frameworks-services -c com.android.server.ConnectivityServiceTest
98 */
99public class ConnectivityServiceTest extends AndroidTestCase {
100    private static final String TAG = "ConnectivityServiceTest";
101
102    private static final String MOBILE_IFACE = "rmnet3";
103    private static final String WIFI_IFACE = "wlan6";
104
105    private static final RouteInfo MOBILE_ROUTE_V4 = RouteInfo.makeHostRoute(parse("10.0.0.33"),
106                                                                             MOBILE_IFACE);
107    private static final RouteInfo MOBILE_ROUTE_V6 = RouteInfo.makeHostRoute(parse("fd00::33"),
108                                                                             MOBILE_IFACE);
109
110    private static final RouteInfo WIFI_ROUTE_V4 = RouteInfo.makeHostRoute(parse("192.168.0.66"),
111                                                                           parse("192.168.0.1"),
112                                                                           WIFI_IFACE);
113    private static final RouteInfo WIFI_ROUTE_V6 = RouteInfo.makeHostRoute(parse("fd00::66"),
114                                                                           parse("fd00::"),
115                                                                           WIFI_IFACE);
116
117    private INetworkManagementService mNetManager;
118    private INetworkStatsService mStatsService;
119    private INetworkPolicyManager mPolicyService;
120
121    private BroadcastInterceptingContext mServiceContext;
122    private WrappedConnectivityService mService;
123    private ConnectivityManager mCm;
124    private MockNetworkAgent mWiFiNetworkAgent;
125    private MockNetworkAgent mCellNetworkAgent;
126
127    private class MockContext extends BroadcastInterceptingContext {
128        MockContext(Context base) {
129            super(base);
130        }
131
132        @Override
133        public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
134            // PendingIntents sent by the AlarmManager are not intercepted by
135            // BroadcastInterceptingContext so we must really register the receiver.
136            // This shouldn't effect the real NetworkMonitors as the action contains a random token.
137            if (filter.getAction(0).startsWith("android.net.netmon.lingerExpired")) {
138                return getBaseContext().registerReceiver(receiver, filter);
139            } else {
140                return super.registerReceiver(receiver, filter);
141            }
142        }
143
144        @Override
145        public Object getSystemService (String name) {
146            if (name == Context.CONNECTIVITY_SERVICE) return mCm;
147            return super.getSystemService(name);
148        }
149    }
150
151    private class MockNetworkAgent {
152        private final WrappedNetworkMonitor mWrappedNetworkMonitor;
153        private final NetworkInfo mNetworkInfo;
154        private final NetworkCapabilities mNetworkCapabilities;
155        private final Thread mThread;
156        private final ConditionVariable mDisconnected = new ConditionVariable();
157        private int mScore;
158        private NetworkAgent mNetworkAgent;
159
160        MockNetworkAgent(int transport) {
161            final int type = transportToLegacyType(transport);
162            final String typeName = ConnectivityManager.getNetworkTypeName(type);
163            mNetworkInfo = new NetworkInfo(type, 0, typeName, "Mock");
164            mNetworkCapabilities = new NetworkCapabilities();
165            mNetworkCapabilities.addTransportType(transport);
166            switch (transport) {
167                case TRANSPORT_WIFI:
168                    mScore = 60;
169                    break;
170                case TRANSPORT_CELLULAR:
171                    mScore = 50;
172                    break;
173                default:
174                    throw new UnsupportedOperationException("unimplemented network type");
175            }
176            final ConditionVariable initComplete = new ConditionVariable();
177            final ConditionVariable networkMonitorAvailable = mService.getNetworkMonitorCreatedCV();
178            mThread = new Thread() {
179                public void run() {
180                    Looper.prepare();
181                    mNetworkAgent = new NetworkAgent(Looper.myLooper(), mServiceContext,
182                            "Mock" + typeName, mNetworkInfo, mNetworkCapabilities,
183                            new LinkProperties(), mScore, new NetworkMisc()) {
184                        public void unwanted() { mDisconnected.open(); }
185                    };
186                    initComplete.open();
187                    Looper.loop();
188                }
189            };
190            mThread.start();
191            waitFor(initComplete);
192            waitFor(networkMonitorAvailable);
193            mWrappedNetworkMonitor = mService.getLastCreatedWrappedNetworkMonitor();
194        }
195
196        public void adjustScore(int change) {
197            mScore += change;
198            mNetworkAgent.sendNetworkScore(mScore);
199        }
200
201        public void addCapability(int capability) {
202            mNetworkCapabilities.addCapability(capability);
203            mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
204        }
205
206        public void connectWithoutInternet() {
207            mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, null);
208            mNetworkAgent.sendNetworkInfo(mNetworkInfo);
209        }
210
211        /**
212         * Transition this NetworkAgent to CONNECTED state with NET_CAPABILITY_INTERNET.
213         * @param validated Indicate if network should pretend to be validated.
214         */
215        public void connect(boolean validated) {
216            assertEquals(mNetworkInfo.getDetailedState(), DetailedState.IDLE);
217            assertFalse(mNetworkCapabilities.hasCapability(NET_CAPABILITY_INTERNET));
218
219            NetworkCallback callback = null;
220            final ConditionVariable validatedCv = new ConditionVariable();
221            if (validated) {
222                mWrappedNetworkMonitor.gen204ProbeResult = 204;
223                NetworkRequest request = new NetworkRequest.Builder()
224                        .addTransportType(mNetworkCapabilities.getTransportTypes()[0])
225                        .build();
226                callback = new NetworkCallback() {
227                    public void onCapabilitiesChanged(Network network,
228                            NetworkCapabilities networkCapabilities) {
229                        if (network.equals(getNetwork()) &&
230                            networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED)) {
231                            validatedCv.open();
232                        }
233                    }
234                };
235                mCm.registerNetworkCallback(request, callback);
236            }
237            addCapability(NET_CAPABILITY_INTERNET);
238
239            connectWithoutInternet();
240
241            if (validated) {
242                // Wait for network to validate.
243                waitFor(validatedCv);
244                mWrappedNetworkMonitor.gen204ProbeResult = 500;
245            }
246
247            if (callback != null) mCm.unregisterNetworkCallback(callback);
248        }
249
250        public void connectWithCaptivePortal() {
251            mWrappedNetworkMonitor.gen204ProbeResult = 200;
252            connect(false);
253            waitFor(new Criteria() { public boolean get() {
254                NetworkCapabilities caps = mCm.getNetworkCapabilities(getNetwork());
255                return caps != null && caps.hasCapability(NET_CAPABILITY_CAPTIVE_PORTAL);} });
256            mWrappedNetworkMonitor.gen204ProbeResult = 500;
257        }
258
259        public void disconnect() {
260            mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, null);
261            mNetworkAgent.sendNetworkInfo(mNetworkInfo);
262        }
263
264        public Network getNetwork() {
265            return new Network(mNetworkAgent.netId);
266        }
267
268        public ConditionVariable getDisconnectedCV() {
269            return mDisconnected;
270        }
271
272        public WrappedNetworkMonitor getWrappedNetworkMonitor() {
273            return mWrappedNetworkMonitor;
274        }
275    }
276
277    private static class MockNetworkFactory extends NetworkFactory {
278        private final ConditionVariable mNetworkStartedCV = new ConditionVariable();
279        private final ConditionVariable mNetworkStoppedCV = new ConditionVariable();
280        private final ConditionVariable mNetworkRequestedCV = new ConditionVariable();
281        private final ConditionVariable mNetworkReleasedCV = new ConditionVariable();
282        private final AtomicBoolean mNetworkStarted = new AtomicBoolean(false);
283
284        public MockNetworkFactory(Looper looper, Context context, String logTag,
285                NetworkCapabilities filter) {
286            super(looper, context, logTag, filter);
287        }
288
289        public int getMyRequestCount() {
290            return getRequestCount();
291        }
292
293        protected void startNetwork() {
294            mNetworkStarted.set(true);
295            mNetworkStartedCV.open();
296        }
297
298        protected void stopNetwork() {
299            mNetworkStarted.set(false);
300            mNetworkStoppedCV.open();
301        }
302
303        public boolean getMyStartRequested() {
304            return mNetworkStarted.get();
305        }
306
307        public ConditionVariable getNetworkStartedCV() {
308            mNetworkStartedCV.close();
309            return mNetworkStartedCV;
310        }
311
312        public ConditionVariable getNetworkStoppedCV() {
313            mNetworkStoppedCV.close();
314            return mNetworkStoppedCV;
315        }
316
317        protected void needNetworkFor(NetworkRequest networkRequest, int score) {
318            super.needNetworkFor(networkRequest, score);
319            mNetworkRequestedCV.open();
320        }
321
322        protected void releaseNetworkFor(NetworkRequest networkRequest) {
323            super.releaseNetworkFor(networkRequest);
324            mNetworkReleasedCV.open();
325        }
326
327        public ConditionVariable getNetworkRequestedCV() {
328            mNetworkRequestedCV.close();
329            return mNetworkRequestedCV;
330        }
331
332        public ConditionVariable getNetworkReleasedCV() {
333            mNetworkReleasedCV.close();
334            return mNetworkReleasedCV;
335        }
336
337        public void waitForNetworkRequests(final int count) {
338            waitFor(new Criteria() { public boolean get() { return count == getRequestCount(); } });
339        }
340    }
341
342    // NetworkMonitor implementation allowing overriding of Internet connectivity probe result.
343    private class WrappedNetworkMonitor extends NetworkMonitor {
344        // HTTP response code fed back to NetworkMonitor for Internet connectivity probe.
345        public int gen204ProbeResult = 500;
346
347        public WrappedNetworkMonitor(Context context, Handler handler,
348            NetworkAgentInfo networkAgentInfo, NetworkRequest defaultRequest) {
349            super(context, handler, networkAgentInfo, defaultRequest);
350        }
351
352        @Override
353        protected int isCaptivePortal() {
354            return gen204ProbeResult;
355        }
356    }
357
358    private class WrappedConnectivityService extends ConnectivityService {
359        private final ConditionVariable mNetworkMonitorCreated = new ConditionVariable();
360        private WrappedNetworkMonitor mLastCreatedNetworkMonitor;
361
362        public WrappedConnectivityService(Context context, INetworkManagementService netManager,
363                INetworkStatsService statsService, INetworkPolicyManager policyManager) {
364            super(context, netManager, statsService, policyManager);
365        }
366
367        @Override
368        protected int getDefaultTcpRwnd() {
369            // Prevent wrapped ConnectivityService from trying to write to SystemProperties.
370            return 0;
371        }
372
373        @Override
374        protected int reserveNetId() {
375            while (true) {
376                final int netId = super.reserveNetId();
377
378                // Don't overlap test NetIDs with real NetIDs as binding sockets to real networks
379                // can have odd side-effects, like network validations succeeding.
380                final Network[] networks = ConnectivityManager.from(getContext()).getAllNetworks();
381                boolean overlaps = false;
382                for (Network network : networks) {
383                    if (netId == network.netId) {
384                        overlaps = true;
385                        break;
386                    }
387                }
388                if (overlaps) continue;
389
390                return netId;
391            }
392        }
393
394        @Override
395        public NetworkMonitor createNetworkMonitor(Context context, Handler handler,
396                NetworkAgentInfo nai, NetworkRequest defaultRequest) {
397            final WrappedNetworkMonitor monitor = new WrappedNetworkMonitor(context, handler, nai,
398                    defaultRequest);
399            mLastCreatedNetworkMonitor = monitor;
400            mNetworkMonitorCreated.open();
401            return monitor;
402        }
403
404        public WrappedNetworkMonitor getLastCreatedWrappedNetworkMonitor() {
405            return mLastCreatedNetworkMonitor;
406        }
407
408        public ConditionVariable getNetworkMonitorCreatedCV() {
409            mNetworkMonitorCreated.close();
410            return mNetworkMonitorCreated;
411        }
412    }
413
414    private interface Criteria {
415        public boolean get();
416    }
417
418    /**
419     * Wait up to 500ms for {@code criteria.get()} to become true, polling.
420     * Fails if 500ms goes by before {@code criteria.get()} to become true.
421     */
422    static private void waitFor(Criteria criteria) {
423        int delays = 0;
424        while (!criteria.get()) {
425            try {
426                Thread.sleep(100);
427            } catch (InterruptedException e) {
428            }
429            if (++delays == 5) fail();
430        }
431    }
432
433    /**
434     * Wait up to 500ms for {@code conditonVariable} to open.
435     * Fails if 500ms goes by before {@code conditionVariable} opens.
436     */
437    static private void waitFor(ConditionVariable conditionVariable) {
438        assertTrue(conditionVariable.block(500));
439    }
440
441    /**
442     * This should only be used to verify that nothing happens, in other words that no unexpected
443     * changes occur.  It should never be used to wait for a specific positive signal to occur.
444     */
445    private void shortSleep() {
446        // TODO: Instead of sleeping, instead wait for all message loops to idle.
447        try {
448            Thread.sleep(500);
449        } catch (InterruptedException e) {
450        }
451    }
452
453    @Override
454    public void setUp() throws Exception {
455        super.setUp();
456
457        mServiceContext = new MockContext(getContext());
458
459        mNetManager = mock(INetworkManagementService.class);
460        mStatsService = mock(INetworkStatsService.class);
461        mPolicyService = mock(INetworkPolicyManager.class);
462
463        mService = new WrappedConnectivityService(
464                mServiceContext, mNetManager, mStatsService, mPolicyService);
465        mService.systemReady();
466        mCm = new ConnectivityManager(mService);
467    }
468
469    private int transportToLegacyType(int transport) {
470        switch (transport) {
471            case TRANSPORT_WIFI:
472                return TYPE_WIFI;
473            case TRANSPORT_CELLULAR:
474                return TYPE_MOBILE;
475            default:
476                throw new IllegalStateException("Unknown transport" + transport);
477        }
478    }
479
480    private void verifyActiveNetwork(int transport) {
481        // Test getActiveNetworkInfo()
482        assertNotNull(mCm.getActiveNetworkInfo());
483        assertEquals(transportToLegacyType(transport), mCm.getActiveNetworkInfo().getType());
484        // Test getActiveNetwork()
485        assertNotNull(mCm.getActiveNetwork());
486        switch (transport) {
487            case TRANSPORT_WIFI:
488                assertEquals(mCm.getActiveNetwork(), mWiFiNetworkAgent.getNetwork());
489                break;
490            case TRANSPORT_CELLULAR:
491                assertEquals(mCm.getActiveNetwork(), mCellNetworkAgent.getNetwork());
492                break;
493            default:
494                throw new IllegalStateException("Unknown transport" + transport);
495        }
496        // Test getNetworkInfo(Network)
497        assertNotNull(mCm.getNetworkInfo(mCm.getActiveNetwork()));
498        assertEquals(transportToLegacyType(transport), mCm.getNetworkInfo(mCm.getActiveNetwork()).getType());
499        // Test getNetworkCapabilities(Network)
500        assertNotNull(mCm.getNetworkCapabilities(mCm.getActiveNetwork()));
501        assertTrue(mCm.getNetworkCapabilities(mCm.getActiveNetwork()).hasTransport(transport));
502    }
503
504    private void verifyNoNetwork() {
505        // Test getActiveNetworkInfo()
506        assertNull(mCm.getActiveNetworkInfo());
507        // Test getActiveNetwork()
508        assertNull(mCm.getActiveNetwork());
509        // Test getAllNetworks()
510        assertEquals(0, mCm.getAllNetworks().length);
511    }
512
513    /**
514     * Return a ConditionVariable that opens when {@code count} numbers of CONNECTIVITY_ACTION
515     * broadcasts are received.
516     */
517    private ConditionVariable waitForConnectivityBroadcasts(final int count) {
518        final ConditionVariable cv = new ConditionVariable();
519        mServiceContext.registerReceiver(new BroadcastReceiver() {
520                    private int remaining = count;
521                    public void onReceive(Context context, Intent intent) {
522                        if (--remaining == 0) {
523                            cv.open();
524                            mServiceContext.unregisterReceiver(this);
525                        }
526                    }
527                }, new IntentFilter(CONNECTIVITY_ACTION));
528        return cv;
529    }
530
531    @LargeTest
532    public void testLingering() throws Exception {
533        // Decrease linger timeout to the minimum allowed by AlarmManagerService.
534        NetworkMonitor.SetDefaultLingerTime(5000);
535        verifyNoNetwork();
536        mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
537        mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
538        assertNull(mCm.getActiveNetworkInfo());
539        assertNull(mCm.getActiveNetwork());
540        // Test bringing up validated cellular.
541        ConditionVariable cv = waitForConnectivityBroadcasts(1);
542        mCellNetworkAgent.connect(true);
543        waitFor(cv);
544        verifyActiveNetwork(TRANSPORT_CELLULAR);
545        assertEquals(2, mCm.getAllNetworks().length);
546        assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) ||
547                mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork()));
548        assertTrue(mCm.getAllNetworks()[0].equals(mWiFiNetworkAgent.getNetwork()) ||
549                mCm.getAllNetworks()[1].equals(mWiFiNetworkAgent.getNetwork()));
550        // Test bringing up validated WiFi.
551        cv = waitForConnectivityBroadcasts(2);
552        mWiFiNetworkAgent.connect(true);
553        waitFor(cv);
554        verifyActiveNetwork(TRANSPORT_WIFI);
555        assertEquals(2, mCm.getAllNetworks().length);
556        assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) ||
557                mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork()));
558        assertTrue(mCm.getAllNetworks()[0].equals(mCellNetworkAgent.getNetwork()) ||
559                mCm.getAllNetworks()[1].equals(mCellNetworkAgent.getNetwork()));
560        // Test cellular linger timeout.
561        try {
562            Thread.sleep(6000);
563        } catch (InterruptedException e) {
564        }
565        verifyActiveNetwork(TRANSPORT_WIFI);
566        assertEquals(1, mCm.getAllNetworks().length);
567        assertEquals(mCm.getAllNetworks()[0], mCm.getActiveNetwork());
568        // Test WiFi disconnect.
569        cv = waitForConnectivityBroadcasts(1);
570        mWiFiNetworkAgent.disconnect();
571        waitFor(cv);
572        verifyNoNetwork();
573    }
574
575    @LargeTest
576    public void testValidatedCellularOutscoresUnvalidatedWiFi() throws Exception {
577        // Test bringing up unvalidated WiFi
578        mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
579        ConditionVariable cv = waitForConnectivityBroadcasts(1);
580        mWiFiNetworkAgent.connect(false);
581        waitFor(cv);
582        verifyActiveNetwork(TRANSPORT_WIFI);
583        // Test bringing up unvalidated cellular
584        mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
585        mCellNetworkAgent.connect(false);
586        shortSleep();
587        verifyActiveNetwork(TRANSPORT_WIFI);
588        // Test cellular disconnect.
589        mCellNetworkAgent.disconnect();
590        shortSleep();
591        verifyActiveNetwork(TRANSPORT_WIFI);
592        // Test bringing up validated cellular
593        mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
594        cv = waitForConnectivityBroadcasts(2);
595        mCellNetworkAgent.connect(true);
596        waitFor(cv);
597        verifyActiveNetwork(TRANSPORT_CELLULAR);
598        // Test cellular disconnect.
599        cv = waitForConnectivityBroadcasts(2);
600        mCellNetworkAgent.disconnect();
601        waitFor(cv);
602        verifyActiveNetwork(TRANSPORT_WIFI);
603        // Test WiFi disconnect.
604        cv = waitForConnectivityBroadcasts(1);
605        mWiFiNetworkAgent.disconnect();
606        waitFor(cv);
607        verifyNoNetwork();
608    }
609
610    @LargeTest
611    public void testUnvalidatedWifiOutscoresUnvalidatedCellular() throws Exception {
612        // Test bringing up unvalidated cellular.
613        mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
614        ConditionVariable cv = waitForConnectivityBroadcasts(1);
615        mCellNetworkAgent.connect(false);
616        waitFor(cv);
617        verifyActiveNetwork(TRANSPORT_CELLULAR);
618        // Test bringing up unvalidated WiFi.
619        mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
620        cv = waitForConnectivityBroadcasts(2);
621        mWiFiNetworkAgent.connect(false);
622        waitFor(cv);
623        verifyActiveNetwork(TRANSPORT_WIFI);
624        // Test WiFi disconnect.
625        cv = waitForConnectivityBroadcasts(2);
626        mWiFiNetworkAgent.disconnect();
627        waitFor(cv);
628        verifyActiveNetwork(TRANSPORT_CELLULAR);
629        // Test cellular disconnect.
630        cv = waitForConnectivityBroadcasts(1);
631        mCellNetworkAgent.disconnect();
632        waitFor(cv);
633        verifyNoNetwork();
634    }
635
636    @LargeTest
637    public void testUnlingeringDoesNotValidate() throws Exception {
638        // Test bringing up unvalidated WiFi.
639        mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
640        ConditionVariable cv = waitForConnectivityBroadcasts(1);
641        mWiFiNetworkAgent.connect(false);
642        waitFor(cv);
643        verifyActiveNetwork(TRANSPORT_WIFI);
644        assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
645                NET_CAPABILITY_VALIDATED));
646        // Test bringing up validated cellular.
647        mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
648        cv = waitForConnectivityBroadcasts(2);
649        mCellNetworkAgent.connect(true);
650        waitFor(cv);
651        verifyActiveNetwork(TRANSPORT_CELLULAR);
652        assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
653                NET_CAPABILITY_VALIDATED));
654        // Test cellular disconnect.
655        cv = waitForConnectivityBroadcasts(2);
656        mCellNetworkAgent.disconnect();
657        waitFor(cv);
658        verifyActiveNetwork(TRANSPORT_WIFI);
659        // Unlingering a network should not cause it to be marked as validated.
660        assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
661                NET_CAPABILITY_VALIDATED));
662    }
663
664    @LargeTest
665    public void testCellularOutscoresWeakWifi() throws Exception {
666        // Test bringing up validated cellular.
667        mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
668        ConditionVariable cv = waitForConnectivityBroadcasts(1);
669        mCellNetworkAgent.connect(true);
670        waitFor(cv);
671        verifyActiveNetwork(TRANSPORT_CELLULAR);
672        // Test bringing up validated WiFi.
673        mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
674        cv = waitForConnectivityBroadcasts(2);
675        mWiFiNetworkAgent.connect(true);
676        waitFor(cv);
677        verifyActiveNetwork(TRANSPORT_WIFI);
678        // Test WiFi getting really weak.
679        cv = waitForConnectivityBroadcasts(2);
680        mWiFiNetworkAgent.adjustScore(-11);
681        waitFor(cv);
682        verifyActiveNetwork(TRANSPORT_CELLULAR);
683        // Test WiFi restoring signal strength.
684        cv = waitForConnectivityBroadcasts(2);
685        mWiFiNetworkAgent.adjustScore(11);
686        waitFor(cv);
687        verifyActiveNetwork(TRANSPORT_WIFI);
688        mCellNetworkAgent.disconnect();
689        mWiFiNetworkAgent.disconnect();
690    }
691
692    @LargeTest
693    public void testReapingNetwork() throws Exception {
694        // Test bringing up WiFi without NET_CAPABILITY_INTERNET.
695        // Expect it to be torn down immediately because it satisfies no requests.
696        mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
697        ConditionVariable cv = mWiFiNetworkAgent.getDisconnectedCV();
698        mWiFiNetworkAgent.connectWithoutInternet();
699        waitFor(cv);
700        // Test bringing up cellular without NET_CAPABILITY_INTERNET.
701        // Expect it to be torn down immediately because it satisfies no requests.
702        mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
703        cv = mCellNetworkAgent.getDisconnectedCV();
704        mCellNetworkAgent.connectWithoutInternet();
705        waitFor(cv);
706        // Test bringing up validated WiFi.
707        mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
708        cv = waitForConnectivityBroadcasts(1);
709        mWiFiNetworkAgent.connect(true);
710        waitFor(cv);
711        verifyActiveNetwork(TRANSPORT_WIFI);
712        // Test bringing up unvalidated cellular.
713        // Expect it to be torn down because it could never be the highest scoring network
714        // satisfying the default request even if it validated.
715        mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
716        cv = mCellNetworkAgent.getDisconnectedCV();
717        mCellNetworkAgent.connect(false);
718        waitFor(cv);
719        verifyActiveNetwork(TRANSPORT_WIFI);
720        cv = mWiFiNetworkAgent.getDisconnectedCV();
721        mWiFiNetworkAgent.disconnect();
722        waitFor(cv);
723    }
724
725    @LargeTest
726    public void testCellularFallback() throws Exception {
727        // Test bringing up validated cellular.
728        mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
729        ConditionVariable cv = waitForConnectivityBroadcasts(1);
730        mCellNetworkAgent.connect(true);
731        waitFor(cv);
732        verifyActiveNetwork(TRANSPORT_CELLULAR);
733        // Test bringing up validated WiFi.
734        mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
735        cv = waitForConnectivityBroadcasts(2);
736        mWiFiNetworkAgent.connect(true);
737        waitFor(cv);
738        verifyActiveNetwork(TRANSPORT_WIFI);
739        // Reevaluate WiFi (it'll instantly fail DNS).
740        cv = waitForConnectivityBroadcasts(2);
741        assertTrue(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
742                NET_CAPABILITY_VALIDATED));
743        mCm.reportBadNetwork(mWiFiNetworkAgent.getNetwork());
744        // Should quickly fall back to Cellular.
745        waitFor(cv);
746        assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
747                NET_CAPABILITY_VALIDATED));
748        verifyActiveNetwork(TRANSPORT_CELLULAR);
749        // Reevaluate cellular (it'll instantly fail DNS).
750        cv = waitForConnectivityBroadcasts(2);
751        assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
752                NET_CAPABILITY_VALIDATED));
753        mCm.reportBadNetwork(mCellNetworkAgent.getNetwork());
754        // Should quickly fall back to WiFi.
755        waitFor(cv);
756        assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
757                NET_CAPABILITY_VALIDATED));
758        assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
759                NET_CAPABILITY_VALIDATED));
760        verifyActiveNetwork(TRANSPORT_WIFI);
761        mCellNetworkAgent.disconnect();
762        mWiFiNetworkAgent.disconnect();
763    }
764
765    @LargeTest
766    public void testWiFiFallback() throws Exception {
767        // Test bringing up unvalidated WiFi.
768        mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
769        ConditionVariable cv = waitForConnectivityBroadcasts(1);
770        mWiFiNetworkAgent.connect(false);
771        waitFor(cv);
772        verifyActiveNetwork(TRANSPORT_WIFI);
773        // Test bringing up validated cellular.
774        mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
775        cv = waitForConnectivityBroadcasts(2);
776        mCellNetworkAgent.connect(true);
777        waitFor(cv);
778        verifyActiveNetwork(TRANSPORT_CELLULAR);
779        // Reevaluate cellular (it'll instantly fail DNS).
780        cv = waitForConnectivityBroadcasts(2);
781        assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
782                NET_CAPABILITY_VALIDATED));
783        mCm.reportBadNetwork(mCellNetworkAgent.getNetwork());
784        // Should quickly fall back to WiFi.
785        waitFor(cv);
786        assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
787                NET_CAPABILITY_VALIDATED));
788        verifyActiveNetwork(TRANSPORT_WIFI);
789        mCellNetworkAgent.disconnect();
790        mWiFiNetworkAgent.disconnect();
791    }
792
793    enum CallbackState {
794        NONE,
795        AVAILABLE,
796        LOSING,
797        LOST
798    }
799
800    private class TestNetworkCallback extends NetworkCallback {
801        private final ConditionVariable mConditionVariable = new ConditionVariable();
802        private CallbackState mLastCallback = CallbackState.NONE;
803
804        public void onAvailable(Network network) {
805            assertEquals(CallbackState.NONE, mLastCallback);
806            mLastCallback = CallbackState.AVAILABLE;
807            mConditionVariable.open();
808        }
809
810        public void onLosing(Network network, int maxMsToLive) {
811            assertEquals(CallbackState.NONE, mLastCallback);
812            mLastCallback = CallbackState.LOSING;
813            mConditionVariable.open();
814        }
815
816        public void onLost(Network network) {
817            assertEquals(CallbackState.NONE, mLastCallback);
818            mLastCallback = CallbackState.LOST;
819            mConditionVariable.open();
820        }
821
822        ConditionVariable getConditionVariable() {
823            mLastCallback = CallbackState.NONE;
824            mConditionVariable.close();
825            return mConditionVariable;
826        }
827
828        CallbackState getLastCallback() {
829            return mLastCallback;
830        }
831    }
832
833    @LargeTest
834    public void testStateChangeNetworkCallbacks() throws Exception {
835        final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
836        final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
837        final NetworkRequest wifiRequest = new NetworkRequest.Builder()
838                .addTransportType(TRANSPORT_WIFI).build();
839        final NetworkRequest cellRequest = new NetworkRequest.Builder()
840                .addTransportType(TRANSPORT_CELLULAR).build();
841        mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
842        mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
843
844        // Test unvalidated networks
845        ConditionVariable cellCv = cellNetworkCallback.getConditionVariable();
846        ConditionVariable wifiCv = wifiNetworkCallback.getConditionVariable();
847        ConditionVariable cv = waitForConnectivityBroadcasts(1);
848        mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
849        mCellNetworkAgent.connect(false);
850        waitFor(cellCv);
851        assertEquals(CallbackState.AVAILABLE, cellNetworkCallback.getLastCallback());
852        assertEquals(CallbackState.NONE, wifiNetworkCallback.getLastCallback());
853        assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
854        waitFor(cv);
855
856        cellCv = cellNetworkCallback.getConditionVariable();
857        wifiCv = wifiNetworkCallback.getConditionVariable();
858        // This should not trigger spurious onAvailable() callbacks, b/21762680.
859        mCellNetworkAgent.adjustScore(-1);
860        shortSleep();
861        assertEquals(CallbackState.NONE, wifiNetworkCallback.getLastCallback());
862        assertEquals(CallbackState.NONE, cellNetworkCallback.getLastCallback());
863        assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
864
865        cellCv = cellNetworkCallback.getConditionVariable();
866        wifiCv = wifiNetworkCallback.getConditionVariable();
867        cv = waitForConnectivityBroadcasts(2);
868        mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
869        mWiFiNetworkAgent.connect(false);
870        waitFor(wifiCv);
871        assertEquals(CallbackState.AVAILABLE, wifiNetworkCallback.getLastCallback());
872        assertEquals(CallbackState.NONE, cellNetworkCallback.getLastCallback());
873        assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
874        waitFor(cv);
875
876        cellCv = cellNetworkCallback.getConditionVariable();
877        wifiCv = wifiNetworkCallback.getConditionVariable();
878        cv = waitForConnectivityBroadcasts(2);
879        mWiFiNetworkAgent.disconnect();
880        waitFor(wifiCv);
881        assertEquals(CallbackState.LOST, wifiNetworkCallback.getLastCallback());
882        assertEquals(CallbackState.NONE, cellNetworkCallback.getLastCallback());
883        waitFor(cv);
884
885        cellCv = cellNetworkCallback.getConditionVariable();
886        wifiCv = wifiNetworkCallback.getConditionVariable();
887        cv = waitForConnectivityBroadcasts(1);
888        mCellNetworkAgent.disconnect();
889        waitFor(cellCv);
890        assertEquals(CallbackState.LOST, cellNetworkCallback.getLastCallback());
891        assertEquals(CallbackState.NONE, wifiNetworkCallback.getLastCallback());
892        waitFor(cv);
893
894        // Test validated networks
895
896        cellCv = cellNetworkCallback.getConditionVariable();
897        wifiCv = wifiNetworkCallback.getConditionVariable();
898        mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
899        mCellNetworkAgent.connect(true);
900        waitFor(cellCv);
901        assertEquals(CallbackState.AVAILABLE, cellNetworkCallback.getLastCallback());
902        assertEquals(CallbackState.NONE, wifiNetworkCallback.getLastCallback());
903        assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
904
905        cellCv = cellNetworkCallback.getConditionVariable();
906        wifiCv = wifiNetworkCallback.getConditionVariable();
907        // This should not trigger spurious onAvailable() callbacks, b/21762680.
908        mCellNetworkAgent.adjustScore(-1);
909        shortSleep();
910        assertEquals(CallbackState.NONE, wifiNetworkCallback.getLastCallback());
911        assertEquals(CallbackState.NONE, cellNetworkCallback.getLastCallback());
912        assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
913
914        cellCv = cellNetworkCallback.getConditionVariable();
915        wifiCv = wifiNetworkCallback.getConditionVariable();
916        mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
917        mWiFiNetworkAgent.connect(true);
918        waitFor(wifiCv);
919        assertEquals(CallbackState.AVAILABLE, wifiNetworkCallback.getLastCallback());
920        waitFor(cellCv);
921        assertEquals(CallbackState.LOSING, cellNetworkCallback.getLastCallback());
922        assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
923
924        cellCv = cellNetworkCallback.getConditionVariable();
925        wifiCv = wifiNetworkCallback.getConditionVariable();
926        mWiFiNetworkAgent.disconnect();
927        waitFor(wifiCv);
928        assertEquals(CallbackState.LOST, wifiNetworkCallback.getLastCallback());
929        assertEquals(CallbackState.NONE, cellNetworkCallback.getLastCallback());
930
931        cellCv = cellNetworkCallback.getConditionVariable();
932        wifiCv = wifiNetworkCallback.getConditionVariable();
933        mCellNetworkAgent.disconnect();
934        waitFor(cellCv);
935        assertEquals(CallbackState.LOST, cellNetworkCallback.getLastCallback());
936        assertEquals(CallbackState.NONE, wifiNetworkCallback.getLastCallback());
937    }
938
939    private void tryNetworkFactoryRequests(int capability) throws Exception {
940        NetworkCapabilities filter = new NetworkCapabilities();
941        filter.addCapability(capability);
942        final HandlerThread handlerThread = new HandlerThread("testNetworkFactoryRequests");
943        handlerThread.start();
944        final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
945                mServiceContext, "testFactory", filter);
946        testFactory.setScoreFilter(40);
947        ConditionVariable cv = testFactory.getNetworkStartedCV();
948        testFactory.register();
949        int expectedRequestCount = 1;
950        NetworkCallback networkCallback = null;
951        // For non-INTERNET capabilities we cannot rely on the default request being present, so
952        // add one.
953        if (capability != NET_CAPABILITY_INTERNET) {
954            testFactory.waitForNetworkRequests(1);
955            assertFalse(testFactory.getMyStartRequested());
956            NetworkRequest request = new NetworkRequest.Builder().addCapability(capability).build();
957            networkCallback = new NetworkCallback();
958            mCm.requestNetwork(request, networkCallback);
959            expectedRequestCount++;
960        }
961        waitFor(cv);
962        assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
963        assertTrue(testFactory.getMyStartRequested());
964
965        // Now bring in a higher scored network.
966        MockNetworkAgent testAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
967        // Rather than create a validated network which complicates things by registering it's
968        // own NetworkRequest during startup, just bump up the score to cancel out the
969        // unvalidated penalty.
970        testAgent.adjustScore(40);
971        cv = testFactory.getNetworkStoppedCV();
972        testAgent.connect(false);
973        testAgent.addCapability(capability);
974        waitFor(cv);
975        assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
976        assertFalse(testFactory.getMyStartRequested());
977
978        // Bring in a bunch of requests.
979        ConnectivityManager.NetworkCallback[] networkCallbacks =
980                new ConnectivityManager.NetworkCallback[10];
981        for (int i = 0; i< networkCallbacks.length; i++) {
982            networkCallbacks[i] = new ConnectivityManager.NetworkCallback();
983            NetworkRequest.Builder builder = new NetworkRequest.Builder();
984            builder.addCapability(capability);
985            mCm.requestNetwork(builder.build(), networkCallbacks[i]);
986        }
987        testFactory.waitForNetworkRequests(10 + expectedRequestCount);
988        assertFalse(testFactory.getMyStartRequested());
989
990        // Remove the requests.
991        for (int i = 0; i < networkCallbacks.length; i++) {
992            mCm.unregisterNetworkCallback(networkCallbacks[i]);
993        }
994        testFactory.waitForNetworkRequests(expectedRequestCount);
995        assertFalse(testFactory.getMyStartRequested());
996
997        // Drop the higher scored network.
998        cv = testFactory.getNetworkStartedCV();
999        testAgent.disconnect();
1000        waitFor(cv);
1001        assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
1002        assertTrue(testFactory.getMyStartRequested());
1003
1004        testFactory.unregister();
1005        if (networkCallback != null) mCm.unregisterNetworkCallback(networkCallback);
1006        handlerThread.quit();
1007    }
1008
1009    @LargeTest
1010    public void testNetworkFactoryRequests() throws Exception {
1011        tryNetworkFactoryRequests(NET_CAPABILITY_MMS);
1012        tryNetworkFactoryRequests(NET_CAPABILITY_SUPL);
1013        tryNetworkFactoryRequests(NET_CAPABILITY_DUN);
1014        tryNetworkFactoryRequests(NET_CAPABILITY_FOTA);
1015        tryNetworkFactoryRequests(NET_CAPABILITY_IMS);
1016        tryNetworkFactoryRequests(NET_CAPABILITY_CBS);
1017        tryNetworkFactoryRequests(NET_CAPABILITY_WIFI_P2P);
1018        tryNetworkFactoryRequests(NET_CAPABILITY_IA);
1019        tryNetworkFactoryRequests(NET_CAPABILITY_RCS);
1020        tryNetworkFactoryRequests(NET_CAPABILITY_XCAP);
1021        tryNetworkFactoryRequests(NET_CAPABILITY_EIMS);
1022        tryNetworkFactoryRequests(NET_CAPABILITY_NOT_METERED);
1023        tryNetworkFactoryRequests(NET_CAPABILITY_INTERNET);
1024        tryNetworkFactoryRequests(NET_CAPABILITY_TRUSTED);
1025        tryNetworkFactoryRequests(NET_CAPABILITY_NOT_VPN);
1026        // Skipping VALIDATED and CAPTIVE_PORTAL as they're disallowed.
1027    }
1028
1029    @LargeTest
1030    public void testNoMutableNetworkRequests() throws Exception {
1031        PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, new Intent("a"), 0);
1032        NetworkRequest.Builder builder = new NetworkRequest.Builder();
1033        builder.addCapability(NET_CAPABILITY_VALIDATED);
1034        try {
1035            mCm.requestNetwork(builder.build(), new NetworkCallback());
1036            fail();
1037        } catch (IllegalArgumentException expected) {}
1038        try {
1039            mCm.requestNetwork(builder.build(), pendingIntent);
1040            fail();
1041        } catch (IllegalArgumentException expected) {}
1042        builder = new NetworkRequest.Builder();
1043        builder.addCapability(NET_CAPABILITY_CAPTIVE_PORTAL);
1044        try {
1045            mCm.requestNetwork(builder.build(), new NetworkCallback());
1046            fail();
1047        } catch (IllegalArgumentException expected) {}
1048        try {
1049            mCm.requestNetwork(builder.build(), pendingIntent);
1050            fail();
1051        } catch (IllegalArgumentException expected) {}
1052    }
1053
1054    @LargeTest
1055    public void testMMSonWiFi() throws Exception {
1056        // Test bringing up cellular without MMS NetworkRequest gets reaped
1057        mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1058        mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS);
1059        ConditionVariable cv = mCellNetworkAgent.getDisconnectedCV();
1060        mCellNetworkAgent.connectWithoutInternet();
1061        waitFor(cv);
1062        waitFor(new Criteria() {
1063                public boolean get() { return mCm.getAllNetworks().length == 0; } });
1064        verifyNoNetwork();
1065        // Test bringing up validated WiFi.
1066        mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1067        cv = waitForConnectivityBroadcasts(1);
1068        mWiFiNetworkAgent.connect(true);
1069        waitFor(cv);
1070        verifyActiveNetwork(TRANSPORT_WIFI);
1071        // Register MMS NetworkRequest
1072        NetworkRequest.Builder builder = new NetworkRequest.Builder();
1073        builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
1074        final TestNetworkCallback networkCallback = new TestNetworkCallback();
1075        mCm.requestNetwork(builder.build(), networkCallback);
1076        // Test bringing up unvalidated cellular with MMS
1077        mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1078        mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS);
1079        cv = networkCallback.getConditionVariable();
1080        mCellNetworkAgent.connectWithoutInternet();
1081        waitFor(cv);
1082        assertEquals(CallbackState.AVAILABLE, networkCallback.getLastCallback());
1083        verifyActiveNetwork(TRANSPORT_WIFI);
1084        // Test releasing NetworkRequest disconnects cellular with MMS
1085        cv = mCellNetworkAgent.getDisconnectedCV();
1086        mCm.unregisterNetworkCallback(networkCallback);
1087        waitFor(cv);
1088        verifyActiveNetwork(TRANSPORT_WIFI);
1089    }
1090
1091    @LargeTest
1092    public void testMMSonCell() throws Exception {
1093        // Test bringing up cellular without MMS
1094        mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1095        ConditionVariable cv = waitForConnectivityBroadcasts(1);
1096        mCellNetworkAgent.connect(false);
1097        waitFor(cv);
1098        verifyActiveNetwork(TRANSPORT_CELLULAR);
1099        // Register MMS NetworkRequest
1100        NetworkRequest.Builder builder = new NetworkRequest.Builder();
1101        builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
1102        final TestNetworkCallback networkCallback = new TestNetworkCallback();
1103        mCm.requestNetwork(builder.build(), networkCallback);
1104        // Test bringing up MMS cellular network
1105        cv = networkCallback.getConditionVariable();
1106        MockNetworkAgent mmsNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1107        mmsNetworkAgent.addCapability(NET_CAPABILITY_MMS);
1108        mmsNetworkAgent.connectWithoutInternet();
1109        waitFor(cv);
1110        assertEquals(CallbackState.AVAILABLE, networkCallback.getLastCallback());
1111        verifyActiveNetwork(TRANSPORT_CELLULAR);
1112        // Test releasing MMS NetworkRequest does not disconnect main cellular NetworkAgent
1113        cv = mmsNetworkAgent.getDisconnectedCV();
1114        mCm.unregisterNetworkCallback(networkCallback);
1115        waitFor(cv);
1116        verifyActiveNetwork(TRANSPORT_CELLULAR);
1117    }
1118
1119    @LargeTest
1120    public void testCaptivePortal() {
1121        final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
1122        final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
1123                .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
1124        mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
1125
1126        final TestNetworkCallback validatedCallback = new TestNetworkCallback();
1127        final NetworkRequest validatedRequest = new NetworkRequest.Builder()
1128                .addCapability(NET_CAPABILITY_VALIDATED).build();
1129        mCm.registerNetworkCallback(validatedRequest, validatedCallback);
1130        ConditionVariable validatedCv = validatedCallback.getConditionVariable();
1131
1132        // Bring up a network with a captive portal.
1133        // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
1134        ConditionVariable cv = captivePortalCallback.getConditionVariable();
1135        mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1136        mWiFiNetworkAgent.connectWithCaptivePortal();
1137        waitFor(cv);
1138        assertEquals(CallbackState.AVAILABLE, captivePortalCallback.getLastCallback());
1139
1140        // Take down network.
1141        // Expect onLost callback.
1142        cv = captivePortalCallback.getConditionVariable();
1143        mWiFiNetworkAgent.disconnect();
1144        waitFor(cv);
1145        assertEquals(CallbackState.LOST, captivePortalCallback.getLastCallback());
1146
1147        // Bring up a network with a captive portal.
1148        // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
1149        cv = captivePortalCallback.getConditionVariable();
1150        mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1151        mWiFiNetworkAgent.connectWithCaptivePortal();
1152        waitFor(cv);
1153        assertEquals(CallbackState.AVAILABLE, captivePortalCallback.getLastCallback());
1154
1155        // Make captive portal disappear then revalidate.
1156        // Expect onLost callback because network no longer provides NET_CAPABILITY_CAPTIVE_PORTAL.
1157        cv = captivePortalCallback.getConditionVariable();
1158        mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 204;
1159        mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
1160        waitFor(cv);
1161        assertEquals(CallbackState.LOST, captivePortalCallback.getLastCallback());
1162
1163        // Expect NET_CAPABILITY_VALIDATED onAvailable callback.
1164        waitFor(validatedCv);
1165        assertEquals(CallbackState.AVAILABLE, validatedCallback.getLastCallback());
1166
1167        // Break network connectivity.
1168        // Expect NET_CAPABILITY_VALIDATED onLost callback.
1169        validatedCv = validatedCallback.getConditionVariable();
1170        mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 500;
1171        mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), false);
1172        waitFor(validatedCv);
1173        assertEquals(CallbackState.LOST, validatedCallback.getLastCallback());
1174    }
1175
1176//    @Override
1177//    public void tearDown() throws Exception {
1178//        super.tearDown();
1179//    }
1180//
1181//    public void testMobileConnectedAddedRoutes() throws Exception {
1182//        Future<?> nextConnBroadcast;
1183//
1184//        // bring up mobile network
1185//        mMobile.info.setDetailedState(DetailedState.CONNECTED, null, null);
1186//        mMobile.link.setInterfaceName(MOBILE_IFACE);
1187//        mMobile.link.addRoute(MOBILE_ROUTE_V4);
1188//        mMobile.link.addRoute(MOBILE_ROUTE_V6);
1189//        mMobile.doReturnDefaults();
1190//
1191//        cv = waitForConnectivityBroadcasts(1);
1192//        mTrackerHandler.obtainMessage(EVENT_STATE_CHANGED, mMobile.info).sendToTarget();
1193//        waitFor(cv);
1194//
1195//        // verify that both routes were added
1196//        int mobileNetId = mMobile.tracker.getNetwork().netId;
1197//        verify(mNetManager).addRoute(eq(mobileNetId), eq(MOBILE_ROUTE_V4));
1198//        verify(mNetManager).addRoute(eq(mobileNetId), eq(MOBILE_ROUTE_V6));
1199//    }
1200//
1201//    public void testMobileWifiHandoff() throws Exception {
1202//        Future<?> nextConnBroadcast;
1203//
1204//        // bring up mobile network
1205//        mMobile.info.setDetailedState(DetailedState.CONNECTED, null, null);
1206//        mMobile.link.setInterfaceName(MOBILE_IFACE);
1207//        mMobile.link.addRoute(MOBILE_ROUTE_V4);
1208//        mMobile.link.addRoute(MOBILE_ROUTE_V6);
1209//        mMobile.doReturnDefaults();
1210//
1211//        cv = waitForConnectivityBroadcasts(1);
1212//        mTrackerHandler.obtainMessage(EVENT_STATE_CHANGED, mMobile.info).sendToTarget();
1213//        waitFor(cv);
1214//
1215//        reset(mNetManager);
1216//
1217//        // now bring up wifi network
1218//        mWifi.info.setDetailedState(DetailedState.CONNECTED, null, null);
1219//        mWifi.link.setInterfaceName(WIFI_IFACE);
1220//        mWifi.link.addRoute(WIFI_ROUTE_V4);
1221//        mWifi.link.addRoute(WIFI_ROUTE_V6);
1222//        mWifi.doReturnDefaults();
1223//
1224//        // expect that mobile will be torn down
1225//        doReturn(true).when(mMobile.tracker).teardown();
1226//
1227//        cv = waitForConnectivityBroadcasts(1);
1228//        mTrackerHandler.obtainMessage(EVENT_STATE_CHANGED, mWifi.info).sendToTarget();
1229//        waitFor(cv);
1230//
1231//        // verify that wifi routes added, and teardown requested
1232//        int wifiNetId = mWifi.tracker.getNetwork().netId;
1233//        verify(mNetManager).addRoute(eq(wifiNetId), eq(WIFI_ROUTE_V4));
1234//        verify(mNetManager).addRoute(eq(wifiNetId), eq(WIFI_ROUTE_V6));
1235//        verify(mMobile.tracker).teardown();
1236//
1237//        int mobileNetId = mMobile.tracker.getNetwork().netId;
1238//
1239//        reset(mNetManager, mMobile.tracker);
1240//
1241//        // tear down mobile network, as requested
1242//        mMobile.info.setDetailedState(DetailedState.DISCONNECTED, null, null);
1243//        mMobile.link.clear();
1244//        mMobile.doReturnDefaults();
1245//
1246//        cv = waitForConnectivityBroadcasts(1);
1247//        mTrackerHandler.obtainMessage(EVENT_STATE_CHANGED, mMobile.info).sendToTarget();
1248//        waitFor(cv);
1249//
1250//        verify(mNetManager).removeRoute(eq(mobileNetId), eq(MOBILE_ROUTE_V4));
1251//        verify(mNetManager).removeRoute(eq(mobileNetId), eq(MOBILE_ROUTE_V6));
1252//
1253//    }
1254
1255    private static InetAddress parse(String addr) {
1256        return InetAddress.parseNumericAddress(addr);
1257    }
1258
1259}
1260