OSDN Git Service

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