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.*;
24
25import static org.mockito.Mockito.mock;
26
27import android.app.PendingIntent;
28import android.content.BroadcastReceiver;
29import android.content.Context;
30import android.content.ContextWrapper;
31import android.content.Intent;
32import android.content.IntentFilter;
33import android.net.ConnectivityManager;
34import android.net.ConnectivityManager.NetworkCallback;
35import android.net.ConnectivityManager.PacketKeepalive;
36import android.net.ConnectivityManager.PacketKeepaliveCallback;
37import android.net.INetworkPolicyManager;
38import android.net.INetworkStatsService;
39import android.net.IpPrefix;
40import android.net.LinkAddress;
41import android.net.LinkProperties;
42import android.net.Network;
43import android.net.NetworkAgent;
44import android.net.NetworkCapabilities;
45import android.net.NetworkConfig;
46import android.net.NetworkFactory;
47import android.net.NetworkInfo;
48import android.net.NetworkInfo.DetailedState;
49import android.net.NetworkMisc;
50import android.net.NetworkRequest;
51import android.net.RouteInfo;
52import android.os.ConditionVariable;
53import android.os.Handler;
54import android.os.HandlerThread;
55import android.os.INetworkManagementService;
56import android.os.Looper;
57import android.os.Message;
58import android.os.MessageQueue;
59import android.os.MessageQueue.IdleHandler;
60import android.test.AndroidTestCase;
61import android.test.suitebuilder.annotation.LargeTest;
62import android.util.Log;
63import android.util.LogPrinter;
64
65import com.android.server.connectivity.NetworkAgentInfo;
66import com.android.server.connectivity.NetworkMonitor;
67
68import java.net.InetAddress;
69import java.util.concurrent.CountDownLatch;
70import java.util.concurrent.LinkedBlockingQueue;
71import java.util.concurrent.TimeUnit;
72import java.util.concurrent.atomic.AtomicBoolean;
73
74/**
75 * Tests for {@link ConnectivityService}.
76 *
77 * Build, install and run with:
78 *  runtest frameworks-services -c com.android.server.ConnectivityServiceTest
79 */
80public class ConnectivityServiceTest extends AndroidTestCase {
81    private static final String TAG = "ConnectivityServiceTest";
82
83    private static final int TIMEOUT_MS = 500;
84
85    private BroadcastInterceptingContext mServiceContext;
86    private WrappedConnectivityService mService;
87    private ConnectivityManager mCm;
88    private MockNetworkAgent mWiFiNetworkAgent;
89    private MockNetworkAgent mCellNetworkAgent;
90
91    private class MockContext extends BroadcastInterceptingContext {
92        MockContext(Context base) {
93            super(base);
94        }
95
96        @Override
97        public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
98            // PendingIntents sent by the AlarmManager are not intercepted by
99            // BroadcastInterceptingContext so we must really register the receiver.
100            // This shouldn't effect the real NetworkMonitors as the action contains a random token.
101            if (filter.getAction(0).startsWith("android.net.netmon.lingerExpired")) {
102                return getBaseContext().registerReceiver(receiver, filter);
103            } else {
104                return super.registerReceiver(receiver, filter);
105            }
106        }
107
108        @Override
109        public Object getSystemService (String name) {
110            if (name == Context.CONNECTIVITY_SERVICE) return mCm;
111            return super.getSystemService(name);
112        }
113    }
114
115    /**
116     * A subclass of HandlerThread that allows callers to wait for it to become idle. waitForIdle
117     * will return immediately if the handler is already idle.
118     */
119    private class IdleableHandlerThread extends HandlerThread {
120        private IdleHandler mIdleHandler;
121
122        public IdleableHandlerThread(String name) {
123            super(name);
124        }
125
126        public void waitForIdle(int timeoutMs) {
127            final ConditionVariable cv = new ConditionVariable();
128            final MessageQueue queue = getLooper().getQueue();
129
130            synchronized (queue) {
131                if (queue.isIdle()) {
132                    return;
133                }
134
135                assertNull("BUG: only one idle handler allowed", mIdleHandler);
136                mIdleHandler = new IdleHandler() {
137                    public boolean queueIdle() {
138                        cv.open();
139                        mIdleHandler = null;
140                        return false;  // Remove the handler.
141                    }
142                };
143                queue.addIdleHandler(mIdleHandler);
144            }
145
146            if (!cv.block(timeoutMs)) {
147                fail("HandlerThread " + getName() +
148                        " did not become idle after " + timeoutMs + " ms");
149                queue.removeIdleHandler(mIdleHandler);
150            }
151        }
152    }
153
154    // Tests that IdleableHandlerThread works as expected.
155    public void testIdleableHandlerThread() {
156        final int attempts = 50;  // Causes the test to take about 200ms on bullhead-eng.
157
158        // Tests that waitForIdle returns immediately if the service is already idle.
159        for (int i = 0; i < attempts; i++) {
160            mService.waitForIdle();
161        }
162
163        // Bring up a network that we can use to send messages to ConnectivityService.
164        ConditionVariable cv = waitForConnectivityBroadcasts(1);
165        mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
166        mWiFiNetworkAgent.connect(false);
167        waitFor(cv);
168        Network n = mWiFiNetworkAgent.getNetwork();
169        assertNotNull(n);
170
171        // Tests that calling waitForIdle waits for messages to be processed.
172        for (int i = 0; i < attempts; i++) {
173            mWiFiNetworkAgent.setSignalStrength(i);
174            mService.waitForIdle();
175            assertEquals(i, mCm.getNetworkCapabilities(n).getSignalStrength());
176        }
177
178        // Ensure that not calling waitForIdle causes a race condition.
179        for (int i = 0; i < attempts; i++) {
180            mWiFiNetworkAgent.setSignalStrength(i);
181            if (i != mCm.getNetworkCapabilities(n).getSignalStrength()) {
182                // We hit a race condition, as expected. Pass the test.
183                return;
184            }
185        }
186
187        // No race? There is a bug in this test.
188        fail("expected race condition at least once in " + attempts + " attempts");
189    }
190
191    private class MockNetworkAgent {
192        private final WrappedNetworkMonitor mWrappedNetworkMonitor;
193        private final NetworkInfo mNetworkInfo;
194        private final NetworkCapabilities mNetworkCapabilities;
195        private final IdleableHandlerThread mHandlerThread;
196        private final ConditionVariable mDisconnected = new ConditionVariable();
197        private int mScore;
198        private NetworkAgent mNetworkAgent;
199        private int mStartKeepaliveError = PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED;
200        private int mStopKeepaliveError = PacketKeepalive.NO_KEEPALIVE;
201        private Integer mExpectedKeepaliveSlot = null;
202
203        MockNetworkAgent(int transport) {
204            final int type = transportToLegacyType(transport);
205            final String typeName = ConnectivityManager.getNetworkTypeName(type);
206            mNetworkInfo = new NetworkInfo(type, 0, typeName, "Mock");
207            mNetworkCapabilities = new NetworkCapabilities();
208            mNetworkCapabilities.addTransportType(transport);
209            switch (transport) {
210                case TRANSPORT_WIFI:
211                    mScore = 60;
212                    break;
213                case TRANSPORT_CELLULAR:
214                    mScore = 50;
215                    break;
216                default:
217                    throw new UnsupportedOperationException("unimplemented network type");
218            }
219            mHandlerThread = new IdleableHandlerThread("Mock-" + typeName);
220            mHandlerThread.start();
221            mNetworkAgent = new NetworkAgent(mHandlerThread.getLooper(), mServiceContext,
222                    "Mock-" + typeName, mNetworkInfo, mNetworkCapabilities,
223                    new LinkProperties(), mScore, new NetworkMisc()) {
224                @Override
225                public void unwanted() { mDisconnected.open(); }
226
227                @Override
228                public void startPacketKeepalive(Message msg) {
229                    int slot = msg.arg1;
230                    if (mExpectedKeepaliveSlot != null) {
231                        assertEquals((int) mExpectedKeepaliveSlot, slot);
232                    }
233                    onPacketKeepaliveEvent(slot, mStartKeepaliveError);
234                }
235
236                @Override
237                public void stopPacketKeepalive(Message msg) {
238                    onPacketKeepaliveEvent(msg.arg1, mStopKeepaliveError);
239                }
240            };
241            // Waits for the NetworkAgent to be registered, which includes the creation of the
242            // NetworkMonitor.
243            mService.waitForIdle();
244            mWrappedNetworkMonitor = mService.getLastCreatedWrappedNetworkMonitor();
245        }
246
247        public void waitForIdle(int timeoutMs) {
248            mHandlerThread.waitForIdle(timeoutMs);
249        }
250
251        public void waitForIdle() {
252            waitForIdle(TIMEOUT_MS);
253        }
254
255        public void adjustScore(int change) {
256            mScore += change;
257            mNetworkAgent.sendNetworkScore(mScore);
258        }
259
260        public void addCapability(int capability) {
261            mNetworkCapabilities.addCapability(capability);
262            mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
263        }
264
265        public void setSignalStrength(int signalStrength) {
266            mNetworkCapabilities.setSignalStrength(signalStrength);
267            mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
268        }
269
270        public void connectWithoutInternet() {
271            mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, null);
272            mNetworkAgent.sendNetworkInfo(mNetworkInfo);
273        }
274
275        /**
276         * Transition this NetworkAgent to CONNECTED state with NET_CAPABILITY_INTERNET.
277         * @param validated Indicate if network should pretend to be validated.
278         */
279        public void connect(boolean validated) {
280            assertEquals(mNetworkInfo.getDetailedState(), DetailedState.IDLE);
281            assertFalse(mNetworkCapabilities.hasCapability(NET_CAPABILITY_INTERNET));
282
283            NetworkCallback callback = null;
284            final ConditionVariable validatedCv = new ConditionVariable();
285            if (validated) {
286                mWrappedNetworkMonitor.gen204ProbeResult = 204;
287                NetworkRequest request = new NetworkRequest.Builder()
288                        .addTransportType(mNetworkCapabilities.getTransportTypes()[0])
289                        .build();
290                callback = new NetworkCallback() {
291                    public void onCapabilitiesChanged(Network network,
292                            NetworkCapabilities networkCapabilities) {
293                        if (network.equals(getNetwork()) &&
294                            networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED)) {
295                            validatedCv.open();
296                        }
297                    }
298                };
299                mCm.registerNetworkCallback(request, callback);
300            }
301            addCapability(NET_CAPABILITY_INTERNET);
302
303            connectWithoutInternet();
304
305            if (validated) {
306                // Wait for network to validate.
307                waitFor(validatedCv);
308                mWrappedNetworkMonitor.gen204ProbeResult = 500;
309            }
310
311            if (callback != null) mCm.unregisterNetworkCallback(callback);
312        }
313
314        public void connectWithCaptivePortal() {
315            mWrappedNetworkMonitor.gen204ProbeResult = 200;
316            connect(false);
317            waitFor(new Criteria() { public boolean get() {
318                NetworkCapabilities caps = mCm.getNetworkCapabilities(getNetwork());
319                return caps != null && caps.hasCapability(NET_CAPABILITY_CAPTIVE_PORTAL);} });
320            mWrappedNetworkMonitor.gen204ProbeResult = 500;
321        }
322
323        public void disconnect() {
324            mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, null);
325            mNetworkAgent.sendNetworkInfo(mNetworkInfo);
326        }
327
328        public Network getNetwork() {
329            return new Network(mNetworkAgent.netId);
330        }
331
332        public ConditionVariable getDisconnectedCV() {
333            return mDisconnected;
334        }
335
336        public WrappedNetworkMonitor getWrappedNetworkMonitor() {
337            return mWrappedNetworkMonitor;
338        }
339
340        public void sendLinkProperties(LinkProperties lp) {
341            mNetworkAgent.sendLinkProperties(lp);
342        }
343
344        public void setStartKeepaliveError(int error) {
345            mStartKeepaliveError = error;
346        }
347
348        public void setStopKeepaliveError(int error) {
349            mStopKeepaliveError = error;
350        }
351
352        public void setExpectedKeepaliveSlot(Integer slot) {
353            mExpectedKeepaliveSlot = slot;
354        }
355    }
356
357    /**
358     * A NetworkFactory that allows tests to wait until any in-flight NetworkRequest add or remove
359     * operations have been processed. Before ConnectivityService can add or remove any requests,
360     * the factory must be told to expect those operations by calling expectAddRequests or
361     * expectRemoveRequests.
362     */
363    private static class MockNetworkFactory extends NetworkFactory {
364        private final ConditionVariable mNetworkStartedCV = new ConditionVariable();
365        private final ConditionVariable mNetworkStoppedCV = new ConditionVariable();
366        private final AtomicBoolean mNetworkStarted = new AtomicBoolean(false);
367
368        // Used to expect that requests be removed or added on a separate thread, without sleeping.
369        // Callers can call either expectAddRequests() or expectRemoveRequests() exactly once, then
370        // cause some other thread to add or remove requests, then call waitForRequests(). We can
371        // either expect requests to be added or removed, but not both, because CountDownLatch can
372        // only count in one direction.
373        private CountDownLatch mExpectations;
374
375        // Whether we are currently expecting requests to be added or removed. Valid only if
376        // mExpectations is non-null.
377        private boolean mExpectingAdditions;
378
379        public MockNetworkFactory(Looper looper, Context context, String logTag,
380                NetworkCapabilities filter) {
381            super(looper, context, logTag, filter);
382        }
383
384        public int getMyRequestCount() {
385            return getRequestCount();
386        }
387
388        protected void startNetwork() {
389            mNetworkStarted.set(true);
390            mNetworkStartedCV.open();
391        }
392
393        protected void stopNetwork() {
394            mNetworkStarted.set(false);
395            mNetworkStoppedCV.open();
396        }
397
398        public boolean getMyStartRequested() {
399            return mNetworkStarted.get();
400        }
401
402        public ConditionVariable getNetworkStartedCV() {
403            mNetworkStartedCV.close();
404            return mNetworkStartedCV;
405        }
406
407        public ConditionVariable getNetworkStoppedCV() {
408            mNetworkStoppedCV.close();
409            return mNetworkStoppedCV;
410        }
411
412        @Override
413        protected void handleAddRequest(NetworkRequest request, int score) {
414            // If we're expecting anything, we must be expecting additions.
415            if (mExpectations != null && !mExpectingAdditions) {
416                fail("Can't add requests while expecting requests to be removed");
417            }
418
419            // Add the request.
420            super.handleAddRequest(request, score);
421
422            // Reduce the number of request additions we're waiting for.
423            if (mExpectingAdditions) {
424                assertTrue("Added more requests than expected", mExpectations.getCount() > 0);
425                mExpectations.countDown();
426            }
427        }
428
429        @Override
430        protected void handleRemoveRequest(NetworkRequest request) {
431            // If we're expecting anything, we must be expecting removals.
432            if (mExpectations != null && mExpectingAdditions) {
433                fail("Can't remove requests while expecting requests to be added");
434            }
435
436            // Remove the request.
437            super.handleRemoveRequest(request);
438
439            // Reduce the number of request removals we're waiting for.
440            if (!mExpectingAdditions) {
441                assertTrue("Removed more requests than expected", mExpectations.getCount() > 0);
442                mExpectations.countDown();
443            }
444        }
445
446        private void assertNoExpectations() {
447            if (mExpectations != null) {
448                fail("Can't add expectation, " + mExpectations.getCount() + " already pending");
449            }
450        }
451
452        // Expects that count requests will be added.
453        public void expectAddRequests(final int count) {
454            assertNoExpectations();
455            mExpectingAdditions = true;
456            mExpectations = new CountDownLatch(count);
457        }
458
459        // Expects that count requests will be removed.
460        public void expectRemoveRequests(final int count) {
461            assertNoExpectations();
462            mExpectingAdditions = false;
463            mExpectations = new CountDownLatch(count);
464        }
465
466        // Waits for the expected request additions or removals to happen within a timeout.
467        public void waitForRequests() throws InterruptedException {
468            assertNotNull("Nothing to wait for", mExpectations);
469            mExpectations.await(TIMEOUT_MS, TimeUnit.MILLISECONDS);
470            final long count = mExpectations.getCount();
471            final String msg = count + " requests still not " +
472                    (mExpectingAdditions ? "added" : "removed") +
473                    " after " + TIMEOUT_MS + " ms";
474            assertEquals(msg, 0, count);
475            mExpectations = null;
476        }
477
478        public void waitForNetworkRequests(final int count) throws InterruptedException {
479            waitForRequests();
480            assertEquals(count, getMyRequestCount());
481        }
482    }
483
484    // NetworkMonitor implementation allowing overriding of Internet connectivity probe result.
485    private class WrappedNetworkMonitor extends NetworkMonitor {
486        // HTTP response code fed back to NetworkMonitor for Internet connectivity probe.
487        public int gen204ProbeResult = 500;
488
489        public WrappedNetworkMonitor(Context context, Handler handler,
490            NetworkAgentInfo networkAgentInfo, NetworkRequest defaultRequest) {
491            super(context, handler, networkAgentInfo, defaultRequest);
492        }
493
494        @Override
495        protected int isCaptivePortal() {
496            return gen204ProbeResult;
497        }
498    }
499
500    private class WrappedConnectivityService extends ConnectivityService {
501        private WrappedNetworkMonitor mLastCreatedNetworkMonitor;
502
503        public WrappedConnectivityService(Context context, INetworkManagementService netManager,
504                INetworkStatsService statsService, INetworkPolicyManager policyManager) {
505            super(context, netManager, statsService, policyManager);
506        }
507
508        @Override
509        protected HandlerThread createHandlerThread() {
510            return new IdleableHandlerThread("WrappedConnectivityService");
511        }
512
513        @Override
514        protected int getDefaultTcpRwnd() {
515            // Prevent wrapped ConnectivityService from trying to write to SystemProperties.
516            return 0;
517        }
518
519        @Override
520        protected int reserveNetId() {
521            while (true) {
522                final int netId = super.reserveNetId();
523
524                // Don't overlap test NetIDs with real NetIDs as binding sockets to real networks
525                // can have odd side-effects, like network validations succeeding.
526                final Network[] networks = ConnectivityManager.from(getContext()).getAllNetworks();
527                boolean overlaps = false;
528                for (Network network : networks) {
529                    if (netId == network.netId) {
530                        overlaps = true;
531                        break;
532                    }
533                }
534                if (overlaps) continue;
535
536                return netId;
537            }
538        }
539
540        @Override
541        public NetworkMonitor createNetworkMonitor(Context context, Handler handler,
542                NetworkAgentInfo nai, NetworkRequest defaultRequest) {
543            final WrappedNetworkMonitor monitor = new WrappedNetworkMonitor(context, handler, nai,
544                    defaultRequest);
545            mLastCreatedNetworkMonitor = monitor;
546            return monitor;
547        }
548
549        public WrappedNetworkMonitor getLastCreatedWrappedNetworkMonitor() {
550            return mLastCreatedNetworkMonitor;
551        }
552
553        public void waitForIdle(int timeoutMs) {
554            ((IdleableHandlerThread) mHandlerThread).waitForIdle(timeoutMs);
555        }
556
557        public void waitForIdle() {
558            waitForIdle(TIMEOUT_MS);
559        }
560
561    }
562
563    private interface Criteria {
564        public boolean get();
565    }
566
567    /**
568     * Wait up to 500ms for {@code criteria.get()} to become true, polling.
569     * Fails if 500ms goes by before {@code criteria.get()} to become true.
570     */
571    static private void waitFor(Criteria criteria) {
572        int delays = 0;
573        while (!criteria.get()) {
574            try {
575                Thread.sleep(100);
576            } catch (InterruptedException e) {
577            }
578            if (++delays == 5) fail();
579        }
580    }
581
582    /**
583     * Wait up to TIMEOUT_MS for {@code conditionVariable} to open.
584     * Fails if TIMEOUT_MS goes by before {@code conditionVariable} opens.
585     */
586    static private void waitFor(ConditionVariable conditionVariable) {
587        assertTrue(conditionVariable.block(TIMEOUT_MS));
588    }
589
590    @Override
591    public void setUp() throws Exception {
592        super.setUp();
593
594        mServiceContext = new MockContext(getContext());
595        mService = new WrappedConnectivityService(mServiceContext,
596                mock(INetworkManagementService.class),
597                mock(INetworkStatsService.class),
598                mock(INetworkPolicyManager.class));
599
600        mService.systemReady();
601        mCm = new ConnectivityManager(getContext(), mService);
602    }
603
604    private int transportToLegacyType(int transport) {
605        switch (transport) {
606            case TRANSPORT_WIFI:
607                return TYPE_WIFI;
608            case TRANSPORT_CELLULAR:
609                return TYPE_MOBILE;
610            default:
611                throw new IllegalStateException("Unknown transport" + transport);
612        }
613    }
614
615    private void verifyActiveNetwork(int transport) {
616        // Test getActiveNetworkInfo()
617        assertNotNull(mCm.getActiveNetworkInfo());
618        assertEquals(transportToLegacyType(transport), mCm.getActiveNetworkInfo().getType());
619        // Test getActiveNetwork()
620        assertNotNull(mCm.getActiveNetwork());
621        switch (transport) {
622            case TRANSPORT_WIFI:
623                assertEquals(mCm.getActiveNetwork(), mWiFiNetworkAgent.getNetwork());
624                break;
625            case TRANSPORT_CELLULAR:
626                assertEquals(mCm.getActiveNetwork(), mCellNetworkAgent.getNetwork());
627                break;
628            default:
629                throw new IllegalStateException("Unknown transport" + transport);
630        }
631        // Test getNetworkInfo(Network)
632        assertNotNull(mCm.getNetworkInfo(mCm.getActiveNetwork()));
633        assertEquals(transportToLegacyType(transport), mCm.getNetworkInfo(mCm.getActiveNetwork()).getType());
634        // Test getNetworkCapabilities(Network)
635        assertNotNull(mCm.getNetworkCapabilities(mCm.getActiveNetwork()));
636        assertTrue(mCm.getNetworkCapabilities(mCm.getActiveNetwork()).hasTransport(transport));
637    }
638
639    private void verifyNoNetwork() {
640        // Test getActiveNetworkInfo()
641        assertNull(mCm.getActiveNetworkInfo());
642        // Test getActiveNetwork()
643        assertNull(mCm.getActiveNetwork());
644        // Test getAllNetworks()
645        assertEquals(0, mCm.getAllNetworks().length);
646    }
647
648    /**
649     * Return a ConditionVariable that opens when {@code count} numbers of CONNECTIVITY_ACTION
650     * broadcasts are received.
651     */
652    private ConditionVariable waitForConnectivityBroadcasts(final int count) {
653        final ConditionVariable cv = new ConditionVariable();
654        mServiceContext.registerReceiver(new BroadcastReceiver() {
655                    private int remaining = count;
656                    public void onReceive(Context context, Intent intent) {
657                        if (--remaining == 0) {
658                            cv.open();
659                            mServiceContext.unregisterReceiver(this);
660                        }
661                    }
662                }, new IntentFilter(CONNECTIVITY_ACTION));
663        return cv;
664    }
665
666    @LargeTest
667    public void testLingering() throws Exception {
668        // Decrease linger timeout to the minimum allowed by AlarmManagerService.
669        NetworkMonitor.SetDefaultLingerTime(5000);
670        verifyNoNetwork();
671        mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
672        mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
673        assertNull(mCm.getActiveNetworkInfo());
674        assertNull(mCm.getActiveNetwork());
675        // Test bringing up validated cellular.
676        ConditionVariable cv = waitForConnectivityBroadcasts(1);
677        mCellNetworkAgent.connect(true);
678        waitFor(cv);
679        verifyActiveNetwork(TRANSPORT_CELLULAR);
680        assertEquals(2, mCm.getAllNetworks().length);
681        assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) ||
682                mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork()));
683        assertTrue(mCm.getAllNetworks()[0].equals(mWiFiNetworkAgent.getNetwork()) ||
684                mCm.getAllNetworks()[1].equals(mWiFiNetworkAgent.getNetwork()));
685        // Test bringing up validated WiFi.
686        cv = waitForConnectivityBroadcasts(2);
687        mWiFiNetworkAgent.connect(true);
688        waitFor(cv);
689        verifyActiveNetwork(TRANSPORT_WIFI);
690        assertEquals(2, mCm.getAllNetworks().length);
691        assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) ||
692                mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork()));
693        assertTrue(mCm.getAllNetworks()[0].equals(mCellNetworkAgent.getNetwork()) ||
694                mCm.getAllNetworks()[1].equals(mCellNetworkAgent.getNetwork()));
695        // Test cellular linger timeout.
696        try {
697            Thread.sleep(6000);
698        } catch (InterruptedException e) {
699        }
700        verifyActiveNetwork(TRANSPORT_WIFI);
701        assertEquals(1, mCm.getAllNetworks().length);
702        assertEquals(mCm.getAllNetworks()[0], mCm.getActiveNetwork());
703        // Test WiFi disconnect.
704        cv = waitForConnectivityBroadcasts(1);
705        mWiFiNetworkAgent.disconnect();
706        waitFor(cv);
707        verifyNoNetwork();
708    }
709
710    @LargeTest
711    public void testValidatedCellularOutscoresUnvalidatedWiFi() throws Exception {
712        // Test bringing up unvalidated WiFi
713        mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
714        ConditionVariable cv = waitForConnectivityBroadcasts(1);
715        mWiFiNetworkAgent.connect(false);
716        waitFor(cv);
717        verifyActiveNetwork(TRANSPORT_WIFI);
718        // Test bringing up unvalidated cellular
719        mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
720        mCellNetworkAgent.connect(false);
721        mService.waitForIdle();
722        verifyActiveNetwork(TRANSPORT_WIFI);
723        // Test cellular disconnect.
724        mCellNetworkAgent.disconnect();
725        mService.waitForIdle();
726        verifyActiveNetwork(TRANSPORT_WIFI);
727        // Test bringing up validated cellular
728        mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
729        cv = waitForConnectivityBroadcasts(2);
730        mCellNetworkAgent.connect(true);
731        waitFor(cv);
732        verifyActiveNetwork(TRANSPORT_CELLULAR);
733        // Test cellular disconnect.
734        cv = waitForConnectivityBroadcasts(2);
735        mCellNetworkAgent.disconnect();
736        waitFor(cv);
737        verifyActiveNetwork(TRANSPORT_WIFI);
738        // Test WiFi disconnect.
739        cv = waitForConnectivityBroadcasts(1);
740        mWiFiNetworkAgent.disconnect();
741        waitFor(cv);
742        verifyNoNetwork();
743    }
744
745    @LargeTest
746    public void testUnvalidatedWifiOutscoresUnvalidatedCellular() throws Exception {
747        // Test bringing up unvalidated cellular.
748        mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
749        ConditionVariable cv = waitForConnectivityBroadcasts(1);
750        mCellNetworkAgent.connect(false);
751        waitFor(cv);
752        verifyActiveNetwork(TRANSPORT_CELLULAR);
753        // Test bringing up unvalidated WiFi.
754        mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
755        cv = waitForConnectivityBroadcasts(2);
756        mWiFiNetworkAgent.connect(false);
757        waitFor(cv);
758        verifyActiveNetwork(TRANSPORT_WIFI);
759        // Test WiFi disconnect.
760        cv = waitForConnectivityBroadcasts(2);
761        mWiFiNetworkAgent.disconnect();
762        waitFor(cv);
763        verifyActiveNetwork(TRANSPORT_CELLULAR);
764        // Test cellular disconnect.
765        cv = waitForConnectivityBroadcasts(1);
766        mCellNetworkAgent.disconnect();
767        waitFor(cv);
768        verifyNoNetwork();
769    }
770
771    @LargeTest
772    public void testUnlingeringDoesNotValidate() throws Exception {
773        // Test bringing up unvalidated WiFi.
774        mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
775        ConditionVariable cv = waitForConnectivityBroadcasts(1);
776        mWiFiNetworkAgent.connect(false);
777        waitFor(cv);
778        verifyActiveNetwork(TRANSPORT_WIFI);
779        assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
780                NET_CAPABILITY_VALIDATED));
781        // Test bringing up validated cellular.
782        mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
783        cv = waitForConnectivityBroadcasts(2);
784        mCellNetworkAgent.connect(true);
785        waitFor(cv);
786        verifyActiveNetwork(TRANSPORT_CELLULAR);
787        assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
788                NET_CAPABILITY_VALIDATED));
789        // Test cellular disconnect.
790        cv = waitForConnectivityBroadcasts(2);
791        mCellNetworkAgent.disconnect();
792        waitFor(cv);
793        verifyActiveNetwork(TRANSPORT_WIFI);
794        // Unlingering a network should not cause it to be marked as validated.
795        assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
796                NET_CAPABILITY_VALIDATED));
797    }
798
799    @LargeTest
800    public void testCellularOutscoresWeakWifi() throws Exception {
801        // Test bringing up validated cellular.
802        mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
803        ConditionVariable cv = waitForConnectivityBroadcasts(1);
804        mCellNetworkAgent.connect(true);
805        waitFor(cv);
806        verifyActiveNetwork(TRANSPORT_CELLULAR);
807        // Test bringing up validated WiFi.
808        mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
809        cv = waitForConnectivityBroadcasts(2);
810        mWiFiNetworkAgent.connect(true);
811        waitFor(cv);
812        verifyActiveNetwork(TRANSPORT_WIFI);
813        // Test WiFi getting really weak.
814        cv = waitForConnectivityBroadcasts(2);
815        mWiFiNetworkAgent.adjustScore(-11);
816        waitFor(cv);
817        verifyActiveNetwork(TRANSPORT_CELLULAR);
818        // Test WiFi restoring signal strength.
819        cv = waitForConnectivityBroadcasts(2);
820        mWiFiNetworkAgent.adjustScore(11);
821        waitFor(cv);
822        verifyActiveNetwork(TRANSPORT_WIFI);
823        mCellNetworkAgent.disconnect();
824        mWiFiNetworkAgent.disconnect();
825    }
826
827    @LargeTest
828    public void testReapingNetwork() throws Exception {
829        // Test bringing up WiFi without NET_CAPABILITY_INTERNET.
830        // Expect it to be torn down immediately because it satisfies no requests.
831        mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
832        ConditionVariable cv = mWiFiNetworkAgent.getDisconnectedCV();
833        mWiFiNetworkAgent.connectWithoutInternet();
834        waitFor(cv);
835        // Test bringing up cellular without NET_CAPABILITY_INTERNET.
836        // Expect it to be torn down immediately because it satisfies no requests.
837        mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
838        cv = mCellNetworkAgent.getDisconnectedCV();
839        mCellNetworkAgent.connectWithoutInternet();
840        waitFor(cv);
841        // Test bringing up validated WiFi.
842        mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
843        cv = waitForConnectivityBroadcasts(1);
844        mWiFiNetworkAgent.connect(true);
845        waitFor(cv);
846        verifyActiveNetwork(TRANSPORT_WIFI);
847        // Test bringing up unvalidated cellular.
848        // Expect it to be torn down because it could never be the highest scoring network
849        // satisfying the default request even if it validated.
850        mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
851        cv = mCellNetworkAgent.getDisconnectedCV();
852        mCellNetworkAgent.connect(false);
853        waitFor(cv);
854        verifyActiveNetwork(TRANSPORT_WIFI);
855        cv = mWiFiNetworkAgent.getDisconnectedCV();
856        mWiFiNetworkAgent.disconnect();
857        waitFor(cv);
858    }
859
860    @LargeTest
861    public void testCellularFallback() throws Exception {
862        // Test bringing up validated cellular.
863        mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
864        ConditionVariable cv = waitForConnectivityBroadcasts(1);
865        mCellNetworkAgent.connect(true);
866        waitFor(cv);
867        verifyActiveNetwork(TRANSPORT_CELLULAR);
868        // Test bringing up validated WiFi.
869        mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
870        cv = waitForConnectivityBroadcasts(2);
871        mWiFiNetworkAgent.connect(true);
872        waitFor(cv);
873        verifyActiveNetwork(TRANSPORT_WIFI);
874        // Reevaluate WiFi (it'll instantly fail DNS).
875        cv = waitForConnectivityBroadcasts(2);
876        assertTrue(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
877                NET_CAPABILITY_VALIDATED));
878        mCm.reportBadNetwork(mWiFiNetworkAgent.getNetwork());
879        // Should quickly fall back to Cellular.
880        waitFor(cv);
881        assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
882                NET_CAPABILITY_VALIDATED));
883        verifyActiveNetwork(TRANSPORT_CELLULAR);
884        // Reevaluate cellular (it'll instantly fail DNS).
885        cv = waitForConnectivityBroadcasts(2);
886        assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
887                NET_CAPABILITY_VALIDATED));
888        mCm.reportBadNetwork(mCellNetworkAgent.getNetwork());
889        // Should quickly fall back to WiFi.
890        waitFor(cv);
891        assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
892                NET_CAPABILITY_VALIDATED));
893        assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
894                NET_CAPABILITY_VALIDATED));
895        verifyActiveNetwork(TRANSPORT_WIFI);
896        mCellNetworkAgent.disconnect();
897        mWiFiNetworkAgent.disconnect();
898    }
899
900    @LargeTest
901    public void testWiFiFallback() throws Exception {
902        // Test bringing up unvalidated WiFi.
903        mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
904        ConditionVariable cv = waitForConnectivityBroadcasts(1);
905        mWiFiNetworkAgent.connect(false);
906        waitFor(cv);
907        verifyActiveNetwork(TRANSPORT_WIFI);
908        // Test bringing up validated cellular.
909        mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
910        cv = waitForConnectivityBroadcasts(2);
911        mCellNetworkAgent.connect(true);
912        waitFor(cv);
913        verifyActiveNetwork(TRANSPORT_CELLULAR);
914        // Reevaluate cellular (it'll instantly fail DNS).
915        cv = waitForConnectivityBroadcasts(2);
916        assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
917                NET_CAPABILITY_VALIDATED));
918        mCm.reportBadNetwork(mCellNetworkAgent.getNetwork());
919        // Should quickly fall back to WiFi.
920        waitFor(cv);
921        assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
922                NET_CAPABILITY_VALIDATED));
923        verifyActiveNetwork(TRANSPORT_WIFI);
924        mCellNetworkAgent.disconnect();
925        mWiFiNetworkAgent.disconnect();
926    }
927
928    enum CallbackState {
929        NONE,
930        AVAILABLE,
931        LOSING,
932        LOST
933    }
934
935    /**
936     * Utility NetworkCallback for testing. The caller must explicitly test for all the callbacks
937     * this class receives, by calling expectCallback() exactly once each time a callback is
938     * received. assertNoCallback may be called at any time.
939     */
940    private class TestNetworkCallback extends NetworkCallback {
941        private final ConditionVariable mConditionVariable = new ConditionVariable();
942        private CallbackState mLastCallback = CallbackState.NONE;
943
944        public void onAvailable(Network network) {
945            assertEquals(CallbackState.NONE, mLastCallback);
946            mLastCallback = CallbackState.AVAILABLE;
947            mConditionVariable.open();
948        }
949
950        public void onLosing(Network network, int maxMsToLive) {
951            assertEquals(CallbackState.NONE, mLastCallback);
952            mLastCallback = CallbackState.LOSING;
953            mConditionVariable.open();
954        }
955
956        public void onLost(Network network) {
957            assertEquals(CallbackState.NONE, mLastCallback);
958            mLastCallback = CallbackState.LOST;
959            mConditionVariable.open();
960        }
961
962        void expectCallback(CallbackState state) {
963            waitFor(mConditionVariable);
964            assertEquals(state, mLastCallback);
965            mLastCallback = CallbackState.NONE;
966            mConditionVariable.close();
967        }
968
969        void assertNoCallback() {
970            assertEquals(CallbackState.NONE, mLastCallback);
971        }
972    }
973
974    @LargeTest
975    public void testStateChangeNetworkCallbacks() throws Exception {
976        final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
977        final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
978        final NetworkRequest wifiRequest = new NetworkRequest.Builder()
979                .addTransportType(TRANSPORT_WIFI).build();
980        final NetworkRequest cellRequest = new NetworkRequest.Builder()
981                .addTransportType(TRANSPORT_CELLULAR).build();
982        mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
983        mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
984
985        // Test unvalidated networks
986        ConditionVariable cv = waitForConnectivityBroadcasts(1);
987        mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
988        mCellNetworkAgent.connect(false);
989        cellNetworkCallback.expectCallback(CallbackState.AVAILABLE);
990        wifiNetworkCallback.assertNoCallback();
991        assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
992        waitFor(cv);
993
994        // This should not trigger spurious onAvailable() callbacks, b/21762680.
995        mCellNetworkAgent.adjustScore(-1);
996        mService.waitForIdle();
997        wifiNetworkCallback.assertNoCallback();
998        cellNetworkCallback.assertNoCallback();
999        assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1000
1001        cv = waitForConnectivityBroadcasts(2);
1002        mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1003        mWiFiNetworkAgent.connect(false);
1004        wifiNetworkCallback.expectCallback(CallbackState.AVAILABLE);
1005        cellNetworkCallback.assertNoCallback();
1006        assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1007        waitFor(cv);
1008
1009        cv = waitForConnectivityBroadcasts(2);
1010        mWiFiNetworkAgent.disconnect();
1011        wifiNetworkCallback.expectCallback(CallbackState.LOST);
1012        cellNetworkCallback.assertNoCallback();
1013        waitFor(cv);
1014
1015        cv = waitForConnectivityBroadcasts(1);
1016        mCellNetworkAgent.disconnect();
1017        cellNetworkCallback.expectCallback(CallbackState.LOST);
1018        wifiNetworkCallback.assertNoCallback();
1019        waitFor(cv);
1020
1021        // Test validated networks
1022        mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1023        mCellNetworkAgent.connect(true);
1024        cellNetworkCallback.expectCallback(CallbackState.AVAILABLE);
1025        wifiNetworkCallback.assertNoCallback();
1026        assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1027
1028        // This should not trigger spurious onAvailable() callbacks, b/21762680.
1029        mCellNetworkAgent.adjustScore(-1);
1030        mService.waitForIdle();
1031        wifiNetworkCallback.assertNoCallback();
1032        cellNetworkCallback.assertNoCallback();
1033        assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1034
1035        mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1036        mWiFiNetworkAgent.connect(true);
1037        wifiNetworkCallback.expectCallback(CallbackState.AVAILABLE);
1038        cellNetworkCallback.expectCallback(CallbackState.LOSING);
1039        assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1040
1041        mWiFiNetworkAgent.disconnect();
1042        wifiNetworkCallback.expectCallback(CallbackState.LOST);
1043        cellNetworkCallback.assertNoCallback();
1044
1045        mCellNetworkAgent.disconnect();
1046        cellNetworkCallback.expectCallback(CallbackState.LOST);
1047        wifiNetworkCallback.assertNoCallback();
1048    }
1049
1050    private void tryNetworkFactoryRequests(int capability) throws Exception {
1051        // Verify NOT_RESTRICTED is set appropriately
1052        final NetworkCapabilities nc = new NetworkRequest.Builder().addCapability(capability)
1053                .build().networkCapabilities;
1054        if (capability == NET_CAPABILITY_CBS || capability == NET_CAPABILITY_DUN ||
1055                capability == NET_CAPABILITY_EIMS || capability == NET_CAPABILITY_FOTA ||
1056                capability == NET_CAPABILITY_IA || capability == NET_CAPABILITY_IMS ||
1057                capability == NET_CAPABILITY_RCS || capability == NET_CAPABILITY_XCAP) {
1058            assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
1059        } else {
1060            assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
1061        }
1062
1063        NetworkCapabilities filter = new NetworkCapabilities();
1064        filter.addCapability(capability);
1065        final HandlerThread handlerThread = new HandlerThread("testNetworkFactoryRequests");
1066        handlerThread.start();
1067        final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
1068                mServiceContext, "testFactory", filter);
1069        testFactory.setScoreFilter(40);
1070        ConditionVariable cv = testFactory.getNetworkStartedCV();
1071        testFactory.expectAddRequests(1);
1072        testFactory.register();
1073        testFactory.waitForNetworkRequests(1);
1074        int expectedRequestCount = 1;
1075        NetworkCallback networkCallback = null;
1076        // For non-INTERNET capabilities we cannot rely on the default request being present, so
1077        // add one.
1078        if (capability != NET_CAPABILITY_INTERNET) {
1079            assertFalse(testFactory.getMyStartRequested());
1080            NetworkRequest request = new NetworkRequest.Builder().addCapability(capability).build();
1081            networkCallback = new NetworkCallback();
1082            testFactory.expectAddRequests(1);
1083            mCm.requestNetwork(request, networkCallback);
1084            expectedRequestCount++;
1085            testFactory.waitForNetworkRequests(expectedRequestCount);
1086        }
1087        waitFor(cv);
1088        assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
1089        assertTrue(testFactory.getMyStartRequested());
1090
1091        // Now bring in a higher scored network.
1092        MockNetworkAgent testAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1093        // Rather than create a validated network which complicates things by registering it's
1094        // own NetworkRequest during startup, just bump up the score to cancel out the
1095        // unvalidated penalty.
1096        testAgent.adjustScore(40);
1097        cv = testFactory.getNetworkStoppedCV();
1098
1099        // When testAgent connects, ConnectivityService will re-send us all current requests with
1100        // the new score. There are expectedRequestCount such requests, and we must wait for all of
1101        // them.
1102        testFactory.expectAddRequests(expectedRequestCount);
1103        testAgent.connect(false);
1104        testAgent.addCapability(capability);
1105        waitFor(cv);
1106        testFactory.waitForNetworkRequests(expectedRequestCount);
1107        assertFalse(testFactory.getMyStartRequested());
1108
1109        // Bring in a bunch of requests.
1110        testFactory.expectAddRequests(10);
1111        assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
1112        ConnectivityManager.NetworkCallback[] networkCallbacks =
1113                new ConnectivityManager.NetworkCallback[10];
1114        for (int i = 0; i< networkCallbacks.length; i++) {
1115            networkCallbacks[i] = new ConnectivityManager.NetworkCallback();
1116            NetworkRequest.Builder builder = new NetworkRequest.Builder();
1117            builder.addCapability(capability);
1118            mCm.requestNetwork(builder.build(), networkCallbacks[i]);
1119        }
1120        testFactory.waitForNetworkRequests(10 + expectedRequestCount);
1121        assertFalse(testFactory.getMyStartRequested());
1122
1123        // Remove the requests.
1124        testFactory.expectRemoveRequests(10);
1125        for (int i = 0; i < networkCallbacks.length; i++) {
1126            mCm.unregisterNetworkCallback(networkCallbacks[i]);
1127        }
1128        testFactory.waitForNetworkRequests(expectedRequestCount);
1129        assertFalse(testFactory.getMyStartRequested());
1130
1131        // Drop the higher scored network.
1132        cv = testFactory.getNetworkStartedCV();
1133        testAgent.disconnect();
1134        waitFor(cv);
1135        assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
1136        assertTrue(testFactory.getMyStartRequested());
1137
1138        testFactory.unregister();
1139        if (networkCallback != null) mCm.unregisterNetworkCallback(networkCallback);
1140        handlerThread.quit();
1141    }
1142
1143    @LargeTest
1144    public void testNetworkFactoryRequests() throws Exception {
1145        tryNetworkFactoryRequests(NET_CAPABILITY_MMS);
1146        tryNetworkFactoryRequests(NET_CAPABILITY_SUPL);
1147        tryNetworkFactoryRequests(NET_CAPABILITY_DUN);
1148        tryNetworkFactoryRequests(NET_CAPABILITY_FOTA);
1149        tryNetworkFactoryRequests(NET_CAPABILITY_IMS);
1150        tryNetworkFactoryRequests(NET_CAPABILITY_CBS);
1151        tryNetworkFactoryRequests(NET_CAPABILITY_WIFI_P2P);
1152        tryNetworkFactoryRequests(NET_CAPABILITY_IA);
1153        tryNetworkFactoryRequests(NET_CAPABILITY_RCS);
1154        tryNetworkFactoryRequests(NET_CAPABILITY_XCAP);
1155        tryNetworkFactoryRequests(NET_CAPABILITY_EIMS);
1156        tryNetworkFactoryRequests(NET_CAPABILITY_NOT_METERED);
1157        tryNetworkFactoryRequests(NET_CAPABILITY_INTERNET);
1158        tryNetworkFactoryRequests(NET_CAPABILITY_TRUSTED);
1159        tryNetworkFactoryRequests(NET_CAPABILITY_NOT_VPN);
1160        // Skipping VALIDATED and CAPTIVE_PORTAL as they're disallowed.
1161    }
1162
1163    @LargeTest
1164    public void testNoMutableNetworkRequests() throws Exception {
1165        PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, new Intent("a"), 0);
1166        NetworkRequest.Builder builder = new NetworkRequest.Builder();
1167        builder.addCapability(NET_CAPABILITY_VALIDATED);
1168        try {
1169            mCm.requestNetwork(builder.build(), new NetworkCallback());
1170            fail();
1171        } catch (IllegalArgumentException expected) {}
1172        try {
1173            mCm.requestNetwork(builder.build(), pendingIntent);
1174            fail();
1175        } catch (IllegalArgumentException expected) {}
1176        builder = new NetworkRequest.Builder();
1177        builder.addCapability(NET_CAPABILITY_CAPTIVE_PORTAL);
1178        try {
1179            mCm.requestNetwork(builder.build(), new NetworkCallback());
1180            fail();
1181        } catch (IllegalArgumentException expected) {}
1182        try {
1183            mCm.requestNetwork(builder.build(), pendingIntent);
1184            fail();
1185        } catch (IllegalArgumentException expected) {}
1186    }
1187
1188    @LargeTest
1189    public void testMMSonWiFi() throws Exception {
1190        // Test bringing up cellular without MMS NetworkRequest gets reaped
1191        mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1192        mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS);
1193        ConditionVariable cv = mCellNetworkAgent.getDisconnectedCV();
1194        mCellNetworkAgent.connectWithoutInternet();
1195        waitFor(cv);
1196        waitFor(new Criteria() {
1197                public boolean get() { return mCm.getAllNetworks().length == 0; } });
1198        verifyNoNetwork();
1199        // Test bringing up validated WiFi.
1200        mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1201        cv = waitForConnectivityBroadcasts(1);
1202        mWiFiNetworkAgent.connect(true);
1203        waitFor(cv);
1204        verifyActiveNetwork(TRANSPORT_WIFI);
1205        // Register MMS NetworkRequest
1206        NetworkRequest.Builder builder = new NetworkRequest.Builder();
1207        builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
1208        final TestNetworkCallback networkCallback = new TestNetworkCallback();
1209        mCm.requestNetwork(builder.build(), networkCallback);
1210        // Test bringing up unvalidated cellular with MMS
1211        mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1212        mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS);
1213        mCellNetworkAgent.connectWithoutInternet();
1214        networkCallback.expectCallback(CallbackState.AVAILABLE);
1215        verifyActiveNetwork(TRANSPORT_WIFI);
1216        // Test releasing NetworkRequest disconnects cellular with MMS
1217        cv = mCellNetworkAgent.getDisconnectedCV();
1218        mCm.unregisterNetworkCallback(networkCallback);
1219        waitFor(cv);
1220        verifyActiveNetwork(TRANSPORT_WIFI);
1221    }
1222
1223    @LargeTest
1224    public void testMMSonCell() throws Exception {
1225        // Test bringing up cellular without MMS
1226        mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1227        ConditionVariable cv = waitForConnectivityBroadcasts(1);
1228        mCellNetworkAgent.connect(false);
1229        waitFor(cv);
1230        verifyActiveNetwork(TRANSPORT_CELLULAR);
1231        // Register MMS NetworkRequest
1232        NetworkRequest.Builder builder = new NetworkRequest.Builder();
1233        builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
1234        final TestNetworkCallback networkCallback = new TestNetworkCallback();
1235        mCm.requestNetwork(builder.build(), networkCallback);
1236        // Test bringing up MMS cellular network
1237        MockNetworkAgent mmsNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1238        mmsNetworkAgent.addCapability(NET_CAPABILITY_MMS);
1239        mmsNetworkAgent.connectWithoutInternet();
1240        networkCallback.expectCallback(CallbackState.AVAILABLE);
1241        verifyActiveNetwork(TRANSPORT_CELLULAR);
1242        // Test releasing MMS NetworkRequest does not disconnect main cellular NetworkAgent
1243        cv = mmsNetworkAgent.getDisconnectedCV();
1244        mCm.unregisterNetworkCallback(networkCallback);
1245        waitFor(cv);
1246        verifyActiveNetwork(TRANSPORT_CELLULAR);
1247    }
1248
1249    @LargeTest
1250    public void testCaptivePortal() {
1251        final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
1252        final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
1253                .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
1254        mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
1255
1256        final TestNetworkCallback validatedCallback = new TestNetworkCallback();
1257        final NetworkRequest validatedRequest = new NetworkRequest.Builder()
1258                .addCapability(NET_CAPABILITY_VALIDATED).build();
1259        mCm.registerNetworkCallback(validatedRequest, validatedCallback);
1260
1261        // Bring up a network with a captive portal.
1262        // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
1263        mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1264        mWiFiNetworkAgent.connectWithCaptivePortal();
1265        captivePortalCallback.expectCallback(CallbackState.AVAILABLE);
1266
1267        // Take down network.
1268        // Expect onLost callback.
1269        mWiFiNetworkAgent.disconnect();
1270        captivePortalCallback.expectCallback(CallbackState.LOST);
1271
1272        // Bring up a network with a captive portal.
1273        // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
1274        mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1275        mWiFiNetworkAgent.connectWithCaptivePortal();
1276        captivePortalCallback.expectCallback(CallbackState.AVAILABLE);
1277
1278        // Make captive portal disappear then revalidate.
1279        // Expect onLost callback because network no longer provides NET_CAPABILITY_CAPTIVE_PORTAL.
1280        mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 204;
1281        mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
1282        captivePortalCallback.expectCallback(CallbackState.LOST);
1283
1284        // Expect NET_CAPABILITY_VALIDATED onAvailable callback.
1285        validatedCallback.expectCallback(CallbackState.AVAILABLE);
1286
1287        // Break network connectivity.
1288        // Expect NET_CAPABILITY_VALIDATED onLost callback.
1289        mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 500;
1290        mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), false);
1291        validatedCallback.expectCallback(CallbackState.LOST);
1292    }
1293
1294    private static class TestKeepaliveCallback extends PacketKeepaliveCallback {
1295
1296        public static enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR };
1297
1298        private class CallbackValue {
1299            public CallbackType callbackType;
1300            public int error;
1301
1302            public CallbackValue(CallbackType type) {
1303                this.callbackType = type;
1304                this.error = PacketKeepalive.SUCCESS;
1305                assertTrue("onError callback must have error", type != CallbackType.ON_ERROR);
1306            }
1307
1308            public CallbackValue(CallbackType type, int error) {
1309                this.callbackType = type;
1310                this.error = error;
1311                assertEquals("error can only be set for onError", type, CallbackType.ON_ERROR);
1312            }
1313
1314            @Override
1315            public boolean equals(Object o) {
1316                return o instanceof CallbackValue &&
1317                        this.callbackType == ((CallbackValue) o).callbackType &&
1318                        this.error == ((CallbackValue) o).error;
1319            }
1320
1321            @Override
1322            public String toString() {
1323                return String.format("%s(%s, %d)", getClass().getSimpleName(), callbackType, error);
1324            }
1325        }
1326
1327        private LinkedBlockingQueue<CallbackValue> mCallbacks = new LinkedBlockingQueue<>();
1328
1329        @Override
1330        public void onStarted() {
1331            mCallbacks.add(new CallbackValue(CallbackType.ON_STARTED));
1332        }
1333
1334        @Override
1335        public void onStopped() {
1336            mCallbacks.add(new CallbackValue(CallbackType.ON_STOPPED));
1337        }
1338
1339        @Override
1340        public void onError(int error) {
1341            mCallbacks.add(new CallbackValue(CallbackType.ON_ERROR, error));
1342        }
1343
1344        private void expectCallback(CallbackValue callbackValue) {
1345            try {
1346                assertEquals(
1347                        callbackValue,
1348                        mCallbacks.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
1349            } catch (InterruptedException e) {
1350                fail(callbackValue.callbackType + " callback not seen after " + TIMEOUT_MS + " ms");
1351            }
1352        }
1353
1354        public void expectStarted() {
1355            expectCallback(new CallbackValue(CallbackType.ON_STARTED));
1356        }
1357
1358        public void expectStopped() {
1359            expectCallback(new CallbackValue(CallbackType.ON_STOPPED));
1360        }
1361
1362        public void expectError(int error) {
1363            expectCallback(new CallbackValue(CallbackType.ON_ERROR, error));
1364        }
1365    }
1366
1367    private Network connectKeepaliveNetwork(LinkProperties lp) {
1368        // Ensure the network is disconnected before we do anything.
1369        if (mWiFiNetworkAgent != null) {
1370            assertNull(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()));
1371        }
1372
1373        mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1374        ConditionVariable cv = waitForConnectivityBroadcasts(1);
1375        mWiFiNetworkAgent.connect(true);
1376        waitFor(cv);
1377        verifyActiveNetwork(TRANSPORT_WIFI);
1378        mWiFiNetworkAgent.sendLinkProperties(lp);
1379        mService.waitForIdle();
1380        return mWiFiNetworkAgent.getNetwork();
1381    }
1382
1383    public void testPacketKeepalives() throws Exception {
1384        InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
1385        InetAddress notMyIPv4 = InetAddress.getByName("192.0.2.35");
1386        InetAddress myIPv6 = InetAddress.getByName("2001:db8::1");
1387        InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8");
1388        InetAddress dstIPv6 = InetAddress.getByName("2001:4860:4860::8888");
1389
1390        LinkProperties lp = new LinkProperties();
1391        lp.setInterfaceName("wlan12");
1392        lp.addLinkAddress(new LinkAddress(myIPv6, 64));
1393        lp.addLinkAddress(new LinkAddress(myIPv4, 25));
1394        lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
1395        lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
1396
1397        Network notMyNet = new Network(61234);
1398        Network myNet = connectKeepaliveNetwork(lp);
1399
1400        TestKeepaliveCallback callback = new TestKeepaliveCallback();
1401        PacketKeepalive ka;
1402
1403        // Attempt to start keepalives with invalid parameters and check for errors.
1404        ka = mCm.startNattKeepalive(notMyNet, 25, callback, myIPv4, 1234, dstIPv4);
1405        callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK);
1406
1407        ka = mCm.startNattKeepalive(myNet, 19, callback, notMyIPv4, 1234, dstIPv4);
1408        callback.expectError(PacketKeepalive.ERROR_INVALID_INTERVAL);
1409
1410        ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 1234, dstIPv6);
1411        callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
1412
1413        ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv6, 1234, dstIPv4);
1414        callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
1415
1416        ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv6, 1234, dstIPv6);
1417        callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);  // NAT-T is IPv4-only.
1418
1419        ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 123456, dstIPv4);
1420        callback.expectError(PacketKeepalive.ERROR_INVALID_PORT);
1421
1422        ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 123456, dstIPv4);
1423        callback.expectError(PacketKeepalive.ERROR_INVALID_PORT);
1424
1425        ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
1426        callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
1427
1428        ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
1429        callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
1430
1431        // Check that a started keepalive can be stopped.
1432        mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS);
1433        ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
1434        callback.expectStarted();
1435        mWiFiNetworkAgent.setStopKeepaliveError(PacketKeepalive.SUCCESS);
1436        ka.stop();
1437        callback.expectStopped();
1438
1439        // Check that deleting the IP address stops the keepalive.
1440        LinkProperties bogusLp = new LinkProperties(lp);
1441        ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
1442        callback.expectStarted();
1443        bogusLp.removeLinkAddress(new LinkAddress(myIPv4, 25));
1444        bogusLp.addLinkAddress(new LinkAddress(notMyIPv4, 25));
1445        mWiFiNetworkAgent.sendLinkProperties(bogusLp);
1446        callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
1447        mWiFiNetworkAgent.sendLinkProperties(lp);
1448
1449        // Check that a started keepalive is stopped correctly when the network disconnects.
1450        ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
1451        callback.expectStarted();
1452        mWiFiNetworkAgent.disconnect();
1453        callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK);
1454
1455        // ... and that stopping it after that has no adverse effects.
1456        assertNull(mCm.getNetworkCapabilities(myNet));
1457        ka.stop();
1458
1459        // Reconnect.
1460        myNet = connectKeepaliveNetwork(lp);
1461        mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS);
1462
1463        // Check things work as expected when the keepalive is stopped and the network disconnects.
1464        ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
1465        callback.expectStarted();
1466        ka.stop();
1467        mWiFiNetworkAgent.disconnect();
1468        mService.waitForIdle();
1469        callback.expectStopped();
1470
1471        // Reconnect.
1472        myNet = connectKeepaliveNetwork(lp);
1473        mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS);
1474
1475        // Check that keepalive slots start from 1 and increment. The first one gets slot 1.
1476        mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
1477        ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
1478        callback.expectStarted();
1479
1480        // The second one gets slot 2.
1481        mWiFiNetworkAgent.setExpectedKeepaliveSlot(2);
1482        TestKeepaliveCallback callback2 = new TestKeepaliveCallback();
1483        PacketKeepalive ka2 = mCm.startNattKeepalive(myNet, 25, callback2, myIPv4, 6789, dstIPv4);
1484        callback2.expectStarted();
1485
1486        // Now stop the first one and create a third. This also gets slot 1.
1487        ka.stop();
1488        callback.expectStopped();
1489
1490        mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
1491        TestKeepaliveCallback callback3 = new TestKeepaliveCallback();
1492        PacketKeepalive ka3 = mCm.startNattKeepalive(myNet, 25, callback3, myIPv4, 9876, dstIPv4);
1493        callback3.expectStarted();
1494
1495        ka2.stop();
1496        callback2.expectStopped();
1497
1498        ka3.stop();
1499        callback3.expectStopped();
1500    }
1501}
1502