[go: nahoru, domu]

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