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(getContext(), 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        // Verify NOT_RESTRICTED is set appropriately
941        final NetworkCapabilities nc = new NetworkRequest.Builder().addCapability(capability)
942                .build().networkCapabilities;
943        if (capability == NET_CAPABILITY_CBS || capability == NET_CAPABILITY_DUN ||
944                capability == NET_CAPABILITY_EIMS || capability == NET_CAPABILITY_FOTA ||
945                capability == NET_CAPABILITY_IA || capability == NET_CAPABILITY_IMS ||
946                capability == NET_CAPABILITY_RCS || capability == NET_CAPABILITY_XCAP) {
947            assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
948        } else {
949            assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
950        }
951
952        NetworkCapabilities filter = new NetworkCapabilities();
953        filter.addCapability(capability);
954        final HandlerThread handlerThread = new HandlerThread("testNetworkFactoryRequests");
955        handlerThread.start();
956        final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
957                mServiceContext, "testFactory", filter);
958        testFactory.setScoreFilter(40);
959        ConditionVariable cv = testFactory.getNetworkStartedCV();
960        testFactory.register();
961        int expectedRequestCount = 1;
962        NetworkCallback networkCallback = null;
963        // For non-INTERNET capabilities we cannot rely on the default request being present, so
964        // add one.
965        if (capability != NET_CAPABILITY_INTERNET) {
966            testFactory.waitForNetworkRequests(1);
967            assertFalse(testFactory.getMyStartRequested());
968            NetworkRequest request = new NetworkRequest.Builder().addCapability(capability).build();
969            networkCallback = new NetworkCallback();
970            mCm.requestNetwork(request, networkCallback);
971            expectedRequestCount++;
972        }
973        waitFor(cv);
974        assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
975        assertTrue(testFactory.getMyStartRequested());
976
977        // Now bring in a higher scored network.
978        MockNetworkAgent testAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
979        // Rather than create a validated network which complicates things by registering it's
980        // own NetworkRequest during startup, just bump up the score to cancel out the
981        // unvalidated penalty.
982        testAgent.adjustScore(40);
983        cv = testFactory.getNetworkStoppedCV();
984        testAgent.connect(false);
985        testAgent.addCapability(capability);
986        waitFor(cv);
987        assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
988        assertFalse(testFactory.getMyStartRequested());
989
990        // Bring in a bunch of requests.
991        ConnectivityManager.NetworkCallback[] networkCallbacks =
992                new ConnectivityManager.NetworkCallback[10];
993        for (int i = 0; i< networkCallbacks.length; i++) {
994            networkCallbacks[i] = new ConnectivityManager.NetworkCallback();
995            NetworkRequest.Builder builder = new NetworkRequest.Builder();
996            builder.addCapability(capability);
997            mCm.requestNetwork(builder.build(), networkCallbacks[i]);
998        }
999        testFactory.waitForNetworkRequests(10 + expectedRequestCount);
1000        assertFalse(testFactory.getMyStartRequested());
1001
1002        // Remove the requests.
1003        for (int i = 0; i < networkCallbacks.length; i++) {
1004            mCm.unregisterNetworkCallback(networkCallbacks[i]);
1005        }
1006        testFactory.waitForNetworkRequests(expectedRequestCount);
1007        assertFalse(testFactory.getMyStartRequested());
1008
1009        // Drop the higher scored network.
1010        cv = testFactory.getNetworkStartedCV();
1011        testAgent.disconnect();
1012        waitFor(cv);
1013        assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
1014        assertTrue(testFactory.getMyStartRequested());
1015
1016        testFactory.unregister();
1017        if (networkCallback != null) mCm.unregisterNetworkCallback(networkCallback);
1018        handlerThread.quit();
1019    }
1020
1021    @LargeTest
1022    public void testNetworkFactoryRequests() throws Exception {
1023        tryNetworkFactoryRequests(NET_CAPABILITY_MMS);
1024        tryNetworkFactoryRequests(NET_CAPABILITY_SUPL);
1025        tryNetworkFactoryRequests(NET_CAPABILITY_DUN);
1026        tryNetworkFactoryRequests(NET_CAPABILITY_FOTA);
1027        tryNetworkFactoryRequests(NET_CAPABILITY_IMS);
1028        tryNetworkFactoryRequests(NET_CAPABILITY_CBS);
1029        tryNetworkFactoryRequests(NET_CAPABILITY_WIFI_P2P);
1030        tryNetworkFactoryRequests(NET_CAPABILITY_IA);
1031        tryNetworkFactoryRequests(NET_CAPABILITY_RCS);
1032        tryNetworkFactoryRequests(NET_CAPABILITY_XCAP);
1033        tryNetworkFactoryRequests(NET_CAPABILITY_EIMS);
1034        tryNetworkFactoryRequests(NET_CAPABILITY_NOT_METERED);
1035        tryNetworkFactoryRequests(NET_CAPABILITY_INTERNET);
1036        tryNetworkFactoryRequests(NET_CAPABILITY_TRUSTED);
1037        tryNetworkFactoryRequests(NET_CAPABILITY_NOT_VPN);
1038        // Skipping VALIDATED and CAPTIVE_PORTAL as they're disallowed.
1039    }
1040
1041    @LargeTest
1042    public void testNoMutableNetworkRequests() throws Exception {
1043        PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, new Intent("a"), 0);
1044        NetworkRequest.Builder builder = new NetworkRequest.Builder();
1045        builder.addCapability(NET_CAPABILITY_VALIDATED);
1046        try {
1047            mCm.requestNetwork(builder.build(), new NetworkCallback());
1048            fail();
1049        } catch (IllegalArgumentException expected) {}
1050        try {
1051            mCm.requestNetwork(builder.build(), pendingIntent);
1052            fail();
1053        } catch (IllegalArgumentException expected) {}
1054        builder = new NetworkRequest.Builder();
1055        builder.addCapability(NET_CAPABILITY_CAPTIVE_PORTAL);
1056        try {
1057            mCm.requestNetwork(builder.build(), new NetworkCallback());
1058            fail();
1059        } catch (IllegalArgumentException expected) {}
1060        try {
1061            mCm.requestNetwork(builder.build(), pendingIntent);
1062            fail();
1063        } catch (IllegalArgumentException expected) {}
1064    }
1065
1066    @LargeTest
1067    public void testMMSonWiFi() throws Exception {
1068        // Test bringing up cellular without MMS NetworkRequest gets reaped
1069        mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1070        mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS);
1071        ConditionVariable cv = mCellNetworkAgent.getDisconnectedCV();
1072        mCellNetworkAgent.connectWithoutInternet();
1073        waitFor(cv);
1074        waitFor(new Criteria() {
1075                public boolean get() { return mCm.getAllNetworks().length == 0; } });
1076        verifyNoNetwork();
1077        // Test bringing up validated WiFi.
1078        mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1079        cv = waitForConnectivityBroadcasts(1);
1080        mWiFiNetworkAgent.connect(true);
1081        waitFor(cv);
1082        verifyActiveNetwork(TRANSPORT_WIFI);
1083        // Register MMS NetworkRequest
1084        NetworkRequest.Builder builder = new NetworkRequest.Builder();
1085        builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
1086        final TestNetworkCallback networkCallback = new TestNetworkCallback();
1087        mCm.requestNetwork(builder.build(), networkCallback);
1088        // Test bringing up unvalidated cellular with MMS
1089        mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1090        mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS);
1091        cv = networkCallback.getConditionVariable();
1092        mCellNetworkAgent.connectWithoutInternet();
1093        waitFor(cv);
1094        assertEquals(CallbackState.AVAILABLE, networkCallback.getLastCallback());
1095        verifyActiveNetwork(TRANSPORT_WIFI);
1096        // Test releasing NetworkRequest disconnects cellular with MMS
1097        cv = mCellNetworkAgent.getDisconnectedCV();
1098        mCm.unregisterNetworkCallback(networkCallback);
1099        waitFor(cv);
1100        verifyActiveNetwork(TRANSPORT_WIFI);
1101    }
1102
1103    @LargeTest
1104    public void testMMSonCell() throws Exception {
1105        // Test bringing up cellular without MMS
1106        mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1107        ConditionVariable cv = waitForConnectivityBroadcasts(1);
1108        mCellNetworkAgent.connect(false);
1109        waitFor(cv);
1110        verifyActiveNetwork(TRANSPORT_CELLULAR);
1111        // Register MMS NetworkRequest
1112        NetworkRequest.Builder builder = new NetworkRequest.Builder();
1113        builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
1114        final TestNetworkCallback networkCallback = new TestNetworkCallback();
1115        mCm.requestNetwork(builder.build(), networkCallback);
1116        // Test bringing up MMS cellular network
1117        cv = networkCallback.getConditionVariable();
1118        MockNetworkAgent mmsNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1119        mmsNetworkAgent.addCapability(NET_CAPABILITY_MMS);
1120        mmsNetworkAgent.connectWithoutInternet();
1121        waitFor(cv);
1122        assertEquals(CallbackState.AVAILABLE, networkCallback.getLastCallback());
1123        verifyActiveNetwork(TRANSPORT_CELLULAR);
1124        // Test releasing MMS NetworkRequest does not disconnect main cellular NetworkAgent
1125        cv = mmsNetworkAgent.getDisconnectedCV();
1126        mCm.unregisterNetworkCallback(networkCallback);
1127        waitFor(cv);
1128        verifyActiveNetwork(TRANSPORT_CELLULAR);
1129    }
1130
1131    @LargeTest
1132    public void testCaptivePortal() {
1133        final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
1134        final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
1135                .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
1136        mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
1137
1138        final TestNetworkCallback validatedCallback = new TestNetworkCallback();
1139        final NetworkRequest validatedRequest = new NetworkRequest.Builder()
1140                .addCapability(NET_CAPABILITY_VALIDATED).build();
1141        mCm.registerNetworkCallback(validatedRequest, validatedCallback);
1142        ConditionVariable validatedCv = validatedCallback.getConditionVariable();
1143
1144        // Bring up a network with a captive portal.
1145        // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
1146        ConditionVariable cv = captivePortalCallback.getConditionVariable();
1147        mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1148        mWiFiNetworkAgent.connectWithCaptivePortal();
1149        waitFor(cv);
1150        assertEquals(CallbackState.AVAILABLE, captivePortalCallback.getLastCallback());
1151
1152        // Take down network.
1153        // Expect onLost callback.
1154        cv = captivePortalCallback.getConditionVariable();
1155        mWiFiNetworkAgent.disconnect();
1156        waitFor(cv);
1157        assertEquals(CallbackState.LOST, captivePortalCallback.getLastCallback());
1158
1159        // Bring up a network with a captive portal.
1160        // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
1161        cv = captivePortalCallback.getConditionVariable();
1162        mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1163        mWiFiNetworkAgent.connectWithCaptivePortal();
1164        waitFor(cv);
1165        assertEquals(CallbackState.AVAILABLE, captivePortalCallback.getLastCallback());
1166
1167        // Make captive portal disappear then revalidate.
1168        // Expect onLost callback because network no longer provides NET_CAPABILITY_CAPTIVE_PORTAL.
1169        cv = captivePortalCallback.getConditionVariable();
1170        mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 204;
1171        mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
1172        waitFor(cv);
1173        assertEquals(CallbackState.LOST, captivePortalCallback.getLastCallback());
1174
1175        // Expect NET_CAPABILITY_VALIDATED onAvailable callback.
1176        waitFor(validatedCv);
1177        assertEquals(CallbackState.AVAILABLE, validatedCallback.getLastCallback());
1178
1179        // Break network connectivity.
1180        // Expect NET_CAPABILITY_VALIDATED onLost callback.
1181        validatedCv = validatedCallback.getConditionVariable();
1182        mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 500;
1183        mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), false);
1184        waitFor(validatedCv);
1185        assertEquals(CallbackState.LOST, validatedCallback.getLastCallback());
1186    }
1187
1188//    @Override
1189//    public void tearDown() throws Exception {
1190//        super.tearDown();
1191//    }
1192//
1193//    public void testMobileConnectedAddedRoutes() throws Exception {
1194//        Future<?> nextConnBroadcast;
1195//
1196//        // bring up mobile network
1197//        mMobile.info.setDetailedState(DetailedState.CONNECTED, null, null);
1198//        mMobile.link.setInterfaceName(MOBILE_IFACE);
1199//        mMobile.link.addRoute(MOBILE_ROUTE_V4);
1200//        mMobile.link.addRoute(MOBILE_ROUTE_V6);
1201//        mMobile.doReturnDefaults();
1202//
1203//        cv = waitForConnectivityBroadcasts(1);
1204//        mTrackerHandler.obtainMessage(EVENT_STATE_CHANGED, mMobile.info).sendToTarget();
1205//        waitFor(cv);
1206//
1207//        // verify that both routes were added
1208//        int mobileNetId = mMobile.tracker.getNetwork().netId;
1209//        verify(mNetManager).addRoute(eq(mobileNetId), eq(MOBILE_ROUTE_V4));
1210//        verify(mNetManager).addRoute(eq(mobileNetId), eq(MOBILE_ROUTE_V6));
1211//    }
1212//
1213//    public void testMobileWifiHandoff() throws Exception {
1214//        Future<?> nextConnBroadcast;
1215//
1216//        // bring up mobile network
1217//        mMobile.info.setDetailedState(DetailedState.CONNECTED, null, null);
1218//        mMobile.link.setInterfaceName(MOBILE_IFACE);
1219//        mMobile.link.addRoute(MOBILE_ROUTE_V4);
1220//        mMobile.link.addRoute(MOBILE_ROUTE_V6);
1221//        mMobile.doReturnDefaults();
1222//
1223//        cv = waitForConnectivityBroadcasts(1);
1224//        mTrackerHandler.obtainMessage(EVENT_STATE_CHANGED, mMobile.info).sendToTarget();
1225//        waitFor(cv);
1226//
1227//        reset(mNetManager);
1228//
1229//        // now bring up wifi network
1230//        mWifi.info.setDetailedState(DetailedState.CONNECTED, null, null);
1231//        mWifi.link.setInterfaceName(WIFI_IFACE);
1232//        mWifi.link.addRoute(WIFI_ROUTE_V4);
1233//        mWifi.link.addRoute(WIFI_ROUTE_V6);
1234//        mWifi.doReturnDefaults();
1235//
1236//        // expect that mobile will be torn down
1237//        doReturn(true).when(mMobile.tracker).teardown();
1238//
1239//        cv = waitForConnectivityBroadcasts(1);
1240//        mTrackerHandler.obtainMessage(EVENT_STATE_CHANGED, mWifi.info).sendToTarget();
1241//        waitFor(cv);
1242//
1243//        // verify that wifi routes added, and teardown requested
1244//        int wifiNetId = mWifi.tracker.getNetwork().netId;
1245//        verify(mNetManager).addRoute(eq(wifiNetId), eq(WIFI_ROUTE_V4));
1246//        verify(mNetManager).addRoute(eq(wifiNetId), eq(WIFI_ROUTE_V6));
1247//        verify(mMobile.tracker).teardown();
1248//
1249//        int mobileNetId = mMobile.tracker.getNetwork().netId;
1250//
1251//        reset(mNetManager, mMobile.tracker);
1252//
1253//        // tear down mobile network, as requested
1254//        mMobile.info.setDetailedState(DetailedState.DISCONNECTED, null, null);
1255//        mMobile.link.clear();
1256//        mMobile.doReturnDefaults();
1257//
1258//        cv = waitForConnectivityBroadcasts(1);
1259//        mTrackerHandler.obtainMessage(EVENT_STATE_CHANGED, mMobile.info).sendToTarget();
1260//        waitFor(cv);
1261//
1262//        verify(mNetManager).removeRoute(eq(mobileNetId), eq(MOBILE_ROUTE_V4));
1263//        verify(mNetManager).removeRoute(eq(mobileNetId), eq(MOBILE_ROUTE_V6));
1264//
1265//    }
1266
1267    private static InetAddress parse(String addr) {
1268        return InetAddress.parseNumericAddress(addr);
1269    }
1270
1271}
1272