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