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