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