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