OSDN Git Service

Docs: Fixes broken link in Javadoc. am: df0fd34d50 am: 506a8b39fb
[android-x86/frameworks-base.git] / services / tests / servicestests / src / com / android / server / ConnectivityServiceTest.java
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
17 package com.android.server;
18
19 import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
20 import static android.net.ConnectivityManager.TYPE_ETHERNET;
21 import static android.net.ConnectivityManager.TYPE_MOBILE;
22 import static android.net.ConnectivityManager.TYPE_WIFI;
23 import static android.net.ConnectivityManager.getNetworkTypeName;
24 import static android.net.NetworkCapabilities.*;
25
26 import static org.mockito.Mockito.mock;
27
28 import android.app.NotificationManager;
29 import android.app.PendingIntent;
30 import android.content.BroadcastReceiver;
31 import android.content.ContentResolver;
32 import android.content.Context;
33 import android.content.ContextWrapper;
34 import android.content.Intent;
35 import android.content.IntentFilter;
36 import android.net.ConnectivityManager;
37 import android.net.ConnectivityManager.NetworkCallback;
38 import android.net.ConnectivityManager.PacketKeepalive;
39 import android.net.ConnectivityManager.PacketKeepaliveCallback;
40 import android.net.INetworkPolicyManager;
41 import android.net.INetworkStatsService;
42 import android.net.IpPrefix;
43 import android.net.LinkAddress;
44 import android.net.LinkProperties;
45 import android.net.Network;
46 import android.net.NetworkAgent;
47 import android.net.NetworkCapabilities;
48 import android.net.NetworkConfig;
49 import android.net.NetworkFactory;
50 import android.net.NetworkInfo;
51 import android.net.NetworkInfo.DetailedState;
52 import android.net.NetworkMisc;
53 import android.net.NetworkRequest;
54 import android.net.RouteInfo;
55 import android.net.metrics.IpConnectivityLog;
56 import android.net.util.AvoidBadWifiTracker;
57 import android.os.ConditionVariable;
58 import android.os.Handler;
59 import android.os.HandlerThread;
60 import android.os.IBinder;
61 import android.os.INetworkManagementService;
62 import android.os.Looper;
63 import android.os.Message;
64 import android.os.MessageQueue;
65 import android.os.Messenger;
66 import android.os.MessageQueue.IdleHandler;
67 import android.os.Process;
68 import android.os.SystemClock;
69 import android.provider.Settings;
70 import android.test.AndroidTestCase;
71 import android.test.mock.MockContentResolver;
72 import android.test.suitebuilder.annotation.LargeTest;
73 import android.test.suitebuilder.annotation.SmallTest;
74 import android.util.Log;
75 import android.util.LogPrinter;
76
77 import com.android.internal.util.FakeSettingsProvider;
78 import com.android.internal.util.WakeupMessage;
79 import com.android.server.connectivity.NetworkAgentInfo;
80 import com.android.server.connectivity.NetworkMonitor;
81 import com.android.server.connectivity.NetworkMonitor.CaptivePortalProbeResult;
82 import com.android.server.net.NetworkPinner;
83
84 import java.net.InetAddress;
85 import java.util.ArrayList;
86 import java.util.Arrays;
87 import java.util.Objects;
88 import java.util.concurrent.CountDownLatch;
89 import java.util.concurrent.LinkedBlockingQueue;
90 import java.util.concurrent.TimeUnit;
91 import java.util.concurrent.atomic.AtomicBoolean;
92
93 /**
94  * Tests for {@link ConnectivityService}.
95  *
96  * Build, install and run with:
97  *  runtest frameworks-services -c com.android.server.ConnectivityServiceTest
98  */
99 public class ConnectivityServiceTest extends AndroidTestCase {
100     private static final String TAG = "ConnectivityServiceTest";
101
102     private static final int TIMEOUT_MS = 500;
103     private static final int TEST_LINGER_DELAY_MS = 120;
104
105     private BroadcastInterceptingContext mServiceContext;
106     private WrappedConnectivityService mService;
107     private WrappedConnectivityManager mCm;
108     private MockNetworkAgent mWiFiNetworkAgent;
109     private MockNetworkAgent mCellNetworkAgent;
110     private MockNetworkAgent mEthernetNetworkAgent;
111
112     // This class exists to test bindProcessToNetwork and getBoundNetworkForProcess. These methods
113     // do not go through ConnectivityService but talk to netd directly, so they don't automatically
114     // reflect the state of our test ConnectivityService.
115     private class WrappedConnectivityManager extends ConnectivityManager {
116         private Network mFakeBoundNetwork;
117
118         public synchronized boolean bindProcessToNetwork(Network network) {
119             mFakeBoundNetwork = network;
120             return true;
121         }
122
123         public synchronized Network getBoundNetworkForProcess() {
124             return mFakeBoundNetwork;
125         }
126
127         public WrappedConnectivityManager(Context context, ConnectivityService service) {
128             super(context, service);
129         }
130     }
131
132     private class MockContext extends BroadcastInterceptingContext {
133         private final MockContentResolver mContentResolver;
134
135         MockContext(Context base) {
136             super(base);
137             mContentResolver = new MockContentResolver();
138             mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
139         }
140
141         @Override
142         public Object getSystemService(String name) {
143             if (Context.CONNECTIVITY_SERVICE.equals(name)) return mCm;
144             if (Context.NOTIFICATION_SERVICE.equals(name)) return mock(NotificationManager.class);
145             return super.getSystemService(name);
146         }
147
148         @Override
149         public ContentResolver getContentResolver() {
150             return mContentResolver;
151         }
152     }
153
154     /**
155      * A subclass of HandlerThread that allows callers to wait for it to become idle. waitForIdle
156      * will return immediately if the handler is already idle.
157      */
158     private class IdleableHandlerThread extends HandlerThread {
159         private IdleHandler mIdleHandler;
160
161         public IdleableHandlerThread(String name) {
162             super(name);
163         }
164
165         public void waitForIdle(int timeoutMs) {
166             final ConditionVariable cv = new ConditionVariable();
167             final MessageQueue queue = getLooper().getQueue();
168
169             synchronized (queue) {
170                 if (queue.isIdle()) {
171                     return;
172                 }
173
174                 assertNull("BUG: only one idle handler allowed", mIdleHandler);
175                 mIdleHandler = new IdleHandler() {
176                     public boolean queueIdle() {
177                         synchronized (queue) {
178                             cv.open();
179                             mIdleHandler = null;
180                             return false;  // Remove the handler.
181                         }
182                     }
183                 };
184                 queue.addIdleHandler(mIdleHandler);
185             }
186
187             if (!cv.block(timeoutMs)) {
188                 fail("HandlerThread " + getName() +
189                         " did not become idle after " + timeoutMs + " ms");
190                 queue.removeIdleHandler(mIdleHandler);
191             }
192         }
193     }
194
195     // Tests that IdleableHandlerThread works as expected.
196     public void testIdleableHandlerThread() {
197         final int attempts = 50;  // Causes the test to take about 200ms on bullhead-eng.
198
199         // Tests that waitForIdle returns immediately if the service is already idle.
200         for (int i = 0; i < attempts; i++) {
201             mService.waitForIdle();
202         }
203
204         // Bring up a network that we can use to send messages to ConnectivityService.
205         ConditionVariable cv = waitForConnectivityBroadcasts(1);
206         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
207         mWiFiNetworkAgent.connect(false);
208         waitFor(cv);
209         Network n = mWiFiNetworkAgent.getNetwork();
210         assertNotNull(n);
211
212         // Tests that calling waitForIdle waits for messages to be processed.
213         for (int i = 0; i < attempts; i++) {
214             mWiFiNetworkAgent.setSignalStrength(i);
215             mService.waitForIdle();
216             assertEquals(i, mCm.getNetworkCapabilities(n).getSignalStrength());
217         }
218
219         // Ensure that not calling waitForIdle causes a race condition.
220         for (int i = 0; i < attempts; i++) {
221             mWiFiNetworkAgent.setSignalStrength(i);
222             if (i != mCm.getNetworkCapabilities(n).getSignalStrength()) {
223                 // We hit a race condition, as expected. Pass the test.
224                 return;
225             }
226         }
227
228         // No race? There is a bug in this test.
229         fail("expected race condition at least once in " + attempts + " attempts");
230     }
231
232     private class MockNetworkAgent {
233         private final WrappedNetworkMonitor mWrappedNetworkMonitor;
234         private final NetworkInfo mNetworkInfo;
235         private final NetworkCapabilities mNetworkCapabilities;
236         private final IdleableHandlerThread mHandlerThread;
237         private final ConditionVariable mDisconnected = new ConditionVariable();
238         private final ConditionVariable mNetworkStatusReceived = new ConditionVariable();
239         private final ConditionVariable mPreventReconnectReceived = new ConditionVariable();
240         private int mScore;
241         private NetworkAgent mNetworkAgent;
242         private int mStartKeepaliveError = PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED;
243         private int mStopKeepaliveError = PacketKeepalive.NO_KEEPALIVE;
244         private Integer mExpectedKeepaliveSlot = null;
245         // Contains the redirectUrl from networkStatus(). Before reading, wait for
246         // mNetworkStatusReceived.
247         private String mRedirectUrl;
248
249         MockNetworkAgent(int transport) {
250             final int type = transportToLegacyType(transport);
251             final String typeName = ConnectivityManager.getNetworkTypeName(type);
252             mNetworkInfo = new NetworkInfo(type, 0, typeName, "Mock");
253             mNetworkCapabilities = new NetworkCapabilities();
254             mNetworkCapabilities.addTransportType(transport);
255             switch (transport) {
256                 case TRANSPORT_ETHERNET:
257                     mScore = 70;
258                     break;
259                 case TRANSPORT_WIFI:
260                     mScore = 60;
261                     break;
262                 case TRANSPORT_CELLULAR:
263                     mScore = 50;
264                     break;
265                 default:
266                     throw new UnsupportedOperationException("unimplemented network type");
267             }
268             mHandlerThread = new IdleableHandlerThread("Mock-" + typeName);
269             mHandlerThread.start();
270             mNetworkAgent = new NetworkAgent(mHandlerThread.getLooper(), mServiceContext,
271                     "Mock-" + typeName, mNetworkInfo, mNetworkCapabilities,
272                     new LinkProperties(), mScore, new NetworkMisc()) {
273                 @Override
274                 public void unwanted() { mDisconnected.open(); }
275
276                 @Override
277                 public void startPacketKeepalive(Message msg) {
278                     int slot = msg.arg1;
279                     if (mExpectedKeepaliveSlot != null) {
280                         assertEquals((int) mExpectedKeepaliveSlot, slot);
281                     }
282                     onPacketKeepaliveEvent(slot, mStartKeepaliveError);
283                 }
284
285                 @Override
286                 public void stopPacketKeepalive(Message msg) {
287                     onPacketKeepaliveEvent(msg.arg1, mStopKeepaliveError);
288                 }
289
290                 @Override
291                 public void networkStatus(int status, String redirectUrl) {
292                     mRedirectUrl = redirectUrl;
293                     mNetworkStatusReceived.open();
294                 }
295
296                 @Override
297                 protected void preventAutomaticReconnect() {
298                     mPreventReconnectReceived.open();
299                 }
300             };
301             // Waits for the NetworkAgent to be registered, which includes the creation of the
302             // NetworkMonitor.
303             mService.waitForIdle();
304             mWrappedNetworkMonitor = mService.getLastCreatedWrappedNetworkMonitor();
305         }
306
307         public void waitForIdle(int timeoutMs) {
308             mHandlerThread.waitForIdle(timeoutMs);
309         }
310
311         public void waitForIdle() {
312             waitForIdle(TIMEOUT_MS);
313         }
314
315         public void adjustScore(int change) {
316             mScore += change;
317             mNetworkAgent.sendNetworkScore(mScore);
318         }
319
320         public void addCapability(int capability) {
321             mNetworkCapabilities.addCapability(capability);
322             mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
323         }
324
325         public void removeCapability(int capability) {
326             mNetworkCapabilities.removeCapability(capability);
327             mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
328         }
329
330         public void setSignalStrength(int signalStrength) {
331             mNetworkCapabilities.setSignalStrength(signalStrength);
332             mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
333         }
334
335         public void connectWithoutInternet() {
336             mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, null);
337             mNetworkAgent.sendNetworkInfo(mNetworkInfo);
338         }
339
340         /**
341          * Transition this NetworkAgent to CONNECTED state with NET_CAPABILITY_INTERNET.
342          * @param validated Indicate if network should pretend to be validated.
343          */
344         public void connect(boolean validated) {
345             assertEquals("MockNetworkAgents can only be connected once",
346                     mNetworkInfo.getDetailedState(), DetailedState.IDLE);
347             assertFalse(mNetworkCapabilities.hasCapability(NET_CAPABILITY_INTERNET));
348
349             NetworkCallback callback = null;
350             final ConditionVariable validatedCv = new ConditionVariable();
351             if (validated) {
352                 mWrappedNetworkMonitor.gen204ProbeResult = 204;
353                 NetworkRequest request = new NetworkRequest.Builder()
354                         .addTransportType(mNetworkCapabilities.getTransportTypes()[0])
355                         .build();
356                 callback = new NetworkCallback() {
357                     public void onCapabilitiesChanged(Network network,
358                             NetworkCapabilities networkCapabilities) {
359                         if (network.equals(getNetwork()) &&
360                             networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED)) {
361                             validatedCv.open();
362                         }
363                     }
364                 };
365                 mCm.registerNetworkCallback(request, callback);
366             }
367             addCapability(NET_CAPABILITY_INTERNET);
368
369             connectWithoutInternet();
370
371             if (validated) {
372                 // Wait for network to validate.
373                 waitFor(validatedCv);
374                 mWrappedNetworkMonitor.gen204ProbeResult = 500;
375             }
376
377             if (callback != null) mCm.unregisterNetworkCallback(callback);
378         }
379
380         public void connectWithCaptivePortal(String redirectUrl) {
381             mWrappedNetworkMonitor.gen204ProbeResult = 200;
382             mWrappedNetworkMonitor.gen204ProbeRedirectUrl = redirectUrl;
383             connect(false);
384         }
385
386         public void disconnect() {
387             mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, null);
388             mNetworkAgent.sendNetworkInfo(mNetworkInfo);
389         }
390
391         public Network getNetwork() {
392             return new Network(mNetworkAgent.netId);
393         }
394
395         public ConditionVariable getPreventReconnectReceived() {
396             return mPreventReconnectReceived;
397         }
398
399         public ConditionVariable getDisconnectedCV() {
400             return mDisconnected;
401         }
402
403         public WrappedNetworkMonitor getWrappedNetworkMonitor() {
404             return mWrappedNetworkMonitor;
405         }
406
407         public void sendLinkProperties(LinkProperties lp) {
408             mNetworkAgent.sendLinkProperties(lp);
409         }
410
411         public void setStartKeepaliveError(int error) {
412             mStartKeepaliveError = error;
413         }
414
415         public void setStopKeepaliveError(int error) {
416             mStopKeepaliveError = error;
417         }
418
419         public void setExpectedKeepaliveSlot(Integer slot) {
420             mExpectedKeepaliveSlot = slot;
421         }
422
423         public String waitForRedirectUrl() {
424             assertTrue(mNetworkStatusReceived.block(TIMEOUT_MS));
425             return mRedirectUrl;
426         }
427     }
428
429     /**
430      * A NetworkFactory that allows tests to wait until any in-flight NetworkRequest add or remove
431      * operations have been processed. Before ConnectivityService can add or remove any requests,
432      * the factory must be told to expect those operations by calling expectAddRequests or
433      * expectRemoveRequests.
434      */
435     private static class MockNetworkFactory extends NetworkFactory {
436         private final ConditionVariable mNetworkStartedCV = new ConditionVariable();
437         private final ConditionVariable mNetworkStoppedCV = new ConditionVariable();
438         private final AtomicBoolean mNetworkStarted = new AtomicBoolean(false);
439
440         // Used to expect that requests be removed or added on a separate thread, without sleeping.
441         // Callers can call either expectAddRequests() or expectRemoveRequests() exactly once, then
442         // cause some other thread to add or remove requests, then call waitForRequests(). We can
443         // either expect requests to be added or removed, but not both, because CountDownLatch can
444         // only count in one direction.
445         private CountDownLatch mExpectations;
446
447         // Whether we are currently expecting requests to be added or removed. Valid only if
448         // mExpectations is non-null.
449         private boolean mExpectingAdditions;
450
451         public MockNetworkFactory(Looper looper, Context context, String logTag,
452                 NetworkCapabilities filter) {
453             super(looper, context, logTag, filter);
454         }
455
456         public int getMyRequestCount() {
457             return getRequestCount();
458         }
459
460         protected void startNetwork() {
461             mNetworkStarted.set(true);
462             mNetworkStartedCV.open();
463         }
464
465         protected void stopNetwork() {
466             mNetworkStarted.set(false);
467             mNetworkStoppedCV.open();
468         }
469
470         public boolean getMyStartRequested() {
471             return mNetworkStarted.get();
472         }
473
474         public ConditionVariable getNetworkStartedCV() {
475             mNetworkStartedCV.close();
476             return mNetworkStartedCV;
477         }
478
479         public ConditionVariable getNetworkStoppedCV() {
480             mNetworkStoppedCV.close();
481             return mNetworkStoppedCV;
482         }
483
484         @Override
485         protected void handleAddRequest(NetworkRequest request, int score) {
486             // If we're expecting anything, we must be expecting additions.
487             if (mExpectations != null && !mExpectingAdditions) {
488                 fail("Can't add requests while expecting requests to be removed");
489             }
490
491             // Add the request.
492             super.handleAddRequest(request, score);
493
494             // Reduce the number of request additions we're waiting for.
495             if (mExpectingAdditions) {
496                 assertTrue("Added more requests than expected", mExpectations.getCount() > 0);
497                 mExpectations.countDown();
498             }
499         }
500
501         @Override
502         protected void handleRemoveRequest(NetworkRequest request) {
503             // If we're expecting anything, we must be expecting removals.
504             if (mExpectations != null && mExpectingAdditions) {
505                 fail("Can't remove requests while expecting requests to be added");
506             }
507
508             // Remove the request.
509             super.handleRemoveRequest(request);
510
511             // Reduce the number of request removals we're waiting for.
512             if (!mExpectingAdditions) {
513                 assertTrue("Removed more requests than expected", mExpectations.getCount() > 0);
514                 mExpectations.countDown();
515             }
516         }
517
518         private void assertNoExpectations() {
519             if (mExpectations != null) {
520                 fail("Can't add expectation, " + mExpectations.getCount() + " already pending");
521             }
522         }
523
524         // Expects that count requests will be added.
525         public void expectAddRequests(final int count) {
526             assertNoExpectations();
527             mExpectingAdditions = true;
528             mExpectations = new CountDownLatch(count);
529         }
530
531         // Expects that count requests will be removed.
532         public void expectRemoveRequests(final int count) {
533             assertNoExpectations();
534             mExpectingAdditions = false;
535             mExpectations = new CountDownLatch(count);
536         }
537
538         // Waits for the expected request additions or removals to happen within a timeout.
539         public void waitForRequests() throws InterruptedException {
540             assertNotNull("Nothing to wait for", mExpectations);
541             mExpectations.await(TIMEOUT_MS, TimeUnit.MILLISECONDS);
542             final long count = mExpectations.getCount();
543             final String msg = count + " requests still not " +
544                     (mExpectingAdditions ? "added" : "removed") +
545                     " after " + TIMEOUT_MS + " ms";
546             assertEquals(msg, 0, count);
547             mExpectations = null;
548         }
549
550         public void waitForNetworkRequests(final int count) throws InterruptedException {
551             waitForRequests();
552             assertEquals(count, getMyRequestCount());
553         }
554     }
555
556     private class FakeWakeupMessage extends WakeupMessage {
557         private static final int UNREASONABLY_LONG_WAIT = 1000;
558
559         public FakeWakeupMessage(Context context, Handler handler, String cmdName, int cmd) {
560             super(context, handler, cmdName, cmd);
561         }
562
563         public FakeWakeupMessage(Context context, Handler handler, String cmdName, int cmd,
564                 int arg1, int arg2, Object obj) {
565             super(context, handler, cmdName, cmd, arg1, arg2, obj);
566         }
567
568         @Override
569         public void schedule(long when) {
570             long delayMs = when - SystemClock.elapsedRealtime();
571             if (delayMs < 0) delayMs = 0;
572             if (delayMs > UNREASONABLY_LONG_WAIT) {
573                 fail("Attempting to send msg more than " + UNREASONABLY_LONG_WAIT +
574                         "ms into the future: " + delayMs);
575             }
576             Message msg = mHandler.obtainMessage(mCmd, mArg1, mArg2, mObj);
577             mHandler.sendMessageDelayed(msg, delayMs);
578         }
579
580         @Override
581         public void cancel() {
582             mHandler.removeMessages(mCmd, mObj);
583         }
584
585         @Override
586         public void onAlarm() {
587             throw new AssertionError("Should never happen. Update this fake.");
588         }
589     }
590
591     // NetworkMonitor implementation allowing overriding of Internet connectivity probe result.
592     private class WrappedNetworkMonitor extends NetworkMonitor {
593         // HTTP response code fed back to NetworkMonitor for Internet connectivity probe.
594         public int gen204ProbeResult = 500;
595         public String gen204ProbeRedirectUrl = null;
596
597         public WrappedNetworkMonitor(Context context, Handler handler,
598                 NetworkAgentInfo networkAgentInfo, NetworkRequest defaultRequest,
599                 IpConnectivityLog log) {
600             super(context, handler, networkAgentInfo, defaultRequest, log);
601         }
602
603         @Override
604         protected CaptivePortalProbeResult isCaptivePortal() {
605             if (!mIsCaptivePortalCheckEnabled) { return new CaptivePortalProbeResult(204); }
606             return new CaptivePortalProbeResult(gen204ProbeResult, gen204ProbeRedirectUrl, null);
607         }
608     }
609
610     private class WrappedAvoidBadWifiTracker extends AvoidBadWifiTracker {
611         public boolean configRestrictsAvoidBadWifi;
612
613         public WrappedAvoidBadWifiTracker(Context c, Handler h, Runnable r) {
614             super(c, h, r);
615         }
616
617         @Override
618         public boolean configRestrictsAvoidBadWifi() {
619             return configRestrictsAvoidBadWifi;
620         }
621     }
622
623     private class WrappedConnectivityService extends ConnectivityService {
624         public WrappedAvoidBadWifiTracker wrappedAvoidBadWifiTracker;
625         private WrappedNetworkMonitor mLastCreatedNetworkMonitor;
626
627         public WrappedConnectivityService(Context context, INetworkManagementService netManager,
628                 INetworkStatsService statsService, INetworkPolicyManager policyManager,
629                 IpConnectivityLog log) {
630             super(context, netManager, statsService, policyManager, log);
631             mLingerDelayMs = TEST_LINGER_DELAY_MS;
632         }
633
634         @Override
635         protected HandlerThread createHandlerThread() {
636             return new IdleableHandlerThread("WrappedConnectivityService");
637         }
638
639         @Override
640         protected int getDefaultTcpRwnd() {
641             // Prevent wrapped ConnectivityService from trying to write to SystemProperties.
642             return 0;
643         }
644
645         @Override
646         protected int reserveNetId() {
647             while (true) {
648                 final int netId = super.reserveNetId();
649
650                 // Don't overlap test NetIDs with real NetIDs as binding sockets to real networks
651                 // can have odd side-effects, like network validations succeeding.
652                 final Network[] networks = ConnectivityManager.from(getContext()).getAllNetworks();
653                 boolean overlaps = false;
654                 for (Network network : networks) {
655                     if (netId == network.netId) {
656                         overlaps = true;
657                         break;
658                     }
659                 }
660                 if (overlaps) continue;
661
662                 return netId;
663             }
664         }
665
666         @Override
667         public NetworkMonitor createNetworkMonitor(Context context, Handler handler,
668                 NetworkAgentInfo nai, NetworkRequest defaultRequest) {
669             final WrappedNetworkMonitor monitor = new WrappedNetworkMonitor(
670                     context, handler, nai, defaultRequest, mock(IpConnectivityLog.class));
671             mLastCreatedNetworkMonitor = monitor;
672             return monitor;
673         }
674
675         @Override
676         public AvoidBadWifiTracker createAvoidBadWifiTracker(
677                 Context c, Handler h, Runnable r) {
678             final WrappedAvoidBadWifiTracker tracker = new WrappedAvoidBadWifiTracker(c, h, r);
679             return tracker;
680         }
681
682         public WrappedAvoidBadWifiTracker getAvoidBadWifiTracker() {
683             return (WrappedAvoidBadWifiTracker) mAvoidBadWifiTracker;
684         }
685
686         @Override
687         public WakeupMessage makeWakeupMessage(
688                 Context context, Handler handler, String cmdName, int cmd, Object obj) {
689             return new FakeWakeupMessage(context, handler, cmdName, cmd, 0, 0, obj);
690         }
691
692         public WrappedNetworkMonitor getLastCreatedWrappedNetworkMonitor() {
693             return mLastCreatedNetworkMonitor;
694         }
695
696         public void waitForIdle(int timeoutMs) {
697             ((IdleableHandlerThread) mHandlerThread).waitForIdle(timeoutMs);
698         }
699
700         public void waitForIdle() {
701             waitForIdle(TIMEOUT_MS);
702         }
703     }
704
705     private interface Criteria {
706         public boolean get();
707     }
708
709     /**
710      * Wait up to 500ms for {@code criteria.get()} to become true, polling.
711      * Fails if 500ms goes by before {@code criteria.get()} to become true.
712      */
713     static private void waitFor(Criteria criteria) {
714         int delays = 0;
715         while (!criteria.get()) {
716             try {
717                 Thread.sleep(50);
718             } catch (InterruptedException e) {
719             }
720             if (++delays == 10) fail();
721         }
722     }
723
724     /**
725      * Wait up to TIMEOUT_MS for {@code conditionVariable} to open.
726      * Fails if TIMEOUT_MS goes by before {@code conditionVariable} opens.
727      */
728     static private void waitFor(ConditionVariable conditionVariable) {
729         assertTrue(conditionVariable.block(TIMEOUT_MS));
730     }
731
732     @Override
733     public void setUp() throws Exception {
734         super.setUp();
735
736         // InstrumentationTestRunner prepares a looper, but AndroidJUnitRunner does not.
737         // http://b/25897652 .
738         if (Looper.myLooper() == null) {
739             Looper.prepare();
740         }
741
742         mServiceContext = new MockContext(getContext());
743         mService = new WrappedConnectivityService(mServiceContext,
744                 mock(INetworkManagementService.class),
745                 mock(INetworkStatsService.class),
746                 mock(INetworkPolicyManager.class),
747                 mock(IpConnectivityLog.class));
748
749         mService.systemReady();
750         mCm = new WrappedConnectivityManager(getContext(), mService);
751         mCm.bindProcessToNetwork(null);
752
753         // Ensure that the default setting for Captive Portals is used for most tests
754         setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_PROMPT);
755     }
756
757     public void tearDown() throws Exception {
758         setMobileDataAlwaysOn(false);
759         if (mCellNetworkAgent != null) { mCellNetworkAgent.disconnect(); }
760         if (mWiFiNetworkAgent != null) { mWiFiNetworkAgent.disconnect(); }
761         mCellNetworkAgent = mWiFiNetworkAgent = null;
762         super.tearDown();
763     }
764
765     private int transportToLegacyType(int transport) {
766         switch (transport) {
767             case TRANSPORT_ETHERNET:
768                 return TYPE_ETHERNET;
769             case TRANSPORT_WIFI:
770                 return TYPE_WIFI;
771             case TRANSPORT_CELLULAR:
772                 return TYPE_MOBILE;
773             default:
774                 throw new IllegalStateException("Unknown transport " + transport);
775         }
776     }
777
778     private void verifyActiveNetwork(int transport) {
779         // Test getActiveNetworkInfo()
780         assertNotNull(mCm.getActiveNetworkInfo());
781         assertEquals(transportToLegacyType(transport), mCm.getActiveNetworkInfo().getType());
782         // Test getActiveNetwork()
783         assertNotNull(mCm.getActiveNetwork());
784         assertEquals(mCm.getActiveNetwork(), mCm.getActiveNetworkForUid(Process.myUid()));
785         switch (transport) {
786             case TRANSPORT_WIFI:
787                 assertEquals(mCm.getActiveNetwork(), mWiFiNetworkAgent.getNetwork());
788                 break;
789             case TRANSPORT_CELLULAR:
790                 assertEquals(mCm.getActiveNetwork(), mCellNetworkAgent.getNetwork());
791                 break;
792             default:
793                 throw new IllegalStateException("Unknown transport" + transport);
794         }
795         // Test getNetworkInfo(Network)
796         assertNotNull(mCm.getNetworkInfo(mCm.getActiveNetwork()));
797         assertEquals(transportToLegacyType(transport), mCm.getNetworkInfo(mCm.getActiveNetwork()).getType());
798         // Test getNetworkCapabilities(Network)
799         assertNotNull(mCm.getNetworkCapabilities(mCm.getActiveNetwork()));
800         assertTrue(mCm.getNetworkCapabilities(mCm.getActiveNetwork()).hasTransport(transport));
801     }
802
803     private void verifyNoNetwork() {
804         // Test getActiveNetworkInfo()
805         assertNull(mCm.getActiveNetworkInfo());
806         // Test getActiveNetwork()
807         assertNull(mCm.getActiveNetwork());
808         assertNull(mCm.getActiveNetworkForUid(Process.myUid()));
809         // Test getAllNetworks()
810         assertEquals(0, mCm.getAllNetworks().length);
811     }
812
813     /**
814      * Return a ConditionVariable that opens when {@code count} numbers of CONNECTIVITY_ACTION
815      * broadcasts are received.
816      */
817     private ConditionVariable waitForConnectivityBroadcasts(final int count) {
818         final ConditionVariable cv = new ConditionVariable();
819         mServiceContext.registerReceiver(new BroadcastReceiver() {
820                     private int remaining = count;
821                     public void onReceive(Context context, Intent intent) {
822                         if (--remaining == 0) {
823                             cv.open();
824                             mServiceContext.unregisterReceiver(this);
825                         }
826                     }
827                 }, new IntentFilter(CONNECTIVITY_ACTION));
828         return cv;
829     }
830
831     @LargeTest
832     public void testLingering() throws Exception {
833         verifyNoNetwork();
834         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
835         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
836         assertNull(mCm.getActiveNetworkInfo());
837         assertNull(mCm.getActiveNetwork());
838         // Test bringing up validated cellular.
839         ConditionVariable cv = waitForConnectivityBroadcasts(1);
840         mCellNetworkAgent.connect(true);
841         waitFor(cv);
842         verifyActiveNetwork(TRANSPORT_CELLULAR);
843         assertEquals(2, mCm.getAllNetworks().length);
844         assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) ||
845                 mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork()));
846         assertTrue(mCm.getAllNetworks()[0].equals(mWiFiNetworkAgent.getNetwork()) ||
847                 mCm.getAllNetworks()[1].equals(mWiFiNetworkAgent.getNetwork()));
848         // Test bringing up validated WiFi.
849         cv = waitForConnectivityBroadcasts(2);
850         mWiFiNetworkAgent.connect(true);
851         waitFor(cv);
852         verifyActiveNetwork(TRANSPORT_WIFI);
853         assertEquals(2, mCm.getAllNetworks().length);
854         assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) ||
855                 mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork()));
856         assertTrue(mCm.getAllNetworks()[0].equals(mCellNetworkAgent.getNetwork()) ||
857                 mCm.getAllNetworks()[1].equals(mCellNetworkAgent.getNetwork()));
858         // Test cellular linger timeout.
859         waitFor(new Criteria() {
860                 public boolean get() { return mCm.getAllNetworks().length == 1; } });
861         verifyActiveNetwork(TRANSPORT_WIFI);
862         assertEquals(1, mCm.getAllNetworks().length);
863         assertEquals(mCm.getAllNetworks()[0], mCm.getActiveNetwork());
864         // Test WiFi disconnect.
865         cv = waitForConnectivityBroadcasts(1);
866         mWiFiNetworkAgent.disconnect();
867         waitFor(cv);
868         verifyNoNetwork();
869     }
870
871     @LargeTest
872     public void testValidatedCellularOutscoresUnvalidatedWiFi() throws Exception {
873         // Test bringing up unvalidated WiFi
874         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
875         ConditionVariable cv = waitForConnectivityBroadcasts(1);
876         mWiFiNetworkAgent.connect(false);
877         waitFor(cv);
878         verifyActiveNetwork(TRANSPORT_WIFI);
879         // Test bringing up unvalidated cellular
880         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
881         mCellNetworkAgent.connect(false);
882         mService.waitForIdle();
883         verifyActiveNetwork(TRANSPORT_WIFI);
884         // Test cellular disconnect.
885         mCellNetworkAgent.disconnect();
886         mService.waitForIdle();
887         verifyActiveNetwork(TRANSPORT_WIFI);
888         // Test bringing up validated cellular
889         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
890         cv = waitForConnectivityBroadcasts(2);
891         mCellNetworkAgent.connect(true);
892         waitFor(cv);
893         verifyActiveNetwork(TRANSPORT_CELLULAR);
894         // Test cellular disconnect.
895         cv = waitForConnectivityBroadcasts(2);
896         mCellNetworkAgent.disconnect();
897         waitFor(cv);
898         verifyActiveNetwork(TRANSPORT_WIFI);
899         // Test WiFi disconnect.
900         cv = waitForConnectivityBroadcasts(1);
901         mWiFiNetworkAgent.disconnect();
902         waitFor(cv);
903         verifyNoNetwork();
904     }
905
906     @LargeTest
907     public void testUnvalidatedWifiOutscoresUnvalidatedCellular() throws Exception {
908         // Test bringing up unvalidated cellular.
909         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
910         ConditionVariable cv = waitForConnectivityBroadcasts(1);
911         mCellNetworkAgent.connect(false);
912         waitFor(cv);
913         verifyActiveNetwork(TRANSPORT_CELLULAR);
914         // Test bringing up unvalidated WiFi.
915         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
916         cv = waitForConnectivityBroadcasts(2);
917         mWiFiNetworkAgent.connect(false);
918         waitFor(cv);
919         verifyActiveNetwork(TRANSPORT_WIFI);
920         // Test WiFi disconnect.
921         cv = waitForConnectivityBroadcasts(2);
922         mWiFiNetworkAgent.disconnect();
923         waitFor(cv);
924         verifyActiveNetwork(TRANSPORT_CELLULAR);
925         // Test cellular disconnect.
926         cv = waitForConnectivityBroadcasts(1);
927         mCellNetworkAgent.disconnect();
928         waitFor(cv);
929         verifyNoNetwork();
930     }
931
932     @LargeTest
933     public void testUnlingeringDoesNotValidate() throws Exception {
934         // Test bringing up unvalidated WiFi.
935         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
936         ConditionVariable cv = waitForConnectivityBroadcasts(1);
937         mWiFiNetworkAgent.connect(false);
938         waitFor(cv);
939         verifyActiveNetwork(TRANSPORT_WIFI);
940         assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
941                 NET_CAPABILITY_VALIDATED));
942         // Test bringing up validated cellular.
943         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
944         cv = waitForConnectivityBroadcasts(2);
945         mCellNetworkAgent.connect(true);
946         waitFor(cv);
947         verifyActiveNetwork(TRANSPORT_CELLULAR);
948         assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
949                 NET_CAPABILITY_VALIDATED));
950         // Test cellular disconnect.
951         cv = waitForConnectivityBroadcasts(2);
952         mCellNetworkAgent.disconnect();
953         waitFor(cv);
954         verifyActiveNetwork(TRANSPORT_WIFI);
955         // Unlingering a network should not cause it to be marked as validated.
956         assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
957                 NET_CAPABILITY_VALIDATED));
958     }
959
960     @LargeTest
961     public void testCellularOutscoresWeakWifi() throws Exception {
962         // Test bringing up validated cellular.
963         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
964         ConditionVariable cv = waitForConnectivityBroadcasts(1);
965         mCellNetworkAgent.connect(true);
966         waitFor(cv);
967         verifyActiveNetwork(TRANSPORT_CELLULAR);
968         // Test bringing up validated WiFi.
969         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
970         cv = waitForConnectivityBroadcasts(2);
971         mWiFiNetworkAgent.connect(true);
972         waitFor(cv);
973         verifyActiveNetwork(TRANSPORT_WIFI);
974         // Test WiFi getting really weak.
975         cv = waitForConnectivityBroadcasts(2);
976         mWiFiNetworkAgent.adjustScore(-11);
977         waitFor(cv);
978         verifyActiveNetwork(TRANSPORT_CELLULAR);
979         // Test WiFi restoring signal strength.
980         cv = waitForConnectivityBroadcasts(2);
981         mWiFiNetworkAgent.adjustScore(11);
982         waitFor(cv);
983         verifyActiveNetwork(TRANSPORT_WIFI);
984     }
985
986     @LargeTest
987     public void testReapingNetwork() throws Exception {
988         // Test bringing up WiFi without NET_CAPABILITY_INTERNET.
989         // Expect it to be torn down immediately because it satisfies no requests.
990         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
991         ConditionVariable cv = mWiFiNetworkAgent.getDisconnectedCV();
992         mWiFiNetworkAgent.connectWithoutInternet();
993         waitFor(cv);
994         // Test bringing up cellular without NET_CAPABILITY_INTERNET.
995         // Expect it to be torn down immediately because it satisfies no requests.
996         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
997         cv = mCellNetworkAgent.getDisconnectedCV();
998         mCellNetworkAgent.connectWithoutInternet();
999         waitFor(cv);
1000         // Test bringing up validated WiFi.
1001         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1002         cv = waitForConnectivityBroadcasts(1);
1003         mWiFiNetworkAgent.connect(true);
1004         waitFor(cv);
1005         verifyActiveNetwork(TRANSPORT_WIFI);
1006         // Test bringing up unvalidated cellular.
1007         // Expect it to be torn down because it could never be the highest scoring network
1008         // satisfying the default request even if it validated.
1009         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1010         cv = mCellNetworkAgent.getDisconnectedCV();
1011         mCellNetworkAgent.connect(false);
1012         waitFor(cv);
1013         verifyActiveNetwork(TRANSPORT_WIFI);
1014         cv = mWiFiNetworkAgent.getDisconnectedCV();
1015         mWiFiNetworkAgent.disconnect();
1016         waitFor(cv);
1017     }
1018
1019     @LargeTest
1020     public void testCellularFallback() throws Exception {
1021         // Test bringing up validated cellular.
1022         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1023         ConditionVariable cv = waitForConnectivityBroadcasts(1);
1024         mCellNetworkAgent.connect(true);
1025         waitFor(cv);
1026         verifyActiveNetwork(TRANSPORT_CELLULAR);
1027         // Test bringing up validated WiFi.
1028         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1029         cv = waitForConnectivityBroadcasts(2);
1030         mWiFiNetworkAgent.connect(true);
1031         waitFor(cv);
1032         verifyActiveNetwork(TRANSPORT_WIFI);
1033         // Reevaluate WiFi (it'll instantly fail DNS).
1034         cv = waitForConnectivityBroadcasts(2);
1035         assertTrue(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1036                 NET_CAPABILITY_VALIDATED));
1037         mCm.reportBadNetwork(mWiFiNetworkAgent.getNetwork());
1038         // Should quickly fall back to Cellular.
1039         waitFor(cv);
1040         assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1041                 NET_CAPABILITY_VALIDATED));
1042         verifyActiveNetwork(TRANSPORT_CELLULAR);
1043         // Reevaluate cellular (it'll instantly fail DNS).
1044         cv = waitForConnectivityBroadcasts(2);
1045         assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1046                 NET_CAPABILITY_VALIDATED));
1047         mCm.reportBadNetwork(mCellNetworkAgent.getNetwork());
1048         // Should quickly fall back to WiFi.
1049         waitFor(cv);
1050         assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1051                 NET_CAPABILITY_VALIDATED));
1052         assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1053                 NET_CAPABILITY_VALIDATED));
1054         verifyActiveNetwork(TRANSPORT_WIFI);
1055     }
1056
1057     @LargeTest
1058     public void testWiFiFallback() throws Exception {
1059         // Test bringing up unvalidated WiFi.
1060         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1061         ConditionVariable cv = waitForConnectivityBroadcasts(1);
1062         mWiFiNetworkAgent.connect(false);
1063         waitFor(cv);
1064         verifyActiveNetwork(TRANSPORT_WIFI);
1065         // Test bringing up validated cellular.
1066         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1067         cv = waitForConnectivityBroadcasts(2);
1068         mCellNetworkAgent.connect(true);
1069         waitFor(cv);
1070         verifyActiveNetwork(TRANSPORT_CELLULAR);
1071         // Reevaluate cellular (it'll instantly fail DNS).
1072         cv = waitForConnectivityBroadcasts(2);
1073         assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1074                 NET_CAPABILITY_VALIDATED));
1075         mCm.reportBadNetwork(mCellNetworkAgent.getNetwork());
1076         // Should quickly fall back to WiFi.
1077         waitFor(cv);
1078         assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1079                 NET_CAPABILITY_VALIDATED));
1080         verifyActiveNetwork(TRANSPORT_WIFI);
1081     }
1082
1083     enum CallbackState {
1084         NONE,
1085         AVAILABLE,
1086         NETWORK_CAPABILITIES,
1087         LINK_PROPERTIES,
1088         LOSING,
1089         LOST
1090     }
1091
1092     /**
1093      * Utility NetworkCallback for testing. The caller must explicitly test for all the callbacks
1094      * this class receives, by calling expectCallback() exactly once each time a callback is
1095      * received. assertNoCallback may be called at any time.
1096      */
1097     private class TestNetworkCallback extends NetworkCallback {
1098         // Chosen to be much less than the linger timeout. This ensures that we can distinguish
1099         // between a LOST callback that arrives immediately and a LOST callback that arrives after
1100         // the linger timeout.
1101         private final static int TIMEOUT_MS = 50;
1102
1103         private class CallbackInfo {
1104             public final CallbackState state;
1105             public final Network network;
1106             public Object arg;
1107             public CallbackInfo(CallbackState s, Network n, Object o) {
1108                 state = s; network = n; arg = o;
1109             }
1110             public String toString() { return String.format("%s (%s)", state, network); }
1111             public boolean equals(Object o) {
1112                 if (!(o instanceof CallbackInfo)) return false;
1113                 // Ignore timeMs, since it's unpredictable.
1114                 CallbackInfo other = (CallbackInfo) o;
1115                 return state == other.state && Objects.equals(network, other.network);
1116             }
1117         }
1118         private final LinkedBlockingQueue<CallbackInfo> mCallbacks = new LinkedBlockingQueue<>();
1119
1120         protected void setLastCallback(CallbackState state, Network network, Object o) {
1121             mCallbacks.offer(new CallbackInfo(state, network, o));
1122         }
1123
1124         @Override
1125         public void onAvailable(Network network) {
1126             setLastCallback(CallbackState.AVAILABLE, network, null);
1127         }
1128
1129         @Override
1130         public void onLosing(Network network, int maxMsToLive) {
1131             setLastCallback(CallbackState.LOSING, network, maxMsToLive /* autoboxed int */);
1132         }
1133
1134         @Override
1135         public void onLost(Network network) {
1136             setLastCallback(CallbackState.LOST, network, null);
1137         }
1138
1139         void expectCallback(CallbackState state, MockNetworkAgent mockAgent, int timeoutMs) {
1140             CallbackInfo expected = new CallbackInfo(
1141                     state, (mockAgent != null) ? mockAgent.getNetwork() : null, 0);
1142             CallbackInfo actual;
1143             try {
1144                 actual = mCallbacks.poll(timeoutMs, TimeUnit.MILLISECONDS);
1145                 assertEquals("Unexpected callback:", expected, actual);
1146             } catch (InterruptedException e) {
1147                 fail("Did not receive expected " + expected + " after " + TIMEOUT_MS + "ms");
1148                 actual = null;  // Or the compiler can't tell it's never used uninitialized.
1149             }
1150             if (state == CallbackState.LOSING) {
1151                 String msg = String.format(
1152                         "Invalid linger time value %d, must be between %d and %d",
1153                         actual.arg, 0, TEST_LINGER_DELAY_MS);
1154                 int maxMsToLive = (Integer) actual.arg;
1155                 assertTrue(msg, 0 <= maxMsToLive && maxMsToLive <= TEST_LINGER_DELAY_MS);
1156             }
1157         }
1158
1159         void expectCallback(CallbackState state, MockNetworkAgent mockAgent) {
1160             expectCallback(state, mockAgent, TIMEOUT_MS);
1161         }
1162
1163         void assertNoCallback() {
1164             mService.waitForIdle();
1165             CallbackInfo c = mCallbacks.peek();
1166             assertNull("Unexpected callback: " + c, c);
1167         }
1168     }
1169
1170     // Can't be part of TestNetworkCallback because "cannot be declared static; static methods can
1171     // only be declared in a static or top level type".
1172     static void assertNoCallbacks(TestNetworkCallback ... callbacks) {
1173         for (TestNetworkCallback c : callbacks) {
1174             c.assertNoCallback();
1175         }
1176     }
1177
1178     @LargeTest
1179     public void testStateChangeNetworkCallbacks() throws Exception {
1180         final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback();
1181         final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
1182         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
1183         final NetworkRequest genericRequest = new NetworkRequest.Builder()
1184                 .clearCapabilities().build();
1185         final NetworkRequest wifiRequest = new NetworkRequest.Builder()
1186                 .addTransportType(TRANSPORT_WIFI).build();
1187         final NetworkRequest cellRequest = new NetworkRequest.Builder()
1188                 .addTransportType(TRANSPORT_CELLULAR).build();
1189         mCm.registerNetworkCallback(genericRequest, genericNetworkCallback);
1190         mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
1191         mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
1192
1193         // Test unvalidated networks
1194         ConditionVariable cv = waitForConnectivityBroadcasts(1);
1195         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1196         mCellNetworkAgent.connect(false);
1197         genericNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1198         cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1199         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1200         waitFor(cv);
1201         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
1202
1203         // This should not trigger spurious onAvailable() callbacks, b/21762680.
1204         mCellNetworkAgent.adjustScore(-1);
1205         mService.waitForIdle();
1206         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
1207         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1208
1209         cv = waitForConnectivityBroadcasts(2);
1210         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1211         mWiFiNetworkAgent.connect(false);
1212         genericNetworkCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1213         wifiNetworkCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1214         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1215         waitFor(cv);
1216         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
1217
1218         cv = waitForConnectivityBroadcasts(2);
1219         mWiFiNetworkAgent.disconnect();
1220         genericNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1221         wifiNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1222         cellNetworkCallback.assertNoCallback();
1223         waitFor(cv);
1224         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
1225
1226         cv = waitForConnectivityBroadcasts(1);
1227         mCellNetworkAgent.disconnect();
1228         genericNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1229         cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1230         waitFor(cv);
1231         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
1232
1233         // Test validated networks
1234         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1235         mCellNetworkAgent.connect(true);
1236         genericNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1237         cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1238         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1239         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
1240
1241         // This should not trigger spurious onAvailable() callbacks, b/21762680.
1242         mCellNetworkAgent.adjustScore(-1);
1243         mService.waitForIdle();
1244         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
1245         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1246
1247         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1248         mWiFiNetworkAgent.connect(true);
1249         genericNetworkCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1250         genericNetworkCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
1251         wifiNetworkCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1252         cellNetworkCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
1253         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1254         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
1255
1256         mWiFiNetworkAgent.disconnect();
1257         genericNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1258         wifiNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1259         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
1260
1261         mCellNetworkAgent.disconnect();
1262         genericNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1263         cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1264         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
1265     }
1266
1267     @SmallTest
1268     public void testMultipleLingering() {
1269         NetworkRequest request = new NetworkRequest.Builder()
1270                 .clearCapabilities().addCapability(NET_CAPABILITY_NOT_METERED)
1271                 .build();
1272         TestNetworkCallback callback = new TestNetworkCallback();
1273         mCm.registerNetworkCallback(request, callback);
1274
1275         TestNetworkCallback defaultCallback = new TestNetworkCallback();
1276         mCm.registerDefaultNetworkCallback(defaultCallback);
1277
1278         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1279         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1280         mEthernetNetworkAgent = new MockNetworkAgent(TRANSPORT_ETHERNET);
1281
1282         mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
1283         mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
1284         mEthernetNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
1285
1286         mCellNetworkAgent.connect(true);
1287         callback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1288         defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1289         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1290
1291         mWiFiNetworkAgent.connect(true);
1292         // We get AVAILABLE on wifi when wifi connects and satisfies our unmetered request.
1293         // We then get LOSING when wifi validates and cell is outscored.
1294         callback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1295         callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
1296         defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1297         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1298
1299         mEthernetNetworkAgent.connect(true);
1300         callback.expectCallback(CallbackState.AVAILABLE, mEthernetNetworkAgent);
1301         callback.expectCallback(CallbackState.LOSING, mWiFiNetworkAgent);
1302         defaultCallback.expectCallback(CallbackState.AVAILABLE, mEthernetNetworkAgent);
1303         assertEquals(mEthernetNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1304
1305         mEthernetNetworkAgent.disconnect();
1306         callback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
1307         defaultCallback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
1308         defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1309
1310         for (int i = 0; i < 4; i++) {
1311             MockNetworkAgent oldNetwork, newNetwork;
1312             if (i % 2 == 0) {
1313                 mWiFiNetworkAgent.adjustScore(-15);
1314                 oldNetwork = mWiFiNetworkAgent;
1315                 newNetwork = mCellNetworkAgent;
1316             } else {
1317                 mWiFiNetworkAgent.adjustScore(15);
1318                 oldNetwork = mCellNetworkAgent;
1319                 newNetwork = mWiFiNetworkAgent;
1320
1321             }
1322             callback.expectCallback(CallbackState.LOSING, oldNetwork);
1323             // TODO: should we send an AVAILABLE callback to newNetwork, to indicate that it is no
1324             // longer lingering?
1325             defaultCallback.expectCallback(CallbackState.AVAILABLE, newNetwork);
1326             assertEquals(newNetwork.getNetwork(), mCm.getActiveNetwork());
1327         }
1328         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1329
1330         // Verify that if a network no longer satisfies a request, we send LOST and not LOSING, even
1331         // if the network is still up.
1332         mWiFiNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
1333         callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1334
1335         // Wifi no longer satisfies our listen, which is for an unmetered network.
1336         // But because its score is 55, it's still up (and the default network).
1337         defaultCallback.assertNoCallback();
1338         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1339
1340         // Disconnect our test networks.
1341         mWiFiNetworkAgent.disconnect();
1342         defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1343         defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1344         mCellNetworkAgent.disconnect();
1345         defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1346
1347         mCm.unregisterNetworkCallback(callback);
1348         mService.waitForIdle();
1349
1350         // Check that a network is only lingered or torn down if it would not satisfy a request even
1351         // if it validated.
1352         request = new NetworkRequest.Builder().clearCapabilities().build();
1353         callback = new TestNetworkCallback();
1354
1355         mCm.registerNetworkCallback(request, callback);
1356
1357         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1358         mCellNetworkAgent.connect(false);   // Score: 10
1359         callback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1360         defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1361         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1362
1363         // Bring up wifi with a score of 20.
1364         // Cell stays up because it would satisfy the default request if it validated.
1365         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1366         mWiFiNetworkAgent.connect(false);   // Score: 20
1367         callback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1368         defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1369         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1370
1371         mWiFiNetworkAgent.disconnect();
1372         callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1373         defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1374         defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1375         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1376
1377         // Bring up wifi with a score of 70.
1378         // Cell is lingered because it would not satisfy any request, even if it validated.
1379         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1380         mWiFiNetworkAgent.adjustScore(50);
1381         mWiFiNetworkAgent.connect(false);   // Score: 70
1382         callback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1383         callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
1384         defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1385         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1386
1387         // Tear down wifi.
1388         mWiFiNetworkAgent.disconnect();
1389         callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1390         defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1391         defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1392         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1393
1394         // Bring up wifi, then validate it. Previous versions would immediately tear down cell, but
1395         // it's arguably correct to linger it, since it was the default network before it validated.
1396         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1397         mWiFiNetworkAgent.connect(true);
1398         callback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1399         callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
1400         defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1401         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1402
1403         mWiFiNetworkAgent.disconnect();
1404         callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1405         defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1406         defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1407         mCellNetworkAgent.disconnect();
1408         callback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1409         defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1410
1411         // If a network is lingering, and we add and remove a request from it, resume lingering.
1412         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1413         mCellNetworkAgent.connect(true);
1414         callback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1415         defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1416         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1417         mWiFiNetworkAgent.connect(true);
1418         callback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1419         defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1420         callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
1421
1422         NetworkRequest cellRequest = new NetworkRequest.Builder()
1423                 .addTransportType(TRANSPORT_CELLULAR).build();
1424         NetworkCallback noopCallback = new NetworkCallback();
1425         mCm.requestNetwork(cellRequest, noopCallback);
1426         // TODO: should this cause an AVAILABLE callback, to indicate that the network is no longer
1427         // lingering?
1428         mCm.unregisterNetworkCallback(noopCallback);
1429         callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
1430
1431         // Similar to the above: lingering can start even after the lingered request is removed.
1432         // Disconnect wifi and switch to cell.
1433         mWiFiNetworkAgent.disconnect();
1434         callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1435         defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1436         defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1437
1438         // Cell is now the default network. Pin it with a cell-specific request.
1439         noopCallback = new NetworkCallback();  // Can't reuse NetworkCallbacks. http://b/20701525
1440         mCm.requestNetwork(cellRequest, noopCallback);
1441
1442         // Now connect wifi, and expect it to become the default network.
1443         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1444         mWiFiNetworkAgent.connect(true);
1445         callback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1446         defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1447         // The default request is lingering on cell, but nothing happens to cell, and we send no
1448         // callbacks for it, because it's kept up by cellRequest.
1449         callback.assertNoCallback();
1450         // Now unregister cellRequest and expect cell to start lingering.
1451         mCm.unregisterNetworkCallback(noopCallback);
1452         callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
1453
1454         // Let linger run its course.
1455         callback.assertNoCallback();
1456         callback.expectCallback(CallbackState.LOST, mCellNetworkAgent,
1457                 TEST_LINGER_DELAY_MS /* timeoutMs */);
1458
1459         // Clean up.
1460         mWiFiNetworkAgent.disconnect();
1461         callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1462         defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1463
1464         mCm.unregisterNetworkCallback(callback);
1465         mCm.unregisterNetworkCallback(defaultCallback);
1466     }
1467
1468     private void tryNetworkFactoryRequests(int capability) throws Exception {
1469         // Verify NOT_RESTRICTED is set appropriately
1470         final NetworkCapabilities nc = new NetworkRequest.Builder().addCapability(capability)
1471                 .build().networkCapabilities;
1472         if (capability == NET_CAPABILITY_CBS || capability == NET_CAPABILITY_DUN ||
1473                 capability == NET_CAPABILITY_EIMS || capability == NET_CAPABILITY_FOTA ||
1474                 capability == NET_CAPABILITY_IA || capability == NET_CAPABILITY_IMS ||
1475                 capability == NET_CAPABILITY_RCS || capability == NET_CAPABILITY_XCAP) {
1476             assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
1477         } else {
1478             assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
1479         }
1480
1481         NetworkCapabilities filter = new NetworkCapabilities();
1482         filter.addCapability(capability);
1483         final HandlerThread handlerThread = new HandlerThread("testNetworkFactoryRequests");
1484         handlerThread.start();
1485         final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
1486                 mServiceContext, "testFactory", filter);
1487         testFactory.setScoreFilter(40);
1488         ConditionVariable cv = testFactory.getNetworkStartedCV();
1489         testFactory.expectAddRequests(1);
1490         testFactory.register();
1491         testFactory.waitForNetworkRequests(1);
1492         int expectedRequestCount = 1;
1493         NetworkCallback networkCallback = null;
1494         // For non-INTERNET capabilities we cannot rely on the default request being present, so
1495         // add one.
1496         if (capability != NET_CAPABILITY_INTERNET) {
1497             assertFalse(testFactory.getMyStartRequested());
1498             NetworkRequest request = new NetworkRequest.Builder().addCapability(capability).build();
1499             networkCallback = new NetworkCallback();
1500             testFactory.expectAddRequests(1);
1501             mCm.requestNetwork(request, networkCallback);
1502             expectedRequestCount++;
1503             testFactory.waitForNetworkRequests(expectedRequestCount);
1504         }
1505         waitFor(cv);
1506         assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
1507         assertTrue(testFactory.getMyStartRequested());
1508
1509         // Now bring in a higher scored network.
1510         MockNetworkAgent testAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1511         // Rather than create a validated network which complicates things by registering it's
1512         // own NetworkRequest during startup, just bump up the score to cancel out the
1513         // unvalidated penalty.
1514         testAgent.adjustScore(40);
1515         cv = testFactory.getNetworkStoppedCV();
1516
1517         // When testAgent connects, ConnectivityService will re-send us all current requests with
1518         // the new score. There are expectedRequestCount such requests, and we must wait for all of
1519         // them.
1520         testFactory.expectAddRequests(expectedRequestCount);
1521         testAgent.connect(false);
1522         testAgent.addCapability(capability);
1523         waitFor(cv);
1524         testFactory.waitForNetworkRequests(expectedRequestCount);
1525         assertFalse(testFactory.getMyStartRequested());
1526
1527         // Bring in a bunch of requests.
1528         testFactory.expectAddRequests(10);
1529         assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
1530         ConnectivityManager.NetworkCallback[] networkCallbacks =
1531                 new ConnectivityManager.NetworkCallback[10];
1532         for (int i = 0; i< networkCallbacks.length; i++) {
1533             networkCallbacks[i] = new ConnectivityManager.NetworkCallback();
1534             NetworkRequest.Builder builder = new NetworkRequest.Builder();
1535             builder.addCapability(capability);
1536             mCm.requestNetwork(builder.build(), networkCallbacks[i]);
1537         }
1538         testFactory.waitForNetworkRequests(10 + expectedRequestCount);
1539         assertFalse(testFactory.getMyStartRequested());
1540
1541         // Remove the requests.
1542         testFactory.expectRemoveRequests(10);
1543         for (int i = 0; i < networkCallbacks.length; i++) {
1544             mCm.unregisterNetworkCallback(networkCallbacks[i]);
1545         }
1546         testFactory.waitForNetworkRequests(expectedRequestCount);
1547         assertFalse(testFactory.getMyStartRequested());
1548
1549         // Drop the higher scored network.
1550         cv = testFactory.getNetworkStartedCV();
1551         testAgent.disconnect();
1552         waitFor(cv);
1553         assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
1554         assertTrue(testFactory.getMyStartRequested());
1555
1556         testFactory.unregister();
1557         if (networkCallback != null) mCm.unregisterNetworkCallback(networkCallback);
1558         handlerThread.quit();
1559     }
1560
1561     @LargeTest
1562     public void testNetworkFactoryRequests() throws Exception {
1563         tryNetworkFactoryRequests(NET_CAPABILITY_MMS);
1564         tryNetworkFactoryRequests(NET_CAPABILITY_SUPL);
1565         tryNetworkFactoryRequests(NET_CAPABILITY_DUN);
1566         tryNetworkFactoryRequests(NET_CAPABILITY_FOTA);
1567         tryNetworkFactoryRequests(NET_CAPABILITY_IMS);
1568         tryNetworkFactoryRequests(NET_CAPABILITY_CBS);
1569         tryNetworkFactoryRequests(NET_CAPABILITY_WIFI_P2P);
1570         tryNetworkFactoryRequests(NET_CAPABILITY_IA);
1571         tryNetworkFactoryRequests(NET_CAPABILITY_RCS);
1572         tryNetworkFactoryRequests(NET_CAPABILITY_XCAP);
1573         tryNetworkFactoryRequests(NET_CAPABILITY_EIMS);
1574         tryNetworkFactoryRequests(NET_CAPABILITY_NOT_METERED);
1575         tryNetworkFactoryRequests(NET_CAPABILITY_INTERNET);
1576         tryNetworkFactoryRequests(NET_CAPABILITY_TRUSTED);
1577         tryNetworkFactoryRequests(NET_CAPABILITY_NOT_VPN);
1578         // Skipping VALIDATED and CAPTIVE_PORTAL as they're disallowed.
1579     }
1580
1581     @LargeTest
1582     public void testNoMutableNetworkRequests() throws Exception {
1583         PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, new Intent("a"), 0);
1584         NetworkRequest.Builder builder = new NetworkRequest.Builder();
1585         builder.addCapability(NET_CAPABILITY_VALIDATED);
1586         try {
1587             mCm.requestNetwork(builder.build(), new NetworkCallback());
1588             fail();
1589         } catch (IllegalArgumentException expected) {}
1590         try {
1591             mCm.requestNetwork(builder.build(), pendingIntent);
1592             fail();
1593         } catch (IllegalArgumentException expected) {}
1594         builder = new NetworkRequest.Builder();
1595         builder.addCapability(NET_CAPABILITY_CAPTIVE_PORTAL);
1596         try {
1597             mCm.requestNetwork(builder.build(), new NetworkCallback());
1598             fail();
1599         } catch (IllegalArgumentException expected) {}
1600         try {
1601             mCm.requestNetwork(builder.build(), pendingIntent);
1602             fail();
1603         } catch (IllegalArgumentException expected) {}
1604     }
1605
1606     @LargeTest
1607     public void testMMSonWiFi() throws Exception {
1608         // Test bringing up cellular without MMS NetworkRequest gets reaped
1609         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1610         mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS);
1611         ConditionVariable cv = mCellNetworkAgent.getDisconnectedCV();
1612         mCellNetworkAgent.connectWithoutInternet();
1613         waitFor(cv);
1614         waitFor(new Criteria() {
1615                 public boolean get() { return mCm.getAllNetworks().length == 0; } });
1616         verifyNoNetwork();
1617         // Test bringing up validated WiFi.
1618         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1619         cv = waitForConnectivityBroadcasts(1);
1620         mWiFiNetworkAgent.connect(true);
1621         waitFor(cv);
1622         verifyActiveNetwork(TRANSPORT_WIFI);
1623         // Register MMS NetworkRequest
1624         NetworkRequest.Builder builder = new NetworkRequest.Builder();
1625         builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
1626         final TestNetworkCallback networkCallback = new TestNetworkCallback();
1627         mCm.requestNetwork(builder.build(), networkCallback);
1628         // Test bringing up unvalidated cellular with MMS
1629         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1630         mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS);
1631         mCellNetworkAgent.connectWithoutInternet();
1632         networkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1633         verifyActiveNetwork(TRANSPORT_WIFI);
1634         // Test releasing NetworkRequest disconnects cellular with MMS
1635         cv = mCellNetworkAgent.getDisconnectedCV();
1636         mCm.unregisterNetworkCallback(networkCallback);
1637         waitFor(cv);
1638         verifyActiveNetwork(TRANSPORT_WIFI);
1639     }
1640
1641     @LargeTest
1642     public void testMMSonCell() throws Exception {
1643         // Test bringing up cellular without MMS
1644         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1645         ConditionVariable cv = waitForConnectivityBroadcasts(1);
1646         mCellNetworkAgent.connect(false);
1647         waitFor(cv);
1648         verifyActiveNetwork(TRANSPORT_CELLULAR);
1649         // Register MMS NetworkRequest
1650         NetworkRequest.Builder builder = new NetworkRequest.Builder();
1651         builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
1652         final TestNetworkCallback networkCallback = new TestNetworkCallback();
1653         mCm.requestNetwork(builder.build(), networkCallback);
1654         // Test bringing up MMS cellular network
1655         MockNetworkAgent mmsNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1656         mmsNetworkAgent.addCapability(NET_CAPABILITY_MMS);
1657         mmsNetworkAgent.connectWithoutInternet();
1658         networkCallback.expectCallback(CallbackState.AVAILABLE, mmsNetworkAgent);
1659         verifyActiveNetwork(TRANSPORT_CELLULAR);
1660         // Test releasing MMS NetworkRequest does not disconnect main cellular NetworkAgent
1661         cv = mmsNetworkAgent.getDisconnectedCV();
1662         mCm.unregisterNetworkCallback(networkCallback);
1663         waitFor(cv);
1664         verifyActiveNetwork(TRANSPORT_CELLULAR);
1665     }
1666
1667     @LargeTest
1668     public void testCaptivePortal() {
1669         final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
1670         final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
1671                 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
1672         mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
1673
1674         final TestNetworkCallback validatedCallback = new TestNetworkCallback();
1675         final NetworkRequest validatedRequest = new NetworkRequest.Builder()
1676                 .addCapability(NET_CAPABILITY_VALIDATED).build();
1677         mCm.registerNetworkCallback(validatedRequest, validatedCallback);
1678
1679         // Bring up a network with a captive portal.
1680         // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
1681         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1682         String firstRedirectUrl = "http://example.com/firstPath";
1683         mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl);
1684         captivePortalCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1685         assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), firstRedirectUrl);
1686
1687         // Take down network.
1688         // Expect onLost callback.
1689         mWiFiNetworkAgent.disconnect();
1690         captivePortalCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1691
1692         // Bring up a network with a captive portal.
1693         // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
1694         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1695         String secondRedirectUrl = "http://example.com/secondPath";
1696         mWiFiNetworkAgent.connectWithCaptivePortal(secondRedirectUrl);
1697         captivePortalCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1698         assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), secondRedirectUrl);
1699
1700         // Make captive portal disappear then revalidate.
1701         // Expect onLost callback because network no longer provides NET_CAPABILITY_CAPTIVE_PORTAL.
1702         mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 204;
1703         mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
1704         captivePortalCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1705
1706         // Expect NET_CAPABILITY_VALIDATED onAvailable callback.
1707         validatedCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1708
1709         // Break network connectivity.
1710         // Expect NET_CAPABILITY_VALIDATED onLost callback.
1711         mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 500;
1712         mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), false);
1713         validatedCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1714     }
1715
1716     @LargeTest
1717     public void testAvoidOrIgnoreCaptivePortals() {
1718         final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
1719         final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
1720                 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
1721         mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
1722
1723         final TestNetworkCallback validatedCallback = new TestNetworkCallback();
1724         final NetworkRequest validatedRequest = new NetworkRequest.Builder()
1725                 .addCapability(NET_CAPABILITY_VALIDATED).build();
1726         mCm.registerNetworkCallback(validatedRequest, validatedCallback);
1727
1728         setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_AVOID);
1729         // Bring up a network with a captive portal.
1730         // Expect it to fail to connect and not result in any callbacks.
1731         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1732         String firstRedirectUrl = "http://example.com/firstPath";
1733
1734         ConditionVariable disconnectCv = mWiFiNetworkAgent.getDisconnectedCV();
1735         ConditionVariable avoidCv = mWiFiNetworkAgent.getPreventReconnectReceived();
1736         mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl);
1737         waitFor(disconnectCv);
1738         waitFor(avoidCv);
1739
1740         assertNoCallbacks(captivePortalCallback, validatedCallback);
1741
1742         // Now test ignore mode.
1743         setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_IGNORE);
1744
1745         // Bring up a network with a captive portal.
1746         // Since we're ignoring captive portals, the network will validate.
1747         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1748         String secondRedirectUrl = "http://example.com/secondPath";
1749         mWiFiNetworkAgent.connectWithCaptivePortal(secondRedirectUrl);
1750
1751         // Expect NET_CAPABILITY_VALIDATED onAvailable callback.
1752         validatedCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1753         // But there should be no CaptivePortal callback.
1754         captivePortalCallback.assertNoCallback();
1755     }
1756
1757     @SmallTest
1758     public void testInvalidNetworkSpecifier() {
1759         boolean execptionCalled = true;
1760
1761         try {
1762             NetworkRequest.Builder builder = new NetworkRequest.Builder();
1763             builder.setNetworkSpecifier(MATCH_ALL_REQUESTS_NETWORK_SPECIFIER);
1764             execptionCalled = false;
1765         } catch (IllegalArgumentException e) {
1766             // do nothing - should get here
1767         }
1768
1769         assertTrue("NetworkRequest builder with MATCH_ALL_REQUESTS_NETWORK_SPECIFIER",
1770                 execptionCalled);
1771
1772         try {
1773             NetworkCapabilities networkCapabilities = new NetworkCapabilities();
1774             networkCapabilities.addTransportType(TRANSPORT_WIFI)
1775                     .setNetworkSpecifier(NetworkCapabilities.MATCH_ALL_REQUESTS_NETWORK_SPECIFIER);
1776             mService.requestNetwork(networkCapabilities, null, 0, null,
1777                     ConnectivityManager.TYPE_WIFI);
1778             execptionCalled = false;
1779         } catch (IllegalArgumentException e) {
1780             // do nothing - should get here
1781         }
1782
1783         assertTrue("ConnectivityService requestNetwork with MATCH_ALL_REQUESTS_NETWORK_SPECIFIER",
1784                 execptionCalled);
1785     }
1786
1787     @LargeTest
1788     public void testRegisterDefaultNetworkCallback() throws Exception {
1789         final TestNetworkCallback defaultNetworkCallback = new TestNetworkCallback();
1790         mCm.registerDefaultNetworkCallback(defaultNetworkCallback);
1791         defaultNetworkCallback.assertNoCallback();
1792
1793         // Create a TRANSPORT_CELLULAR request to keep the mobile interface up
1794         // whenever Wi-Fi is up. Without this, the mobile network agent is
1795         // reaped before any other activity can take place.
1796         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
1797         final NetworkRequest cellRequest = new NetworkRequest.Builder()
1798                 .addTransportType(TRANSPORT_CELLULAR).build();
1799         mCm.requestNetwork(cellRequest, cellNetworkCallback);
1800         cellNetworkCallback.assertNoCallback();
1801
1802         // Bring up cell and expect CALLBACK_AVAILABLE.
1803         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1804         mCellNetworkAgent.connect(true);
1805         cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1806         defaultNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1807
1808         // Bring up wifi and expect CALLBACK_AVAILABLE.
1809         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1810         mWiFiNetworkAgent.connect(true);
1811         cellNetworkCallback.assertNoCallback();
1812         defaultNetworkCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1813
1814         // Bring down cell. Expect no default network callback, since it wasn't the default.
1815         mCellNetworkAgent.disconnect();
1816         cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1817         defaultNetworkCallback.assertNoCallback();
1818
1819         // Bring up cell. Expect no default network callback, since it won't be the default.
1820         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1821         mCellNetworkAgent.connect(true);
1822         cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1823         defaultNetworkCallback.assertNoCallback();
1824
1825         // Bring down wifi. Expect the default network callback to notified of LOST wifi
1826         // followed by AVAILABLE cell.
1827         mWiFiNetworkAgent.disconnect();
1828         cellNetworkCallback.assertNoCallback();
1829         defaultNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1830         defaultNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1831         mCellNetworkAgent.disconnect();
1832         cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1833         defaultNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1834     }
1835
1836     private class TestRequestUpdateCallback extends TestNetworkCallback {
1837         @Override
1838         public void onCapabilitiesChanged(Network network, NetworkCapabilities netCap) {
1839             setLastCallback(CallbackState.NETWORK_CAPABILITIES, network, netCap);
1840         }
1841
1842         @Override
1843         public void onLinkPropertiesChanged(Network network, LinkProperties linkProp) {
1844             setLastCallback(CallbackState.LINK_PROPERTIES, network, linkProp);
1845         }
1846     }
1847
1848     @LargeTest
1849     public void testRequestCallbackUpdates() throws Exception {
1850         // File a network request for mobile.
1851         final TestNetworkCallback cellNetworkCallback = new TestRequestUpdateCallback();
1852         final NetworkRequest cellRequest = new NetworkRequest.Builder()
1853                 .addTransportType(TRANSPORT_CELLULAR).build();
1854         mCm.requestNetwork(cellRequest, cellNetworkCallback);
1855
1856         // Bring up the mobile network.
1857         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1858         mCellNetworkAgent.connect(true);
1859
1860         // We should get onAvailable().
1861         cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1862         // We should get onCapabilitiesChanged(), when the mobile network successfully validates.
1863         cellNetworkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, mCellNetworkAgent);
1864         cellNetworkCallback.assertNoCallback();
1865
1866         // Update LinkProperties.
1867         final LinkProperties lp = new LinkProperties();
1868         lp.setInterfaceName("foonet_data0");
1869         mCellNetworkAgent.sendLinkProperties(lp);
1870         // We should get onLinkPropertiesChanged().
1871         cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
1872         cellNetworkCallback.assertNoCallback();
1873
1874         // Register a garden variety default network request.
1875         final TestNetworkCallback dfltNetworkCallback = new TestRequestUpdateCallback();
1876         mCm.registerDefaultNetworkCallback(dfltNetworkCallback);
1877         // Only onAvailable() is called; no other information is delivered.
1878         dfltNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1879         dfltNetworkCallback.assertNoCallback();
1880
1881         // Request a NetworkCapabilities update; only the requesting callback is notified.
1882         mCm.requestNetworkCapabilities(dfltNetworkCallback);
1883         dfltNetworkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, mCellNetworkAgent);
1884         cellNetworkCallback.assertNoCallback();
1885         dfltNetworkCallback.assertNoCallback();
1886
1887         // Request a LinkProperties update; only the requesting callback is notified.
1888         mCm.requestLinkProperties(dfltNetworkCallback);
1889         dfltNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
1890         cellNetworkCallback.assertNoCallback();
1891         dfltNetworkCallback.assertNoCallback();
1892
1893         mCm.unregisterNetworkCallback(dfltNetworkCallback);
1894         mCm.unregisterNetworkCallback(cellNetworkCallback);
1895     }
1896
1897     private void setCaptivePortalMode(int mode) {
1898         ContentResolver cr = mServiceContext.getContentResolver();
1899         Settings.Global.putInt(cr, Settings.Global.CAPTIVE_PORTAL_MODE, mode);
1900     }
1901
1902     private void setMobileDataAlwaysOn(boolean enable) {
1903         ContentResolver cr = mServiceContext.getContentResolver();
1904         Settings.Global.putInt(cr, Settings.Global.MOBILE_DATA_ALWAYS_ON, enable ? 1 : 0);
1905         mService.updateMobileDataAlwaysOn();
1906         mService.waitForIdle();
1907     }
1908
1909     private boolean isForegroundNetwork(MockNetworkAgent network) {
1910         NetworkCapabilities nc = mCm.getNetworkCapabilities(network.getNetwork());
1911         assertNotNull(nc);
1912         return nc.hasCapability(NET_CAPABILITY_FOREGROUND);
1913     }
1914
1915     @SmallTest
1916     public void testBackgroundNetworks() throws Exception {
1917         // Create a background request. We can't do this ourselves because ConnectivityService
1918         // doesn't have an API for it. So just turn on mobile data always on.
1919         setMobileDataAlwaysOn(true);
1920         final NetworkRequest request = new NetworkRequest.Builder().build();
1921         final NetworkRequest fgRequest = new NetworkRequest.Builder()
1922                 .addCapability(NET_CAPABILITY_FOREGROUND).build();
1923         final TestNetworkCallback callback = new TestNetworkCallback();
1924         final TestNetworkCallback fgCallback = new TestNetworkCallback();
1925         mCm.registerNetworkCallback(request, callback);
1926         mCm.registerNetworkCallback(fgRequest, fgCallback);
1927
1928         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1929         mCellNetworkAgent.connect(true);
1930         callback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1931         fgCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1932         assertTrue(isForegroundNetwork(mCellNetworkAgent));
1933
1934         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1935         mWiFiNetworkAgent.connect(true);
1936
1937         // When wifi connects, cell lingers.
1938         callback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1939         fgCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
1940         callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
1941         fgCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
1942         assertTrue(isForegroundNetwork(mCellNetworkAgent));
1943         assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
1944
1945         // When lingering is complete, cell is still there but is now in the background.
1946         fgCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent, TEST_LINGER_DELAY_MS);
1947         callback.assertNoCallback();
1948         assertFalse(isForegroundNetwork(mCellNetworkAgent));
1949         assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
1950
1951         // File a cell request and check that cell comes into the foreground.
1952         final NetworkRequest cellRequest = new NetworkRequest.Builder()
1953                 .addTransportType(TRANSPORT_CELLULAR).build();
1954         final TestNetworkCallback cellCallback = new TestNetworkCallback();
1955         mCm.requestNetwork(cellRequest, cellCallback);
1956         cellCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1957         fgCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1958         callback.assertNoCallback();  // Because the network is already up.
1959         assertTrue(isForegroundNetwork(mCellNetworkAgent));
1960         assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
1961
1962         // Release the request. The network immediately goes into the background, since it was not
1963         // lingering.
1964         mCm.unregisterNetworkCallback(cellCallback);
1965         fgCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1966         callback.assertNoCallback();
1967         assertFalse(isForegroundNetwork(mCellNetworkAgent));
1968         assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
1969
1970         // Disconnect wifi and check that cell is foreground again.
1971         mWiFiNetworkAgent.disconnect();
1972         callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1973         fgCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1974         fgCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
1975         assertTrue(isForegroundNetwork(mCellNetworkAgent));
1976
1977         mCm.unregisterNetworkCallback(callback);
1978         mCm.unregisterNetworkCallback(fgCallback);
1979     }
1980
1981     @SmallTest
1982     public void testRequestBenchmark() throws Exception {
1983         // Benchmarks connecting and switching performance in the presence of a large number of
1984         // NetworkRequests.
1985         // 1. File NUM_REQUESTS requests.
1986         // 2. Have a network connect. Wait for NUM_REQUESTS onAvailable callbacks to fire.
1987         // 3. Have a new network connect and outscore the previous. Wait for NUM_REQUESTS onLosing
1988         //    and NUM_REQUESTS onAvailable callbacks to fire.
1989         // See how long it took.
1990         final int NUM_REQUESTS = 90;
1991         final NetworkRequest request = new NetworkRequest.Builder().clearCapabilities().build();
1992         final NetworkCallback[] callbacks = new NetworkCallback[NUM_REQUESTS];
1993         final CountDownLatch availableLatch = new CountDownLatch(NUM_REQUESTS);
1994         final CountDownLatch losingLatch = new CountDownLatch(NUM_REQUESTS);
1995
1996         final int REGISTER_TIME_LIMIT_MS = 100;
1997         long startTime = System.currentTimeMillis();
1998         for (int i = 0; i < NUM_REQUESTS; i++) {
1999             callbacks[i] = new NetworkCallback() {
2000                 @Override public void onAvailable(Network n) { availableLatch.countDown(); }
2001                 @Override public void onLosing(Network n, int t) { losingLatch.countDown(); }
2002             };
2003             mCm.registerNetworkCallback(request, callbacks[i]);
2004         }
2005         long timeTaken = System.currentTimeMillis() - startTime;
2006         String msg = String.format("Register %d callbacks: %dms, acceptable %dms",
2007                 NUM_REQUESTS, timeTaken, REGISTER_TIME_LIMIT_MS);
2008         Log.d(TAG, msg);
2009         assertTrue(msg, timeTaken < REGISTER_TIME_LIMIT_MS);
2010
2011         final int CONNECT_TIME_LIMIT_MS = 30;
2012         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2013         // Don't request that the network validate, because otherwise connect() will block until
2014         // the network gets NET_CAPABILITY_VALIDATED, after all the callbacks below have fired,
2015         // and we won't actually measure anything.
2016         mCellNetworkAgent.connect(false);
2017         startTime = System.currentTimeMillis();
2018         if (!availableLatch.await(CONNECT_TIME_LIMIT_MS, TimeUnit.MILLISECONDS)) {
2019             fail(String.format("Only dispatched %d/%d onAvailable callbacks in %dms",
2020                     NUM_REQUESTS - availableLatch.getCount(), NUM_REQUESTS,
2021                     CONNECT_TIME_LIMIT_MS));
2022         }
2023         timeTaken = System.currentTimeMillis() - startTime;
2024         Log.d(TAG, String.format("Connect, %d callbacks: %dms, acceptable %dms",
2025                 NUM_REQUESTS, timeTaken, CONNECT_TIME_LIMIT_MS));
2026
2027         final int SWITCH_TIME_LIMIT_MS = 30;
2028         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2029         // Give wifi a high enough score that we'll linger cell when wifi comes up.
2030         mWiFiNetworkAgent.adjustScore(40);
2031         mWiFiNetworkAgent.connect(false);
2032         startTime = System.currentTimeMillis();
2033         if (!losingLatch.await(SWITCH_TIME_LIMIT_MS, TimeUnit.MILLISECONDS)) {
2034             fail(String.format("Only dispatched %d/%d onLosing callbacks in %dms",
2035                     NUM_REQUESTS - losingLatch.getCount(), NUM_REQUESTS, SWITCH_TIME_LIMIT_MS));
2036         }
2037         timeTaken = System.currentTimeMillis() - startTime;
2038         Log.d(TAG, String.format("Linger, %d callbacks: %dms, acceptable %dms",
2039                 NUM_REQUESTS, timeTaken, SWITCH_TIME_LIMIT_MS));
2040
2041         final int UNREGISTER_TIME_LIMIT_MS = 10;
2042         startTime = System.currentTimeMillis();
2043         for (int i = 0; i < NUM_REQUESTS; i++) {
2044             mCm.unregisterNetworkCallback(callbacks[i]);
2045         }
2046         timeTaken = System.currentTimeMillis() - startTime;
2047         msg = String.format("Unregister %d callbacks: %dms, acceptable %dms",
2048                 NUM_REQUESTS, timeTaken, UNREGISTER_TIME_LIMIT_MS);
2049         Log.d(TAG, msg);
2050         assertTrue(msg, timeTaken < UNREGISTER_TIME_LIMIT_MS);
2051     }
2052
2053     @SmallTest
2054     public void testMobileDataAlwaysOn() throws Exception {
2055         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
2056         final NetworkRequest cellRequest = new NetworkRequest.Builder()
2057                 .addTransportType(TRANSPORT_CELLULAR).build();
2058         mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
2059
2060         final HandlerThread handlerThread = new HandlerThread("MobileDataAlwaysOnFactory");
2061         handlerThread.start();
2062         NetworkCapabilities filter = new NetworkCapabilities()
2063                 .addTransportType(TRANSPORT_CELLULAR)
2064                 .addCapability(NET_CAPABILITY_INTERNET);
2065         final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
2066                 mServiceContext, "testFactory", filter);
2067         testFactory.setScoreFilter(40);
2068
2069         // Register the factory and expect it to start looking for a network.
2070         testFactory.expectAddRequests(1);
2071         testFactory.register();
2072         testFactory.waitForNetworkRequests(1);
2073         assertTrue(testFactory.getMyStartRequested());
2074
2075         // Bring up wifi. The factory stops looking for a network.
2076         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2077         testFactory.expectAddRequests(2);  // Because the default request changes score twice.
2078         mWiFiNetworkAgent.connect(true);
2079         testFactory.waitForNetworkRequests(1);
2080         assertFalse(testFactory.getMyStartRequested());
2081
2082         ContentResolver cr = mServiceContext.getContentResolver();
2083
2084         // Turn on mobile data always on. The factory starts looking again.
2085         testFactory.expectAddRequests(1);
2086         setMobileDataAlwaysOn(true);
2087         testFactory.waitForNetworkRequests(2);
2088         assertTrue(testFactory.getMyStartRequested());
2089
2090         // Bring up cell data and check that the factory stops looking.
2091         assertEquals(1, mCm.getAllNetworks().length);
2092         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2093         testFactory.expectAddRequests(2);  // Because the cell request changes score twice.
2094         mCellNetworkAgent.connect(true);
2095         cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
2096         testFactory.waitForNetworkRequests(2);
2097         assertFalse(testFactory.getMyStartRequested());  // Because the cell network outscores us.
2098
2099         // Check that cell data stays up.
2100         mService.waitForIdle();
2101         verifyActiveNetwork(TRANSPORT_WIFI);
2102         assertEquals(2, mCm.getAllNetworks().length);
2103
2104         // Turn off mobile data always on and expect the request to disappear...
2105         testFactory.expectRemoveRequests(1);
2106         setMobileDataAlwaysOn(false);
2107         testFactory.waitForNetworkRequests(1);
2108
2109         // ...  and cell data to be torn down.
2110         cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
2111         assertEquals(1, mCm.getAllNetworks().length);
2112
2113         testFactory.unregister();
2114         mCm.unregisterNetworkCallback(cellNetworkCallback);
2115         handlerThread.quit();
2116     }
2117
2118     @SmallTest
2119     public void testAvoidBadWifiSetting() throws Exception {
2120         final ContentResolver cr = mServiceContext.getContentResolver();
2121         final WrappedAvoidBadWifiTracker tracker = mService.getAvoidBadWifiTracker();
2122         final String settingName = Settings.Global.NETWORK_AVOID_BAD_WIFI;
2123
2124         tracker.configRestrictsAvoidBadWifi = false;
2125         String[] values = new String[] {null, "0", "1"};
2126         for (int i = 0; i < values.length; i++) {
2127             Settings.Global.putInt(cr, settingName, 1);
2128             tracker.reevaluate();
2129             mService.waitForIdle();
2130             String msg = String.format("config=false, setting=%s", values[i]);
2131             assertTrue(msg, mService.avoidBadWifi());
2132             assertFalse(msg, tracker.shouldNotifyWifiUnvalidated());
2133         }
2134
2135         tracker.configRestrictsAvoidBadWifi = true;
2136
2137         Settings.Global.putInt(cr, settingName, 0);
2138         tracker.reevaluate();
2139         mService.waitForIdle();
2140         assertFalse(mService.avoidBadWifi());
2141         assertFalse(tracker.shouldNotifyWifiUnvalidated());
2142
2143         Settings.Global.putInt(cr, settingName, 1);
2144         tracker.reevaluate();
2145         mService.waitForIdle();
2146         assertTrue(mService.avoidBadWifi());
2147         assertFalse(tracker.shouldNotifyWifiUnvalidated());
2148
2149         Settings.Global.putString(cr, settingName, null);
2150         tracker.reevaluate();
2151         mService.waitForIdle();
2152         assertFalse(mService.avoidBadWifi());
2153         assertTrue(tracker.shouldNotifyWifiUnvalidated());
2154     }
2155
2156     @SmallTest
2157     public void testAvoidBadWifi() throws Exception {
2158         final ContentResolver cr = mServiceContext.getContentResolver();
2159         final WrappedAvoidBadWifiTracker tracker = mService.getAvoidBadWifiTracker();
2160
2161         // Pretend we're on a carrier that restricts switching away from bad wifi.
2162         tracker.configRestrictsAvoidBadWifi = true;
2163
2164         // File a request for cell to ensure it doesn't go down.
2165         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
2166         final NetworkRequest cellRequest = new NetworkRequest.Builder()
2167                 .addTransportType(TRANSPORT_CELLULAR).build();
2168         mCm.requestNetwork(cellRequest, cellNetworkCallback);
2169
2170         TestNetworkCallback defaultCallback = new TestNetworkCallback();
2171         mCm.registerDefaultNetworkCallback(defaultCallback);
2172
2173         NetworkRequest validatedWifiRequest = new NetworkRequest.Builder()
2174                 .addTransportType(TRANSPORT_WIFI)
2175                 .addCapability(NET_CAPABILITY_VALIDATED)
2176                 .build();
2177         TestNetworkCallback validatedWifiCallback = new TestNetworkCallback();
2178         mCm.registerNetworkCallback(validatedWifiRequest, validatedWifiCallback);
2179
2180         Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 0);
2181         tracker.reevaluate();
2182
2183         // Bring up validated cell.
2184         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2185         mCellNetworkAgent.connect(true);
2186         cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
2187         defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
2188         Network cellNetwork = mCellNetworkAgent.getNetwork();
2189
2190         // Bring up validated wifi.
2191         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2192         mWiFiNetworkAgent.connect(true);
2193         defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
2194         validatedWifiCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
2195         Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
2196
2197         // Fail validation on wifi.
2198         mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 599;
2199         mCm.reportNetworkConnectivity(wifiNetwork, false);
2200         validatedWifiCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2201
2202         // Because avoid bad wifi is off, we don't switch to cellular.
2203         defaultCallback.assertNoCallback();
2204         assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
2205                 NET_CAPABILITY_VALIDATED));
2206         assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
2207                 NET_CAPABILITY_VALIDATED));
2208         assertEquals(mCm.getActiveNetwork(), wifiNetwork);
2209
2210         // Simulate switching to a carrier that does not restrict avoiding bad wifi, and expect
2211         // that we switch back to cell.
2212         tracker.configRestrictsAvoidBadWifi = false;
2213         tracker.reevaluate();
2214         defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
2215         assertEquals(mCm.getActiveNetwork(), cellNetwork);
2216
2217         // Switch back to a restrictive carrier.
2218         tracker.configRestrictsAvoidBadWifi = true;
2219         tracker.reevaluate();
2220         defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
2221         assertEquals(mCm.getActiveNetwork(), wifiNetwork);
2222
2223         // Simulate the user selecting "switch" on the dialog, and check that we switch to cell.
2224         mCm.setAvoidUnvalidated(wifiNetwork);
2225         defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
2226         assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
2227                 NET_CAPABILITY_VALIDATED));
2228         assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
2229                 NET_CAPABILITY_VALIDATED));
2230         assertEquals(mCm.getActiveNetwork(), cellNetwork);
2231
2232         // Disconnect and reconnect wifi to clear the one-time switch above.
2233         mWiFiNetworkAgent.disconnect();
2234         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2235         mWiFiNetworkAgent.connect(true);
2236         defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
2237         validatedWifiCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
2238         wifiNetwork = mWiFiNetworkAgent.getNetwork();
2239
2240         // Fail validation on wifi and expect the dialog to appear.
2241         mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 599;
2242         mCm.reportNetworkConnectivity(wifiNetwork, false);
2243         validatedWifiCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2244
2245         // Simulate the user selecting "switch" and checking the don't ask again checkbox.
2246         Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 1);
2247         tracker.reevaluate();
2248
2249         // We now switch to cell.
2250         defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
2251         assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
2252                 NET_CAPABILITY_VALIDATED));
2253         assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
2254                 NET_CAPABILITY_VALIDATED));
2255         assertEquals(mCm.getActiveNetwork(), cellNetwork);
2256
2257         // Simulate the user turning the cellular fallback setting off and then on.
2258         // We switch to wifi and then to cell.
2259         Settings.Global.putString(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, null);
2260         tracker.reevaluate();
2261         defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
2262         assertEquals(mCm.getActiveNetwork(), wifiNetwork);
2263         Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 1);
2264         tracker.reevaluate();
2265         defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
2266         assertEquals(mCm.getActiveNetwork(), cellNetwork);
2267
2268         // If cell goes down, we switch to wifi.
2269         mCellNetworkAgent.disconnect();
2270         defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
2271         defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
2272         validatedWifiCallback.assertNoCallback();
2273
2274         mCm.unregisterNetworkCallback(cellNetworkCallback);
2275         mCm.unregisterNetworkCallback(validatedWifiCallback);
2276         mCm.unregisterNetworkCallback(defaultCallback);
2277     }
2278
2279     private static class TestKeepaliveCallback extends PacketKeepaliveCallback {
2280
2281         public static enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR };
2282
2283         private class CallbackValue {
2284             public CallbackType callbackType;
2285             public int error;
2286
2287             public CallbackValue(CallbackType type) {
2288                 this.callbackType = type;
2289                 this.error = PacketKeepalive.SUCCESS;
2290                 assertTrue("onError callback must have error", type != CallbackType.ON_ERROR);
2291             }
2292
2293             public CallbackValue(CallbackType type, int error) {
2294                 this.callbackType = type;
2295                 this.error = error;
2296                 assertEquals("error can only be set for onError", type, CallbackType.ON_ERROR);
2297             }
2298
2299             @Override
2300             public boolean equals(Object o) {
2301                 return o instanceof CallbackValue &&
2302                         this.callbackType == ((CallbackValue) o).callbackType &&
2303                         this.error == ((CallbackValue) o).error;
2304             }
2305
2306             @Override
2307             public String toString() {
2308                 return String.format("%s(%s, %d)", getClass().getSimpleName(), callbackType, error);
2309             }
2310         }
2311
2312         private LinkedBlockingQueue<CallbackValue> mCallbacks = new LinkedBlockingQueue<>();
2313
2314         @Override
2315         public void onStarted() {
2316             mCallbacks.add(new CallbackValue(CallbackType.ON_STARTED));
2317         }
2318
2319         @Override
2320         public void onStopped() {
2321             mCallbacks.add(new CallbackValue(CallbackType.ON_STOPPED));
2322         }
2323
2324         @Override
2325         public void onError(int error) {
2326             mCallbacks.add(new CallbackValue(CallbackType.ON_ERROR, error));
2327         }
2328
2329         private void expectCallback(CallbackValue callbackValue) {
2330             try {
2331                 assertEquals(
2332                         callbackValue,
2333                         mCallbacks.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
2334             } catch (InterruptedException e) {
2335                 fail(callbackValue.callbackType + " callback not seen after " + TIMEOUT_MS + " ms");
2336             }
2337         }
2338
2339         public void expectStarted() {
2340             expectCallback(new CallbackValue(CallbackType.ON_STARTED));
2341         }
2342
2343         public void expectStopped() {
2344             expectCallback(new CallbackValue(CallbackType.ON_STOPPED));
2345         }
2346
2347         public void expectError(int error) {
2348             expectCallback(new CallbackValue(CallbackType.ON_ERROR, error));
2349         }
2350     }
2351
2352     private Network connectKeepaliveNetwork(LinkProperties lp) {
2353         // Ensure the network is disconnected before we do anything.
2354         if (mWiFiNetworkAgent != null) {
2355             assertNull(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()));
2356         }
2357
2358         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2359         ConditionVariable cv = waitForConnectivityBroadcasts(1);
2360         mWiFiNetworkAgent.connect(true);
2361         waitFor(cv);
2362         verifyActiveNetwork(TRANSPORT_WIFI);
2363         mWiFiNetworkAgent.sendLinkProperties(lp);
2364         mService.waitForIdle();
2365         return mWiFiNetworkAgent.getNetwork();
2366     }
2367
2368     public void testPacketKeepalives() throws Exception {
2369         InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
2370         InetAddress notMyIPv4 = InetAddress.getByName("192.0.2.35");
2371         InetAddress myIPv6 = InetAddress.getByName("2001:db8::1");
2372         InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8");
2373         InetAddress dstIPv6 = InetAddress.getByName("2001:4860:4860::8888");
2374
2375         LinkProperties lp = new LinkProperties();
2376         lp.setInterfaceName("wlan12");
2377         lp.addLinkAddress(new LinkAddress(myIPv6, 64));
2378         lp.addLinkAddress(new LinkAddress(myIPv4, 25));
2379         lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
2380         lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
2381
2382         Network notMyNet = new Network(61234);
2383         Network myNet = connectKeepaliveNetwork(lp);
2384
2385         TestKeepaliveCallback callback = new TestKeepaliveCallback();
2386         PacketKeepalive ka;
2387
2388         // Attempt to start keepalives with invalid parameters and check for errors.
2389         ka = mCm.startNattKeepalive(notMyNet, 25, callback, myIPv4, 1234, dstIPv4);
2390         callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK);
2391
2392         ka = mCm.startNattKeepalive(myNet, 19, callback, notMyIPv4, 1234, dstIPv4);
2393         callback.expectError(PacketKeepalive.ERROR_INVALID_INTERVAL);
2394
2395         ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 1234, dstIPv6);
2396         callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
2397
2398         ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv6, 1234, dstIPv4);
2399         callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
2400
2401         ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv6, 1234, dstIPv6);
2402         callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);  // NAT-T is IPv4-only.
2403
2404         ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 123456, dstIPv4);
2405         callback.expectError(PacketKeepalive.ERROR_INVALID_PORT);
2406
2407         ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 123456, dstIPv4);
2408         callback.expectError(PacketKeepalive.ERROR_INVALID_PORT);
2409
2410         ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
2411         callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
2412
2413         ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
2414         callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
2415
2416         // Check that a started keepalive can be stopped.
2417         mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS);
2418         ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
2419         callback.expectStarted();
2420         mWiFiNetworkAgent.setStopKeepaliveError(PacketKeepalive.SUCCESS);
2421         ka.stop();
2422         callback.expectStopped();
2423
2424         // Check that deleting the IP address stops the keepalive.
2425         LinkProperties bogusLp = new LinkProperties(lp);
2426         ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
2427         callback.expectStarted();
2428         bogusLp.removeLinkAddress(new LinkAddress(myIPv4, 25));
2429         bogusLp.addLinkAddress(new LinkAddress(notMyIPv4, 25));
2430         mWiFiNetworkAgent.sendLinkProperties(bogusLp);
2431         callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
2432         mWiFiNetworkAgent.sendLinkProperties(lp);
2433
2434         // Check that a started keepalive is stopped correctly when the network disconnects.
2435         ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
2436         callback.expectStarted();
2437         mWiFiNetworkAgent.disconnect();
2438         callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK);
2439
2440         // ... and that stopping it after that has no adverse effects.
2441         assertNull(mCm.getNetworkCapabilities(myNet));
2442         ka.stop();
2443
2444         // Reconnect.
2445         myNet = connectKeepaliveNetwork(lp);
2446         mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS);
2447
2448         // Check things work as expected when the keepalive is stopped and the network disconnects.
2449         ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
2450         callback.expectStarted();
2451         ka.stop();
2452         mWiFiNetworkAgent.disconnect();
2453         mService.waitForIdle();
2454         callback.expectStopped();
2455
2456         // Reconnect.
2457         myNet = connectKeepaliveNetwork(lp);
2458         mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS);
2459
2460         // Check that keepalive slots start from 1 and increment. The first one gets slot 1.
2461         mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
2462         ka = mCm.startNattKeepalive(myNet, 25, callback, myIPv4, 12345, dstIPv4);
2463         callback.expectStarted();
2464
2465         // The second one gets slot 2.
2466         mWiFiNetworkAgent.setExpectedKeepaliveSlot(2);
2467         TestKeepaliveCallback callback2 = new TestKeepaliveCallback();
2468         PacketKeepalive ka2 = mCm.startNattKeepalive(myNet, 25, callback2, myIPv4, 6789, dstIPv4);
2469         callback2.expectStarted();
2470
2471         // Now stop the first one and create a third. This also gets slot 1.
2472         ka.stop();
2473         callback.expectStopped();
2474
2475         mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
2476         TestKeepaliveCallback callback3 = new TestKeepaliveCallback();
2477         PacketKeepalive ka3 = mCm.startNattKeepalive(myNet, 25, callback3, myIPv4, 9876, dstIPv4);
2478         callback3.expectStarted();
2479
2480         ka2.stop();
2481         callback2.expectStopped();
2482
2483         ka3.stop();
2484         callback3.expectStopped();
2485     }
2486
2487     @SmallTest
2488     public void testGetCaptivePortalServerUrl() throws Exception {
2489         String url = mCm.getCaptivePortalServerUrl();
2490         assertEquals("http://connectivitycheck.gstatic.com/generate_204", url);
2491     }
2492
2493     private static class TestNetworkPinner extends NetworkPinner {
2494         public static boolean awaitPin(int timeoutMs) {
2495             synchronized(sLock) {
2496                 if (sNetwork == null) {
2497                     try {
2498                         sLock.wait(timeoutMs);
2499                     } catch (InterruptedException e) {}
2500                 }
2501                 return sNetwork != null;
2502             }
2503         }
2504
2505         public static boolean awaitUnpin(int timeoutMs) {
2506             synchronized(sLock) {
2507                 if (sNetwork != null) {
2508                     try {
2509                         sLock.wait(timeoutMs);
2510                     } catch (InterruptedException e) {}
2511                 }
2512                 return sNetwork == null;
2513             }
2514         }
2515     }
2516
2517     private void assertPinnedToWifiWithCellDefault() {
2518         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess());
2519         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2520     }
2521
2522     private void assertPinnedToWifiWithWifiDefault() {
2523         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess());
2524         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2525     }
2526
2527     private void assertNotPinnedToWifi() {
2528         assertNull(mCm.getBoundNetworkForProcess());
2529         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2530     }
2531
2532     @SmallTest
2533     public void testNetworkPinner() {
2534         NetworkRequest wifiRequest = new NetworkRequest.Builder()
2535                 .addTransportType(TRANSPORT_WIFI)
2536                 .build();
2537         assertNull(mCm.getBoundNetworkForProcess());
2538
2539         TestNetworkPinner.pin(mServiceContext, wifiRequest);
2540         assertNull(mCm.getBoundNetworkForProcess());
2541
2542         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2543         mCellNetworkAgent.connect(true);
2544         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2545         mWiFiNetworkAgent.connect(false);
2546
2547         // When wi-fi connects, expect to be pinned.
2548         assertTrue(TestNetworkPinner.awaitPin(100));
2549         assertPinnedToWifiWithCellDefault();
2550
2551         // Disconnect and expect the pin to drop.
2552         mWiFiNetworkAgent.disconnect();
2553         assertTrue(TestNetworkPinner.awaitUnpin(100));
2554         assertNotPinnedToWifi();
2555
2556         // Reconnecting does not cause the pin to come back.
2557         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2558         mWiFiNetworkAgent.connect(false);
2559         assertFalse(TestNetworkPinner.awaitPin(100));
2560         assertNotPinnedToWifi();
2561
2562         // Pinning while connected causes the pin to take effect immediately.
2563         TestNetworkPinner.pin(mServiceContext, wifiRequest);
2564         assertTrue(TestNetworkPinner.awaitPin(100));
2565         assertPinnedToWifiWithCellDefault();
2566
2567         // Explicitly unpin and expect to use the default network again.
2568         TestNetworkPinner.unpin();
2569         assertNotPinnedToWifi();
2570
2571         // Disconnect cell and wifi.
2572         ConditionVariable cv = waitForConnectivityBroadcasts(3);  // cell down, wifi up, wifi down.
2573         mCellNetworkAgent.disconnect();
2574         mWiFiNetworkAgent.disconnect();
2575         waitFor(cv);
2576
2577         // Pinning takes effect even if the pinned network is the default when the pin is set...
2578         TestNetworkPinner.pin(mServiceContext, wifiRequest);
2579         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2580         mWiFiNetworkAgent.connect(false);
2581         assertTrue(TestNetworkPinner.awaitPin(100));
2582         assertPinnedToWifiWithWifiDefault();
2583
2584         // ... and is maintained even when that network is no longer the default.
2585         cv = waitForConnectivityBroadcasts(1);
2586         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2587         mCellNetworkAgent.connect(true);
2588         waitFor(cv);
2589         assertPinnedToWifiWithCellDefault();
2590     }
2591
2592     @SmallTest
2593     public void testNetworkRequestMaximum() {
2594         final int MAX_REQUESTS = 100;
2595         // Test that the limit is enforced when MAX_REQUESTS simultaneous requests are added.
2596         NetworkRequest networkRequest = new NetworkRequest.Builder().build();
2597         ArrayList<NetworkCallback> networkCallbacks = new ArrayList<NetworkCallback>();
2598         try {
2599             for (int i = 0; i < MAX_REQUESTS; i++) {
2600                 NetworkCallback networkCallback = new NetworkCallback();
2601                 mCm.requestNetwork(networkRequest, networkCallback);
2602                 networkCallbacks.add(networkCallback);
2603             }
2604             fail("Registering " + MAX_REQUESTS + " NetworkRequests did not throw exception");
2605         } catch (IllegalArgumentException expected) {}
2606         for (NetworkCallback networkCallback : networkCallbacks) {
2607             mCm.unregisterNetworkCallback(networkCallback);
2608         }
2609         networkCallbacks.clear();
2610
2611         try {
2612             for (int i = 0; i < MAX_REQUESTS; i++) {
2613                 NetworkCallback networkCallback = new NetworkCallback();
2614                 mCm.registerNetworkCallback(networkRequest, networkCallback);
2615                 networkCallbacks.add(networkCallback);
2616             }
2617             fail("Registering " + MAX_REQUESTS + " NetworkCallbacks did not throw exception");
2618         } catch (IllegalArgumentException expected) {}
2619         for (NetworkCallback networkCallback : networkCallbacks) {
2620             mCm.unregisterNetworkCallback(networkCallback);
2621         }
2622         networkCallbacks.clear();
2623
2624         ArrayList<PendingIntent> pendingIntents = new ArrayList<PendingIntent>();
2625         try {
2626             for (int i = 0; i < MAX_REQUESTS + 1; i++) {
2627                 PendingIntent pendingIntent =
2628                         PendingIntent.getBroadcast(mContext, 0, new Intent("a" + i), 0);
2629                 mCm.requestNetwork(networkRequest, pendingIntent);
2630                 pendingIntents.add(pendingIntent);
2631             }
2632             fail("Registering " + MAX_REQUESTS +
2633                     " PendingIntent NetworkRequests did not throw exception");
2634         } catch (IllegalArgumentException expected) {}
2635         for (PendingIntent pendingIntent : pendingIntents) {
2636             mCm.unregisterNetworkCallback(pendingIntent);
2637         }
2638         pendingIntents.clear();
2639
2640         try {
2641             for (int i = 0; i < MAX_REQUESTS + 1; i++) {
2642                 PendingIntent pendingIntent =
2643                         PendingIntent.getBroadcast(mContext, 0, new Intent("a" + i), 0);
2644                 mCm.registerNetworkCallback(networkRequest, pendingIntent);
2645                 pendingIntents.add(pendingIntent);
2646             }
2647             fail("Registering " + MAX_REQUESTS +
2648                     " PendingIntent NetworkCallbacks did not throw exception");
2649         } catch (IllegalArgumentException expected) {}
2650         for (PendingIntent pendingIntent : pendingIntents) {
2651             mCm.unregisterNetworkCallback(pendingIntent);
2652         }
2653         pendingIntents.clear();
2654         mService.waitForIdle(5000);
2655
2656         // Test that the limit is not hit when MAX_REQUESTS requests are added and removed.
2657         for (int i = 0; i < MAX_REQUESTS; i++) {
2658             NetworkCallback networkCallback = new NetworkCallback();
2659             mCm.requestNetwork(networkRequest, networkCallback);
2660             mCm.unregisterNetworkCallback(networkCallback);
2661         }
2662         mService.waitForIdle();
2663         for (int i = 0; i < MAX_REQUESTS; i++) {
2664             NetworkCallback networkCallback = new NetworkCallback();
2665             mCm.registerNetworkCallback(networkRequest, networkCallback);
2666             mCm.unregisterNetworkCallback(networkCallback);
2667         }
2668         mService.waitForIdle();
2669         for (int i = 0; i < MAX_REQUESTS; i++) {
2670             PendingIntent pendingIntent =
2671                     PendingIntent.getBroadcast(mContext, 0, new Intent("b" + i), 0);
2672             mCm.requestNetwork(networkRequest, pendingIntent);
2673             mCm.unregisterNetworkCallback(pendingIntent);
2674         }
2675         mService.waitForIdle();
2676         for (int i = 0; i < MAX_REQUESTS; i++) {
2677             PendingIntent pendingIntent =
2678                     PendingIntent.getBroadcast(mContext, 0, new Intent("c" + i), 0);
2679             mCm.registerNetworkCallback(networkRequest, pendingIntent);
2680             mCm.unregisterNetworkCallback(pendingIntent);
2681         }
2682     }
2683 }