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.content.pm.PackageManager.GET_PERMISSIONS;
20 import static android.content.pm.PackageManager.MATCH_ANY_USER;
21 import static android.net.ConnectivityManager.ACTION_CAPTIVE_PORTAL_SIGN_IN;
22 import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
23 import static android.net.ConnectivityManager.NETID_UNSET;
24 import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OFF;
25 import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OPPORTUNISTIC;
26 import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_PROVIDER_HOSTNAME;
27 import static android.net.ConnectivityManager.TYPE_ETHERNET;
28 import static android.net.ConnectivityManager.TYPE_MOBILE;
29 import static android.net.ConnectivityManager.TYPE_MOBILE_FOTA;
30 import static android.net.ConnectivityManager.TYPE_MOBILE_MMS;
31 import static android.net.ConnectivityManager.TYPE_NONE;
32 import static android.net.ConnectivityManager.TYPE_VPN;
33 import static android.net.ConnectivityManager.TYPE_WIFI;
34 import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_DNS;
35 import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_FALLBACK;
36 import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_HTTP;
37 import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_HTTPS;
38 import static android.net.INetworkMonitor.NETWORK_VALIDATION_RESULT_PARTIAL;
39 import static android.net.INetworkMonitor.NETWORK_VALIDATION_RESULT_VALID;
40 import static android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL;
41 import static android.net.NetworkCapabilities.NET_CAPABILITY_CBS;
42 import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN;
43 import static android.net.NetworkCapabilities.NET_CAPABILITY_EIMS;
44 import static android.net.NetworkCapabilities.NET_CAPABILITY_FOREGROUND;
45 import static android.net.NetworkCapabilities.NET_CAPABILITY_FOTA;
46 import static android.net.NetworkCapabilities.NET_CAPABILITY_IA;
47 import static android.net.NetworkCapabilities.NET_CAPABILITY_IMS;
48 import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
49 import static android.net.NetworkCapabilities.NET_CAPABILITY_MMS;
50 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
51 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
52 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED;
53 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN;
54 import static android.net.NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVITY;
55 import static android.net.NetworkCapabilities.NET_CAPABILITY_RCS;
56 import static android.net.NetworkCapabilities.NET_CAPABILITY_SUPL;
57 import static android.net.NetworkCapabilities.NET_CAPABILITY_TRUSTED;
58 import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
59 import static android.net.NetworkCapabilities.NET_CAPABILITY_WIFI_P2P;
60 import static android.net.NetworkCapabilities.NET_CAPABILITY_XCAP;
61 import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
62 import static android.net.NetworkCapabilities.TRANSPORT_ETHERNET;
63 import static android.net.NetworkCapabilities.TRANSPORT_VPN;
64 import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
65 import static android.net.NetworkCapabilities.TRANSPORT_WIFI_AWARE;
66 import static android.net.NetworkPolicyManager.RULE_ALLOW_METERED;
67 import static android.net.NetworkPolicyManager.RULE_NONE;
68 import static android.net.NetworkPolicyManager.RULE_REJECT_ALL;
69 import static android.net.NetworkPolicyManager.RULE_REJECT_METERED;
70 import static android.net.RouteInfo.RTN_UNREACHABLE;
71 
72 import static com.android.internal.util.TestUtils.waitForIdleHandler;
73 import static com.android.internal.util.TestUtils.waitForIdleLooper;
74 import static com.android.internal.util.TestUtils.waitForIdleSerialExecutor;
75 
76 import static org.junit.Assert.assertArrayEquals;
77 import static org.junit.Assert.assertEquals;
78 import static org.junit.Assert.assertFalse;
79 import static org.junit.Assert.assertNotEquals;
80 import static org.junit.Assert.assertNotNull;
81 import static org.junit.Assert.assertNull;
82 import static org.junit.Assert.assertTrue;
83 import static org.junit.Assert.fail;
84 import static org.mockito.ArgumentMatchers.anyString;
85 import static org.mockito.ArgumentMatchers.eq;
86 import static org.mockito.Matchers.anyInt;
87 import static org.mockito.Mockito.any;
88 import static org.mockito.Mockito.atLeastOnce;
89 import static org.mockito.Mockito.doAnswer;
90 import static org.mockito.Mockito.doNothing;
91 import static org.mockito.Mockito.inOrder;
92 import static org.mockito.Mockito.mock;
93 import static org.mockito.Mockito.never;
94 import static org.mockito.Mockito.reset;
95 import static org.mockito.Mockito.spy;
96 import static org.mockito.Mockito.timeout;
97 import static org.mockito.Mockito.times;
98 import static org.mockito.Mockito.verify;
99 import static org.mockito.Mockito.verifyNoMoreInteractions;
100 import static org.mockito.Mockito.when;
101 
102 import android.annotation.NonNull;
103 import android.app.NotificationManager;
104 import android.app.PendingIntent;
105 import android.content.BroadcastReceiver;
106 import android.content.ContentProvider;
107 import android.content.ContentResolver;
108 import android.content.Context;
109 import android.content.Intent;
110 import android.content.IntentFilter;
111 import android.content.pm.ApplicationInfo;
112 import android.content.pm.PackageInfo;
113 import android.content.pm.PackageManager;
114 import android.content.pm.UserInfo;
115 import android.content.res.Resources;
116 import android.net.ConnectivityManager;
117 import android.net.ConnectivityManager.NetworkCallback;
118 import android.net.ConnectivityManager.PacketKeepalive;
119 import android.net.ConnectivityManager.PacketKeepaliveCallback;
120 import android.net.ConnectivityManager.TooManyRequestsException;
121 import android.net.ConnectivityThread;
122 import android.net.IDnsResolver;
123 import android.net.INetd;
124 import android.net.INetworkMonitor;
125 import android.net.INetworkMonitorCallbacks;
126 import android.net.INetworkPolicyListener;
127 import android.net.INetworkPolicyManager;
128 import android.net.INetworkStatsService;
129 import android.net.InterfaceConfiguration;
130 import android.net.IpPrefix;
131 import android.net.IpSecManager;
132 import android.net.IpSecManager.UdpEncapsulationSocket;
133 import android.net.LinkAddress;
134 import android.net.LinkProperties;
135 import android.net.MatchAllNetworkSpecifier;
136 import android.net.Network;
137 import android.net.NetworkAgent;
138 import android.net.NetworkCapabilities;
139 import android.net.NetworkFactory;
140 import android.net.NetworkInfo;
141 import android.net.NetworkInfo.DetailedState;
142 import android.net.NetworkMisc;
143 import android.net.NetworkRequest;
144 import android.net.NetworkSpecifier;
145 import android.net.NetworkStack;
146 import android.net.NetworkStackClient;
147 import android.net.NetworkState;
148 import android.net.NetworkUtils;
149 import android.net.ProxyInfo;
150 import android.net.ResolverParamsParcel;
151 import android.net.RouteInfo;
152 import android.net.SocketKeepalive;
153 import android.net.UidRange;
154 import android.net.metrics.IpConnectivityLog;
155 import android.net.shared.NetworkMonitorUtils;
156 import android.net.shared.PrivateDnsConfig;
157 import android.net.util.MultinetworkPolicyTracker;
158 import android.os.Binder;
159 import android.os.Bundle;
160 import android.os.ConditionVariable;
161 import android.os.Handler;
162 import android.os.HandlerThread;
163 import android.os.INetworkManagementService;
164 import android.os.Looper;
165 import android.os.Message;
166 import android.os.Parcel;
167 import android.os.ParcelFileDescriptor;
168 import android.os.Parcelable;
169 import android.os.Process;
170 import android.os.RemoteException;
171 import android.os.SystemClock;
172 import android.os.UserHandle;
173 import android.os.UserManager;
174 import android.provider.Settings;
175 import android.system.Os;
176 import android.test.mock.MockContentResolver;
177 import android.text.TextUtils;
178 import android.util.ArraySet;
179 import android.util.Log;
180 import android.util.SparseArray;
181 
182 import androidx.test.InstrumentationRegistry;
183 import androidx.test.filters.SmallTest;
184 import androidx.test.runner.AndroidJUnit4;
185 
186 import com.android.internal.net.VpnConfig;
187 import com.android.internal.net.VpnInfo;
188 import com.android.internal.util.ArrayUtils;
189 import com.android.internal.util.WakeupMessage;
190 import com.android.internal.util.test.BroadcastInterceptingContext;
191 import com.android.internal.util.test.FakeSettingsProvider;
192 import com.android.server.connectivity.ConnectivityConstants;
193 import com.android.server.connectivity.DefaultNetworkMetrics;
194 import com.android.server.connectivity.IpConnectivityMetrics;
195 import com.android.server.connectivity.MockableSystemProperties;
196 import com.android.server.connectivity.Nat464Xlat;
197 import com.android.server.connectivity.NetworkNotificationManager.NotificationType;
198 import com.android.server.connectivity.ProxyTracker;
199 import com.android.server.connectivity.Tethering;
200 import com.android.server.connectivity.Vpn;
201 import com.android.server.net.NetworkPinner;
202 import com.android.server.net.NetworkPolicyManagerInternal;
203 
204 import org.junit.After;
205 import org.junit.Before;
206 import org.junit.Ignore;
207 import org.junit.Test;
208 import org.junit.runner.RunWith;
209 import org.mockito.ArgumentCaptor;
210 import org.mockito.InOrder;
211 import org.mockito.Mock;
212 import org.mockito.MockitoAnnotations;
213 import org.mockito.Spy;
214 import org.mockito.stubbing.Answer;
215 
216 import java.io.IOException;
217 import java.net.DatagramSocket;
218 import java.net.Inet4Address;
219 import java.net.Inet6Address;
220 import java.net.InetAddress;
221 import java.net.InetSocketAddress;
222 import java.net.Socket;
223 import java.net.UnknownHostException;
224 import java.util.ArrayList;
225 import java.util.Arrays;
226 import java.util.Collection;
227 import java.util.Collections;
228 import java.util.HashSet;
229 import java.util.List;
230 import java.util.Objects;
231 import java.util.Set;
232 import java.util.concurrent.CountDownLatch;
233 import java.util.concurrent.Executor;
234 import java.util.concurrent.ExecutorService;
235 import java.util.concurrent.Executors;
236 import java.util.concurrent.LinkedBlockingQueue;
237 import java.util.concurrent.TimeUnit;
238 import java.util.concurrent.atomic.AtomicBoolean;
239 import java.util.function.Predicate;
240 
241 /**
242  * Tests for {@link ConnectivityService}.
243  *
244  * Build, install and run with:
245  *  runtest frameworks-net -c com.android.server.ConnectivityServiceTest
246  */
247 @RunWith(AndroidJUnit4.class)
248 @SmallTest
249 public class ConnectivityServiceTest {
250     private static final String TAG = "ConnectivityServiceTest";
251 
252     private static final int TIMEOUT_MS = 500;
253     private static final int TEST_LINGER_DELAY_MS = 250;
254     // Chosen to be less than the linger timeout. This ensures that we can distinguish between a
255     // LOST callback that arrives immediately and a LOST callback that arrives after the linger
256     // timeout. For this, our assertions should run fast enough to leave less than
257     // (mService.mLingerDelayMs - TEST_CALLBACK_TIMEOUT_MS) between the time callbacks are
258     // supposedly fired, and the time we call expectCallback.
259     private final static int TEST_CALLBACK_TIMEOUT_MS = 200;
260     // Chosen to be less than TEST_CALLBACK_TIMEOUT_MS. This ensures that requests have time to
261     // complete before callbacks are verified.
262     private final static int TEST_REQUEST_TIMEOUT_MS = 150;
263 
264     private static final String CLAT_PREFIX = "v4-";
265     private static final String MOBILE_IFNAME = "test_rmnet_data0";
266     private static final String WIFI_IFNAME = "test_wlan0";
267     private static final String[] EMPTY_STRING_ARRAY = new String[0];
268 
269     private MockContext mServiceContext;
270     private WrappedConnectivityService mService;
271     private WrappedConnectivityManager mCm;
272     private MockNetworkAgent mWiFiNetworkAgent;
273     private MockNetworkAgent mCellNetworkAgent;
274     private MockNetworkAgent mEthernetNetworkAgent;
275     private MockVpn mMockVpn;
276     private Context mContext;
277     private INetworkPolicyListener mPolicyListener;
278 
279     @Mock IpConnectivityMetrics.Logger mMetricsService;
280     @Mock DefaultNetworkMetrics mDefaultNetworkMetrics;
281     @Mock INetworkManagementService mNetworkManagementService;
282     @Mock INetworkStatsService mStatsService;
283     @Mock INetworkPolicyManager mNpm;
284     @Mock IDnsResolver mMockDnsResolver;
285     @Mock INetd mMockNetd;
286     @Mock NetworkStackClient mNetworkStack;
287     @Mock PackageManager mPackageManager;
288     @Mock UserManager mUserManager;
289     @Mock NotificationManager mNotificationManager;
290 
291     private ArgumentCaptor<ResolverParamsParcel> mResolverParamsParcelCaptor =
292             ArgumentCaptor.forClass(ResolverParamsParcel.class);
293 
294     // This class exists to test bindProcessToNetwork and getBoundNetworkForProcess. These methods
295     // do not go through ConnectivityService but talk to netd directly, so they don't automatically
296     // reflect the state of our test ConnectivityService.
297     private class WrappedConnectivityManager extends ConnectivityManager {
298         private Network mFakeBoundNetwork;
299 
bindProcessToNetwork(Network network)300         public synchronized boolean bindProcessToNetwork(Network network) {
301             mFakeBoundNetwork = network;
302             return true;
303         }
304 
getBoundNetworkForProcess()305         public synchronized Network getBoundNetworkForProcess() {
306             return mFakeBoundNetwork;
307         }
308 
WrappedConnectivityManager(Context context, ConnectivityService service)309         public WrappedConnectivityManager(Context context, ConnectivityService service) {
310             super(context, service);
311         }
312     }
313 
314     private class MockContext extends BroadcastInterceptingContext {
315         private final MockContentResolver mContentResolver;
316 
317         @Spy private Resources mResources;
318         private final LinkedBlockingQueue<Intent> mStartedActivities = new LinkedBlockingQueue<>();
319 
MockContext(Context base, ContentProvider settingsProvider)320         MockContext(Context base, ContentProvider settingsProvider) {
321             super(base);
322 
323             mResources = spy(base.getResources());
324             when(mResources.getStringArray(com.android.internal.R.array.networkAttributes)).
325                     thenReturn(new String[] {
326                             "wifi,1,1,1,-1,true",
327                             "mobile,0,0,0,-1,true",
328                             "mobile_mms,2,0,2,60000,true",
329                     });
330 
331             mContentResolver = new MockContentResolver();
332             mContentResolver.addProvider(Settings.AUTHORITY, settingsProvider);
333         }
334 
335         @Override
startActivityAsUser(Intent intent, UserHandle handle)336         public void startActivityAsUser(Intent intent, UserHandle handle) {
337             mStartedActivities.offer(intent);
338         }
339 
expectStartActivityIntent(int timeoutMs)340         public Intent expectStartActivityIntent(int timeoutMs) {
341             Intent intent = null;
342             try {
343                 intent = mStartedActivities.poll(timeoutMs, TimeUnit.MILLISECONDS);
344             } catch (InterruptedException e) {}
345             assertNotNull("Did not receive sign-in intent after " + timeoutMs + "ms", intent);
346             return intent;
347         }
348 
expectNoStartActivityIntent(int timeoutMs)349         public void expectNoStartActivityIntent(int timeoutMs) {
350             try {
351                 assertNull("Received unexpected Intent to start activity",
352                         mStartedActivities.poll(timeoutMs, TimeUnit.MILLISECONDS));
353             } catch (InterruptedException e) {}
354         }
355 
356         @Override
getSystemService(String name)357         public Object getSystemService(String name) {
358             if (Context.CONNECTIVITY_SERVICE.equals(name)) return mCm;
359             if (Context.NOTIFICATION_SERVICE.equals(name)) return mNotificationManager;
360             if (Context.NETWORK_STACK_SERVICE.equals(name)) return mNetworkStack;
361             if (Context.USER_SERVICE.equals(name)) return mUserManager;
362             return super.getSystemService(name);
363         }
364 
365         @Override
getContentResolver()366         public ContentResolver getContentResolver() {
367             return mContentResolver;
368         }
369 
370         @Override
getResources()371         public Resources getResources() {
372             return mResources;
373         }
374 
375         @Override
getPackageManager()376         public PackageManager getPackageManager() {
377             return mPackageManager;
378         }
379 
380         @Override
enforceCallingOrSelfPermission(String permission, String message)381         public void enforceCallingOrSelfPermission(String permission, String message) {
382             // The mainline permission can only be held if signed with the network stack certificate
383             // Skip testing for this permission.
384             if (NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK.equals(permission)) return;
385             // All other permissions should be held by the test or unnecessary: check as normal to
386             // make sure the code does not rely on unexpected permissions.
387             super.enforceCallingOrSelfPermission(permission, message);
388         }
389     }
390 
waitForIdle(int timeoutMsAsInt)391     public void waitForIdle(int timeoutMsAsInt) {
392         long timeoutMs = timeoutMsAsInt;
393         waitForIdleHandler(mService.mHandlerThread, timeoutMs);
394         waitForIdle(mCellNetworkAgent, timeoutMs);
395         waitForIdle(mWiFiNetworkAgent, timeoutMs);
396         waitForIdle(mEthernetNetworkAgent, timeoutMs);
397         waitForIdleHandler(mService.mHandlerThread, timeoutMs);
398         waitForIdleLooper(ConnectivityThread.getInstanceLooper(), timeoutMs);
399     }
400 
waitForIdle(MockNetworkAgent agent, long timeoutMs)401     public void waitForIdle(MockNetworkAgent agent, long timeoutMs) {
402         if (agent == null) {
403             return;
404         }
405         waitForIdleHandler(agent.mHandlerThread, timeoutMs);
406     }
407 
waitForIdle()408     private void waitForIdle() {
409         waitForIdle(TIMEOUT_MS);
410     }
411 
412     @Test
testWaitForIdle()413     public void testWaitForIdle() {
414         final int attempts = 50;  // Causes the test to take about 200ms on bullhead-eng.
415 
416         // Tests that waitForIdle returns immediately if the service is already idle.
417         for (int i = 0; i < attempts; i++) {
418             waitForIdle();
419         }
420 
421         // Bring up a network that we can use to send messages to ConnectivityService.
422         ConditionVariable cv = waitForConnectivityBroadcasts(1);
423         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
424         mWiFiNetworkAgent.connect(false);
425         waitFor(cv);
426         Network n = mWiFiNetworkAgent.getNetwork();
427         assertNotNull(n);
428 
429         // Tests that calling waitForIdle waits for messages to be processed.
430         for (int i = 0; i < attempts; i++) {
431             mWiFiNetworkAgent.setSignalStrength(i);
432             waitForIdle();
433             assertEquals(i, mCm.getNetworkCapabilities(n).getSignalStrength());
434         }
435     }
436 
437     // This test has an inherent race condition in it, and cannot be enabled for continuous testing
438     // or presubmit tests. It is kept for manual runs and documentation purposes.
439     @Ignore
verifyThatNotWaitingForIdleCausesRaceConditions()440     public void verifyThatNotWaitingForIdleCausesRaceConditions() {
441         // Bring up a network that we can use to send messages to ConnectivityService.
442         ConditionVariable cv = waitForConnectivityBroadcasts(1);
443         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
444         mWiFiNetworkAgent.connect(false);
445         waitFor(cv);
446         Network n = mWiFiNetworkAgent.getNetwork();
447         assertNotNull(n);
448 
449         // Ensure that not calling waitForIdle causes a race condition.
450         final int attempts = 50;  // Causes the test to take about 200ms on bullhead-eng.
451         for (int i = 0; i < attempts; i++) {
452             mWiFiNetworkAgent.setSignalStrength(i);
453             if (i != mCm.getNetworkCapabilities(n).getSignalStrength()) {
454                 // We hit a race condition, as expected. Pass the test.
455                 return;
456             }
457         }
458 
459         // No race? There is a bug in this test.
460         fail("expected race condition at least once in " + attempts + " attempts");
461     }
462 
463     private class MockNetworkAgent {
464         private static final int VALIDATION_RESULT_BASE = NETWORK_VALIDATION_PROBE_DNS
465                 | NETWORK_VALIDATION_PROBE_HTTP
466                 | NETWORK_VALIDATION_PROBE_HTTPS;
467         private static final int VALIDATION_RESULT_VALID = VALIDATION_RESULT_BASE
468                 | NETWORK_VALIDATION_RESULT_VALID;
469         private static final int VALIDATION_RESULT_PARTIAL = VALIDATION_RESULT_BASE
470                 | NETWORK_VALIDATION_PROBE_FALLBACK
471                 | NETWORK_VALIDATION_RESULT_PARTIAL;
472         private static final int VALIDATION_RESULT_INVALID = 0;
473 
474         private final INetworkMonitor mNetworkMonitor;
475         private final NetworkInfo mNetworkInfo;
476         private final NetworkCapabilities mNetworkCapabilities;
477         private final HandlerThread mHandlerThread;
478         private final ConditionVariable mDisconnected = new ConditionVariable();
479         private final ConditionVariable mNetworkStatusReceived = new ConditionVariable();
480         private final ConditionVariable mPreventReconnectReceived = new ConditionVariable();
481         private int mScore;
482         private NetworkAgent mNetworkAgent;
483         private int mStartKeepaliveError = SocketKeepalive.ERROR_UNSUPPORTED;
484         private int mStopKeepaliveError = SocketKeepalive.NO_KEEPALIVE;
485         private Integer mExpectedKeepaliveSlot = null;
486         // Contains the redirectUrl from networkStatus(). Before reading, wait for
487         // mNetworkStatusReceived.
488         private String mRedirectUrl;
489 
490         private INetworkMonitorCallbacks mNmCallbacks;
491         private int mNmValidationResult = VALIDATION_RESULT_BASE;
492         private String mNmValidationRedirectUrl = null;
493         private boolean mNmProvNotificationRequested = false;
494 
setNetworkValid()495         void setNetworkValid() {
496             mNmValidationResult = VALIDATION_RESULT_VALID;
497             mNmValidationRedirectUrl = null;
498         }
499 
setNetworkInvalid()500         void setNetworkInvalid() {
501             mNmValidationResult = VALIDATION_RESULT_INVALID;
502             mNmValidationRedirectUrl = null;
503         }
504 
setNetworkPortal(String redirectUrl)505         void setNetworkPortal(String redirectUrl) {
506             setNetworkInvalid();
507             mNmValidationRedirectUrl = redirectUrl;
508         }
509 
setNetworkPartial()510         void setNetworkPartial() {
511             mNmValidationResult = VALIDATION_RESULT_PARTIAL;
512             mNmValidationRedirectUrl = null;
513         }
514 
setNetworkPartialValid()515         void setNetworkPartialValid() {
516             mNmValidationResult = VALIDATION_RESULT_PARTIAL | VALIDATION_RESULT_VALID;
517             mNmValidationRedirectUrl = null;
518         }
519 
MockNetworkAgent(int transport)520         MockNetworkAgent(int transport) {
521             this(transport, new LinkProperties());
522         }
523 
MockNetworkAgent(int transport, LinkProperties linkProperties)524         MockNetworkAgent(int transport, LinkProperties linkProperties) {
525             final int type = transportToLegacyType(transport);
526             final String typeName = ConnectivityManager.getNetworkTypeName(type);
527             mNetworkInfo = new NetworkInfo(type, 0, typeName, "Mock");
528             mNetworkCapabilities = new NetworkCapabilities();
529             mNetworkCapabilities.addTransportType(transport);
530             switch (transport) {
531                 case TRANSPORT_ETHERNET:
532                     mScore = 70;
533                     break;
534                 case TRANSPORT_WIFI:
535                     mScore = 60;
536                     break;
537                 case TRANSPORT_CELLULAR:
538                     mScore = 50;
539                     break;
540                 case TRANSPORT_WIFI_AWARE:
541                     mScore = 20;
542                     break;
543                 case TRANSPORT_VPN:
544                     mNetworkCapabilities.removeCapability(NET_CAPABILITY_NOT_VPN);
545                     mScore = ConnectivityConstants.VPN_DEFAULT_SCORE;
546                     break;
547                 default:
548                     throw new UnsupportedOperationException("unimplemented network type");
549             }
550             mHandlerThread = new HandlerThread("Mock-" + typeName);
551             mHandlerThread.start();
552 
553             mNetworkMonitor = mock(INetworkMonitor.class);
554             final Answer validateAnswer = inv -> {
555                 new Thread(this::onValidationRequested).start();
556                 return null;
557             };
558 
559             try {
560                 doAnswer(validateAnswer).when(mNetworkMonitor).notifyNetworkConnected(any(), any());
561                 doAnswer(validateAnswer).when(mNetworkMonitor).forceReevaluation(anyInt());
562             } catch (RemoteException e) {
563                 fail(e.getMessage());
564             }
565 
566             final ArgumentCaptor<Network> nmNetworkCaptor = ArgumentCaptor.forClass(Network.class);
567             final ArgumentCaptor<INetworkMonitorCallbacks> nmCbCaptor =
568                     ArgumentCaptor.forClass(INetworkMonitorCallbacks.class);
569             doNothing().when(mNetworkStack).makeNetworkMonitor(
570                     nmNetworkCaptor.capture(),
571                     any() /* name */,
572                     nmCbCaptor.capture());
573 
574             mNetworkAgent = new NetworkAgent(mHandlerThread.getLooper(), mServiceContext,
575                     "Mock-" + typeName, mNetworkInfo, mNetworkCapabilities,
576                     linkProperties, mScore, new NetworkMisc(), NetworkFactory.SerialNumber.NONE) {
577                 @Override
578                 public void unwanted() { mDisconnected.open(); }
579 
580                 @Override
581                 public void startSocketKeepalive(Message msg) {
582                     int slot = msg.arg1;
583                     if (mExpectedKeepaliveSlot != null) {
584                         assertEquals((int) mExpectedKeepaliveSlot, slot);
585                     }
586                     onSocketKeepaliveEvent(slot, mStartKeepaliveError);
587                 }
588 
589                 @Override
590                 public void stopSocketKeepalive(Message msg) {
591                     onSocketKeepaliveEvent(msg.arg1, mStopKeepaliveError);
592                 }
593 
594                 @Override
595                 public void networkStatus(int status, String redirectUrl) {
596                     mRedirectUrl = redirectUrl;
597                     mNetworkStatusReceived.open();
598                 }
599 
600                 @Override
601                 protected void preventAutomaticReconnect() {
602                     mPreventReconnectReceived.open();
603                 }
604 
605                 @Override
606                 protected void addKeepalivePacketFilter(Message msg) {
607                     Log.i(TAG, "Add keepalive packet filter.");
608                 }
609 
610                 @Override
611                 protected void removeKeepalivePacketFilter(Message msg) {
612                     Log.i(TAG, "Remove keepalive packet filter.");
613                 }
614             };
615 
616             assertEquals(mNetworkAgent.netId, nmNetworkCaptor.getValue().netId);
617             mNmCallbacks = nmCbCaptor.getValue();
618 
619             try {
620                 mNmCallbacks.onNetworkMonitorCreated(mNetworkMonitor);
621             } catch (RemoteException e) {
622                 fail(e.getMessage());
623             }
624 
625             // Waits for the NetworkAgent to be registered, which includes the creation of the
626             // NetworkMonitor.
627             waitForIdle();
628         }
629 
onValidationRequested()630         private void onValidationRequested() {
631             try {
632                 if (mNmProvNotificationRequested
633                         && ((mNmValidationResult & NETWORK_VALIDATION_RESULT_VALID) != 0)) {
634                     mNmCallbacks.hideProvisioningNotification();
635                     mNmProvNotificationRequested = false;
636                 }
637 
638                 mNmCallbacks.notifyNetworkTested(
639                         mNmValidationResult, mNmValidationRedirectUrl);
640 
641                 if (mNmValidationRedirectUrl != null) {
642                     mNmCallbacks.showProvisioningNotification(
643                             "test_provisioning_notif_action", "com.android.test.package");
644                     mNmProvNotificationRequested = true;
645                 }
646             } catch (RemoteException e) {
647                 fail(e.getMessage());
648             }
649         }
650 
adjustScore(int change)651         public void adjustScore(int change) {
652             mScore += change;
653             mNetworkAgent.sendNetworkScore(mScore);
654         }
655 
getScore()656         public int getScore() {
657             return mScore;
658         }
659 
explicitlySelected(boolean acceptUnvalidated)660         public void explicitlySelected(boolean acceptUnvalidated) {
661             mNetworkAgent.explicitlySelected(acceptUnvalidated);
662         }
663 
addCapability(int capability)664         public void addCapability(int capability) {
665             mNetworkCapabilities.addCapability(capability);
666             mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
667         }
668 
removeCapability(int capability)669         public void removeCapability(int capability) {
670             mNetworkCapabilities.removeCapability(capability);
671             mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
672         }
673 
setUids(Set<UidRange> uids)674         public void setUids(Set<UidRange> uids) {
675             mNetworkCapabilities.setUids(uids);
676             mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
677         }
678 
setSignalStrength(int signalStrength)679         public void setSignalStrength(int signalStrength) {
680             mNetworkCapabilities.setSignalStrength(signalStrength);
681             mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
682         }
683 
setNetworkSpecifier(NetworkSpecifier networkSpecifier)684         public void setNetworkSpecifier(NetworkSpecifier networkSpecifier) {
685             mNetworkCapabilities.setNetworkSpecifier(networkSpecifier);
686             mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
687         }
688 
setNetworkCapabilities(NetworkCapabilities nc, boolean sendToConnectivityService)689         public void setNetworkCapabilities(NetworkCapabilities nc,
690                 boolean sendToConnectivityService) {
691             mNetworkCapabilities.set(nc);
692             if (sendToConnectivityService) {
693                 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
694             }
695         }
696 
connectWithoutInternet()697         public void connectWithoutInternet() {
698             mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, null);
699             mNetworkAgent.sendNetworkInfo(mNetworkInfo);
700         }
701 
702         /**
703          * Transition this NetworkAgent to CONNECTED state with NET_CAPABILITY_INTERNET.
704          * @param validated Indicate if network should pretend to be validated.
705          */
connect(boolean validated)706         public void connect(boolean validated) {
707             connect(validated, true);
708         }
709 
710         /**
711          * Transition this NetworkAgent to CONNECTED state.
712          * @param validated Indicate if network should pretend to be validated.
713          * @param hasInternet Indicate if network should pretend to have NET_CAPABILITY_INTERNET.
714          */
connect(boolean validated, boolean hasInternet)715         public void connect(boolean validated, boolean hasInternet) {
716             assertEquals("MockNetworkAgents can only be connected once",
717                     mNetworkInfo.getDetailedState(), DetailedState.IDLE);
718             assertFalse(mNetworkCapabilities.hasCapability(NET_CAPABILITY_INTERNET));
719 
720             NetworkCallback callback = null;
721             final ConditionVariable validatedCv = new ConditionVariable();
722             if (validated) {
723                 setNetworkValid();
724                 NetworkRequest request = new NetworkRequest.Builder()
725                         .addTransportType(mNetworkCapabilities.getTransportTypes()[0])
726                         .clearCapabilities()
727                         .build();
728                 callback = new NetworkCallback() {
729                     public void onCapabilitiesChanged(Network network,
730                             NetworkCapabilities networkCapabilities) {
731                         if (network.equals(getNetwork()) &&
732                             networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED)) {
733                             validatedCv.open();
734                         }
735                     }
736                 };
737                 mCm.registerNetworkCallback(request, callback);
738             }
739             if (hasInternet) {
740                 addCapability(NET_CAPABILITY_INTERNET);
741             }
742 
743             connectWithoutInternet();
744 
745             if (validated) {
746                 // Wait for network to validate.
747                 waitFor(validatedCv);
748                 setNetworkInvalid();
749             }
750 
751             if (callback != null) mCm.unregisterNetworkCallback(callback);
752         }
753 
connectWithCaptivePortal(String redirectUrl)754         public void connectWithCaptivePortal(String redirectUrl) {
755             setNetworkPortal(redirectUrl);
756             connect(false);
757         }
758 
connectWithPartialConnectivity()759         public void connectWithPartialConnectivity() {
760             setNetworkPartial();
761             connect(false);
762         }
763 
suspend()764         public void suspend() {
765             mNetworkInfo.setDetailedState(DetailedState.SUSPENDED, null, null);
766             mNetworkAgent.sendNetworkInfo(mNetworkInfo);
767         }
768 
resume()769         public void resume() {
770             mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, null);
771             mNetworkAgent.sendNetworkInfo(mNetworkInfo);
772         }
773 
disconnect()774         public void disconnect() {
775             mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, null);
776             mNetworkAgent.sendNetworkInfo(mNetworkInfo);
777         }
778 
getNetwork()779         public Network getNetwork() {
780             return new Network(mNetworkAgent.netId);
781         }
782 
getPreventReconnectReceived()783         public ConditionVariable getPreventReconnectReceived() {
784             return mPreventReconnectReceived;
785         }
786 
getDisconnectedCV()787         public ConditionVariable getDisconnectedCV() {
788             return mDisconnected;
789         }
790 
sendLinkProperties(LinkProperties lp)791         public void sendLinkProperties(LinkProperties lp) {
792             mNetworkAgent.sendLinkProperties(lp);
793         }
794 
setStartKeepaliveError(int error)795         public void setStartKeepaliveError(int error) {
796             mStartKeepaliveError = error;
797         }
798 
setStopKeepaliveError(int error)799         public void setStopKeepaliveError(int error) {
800             mStopKeepaliveError = error;
801         }
802 
setExpectedKeepaliveSlot(Integer slot)803         public void setExpectedKeepaliveSlot(Integer slot) {
804             mExpectedKeepaliveSlot = slot;
805         }
806 
waitForRedirectUrl()807         public String waitForRedirectUrl() {
808             assertTrue(mNetworkStatusReceived.block(TIMEOUT_MS));
809             return mRedirectUrl;
810         }
811 
getNetworkAgent()812         public NetworkAgent getNetworkAgent() {
813             return mNetworkAgent;
814         }
815 
getNetworkCapabilities()816         public NetworkCapabilities getNetworkCapabilities() {
817             return mNetworkCapabilities;
818         }
819     }
820 
821     /**
822      * A NetworkFactory that allows tests to wait until any in-flight NetworkRequest add or remove
823      * operations have been processed. Before ConnectivityService can add or remove any requests,
824      * the factory must be told to expect those operations by calling expectAddRequestsWithScores or
825      * expectRemoveRequests.
826      */
827     private static class MockNetworkFactory extends NetworkFactory {
828         private final ConditionVariable mNetworkStartedCV = new ConditionVariable();
829         private final ConditionVariable mNetworkStoppedCV = new ConditionVariable();
830         private final AtomicBoolean mNetworkStarted = new AtomicBoolean(false);
831 
832         // Used to expect that requests be removed or added on a separate thread, without sleeping.
833         // Callers can call either expectAddRequestsWithScores() or expectRemoveRequests() exactly
834         // once, then cause some other thread to add or remove requests, then call
835         // waitForRequests().
836         // It is not possible to wait for both add and remove requests. When adding, the queue
837         // contains the expected score. When removing, the value is unused, all matters is the
838         // number of objects in the queue.
839         private final LinkedBlockingQueue<Integer> mExpectations;
840 
841         // Whether we are currently expecting requests to be added or removed. Valid only if
842         // mExpectations is non-empty.
843         private boolean mExpectingAdditions;
844 
845         // Used to collect the networks requests managed by this factory. This is a duplicate of
846         // the internal information stored in the NetworkFactory (which is private).
847         private SparseArray<NetworkRequest> mNetworkRequests = new SparseArray<>();
848 
MockNetworkFactory(Looper looper, Context context, String logTag, NetworkCapabilities filter)849         public MockNetworkFactory(Looper looper, Context context, String logTag,
850                 NetworkCapabilities filter) {
851             super(looper, context, logTag, filter);
852             mExpectations = new LinkedBlockingQueue<>();
853         }
854 
getMyRequestCount()855         public int getMyRequestCount() {
856             return getRequestCount();
857         }
858 
startNetwork()859         protected void startNetwork() {
860             mNetworkStarted.set(true);
861             mNetworkStartedCV.open();
862         }
863 
stopNetwork()864         protected void stopNetwork() {
865             mNetworkStarted.set(false);
866             mNetworkStoppedCV.open();
867         }
868 
getMyStartRequested()869         public boolean getMyStartRequested() {
870             return mNetworkStarted.get();
871         }
872 
getNetworkStartedCV()873         public ConditionVariable getNetworkStartedCV() {
874             mNetworkStartedCV.close();
875             return mNetworkStartedCV;
876         }
877 
getNetworkStoppedCV()878         public ConditionVariable getNetworkStoppedCV() {
879             mNetworkStoppedCV.close();
880             return mNetworkStoppedCV;
881         }
882 
883         @Override
handleAddRequest(NetworkRequest request, int score, int factorySerialNumber)884         protected void handleAddRequest(NetworkRequest request, int score,
885                 int factorySerialNumber) {
886             synchronized (mExpectations) {
887                 final Integer expectedScore = mExpectations.poll(); // null if the queue is empty
888 
889                 assertNotNull("Added more requests than expected (" + request + " score : "
890                         + score + ")", expectedScore);
891                 // If we're expecting anything, we must be expecting additions.
892                 if (!mExpectingAdditions) {
893                     fail("Can't add requests while expecting requests to be removed");
894                 }
895                 if (expectedScore != score) {
896                     fail("Expected score was " + expectedScore + " but actual was " + score
897                             + " in added request");
898                 }
899 
900                 // Add the request.
901                 mNetworkRequests.put(request.requestId, request);
902                 super.handleAddRequest(request, score, factorySerialNumber);
903                 mExpectations.notify();
904             }
905         }
906 
907         @Override
handleRemoveRequest(NetworkRequest request)908         protected void handleRemoveRequest(NetworkRequest request) {
909             synchronized (mExpectations) {
910                 final Integer expectedScore = mExpectations.poll(); // null if the queue is empty
911 
912                 assertTrue("Removed more requests than expected", expectedScore != null);
913                 // If we're expecting anything, we must be expecting removals.
914                 if (mExpectingAdditions) {
915                     fail("Can't remove requests while expecting requests to be added");
916                 }
917 
918                 // Remove the request.
919                 mNetworkRequests.remove(request.requestId);
920                 super.handleRemoveRequest(request);
921                 mExpectations.notify();
922             }
923         }
924 
925         // Trigger releasing the request as unfulfillable
triggerUnfulfillable(NetworkRequest r)926         public void triggerUnfulfillable(NetworkRequest r) {
927             super.releaseRequestAsUnfulfillableByAnyFactory(r);
928         }
929 
assertNoExpectations()930         private void assertNoExpectations() {
931             if (mExpectations.size() != 0) {
932                 fail("Can't add expectation, " + mExpectations.size() + " already pending");
933             }
934         }
935 
936         // Expects that requests with the specified scores will be added.
expectAddRequestsWithScores(final int... scores)937         public void expectAddRequestsWithScores(final int... scores) {
938             assertNoExpectations();
939             mExpectingAdditions = true;
940             for (int score : scores) {
941                 mExpectations.add(score);
942             }
943         }
944 
945         // Expects that count requests will be removed.
expectRemoveRequests(final int count)946         public void expectRemoveRequests(final int count) {
947             assertNoExpectations();
948             mExpectingAdditions = false;
949             for (int i = 0; i < count; ++i) {
950                 mExpectations.add(0); // For removals the score is ignored so any value will do.
951             }
952         }
953 
954         // Waits for the expected request additions or removals to happen within a timeout.
waitForRequests()955         public void waitForRequests() throws InterruptedException {
956             final long deadline = SystemClock.elapsedRealtime() + TIMEOUT_MS;
957             synchronized (mExpectations) {
958                 while (mExpectations.size() > 0 && SystemClock.elapsedRealtime() < deadline) {
959                     mExpectations.wait(deadline - SystemClock.elapsedRealtime());
960                 }
961             }
962             final long count = mExpectations.size();
963             final String msg = count + " requests still not " +
964                     (mExpectingAdditions ? "added" : "removed") +
965                     " after " + TIMEOUT_MS + " ms";
966             assertEquals(msg, 0, count);
967         }
968 
waitForNetworkRequests(final int count)969         public SparseArray<NetworkRequest> waitForNetworkRequests(final int count)
970                 throws InterruptedException {
971             waitForRequests();
972             assertEquals(count, getMyRequestCount());
973             return mNetworkRequests;
974         }
975     }
976 
startHandlerThreadAndReturnLooper()977     private static Looper startHandlerThreadAndReturnLooper() {
978         final HandlerThread handlerThread = new HandlerThread("MockVpnThread");
979         handlerThread.start();
980         return handlerThread.getLooper();
981     }
982 
983     private class MockVpn extends Vpn {
984         // TODO : the interactions between this mock and the mock network agent are too
985         // hard to get right at this moment, because it's unclear in which case which
986         // target needs to get a method call or both, and in what order. It's because
987         // MockNetworkAgent wants to manage its own NetworkCapabilities, but the Vpn
988         // parent class of MockVpn agent wants that responsibility.
989         // That being said inside the test it should be possible to make the interactions
990         // harder to get wrong with precise speccing, judicious comments, helper methods
991         // and a few sprinkled assertions.
992 
993         private boolean mConnected = false;
994         // Careful ! This is different from mNetworkAgent, because MockNetworkAgent does
995         // not inherit from NetworkAgent.
996         private MockNetworkAgent mMockNetworkAgent;
997 
MockVpn(int userId)998         public MockVpn(int userId) {
999             super(startHandlerThreadAndReturnLooper(), mServiceContext, mNetworkManagementService,
1000                     userId);
1001         }
1002 
setNetworkAgent(MockNetworkAgent agent)1003         public void setNetworkAgent(MockNetworkAgent agent) {
1004             waitForIdle(agent, TIMEOUT_MS);
1005             mMockNetworkAgent = agent;
1006             mNetworkAgent = agent.getNetworkAgent();
1007             mNetworkCapabilities.set(agent.getNetworkCapabilities());
1008         }
1009 
setUids(Set<UidRange> uids)1010         public void setUids(Set<UidRange> uids) {
1011             mNetworkCapabilities.setUids(uids);
1012             updateCapabilities(null /* defaultNetwork */);
1013         }
1014 
1015         @Override
getNetId()1016         public int getNetId() {
1017             if (mMockNetworkAgent == null) {
1018                 return NETID_UNSET;
1019             }
1020             return mMockNetworkAgent.getNetwork().netId;
1021         }
1022 
1023         @Override
appliesToUid(int uid)1024         public boolean appliesToUid(int uid) {
1025             return mConnected;  // Trickery to simplify testing.
1026         }
1027 
1028         @Override
isCallerEstablishedOwnerLocked()1029         protected boolean isCallerEstablishedOwnerLocked() {
1030             return mConnected;  // Similar trickery
1031         }
1032 
connect(boolean isAlwaysMetered)1033         private void connect(boolean isAlwaysMetered) {
1034             mNetworkCapabilities.set(mMockNetworkAgent.getNetworkCapabilities());
1035             mConnected = true;
1036             mConfig = new VpnConfig();
1037             mConfig.isMetered = isAlwaysMetered;
1038         }
1039 
connectAsAlwaysMetered()1040         public void connectAsAlwaysMetered() {
1041             connect(true /* isAlwaysMetered */);
1042         }
1043 
connect()1044         public void connect() {
1045             connect(false /* isAlwaysMetered */);
1046         }
1047 
1048         @Override
updateCapabilities(Network defaultNetwork)1049         public NetworkCapabilities updateCapabilities(Network defaultNetwork) {
1050             if (!mConnected) return null;
1051             super.updateCapabilities(defaultNetwork);
1052             // Because super.updateCapabilities will update the capabilities of the agent but
1053             // not the mock agent, the mock agent needs to know about them.
1054             copyCapabilitiesToNetworkAgent();
1055             return new NetworkCapabilities(mNetworkCapabilities);
1056         }
1057 
copyCapabilitiesToNetworkAgent()1058         private void copyCapabilitiesToNetworkAgent() {
1059             if (null != mMockNetworkAgent) {
1060                 mMockNetworkAgent.setNetworkCapabilities(mNetworkCapabilities,
1061                         false /* sendToConnectivityService */);
1062             }
1063         }
1064 
disconnect()1065         public void disconnect() {
1066             mConnected = false;
1067             mConfig = null;
1068         }
1069     }
1070 
1071     private class FakeWakeupMessage extends WakeupMessage {
1072         private static final int UNREASONABLY_LONG_WAIT = 1000;
1073 
FakeWakeupMessage(Context context, Handler handler, String cmdName, int cmd)1074         public FakeWakeupMessage(Context context, Handler handler, String cmdName, int cmd) {
1075             super(context, handler, cmdName, cmd);
1076         }
1077 
FakeWakeupMessage(Context context, Handler handler, String cmdName, int cmd, int arg1, int arg2, Object obj)1078         public FakeWakeupMessage(Context context, Handler handler, String cmdName, int cmd,
1079                 int arg1, int arg2, Object obj) {
1080             super(context, handler, cmdName, cmd, arg1, arg2, obj);
1081         }
1082 
1083         @Override
schedule(long when)1084         public void schedule(long when) {
1085             long delayMs = when - SystemClock.elapsedRealtime();
1086             if (delayMs < 0) delayMs = 0;
1087             if (delayMs > UNREASONABLY_LONG_WAIT) {
1088                 fail("Attempting to send msg more than " + UNREASONABLY_LONG_WAIT +
1089                         "ms into the future: " + delayMs);
1090             }
1091             Message msg = mHandler.obtainMessage(mCmd, mArg1, mArg2, mObj);
1092             mHandler.sendMessageDelayed(msg, delayMs);
1093         }
1094 
1095         @Override
cancel()1096         public void cancel() {
1097             mHandler.removeMessages(mCmd, mObj);
1098         }
1099 
1100         @Override
onAlarm()1101         public void onAlarm() {
1102             throw new AssertionError("Should never happen. Update this fake.");
1103         }
1104     }
1105 
1106     private class WrappedMultinetworkPolicyTracker extends MultinetworkPolicyTracker {
1107         public volatile boolean configRestrictsAvoidBadWifi;
1108         public volatile int configMeteredMultipathPreference;
1109 
WrappedMultinetworkPolicyTracker(Context c, Handler h, Runnable r)1110         public WrappedMultinetworkPolicyTracker(Context c, Handler h, Runnable r) {
1111             super(c, h, r);
1112         }
1113 
1114         @Override
configRestrictsAvoidBadWifi()1115         public boolean configRestrictsAvoidBadWifi() {
1116             return configRestrictsAvoidBadWifi;
1117         }
1118 
1119         @Override
configMeteredMultipathPreference()1120         public int configMeteredMultipathPreference() {
1121             return configMeteredMultipathPreference;
1122         }
1123     }
1124 
1125     private class WrappedConnectivityService extends ConnectivityService {
1126         public WrappedMultinetworkPolicyTracker wrappedMultinetworkPolicyTracker;
1127         private MockableSystemProperties mSystemProperties;
1128 
WrappedConnectivityService(Context context, INetworkManagementService netManager, INetworkStatsService statsService, INetworkPolicyManager policyManager, IpConnectivityLog log, INetd netd, IDnsResolver dnsResolver)1129         public WrappedConnectivityService(Context context, INetworkManagementService netManager,
1130                 INetworkStatsService statsService, INetworkPolicyManager policyManager,
1131                 IpConnectivityLog log, INetd netd, IDnsResolver dnsResolver) {
1132             super(context, netManager, statsService, policyManager, dnsResolver, log, netd);
1133             mNetd = netd;
1134             mLingerDelayMs = TEST_LINGER_DELAY_MS;
1135         }
1136 
1137         @Override
getSystemProperties()1138         protected MockableSystemProperties getSystemProperties() {
1139             // Minimal approach to overriding system properties: let most calls fall through to real
1140             // device values, and only override ones values that are important to this test.
1141             mSystemProperties = spy(new MockableSystemProperties());
1142             when(mSystemProperties.getInt("net.tcp.default_init_rwnd", 0)).thenReturn(0);
1143             when(mSystemProperties.getBoolean("ro.radio.noril", false)).thenReturn(false);
1144             return mSystemProperties;
1145         }
1146 
1147         @Override
makeTethering()1148         protected Tethering makeTethering() {
1149             return mock(Tethering.class);
1150         }
1151 
1152         @Override
makeProxyTracker()1153         protected ProxyTracker makeProxyTracker() {
1154             return mock(ProxyTracker.class);
1155         }
1156 
1157         @Override
reserveNetId()1158         protected int reserveNetId() {
1159             while (true) {
1160                 final int netId = super.reserveNetId();
1161 
1162                 // Don't overlap test NetIDs with real NetIDs as binding sockets to real networks
1163                 // can have odd side-effects, like network validations succeeding.
1164                 Context context = InstrumentationRegistry.getContext();
1165                 final Network[] networks = ConnectivityManager.from(context).getAllNetworks();
1166                 boolean overlaps = false;
1167                 for (Network network : networks) {
1168                     if (netId == network.netId) {
1169                         overlaps = true;
1170                         break;
1171                     }
1172                 }
1173                 if (overlaps) continue;
1174 
1175                 return netId;
1176             }
1177         }
1178 
1179         @Override
queryUserAccess(int uid, int netId)1180         protected boolean queryUserAccess(int uid, int netId) {
1181             return true;
1182         }
1183 
getNat464Xlat(MockNetworkAgent mna)1184         public Nat464Xlat getNat464Xlat(MockNetworkAgent mna) {
1185             return getNetworkAgentInfoForNetwork(mna.getNetwork()).clatd;
1186         }
1187 
1188         @Override
createMultinetworkPolicyTracker( Context c, Handler h, Runnable r)1189         public MultinetworkPolicyTracker createMultinetworkPolicyTracker(
1190                 Context c, Handler h, Runnable r) {
1191             final WrappedMultinetworkPolicyTracker tracker = new WrappedMultinetworkPolicyTracker(c, h, r);
1192             return tracker;
1193         }
1194 
getMultinetworkPolicyTracker()1195         public WrappedMultinetworkPolicyTracker getMultinetworkPolicyTracker() {
1196             return (WrappedMultinetworkPolicyTracker) mMultinetworkPolicyTracker;
1197         }
1198 
1199         @Override
getNetworkStack()1200         protected NetworkStackClient getNetworkStack() {
1201             return mNetworkStack;
1202         }
1203 
1204         @Override
makeWakeupMessage( Context context, Handler handler, String cmdName, int cmd, Object obj)1205         public WakeupMessage makeWakeupMessage(
1206                 Context context, Handler handler, String cmdName, int cmd, Object obj) {
1207             return new FakeWakeupMessage(context, handler, cmdName, cmd, 0, 0, obj);
1208         }
1209 
1210         @Override
hasService(String name)1211         public boolean hasService(String name) {
1212             // Currenty, the only relevant service that ConnectivityService checks for is
1213             // ETHERNET_SERVICE.
1214             return Context.ETHERNET_SERVICE.equals(name);
1215         }
1216 
1217         @Override
metricsLogger()1218         protected IpConnectivityMetrics.Logger metricsLogger() {
1219             return mMetricsService;
1220         }
1221 
1222         @Override
registerNetdEventCallback()1223         protected void registerNetdEventCallback() {
1224         }
1225 
mockVpn(int uid)1226         public void mockVpn(int uid) {
1227             synchronized (mVpns) {
1228                 int userId = UserHandle.getUserId(uid);
1229                 mMockVpn = new MockVpn(userId);
1230                 // This has no effect unless the VPN is actually connected, because things like
1231                 // getActiveNetworkForUidInternal call getNetworkAgentInfoForNetId on the VPN
1232                 // netId, and check if that network is actually connected.
1233                 mVpns.put(userId, mMockVpn);
1234             }
1235         }
1236 
waitForIdle(int timeoutMs)1237         public void waitForIdle(int timeoutMs) {
1238             waitForIdleHandler(mHandlerThread, timeoutMs);
1239         }
1240 
waitForIdle()1241         public void waitForIdle() {
1242             waitForIdle(TIMEOUT_MS);
1243         }
1244 
setUidRulesChanged(int uidRules)1245         public void setUidRulesChanged(int uidRules) {
1246             try {
1247                 mPolicyListener.onUidRulesChanged(Process.myUid(), uidRules);
1248             } catch (RemoteException ignored) {
1249             }
1250         }
1251 
setRestrictBackgroundChanged(boolean restrictBackground)1252         public void setRestrictBackgroundChanged(boolean restrictBackground) {
1253             try {
1254                 mPolicyListener.onRestrictBackgroundChanged(restrictBackground);
1255             } catch (RemoteException ignored) {
1256             }
1257         }
1258     }
1259 
1260     /**
1261      * Wait up to TIMEOUT_MS for {@code conditionVariable} to open.
1262      * Fails if TIMEOUT_MS goes by before {@code conditionVariable} opens.
1263      */
waitFor(ConditionVariable conditionVariable)1264     static private void waitFor(ConditionVariable conditionVariable) {
1265         if (conditionVariable.block(TIMEOUT_MS)) {
1266             return;
1267         }
1268         fail("ConditionVariable was blocked for more than " + TIMEOUT_MS + "ms");
1269     }
1270 
1271     private static final int VPN_USER = 0;
1272     private static final int APP1_UID = UserHandle.getUid(VPN_USER, 10100);
1273     private static final int APP2_UID = UserHandle.getUid(VPN_USER, 10101);
1274     private static final int VPN_UID = UserHandle.getUid(VPN_USER, 10043);
1275 
1276     @Before
setUp()1277     public void setUp() throws Exception {
1278         mContext = InstrumentationRegistry.getContext();
1279 
1280         MockitoAnnotations.initMocks(this);
1281         when(mMetricsService.defaultNetworkMetrics()).thenReturn(mDefaultNetworkMetrics);
1282 
1283         when(mUserManager.getUsers(eq(true))).thenReturn(
1284                 Arrays.asList(new UserInfo[] {
1285                         new UserInfo(VPN_USER, "", 0),
1286                 }));
1287 
1288         // InstrumentationTestRunner prepares a looper, but AndroidJUnitRunner does not.
1289         // http://b/25897652 .
1290         if (Looper.myLooper() == null) {
1291             Looper.prepare();
1292         }
1293         mockDefaultPackages();
1294 
1295         FakeSettingsProvider.clearSettingsProvider();
1296         mServiceContext = new MockContext(InstrumentationRegistry.getContext(),
1297                 new FakeSettingsProvider());
1298         LocalServices.removeServiceForTest(NetworkPolicyManagerInternal.class);
1299         LocalServices.addService(
1300                 NetworkPolicyManagerInternal.class, mock(NetworkPolicyManagerInternal.class));
1301 
1302         mService = new WrappedConnectivityService(mServiceContext,
1303                 mNetworkManagementService,
1304                 mStatsService,
1305                 mNpm,
1306                 mock(IpConnectivityLog.class),
1307                 mMockNetd,
1308                 mMockDnsResolver);
1309 
1310         final ArgumentCaptor<INetworkPolicyListener> policyListenerCaptor =
1311                 ArgumentCaptor.forClass(INetworkPolicyListener.class);
1312         verify(mNpm).registerListener(policyListenerCaptor.capture());
1313         mPolicyListener = policyListenerCaptor.getValue();
1314 
1315         // Create local CM before sending system ready so that we can answer
1316         // getSystemService() correctly.
1317         mCm = new WrappedConnectivityManager(InstrumentationRegistry.getContext(), mService);
1318         mService.systemReady();
1319         mService.mockVpn(Process.myUid());
1320         mCm.bindProcessToNetwork(null);
1321 
1322         // Ensure that the default setting for Captive Portals is used for most tests
1323         setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_PROMPT);
1324         setAlwaysOnNetworks(false);
1325         setPrivateDnsSettings(PRIVATE_DNS_MODE_OFF, "ignored.example.com");
1326     }
1327 
1328     @After
tearDown()1329     public void tearDown() throws Exception {
1330         setAlwaysOnNetworks(false);
1331         if (mCellNetworkAgent != null) {
1332             mCellNetworkAgent.disconnect();
1333             mCellNetworkAgent = null;
1334         }
1335         if (mWiFiNetworkAgent != null) {
1336             mWiFiNetworkAgent.disconnect();
1337             mWiFiNetworkAgent = null;
1338         }
1339         if (mEthernetNetworkAgent != null) {
1340             mEthernetNetworkAgent.disconnect();
1341             mEthernetNetworkAgent = null;
1342         }
1343         FakeSettingsProvider.clearSettingsProvider();
1344     }
1345 
mockDefaultPackages()1346     private void mockDefaultPackages() throws Exception {
1347         final String testPackageName = mContext.getPackageName();
1348         final PackageInfo testPackageInfo = mContext.getPackageManager().getPackageInfo(
1349                 testPackageName, PackageManager.GET_PERMISSIONS);
1350         when(mPackageManager.getPackagesForUid(Binder.getCallingUid())).thenReturn(
1351                 new String[] {testPackageName});
1352         when(mPackageManager.getPackageInfoAsUser(eq(testPackageName), anyInt(),
1353                 eq(UserHandle.getCallingUserId()))).thenReturn(testPackageInfo);
1354 
1355         when(mPackageManager.getInstalledPackages(eq(GET_PERMISSIONS | MATCH_ANY_USER))).thenReturn(
1356                 Arrays.asList(new PackageInfo[] {
1357                         buildPackageInfo(/* SYSTEM */ false, APP1_UID),
1358                         buildPackageInfo(/* SYSTEM */ false, APP2_UID),
1359                         buildPackageInfo(/* SYSTEM */ false, VPN_UID)
1360                 }));
1361     }
1362 
transportToLegacyType(int transport)1363    private static int transportToLegacyType(int transport) {
1364         switch (transport) {
1365             case TRANSPORT_ETHERNET:
1366                 return TYPE_ETHERNET;
1367             case TRANSPORT_WIFI:
1368                 return TYPE_WIFI;
1369             case TRANSPORT_CELLULAR:
1370                 return TYPE_MOBILE;
1371             case TRANSPORT_VPN:
1372                 return TYPE_VPN;
1373             default:
1374                 return TYPE_NONE;
1375         }
1376     }
1377 
verifyActiveNetwork(int transport)1378     private void verifyActiveNetwork(int transport) {
1379         // Test getActiveNetworkInfo()
1380         assertNotNull(mCm.getActiveNetworkInfo());
1381         assertEquals(transportToLegacyType(transport), mCm.getActiveNetworkInfo().getType());
1382         // Test getActiveNetwork()
1383         assertNotNull(mCm.getActiveNetwork());
1384         assertEquals(mCm.getActiveNetwork(), mCm.getActiveNetworkForUid(Process.myUid()));
1385         if (!NetworkCapabilities.isValidTransport(transport)) {
1386             throw new IllegalStateException("Unknown transport " + transport);
1387         }
1388         switch (transport) {
1389             case TRANSPORT_WIFI:
1390                 assertEquals(mCm.getActiveNetwork(), mWiFiNetworkAgent.getNetwork());
1391                 break;
1392             case TRANSPORT_CELLULAR:
1393                 assertEquals(mCm.getActiveNetwork(), mCellNetworkAgent.getNetwork());
1394                 break;
1395             default:
1396                 break;
1397         }
1398         // Test getNetworkInfo(Network)
1399         assertNotNull(mCm.getNetworkInfo(mCm.getActiveNetwork()));
1400         assertEquals(transportToLegacyType(transport),
1401                 mCm.getNetworkInfo(mCm.getActiveNetwork()).getType());
1402         // Test getNetworkCapabilities(Network)
1403         assertNotNull(mCm.getNetworkCapabilities(mCm.getActiveNetwork()));
1404         assertTrue(mCm.getNetworkCapabilities(mCm.getActiveNetwork()).hasTransport(transport));
1405     }
1406 
verifyNoNetwork()1407     private void verifyNoNetwork() {
1408         waitForIdle();
1409         // Test getActiveNetworkInfo()
1410         assertNull(mCm.getActiveNetworkInfo());
1411         // Test getActiveNetwork()
1412         assertNull(mCm.getActiveNetwork());
1413         assertNull(mCm.getActiveNetworkForUid(Process.myUid()));
1414         // Test getAllNetworks()
1415         assertEmpty(mCm.getAllNetworks());
1416     }
1417 
1418     /**
1419      * Return a ConditionVariable that opens when {@code count} numbers of CONNECTIVITY_ACTION
1420      * broadcasts are received.
1421      */
waitForConnectivityBroadcasts(final int count)1422     private ConditionVariable waitForConnectivityBroadcasts(final int count) {
1423         final ConditionVariable cv = new ConditionVariable();
1424         mServiceContext.registerReceiver(new BroadcastReceiver() {
1425                     private int remaining = count;
1426                     public void onReceive(Context context, Intent intent) {
1427                         if (--remaining == 0) {
1428                             cv.open();
1429                             mServiceContext.unregisterReceiver(this);
1430                         }
1431                     }
1432                 }, new IntentFilter(CONNECTIVITY_ACTION));
1433         return cv;
1434     }
1435 
1436     @Test
testNetworkTypes()1437     public void testNetworkTypes() {
1438         // Ensure that our mocks for the networkAttributes config variable work as expected. If they
1439         // don't, then tests that depend on CONNECTIVITY_ACTION broadcasts for these network types
1440         // will fail. Failing here is much easier to debug.
1441         assertTrue(mCm.isNetworkSupported(TYPE_WIFI));
1442         assertTrue(mCm.isNetworkSupported(TYPE_MOBILE));
1443         assertTrue(mCm.isNetworkSupported(TYPE_MOBILE_MMS));
1444         assertFalse(mCm.isNetworkSupported(TYPE_MOBILE_FOTA));
1445 
1446         // Check that TYPE_ETHERNET is supported. Unlike the asserts above, which only validate our
1447         // mocks, this assert exercises the ConnectivityService code path that ensures that
1448         // TYPE_ETHERNET is supported if the ethernet service is running.
1449         assertTrue(mCm.isNetworkSupported(TYPE_ETHERNET));
1450     }
1451 
1452     @Test
testLingering()1453     public void testLingering() throws Exception {
1454         verifyNoNetwork();
1455         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1456         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1457         assertNull(mCm.getActiveNetworkInfo());
1458         assertNull(mCm.getActiveNetwork());
1459         // Test bringing up validated cellular.
1460         ConditionVariable cv = waitForConnectivityBroadcasts(1);
1461         mCellNetworkAgent.connect(true);
1462         waitFor(cv);
1463         verifyActiveNetwork(TRANSPORT_CELLULAR);
1464         assertLength(2, mCm.getAllNetworks());
1465         assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) ||
1466                 mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork()));
1467         assertTrue(mCm.getAllNetworks()[0].equals(mWiFiNetworkAgent.getNetwork()) ||
1468                 mCm.getAllNetworks()[1].equals(mWiFiNetworkAgent.getNetwork()));
1469         // Test bringing up validated WiFi.
1470         cv = waitForConnectivityBroadcasts(2);
1471         mWiFiNetworkAgent.connect(true);
1472         waitFor(cv);
1473         verifyActiveNetwork(TRANSPORT_WIFI);
1474         assertLength(2, mCm.getAllNetworks());
1475         assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) ||
1476                 mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork()));
1477         assertTrue(mCm.getAllNetworks()[0].equals(mCellNetworkAgent.getNetwork()) ||
1478                 mCm.getAllNetworks()[1].equals(mCellNetworkAgent.getNetwork()));
1479         // Test cellular linger timeout.
1480         waitFor(mCellNetworkAgent.getDisconnectedCV());
1481         waitForIdle();
1482         assertLength(1, mCm.getAllNetworks());
1483         verifyActiveNetwork(TRANSPORT_WIFI);
1484         assertLength(1, mCm.getAllNetworks());
1485         assertEquals(mCm.getAllNetworks()[0], mCm.getActiveNetwork());
1486         // Test WiFi disconnect.
1487         cv = waitForConnectivityBroadcasts(1);
1488         mWiFiNetworkAgent.disconnect();
1489         waitFor(cv);
1490         verifyNoNetwork();
1491     }
1492 
1493     @Test
testValidatedCellularOutscoresUnvalidatedWiFi()1494     public void testValidatedCellularOutscoresUnvalidatedWiFi() throws Exception {
1495         // Test bringing up unvalidated WiFi
1496         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1497         ConditionVariable cv = waitForConnectivityBroadcasts(1);
1498         mWiFiNetworkAgent.connect(false);
1499         waitFor(cv);
1500         verifyActiveNetwork(TRANSPORT_WIFI);
1501         // Test bringing up unvalidated cellular
1502         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1503         mCellNetworkAgent.connect(false);
1504         waitForIdle();
1505         verifyActiveNetwork(TRANSPORT_WIFI);
1506         // Test cellular disconnect.
1507         mCellNetworkAgent.disconnect();
1508         waitForIdle();
1509         verifyActiveNetwork(TRANSPORT_WIFI);
1510         // Test bringing up validated cellular
1511         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1512         cv = waitForConnectivityBroadcasts(2);
1513         mCellNetworkAgent.connect(true);
1514         waitFor(cv);
1515         verifyActiveNetwork(TRANSPORT_CELLULAR);
1516         // Test cellular disconnect.
1517         cv = waitForConnectivityBroadcasts(2);
1518         mCellNetworkAgent.disconnect();
1519         waitFor(cv);
1520         verifyActiveNetwork(TRANSPORT_WIFI);
1521         // Test WiFi disconnect.
1522         cv = waitForConnectivityBroadcasts(1);
1523         mWiFiNetworkAgent.disconnect();
1524         waitFor(cv);
1525         verifyNoNetwork();
1526     }
1527 
1528     @Test
testUnvalidatedWifiOutscoresUnvalidatedCellular()1529     public void testUnvalidatedWifiOutscoresUnvalidatedCellular() throws Exception {
1530         // Test bringing up unvalidated cellular.
1531         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1532         ConditionVariable cv = waitForConnectivityBroadcasts(1);
1533         mCellNetworkAgent.connect(false);
1534         waitFor(cv);
1535         verifyActiveNetwork(TRANSPORT_CELLULAR);
1536         // Test bringing up unvalidated WiFi.
1537         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1538         cv = waitForConnectivityBroadcasts(2);
1539         mWiFiNetworkAgent.connect(false);
1540         waitFor(cv);
1541         verifyActiveNetwork(TRANSPORT_WIFI);
1542         // Test WiFi disconnect.
1543         cv = waitForConnectivityBroadcasts(2);
1544         mWiFiNetworkAgent.disconnect();
1545         waitFor(cv);
1546         verifyActiveNetwork(TRANSPORT_CELLULAR);
1547         // Test cellular disconnect.
1548         cv = waitForConnectivityBroadcasts(1);
1549         mCellNetworkAgent.disconnect();
1550         waitFor(cv);
1551         verifyNoNetwork();
1552     }
1553 
1554     @Test
testUnlingeringDoesNotValidate()1555     public void testUnlingeringDoesNotValidate() throws Exception {
1556         // Test bringing up unvalidated WiFi.
1557         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1558         ConditionVariable cv = waitForConnectivityBroadcasts(1);
1559         mWiFiNetworkAgent.connect(false);
1560         waitFor(cv);
1561         verifyActiveNetwork(TRANSPORT_WIFI);
1562         assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1563                 NET_CAPABILITY_VALIDATED));
1564         // Test bringing up validated cellular.
1565         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1566         cv = waitForConnectivityBroadcasts(2);
1567         mCellNetworkAgent.connect(true);
1568         waitFor(cv);
1569         verifyActiveNetwork(TRANSPORT_CELLULAR);
1570         assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1571                 NET_CAPABILITY_VALIDATED));
1572         // Test cellular disconnect.
1573         cv = waitForConnectivityBroadcasts(2);
1574         mCellNetworkAgent.disconnect();
1575         waitFor(cv);
1576         verifyActiveNetwork(TRANSPORT_WIFI);
1577         // Unlingering a network should not cause it to be marked as validated.
1578         assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1579                 NET_CAPABILITY_VALIDATED));
1580     }
1581 
1582     @Test
testCellularOutscoresWeakWifi()1583     public void testCellularOutscoresWeakWifi() throws Exception {
1584         // Test bringing up validated cellular.
1585         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1586         ConditionVariable cv = waitForConnectivityBroadcasts(1);
1587         mCellNetworkAgent.connect(true);
1588         waitFor(cv);
1589         verifyActiveNetwork(TRANSPORT_CELLULAR);
1590         // Test bringing up validated WiFi.
1591         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1592         cv = waitForConnectivityBroadcasts(2);
1593         mWiFiNetworkAgent.connect(true);
1594         waitFor(cv);
1595         verifyActiveNetwork(TRANSPORT_WIFI);
1596         // Test WiFi getting really weak.
1597         cv = waitForConnectivityBroadcasts(2);
1598         mWiFiNetworkAgent.adjustScore(-11);
1599         waitFor(cv);
1600         verifyActiveNetwork(TRANSPORT_CELLULAR);
1601         // Test WiFi restoring signal strength.
1602         cv = waitForConnectivityBroadcasts(2);
1603         mWiFiNetworkAgent.adjustScore(11);
1604         waitFor(cv);
1605         verifyActiveNetwork(TRANSPORT_WIFI);
1606     }
1607 
1608     @Test
testReapingNetwork()1609     public void testReapingNetwork() throws Exception {
1610         // Test bringing up WiFi without NET_CAPABILITY_INTERNET.
1611         // Expect it to be torn down immediately because it satisfies no requests.
1612         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1613         ConditionVariable cv = mWiFiNetworkAgent.getDisconnectedCV();
1614         mWiFiNetworkAgent.connectWithoutInternet();
1615         waitFor(cv);
1616         // Test bringing up cellular without NET_CAPABILITY_INTERNET.
1617         // Expect it to be torn down immediately because it satisfies no requests.
1618         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1619         cv = mCellNetworkAgent.getDisconnectedCV();
1620         mCellNetworkAgent.connectWithoutInternet();
1621         waitFor(cv);
1622         // Test bringing up validated WiFi.
1623         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1624         cv = waitForConnectivityBroadcasts(1);
1625         mWiFiNetworkAgent.connect(true);
1626         waitFor(cv);
1627         verifyActiveNetwork(TRANSPORT_WIFI);
1628         // Test bringing up unvalidated cellular.
1629         // Expect it to be torn down because it could never be the highest scoring network
1630         // satisfying the default request even if it validated.
1631         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1632         cv = mCellNetworkAgent.getDisconnectedCV();
1633         mCellNetworkAgent.connect(false);
1634         waitFor(cv);
1635         verifyActiveNetwork(TRANSPORT_WIFI);
1636         cv = mWiFiNetworkAgent.getDisconnectedCV();
1637         mWiFiNetworkAgent.disconnect();
1638         waitFor(cv);
1639     }
1640 
1641     @Test
testCellularFallback()1642     public void testCellularFallback() throws Exception {
1643         // Test bringing up validated cellular.
1644         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1645         ConditionVariable cv = waitForConnectivityBroadcasts(1);
1646         mCellNetworkAgent.connect(true);
1647         waitFor(cv);
1648         verifyActiveNetwork(TRANSPORT_CELLULAR);
1649         // Test bringing up validated WiFi.
1650         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1651         cv = waitForConnectivityBroadcasts(2);
1652         mWiFiNetworkAgent.connect(true);
1653         waitFor(cv);
1654         verifyActiveNetwork(TRANSPORT_WIFI);
1655         // Reevaluate WiFi (it'll instantly fail DNS).
1656         cv = waitForConnectivityBroadcasts(2);
1657         assertTrue(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1658                 NET_CAPABILITY_VALIDATED));
1659         mCm.reportBadNetwork(mWiFiNetworkAgent.getNetwork());
1660         // Should quickly fall back to Cellular.
1661         waitFor(cv);
1662         assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1663                 NET_CAPABILITY_VALIDATED));
1664         verifyActiveNetwork(TRANSPORT_CELLULAR);
1665         // Reevaluate cellular (it'll instantly fail DNS).
1666         cv = waitForConnectivityBroadcasts(2);
1667         assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1668                 NET_CAPABILITY_VALIDATED));
1669         mCm.reportBadNetwork(mCellNetworkAgent.getNetwork());
1670         // Should quickly fall back to WiFi.
1671         waitFor(cv);
1672         assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1673                 NET_CAPABILITY_VALIDATED));
1674         assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1675                 NET_CAPABILITY_VALIDATED));
1676         verifyActiveNetwork(TRANSPORT_WIFI);
1677     }
1678 
1679     @Test
testWiFiFallback()1680     public void testWiFiFallback() throws Exception {
1681         // Test bringing up unvalidated WiFi.
1682         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1683         ConditionVariable cv = waitForConnectivityBroadcasts(1);
1684         mWiFiNetworkAgent.connect(false);
1685         waitFor(cv);
1686         verifyActiveNetwork(TRANSPORT_WIFI);
1687         // Test bringing up validated cellular.
1688         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1689         cv = waitForConnectivityBroadcasts(2);
1690         mCellNetworkAgent.connect(true);
1691         waitFor(cv);
1692         verifyActiveNetwork(TRANSPORT_CELLULAR);
1693         // Reevaluate cellular (it'll instantly fail DNS).
1694         cv = waitForConnectivityBroadcasts(2);
1695         assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1696                 NET_CAPABILITY_VALIDATED));
1697         mCm.reportBadNetwork(mCellNetworkAgent.getNetwork());
1698         // Should quickly fall back to WiFi.
1699         waitFor(cv);
1700         assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1701                 NET_CAPABILITY_VALIDATED));
1702         verifyActiveNetwork(TRANSPORT_WIFI);
1703     }
1704 
1705     @Test
testRequiresValidation()1706     public void testRequiresValidation() {
1707         assertTrue(NetworkMonitorUtils.isValidationRequired(
1708                 mCm.getDefaultRequest().networkCapabilities));
1709     }
1710 
1711     enum CallbackState {
1712         NONE,
1713         AVAILABLE,
1714         NETWORK_CAPABILITIES,
1715         LINK_PROPERTIES,
1716         SUSPENDED,
1717         RESUMED,
1718         LOSING,
1719         LOST,
1720         UNAVAILABLE,
1721         BLOCKED_STATUS
1722     }
1723 
1724     private static class CallbackInfo {
1725         public final CallbackState state;
1726         public final Network network;
1727         public final Object arg;
CallbackInfo(CallbackState s, Network n, Object o)1728         public CallbackInfo(CallbackState s, Network n, Object o) {
1729             state = s; network = n; arg = o;
1730         }
toString()1731         public String toString() {
1732             return String.format("%s (%s) (%s)", state, network, arg);
1733         }
1734         @Override
equals(Object o)1735         public boolean equals(Object o) {
1736             if (!(o instanceof CallbackInfo)) return false;
1737             // Ignore timeMs, since it's unpredictable.
1738             CallbackInfo other = (CallbackInfo) o;
1739             return (state == other.state) && Objects.equals(network, other.network);
1740         }
1741         @Override
hashCode()1742         public int hashCode() {
1743             return Objects.hash(state, network);
1744         }
1745     }
1746 
1747     /**
1748      * Utility NetworkCallback for testing. The caller must explicitly test for all the callbacks
1749      * this class receives, by calling expectCallback() exactly once each time a callback is
1750      * received. assertNoCallback may be called at any time.
1751      */
1752     private class TestNetworkCallback extends NetworkCallback {
1753         private final LinkedBlockingQueue<CallbackInfo> mCallbacks = new LinkedBlockingQueue<>();
1754         private Network mLastAvailableNetwork;
1755 
setLastCallback(CallbackState state, Network network, Object o)1756         protected void setLastCallback(CallbackState state, Network network, Object o) {
1757             mCallbacks.offer(new CallbackInfo(state, network, o));
1758         }
1759 
1760         @Override
onAvailable(Network network)1761         public void onAvailable(Network network) {
1762             mLastAvailableNetwork = network;
1763             setLastCallback(CallbackState.AVAILABLE, network, null);
1764         }
1765 
1766         @Override
onCapabilitiesChanged(Network network, NetworkCapabilities netCap)1767         public void onCapabilitiesChanged(Network network, NetworkCapabilities netCap) {
1768             setLastCallback(CallbackState.NETWORK_CAPABILITIES, network, netCap);
1769         }
1770 
1771         @Override
onLinkPropertiesChanged(Network network, LinkProperties linkProp)1772         public void onLinkPropertiesChanged(Network network, LinkProperties linkProp) {
1773             setLastCallback(CallbackState.LINK_PROPERTIES, network, linkProp);
1774         }
1775 
1776         @Override
onUnavailable()1777         public void onUnavailable() {
1778             setLastCallback(CallbackState.UNAVAILABLE, null, null);
1779         }
1780 
1781         @Override
onNetworkSuspended(Network network)1782         public void onNetworkSuspended(Network network) {
1783             setLastCallback(CallbackState.SUSPENDED, network, null);
1784         }
1785 
1786         @Override
onNetworkResumed(Network network)1787         public void onNetworkResumed(Network network) {
1788             setLastCallback(CallbackState.RESUMED, network, null);
1789         }
1790 
1791         @Override
onLosing(Network network, int maxMsToLive)1792         public void onLosing(Network network, int maxMsToLive) {
1793             setLastCallback(CallbackState.LOSING, network, maxMsToLive /* autoboxed int */);
1794         }
1795 
1796         @Override
onLost(Network network)1797         public void onLost(Network network) {
1798             mLastAvailableNetwork = null;
1799             setLastCallback(CallbackState.LOST, network, null);
1800         }
1801 
1802         @Override
onBlockedStatusChanged(Network network, boolean blocked)1803         public void onBlockedStatusChanged(Network network, boolean blocked) {
1804             setLastCallback(CallbackState.BLOCKED_STATUS, network, blocked);
1805         }
1806 
getLastAvailableNetwork()1807         public Network getLastAvailableNetwork() {
1808             return mLastAvailableNetwork;
1809         }
1810 
nextCallback(int timeoutMs)1811         CallbackInfo nextCallback(int timeoutMs) {
1812             CallbackInfo cb = null;
1813             try {
1814                 cb = mCallbacks.poll(timeoutMs, TimeUnit.MILLISECONDS);
1815             } catch (InterruptedException e) {
1816             }
1817             if (cb == null) {
1818                 // LinkedBlockingQueue.poll() returns null if it timeouts.
1819                 fail("Did not receive callback after " + timeoutMs + "ms");
1820             }
1821             return cb;
1822         }
1823 
expectCallback(CallbackState state, MockNetworkAgent agent, int timeoutMs)1824         CallbackInfo expectCallback(CallbackState state, MockNetworkAgent agent, int timeoutMs) {
1825             final Network expectedNetwork = (agent != null) ? agent.getNetwork() : null;
1826             CallbackInfo expected = new CallbackInfo(state, expectedNetwork, 0);
1827             CallbackInfo actual = nextCallback(timeoutMs);
1828             assertEquals("Unexpected callback:", expected, actual);
1829 
1830             if (state == CallbackState.LOSING) {
1831                 String msg = String.format(
1832                         "Invalid linger time value %d, must be between %d and %d",
1833                         actual.arg, 0, mService.mLingerDelayMs);
1834                 int maxMsToLive = (Integer) actual.arg;
1835                 assertTrue(msg, 0 <= maxMsToLive && maxMsToLive <= mService.mLingerDelayMs);
1836             }
1837 
1838             return actual;
1839         }
1840 
expectCallback(CallbackState state, MockNetworkAgent agent)1841         CallbackInfo expectCallback(CallbackState state, MockNetworkAgent agent) {
1842             return expectCallback(state, agent, TEST_CALLBACK_TIMEOUT_MS);
1843         }
1844 
expectCallbackLike(Predicate<CallbackInfo> fn)1845         CallbackInfo expectCallbackLike(Predicate<CallbackInfo> fn) {
1846             return expectCallbackLike(fn, TEST_CALLBACK_TIMEOUT_MS);
1847         }
1848 
expectCallbackLike(Predicate<CallbackInfo> fn, int timeoutMs)1849         CallbackInfo expectCallbackLike(Predicate<CallbackInfo> fn, int timeoutMs) {
1850             int timeLeft = timeoutMs;
1851             while (timeLeft > 0) {
1852                 long start = SystemClock.elapsedRealtime();
1853                 CallbackInfo info = nextCallback(timeLeft);
1854                 if (fn.test(info)) {
1855                     return info;
1856                 }
1857                 timeLeft -= (SystemClock.elapsedRealtime() - start);
1858             }
1859             fail("Did not receive expected callback after " + timeoutMs + "ms");
1860             return null;
1861         }
1862 
1863         // Expects onAvailable and the callbacks that follow it. These are:
1864         // - onSuspended, iff the network was suspended when the callbacks fire.
1865         // - onCapabilitiesChanged.
1866         // - onLinkPropertiesChanged.
1867         // - onBlockedStatusChanged.
1868         //
1869         // @param agent the network to expect the callbacks on.
1870         // @param expectSuspended whether to expect a SUSPENDED callback.
1871         // @param expectValidated the expected value of the VALIDATED capability in the
1872         //        onCapabilitiesChanged callback.
1873         // @param timeoutMs how long to wait for the callbacks.
expectAvailableCallbacks(MockNetworkAgent agent, boolean expectSuspended, boolean expectValidated, boolean expectBlocked, int timeoutMs)1874         void expectAvailableCallbacks(MockNetworkAgent agent, boolean expectSuspended,
1875                 boolean expectValidated, boolean expectBlocked, int timeoutMs) {
1876             expectCallback(CallbackState.AVAILABLE, agent, timeoutMs);
1877             if (expectSuspended) {
1878                 expectCallback(CallbackState.SUSPENDED, agent, timeoutMs);
1879             }
1880             if (expectValidated) {
1881                 expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, agent, timeoutMs);
1882             } else {
1883                 expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, agent, timeoutMs);
1884             }
1885             expectCallback(CallbackState.LINK_PROPERTIES, agent, timeoutMs);
1886             expectBlockedStatusCallback(expectBlocked, agent);
1887         }
1888 
1889         // Expects the available callbacks (validated), plus onSuspended.
expectAvailableAndSuspendedCallbacks(MockNetworkAgent agent, boolean expectValidated)1890         void expectAvailableAndSuspendedCallbacks(MockNetworkAgent agent, boolean expectValidated) {
1891             expectAvailableCallbacks(agent, true, expectValidated, false, TEST_CALLBACK_TIMEOUT_MS);
1892         }
1893 
expectAvailableCallbacksValidated(MockNetworkAgent agent)1894         void expectAvailableCallbacksValidated(MockNetworkAgent agent) {
1895             expectAvailableCallbacks(agent, false, true, false, TEST_CALLBACK_TIMEOUT_MS);
1896         }
1897 
expectAvailableCallbacksValidatedAndBlocked(MockNetworkAgent agent)1898         void expectAvailableCallbacksValidatedAndBlocked(MockNetworkAgent agent) {
1899             expectAvailableCallbacks(agent, false, true, true, TEST_CALLBACK_TIMEOUT_MS);
1900         }
1901 
expectAvailableCallbacksUnvalidated(MockNetworkAgent agent)1902         void expectAvailableCallbacksUnvalidated(MockNetworkAgent agent) {
1903             expectAvailableCallbacks(agent, false, false, false, TEST_CALLBACK_TIMEOUT_MS);
1904         }
1905 
expectAvailableCallbacksUnvalidatedAndBlocked(MockNetworkAgent agent)1906         void expectAvailableCallbacksUnvalidatedAndBlocked(MockNetworkAgent agent) {
1907             expectAvailableCallbacks(agent, false, false, true, TEST_CALLBACK_TIMEOUT_MS);
1908         }
1909 
1910         // Expects the available callbacks (where the onCapabilitiesChanged must contain the
1911         // VALIDATED capability), plus another onCapabilitiesChanged which is identical to the
1912         // one we just sent.
1913         // TODO: this is likely a bug. Fix it and remove this method.
expectAvailableDoubleValidatedCallbacks(MockNetworkAgent agent)1914         void expectAvailableDoubleValidatedCallbacks(MockNetworkAgent agent) {
1915             expectCallback(CallbackState.AVAILABLE, agent, TEST_CALLBACK_TIMEOUT_MS);
1916             NetworkCapabilities nc1 = expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, agent);
1917             expectCallback(CallbackState.LINK_PROPERTIES, agent, TEST_CALLBACK_TIMEOUT_MS);
1918             // Implicitly check the network is allowed to use.
1919             // TODO: should we need to consider if network is in blocked status in this case?
1920             expectBlockedStatusCallback(false, agent);
1921             NetworkCapabilities nc2 = expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, agent);
1922             assertEquals(nc1, nc2);
1923         }
1924 
1925         // Expects the available callbacks where the onCapabilitiesChanged must not have validated,
1926         // then expects another onCapabilitiesChanged that has the validated bit set. This is used
1927         // when a network connects and satisfies a callback, and then immediately validates.
expectAvailableThenValidatedCallbacks(MockNetworkAgent agent)1928         void expectAvailableThenValidatedCallbacks(MockNetworkAgent agent) {
1929             expectAvailableCallbacksUnvalidated(agent);
1930             expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, agent);
1931         }
1932 
expectCapabilitiesWith(int capability, MockNetworkAgent agent)1933         NetworkCapabilities expectCapabilitiesWith(int capability, MockNetworkAgent agent) {
1934             return expectCapabilitiesWith(capability, agent, TEST_CALLBACK_TIMEOUT_MS);
1935         }
1936 
expectCapabilitiesWith(int capability, MockNetworkAgent agent, int timeoutMs)1937         NetworkCapabilities expectCapabilitiesWith(int capability, MockNetworkAgent agent,
1938                 int timeoutMs) {
1939             CallbackInfo cbi = expectCallback(CallbackState.NETWORK_CAPABILITIES, agent, timeoutMs);
1940             NetworkCapabilities nc = (NetworkCapabilities) cbi.arg;
1941             assertTrue(nc.hasCapability(capability));
1942             return nc;
1943         }
1944 
expectCapabilitiesWithout(int capability, MockNetworkAgent agent)1945         NetworkCapabilities expectCapabilitiesWithout(int capability, MockNetworkAgent agent) {
1946             return expectCapabilitiesWithout(capability, agent, TEST_CALLBACK_TIMEOUT_MS);
1947         }
1948 
expectCapabilitiesWithout(int capability, MockNetworkAgent agent, int timeoutMs)1949         NetworkCapabilities expectCapabilitiesWithout(int capability, MockNetworkAgent agent,
1950                 int timeoutMs) {
1951             CallbackInfo cbi = expectCallback(CallbackState.NETWORK_CAPABILITIES, agent, timeoutMs);
1952             NetworkCapabilities nc = (NetworkCapabilities) cbi.arg;
1953             assertFalse(nc.hasCapability(capability));
1954             return nc;
1955         }
1956 
expectCapabilitiesLike(Predicate<NetworkCapabilities> fn, MockNetworkAgent agent)1957         void expectCapabilitiesLike(Predicate<NetworkCapabilities> fn, MockNetworkAgent agent) {
1958             CallbackInfo cbi = expectCallback(CallbackState.NETWORK_CAPABILITIES, agent);
1959             assertTrue("Received capabilities don't match expectations : " + cbi.arg,
1960                     fn.test((NetworkCapabilities) cbi.arg));
1961         }
1962 
expectLinkPropertiesLike(Predicate<LinkProperties> fn, MockNetworkAgent agent)1963         void expectLinkPropertiesLike(Predicate<LinkProperties> fn, MockNetworkAgent agent) {
1964             CallbackInfo cbi = expectCallback(CallbackState.LINK_PROPERTIES, agent);
1965             assertTrue("Received LinkProperties don't match expectations : " + cbi.arg,
1966                     fn.test((LinkProperties) cbi.arg));
1967         }
1968 
expectBlockedStatusCallback(boolean expectBlocked, MockNetworkAgent agent)1969         void expectBlockedStatusCallback(boolean expectBlocked, MockNetworkAgent agent) {
1970             CallbackInfo cbi = expectCallback(CallbackState.BLOCKED_STATUS, agent);
1971             boolean actualBlocked = (boolean) cbi.arg;
1972             assertEquals(expectBlocked, actualBlocked);
1973         }
1974 
assertNoCallback()1975         void assertNoCallback() {
1976             waitForIdle();
1977             CallbackInfo c = mCallbacks.peek();
1978             assertNull("Unexpected callback: " + c, c);
1979         }
1980     }
1981 
1982     // Can't be part of TestNetworkCallback because "cannot be declared static; static methods can
1983     // only be declared in a static or top level type".
assertNoCallbacks(TestNetworkCallback .... callbacks)1984     static void assertNoCallbacks(TestNetworkCallback ... callbacks) {
1985         for (TestNetworkCallback c : callbacks) {
1986             c.assertNoCallback();
1987         }
1988     }
1989 
1990     @Test
testStateChangeNetworkCallbacks()1991     public void testStateChangeNetworkCallbacks() throws Exception {
1992         final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback();
1993         final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
1994         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
1995         final NetworkRequest genericRequest = new NetworkRequest.Builder()
1996                 .clearCapabilities().build();
1997         final NetworkRequest wifiRequest = new NetworkRequest.Builder()
1998                 .addTransportType(TRANSPORT_WIFI).build();
1999         final NetworkRequest cellRequest = new NetworkRequest.Builder()
2000                 .addTransportType(TRANSPORT_CELLULAR).build();
2001         mCm.registerNetworkCallback(genericRequest, genericNetworkCallback);
2002         mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
2003         mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
2004 
2005         // Test unvalidated networks
2006         ConditionVariable cv = waitForConnectivityBroadcasts(1);
2007         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2008         mCellNetworkAgent.connect(false);
2009         genericNetworkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
2010         cellNetworkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
2011         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2012         waitFor(cv);
2013         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
2014 
2015         // This should not trigger spurious onAvailable() callbacks, b/21762680.
2016         mCellNetworkAgent.adjustScore(-1);
2017         waitForIdle();
2018         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
2019         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2020 
2021         cv = waitForConnectivityBroadcasts(2);
2022         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2023         mWiFiNetworkAgent.connect(false);
2024         genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2025         wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2026         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2027         waitFor(cv);
2028         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
2029 
2030         cv = waitForConnectivityBroadcasts(2);
2031         mWiFiNetworkAgent.disconnect();
2032         genericNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2033         wifiNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2034         cellNetworkCallback.assertNoCallback();
2035         waitFor(cv);
2036         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
2037 
2038         cv = waitForConnectivityBroadcasts(1);
2039         mCellNetworkAgent.disconnect();
2040         genericNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
2041         cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
2042         waitFor(cv);
2043         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
2044 
2045         // Test validated networks
2046         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2047         mCellNetworkAgent.connect(true);
2048         genericNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2049         cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2050         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2051         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
2052 
2053         // This should not trigger spurious onAvailable() callbacks, b/21762680.
2054         mCellNetworkAgent.adjustScore(-1);
2055         waitForIdle();
2056         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
2057         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2058 
2059         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2060         mWiFiNetworkAgent.connect(true);
2061         genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2062         genericNetworkCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
2063         genericNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
2064         wifiNetworkCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
2065         cellNetworkCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
2066         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2067         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
2068 
2069         mWiFiNetworkAgent.disconnect();
2070         genericNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2071         wifiNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2072         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
2073 
2074         mCellNetworkAgent.disconnect();
2075         genericNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
2076         cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
2077         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
2078     }
2079 
2080     @Test
testMultipleLingering()2081     public void testMultipleLingering() {
2082         // This test would be flaky with the default 120ms timer: that is short enough that
2083         // lingered networks are torn down before assertions can be run. We don't want to mock the
2084         // lingering timer to keep the WakeupMessage logic realistic: this has already proven useful
2085         // in detecting races.
2086         mService.mLingerDelayMs = 300;
2087 
2088         NetworkRequest request = new NetworkRequest.Builder()
2089                 .clearCapabilities().addCapability(NET_CAPABILITY_NOT_METERED)
2090                 .build();
2091         TestNetworkCallback callback = new TestNetworkCallback();
2092         mCm.registerNetworkCallback(request, callback);
2093 
2094         TestNetworkCallback defaultCallback = new TestNetworkCallback();
2095         mCm.registerDefaultNetworkCallback(defaultCallback);
2096 
2097         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2098         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2099         mEthernetNetworkAgent = new MockNetworkAgent(TRANSPORT_ETHERNET);
2100 
2101         mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
2102         mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
2103         mEthernetNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
2104 
2105         mCellNetworkAgent.connect(true);
2106         callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2107         defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2108         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2109         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
2110 
2111         mWiFiNetworkAgent.connect(true);
2112         // We get AVAILABLE on wifi when wifi connects and satisfies our unmetered request.
2113         // We then get LOSING when wifi validates and cell is outscored.
2114         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2115         // TODO: Investigate sending validated before losing.
2116         callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
2117         callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
2118         defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
2119         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2120         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
2121 
2122         mEthernetNetworkAgent.connect(true);
2123         callback.expectAvailableCallbacksUnvalidated(mEthernetNetworkAgent);
2124         // TODO: Investigate sending validated before losing.
2125         callback.expectCallback(CallbackState.LOSING, mWiFiNetworkAgent);
2126         callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mEthernetNetworkAgent);
2127         defaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent);
2128         assertEquals(mEthernetNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2129         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
2130 
2131         mEthernetNetworkAgent.disconnect();
2132         callback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
2133         defaultCallback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
2134         defaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
2135         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
2136 
2137         for (int i = 0; i < 4; i++) {
2138             MockNetworkAgent oldNetwork, newNetwork;
2139             if (i % 2 == 0) {
2140                 mWiFiNetworkAgent.adjustScore(-15);
2141                 oldNetwork = mWiFiNetworkAgent;
2142                 newNetwork = mCellNetworkAgent;
2143             } else {
2144                 mWiFiNetworkAgent.adjustScore(15);
2145                 oldNetwork = mCellNetworkAgent;
2146                 newNetwork = mWiFiNetworkAgent;
2147 
2148             }
2149             callback.expectCallback(CallbackState.LOSING, oldNetwork);
2150             // TODO: should we send an AVAILABLE callback to newNetwork, to indicate that it is no
2151             // longer lingering?
2152             defaultCallback.expectAvailableCallbacksValidated(newNetwork);
2153             assertEquals(newNetwork.getNetwork(), mCm.getActiveNetwork());
2154         }
2155         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2156 
2157         // Verify that if a network no longer satisfies a request, we send LOST and not LOSING, even
2158         // if the network is still up.
2159         mWiFiNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
2160         // We expect a notification about the capabilities change, and nothing else.
2161         defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_METERED, mWiFiNetworkAgent);
2162         defaultCallback.assertNoCallback();
2163         callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2164         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
2165 
2166         // Wifi no longer satisfies our listen, which is for an unmetered network.
2167         // But because its score is 55, it's still up (and the default network).
2168         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2169 
2170         // Disconnect our test networks.
2171         mWiFiNetworkAgent.disconnect();
2172         defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2173         defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
2174         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
2175         mCellNetworkAgent.disconnect();
2176         defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
2177         waitForIdle();
2178         assertEquals(null, mCm.getActiveNetwork());
2179 
2180         mCm.unregisterNetworkCallback(callback);
2181         waitForIdle();
2182 
2183         // Check that a network is only lingered or torn down if it would not satisfy a request even
2184         // if it validated.
2185         request = new NetworkRequest.Builder().clearCapabilities().build();
2186         callback = new TestNetworkCallback();
2187 
2188         mCm.registerNetworkCallback(request, callback);
2189 
2190         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2191         mCellNetworkAgent.connect(false);   // Score: 10
2192         callback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
2193         defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
2194         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2195         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
2196 
2197         // Bring up wifi with a score of 20.
2198         // Cell stays up because it would satisfy the default request if it validated.
2199         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2200         mWiFiNetworkAgent.connect(false);   // Score: 20
2201         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2202         defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2203         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2204         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
2205 
2206         mWiFiNetworkAgent.disconnect();
2207         callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2208         defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2209         defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
2210         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2211         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
2212 
2213         // Bring up wifi with a score of 70.
2214         // Cell is lingered because it would not satisfy any request, even if it validated.
2215         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2216         mWiFiNetworkAgent.adjustScore(50);
2217         mWiFiNetworkAgent.connect(false);   // Score: 70
2218         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2219         callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
2220         defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2221         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2222         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
2223 
2224         // Tear down wifi.
2225         mWiFiNetworkAgent.disconnect();
2226         callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2227         defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2228         defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
2229         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2230         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
2231 
2232         // Bring up wifi, then validate it. Previous versions would immediately tear down cell, but
2233         // it's arguably correct to linger it, since it was the default network before it validated.
2234         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2235         mWiFiNetworkAgent.connect(true);
2236         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2237         // TODO: Investigate sending validated before losing.
2238         callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
2239         callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
2240         defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
2241         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2242         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
2243 
2244         mWiFiNetworkAgent.disconnect();
2245         callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2246         defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2247         defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
2248         mCellNetworkAgent.disconnect();
2249         callback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
2250         defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
2251         waitForIdle();
2252         assertEquals(null, mCm.getActiveNetwork());
2253 
2254         // If a network is lingering, and we add and remove a request from it, resume lingering.
2255         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2256         mCellNetworkAgent.connect(true);
2257         callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2258         defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2259         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
2260         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2261         mWiFiNetworkAgent.connect(true);
2262         defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
2263         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2264         // TODO: Investigate sending validated before losing.
2265         callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
2266         callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
2267         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
2268 
2269         NetworkRequest cellRequest = new NetworkRequest.Builder()
2270                 .addTransportType(TRANSPORT_CELLULAR).build();
2271         NetworkCallback noopCallback = new NetworkCallback();
2272         mCm.requestNetwork(cellRequest, noopCallback);
2273         // TODO: should this cause an AVAILABLE callback, to indicate that the network is no longer
2274         // lingering?
2275         mCm.unregisterNetworkCallback(noopCallback);
2276         callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
2277 
2278         // Similar to the above: lingering can start even after the lingered request is removed.
2279         // Disconnect wifi and switch to cell.
2280         mWiFiNetworkAgent.disconnect();
2281         callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2282         defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2283         defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
2284         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
2285 
2286         // Cell is now the default network. Pin it with a cell-specific request.
2287         noopCallback = new NetworkCallback();  // Can't reuse NetworkCallbacks. http://b/20701525
2288         mCm.requestNetwork(cellRequest, noopCallback);
2289 
2290         // Now connect wifi, and expect it to become the default network.
2291         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2292         mWiFiNetworkAgent.connect(true);
2293         callback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
2294         defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
2295         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
2296         // The default request is lingering on cell, but nothing happens to cell, and we send no
2297         // callbacks for it, because it's kept up by cellRequest.
2298         callback.assertNoCallback();
2299         // Now unregister cellRequest and expect cell to start lingering.
2300         mCm.unregisterNetworkCallback(noopCallback);
2301         callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
2302 
2303         // Let linger run its course.
2304         callback.assertNoCallback();
2305         final int lingerTimeoutMs = mService.mLingerDelayMs + mService.mLingerDelayMs / 4;
2306         callback.expectCallback(CallbackState.LOST, mCellNetworkAgent, lingerTimeoutMs);
2307 
2308         // Register a TRACK_DEFAULT request and check that it does not affect lingering.
2309         TestNetworkCallback trackDefaultCallback = new TestNetworkCallback();
2310         mCm.registerDefaultNetworkCallback(trackDefaultCallback);
2311         trackDefaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
2312         mEthernetNetworkAgent = new MockNetworkAgent(TRANSPORT_ETHERNET);
2313         mEthernetNetworkAgent.connect(true);
2314         callback.expectAvailableCallbacksUnvalidated(mEthernetNetworkAgent);
2315         callback.expectCallback(CallbackState.LOSING, mWiFiNetworkAgent);
2316         callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mEthernetNetworkAgent);
2317         trackDefaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent);
2318         defaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent);
2319         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
2320 
2321         // Let linger run its course.
2322         callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent, lingerTimeoutMs);
2323 
2324         // Clean up.
2325         mEthernetNetworkAgent.disconnect();
2326         callback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
2327         defaultCallback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
2328         trackDefaultCallback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
2329 
2330         mCm.unregisterNetworkCallback(callback);
2331         mCm.unregisterNetworkCallback(defaultCallback);
2332         mCm.unregisterNetworkCallback(trackDefaultCallback);
2333     }
2334 
2335     @Test
testNetworkGoesIntoBackgroundAfterLinger()2336     public void testNetworkGoesIntoBackgroundAfterLinger() {
2337         setAlwaysOnNetworks(true);
2338         NetworkRequest request = new NetworkRequest.Builder()
2339                 .clearCapabilities()
2340                 .build();
2341         TestNetworkCallback callback = new TestNetworkCallback();
2342         mCm.registerNetworkCallback(request, callback);
2343 
2344         TestNetworkCallback defaultCallback = new TestNetworkCallback();
2345         mCm.registerDefaultNetworkCallback(defaultCallback);
2346 
2347         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2348         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2349 
2350         mCellNetworkAgent.connect(true);
2351         callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2352         defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2353 
2354         // Wifi comes up and cell lingers.
2355         mWiFiNetworkAgent.connect(true);
2356         defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
2357         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2358         callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
2359         callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
2360 
2361         // File a request for cellular, then release it.
2362         NetworkRequest cellRequest = new NetworkRequest.Builder()
2363                 .addTransportType(TRANSPORT_CELLULAR).build();
2364         NetworkCallback noopCallback = new NetworkCallback();
2365         mCm.requestNetwork(cellRequest, noopCallback);
2366         mCm.unregisterNetworkCallback(noopCallback);
2367         callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
2368 
2369         // Let linger run its course.
2370         callback.assertNoCallback();
2371         final int lingerTimeoutMs = TEST_LINGER_DELAY_MS + TEST_LINGER_DELAY_MS / 4;
2372         callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent,
2373                 lingerTimeoutMs);
2374 
2375         // Clean up.
2376         mCm.unregisterNetworkCallback(defaultCallback);
2377         mCm.unregisterNetworkCallback(callback);
2378     }
2379 
2380     @Test
testExplicitlySelected()2381     public void testExplicitlySelected() {
2382         NetworkRequest request = new NetworkRequest.Builder()
2383                 .clearCapabilities().addCapability(NET_CAPABILITY_INTERNET)
2384                 .build();
2385         TestNetworkCallback callback = new TestNetworkCallback();
2386         mCm.registerNetworkCallback(request, callback);
2387 
2388         // Bring up validated cell.
2389         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2390         mCellNetworkAgent.connect(true);
2391         callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2392 
2393         // Bring up unvalidated wifi with explicitlySelected=true.
2394         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2395         mWiFiNetworkAgent.explicitlySelected(false);
2396         mWiFiNetworkAgent.connect(false);
2397         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2398 
2399         // Cell Remains the default.
2400         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2401 
2402         // Lower wifi's score to below than cell, and check that it doesn't disconnect because
2403         // it's explicitly selected.
2404         mWiFiNetworkAgent.adjustScore(-40);
2405         mWiFiNetworkAgent.adjustScore(40);
2406         callback.assertNoCallback();
2407 
2408         // If the user chooses yes on the "No Internet access, stay connected?" dialog, we switch to
2409         // wifi even though it's unvalidated.
2410         mCm.setAcceptUnvalidated(mWiFiNetworkAgent.getNetwork(), true, false);
2411         callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
2412         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2413 
2414         // Disconnect wifi, and then reconnect, again with explicitlySelected=true.
2415         mWiFiNetworkAgent.disconnect();
2416         callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2417         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2418         mWiFiNetworkAgent.explicitlySelected(false);
2419         mWiFiNetworkAgent.connect(false);
2420         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2421 
2422         // If the user chooses no on the "No Internet access, stay connected?" dialog, we ask the
2423         // network to disconnect.
2424         mCm.setAcceptUnvalidated(mWiFiNetworkAgent.getNetwork(), false, false);
2425         callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2426 
2427         // Reconnect, again with explicitlySelected=true, but this time validate.
2428         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2429         mWiFiNetworkAgent.explicitlySelected(false);
2430         mWiFiNetworkAgent.connect(true);
2431         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2432         callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
2433         callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
2434         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2435 
2436         // BUG: the network will no longer linger, even though it's validated and outscored.
2437         // TODO: fix this.
2438         mEthernetNetworkAgent = new MockNetworkAgent(TRANSPORT_ETHERNET);
2439         mEthernetNetworkAgent.connect(true);
2440         callback.expectAvailableThenValidatedCallbacks(mEthernetNetworkAgent);
2441         assertEquals(mEthernetNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2442         callback.assertNoCallback();
2443 
2444         // Clean up.
2445         mWiFiNetworkAgent.disconnect();
2446         mCellNetworkAgent.disconnect();
2447         mEthernetNetworkAgent.disconnect();
2448 
2449         callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2450         callback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
2451         callback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
2452     }
2453 
makeIntArray(final int size, final int value)2454     private int[] makeIntArray(final int size, final int value) {
2455         final int[] array = new int[size];
2456         Arrays.fill(array, value);
2457         return array;
2458     }
2459 
tryNetworkFactoryRequests(int capability)2460     private void tryNetworkFactoryRequests(int capability) throws Exception {
2461         // Verify NOT_RESTRICTED is set appropriately
2462         final NetworkCapabilities nc = new NetworkRequest.Builder().addCapability(capability)
2463                 .build().networkCapabilities;
2464         if (capability == NET_CAPABILITY_CBS || capability == NET_CAPABILITY_DUN ||
2465                 capability == NET_CAPABILITY_EIMS || capability == NET_CAPABILITY_FOTA ||
2466                 capability == NET_CAPABILITY_IA || capability == NET_CAPABILITY_IMS ||
2467                 capability == NET_CAPABILITY_RCS || capability == NET_CAPABILITY_XCAP) {
2468             assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
2469         } else {
2470             assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
2471         }
2472 
2473         NetworkCapabilities filter = new NetworkCapabilities();
2474         filter.addCapability(capability);
2475         final HandlerThread handlerThread = new HandlerThread("testNetworkFactoryRequests");
2476         handlerThread.start();
2477         final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
2478                 mServiceContext, "testFactory", filter);
2479         testFactory.setScoreFilter(40);
2480         ConditionVariable cv = testFactory.getNetworkStartedCV();
2481         testFactory.expectAddRequestsWithScores(0);
2482         testFactory.register();
2483         testFactory.waitForNetworkRequests(1);
2484         int expectedRequestCount = 1;
2485         NetworkCallback networkCallback = null;
2486         // For non-INTERNET capabilities we cannot rely on the default request being present, so
2487         // add one.
2488         if (capability != NET_CAPABILITY_INTERNET) {
2489             assertFalse(testFactory.getMyStartRequested());
2490             NetworkRequest request = new NetworkRequest.Builder().addCapability(capability).build();
2491             networkCallback = new NetworkCallback();
2492             testFactory.expectAddRequestsWithScores(0);  // New request
2493             mCm.requestNetwork(request, networkCallback);
2494             expectedRequestCount++;
2495             testFactory.waitForNetworkRequests(expectedRequestCount);
2496         }
2497         waitFor(cv);
2498         assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
2499         assertTrue(testFactory.getMyStartRequested());
2500 
2501         // Now bring in a higher scored network.
2502         MockNetworkAgent testAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2503         // Rather than create a validated network which complicates things by registering it's
2504         // own NetworkRequest during startup, just bump up the score to cancel out the
2505         // unvalidated penalty.
2506         testAgent.adjustScore(40);
2507         cv = testFactory.getNetworkStoppedCV();
2508 
2509         // When testAgent connects, ConnectivityService will re-send us all current requests with
2510         // the new score. There are expectedRequestCount such requests, and we must wait for all of
2511         // them.
2512         testFactory.expectAddRequestsWithScores(makeIntArray(expectedRequestCount, 50));
2513         testAgent.connect(false);
2514         testAgent.addCapability(capability);
2515         waitFor(cv);
2516         testFactory.waitForNetworkRequests(expectedRequestCount);
2517         assertFalse(testFactory.getMyStartRequested());
2518 
2519         // Bring in a bunch of requests.
2520         testFactory.expectAddRequestsWithScores(makeIntArray(10, 50));
2521         assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
2522         ConnectivityManager.NetworkCallback[] networkCallbacks =
2523                 new ConnectivityManager.NetworkCallback[10];
2524         for (int i = 0; i< networkCallbacks.length; i++) {
2525             networkCallbacks[i] = new ConnectivityManager.NetworkCallback();
2526             NetworkRequest.Builder builder = new NetworkRequest.Builder();
2527             builder.addCapability(capability);
2528             mCm.requestNetwork(builder.build(), networkCallbacks[i]);
2529         }
2530         testFactory.waitForNetworkRequests(10 + expectedRequestCount);
2531         assertFalse(testFactory.getMyStartRequested());
2532 
2533         // Remove the requests.
2534         testFactory.expectRemoveRequests(10);
2535         for (int i = 0; i < networkCallbacks.length; i++) {
2536             mCm.unregisterNetworkCallback(networkCallbacks[i]);
2537         }
2538         testFactory.waitForNetworkRequests(expectedRequestCount);
2539         assertFalse(testFactory.getMyStartRequested());
2540 
2541         // Drop the higher scored network.
2542         cv = testFactory.getNetworkStartedCV();
2543         // With the default network disconnecting, the requests are sent with score 0 to factories.
2544         testFactory.expectAddRequestsWithScores(makeIntArray(expectedRequestCount, 0));
2545         testAgent.disconnect();
2546         waitFor(cv);
2547         testFactory.waitForNetworkRequests(expectedRequestCount);
2548         assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
2549         assertTrue(testFactory.getMyStartRequested());
2550 
2551         testFactory.unregister();
2552         if (networkCallback != null) mCm.unregisterNetworkCallback(networkCallback);
2553         handlerThread.quit();
2554     }
2555 
2556     @Test
testNetworkFactoryRequests()2557     public void testNetworkFactoryRequests() throws Exception {
2558         tryNetworkFactoryRequests(NET_CAPABILITY_MMS);
2559         tryNetworkFactoryRequests(NET_CAPABILITY_SUPL);
2560         tryNetworkFactoryRequests(NET_CAPABILITY_DUN);
2561         tryNetworkFactoryRequests(NET_CAPABILITY_FOTA);
2562         tryNetworkFactoryRequests(NET_CAPABILITY_IMS);
2563         tryNetworkFactoryRequests(NET_CAPABILITY_CBS);
2564         tryNetworkFactoryRequests(NET_CAPABILITY_WIFI_P2P);
2565         tryNetworkFactoryRequests(NET_CAPABILITY_IA);
2566         tryNetworkFactoryRequests(NET_CAPABILITY_RCS);
2567         tryNetworkFactoryRequests(NET_CAPABILITY_XCAP);
2568         tryNetworkFactoryRequests(NET_CAPABILITY_EIMS);
2569         tryNetworkFactoryRequests(NET_CAPABILITY_NOT_METERED);
2570         tryNetworkFactoryRequests(NET_CAPABILITY_INTERNET);
2571         tryNetworkFactoryRequests(NET_CAPABILITY_TRUSTED);
2572         tryNetworkFactoryRequests(NET_CAPABILITY_NOT_VPN);
2573         // Skipping VALIDATED and CAPTIVE_PORTAL as they're disallowed.
2574     }
2575 
2576     @Test
testNoMutableNetworkRequests()2577     public void testNoMutableNetworkRequests() throws Exception {
2578         PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, new Intent("a"), 0);
2579         NetworkRequest request1 = new NetworkRequest.Builder()
2580                 .addCapability(NET_CAPABILITY_VALIDATED)
2581                 .build();
2582         NetworkRequest request2 = new NetworkRequest.Builder()
2583                 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL)
2584                 .build();
2585 
2586         Class<IllegalArgumentException> expected = IllegalArgumentException.class;
2587         assertException(() -> { mCm.requestNetwork(request1, new NetworkCallback()); }, expected);
2588         assertException(() -> { mCm.requestNetwork(request1, pendingIntent); }, expected);
2589         assertException(() -> { mCm.requestNetwork(request2, new NetworkCallback()); }, expected);
2590         assertException(() -> { mCm.requestNetwork(request2, pendingIntent); }, expected);
2591     }
2592 
2593     @Test
testMMSonWiFi()2594     public void testMMSonWiFi() throws Exception {
2595         // Test bringing up cellular without MMS NetworkRequest gets reaped
2596         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2597         mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS);
2598         ConditionVariable cv = mCellNetworkAgent.getDisconnectedCV();
2599         mCellNetworkAgent.connectWithoutInternet();
2600         waitFor(cv);
2601         waitForIdle();
2602         assertEmpty(mCm.getAllNetworks());
2603         verifyNoNetwork();
2604 
2605         // Test bringing up validated WiFi.
2606         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2607         cv = waitForConnectivityBroadcasts(1);
2608         mWiFiNetworkAgent.connect(true);
2609         waitFor(cv);
2610         verifyActiveNetwork(TRANSPORT_WIFI);
2611 
2612         // Register MMS NetworkRequest
2613         NetworkRequest.Builder builder = new NetworkRequest.Builder();
2614         builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
2615         final TestNetworkCallback networkCallback = new TestNetworkCallback();
2616         mCm.requestNetwork(builder.build(), networkCallback);
2617 
2618         // Test bringing up unvalidated cellular with MMS
2619         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2620         mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS);
2621         mCellNetworkAgent.connectWithoutInternet();
2622         networkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
2623         verifyActiveNetwork(TRANSPORT_WIFI);
2624 
2625         // Test releasing NetworkRequest disconnects cellular with MMS
2626         cv = mCellNetworkAgent.getDisconnectedCV();
2627         mCm.unregisterNetworkCallback(networkCallback);
2628         waitFor(cv);
2629         verifyActiveNetwork(TRANSPORT_WIFI);
2630     }
2631 
2632     @Test
testMMSonCell()2633     public void testMMSonCell() throws Exception {
2634         // Test bringing up cellular without MMS
2635         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2636         ConditionVariable cv = waitForConnectivityBroadcasts(1);
2637         mCellNetworkAgent.connect(false);
2638         waitFor(cv);
2639         verifyActiveNetwork(TRANSPORT_CELLULAR);
2640 
2641         // Register MMS NetworkRequest
2642         NetworkRequest.Builder builder = new NetworkRequest.Builder();
2643         builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
2644         final TestNetworkCallback networkCallback = new TestNetworkCallback();
2645         mCm.requestNetwork(builder.build(), networkCallback);
2646 
2647         // Test bringing up MMS cellular network
2648         MockNetworkAgent mmsNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2649         mmsNetworkAgent.addCapability(NET_CAPABILITY_MMS);
2650         mmsNetworkAgent.connectWithoutInternet();
2651         networkCallback.expectAvailableCallbacksUnvalidated(mmsNetworkAgent);
2652         verifyActiveNetwork(TRANSPORT_CELLULAR);
2653 
2654         // Test releasing MMS NetworkRequest does not disconnect main cellular NetworkAgent
2655         cv = mmsNetworkAgent.getDisconnectedCV();
2656         mCm.unregisterNetworkCallback(networkCallback);
2657         waitFor(cv);
2658         verifyActiveNetwork(TRANSPORT_CELLULAR);
2659     }
2660 
2661     @Test
testPartialConnectivity()2662     public void testPartialConnectivity() {
2663         // Register network callback.
2664         NetworkRequest request = new NetworkRequest.Builder()
2665                 .clearCapabilities().addCapability(NET_CAPABILITY_INTERNET)
2666                 .build();
2667         TestNetworkCallback callback = new TestNetworkCallback();
2668         mCm.registerNetworkCallback(request, callback);
2669 
2670         // Bring up validated mobile data.
2671         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2672         mCellNetworkAgent.connect(true);
2673         callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2674 
2675         // Bring up wifi with partial connectivity.
2676         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2677         mWiFiNetworkAgent.connectWithPartialConnectivity();
2678         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2679         callback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY, mWiFiNetworkAgent);
2680 
2681         // Mobile data should be the default network.
2682         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2683         callback.assertNoCallback();
2684 
2685         // With HTTPS probe disabled, NetworkMonitor should pass the network validation with http
2686         // probe.
2687         mWiFiNetworkAgent.setNetworkPartialValid();
2688         // If the user chooses yes to use this partial connectivity wifi, switch the default
2689         // network to wifi and check if wifi becomes valid or not.
2690         mCm.setAcceptPartialConnectivity(mWiFiNetworkAgent.getNetwork(), true /* accept */,
2691                 false /* always */);
2692         // If user accepts partial connectivity network,
2693         // NetworkMonitor#setAcceptPartialConnectivity() should be called too.
2694         waitForIdle();
2695         try {
2696             verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
2697         } catch (RemoteException e) {
2698             fail(e.getMessage());
2699         }
2700         // Need a trigger point to let NetworkMonitor tell ConnectivityService that network is
2701         // validated.
2702         mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
2703         callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
2704         NetworkCapabilities nc = callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED,
2705                 mWiFiNetworkAgent);
2706         assertTrue(nc.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY));
2707         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2708 
2709         // Disconnect and reconnect wifi with partial connectivity again.
2710         mWiFiNetworkAgent.disconnect();
2711         callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2712         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2713         mWiFiNetworkAgent.connectWithPartialConnectivity();
2714         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2715         callback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY, mWiFiNetworkAgent);
2716 
2717         // Mobile data should be the default network.
2718         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2719 
2720         // If the user chooses no, disconnect wifi immediately.
2721         mCm.setAcceptPartialConnectivity(mWiFiNetworkAgent.getNetwork(), false/* accept */,
2722                 false /* always */);
2723         callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2724 
2725         // If user accepted partial connectivity before, and device reconnects to that network
2726         // again, but now the network has full connectivity. The network shouldn't contain
2727         // NET_CAPABILITY_PARTIAL_CONNECTIVITY.
2728         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2729         // acceptUnvalidated is also used as setting for accepting partial networks.
2730         mWiFiNetworkAgent.explicitlySelected(true /* acceptUnvalidated */);
2731         mWiFiNetworkAgent.connect(true);
2732         // If user accepted partial connectivity network before,
2733         // NetworkMonitor#setAcceptPartialConnectivity() will be called in
2734         // ConnectivityService#updateNetworkInfo().
2735         waitForIdle();
2736         try {
2737             verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
2738         } catch (RemoteException e) {
2739             fail(e.getMessage());
2740         }
2741         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2742         callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
2743         nc = callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
2744         assertFalse(nc.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY));
2745         // Wifi should be the default network.
2746         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2747         mWiFiNetworkAgent.disconnect();
2748         callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2749 
2750         // If user accepted partial connectivity before, and now the device reconnects to the
2751         // partial connectivity network. The network should be valid and contain
2752         // NET_CAPABILITY_PARTIAL_CONNECTIVITY.
2753         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2754         mWiFiNetworkAgent.explicitlySelected(true /* acceptUnvalidated */);
2755         // Current design cannot send multi-testResult from NetworkMonitor to ConnectivityService.
2756         // So, if user accepts partial connectivity, NetworkMonitor will send PARTIAL_CONNECTIVITY
2757         // to ConnectivityService first then send VALID. Once NetworkMonitor support
2758         // multi-testResult, this test case also need to be changed to meet the new design.
2759         mWiFiNetworkAgent.connectWithPartialConnectivity();
2760         // If user accepted partial connectivity network before,
2761         // NetworkMonitor#setAcceptPartialConnectivity() will be called in
2762         // ConnectivityService#updateNetworkInfo().
2763         waitForIdle();
2764         try {
2765             verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
2766         } catch (RemoteException e) {
2767             fail(e.getMessage());
2768         }
2769         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2770         callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
2771         // TODO: If the user accepted partial connectivity, we shouldn't switch to wifi until
2772         // NetworkMonitor detects partial connectivity
2773         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2774         callback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY, mWiFiNetworkAgent);
2775         mWiFiNetworkAgent.setNetworkValid();
2776         // Need a trigger point to let NetworkMonitor tell ConnectivityService that network is
2777         // validated.
2778         mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
2779         callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
2780         mWiFiNetworkAgent.disconnect();
2781         callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2782     }
2783 
2784     @Test
testCaptivePortalOnPartialConnectivity()2785     public void testCaptivePortalOnPartialConnectivity() throws RemoteException {
2786         final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
2787         final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
2788                 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
2789         mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
2790 
2791         final TestNetworkCallback validatedCallback = new TestNetworkCallback();
2792         final NetworkRequest validatedRequest = new NetworkRequest.Builder()
2793                 .addCapability(NET_CAPABILITY_VALIDATED).build();
2794         mCm.registerNetworkCallback(validatedRequest, validatedCallback);
2795 
2796         // Bring up a network with a captive portal.
2797         // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
2798         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2799         String redirectUrl = "http://android.com/path";
2800         mWiFiNetworkAgent.connectWithCaptivePortal(redirectUrl);
2801         captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2802         assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), redirectUrl);
2803 
2804         // Check that startCaptivePortalApp sends the expected command to NetworkMonitor.
2805         mCm.startCaptivePortalApp(mWiFiNetworkAgent.getNetwork());
2806         verify(mWiFiNetworkAgent.mNetworkMonitor, timeout(TIMEOUT_MS).times(1))
2807                 .launchCaptivePortalApp();
2808 
2809         // Report that the captive portal is dismissed with partial connectivity, and check that
2810         // callbacks are fired.
2811         mWiFiNetworkAgent.setNetworkPartial();
2812         mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
2813         waitForIdle();
2814         captivePortalCallback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY,
2815                 mWiFiNetworkAgent);
2816 
2817         // Report partial connectivity is accepted.
2818         mWiFiNetworkAgent.setNetworkPartialValid();
2819         mCm.setAcceptPartialConnectivity(mWiFiNetworkAgent.getNetwork(), true /* accept */,
2820                 false /* always */);
2821         waitForIdle();
2822         mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
2823         captivePortalCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2824         validatedCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
2825         NetworkCapabilities nc =
2826                 validatedCallback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY,
2827                 mWiFiNetworkAgent);
2828 
2829         mCm.unregisterNetworkCallback(captivePortalCallback);
2830         mCm.unregisterNetworkCallback(validatedCallback);
2831     }
2832 
2833     @Test
testCaptivePortal()2834     public void testCaptivePortal() {
2835         final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
2836         final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
2837                 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
2838         mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
2839 
2840         final TestNetworkCallback validatedCallback = new TestNetworkCallback();
2841         final NetworkRequest validatedRequest = new NetworkRequest.Builder()
2842                 .addCapability(NET_CAPABILITY_VALIDATED).build();
2843         mCm.registerNetworkCallback(validatedRequest, validatedCallback);
2844 
2845         // Bring up a network with a captive portal.
2846         // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
2847         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2848         String firstRedirectUrl = "http://example.com/firstPath";
2849         mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl);
2850         captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2851         assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), firstRedirectUrl);
2852 
2853         // Take down network.
2854         // Expect onLost callback.
2855         mWiFiNetworkAgent.disconnect();
2856         captivePortalCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2857 
2858         // Bring up a network with a captive portal.
2859         // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
2860         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2861         String secondRedirectUrl = "http://example.com/secondPath";
2862         mWiFiNetworkAgent.connectWithCaptivePortal(secondRedirectUrl);
2863         captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2864         assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), secondRedirectUrl);
2865 
2866         // Make captive portal disappear then revalidate.
2867         // Expect onLost callback because network no longer provides NET_CAPABILITY_CAPTIVE_PORTAL.
2868         mWiFiNetworkAgent.setNetworkValid();
2869         mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
2870         captivePortalCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2871 
2872         // Expect NET_CAPABILITY_VALIDATED onAvailable callback.
2873         validatedCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
2874         // Expect no notification to be shown when captive portal disappears by itself
2875         verify(mNotificationManager, never()).notifyAsUser(
2876                 anyString(), eq(NotificationType.LOGGED_IN.eventId), any(), any());
2877 
2878         // Break network connectivity.
2879         // Expect NET_CAPABILITY_VALIDATED onLost callback.
2880         mWiFiNetworkAgent.setNetworkInvalid();
2881         mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), false);
2882         validatedCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2883     }
2884 
2885     @Test
testCaptivePortalApp()2886     public void testCaptivePortalApp() throws RemoteException {
2887         final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
2888         final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
2889                 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
2890         mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
2891 
2892         final TestNetworkCallback validatedCallback = new TestNetworkCallback();
2893         final NetworkRequest validatedRequest = new NetworkRequest.Builder()
2894                 .addCapability(NET_CAPABILITY_VALIDATED).build();
2895         mCm.registerNetworkCallback(validatedRequest, validatedCallback);
2896 
2897         // Bring up wifi.
2898         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2899         mWiFiNetworkAgent.connect(true);
2900         validatedCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
2901         Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
2902 
2903         // Check that calling startCaptivePortalApp does nothing.
2904         final int fastTimeoutMs = 100;
2905         mCm.startCaptivePortalApp(wifiNetwork);
2906         waitForIdle();
2907         verify(mWiFiNetworkAgent.mNetworkMonitor, never()).launchCaptivePortalApp();
2908         mServiceContext.expectNoStartActivityIntent(fastTimeoutMs);
2909 
2910         // Turn into a captive portal.
2911         mWiFiNetworkAgent.setNetworkPortal("http://example.com");
2912         mCm.reportNetworkConnectivity(wifiNetwork, false);
2913         captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2914         validatedCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2915 
2916         // Check that startCaptivePortalApp sends the expected command to NetworkMonitor.
2917         mCm.startCaptivePortalApp(wifiNetwork);
2918         waitForIdle();
2919         verify(mWiFiNetworkAgent.mNetworkMonitor).launchCaptivePortalApp();
2920 
2921         // NetworkMonitor uses startCaptivePortal(Network, Bundle) (startCaptivePortalAppInternal)
2922         final Bundle testBundle = new Bundle();
2923         final String testKey = "testkey";
2924         final String testValue = "testvalue";
2925         testBundle.putString(testKey, testValue);
2926         mCm.startCaptivePortalApp(wifiNetwork, testBundle);
2927         final Intent signInIntent = mServiceContext.expectStartActivityIntent(TIMEOUT_MS);
2928         assertEquals(ACTION_CAPTIVE_PORTAL_SIGN_IN, signInIntent.getAction());
2929         assertEquals(testValue, signInIntent.getStringExtra(testKey));
2930 
2931         // Report that the captive portal is dismissed, and check that callbacks are fired
2932         mWiFiNetworkAgent.setNetworkValid();
2933         mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
2934         validatedCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
2935         captivePortalCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2936         verify(mNotificationManager, times(1)).notifyAsUser(anyString(),
2937                 eq(NotificationType.LOGGED_IN.eventId), any(), eq(UserHandle.ALL));
2938 
2939         mCm.unregisterNetworkCallback(validatedCallback);
2940         mCm.unregisterNetworkCallback(captivePortalCallback);
2941     }
2942 
2943     @Test
testAvoidOrIgnoreCaptivePortals()2944     public void testAvoidOrIgnoreCaptivePortals() {
2945         final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
2946         final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
2947                 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
2948         mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
2949 
2950         final TestNetworkCallback validatedCallback = new TestNetworkCallback();
2951         final NetworkRequest validatedRequest = new NetworkRequest.Builder()
2952                 .addCapability(NET_CAPABILITY_VALIDATED).build();
2953         mCm.registerNetworkCallback(validatedRequest, validatedCallback);
2954 
2955         setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_AVOID);
2956         // Bring up a network with a captive portal.
2957         // Expect it to fail to connect and not result in any callbacks.
2958         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2959         String firstRedirectUrl = "http://example.com/firstPath";
2960 
2961         ConditionVariable disconnectCv = mWiFiNetworkAgent.getDisconnectedCV();
2962         ConditionVariable avoidCv = mWiFiNetworkAgent.getPreventReconnectReceived();
2963         mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl);
2964         waitFor(disconnectCv);
2965         waitFor(avoidCv);
2966 
2967         assertNoCallbacks(captivePortalCallback, validatedCallback);
2968     }
2969 
newWifiRequestBuilder()2970     private NetworkRequest.Builder newWifiRequestBuilder() {
2971         return new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI);
2972     }
2973 
2974     /**
2975      * Verify request matching behavior with network specifiers.
2976      *
2977      * Note: this test is somewhat problematic since it involves removing capabilities from
2978      * agents - i.e. agents rejecting requests which they previously accepted. This is flagged
2979      * as a WTF bug in
2980      * {@link ConnectivityService#mixInCapabilities(NetworkAgentInfo, NetworkCapabilities)} but
2981      * does work.
2982      */
2983     @Test
testNetworkSpecifier()2984     public void testNetworkSpecifier() {
2985         // A NetworkSpecifier subclass that matches all networks but must not be visible to apps.
2986         class ConfidentialMatchAllNetworkSpecifier extends NetworkSpecifier implements
2987                 Parcelable {
2988             @Override
2989             public boolean satisfiedBy(NetworkSpecifier other) {
2990                 return true;
2991             }
2992 
2993             @Override
2994             public int describeContents() {
2995                 return 0;
2996             }
2997 
2998             @Override
2999             public void writeToParcel(Parcel dest, int flags) {}
3000 
3001             @Override
3002             public NetworkSpecifier redact() {
3003                 return null;
3004             }
3005         }
3006 
3007         // A network specifier that matches either another LocalNetworkSpecifier with the same
3008         // string or a ConfidentialMatchAllNetworkSpecifier, and can be passed to apps as is.
3009         class LocalStringNetworkSpecifier extends NetworkSpecifier implements Parcelable {
3010             private String mString;
3011 
3012             LocalStringNetworkSpecifier(String string) {
3013                 mString = string;
3014             }
3015 
3016             @Override
3017             public boolean satisfiedBy(NetworkSpecifier other) {
3018                 if (other instanceof LocalStringNetworkSpecifier) {
3019                     return TextUtils.equals(mString,
3020                             ((LocalStringNetworkSpecifier) other).mString);
3021                 }
3022                 if (other instanceof ConfidentialMatchAllNetworkSpecifier) return true;
3023                 return false;
3024             }
3025 
3026             @Override
3027             public int describeContents() {
3028                 return 0;
3029             }
3030             @Override
3031             public void writeToParcel(Parcel dest, int flags) {}
3032         }
3033 
3034 
3035         NetworkRequest rEmpty1 = newWifiRequestBuilder().build();
3036         NetworkRequest rEmpty2 = newWifiRequestBuilder().setNetworkSpecifier((String) null).build();
3037         NetworkRequest rEmpty3 = newWifiRequestBuilder().setNetworkSpecifier("").build();
3038         NetworkRequest rEmpty4 = newWifiRequestBuilder().setNetworkSpecifier(
3039             (NetworkSpecifier) null).build();
3040         NetworkRequest rFoo = newWifiRequestBuilder().setNetworkSpecifier(
3041                 new LocalStringNetworkSpecifier("foo")).build();
3042         NetworkRequest rBar = newWifiRequestBuilder().setNetworkSpecifier(
3043                 new LocalStringNetworkSpecifier("bar")).build();
3044 
3045         TestNetworkCallback cEmpty1 = new TestNetworkCallback();
3046         TestNetworkCallback cEmpty2 = new TestNetworkCallback();
3047         TestNetworkCallback cEmpty3 = new TestNetworkCallback();
3048         TestNetworkCallback cEmpty4 = new TestNetworkCallback();
3049         TestNetworkCallback cFoo = new TestNetworkCallback();
3050         TestNetworkCallback cBar = new TestNetworkCallback();
3051         TestNetworkCallback[] emptyCallbacks = new TestNetworkCallback[] {
3052                 cEmpty1, cEmpty2, cEmpty3, cEmpty4 };
3053 
3054         mCm.registerNetworkCallback(rEmpty1, cEmpty1);
3055         mCm.registerNetworkCallback(rEmpty2, cEmpty2);
3056         mCm.registerNetworkCallback(rEmpty3, cEmpty3);
3057         mCm.registerNetworkCallback(rEmpty4, cEmpty4);
3058         mCm.registerNetworkCallback(rFoo, cFoo);
3059         mCm.registerNetworkCallback(rBar, cBar);
3060 
3061         LocalStringNetworkSpecifier nsFoo = new LocalStringNetworkSpecifier("foo");
3062         LocalStringNetworkSpecifier nsBar = new LocalStringNetworkSpecifier("bar");
3063 
3064         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3065         mWiFiNetworkAgent.connect(false);
3066         cEmpty1.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
3067         cEmpty2.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
3068         cEmpty3.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
3069         cEmpty4.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
3070         assertNoCallbacks(cFoo, cBar);
3071 
3072         mWiFiNetworkAgent.setNetworkSpecifier(nsFoo);
3073         cFoo.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
3074         for (TestNetworkCallback c: emptyCallbacks) {
3075             c.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier().equals(nsFoo),
3076                     mWiFiNetworkAgent);
3077         }
3078         cFoo.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier().equals(nsFoo),
3079                 mWiFiNetworkAgent);
3080         assertEquals(nsFoo,
3081                 mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier());
3082         cFoo.assertNoCallback();
3083 
3084         mWiFiNetworkAgent.setNetworkSpecifier(nsBar);
3085         cFoo.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
3086         cBar.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
3087         for (TestNetworkCallback c: emptyCallbacks) {
3088             c.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier().equals(nsBar),
3089                     mWiFiNetworkAgent);
3090         }
3091         cBar.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier().equals(nsBar),
3092                 mWiFiNetworkAgent);
3093         assertEquals(nsBar,
3094                 mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier());
3095         cBar.assertNoCallback();
3096 
3097         mWiFiNetworkAgent.setNetworkSpecifier(new ConfidentialMatchAllNetworkSpecifier());
3098         cFoo.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
3099         for (TestNetworkCallback c : emptyCallbacks) {
3100             c.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier() == null,
3101                     mWiFiNetworkAgent);
3102         }
3103         cFoo.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier() == null,
3104                 mWiFiNetworkAgent);
3105         cBar.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier() == null,
3106                 mWiFiNetworkAgent);
3107         assertNull(
3108                 mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier());
3109         cFoo.assertNoCallback();
3110         cBar.assertNoCallback();
3111 
3112         mWiFiNetworkAgent.setNetworkSpecifier(null);
3113         cFoo.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
3114         cBar.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
3115         for (TestNetworkCallback c: emptyCallbacks) {
3116             c.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent);
3117         }
3118 
3119         assertNoCallbacks(cEmpty1, cEmpty2, cEmpty3, cEmpty4, cFoo, cBar);
3120     }
3121 
3122     @Test
testInvalidNetworkSpecifier()3123     public void testInvalidNetworkSpecifier() {
3124         try {
3125             NetworkRequest.Builder builder = new NetworkRequest.Builder();
3126             builder.setNetworkSpecifier(new MatchAllNetworkSpecifier());
3127             fail("NetworkRequest builder with MatchAllNetworkSpecifier");
3128         } catch (IllegalArgumentException expected) {
3129             // expected
3130         }
3131 
3132         try {
3133             NetworkCapabilities networkCapabilities = new NetworkCapabilities();
3134             networkCapabilities.addTransportType(TRANSPORT_WIFI)
3135                     .setNetworkSpecifier(new MatchAllNetworkSpecifier());
3136             mService.requestNetwork(networkCapabilities, null, 0, null,
3137                     ConnectivityManager.TYPE_WIFI);
3138             fail("ConnectivityService requestNetwork with MatchAllNetworkSpecifier");
3139         } catch (IllegalArgumentException expected) {
3140             // expected
3141         }
3142 
3143         class NonParcelableSpecifier extends NetworkSpecifier {
3144             public boolean satisfiedBy(NetworkSpecifier other) { return false; }
3145         };
3146         class ParcelableSpecifier extends NonParcelableSpecifier implements Parcelable {
3147             @Override public int describeContents() { return 0; }
3148             @Override public void writeToParcel(Parcel p, int flags) {}
3149         }
3150         NetworkRequest.Builder builder;
3151 
3152         builder = new NetworkRequest.Builder().addTransportType(TRANSPORT_ETHERNET);
3153         try {
3154             builder.setNetworkSpecifier(new NonParcelableSpecifier());
3155             Parcel parcelW = Parcel.obtain();
3156             builder.build().writeToParcel(parcelW, 0);
3157             fail("Parceling a non-parcelable specifier did not throw an exception");
3158         } catch (Exception e) {
3159             // expected
3160         }
3161 
3162         builder = new NetworkRequest.Builder().addTransportType(TRANSPORT_ETHERNET);
3163         builder.setNetworkSpecifier(new ParcelableSpecifier());
3164         NetworkRequest nr = builder.build();
3165         assertNotNull(nr);
3166 
3167         try {
3168             Parcel parcelW = Parcel.obtain();
3169             nr.writeToParcel(parcelW, 0);
3170             byte[] bytes = parcelW.marshall();
3171             parcelW.recycle();
3172 
3173             Parcel parcelR = Parcel.obtain();
3174             parcelR.unmarshall(bytes, 0, bytes.length);
3175             parcelR.setDataPosition(0);
3176             NetworkRequest rereadNr = NetworkRequest.CREATOR.createFromParcel(parcelR);
3177             fail("Unparceling a non-framework NetworkSpecifier did not throw an exception");
3178         } catch (Exception e) {
3179             // expected
3180         }
3181     }
3182 
3183     @Test
testNetworkSpecifierUidSpoofSecurityException()3184     public void testNetworkSpecifierUidSpoofSecurityException() {
3185         class UidAwareNetworkSpecifier extends NetworkSpecifier implements Parcelable {
3186             @Override
3187             public boolean satisfiedBy(NetworkSpecifier other) {
3188                 return true;
3189             }
3190 
3191             @Override
3192             public void assertValidFromUid(int requestorUid) {
3193                 throw new SecurityException("failure");
3194             }
3195 
3196             @Override
3197             public int describeContents() { return 0; }
3198             @Override
3199             public void writeToParcel(Parcel dest, int flags) {}
3200         }
3201 
3202         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3203         mWiFiNetworkAgent.connect(false);
3204 
3205         UidAwareNetworkSpecifier networkSpecifier = new UidAwareNetworkSpecifier();
3206         NetworkRequest networkRequest = newWifiRequestBuilder().setNetworkSpecifier(
3207                 networkSpecifier).build();
3208         TestNetworkCallback networkCallback = new TestNetworkCallback();
3209         try {
3210             mCm.requestNetwork(networkRequest, networkCallback);
3211             fail("Network request with spoofed UID did not throw a SecurityException");
3212         } catch (SecurityException e) {
3213             // expected
3214         }
3215     }
3216 
3217     @Test
testInvalidSignalStrength()3218     public void testInvalidSignalStrength() {
3219         NetworkRequest r = new NetworkRequest.Builder()
3220                 .addCapability(NET_CAPABILITY_INTERNET)
3221                 .addTransportType(TRANSPORT_WIFI)
3222                 .setSignalStrength(-75)
3223                 .build();
3224         // Registering a NetworkCallback with signal strength but w/o NETWORK_SIGNAL_STRENGTH_WAKEUP
3225         // permission should get SecurityException.
3226         try {
3227             mCm.registerNetworkCallback(r, new NetworkCallback());
3228             fail("Expected SecurityException filing a callback with signal strength");
3229         } catch (SecurityException expected) {
3230             // expected
3231         }
3232 
3233         try {
3234             mCm.registerNetworkCallback(r, PendingIntent.getService(
3235                     mServiceContext, 0, new Intent(), 0));
3236             fail("Expected SecurityException filing a callback with signal strength");
3237         } catch (SecurityException expected) {
3238             // expected
3239         }
3240 
3241         // Requesting a Network with signal strength should get IllegalArgumentException.
3242         try {
3243             mCm.requestNetwork(r, new NetworkCallback());
3244             fail("Expected IllegalArgumentException filing a request with signal strength");
3245         } catch (IllegalArgumentException expected) {
3246             // expected
3247         }
3248 
3249         try {
3250             mCm.requestNetwork(r, PendingIntent.getService(
3251                     mServiceContext, 0, new Intent(), 0));
3252             fail("Expected IllegalArgumentException filing a request with signal strength");
3253         } catch (IllegalArgumentException expected) {
3254             // expected
3255         }
3256     }
3257 
3258     @Test
testRegisterDefaultNetworkCallback()3259     public void testRegisterDefaultNetworkCallback() throws Exception {
3260         final TestNetworkCallback defaultNetworkCallback = new TestNetworkCallback();
3261         mCm.registerDefaultNetworkCallback(defaultNetworkCallback);
3262         defaultNetworkCallback.assertNoCallback();
3263 
3264         // Create a TRANSPORT_CELLULAR request to keep the mobile interface up
3265         // whenever Wi-Fi is up. Without this, the mobile network agent is
3266         // reaped before any other activity can take place.
3267         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
3268         final NetworkRequest cellRequest = new NetworkRequest.Builder()
3269                 .addTransportType(TRANSPORT_CELLULAR).build();
3270         mCm.requestNetwork(cellRequest, cellNetworkCallback);
3271         cellNetworkCallback.assertNoCallback();
3272 
3273         // Bring up cell and expect CALLBACK_AVAILABLE.
3274         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
3275         mCellNetworkAgent.connect(true);
3276         cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
3277         defaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
3278         assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
3279 
3280         // Bring up wifi and expect CALLBACK_AVAILABLE.
3281         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3282         mWiFiNetworkAgent.connect(true);
3283         cellNetworkCallback.assertNoCallback();
3284         defaultNetworkCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
3285         assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
3286 
3287         // Bring down cell. Expect no default network callback, since it wasn't the default.
3288         mCellNetworkAgent.disconnect();
3289         cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
3290         defaultNetworkCallback.assertNoCallback();
3291         assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
3292 
3293         // Bring up cell. Expect no default network callback, since it won't be the default.
3294         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
3295         mCellNetworkAgent.connect(true);
3296         cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
3297         defaultNetworkCallback.assertNoCallback();
3298         assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
3299 
3300         // Bring down wifi. Expect the default network callback to notified of LOST wifi
3301         // followed by AVAILABLE cell.
3302         mWiFiNetworkAgent.disconnect();
3303         cellNetworkCallback.assertNoCallback();
3304         defaultNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
3305         defaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
3306         mCellNetworkAgent.disconnect();
3307         cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
3308         defaultNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
3309         waitForIdle();
3310         assertEquals(null, mCm.getActiveNetwork());
3311 
3312         final int uid = Process.myUid();
3313         final MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
3314         final ArraySet<UidRange> ranges = new ArraySet<>();
3315         ranges.add(new UidRange(uid, uid));
3316         mMockVpn.setNetworkAgent(vpnNetworkAgent);
3317         mMockVpn.setUids(ranges);
3318         vpnNetworkAgent.connect(true);
3319         mMockVpn.connect();
3320         defaultNetworkCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
3321         assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
3322 
3323         vpnNetworkAgent.disconnect();
3324         defaultNetworkCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
3325         waitForIdle();
3326         assertEquals(null, mCm.getActiveNetwork());
3327     }
3328 
3329     @Test
testAdditionalStateCallbacks()3330     public void testAdditionalStateCallbacks() throws Exception {
3331         // File a network request for mobile.
3332         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
3333         final NetworkRequest cellRequest = new NetworkRequest.Builder()
3334                 .addTransportType(TRANSPORT_CELLULAR).build();
3335         mCm.requestNetwork(cellRequest, cellNetworkCallback);
3336 
3337         // Bring up the mobile network.
3338         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
3339         mCellNetworkAgent.connect(true);
3340 
3341         // We should get onAvailable(), onCapabilitiesChanged(), and
3342         // onLinkPropertiesChanged() in rapid succession. Additionally, we
3343         // should get onCapabilitiesChanged() when the mobile network validates.
3344         cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
3345         cellNetworkCallback.assertNoCallback();
3346 
3347         // Update LinkProperties.
3348         final LinkProperties lp = new LinkProperties();
3349         lp.setInterfaceName("foonet_data0");
3350         mCellNetworkAgent.sendLinkProperties(lp);
3351         // We should get onLinkPropertiesChanged().
3352         cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
3353         cellNetworkCallback.assertNoCallback();
3354 
3355         // Suspend the network.
3356         mCellNetworkAgent.suspend();
3357         cellNetworkCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_SUSPENDED,
3358                 mCellNetworkAgent);
3359         cellNetworkCallback.expectCallback(CallbackState.SUSPENDED, mCellNetworkAgent);
3360         cellNetworkCallback.assertNoCallback();
3361 
3362         // Register a garden variety default network request.
3363         TestNetworkCallback dfltNetworkCallback = new TestNetworkCallback();
3364         mCm.registerDefaultNetworkCallback(dfltNetworkCallback);
3365         // We should get onAvailable(), onCapabilitiesChanged(), onLinkPropertiesChanged(),
3366         // as well as onNetworkSuspended() in rapid succession.
3367         dfltNetworkCallback.expectAvailableAndSuspendedCallbacks(mCellNetworkAgent, true);
3368         dfltNetworkCallback.assertNoCallback();
3369         mCm.unregisterNetworkCallback(dfltNetworkCallback);
3370 
3371         mCellNetworkAgent.resume();
3372         cellNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_NOT_SUSPENDED,
3373                 mCellNetworkAgent);
3374         cellNetworkCallback.expectCallback(CallbackState.RESUMED, mCellNetworkAgent);
3375         cellNetworkCallback.assertNoCallback();
3376 
3377         dfltNetworkCallback = new TestNetworkCallback();
3378         mCm.registerDefaultNetworkCallback(dfltNetworkCallback);
3379         // This time onNetworkSuspended should not be called.
3380         dfltNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
3381         dfltNetworkCallback.assertNoCallback();
3382 
3383         mCm.unregisterNetworkCallback(dfltNetworkCallback);
3384         mCm.unregisterNetworkCallback(cellNetworkCallback);
3385     }
3386 
setCaptivePortalMode(int mode)3387     private void setCaptivePortalMode(int mode) {
3388         ContentResolver cr = mServiceContext.getContentResolver();
3389         Settings.Global.putInt(cr, Settings.Global.CAPTIVE_PORTAL_MODE, mode);
3390     }
3391 
setAlwaysOnNetworks(boolean enable)3392     private void setAlwaysOnNetworks(boolean enable) {
3393         ContentResolver cr = mServiceContext.getContentResolver();
3394         Settings.Global.putInt(cr, Settings.Global.MOBILE_DATA_ALWAYS_ON, enable ? 1 : 0);
3395         mService.updateAlwaysOnNetworks();
3396         waitForIdle();
3397     }
3398 
setPrivateDnsSettings(String mode, String specifier)3399     private void setPrivateDnsSettings(String mode, String specifier) {
3400         final ContentResolver cr = mServiceContext.getContentResolver();
3401         Settings.Global.putString(cr, Settings.Global.PRIVATE_DNS_MODE, mode);
3402         Settings.Global.putString(cr, Settings.Global.PRIVATE_DNS_SPECIFIER, specifier);
3403         mService.updatePrivateDnsSettings();
3404         waitForIdle();
3405     }
3406 
isForegroundNetwork(MockNetworkAgent network)3407     private boolean isForegroundNetwork(MockNetworkAgent network) {
3408         NetworkCapabilities nc = mCm.getNetworkCapabilities(network.getNetwork());
3409         assertNotNull(nc);
3410         return nc.hasCapability(NET_CAPABILITY_FOREGROUND);
3411     }
3412 
3413     @Test
testBackgroundNetworks()3414     public void testBackgroundNetworks() throws Exception {
3415         // Create a background request. We can't do this ourselves because ConnectivityService
3416         // doesn't have an API for it. So just turn on mobile data always on.
3417         setAlwaysOnNetworks(true);
3418         final NetworkRequest request = new NetworkRequest.Builder().build();
3419         final NetworkRequest fgRequest = new NetworkRequest.Builder()
3420                 .addCapability(NET_CAPABILITY_FOREGROUND).build();
3421         final TestNetworkCallback callback = new TestNetworkCallback();
3422         final TestNetworkCallback fgCallback = new TestNetworkCallback();
3423         mCm.registerNetworkCallback(request, callback);
3424         mCm.registerNetworkCallback(fgRequest, fgCallback);
3425 
3426         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
3427         mCellNetworkAgent.connect(true);
3428         callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
3429         fgCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
3430         assertTrue(isForegroundNetwork(mCellNetworkAgent));
3431 
3432         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3433         mWiFiNetworkAgent.connect(true);
3434 
3435         // When wifi connects, cell lingers.
3436         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
3437         callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
3438         callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
3439         fgCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
3440         fgCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
3441         fgCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
3442         assertTrue(isForegroundNetwork(mCellNetworkAgent));
3443         assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
3444 
3445         // When lingering is complete, cell is still there but is now in the background.
3446         waitForIdle();
3447         int timeoutMs = TEST_LINGER_DELAY_MS + TEST_LINGER_DELAY_MS / 4;
3448         fgCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent, timeoutMs);
3449         // Expect a network capabilities update sans FOREGROUND.
3450         callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
3451         assertFalse(isForegroundNetwork(mCellNetworkAgent));
3452         assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
3453 
3454         // File a cell request and check that cell comes into the foreground.
3455         final NetworkRequest cellRequest = new NetworkRequest.Builder()
3456                 .addTransportType(TRANSPORT_CELLULAR).build();
3457         final TestNetworkCallback cellCallback = new TestNetworkCallback();
3458         mCm.requestNetwork(cellRequest, cellCallback);
3459         // NOTE: This request causes the network's capabilities to change. This
3460         // is currently delivered before the onAvailable() callbacks.
3461         // TODO: Fix this.
3462         cellCallback.expectCapabilitiesWith(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
3463         cellCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
3464         fgCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
3465         // Expect a network capabilities update with FOREGROUND, because the most recent
3466         // request causes its state to change.
3467         callback.expectCapabilitiesWith(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
3468         assertTrue(isForegroundNetwork(mCellNetworkAgent));
3469         assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
3470 
3471         // Release the request. The network immediately goes into the background, since it was not
3472         // lingering.
3473         mCm.unregisterNetworkCallback(cellCallback);
3474         fgCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
3475         // Expect a network capabilities update sans FOREGROUND.
3476         callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
3477         assertFalse(isForegroundNetwork(mCellNetworkAgent));
3478         assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
3479 
3480         // Disconnect wifi and check that cell is foreground again.
3481         mWiFiNetworkAgent.disconnect();
3482         callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
3483         fgCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
3484         fgCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
3485         assertTrue(isForegroundNetwork(mCellNetworkAgent));
3486 
3487         mCm.unregisterNetworkCallback(callback);
3488         mCm.unregisterNetworkCallback(fgCallback);
3489     }
3490 
3491     @Ignore // This test has instrinsic chances of spurious failures: ignore for continuous testing.
benchmarkRequestRegistrationAndCallbackDispatch()3492     public void benchmarkRequestRegistrationAndCallbackDispatch() throws Exception {
3493         // TODO: turn this unit test into a real benchmarking test.
3494         // Benchmarks connecting and switching performance in the presence of a large number of
3495         // NetworkRequests.
3496         // 1. File NUM_REQUESTS requests.
3497         // 2. Have a network connect. Wait for NUM_REQUESTS onAvailable callbacks to fire.
3498         // 3. Have a new network connect and outscore the previous. Wait for NUM_REQUESTS onLosing
3499         //    and NUM_REQUESTS onAvailable callbacks to fire.
3500         // See how long it took.
3501         final int NUM_REQUESTS = 90;
3502         final int REGISTER_TIME_LIMIT_MS = 200;
3503         final int CONNECT_TIME_LIMIT_MS = 60;
3504         final int SWITCH_TIME_LIMIT_MS = 60;
3505         final int UNREGISTER_TIME_LIMIT_MS = 20;
3506 
3507         final NetworkRequest request = new NetworkRequest.Builder().clearCapabilities().build();
3508         final NetworkCallback[] callbacks = new NetworkCallback[NUM_REQUESTS];
3509         final CountDownLatch availableLatch = new CountDownLatch(NUM_REQUESTS);
3510         final CountDownLatch losingLatch = new CountDownLatch(NUM_REQUESTS);
3511 
3512         for (int i = 0; i < NUM_REQUESTS; i++) {
3513             callbacks[i] = new NetworkCallback() {
3514                 @Override public void onAvailable(Network n) { availableLatch.countDown(); }
3515                 @Override public void onLosing(Network n, int t) { losingLatch.countDown(); }
3516             };
3517         }
3518 
3519         assertTimeLimit("Registering callbacks", REGISTER_TIME_LIMIT_MS, () -> {
3520             for (NetworkCallback cb : callbacks) {
3521                 mCm.registerNetworkCallback(request, cb);
3522             }
3523         });
3524 
3525         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
3526         // Don't request that the network validate, because otherwise connect() will block until
3527         // the network gets NET_CAPABILITY_VALIDATED, after all the callbacks below have fired,
3528         // and we won't actually measure anything.
3529         mCellNetworkAgent.connect(false);
3530 
3531         long onAvailableDispatchingDuration = durationOf(() -> {
3532             awaitLatch(availableLatch, 10 * CONNECT_TIME_LIMIT_MS);
3533         });
3534         Log.d(TAG, String.format("Dispatched %d of %d onAvailable callbacks in %dms",
3535                 NUM_REQUESTS - availableLatch.getCount(), NUM_REQUESTS,
3536                 onAvailableDispatchingDuration));
3537         assertTrue(String.format("Dispatching %d onAvailable callbacks in %dms, expected %dms",
3538                 NUM_REQUESTS, onAvailableDispatchingDuration, CONNECT_TIME_LIMIT_MS),
3539                 onAvailableDispatchingDuration <= CONNECT_TIME_LIMIT_MS);
3540 
3541         // Give wifi a high enough score that we'll linger cell when wifi comes up.
3542         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3543         mWiFiNetworkAgent.adjustScore(40);
3544         mWiFiNetworkAgent.connect(false);
3545 
3546         long onLostDispatchingDuration = durationOf(() -> {
3547             awaitLatch(losingLatch, 10 * SWITCH_TIME_LIMIT_MS);
3548         });
3549         Log.d(TAG, String.format("Dispatched %d of %d onLosing callbacks in %dms",
3550                 NUM_REQUESTS - losingLatch.getCount(), NUM_REQUESTS, onLostDispatchingDuration));
3551         assertTrue(String.format("Dispatching %d onLosing callbacks in %dms, expected %dms",
3552                 NUM_REQUESTS, onLostDispatchingDuration, SWITCH_TIME_LIMIT_MS),
3553                 onLostDispatchingDuration <= SWITCH_TIME_LIMIT_MS);
3554 
3555         assertTimeLimit("Unregistering callbacks", UNREGISTER_TIME_LIMIT_MS, () -> {
3556             for (NetworkCallback cb : callbacks) {
3557                 mCm.unregisterNetworkCallback(cb);
3558             }
3559         });
3560     }
3561 
durationOf(Runnable fn)3562     private long durationOf(Runnable fn) {
3563         long startTime = SystemClock.elapsedRealtime();
3564         fn.run();
3565         return SystemClock.elapsedRealtime() - startTime;
3566     }
3567 
assertTimeLimit(String descr, long timeLimit, Runnable fn)3568     private void assertTimeLimit(String descr, long timeLimit, Runnable fn) {
3569         long timeTaken = durationOf(fn);
3570         String msg = String.format("%s: took %dms, limit was %dms", descr, timeTaken, timeLimit);
3571         Log.d(TAG, msg);
3572         assertTrue(msg, timeTaken <= timeLimit);
3573     }
3574 
awaitLatch(CountDownLatch l, long timeoutMs)3575     private boolean awaitLatch(CountDownLatch l, long timeoutMs) {
3576         try {
3577             return l.await(timeoutMs, TimeUnit.MILLISECONDS);
3578         } catch (InterruptedException e) {}
3579         return false;
3580     }
3581 
3582     @Test
testMobileDataAlwaysOn()3583     public void testMobileDataAlwaysOn() throws Exception {
3584         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
3585         final NetworkRequest cellRequest = new NetworkRequest.Builder()
3586                 .addTransportType(TRANSPORT_CELLULAR).build();
3587         mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
3588 
3589         final HandlerThread handlerThread = new HandlerThread("MobileDataAlwaysOnFactory");
3590         handlerThread.start();
3591         NetworkCapabilities filter = new NetworkCapabilities()
3592                 .addTransportType(TRANSPORT_CELLULAR)
3593                 .addCapability(NET_CAPABILITY_INTERNET);
3594         final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
3595                 mServiceContext, "testFactory", filter);
3596         testFactory.setScoreFilter(40);
3597 
3598         // Register the factory and expect it to start looking for a network.
3599         testFactory.expectAddRequestsWithScores(0);  // Score 0 as the request is not served yet.
3600         testFactory.register();
3601         testFactory.waitForNetworkRequests(1);
3602         assertTrue(testFactory.getMyStartRequested());
3603 
3604         // Bring up wifi. The factory stops looking for a network.
3605         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3606         // Score 60 - 40 penalty for not validated yet, then 60 when it validates
3607         testFactory.expectAddRequestsWithScores(20, 60);
3608         mWiFiNetworkAgent.connect(true);
3609         testFactory.waitForRequests();
3610         assertFalse(testFactory.getMyStartRequested());
3611 
3612         ContentResolver cr = mServiceContext.getContentResolver();
3613 
3614         // Turn on mobile data always on. The factory starts looking again.
3615         testFactory.expectAddRequestsWithScores(0);  // Always on requests comes up with score 0
3616         setAlwaysOnNetworks(true);
3617         testFactory.waitForNetworkRequests(2);
3618         assertTrue(testFactory.getMyStartRequested());
3619 
3620         // Bring up cell data and check that the factory stops looking.
3621         assertLength(1, mCm.getAllNetworks());
3622         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
3623         testFactory.expectAddRequestsWithScores(10, 50);  // Unvalidated, then validated
3624         mCellNetworkAgent.connect(true);
3625         cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
3626         testFactory.waitForNetworkRequests(2);
3627         assertFalse(testFactory.getMyStartRequested());  // Because the cell network outscores us.
3628 
3629         // Check that cell data stays up.
3630         waitForIdle();
3631         verifyActiveNetwork(TRANSPORT_WIFI);
3632         assertLength(2, mCm.getAllNetworks());
3633 
3634         // Turn off mobile data always on and expect the request to disappear...
3635         testFactory.expectRemoveRequests(1);
3636         setAlwaysOnNetworks(false);
3637         testFactory.waitForNetworkRequests(1);
3638 
3639         // ...  and cell data to be torn down.
3640         cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
3641         assertLength(1, mCm.getAllNetworks());
3642 
3643         testFactory.unregister();
3644         mCm.unregisterNetworkCallback(cellNetworkCallback);
3645         handlerThread.quit();
3646     }
3647 
3648     @Test
testAvoidBadWifiSetting()3649     public void testAvoidBadWifiSetting() throws Exception {
3650         final ContentResolver cr = mServiceContext.getContentResolver();
3651         final WrappedMultinetworkPolicyTracker tracker = mService.getMultinetworkPolicyTracker();
3652         final String settingName = Settings.Global.NETWORK_AVOID_BAD_WIFI;
3653 
3654         tracker.configRestrictsAvoidBadWifi = false;
3655         String[] values = new String[] {null, "0", "1"};
3656         for (int i = 0; i < values.length; i++) {
3657             Settings.Global.putInt(cr, settingName, 1);
3658             tracker.reevaluate();
3659             waitForIdle();
3660             String msg = String.format("config=false, setting=%s", values[i]);
3661             assertTrue(mService.avoidBadWifi());
3662             assertFalse(msg, tracker.shouldNotifyWifiUnvalidated());
3663         }
3664 
3665         tracker.configRestrictsAvoidBadWifi = true;
3666 
3667         Settings.Global.putInt(cr, settingName, 0);
3668         tracker.reevaluate();
3669         waitForIdle();
3670         assertFalse(mService.avoidBadWifi());
3671         assertFalse(tracker.shouldNotifyWifiUnvalidated());
3672 
3673         Settings.Global.putInt(cr, settingName, 1);
3674         tracker.reevaluate();
3675         waitForIdle();
3676         assertTrue(mService.avoidBadWifi());
3677         assertFalse(tracker.shouldNotifyWifiUnvalidated());
3678 
3679         Settings.Global.putString(cr, settingName, null);
3680         tracker.reevaluate();
3681         waitForIdle();
3682         assertFalse(mService.avoidBadWifi());
3683         assertTrue(tracker.shouldNotifyWifiUnvalidated());
3684     }
3685 
3686     @Test
testAvoidBadWifi()3687     public void testAvoidBadWifi() throws Exception {
3688         final ContentResolver cr = mServiceContext.getContentResolver();
3689         final WrappedMultinetworkPolicyTracker tracker = mService.getMultinetworkPolicyTracker();
3690 
3691         // Pretend we're on a carrier that restricts switching away from bad wifi.
3692         tracker.configRestrictsAvoidBadWifi = true;
3693 
3694         // File a request for cell to ensure it doesn't go down.
3695         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
3696         final NetworkRequest cellRequest = new NetworkRequest.Builder()
3697                 .addTransportType(TRANSPORT_CELLULAR).build();
3698         mCm.requestNetwork(cellRequest, cellNetworkCallback);
3699 
3700         TestNetworkCallback defaultCallback = new TestNetworkCallback();
3701         mCm.registerDefaultNetworkCallback(defaultCallback);
3702 
3703         NetworkRequest validatedWifiRequest = new NetworkRequest.Builder()
3704                 .addTransportType(TRANSPORT_WIFI)
3705                 .addCapability(NET_CAPABILITY_VALIDATED)
3706                 .build();
3707         TestNetworkCallback validatedWifiCallback = new TestNetworkCallback();
3708         mCm.registerNetworkCallback(validatedWifiRequest, validatedWifiCallback);
3709 
3710         Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 0);
3711         tracker.reevaluate();
3712 
3713         // Bring up validated cell.
3714         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
3715         mCellNetworkAgent.connect(true);
3716         cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
3717         defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
3718         Network cellNetwork = mCellNetworkAgent.getNetwork();
3719 
3720         // Bring up validated wifi.
3721         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3722         mWiFiNetworkAgent.connect(true);
3723         defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
3724         validatedWifiCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
3725         Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
3726 
3727         // Fail validation on wifi.
3728         mWiFiNetworkAgent.setNetworkInvalid();
3729         mCm.reportNetworkConnectivity(wifiNetwork, false);
3730         defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
3731         validatedWifiCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
3732 
3733         // Because avoid bad wifi is off, we don't switch to cellular.
3734         defaultCallback.assertNoCallback();
3735         assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
3736                 NET_CAPABILITY_VALIDATED));
3737         assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
3738                 NET_CAPABILITY_VALIDATED));
3739         assertEquals(mCm.getActiveNetwork(), wifiNetwork);
3740 
3741         // Simulate switching to a carrier that does not restrict avoiding bad wifi, and expect
3742         // that we switch back to cell.
3743         tracker.configRestrictsAvoidBadWifi = false;
3744         tracker.reevaluate();
3745         defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
3746         assertEquals(mCm.getActiveNetwork(), cellNetwork);
3747 
3748         // Switch back to a restrictive carrier.
3749         tracker.configRestrictsAvoidBadWifi = true;
3750         tracker.reevaluate();
3751         defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
3752         assertEquals(mCm.getActiveNetwork(), wifiNetwork);
3753 
3754         // Simulate the user selecting "switch" on the dialog, and check that we switch to cell.
3755         mCm.setAvoidUnvalidated(wifiNetwork);
3756         defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
3757         assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
3758                 NET_CAPABILITY_VALIDATED));
3759         assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
3760                 NET_CAPABILITY_VALIDATED));
3761         assertEquals(mCm.getActiveNetwork(), cellNetwork);
3762 
3763         // Disconnect and reconnect wifi to clear the one-time switch above.
3764         mWiFiNetworkAgent.disconnect();
3765         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3766         mWiFiNetworkAgent.connect(true);
3767         defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
3768         validatedWifiCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
3769         wifiNetwork = mWiFiNetworkAgent.getNetwork();
3770 
3771         // Fail validation on wifi and expect the dialog to appear.
3772         mWiFiNetworkAgent.setNetworkInvalid();
3773         mCm.reportNetworkConnectivity(wifiNetwork, false);
3774         defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
3775         validatedWifiCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
3776 
3777         // Simulate the user selecting "switch" and checking the don't ask again checkbox.
3778         Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 1);
3779         tracker.reevaluate();
3780 
3781         // We now switch to cell.
3782         defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
3783         assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
3784                 NET_CAPABILITY_VALIDATED));
3785         assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
3786                 NET_CAPABILITY_VALIDATED));
3787         assertEquals(mCm.getActiveNetwork(), cellNetwork);
3788 
3789         // Simulate the user turning the cellular fallback setting off and then on.
3790         // We switch to wifi and then to cell.
3791         Settings.Global.putString(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, null);
3792         tracker.reevaluate();
3793         defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
3794         assertEquals(mCm.getActiveNetwork(), wifiNetwork);
3795         Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 1);
3796         tracker.reevaluate();
3797         defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
3798         assertEquals(mCm.getActiveNetwork(), cellNetwork);
3799 
3800         // If cell goes down, we switch to wifi.
3801         mCellNetworkAgent.disconnect();
3802         defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
3803         defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
3804         validatedWifiCallback.assertNoCallback();
3805 
3806         mCm.unregisterNetworkCallback(cellNetworkCallback);
3807         mCm.unregisterNetworkCallback(validatedWifiCallback);
3808         mCm.unregisterNetworkCallback(defaultCallback);
3809     }
3810 
3811     @Test
testMeteredMultipathPreferenceSetting()3812     public void testMeteredMultipathPreferenceSetting() throws Exception {
3813         final ContentResolver cr = mServiceContext.getContentResolver();
3814         final WrappedMultinetworkPolicyTracker tracker = mService.getMultinetworkPolicyTracker();
3815         final String settingName = Settings.Global.NETWORK_METERED_MULTIPATH_PREFERENCE;
3816 
3817         for (int config : Arrays.asList(0, 3, 2)) {
3818             for (String setting: Arrays.asList(null, "0", "2", "1")) {
3819                 tracker.configMeteredMultipathPreference = config;
3820                 Settings.Global.putString(cr, settingName, setting);
3821                 tracker.reevaluate();
3822                 waitForIdle();
3823 
3824                 final int expected = (setting != null) ? Integer.parseInt(setting) : config;
3825                 String msg = String.format("config=%d, setting=%s", config, setting);
3826                 assertEquals(msg, expected, mCm.getMultipathPreference(null));
3827             }
3828         }
3829     }
3830 
3831     /**
3832      * Validate that a satisfied network request does not trigger onUnavailable() once the
3833      * time-out period expires.
3834      */
3835     @Test
testSatisfiedNetworkRequestDoesNotTriggerOnUnavailable()3836     public void testSatisfiedNetworkRequestDoesNotTriggerOnUnavailable() {
3837         NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3838                 NetworkCapabilities.TRANSPORT_WIFI).build();
3839         final TestNetworkCallback networkCallback = new TestNetworkCallback();
3840         mCm.requestNetwork(nr, networkCallback, TEST_REQUEST_TIMEOUT_MS);
3841 
3842         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3843         mWiFiNetworkAgent.connect(false);
3844         networkCallback.expectAvailableCallbacks(mWiFiNetworkAgent, false, false, false,
3845                 TEST_CALLBACK_TIMEOUT_MS);
3846 
3847         // pass timeout and validate that UNAVAILABLE is not called
3848         networkCallback.assertNoCallback();
3849     }
3850 
3851     /**
3852      * Validate that a satisfied network request followed by a disconnected (lost) network does
3853      * not trigger onUnavailable() once the time-out period expires.
3854      */
3855     @Test
testSatisfiedThenLostNetworkRequestDoesNotTriggerOnUnavailable()3856     public void testSatisfiedThenLostNetworkRequestDoesNotTriggerOnUnavailable() {
3857         NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3858                 NetworkCapabilities.TRANSPORT_WIFI).build();
3859         final TestNetworkCallback networkCallback = new TestNetworkCallback();
3860         mCm.requestNetwork(nr, networkCallback, TEST_REQUEST_TIMEOUT_MS);
3861 
3862         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3863         mWiFiNetworkAgent.connect(false);
3864         networkCallback.expectAvailableCallbacks(mWiFiNetworkAgent, false, false, false,
3865                 TEST_CALLBACK_TIMEOUT_MS);
3866         mWiFiNetworkAgent.disconnect();
3867         networkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
3868 
3869         // Validate that UNAVAILABLE is not called
3870         networkCallback.assertNoCallback();
3871     }
3872 
3873     /**
3874      * Validate that when a time-out is specified for a network request the onUnavailable()
3875      * callback is called when time-out expires. Then validate that if network request is
3876      * (somehow) satisfied - the callback isn't called later.
3877      */
3878     @Test
testTimedoutNetworkRequest()3879     public void testTimedoutNetworkRequest() {
3880         NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3881                 NetworkCapabilities.TRANSPORT_WIFI).build();
3882         final TestNetworkCallback networkCallback = new TestNetworkCallback();
3883         final int timeoutMs = 10;
3884         mCm.requestNetwork(nr, networkCallback, timeoutMs);
3885 
3886         // pass timeout and validate that UNAVAILABLE is called
3887         networkCallback.expectCallback(CallbackState.UNAVAILABLE, null);
3888 
3889         // create a network satisfying request - validate that request not triggered
3890         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3891         mWiFiNetworkAgent.connect(false);
3892         networkCallback.assertNoCallback();
3893     }
3894 
3895     /**
3896      * Validate that when a network request is unregistered (cancelled), no posterior event can
3897      * trigger the callback.
3898      */
3899     @Test
testNoCallbackAfterUnregisteredNetworkRequest()3900     public void testNoCallbackAfterUnregisteredNetworkRequest() {
3901         NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3902                 NetworkCapabilities.TRANSPORT_WIFI).build();
3903         final TestNetworkCallback networkCallback = new TestNetworkCallback();
3904         final int timeoutMs = 10;
3905 
3906         mCm.requestNetwork(nr, networkCallback, timeoutMs);
3907         mCm.unregisterNetworkCallback(networkCallback);
3908         // Regardless of the timeout, unregistering the callback in ConnectivityManager ensures
3909         // that this callback will not be called.
3910         networkCallback.assertNoCallback();
3911 
3912         // create a network satisfying request - validate that request not triggered
3913         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3914         mWiFiNetworkAgent.connect(false);
3915         networkCallback.assertNoCallback();
3916     }
3917 
3918     @Test
testUnfulfillableNetworkRequest()3919     public void testUnfulfillableNetworkRequest() throws Exception {
3920         runUnfulfillableNetworkRequest(false);
3921     }
3922 
3923     @Test
testUnfulfillableNetworkRequestAfterUnregister()3924     public void testUnfulfillableNetworkRequestAfterUnregister() throws Exception {
3925         runUnfulfillableNetworkRequest(true);
3926     }
3927 
3928     /**
3929      * Validate the callback flow for a factory releasing a request as unfulfillable.
3930      */
runUnfulfillableNetworkRequest(boolean preUnregister)3931     private void runUnfulfillableNetworkRequest(boolean preUnregister) throws Exception {
3932         NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3933                 NetworkCapabilities.TRANSPORT_WIFI).build();
3934         final TestNetworkCallback networkCallback = new TestNetworkCallback();
3935 
3936         final HandlerThread handlerThread = new HandlerThread("testUnfulfillableNetworkRequest");
3937         handlerThread.start();
3938         NetworkCapabilities filter = new NetworkCapabilities()
3939                 .addTransportType(TRANSPORT_WIFI)
3940                 .addCapability(NET_CAPABILITY_INTERNET);
3941         final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
3942                 mServiceContext, "testFactory", filter);
3943         testFactory.setScoreFilter(40);
3944 
3945         // Register the factory and expect it to receive the default request.
3946         testFactory.expectAddRequestsWithScores(0);
3947         testFactory.register();
3948         SparseArray<NetworkRequest> requests = testFactory.waitForNetworkRequests(1);
3949 
3950         assertEquals(1, requests.size()); // have 1 request at this point
3951         int origRequestId = requests.valueAt(0).requestId;
3952 
3953         // Now file the test request and expect it.
3954         testFactory.expectAddRequestsWithScores(0);
3955         mCm.requestNetwork(nr, networkCallback);
3956         requests = testFactory.waitForNetworkRequests(2); // have 2 requests at this point
3957 
3958         int newRequestId = 0;
3959         for (int i = 0; i < requests.size(); ++i) {
3960             if (requests.valueAt(i).requestId != origRequestId) {
3961                 newRequestId = requests.valueAt(i).requestId;
3962                 break;
3963             }
3964         }
3965 
3966         testFactory.expectRemoveRequests(1);
3967         if (preUnregister) {
3968             mCm.unregisterNetworkCallback(networkCallback);
3969 
3970             // Simulate the factory releasing the request as unfulfillable: no-op since
3971             // the callback has already been unregistered (but a test that no exceptions are
3972             // thrown).
3973             testFactory.triggerUnfulfillable(requests.get(newRequestId));
3974         } else {
3975             // Simulate the factory releasing the request as unfulfillable and expect onUnavailable!
3976             testFactory.triggerUnfulfillable(requests.get(newRequestId));
3977 
3978             networkCallback.expectCallback(CallbackState.UNAVAILABLE, null);
3979             testFactory.waitForRequests();
3980 
3981             // unregister network callback - a no-op (since already freed by the
3982             // on-unavailable), but should not fail or throw exceptions.
3983             mCm.unregisterNetworkCallback(networkCallback);
3984         }
3985 
3986         testFactory.unregister();
3987         handlerThread.quit();
3988     }
3989 
3990     private static class TestKeepaliveCallback extends PacketKeepaliveCallback {
3991 
3992         public static enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR };
3993 
3994         private class CallbackValue {
3995             public CallbackType callbackType;
3996             public int error;
3997 
CallbackValue(CallbackType type)3998             public CallbackValue(CallbackType type) {
3999                 this.callbackType = type;
4000                 this.error = PacketKeepalive.SUCCESS;
4001                 assertTrue("onError callback must have error", type != CallbackType.ON_ERROR);
4002             }
4003 
CallbackValue(CallbackType type, int error)4004             public CallbackValue(CallbackType type, int error) {
4005                 this.callbackType = type;
4006                 this.error = error;
4007                 assertEquals("error can only be set for onError", type, CallbackType.ON_ERROR);
4008             }
4009 
4010             @Override
equals(Object o)4011             public boolean equals(Object o) {
4012                 return o instanceof CallbackValue &&
4013                         this.callbackType == ((CallbackValue) o).callbackType &&
4014                         this.error == ((CallbackValue) o).error;
4015             }
4016 
4017             @Override
toString()4018             public String toString() {
4019                 return String.format("%s(%s, %d)", getClass().getSimpleName(), callbackType, error);
4020             }
4021         }
4022 
4023         private final LinkedBlockingQueue<CallbackValue> mCallbacks = new LinkedBlockingQueue<>();
4024 
4025         @Override
onStarted()4026         public void onStarted() {
4027             mCallbacks.add(new CallbackValue(CallbackType.ON_STARTED));
4028         }
4029 
4030         @Override
onStopped()4031         public void onStopped() {
4032             mCallbacks.add(new CallbackValue(CallbackType.ON_STOPPED));
4033         }
4034 
4035         @Override
onError(int error)4036         public void onError(int error) {
4037             mCallbacks.add(new CallbackValue(CallbackType.ON_ERROR, error));
4038         }
4039 
expectCallback(CallbackValue callbackValue)4040         private void expectCallback(CallbackValue callbackValue) {
4041             try {
4042                 assertEquals(
4043                         callbackValue,
4044                         mCallbacks.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
4045             } catch (InterruptedException e) {
4046                 fail(callbackValue.callbackType + " callback not seen after " + TIMEOUT_MS + " ms");
4047             }
4048         }
4049 
expectStarted()4050         public void expectStarted() {
4051             expectCallback(new CallbackValue(CallbackType.ON_STARTED));
4052         }
4053 
expectStopped()4054         public void expectStopped() {
4055             expectCallback(new CallbackValue(CallbackType.ON_STOPPED));
4056         }
4057 
expectError(int error)4058         public void expectError(int error) {
4059             expectCallback(new CallbackValue(CallbackType.ON_ERROR, error));
4060         }
4061     }
4062 
4063     private static class TestSocketKeepaliveCallback extends SocketKeepalive.Callback {
4064 
4065         public enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR };
4066 
4067         private class CallbackValue {
4068             public CallbackType callbackType;
4069             public int error;
4070 
CallbackValue(CallbackType type)4071             CallbackValue(CallbackType type) {
4072                 this.callbackType = type;
4073                 this.error = SocketKeepalive.SUCCESS;
4074                 assertTrue("onError callback must have error", type != CallbackType.ON_ERROR);
4075             }
4076 
CallbackValue(CallbackType type, int error)4077             CallbackValue(CallbackType type, int error) {
4078                 this.callbackType = type;
4079                 this.error = error;
4080                 assertEquals("error can only be set for onError", type, CallbackType.ON_ERROR);
4081             }
4082 
4083             @Override
equals(Object o)4084             public boolean equals(Object o) {
4085                 return o instanceof CallbackValue
4086                         && this.callbackType == ((CallbackValue) o).callbackType
4087                         && this.error == ((CallbackValue) o).error;
4088             }
4089 
4090             @Override
toString()4091             public String toString() {
4092                 return String.format("%s(%s, %d)", getClass().getSimpleName(), callbackType,
4093                         error);
4094             }
4095         }
4096 
4097         private LinkedBlockingQueue<CallbackValue> mCallbacks = new LinkedBlockingQueue<>();
4098         private final Executor mExecutor;
4099 
TestSocketKeepaliveCallback(@onNull Executor executor)4100         TestSocketKeepaliveCallback(@NonNull Executor executor) {
4101             mExecutor = executor;
4102         }
4103 
4104         @Override
onStarted()4105         public void onStarted() {
4106             mCallbacks.add(new CallbackValue(CallbackType.ON_STARTED));
4107         }
4108 
4109         @Override
onStopped()4110         public void onStopped() {
4111             mCallbacks.add(new CallbackValue(CallbackType.ON_STOPPED));
4112         }
4113 
4114         @Override
onError(int error)4115         public void onError(int error) {
4116             mCallbacks.add(new CallbackValue(CallbackType.ON_ERROR, error));
4117         }
4118 
expectCallback(CallbackValue callbackValue)4119         private void expectCallback(CallbackValue callbackValue) {
4120             try {
4121                 assertEquals(
4122                         callbackValue,
4123                         mCallbacks.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
4124             } catch (InterruptedException e) {
4125                 fail(callbackValue.callbackType + " callback not seen after " + TIMEOUT_MS + " ms");
4126             }
4127         }
4128 
expectStarted()4129         public void expectStarted() {
4130             expectCallback(new CallbackValue(CallbackType.ON_STARTED));
4131         }
4132 
expectStopped()4133         public void expectStopped() {
4134             expectCallback(new CallbackValue(CallbackType.ON_STOPPED));
4135         }
4136 
expectError(int error)4137         public void expectError(int error) {
4138             expectCallback(new CallbackValue(CallbackType.ON_ERROR, error));
4139         }
4140 
assertNoCallback()4141         public void assertNoCallback() {
4142             waitForIdleSerialExecutor(mExecutor, TIMEOUT_MS);
4143             CallbackValue cv = mCallbacks.peek();
4144             assertNull("Unexpected callback: " + cv, cv);
4145         }
4146     }
4147 
connectKeepaliveNetwork(LinkProperties lp)4148     private Network connectKeepaliveNetwork(LinkProperties lp) {
4149         // Ensure the network is disconnected before we do anything.
4150         if (mWiFiNetworkAgent != null) {
4151             assertNull(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()));
4152         }
4153 
4154         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
4155         ConditionVariable cv = waitForConnectivityBroadcasts(1);
4156         mWiFiNetworkAgent.connect(true);
4157         waitFor(cv);
4158         verifyActiveNetwork(TRANSPORT_WIFI);
4159         mWiFiNetworkAgent.sendLinkProperties(lp);
4160         waitForIdle();
4161         return mWiFiNetworkAgent.getNetwork();
4162     }
4163 
4164     @Test
testPacketKeepalives()4165     public void testPacketKeepalives() throws Exception {
4166         InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
4167         InetAddress notMyIPv4 = InetAddress.getByName("192.0.2.35");
4168         InetAddress myIPv6 = InetAddress.getByName("2001:db8::1");
4169         InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8");
4170         InetAddress dstIPv6 = InetAddress.getByName("2001:4860:4860::8888");
4171 
4172         final int validKaInterval = 15;
4173         final int invalidKaInterval = 9;
4174 
4175         LinkProperties lp = new LinkProperties();
4176         lp.setInterfaceName("wlan12");
4177         lp.addLinkAddress(new LinkAddress(myIPv6, 64));
4178         lp.addLinkAddress(new LinkAddress(myIPv4, 25));
4179         lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
4180         lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
4181 
4182         Network notMyNet = new Network(61234);
4183         Network myNet = connectKeepaliveNetwork(lp);
4184 
4185         TestKeepaliveCallback callback = new TestKeepaliveCallback();
4186         PacketKeepalive ka;
4187 
4188         // Attempt to start keepalives with invalid parameters and check for errors.
4189         ka = mCm.startNattKeepalive(notMyNet, validKaInterval, callback, myIPv4, 1234, dstIPv4);
4190         callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK);
4191 
4192         ka = mCm.startNattKeepalive(myNet, invalidKaInterval, callback, myIPv4, 1234, dstIPv4);
4193         callback.expectError(PacketKeepalive.ERROR_INVALID_INTERVAL);
4194 
4195         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 1234, dstIPv6);
4196         callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
4197 
4198         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv6, 1234, dstIPv4);
4199         callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
4200 
4201         // NAT-T is only supported for IPv4.
4202         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv6, 1234, dstIPv6);
4203         callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
4204 
4205         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 123456, dstIPv4);
4206         callback.expectError(PacketKeepalive.ERROR_INVALID_PORT);
4207 
4208         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 123456, dstIPv4);
4209         callback.expectError(PacketKeepalive.ERROR_INVALID_PORT);
4210 
4211         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
4212         callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
4213 
4214         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
4215         callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
4216 
4217         // Check that a started keepalive can be stopped.
4218         mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS);
4219         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
4220         callback.expectStarted();
4221         mWiFiNetworkAgent.setStopKeepaliveError(PacketKeepalive.SUCCESS);
4222         ka.stop();
4223         callback.expectStopped();
4224 
4225         // Check that deleting the IP address stops the keepalive.
4226         LinkProperties bogusLp = new LinkProperties(lp);
4227         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
4228         callback.expectStarted();
4229         bogusLp.removeLinkAddress(new LinkAddress(myIPv4, 25));
4230         bogusLp.addLinkAddress(new LinkAddress(notMyIPv4, 25));
4231         mWiFiNetworkAgent.sendLinkProperties(bogusLp);
4232         callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
4233         mWiFiNetworkAgent.sendLinkProperties(lp);
4234 
4235         // Check that a started keepalive is stopped correctly when the network disconnects.
4236         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
4237         callback.expectStarted();
4238         mWiFiNetworkAgent.disconnect();
4239         waitFor(mWiFiNetworkAgent.getDisconnectedCV());
4240         callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK);
4241 
4242         // ... and that stopping it after that has no adverse effects.
4243         waitForIdle();
4244         final Network myNetAlias = myNet;
4245         assertNull(mCm.getNetworkCapabilities(myNetAlias));
4246         ka.stop();
4247 
4248         // Reconnect.
4249         myNet = connectKeepaliveNetwork(lp);
4250         mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS);
4251 
4252         // Check that keepalive slots start from 1 and increment. The first one gets slot 1.
4253         mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
4254         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
4255         callback.expectStarted();
4256 
4257         // The second one gets slot 2.
4258         mWiFiNetworkAgent.setExpectedKeepaliveSlot(2);
4259         TestKeepaliveCallback callback2 = new TestKeepaliveCallback();
4260         PacketKeepalive ka2 = mCm.startNattKeepalive(
4261                 myNet, validKaInterval, callback2, myIPv4, 6789, dstIPv4);
4262         callback2.expectStarted();
4263 
4264         // Now stop the first one and create a third. This also gets slot 1.
4265         ka.stop();
4266         callback.expectStopped();
4267 
4268         mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
4269         TestKeepaliveCallback callback3 = new TestKeepaliveCallback();
4270         PacketKeepalive ka3 = mCm.startNattKeepalive(
4271                 myNet, validKaInterval, callback3, myIPv4, 9876, dstIPv4);
4272         callback3.expectStarted();
4273 
4274         ka2.stop();
4275         callback2.expectStopped();
4276 
4277         ka3.stop();
4278         callback3.expectStopped();
4279     }
4280 
4281     @FunctionalInterface
4282     private interface ThrowingConsumer<T> {
accept(T t)4283         void accept(T t) throws Exception;
4284     }
4285 
4286     // Helper method to prepare the executor and run test
runTestWithSerialExecutors(ThrowingConsumer<Executor> functor)4287     private void runTestWithSerialExecutors(ThrowingConsumer<Executor> functor) throws Exception {
4288         final ExecutorService executorSingleThread = Executors.newSingleThreadExecutor();
4289         final Executor executorInline = (Runnable r) -> r.run();
4290         functor.accept(executorSingleThread);
4291         executorSingleThread.shutdown();
4292         functor.accept(executorInline);
4293     }
4294 
4295     @Test
testNattSocketKeepalives()4296     public void testNattSocketKeepalives() throws Exception {
4297         runTestWithSerialExecutors(executor -> doTestNattSocketKeepalivesWithExecutor(executor));
4298         runTestWithSerialExecutors(executor -> doTestNattSocketKeepalivesFdWithExecutor(executor));
4299     }
4300 
doTestNattSocketKeepalivesWithExecutor(Executor executor)4301     private void doTestNattSocketKeepalivesWithExecutor(Executor executor) throws Exception {
4302         // TODO: 1. Move this outside of ConnectivityServiceTest.
4303         //       2. Make test to verify that Nat-T keepalive socket is created by IpSecService.
4304         //       3. Mock ipsec service.
4305         final InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
4306         final InetAddress notMyIPv4 = InetAddress.getByName("192.0.2.35");
4307         final InetAddress myIPv6 = InetAddress.getByName("2001:db8::1");
4308         final InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8");
4309         final InetAddress dstIPv6 = InetAddress.getByName("2001:4860:4860::8888");
4310 
4311         final int validKaInterval = 15;
4312         final int invalidKaInterval = 9;
4313 
4314         final IpSecManager mIpSec = (IpSecManager) mContext.getSystemService(Context.IPSEC_SERVICE);
4315         final UdpEncapsulationSocket testSocket = mIpSec.openUdpEncapsulationSocket();
4316         final int srcPort = testSocket.getPort();
4317 
4318         LinkProperties lp = new LinkProperties();
4319         lp.setInterfaceName("wlan12");
4320         lp.addLinkAddress(new LinkAddress(myIPv6, 64));
4321         lp.addLinkAddress(new LinkAddress(myIPv4, 25));
4322         lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
4323         lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
4324 
4325         Network notMyNet = new Network(61234);
4326         Network myNet = connectKeepaliveNetwork(lp);
4327 
4328         TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback(executor);
4329 
4330         // Attempt to start keepalives with invalid parameters and check for errors.
4331         // Invalid network.
4332         try (SocketKeepalive ka = mCm.createSocketKeepalive(
4333                 notMyNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
4334             ka.start(validKaInterval);
4335             callback.expectError(SocketKeepalive.ERROR_INVALID_NETWORK);
4336         }
4337 
4338         // Invalid interval.
4339         try (SocketKeepalive ka = mCm.createSocketKeepalive(
4340                 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
4341             ka.start(invalidKaInterval);
4342             callback.expectError(SocketKeepalive.ERROR_INVALID_INTERVAL);
4343         }
4344 
4345         // Invalid destination.
4346         try (SocketKeepalive ka = mCm.createSocketKeepalive(
4347                 myNet, testSocket, myIPv4, dstIPv6, executor, callback)) {
4348             ka.start(validKaInterval);
4349             callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
4350         }
4351 
4352         // Invalid source;
4353         try (SocketKeepalive ka = mCm.createSocketKeepalive(
4354                 myNet, testSocket, myIPv6, dstIPv4, executor, callback)) {
4355             ka.start(validKaInterval);
4356             callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
4357         }
4358 
4359         // NAT-T is only supported for IPv4.
4360         try (SocketKeepalive ka = mCm.createSocketKeepalive(
4361                 myNet, testSocket, myIPv6, dstIPv6, executor, callback)) {
4362             ka.start(validKaInterval);
4363             callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
4364         }
4365 
4366         // Sanity check before testing started keepalive.
4367         try (SocketKeepalive ka = mCm.createSocketKeepalive(
4368                 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
4369             ka.start(validKaInterval);
4370             callback.expectError(SocketKeepalive.ERROR_UNSUPPORTED);
4371         }
4372 
4373         // Check that a started keepalive can be stopped.
4374         mWiFiNetworkAgent.setStartKeepaliveError(SocketKeepalive.SUCCESS);
4375         try (SocketKeepalive ka = mCm.createSocketKeepalive(
4376                 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
4377             ka.start(validKaInterval);
4378             callback.expectStarted();
4379             mWiFiNetworkAgent.setStopKeepaliveError(SocketKeepalive.SUCCESS);
4380             ka.stop();
4381             callback.expectStopped();
4382 
4383             // Check that keepalive could be restarted.
4384             ka.start(validKaInterval);
4385             callback.expectStarted();
4386             ka.stop();
4387             callback.expectStopped();
4388 
4389             // Check that keepalive can be restarted without waiting for callback.
4390             ka.start(validKaInterval);
4391             callback.expectStarted();
4392             ka.stop();
4393             ka.start(validKaInterval);
4394             callback.expectStopped();
4395             callback.expectStarted();
4396             ka.stop();
4397             callback.expectStopped();
4398         }
4399 
4400         // Check that deleting the IP address stops the keepalive.
4401         LinkProperties bogusLp = new LinkProperties(lp);
4402         try (SocketKeepalive ka = mCm.createSocketKeepalive(
4403                 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
4404             ka.start(validKaInterval);
4405             callback.expectStarted();
4406             bogusLp.removeLinkAddress(new LinkAddress(myIPv4, 25));
4407             bogusLp.addLinkAddress(new LinkAddress(notMyIPv4, 25));
4408             mWiFiNetworkAgent.sendLinkProperties(bogusLp);
4409             callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
4410             mWiFiNetworkAgent.sendLinkProperties(lp);
4411         }
4412 
4413         // Check that a started keepalive is stopped correctly when the network disconnects.
4414         try (SocketKeepalive ka = mCm.createSocketKeepalive(
4415                 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
4416             ka.start(validKaInterval);
4417             callback.expectStarted();
4418             mWiFiNetworkAgent.disconnect();
4419             waitFor(mWiFiNetworkAgent.getDisconnectedCV());
4420             callback.expectError(SocketKeepalive.ERROR_INVALID_NETWORK);
4421 
4422             // ... and that stopping it after that has no adverse effects.
4423             waitForIdle();
4424             final Network myNetAlias = myNet;
4425             assertNull(mCm.getNetworkCapabilities(myNetAlias));
4426             ka.stop();
4427             callback.assertNoCallback();
4428         }
4429 
4430         // Reconnect.
4431         myNet = connectKeepaliveNetwork(lp);
4432         mWiFiNetworkAgent.setStartKeepaliveError(SocketKeepalive.SUCCESS);
4433 
4434         // Check that keepalive slots start from 1 and increment. The first one gets slot 1.
4435         mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
4436         int srcPort2 = 0;
4437         try (SocketKeepalive ka = mCm.createSocketKeepalive(
4438                 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
4439             ka.start(validKaInterval);
4440             callback.expectStarted();
4441 
4442             // The second one gets slot 2.
4443             mWiFiNetworkAgent.setExpectedKeepaliveSlot(2);
4444             final UdpEncapsulationSocket testSocket2 = mIpSec.openUdpEncapsulationSocket();
4445             srcPort2 = testSocket2.getPort();
4446             TestSocketKeepaliveCallback callback2 = new TestSocketKeepaliveCallback(executor);
4447             try (SocketKeepalive ka2 = mCm.createSocketKeepalive(
4448                     myNet, testSocket2, myIPv4, dstIPv4, executor, callback2)) {
4449                 ka2.start(validKaInterval);
4450                 callback2.expectStarted();
4451 
4452                 ka.stop();
4453                 callback.expectStopped();
4454 
4455                 ka2.stop();
4456                 callback2.expectStopped();
4457 
4458                 testSocket.close();
4459                 testSocket2.close();
4460             }
4461         }
4462 
4463         // Check that there is no port leaked after all keepalives and sockets are closed.
4464         // TODO: enable this check after ensuring a valid free port. See b/129512753#comment7.
4465         // assertFalse(isUdpPortInUse(srcPort));
4466         // assertFalse(isUdpPortInUse(srcPort2));
4467 
4468         mWiFiNetworkAgent.disconnect();
4469         waitFor(mWiFiNetworkAgent.getDisconnectedCV());
4470         mWiFiNetworkAgent = null;
4471     }
4472 
4473     @Test
testTcpSocketKeepalives()4474     public void testTcpSocketKeepalives() throws Exception {
4475         runTestWithSerialExecutors(executor -> doTestTcpSocketKeepalivesWithExecutor(executor));
4476     }
4477 
doTestTcpSocketKeepalivesWithExecutor(Executor executor)4478     private void doTestTcpSocketKeepalivesWithExecutor(Executor executor) throws Exception {
4479         final int srcPortV4 = 12345;
4480         final int srcPortV6 = 23456;
4481         final InetAddress myIPv4 = InetAddress.getByName("127.0.0.1");
4482         final InetAddress myIPv6 = InetAddress.getByName("::1");
4483 
4484         final int validKaInterval = 15;
4485 
4486         final LinkProperties lp = new LinkProperties();
4487         lp.setInterfaceName("wlan12");
4488         lp.addLinkAddress(new LinkAddress(myIPv6, 64));
4489         lp.addLinkAddress(new LinkAddress(myIPv4, 25));
4490         lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
4491         lp.addRoute(new RouteInfo(InetAddress.getByName("127.0.0.254")));
4492 
4493         final Network notMyNet = new Network(61234);
4494         final Network myNet = connectKeepaliveNetwork(lp);
4495 
4496         final Socket testSocketV4 = new Socket();
4497         final Socket testSocketV6 = new Socket();
4498 
4499         TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback(executor);
4500 
4501         // Attempt to start Tcp keepalives with invalid parameters and check for errors.
4502         // Invalid network.
4503         try (SocketKeepalive ka = mCm.createSocketKeepalive(
4504             notMyNet, testSocketV4, executor, callback)) {
4505             ka.start(validKaInterval);
4506             callback.expectError(SocketKeepalive.ERROR_INVALID_NETWORK);
4507         }
4508 
4509         // Invalid Socket (socket is not bound with IPv4 address).
4510         try (SocketKeepalive ka = mCm.createSocketKeepalive(
4511             myNet, testSocketV4, executor, callback)) {
4512             ka.start(validKaInterval);
4513             callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
4514         }
4515 
4516         // Invalid Socket (socket is not bound with IPv6 address).
4517         try (SocketKeepalive ka = mCm.createSocketKeepalive(
4518             myNet, testSocketV6, executor, callback)) {
4519             ka.start(validKaInterval);
4520             callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
4521         }
4522 
4523         // Bind the socket address
4524         testSocketV4.bind(new InetSocketAddress(myIPv4, srcPortV4));
4525         testSocketV6.bind(new InetSocketAddress(myIPv6, srcPortV6));
4526 
4527         // Invalid Socket (socket is bound with IPv4 address).
4528         try (SocketKeepalive ka = mCm.createSocketKeepalive(
4529             myNet, testSocketV4, executor, callback)) {
4530             ka.start(validKaInterval);
4531             callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
4532         }
4533 
4534         // Invalid Socket (socket is bound with IPv6 address).
4535         try (SocketKeepalive ka = mCm.createSocketKeepalive(
4536             myNet, testSocketV6, executor, callback)) {
4537             ka.start(validKaInterval);
4538             callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
4539         }
4540 
4541         testSocketV4.close();
4542         testSocketV6.close();
4543 
4544         mWiFiNetworkAgent.disconnect();
4545         waitFor(mWiFiNetworkAgent.getDisconnectedCV());
4546         mWiFiNetworkAgent = null;
4547     }
4548 
doTestNattSocketKeepalivesFdWithExecutor(Executor executor)4549     private void doTestNattSocketKeepalivesFdWithExecutor(Executor executor) throws Exception {
4550         final InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
4551         final InetAddress anyIPv4 = InetAddress.getByName("0.0.0.0");
4552         final InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8");
4553         final int validKaInterval = 15;
4554 
4555         // Prepare the target network.
4556         LinkProperties lp = new LinkProperties();
4557         lp.setInterfaceName("wlan12");
4558         lp.addLinkAddress(new LinkAddress(myIPv4, 25));
4559         lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
4560         Network myNet = connectKeepaliveNetwork(lp);
4561         mWiFiNetworkAgent.setStartKeepaliveError(SocketKeepalive.SUCCESS);
4562         mWiFiNetworkAgent.setStopKeepaliveError(SocketKeepalive.SUCCESS);
4563 
4564         TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback(executor);
4565 
4566         // Prepare the target file descriptor, keep only one instance.
4567         final IpSecManager mIpSec = (IpSecManager) mContext.getSystemService(Context.IPSEC_SERVICE);
4568         final UdpEncapsulationSocket testSocket = mIpSec.openUdpEncapsulationSocket();
4569         final int srcPort = testSocket.getPort();
4570         final ParcelFileDescriptor testPfd =
4571                 ParcelFileDescriptor.dup(testSocket.getFileDescriptor());
4572         testSocket.close();
4573         assertTrue(isUdpPortInUse(srcPort));
4574 
4575         // Start keepalive and explicit make the variable goes out of scope with try-with-resources
4576         // block.
4577         try (SocketKeepalive ka = mCm.createNattKeepalive(
4578                 myNet, testPfd, myIPv4, dstIPv4, executor, callback)) {
4579             ka.start(validKaInterval);
4580             callback.expectStarted();
4581             ka.stop();
4582             callback.expectStopped();
4583         }
4584 
4585         // Check that the ParcelFileDescriptor is still valid after keepalive stopped,
4586         // ErrnoException with EBADF will be thrown if the socket is closed when checking local
4587         // address.
4588         assertTrue(isUdpPortInUse(srcPort));
4589         final InetSocketAddress sa =
4590                 (InetSocketAddress) Os.getsockname(testPfd.getFileDescriptor());
4591         assertEquals(anyIPv4, sa.getAddress());
4592 
4593         testPfd.close();
4594         // TODO: enable this check after ensuring a valid free port. See b/129512753#comment7.
4595         // assertFalse(isUdpPortInUse(srcPort));
4596 
4597         mWiFiNetworkAgent.disconnect();
4598         waitFor(mWiFiNetworkAgent.getDisconnectedCV());
4599         mWiFiNetworkAgent = null;
4600     }
4601 
isUdpPortInUse(int port)4602     private static boolean isUdpPortInUse(int port) {
4603         try (DatagramSocket ignored = new DatagramSocket(port)) {
4604             return false;
4605         } catch (IOException ignored) {
4606             return true;
4607         }
4608     }
4609 
4610     @Test
testGetCaptivePortalServerUrl()4611     public void testGetCaptivePortalServerUrl() throws Exception {
4612         String url = mCm.getCaptivePortalServerUrl();
4613         assertEquals("http://connectivitycheck.gstatic.com/generate_204", url);
4614     }
4615 
4616     private static class TestNetworkPinner extends NetworkPinner {
awaitPin(int timeoutMs)4617         public static boolean awaitPin(int timeoutMs) {
4618             synchronized(sLock) {
4619                 if (sNetwork == null) {
4620                     try {
4621                         sLock.wait(timeoutMs);
4622                     } catch (InterruptedException e) {}
4623                 }
4624                 return sNetwork != null;
4625             }
4626         }
4627 
awaitUnpin(int timeoutMs)4628         public static boolean awaitUnpin(int timeoutMs) {
4629             synchronized(sLock) {
4630                 if (sNetwork != null) {
4631                     try {
4632                         sLock.wait(timeoutMs);
4633                     } catch (InterruptedException e) {}
4634                 }
4635                 return sNetwork == null;
4636             }
4637         }
4638     }
4639 
assertPinnedToWifiWithCellDefault()4640     private void assertPinnedToWifiWithCellDefault() {
4641         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess());
4642         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
4643     }
4644 
assertPinnedToWifiWithWifiDefault()4645     private void assertPinnedToWifiWithWifiDefault() {
4646         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess());
4647         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
4648     }
4649 
assertNotPinnedToWifi()4650     private void assertNotPinnedToWifi() {
4651         assertNull(mCm.getBoundNetworkForProcess());
4652         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
4653     }
4654 
4655     @Test
testNetworkPinner()4656     public void testNetworkPinner() {
4657         NetworkRequest wifiRequest = new NetworkRequest.Builder()
4658                 .addTransportType(TRANSPORT_WIFI)
4659                 .build();
4660         assertNull(mCm.getBoundNetworkForProcess());
4661 
4662         TestNetworkPinner.pin(mServiceContext, wifiRequest);
4663         assertNull(mCm.getBoundNetworkForProcess());
4664 
4665         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
4666         mCellNetworkAgent.connect(true);
4667         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
4668         mWiFiNetworkAgent.connect(false);
4669 
4670         // When wi-fi connects, expect to be pinned.
4671         assertTrue(TestNetworkPinner.awaitPin(100));
4672         assertPinnedToWifiWithCellDefault();
4673 
4674         // Disconnect and expect the pin to drop.
4675         mWiFiNetworkAgent.disconnect();
4676         assertTrue(TestNetworkPinner.awaitUnpin(100));
4677         assertNotPinnedToWifi();
4678 
4679         // Reconnecting does not cause the pin to come back.
4680         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
4681         mWiFiNetworkAgent.connect(false);
4682         assertFalse(TestNetworkPinner.awaitPin(100));
4683         assertNotPinnedToWifi();
4684 
4685         // Pinning while connected causes the pin to take effect immediately.
4686         TestNetworkPinner.pin(mServiceContext, wifiRequest);
4687         assertTrue(TestNetworkPinner.awaitPin(100));
4688         assertPinnedToWifiWithCellDefault();
4689 
4690         // Explicitly unpin and expect to use the default network again.
4691         TestNetworkPinner.unpin();
4692         assertNotPinnedToWifi();
4693 
4694         // Disconnect cell and wifi.
4695         ConditionVariable cv = waitForConnectivityBroadcasts(3);  // cell down, wifi up, wifi down.
4696         mCellNetworkAgent.disconnect();
4697         mWiFiNetworkAgent.disconnect();
4698         waitFor(cv);
4699 
4700         // Pinning takes effect even if the pinned network is the default when the pin is set...
4701         TestNetworkPinner.pin(mServiceContext, wifiRequest);
4702         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
4703         mWiFiNetworkAgent.connect(false);
4704         assertTrue(TestNetworkPinner.awaitPin(100));
4705         assertPinnedToWifiWithWifiDefault();
4706 
4707         // ... and is maintained even when that network is no longer the default.
4708         cv = waitForConnectivityBroadcasts(1);
4709         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
4710         mCellNetworkAgent.connect(true);
4711         waitFor(cv);
4712         assertPinnedToWifiWithCellDefault();
4713     }
4714 
4715     @Test
testNetworkCallbackMaximum()4716     public void testNetworkCallbackMaximum() {
4717         // We can only have 99 callbacks, because MultipathPolicyTracker is
4718         // already one of them.
4719         final int MAX_REQUESTS = 99;
4720         final int CALLBACKS = 89;
4721         final int INTENTS = 10;
4722         assertEquals(MAX_REQUESTS, CALLBACKS + INTENTS);
4723 
4724         NetworkRequest networkRequest = new NetworkRequest.Builder().build();
4725         ArrayList<Object> registered = new ArrayList<>();
4726 
4727         int j = 0;
4728         while (j++ < CALLBACKS / 2) {
4729             NetworkCallback cb = new NetworkCallback();
4730             mCm.requestNetwork(networkRequest, cb);
4731             registered.add(cb);
4732         }
4733         while (j++ < CALLBACKS) {
4734             NetworkCallback cb = new NetworkCallback();
4735             mCm.registerNetworkCallback(networkRequest, cb);
4736             registered.add(cb);
4737         }
4738         j = 0;
4739         while (j++ < INTENTS / 2) {
4740             PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, new Intent("a" + j), 0);
4741             mCm.requestNetwork(networkRequest, pi);
4742             registered.add(pi);
4743         }
4744         while (j++ < INTENTS) {
4745             PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, new Intent("b" + j), 0);
4746             mCm.registerNetworkCallback(networkRequest, pi);
4747             registered.add(pi);
4748         }
4749 
4750         // Test that the limit is enforced when MAX_REQUESTS simultaneous requests are added.
4751         try {
4752             mCm.requestNetwork(networkRequest, new NetworkCallback());
4753             fail("Registering " + MAX_REQUESTS + " network requests did not throw exception");
4754         } catch (TooManyRequestsException expected) {}
4755         try {
4756             mCm.registerNetworkCallback(networkRequest, new NetworkCallback());
4757             fail("Registering " + MAX_REQUESTS + " network callbacks did not throw exception");
4758         } catch (TooManyRequestsException expected) {}
4759         try {
4760             mCm.requestNetwork(networkRequest,
4761                 PendingIntent.getBroadcast(mContext, 0, new Intent("c"), 0));
4762             fail("Registering " + MAX_REQUESTS + " PendingIntent requests did not throw exception");
4763         } catch (TooManyRequestsException expected) {}
4764         try {
4765             mCm.registerNetworkCallback(networkRequest,
4766                 PendingIntent.getBroadcast(mContext, 0, new Intent("d"), 0));
4767             fail("Registering " + MAX_REQUESTS
4768                     + " PendingIntent callbacks did not throw exception");
4769         } catch (TooManyRequestsException expected) {}
4770 
4771         for (Object o : registered) {
4772             if (o instanceof NetworkCallback) {
4773                 mCm.unregisterNetworkCallback((NetworkCallback)o);
4774             }
4775             if (o instanceof PendingIntent) {
4776                 mCm.unregisterNetworkCallback((PendingIntent)o);
4777             }
4778         }
4779         waitForIdle();
4780 
4781         // Test that the limit is not hit when MAX_REQUESTS requests are added and removed.
4782         for (int i = 0; i < MAX_REQUESTS; i++) {
4783             NetworkCallback networkCallback = new NetworkCallback();
4784             mCm.requestNetwork(networkRequest, networkCallback);
4785             mCm.unregisterNetworkCallback(networkCallback);
4786         }
4787         waitForIdle();
4788 
4789         for (int i = 0; i < MAX_REQUESTS; i++) {
4790             NetworkCallback networkCallback = new NetworkCallback();
4791             mCm.registerNetworkCallback(networkRequest, networkCallback);
4792             mCm.unregisterNetworkCallback(networkCallback);
4793         }
4794         waitForIdle();
4795 
4796         for (int i = 0; i < MAX_REQUESTS; i++) {
4797             PendingIntent pendingIntent =
4798                     PendingIntent.getBroadcast(mContext, 0, new Intent("e" + i), 0);
4799             mCm.requestNetwork(networkRequest, pendingIntent);
4800             mCm.unregisterNetworkCallback(pendingIntent);
4801         }
4802         waitForIdle();
4803 
4804         for (int i = 0; i < MAX_REQUESTS; i++) {
4805             PendingIntent pendingIntent =
4806                     PendingIntent.getBroadcast(mContext, 0, new Intent("f" + i), 0);
4807             mCm.registerNetworkCallback(networkRequest, pendingIntent);
4808             mCm.unregisterNetworkCallback(pendingIntent);
4809         }
4810     }
4811 
4812     @Test
testNetworkInfoOfTypeNone()4813     public void testNetworkInfoOfTypeNone() {
4814         ConditionVariable broadcastCV = waitForConnectivityBroadcasts(1);
4815 
4816         verifyNoNetwork();
4817         MockNetworkAgent wifiAware = new MockNetworkAgent(TRANSPORT_WIFI_AWARE);
4818         assertNull(mCm.getActiveNetworkInfo());
4819 
4820         Network[] allNetworks = mCm.getAllNetworks();
4821         assertLength(1, allNetworks);
4822         Network network = allNetworks[0];
4823         NetworkCapabilities capabilities = mCm.getNetworkCapabilities(network);
4824         assertTrue(capabilities.hasTransport(TRANSPORT_WIFI_AWARE));
4825 
4826         final NetworkRequest request =
4827                 new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI_AWARE).build();
4828         final TestNetworkCallback callback = new TestNetworkCallback();
4829         mCm.registerNetworkCallback(request, callback);
4830 
4831         // Bring up wifi aware network.
4832         wifiAware.connect(false, false);
4833         callback.expectAvailableCallbacksUnvalidated(wifiAware);
4834 
4835         assertNull(mCm.getActiveNetworkInfo());
4836         assertNull(mCm.getActiveNetwork());
4837         // TODO: getAllNetworkInfo is dirty and returns a non-empty array right from the start
4838         // of this test. Fix it and uncomment the assert below.
4839         //assertEmpty(mCm.getAllNetworkInfo());
4840 
4841         // Disconnect wifi aware network.
4842         wifiAware.disconnect();
4843         callback.expectCallbackLike((info) -> info.state == CallbackState.LOST, TIMEOUT_MS);
4844         mCm.unregisterNetworkCallback(callback);
4845 
4846         verifyNoNetwork();
4847         if (broadcastCV.block(10)) {
4848             fail("expected no broadcast, but got CONNECTIVITY_ACTION broadcast");
4849         }
4850     }
4851 
4852     @Test
testDeprecatedAndUnsupportedOperations()4853     public void testDeprecatedAndUnsupportedOperations() throws Exception {
4854         final int TYPE_NONE = ConnectivityManager.TYPE_NONE;
4855         assertNull(mCm.getNetworkInfo(TYPE_NONE));
4856         assertNull(mCm.getNetworkForType(TYPE_NONE));
4857         assertNull(mCm.getLinkProperties(TYPE_NONE));
4858         assertFalse(mCm.isNetworkSupported(TYPE_NONE));
4859 
4860         assertException(() -> { mCm.networkCapabilitiesForType(TYPE_NONE); },
4861                 IllegalArgumentException.class);
4862 
4863         Class<UnsupportedOperationException> unsupported = UnsupportedOperationException.class;
4864         assertException(() -> { mCm.startUsingNetworkFeature(TYPE_WIFI, ""); }, unsupported);
4865         assertException(() -> { mCm.stopUsingNetworkFeature(TYPE_WIFI, ""); }, unsupported);
4866         // TODO: let test context have configuration application target sdk version
4867         // and test that pre-M requesting for TYPE_NONE sends back APN_REQUEST_FAILED
4868         assertException(() -> { mCm.startUsingNetworkFeature(TYPE_NONE, ""); }, unsupported);
4869         assertException(() -> { mCm.stopUsingNetworkFeature(TYPE_NONE, ""); }, unsupported);
4870         assertException(() -> { mCm.requestRouteToHostAddress(TYPE_NONE, null); }, unsupported);
4871     }
4872 
4873     @Test
testLinkPropertiesEnsuresDirectlyConnectedRoutes()4874     public void testLinkPropertiesEnsuresDirectlyConnectedRoutes() {
4875         final NetworkRequest networkRequest = new NetworkRequest.Builder()
4876                 .addTransportType(TRANSPORT_WIFI).build();
4877         final TestNetworkCallback networkCallback = new TestNetworkCallback();
4878         mCm.registerNetworkCallback(networkRequest, networkCallback);
4879 
4880         LinkProperties lp = new LinkProperties();
4881         lp.setInterfaceName(WIFI_IFNAME);
4882         LinkAddress myIpv4Address = new LinkAddress("192.168.12.3/24");
4883         RouteInfo myIpv4DefaultRoute = new RouteInfo((IpPrefix) null,
4884                 NetworkUtils.numericToInetAddress("192.168.12.1"), lp.getInterfaceName());
4885         lp.addLinkAddress(myIpv4Address);
4886         lp.addRoute(myIpv4DefaultRoute);
4887 
4888         // Verify direct routes are added when network agent is first registered in
4889         // ConnectivityService.
4890         MockNetworkAgent networkAgent = new MockNetworkAgent(TRANSPORT_WIFI, lp);
4891         networkAgent.connect(true);
4892         networkCallback.expectCallback(CallbackState.AVAILABLE, networkAgent);
4893         networkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, networkAgent);
4894         CallbackInfo cbi = networkCallback.expectCallback(CallbackState.LINK_PROPERTIES,
4895                 networkAgent);
4896         networkCallback.expectCallback(CallbackState.BLOCKED_STATUS, networkAgent);
4897         networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, networkAgent);
4898         networkCallback.assertNoCallback();
4899         checkDirectlyConnectedRoutes(cbi.arg, Arrays.asList(myIpv4Address),
4900                 Arrays.asList(myIpv4DefaultRoute));
4901         checkDirectlyConnectedRoutes(mCm.getLinkProperties(networkAgent.getNetwork()),
4902                 Arrays.asList(myIpv4Address), Arrays.asList(myIpv4DefaultRoute));
4903 
4904         // Verify direct routes are added during subsequent link properties updates.
4905         LinkProperties newLp = new LinkProperties(lp);
4906         LinkAddress myIpv6Address1 = new LinkAddress("fe80::cafe/64");
4907         LinkAddress myIpv6Address2 = new LinkAddress("2001:db8::2/64");
4908         newLp.addLinkAddress(myIpv6Address1);
4909         newLp.addLinkAddress(myIpv6Address2);
4910         networkAgent.sendLinkProperties(newLp);
4911         cbi = networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, networkAgent);
4912         networkCallback.assertNoCallback();
4913         checkDirectlyConnectedRoutes(cbi.arg,
4914                 Arrays.asList(myIpv4Address, myIpv6Address1, myIpv6Address2),
4915                 Arrays.asList(myIpv4DefaultRoute));
4916         mCm.unregisterNetworkCallback(networkCallback);
4917     }
4918 
4919     @Test
testStatsIfacesChanged()4920     public void testStatsIfacesChanged() throws Exception {
4921         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
4922         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
4923 
4924         Network[] onlyCell = new Network[] {mCellNetworkAgent.getNetwork()};
4925         Network[] onlyWifi = new Network[] {mWiFiNetworkAgent.getNetwork()};
4926 
4927         LinkProperties cellLp = new LinkProperties();
4928         cellLp.setInterfaceName(MOBILE_IFNAME);
4929         LinkProperties wifiLp = new LinkProperties();
4930         wifiLp.setInterfaceName(WIFI_IFNAME);
4931 
4932         // Simple connection should have updated ifaces
4933         mCellNetworkAgent.connect(false);
4934         mCellNetworkAgent.sendLinkProperties(cellLp);
4935         waitForIdle();
4936         verify(mStatsService, atLeastOnce())
4937                 .forceUpdateIfaces(
4938                         eq(onlyCell),
4939                         eq(new VpnInfo[0]),
4940                         any(NetworkState[].class),
4941                         eq(MOBILE_IFNAME));
4942         reset(mStatsService);
4943 
4944         // Default network switch should update ifaces.
4945         mWiFiNetworkAgent.connect(false);
4946         mWiFiNetworkAgent.sendLinkProperties(wifiLp);
4947         waitForIdle();
4948         assertEquals(wifiLp, mService.getActiveLinkProperties());
4949         verify(mStatsService, atLeastOnce())
4950                 .forceUpdateIfaces(
4951                         eq(onlyWifi),
4952                         eq(new VpnInfo[0]),
4953                         any(NetworkState[].class),
4954                         eq(WIFI_IFNAME));
4955         reset(mStatsService);
4956 
4957         // Disconnect should update ifaces.
4958         mWiFiNetworkAgent.disconnect();
4959         waitForIdle();
4960         verify(mStatsService, atLeastOnce())
4961                 .forceUpdateIfaces(
4962                         eq(onlyCell),
4963                         eq(new VpnInfo[0]),
4964                         any(NetworkState[].class),
4965                         eq(MOBILE_IFNAME));
4966         reset(mStatsService);
4967 
4968         // Metered change should update ifaces
4969         mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
4970         waitForIdle();
4971         verify(mStatsService, atLeastOnce())
4972                 .forceUpdateIfaces(
4973                         eq(onlyCell),
4974                         eq(new VpnInfo[0]),
4975                         any(NetworkState[].class),
4976                         eq(MOBILE_IFNAME));
4977         reset(mStatsService);
4978 
4979         mCellNetworkAgent.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
4980         waitForIdle();
4981         verify(mStatsService, atLeastOnce())
4982                 .forceUpdateIfaces(
4983                         eq(onlyCell),
4984                         eq(new VpnInfo[0]),
4985                         any(NetworkState[].class),
4986                         eq(MOBILE_IFNAME));
4987         reset(mStatsService);
4988 
4989         // Captive portal change shouldn't update ifaces
4990         mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL);
4991         waitForIdle();
4992         verify(mStatsService, never())
4993                 .forceUpdateIfaces(
4994                         eq(onlyCell),
4995                         eq(new VpnInfo[0]),
4996                         any(NetworkState[].class),
4997                         eq(MOBILE_IFNAME));
4998         reset(mStatsService);
4999 
5000         // Roaming change should update ifaces
5001         mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING);
5002         waitForIdle();
5003         verify(mStatsService, atLeastOnce())
5004                 .forceUpdateIfaces(
5005                         eq(onlyCell),
5006                         eq(new VpnInfo[0]),
5007                         any(NetworkState[].class),
5008                         eq(MOBILE_IFNAME));
5009         reset(mStatsService);
5010     }
5011 
5012     @Test
testBasicDnsConfigurationPushed()5013     public void testBasicDnsConfigurationPushed() throws Exception {
5014         setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
5015 
5016         // Clear any interactions that occur as a result of CS starting up.
5017         reset(mMockDnsResolver);
5018 
5019         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
5020         waitForIdle();
5021         verify(mMockDnsResolver, never()).setResolverConfiguration(any());
5022         verifyNoMoreInteractions(mMockDnsResolver);
5023 
5024         final LinkProperties cellLp = new LinkProperties();
5025         cellLp.setInterfaceName(MOBILE_IFNAME);
5026         // Add IPv4 and IPv6 default routes, because DNS-over-TLS code does
5027         // "is-reachable" testing in order to not program netd with unreachable
5028         // nameservers that it might try repeated to validate.
5029         cellLp.addLinkAddress(new LinkAddress("192.0.2.4/24"));
5030         cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("192.0.2.4"),
5031                 MOBILE_IFNAME));
5032         cellLp.addLinkAddress(new LinkAddress("2001:db8:1::1/64"));
5033         cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("2001:db8:1::1"),
5034                 MOBILE_IFNAME));
5035         mCellNetworkAgent.sendLinkProperties(cellLp);
5036         mCellNetworkAgent.connect(false);
5037         waitForIdle();
5038 
5039         verify(mMockDnsResolver, times(1)).createNetworkCache(
5040                 eq(mCellNetworkAgent.getNetwork().netId));
5041         // CS tells dnsresolver about the empty DNS config for this network.
5042         verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(any());
5043         reset(mMockDnsResolver);
5044 
5045         cellLp.addDnsServer(InetAddress.getByName("2001:db8::1"));
5046         mCellNetworkAgent.sendLinkProperties(cellLp);
5047         waitForIdle();
5048         verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
5049                 mResolverParamsParcelCaptor.capture());
5050         ResolverParamsParcel resolvrParams = mResolverParamsParcelCaptor.getValue();
5051         assertEquals(1, resolvrParams.servers.length);
5052         assertTrue(ArrayUtils.contains(resolvrParams.servers, "2001:db8::1"));
5053         // Opportunistic mode.
5054         assertTrue(ArrayUtils.contains(resolvrParams.tlsServers, "2001:db8::1"));
5055         reset(mMockDnsResolver);
5056 
5057         cellLp.addDnsServer(InetAddress.getByName("192.0.2.1"));
5058         mCellNetworkAgent.sendLinkProperties(cellLp);
5059         waitForIdle();
5060         verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
5061                 mResolverParamsParcelCaptor.capture());
5062         resolvrParams = mResolverParamsParcelCaptor.getValue();
5063         assertEquals(2, resolvrParams.servers.length);
5064         assertTrue(ArrayUtils.containsAll(resolvrParams.servers,
5065                 new String[]{"2001:db8::1", "192.0.2.1"}));
5066         // Opportunistic mode.
5067         assertEquals(2, resolvrParams.tlsServers.length);
5068         assertTrue(ArrayUtils.containsAll(resolvrParams.tlsServers,
5069                 new String[]{"2001:db8::1", "192.0.2.1"}));
5070         reset(mMockDnsResolver);
5071 
5072         final String TLS_SPECIFIER = "tls.example.com";
5073         final String TLS_SERVER6 = "2001:db8:53::53";
5074         final InetAddress[] TLS_IPS = new InetAddress[]{ InetAddress.getByName(TLS_SERVER6) };
5075         final String[] TLS_SERVERS = new String[]{ TLS_SERVER6 };
5076         mCellNetworkAgent.mNmCallbacks.notifyPrivateDnsConfigResolved(
5077                 new PrivateDnsConfig(TLS_SPECIFIER, TLS_IPS).toParcel());
5078 
5079         waitForIdle();
5080         verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
5081                 mResolverParamsParcelCaptor.capture());
5082         resolvrParams = mResolverParamsParcelCaptor.getValue();
5083         assertEquals(2, resolvrParams.servers.length);
5084         assertTrue(ArrayUtils.containsAll(resolvrParams.servers,
5085                 new String[]{"2001:db8::1", "192.0.2.1"}));
5086         reset(mMockDnsResolver);
5087     }
5088 
5089     @Test
testPrivateDnsSettingsChange()5090     public void testPrivateDnsSettingsChange() throws Exception {
5091         // Clear any interactions that occur as a result of CS starting up.
5092         reset(mMockDnsResolver);
5093 
5094         // The default on Android is opportunistic mode ("Automatic").
5095         setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
5096 
5097         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
5098         final NetworkRequest cellRequest = new NetworkRequest.Builder()
5099                 .addTransportType(TRANSPORT_CELLULAR).build();
5100         mCm.requestNetwork(cellRequest, cellNetworkCallback);
5101 
5102         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
5103         waitForIdle();
5104         // CS tells netd about the empty DNS config for this network.
5105         verify(mMockDnsResolver, never()).setResolverConfiguration(any());
5106         verifyNoMoreInteractions(mMockDnsResolver);
5107 
5108         final LinkProperties cellLp = new LinkProperties();
5109         cellLp.setInterfaceName(MOBILE_IFNAME);
5110         // Add IPv4 and IPv6 default routes, because DNS-over-TLS code does
5111         // "is-reachable" testing in order to not program netd with unreachable
5112         // nameservers that it might try repeated to validate.
5113         cellLp.addLinkAddress(new LinkAddress("192.0.2.4/24"));
5114         cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("192.0.2.4"),
5115                 MOBILE_IFNAME));
5116         cellLp.addLinkAddress(new LinkAddress("2001:db8:1::1/64"));
5117         cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("2001:db8:1::1"),
5118                 MOBILE_IFNAME));
5119         cellLp.addDnsServer(InetAddress.getByName("2001:db8::1"));
5120         cellLp.addDnsServer(InetAddress.getByName("192.0.2.1"));
5121 
5122         mCellNetworkAgent.sendLinkProperties(cellLp);
5123         mCellNetworkAgent.connect(false);
5124         waitForIdle();
5125         verify(mMockDnsResolver, times(1)).createNetworkCache(
5126                 eq(mCellNetworkAgent.getNetwork().netId));
5127         verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
5128                 mResolverParamsParcelCaptor.capture());
5129         ResolverParamsParcel resolvrParams = mResolverParamsParcelCaptor.getValue();
5130         assertEquals(2, resolvrParams.tlsServers.length);
5131         assertTrue(ArrayUtils.containsAll(resolvrParams.tlsServers,
5132                 new String[]{"2001:db8::1", "192.0.2.1"}));
5133         // Opportunistic mode.
5134         assertEquals(2, resolvrParams.tlsServers.length);
5135         assertTrue(ArrayUtils.containsAll(resolvrParams.tlsServers,
5136                 new String[]{"2001:db8::1", "192.0.2.1"}));
5137         reset(mMockDnsResolver);
5138         cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
5139         cellNetworkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES,
5140                 mCellNetworkAgent);
5141         CallbackInfo cbi = cellNetworkCallback.expectCallback(
5142                 CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
5143         cellNetworkCallback.expectCallback(CallbackState.BLOCKED_STATUS, mCellNetworkAgent);
5144         cellNetworkCallback.assertNoCallback();
5145         assertFalse(((LinkProperties)cbi.arg).isPrivateDnsActive());
5146         assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName());
5147 
5148         setPrivateDnsSettings(PRIVATE_DNS_MODE_OFF, "ignored.example.com");
5149         verify(mMockDnsResolver, times(1)).setResolverConfiguration(
5150                 mResolverParamsParcelCaptor.capture());
5151         resolvrParams = mResolverParamsParcelCaptor.getValue();
5152         assertEquals(2, resolvrParams.servers.length);
5153         assertTrue(ArrayUtils.containsAll(resolvrParams.servers,
5154                 new String[]{"2001:db8::1", "192.0.2.1"}));
5155         reset(mMockDnsResolver);
5156         cellNetworkCallback.assertNoCallback();
5157 
5158         setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
5159         verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
5160                 mResolverParamsParcelCaptor.capture());
5161         resolvrParams = mResolverParamsParcelCaptor.getValue();
5162         assertEquals(2, resolvrParams.servers.length);
5163         assertTrue(ArrayUtils.containsAll(resolvrParams.servers,
5164                 new String[]{"2001:db8::1", "192.0.2.1"}));
5165         assertEquals(2, resolvrParams.tlsServers.length);
5166         assertTrue(ArrayUtils.containsAll(resolvrParams.tlsServers,
5167                 new String[]{"2001:db8::1", "192.0.2.1"}));
5168         reset(mMockDnsResolver);
5169         cellNetworkCallback.assertNoCallback();
5170 
5171         setPrivateDnsSettings(PRIVATE_DNS_MODE_PROVIDER_HOSTNAME, "strict.example.com");
5172         // Can't test dns configuration for strict mode without properly mocking
5173         // out the DNS lookups, but can test that LinkProperties is updated.
5174         cbi = cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES,
5175                 mCellNetworkAgent);
5176         cellNetworkCallback.assertNoCallback();
5177         assertTrue(((LinkProperties)cbi.arg).isPrivateDnsActive());
5178         assertEquals("strict.example.com", ((LinkProperties)cbi.arg).getPrivateDnsServerName());
5179     }
5180 
5181     @Test
testLinkPropertiesWithPrivateDnsValidationEvents()5182     public void testLinkPropertiesWithPrivateDnsValidationEvents() throws Exception {
5183         // The default on Android is opportunistic mode ("Automatic").
5184         setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
5185 
5186         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
5187         final NetworkRequest cellRequest = new NetworkRequest.Builder()
5188                 .addTransportType(TRANSPORT_CELLULAR).build();
5189         mCm.requestNetwork(cellRequest, cellNetworkCallback);
5190 
5191         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
5192         waitForIdle();
5193         LinkProperties lp = new LinkProperties();
5194         mCellNetworkAgent.sendLinkProperties(lp);
5195         mCellNetworkAgent.connect(false);
5196         waitForIdle();
5197         cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
5198         cellNetworkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES,
5199                 mCellNetworkAgent);
5200         CallbackInfo cbi = cellNetworkCallback.expectCallback(
5201                 CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
5202         cellNetworkCallback.expectCallback(CallbackState.BLOCKED_STATUS, mCellNetworkAgent);
5203         cellNetworkCallback.assertNoCallback();
5204         assertFalse(((LinkProperties)cbi.arg).isPrivateDnsActive());
5205         assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName());
5206         Set<InetAddress> dnsServers = new HashSet<>();
5207         checkDnsServers(cbi.arg, dnsServers);
5208 
5209         // Send a validation event for a server that is not part of the current
5210         // resolver config. The validation event should be ignored.
5211         mService.mNetdEventCallback.onPrivateDnsValidationEvent(
5212                 mCellNetworkAgent.getNetwork().netId, "", "145.100.185.18", true);
5213         cellNetworkCallback.assertNoCallback();
5214 
5215         // Add a dns server to the LinkProperties.
5216         LinkProperties lp2 = new LinkProperties(lp);
5217         lp2.addDnsServer(InetAddress.getByName("145.100.185.16"));
5218         mCellNetworkAgent.sendLinkProperties(lp2);
5219         cbi = cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES,
5220                 mCellNetworkAgent);
5221         cellNetworkCallback.assertNoCallback();
5222         assertFalse(((LinkProperties)cbi.arg).isPrivateDnsActive());
5223         assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName());
5224         dnsServers.add(InetAddress.getByName("145.100.185.16"));
5225         checkDnsServers(cbi.arg, dnsServers);
5226 
5227         // Send a validation event containing a hostname that is not part of
5228         // the current resolver config. The validation event should be ignored.
5229         mService.mNetdEventCallback.onPrivateDnsValidationEvent(
5230                 mCellNetworkAgent.getNetwork().netId, "145.100.185.16", "hostname", true);
5231         cellNetworkCallback.assertNoCallback();
5232 
5233         // Send a validation event where validation failed.
5234         mService.mNetdEventCallback.onPrivateDnsValidationEvent(
5235                 mCellNetworkAgent.getNetwork().netId, "145.100.185.16", "", false);
5236         cellNetworkCallback.assertNoCallback();
5237 
5238         // Send a validation event where validation succeeded for a server in
5239         // the current resolver config. A LinkProperties callback with updated
5240         // private dns fields should be sent.
5241         mService.mNetdEventCallback.onPrivateDnsValidationEvent(
5242                 mCellNetworkAgent.getNetwork().netId, "145.100.185.16", "", true);
5243         cbi = cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES,
5244                 mCellNetworkAgent);
5245         cellNetworkCallback.assertNoCallback();
5246         assertTrue(((LinkProperties)cbi.arg).isPrivateDnsActive());
5247         assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName());
5248         checkDnsServers(cbi.arg, dnsServers);
5249 
5250         // The private dns fields in LinkProperties should be preserved when
5251         // the network agent sends unrelated changes.
5252         LinkProperties lp3 = new LinkProperties(lp2);
5253         lp3.setMtu(1300);
5254         mCellNetworkAgent.sendLinkProperties(lp3);
5255         cbi = cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES,
5256                 mCellNetworkAgent);
5257         cellNetworkCallback.assertNoCallback();
5258         assertTrue(((LinkProperties)cbi.arg).isPrivateDnsActive());
5259         assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName());
5260         checkDnsServers(cbi.arg, dnsServers);
5261         assertEquals(1300, ((LinkProperties)cbi.arg).getMtu());
5262 
5263         // Removing the only validated server should affect the private dns
5264         // fields in LinkProperties.
5265         LinkProperties lp4 = new LinkProperties(lp3);
5266         lp4.removeDnsServer(InetAddress.getByName("145.100.185.16"));
5267         mCellNetworkAgent.sendLinkProperties(lp4);
5268         cbi = cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES,
5269                 mCellNetworkAgent);
5270         cellNetworkCallback.assertNoCallback();
5271         assertFalse(((LinkProperties)cbi.arg).isPrivateDnsActive());
5272         assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName());
5273         dnsServers.remove(InetAddress.getByName("145.100.185.16"));
5274         checkDnsServers(cbi.arg, dnsServers);
5275         assertEquals(1300, ((LinkProperties)cbi.arg).getMtu());
5276     }
5277 
checkDirectlyConnectedRoutes(Object callbackObj, Collection<LinkAddress> linkAddresses, Collection<RouteInfo> otherRoutes)5278     private void checkDirectlyConnectedRoutes(Object callbackObj,
5279             Collection<LinkAddress> linkAddresses, Collection<RouteInfo> otherRoutes) {
5280         assertTrue(callbackObj instanceof LinkProperties);
5281         LinkProperties lp = (LinkProperties) callbackObj;
5282 
5283         Set<RouteInfo> expectedRoutes = new ArraySet<>();
5284         expectedRoutes.addAll(otherRoutes);
5285         for (LinkAddress address : linkAddresses) {
5286             RouteInfo localRoute = new RouteInfo(address, null, lp.getInterfaceName());
5287             // Duplicates in linkAddresses are considered failures
5288             assertTrue(expectedRoutes.add(localRoute));
5289         }
5290         List<RouteInfo> observedRoutes = lp.getRoutes();
5291         assertEquals(expectedRoutes.size(), observedRoutes.size());
5292         assertTrue(observedRoutes.containsAll(expectedRoutes));
5293     }
5294 
checkDnsServers(Object callbackObj, Set<InetAddress> dnsServers)5295     private static void checkDnsServers(Object callbackObj, Set<InetAddress> dnsServers) {
5296         assertTrue(callbackObj instanceof LinkProperties);
5297         LinkProperties lp = (LinkProperties) callbackObj;
5298         assertEquals(dnsServers.size(), lp.getDnsServers().size());
5299         assertTrue(lp.getDnsServers().containsAll(dnsServers));
5300     }
5301 
assertEmpty(T[] ts)5302     private static <T> void assertEmpty(T[] ts) {
5303         int length = ts.length;
5304         assertEquals("expected empty array, but length was " + length, 0, length);
5305     }
5306 
assertLength(int expected, T[] got)5307     private static <T> void assertLength(int expected, T[] got) {
5308         int length = got.length;
5309         assertEquals(String.format("expected array of length %s, but length was %s for %s",
5310                 expected, length, Arrays.toString(got)), expected, length);
5311     }
5312 
assertException(Runnable block, Class<T> expected)5313     private static <T> void assertException(Runnable block, Class<T> expected) {
5314         try {
5315             block.run();
5316             fail("Expected exception of type " + expected);
5317         } catch (Exception got) {
5318             if (!got.getClass().equals(expected)) {
5319                 fail("Expected exception of type " + expected + " but got " + got);
5320             }
5321             return;
5322         }
5323     }
5324 
5325     @Test
testVpnNetworkActive()5326     public void testVpnNetworkActive() {
5327         final int uid = Process.myUid();
5328 
5329         final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback();
5330         final TestNetworkCallback genericNotVpnNetworkCallback = new TestNetworkCallback();
5331         final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
5332         final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
5333         final TestNetworkCallback defaultCallback = new TestNetworkCallback();
5334         final NetworkRequest genericNotVpnRequest = new NetworkRequest.Builder().build();
5335         final NetworkRequest genericRequest = new NetworkRequest.Builder()
5336                 .removeCapability(NET_CAPABILITY_NOT_VPN).build();
5337         final NetworkRequest wifiRequest = new NetworkRequest.Builder()
5338                 .addTransportType(TRANSPORT_WIFI).build();
5339         final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder()
5340                 .removeCapability(NET_CAPABILITY_NOT_VPN)
5341                 .addTransportType(TRANSPORT_VPN).build();
5342         mCm.registerNetworkCallback(genericRequest, genericNetworkCallback);
5343         mCm.registerNetworkCallback(genericNotVpnRequest, genericNotVpnNetworkCallback);
5344         mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
5345         mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
5346         mCm.registerDefaultNetworkCallback(defaultCallback);
5347         defaultCallback.assertNoCallback();
5348 
5349         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
5350         mWiFiNetworkAgent.connect(false);
5351 
5352         genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
5353         genericNotVpnNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
5354         wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
5355         defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
5356         vpnNetworkCallback.assertNoCallback();
5357         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
5358 
5359         final MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
5360         final ArraySet<UidRange> ranges = new ArraySet<>();
5361         ranges.add(new UidRange(uid, uid));
5362         mMockVpn.setNetworkAgent(vpnNetworkAgent);
5363         mMockVpn.setUids(ranges);
5364         // VPN networks do not satisfy the default request and are automatically validated
5365         // by NetworkMonitor
5366         assertFalse(NetworkMonitorUtils.isValidationRequired(vpnNetworkAgent.mNetworkCapabilities));
5367         vpnNetworkAgent.setNetworkValid();
5368 
5369         vpnNetworkAgent.connect(false);
5370         mMockVpn.connect();
5371         mMockVpn.setUnderlyingNetworks(new Network[0]);
5372 
5373         genericNetworkCallback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
5374         genericNotVpnNetworkCallback.assertNoCallback();
5375         wifiNetworkCallback.assertNoCallback();
5376         vpnNetworkCallback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
5377         defaultCallback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
5378         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
5379 
5380         genericNetworkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, vpnNetworkAgent);
5381         genericNotVpnNetworkCallback.assertNoCallback();
5382         vpnNetworkCallback.expectCapabilitiesLike(nc -> null == nc.getUids(), vpnNetworkAgent);
5383         defaultCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, vpnNetworkAgent);
5384         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
5385 
5386         ranges.clear();
5387         vpnNetworkAgent.setUids(ranges);
5388 
5389         genericNetworkCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
5390         genericNotVpnNetworkCallback.assertNoCallback();
5391         wifiNetworkCallback.assertNoCallback();
5392         vpnNetworkCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
5393 
5394         // TODO : The default network callback should actually get a LOST call here (also see the
5395         // comment below for AVAILABLE). This is because ConnectivityService does not look at UID
5396         // ranges at all when determining whether a network should be rematched. In practice, VPNs
5397         // can't currently update their UIDs without disconnecting, so this does not matter too
5398         // much, but that is the reason the test here has to check for an update to the
5399         // capabilities instead of the expected LOST then AVAILABLE.
5400         defaultCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, vpnNetworkAgent);
5401 
5402         ranges.add(new UidRange(uid, uid));
5403         mMockVpn.setUids(ranges);
5404         vpnNetworkAgent.setUids(ranges);
5405 
5406         genericNetworkCallback.expectAvailableCallbacksValidated(vpnNetworkAgent);
5407         genericNotVpnNetworkCallback.assertNoCallback();
5408         wifiNetworkCallback.assertNoCallback();
5409         vpnNetworkCallback.expectAvailableCallbacksValidated(vpnNetworkAgent);
5410         // TODO : Here like above, AVAILABLE would be correct, but because this can't actually
5411         // happen outside of the test, ConnectivityService does not rematch callbacks.
5412         defaultCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, vpnNetworkAgent);
5413 
5414         mWiFiNetworkAgent.disconnect();
5415 
5416         genericNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
5417         genericNotVpnNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
5418         wifiNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
5419         vpnNetworkCallback.assertNoCallback();
5420         defaultCallback.assertNoCallback();
5421 
5422         vpnNetworkAgent.disconnect();
5423 
5424         genericNetworkCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
5425         genericNotVpnNetworkCallback.assertNoCallback();
5426         wifiNetworkCallback.assertNoCallback();
5427         vpnNetworkCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
5428         defaultCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
5429         assertEquals(null, mCm.getActiveNetwork());
5430 
5431         mCm.unregisterNetworkCallback(genericNetworkCallback);
5432         mCm.unregisterNetworkCallback(wifiNetworkCallback);
5433         mCm.unregisterNetworkCallback(vpnNetworkCallback);
5434         mCm.unregisterNetworkCallback(defaultCallback);
5435     }
5436 
5437     @Test
testVpnWithoutInternet()5438     public void testVpnWithoutInternet() {
5439         final int uid = Process.myUid();
5440 
5441         final TestNetworkCallback defaultCallback = new TestNetworkCallback();
5442         mCm.registerDefaultNetworkCallback(defaultCallback);
5443 
5444         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
5445         mWiFiNetworkAgent.connect(true);
5446 
5447         defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
5448         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
5449 
5450         MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
5451         final ArraySet<UidRange> ranges = new ArraySet<>();
5452         ranges.add(new UidRange(uid, uid));
5453         mMockVpn.setNetworkAgent(vpnNetworkAgent);
5454         mMockVpn.setUids(ranges);
5455         vpnNetworkAgent.connect(true /* validated */, false /* hasInternet */);
5456         mMockVpn.connect();
5457 
5458         defaultCallback.assertNoCallback();
5459         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
5460 
5461         vpnNetworkAgent.disconnect();
5462         defaultCallback.assertNoCallback();
5463 
5464         mCm.unregisterNetworkCallback(defaultCallback);
5465     }
5466 
5467     @Test
testVpnWithInternet()5468     public void testVpnWithInternet() {
5469         final int uid = Process.myUid();
5470 
5471         final TestNetworkCallback defaultCallback = new TestNetworkCallback();
5472         mCm.registerDefaultNetworkCallback(defaultCallback);
5473 
5474         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
5475         mWiFiNetworkAgent.connect(true);
5476 
5477         defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
5478         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
5479 
5480         MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
5481         final ArraySet<UidRange> ranges = new ArraySet<>();
5482         ranges.add(new UidRange(uid, uid));
5483         mMockVpn.setNetworkAgent(vpnNetworkAgent);
5484         mMockVpn.setUids(ranges);
5485         vpnNetworkAgent.connect(true /* validated */, true /* hasInternet */);
5486         mMockVpn.connect();
5487 
5488         defaultCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
5489         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
5490 
5491         vpnNetworkAgent.disconnect();
5492         defaultCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
5493         defaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
5494 
5495         mCm.unregisterNetworkCallback(defaultCallback);
5496     }
5497 
5498     @Test
testVpnUnvalidated()5499     public void testVpnUnvalidated() throws Exception {
5500         final TestNetworkCallback callback = new TestNetworkCallback();
5501         mCm.registerDefaultNetworkCallback(callback);
5502 
5503         // Bring up Ethernet.
5504         mEthernetNetworkAgent = new MockNetworkAgent(TRANSPORT_ETHERNET);
5505         mEthernetNetworkAgent.connect(true);
5506         callback.expectAvailableThenValidatedCallbacks(mEthernetNetworkAgent);
5507         callback.assertNoCallback();
5508 
5509         // Bring up a VPN that has the INTERNET capability, initially unvalidated.
5510         final int uid = Process.myUid();
5511         final MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
5512         final ArraySet<UidRange> ranges = new ArraySet<>();
5513         ranges.add(new UidRange(uid, uid));
5514         mMockVpn.setNetworkAgent(vpnNetworkAgent);
5515         mMockVpn.setUids(ranges);
5516         vpnNetworkAgent.connect(false /* validated */, true /* hasInternet */);
5517         mMockVpn.connect();
5518 
5519         // Even though the VPN is unvalidated, it becomes the default network for our app.
5520         callback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
5521         // TODO: this looks like a spurious callback.
5522         callback.expectCallback(CallbackState.NETWORK_CAPABILITIES, vpnNetworkAgent);
5523         callback.assertNoCallback();
5524 
5525         assertTrue(vpnNetworkAgent.getScore() > mEthernetNetworkAgent.getScore());
5526         assertEquals(ConnectivityConstants.VPN_DEFAULT_SCORE, vpnNetworkAgent.getScore());
5527         assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
5528 
5529         NetworkCapabilities nc = mCm.getNetworkCapabilities(vpnNetworkAgent.getNetwork());
5530         assertFalse(nc.hasCapability(NET_CAPABILITY_VALIDATED));
5531         assertTrue(nc.hasCapability(NET_CAPABILITY_INTERNET));
5532 
5533         assertFalse(NetworkMonitorUtils.isValidationRequired(vpnNetworkAgent.mNetworkCapabilities));
5534         assertTrue(NetworkMonitorUtils.isPrivateDnsValidationRequired(
5535                 vpnNetworkAgent.mNetworkCapabilities));
5536 
5537         // Pretend that the VPN network validates.
5538         vpnNetworkAgent.setNetworkValid();
5539         vpnNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
5540         // Expect to see the validated capability, but no other changes, because the VPN is already
5541         // the default network for the app.
5542         callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, vpnNetworkAgent);
5543         callback.assertNoCallback();
5544 
5545         vpnNetworkAgent.disconnect();
5546         callback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
5547         callback.expectAvailableCallbacksValidated(mEthernetNetworkAgent);
5548     }
5549 
5550     @Test
testVpnSetUnderlyingNetworks()5551     public void testVpnSetUnderlyingNetworks() {
5552         final int uid = Process.myUid();
5553 
5554         final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
5555         final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder()
5556                 .removeCapability(NET_CAPABILITY_NOT_VPN)
5557                 .addTransportType(TRANSPORT_VPN)
5558                 .build();
5559         NetworkCapabilities nc;
5560         mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
5561         vpnNetworkCallback.assertNoCallback();
5562 
5563         final MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
5564         final ArraySet<UidRange> ranges = new ArraySet<>();
5565         ranges.add(new UidRange(uid, uid));
5566         mMockVpn.setNetworkAgent(vpnNetworkAgent);
5567         mMockVpn.connect();
5568         mMockVpn.setUids(ranges);
5569         vpnNetworkAgent.connect(true /* validated */, false /* hasInternet */);
5570 
5571         vpnNetworkCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
5572         nc = mCm.getNetworkCapabilities(vpnNetworkAgent.getNetwork());
5573         assertTrue(nc.hasTransport(TRANSPORT_VPN));
5574         assertFalse(nc.hasTransport(TRANSPORT_CELLULAR));
5575         assertFalse(nc.hasTransport(TRANSPORT_WIFI));
5576         // For safety reasons a VPN without underlying networks is considered metered.
5577         assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED));
5578 
5579         // Connect cell and use it as an underlying network.
5580         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
5581         mCellNetworkAgent.connect(true);
5582 
5583         mService.setUnderlyingNetworksForVpn(
5584                 new Network[] { mCellNetworkAgent.getNetwork() });
5585 
5586         vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
5587                 && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
5588                 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
5589                 vpnNetworkAgent);
5590 
5591         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
5592         mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5593         mWiFiNetworkAgent.connect(true);
5594 
5595         mService.setUnderlyingNetworksForVpn(
5596                 new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() });
5597 
5598         vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
5599                 && caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
5600                 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
5601                 vpnNetworkAgent);
5602 
5603         // Don't disconnect, but note the VPN is not using wifi any more.
5604         mService.setUnderlyingNetworksForVpn(
5605                 new Network[] { mCellNetworkAgent.getNetwork() });
5606 
5607         vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
5608                 && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
5609                 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
5610                 vpnNetworkAgent);
5611 
5612         // Use Wifi but not cell. Note the VPN is now unmetered.
5613         mService.setUnderlyingNetworksForVpn(
5614                 new Network[] { mWiFiNetworkAgent.getNetwork() });
5615 
5616         vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
5617                 && !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
5618                 && caps.hasCapability(NET_CAPABILITY_NOT_METERED),
5619                 vpnNetworkAgent);
5620 
5621         // Use both again.
5622         mService.setUnderlyingNetworksForVpn(
5623                 new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() });
5624 
5625         vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
5626                 && caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
5627                 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
5628                 vpnNetworkAgent);
5629 
5630         // Disconnect cell. Receive update without even removing the dead network from the
5631         // underlying networks – it's dead anyway. Not metered any more.
5632         mCellNetworkAgent.disconnect();
5633         vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
5634                 && !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
5635                 && caps.hasCapability(NET_CAPABILITY_NOT_METERED),
5636                 vpnNetworkAgent);
5637 
5638         // Disconnect wifi too. No underlying networks means this is now metered.
5639         mWiFiNetworkAgent.disconnect();
5640         vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
5641                 && !caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
5642                 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
5643                 vpnNetworkAgent);
5644 
5645         mMockVpn.disconnect();
5646     }
5647 
5648     @Test
testNullUnderlyingNetworks()5649     public void testNullUnderlyingNetworks() {
5650         final int uid = Process.myUid();
5651 
5652         final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
5653         final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder()
5654                 .removeCapability(NET_CAPABILITY_NOT_VPN)
5655                 .addTransportType(TRANSPORT_VPN)
5656                 .build();
5657         NetworkCapabilities nc;
5658         mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
5659         vpnNetworkCallback.assertNoCallback();
5660 
5661         final MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
5662         final ArraySet<UidRange> ranges = new ArraySet<>();
5663         ranges.add(new UidRange(uid, uid));
5664         mMockVpn.setNetworkAgent(vpnNetworkAgent);
5665         mMockVpn.connect();
5666         mMockVpn.setUids(ranges);
5667         vpnNetworkAgent.connect(true /* validated */, false /* hasInternet */);
5668 
5669         vpnNetworkCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
5670         nc = mCm.getNetworkCapabilities(vpnNetworkAgent.getNetwork());
5671         assertTrue(nc.hasTransport(TRANSPORT_VPN));
5672         assertFalse(nc.hasTransport(TRANSPORT_CELLULAR));
5673         assertFalse(nc.hasTransport(TRANSPORT_WIFI));
5674         // By default, VPN is set to track default network (i.e. its underlying networks is null).
5675         // In case of no default network, VPN is considered metered.
5676         assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED));
5677 
5678         // Connect to Cell; Cell is the default network.
5679         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
5680         mCellNetworkAgent.connect(true);
5681 
5682         vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
5683                 && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
5684                 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
5685                 vpnNetworkAgent);
5686 
5687         // Connect to WiFi; WiFi is the new default.
5688         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
5689         mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5690         mWiFiNetworkAgent.connect(true);
5691 
5692         vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
5693                 && !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
5694                 && caps.hasCapability(NET_CAPABILITY_NOT_METERED),
5695                 vpnNetworkAgent);
5696 
5697         // Disconnect Cell. The default network did not change, so there shouldn't be any changes in
5698         // the capabilities.
5699         mCellNetworkAgent.disconnect();
5700 
5701         // Disconnect wifi too. Now we have no default network.
5702         mWiFiNetworkAgent.disconnect();
5703 
5704         vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
5705                 && !caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
5706                 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
5707                 vpnNetworkAgent);
5708 
5709         mMockVpn.disconnect();
5710     }
5711 
5712     @Test
testIsActiveNetworkMeteredOverWifi()5713     public void testIsActiveNetworkMeteredOverWifi() {
5714         // Returns true by default when no network is available.
5715         assertTrue(mCm.isActiveNetworkMetered());
5716         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
5717         mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5718         mWiFiNetworkAgent.connect(true);
5719         waitForIdle();
5720 
5721         assertFalse(mCm.isActiveNetworkMetered());
5722     }
5723 
5724     @Test
testIsActiveNetworkMeteredOverCell()5725     public void testIsActiveNetworkMeteredOverCell() {
5726         // Returns true by default when no network is available.
5727         assertTrue(mCm.isActiveNetworkMetered());
5728         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
5729         mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
5730         mCellNetworkAgent.connect(true);
5731         waitForIdle();
5732 
5733         assertTrue(mCm.isActiveNetworkMetered());
5734     }
5735 
5736     @Test
testIsActiveNetworkMeteredOverVpnTrackingPlatformDefault()5737     public void testIsActiveNetworkMeteredOverVpnTrackingPlatformDefault() {
5738         // Returns true by default when no network is available.
5739         assertTrue(mCm.isActiveNetworkMetered());
5740         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
5741         mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
5742         mCellNetworkAgent.connect(true);
5743         waitForIdle();
5744         assertTrue(mCm.isActiveNetworkMetered());
5745 
5746         // Connect VPN network. By default it is using current default network (Cell).
5747         MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
5748         final ArraySet<UidRange> ranges = new ArraySet<>();
5749         final int uid = Process.myUid();
5750         ranges.add(new UidRange(uid, uid));
5751         mMockVpn.setNetworkAgent(vpnNetworkAgent);
5752         mMockVpn.setUids(ranges);
5753         vpnNetworkAgent.connect(true);
5754         mMockVpn.connect();
5755         waitForIdle();
5756         // Ensure VPN is now the active network.
5757         assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
5758 
5759         // Expect VPN to be metered.
5760         assertTrue(mCm.isActiveNetworkMetered());
5761 
5762         // Connect WiFi.
5763         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
5764         mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5765         mWiFiNetworkAgent.connect(true);
5766         waitForIdle();
5767         // VPN should still be the active network.
5768         assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
5769 
5770         // Expect VPN to be unmetered as it should now be using WiFi (new default).
5771         assertFalse(mCm.isActiveNetworkMetered());
5772 
5773         // Disconnecting Cell should not affect VPN's meteredness.
5774         mCellNetworkAgent.disconnect();
5775         waitForIdle();
5776 
5777         assertFalse(mCm.isActiveNetworkMetered());
5778 
5779         // Disconnect WiFi; Now there is no platform default network.
5780         mWiFiNetworkAgent.disconnect();
5781         waitForIdle();
5782 
5783         // VPN without any underlying networks is treated as metered.
5784         assertTrue(mCm.isActiveNetworkMetered());
5785 
5786         vpnNetworkAgent.disconnect();
5787         mMockVpn.disconnect();
5788     }
5789 
5790    @Test
testIsActiveNetworkMeteredOverVpnSpecifyingUnderlyingNetworks()5791    public void testIsActiveNetworkMeteredOverVpnSpecifyingUnderlyingNetworks() {
5792         // Returns true by default when no network is available.
5793         assertTrue(mCm.isActiveNetworkMetered());
5794         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
5795         mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
5796         mCellNetworkAgent.connect(true);
5797         waitForIdle();
5798         assertTrue(mCm.isActiveNetworkMetered());
5799 
5800         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
5801         mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5802         mWiFiNetworkAgent.connect(true);
5803         waitForIdle();
5804         assertFalse(mCm.isActiveNetworkMetered());
5805 
5806         // Connect VPN network.
5807         MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
5808         final ArraySet<UidRange> ranges = new ArraySet<>();
5809         final int uid = Process.myUid();
5810         ranges.add(new UidRange(uid, uid));
5811         mMockVpn.setNetworkAgent(vpnNetworkAgent);
5812         mMockVpn.setUids(ranges);
5813         vpnNetworkAgent.connect(true);
5814         mMockVpn.connect();
5815         waitForIdle();
5816         // Ensure VPN is now the active network.
5817         assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
5818         // VPN is using Cell
5819         mService.setUnderlyingNetworksForVpn(
5820                 new Network[] { mCellNetworkAgent.getNetwork() });
5821         waitForIdle();
5822 
5823         // Expect VPN to be metered.
5824         assertTrue(mCm.isActiveNetworkMetered());
5825 
5826         // VPN is now using WiFi
5827         mService.setUnderlyingNetworksForVpn(
5828                 new Network[] { mWiFiNetworkAgent.getNetwork() });
5829         waitForIdle();
5830 
5831         // Expect VPN to be unmetered
5832         assertFalse(mCm.isActiveNetworkMetered());
5833 
5834         // VPN is using Cell | WiFi.
5835         mService.setUnderlyingNetworksForVpn(
5836                 new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() });
5837         waitForIdle();
5838 
5839         // Expect VPN to be metered.
5840         assertTrue(mCm.isActiveNetworkMetered());
5841 
5842         // VPN is using WiFi | Cell.
5843         mService.setUnderlyingNetworksForVpn(
5844                 new Network[] { mWiFiNetworkAgent.getNetwork(), mCellNetworkAgent.getNetwork() });
5845         waitForIdle();
5846 
5847         // Order should not matter and VPN should still be metered.
5848         assertTrue(mCm.isActiveNetworkMetered());
5849 
5850         // VPN is not using any underlying networks.
5851         mService.setUnderlyingNetworksForVpn(new Network[0]);
5852         waitForIdle();
5853 
5854         // VPN without underlying networks is treated as metered.
5855         assertTrue(mCm.isActiveNetworkMetered());
5856 
5857         vpnNetworkAgent.disconnect();
5858         mMockVpn.disconnect();
5859     }
5860 
5861     @Test
testIsActiveNetworkMeteredOverAlwaysMeteredVpn()5862     public void testIsActiveNetworkMeteredOverAlwaysMeteredVpn() {
5863         // Returns true by default when no network is available.
5864         assertTrue(mCm.isActiveNetworkMetered());
5865         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
5866         mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5867         mWiFiNetworkAgent.connect(true);
5868         waitForIdle();
5869         assertFalse(mCm.isActiveNetworkMetered());
5870 
5871         // Connect VPN network.
5872         MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
5873         final ArraySet<UidRange> ranges = new ArraySet<>();
5874         final int uid = Process.myUid();
5875         ranges.add(new UidRange(uid, uid));
5876         mMockVpn.setNetworkAgent(vpnNetworkAgent);
5877         mMockVpn.setUids(ranges);
5878         vpnNetworkAgent.connect(true);
5879         mMockVpn.connectAsAlwaysMetered();
5880         waitForIdle();
5881         assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
5882 
5883         // VPN is tracking current platform default (WiFi).
5884         mService.setUnderlyingNetworksForVpn(null);
5885         waitForIdle();
5886 
5887         // Despite VPN using WiFi (which is unmetered), VPN itself is marked as always metered.
5888         assertTrue(mCm.isActiveNetworkMetered());
5889 
5890         // VPN explicitly declares WiFi as its underlying network.
5891         mService.setUnderlyingNetworksForVpn(
5892                 new Network[] { mWiFiNetworkAgent.getNetwork() });
5893         waitForIdle();
5894 
5895         // Doesn't really matter whether VPN declares its underlying networks explicitly.
5896         assertTrue(mCm.isActiveNetworkMetered());
5897 
5898         // With WiFi lost, VPN is basically without any underlying networks. And in that case it is
5899         // anyways suppose to be metered.
5900         mWiFiNetworkAgent.disconnect();
5901         waitForIdle();
5902 
5903         assertTrue(mCm.isActiveNetworkMetered());
5904 
5905         vpnNetworkAgent.disconnect();
5906     }
5907 
5908     @Test
testNetworkBlockedStatus()5909     public void testNetworkBlockedStatus() {
5910         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
5911         final NetworkRequest cellRequest = new NetworkRequest.Builder()
5912                 .addTransportType(TRANSPORT_CELLULAR)
5913                 .build();
5914         mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
5915 
5916         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
5917         mCellNetworkAgent.connect(true);
5918         cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
5919 
5920         mService.setUidRulesChanged(RULE_REJECT_ALL);
5921         cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
5922 
5923         // ConnectivityService should cache it not to invoke the callback again.
5924         mService.setUidRulesChanged(RULE_REJECT_METERED);
5925         cellNetworkCallback.assertNoCallback();
5926 
5927         mService.setUidRulesChanged(RULE_NONE);
5928         cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
5929 
5930         mService.setUidRulesChanged(RULE_REJECT_METERED);
5931         cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
5932 
5933         // Restrict the network based on UID rule and NOT_METERED capability change.
5934         mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5935         cellNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_NOT_METERED, mCellNetworkAgent);
5936         cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
5937         mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
5938         cellNetworkCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_METERED,
5939                 mCellNetworkAgent);
5940         cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
5941         mService.setUidRulesChanged(RULE_ALLOW_METERED);
5942         cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
5943 
5944         mService.setUidRulesChanged(RULE_NONE);
5945         cellNetworkCallback.assertNoCallback();
5946 
5947         // Restrict the network based on BackgroundRestricted.
5948         mService.setRestrictBackgroundChanged(true);
5949         cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
5950         mService.setRestrictBackgroundChanged(true);
5951         cellNetworkCallback.assertNoCallback();
5952         mService.setRestrictBackgroundChanged(false);
5953         cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
5954         cellNetworkCallback.assertNoCallback();
5955 
5956         mCm.unregisterNetworkCallback(cellNetworkCallback);
5957     }
5958 
5959     @Test
testNetworkBlockedStatusBeforeAndAfterConnect()5960     public void testNetworkBlockedStatusBeforeAndAfterConnect() {
5961         final TestNetworkCallback defaultCallback = new TestNetworkCallback();
5962         mCm.registerDefaultNetworkCallback(defaultCallback);
5963 
5964         // No Networkcallbacks invoked before any network is active.
5965         mService.setUidRulesChanged(RULE_REJECT_ALL);
5966         mService.setUidRulesChanged(RULE_NONE);
5967         mService.setUidRulesChanged(RULE_REJECT_METERED);
5968         defaultCallback.assertNoCallback();
5969 
5970         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
5971         mCellNetworkAgent.connect(true);
5972         defaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mCellNetworkAgent);
5973         defaultCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mCellNetworkAgent);
5974 
5975         // Allow to use the network after switching to NOT_METERED network.
5976         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
5977         mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5978         mWiFiNetworkAgent.connect(true);
5979         defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
5980 
5981         // Switch to METERED network. Restrict the use of the network.
5982         mWiFiNetworkAgent.disconnect();
5983         defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
5984         defaultCallback.expectAvailableCallbacksValidatedAndBlocked(mCellNetworkAgent);
5985 
5986         // Network becomes NOT_METERED.
5987         mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5988         defaultCallback.expectCapabilitiesWith(NET_CAPABILITY_NOT_METERED, mCellNetworkAgent);
5989         defaultCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
5990 
5991         // Verify there's no Networkcallbacks invoked after data saver on/off.
5992         mService.setRestrictBackgroundChanged(true);
5993         mService.setRestrictBackgroundChanged(false);
5994         defaultCallback.assertNoCallback();
5995 
5996         mCellNetworkAgent.disconnect();
5997         defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
5998         defaultCallback.assertNoCallback();
5999 
6000         mCm.unregisterNetworkCallback(defaultCallback);
6001     }
6002 
6003     /**
6004      * Make simulated InterfaceConfig for Nat464Xlat to query clat lower layer info.
6005      */
getClatInterfaceConfig(LinkAddress la)6006     private InterfaceConfiguration getClatInterfaceConfig(LinkAddress la) {
6007         InterfaceConfiguration cfg = new InterfaceConfiguration();
6008         cfg.setHardwareAddress("11:22:33:44:55:66");
6009         cfg.setLinkAddress(la);
6010         return cfg;
6011     }
6012 
6013     /**
6014      * Make expected stack link properties, copied from Nat464Xlat.
6015      */
makeClatLinkProperties(LinkAddress la)6016     private LinkProperties makeClatLinkProperties(LinkAddress la) {
6017         LinkAddress clatAddress = la;
6018         LinkProperties stacked = new LinkProperties();
6019         stacked.setInterfaceName(CLAT_PREFIX + MOBILE_IFNAME);
6020         RouteInfo ipv4Default = new RouteInfo(
6021                 new LinkAddress(Inet4Address.ANY, 0),
6022                 clatAddress.getAddress(), CLAT_PREFIX + MOBILE_IFNAME);
6023         stacked.addRoute(ipv4Default);
6024         stacked.addLinkAddress(clatAddress);
6025         return stacked;
6026     }
6027 
6028     @Test
testStackedLinkProperties()6029     public void testStackedLinkProperties() throws UnknownHostException, RemoteException {
6030         final LinkAddress myIpv4 = new LinkAddress("1.2.3.4/24");
6031         final LinkAddress myIpv6 = new LinkAddress("2001:db8:1::1/64");
6032         final String kNat64PrefixString = "2001:db8:64:64:64:64::";
6033         final IpPrefix kNat64Prefix = new IpPrefix(InetAddress.getByName(kNat64PrefixString), 96);
6034 
6035         final NetworkRequest networkRequest = new NetworkRequest.Builder()
6036                 .addTransportType(TRANSPORT_CELLULAR)
6037                 .addCapability(NET_CAPABILITY_INTERNET)
6038                 .build();
6039         final TestNetworkCallback networkCallback = new TestNetworkCallback();
6040         mCm.registerNetworkCallback(networkRequest, networkCallback);
6041 
6042         // Prepare ipv6 only link properties.
6043         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
6044         final int cellNetId = mCellNetworkAgent.getNetwork().netId;
6045         final LinkProperties cellLp = new LinkProperties();
6046         cellLp.setInterfaceName(MOBILE_IFNAME);
6047         cellLp.addLinkAddress(myIpv6);
6048         cellLp.addRoute(new RouteInfo((IpPrefix) null, myIpv6.getAddress(), MOBILE_IFNAME));
6049         cellLp.addRoute(new RouteInfo(myIpv6, null, MOBILE_IFNAME));
6050         reset(mNetworkManagementService);
6051         reset(mMockDnsResolver);
6052         reset(mMockNetd);
6053         when(mNetworkManagementService.getInterfaceConfig(CLAT_PREFIX + MOBILE_IFNAME))
6054                 .thenReturn(getClatInterfaceConfig(myIpv4));
6055 
6056         // Connect with ipv6 link properties. Expect prefix discovery to be started.
6057         mCellNetworkAgent.sendLinkProperties(cellLp);
6058         mCellNetworkAgent.connect(true);
6059 
6060         verify(mMockNetd, times(1)).networkCreatePhysical(eq(cellNetId), anyInt());
6061         verify(mMockDnsResolver, times(1)).createNetworkCache(eq(cellNetId));
6062 
6063         networkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
6064         verify(mMockDnsResolver, times(1)).startPrefix64Discovery(cellNetId);
6065 
6066         // Switching default network updates TCP buffer sizes.
6067         verifyTcpBufferSizeChange(ConnectivityService.DEFAULT_TCP_BUFFER_SIZES);
6068 
6069         // Add an IPv4 address. Expect prefix discovery to be stopped. Netd doesn't tell us that
6070         // the NAT64 prefix was removed because one was never discovered.
6071         cellLp.addLinkAddress(myIpv4);
6072         mCellNetworkAgent.sendLinkProperties(cellLp);
6073         networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
6074         verify(mMockDnsResolver, times(1)).stopPrefix64Discovery(cellNetId);
6075         verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(any());
6076 
6077         verifyNoMoreInteractions(mMockNetd);
6078         verifyNoMoreInteractions(mMockDnsResolver);
6079         reset(mMockNetd);
6080         reset(mMockDnsResolver);
6081 
6082         // Remove IPv4 address. Expect prefix discovery to be started again.
6083         cellLp.removeLinkAddress(myIpv4);
6084         cellLp.removeRoute(new RouteInfo(myIpv4, null, MOBILE_IFNAME));
6085         mCellNetworkAgent.sendLinkProperties(cellLp);
6086         networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
6087         verify(mMockDnsResolver, times(1)).startPrefix64Discovery(cellNetId);
6088 
6089         // When NAT64 prefix discovery succeeds, LinkProperties are updated and clatd is started.
6090         Nat464Xlat clat = mService.getNat464Xlat(mCellNetworkAgent);
6091         assertNull(mCm.getLinkProperties(mCellNetworkAgent.getNetwork()).getNat64Prefix());
6092         mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, true /* added */,
6093                 kNat64PrefixString, 96);
6094         LinkProperties lpBeforeClat = (LinkProperties) networkCallback.expectCallback(
6095                 CallbackState.LINK_PROPERTIES, mCellNetworkAgent).arg;
6096         assertEquals(0, lpBeforeClat.getStackedLinks().size());
6097         assertEquals(kNat64Prefix, lpBeforeClat.getNat64Prefix());
6098         verify(mMockNetd, times(1)).clatdStart(MOBILE_IFNAME, kNat64Prefix.toString());
6099 
6100         // Clat iface comes up. Expect stacked link to be added.
6101         clat.interfaceLinkStateChanged(CLAT_PREFIX + MOBILE_IFNAME, true);
6102         networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
6103         List<LinkProperties> stackedLps = mCm.getLinkProperties(mCellNetworkAgent.getNetwork())
6104                 .getStackedLinks();
6105         assertEquals(makeClatLinkProperties(myIpv4), stackedLps.get(0));
6106 
6107         // Change trivial linkproperties and see if stacked link is preserved.
6108         cellLp.addDnsServer(InetAddress.getByName("8.8.8.8"));
6109         mCellNetworkAgent.sendLinkProperties(cellLp);
6110         networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
6111 
6112         List<LinkProperties> stackedLpsAfterChange =
6113                 mCm.getLinkProperties(mCellNetworkAgent.getNetwork()).getStackedLinks();
6114         assertNotEquals(stackedLpsAfterChange, Collections.EMPTY_LIST);
6115         assertEquals(makeClatLinkProperties(myIpv4), stackedLpsAfterChange.get(0));
6116 
6117         verify(mMockDnsResolver, times(1)).setResolverConfiguration(
6118                 mResolverParamsParcelCaptor.capture());
6119         ResolverParamsParcel resolvrParams = mResolverParamsParcelCaptor.getValue();
6120         assertEquals(1, resolvrParams.servers.length);
6121         assertTrue(ArrayUtils.contains(resolvrParams.servers, "8.8.8.8"));
6122 
6123         // Add ipv4 address, expect that clatd and prefix discovery are stopped and stacked
6124         // linkproperties are cleaned up.
6125         cellLp.addLinkAddress(myIpv4);
6126         cellLp.addRoute(new RouteInfo(myIpv4, null, MOBILE_IFNAME));
6127         mCellNetworkAgent.sendLinkProperties(cellLp);
6128         networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
6129         verify(mMockNetd, times(1)).clatdStop(MOBILE_IFNAME);
6130         verify(mMockDnsResolver, times(1)).stopPrefix64Discovery(cellNetId);
6131 
6132         // As soon as stop is called, the linkproperties lose the stacked interface.
6133         networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
6134         LinkProperties actualLpAfterIpv4 = mCm.getLinkProperties(mCellNetworkAgent.getNetwork());
6135         LinkProperties expected = new LinkProperties(cellLp);
6136         expected.setNat64Prefix(kNat64Prefix);
6137         assertEquals(expected, actualLpAfterIpv4);
6138         assertEquals(0, actualLpAfterIpv4.getStackedLinks().size());
6139 
6140         // The interface removed callback happens but has no effect after stop is called.
6141         clat.interfaceRemoved(CLAT_PREFIX + MOBILE_IFNAME);
6142         networkCallback.assertNoCallback();
6143 
6144         verifyNoMoreInteractions(mMockNetd);
6145         verifyNoMoreInteractions(mMockDnsResolver);
6146         reset(mMockNetd);
6147         reset(mMockDnsResolver);
6148 
6149         // Stopping prefix discovery causes netd to tell us that the NAT64 prefix is gone.
6150         mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, false /* added */,
6151                 kNat64PrefixString, 96);
6152         networkCallback.expectLinkPropertiesLike((lp) -> lp.getNat64Prefix() == null,
6153                 mCellNetworkAgent);
6154 
6155         // Remove IPv4 address and expect prefix discovery and clatd to be started again.
6156         cellLp.removeLinkAddress(myIpv4);
6157         cellLp.removeRoute(new RouteInfo(myIpv4, null, MOBILE_IFNAME));
6158         cellLp.removeDnsServer(InetAddress.getByName("8.8.8.8"));
6159         mCellNetworkAgent.sendLinkProperties(cellLp);
6160         networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
6161         verify(mMockDnsResolver, times(1)).startPrefix64Discovery(cellNetId);
6162         mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, true /* added */,
6163                 kNat64PrefixString, 96);
6164         networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
6165         verify(mMockNetd, times(1)).clatdStart(MOBILE_IFNAME, kNat64Prefix.toString());
6166 
6167 
6168         // Clat iface comes up. Expect stacked link to be added.
6169         clat.interfaceLinkStateChanged(CLAT_PREFIX + MOBILE_IFNAME, true);
6170         networkCallback.expectLinkPropertiesLike(
6171                 (lp) -> lp.getStackedLinks().size() == 1 && lp.getNat64Prefix() != null,
6172                 mCellNetworkAgent);
6173 
6174         // NAT64 prefix is removed. Expect that clat is stopped.
6175         mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, false /* added */,
6176                 kNat64PrefixString, 96);
6177         networkCallback.expectLinkPropertiesLike(
6178                 (lp) -> lp.getStackedLinks().size() == 0 && lp.getNat64Prefix() == null,
6179                 mCellNetworkAgent);
6180         verify(mMockNetd, times(1)).clatdStop(MOBILE_IFNAME);
6181         networkCallback.expectLinkPropertiesLike((lp) -> lp.getStackedLinks().size() == 0,
6182                 mCellNetworkAgent);
6183 
6184         // Clean up.
6185         mCellNetworkAgent.disconnect();
6186         networkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
6187         networkCallback.assertNoCallback();
6188         mCm.unregisterNetworkCallback(networkCallback);
6189     }
6190 
6191     @Test
testDataActivityTracking()6192     public void testDataActivityTracking() throws RemoteException {
6193         final TestNetworkCallback networkCallback = new TestNetworkCallback();
6194         final NetworkRequest networkRequest = new NetworkRequest.Builder()
6195                 .addCapability(NET_CAPABILITY_INTERNET)
6196                 .build();
6197         mCm.registerNetworkCallback(networkRequest, networkCallback);
6198 
6199         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
6200         final LinkProperties cellLp = new LinkProperties();
6201         cellLp.setInterfaceName(MOBILE_IFNAME);
6202         mCellNetworkAgent.sendLinkProperties(cellLp);
6203         reset(mNetworkManagementService);
6204         mCellNetworkAgent.connect(true);
6205         networkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
6206         verify(mNetworkManagementService, times(1)).addIdleTimer(eq(MOBILE_IFNAME), anyInt(),
6207                 eq(ConnectivityManager.TYPE_MOBILE));
6208 
6209         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
6210         final LinkProperties wifiLp = new LinkProperties();
6211         wifiLp.setInterfaceName(WIFI_IFNAME);
6212         mWiFiNetworkAgent.sendLinkProperties(wifiLp);
6213 
6214         // Network switch
6215         reset(mNetworkManagementService);
6216         mWiFiNetworkAgent.connect(true);
6217         networkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
6218         networkCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
6219         networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
6220         verify(mNetworkManagementService, times(1)).addIdleTimer(eq(WIFI_IFNAME), anyInt(),
6221                 eq(ConnectivityManager.TYPE_WIFI));
6222         verify(mNetworkManagementService, times(1)).removeIdleTimer(eq(MOBILE_IFNAME));
6223 
6224         // Disconnect wifi and switch back to cell
6225         reset(mNetworkManagementService);
6226         mWiFiNetworkAgent.disconnect();
6227         networkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
6228         assertNoCallbacks(networkCallback);
6229         verify(mNetworkManagementService, times(1)).removeIdleTimer(eq(WIFI_IFNAME));
6230         verify(mNetworkManagementService, times(1)).addIdleTimer(eq(MOBILE_IFNAME), anyInt(),
6231                 eq(ConnectivityManager.TYPE_MOBILE));
6232 
6233         // reconnect wifi
6234         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
6235         wifiLp.setInterfaceName(WIFI_IFNAME);
6236         mWiFiNetworkAgent.sendLinkProperties(wifiLp);
6237         mWiFiNetworkAgent.connect(true);
6238         networkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
6239         networkCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
6240         networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
6241 
6242         // Disconnect cell
6243         reset(mNetworkManagementService);
6244         reset(mMockNetd);
6245         mCellNetworkAgent.disconnect();
6246         networkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
6247         // LOST callback is triggered earlier than removing idle timer. Broadcast should also be
6248         // sent as network being switched. Ensure rule removal for cell will not be triggered
6249         // unexpectedly before network being removed.
6250         waitForIdle();
6251         verify(mNetworkManagementService, times(0)).removeIdleTimer(eq(MOBILE_IFNAME));
6252         verify(mMockNetd, times(1)).networkDestroy(eq(mCellNetworkAgent.getNetwork().netId));
6253         verify(mMockDnsResolver, times(1))
6254                 .destroyNetworkCache(eq(mCellNetworkAgent.getNetwork().netId));
6255 
6256         // Disconnect wifi
6257         ConditionVariable cv = waitForConnectivityBroadcasts(1);
6258         reset(mNetworkManagementService);
6259         mWiFiNetworkAgent.disconnect();
6260         waitFor(cv);
6261         verify(mNetworkManagementService, times(1)).removeIdleTimer(eq(WIFI_IFNAME));
6262 
6263         // Clean up
6264         mCm.unregisterNetworkCallback(networkCallback);
6265     }
6266 
verifyTcpBufferSizeChange(String tcpBufferSizes)6267     private void verifyTcpBufferSizeChange(String tcpBufferSizes) {
6268         String[] values = tcpBufferSizes.split(",");
6269         String rmemValues = String.join(" ", values[0], values[1], values[2]);
6270         String wmemValues = String.join(" ", values[3], values[4], values[5]);
6271         waitForIdle();
6272         try {
6273             verify(mMockNetd, atLeastOnce()).setTcpRWmemorySize(rmemValues, wmemValues);
6274         } catch (RemoteException e) {
6275             fail("mMockNetd should never throw RemoteException");
6276         }
6277         reset(mMockNetd);
6278     }
6279 
6280     @Test
testTcpBufferReset()6281     public void testTcpBufferReset() {
6282         final String testTcpBufferSizes = "1,2,3,4,5,6";
6283 
6284         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
6285         reset(mMockNetd);
6286         // Switching default network updates TCP buffer sizes.
6287         mCellNetworkAgent.connect(false);
6288         verifyTcpBufferSizeChange(ConnectivityService.DEFAULT_TCP_BUFFER_SIZES);
6289 
6290         // Change link Properties should have updated tcp buffer size.
6291         LinkProperties lp = new LinkProperties();
6292         lp.setTcpBufferSizes(testTcpBufferSizes);
6293         mCellNetworkAgent.sendLinkProperties(lp);
6294         verifyTcpBufferSizeChange(testTcpBufferSizes);
6295     }
6296 
6297     @Test
testGetGlobalProxyForNetwork()6298     public void testGetGlobalProxyForNetwork() {
6299         final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
6300         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
6301         final Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
6302         when(mService.mProxyTracker.getGlobalProxy()).thenReturn(testProxyInfo);
6303         assertEquals(testProxyInfo, mService.getProxyForNetwork(wifiNetwork));
6304     }
6305 
6306     @Test
testGetProxyForActiveNetwork()6307     public void testGetProxyForActiveNetwork() {
6308         final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
6309         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
6310         mWiFiNetworkAgent.connect(true);
6311         waitForIdle();
6312         assertNull(mService.getProxyForNetwork(null));
6313 
6314         final LinkProperties testLinkProperties = new LinkProperties();
6315         testLinkProperties.setHttpProxy(testProxyInfo);
6316 
6317         mWiFiNetworkAgent.sendLinkProperties(testLinkProperties);
6318         waitForIdle();
6319 
6320         assertEquals(testProxyInfo, mService.getProxyForNetwork(null));
6321     }
6322 
6323     @Test
testGetProxyForVPN()6324     public void testGetProxyForVPN() {
6325         final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
6326 
6327         // Set up a WiFi network with no proxy
6328         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
6329         mWiFiNetworkAgent.connect(true);
6330         waitForIdle();
6331         assertNull(mService.getProxyForNetwork(null));
6332 
6333         // Set up a VPN network with a proxy
6334         final int uid = Process.myUid();
6335         final MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
6336         final ArraySet<UidRange> ranges = new ArraySet<>();
6337         ranges.add(new UidRange(uid, uid));
6338         mMockVpn.setUids(ranges);
6339         LinkProperties testLinkProperties = new LinkProperties();
6340         testLinkProperties.setHttpProxy(testProxyInfo);
6341         vpnNetworkAgent.sendLinkProperties(testLinkProperties);
6342         waitForIdle();
6343 
6344         // Connect to VPN with proxy
6345         mMockVpn.setNetworkAgent(vpnNetworkAgent);
6346         vpnNetworkAgent.connect(true);
6347         mMockVpn.connect();
6348         waitForIdle();
6349 
6350         // Test that the VPN network returns a proxy, and the WiFi does not.
6351         assertEquals(testProxyInfo, mService.getProxyForNetwork(vpnNetworkAgent.getNetwork()));
6352         assertEquals(testProxyInfo, mService.getProxyForNetwork(null));
6353         assertNull(mService.getProxyForNetwork(mWiFiNetworkAgent.getNetwork()));
6354 
6355         // Test that the VPN network returns no proxy when it is set to null.
6356         testLinkProperties.setHttpProxy(null);
6357         vpnNetworkAgent.sendLinkProperties(testLinkProperties);
6358         waitForIdle();
6359         assertNull(mService.getProxyForNetwork(vpnNetworkAgent.getNetwork()));
6360         assertNull(mService.getProxyForNetwork(null));
6361 
6362         // Set WiFi proxy and check that the vpn proxy is still null.
6363         testLinkProperties.setHttpProxy(testProxyInfo);
6364         mWiFiNetworkAgent.sendLinkProperties(testLinkProperties);
6365         waitForIdle();
6366         assertNull(mService.getProxyForNetwork(null));
6367 
6368         // Disconnect from VPN and check that the active network, which is now the WiFi, has the
6369         // correct proxy setting.
6370         vpnNetworkAgent.disconnect();
6371         waitForIdle();
6372         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
6373         assertEquals(testProxyInfo, mService.getProxyForNetwork(mWiFiNetworkAgent.getNetwork()));
6374         assertEquals(testProxyInfo, mService.getProxyForNetwork(null));
6375     }
6376 
6377     @Test
testFullyRoutedVpnResultsInInterfaceFilteringRules()6378     public void testFullyRoutedVpnResultsInInterfaceFilteringRules() throws Exception {
6379         LinkProperties lp = new LinkProperties();
6380         lp.setInterfaceName("tun0");
6381         lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
6382         // The uid range needs to cover the test app so the network is visible to it.
6383         final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(VPN_USER));
6384         final MockNetworkAgent vpnNetworkAgent = establishVpn(lp, VPN_UID, vpnRange);
6385 
6386         // Connected VPN should have interface rules set up. There are two expected invocations,
6387         // one during VPN uid update, one during VPN LinkProperties update
6388         ArgumentCaptor<int[]> uidCaptor = ArgumentCaptor.forClass(int[].class);
6389         verify(mMockNetd, times(2)).firewallAddUidInterfaceRules(eq("tun0"), uidCaptor.capture());
6390         assertContainsExactly(uidCaptor.getAllValues().get(0), APP1_UID, APP2_UID);
6391         assertContainsExactly(uidCaptor.getAllValues().get(1), APP1_UID, APP2_UID);
6392         assertTrue(mService.mPermissionMonitor.getVpnUidRanges("tun0").equals(vpnRange));
6393 
6394         vpnNetworkAgent.disconnect();
6395         waitForIdle();
6396 
6397         // Disconnected VPN should have interface rules removed
6398         verify(mMockNetd).firewallRemoveUidInterfaceRules(uidCaptor.capture());
6399         assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
6400         assertNull(mService.mPermissionMonitor.getVpnUidRanges("tun0"));
6401     }
6402 
6403     @Test
testLegacyVpnDoesNotResultInInterfaceFilteringRule()6404     public void testLegacyVpnDoesNotResultInInterfaceFilteringRule() throws Exception {
6405         LinkProperties lp = new LinkProperties();
6406         lp.setInterfaceName("tun0");
6407         lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
6408         // The uid range needs to cover the test app so the network is visible to it.
6409         final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(VPN_USER));
6410         final MockNetworkAgent vpnNetworkAgent = establishVpn(lp, Process.SYSTEM_UID, vpnRange);
6411 
6412         // Legacy VPN should not have interface rules set up
6413         verify(mMockNetd, never()).firewallAddUidInterfaceRules(any(), any());
6414     }
6415 
6416     @Test
testLocalIpv4OnlyVpnDoesNotResultInInterfaceFilteringRule()6417     public void testLocalIpv4OnlyVpnDoesNotResultInInterfaceFilteringRule()
6418             throws Exception {
6419         LinkProperties lp = new LinkProperties();
6420         lp.setInterfaceName("tun0");
6421         lp.addRoute(new RouteInfo(new IpPrefix("192.0.2.0/24"), null, "tun0"));
6422         lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), RTN_UNREACHABLE));
6423         // The uid range needs to cover the test app so the network is visible to it.
6424         final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(VPN_USER));
6425         final MockNetworkAgent vpnNetworkAgent = establishVpn(lp, Process.SYSTEM_UID, vpnRange);
6426 
6427         // IPv6 unreachable route should not be misinterpreted as a default route
6428         verify(mMockNetd, never()).firewallAddUidInterfaceRules(any(), any());
6429     }
6430 
6431     @Test
testVpnHandoverChangesInterfaceFilteringRule()6432     public void testVpnHandoverChangesInterfaceFilteringRule() throws Exception {
6433         LinkProperties lp = new LinkProperties();
6434         lp.setInterfaceName("tun0");
6435         lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
6436         // The uid range needs to cover the test app so the network is visible to it.
6437         final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(VPN_USER));
6438         final MockNetworkAgent vpnNetworkAgent = establishVpn(lp, VPN_UID, vpnRange);
6439 
6440         // Connected VPN should have interface rules set up. There are two expected invocations,
6441         // one during VPN uid update, one during VPN LinkProperties update
6442         ArgumentCaptor<int[]> uidCaptor = ArgumentCaptor.forClass(int[].class);
6443         verify(mMockNetd, times(2)).firewallAddUidInterfaceRules(eq("tun0"), uidCaptor.capture());
6444         assertContainsExactly(uidCaptor.getAllValues().get(0), APP1_UID, APP2_UID);
6445         assertContainsExactly(uidCaptor.getAllValues().get(1), APP1_UID, APP2_UID);
6446 
6447         reset(mMockNetd);
6448         InOrder inOrder = inOrder(mMockNetd);
6449         lp.setInterfaceName("tun1");
6450         vpnNetworkAgent.sendLinkProperties(lp);
6451         waitForIdle();
6452         // VPN handover (switch to a new interface) should result in rules being updated (old rules
6453         // removed first, then new rules added)
6454         inOrder.verify(mMockNetd).firewallRemoveUidInterfaceRules(uidCaptor.capture());
6455         assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
6456         inOrder.verify(mMockNetd).firewallAddUidInterfaceRules(eq("tun1"), uidCaptor.capture());
6457         assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
6458 
6459         reset(mMockNetd);
6460         lp = new LinkProperties();
6461         lp.setInterfaceName("tun1");
6462         lp.addRoute(new RouteInfo(new IpPrefix("192.0.2.0/24"), null, "tun1"));
6463         vpnNetworkAgent.sendLinkProperties(lp);
6464         waitForIdle();
6465         // VPN not routing everything should no longer have interface filtering rules
6466         verify(mMockNetd).firewallRemoveUidInterfaceRules(uidCaptor.capture());
6467         assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
6468 
6469         reset(mMockNetd);
6470         lp = new LinkProperties();
6471         lp.setInterfaceName("tun1");
6472         lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
6473         vpnNetworkAgent.sendLinkProperties(lp);
6474         waitForIdle();
6475         // Back to routing all IPv6 traffic should have filtering rules
6476         verify(mMockNetd).firewallAddUidInterfaceRules(eq("tun1"), uidCaptor.capture());
6477         assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
6478     }
6479 
6480     @Test
testUidUpdateChangesInterfaceFilteringRule()6481     public void testUidUpdateChangesInterfaceFilteringRule() throws Exception {
6482         LinkProperties lp = new LinkProperties();
6483         lp.setInterfaceName("tun0");
6484         lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
6485         // The uid range needs to cover the test app so the network is visible to it.
6486         final UidRange vpnRange = UidRange.createForUser(VPN_USER);
6487         final MockNetworkAgent vpnNetworkAgent = establishVpn(lp, VPN_UID,
6488                 Collections.singleton(vpnRange));
6489 
6490         reset(mMockNetd);
6491         InOrder inOrder = inOrder(mMockNetd);
6492 
6493         // Update to new range which is old range minus APP1, i.e. only APP2
6494         final Set<UidRange> newRanges = new HashSet<>(Arrays.asList(
6495                 new UidRange(vpnRange.start, APP1_UID - 1),
6496                 new UidRange(APP1_UID + 1, vpnRange.stop)));
6497         vpnNetworkAgent.setUids(newRanges);
6498         waitForIdle();
6499 
6500         ArgumentCaptor<int[]> uidCaptor = ArgumentCaptor.forClass(int[].class);
6501         // Verify old rules are removed before new rules are added
6502         inOrder.verify(mMockNetd).firewallRemoveUidInterfaceRules(uidCaptor.capture());
6503         assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
6504         inOrder.verify(mMockNetd).firewallAddUidInterfaceRules(eq("tun0"), uidCaptor.capture());
6505         assertContainsExactly(uidCaptor.getValue(), APP2_UID);
6506     }
6507 
6508 
establishVpn(LinkProperties lp, int establishingUid, Set<UidRange> vpnRange)6509     private MockNetworkAgent establishVpn(LinkProperties lp, int establishingUid,
6510             Set<UidRange> vpnRange) {
6511         final MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN, lp);
6512         vpnNetworkAgent.getNetworkCapabilities().setEstablishingVpnAppUid(establishingUid);
6513         mMockVpn.setNetworkAgent(vpnNetworkAgent);
6514         mMockVpn.connect();
6515         mMockVpn.setUids(vpnRange);
6516         vpnNetworkAgent.connect(true);
6517         waitForIdle();
6518         return vpnNetworkAgent;
6519     }
6520 
assertContainsExactly(int[] actual, int... expected)6521     private void assertContainsExactly(int[] actual, int... expected) {
6522         int[] sortedActual = Arrays.copyOf(actual, actual.length);
6523         int[] sortedExpected = Arrays.copyOf(expected, expected.length);
6524         Arrays.sort(sortedActual);
6525         Arrays.sort(sortedExpected);
6526         assertArrayEquals(sortedExpected, sortedActual);
6527     }
6528 
buildPackageInfo(boolean hasSystemPermission, int uid)6529     private static PackageInfo buildPackageInfo(boolean hasSystemPermission, int uid) {
6530         final PackageInfo packageInfo = new PackageInfo();
6531         packageInfo.requestedPermissions = new String[0];
6532         packageInfo.applicationInfo = new ApplicationInfo();
6533         packageInfo.applicationInfo.privateFlags = 0;
6534         packageInfo.applicationInfo.uid = UserHandle.getUid(UserHandle.USER_SYSTEM,
6535                 UserHandle.getAppId(uid));
6536         return packageInfo;
6537     }
6538 }
6539