• 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.PRIVATE_DNS_MODE_OFF;
21 import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OPPORTUNISTIC;
22 import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_PROVIDER_HOSTNAME;
23 import static android.net.ConnectivityManager.TYPE_ETHERNET;
24 import static android.net.ConnectivityManager.TYPE_MOBILE;
25 import static android.net.ConnectivityManager.TYPE_MOBILE_FOTA;
26 import static android.net.ConnectivityManager.TYPE_MOBILE_MMS;
27 import static android.net.ConnectivityManager.TYPE_NONE;
28 import static android.net.ConnectivityManager.TYPE_VPN;
29 import static android.net.ConnectivityManager.TYPE_WIFI;
30 import static android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL;
31 import static android.net.NetworkCapabilities.NET_CAPABILITY_CBS;
32 import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN;
33 import static android.net.NetworkCapabilities.NET_CAPABILITY_EIMS;
34 import static android.net.NetworkCapabilities.NET_CAPABILITY_FOREGROUND;
35 import static android.net.NetworkCapabilities.NET_CAPABILITY_FOTA;
36 import static android.net.NetworkCapabilities.NET_CAPABILITY_IA;
37 import static android.net.NetworkCapabilities.NET_CAPABILITY_IMS;
38 import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
39 import static android.net.NetworkCapabilities.NET_CAPABILITY_MMS;
40 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
41 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
42 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED;
43 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN;
44 import static android.net.NetworkCapabilities.NET_CAPABILITY_RCS;
45 import static android.net.NetworkCapabilities.NET_CAPABILITY_SUPL;
46 import static android.net.NetworkCapabilities.NET_CAPABILITY_TRUSTED;
47 import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
48 import static android.net.NetworkCapabilities.NET_CAPABILITY_WIFI_P2P;
49 import static android.net.NetworkCapabilities.NET_CAPABILITY_XCAP;
50 import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
51 import static android.net.NetworkCapabilities.TRANSPORT_ETHERNET;
52 import static android.net.NetworkCapabilities.TRANSPORT_VPN;
53 import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
54 import static android.net.NetworkCapabilities.TRANSPORT_WIFI_AWARE;
55 
56 import static com.android.internal.util.TestUtils.waitForIdleHandler;
57 import static com.android.internal.util.TestUtils.waitForIdleLooper;
58 
59 import static org.junit.Assert.assertEquals;
60 import static org.junit.Assert.assertFalse;
61 import static org.junit.Assert.assertNotNull;
62 import static org.junit.Assert.assertNull;
63 import static org.junit.Assert.assertTrue;
64 import static org.junit.Assert.fail;
65 import static org.mockito.Matchers.anyBoolean;
66 import static org.mockito.Matchers.anyInt;
67 import static org.mockito.Matchers.anyString;
68 import static org.mockito.Mockito.any;
69 import static org.mockito.Mockito.atLeastOnce;
70 import static org.mockito.Mockito.eq;
71 import static org.mockito.Mockito.mock;
72 import static org.mockito.Mockito.never;
73 import static org.mockito.Mockito.reset;
74 import static org.mockito.Mockito.spy;
75 import static org.mockito.Mockito.times;
76 import static org.mockito.Mockito.verify;
77 import static org.mockito.Mockito.verifyNoMoreInteractions;
78 import static org.mockito.Mockito.when;
79 
80 
81 import android.app.NotificationManager;
82 import android.app.PendingIntent;
83 import android.content.BroadcastReceiver;
84 import android.content.ContentResolver;
85 import android.content.Context;
86 import android.content.Intent;
87 import android.content.IntentFilter;
88 import android.content.pm.UserInfo;
89 import android.content.res.Resources;
90 import android.net.CaptivePortal;
91 import android.net.ConnectivityManager;
92 import android.net.ConnectivityManager.NetworkCallback;
93 import android.net.ConnectivityManager.PacketKeepalive;
94 import android.net.ConnectivityManager.PacketKeepaliveCallback;
95 import android.net.ConnectivityManager.TooManyRequestsException;
96 import android.net.ConnectivityThread;
97 import android.net.INetworkPolicyManager;
98 import android.net.INetworkStatsService;
99 import android.net.IpPrefix;
100 import android.net.LinkAddress;
101 import android.net.LinkProperties;
102 import android.net.MatchAllNetworkSpecifier;
103 import android.net.Network;
104 import android.net.NetworkAgent;
105 import android.net.NetworkCapabilities;
106 import android.net.NetworkFactory;
107 import android.net.NetworkInfo;
108 import android.net.NetworkInfo.DetailedState;
109 import android.net.NetworkMisc;
110 import android.net.NetworkRequest;
111 import android.net.NetworkSpecifier;
112 import android.net.NetworkUtils;
113 import android.net.RouteInfo;
114 import android.net.StringNetworkSpecifier;
115 import android.net.UidRange;
116 import android.net.VpnService;
117 import android.net.captiveportal.CaptivePortalProbeResult;
118 import android.net.metrics.IpConnectivityLog;
119 import android.net.util.MultinetworkPolicyTracker;
120 import android.os.ConditionVariable;
121 import android.os.Handler;
122 import android.os.HandlerThread;
123 import android.os.INetworkManagementService;
124 import android.os.Looper;
125 import android.os.Message;
126 import android.os.Parcel;
127 import android.os.Parcelable;
128 import android.os.Process;
129 import android.os.SystemClock;
130 import android.os.UserHandle;
131 import android.provider.Settings;
132 import android.support.test.InstrumentationRegistry;
133 import android.support.test.filters.SmallTest;
134 import android.support.test.runner.AndroidJUnit4;
135 import android.test.mock.MockContentResolver;
136 import android.util.ArraySet;
137 import android.util.Log;
138 
139 import com.android.internal.net.VpnConfig;
140 import com.android.internal.util.ArrayUtils;
141 import com.android.internal.util.WakeupMessage;
142 import com.android.internal.util.test.BroadcastInterceptingContext;
143 import com.android.internal.util.test.FakeSettingsProvider;
144 import com.android.server.connectivity.ConnectivityConstants;
145 import com.android.server.connectivity.DefaultNetworkMetrics;
146 import com.android.server.connectivity.DnsManager;
147 import com.android.server.connectivity.IpConnectivityMetrics;
148 import com.android.server.connectivity.MockableSystemProperties;
149 import com.android.server.connectivity.NetworkAgentInfo;
150 import com.android.server.connectivity.NetworkMonitor;
151 import com.android.server.connectivity.Vpn;
152 import com.android.server.net.NetworkPinner;
153 import com.android.server.net.NetworkPolicyManagerInternal;
154 
155 import org.junit.After;
156 import org.junit.Before;
157 import org.junit.Ignore;
158 import org.junit.Test;
159 import org.junit.runner.RunWith;
160 import org.mockito.ArgumentCaptor;
161 import org.mockito.Mock;
162 import org.mockito.MockitoAnnotations;
163 import org.mockito.Spy;
164 
165 import java.net.InetAddress;
166 import java.net.UnknownHostException;
167 import java.util.ArrayList;
168 import java.util.Arrays;
169 import java.util.Collection;
170 import java.util.HashSet;
171 import java.util.List;
172 import java.util.Objects;
173 import java.util.Set;
174 import java.util.concurrent.CountDownLatch;
175 import java.util.concurrent.LinkedBlockingQueue;
176 import java.util.concurrent.TimeUnit;
177 import java.util.concurrent.atomic.AtomicBoolean;
178 import java.util.function.Predicate;
179 
180 
181 /**
182  * Tests for {@link ConnectivityService}.
183  *
184  * Build, install and run with:
185  *  runtest frameworks-net -c com.android.server.ConnectivityServiceTest
186  */
187 @RunWith(AndroidJUnit4.class)
188 @SmallTest
189 public class ConnectivityServiceTest {
190     private static final String TAG = "ConnectivityServiceTest";
191 
192     private static final int TIMEOUT_MS = 500;
193     private static final int TEST_LINGER_DELAY_MS = 120;
194 
195     private static final String MOBILE_IFNAME = "test_rmnet_data0";
196     private static final String WIFI_IFNAME = "test_wlan0";
197 
198     private MockContext mServiceContext;
199     private WrappedConnectivityService mService;
200     private WrappedConnectivityManager mCm;
201     private MockNetworkAgent mWiFiNetworkAgent;
202     private MockNetworkAgent mCellNetworkAgent;
203     private MockNetworkAgent mEthernetNetworkAgent;
204     private MockVpn mMockVpn;
205     private Context mContext;
206 
207     @Mock IpConnectivityMetrics.Logger mMetricsService;
208     @Mock DefaultNetworkMetrics mDefaultNetworkMetrics;
209     @Mock INetworkManagementService mNetworkManagementService;
210     @Mock INetworkStatsService mStatsService;
211 
212     private ArgumentCaptor<String[]> mStringArrayCaptor = ArgumentCaptor.forClass(String[].class);
213 
214     // This class exists to test bindProcessToNetwork and getBoundNetworkForProcess. These methods
215     // do not go through ConnectivityService but talk to netd directly, so they don't automatically
216     // reflect the state of our test ConnectivityService.
217     private class WrappedConnectivityManager extends ConnectivityManager {
218         private Network mFakeBoundNetwork;
219 
bindProcessToNetwork(Network network)220         public synchronized boolean bindProcessToNetwork(Network network) {
221             mFakeBoundNetwork = network;
222             return true;
223         }
224 
getBoundNetworkForProcess()225         public synchronized Network getBoundNetworkForProcess() {
226             return mFakeBoundNetwork;
227         }
228 
WrappedConnectivityManager(Context context, ConnectivityService service)229         public WrappedConnectivityManager(Context context, ConnectivityService service) {
230             super(context, service);
231         }
232     }
233 
234     private class MockContext extends BroadcastInterceptingContext {
235         private final MockContentResolver mContentResolver;
236 
237         @Spy private Resources mResources;
238         private final LinkedBlockingQueue<Intent> mStartedActivities = new LinkedBlockingQueue<>();
239 
MockContext(Context base)240         MockContext(Context base) {
241             super(base);
242 
243             mResources = spy(base.getResources());
244             when(mResources.getStringArray(com.android.internal.R.array.networkAttributes)).
245                     thenReturn(new String[] {
246                             "wifi,1,1,1,-1,true",
247                             "mobile,0,0,0,-1,true",
248                             "mobile_mms,2,0,2,60000,true",
249                     });
250 
251             mContentResolver = new MockContentResolver();
252             mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
253         }
254 
255         @Override
startActivityAsUser(Intent intent, UserHandle handle)256         public void startActivityAsUser(Intent intent, UserHandle handle) {
257             mStartedActivities.offer(intent);
258         }
259 
expectStartActivityIntent(int timeoutMs)260         public Intent expectStartActivityIntent(int timeoutMs) {
261             Intent intent = null;
262             try {
263                 intent = mStartedActivities.poll(timeoutMs, TimeUnit.MILLISECONDS);
264             } catch (InterruptedException e) {}
265             assertNotNull("Did not receive sign-in intent after " + timeoutMs + "ms", intent);
266             return intent;
267         }
268 
expectNoStartActivityIntent(int timeoutMs)269         public void expectNoStartActivityIntent(int timeoutMs) {
270             try {
271                 assertNull("Received unexpected Intent to start activity",
272                         mStartedActivities.poll(timeoutMs, TimeUnit.MILLISECONDS));
273             } catch (InterruptedException e) {}
274         }
275 
276         @Override
getSystemService(String name)277         public Object getSystemService(String name) {
278             if (Context.CONNECTIVITY_SERVICE.equals(name)) return mCm;
279             if (Context.NOTIFICATION_SERVICE.equals(name)) return mock(NotificationManager.class);
280             return super.getSystemService(name);
281         }
282 
283         @Override
getContentResolver()284         public ContentResolver getContentResolver() {
285             return mContentResolver;
286         }
287 
288         @Override
getResources()289         public Resources getResources() {
290             return mResources;
291         }
292     }
293 
waitForIdle(int timeoutMsAsInt)294     public void waitForIdle(int timeoutMsAsInt) {
295         long timeoutMs = timeoutMsAsInt;
296         waitForIdleHandler(mService.mHandlerThread, timeoutMs);
297         waitForIdle(mCellNetworkAgent, timeoutMs);
298         waitForIdle(mWiFiNetworkAgent, timeoutMs);
299         waitForIdle(mEthernetNetworkAgent, timeoutMs);
300         waitForIdleHandler(mService.mHandlerThread, timeoutMs);
301         waitForIdleLooper(ConnectivityThread.getInstanceLooper(), timeoutMs);
302     }
303 
waitForIdle(MockNetworkAgent agent, long timeoutMs)304     public void waitForIdle(MockNetworkAgent agent, long timeoutMs) {
305         if (agent == null) {
306             return;
307         }
308         waitForIdleHandler(agent.mHandlerThread, timeoutMs);
309     }
310 
waitForIdle()311     private void waitForIdle() {
312         waitForIdle(TIMEOUT_MS);
313     }
314 
315     @Test
testWaitForIdle()316     public void testWaitForIdle() {
317         final int attempts = 50;  // Causes the test to take about 200ms on bullhead-eng.
318 
319         // Tests that waitForIdle returns immediately if the service is already idle.
320         for (int i = 0; i < attempts; i++) {
321             waitForIdle();
322         }
323 
324         // Bring up a network that we can use to send messages to ConnectivityService.
325         ConditionVariable cv = waitForConnectivityBroadcasts(1);
326         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
327         mWiFiNetworkAgent.connect(false);
328         waitFor(cv);
329         Network n = mWiFiNetworkAgent.getNetwork();
330         assertNotNull(n);
331 
332         // Tests that calling waitForIdle waits for messages to be processed.
333         for (int i = 0; i < attempts; i++) {
334             mWiFiNetworkAgent.setSignalStrength(i);
335             waitForIdle();
336             assertEquals(i, mCm.getNetworkCapabilities(n).getSignalStrength());
337         }
338     }
339 
340     // This test has an inherent race condition in it, and cannot be enabled for continuous testing
341     // or presubmit tests. It is kept for manual runs and documentation purposes.
342     @Ignore
verifyThatNotWaitingForIdleCausesRaceConditions()343     public void verifyThatNotWaitingForIdleCausesRaceConditions() {
344         // Bring up a network that we can use to send messages to ConnectivityService.
345         ConditionVariable cv = waitForConnectivityBroadcasts(1);
346         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
347         mWiFiNetworkAgent.connect(false);
348         waitFor(cv);
349         Network n = mWiFiNetworkAgent.getNetwork();
350         assertNotNull(n);
351 
352         // Ensure that not calling waitForIdle causes a race condition.
353         final int attempts = 50;  // Causes the test to take about 200ms on bullhead-eng.
354         for (int i = 0; i < attempts; i++) {
355             mWiFiNetworkAgent.setSignalStrength(i);
356             if (i != mCm.getNetworkCapabilities(n).getSignalStrength()) {
357                 // We hit a race condition, as expected. Pass the test.
358                 return;
359             }
360         }
361 
362         // No race? There is a bug in this test.
363         fail("expected race condition at least once in " + attempts + " attempts");
364     }
365 
366     private class MockNetworkAgent {
367         private final WrappedNetworkMonitor mWrappedNetworkMonitor;
368         private final NetworkInfo mNetworkInfo;
369         private final NetworkCapabilities mNetworkCapabilities;
370         private final HandlerThread mHandlerThread;
371         private final ConditionVariable mDisconnected = new ConditionVariable();
372         private final ConditionVariable mNetworkStatusReceived = new ConditionVariable();
373         private final ConditionVariable mPreventReconnectReceived = new ConditionVariable();
374         private int mScore;
375         private NetworkAgent mNetworkAgent;
376         private int mStartKeepaliveError = PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED;
377         private int mStopKeepaliveError = PacketKeepalive.NO_KEEPALIVE;
378         private Integer mExpectedKeepaliveSlot = null;
379         // Contains the redirectUrl from networkStatus(). Before reading, wait for
380         // mNetworkStatusReceived.
381         private String mRedirectUrl;
382 
MockNetworkAgent(int transport)383         MockNetworkAgent(int transport) {
384             this(transport, new LinkProperties());
385         }
386 
MockNetworkAgent(int transport, LinkProperties linkProperties)387         MockNetworkAgent(int transport, LinkProperties linkProperties) {
388             final int type = transportToLegacyType(transport);
389             final String typeName = ConnectivityManager.getNetworkTypeName(type);
390             mNetworkInfo = new NetworkInfo(type, 0, typeName, "Mock");
391             mNetworkCapabilities = new NetworkCapabilities();
392             mNetworkCapabilities.addTransportType(transport);
393             switch (transport) {
394                 case TRANSPORT_ETHERNET:
395                     mScore = 70;
396                     break;
397                 case TRANSPORT_WIFI:
398                     mScore = 60;
399                     break;
400                 case TRANSPORT_CELLULAR:
401                     mScore = 50;
402                     break;
403                 case TRANSPORT_WIFI_AWARE:
404                     mScore = 20;
405                     break;
406                 case TRANSPORT_VPN:
407                     mNetworkCapabilities.removeCapability(NET_CAPABILITY_NOT_VPN);
408                     mScore = ConnectivityConstants.VPN_DEFAULT_SCORE;
409                     break;
410                 default:
411                     throw new UnsupportedOperationException("unimplemented network type");
412             }
413             mHandlerThread = new HandlerThread("Mock-" + typeName);
414             mHandlerThread.start();
415             mNetworkAgent = new NetworkAgent(mHandlerThread.getLooper(), mServiceContext,
416                     "Mock-" + typeName, mNetworkInfo, mNetworkCapabilities,
417                     linkProperties, mScore, new NetworkMisc()) {
418                 @Override
419                 public void unwanted() { mDisconnected.open(); }
420 
421                 @Override
422                 public void startPacketKeepalive(Message msg) {
423                     int slot = msg.arg1;
424                     if (mExpectedKeepaliveSlot != null) {
425                         assertEquals((int) mExpectedKeepaliveSlot, slot);
426                     }
427                     onPacketKeepaliveEvent(slot, mStartKeepaliveError);
428                 }
429 
430                 @Override
431                 public void stopPacketKeepalive(Message msg) {
432                     onPacketKeepaliveEvent(msg.arg1, mStopKeepaliveError);
433                 }
434 
435                 @Override
436                 public void networkStatus(int status, String redirectUrl) {
437                     mRedirectUrl = redirectUrl;
438                     mNetworkStatusReceived.open();
439                 }
440 
441                 @Override
442                 protected void preventAutomaticReconnect() {
443                     mPreventReconnectReceived.open();
444                 }
445             };
446             // Waits for the NetworkAgent to be registered, which includes the creation of the
447             // NetworkMonitor.
448             waitForIdle();
449             mWrappedNetworkMonitor = mService.getLastCreatedWrappedNetworkMonitor();
450         }
451 
adjustScore(int change)452         public void adjustScore(int change) {
453             mScore += change;
454             mNetworkAgent.sendNetworkScore(mScore);
455         }
456 
getScore()457         public int getScore() {
458             return mScore;
459         }
460 
explicitlySelected(boolean acceptUnvalidated)461         public void explicitlySelected(boolean acceptUnvalidated) {
462             mNetworkAgent.explicitlySelected(acceptUnvalidated);
463         }
464 
addCapability(int capability)465         public void addCapability(int capability) {
466             mNetworkCapabilities.addCapability(capability);
467             mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
468         }
469 
removeCapability(int capability)470         public void removeCapability(int capability) {
471             mNetworkCapabilities.removeCapability(capability);
472             mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
473         }
474 
setUids(Set<UidRange> uids)475         public void setUids(Set<UidRange> uids) {
476             mNetworkCapabilities.setUids(uids);
477             mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
478         }
479 
setSignalStrength(int signalStrength)480         public void setSignalStrength(int signalStrength) {
481             mNetworkCapabilities.setSignalStrength(signalStrength);
482             mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
483         }
484 
setNetworkSpecifier(NetworkSpecifier networkSpecifier)485         public void setNetworkSpecifier(NetworkSpecifier networkSpecifier) {
486             mNetworkCapabilities.setNetworkSpecifier(networkSpecifier);
487             mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
488         }
489 
setNetworkCapabilities(NetworkCapabilities nc, boolean sendToConnectivityService)490         public void setNetworkCapabilities(NetworkCapabilities nc,
491                 boolean sendToConnectivityService) {
492             mNetworkCapabilities.set(nc);
493             if (sendToConnectivityService) {
494                 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
495             }
496         }
497 
connectWithoutInternet()498         public void connectWithoutInternet() {
499             mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, null);
500             mNetworkAgent.sendNetworkInfo(mNetworkInfo);
501         }
502 
503         /**
504          * Transition this NetworkAgent to CONNECTED state with NET_CAPABILITY_INTERNET.
505          * @param validated Indicate if network should pretend to be validated.
506          */
connect(boolean validated)507         public void connect(boolean validated) {
508             connect(validated, true);
509         }
510 
511         /**
512          * Transition this NetworkAgent to CONNECTED state.
513          * @param validated Indicate if network should pretend to be validated.
514          * @param hasInternet Indicate if network should pretend to have NET_CAPABILITY_INTERNET.
515          */
connect(boolean validated, boolean hasInternet)516         public void connect(boolean validated, boolean hasInternet) {
517             assertEquals("MockNetworkAgents can only be connected once",
518                     mNetworkInfo.getDetailedState(), DetailedState.IDLE);
519             assertFalse(mNetworkCapabilities.hasCapability(NET_CAPABILITY_INTERNET));
520 
521             NetworkCallback callback = null;
522             final ConditionVariable validatedCv = new ConditionVariable();
523             if (validated) {
524                 mWrappedNetworkMonitor.gen204ProbeResult = 204;
525                 NetworkRequest request = new NetworkRequest.Builder()
526                         .addTransportType(mNetworkCapabilities.getTransportTypes()[0])
527                         .clearCapabilities()
528                         .build();
529                 callback = new NetworkCallback() {
530                     public void onCapabilitiesChanged(Network network,
531                             NetworkCapabilities networkCapabilities) {
532                         if (network.equals(getNetwork()) &&
533                             networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED)) {
534                             validatedCv.open();
535                         }
536                     }
537                 };
538                 mCm.registerNetworkCallback(request, callback);
539             }
540             if (hasInternet) {
541                 addCapability(NET_CAPABILITY_INTERNET);
542             }
543 
544             connectWithoutInternet();
545 
546             if (validated) {
547                 // Wait for network to validate.
548                 waitFor(validatedCv);
549                 mWrappedNetworkMonitor.gen204ProbeResult = 500;
550             }
551 
552             if (callback != null) mCm.unregisterNetworkCallback(callback);
553         }
554 
connectWithCaptivePortal(String redirectUrl)555         public void connectWithCaptivePortal(String redirectUrl) {
556             mWrappedNetworkMonitor.gen204ProbeResult = 200;
557             mWrappedNetworkMonitor.gen204ProbeRedirectUrl = redirectUrl;
558             connect(false);
559         }
560 
suspend()561         public void suspend() {
562             mNetworkInfo.setDetailedState(DetailedState.SUSPENDED, null, null);
563             mNetworkAgent.sendNetworkInfo(mNetworkInfo);
564         }
565 
resume()566         public void resume() {
567             mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, null);
568             mNetworkAgent.sendNetworkInfo(mNetworkInfo);
569         }
570 
disconnect()571         public void disconnect() {
572             mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, null);
573             mNetworkAgent.sendNetworkInfo(mNetworkInfo);
574         }
575 
getNetwork()576         public Network getNetwork() {
577             return new Network(mNetworkAgent.netId);
578         }
579 
getPreventReconnectReceived()580         public ConditionVariable getPreventReconnectReceived() {
581             return mPreventReconnectReceived;
582         }
583 
getDisconnectedCV()584         public ConditionVariable getDisconnectedCV() {
585             return mDisconnected;
586         }
587 
getWrappedNetworkMonitor()588         public WrappedNetworkMonitor getWrappedNetworkMonitor() {
589             return mWrappedNetworkMonitor;
590         }
591 
sendLinkProperties(LinkProperties lp)592         public void sendLinkProperties(LinkProperties lp) {
593             mNetworkAgent.sendLinkProperties(lp);
594         }
595 
setStartKeepaliveError(int error)596         public void setStartKeepaliveError(int error) {
597             mStartKeepaliveError = error;
598         }
599 
setStopKeepaliveError(int error)600         public void setStopKeepaliveError(int error) {
601             mStopKeepaliveError = error;
602         }
603 
setExpectedKeepaliveSlot(Integer slot)604         public void setExpectedKeepaliveSlot(Integer slot) {
605             mExpectedKeepaliveSlot = slot;
606         }
607 
waitForRedirectUrl()608         public String waitForRedirectUrl() {
609             assertTrue(mNetworkStatusReceived.block(TIMEOUT_MS));
610             return mRedirectUrl;
611         }
612 
getNetworkAgent()613         public NetworkAgent getNetworkAgent() {
614             return mNetworkAgent;
615         }
616 
getNetworkCapabilities()617         public NetworkCapabilities getNetworkCapabilities() {
618             return mNetworkCapabilities;
619         }
620     }
621 
622     /**
623      * A NetworkFactory that allows tests to wait until any in-flight NetworkRequest add or remove
624      * operations have been processed. Before ConnectivityService can add or remove any requests,
625      * the factory must be told to expect those operations by calling expectAddRequests or
626      * expectRemoveRequests.
627      */
628     private static class MockNetworkFactory extends NetworkFactory {
629         private final ConditionVariable mNetworkStartedCV = new ConditionVariable();
630         private final ConditionVariable mNetworkStoppedCV = new ConditionVariable();
631         private final AtomicBoolean mNetworkStarted = new AtomicBoolean(false);
632 
633         // Used to expect that requests be removed or added on a separate thread, without sleeping.
634         // Callers can call either expectAddRequests() or expectRemoveRequests() exactly once, then
635         // cause some other thread to add or remove requests, then call waitForRequests(). We can
636         // either expect requests to be added or removed, but not both, because CountDownLatch can
637         // only count in one direction.
638         private CountDownLatch mExpectations;
639 
640         // Whether we are currently expecting requests to be added or removed. Valid only if
641         // mExpectations is non-null.
642         private boolean mExpectingAdditions;
643 
MockNetworkFactory(Looper looper, Context context, String logTag, NetworkCapabilities filter)644         public MockNetworkFactory(Looper looper, Context context, String logTag,
645                 NetworkCapabilities filter) {
646             super(looper, context, logTag, filter);
647         }
648 
getMyRequestCount()649         public int getMyRequestCount() {
650             return getRequestCount();
651         }
652 
startNetwork()653         protected void startNetwork() {
654             mNetworkStarted.set(true);
655             mNetworkStartedCV.open();
656         }
657 
stopNetwork()658         protected void stopNetwork() {
659             mNetworkStarted.set(false);
660             mNetworkStoppedCV.open();
661         }
662 
getMyStartRequested()663         public boolean getMyStartRequested() {
664             return mNetworkStarted.get();
665         }
666 
getNetworkStartedCV()667         public ConditionVariable getNetworkStartedCV() {
668             mNetworkStartedCV.close();
669             return mNetworkStartedCV;
670         }
671 
getNetworkStoppedCV()672         public ConditionVariable getNetworkStoppedCV() {
673             mNetworkStoppedCV.close();
674             return mNetworkStoppedCV;
675         }
676 
677         @Override
handleAddRequest(NetworkRequest request, int score)678         protected void handleAddRequest(NetworkRequest request, int score) {
679             // If we're expecting anything, we must be expecting additions.
680             if (mExpectations != null && !mExpectingAdditions) {
681                 fail("Can't add requests while expecting requests to be removed");
682             }
683 
684             // Add the request.
685             super.handleAddRequest(request, score);
686 
687             // Reduce the number of request additions we're waiting for.
688             if (mExpectingAdditions) {
689                 assertTrue("Added more requests than expected", mExpectations.getCount() > 0);
690                 mExpectations.countDown();
691             }
692         }
693 
694         @Override
handleRemoveRequest(NetworkRequest request)695         protected void handleRemoveRequest(NetworkRequest request) {
696             // If we're expecting anything, we must be expecting removals.
697             if (mExpectations != null && mExpectingAdditions) {
698                 fail("Can't remove requests while expecting requests to be added");
699             }
700 
701             // Remove the request.
702             super.handleRemoveRequest(request);
703 
704             // Reduce the number of request removals we're waiting for.
705             if (!mExpectingAdditions) {
706                 assertTrue("Removed more requests than expected", mExpectations.getCount() > 0);
707                 mExpectations.countDown();
708             }
709         }
710 
assertNoExpectations()711         private void assertNoExpectations() {
712             if (mExpectations != null) {
713                 fail("Can't add expectation, " + mExpectations.getCount() + " already pending");
714             }
715         }
716 
717         // Expects that count requests will be added.
expectAddRequests(final int count)718         public void expectAddRequests(final int count) {
719             assertNoExpectations();
720             mExpectingAdditions = true;
721             mExpectations = new CountDownLatch(count);
722         }
723 
724         // Expects that count requests will be removed.
expectRemoveRequests(final int count)725         public void expectRemoveRequests(final int count) {
726             assertNoExpectations();
727             mExpectingAdditions = false;
728             mExpectations = new CountDownLatch(count);
729         }
730 
731         // Waits for the expected request additions or removals to happen within a timeout.
waitForRequests()732         public void waitForRequests() throws InterruptedException {
733             assertNotNull("Nothing to wait for", mExpectations);
734             mExpectations.await(TIMEOUT_MS, TimeUnit.MILLISECONDS);
735             final long count = mExpectations.getCount();
736             final String msg = count + " requests still not " +
737                     (mExpectingAdditions ? "added" : "removed") +
738                     " after " + TIMEOUT_MS + " ms";
739             assertEquals(msg, 0, count);
740             mExpectations = null;
741         }
742 
waitForNetworkRequests(final int count)743         public void waitForNetworkRequests(final int count) throws InterruptedException {
744             waitForRequests();
745             assertEquals(count, getMyRequestCount());
746         }
747     }
748 
startHandlerThreadAndReturnLooper()749     private static Looper startHandlerThreadAndReturnLooper() {
750         final HandlerThread handlerThread = new HandlerThread("MockVpnThread");
751         handlerThread.start();
752         return handlerThread.getLooper();
753     }
754 
755     private class MockVpn extends Vpn {
756         // TODO : the interactions between this mock and the mock network agent are too
757         // hard to get right at this moment, because it's unclear in which case which
758         // target needs to get a method call or both, and in what order. It's because
759         // MockNetworkAgent wants to manage its own NetworkCapabilities, but the Vpn
760         // parent class of MockVpn agent wants that responsibility.
761         // That being said inside the test it should be possible to make the interactions
762         // harder to get wrong with precise speccing, judicious comments, helper methods
763         // and a few sprinkled assertions.
764 
765         private boolean mConnected = false;
766         // Careful ! This is different from mNetworkAgent, because MockNetworkAgent does
767         // not inherit from NetworkAgent.
768         private MockNetworkAgent mMockNetworkAgent;
769 
MockVpn(int userId)770         public MockVpn(int userId) {
771             super(startHandlerThreadAndReturnLooper(), mServiceContext, mNetworkManagementService,
772                     userId);
773         }
774 
setNetworkAgent(MockNetworkAgent agent)775         public void setNetworkAgent(MockNetworkAgent agent) {
776             waitForIdle(agent, TIMEOUT_MS);
777             mMockNetworkAgent = agent;
778             mNetworkAgent = agent.getNetworkAgent();
779             mNetworkCapabilities.set(agent.getNetworkCapabilities());
780         }
781 
setUids(Set<UidRange> uids)782         public void setUids(Set<UidRange> uids) {
783             mNetworkCapabilities.setUids(uids);
784             updateCapabilities();
785         }
786 
787         @Override
getNetId()788         public int getNetId() {
789             return mMockNetworkAgent.getNetwork().netId;
790         }
791 
792         @Override
appliesToUid(int uid)793         public boolean appliesToUid(int uid) {
794             return mConnected;  // Trickery to simplify testing.
795         }
796 
797         @Override
isCallerEstablishedOwnerLocked()798         protected boolean isCallerEstablishedOwnerLocked() {
799             return mConnected;  // Similar trickery
800         }
801 
connect()802         public void connect() {
803             mNetworkCapabilities.set(mMockNetworkAgent.getNetworkCapabilities());
804             mConnected = true;
805             mConfig = new VpnConfig();
806         }
807 
808         @Override
updateCapabilities()809         public void updateCapabilities() {
810             if (!mConnected) return;
811             super.updateCapabilities();
812             // Because super.updateCapabilities will update the capabilities of the agent but not
813             // the mock agent, the mock agent needs to know about them.
814             copyCapabilitiesToNetworkAgent();
815         }
816 
copyCapabilitiesToNetworkAgent()817         private void copyCapabilitiesToNetworkAgent() {
818             if (null != mMockNetworkAgent) {
819                 mMockNetworkAgent.setNetworkCapabilities(mNetworkCapabilities,
820                         false /* sendToConnectivityService */);
821             }
822         }
823 
disconnect()824         public void disconnect() {
825             mConnected = false;
826             mConfig = null;
827         }
828     }
829 
830     private class FakeWakeupMessage extends WakeupMessage {
831         private static final int UNREASONABLY_LONG_WAIT = 1000;
832 
FakeWakeupMessage(Context context, Handler handler, String cmdName, int cmd)833         public FakeWakeupMessage(Context context, Handler handler, String cmdName, int cmd) {
834             super(context, handler, cmdName, cmd);
835         }
836 
FakeWakeupMessage(Context context, Handler handler, String cmdName, int cmd, int arg1, int arg2, Object obj)837         public FakeWakeupMessage(Context context, Handler handler, String cmdName, int cmd,
838                 int arg1, int arg2, Object obj) {
839             super(context, handler, cmdName, cmd, arg1, arg2, obj);
840         }
841 
842         @Override
schedule(long when)843         public void schedule(long when) {
844             long delayMs = when - SystemClock.elapsedRealtime();
845             if (delayMs < 0) delayMs = 0;
846             if (delayMs > UNREASONABLY_LONG_WAIT) {
847                 fail("Attempting to send msg more than " + UNREASONABLY_LONG_WAIT +
848                         "ms into the future: " + delayMs);
849             }
850             Message msg = mHandler.obtainMessage(mCmd, mArg1, mArg2, mObj);
851             mHandler.sendMessageDelayed(msg, delayMs);
852         }
853 
854         @Override
cancel()855         public void cancel() {
856             mHandler.removeMessages(mCmd, mObj);
857         }
858 
859         @Override
onAlarm()860         public void onAlarm() {
861             throw new AssertionError("Should never happen. Update this fake.");
862         }
863     }
864 
865     // NetworkMonitor implementation allowing overriding of Internet connectivity probe result.
866     private class WrappedNetworkMonitor extends NetworkMonitor {
867         public final Handler connectivityHandler;
868         // HTTP response code fed back to NetworkMonitor for Internet connectivity probe.
869         public int gen204ProbeResult = 500;
870         public String gen204ProbeRedirectUrl = null;
871         public volatile InetAddress[] dnsLookupResults = null;
872 
WrappedNetworkMonitor(Context context, Handler handler, NetworkAgentInfo networkAgentInfo, NetworkRequest defaultRequest, IpConnectivityLog log)873         public WrappedNetworkMonitor(Context context, Handler handler,
874                 NetworkAgentInfo networkAgentInfo, NetworkRequest defaultRequest,
875                 IpConnectivityLog log) {
876             super(context, handler, networkAgentInfo, defaultRequest, log,
877                     NetworkMonitor.NetworkMonitorSettings.DEFAULT);
878             connectivityHandler = handler;
879         }
880 
881         @Override
isCaptivePortal()882         protected CaptivePortalProbeResult isCaptivePortal() {
883             if (!mIsCaptivePortalCheckEnabled) { return new CaptivePortalProbeResult(204); }
884             return new CaptivePortalProbeResult(gen204ProbeResult, gen204ProbeRedirectUrl, null);
885         }
886 
fakeDnsLookup()887         private InetAddress[] fakeDnsLookup() throws UnknownHostException {
888             if (dnsLookupResults == null) {
889                 throw new UnknownHostException();
890             }
891             return dnsLookupResults;
892         }
893 
894         @Override
getAllByName(Network network, String hostname)895         protected InetAddress[] getAllByName(Network network, String hostname)
896                 throws UnknownHostException {
897             return fakeDnsLookup();
898         }
899 
900         @Override
resolveAllLocally(Network network, String hostname, int flags)901         protected InetAddress[] resolveAllLocally(Network network, String hostname, int flags)
902                 throws UnknownHostException {
903             return fakeDnsLookup();
904         }
905     }
906 
907     private class WrappedMultinetworkPolicyTracker extends MultinetworkPolicyTracker {
908         public volatile boolean configRestrictsAvoidBadWifi;
909         public volatile int configMeteredMultipathPreference;
910 
WrappedMultinetworkPolicyTracker(Context c, Handler h, Runnable r)911         public WrappedMultinetworkPolicyTracker(Context c, Handler h, Runnable r) {
912             super(c, h, r);
913         }
914 
915         @Override
configRestrictsAvoidBadWifi()916         public boolean configRestrictsAvoidBadWifi() {
917             return configRestrictsAvoidBadWifi;
918         }
919 
920         @Override
configMeteredMultipathPreference()921         public int configMeteredMultipathPreference() {
922             return configMeteredMultipathPreference;
923         }
924     }
925 
926     private class WrappedConnectivityService extends ConnectivityService {
927         public WrappedMultinetworkPolicyTracker wrappedMultinetworkPolicyTracker;
928         private WrappedNetworkMonitor mLastCreatedNetworkMonitor;
929         private MockableSystemProperties mSystemProperties;
930 
WrappedConnectivityService(Context context, INetworkManagementService netManager, INetworkStatsService statsService, INetworkPolicyManager policyManager, IpConnectivityLog log)931         public WrappedConnectivityService(Context context, INetworkManagementService netManager,
932                 INetworkStatsService statsService, INetworkPolicyManager policyManager,
933                 IpConnectivityLog log) {
934             super(context, netManager, statsService, policyManager, log);
935             mLingerDelayMs = TEST_LINGER_DELAY_MS;
936         }
937 
938         @Override
getSystemProperties()939         protected MockableSystemProperties getSystemProperties() {
940             // Minimal approach to overriding system properties: let most calls fall through to real
941             // device values, and only override ones values that are important to this test.
942             mSystemProperties = spy(new MockableSystemProperties());
943             when(mSystemProperties.getInt("net.tcp.default_init_rwnd", 0)).thenReturn(0);
944             when(mSystemProperties.getBoolean("ro.radio.noril", false)).thenReturn(false);
945             return mSystemProperties;
946         }
947 
948         @Override
reserveNetId()949         protected int reserveNetId() {
950             while (true) {
951                 final int netId = super.reserveNetId();
952 
953                 // Don't overlap test NetIDs with real NetIDs as binding sockets to real networks
954                 // can have odd side-effects, like network validations succeeding.
955                 Context context = InstrumentationRegistry.getContext();
956                 final Network[] networks = ConnectivityManager.from(context).getAllNetworks();
957                 boolean overlaps = false;
958                 for (Network network : networks) {
959                     if (netId == network.netId) {
960                         overlaps = true;
961                         break;
962                     }
963                 }
964                 if (overlaps) continue;
965 
966                 return netId;
967             }
968         }
969 
970         @Override
createNetworkMonitor(Context context, Handler handler, NetworkAgentInfo nai, NetworkRequest defaultRequest)971         public NetworkMonitor createNetworkMonitor(Context context, Handler handler,
972                 NetworkAgentInfo nai, NetworkRequest defaultRequest) {
973             final WrappedNetworkMonitor monitor = new WrappedNetworkMonitor(
974                     context, handler, nai, defaultRequest, mock(IpConnectivityLog.class));
975             mLastCreatedNetworkMonitor = monitor;
976             return monitor;
977         }
978 
979         @Override
createMultinetworkPolicyTracker( Context c, Handler h, Runnable r)980         public MultinetworkPolicyTracker createMultinetworkPolicyTracker(
981                 Context c, Handler h, Runnable r) {
982             final WrappedMultinetworkPolicyTracker tracker = new WrappedMultinetworkPolicyTracker(c, h, r);
983             return tracker;
984         }
985 
getMultinetworkPolicyTracker()986         public WrappedMultinetworkPolicyTracker getMultinetworkPolicyTracker() {
987             return (WrappedMultinetworkPolicyTracker) mMultinetworkPolicyTracker;
988         }
989 
990         @Override
makeWakeupMessage( Context context, Handler handler, String cmdName, int cmd, Object obj)991         public WakeupMessage makeWakeupMessage(
992                 Context context, Handler handler, String cmdName, int cmd, Object obj) {
993             return new FakeWakeupMessage(context, handler, cmdName, cmd, 0, 0, obj);
994         }
995 
996         @Override
hasService(String name)997         public boolean hasService(String name) {
998             // Currenty, the only relevant service that ConnectivityService checks for is
999             // ETHERNET_SERVICE.
1000             return Context.ETHERNET_SERVICE.equals(name);
1001         }
1002 
1003         @Override
metricsLogger()1004         protected IpConnectivityMetrics.Logger metricsLogger() {
1005             return mMetricsService;
1006         }
1007 
1008         @Override
registerNetdEventCallback()1009         protected void registerNetdEventCallback() {
1010         }
1011 
getLastCreatedWrappedNetworkMonitor()1012         public WrappedNetworkMonitor getLastCreatedWrappedNetworkMonitor() {
1013             return mLastCreatedNetworkMonitor;
1014         }
1015 
mockVpn(int uid)1016         public void mockVpn(int uid) {
1017             synchronized (mVpns) {
1018                 int userId = UserHandle.getUserId(uid);
1019                 mMockVpn = new MockVpn(userId);
1020                 // This has no effect unless the VPN is actually connected, because things like
1021                 // getActiveNetworkForUidInternal call getNetworkAgentInfoForNetId on the VPN
1022                 // netId, and check if that network is actually connected.
1023                 mVpns.put(userId, mMockVpn);
1024             }
1025         }
1026 
waitForIdle(int timeoutMs)1027         public void waitForIdle(int timeoutMs) {
1028             waitForIdleHandler(mHandlerThread, timeoutMs);
1029         }
1030 
waitForIdle()1031         public void waitForIdle() {
1032             waitForIdle(TIMEOUT_MS);
1033         }
1034     }
1035 
1036     /**
1037      * Wait up to TIMEOUT_MS for {@code conditionVariable} to open.
1038      * Fails if TIMEOUT_MS goes by before {@code conditionVariable} opens.
1039      */
waitFor(ConditionVariable conditionVariable)1040     static private void waitFor(ConditionVariable conditionVariable) {
1041         if (conditionVariable.block(TIMEOUT_MS)) {
1042             return;
1043         }
1044         fail("ConditionVariable was blocked for more than " + TIMEOUT_MS + "ms");
1045     }
1046 
1047     @Before
setUp()1048     public void setUp() throws Exception {
1049         mContext = InstrumentationRegistry.getContext();
1050 
1051         MockitoAnnotations.initMocks(this);
1052         when(mMetricsService.defaultNetworkMetrics()).thenReturn(mDefaultNetworkMetrics);
1053 
1054         // InstrumentationTestRunner prepares a looper, but AndroidJUnitRunner does not.
1055         // http://b/25897652 .
1056         if (Looper.myLooper() == null) {
1057             Looper.prepare();
1058         }
1059 
1060         mServiceContext = new MockContext(InstrumentationRegistry.getContext());
1061         LocalServices.removeServiceForTest(NetworkPolicyManagerInternal.class);
1062         LocalServices.addService(
1063                 NetworkPolicyManagerInternal.class, mock(NetworkPolicyManagerInternal.class));
1064         mService = new WrappedConnectivityService(mServiceContext,
1065                 mNetworkManagementService,
1066                 mStatsService,
1067                 mock(INetworkPolicyManager.class),
1068                 mock(IpConnectivityLog.class));
1069 
1070         // Create local CM before sending system ready so that we can answer
1071         // getSystemService() correctly.
1072         mCm = new WrappedConnectivityManager(InstrumentationRegistry.getContext(), mService);
1073         mService.systemReady();
1074         mService.mockVpn(Process.myUid());
1075         mCm.bindProcessToNetwork(null);
1076 
1077         // Ensure that the default setting for Captive Portals is used for most tests
1078         setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_PROMPT);
1079         setMobileDataAlwaysOn(false);
1080         setPrivateDnsSettings(PRIVATE_DNS_MODE_OFF, "ignored.example.com");
1081     }
1082 
1083     @After
tearDown()1084     public void tearDown() throws Exception {
1085         setMobileDataAlwaysOn(false);
1086         if (mCellNetworkAgent != null) {
1087             mCellNetworkAgent.disconnect();
1088             mCellNetworkAgent = null;
1089         }
1090         if (mWiFiNetworkAgent != null) {
1091             mWiFiNetworkAgent.disconnect();
1092             mWiFiNetworkAgent = null;
1093         }
1094         if (mEthernetNetworkAgent != null) {
1095             mEthernetNetworkAgent.disconnect();
1096             mEthernetNetworkAgent = null;
1097         }
1098     }
1099 
transportToLegacyType(int transport)1100     private static int transportToLegacyType(int transport) {
1101         switch (transport) {
1102             case TRANSPORT_ETHERNET:
1103                 return TYPE_ETHERNET;
1104             case TRANSPORT_WIFI:
1105                 return TYPE_WIFI;
1106             case TRANSPORT_CELLULAR:
1107                 return TYPE_MOBILE;
1108             case TRANSPORT_VPN:
1109                 return TYPE_VPN;
1110             default:
1111                 return TYPE_NONE;
1112         }
1113     }
1114 
verifyActiveNetwork(int transport)1115     private void verifyActiveNetwork(int transport) {
1116         // Test getActiveNetworkInfo()
1117         assertNotNull(mCm.getActiveNetworkInfo());
1118         assertEquals(transportToLegacyType(transport), mCm.getActiveNetworkInfo().getType());
1119         // Test getActiveNetwork()
1120         assertNotNull(mCm.getActiveNetwork());
1121         assertEquals(mCm.getActiveNetwork(), mCm.getActiveNetworkForUid(Process.myUid()));
1122         if (!NetworkCapabilities.isValidTransport(transport)) {
1123             throw new IllegalStateException("Unknown transport " + transport);
1124         }
1125         switch (transport) {
1126             case TRANSPORT_WIFI:
1127                 assertEquals(mCm.getActiveNetwork(), mWiFiNetworkAgent.getNetwork());
1128                 break;
1129             case TRANSPORT_CELLULAR:
1130                 assertEquals(mCm.getActiveNetwork(), mCellNetworkAgent.getNetwork());
1131                 break;
1132             default:
1133                 break;
1134         }
1135         // Test getNetworkInfo(Network)
1136         assertNotNull(mCm.getNetworkInfo(mCm.getActiveNetwork()));
1137         assertEquals(transportToLegacyType(transport),
1138                 mCm.getNetworkInfo(mCm.getActiveNetwork()).getType());
1139         // Test getNetworkCapabilities(Network)
1140         assertNotNull(mCm.getNetworkCapabilities(mCm.getActiveNetwork()));
1141         assertTrue(mCm.getNetworkCapabilities(mCm.getActiveNetwork()).hasTransport(transport));
1142     }
1143 
verifyNoNetwork()1144     private void verifyNoNetwork() {
1145         waitForIdle();
1146         // Test getActiveNetworkInfo()
1147         assertNull(mCm.getActiveNetworkInfo());
1148         // Test getActiveNetwork()
1149         assertNull(mCm.getActiveNetwork());
1150         assertNull(mCm.getActiveNetworkForUid(Process.myUid()));
1151         // Test getAllNetworks()
1152         assertEmpty(mCm.getAllNetworks());
1153     }
1154 
1155     /**
1156      * Return a ConditionVariable that opens when {@code count} numbers of CONNECTIVITY_ACTION
1157      * broadcasts are received.
1158      */
waitForConnectivityBroadcasts(final int count)1159     private ConditionVariable waitForConnectivityBroadcasts(final int count) {
1160         final ConditionVariable cv = new ConditionVariable();
1161         mServiceContext.registerReceiver(new BroadcastReceiver() {
1162                     private int remaining = count;
1163                     public void onReceive(Context context, Intent intent) {
1164                         if (--remaining == 0) {
1165                             cv.open();
1166                             mServiceContext.unregisterReceiver(this);
1167                         }
1168                     }
1169                 }, new IntentFilter(CONNECTIVITY_ACTION));
1170         return cv;
1171     }
1172 
1173     @Test
testNetworkTypes()1174     public void testNetworkTypes() {
1175         // Ensure that our mocks for the networkAttributes config variable work as expected. If they
1176         // don't, then tests that depend on CONNECTIVITY_ACTION broadcasts for these network types
1177         // will fail. Failing here is much easier to debug.
1178         assertTrue(mCm.isNetworkSupported(TYPE_WIFI));
1179         assertTrue(mCm.isNetworkSupported(TYPE_MOBILE));
1180         assertTrue(mCm.isNetworkSupported(TYPE_MOBILE_MMS));
1181         assertFalse(mCm.isNetworkSupported(TYPE_MOBILE_FOTA));
1182 
1183         // Check that TYPE_ETHERNET is supported. Unlike the asserts above, which only validate our
1184         // mocks, this assert exercises the ConnectivityService code path that ensures that
1185         // TYPE_ETHERNET is supported if the ethernet service is running.
1186         assertTrue(mCm.isNetworkSupported(TYPE_ETHERNET));
1187     }
1188 
1189     @Test
testLingering()1190     public void testLingering() throws Exception {
1191         verifyNoNetwork();
1192         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1193         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1194         assertNull(mCm.getActiveNetworkInfo());
1195         assertNull(mCm.getActiveNetwork());
1196         // Test bringing up validated cellular.
1197         ConditionVariable cv = waitForConnectivityBroadcasts(1);
1198         mCellNetworkAgent.connect(true);
1199         waitFor(cv);
1200         verifyActiveNetwork(TRANSPORT_CELLULAR);
1201         assertLength(2, mCm.getAllNetworks());
1202         assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) ||
1203                 mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork()));
1204         assertTrue(mCm.getAllNetworks()[0].equals(mWiFiNetworkAgent.getNetwork()) ||
1205                 mCm.getAllNetworks()[1].equals(mWiFiNetworkAgent.getNetwork()));
1206         // Test bringing up validated WiFi.
1207         cv = waitForConnectivityBroadcasts(2);
1208         mWiFiNetworkAgent.connect(true);
1209         waitFor(cv);
1210         verifyActiveNetwork(TRANSPORT_WIFI);
1211         assertLength(2, mCm.getAllNetworks());
1212         assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) ||
1213                 mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork()));
1214         assertTrue(mCm.getAllNetworks()[0].equals(mCellNetworkAgent.getNetwork()) ||
1215                 mCm.getAllNetworks()[1].equals(mCellNetworkAgent.getNetwork()));
1216         // Test cellular linger timeout.
1217         waitFor(mCellNetworkAgent.getDisconnectedCV());
1218         waitForIdle();
1219         assertLength(1, mCm.getAllNetworks());
1220         verifyActiveNetwork(TRANSPORT_WIFI);
1221         assertLength(1, mCm.getAllNetworks());
1222         assertEquals(mCm.getAllNetworks()[0], mCm.getActiveNetwork());
1223         // Test WiFi disconnect.
1224         cv = waitForConnectivityBroadcasts(1);
1225         mWiFiNetworkAgent.disconnect();
1226         waitFor(cv);
1227         verifyNoNetwork();
1228     }
1229 
1230     @Test
testValidatedCellularOutscoresUnvalidatedWiFi()1231     public void testValidatedCellularOutscoresUnvalidatedWiFi() throws Exception {
1232         // Test bringing up unvalidated WiFi
1233         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1234         ConditionVariable cv = waitForConnectivityBroadcasts(1);
1235         mWiFiNetworkAgent.connect(false);
1236         waitFor(cv);
1237         verifyActiveNetwork(TRANSPORT_WIFI);
1238         // Test bringing up unvalidated cellular
1239         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1240         mCellNetworkAgent.connect(false);
1241         waitForIdle();
1242         verifyActiveNetwork(TRANSPORT_WIFI);
1243         // Test cellular disconnect.
1244         mCellNetworkAgent.disconnect();
1245         waitForIdle();
1246         verifyActiveNetwork(TRANSPORT_WIFI);
1247         // Test bringing up validated cellular
1248         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1249         cv = waitForConnectivityBroadcasts(2);
1250         mCellNetworkAgent.connect(true);
1251         waitFor(cv);
1252         verifyActiveNetwork(TRANSPORT_CELLULAR);
1253         // Test cellular disconnect.
1254         cv = waitForConnectivityBroadcasts(2);
1255         mCellNetworkAgent.disconnect();
1256         waitFor(cv);
1257         verifyActiveNetwork(TRANSPORT_WIFI);
1258         // Test WiFi disconnect.
1259         cv = waitForConnectivityBroadcasts(1);
1260         mWiFiNetworkAgent.disconnect();
1261         waitFor(cv);
1262         verifyNoNetwork();
1263     }
1264 
1265     @Test
testUnvalidatedWifiOutscoresUnvalidatedCellular()1266     public void testUnvalidatedWifiOutscoresUnvalidatedCellular() throws Exception {
1267         // Test bringing up unvalidated cellular.
1268         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1269         ConditionVariable cv = waitForConnectivityBroadcasts(1);
1270         mCellNetworkAgent.connect(false);
1271         waitFor(cv);
1272         verifyActiveNetwork(TRANSPORT_CELLULAR);
1273         // Test bringing up unvalidated WiFi.
1274         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1275         cv = waitForConnectivityBroadcasts(2);
1276         mWiFiNetworkAgent.connect(false);
1277         waitFor(cv);
1278         verifyActiveNetwork(TRANSPORT_WIFI);
1279         // Test WiFi disconnect.
1280         cv = waitForConnectivityBroadcasts(2);
1281         mWiFiNetworkAgent.disconnect();
1282         waitFor(cv);
1283         verifyActiveNetwork(TRANSPORT_CELLULAR);
1284         // Test cellular disconnect.
1285         cv = waitForConnectivityBroadcasts(1);
1286         mCellNetworkAgent.disconnect();
1287         waitFor(cv);
1288         verifyNoNetwork();
1289     }
1290 
1291     @Test
testUnlingeringDoesNotValidate()1292     public void testUnlingeringDoesNotValidate() throws Exception {
1293         // Test bringing up unvalidated WiFi.
1294         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1295         ConditionVariable cv = waitForConnectivityBroadcasts(1);
1296         mWiFiNetworkAgent.connect(false);
1297         waitFor(cv);
1298         verifyActiveNetwork(TRANSPORT_WIFI);
1299         assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1300                 NET_CAPABILITY_VALIDATED));
1301         // Test bringing up validated cellular.
1302         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1303         cv = waitForConnectivityBroadcasts(2);
1304         mCellNetworkAgent.connect(true);
1305         waitFor(cv);
1306         verifyActiveNetwork(TRANSPORT_CELLULAR);
1307         assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1308                 NET_CAPABILITY_VALIDATED));
1309         // Test cellular disconnect.
1310         cv = waitForConnectivityBroadcasts(2);
1311         mCellNetworkAgent.disconnect();
1312         waitFor(cv);
1313         verifyActiveNetwork(TRANSPORT_WIFI);
1314         // Unlingering a network should not cause it to be marked as validated.
1315         assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1316                 NET_CAPABILITY_VALIDATED));
1317     }
1318 
1319     @Test
testCellularOutscoresWeakWifi()1320     public void testCellularOutscoresWeakWifi() throws Exception {
1321         // Test bringing up validated cellular.
1322         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1323         ConditionVariable cv = waitForConnectivityBroadcasts(1);
1324         mCellNetworkAgent.connect(true);
1325         waitFor(cv);
1326         verifyActiveNetwork(TRANSPORT_CELLULAR);
1327         // Test bringing up validated WiFi.
1328         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1329         cv = waitForConnectivityBroadcasts(2);
1330         mWiFiNetworkAgent.connect(true);
1331         waitFor(cv);
1332         verifyActiveNetwork(TRANSPORT_WIFI);
1333         // Test WiFi getting really weak.
1334         cv = waitForConnectivityBroadcasts(2);
1335         mWiFiNetworkAgent.adjustScore(-11);
1336         waitFor(cv);
1337         verifyActiveNetwork(TRANSPORT_CELLULAR);
1338         // Test WiFi restoring signal strength.
1339         cv = waitForConnectivityBroadcasts(2);
1340         mWiFiNetworkAgent.adjustScore(11);
1341         waitFor(cv);
1342         verifyActiveNetwork(TRANSPORT_WIFI);
1343     }
1344 
1345     @Test
testReapingNetwork()1346     public void testReapingNetwork() throws Exception {
1347         // Test bringing up WiFi without NET_CAPABILITY_INTERNET.
1348         // Expect it to be torn down immediately because it satisfies no requests.
1349         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1350         ConditionVariable cv = mWiFiNetworkAgent.getDisconnectedCV();
1351         mWiFiNetworkAgent.connectWithoutInternet();
1352         waitFor(cv);
1353         // Test bringing up cellular without NET_CAPABILITY_INTERNET.
1354         // Expect it to be torn down immediately because it satisfies no requests.
1355         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1356         cv = mCellNetworkAgent.getDisconnectedCV();
1357         mCellNetworkAgent.connectWithoutInternet();
1358         waitFor(cv);
1359         // Test bringing up validated WiFi.
1360         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1361         cv = waitForConnectivityBroadcasts(1);
1362         mWiFiNetworkAgent.connect(true);
1363         waitFor(cv);
1364         verifyActiveNetwork(TRANSPORT_WIFI);
1365         // Test bringing up unvalidated cellular.
1366         // Expect it to be torn down because it could never be the highest scoring network
1367         // satisfying the default request even if it validated.
1368         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1369         cv = mCellNetworkAgent.getDisconnectedCV();
1370         mCellNetworkAgent.connect(false);
1371         waitFor(cv);
1372         verifyActiveNetwork(TRANSPORT_WIFI);
1373         cv = mWiFiNetworkAgent.getDisconnectedCV();
1374         mWiFiNetworkAgent.disconnect();
1375         waitFor(cv);
1376     }
1377 
1378     @Test
testCellularFallback()1379     public void testCellularFallback() throws Exception {
1380         // Test bringing up validated cellular.
1381         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1382         ConditionVariable cv = waitForConnectivityBroadcasts(1);
1383         mCellNetworkAgent.connect(true);
1384         waitFor(cv);
1385         verifyActiveNetwork(TRANSPORT_CELLULAR);
1386         // Test bringing up validated WiFi.
1387         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1388         cv = waitForConnectivityBroadcasts(2);
1389         mWiFiNetworkAgent.connect(true);
1390         waitFor(cv);
1391         verifyActiveNetwork(TRANSPORT_WIFI);
1392         // Reevaluate WiFi (it'll instantly fail DNS).
1393         cv = waitForConnectivityBroadcasts(2);
1394         assertTrue(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1395                 NET_CAPABILITY_VALIDATED));
1396         mCm.reportBadNetwork(mWiFiNetworkAgent.getNetwork());
1397         // Should quickly fall back to Cellular.
1398         waitFor(cv);
1399         assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1400                 NET_CAPABILITY_VALIDATED));
1401         verifyActiveNetwork(TRANSPORT_CELLULAR);
1402         // Reevaluate cellular (it'll instantly fail DNS).
1403         cv = waitForConnectivityBroadcasts(2);
1404         assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1405                 NET_CAPABILITY_VALIDATED));
1406         mCm.reportBadNetwork(mCellNetworkAgent.getNetwork());
1407         // Should quickly fall back to WiFi.
1408         waitFor(cv);
1409         assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1410                 NET_CAPABILITY_VALIDATED));
1411         assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1412                 NET_CAPABILITY_VALIDATED));
1413         verifyActiveNetwork(TRANSPORT_WIFI);
1414     }
1415 
1416     @Test
testWiFiFallback()1417     public void testWiFiFallback() throws Exception {
1418         // Test bringing up unvalidated WiFi.
1419         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1420         ConditionVariable cv = waitForConnectivityBroadcasts(1);
1421         mWiFiNetworkAgent.connect(false);
1422         waitFor(cv);
1423         verifyActiveNetwork(TRANSPORT_WIFI);
1424         // Test bringing up validated cellular.
1425         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1426         cv = waitForConnectivityBroadcasts(2);
1427         mCellNetworkAgent.connect(true);
1428         waitFor(cv);
1429         verifyActiveNetwork(TRANSPORT_CELLULAR);
1430         // Reevaluate cellular (it'll instantly fail DNS).
1431         cv = waitForConnectivityBroadcasts(2);
1432         assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1433                 NET_CAPABILITY_VALIDATED));
1434         mCm.reportBadNetwork(mCellNetworkAgent.getNetwork());
1435         // Should quickly fall back to WiFi.
1436         waitFor(cv);
1437         assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1438                 NET_CAPABILITY_VALIDATED));
1439         verifyActiveNetwork(TRANSPORT_WIFI);
1440     }
1441 
1442     enum CallbackState {
1443         NONE,
1444         AVAILABLE,
1445         NETWORK_CAPABILITIES,
1446         LINK_PROPERTIES,
1447         SUSPENDED,
1448         RESUMED,
1449         LOSING,
1450         LOST,
1451         UNAVAILABLE
1452     }
1453 
1454     private static class CallbackInfo {
1455         public final CallbackState state;
1456         public final Network network;
1457         public final Object arg;
CallbackInfo(CallbackState s, Network n, Object o)1458         public CallbackInfo(CallbackState s, Network n, Object o) {
1459             state = s; network = n; arg = o;
1460         }
toString()1461         public String toString() {
1462             return String.format("%s (%s) (%s)", state, network, arg);
1463         }
1464         @Override
equals(Object o)1465         public boolean equals(Object o) {
1466             if (!(o instanceof CallbackInfo)) return false;
1467             // Ignore timeMs, since it's unpredictable.
1468             CallbackInfo other = (CallbackInfo) o;
1469             return (state == other.state) && Objects.equals(network, other.network);
1470         }
1471         @Override
hashCode()1472         public int hashCode() {
1473             return Objects.hash(state, network);
1474         }
1475     }
1476 
1477     /**
1478      * Utility NetworkCallback for testing. The caller must explicitly test for all the callbacks
1479      * this class receives, by calling expectCallback() exactly once each time a callback is
1480      * received. assertNoCallback may be called at any time.
1481      */
1482     private class TestNetworkCallback extends NetworkCallback {
1483         // Chosen to be much less than the linger timeout. This ensures that we can distinguish
1484         // between a LOST callback that arrives immediately and a LOST callback that arrives after
1485         // the linger timeout.
1486         private final static int TIMEOUT_MS = 100;
1487 
1488         private final LinkedBlockingQueue<CallbackInfo> mCallbacks = new LinkedBlockingQueue<>();
1489         private Network mLastAvailableNetwork;
1490 
setLastCallback(CallbackState state, Network network, Object o)1491         protected void setLastCallback(CallbackState state, Network network, Object o) {
1492             mCallbacks.offer(new CallbackInfo(state, network, o));
1493         }
1494 
1495         @Override
onAvailable(Network network)1496         public void onAvailable(Network network) {
1497             mLastAvailableNetwork = network;
1498             setLastCallback(CallbackState.AVAILABLE, network, null);
1499         }
1500 
1501         @Override
onCapabilitiesChanged(Network network, NetworkCapabilities netCap)1502         public void onCapabilitiesChanged(Network network, NetworkCapabilities netCap) {
1503             setLastCallback(CallbackState.NETWORK_CAPABILITIES, network, netCap);
1504         }
1505 
1506         @Override
onLinkPropertiesChanged(Network network, LinkProperties linkProp)1507         public void onLinkPropertiesChanged(Network network, LinkProperties linkProp) {
1508             setLastCallback(CallbackState.LINK_PROPERTIES, network, linkProp);
1509         }
1510 
1511         @Override
onUnavailable()1512         public void onUnavailable() {
1513             setLastCallback(CallbackState.UNAVAILABLE, null, null);
1514         }
1515 
1516         @Override
onNetworkSuspended(Network network)1517         public void onNetworkSuspended(Network network) {
1518             setLastCallback(CallbackState.SUSPENDED, network, null);
1519         }
1520 
1521         @Override
onNetworkResumed(Network network)1522         public void onNetworkResumed(Network network) {
1523             setLastCallback(CallbackState.RESUMED, network, null);
1524         }
1525 
1526         @Override
onLosing(Network network, int maxMsToLive)1527         public void onLosing(Network network, int maxMsToLive) {
1528             setLastCallback(CallbackState.LOSING, network, maxMsToLive /* autoboxed int */);
1529         }
1530 
1531         @Override
onLost(Network network)1532         public void onLost(Network network) {
1533             mLastAvailableNetwork = null;
1534             setLastCallback(CallbackState.LOST, network, null);
1535         }
1536 
getLastAvailableNetwork()1537         public Network getLastAvailableNetwork() {
1538             return mLastAvailableNetwork;
1539         }
1540 
nextCallback(int timeoutMs)1541         CallbackInfo nextCallback(int timeoutMs) {
1542             CallbackInfo cb = null;
1543             try {
1544                 cb = mCallbacks.poll(timeoutMs, TimeUnit.MILLISECONDS);
1545             } catch (InterruptedException e) {
1546             }
1547             if (cb == null) {
1548                 // LinkedBlockingQueue.poll() returns null if it timeouts.
1549                 fail("Did not receive callback after " + timeoutMs + "ms");
1550             }
1551             return cb;
1552         }
1553 
expectCallback(CallbackState state, MockNetworkAgent agent, int timeoutMs)1554         CallbackInfo expectCallback(CallbackState state, MockNetworkAgent agent, int timeoutMs) {
1555             final Network expectedNetwork = (agent != null) ? agent.getNetwork() : null;
1556             CallbackInfo expected = new CallbackInfo(state, expectedNetwork, 0);
1557             CallbackInfo actual = nextCallback(timeoutMs);
1558             assertEquals("Unexpected callback:", expected, actual);
1559 
1560             if (state == CallbackState.LOSING) {
1561                 String msg = String.format(
1562                         "Invalid linger time value %d, must be between %d and %d",
1563                         actual.arg, 0, TEST_LINGER_DELAY_MS);
1564                 int maxMsToLive = (Integer) actual.arg;
1565                 assertTrue(msg, 0 <= maxMsToLive && maxMsToLive <= TEST_LINGER_DELAY_MS);
1566             }
1567 
1568             return actual;
1569         }
1570 
expectCallback(CallbackState state, MockNetworkAgent agent)1571         CallbackInfo expectCallback(CallbackState state, MockNetworkAgent agent) {
1572             return expectCallback(state, agent, TIMEOUT_MS);
1573         }
1574 
expectCallbackLike(Predicate<CallbackInfo> fn)1575         CallbackInfo expectCallbackLike(Predicate<CallbackInfo> fn) {
1576             return expectCallbackLike(fn, TIMEOUT_MS);
1577         }
1578 
expectCallbackLike(Predicate<CallbackInfo> fn, int timeoutMs)1579         CallbackInfo expectCallbackLike(Predicate<CallbackInfo> fn, int timeoutMs) {
1580             int timeLeft = timeoutMs;
1581             while (timeLeft > 0) {
1582                 long start = SystemClock.elapsedRealtime();
1583                 CallbackInfo info = nextCallback(timeLeft);
1584                 if (fn.test(info)) {
1585                     return info;
1586                 }
1587                 timeLeft -= (SystemClock.elapsedRealtime() - start);
1588             }
1589             fail("Did not receive expected callback after " + timeoutMs + "ms");
1590             return null;
1591         }
1592 
1593         // Expects onAvailable and the callbacks that follow it. These are:
1594         // - onSuspended, iff the network was suspended when the callbacks fire.
1595         // - onCapabilitiesChanged.
1596         // - onLinkPropertiesChanged.
1597         //
1598         // @param agent the network to expect the callbacks on.
1599         // @param expectSuspended whether to expect a SUSPENDED callback.
1600         // @param expectValidated the expected value of the VALIDATED capability in the
1601         //        onCapabilitiesChanged callback.
1602         // @param timeoutMs how long to wait for the callbacks.
expectAvailableCallbacks(MockNetworkAgent agent, boolean expectSuspended, boolean expectValidated, int timeoutMs)1603         void expectAvailableCallbacks(MockNetworkAgent agent, boolean expectSuspended,
1604                 boolean expectValidated, int timeoutMs) {
1605             expectCallback(CallbackState.AVAILABLE, agent, timeoutMs);
1606             if (expectSuspended) {
1607                 expectCallback(CallbackState.SUSPENDED, agent, timeoutMs);
1608             }
1609             if (expectValidated) {
1610                 expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, agent, timeoutMs);
1611             } else {
1612                 expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, agent, timeoutMs);
1613             }
1614             expectCallback(CallbackState.LINK_PROPERTIES, agent, timeoutMs);
1615         }
1616 
1617         // Expects the available callbacks (validated), plus onSuspended.
expectAvailableAndSuspendedCallbacks(MockNetworkAgent agent, boolean expectValidated)1618         void expectAvailableAndSuspendedCallbacks(MockNetworkAgent agent, boolean expectValidated) {
1619             expectAvailableCallbacks(agent, true, expectValidated, TIMEOUT_MS);
1620         }
1621 
expectAvailableCallbacksValidated(MockNetworkAgent agent)1622         void expectAvailableCallbacksValidated(MockNetworkAgent agent) {
1623             expectAvailableCallbacks(agent, false, true, TIMEOUT_MS);
1624         }
1625 
expectAvailableCallbacksUnvalidated(MockNetworkAgent agent)1626         void expectAvailableCallbacksUnvalidated(MockNetworkAgent agent) {
1627             expectAvailableCallbacks(agent, false, false, TIMEOUT_MS);
1628         }
1629 
1630         // Expects the available callbacks (where the onCapabilitiesChanged must contain the
1631         // VALIDATED capability), plus another onCapabilitiesChanged which is identical to the
1632         // one we just sent.
1633         // TODO: this is likely a bug. Fix it and remove this method.
expectAvailableDoubleValidatedCallbacks(MockNetworkAgent agent)1634         void expectAvailableDoubleValidatedCallbacks(MockNetworkAgent agent) {
1635             expectCallback(CallbackState.AVAILABLE, agent, TIMEOUT_MS);
1636             NetworkCapabilities nc1 = expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, agent);
1637             expectCallback(CallbackState.LINK_PROPERTIES, agent, TIMEOUT_MS);
1638             NetworkCapabilities nc2 = expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, agent);
1639             assertEquals(nc1, nc2);
1640         }
1641 
1642         // Expects the available callbacks where the onCapabilitiesChanged must not have validated,
1643         // then expects another onCapabilitiesChanged that has the validated bit set. This is used
1644         // when a network connects and satisfies a callback, and then immediately validates.
expectAvailableThenValidatedCallbacks(MockNetworkAgent agent)1645         void expectAvailableThenValidatedCallbacks(MockNetworkAgent agent) {
1646             expectAvailableCallbacksUnvalidated(agent);
1647             expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, agent);
1648         }
1649 
expectCapabilitiesWith(int capability, MockNetworkAgent agent)1650         NetworkCapabilities expectCapabilitiesWith(int capability, MockNetworkAgent agent) {
1651             return expectCapabilitiesWith(capability, agent, TIMEOUT_MS);
1652         }
1653 
expectCapabilitiesWith(int capability, MockNetworkAgent agent, int timeoutMs)1654         NetworkCapabilities expectCapabilitiesWith(int capability, MockNetworkAgent agent,
1655                 int timeoutMs) {
1656             CallbackInfo cbi = expectCallback(CallbackState.NETWORK_CAPABILITIES, agent, timeoutMs);
1657             NetworkCapabilities nc = (NetworkCapabilities) cbi.arg;
1658             assertTrue(nc.hasCapability(capability));
1659             return nc;
1660         }
1661 
expectCapabilitiesWithout(int capability, MockNetworkAgent agent)1662         NetworkCapabilities expectCapabilitiesWithout(int capability, MockNetworkAgent agent) {
1663             return expectCapabilitiesWithout(capability, agent, TIMEOUT_MS);
1664         }
1665 
expectCapabilitiesWithout(int capability, MockNetworkAgent agent, int timeoutMs)1666         NetworkCapabilities expectCapabilitiesWithout(int capability, MockNetworkAgent agent,
1667                 int timeoutMs) {
1668             CallbackInfo cbi = expectCallback(CallbackState.NETWORK_CAPABILITIES, agent, timeoutMs);
1669             NetworkCapabilities nc = (NetworkCapabilities) cbi.arg;
1670             assertFalse(nc.hasCapability(capability));
1671             return nc;
1672         }
1673 
expectCapabilitiesLike(Predicate<NetworkCapabilities> fn, MockNetworkAgent agent)1674         void expectCapabilitiesLike(Predicate<NetworkCapabilities> fn, MockNetworkAgent agent) {
1675             CallbackInfo cbi = expectCallback(CallbackState.NETWORK_CAPABILITIES, agent);
1676             assertTrue("Received capabilities don't match expectations : " + cbi.arg,
1677                     fn.test((NetworkCapabilities) cbi.arg));
1678         }
1679 
assertNoCallback()1680         void assertNoCallback() {
1681             waitForIdle();
1682             CallbackInfo c = mCallbacks.peek();
1683             assertNull("Unexpected callback: " + c, c);
1684         }
1685     }
1686 
1687     // Can't be part of TestNetworkCallback because "cannot be declared static; static methods can
1688     // only be declared in a static or top level type".
assertNoCallbacks(TestNetworkCallback .... callbacks)1689     static void assertNoCallbacks(TestNetworkCallback ... callbacks) {
1690         for (TestNetworkCallback c : callbacks) {
1691             c.assertNoCallback();
1692         }
1693     }
1694 
1695     @Test
testStateChangeNetworkCallbacks()1696     public void testStateChangeNetworkCallbacks() throws Exception {
1697         final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback();
1698         final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
1699         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
1700         final NetworkRequest genericRequest = new NetworkRequest.Builder()
1701                 .clearCapabilities().build();
1702         final NetworkRequest wifiRequest = new NetworkRequest.Builder()
1703                 .addTransportType(TRANSPORT_WIFI).build();
1704         final NetworkRequest cellRequest = new NetworkRequest.Builder()
1705                 .addTransportType(TRANSPORT_CELLULAR).build();
1706         mCm.registerNetworkCallback(genericRequest, genericNetworkCallback);
1707         mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
1708         mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
1709 
1710         // Test unvalidated networks
1711         ConditionVariable cv = waitForConnectivityBroadcasts(1);
1712         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1713         mCellNetworkAgent.connect(false);
1714         genericNetworkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
1715         cellNetworkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
1716         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1717         waitFor(cv);
1718         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
1719 
1720         // This should not trigger spurious onAvailable() callbacks, b/21762680.
1721         mCellNetworkAgent.adjustScore(-1);
1722         waitForIdle();
1723         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
1724         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1725 
1726         cv = waitForConnectivityBroadcasts(2);
1727         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1728         mWiFiNetworkAgent.connect(false);
1729         genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
1730         wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
1731         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1732         waitFor(cv);
1733         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
1734 
1735         cv = waitForConnectivityBroadcasts(2);
1736         mWiFiNetworkAgent.disconnect();
1737         genericNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1738         wifiNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1739         cellNetworkCallback.assertNoCallback();
1740         waitFor(cv);
1741         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
1742 
1743         cv = waitForConnectivityBroadcasts(1);
1744         mCellNetworkAgent.disconnect();
1745         genericNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1746         cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1747         waitFor(cv);
1748         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
1749 
1750         // Test validated networks
1751         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1752         mCellNetworkAgent.connect(true);
1753         genericNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
1754         cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
1755         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1756         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
1757 
1758         // This should not trigger spurious onAvailable() callbacks, b/21762680.
1759         mCellNetworkAgent.adjustScore(-1);
1760         waitForIdle();
1761         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
1762         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1763 
1764         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1765         mWiFiNetworkAgent.connect(true);
1766         genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
1767         genericNetworkCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
1768         genericNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
1769         wifiNetworkCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
1770         cellNetworkCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
1771         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1772         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
1773 
1774         mWiFiNetworkAgent.disconnect();
1775         genericNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1776         wifiNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1777         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
1778 
1779         mCellNetworkAgent.disconnect();
1780         genericNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1781         cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1782         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
1783     }
1784 
1785     @Test
testMultipleLingering()1786     public void testMultipleLingering() {
1787         NetworkRequest request = new NetworkRequest.Builder()
1788                 .clearCapabilities().addCapability(NET_CAPABILITY_NOT_METERED)
1789                 .build();
1790         TestNetworkCallback callback = new TestNetworkCallback();
1791         mCm.registerNetworkCallback(request, callback);
1792 
1793         TestNetworkCallback defaultCallback = new TestNetworkCallback();
1794         mCm.registerDefaultNetworkCallback(defaultCallback);
1795 
1796         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1797         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1798         mEthernetNetworkAgent = new MockNetworkAgent(TRANSPORT_ETHERNET);
1799 
1800         mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
1801         mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
1802         mEthernetNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
1803 
1804         mCellNetworkAgent.connect(true);
1805         callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
1806         defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
1807         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1808         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
1809 
1810         mWiFiNetworkAgent.connect(true);
1811         // We get AVAILABLE on wifi when wifi connects and satisfies our unmetered request.
1812         // We then get LOSING when wifi validates and cell is outscored.
1813         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
1814         // TODO: Investigate sending validated before losing.
1815         callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
1816         callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
1817         defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
1818         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1819         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
1820 
1821         mEthernetNetworkAgent.connect(true);
1822         callback.expectAvailableCallbacksUnvalidated(mEthernetNetworkAgent);
1823         // TODO: Investigate sending validated before losing.
1824         callback.expectCallback(CallbackState.LOSING, mWiFiNetworkAgent);
1825         callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mEthernetNetworkAgent);
1826         defaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent);
1827         assertEquals(mEthernetNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1828         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
1829 
1830         mEthernetNetworkAgent.disconnect();
1831         callback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
1832         defaultCallback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
1833         defaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
1834         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
1835 
1836         for (int i = 0; i < 4; i++) {
1837             MockNetworkAgent oldNetwork, newNetwork;
1838             if (i % 2 == 0) {
1839                 mWiFiNetworkAgent.adjustScore(-15);
1840                 oldNetwork = mWiFiNetworkAgent;
1841                 newNetwork = mCellNetworkAgent;
1842             } else {
1843                 mWiFiNetworkAgent.adjustScore(15);
1844                 oldNetwork = mCellNetworkAgent;
1845                 newNetwork = mWiFiNetworkAgent;
1846 
1847             }
1848             callback.expectCallback(CallbackState.LOSING, oldNetwork);
1849             // TODO: should we send an AVAILABLE callback to newNetwork, to indicate that it is no
1850             // longer lingering?
1851             defaultCallback.expectAvailableCallbacksValidated(newNetwork);
1852             assertEquals(newNetwork.getNetwork(), mCm.getActiveNetwork());
1853         }
1854         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1855 
1856         // Verify that if a network no longer satisfies a request, we send LOST and not LOSING, even
1857         // if the network is still up.
1858         mWiFiNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
1859         // We expect a notification about the capabilities change, and nothing else.
1860         defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_METERED, mWiFiNetworkAgent);
1861         defaultCallback.assertNoCallback();
1862         callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1863         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
1864 
1865         // Wifi no longer satisfies our listen, which is for an unmetered network.
1866         // But because its score is 55, it's still up (and the default network).
1867         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1868 
1869         // Disconnect our test networks.
1870         mWiFiNetworkAgent.disconnect();
1871         defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1872         defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
1873         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
1874         mCellNetworkAgent.disconnect();
1875         defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1876         waitForIdle();
1877         assertEquals(null, mCm.getActiveNetwork());
1878 
1879         mCm.unregisterNetworkCallback(callback);
1880         waitForIdle();
1881 
1882         // Check that a network is only lingered or torn down if it would not satisfy a request even
1883         // if it validated.
1884         request = new NetworkRequest.Builder().clearCapabilities().build();
1885         callback = new TestNetworkCallback();
1886 
1887         mCm.registerNetworkCallback(request, callback);
1888 
1889         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1890         mCellNetworkAgent.connect(false);   // Score: 10
1891         callback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
1892         defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
1893         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1894         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
1895 
1896         // Bring up wifi with a score of 20.
1897         // Cell stays up because it would satisfy the default request if it validated.
1898         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1899         mWiFiNetworkAgent.connect(false);   // Score: 20
1900         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
1901         defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
1902         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1903         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
1904 
1905         mWiFiNetworkAgent.disconnect();
1906         callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1907         defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1908         defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
1909         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1910         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
1911 
1912         // Bring up wifi with a score of 70.
1913         // Cell is lingered because it would not satisfy any request, even if it validated.
1914         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1915         mWiFiNetworkAgent.adjustScore(50);
1916         mWiFiNetworkAgent.connect(false);   // Score: 70
1917         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
1918         callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
1919         defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
1920         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1921         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
1922 
1923         // Tear down wifi.
1924         mWiFiNetworkAgent.disconnect();
1925         callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1926         defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1927         defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
1928         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1929         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
1930 
1931         // Bring up wifi, then validate it. Previous versions would immediately tear down cell, but
1932         // it's arguably correct to linger it, since it was the default network before it validated.
1933         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1934         mWiFiNetworkAgent.connect(true);
1935         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
1936         // TODO: Investigate sending validated before losing.
1937         callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
1938         callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
1939         defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
1940         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1941         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
1942 
1943         mWiFiNetworkAgent.disconnect();
1944         callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1945         defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1946         defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
1947         mCellNetworkAgent.disconnect();
1948         callback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1949         defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1950         waitForIdle();
1951         assertEquals(null, mCm.getActiveNetwork());
1952 
1953         // If a network is lingering, and we add and remove a request from it, resume lingering.
1954         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1955         mCellNetworkAgent.connect(true);
1956         callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
1957         defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
1958         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
1959         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1960         mWiFiNetworkAgent.connect(true);
1961         defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
1962         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
1963         // TODO: Investigate sending validated before losing.
1964         callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
1965         callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
1966         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
1967 
1968         NetworkRequest cellRequest = new NetworkRequest.Builder()
1969                 .addTransportType(TRANSPORT_CELLULAR).build();
1970         NetworkCallback noopCallback = new NetworkCallback();
1971         mCm.requestNetwork(cellRequest, noopCallback);
1972         // TODO: should this cause an AVAILABLE callback, to indicate that the network is no longer
1973         // lingering?
1974         mCm.unregisterNetworkCallback(noopCallback);
1975         callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
1976 
1977         // Similar to the above: lingering can start even after the lingered request is removed.
1978         // Disconnect wifi and switch to cell.
1979         mWiFiNetworkAgent.disconnect();
1980         callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1981         defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1982         defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
1983         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
1984 
1985         // Cell is now the default network. Pin it with a cell-specific request.
1986         noopCallback = new NetworkCallback();  // Can't reuse NetworkCallbacks. http://b/20701525
1987         mCm.requestNetwork(cellRequest, noopCallback);
1988 
1989         // Now connect wifi, and expect it to become the default network.
1990         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1991         mWiFiNetworkAgent.connect(true);
1992         callback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
1993         defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
1994         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
1995         // The default request is lingering on cell, but nothing happens to cell, and we send no
1996         // callbacks for it, because it's kept up by cellRequest.
1997         callback.assertNoCallback();
1998         // Now unregister cellRequest and expect cell to start lingering.
1999         mCm.unregisterNetworkCallback(noopCallback);
2000         callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
2001 
2002         // Let linger run its course.
2003         callback.assertNoCallback();
2004         final int lingerTimeoutMs = TEST_LINGER_DELAY_MS + TEST_LINGER_DELAY_MS / 4;
2005         callback.expectCallback(CallbackState.LOST, mCellNetworkAgent, lingerTimeoutMs);
2006 
2007         // Register a TRACK_DEFAULT request and check that it does not affect lingering.
2008         TestNetworkCallback trackDefaultCallback = new TestNetworkCallback();
2009         mCm.registerDefaultNetworkCallback(trackDefaultCallback);
2010         trackDefaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
2011         mEthernetNetworkAgent = new MockNetworkAgent(TRANSPORT_ETHERNET);
2012         mEthernetNetworkAgent.connect(true);
2013         callback.expectAvailableCallbacksUnvalidated(mEthernetNetworkAgent);
2014         callback.expectCallback(CallbackState.LOSING, mWiFiNetworkAgent);
2015         callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mEthernetNetworkAgent);
2016         trackDefaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent);
2017         defaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent);
2018         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
2019 
2020         // Let linger run its course.
2021         callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent, lingerTimeoutMs);
2022 
2023         // Clean up.
2024         mEthernetNetworkAgent.disconnect();
2025         callback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
2026         defaultCallback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
2027         trackDefaultCallback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
2028 
2029         mCm.unregisterNetworkCallback(callback);
2030         mCm.unregisterNetworkCallback(defaultCallback);
2031         mCm.unregisterNetworkCallback(trackDefaultCallback);
2032     }
2033 
2034     @Test
testNetworkGoesIntoBackgroundAfterLinger()2035     public void testNetworkGoesIntoBackgroundAfterLinger() {
2036         setMobileDataAlwaysOn(true);
2037         NetworkRequest request = new NetworkRequest.Builder()
2038                 .clearCapabilities()
2039                 .build();
2040         TestNetworkCallback callback = new TestNetworkCallback();
2041         mCm.registerNetworkCallback(request, callback);
2042 
2043         TestNetworkCallback defaultCallback = new TestNetworkCallback();
2044         mCm.registerDefaultNetworkCallback(defaultCallback);
2045 
2046         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2047         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2048 
2049         mCellNetworkAgent.connect(true);
2050         callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2051         defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2052 
2053         // Wifi comes up and cell lingers.
2054         mWiFiNetworkAgent.connect(true);
2055         defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
2056         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2057         callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
2058         callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
2059 
2060         // File a request for cellular, then release it.
2061         NetworkRequest cellRequest = new NetworkRequest.Builder()
2062                 .addTransportType(TRANSPORT_CELLULAR).build();
2063         NetworkCallback noopCallback = new NetworkCallback();
2064         mCm.requestNetwork(cellRequest, noopCallback);
2065         mCm.unregisterNetworkCallback(noopCallback);
2066         callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
2067 
2068         // Let linger run its course.
2069         callback.assertNoCallback();
2070         final int lingerTimeoutMs = TEST_LINGER_DELAY_MS + TEST_LINGER_DELAY_MS / 4;
2071         callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent,
2072                 lingerTimeoutMs);
2073 
2074         // Clean up.
2075         mCm.unregisterNetworkCallback(defaultCallback);
2076         mCm.unregisterNetworkCallback(callback);
2077     }
2078 
2079     @Test
testExplicitlySelected()2080     public void testExplicitlySelected() {
2081         NetworkRequest request = new NetworkRequest.Builder()
2082                 .clearCapabilities().addCapability(NET_CAPABILITY_INTERNET)
2083                 .build();
2084         TestNetworkCallback callback = new TestNetworkCallback();
2085         mCm.registerNetworkCallback(request, callback);
2086 
2087         // Bring up validated cell.
2088         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2089         mCellNetworkAgent.connect(true);
2090         callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2091 
2092         // Bring up unvalidated wifi with explicitlySelected=true.
2093         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2094         mWiFiNetworkAgent.explicitlySelected(false);
2095         mWiFiNetworkAgent.connect(false);
2096         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2097 
2098         // Cell Remains the default.
2099         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2100 
2101         // Lower wifi's score to below than cell, and check that it doesn't disconnect because
2102         // it's explicitly selected.
2103         mWiFiNetworkAgent.adjustScore(-40);
2104         mWiFiNetworkAgent.adjustScore(40);
2105         callback.assertNoCallback();
2106 
2107         // If the user chooses yes on the "No Internet access, stay connected?" dialog, we switch to
2108         // wifi even though it's unvalidated.
2109         mCm.setAcceptUnvalidated(mWiFiNetworkAgent.getNetwork(), true, false);
2110         callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
2111         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2112 
2113         // Disconnect wifi, and then reconnect, again with explicitlySelected=true.
2114         mWiFiNetworkAgent.disconnect();
2115         callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2116         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2117         mWiFiNetworkAgent.explicitlySelected(false);
2118         mWiFiNetworkAgent.connect(false);
2119         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2120 
2121         // If the user chooses no on the "No Internet access, stay connected?" dialog, we ask the
2122         // network to disconnect.
2123         mCm.setAcceptUnvalidated(mWiFiNetworkAgent.getNetwork(), false, false);
2124         callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2125 
2126         // Reconnect, again with explicitlySelected=true, but this time validate.
2127         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2128         mWiFiNetworkAgent.explicitlySelected(false);
2129         mWiFiNetworkAgent.connect(true);
2130         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2131         callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
2132         callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
2133         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2134 
2135         // BUG: the network will no longer linger, even though it's validated and outscored.
2136         // TODO: fix this.
2137         mEthernetNetworkAgent = new MockNetworkAgent(TRANSPORT_ETHERNET);
2138         mEthernetNetworkAgent.connect(true);
2139         callback.expectAvailableThenValidatedCallbacks(mEthernetNetworkAgent);
2140         assertEquals(mEthernetNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2141         callback.assertNoCallback();
2142 
2143         // Clean up.
2144         mWiFiNetworkAgent.disconnect();
2145         mCellNetworkAgent.disconnect();
2146         mEthernetNetworkAgent.disconnect();
2147 
2148         callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2149         callback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
2150         callback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
2151     }
2152 
tryNetworkFactoryRequests(int capability)2153     private void tryNetworkFactoryRequests(int capability) throws Exception {
2154         // Verify NOT_RESTRICTED is set appropriately
2155         final NetworkCapabilities nc = new NetworkRequest.Builder().addCapability(capability)
2156                 .build().networkCapabilities;
2157         if (capability == NET_CAPABILITY_CBS || capability == NET_CAPABILITY_DUN ||
2158                 capability == NET_CAPABILITY_EIMS || capability == NET_CAPABILITY_FOTA ||
2159                 capability == NET_CAPABILITY_IA || capability == NET_CAPABILITY_IMS ||
2160                 capability == NET_CAPABILITY_RCS || capability == NET_CAPABILITY_XCAP) {
2161             assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
2162         } else {
2163             assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
2164         }
2165 
2166         NetworkCapabilities filter = new NetworkCapabilities();
2167         filter.addCapability(capability);
2168         final HandlerThread handlerThread = new HandlerThread("testNetworkFactoryRequests");
2169         handlerThread.start();
2170         final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
2171                 mServiceContext, "testFactory", filter);
2172         testFactory.setScoreFilter(40);
2173         ConditionVariable cv = testFactory.getNetworkStartedCV();
2174         testFactory.expectAddRequests(1);
2175         testFactory.register();
2176         testFactory.waitForNetworkRequests(1);
2177         int expectedRequestCount = 1;
2178         NetworkCallback networkCallback = null;
2179         // For non-INTERNET capabilities we cannot rely on the default request being present, so
2180         // add one.
2181         if (capability != NET_CAPABILITY_INTERNET) {
2182             assertFalse(testFactory.getMyStartRequested());
2183             NetworkRequest request = new NetworkRequest.Builder().addCapability(capability).build();
2184             networkCallback = new NetworkCallback();
2185             testFactory.expectAddRequests(1);
2186             mCm.requestNetwork(request, networkCallback);
2187             expectedRequestCount++;
2188             testFactory.waitForNetworkRequests(expectedRequestCount);
2189         }
2190         waitFor(cv);
2191         assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
2192         assertTrue(testFactory.getMyStartRequested());
2193 
2194         // Now bring in a higher scored network.
2195         MockNetworkAgent testAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2196         // Rather than create a validated network which complicates things by registering it's
2197         // own NetworkRequest during startup, just bump up the score to cancel out the
2198         // unvalidated penalty.
2199         testAgent.adjustScore(40);
2200         cv = testFactory.getNetworkStoppedCV();
2201 
2202         // When testAgent connects, ConnectivityService will re-send us all current requests with
2203         // the new score. There are expectedRequestCount such requests, and we must wait for all of
2204         // them.
2205         testFactory.expectAddRequests(expectedRequestCount);
2206         testAgent.connect(false);
2207         testAgent.addCapability(capability);
2208         waitFor(cv);
2209         testFactory.waitForNetworkRequests(expectedRequestCount);
2210         assertFalse(testFactory.getMyStartRequested());
2211 
2212         // Bring in a bunch of requests.
2213         testFactory.expectAddRequests(10);
2214         assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
2215         ConnectivityManager.NetworkCallback[] networkCallbacks =
2216                 new ConnectivityManager.NetworkCallback[10];
2217         for (int i = 0; i< networkCallbacks.length; i++) {
2218             networkCallbacks[i] = new ConnectivityManager.NetworkCallback();
2219             NetworkRequest.Builder builder = new NetworkRequest.Builder();
2220             builder.addCapability(capability);
2221             mCm.requestNetwork(builder.build(), networkCallbacks[i]);
2222         }
2223         testFactory.waitForNetworkRequests(10 + expectedRequestCount);
2224         assertFalse(testFactory.getMyStartRequested());
2225 
2226         // Remove the requests.
2227         testFactory.expectRemoveRequests(10);
2228         for (int i = 0; i < networkCallbacks.length; i++) {
2229             mCm.unregisterNetworkCallback(networkCallbacks[i]);
2230         }
2231         testFactory.waitForNetworkRequests(expectedRequestCount);
2232         assertFalse(testFactory.getMyStartRequested());
2233 
2234         // Drop the higher scored network.
2235         cv = testFactory.getNetworkStartedCV();
2236         testAgent.disconnect();
2237         waitFor(cv);
2238         assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
2239         assertTrue(testFactory.getMyStartRequested());
2240 
2241         testFactory.unregister();
2242         if (networkCallback != null) mCm.unregisterNetworkCallback(networkCallback);
2243         handlerThread.quit();
2244     }
2245 
2246     @Test
testNetworkFactoryRequests()2247     public void testNetworkFactoryRequests() throws Exception {
2248         tryNetworkFactoryRequests(NET_CAPABILITY_MMS);
2249         tryNetworkFactoryRequests(NET_CAPABILITY_SUPL);
2250         tryNetworkFactoryRequests(NET_CAPABILITY_DUN);
2251         tryNetworkFactoryRequests(NET_CAPABILITY_FOTA);
2252         tryNetworkFactoryRequests(NET_CAPABILITY_IMS);
2253         tryNetworkFactoryRequests(NET_CAPABILITY_CBS);
2254         tryNetworkFactoryRequests(NET_CAPABILITY_WIFI_P2P);
2255         tryNetworkFactoryRequests(NET_CAPABILITY_IA);
2256         tryNetworkFactoryRequests(NET_CAPABILITY_RCS);
2257         tryNetworkFactoryRequests(NET_CAPABILITY_XCAP);
2258         tryNetworkFactoryRequests(NET_CAPABILITY_EIMS);
2259         tryNetworkFactoryRequests(NET_CAPABILITY_NOT_METERED);
2260         tryNetworkFactoryRequests(NET_CAPABILITY_INTERNET);
2261         tryNetworkFactoryRequests(NET_CAPABILITY_TRUSTED);
2262         tryNetworkFactoryRequests(NET_CAPABILITY_NOT_VPN);
2263         // Skipping VALIDATED and CAPTIVE_PORTAL as they're disallowed.
2264     }
2265 
2266     @Test
testNoMutableNetworkRequests()2267     public void testNoMutableNetworkRequests() throws Exception {
2268         PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, new Intent("a"), 0);
2269         NetworkRequest request1 = new NetworkRequest.Builder()
2270                 .addCapability(NET_CAPABILITY_VALIDATED)
2271                 .build();
2272         NetworkRequest request2 = new NetworkRequest.Builder()
2273                 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL)
2274                 .build();
2275 
2276         Class<IllegalArgumentException> expected = IllegalArgumentException.class;
2277         assertException(() -> { mCm.requestNetwork(request1, new NetworkCallback()); }, expected);
2278         assertException(() -> { mCm.requestNetwork(request1, pendingIntent); }, expected);
2279         assertException(() -> { mCm.requestNetwork(request2, new NetworkCallback()); }, expected);
2280         assertException(() -> { mCm.requestNetwork(request2, pendingIntent); }, expected);
2281     }
2282 
2283     @Test
testMMSonWiFi()2284     public void testMMSonWiFi() throws Exception {
2285         // Test bringing up cellular without MMS NetworkRequest gets reaped
2286         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2287         mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS);
2288         ConditionVariable cv = mCellNetworkAgent.getDisconnectedCV();
2289         mCellNetworkAgent.connectWithoutInternet();
2290         waitFor(cv);
2291         waitForIdle();
2292         assertEmpty(mCm.getAllNetworks());
2293         verifyNoNetwork();
2294 
2295         // Test bringing up validated WiFi.
2296         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2297         cv = waitForConnectivityBroadcasts(1);
2298         mWiFiNetworkAgent.connect(true);
2299         waitFor(cv);
2300         verifyActiveNetwork(TRANSPORT_WIFI);
2301 
2302         // Register MMS NetworkRequest
2303         NetworkRequest.Builder builder = new NetworkRequest.Builder();
2304         builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
2305         final TestNetworkCallback networkCallback = new TestNetworkCallback();
2306         mCm.requestNetwork(builder.build(), networkCallback);
2307 
2308         // Test bringing up unvalidated cellular with MMS
2309         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2310         mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS);
2311         mCellNetworkAgent.connectWithoutInternet();
2312         networkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
2313         verifyActiveNetwork(TRANSPORT_WIFI);
2314 
2315         // Test releasing NetworkRequest disconnects cellular with MMS
2316         cv = mCellNetworkAgent.getDisconnectedCV();
2317         mCm.unregisterNetworkCallback(networkCallback);
2318         waitFor(cv);
2319         verifyActiveNetwork(TRANSPORT_WIFI);
2320     }
2321 
2322     @Test
testMMSonCell()2323     public void testMMSonCell() throws Exception {
2324         // Test bringing up cellular without MMS
2325         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2326         ConditionVariable cv = waitForConnectivityBroadcasts(1);
2327         mCellNetworkAgent.connect(false);
2328         waitFor(cv);
2329         verifyActiveNetwork(TRANSPORT_CELLULAR);
2330 
2331         // Register MMS NetworkRequest
2332         NetworkRequest.Builder builder = new NetworkRequest.Builder();
2333         builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
2334         final TestNetworkCallback networkCallback = new TestNetworkCallback();
2335         mCm.requestNetwork(builder.build(), networkCallback);
2336 
2337         // Test bringing up MMS cellular network
2338         MockNetworkAgent mmsNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2339         mmsNetworkAgent.addCapability(NET_CAPABILITY_MMS);
2340         mmsNetworkAgent.connectWithoutInternet();
2341         networkCallback.expectAvailableCallbacksUnvalidated(mmsNetworkAgent);
2342         verifyActiveNetwork(TRANSPORT_CELLULAR);
2343 
2344         // Test releasing MMS NetworkRequest does not disconnect main cellular NetworkAgent
2345         cv = mmsNetworkAgent.getDisconnectedCV();
2346         mCm.unregisterNetworkCallback(networkCallback);
2347         waitFor(cv);
2348         verifyActiveNetwork(TRANSPORT_CELLULAR);
2349     }
2350 
2351     @Test
testCaptivePortal()2352     public void testCaptivePortal() {
2353         final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
2354         final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
2355                 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
2356         mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
2357 
2358         final TestNetworkCallback validatedCallback = new TestNetworkCallback();
2359         final NetworkRequest validatedRequest = new NetworkRequest.Builder()
2360                 .addCapability(NET_CAPABILITY_VALIDATED).build();
2361         mCm.registerNetworkCallback(validatedRequest, validatedCallback);
2362 
2363         // Bring up a network with a captive portal.
2364         // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
2365         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2366         String firstRedirectUrl = "http://example.com/firstPath";
2367         mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl);
2368         captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2369         assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), firstRedirectUrl);
2370 
2371         // Take down network.
2372         // Expect onLost callback.
2373         mWiFiNetworkAgent.disconnect();
2374         captivePortalCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2375 
2376         // Bring up a network with a captive portal.
2377         // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
2378         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2379         String secondRedirectUrl = "http://example.com/secondPath";
2380         mWiFiNetworkAgent.connectWithCaptivePortal(secondRedirectUrl);
2381         captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2382         assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), secondRedirectUrl);
2383 
2384         // Make captive portal disappear then revalidate.
2385         // Expect onLost callback because network no longer provides NET_CAPABILITY_CAPTIVE_PORTAL.
2386         mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 204;
2387         mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
2388         captivePortalCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2389 
2390         // Expect NET_CAPABILITY_VALIDATED onAvailable callback.
2391         validatedCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
2392 
2393         // Break network connectivity.
2394         // Expect NET_CAPABILITY_VALIDATED onLost callback.
2395         mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 500;
2396         mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), false);
2397         validatedCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2398     }
2399 
2400     @Test
testCaptivePortalApp()2401     public void testCaptivePortalApp() {
2402         final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
2403         final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
2404                 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
2405         mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
2406 
2407         final TestNetworkCallback validatedCallback = new TestNetworkCallback();
2408         final NetworkRequest validatedRequest = new NetworkRequest.Builder()
2409                 .addCapability(NET_CAPABILITY_VALIDATED).build();
2410         mCm.registerNetworkCallback(validatedRequest, validatedCallback);
2411 
2412         // Bring up wifi.
2413         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2414         mWiFiNetworkAgent.connect(true);
2415         validatedCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
2416         Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
2417 
2418         // Check that calling startCaptivePortalApp does nothing.
2419         final int fastTimeoutMs = 100;
2420         mCm.startCaptivePortalApp(wifiNetwork);
2421         mServiceContext.expectNoStartActivityIntent(fastTimeoutMs);
2422 
2423         // Turn into a captive portal.
2424         mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 302;
2425         mCm.reportNetworkConnectivity(wifiNetwork, false);
2426         captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2427         validatedCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2428 
2429         // Check that startCaptivePortalApp sends the expected intent.
2430         mCm.startCaptivePortalApp(wifiNetwork);
2431         Intent intent = mServiceContext.expectStartActivityIntent(TIMEOUT_MS);
2432         assertEquals(ConnectivityManager.ACTION_CAPTIVE_PORTAL_SIGN_IN, intent.getAction());
2433         assertEquals(wifiNetwork, intent.getExtra(ConnectivityManager.EXTRA_NETWORK));
2434 
2435         // Have the app report that the captive portal is dismissed, and check that we revalidate.
2436         mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 204;
2437         CaptivePortal c = (CaptivePortal) intent.getExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL);
2438         c.reportCaptivePortalDismissed();
2439         validatedCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
2440         captivePortalCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2441 
2442         mCm.unregisterNetworkCallback(validatedCallback);
2443         mCm.unregisterNetworkCallback(captivePortalCallback);
2444     }
2445 
2446     @Test
testAvoidOrIgnoreCaptivePortals()2447     public void testAvoidOrIgnoreCaptivePortals() {
2448         final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
2449         final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
2450                 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
2451         mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
2452 
2453         final TestNetworkCallback validatedCallback = new TestNetworkCallback();
2454         final NetworkRequest validatedRequest = new NetworkRequest.Builder()
2455                 .addCapability(NET_CAPABILITY_VALIDATED).build();
2456         mCm.registerNetworkCallback(validatedRequest, validatedCallback);
2457 
2458         setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_AVOID);
2459         // Bring up a network with a captive portal.
2460         // Expect it to fail to connect and not result in any callbacks.
2461         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2462         String firstRedirectUrl = "http://example.com/firstPath";
2463 
2464         ConditionVariable disconnectCv = mWiFiNetworkAgent.getDisconnectedCV();
2465         ConditionVariable avoidCv = mWiFiNetworkAgent.getPreventReconnectReceived();
2466         mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl);
2467         waitFor(disconnectCv);
2468         waitFor(avoidCv);
2469 
2470         assertNoCallbacks(captivePortalCallback, validatedCallback);
2471 
2472         // Now test ignore mode.
2473         setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_IGNORE);
2474 
2475         // Bring up a network with a captive portal.
2476         // Since we're ignoring captive portals, the network will validate.
2477         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2478         String secondRedirectUrl = "http://example.com/secondPath";
2479         mWiFiNetworkAgent.connectWithCaptivePortal(secondRedirectUrl);
2480 
2481         // Expect NET_CAPABILITY_VALIDATED onAvailable callback.
2482         validatedCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
2483         // But there should be no CaptivePortal callback.
2484         captivePortalCallback.assertNoCallback();
2485     }
2486 
newWifiRequestBuilder()2487     private NetworkRequest.Builder newWifiRequestBuilder() {
2488         return new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI);
2489     }
2490 
2491     @Test
testNetworkSpecifier()2492     public void testNetworkSpecifier() {
2493         NetworkRequest rEmpty1 = newWifiRequestBuilder().build();
2494         NetworkRequest rEmpty2 = newWifiRequestBuilder().setNetworkSpecifier((String) null).build();
2495         NetworkRequest rEmpty3 = newWifiRequestBuilder().setNetworkSpecifier("").build();
2496         NetworkRequest rEmpty4 = newWifiRequestBuilder().setNetworkSpecifier(
2497             (NetworkSpecifier) null).build();
2498         NetworkRequest rFoo = newWifiRequestBuilder().setNetworkSpecifier("foo").build();
2499         NetworkRequest rBar = newWifiRequestBuilder().setNetworkSpecifier(
2500                 new StringNetworkSpecifier("bar")).build();
2501 
2502         TestNetworkCallback cEmpty1 = new TestNetworkCallback();
2503         TestNetworkCallback cEmpty2 = new TestNetworkCallback();
2504         TestNetworkCallback cEmpty3 = new TestNetworkCallback();
2505         TestNetworkCallback cEmpty4 = new TestNetworkCallback();
2506         TestNetworkCallback cFoo = new TestNetworkCallback();
2507         TestNetworkCallback cBar = new TestNetworkCallback();
2508         TestNetworkCallback[] emptyCallbacks = new TestNetworkCallback[] {
2509                 cEmpty1, cEmpty2, cEmpty3 };
2510 
2511         mCm.registerNetworkCallback(rEmpty1, cEmpty1);
2512         mCm.registerNetworkCallback(rEmpty2, cEmpty2);
2513         mCm.registerNetworkCallback(rEmpty3, cEmpty3);
2514         mCm.registerNetworkCallback(rEmpty4, cEmpty4);
2515         mCm.registerNetworkCallback(rFoo, cFoo);
2516         mCm.registerNetworkCallback(rBar, cBar);
2517 
2518         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2519         mWiFiNetworkAgent.connect(false);
2520         cEmpty1.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2521         cEmpty2.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2522         cEmpty3.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2523         cEmpty4.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2524         assertNoCallbacks(cFoo, cBar);
2525 
2526         mWiFiNetworkAgent.setNetworkSpecifier(new StringNetworkSpecifier("foo"));
2527         cFoo.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2528         for (TestNetworkCallback c: emptyCallbacks) {
2529             c.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent);
2530         }
2531         cFoo.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent);
2532         cFoo.assertNoCallback();
2533 
2534         mWiFiNetworkAgent.setNetworkSpecifier(new StringNetworkSpecifier("bar"));
2535         cFoo.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2536         cBar.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2537         for (TestNetworkCallback c: emptyCallbacks) {
2538             c.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent);
2539         }
2540         cBar.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent);
2541         cBar.assertNoCallback();
2542 
2543         mWiFiNetworkAgent.setNetworkSpecifier(null);
2544         cBar.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2545         for (TestNetworkCallback c: emptyCallbacks) {
2546             c.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent);
2547         }
2548 
2549         assertNoCallbacks(cEmpty1, cEmpty2, cEmpty3, cFoo, cBar);
2550     }
2551 
2552     @Test
testInvalidNetworkSpecifier()2553     public void testInvalidNetworkSpecifier() {
2554         try {
2555             NetworkRequest.Builder builder = new NetworkRequest.Builder();
2556             builder.setNetworkSpecifier(new MatchAllNetworkSpecifier());
2557             fail("NetworkRequest builder with MatchAllNetworkSpecifier");
2558         } catch (IllegalArgumentException expected) {
2559             // expected
2560         }
2561 
2562         try {
2563             NetworkCapabilities networkCapabilities = new NetworkCapabilities();
2564             networkCapabilities.addTransportType(TRANSPORT_WIFI)
2565                     .setNetworkSpecifier(new MatchAllNetworkSpecifier());
2566             mService.requestNetwork(networkCapabilities, null, 0, null,
2567                     ConnectivityManager.TYPE_WIFI);
2568             fail("ConnectivityService requestNetwork with MatchAllNetworkSpecifier");
2569         } catch (IllegalArgumentException expected) {
2570             // expected
2571         }
2572 
2573         class NonParcelableSpecifier extends NetworkSpecifier {
2574             public boolean satisfiedBy(NetworkSpecifier other) { return false; }
2575         };
2576         class ParcelableSpecifier extends NonParcelableSpecifier implements Parcelable {
2577             @Override public int describeContents() { return 0; }
2578             @Override public void writeToParcel(Parcel p, int flags) {}
2579         }
2580         NetworkRequest.Builder builder;
2581 
2582         builder = new NetworkRequest.Builder().addTransportType(TRANSPORT_ETHERNET);
2583         try {
2584             builder.setNetworkSpecifier(new NonParcelableSpecifier());
2585             Parcel parcelW = Parcel.obtain();
2586             builder.build().writeToParcel(parcelW, 0);
2587             fail("Parceling a non-parcelable specifier did not throw an exception");
2588         } catch (Exception e) {
2589             // expected
2590         }
2591 
2592         builder = new NetworkRequest.Builder().addTransportType(TRANSPORT_ETHERNET);
2593         builder.setNetworkSpecifier(new ParcelableSpecifier());
2594         NetworkRequest nr = builder.build();
2595         assertNotNull(nr);
2596 
2597         try {
2598             Parcel parcelW = Parcel.obtain();
2599             nr.writeToParcel(parcelW, 0);
2600             byte[] bytes = parcelW.marshall();
2601             parcelW.recycle();
2602 
2603             Parcel parcelR = Parcel.obtain();
2604             parcelR.unmarshall(bytes, 0, bytes.length);
2605             parcelR.setDataPosition(0);
2606             NetworkRequest rereadNr = NetworkRequest.CREATOR.createFromParcel(parcelR);
2607             fail("Unparceling a non-framework NetworkSpecifier did not throw an exception");
2608         } catch (Exception e) {
2609             // expected
2610         }
2611     }
2612 
2613     @Test
testNetworkSpecifierUidSpoofSecurityException()2614     public void testNetworkSpecifierUidSpoofSecurityException() {
2615         class UidAwareNetworkSpecifier extends NetworkSpecifier implements Parcelable {
2616             @Override
2617             public boolean satisfiedBy(NetworkSpecifier other) {
2618                 return true;
2619             }
2620 
2621             @Override
2622             public void assertValidFromUid(int requestorUid) {
2623                 throw new SecurityException("failure");
2624             }
2625 
2626             @Override
2627             public int describeContents() { return 0; }
2628             @Override
2629             public void writeToParcel(Parcel dest, int flags) {}
2630         }
2631 
2632         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2633         mWiFiNetworkAgent.connect(false);
2634 
2635         UidAwareNetworkSpecifier networkSpecifier = new UidAwareNetworkSpecifier();
2636         NetworkRequest networkRequest = newWifiRequestBuilder().setNetworkSpecifier(
2637                 networkSpecifier).build();
2638         TestNetworkCallback networkCallback = new TestNetworkCallback();
2639         try {
2640             mCm.requestNetwork(networkRequest, networkCallback);
2641             fail("Network request with spoofed UID did not throw a SecurityException");
2642         } catch (SecurityException e) {
2643             // expected
2644         }
2645     }
2646 
2647     @Test
testRegisterDefaultNetworkCallback()2648     public void testRegisterDefaultNetworkCallback() throws Exception {
2649         final TestNetworkCallback defaultNetworkCallback = new TestNetworkCallback();
2650         mCm.registerDefaultNetworkCallback(defaultNetworkCallback);
2651         defaultNetworkCallback.assertNoCallback();
2652 
2653         // Create a TRANSPORT_CELLULAR request to keep the mobile interface up
2654         // whenever Wi-Fi is up. Without this, the mobile network agent is
2655         // reaped before any other activity can take place.
2656         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
2657         final NetworkRequest cellRequest = new NetworkRequest.Builder()
2658                 .addTransportType(TRANSPORT_CELLULAR).build();
2659         mCm.requestNetwork(cellRequest, cellNetworkCallback);
2660         cellNetworkCallback.assertNoCallback();
2661 
2662         // Bring up cell and expect CALLBACK_AVAILABLE.
2663         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2664         mCellNetworkAgent.connect(true);
2665         cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2666         defaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2667         assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
2668 
2669         // Bring up wifi and expect CALLBACK_AVAILABLE.
2670         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2671         mWiFiNetworkAgent.connect(true);
2672         cellNetworkCallback.assertNoCallback();
2673         defaultNetworkCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
2674         assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
2675 
2676         // Bring down cell. Expect no default network callback, since it wasn't the default.
2677         mCellNetworkAgent.disconnect();
2678         cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
2679         defaultNetworkCallback.assertNoCallback();
2680         assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
2681 
2682         // Bring up cell. Expect no default network callback, since it won't be the default.
2683         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2684         mCellNetworkAgent.connect(true);
2685         cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2686         defaultNetworkCallback.assertNoCallback();
2687         assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
2688 
2689         // Bring down wifi. Expect the default network callback to notified of LOST wifi
2690         // followed by AVAILABLE cell.
2691         mWiFiNetworkAgent.disconnect();
2692         cellNetworkCallback.assertNoCallback();
2693         defaultNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2694         defaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
2695         mCellNetworkAgent.disconnect();
2696         cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
2697         defaultNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
2698         waitForIdle();
2699         assertEquals(null, mCm.getActiveNetwork());
2700 
2701         final int uid = Process.myUid();
2702         final MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
2703         final ArraySet<UidRange> ranges = new ArraySet<>();
2704         ranges.add(new UidRange(uid, uid));
2705         mMockVpn.setNetworkAgent(vpnNetworkAgent);
2706         mMockVpn.setUids(ranges);
2707         vpnNetworkAgent.connect(true);
2708         mMockVpn.connect();
2709         defaultNetworkCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
2710         assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
2711 
2712         vpnNetworkAgent.disconnect();
2713         defaultNetworkCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
2714         waitForIdle();
2715         assertEquals(null, mCm.getActiveNetwork());
2716     }
2717 
2718     @Test
testAdditionalStateCallbacks()2719     public void testAdditionalStateCallbacks() throws Exception {
2720         // File a network request for mobile.
2721         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
2722         final NetworkRequest cellRequest = new NetworkRequest.Builder()
2723                 .addTransportType(TRANSPORT_CELLULAR).build();
2724         mCm.requestNetwork(cellRequest, cellNetworkCallback);
2725 
2726         // Bring up the mobile network.
2727         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2728         mCellNetworkAgent.connect(true);
2729 
2730         // We should get onAvailable(), onCapabilitiesChanged(), and
2731         // onLinkPropertiesChanged() in rapid succession. Additionally, we
2732         // should get onCapabilitiesChanged() when the mobile network validates.
2733         cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2734         cellNetworkCallback.assertNoCallback();
2735 
2736         // Update LinkProperties.
2737         final LinkProperties lp = new LinkProperties();
2738         lp.setInterfaceName("foonet_data0");
2739         mCellNetworkAgent.sendLinkProperties(lp);
2740         // We should get onLinkPropertiesChanged().
2741         cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
2742         cellNetworkCallback.assertNoCallback();
2743 
2744         // Suspend the network.
2745         mCellNetworkAgent.suspend();
2746         cellNetworkCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_SUSPENDED,
2747                 mCellNetworkAgent);
2748         cellNetworkCallback.expectCallback(CallbackState.SUSPENDED, mCellNetworkAgent);
2749         cellNetworkCallback.assertNoCallback();
2750 
2751         // Register a garden variety default network request.
2752         TestNetworkCallback dfltNetworkCallback = new TestNetworkCallback();
2753         mCm.registerDefaultNetworkCallback(dfltNetworkCallback);
2754         // We should get onAvailable(), onCapabilitiesChanged(), onLinkPropertiesChanged(),
2755         // as well as onNetworkSuspended() in rapid succession.
2756         dfltNetworkCallback.expectAvailableAndSuspendedCallbacks(mCellNetworkAgent, true);
2757         dfltNetworkCallback.assertNoCallback();
2758         mCm.unregisterNetworkCallback(dfltNetworkCallback);
2759 
2760         mCellNetworkAgent.resume();
2761         cellNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_NOT_SUSPENDED,
2762                 mCellNetworkAgent);
2763         cellNetworkCallback.expectCallback(CallbackState.RESUMED, mCellNetworkAgent);
2764         cellNetworkCallback.assertNoCallback();
2765 
2766         dfltNetworkCallback = new TestNetworkCallback();
2767         mCm.registerDefaultNetworkCallback(dfltNetworkCallback);
2768         // This time onNetworkSuspended should not be called.
2769         dfltNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
2770         dfltNetworkCallback.assertNoCallback();
2771 
2772         mCm.unregisterNetworkCallback(dfltNetworkCallback);
2773         mCm.unregisterNetworkCallback(cellNetworkCallback);
2774     }
2775 
setCaptivePortalMode(int mode)2776     private void setCaptivePortalMode(int mode) {
2777         ContentResolver cr = mServiceContext.getContentResolver();
2778         Settings.Global.putInt(cr, Settings.Global.CAPTIVE_PORTAL_MODE, mode);
2779     }
2780 
setMobileDataAlwaysOn(boolean enable)2781     private void setMobileDataAlwaysOn(boolean enable) {
2782         ContentResolver cr = mServiceContext.getContentResolver();
2783         Settings.Global.putInt(cr, Settings.Global.MOBILE_DATA_ALWAYS_ON, enable ? 1 : 0);
2784         mService.updateMobileDataAlwaysOn();
2785         waitForIdle();
2786     }
2787 
setPrivateDnsSettings(String mode, String specifier)2788     private void setPrivateDnsSettings(String mode, String specifier) {
2789         final ContentResolver cr = mServiceContext.getContentResolver();
2790         Settings.Global.putString(cr, Settings.Global.PRIVATE_DNS_MODE, mode);
2791         Settings.Global.putString(cr, Settings.Global.PRIVATE_DNS_SPECIFIER, specifier);
2792         mService.updatePrivateDnsSettings();
2793         waitForIdle();
2794     }
2795 
isForegroundNetwork(MockNetworkAgent network)2796     private boolean isForegroundNetwork(MockNetworkAgent network) {
2797         NetworkCapabilities nc = mCm.getNetworkCapabilities(network.getNetwork());
2798         assertNotNull(nc);
2799         return nc.hasCapability(NET_CAPABILITY_FOREGROUND);
2800     }
2801 
2802     @Test
testBackgroundNetworks()2803     public void testBackgroundNetworks() throws Exception {
2804         // Create a background request. We can't do this ourselves because ConnectivityService
2805         // doesn't have an API for it. So just turn on mobile data always on.
2806         setMobileDataAlwaysOn(true);
2807         final NetworkRequest request = new NetworkRequest.Builder().build();
2808         final NetworkRequest fgRequest = new NetworkRequest.Builder()
2809                 .addCapability(NET_CAPABILITY_FOREGROUND).build();
2810         final TestNetworkCallback callback = new TestNetworkCallback();
2811         final TestNetworkCallback fgCallback = new TestNetworkCallback();
2812         mCm.registerNetworkCallback(request, callback);
2813         mCm.registerNetworkCallback(fgRequest, fgCallback);
2814 
2815         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2816         mCellNetworkAgent.connect(true);
2817         callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2818         fgCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2819         assertTrue(isForegroundNetwork(mCellNetworkAgent));
2820 
2821         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2822         mWiFiNetworkAgent.connect(true);
2823 
2824         // When wifi connects, cell lingers.
2825         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2826         callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
2827         callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
2828         fgCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2829         fgCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
2830         fgCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
2831         assertTrue(isForegroundNetwork(mCellNetworkAgent));
2832         assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
2833 
2834         // When lingering is complete, cell is still there but is now in the background.
2835         waitForIdle();
2836         int timeoutMs = TEST_LINGER_DELAY_MS + TEST_LINGER_DELAY_MS / 4;
2837         fgCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent, timeoutMs);
2838         // Expect a network capabilities update sans FOREGROUND.
2839         callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
2840         assertFalse(isForegroundNetwork(mCellNetworkAgent));
2841         assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
2842 
2843         // File a cell request and check that cell comes into the foreground.
2844         final NetworkRequest cellRequest = new NetworkRequest.Builder()
2845                 .addTransportType(TRANSPORT_CELLULAR).build();
2846         final TestNetworkCallback cellCallback = new TestNetworkCallback();
2847         mCm.requestNetwork(cellRequest, cellCallback);
2848         // NOTE: This request causes the network's capabilities to change. This
2849         // is currently delivered before the onAvailable() callbacks.
2850         // TODO: Fix this.
2851         cellCallback.expectCapabilitiesWith(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
2852         cellCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
2853         fgCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
2854         // Expect a network capabilities update with FOREGROUND, because the most recent
2855         // request causes its state to change.
2856         callback.expectCapabilitiesWith(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
2857         assertTrue(isForegroundNetwork(mCellNetworkAgent));
2858         assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
2859 
2860         // Release the request. The network immediately goes into the background, since it was not
2861         // lingering.
2862         mCm.unregisterNetworkCallback(cellCallback);
2863         fgCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
2864         // Expect a network capabilities update sans FOREGROUND.
2865         callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
2866         assertFalse(isForegroundNetwork(mCellNetworkAgent));
2867         assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
2868 
2869         // Disconnect wifi and check that cell is foreground again.
2870         mWiFiNetworkAgent.disconnect();
2871         callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2872         fgCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2873         fgCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
2874         assertTrue(isForegroundNetwork(mCellNetworkAgent));
2875 
2876         mCm.unregisterNetworkCallback(callback);
2877         mCm.unregisterNetworkCallback(fgCallback);
2878     }
2879 
2880     @Ignore // This test has instrinsic chances of spurious failures: ignore for continuous testing.
benchmarkRequestRegistrationAndCallbackDispatch()2881     public void benchmarkRequestRegistrationAndCallbackDispatch() throws Exception {
2882         // TODO: turn this unit test into a real benchmarking test.
2883         // Benchmarks connecting and switching performance in the presence of a large number of
2884         // NetworkRequests.
2885         // 1. File NUM_REQUESTS requests.
2886         // 2. Have a network connect. Wait for NUM_REQUESTS onAvailable callbacks to fire.
2887         // 3. Have a new network connect and outscore the previous. Wait for NUM_REQUESTS onLosing
2888         //    and NUM_REQUESTS onAvailable callbacks to fire.
2889         // See how long it took.
2890         final int NUM_REQUESTS = 90;
2891         final int REGISTER_TIME_LIMIT_MS = 200;
2892         final int CONNECT_TIME_LIMIT_MS = 60;
2893         final int SWITCH_TIME_LIMIT_MS = 60;
2894         final int UNREGISTER_TIME_LIMIT_MS = 20;
2895 
2896         final NetworkRequest request = new NetworkRequest.Builder().clearCapabilities().build();
2897         final NetworkCallback[] callbacks = new NetworkCallback[NUM_REQUESTS];
2898         final CountDownLatch availableLatch = new CountDownLatch(NUM_REQUESTS);
2899         final CountDownLatch losingLatch = new CountDownLatch(NUM_REQUESTS);
2900 
2901         for (int i = 0; i < NUM_REQUESTS; i++) {
2902             callbacks[i] = new NetworkCallback() {
2903                 @Override public void onAvailable(Network n) { availableLatch.countDown(); }
2904                 @Override public void onLosing(Network n, int t) { losingLatch.countDown(); }
2905             };
2906         }
2907 
2908         assertTimeLimit("Registering callbacks", REGISTER_TIME_LIMIT_MS, () -> {
2909             for (NetworkCallback cb : callbacks) {
2910                 mCm.registerNetworkCallback(request, cb);
2911             }
2912         });
2913 
2914         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2915         // Don't request that the network validate, because otherwise connect() will block until
2916         // the network gets NET_CAPABILITY_VALIDATED, after all the callbacks below have fired,
2917         // and we won't actually measure anything.
2918         mCellNetworkAgent.connect(false);
2919 
2920         long onAvailableDispatchingDuration = durationOf(() -> {
2921             awaitLatch(availableLatch, 10 * CONNECT_TIME_LIMIT_MS);
2922         });
2923         Log.d(TAG, String.format("Dispatched %d of %d onAvailable callbacks in %dms",
2924                 NUM_REQUESTS - availableLatch.getCount(), NUM_REQUESTS,
2925                 onAvailableDispatchingDuration));
2926         assertTrue(String.format("Dispatching %d onAvailable callbacks in %dms, expected %dms",
2927                 NUM_REQUESTS, onAvailableDispatchingDuration, CONNECT_TIME_LIMIT_MS),
2928                 onAvailableDispatchingDuration <= CONNECT_TIME_LIMIT_MS);
2929 
2930         // Give wifi a high enough score that we'll linger cell when wifi comes up.
2931         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2932         mWiFiNetworkAgent.adjustScore(40);
2933         mWiFiNetworkAgent.connect(false);
2934 
2935         long onLostDispatchingDuration = durationOf(() -> {
2936             awaitLatch(losingLatch, 10 * SWITCH_TIME_LIMIT_MS);
2937         });
2938         Log.d(TAG, String.format("Dispatched %d of %d onLosing callbacks in %dms",
2939                 NUM_REQUESTS - losingLatch.getCount(), NUM_REQUESTS, onLostDispatchingDuration));
2940         assertTrue(String.format("Dispatching %d onLosing callbacks in %dms, expected %dms",
2941                 NUM_REQUESTS, onLostDispatchingDuration, SWITCH_TIME_LIMIT_MS),
2942                 onLostDispatchingDuration <= SWITCH_TIME_LIMIT_MS);
2943 
2944         assertTimeLimit("Unregistering callbacks", UNREGISTER_TIME_LIMIT_MS, () -> {
2945             for (NetworkCallback cb : callbacks) {
2946                 mCm.unregisterNetworkCallback(cb);
2947             }
2948         });
2949     }
2950 
durationOf(Runnable fn)2951     private long durationOf(Runnable fn) {
2952         long startTime = SystemClock.elapsedRealtime();
2953         fn.run();
2954         return SystemClock.elapsedRealtime() - startTime;
2955     }
2956 
assertTimeLimit(String descr, long timeLimit, Runnable fn)2957     private void assertTimeLimit(String descr, long timeLimit, Runnable fn) {
2958         long timeTaken = durationOf(fn);
2959         String msg = String.format("%s: took %dms, limit was %dms", descr, timeTaken, timeLimit);
2960         Log.d(TAG, msg);
2961         assertTrue(msg, timeTaken <= timeLimit);
2962     }
2963 
awaitLatch(CountDownLatch l, long timeoutMs)2964     private boolean awaitLatch(CountDownLatch l, long timeoutMs) {
2965         try {
2966             return l.await(timeoutMs, TimeUnit.MILLISECONDS);
2967         } catch (InterruptedException e) {}
2968         return false;
2969     }
2970 
2971     @Test
testMobileDataAlwaysOn()2972     public void testMobileDataAlwaysOn() throws Exception {
2973         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
2974         final NetworkRequest cellRequest = new NetworkRequest.Builder()
2975                 .addTransportType(TRANSPORT_CELLULAR).build();
2976         mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
2977 
2978         final HandlerThread handlerThread = new HandlerThread("MobileDataAlwaysOnFactory");
2979         handlerThread.start();
2980         NetworkCapabilities filter = new NetworkCapabilities()
2981                 .addTransportType(TRANSPORT_CELLULAR)
2982                 .addCapability(NET_CAPABILITY_INTERNET);
2983         final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
2984                 mServiceContext, "testFactory", filter);
2985         testFactory.setScoreFilter(40);
2986 
2987         // Register the factory and expect it to start looking for a network.
2988         testFactory.expectAddRequests(1);
2989         testFactory.register();
2990         testFactory.waitForNetworkRequests(1);
2991         assertTrue(testFactory.getMyStartRequested());
2992 
2993         // Bring up wifi. The factory stops looking for a network.
2994         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2995         testFactory.expectAddRequests(2);  // Because the default request changes score twice.
2996         mWiFiNetworkAgent.connect(true);
2997         testFactory.waitForNetworkRequests(1);
2998         assertFalse(testFactory.getMyStartRequested());
2999 
3000         ContentResolver cr = mServiceContext.getContentResolver();
3001 
3002         // Turn on mobile data always on. The factory starts looking again.
3003         testFactory.expectAddRequests(1);
3004         setMobileDataAlwaysOn(true);
3005         testFactory.waitForNetworkRequests(2);
3006         assertTrue(testFactory.getMyStartRequested());
3007 
3008         // Bring up cell data and check that the factory stops looking.
3009         assertLength(1, mCm.getAllNetworks());
3010         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
3011         testFactory.expectAddRequests(2);  // Because the cell request changes score twice.
3012         mCellNetworkAgent.connect(true);
3013         cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
3014         testFactory.waitForNetworkRequests(2);
3015         assertFalse(testFactory.getMyStartRequested());  // Because the cell network outscores us.
3016 
3017         // Check that cell data stays up.
3018         waitForIdle();
3019         verifyActiveNetwork(TRANSPORT_WIFI);
3020         assertLength(2, mCm.getAllNetworks());
3021 
3022         // Turn off mobile data always on and expect the request to disappear...
3023         testFactory.expectRemoveRequests(1);
3024         setMobileDataAlwaysOn(false);
3025         testFactory.waitForNetworkRequests(1);
3026 
3027         // ...  and cell data to be torn down.
3028         cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
3029         assertLength(1, mCm.getAllNetworks());
3030 
3031         testFactory.unregister();
3032         mCm.unregisterNetworkCallback(cellNetworkCallback);
3033         handlerThread.quit();
3034     }
3035 
3036     @Test
testAvoidBadWifiSetting()3037     public void testAvoidBadWifiSetting() throws Exception {
3038         final ContentResolver cr = mServiceContext.getContentResolver();
3039         final WrappedMultinetworkPolicyTracker tracker = mService.getMultinetworkPolicyTracker();
3040         final String settingName = Settings.Global.NETWORK_AVOID_BAD_WIFI;
3041 
3042         tracker.configRestrictsAvoidBadWifi = false;
3043         String[] values = new String[] {null, "0", "1"};
3044         for (int i = 0; i < values.length; i++) {
3045             Settings.Global.putInt(cr, settingName, 1);
3046             tracker.reevaluate();
3047             waitForIdle();
3048             String msg = String.format("config=false, setting=%s", values[i]);
3049             assertTrue(mService.avoidBadWifi());
3050             assertFalse(msg, tracker.shouldNotifyWifiUnvalidated());
3051         }
3052 
3053         tracker.configRestrictsAvoidBadWifi = true;
3054 
3055         Settings.Global.putInt(cr, settingName, 0);
3056         tracker.reevaluate();
3057         waitForIdle();
3058         assertFalse(mService.avoidBadWifi());
3059         assertFalse(tracker.shouldNotifyWifiUnvalidated());
3060 
3061         Settings.Global.putInt(cr, settingName, 1);
3062         tracker.reevaluate();
3063         waitForIdle();
3064         assertTrue(mService.avoidBadWifi());
3065         assertFalse(tracker.shouldNotifyWifiUnvalidated());
3066 
3067         Settings.Global.putString(cr, settingName, null);
3068         tracker.reevaluate();
3069         waitForIdle();
3070         assertFalse(mService.avoidBadWifi());
3071         assertTrue(tracker.shouldNotifyWifiUnvalidated());
3072     }
3073 
3074     @Test
testAvoidBadWifi()3075     public void testAvoidBadWifi() throws Exception {
3076         final ContentResolver cr = mServiceContext.getContentResolver();
3077         final WrappedMultinetworkPolicyTracker tracker = mService.getMultinetworkPolicyTracker();
3078 
3079         // Pretend we're on a carrier that restricts switching away from bad wifi.
3080         tracker.configRestrictsAvoidBadWifi = true;
3081 
3082         // File a request for cell to ensure it doesn't go down.
3083         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
3084         final NetworkRequest cellRequest = new NetworkRequest.Builder()
3085                 .addTransportType(TRANSPORT_CELLULAR).build();
3086         mCm.requestNetwork(cellRequest, cellNetworkCallback);
3087 
3088         TestNetworkCallback defaultCallback = new TestNetworkCallback();
3089         mCm.registerDefaultNetworkCallback(defaultCallback);
3090 
3091         NetworkRequest validatedWifiRequest = new NetworkRequest.Builder()
3092                 .addTransportType(TRANSPORT_WIFI)
3093                 .addCapability(NET_CAPABILITY_VALIDATED)
3094                 .build();
3095         TestNetworkCallback validatedWifiCallback = new TestNetworkCallback();
3096         mCm.registerNetworkCallback(validatedWifiRequest, validatedWifiCallback);
3097 
3098         Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 0);
3099         tracker.reevaluate();
3100 
3101         // Bring up validated cell.
3102         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
3103         mCellNetworkAgent.connect(true);
3104         cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
3105         defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
3106         Network cellNetwork = mCellNetworkAgent.getNetwork();
3107 
3108         // Bring up validated wifi.
3109         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3110         mWiFiNetworkAgent.connect(true);
3111         defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
3112         validatedWifiCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
3113         Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
3114 
3115         // Fail validation on wifi.
3116         mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 599;
3117         mCm.reportNetworkConnectivity(wifiNetwork, false);
3118         defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
3119         validatedWifiCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
3120 
3121         // Because avoid bad wifi is off, we don't switch to cellular.
3122         defaultCallback.assertNoCallback();
3123         assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
3124                 NET_CAPABILITY_VALIDATED));
3125         assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
3126                 NET_CAPABILITY_VALIDATED));
3127         assertEquals(mCm.getActiveNetwork(), wifiNetwork);
3128 
3129         // Simulate switching to a carrier that does not restrict avoiding bad wifi, and expect
3130         // that we switch back to cell.
3131         tracker.configRestrictsAvoidBadWifi = false;
3132         tracker.reevaluate();
3133         defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
3134         assertEquals(mCm.getActiveNetwork(), cellNetwork);
3135 
3136         // Switch back to a restrictive carrier.
3137         tracker.configRestrictsAvoidBadWifi = true;
3138         tracker.reevaluate();
3139         defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
3140         assertEquals(mCm.getActiveNetwork(), wifiNetwork);
3141 
3142         // Simulate the user selecting "switch" on the dialog, and check that we switch to cell.
3143         mCm.setAvoidUnvalidated(wifiNetwork);
3144         defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
3145         assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
3146                 NET_CAPABILITY_VALIDATED));
3147         assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
3148                 NET_CAPABILITY_VALIDATED));
3149         assertEquals(mCm.getActiveNetwork(), cellNetwork);
3150 
3151         // Disconnect and reconnect wifi to clear the one-time switch above.
3152         mWiFiNetworkAgent.disconnect();
3153         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3154         mWiFiNetworkAgent.connect(true);
3155         defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
3156         validatedWifiCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
3157         wifiNetwork = mWiFiNetworkAgent.getNetwork();
3158 
3159         // Fail validation on wifi and expect the dialog to appear.
3160         mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 599;
3161         mCm.reportNetworkConnectivity(wifiNetwork, false);
3162         defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
3163         validatedWifiCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
3164 
3165         // Simulate the user selecting "switch" and checking the don't ask again checkbox.
3166         Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 1);
3167         tracker.reevaluate();
3168 
3169         // We now switch to cell.
3170         defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
3171         assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
3172                 NET_CAPABILITY_VALIDATED));
3173         assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
3174                 NET_CAPABILITY_VALIDATED));
3175         assertEquals(mCm.getActiveNetwork(), cellNetwork);
3176 
3177         // Simulate the user turning the cellular fallback setting off and then on.
3178         // We switch to wifi and then to cell.
3179         Settings.Global.putString(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, null);
3180         tracker.reevaluate();
3181         defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
3182         assertEquals(mCm.getActiveNetwork(), wifiNetwork);
3183         Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 1);
3184         tracker.reevaluate();
3185         defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
3186         assertEquals(mCm.getActiveNetwork(), cellNetwork);
3187 
3188         // If cell goes down, we switch to wifi.
3189         mCellNetworkAgent.disconnect();
3190         defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
3191         defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
3192         validatedWifiCallback.assertNoCallback();
3193 
3194         mCm.unregisterNetworkCallback(cellNetworkCallback);
3195         mCm.unregisterNetworkCallback(validatedWifiCallback);
3196         mCm.unregisterNetworkCallback(defaultCallback);
3197     }
3198 
3199     @Test
testMeteredMultipathPreferenceSetting()3200     public void testMeteredMultipathPreferenceSetting() throws Exception {
3201         final ContentResolver cr = mServiceContext.getContentResolver();
3202         final WrappedMultinetworkPolicyTracker tracker = mService.getMultinetworkPolicyTracker();
3203         final String settingName = Settings.Global.NETWORK_METERED_MULTIPATH_PREFERENCE;
3204 
3205         for (int config : Arrays.asList(0, 3, 2)) {
3206             for (String setting: Arrays.asList(null, "0", "2", "1")) {
3207                 tracker.configMeteredMultipathPreference = config;
3208                 Settings.Global.putString(cr, settingName, setting);
3209                 tracker.reevaluate();
3210                 waitForIdle();
3211 
3212                 final int expected = (setting != null) ? Integer.parseInt(setting) : config;
3213                 String msg = String.format("config=%d, setting=%s", config, setting);
3214                 assertEquals(msg, expected, mCm.getMultipathPreference(null));
3215             }
3216         }
3217     }
3218 
3219     /**
3220      * Validate that a satisfied network request does not trigger onUnavailable() once the
3221      * time-out period expires.
3222      */
3223     @Test
testSatisfiedNetworkRequestDoesNotTriggerOnUnavailable()3224     public void testSatisfiedNetworkRequestDoesNotTriggerOnUnavailable() {
3225         NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3226                 NetworkCapabilities.TRANSPORT_WIFI).build();
3227         final TestNetworkCallback networkCallback = new TestNetworkCallback();
3228         final int timeoutMs = 150;
3229         mCm.requestNetwork(nr, networkCallback, timeoutMs);
3230 
3231         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3232         mWiFiNetworkAgent.connect(false);
3233         networkCallback.expectAvailableCallbacks(mWiFiNetworkAgent, false, false, timeoutMs);
3234 
3235         // pass timeout and validate that UNAVAILABLE is not called
3236         networkCallback.assertNoCallback();
3237     }
3238 
3239     /**
3240      * Validate that a satisfied network request followed by a disconnected (lost) network does
3241      * not trigger onUnavailable() once the time-out period expires.
3242      */
3243     @Test
testSatisfiedThenLostNetworkRequestDoesNotTriggerOnUnavailable()3244     public void testSatisfiedThenLostNetworkRequestDoesNotTriggerOnUnavailable() {
3245         NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3246                 NetworkCapabilities.TRANSPORT_WIFI).build();
3247         final TestNetworkCallback networkCallback = new TestNetworkCallback();
3248         final int requestTimeoutMs = 50;
3249         mCm.requestNetwork(nr, networkCallback, requestTimeoutMs);
3250 
3251         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3252         mWiFiNetworkAgent.connect(false);
3253         final int assertTimeoutMs = 100;
3254         networkCallback.expectAvailableCallbacks(mWiFiNetworkAgent, false, false, assertTimeoutMs);
3255         mWiFiNetworkAgent.disconnect();
3256         networkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
3257 
3258         // Validate that UNAVAILABLE is not called
3259         networkCallback.assertNoCallback();
3260     }
3261 
3262     /**
3263      * Validate that when a time-out is specified for a network request the onUnavailable()
3264      * callback is called when time-out expires. Then validate that if network request is
3265      * (somehow) satisfied - the callback isn't called later.
3266      */
3267     @Test
testTimedoutNetworkRequest()3268     public void testTimedoutNetworkRequest() {
3269         NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3270                 NetworkCapabilities.TRANSPORT_WIFI).build();
3271         final TestNetworkCallback networkCallback = new TestNetworkCallback();
3272         final int timeoutMs = 10;
3273         mCm.requestNetwork(nr, networkCallback, timeoutMs);
3274 
3275         // pass timeout and validate that UNAVAILABLE is called
3276         networkCallback.expectCallback(CallbackState.UNAVAILABLE, null);
3277 
3278         // create a network satisfying request - validate that request not triggered
3279         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3280         mWiFiNetworkAgent.connect(false);
3281         networkCallback.assertNoCallback();
3282     }
3283 
3284     /**
3285      * Validate that when a network request is unregistered (cancelled), no posterior event can
3286      * trigger the callback.
3287      */
3288     @Test
testNoCallbackAfterUnregisteredNetworkRequest()3289     public void testNoCallbackAfterUnregisteredNetworkRequest() {
3290         NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3291                 NetworkCapabilities.TRANSPORT_WIFI).build();
3292         final TestNetworkCallback networkCallback = new TestNetworkCallback();
3293         final int timeoutMs = 10;
3294 
3295         mCm.requestNetwork(nr, networkCallback, timeoutMs);
3296         mCm.unregisterNetworkCallback(networkCallback);
3297         // Regardless of the timeout, unregistering the callback in ConnectivityManager ensures
3298         // that this callback will not be called.
3299         networkCallback.assertNoCallback();
3300 
3301         // create a network satisfying request - validate that request not triggered
3302         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3303         mWiFiNetworkAgent.connect(false);
3304         networkCallback.assertNoCallback();
3305     }
3306 
3307     private static class TestKeepaliveCallback extends PacketKeepaliveCallback {
3308 
3309         public static enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR };
3310 
3311         private class CallbackValue {
3312             public CallbackType callbackType;
3313             public int error;
3314 
CallbackValue(CallbackType type)3315             public CallbackValue(CallbackType type) {
3316                 this.callbackType = type;
3317                 this.error = PacketKeepalive.SUCCESS;
3318                 assertTrue("onError callback must have error", type != CallbackType.ON_ERROR);
3319             }
3320 
CallbackValue(CallbackType type, int error)3321             public CallbackValue(CallbackType type, int error) {
3322                 this.callbackType = type;
3323                 this.error = error;
3324                 assertEquals("error can only be set for onError", type, CallbackType.ON_ERROR);
3325             }
3326 
3327             @Override
equals(Object o)3328             public boolean equals(Object o) {
3329                 return o instanceof CallbackValue &&
3330                         this.callbackType == ((CallbackValue) o).callbackType &&
3331                         this.error == ((CallbackValue) o).error;
3332             }
3333 
3334             @Override
toString()3335             public String toString() {
3336                 return String.format("%s(%s, %d)", getClass().getSimpleName(), callbackType, error);
3337             }
3338         }
3339 
3340         private LinkedBlockingQueue<CallbackValue> mCallbacks = new LinkedBlockingQueue<>();
3341 
3342         @Override
onStarted()3343         public void onStarted() {
3344             mCallbacks.add(new CallbackValue(CallbackType.ON_STARTED));
3345         }
3346 
3347         @Override
onStopped()3348         public void onStopped() {
3349             mCallbacks.add(new CallbackValue(CallbackType.ON_STOPPED));
3350         }
3351 
3352         @Override
onError(int error)3353         public void onError(int error) {
3354             mCallbacks.add(new CallbackValue(CallbackType.ON_ERROR, error));
3355         }
3356 
expectCallback(CallbackValue callbackValue)3357         private void expectCallback(CallbackValue callbackValue) {
3358             try {
3359                 assertEquals(
3360                         callbackValue,
3361                         mCallbacks.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
3362             } catch (InterruptedException e) {
3363                 fail(callbackValue.callbackType + " callback not seen after " + TIMEOUT_MS + " ms");
3364             }
3365         }
3366 
expectStarted()3367         public void expectStarted() {
3368             expectCallback(new CallbackValue(CallbackType.ON_STARTED));
3369         }
3370 
expectStopped()3371         public void expectStopped() {
3372             expectCallback(new CallbackValue(CallbackType.ON_STOPPED));
3373         }
3374 
expectError(int error)3375         public void expectError(int error) {
3376             expectCallback(new CallbackValue(CallbackType.ON_ERROR, error));
3377         }
3378     }
3379 
connectKeepaliveNetwork(LinkProperties lp)3380     private Network connectKeepaliveNetwork(LinkProperties lp) {
3381         // Ensure the network is disconnected before we do anything.
3382         if (mWiFiNetworkAgent != null) {
3383             assertNull(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()));
3384         }
3385 
3386         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3387         ConditionVariable cv = waitForConnectivityBroadcasts(1);
3388         mWiFiNetworkAgent.connect(true);
3389         waitFor(cv);
3390         verifyActiveNetwork(TRANSPORT_WIFI);
3391         mWiFiNetworkAgent.sendLinkProperties(lp);
3392         waitForIdle();
3393         return mWiFiNetworkAgent.getNetwork();
3394     }
3395 
3396     @Test
testPacketKeepalives()3397     public void testPacketKeepalives() throws Exception {
3398         InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
3399         InetAddress notMyIPv4 = InetAddress.getByName("192.0.2.35");
3400         InetAddress myIPv6 = InetAddress.getByName("2001:db8::1");
3401         InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8");
3402         InetAddress dstIPv6 = InetAddress.getByName("2001:4860:4860::8888");
3403 
3404         final int validKaInterval = 15;
3405         final int invalidKaInterval = 9;
3406 
3407         LinkProperties lp = new LinkProperties();
3408         lp.setInterfaceName("wlan12");
3409         lp.addLinkAddress(new LinkAddress(myIPv6, 64));
3410         lp.addLinkAddress(new LinkAddress(myIPv4, 25));
3411         lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
3412         lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
3413 
3414         Network notMyNet = new Network(61234);
3415         Network myNet = connectKeepaliveNetwork(lp);
3416 
3417         TestKeepaliveCallback callback = new TestKeepaliveCallback();
3418         PacketKeepalive ka;
3419 
3420         // Attempt to start keepalives with invalid parameters and check for errors.
3421         ka = mCm.startNattKeepalive(notMyNet, validKaInterval, callback, myIPv4, 1234, dstIPv4);
3422         callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK);
3423 
3424         ka = mCm.startNattKeepalive(myNet, invalidKaInterval, callback, myIPv4, 1234, dstIPv4);
3425         callback.expectError(PacketKeepalive.ERROR_INVALID_INTERVAL);
3426 
3427         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 1234, dstIPv6);
3428         callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
3429 
3430         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv6, 1234, dstIPv4);
3431         callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
3432 
3433         // NAT-T is only supported for IPv4.
3434         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv6, 1234, dstIPv6);
3435         callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
3436 
3437         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 123456, dstIPv4);
3438         callback.expectError(PacketKeepalive.ERROR_INVALID_PORT);
3439 
3440         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 123456, dstIPv4);
3441         callback.expectError(PacketKeepalive.ERROR_INVALID_PORT);
3442 
3443         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
3444         callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
3445 
3446         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
3447         callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
3448 
3449         // Check that a started keepalive can be stopped.
3450         mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS);
3451         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
3452         callback.expectStarted();
3453         mWiFiNetworkAgent.setStopKeepaliveError(PacketKeepalive.SUCCESS);
3454         ka.stop();
3455         callback.expectStopped();
3456 
3457         // Check that deleting the IP address stops the keepalive.
3458         LinkProperties bogusLp = new LinkProperties(lp);
3459         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
3460         callback.expectStarted();
3461         bogusLp.removeLinkAddress(new LinkAddress(myIPv4, 25));
3462         bogusLp.addLinkAddress(new LinkAddress(notMyIPv4, 25));
3463         mWiFiNetworkAgent.sendLinkProperties(bogusLp);
3464         callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
3465         mWiFiNetworkAgent.sendLinkProperties(lp);
3466 
3467         // Check that a started keepalive is stopped correctly when the network disconnects.
3468         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
3469         callback.expectStarted();
3470         mWiFiNetworkAgent.disconnect();
3471         waitFor(mWiFiNetworkAgent.getDisconnectedCV());
3472         callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK);
3473 
3474         // ... and that stopping it after that has no adverse effects.
3475         waitForIdle();
3476         final Network myNetAlias = myNet;
3477         assertNull(mCm.getNetworkCapabilities(myNetAlias));
3478         ka.stop();
3479 
3480         // Reconnect.
3481         myNet = connectKeepaliveNetwork(lp);
3482         mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS);
3483 
3484         // Check things work as expected when the keepalive is stopped and the network disconnects.
3485         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
3486         callback.expectStarted();
3487         ka.stop();
3488         mWiFiNetworkAgent.disconnect();
3489         waitFor(mWiFiNetworkAgent.getDisconnectedCV());
3490         waitForIdle();
3491         callback.expectStopped();
3492 
3493         // Reconnect.
3494         myNet = connectKeepaliveNetwork(lp);
3495         mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS);
3496 
3497         // Check that keepalive slots start from 1 and increment. The first one gets slot 1.
3498         mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
3499         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
3500         callback.expectStarted();
3501 
3502         // The second one gets slot 2.
3503         mWiFiNetworkAgent.setExpectedKeepaliveSlot(2);
3504         TestKeepaliveCallback callback2 = new TestKeepaliveCallback();
3505         PacketKeepalive ka2 = mCm.startNattKeepalive(
3506                 myNet, validKaInterval, callback2, myIPv4, 6789, dstIPv4);
3507         callback2.expectStarted();
3508 
3509         // Now stop the first one and create a third. This also gets slot 1.
3510         ka.stop();
3511         callback.expectStopped();
3512 
3513         mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
3514         TestKeepaliveCallback callback3 = new TestKeepaliveCallback();
3515         PacketKeepalive ka3 = mCm.startNattKeepalive(
3516                 myNet, validKaInterval, callback3, myIPv4, 9876, dstIPv4);
3517         callback3.expectStarted();
3518 
3519         ka2.stop();
3520         callback2.expectStopped();
3521 
3522         ka3.stop();
3523         callback3.expectStopped();
3524     }
3525 
3526     @Test
testGetCaptivePortalServerUrl()3527     public void testGetCaptivePortalServerUrl() throws Exception {
3528         String url = mCm.getCaptivePortalServerUrl();
3529         assertEquals("http://connectivitycheck.gstatic.com/generate_204", url);
3530     }
3531 
3532     private static class TestNetworkPinner extends NetworkPinner {
awaitPin(int timeoutMs)3533         public static boolean awaitPin(int timeoutMs) {
3534             synchronized(sLock) {
3535                 if (sNetwork == null) {
3536                     try {
3537                         sLock.wait(timeoutMs);
3538                     } catch (InterruptedException e) {}
3539                 }
3540                 return sNetwork != null;
3541             }
3542         }
3543 
awaitUnpin(int timeoutMs)3544         public static boolean awaitUnpin(int timeoutMs) {
3545             synchronized(sLock) {
3546                 if (sNetwork != null) {
3547                     try {
3548                         sLock.wait(timeoutMs);
3549                     } catch (InterruptedException e) {}
3550                 }
3551                 return sNetwork == null;
3552             }
3553         }
3554     }
3555 
assertPinnedToWifiWithCellDefault()3556     private void assertPinnedToWifiWithCellDefault() {
3557         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess());
3558         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
3559     }
3560 
assertPinnedToWifiWithWifiDefault()3561     private void assertPinnedToWifiWithWifiDefault() {
3562         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess());
3563         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
3564     }
3565 
assertNotPinnedToWifi()3566     private void assertNotPinnedToWifi() {
3567         assertNull(mCm.getBoundNetworkForProcess());
3568         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
3569     }
3570 
3571     @Test
testNetworkPinner()3572     public void testNetworkPinner() {
3573         NetworkRequest wifiRequest = new NetworkRequest.Builder()
3574                 .addTransportType(TRANSPORT_WIFI)
3575                 .build();
3576         assertNull(mCm.getBoundNetworkForProcess());
3577 
3578         TestNetworkPinner.pin(mServiceContext, wifiRequest);
3579         assertNull(mCm.getBoundNetworkForProcess());
3580 
3581         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
3582         mCellNetworkAgent.connect(true);
3583         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3584         mWiFiNetworkAgent.connect(false);
3585 
3586         // When wi-fi connects, expect to be pinned.
3587         assertTrue(TestNetworkPinner.awaitPin(100));
3588         assertPinnedToWifiWithCellDefault();
3589 
3590         // Disconnect and expect the pin to drop.
3591         mWiFiNetworkAgent.disconnect();
3592         assertTrue(TestNetworkPinner.awaitUnpin(100));
3593         assertNotPinnedToWifi();
3594 
3595         // Reconnecting does not cause the pin to come back.
3596         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3597         mWiFiNetworkAgent.connect(false);
3598         assertFalse(TestNetworkPinner.awaitPin(100));
3599         assertNotPinnedToWifi();
3600 
3601         // Pinning while connected causes the pin to take effect immediately.
3602         TestNetworkPinner.pin(mServiceContext, wifiRequest);
3603         assertTrue(TestNetworkPinner.awaitPin(100));
3604         assertPinnedToWifiWithCellDefault();
3605 
3606         // Explicitly unpin and expect to use the default network again.
3607         TestNetworkPinner.unpin();
3608         assertNotPinnedToWifi();
3609 
3610         // Disconnect cell and wifi.
3611         ConditionVariable cv = waitForConnectivityBroadcasts(3);  // cell down, wifi up, wifi down.
3612         mCellNetworkAgent.disconnect();
3613         mWiFiNetworkAgent.disconnect();
3614         waitFor(cv);
3615 
3616         // Pinning takes effect even if the pinned network is the default when the pin is set...
3617         TestNetworkPinner.pin(mServiceContext, wifiRequest);
3618         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3619         mWiFiNetworkAgent.connect(false);
3620         assertTrue(TestNetworkPinner.awaitPin(100));
3621         assertPinnedToWifiWithWifiDefault();
3622 
3623         // ... and is maintained even when that network is no longer the default.
3624         cv = waitForConnectivityBroadcasts(1);
3625         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3626         mCellNetworkAgent.connect(true);
3627         waitFor(cv);
3628         assertPinnedToWifiWithCellDefault();
3629     }
3630 
3631     @Test
testNetworkCallbackMaximum()3632     public void testNetworkCallbackMaximum() {
3633         // We can only have 99 callbacks, because MultipathPolicyTracker is
3634         // already one of them.
3635         final int MAX_REQUESTS = 99;
3636         final int CALLBACKS = 89;
3637         final int INTENTS = 10;
3638         assertEquals(MAX_REQUESTS, CALLBACKS + INTENTS);
3639 
3640         NetworkRequest networkRequest = new NetworkRequest.Builder().build();
3641         ArrayList<Object> registered = new ArrayList<>();
3642 
3643         int j = 0;
3644         while (j++ < CALLBACKS / 2) {
3645             NetworkCallback cb = new NetworkCallback();
3646             mCm.requestNetwork(networkRequest, cb);
3647             registered.add(cb);
3648         }
3649         while (j++ < CALLBACKS) {
3650             NetworkCallback cb = new NetworkCallback();
3651             mCm.registerNetworkCallback(networkRequest, cb);
3652             registered.add(cb);
3653         }
3654         j = 0;
3655         while (j++ < INTENTS / 2) {
3656             PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, new Intent("a" + j), 0);
3657             mCm.requestNetwork(networkRequest, pi);
3658             registered.add(pi);
3659         }
3660         while (j++ < INTENTS) {
3661             PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, new Intent("b" + j), 0);
3662             mCm.registerNetworkCallback(networkRequest, pi);
3663             registered.add(pi);
3664         }
3665 
3666         // Test that the limit is enforced when MAX_REQUESTS simultaneous requests are added.
3667         try {
3668             mCm.requestNetwork(networkRequest, new NetworkCallback());
3669             fail("Registering " + MAX_REQUESTS + " network requests did not throw exception");
3670         } catch (TooManyRequestsException expected) {}
3671         try {
3672             mCm.registerNetworkCallback(networkRequest, new NetworkCallback());
3673             fail("Registering " + MAX_REQUESTS + " network callbacks did not throw exception");
3674         } catch (TooManyRequestsException expected) {}
3675         try {
3676             mCm.requestNetwork(networkRequest,
3677                 PendingIntent.getBroadcast(mContext, 0, new Intent("c"), 0));
3678             fail("Registering " + MAX_REQUESTS + " PendingIntent requests did not throw exception");
3679         } catch (TooManyRequestsException expected) {}
3680         try {
3681             mCm.registerNetworkCallback(networkRequest,
3682                 PendingIntent.getBroadcast(mContext, 0, new Intent("d"), 0));
3683             fail("Registering " + MAX_REQUESTS
3684                     + " PendingIntent callbacks did not throw exception");
3685         } catch (TooManyRequestsException expected) {}
3686 
3687         for (Object o : registered) {
3688             if (o instanceof NetworkCallback) {
3689                 mCm.unregisterNetworkCallback((NetworkCallback)o);
3690             }
3691             if (o instanceof PendingIntent) {
3692                 mCm.unregisterNetworkCallback((PendingIntent)o);
3693             }
3694         }
3695         waitForIdle();
3696 
3697         // Test that the limit is not hit when MAX_REQUESTS requests are added and removed.
3698         for (int i = 0; i < MAX_REQUESTS; i++) {
3699             NetworkCallback networkCallback = new NetworkCallback();
3700             mCm.requestNetwork(networkRequest, networkCallback);
3701             mCm.unregisterNetworkCallback(networkCallback);
3702         }
3703         waitForIdle();
3704 
3705         for (int i = 0; i < MAX_REQUESTS; i++) {
3706             NetworkCallback networkCallback = new NetworkCallback();
3707             mCm.registerNetworkCallback(networkRequest, networkCallback);
3708             mCm.unregisterNetworkCallback(networkCallback);
3709         }
3710         waitForIdle();
3711 
3712         for (int i = 0; i < MAX_REQUESTS; i++) {
3713             PendingIntent pendingIntent =
3714                     PendingIntent.getBroadcast(mContext, 0, new Intent("e" + i), 0);
3715             mCm.requestNetwork(networkRequest, pendingIntent);
3716             mCm.unregisterNetworkCallback(pendingIntent);
3717         }
3718         waitForIdle();
3719 
3720         for (int i = 0; i < MAX_REQUESTS; i++) {
3721             PendingIntent pendingIntent =
3722                     PendingIntent.getBroadcast(mContext, 0, new Intent("f" + i), 0);
3723             mCm.registerNetworkCallback(networkRequest, pendingIntent);
3724             mCm.unregisterNetworkCallback(pendingIntent);
3725         }
3726     }
3727 
3728     @Test
testNetworkInfoOfTypeNone()3729     public void testNetworkInfoOfTypeNone() {
3730         ConditionVariable broadcastCV = waitForConnectivityBroadcasts(1);
3731 
3732         verifyNoNetwork();
3733         MockNetworkAgent wifiAware = new MockNetworkAgent(TRANSPORT_WIFI_AWARE);
3734         assertNull(mCm.getActiveNetworkInfo());
3735 
3736         Network[] allNetworks = mCm.getAllNetworks();
3737         assertLength(1, allNetworks);
3738         Network network = allNetworks[0];
3739         NetworkCapabilities capabilities = mCm.getNetworkCapabilities(network);
3740         assertTrue(capabilities.hasTransport(TRANSPORT_WIFI_AWARE));
3741 
3742         final NetworkRequest request =
3743                 new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI_AWARE).build();
3744         final TestNetworkCallback callback = new TestNetworkCallback();
3745         mCm.registerNetworkCallback(request, callback);
3746 
3747         // Bring up wifi aware network.
3748         wifiAware.connect(false, false);
3749         callback.expectAvailableCallbacksUnvalidated(wifiAware);
3750 
3751         assertNull(mCm.getActiveNetworkInfo());
3752         assertNull(mCm.getActiveNetwork());
3753         // TODO: getAllNetworkInfo is dirty and returns a non-empty array right from the start
3754         // of this test. Fix it and uncomment the assert below.
3755         //assertEmpty(mCm.getAllNetworkInfo());
3756 
3757         // Disconnect wifi aware network.
3758         wifiAware.disconnect();
3759         callback.expectCallbackLike((info) -> info.state == CallbackState.LOST, TIMEOUT_MS);
3760         mCm.unregisterNetworkCallback(callback);
3761 
3762         verifyNoNetwork();
3763         if (broadcastCV.block(10)) {
3764             fail("expected no broadcast, but got CONNECTIVITY_ACTION broadcast");
3765         }
3766     }
3767 
3768     @Test
testDeprecatedAndUnsupportedOperations()3769     public void testDeprecatedAndUnsupportedOperations() throws Exception {
3770         final int TYPE_NONE = ConnectivityManager.TYPE_NONE;
3771         assertNull(mCm.getNetworkInfo(TYPE_NONE));
3772         assertNull(mCm.getNetworkForType(TYPE_NONE));
3773         assertNull(mCm.getLinkProperties(TYPE_NONE));
3774         assertFalse(mCm.isNetworkSupported(TYPE_NONE));
3775 
3776         assertException(() -> { mCm.networkCapabilitiesForType(TYPE_NONE); },
3777                 IllegalArgumentException.class);
3778 
3779         Class<UnsupportedOperationException> unsupported = UnsupportedOperationException.class;
3780         assertException(() -> { mCm.startUsingNetworkFeature(TYPE_WIFI, ""); }, unsupported);
3781         assertException(() -> { mCm.stopUsingNetworkFeature(TYPE_WIFI, ""); }, unsupported);
3782         // TODO: let test context have configuration application target sdk version
3783         // and test that pre-M requesting for TYPE_NONE sends back APN_REQUEST_FAILED
3784         assertException(() -> { mCm.startUsingNetworkFeature(TYPE_NONE, ""); }, unsupported);
3785         assertException(() -> { mCm.stopUsingNetworkFeature(TYPE_NONE, ""); }, unsupported);
3786         assertException(() -> { mCm.requestRouteToHostAddress(TYPE_NONE, null); }, unsupported);
3787     }
3788 
3789     @Test
testLinkPropertiesEnsuresDirectlyConnectedRoutes()3790     public void testLinkPropertiesEnsuresDirectlyConnectedRoutes() {
3791         final NetworkRequest networkRequest = new NetworkRequest.Builder()
3792                 .addTransportType(TRANSPORT_WIFI).build();
3793         final TestNetworkCallback networkCallback = new TestNetworkCallback();
3794         mCm.registerNetworkCallback(networkRequest, networkCallback);
3795 
3796         LinkProperties lp = new LinkProperties();
3797         lp.setInterfaceName(WIFI_IFNAME);
3798         LinkAddress myIpv4Address = new LinkAddress("192.168.12.3/24");
3799         RouteInfo myIpv4DefaultRoute = new RouteInfo((IpPrefix) null,
3800                 NetworkUtils.numericToInetAddress("192.168.12.1"), lp.getInterfaceName());
3801         lp.addLinkAddress(myIpv4Address);
3802         lp.addRoute(myIpv4DefaultRoute);
3803 
3804         // Verify direct routes are added when network agent is first registered in
3805         // ConnectivityService.
3806         MockNetworkAgent networkAgent = new MockNetworkAgent(TRANSPORT_WIFI, lp);
3807         networkAgent.connect(true);
3808         networkCallback.expectCallback(CallbackState.AVAILABLE, networkAgent);
3809         networkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, networkAgent);
3810         CallbackInfo cbi = networkCallback.expectCallback(CallbackState.LINK_PROPERTIES,
3811                 networkAgent);
3812         networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, networkAgent);
3813         networkCallback.assertNoCallback();
3814         checkDirectlyConnectedRoutes(cbi.arg, Arrays.asList(myIpv4Address),
3815                 Arrays.asList(myIpv4DefaultRoute));
3816         checkDirectlyConnectedRoutes(mCm.getLinkProperties(networkAgent.getNetwork()),
3817                 Arrays.asList(myIpv4Address), Arrays.asList(myIpv4DefaultRoute));
3818 
3819         // Verify direct routes are added during subsequent link properties updates.
3820         LinkProperties newLp = new LinkProperties(lp);
3821         LinkAddress myIpv6Address1 = new LinkAddress("fe80::cafe/64");
3822         LinkAddress myIpv6Address2 = new LinkAddress("2001:db8::2/64");
3823         newLp.addLinkAddress(myIpv6Address1);
3824         newLp.addLinkAddress(myIpv6Address2);
3825         networkAgent.sendLinkProperties(newLp);
3826         cbi = networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, networkAgent);
3827         networkCallback.assertNoCallback();
3828         checkDirectlyConnectedRoutes(cbi.arg,
3829                 Arrays.asList(myIpv4Address, myIpv6Address1, myIpv6Address2),
3830                 Arrays.asList(myIpv4DefaultRoute));
3831         mCm.unregisterNetworkCallback(networkCallback);
3832     }
3833 
3834     @Test
testStatsIfacesChanged()3835     public void testStatsIfacesChanged() throws Exception {
3836         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
3837         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3838 
3839         Network[] onlyCell = new Network[]{mCellNetworkAgent.getNetwork()};
3840         Network[] onlyWifi = new Network[]{mWiFiNetworkAgent.getNetwork()};
3841 
3842         // Simple connection should have updated ifaces
3843         mCellNetworkAgent.connect(false);
3844         waitForIdle();
3845         verify(mStatsService, atLeastOnce()).forceUpdateIfaces(onlyCell);
3846         reset(mStatsService);
3847 
3848         // Default network switch should update ifaces.
3849         mWiFiNetworkAgent.connect(false);
3850         waitForIdle();
3851         verify(mStatsService, atLeastOnce()).forceUpdateIfaces(onlyWifi);
3852         reset(mStatsService);
3853 
3854         // Disconnect should update ifaces.
3855         mWiFiNetworkAgent.disconnect();
3856         waitForIdle();
3857         verify(mStatsService, atLeastOnce()).forceUpdateIfaces(onlyCell);
3858         reset(mStatsService);
3859 
3860         // Metered change should update ifaces
3861         mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
3862         waitForIdle();
3863         verify(mStatsService, atLeastOnce()).forceUpdateIfaces(onlyCell);
3864         reset(mStatsService);
3865 
3866         mCellNetworkAgent.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
3867         waitForIdle();
3868         verify(mStatsService, atLeastOnce()).forceUpdateIfaces(onlyCell);
3869         reset(mStatsService);
3870 
3871         // Captive portal change shouldn't update ifaces
3872         mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL);
3873         waitForIdle();
3874         verify(mStatsService, never()).forceUpdateIfaces(onlyCell);
3875         reset(mStatsService);
3876 
3877         // Roaming change should update ifaces
3878         mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING);
3879         waitForIdle();
3880         verify(mStatsService, atLeastOnce()).forceUpdateIfaces(onlyCell);
3881         reset(mStatsService);
3882     }
3883 
3884     @Test
testBasicDnsConfigurationPushed()3885     public void testBasicDnsConfigurationPushed() throws Exception {
3886         setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
3887         ArgumentCaptor<String[]> tlsServers = ArgumentCaptor.forClass(String[].class);
3888 
3889         // Clear any interactions that occur as a result of CS starting up.
3890         reset(mNetworkManagementService);
3891 
3892         final String[] EMPTY_STRING_ARRAY = new String[0];
3893         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
3894         waitForIdle();
3895         verify(mNetworkManagementService, never()).setDnsConfigurationForNetwork(
3896                 anyInt(), eq(EMPTY_STRING_ARRAY), any(), any(), eq(""), eq(EMPTY_STRING_ARRAY));
3897         verifyNoMoreInteractions(mNetworkManagementService);
3898 
3899         final LinkProperties cellLp = new LinkProperties();
3900         cellLp.setInterfaceName(MOBILE_IFNAME);
3901         // Add IPv4 and IPv6 default routes, because DNS-over-TLS code does
3902         // "is-reachable" testing in order to not program netd with unreachable
3903         // nameservers that it might try repeated to validate.
3904         cellLp.addLinkAddress(new LinkAddress("192.0.2.4/24"));
3905         cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("192.0.2.4"),
3906                 MOBILE_IFNAME));
3907         cellLp.addLinkAddress(new LinkAddress("2001:db8:1::1/64"));
3908         cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("2001:db8:1::1"),
3909                 MOBILE_IFNAME));
3910         mCellNetworkAgent.sendLinkProperties(cellLp);
3911         mCellNetworkAgent.connect(false);
3912         waitForIdle();
3913         // CS tells netd about the empty DNS config for this network.
3914         verify(mNetworkManagementService, atLeastOnce()).setDnsConfigurationForNetwork(
3915                 anyInt(), eq(EMPTY_STRING_ARRAY), any(), any(), eq(""), eq(EMPTY_STRING_ARRAY));
3916         reset(mNetworkManagementService);
3917 
3918         cellLp.addDnsServer(InetAddress.getByName("2001:db8::1"));
3919         mCellNetworkAgent.sendLinkProperties(cellLp);
3920         waitForIdle();
3921         verify(mNetworkManagementService, atLeastOnce()).setDnsConfigurationForNetwork(
3922                 anyInt(), mStringArrayCaptor.capture(), any(), any(),
3923                 eq(""), tlsServers.capture());
3924         assertEquals(1, mStringArrayCaptor.getValue().length);
3925         assertTrue(ArrayUtils.contains(mStringArrayCaptor.getValue(), "2001:db8::1"));
3926         // Opportunistic mode.
3927         assertTrue(ArrayUtils.contains(tlsServers.getValue(), "2001:db8::1"));
3928         reset(mNetworkManagementService);
3929 
3930         cellLp.addDnsServer(InetAddress.getByName("192.0.2.1"));
3931         mCellNetworkAgent.sendLinkProperties(cellLp);
3932         waitForIdle();
3933         verify(mNetworkManagementService, atLeastOnce()).setDnsConfigurationForNetwork(
3934                 anyInt(), mStringArrayCaptor.capture(), any(), any(),
3935                 eq(""), tlsServers.capture());
3936         assertEquals(2, mStringArrayCaptor.getValue().length);
3937         assertTrue(ArrayUtils.containsAll(mStringArrayCaptor.getValue(),
3938                 new String[]{"2001:db8::1", "192.0.2.1"}));
3939         // Opportunistic mode.
3940         assertEquals(2, tlsServers.getValue().length);
3941         assertTrue(ArrayUtils.containsAll(tlsServers.getValue(),
3942                 new String[]{"2001:db8::1", "192.0.2.1"}));
3943         reset(mNetworkManagementService);
3944 
3945         final String TLS_SPECIFIER = "tls.example.com";
3946         final String TLS_SERVER6 = "2001:db8:53::53";
3947         final InetAddress[] TLS_IPS = new InetAddress[]{ InetAddress.getByName(TLS_SERVER6) };
3948         final String[] TLS_SERVERS = new String[]{ TLS_SERVER6 };
3949         final Handler h = mCellNetworkAgent.getWrappedNetworkMonitor().connectivityHandler;
3950         h.sendMessage(h.obtainMessage(
3951                 NetworkMonitor.EVENT_PRIVATE_DNS_CONFIG_RESOLVED, 0,
3952                 mCellNetworkAgent.getNetwork().netId,
3953                 new DnsManager.PrivateDnsConfig(TLS_SPECIFIER, TLS_IPS)));
3954         waitForIdle();
3955         verify(mNetworkManagementService, atLeastOnce()).setDnsConfigurationForNetwork(
3956                 anyInt(), mStringArrayCaptor.capture(), any(), any(),
3957                 eq(TLS_SPECIFIER), eq(TLS_SERVERS));
3958         assertEquals(2, mStringArrayCaptor.getValue().length);
3959         assertTrue(ArrayUtils.containsAll(mStringArrayCaptor.getValue(),
3960                 new String[]{"2001:db8::1", "192.0.2.1"}));
3961         reset(mNetworkManagementService);
3962     }
3963 
3964     @Test
testPrivateDnsSettingsChange()3965     public void testPrivateDnsSettingsChange() throws Exception {
3966         final String[] EMPTY_STRING_ARRAY = new String[0];
3967         ArgumentCaptor<String[]> tlsServers = ArgumentCaptor.forClass(String[].class);
3968 
3969         // Clear any interactions that occur as a result of CS starting up.
3970         reset(mNetworkManagementService);
3971 
3972         // The default on Android is opportunistic mode ("Automatic").
3973         setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
3974 
3975         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
3976         final NetworkRequest cellRequest = new NetworkRequest.Builder()
3977                 .addTransportType(TRANSPORT_CELLULAR).build();
3978         mCm.requestNetwork(cellRequest, cellNetworkCallback);
3979 
3980         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
3981         waitForIdle();
3982         // CS tells netd about the empty DNS config for this network.
3983         verify(mNetworkManagementService, never()).setDnsConfigurationForNetwork(
3984                 anyInt(), eq(EMPTY_STRING_ARRAY), any(), any(), eq(""), eq(EMPTY_STRING_ARRAY));
3985         verifyNoMoreInteractions(mNetworkManagementService);
3986 
3987         final LinkProperties cellLp = new LinkProperties();
3988         cellLp.setInterfaceName(MOBILE_IFNAME);
3989         // Add IPv4 and IPv6 default routes, because DNS-over-TLS code does
3990         // "is-reachable" testing in order to not program netd with unreachable
3991         // nameservers that it might try repeated to validate.
3992         cellLp.addLinkAddress(new LinkAddress("192.0.2.4/24"));
3993         cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("192.0.2.4"),
3994                 MOBILE_IFNAME));
3995         cellLp.addLinkAddress(new LinkAddress("2001:db8:1::1/64"));
3996         cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("2001:db8:1::1"),
3997                 MOBILE_IFNAME));
3998         cellLp.addDnsServer(InetAddress.getByName("2001:db8::1"));
3999         cellLp.addDnsServer(InetAddress.getByName("192.0.2.1"));
4000 
4001         mCellNetworkAgent.sendLinkProperties(cellLp);
4002         mCellNetworkAgent.connect(true);
4003         waitForIdle();
4004         verify(mNetworkManagementService, atLeastOnce()).setDnsConfigurationForNetwork(
4005                 anyInt(), mStringArrayCaptor.capture(), any(), any(),
4006                 eq(""), tlsServers.capture());
4007         assertEquals(2, mStringArrayCaptor.getValue().length);
4008         assertTrue(ArrayUtils.containsAll(mStringArrayCaptor.getValue(),
4009                 new String[]{"2001:db8::1", "192.0.2.1"}));
4010         // Opportunistic mode.
4011         assertEquals(2, tlsServers.getValue().length);
4012         assertTrue(ArrayUtils.containsAll(tlsServers.getValue(),
4013                 new String[]{"2001:db8::1", "192.0.2.1"}));
4014         reset(mNetworkManagementService);
4015         cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
4016         cellNetworkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES,
4017                 mCellNetworkAgent);
4018         CallbackInfo cbi = cellNetworkCallback.expectCallback(
4019                 CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
4020         assertFalse(((LinkProperties)cbi.arg).isPrivateDnsActive());
4021         assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName());
4022         cellNetworkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, mCellNetworkAgent);
4023         cellNetworkCallback.assertNoCallback();
4024 
4025         setPrivateDnsSettings(PRIVATE_DNS_MODE_OFF, "ignored.example.com");
4026         verify(mNetworkManagementService, times(1)).setDnsConfigurationForNetwork(
4027                 anyInt(), mStringArrayCaptor.capture(), any(), any(),
4028                 eq(""), eq(EMPTY_STRING_ARRAY));
4029         assertEquals(2, mStringArrayCaptor.getValue().length);
4030         assertTrue(ArrayUtils.containsAll(mStringArrayCaptor.getValue(),
4031                 new String[]{"2001:db8::1", "192.0.2.1"}));
4032         reset(mNetworkManagementService);
4033         cellNetworkCallback.assertNoCallback();
4034 
4035         setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
4036         verify(mNetworkManagementService, atLeastOnce()).setDnsConfigurationForNetwork(
4037                 anyInt(), mStringArrayCaptor.capture(), any(), any(),
4038                 eq(""), tlsServers.capture());
4039         assertEquals(2, mStringArrayCaptor.getValue().length);
4040         assertTrue(ArrayUtils.containsAll(mStringArrayCaptor.getValue(),
4041                 new String[]{"2001:db8::1", "192.0.2.1"}));
4042         assertEquals(2, tlsServers.getValue().length);
4043         assertTrue(ArrayUtils.containsAll(tlsServers.getValue(),
4044                 new String[]{"2001:db8::1", "192.0.2.1"}));
4045         reset(mNetworkManagementService);
4046         cellNetworkCallback.assertNoCallback();
4047 
4048         // Strict mode.
4049         mCellNetworkAgent.getWrappedNetworkMonitor().dnsLookupResults = new InetAddress[] {
4050                 InetAddress.getByName("2001:db8::66"),
4051                 InetAddress.getByName("192.0.2.44")
4052         };
4053         setPrivateDnsSettings(PRIVATE_DNS_MODE_PROVIDER_HOSTNAME, "strict.example.com");
4054 
4055         // Expect a callback saying that private DNS is now in strict mode.
4056         cbi = cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES,
4057                 mCellNetworkAgent);
4058         LinkProperties lp = (LinkProperties) cbi.arg;
4059         assertTrue(lp.isPrivateDnsActive());
4060         assertEquals("strict.example.com", lp.getPrivateDnsServerName());
4061         cellNetworkCallback.assertNoCallback();
4062 
4063         // When the validation callback arrives, LinkProperties are updated.
4064         // We need to wait for this callback because the test thread races with the NetworkMonitor
4065         // thread, and if the test thread wins the race, then the times(2) verify call below will
4066         // fail.
4067         mService.mNetdEventCallback.onPrivateDnsValidationEvent(
4068                 mCellNetworkAgent.getNetwork().netId, "2001:db8::66", "strict.example.com", true);
4069         cbi = cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES,
4070                 mCellNetworkAgent);
4071         lp = (LinkProperties) cbi.arg;
4072         assertTrue(lp.isPrivateDnsActive());
4073         assertEquals(1, lp.getValidatedPrivateDnsServers().size());
4074 
4075         // setDnsConfigurationForNetwork is called twice: once when private DNS is set to strict
4076         // mode and once when the hostname resolves.
4077         verify(mNetworkManagementService, times(2)).setDnsConfigurationForNetwork(
4078                 anyInt(), mStringArrayCaptor.capture(), any(), any(),
4079                 eq("strict.example.com"), tlsServers.capture());
4080         assertEquals(2, mStringArrayCaptor.getValue().length);
4081         assertTrue(ArrayUtils.containsAll(mStringArrayCaptor.getValue(),
4082                 new String[]{"2001:db8::1", "192.0.2.1"}));
4083         assertEquals(2, tlsServers.getValue().length);
4084         assertTrue(ArrayUtils.containsAll(tlsServers.getValue(),
4085                 new String[]{"2001:db8::66", "192.0.2.44"}));
4086         reset(mNetworkManagementService);
4087 
4088         // Send the same LinkProperties and expect getting the same result including private dns.
4089         // b/118518971
4090         LinkProperties oldLp = (LinkProperties) cbi.arg;
4091         mCellNetworkAgent.sendLinkProperties(cellLp);
4092         waitForIdle();
4093         LinkProperties newLp = mCm.getLinkProperties(cbi.network);
4094         assertEquals(oldLp, newLp);
4095     }
4096 
4097     @Test
testLinkPropertiesWithPrivateDnsValidationEvents()4098     public void testLinkPropertiesWithPrivateDnsValidationEvents() throws Exception {
4099         // The default on Android is opportunistic mode ("Automatic").
4100         setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
4101 
4102         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
4103         final NetworkRequest cellRequest = new NetworkRequest.Builder()
4104                 .addTransportType(TRANSPORT_CELLULAR).build();
4105         mCm.requestNetwork(cellRequest, cellNetworkCallback);
4106 
4107         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
4108         waitForIdle();
4109         LinkProperties lp = new LinkProperties();
4110         mCellNetworkAgent.sendLinkProperties(lp);
4111         mCellNetworkAgent.connect(false);
4112         waitForIdle();
4113         cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
4114         cellNetworkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES,
4115                 mCellNetworkAgent);
4116         CallbackInfo cbi = cellNetworkCallback.expectCallback(
4117                 CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
4118         cellNetworkCallback.assertNoCallback();
4119         assertFalse(((LinkProperties)cbi.arg).isPrivateDnsActive());
4120         assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName());
4121         Set<InetAddress> dnsServers = new HashSet<>();
4122         checkDnsServers(cbi.arg, dnsServers);
4123 
4124         // Send a validation event for a server that is not part of the current
4125         // resolver config. The validation event should be ignored.
4126         mService.mNetdEventCallback.onPrivateDnsValidationEvent(
4127                 mCellNetworkAgent.getNetwork().netId, "", "145.100.185.18", true);
4128         cellNetworkCallback.assertNoCallback();
4129 
4130         // Add a dns server to the LinkProperties.
4131         LinkProperties lp2 = new LinkProperties(lp);
4132         lp2.addDnsServer(InetAddress.getByName("145.100.185.16"));
4133         mCellNetworkAgent.sendLinkProperties(lp2);
4134         cbi = cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES,
4135                 mCellNetworkAgent);
4136         cellNetworkCallback.assertNoCallback();
4137         assertFalse(((LinkProperties)cbi.arg).isPrivateDnsActive());
4138         assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName());
4139         dnsServers.add(InetAddress.getByName("145.100.185.16"));
4140         checkDnsServers(cbi.arg, dnsServers);
4141 
4142         // Send a validation event containing a hostname that is not part of
4143         // the current resolver config. The validation event should be ignored.
4144         mService.mNetdEventCallback.onPrivateDnsValidationEvent(
4145                 mCellNetworkAgent.getNetwork().netId, "145.100.185.16", "hostname", true);
4146         cellNetworkCallback.assertNoCallback();
4147 
4148         // Send a validation event where validation failed.
4149         mService.mNetdEventCallback.onPrivateDnsValidationEvent(
4150                 mCellNetworkAgent.getNetwork().netId, "145.100.185.16", "", false);
4151         cellNetworkCallback.assertNoCallback();
4152 
4153         // Send a validation event where validation succeeded for a server in
4154         // the current resolver config. A LinkProperties callback with updated
4155         // private dns fields should be sent.
4156         mService.mNetdEventCallback.onPrivateDnsValidationEvent(
4157                 mCellNetworkAgent.getNetwork().netId, "145.100.185.16", "", true);
4158         cbi = cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES,
4159                 mCellNetworkAgent);
4160         cellNetworkCallback.assertNoCallback();
4161         assertTrue(((LinkProperties)cbi.arg).isPrivateDnsActive());
4162         assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName());
4163         checkDnsServers(cbi.arg, dnsServers);
4164 
4165         // The private dns fields in LinkProperties should be preserved when
4166         // the network agent sends unrelated changes.
4167         LinkProperties lp3 = new LinkProperties(lp2);
4168         lp3.setMtu(1300);
4169         mCellNetworkAgent.sendLinkProperties(lp3);
4170         cbi = cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES,
4171                 mCellNetworkAgent);
4172         cellNetworkCallback.assertNoCallback();
4173         assertTrue(((LinkProperties)cbi.arg).isPrivateDnsActive());
4174         assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName());
4175         checkDnsServers(cbi.arg, dnsServers);
4176         assertEquals(1300, ((LinkProperties)cbi.arg).getMtu());
4177 
4178         // Removing the only validated server should affect the private dns
4179         // fields in LinkProperties.
4180         LinkProperties lp4 = new LinkProperties(lp3);
4181         lp4.removeDnsServer(InetAddress.getByName("145.100.185.16"));
4182         mCellNetworkAgent.sendLinkProperties(lp4);
4183         cbi = cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES,
4184                 mCellNetworkAgent);
4185         cellNetworkCallback.assertNoCallback();
4186         assertFalse(((LinkProperties)cbi.arg).isPrivateDnsActive());
4187         assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName());
4188         dnsServers.remove(InetAddress.getByName("145.100.185.16"));
4189         checkDnsServers(cbi.arg, dnsServers);
4190         assertEquals(1300, ((LinkProperties)cbi.arg).getMtu());
4191     }
4192 
checkDirectlyConnectedRoutes(Object callbackObj, Collection<LinkAddress> linkAddresses, Collection<RouteInfo> otherRoutes)4193     private void checkDirectlyConnectedRoutes(Object callbackObj,
4194             Collection<LinkAddress> linkAddresses, Collection<RouteInfo> otherRoutes) {
4195         assertTrue(callbackObj instanceof LinkProperties);
4196         LinkProperties lp = (LinkProperties) callbackObj;
4197 
4198         Set<RouteInfo> expectedRoutes = new ArraySet<>();
4199         expectedRoutes.addAll(otherRoutes);
4200         for (LinkAddress address : linkAddresses) {
4201             RouteInfo localRoute = new RouteInfo(address, null, lp.getInterfaceName());
4202             // Duplicates in linkAddresses are considered failures
4203             assertTrue(expectedRoutes.add(localRoute));
4204         }
4205         List<RouteInfo> observedRoutes = lp.getRoutes();
4206         assertEquals(expectedRoutes.size(), observedRoutes.size());
4207         assertTrue(observedRoutes.containsAll(expectedRoutes));
4208     }
4209 
checkDnsServers(Object callbackObj, Set<InetAddress> dnsServers)4210     private static void checkDnsServers(Object callbackObj, Set<InetAddress> dnsServers) {
4211         assertTrue(callbackObj instanceof LinkProperties);
4212         LinkProperties lp = (LinkProperties) callbackObj;
4213         assertEquals(dnsServers.size(), lp.getDnsServers().size());
4214         assertTrue(lp.getDnsServers().containsAll(dnsServers));
4215     }
4216 
assertEmpty(T[] ts)4217     private static <T> void assertEmpty(T[] ts) {
4218         int length = ts.length;
4219         assertEquals("expected empty array, but length was " + length, 0, length);
4220     }
4221 
assertLength(int expected, T[] got)4222     private static <T> void assertLength(int expected, T[] got) {
4223         int length = got.length;
4224         assertEquals(String.format("expected array of length %s, but length was %s for %s",
4225                 expected, length, Arrays.toString(got)), expected, length);
4226     }
4227 
assertException(Runnable block, Class<T> expected)4228     private static <T> void assertException(Runnable block, Class<T> expected) {
4229         try {
4230             block.run();
4231             fail("Expected exception of type " + expected);
4232         } catch (Exception got) {
4233             if (!got.getClass().equals(expected)) {
4234                 fail("Expected exception of type " + expected + " but got " + got);
4235             }
4236             return;
4237         }
4238     }
4239 
4240     @Test
testVpnNetworkActive()4241     public void testVpnNetworkActive() {
4242         final int uid = Process.myUid();
4243 
4244         final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback();
4245         final TestNetworkCallback genericNotVpnNetworkCallback = new TestNetworkCallback();
4246         final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
4247         final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
4248         final TestNetworkCallback defaultCallback = new TestNetworkCallback();
4249         final NetworkRequest genericNotVpnRequest = new NetworkRequest.Builder().build();
4250         final NetworkRequest genericRequest = new NetworkRequest.Builder()
4251                 .removeCapability(NET_CAPABILITY_NOT_VPN).build();
4252         final NetworkRequest wifiRequest = new NetworkRequest.Builder()
4253                 .addTransportType(TRANSPORT_WIFI).build();
4254         final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder()
4255                 .removeCapability(NET_CAPABILITY_NOT_VPN)
4256                 .addTransportType(TRANSPORT_VPN).build();
4257         mCm.registerNetworkCallback(genericRequest, genericNetworkCallback);
4258         mCm.registerNetworkCallback(genericNotVpnRequest, genericNotVpnNetworkCallback);
4259         mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
4260         mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
4261         mCm.registerDefaultNetworkCallback(defaultCallback);
4262         defaultCallback.assertNoCallback();
4263 
4264         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
4265         mWiFiNetworkAgent.connect(false);
4266 
4267         genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
4268         genericNotVpnNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
4269         wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
4270         defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
4271         vpnNetworkCallback.assertNoCallback();
4272         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
4273 
4274         final MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
4275         final ArraySet<UidRange> ranges = new ArraySet<>();
4276         ranges.add(new UidRange(uid, uid));
4277         mMockVpn.setNetworkAgent(vpnNetworkAgent);
4278         mMockVpn.setUids(ranges);
4279         vpnNetworkAgent.connect(false);
4280         mMockVpn.connect();
4281 
4282         genericNetworkCallback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
4283         genericNotVpnNetworkCallback.assertNoCallback();
4284         wifiNetworkCallback.assertNoCallback();
4285         vpnNetworkCallback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
4286         defaultCallback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
4287         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
4288 
4289         genericNetworkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, vpnNetworkAgent);
4290         genericNotVpnNetworkCallback.assertNoCallback();
4291         vpnNetworkCallback.expectCapabilitiesLike(nc -> null == nc.getUids(), vpnNetworkAgent);
4292         defaultCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, vpnNetworkAgent);
4293         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
4294 
4295         ranges.clear();
4296         vpnNetworkAgent.setUids(ranges);
4297 
4298         genericNetworkCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
4299         genericNotVpnNetworkCallback.assertNoCallback();
4300         wifiNetworkCallback.assertNoCallback();
4301         vpnNetworkCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
4302 
4303         // TODO : The default network callback should actually get a LOST call here (also see the
4304         // comment below for AVAILABLE). This is because ConnectivityService does not look at UID
4305         // ranges at all when determining whether a network should be rematched. In practice, VPNs
4306         // can't currently update their UIDs without disconnecting, so this does not matter too
4307         // much, but that is the reason the test here has to check for an update to the
4308         // capabilities instead of the expected LOST then AVAILABLE.
4309         defaultCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, vpnNetworkAgent);
4310 
4311         ranges.add(new UidRange(uid, uid));
4312         mMockVpn.setUids(ranges);
4313 
4314         genericNetworkCallback.expectAvailableCallbacksValidated(vpnNetworkAgent);
4315         genericNotVpnNetworkCallback.assertNoCallback();
4316         wifiNetworkCallback.assertNoCallback();
4317         vpnNetworkCallback.expectAvailableCallbacksValidated(vpnNetworkAgent);
4318         // TODO : Here like above, AVAILABLE would be correct, but because this can't actually
4319         // happen outside of the test, ConnectivityService does not rematch callbacks.
4320         defaultCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, vpnNetworkAgent);
4321 
4322         mWiFiNetworkAgent.disconnect();
4323 
4324         genericNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
4325         genericNotVpnNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
4326         wifiNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
4327         vpnNetworkCallback.assertNoCallback();
4328         defaultCallback.assertNoCallback();
4329 
4330         vpnNetworkAgent.disconnect();
4331 
4332         genericNetworkCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
4333         genericNotVpnNetworkCallback.assertNoCallback();
4334         wifiNetworkCallback.assertNoCallback();
4335         vpnNetworkCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
4336         defaultCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
4337         assertEquals(null, mCm.getActiveNetwork());
4338 
4339         mCm.unregisterNetworkCallback(genericNetworkCallback);
4340         mCm.unregisterNetworkCallback(wifiNetworkCallback);
4341         mCm.unregisterNetworkCallback(vpnNetworkCallback);
4342         mCm.unregisterNetworkCallback(defaultCallback);
4343     }
4344 
4345     @Test
testVpnWithAndWithoutInternet()4346     public void testVpnWithAndWithoutInternet() {
4347         final int uid = Process.myUid();
4348 
4349         final TestNetworkCallback defaultCallback = new TestNetworkCallback();
4350         mCm.registerDefaultNetworkCallback(defaultCallback);
4351         defaultCallback.assertNoCallback();
4352 
4353         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
4354         mWiFiNetworkAgent.connect(true);
4355 
4356         defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
4357         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
4358 
4359         MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
4360         final ArraySet<UidRange> ranges = new ArraySet<>();
4361         ranges.add(new UidRange(uid, uid));
4362         mMockVpn.setNetworkAgent(vpnNetworkAgent);
4363         mMockVpn.setUids(ranges);
4364         vpnNetworkAgent.connect(true /* validated */, false /* hasInternet */);
4365         mMockVpn.connect();
4366 
4367         defaultCallback.assertNoCallback();
4368         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
4369 
4370         vpnNetworkAgent.disconnect();
4371         defaultCallback.assertNoCallback();
4372 
4373         vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
4374         mMockVpn.setNetworkAgent(vpnNetworkAgent);
4375         mMockVpn.setUids(ranges);
4376         vpnNetworkAgent.connect(true /* validated */, true /* hasInternet */);
4377         mMockVpn.connect();
4378         defaultCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
4379         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
4380 
4381         vpnNetworkAgent.disconnect();
4382         defaultCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
4383         defaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
4384 
4385         vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
4386         ranges.clear();
4387         mMockVpn.setNetworkAgent(vpnNetworkAgent);
4388         mMockVpn.setUids(ranges);
4389         vpnNetworkAgent.connect(false /* validated */, true /* hasInternet */);
4390         mMockVpn.connect();
4391         defaultCallback.assertNoCallback();
4392 
4393         mCm.unregisterNetworkCallback(defaultCallback);
4394     }
4395 
4396     @Test
testVpnUnvalidated()4397     public void testVpnUnvalidated() throws Exception {
4398         final TestNetworkCallback callback = new TestNetworkCallback();
4399         mCm.registerDefaultNetworkCallback(callback);
4400 
4401         // Enable private DNS.
4402         setPrivateDnsSettings(PRIVATE_DNS_MODE_PROVIDER_HOSTNAME, "strict.example.com");
4403 
4404         // Bring up Ethernet.
4405         mEthernetNetworkAgent = new MockNetworkAgent(TRANSPORT_ETHERNET);
4406         mEthernetNetworkAgent.getWrappedNetworkMonitor().dnsLookupResults =
4407                 new InetAddress[]{ InetAddress.getByName("2001:db8::1") };
4408         mEthernetNetworkAgent.connect(true);
4409         callback.expectAvailableThenValidatedCallbacks(mEthernetNetworkAgent);
4410         callback.assertNoCallback();
4411 
4412         // Bring up a VPN that has the INTERNET capability but does not validate.
4413         final int uid = Process.myUid();
4414         final MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
4415         vpnNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 500;
4416         vpnNetworkAgent.getWrappedNetworkMonitor().dnsLookupResults = null;
4417 
4418         final ArraySet<UidRange> ranges = new ArraySet<>();
4419         ranges.add(new UidRange(uid, uid));
4420         mMockVpn.setNetworkAgent(vpnNetworkAgent);
4421         mMockVpn.setUids(ranges);
4422         vpnNetworkAgent.connect(false /* validated */, true /* hasInternet */);
4423         mMockVpn.connect();
4424 
4425         // Even though the VPN is unvalidated, it becomes the default network for our app.
4426         callback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
4427         // TODO: this looks like a spurious callback.
4428         callback.expectCallback(CallbackState.NETWORK_CAPABILITIES, vpnNetworkAgent);
4429         callback.assertNoCallback();
4430 
4431         assertTrue(vpnNetworkAgent.getScore() > mEthernetNetworkAgent.getScore());
4432         assertEquals(ConnectivityConstants.VPN_DEFAULT_SCORE, vpnNetworkAgent.getScore());
4433         assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
4434 
4435         NetworkCapabilities nc = mCm.getNetworkCapabilities(vpnNetworkAgent.getNetwork());
4436         assertFalse(nc.hasCapability(NET_CAPABILITY_VALIDATED));
4437         assertTrue(nc.hasCapability(NET_CAPABILITY_INTERNET));
4438 
4439         assertFalse(vpnNetworkAgent.getWrappedNetworkMonitor().isValidationRequired());
4440         assertTrue(vpnNetworkAgent.getWrappedNetworkMonitor().isPrivateDnsValidationRequired());
4441 
4442         // Pretend that the strict mode private DNS hostname now resolves. Even though the
4443         // connectivity probe still returns 500, the network validates because the connectivity
4444         // probe is not used on VPNs.
4445         vpnNetworkAgent.getWrappedNetworkMonitor().dnsLookupResults =
4446                 new InetAddress[]{ InetAddress.getByName("2001:db8::1") };
4447         mCm.reportNetworkConnectivity(vpnNetworkAgent.getNetwork(), true);
4448 
4449         // Expect to see the validated capability, but no other changes, because the VPN is already
4450         // the default network for the app.
4451         callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, vpnNetworkAgent);
4452         callback.assertNoCallback();
4453 
4454         vpnNetworkAgent.disconnect();
4455         callback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
4456         callback.expectAvailableCallbacksValidated(mEthernetNetworkAgent);
4457     }
4458 
4459     @Test
testVpnSetUnderlyingNetworks()4460     public void testVpnSetUnderlyingNetworks() {
4461         final int uid = Process.myUid();
4462 
4463         final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
4464         final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder()
4465                 .removeCapability(NET_CAPABILITY_NOT_VPN)
4466                 .addTransportType(TRANSPORT_VPN)
4467                 .build();
4468         NetworkCapabilities nc;
4469         mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
4470         vpnNetworkCallback.assertNoCallback();
4471 
4472         final MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
4473         final ArraySet<UidRange> ranges = new ArraySet<>();
4474         ranges.add(new UidRange(uid, uid));
4475         mMockVpn.setNetworkAgent(vpnNetworkAgent);
4476         mMockVpn.connect();
4477         mMockVpn.setUids(ranges);
4478         vpnNetworkAgent.connect(true /* validated */, false /* hasInternet */);
4479 
4480         vpnNetworkCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
4481         nc = mCm.getNetworkCapabilities(vpnNetworkAgent.getNetwork());
4482         assertTrue(nc.hasTransport(TRANSPORT_VPN));
4483         assertFalse(nc.hasTransport(TRANSPORT_CELLULAR));
4484         assertFalse(nc.hasTransport(TRANSPORT_WIFI));
4485         // For safety reasons a VPN without underlying networks is considered metered.
4486         assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED));
4487 
4488         // Connect cell and use it as an underlying network.
4489         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
4490         mCellNetworkAgent.connect(true);
4491 
4492         mService.setUnderlyingNetworksForVpn(
4493                 new Network[] { mCellNetworkAgent.getNetwork() });
4494 
4495         vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
4496                 && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
4497                 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
4498                 vpnNetworkAgent);
4499 
4500         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
4501         mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
4502         mWiFiNetworkAgent.connect(true);
4503 
4504         mService.setUnderlyingNetworksForVpn(
4505                 new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() });
4506 
4507         vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
4508                 && caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
4509                 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
4510                 vpnNetworkAgent);
4511 
4512         // Don't disconnect, but note the VPN is not using wifi any more.
4513         mService.setUnderlyingNetworksForVpn(
4514                 new Network[] { mCellNetworkAgent.getNetwork() });
4515 
4516         vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
4517                 && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
4518                 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
4519                 vpnNetworkAgent);
4520 
4521         // Use Wifi but not cell. Note the VPN is now unmetered.
4522         mService.setUnderlyingNetworksForVpn(
4523                 new Network[] { mWiFiNetworkAgent.getNetwork() });
4524 
4525         vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
4526                 && !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
4527                 && caps.hasCapability(NET_CAPABILITY_NOT_METERED),
4528                 vpnNetworkAgent);
4529 
4530         // Use both again.
4531         mService.setUnderlyingNetworksForVpn(
4532                 new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() });
4533 
4534         vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
4535                 && caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
4536                 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
4537                 vpnNetworkAgent);
4538 
4539         // Disconnect cell. Receive update without even removing the dead network from the
4540         // underlying networks – it's dead anyway. Not metered any more.
4541         mCellNetworkAgent.disconnect();
4542         vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
4543                 && !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
4544                 && caps.hasCapability(NET_CAPABILITY_NOT_METERED),
4545                 vpnNetworkAgent);
4546 
4547         // Disconnect wifi too. No underlying networks means this is now metered.
4548         mWiFiNetworkAgent.disconnect();
4549         vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
4550                 && !caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
4551                 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
4552                 vpnNetworkAgent);
4553 
4554         mMockVpn.disconnect();
4555     }
4556 }
4557