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