OSDN Git Service

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