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     /**
3058      * @return the context's attribution tag
3059      */
getAttributionTag()3060     private String getAttributionTag() {
3061         return null;
3062     }
3063 
3064     @Test
testInvalidNetworkSpecifier()3065     public void testInvalidNetworkSpecifier() {
3066         assertThrows(IllegalArgumentException.class, () -> {
3067             NetworkRequest.Builder builder = new NetworkRequest.Builder();
3068             builder.setNetworkSpecifier(new MatchAllNetworkSpecifier());
3069         });
3070 
3071         assertThrows(IllegalArgumentException.class, () -> {
3072             NetworkCapabilities networkCapabilities = new NetworkCapabilities();
3073             networkCapabilities.addTransportType(TRANSPORT_WIFI)
3074                     .setNetworkSpecifier(new MatchAllNetworkSpecifier());
3075             mService.requestNetwork(networkCapabilities, null, 0, null,
3076                     ConnectivityManager.TYPE_WIFI, mContext.getPackageName(),
3077                     getAttributionTag());
3078         });
3079 
3080         class NonParcelableSpecifier extends NetworkSpecifier {
3081             @Override
3082             public boolean canBeSatisfiedBy(NetworkSpecifier other) {
3083                 return false;
3084             }
3085         };
3086         class ParcelableSpecifier extends NonParcelableSpecifier implements Parcelable {
3087             @Override public int describeContents() { return 0; }
3088             @Override public void writeToParcel(Parcel p, int flags) {}
3089         }
3090 
3091         final NetworkRequest.Builder builder =
3092                 new NetworkRequest.Builder().addTransportType(TRANSPORT_ETHERNET);
3093         assertThrows(ClassCastException.class, () -> {
3094             builder.setNetworkSpecifier(new NonParcelableSpecifier());
3095             Parcel parcelW = Parcel.obtain();
3096             builder.build().writeToParcel(parcelW, 0);
3097         });
3098 
3099         final NetworkRequest nr =
3100                 new NetworkRequest.Builder().addTransportType(TRANSPORT_ETHERNET)
3101                 .setNetworkSpecifier(new ParcelableSpecifier())
3102                 .build();
3103         assertNotNull(nr);
3104 
3105         assertThrows(BadParcelableException.class, () -> {
3106             Parcel parcelW = Parcel.obtain();
3107             nr.writeToParcel(parcelW, 0);
3108             byte[] bytes = parcelW.marshall();
3109             parcelW.recycle();
3110 
3111             Parcel parcelR = Parcel.obtain();
3112             parcelR.unmarshall(bytes, 0, bytes.length);
3113             parcelR.setDataPosition(0);
3114             NetworkRequest rereadNr = NetworkRequest.CREATOR.createFromParcel(parcelR);
3115         });
3116     }
3117 
3118     @Test
testNetworkRequestUidSpoofSecurityException()3119     public void testNetworkRequestUidSpoofSecurityException() throws Exception {
3120         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3121         mWiFiNetworkAgent.connect(false);
3122         NetworkRequest networkRequest = newWifiRequestBuilder().build();
3123         TestNetworkCallback networkCallback = new TestNetworkCallback();
3124         doThrow(new SecurityException()).when(mAppOpsManager).checkPackage(anyInt(), anyString());
3125         assertThrows(SecurityException.class, () -> {
3126             mCm.requestNetwork(networkRequest, networkCallback);
3127         });
3128     }
3129 
3130     @Test
testInvalidSignalStrength()3131     public void testInvalidSignalStrength() {
3132         NetworkRequest r = new NetworkRequest.Builder()
3133                 .addCapability(NET_CAPABILITY_INTERNET)
3134                 .addTransportType(TRANSPORT_WIFI)
3135                 .setSignalStrength(-75)
3136                 .build();
3137         // Registering a NetworkCallback with signal strength but w/o NETWORK_SIGNAL_STRENGTH_WAKEUP
3138         // permission should get SecurityException.
3139         assertThrows(SecurityException.class, () ->
3140                 mCm.registerNetworkCallback(r, new NetworkCallback()));
3141 
3142         assertThrows(SecurityException.class, () ->
3143                 mCm.registerNetworkCallback(r, PendingIntent.getService(
3144                         mServiceContext, 0, new Intent(), 0)));
3145 
3146         // Requesting a Network with signal strength should get IllegalArgumentException.
3147         assertThrows(IllegalArgumentException.class, () ->
3148                 mCm.requestNetwork(r, new NetworkCallback()));
3149 
3150         assertThrows(IllegalArgumentException.class, () ->
3151                 mCm.requestNetwork(r, PendingIntent.getService(
3152                         mServiceContext, 0, new Intent(), 0)));
3153     }
3154 
3155     @Test
testRegisterDefaultNetworkCallback()3156     public void testRegisterDefaultNetworkCallback() throws Exception {
3157         final TestNetworkCallback defaultNetworkCallback = new TestNetworkCallback();
3158         mCm.registerDefaultNetworkCallback(defaultNetworkCallback);
3159         defaultNetworkCallback.assertNoCallback();
3160 
3161         // Create a TRANSPORT_CELLULAR request to keep the mobile interface up
3162         // whenever Wi-Fi is up. Without this, the mobile network agent is
3163         // reaped before any other activity can take place.
3164         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
3165         final NetworkRequest cellRequest = new NetworkRequest.Builder()
3166                 .addTransportType(TRANSPORT_CELLULAR).build();
3167         mCm.requestNetwork(cellRequest, cellNetworkCallback);
3168         cellNetworkCallback.assertNoCallback();
3169 
3170         // Bring up cell and expect CALLBACK_AVAILABLE.
3171         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
3172         mCellNetworkAgent.connect(true);
3173         cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
3174         defaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
3175         assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
3176 
3177         // Bring up wifi and expect CALLBACK_AVAILABLE.
3178         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3179         mWiFiNetworkAgent.connect(true);
3180         cellNetworkCallback.assertNoCallback();
3181         defaultNetworkCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
3182         assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
3183 
3184         // Bring down cell. Expect no default network callback, since it wasn't the default.
3185         mCellNetworkAgent.disconnect();
3186         cellNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
3187         defaultNetworkCallback.assertNoCallback();
3188         assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
3189 
3190         // Bring up cell. Expect no default network callback, since it won't be the default.
3191         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
3192         mCellNetworkAgent.connect(true);
3193         cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
3194         defaultNetworkCallback.assertNoCallback();
3195         assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
3196 
3197         // Bring down wifi. Expect the default network callback to notified of LOST wifi
3198         // followed by AVAILABLE cell.
3199         mWiFiNetworkAgent.disconnect();
3200         cellNetworkCallback.assertNoCallback();
3201         defaultNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
3202         defaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
3203         mCellNetworkAgent.disconnect();
3204         cellNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
3205         defaultNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
3206         waitForIdle();
3207         assertEquals(null, mCm.getActiveNetwork());
3208 
3209         final int uid = Process.myUid();
3210         final TestNetworkAgentWrapper
3211                 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
3212         final ArraySet<UidRange> ranges = new ArraySet<>();
3213         ranges.add(new UidRange(uid, uid));
3214         mMockVpn.setNetworkAgent(vpnNetworkAgent);
3215         mMockVpn.setUids(ranges);
3216         vpnNetworkAgent.connect(true);
3217         mMockVpn.connect();
3218         defaultNetworkCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
3219         assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
3220 
3221         vpnNetworkAgent.disconnect();
3222         defaultNetworkCallback.expectCallback(CallbackEntry.LOST, vpnNetworkAgent);
3223         waitForIdle();
3224         assertEquals(null, mCm.getActiveNetwork());
3225     }
3226 
3227     @Test
testAdditionalStateCallbacks()3228     public void testAdditionalStateCallbacks() throws Exception {
3229         // File a network request for mobile.
3230         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
3231         final NetworkRequest cellRequest = new NetworkRequest.Builder()
3232                 .addTransportType(TRANSPORT_CELLULAR).build();
3233         mCm.requestNetwork(cellRequest, cellNetworkCallback);
3234 
3235         // Bring up the mobile network.
3236         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
3237         mCellNetworkAgent.connect(true);
3238 
3239         // We should get onAvailable(), onCapabilitiesChanged(), and
3240         // onLinkPropertiesChanged() in rapid succession. Additionally, we
3241         // should get onCapabilitiesChanged() when the mobile network validates.
3242         cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
3243         cellNetworkCallback.assertNoCallback();
3244 
3245         // Update LinkProperties.
3246         final LinkProperties lp = new LinkProperties();
3247         lp.setInterfaceName("foonet_data0");
3248         mCellNetworkAgent.sendLinkProperties(lp);
3249         // We should get onLinkPropertiesChanged().
3250         cellNetworkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED,
3251                 mCellNetworkAgent);
3252         cellNetworkCallback.assertNoCallback();
3253 
3254         // Suspend the network.
3255         mCellNetworkAgent.suspend();
3256         cellNetworkCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_SUSPENDED,
3257                 mCellNetworkAgent);
3258         cellNetworkCallback.expectCallback(CallbackEntry.SUSPENDED, mCellNetworkAgent);
3259         cellNetworkCallback.assertNoCallback();
3260         assertEquals(NetworkInfo.State.SUSPENDED, mCm.getActiveNetworkInfo().getState());
3261 
3262         // Register a garden variety default network request.
3263         TestNetworkCallback dfltNetworkCallback = new TestNetworkCallback();
3264         mCm.registerDefaultNetworkCallback(dfltNetworkCallback);
3265         // We should get onAvailable(), onCapabilitiesChanged(), onLinkPropertiesChanged(),
3266         // as well as onNetworkSuspended() in rapid succession.
3267         dfltNetworkCallback.expectAvailableAndSuspendedCallbacks(mCellNetworkAgent, true);
3268         dfltNetworkCallback.assertNoCallback();
3269         mCm.unregisterNetworkCallback(dfltNetworkCallback);
3270 
3271         mCellNetworkAgent.resume();
3272         cellNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_NOT_SUSPENDED,
3273                 mCellNetworkAgent);
3274         cellNetworkCallback.expectCallback(CallbackEntry.RESUMED, mCellNetworkAgent);
3275         cellNetworkCallback.assertNoCallback();
3276         assertEquals(NetworkInfo.State.CONNECTED, mCm.getActiveNetworkInfo().getState());
3277 
3278         dfltNetworkCallback = new TestNetworkCallback();
3279         mCm.registerDefaultNetworkCallback(dfltNetworkCallback);
3280         // This time onNetworkSuspended should not be called.
3281         dfltNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
3282         dfltNetworkCallback.assertNoCallback();
3283 
3284         mCm.unregisterNetworkCallback(dfltNetworkCallback);
3285         mCm.unregisterNetworkCallback(cellNetworkCallback);
3286     }
3287 
setCaptivePortalMode(int mode)3288     private void setCaptivePortalMode(int mode) {
3289         ContentResolver cr = mServiceContext.getContentResolver();
3290         Settings.Global.putInt(cr, Settings.Global.CAPTIVE_PORTAL_MODE, mode);
3291     }
3292 
setAlwaysOnNetworks(boolean enable)3293     private void setAlwaysOnNetworks(boolean enable) {
3294         ContentResolver cr = mServiceContext.getContentResolver();
3295         Settings.Global.putInt(cr, Settings.Global.MOBILE_DATA_ALWAYS_ON, enable ? 1 : 0);
3296         mService.updateAlwaysOnNetworks();
3297         waitForIdle();
3298     }
3299 
setPrivateDnsSettings(String mode, String specifier)3300     private void setPrivateDnsSettings(String mode, String specifier) {
3301         final ContentResolver cr = mServiceContext.getContentResolver();
3302         Settings.Global.putString(cr, Settings.Global.PRIVATE_DNS_MODE, mode);
3303         Settings.Global.putString(cr, Settings.Global.PRIVATE_DNS_SPECIFIER, specifier);
3304         mService.updatePrivateDnsSettings();
3305         waitForIdle();
3306     }
3307 
isForegroundNetwork(TestNetworkAgentWrapper network)3308     private boolean isForegroundNetwork(TestNetworkAgentWrapper network) {
3309         NetworkCapabilities nc = mCm.getNetworkCapabilities(network.getNetwork());
3310         assertNotNull(nc);
3311         return nc.hasCapability(NET_CAPABILITY_FOREGROUND);
3312     }
3313 
3314     @Test
testBackgroundNetworks()3315     public void testBackgroundNetworks() throws Exception {
3316         // Create a background request. We can't do this ourselves because ConnectivityService
3317         // doesn't have an API for it. So just turn on mobile data always on.
3318         setAlwaysOnNetworks(true);
3319         grantUsingBackgroundNetworksPermissionForUid(Binder.getCallingUid());
3320         final NetworkRequest request = new NetworkRequest.Builder().build();
3321         final NetworkRequest fgRequest = new NetworkRequest.Builder()
3322                 .addCapability(NET_CAPABILITY_FOREGROUND).build();
3323         final TestNetworkCallback callback = new TestNetworkCallback();
3324         final TestNetworkCallback fgCallback = new TestNetworkCallback();
3325         mCm.registerNetworkCallback(request, callback);
3326         mCm.registerNetworkCallback(fgRequest, fgCallback);
3327 
3328         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
3329         mCellNetworkAgent.connect(true);
3330         callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
3331         fgCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
3332         assertTrue(isForegroundNetwork(mCellNetworkAgent));
3333 
3334         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3335         mWiFiNetworkAgent.connect(true);
3336 
3337         // When wifi connects, cell lingers.
3338         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
3339         callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
3340         callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
3341         fgCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
3342         fgCallback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
3343         fgCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
3344         assertTrue(isForegroundNetwork(mCellNetworkAgent));
3345         assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
3346 
3347         // When lingering is complete, cell is still there but is now in the background.
3348         waitForIdle();
3349         int timeoutMs = TEST_LINGER_DELAY_MS + TEST_LINGER_DELAY_MS / 4;
3350         fgCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent, timeoutMs);
3351         // Expect a network capabilities update sans FOREGROUND.
3352         callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
3353         assertFalse(isForegroundNetwork(mCellNetworkAgent));
3354         assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
3355 
3356         // File a cell request and check that cell comes into the foreground.
3357         final NetworkRequest cellRequest = new NetworkRequest.Builder()
3358                 .addTransportType(TRANSPORT_CELLULAR).build();
3359         final TestNetworkCallback cellCallback = new TestNetworkCallback();
3360         mCm.requestNetwork(cellRequest, cellCallback);
3361         cellCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
3362         fgCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
3363         // Expect a network capabilities update with FOREGROUND, because the most recent
3364         // request causes its state to change.
3365         cellCallback.expectCapabilitiesWith(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
3366         callback.expectCapabilitiesWith(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
3367         assertTrue(isForegroundNetwork(mCellNetworkAgent));
3368         assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
3369 
3370         // Release the request. The network immediately goes into the background, since it was not
3371         // lingering.
3372         mCm.unregisterNetworkCallback(cellCallback);
3373         fgCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
3374         // Expect a network capabilities update sans FOREGROUND.
3375         callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
3376         assertFalse(isForegroundNetwork(mCellNetworkAgent));
3377         assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
3378 
3379         // Disconnect wifi and check that cell is foreground again.
3380         mWiFiNetworkAgent.disconnect();
3381         callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
3382         fgCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
3383         fgCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
3384         assertTrue(isForegroundNetwork(mCellNetworkAgent));
3385 
3386         mCm.unregisterNetworkCallback(callback);
3387         mCm.unregisterNetworkCallback(fgCallback);
3388     }
3389 
3390     @Ignore // This test has instrinsic chances of spurious failures: ignore for continuous testing.
benchmarkRequestRegistrationAndCallbackDispatch()3391     public void benchmarkRequestRegistrationAndCallbackDispatch() throws Exception {
3392         // TODO: turn this unit test into a real benchmarking test.
3393         // Benchmarks connecting and switching performance in the presence of a large number of
3394         // NetworkRequests.
3395         // 1. File NUM_REQUESTS requests.
3396         // 2. Have a network connect. Wait for NUM_REQUESTS onAvailable callbacks to fire.
3397         // 3. Have a new network connect and outscore the previous. Wait for NUM_REQUESTS onLosing
3398         //    and NUM_REQUESTS onAvailable callbacks to fire.
3399         // See how long it took.
3400         final int NUM_REQUESTS = 90;
3401         final int REGISTER_TIME_LIMIT_MS = 200;
3402         final int CONNECT_TIME_LIMIT_MS = 60;
3403         final int SWITCH_TIME_LIMIT_MS = 60;
3404         final int UNREGISTER_TIME_LIMIT_MS = 20;
3405 
3406         final NetworkRequest request = new NetworkRequest.Builder().clearCapabilities().build();
3407         final NetworkCallback[] callbacks = new NetworkCallback[NUM_REQUESTS];
3408         final CountDownLatch availableLatch = new CountDownLatch(NUM_REQUESTS);
3409         final CountDownLatch losingLatch = new CountDownLatch(NUM_REQUESTS);
3410 
3411         for (int i = 0; i < NUM_REQUESTS; i++) {
3412             callbacks[i] = new NetworkCallback() {
3413                 @Override public void onAvailable(Network n) { availableLatch.countDown(); }
3414                 @Override public void onLosing(Network n, int t) { losingLatch.countDown(); }
3415             };
3416         }
3417 
3418         assertRunsInAtMost("Registering callbacks", REGISTER_TIME_LIMIT_MS, () -> {
3419             for (NetworkCallback cb : callbacks) {
3420                 mCm.registerNetworkCallback(request, cb);
3421             }
3422         });
3423 
3424         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
3425         // Don't request that the network validate, because otherwise connect() will block until
3426         // the network gets NET_CAPABILITY_VALIDATED, after all the callbacks below have fired,
3427         // and we won't actually measure anything.
3428         mCellNetworkAgent.connect(false);
3429 
3430         long onAvailableDispatchingDuration = durationOf(() -> {
3431             await(availableLatch, 10 * CONNECT_TIME_LIMIT_MS);
3432         });
3433         Log.d(TAG, String.format("Dispatched %d of %d onAvailable callbacks in %dms",
3434                 NUM_REQUESTS - availableLatch.getCount(), NUM_REQUESTS,
3435                 onAvailableDispatchingDuration));
3436         assertTrue(String.format("Dispatching %d onAvailable callbacks in %dms, expected %dms",
3437                 NUM_REQUESTS, onAvailableDispatchingDuration, CONNECT_TIME_LIMIT_MS),
3438                 onAvailableDispatchingDuration <= CONNECT_TIME_LIMIT_MS);
3439 
3440         // Give wifi a high enough score that we'll linger cell when wifi comes up.
3441         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3442         mWiFiNetworkAgent.adjustScore(40);
3443         mWiFiNetworkAgent.connect(false);
3444 
3445         long onLostDispatchingDuration = durationOf(() -> {
3446             await(losingLatch, 10 * SWITCH_TIME_LIMIT_MS);
3447         });
3448         Log.d(TAG, String.format("Dispatched %d of %d onLosing callbacks in %dms",
3449                 NUM_REQUESTS - losingLatch.getCount(), NUM_REQUESTS, onLostDispatchingDuration));
3450         assertTrue(String.format("Dispatching %d onLosing callbacks in %dms, expected %dms",
3451                 NUM_REQUESTS, onLostDispatchingDuration, SWITCH_TIME_LIMIT_MS),
3452                 onLostDispatchingDuration <= SWITCH_TIME_LIMIT_MS);
3453 
3454         assertRunsInAtMost("Unregistering callbacks", UNREGISTER_TIME_LIMIT_MS, () -> {
3455             for (NetworkCallback cb : callbacks) {
3456                 mCm.unregisterNetworkCallback(cb);
3457             }
3458         });
3459     }
3460 
3461     @Test
testMobileDataAlwaysOn()3462     public void testMobileDataAlwaysOn() throws Exception {
3463         grantUsingBackgroundNetworksPermissionForUid(Binder.getCallingUid());
3464         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
3465         final NetworkRequest cellRequest = new NetworkRequest.Builder()
3466                 .addTransportType(TRANSPORT_CELLULAR).build();
3467         mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
3468 
3469         final HandlerThread handlerThread = new HandlerThread("MobileDataAlwaysOnFactory");
3470         handlerThread.start();
3471         NetworkCapabilities filter = new NetworkCapabilities()
3472                 .addTransportType(TRANSPORT_CELLULAR)
3473                 .addCapability(NET_CAPABILITY_INTERNET);
3474         final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
3475                 mServiceContext, "testFactory", filter);
3476         testFactory.setScoreFilter(40);
3477 
3478         // Register the factory and expect it to start looking for a network.
3479         testFactory.expectAddRequestsWithScores(0);  // Score 0 as the request is not served yet.
3480         testFactory.register();
3481         testFactory.waitForNetworkRequests(1);
3482         assertTrue(testFactory.getMyStartRequested());
3483 
3484         // Bring up wifi. The factory stops looking for a network.
3485         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3486         // Score 60 - 40 penalty for not validated yet, then 60 when it validates
3487         testFactory.expectAddRequestsWithScores(20, 60);
3488         mWiFiNetworkAgent.connect(true);
3489         testFactory.waitForRequests();
3490         assertFalse(testFactory.getMyStartRequested());
3491 
3492         ContentResolver cr = mServiceContext.getContentResolver();
3493 
3494         // Turn on mobile data always on. The factory starts looking again.
3495         testFactory.expectAddRequestsWithScores(0);  // Always on requests comes up with score 0
3496         setAlwaysOnNetworks(true);
3497         testFactory.waitForNetworkRequests(2);
3498         assertTrue(testFactory.getMyStartRequested());
3499 
3500         // Bring up cell data and check that the factory stops looking.
3501         assertLength(1, mCm.getAllNetworks());
3502         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
3503         testFactory.expectAddRequestsWithScores(10, 50);  // Unvalidated, then validated
3504         mCellNetworkAgent.connect(true);
3505         cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
3506         testFactory.waitForNetworkRequests(2);
3507         assertFalse(testFactory.getMyStartRequested());  // Because the cell network outscores us.
3508 
3509         // Check that cell data stays up.
3510         waitForIdle();
3511         verifyActiveNetwork(TRANSPORT_WIFI);
3512         assertLength(2, mCm.getAllNetworks());
3513 
3514         // Turn off mobile data always on and expect the request to disappear...
3515         testFactory.expectRemoveRequests(1);
3516         setAlwaysOnNetworks(false);
3517         testFactory.waitForNetworkRequests(1);
3518 
3519         // ...  and cell data to be torn down.
3520         cellNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
3521         assertLength(1, mCm.getAllNetworks());
3522 
3523         testFactory.terminate();
3524         mCm.unregisterNetworkCallback(cellNetworkCallback);
3525         handlerThread.quit();
3526     }
3527 
3528     @Test
testAvoidBadWifiSetting()3529     public void testAvoidBadWifiSetting() throws Exception {
3530         final ContentResolver cr = mServiceContext.getContentResolver();
3531         final String settingName = Settings.Global.NETWORK_AVOID_BAD_WIFI;
3532 
3533         mPolicyTracker.mConfigRestrictsAvoidBadWifi = false;
3534         String[] values = new String[] {null, "0", "1"};
3535         for (int i = 0; i < values.length; i++) {
3536             Settings.Global.putInt(cr, settingName, 1);
3537             mPolicyTracker.reevaluate();
3538             waitForIdle();
3539             String msg = String.format("config=false, setting=%s", values[i]);
3540             assertTrue(mService.avoidBadWifi());
3541             assertFalse(msg, mPolicyTracker.shouldNotifyWifiUnvalidated());
3542         }
3543 
3544         mPolicyTracker.mConfigRestrictsAvoidBadWifi = true;
3545 
3546         Settings.Global.putInt(cr, settingName, 0);
3547         mPolicyTracker.reevaluate();
3548         waitForIdle();
3549         assertFalse(mService.avoidBadWifi());
3550         assertFalse(mPolicyTracker.shouldNotifyWifiUnvalidated());
3551 
3552         Settings.Global.putInt(cr, settingName, 1);
3553         mPolicyTracker.reevaluate();
3554         waitForIdle();
3555         assertTrue(mService.avoidBadWifi());
3556         assertFalse(mPolicyTracker.shouldNotifyWifiUnvalidated());
3557 
3558         Settings.Global.putString(cr, settingName, null);
3559         mPolicyTracker.reevaluate();
3560         waitForIdle();
3561         assertFalse(mService.avoidBadWifi());
3562         assertTrue(mPolicyTracker.shouldNotifyWifiUnvalidated());
3563     }
3564 
3565     @Test
testAvoidBadWifi()3566     public void testAvoidBadWifi() throws Exception {
3567         final ContentResolver cr = mServiceContext.getContentResolver();
3568 
3569         // Pretend we're on a carrier that restricts switching away from bad wifi.
3570         mPolicyTracker.mConfigRestrictsAvoidBadWifi = true;
3571 
3572         // File a request for cell to ensure it doesn't go down.
3573         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
3574         final NetworkRequest cellRequest = new NetworkRequest.Builder()
3575                 .addTransportType(TRANSPORT_CELLULAR).build();
3576         mCm.requestNetwork(cellRequest, cellNetworkCallback);
3577 
3578         TestNetworkCallback defaultCallback = new TestNetworkCallback();
3579         mCm.registerDefaultNetworkCallback(defaultCallback);
3580 
3581         NetworkRequest validatedWifiRequest = new NetworkRequest.Builder()
3582                 .addTransportType(TRANSPORT_WIFI)
3583                 .addCapability(NET_CAPABILITY_VALIDATED)
3584                 .build();
3585         TestNetworkCallback validatedWifiCallback = new TestNetworkCallback();
3586         mCm.registerNetworkCallback(validatedWifiRequest, validatedWifiCallback);
3587 
3588         Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 0);
3589         mPolicyTracker.reevaluate();
3590 
3591         // Bring up validated cell.
3592         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
3593         mCellNetworkAgent.connect(true);
3594         cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
3595         defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
3596         Network cellNetwork = mCellNetworkAgent.getNetwork();
3597 
3598         // Bring up validated wifi.
3599         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3600         mWiFiNetworkAgent.connect(true);
3601         defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
3602         validatedWifiCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
3603         Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
3604 
3605         // Fail validation on wifi.
3606         mWiFiNetworkAgent.setNetworkInvalid(false /* isStrictMode */);
3607         mCm.reportNetworkConnectivity(wifiNetwork, false);
3608         defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
3609         validatedWifiCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
3610 
3611         // Because avoid bad wifi is off, we don't switch to cellular.
3612         defaultCallback.assertNoCallback();
3613         assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
3614                 NET_CAPABILITY_VALIDATED));
3615         assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
3616                 NET_CAPABILITY_VALIDATED));
3617         assertEquals(mCm.getActiveNetwork(), wifiNetwork);
3618 
3619         // Simulate switching to a carrier that does not restrict avoiding bad wifi, and expect
3620         // that we switch back to cell.
3621         mPolicyTracker.mConfigRestrictsAvoidBadWifi = false;
3622         mPolicyTracker.reevaluate();
3623         defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
3624         assertEquals(mCm.getActiveNetwork(), cellNetwork);
3625 
3626         // Switch back to a restrictive carrier.
3627         mPolicyTracker.mConfigRestrictsAvoidBadWifi = true;
3628         mPolicyTracker.reevaluate();
3629         defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
3630         assertEquals(mCm.getActiveNetwork(), wifiNetwork);
3631 
3632         // Simulate the user selecting "switch" on the dialog, and check that we switch to cell.
3633         mCm.setAvoidUnvalidated(wifiNetwork);
3634         defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
3635         assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
3636                 NET_CAPABILITY_VALIDATED));
3637         assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
3638                 NET_CAPABILITY_VALIDATED));
3639         assertEquals(mCm.getActiveNetwork(), cellNetwork);
3640 
3641         // Disconnect and reconnect wifi to clear the one-time switch above.
3642         mWiFiNetworkAgent.disconnect();
3643         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3644         mWiFiNetworkAgent.connect(true);
3645         defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
3646         validatedWifiCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
3647         wifiNetwork = mWiFiNetworkAgent.getNetwork();
3648 
3649         // Fail validation on wifi and expect the dialog to appear.
3650         mWiFiNetworkAgent.setNetworkInvalid(false /* isStrictMode */);
3651         mCm.reportNetworkConnectivity(wifiNetwork, false);
3652         defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
3653         validatedWifiCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
3654 
3655         // Simulate the user selecting "switch" and checking the don't ask again checkbox.
3656         Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 1);
3657         mPolicyTracker.reevaluate();
3658 
3659         // We now switch to cell.
3660         defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
3661         assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
3662                 NET_CAPABILITY_VALIDATED));
3663         assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
3664                 NET_CAPABILITY_VALIDATED));
3665         assertEquals(mCm.getActiveNetwork(), cellNetwork);
3666 
3667         // Simulate the user turning the cellular fallback setting off and then on.
3668         // We switch to wifi and then to cell.
3669         Settings.Global.putString(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, null);
3670         mPolicyTracker.reevaluate();
3671         defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
3672         assertEquals(mCm.getActiveNetwork(), wifiNetwork);
3673         Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 1);
3674         mPolicyTracker.reevaluate();
3675         defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
3676         assertEquals(mCm.getActiveNetwork(), cellNetwork);
3677 
3678         // If cell goes down, we switch to wifi.
3679         mCellNetworkAgent.disconnect();
3680         defaultCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
3681         defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
3682         validatedWifiCallback.assertNoCallback();
3683 
3684         mCm.unregisterNetworkCallback(cellNetworkCallback);
3685         mCm.unregisterNetworkCallback(validatedWifiCallback);
3686         mCm.unregisterNetworkCallback(defaultCallback);
3687     }
3688 
3689     @Test
testMeteredMultipathPreferenceSetting()3690     public void testMeteredMultipathPreferenceSetting() throws Exception {
3691         final ContentResolver cr = mServiceContext.getContentResolver();
3692         final String settingName = Settings.Global.NETWORK_METERED_MULTIPATH_PREFERENCE;
3693 
3694         for (int config : Arrays.asList(0, 3, 2)) {
3695             for (String setting: Arrays.asList(null, "0", "2", "1")) {
3696                 mPolicyTracker.mConfigMeteredMultipathPreference = config;
3697                 Settings.Global.putString(cr, settingName, setting);
3698                 mPolicyTracker.reevaluate();
3699                 waitForIdle();
3700 
3701                 final int expected = (setting != null) ? Integer.parseInt(setting) : config;
3702                 String msg = String.format("config=%d, setting=%s", config, setting);
3703                 assertEquals(msg, expected, mCm.getMultipathPreference(null));
3704             }
3705         }
3706     }
3707 
3708     /**
3709      * Validate that a satisfied network request does not trigger onUnavailable() once the
3710      * time-out period expires.
3711      */
3712     @Test
testSatisfiedNetworkRequestDoesNotTriggerOnUnavailable()3713     public void testSatisfiedNetworkRequestDoesNotTriggerOnUnavailable() throws Exception {
3714         NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3715                 NetworkCapabilities.TRANSPORT_WIFI).build();
3716         final TestNetworkCallback networkCallback = new TestNetworkCallback();
3717         mCm.requestNetwork(nr, networkCallback, TEST_REQUEST_TIMEOUT_MS);
3718 
3719         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3720         mWiFiNetworkAgent.connect(false);
3721         networkCallback.expectAvailableCallbacks(mWiFiNetworkAgent, false, false, false,
3722                 TEST_CALLBACK_TIMEOUT_MS);
3723 
3724         // pass timeout and validate that UNAVAILABLE is not called
3725         networkCallback.assertNoCallback();
3726     }
3727 
3728     /**
3729      * Validate that a satisfied network request followed by a disconnected (lost) network does
3730      * not trigger onUnavailable() once the time-out period expires.
3731      */
3732     @Test
testSatisfiedThenLostNetworkRequestDoesNotTriggerOnUnavailable()3733     public void testSatisfiedThenLostNetworkRequestDoesNotTriggerOnUnavailable() throws Exception {
3734         NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3735                 NetworkCapabilities.TRANSPORT_WIFI).build();
3736         final TestNetworkCallback networkCallback = new TestNetworkCallback();
3737         mCm.requestNetwork(nr, networkCallback, TEST_REQUEST_TIMEOUT_MS);
3738 
3739         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3740         mWiFiNetworkAgent.connect(false);
3741         networkCallback.expectAvailableCallbacks(mWiFiNetworkAgent, false, false, false,
3742                 TEST_CALLBACK_TIMEOUT_MS);
3743         mWiFiNetworkAgent.disconnect();
3744         networkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
3745 
3746         // Validate that UNAVAILABLE is not called
3747         networkCallback.assertNoCallback();
3748     }
3749 
3750     /**
3751      * Validate that when a time-out is specified for a network request the onUnavailable()
3752      * callback is called when time-out expires. Then validate that if network request is
3753      * (somehow) satisfied - the callback isn't called later.
3754      */
3755     @Test
testTimedoutNetworkRequest()3756     public void testTimedoutNetworkRequest() throws Exception {
3757         NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3758                 NetworkCapabilities.TRANSPORT_WIFI).build();
3759         final TestNetworkCallback networkCallback = new TestNetworkCallback();
3760         final int timeoutMs = 10;
3761         mCm.requestNetwork(nr, networkCallback, timeoutMs);
3762 
3763         // pass timeout and validate that UNAVAILABLE is called
3764         networkCallback.expectCallback(CallbackEntry.UNAVAILABLE, (Network) null);
3765 
3766         // create a network satisfying request - validate that request not triggered
3767         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3768         mWiFiNetworkAgent.connect(false);
3769         networkCallback.assertNoCallback();
3770     }
3771 
3772     /**
3773      * Validate that when a network request is unregistered (cancelled), no posterior event can
3774      * trigger the callback.
3775      */
3776     @Test
testNoCallbackAfterUnregisteredNetworkRequest()3777     public void testNoCallbackAfterUnregisteredNetworkRequest() throws Exception {
3778         NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3779                 NetworkCapabilities.TRANSPORT_WIFI).build();
3780         final TestNetworkCallback networkCallback = new TestNetworkCallback();
3781         final int timeoutMs = 10;
3782 
3783         mCm.requestNetwork(nr, networkCallback, timeoutMs);
3784         mCm.unregisterNetworkCallback(networkCallback);
3785         // Regardless of the timeout, unregistering the callback in ConnectivityManager ensures
3786         // that this callback will not be called.
3787         networkCallback.assertNoCallback();
3788 
3789         // create a network satisfying request - validate that request not triggered
3790         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3791         mWiFiNetworkAgent.connect(false);
3792         networkCallback.assertNoCallback();
3793     }
3794 
3795     @Test
testUnfulfillableNetworkRequest()3796     public void testUnfulfillableNetworkRequest() throws Exception {
3797         runUnfulfillableNetworkRequest(false);
3798     }
3799 
3800     @Test
testUnfulfillableNetworkRequestAfterUnregister()3801     public void testUnfulfillableNetworkRequestAfterUnregister() throws Exception {
3802         runUnfulfillableNetworkRequest(true);
3803     }
3804 
3805     /**
3806      * Validate the callback flow for a factory releasing a request as unfulfillable.
3807      */
runUnfulfillableNetworkRequest(boolean preUnregister)3808     private void runUnfulfillableNetworkRequest(boolean preUnregister) throws Exception {
3809         NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3810                 NetworkCapabilities.TRANSPORT_WIFI).build();
3811         final TestNetworkCallback networkCallback = new TestNetworkCallback();
3812 
3813         final HandlerThread handlerThread = new HandlerThread("testUnfulfillableNetworkRequest");
3814         handlerThread.start();
3815         NetworkCapabilities filter = new NetworkCapabilities()
3816                 .addTransportType(TRANSPORT_WIFI)
3817                 .addCapability(NET_CAPABILITY_INTERNET);
3818         final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
3819                 mServiceContext, "testFactory", filter);
3820         testFactory.setScoreFilter(40);
3821 
3822         // Register the factory and expect it to receive the default request.
3823         testFactory.expectAddRequestsWithScores(0);
3824         testFactory.register();
3825         SparseArray<NetworkRequest> requests = testFactory.waitForNetworkRequests(1);
3826 
3827         assertEquals(1, requests.size()); // have 1 request at this point
3828         int origRequestId = requests.valueAt(0).requestId;
3829 
3830         // Now file the test request and expect it.
3831         testFactory.expectAddRequestsWithScores(0);
3832         mCm.requestNetwork(nr, networkCallback);
3833         requests = testFactory.waitForNetworkRequests(2); // have 2 requests at this point
3834 
3835         int newRequestId = 0;
3836         for (int i = 0; i < requests.size(); ++i) {
3837             if (requests.valueAt(i).requestId != origRequestId) {
3838                 newRequestId = requests.valueAt(i).requestId;
3839                 break;
3840             }
3841         }
3842 
3843         testFactory.expectRemoveRequests(1);
3844         if (preUnregister) {
3845             mCm.unregisterNetworkCallback(networkCallback);
3846 
3847             // Simulate the factory releasing the request as unfulfillable: no-op since
3848             // the callback has already been unregistered (but a test that no exceptions are
3849             // thrown).
3850             testFactory.triggerUnfulfillable(requests.get(newRequestId));
3851         } else {
3852             // Simulate the factory releasing the request as unfulfillable and expect onUnavailable!
3853             testFactory.triggerUnfulfillable(requests.get(newRequestId));
3854 
3855             networkCallback.expectCallback(CallbackEntry.UNAVAILABLE, (Network) null);
3856             testFactory.waitForRequests();
3857 
3858             // unregister network callback - a no-op (since already freed by the
3859             // on-unavailable), but should not fail or throw exceptions.
3860             mCm.unregisterNetworkCallback(networkCallback);
3861         }
3862 
3863         testFactory.terminate();
3864         handlerThread.quit();
3865     }
3866 
3867     private static class TestKeepaliveCallback extends PacketKeepaliveCallback {
3868 
3869         public enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR }
3870 
3871         private class CallbackValue {
3872             public CallbackType callbackType;
3873             public int error;
3874 
CallbackValue(CallbackType type)3875             public CallbackValue(CallbackType type) {
3876                 this.callbackType = type;
3877                 this.error = PacketKeepalive.SUCCESS;
3878                 assertTrue("onError callback must have error", type != CallbackType.ON_ERROR);
3879             }
3880 
CallbackValue(CallbackType type, int error)3881             public CallbackValue(CallbackType type, int error) {
3882                 this.callbackType = type;
3883                 this.error = error;
3884                 assertEquals("error can only be set for onError", type, CallbackType.ON_ERROR);
3885             }
3886 
3887             @Override
equals(Object o)3888             public boolean equals(Object o) {
3889                 return o instanceof CallbackValue &&
3890                         this.callbackType == ((CallbackValue) o).callbackType &&
3891                         this.error == ((CallbackValue) o).error;
3892             }
3893 
3894             @Override
toString()3895             public String toString() {
3896                 return String.format("%s(%s, %d)", getClass().getSimpleName(), callbackType, error);
3897             }
3898         }
3899 
3900         private final LinkedBlockingQueue<CallbackValue> mCallbacks = new LinkedBlockingQueue<>();
3901 
3902         @Override
onStarted()3903         public void onStarted() {
3904             mCallbacks.add(new CallbackValue(CallbackType.ON_STARTED));
3905         }
3906 
3907         @Override
onStopped()3908         public void onStopped() {
3909             mCallbacks.add(new CallbackValue(CallbackType.ON_STOPPED));
3910         }
3911 
3912         @Override
onError(int error)3913         public void onError(int error) {
3914             mCallbacks.add(new CallbackValue(CallbackType.ON_ERROR, error));
3915         }
3916 
expectCallback(CallbackValue callbackValue)3917         private void expectCallback(CallbackValue callbackValue) throws InterruptedException {
3918             assertEquals(callbackValue, mCallbacks.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
3919         }
3920 
expectStarted()3921         public void expectStarted() throws Exception {
3922             expectCallback(new CallbackValue(CallbackType.ON_STARTED));
3923         }
3924 
expectStopped()3925         public void expectStopped() throws Exception {
3926             expectCallback(new CallbackValue(CallbackType.ON_STOPPED));
3927         }
3928 
expectError(int error)3929         public void expectError(int error) throws Exception {
3930             expectCallback(new CallbackValue(CallbackType.ON_ERROR, error));
3931         }
3932     }
3933 
3934     private static class TestSocketKeepaliveCallback extends SocketKeepalive.Callback {
3935 
3936         public enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR };
3937 
3938         private class CallbackValue {
3939             public CallbackType callbackType;
3940             public int error;
3941 
CallbackValue(CallbackType type)3942             CallbackValue(CallbackType type) {
3943                 this.callbackType = type;
3944                 this.error = SocketKeepalive.SUCCESS;
3945                 assertTrue("onError callback must have error", type != CallbackType.ON_ERROR);
3946             }
3947 
CallbackValue(CallbackType type, int error)3948             CallbackValue(CallbackType type, int error) {
3949                 this.callbackType = type;
3950                 this.error = error;
3951                 assertEquals("error can only be set for onError", type, CallbackType.ON_ERROR);
3952             }
3953 
3954             @Override
equals(Object o)3955             public boolean equals(Object o) {
3956                 return o instanceof CallbackValue
3957                         && this.callbackType == ((CallbackValue) o).callbackType
3958                         && this.error == ((CallbackValue) o).error;
3959             }
3960 
3961             @Override
toString()3962             public String toString() {
3963                 return String.format("%s(%s, %d)", getClass().getSimpleName(), callbackType,
3964                         error);
3965             }
3966         }
3967 
3968         private LinkedBlockingQueue<CallbackValue> mCallbacks = new LinkedBlockingQueue<>();
3969         private final Executor mExecutor;
3970 
TestSocketKeepaliveCallback(@onNull Executor executor)3971         TestSocketKeepaliveCallback(@NonNull Executor executor) {
3972             mExecutor = executor;
3973         }
3974 
3975         @Override
onStarted()3976         public void onStarted() {
3977             mCallbacks.add(new CallbackValue(CallbackType.ON_STARTED));
3978         }
3979 
3980         @Override
onStopped()3981         public void onStopped() {
3982             mCallbacks.add(new CallbackValue(CallbackType.ON_STOPPED));
3983         }
3984 
3985         @Override
onError(int error)3986         public void onError(int error) {
3987             mCallbacks.add(new CallbackValue(CallbackType.ON_ERROR, error));
3988         }
3989 
expectCallback(CallbackValue callbackValue)3990         private void expectCallback(CallbackValue callbackValue) throws InterruptedException {
3991             assertEquals(callbackValue, mCallbacks.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
3992 
3993         }
3994 
expectStarted()3995         public void expectStarted() throws InterruptedException {
3996             expectCallback(new CallbackValue(CallbackType.ON_STARTED));
3997         }
3998 
expectStopped()3999         public void expectStopped() throws InterruptedException {
4000             expectCallback(new CallbackValue(CallbackType.ON_STOPPED));
4001         }
4002 
expectError(int error)4003         public void expectError(int error) throws InterruptedException {
4004             expectCallback(new CallbackValue(CallbackType.ON_ERROR, error));
4005         }
4006 
assertNoCallback()4007         public void assertNoCallback() {
4008             waitForIdleSerialExecutor(mExecutor, TIMEOUT_MS);
4009             CallbackValue cv = mCallbacks.peek();
4010             assertNull("Unexpected callback: " + cv, cv);
4011         }
4012     }
4013 
connectKeepaliveNetwork(LinkProperties lp)4014     private Network connectKeepaliveNetwork(LinkProperties lp) throws Exception {
4015         // Ensure the network is disconnected before we do anything.
4016         if (mWiFiNetworkAgent != null) {
4017             assertNull(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()));
4018         }
4019 
4020         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4021         ConditionVariable cv = registerConnectivityBroadcast(1);
4022         mWiFiNetworkAgent.connect(true);
4023         waitFor(cv);
4024         verifyActiveNetwork(TRANSPORT_WIFI);
4025         mWiFiNetworkAgent.sendLinkProperties(lp);
4026         waitForIdle();
4027         return mWiFiNetworkAgent.getNetwork();
4028     }
4029 
4030     @Test
4031     @FlakyTest(bugId = 140305589)
testPacketKeepalives()4032     public void testPacketKeepalives() throws Exception {
4033         InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
4034         InetAddress notMyIPv4 = InetAddress.getByName("192.0.2.35");
4035         InetAddress myIPv6 = InetAddress.getByName("2001:db8::1");
4036         InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8");
4037         InetAddress dstIPv6 = InetAddress.getByName("2001:4860:4860::8888");
4038 
4039         final int validKaInterval = 15;
4040         final int invalidKaInterval = 9;
4041 
4042         LinkProperties lp = new LinkProperties();
4043         lp.setInterfaceName("wlan12");
4044         lp.addLinkAddress(new LinkAddress(myIPv6, 64));
4045         lp.addLinkAddress(new LinkAddress(myIPv4, 25));
4046         lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
4047         lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
4048 
4049         Network notMyNet = new Network(61234);
4050         Network myNet = connectKeepaliveNetwork(lp);
4051 
4052         TestKeepaliveCallback callback = new TestKeepaliveCallback();
4053         PacketKeepalive ka;
4054 
4055         // Attempt to start keepalives with invalid parameters and check for errors.
4056         ka = mCm.startNattKeepalive(notMyNet, validKaInterval, callback, myIPv4, 1234, dstIPv4);
4057         callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK);
4058 
4059         ka = mCm.startNattKeepalive(myNet, invalidKaInterval, callback, myIPv4, 1234, dstIPv4);
4060         callback.expectError(PacketKeepalive.ERROR_INVALID_INTERVAL);
4061 
4062         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 1234, dstIPv6);
4063         callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
4064 
4065         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv6, 1234, dstIPv4);
4066         callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
4067 
4068         // NAT-T is only supported for IPv4.
4069         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv6, 1234, dstIPv6);
4070         callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
4071 
4072         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 123456, dstIPv4);
4073         callback.expectError(PacketKeepalive.ERROR_INVALID_PORT);
4074 
4075         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 123456, dstIPv4);
4076         callback.expectError(PacketKeepalive.ERROR_INVALID_PORT);
4077 
4078         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
4079         callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
4080 
4081         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
4082         callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
4083 
4084         // Check that a started keepalive can be stopped.
4085         mWiFiNetworkAgent.setStartKeepaliveEvent(PacketKeepalive.SUCCESS);
4086         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
4087         callback.expectStarted();
4088         mWiFiNetworkAgent.setStopKeepaliveEvent(PacketKeepalive.SUCCESS);
4089         ka.stop();
4090         callback.expectStopped();
4091 
4092         // Check that deleting the IP address stops the keepalive.
4093         LinkProperties bogusLp = new LinkProperties(lp);
4094         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
4095         callback.expectStarted();
4096         bogusLp.removeLinkAddress(new LinkAddress(myIPv4, 25));
4097         bogusLp.addLinkAddress(new LinkAddress(notMyIPv4, 25));
4098         mWiFiNetworkAgent.sendLinkProperties(bogusLp);
4099         callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
4100         mWiFiNetworkAgent.sendLinkProperties(lp);
4101 
4102         // Check that a started keepalive is stopped correctly when the network disconnects.
4103         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
4104         callback.expectStarted();
4105         mWiFiNetworkAgent.disconnect();
4106         mWiFiNetworkAgent.expectDisconnected();
4107         callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK);
4108 
4109         // ... and that stopping it after that has no adverse effects.
4110         waitForIdle();
4111         final Network myNetAlias = myNet;
4112         assertNull(mCm.getNetworkCapabilities(myNetAlias));
4113         ka.stop();
4114 
4115         // Reconnect.
4116         myNet = connectKeepaliveNetwork(lp);
4117         mWiFiNetworkAgent.setStartKeepaliveEvent(PacketKeepalive.SUCCESS);
4118 
4119         // Check that keepalive slots start from 1 and increment. The first one gets slot 1.
4120         mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
4121         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
4122         callback.expectStarted();
4123 
4124         // The second one gets slot 2.
4125         mWiFiNetworkAgent.setExpectedKeepaliveSlot(2);
4126         TestKeepaliveCallback callback2 = new TestKeepaliveCallback();
4127         PacketKeepalive ka2 = mCm.startNattKeepalive(
4128                 myNet, validKaInterval, callback2, myIPv4, 6789, dstIPv4);
4129         callback2.expectStarted();
4130 
4131         // Now stop the first one and create a third. This also gets slot 1.
4132         ka.stop();
4133         callback.expectStopped();
4134 
4135         mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
4136         TestKeepaliveCallback callback3 = new TestKeepaliveCallback();
4137         PacketKeepalive ka3 = mCm.startNattKeepalive(
4138                 myNet, validKaInterval, callback3, myIPv4, 9876, dstIPv4);
4139         callback3.expectStarted();
4140 
4141         ka2.stop();
4142         callback2.expectStopped();
4143 
4144         ka3.stop();
4145         callback3.expectStopped();
4146     }
4147 
4148     // Helper method to prepare the executor and run test
runTestWithSerialExecutors(ExceptionUtils.ThrowingConsumer<Executor> functor)4149     private void runTestWithSerialExecutors(ExceptionUtils.ThrowingConsumer<Executor> functor)
4150             throws Exception {
4151         final ExecutorService executorSingleThread = Executors.newSingleThreadExecutor();
4152         final Executor executorInline = (Runnable r) -> r.run();
4153         functor.accept(executorSingleThread);
4154         executorSingleThread.shutdown();
4155         functor.accept(executorInline);
4156     }
4157 
4158     @Test
testNattSocketKeepalives()4159     public void testNattSocketKeepalives() throws Exception {
4160         runTestWithSerialExecutors(executor -> doTestNattSocketKeepalivesWithExecutor(executor));
4161         runTestWithSerialExecutors(executor -> doTestNattSocketKeepalivesFdWithExecutor(executor));
4162     }
4163 
doTestNattSocketKeepalivesWithExecutor(Executor executor)4164     private void doTestNattSocketKeepalivesWithExecutor(Executor executor) throws Exception {
4165         // TODO: 1. Move this outside of ConnectivityServiceTest.
4166         //       2. Make test to verify that Nat-T keepalive socket is created by IpSecService.
4167         //       3. Mock ipsec service.
4168         final InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
4169         final InetAddress notMyIPv4 = InetAddress.getByName("192.0.2.35");
4170         final InetAddress myIPv6 = InetAddress.getByName("2001:db8::1");
4171         final InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8");
4172         final InetAddress dstIPv6 = InetAddress.getByName("2001:4860:4860::8888");
4173 
4174         final int validKaInterval = 15;
4175         final int invalidKaInterval = 9;
4176 
4177         final IpSecManager mIpSec = (IpSecManager) mContext.getSystemService(Context.IPSEC_SERVICE);
4178         final UdpEncapsulationSocket testSocket = mIpSec.openUdpEncapsulationSocket();
4179         final int srcPort = testSocket.getPort();
4180 
4181         LinkProperties lp = new LinkProperties();
4182         lp.setInterfaceName("wlan12");
4183         lp.addLinkAddress(new LinkAddress(myIPv6, 64));
4184         lp.addLinkAddress(new LinkAddress(myIPv4, 25));
4185         lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
4186         lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
4187 
4188         Network notMyNet = new Network(61234);
4189         Network myNet = connectKeepaliveNetwork(lp);
4190 
4191         TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback(executor);
4192 
4193         // Attempt to start keepalives with invalid parameters and check for errors.
4194         // Invalid network.
4195         try (SocketKeepalive ka = mCm.createSocketKeepalive(
4196                 notMyNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
4197             ka.start(validKaInterval);
4198             callback.expectError(SocketKeepalive.ERROR_INVALID_NETWORK);
4199         }
4200 
4201         // Invalid interval.
4202         try (SocketKeepalive ka = mCm.createSocketKeepalive(
4203                 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
4204             ka.start(invalidKaInterval);
4205             callback.expectError(SocketKeepalive.ERROR_INVALID_INTERVAL);
4206         }
4207 
4208         // Invalid destination.
4209         try (SocketKeepalive ka = mCm.createSocketKeepalive(
4210                 myNet, testSocket, myIPv4, dstIPv6, executor, callback)) {
4211             ka.start(validKaInterval);
4212             callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
4213         }
4214 
4215         // Invalid source;
4216         try (SocketKeepalive ka = mCm.createSocketKeepalive(
4217                 myNet, testSocket, myIPv6, dstIPv4, executor, callback)) {
4218             ka.start(validKaInterval);
4219             callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
4220         }
4221 
4222         // NAT-T is only supported for IPv4.
4223         try (SocketKeepalive ka = mCm.createSocketKeepalive(
4224                 myNet, testSocket, myIPv6, dstIPv6, executor, callback)) {
4225             ka.start(validKaInterval);
4226             callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
4227         }
4228 
4229         // Basic check before testing started keepalive.
4230         try (SocketKeepalive ka = mCm.createSocketKeepalive(
4231                 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
4232             ka.start(validKaInterval);
4233             callback.expectError(SocketKeepalive.ERROR_UNSUPPORTED);
4234         }
4235 
4236         // Check that a started keepalive can be stopped.
4237         mWiFiNetworkAgent.setStartKeepaliveEvent(SocketKeepalive.SUCCESS);
4238         try (SocketKeepalive ka = mCm.createSocketKeepalive(
4239                 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
4240             ka.start(validKaInterval);
4241             callback.expectStarted();
4242             mWiFiNetworkAgent.setStopKeepaliveEvent(SocketKeepalive.SUCCESS);
4243             ka.stop();
4244             callback.expectStopped();
4245 
4246             // Check that keepalive could be restarted.
4247             ka.start(validKaInterval);
4248             callback.expectStarted();
4249             ka.stop();
4250             callback.expectStopped();
4251 
4252             // Check that keepalive can be restarted without waiting for callback.
4253             ka.start(validKaInterval);
4254             callback.expectStarted();
4255             ka.stop();
4256             ka.start(validKaInterval);
4257             callback.expectStopped();
4258             callback.expectStarted();
4259             ka.stop();
4260             callback.expectStopped();
4261         }
4262 
4263         // Check that deleting the IP address stops the keepalive.
4264         LinkProperties bogusLp = new LinkProperties(lp);
4265         try (SocketKeepalive ka = mCm.createSocketKeepalive(
4266                 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
4267             ka.start(validKaInterval);
4268             callback.expectStarted();
4269             bogusLp.removeLinkAddress(new LinkAddress(myIPv4, 25));
4270             bogusLp.addLinkAddress(new LinkAddress(notMyIPv4, 25));
4271             mWiFiNetworkAgent.sendLinkProperties(bogusLp);
4272             callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
4273             mWiFiNetworkAgent.sendLinkProperties(lp);
4274         }
4275 
4276         // Check that a started keepalive is stopped correctly when the network disconnects.
4277         try (SocketKeepalive ka = mCm.createSocketKeepalive(
4278                 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
4279             ka.start(validKaInterval);
4280             callback.expectStarted();
4281             mWiFiNetworkAgent.disconnect();
4282             mWiFiNetworkAgent.expectDisconnected();
4283             callback.expectError(SocketKeepalive.ERROR_INVALID_NETWORK);
4284 
4285             // ... and that stopping it after that has no adverse effects.
4286             waitForIdle();
4287             final Network myNetAlias = myNet;
4288             assertNull(mCm.getNetworkCapabilities(myNetAlias));
4289             ka.stop();
4290             callback.assertNoCallback();
4291         }
4292 
4293         // Reconnect.
4294         myNet = connectKeepaliveNetwork(lp);
4295         mWiFiNetworkAgent.setStartKeepaliveEvent(SocketKeepalive.SUCCESS);
4296 
4297         // Check that keepalive slots start from 1 and increment. The first one gets slot 1.
4298         mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
4299         int srcPort2 = 0;
4300         try (SocketKeepalive ka = mCm.createSocketKeepalive(
4301                 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
4302             ka.start(validKaInterval);
4303             callback.expectStarted();
4304 
4305             // The second one gets slot 2.
4306             mWiFiNetworkAgent.setExpectedKeepaliveSlot(2);
4307             final UdpEncapsulationSocket testSocket2 = mIpSec.openUdpEncapsulationSocket();
4308             srcPort2 = testSocket2.getPort();
4309             TestSocketKeepaliveCallback callback2 = new TestSocketKeepaliveCallback(executor);
4310             try (SocketKeepalive ka2 = mCm.createSocketKeepalive(
4311                     myNet, testSocket2, myIPv4, dstIPv4, executor, callback2)) {
4312                 ka2.start(validKaInterval);
4313                 callback2.expectStarted();
4314 
4315                 ka.stop();
4316                 callback.expectStopped();
4317 
4318                 ka2.stop();
4319                 callback2.expectStopped();
4320 
4321                 testSocket.close();
4322                 testSocket2.close();
4323             }
4324         }
4325 
4326         // Check that there is no port leaked after all keepalives and sockets are closed.
4327         // TODO: enable this check after ensuring a valid free port. See b/129512753#comment7.
4328         // assertFalse(isUdpPortInUse(srcPort));
4329         // assertFalse(isUdpPortInUse(srcPort2));
4330 
4331         mWiFiNetworkAgent.disconnect();
4332         mWiFiNetworkAgent.expectDisconnected();
4333         mWiFiNetworkAgent = null;
4334     }
4335 
4336     @Test
testTcpSocketKeepalives()4337     public void testTcpSocketKeepalives() throws Exception {
4338         runTestWithSerialExecutors(executor -> doTestTcpSocketKeepalivesWithExecutor(executor));
4339     }
4340 
doTestTcpSocketKeepalivesWithExecutor(Executor executor)4341     private void doTestTcpSocketKeepalivesWithExecutor(Executor executor) throws Exception {
4342         final int srcPortV4 = 12345;
4343         final int srcPortV6 = 23456;
4344         final InetAddress myIPv4 = InetAddress.getByName("127.0.0.1");
4345         final InetAddress myIPv6 = InetAddress.getByName("::1");
4346 
4347         final int validKaInterval = 15;
4348 
4349         final LinkProperties lp = new LinkProperties();
4350         lp.setInterfaceName("wlan12");
4351         lp.addLinkAddress(new LinkAddress(myIPv6, 64));
4352         lp.addLinkAddress(new LinkAddress(myIPv4, 25));
4353         lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
4354         lp.addRoute(new RouteInfo(InetAddress.getByName("127.0.0.254")));
4355 
4356         final Network notMyNet = new Network(61234);
4357         final Network myNet = connectKeepaliveNetwork(lp);
4358 
4359         final Socket testSocketV4 = new Socket();
4360         final Socket testSocketV6 = new Socket();
4361 
4362         TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback(executor);
4363 
4364         // Attempt to start Tcp keepalives with invalid parameters and check for errors.
4365         // Invalid network.
4366         try (SocketKeepalive ka = mCm.createSocketKeepalive(
4367             notMyNet, testSocketV4, executor, callback)) {
4368             ka.start(validKaInterval);
4369             callback.expectError(SocketKeepalive.ERROR_INVALID_NETWORK);
4370         }
4371 
4372         // Invalid Socket (socket is not bound with IPv4 address).
4373         try (SocketKeepalive ka = mCm.createSocketKeepalive(
4374             myNet, testSocketV4, executor, callback)) {
4375             ka.start(validKaInterval);
4376             callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
4377         }
4378 
4379         // Invalid Socket (socket is not bound with IPv6 address).
4380         try (SocketKeepalive ka = mCm.createSocketKeepalive(
4381             myNet, testSocketV6, executor, callback)) {
4382             ka.start(validKaInterval);
4383             callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
4384         }
4385 
4386         // Bind the socket address
4387         testSocketV4.bind(new InetSocketAddress(myIPv4, srcPortV4));
4388         testSocketV6.bind(new InetSocketAddress(myIPv6, srcPortV6));
4389 
4390         // Invalid Socket (socket is bound with IPv4 address).
4391         try (SocketKeepalive ka = mCm.createSocketKeepalive(
4392             myNet, testSocketV4, executor, callback)) {
4393             ka.start(validKaInterval);
4394             callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
4395         }
4396 
4397         // Invalid Socket (socket is bound with IPv6 address).
4398         try (SocketKeepalive ka = mCm.createSocketKeepalive(
4399             myNet, testSocketV6, executor, callback)) {
4400             ka.start(validKaInterval);
4401             callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
4402         }
4403 
4404         testSocketV4.close();
4405         testSocketV6.close();
4406 
4407         mWiFiNetworkAgent.disconnect();
4408         mWiFiNetworkAgent.expectDisconnected();
4409         mWiFiNetworkAgent = null;
4410     }
4411 
doTestNattSocketKeepalivesFdWithExecutor(Executor executor)4412     private void doTestNattSocketKeepalivesFdWithExecutor(Executor executor) throws Exception {
4413         final InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
4414         final InetAddress anyIPv4 = InetAddress.getByName("0.0.0.0");
4415         final InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8");
4416         final int validKaInterval = 15;
4417 
4418         // Prepare the target network.
4419         LinkProperties lp = new LinkProperties();
4420         lp.setInterfaceName("wlan12");
4421         lp.addLinkAddress(new LinkAddress(myIPv4, 25));
4422         lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
4423         Network myNet = connectKeepaliveNetwork(lp);
4424         mWiFiNetworkAgent.setStartKeepaliveEvent(SocketKeepalive.SUCCESS);
4425         mWiFiNetworkAgent.setStopKeepaliveEvent(SocketKeepalive.SUCCESS);
4426 
4427         TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback(executor);
4428 
4429         // Prepare the target file descriptor, keep only one instance.
4430         final IpSecManager mIpSec = (IpSecManager) mContext.getSystemService(Context.IPSEC_SERVICE);
4431         final UdpEncapsulationSocket testSocket = mIpSec.openUdpEncapsulationSocket();
4432         final int srcPort = testSocket.getPort();
4433         final ParcelFileDescriptor testPfd =
4434                 ParcelFileDescriptor.dup(testSocket.getFileDescriptor());
4435         testSocket.close();
4436         assertTrue(isUdpPortInUse(srcPort));
4437 
4438         // Start keepalive and explicit make the variable goes out of scope with try-with-resources
4439         // block.
4440         try (SocketKeepalive ka = mCm.createNattKeepalive(
4441                 myNet, testPfd, myIPv4, dstIPv4, executor, callback)) {
4442             ka.start(validKaInterval);
4443             callback.expectStarted();
4444             ka.stop();
4445             callback.expectStopped();
4446         }
4447 
4448         // Check that the ParcelFileDescriptor is still valid after keepalive stopped,
4449         // ErrnoException with EBADF will be thrown if the socket is closed when checking local
4450         // address.
4451         assertTrue(isUdpPortInUse(srcPort));
4452         final InetSocketAddress sa =
4453                 (InetSocketAddress) Os.getsockname(testPfd.getFileDescriptor());
4454         assertEquals(anyIPv4, sa.getAddress());
4455 
4456         testPfd.close();
4457         // TODO: enable this check after ensuring a valid free port. See b/129512753#comment7.
4458         // assertFalse(isUdpPortInUse(srcPort));
4459 
4460         mWiFiNetworkAgent.disconnect();
4461         mWiFiNetworkAgent.expectDisconnected();
4462         mWiFiNetworkAgent = null;
4463     }
4464 
isUdpPortInUse(int port)4465     private static boolean isUdpPortInUse(int port) {
4466         try (DatagramSocket ignored = new DatagramSocket(port)) {
4467             return false;
4468         } catch (IOException alreadyInUse) {
4469             return true;
4470         }
4471     }
4472 
4473     @Test
testGetCaptivePortalServerUrl()4474     public void testGetCaptivePortalServerUrl() throws Exception {
4475         String url = mCm.getCaptivePortalServerUrl();
4476         assertEquals("http://connectivitycheck.gstatic.com/generate_204", url);
4477     }
4478 
4479     private static class TestNetworkPinner extends NetworkPinner {
awaitPin(int timeoutMs)4480         public static boolean awaitPin(int timeoutMs) throws InterruptedException {
4481             synchronized(sLock) {
4482                 if (sNetwork == null) {
4483                     sLock.wait(timeoutMs);
4484                 }
4485                 return sNetwork != null;
4486             }
4487         }
4488 
awaitUnpin(int timeoutMs)4489         public static boolean awaitUnpin(int timeoutMs) throws InterruptedException {
4490             synchronized(sLock) {
4491                 if (sNetwork != null) {
4492                     sLock.wait(timeoutMs);
4493                 }
4494                 return sNetwork == null;
4495             }
4496         }
4497     }
4498 
assertPinnedToWifiWithCellDefault()4499     private void assertPinnedToWifiWithCellDefault() {
4500         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess());
4501         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
4502     }
4503 
assertPinnedToWifiWithWifiDefault()4504     private void assertPinnedToWifiWithWifiDefault() {
4505         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess());
4506         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
4507     }
4508 
assertNotPinnedToWifi()4509     private void assertNotPinnedToWifi() {
4510         assertNull(mCm.getBoundNetworkForProcess());
4511         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
4512     }
4513 
4514     @Test
testNetworkPinner()4515     public void testNetworkPinner() throws Exception {
4516         NetworkRequest wifiRequest = new NetworkRequest.Builder()
4517                 .addTransportType(TRANSPORT_WIFI)
4518                 .build();
4519         assertNull(mCm.getBoundNetworkForProcess());
4520 
4521         TestNetworkPinner.pin(mServiceContext, wifiRequest);
4522         assertNull(mCm.getBoundNetworkForProcess());
4523 
4524         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
4525         mCellNetworkAgent.connect(true);
4526         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4527         mWiFiNetworkAgent.connect(false);
4528 
4529         // When wi-fi connects, expect to be pinned.
4530         assertTrue(TestNetworkPinner.awaitPin(100));
4531         assertPinnedToWifiWithCellDefault();
4532 
4533         // Disconnect and expect the pin to drop.
4534         mWiFiNetworkAgent.disconnect();
4535         assertTrue(TestNetworkPinner.awaitUnpin(100));
4536         assertNotPinnedToWifi();
4537 
4538         // Reconnecting does not cause the pin to come back.
4539         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4540         mWiFiNetworkAgent.connect(false);
4541         assertFalse(TestNetworkPinner.awaitPin(100));
4542         assertNotPinnedToWifi();
4543 
4544         // Pinning while connected causes the pin to take effect immediately.
4545         TestNetworkPinner.pin(mServiceContext, wifiRequest);
4546         assertTrue(TestNetworkPinner.awaitPin(100));
4547         assertPinnedToWifiWithCellDefault();
4548 
4549         // Explicitly unpin and expect to use the default network again.
4550         TestNetworkPinner.unpin();
4551         assertNotPinnedToWifi();
4552 
4553         // Disconnect cell and wifi.
4554         ConditionVariable cv = registerConnectivityBroadcast(3);  // cell down, wifi up, wifi down.
4555         mCellNetworkAgent.disconnect();
4556         mWiFiNetworkAgent.disconnect();
4557         waitFor(cv);
4558 
4559         // Pinning takes effect even if the pinned network is the default when the pin is set...
4560         TestNetworkPinner.pin(mServiceContext, wifiRequest);
4561         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4562         mWiFiNetworkAgent.connect(false);
4563         assertTrue(TestNetworkPinner.awaitPin(100));
4564         assertPinnedToWifiWithWifiDefault();
4565 
4566         // ... and is maintained even when that network is no longer the default.
4567         cv = registerConnectivityBroadcast(1);
4568         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4569         mCellNetworkAgent.connect(true);
4570         waitFor(cv);
4571         assertPinnedToWifiWithCellDefault();
4572     }
4573 
4574     @Test
testNetworkCallbackMaximum()4575     public void testNetworkCallbackMaximum() {
4576         // We can only have 99 callbacks, because MultipathPolicyTracker is
4577         // already one of them.
4578         final int MAX_REQUESTS = 99;
4579         final int CALLBACKS = 89;
4580         final int INTENTS = 10;
4581         assertEquals(MAX_REQUESTS, CALLBACKS + INTENTS);
4582 
4583         NetworkRequest networkRequest = new NetworkRequest.Builder().build();
4584         ArrayList<Object> registered = new ArrayList<>();
4585 
4586         int j = 0;
4587         while (j++ < CALLBACKS / 2) {
4588             NetworkCallback cb = new NetworkCallback();
4589             mCm.requestNetwork(networkRequest, cb);
4590             registered.add(cb);
4591         }
4592         while (j++ < CALLBACKS) {
4593             NetworkCallback cb = new NetworkCallback();
4594             mCm.registerNetworkCallback(networkRequest, cb);
4595             registered.add(cb);
4596         }
4597         j = 0;
4598         while (j++ < INTENTS / 2) {
4599             PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, new Intent("a" + j), 0);
4600             mCm.requestNetwork(networkRequest, pi);
4601             registered.add(pi);
4602         }
4603         while (j++ < INTENTS) {
4604             PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, new Intent("b" + j), 0);
4605             mCm.registerNetworkCallback(networkRequest, pi);
4606             registered.add(pi);
4607         }
4608 
4609         // Test that the limit is enforced when MAX_REQUESTS simultaneous requests are added.
4610         assertThrows(TooManyRequestsException.class, () ->
4611                 mCm.requestNetwork(networkRequest, new NetworkCallback())
4612         );
4613         assertThrows(TooManyRequestsException.class, () ->
4614                 mCm.registerNetworkCallback(networkRequest, new NetworkCallback())
4615         );
4616         assertThrows(TooManyRequestsException.class, () ->
4617                 mCm.requestNetwork(networkRequest,
4618                         PendingIntent.getBroadcast(mContext, 0, new Intent("c"), 0))
4619         );
4620         assertThrows(TooManyRequestsException.class, () ->
4621                 mCm.registerNetworkCallback(networkRequest,
4622                         PendingIntent.getBroadcast(mContext, 0, new Intent("d"), 0))
4623         );
4624 
4625         for (Object o : registered) {
4626             if (o instanceof NetworkCallback) {
4627                 mCm.unregisterNetworkCallback((NetworkCallback)o);
4628             }
4629             if (o instanceof PendingIntent) {
4630                 mCm.unregisterNetworkCallback((PendingIntent)o);
4631             }
4632         }
4633         waitForIdle();
4634 
4635         // Test that the limit is not hit when MAX_REQUESTS requests are added and removed.
4636         for (int i = 0; i < MAX_REQUESTS; i++) {
4637             NetworkCallback networkCallback = new NetworkCallback();
4638             mCm.requestNetwork(networkRequest, networkCallback);
4639             mCm.unregisterNetworkCallback(networkCallback);
4640         }
4641         waitForIdle();
4642 
4643         for (int i = 0; i < MAX_REQUESTS; i++) {
4644             NetworkCallback networkCallback = new NetworkCallback();
4645             mCm.registerNetworkCallback(networkRequest, networkCallback);
4646             mCm.unregisterNetworkCallback(networkCallback);
4647         }
4648         waitForIdle();
4649 
4650         for (int i = 0; i < MAX_REQUESTS; i++) {
4651             PendingIntent pendingIntent =
4652                     PendingIntent.getBroadcast(mContext, 0, new Intent("e" + i), 0);
4653             mCm.requestNetwork(networkRequest, pendingIntent);
4654             mCm.unregisterNetworkCallback(pendingIntent);
4655         }
4656         waitForIdle();
4657 
4658         for (int i = 0; i < MAX_REQUESTS; i++) {
4659             PendingIntent pendingIntent =
4660                     PendingIntent.getBroadcast(mContext, 0, new Intent("f" + i), 0);
4661             mCm.registerNetworkCallback(networkRequest, pendingIntent);
4662             mCm.unregisterNetworkCallback(pendingIntent);
4663         }
4664     }
4665 
4666     @Test
testNetworkInfoOfTypeNone()4667     public void testNetworkInfoOfTypeNone() throws Exception {
4668         ConditionVariable broadcastCV = registerConnectivityBroadcast(1);
4669 
4670         verifyNoNetwork();
4671         TestNetworkAgentWrapper wifiAware = new TestNetworkAgentWrapper(TRANSPORT_WIFI_AWARE);
4672         assertNull(mCm.getActiveNetworkInfo());
4673 
4674         Network[] allNetworks = mCm.getAllNetworks();
4675         assertLength(1, allNetworks);
4676         Network network = allNetworks[0];
4677         NetworkCapabilities capabilities = mCm.getNetworkCapabilities(network);
4678         assertTrue(capabilities.hasTransport(TRANSPORT_WIFI_AWARE));
4679 
4680         final NetworkRequest request =
4681                 new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI_AWARE).build();
4682         final TestNetworkCallback callback = new TestNetworkCallback();
4683         mCm.registerNetworkCallback(request, callback);
4684 
4685         // Bring up wifi aware network.
4686         wifiAware.connect(false, false, false /* isStrictMode */);
4687         callback.expectAvailableCallbacksUnvalidated(wifiAware);
4688 
4689         assertNull(mCm.getActiveNetworkInfo());
4690         assertNull(mCm.getActiveNetwork());
4691         // TODO: getAllNetworkInfo is dirty and returns a non-empty array right from the start
4692         // of this test. Fix it and uncomment the assert below.
4693         //assertEmpty(mCm.getAllNetworkInfo());
4694 
4695         // Disconnect wifi aware network.
4696         wifiAware.disconnect();
4697         callback.expectCallbackThat(TIMEOUT_MS, (info) -> info instanceof CallbackEntry.Lost);
4698         mCm.unregisterNetworkCallback(callback);
4699 
4700         verifyNoNetwork();
4701         if (broadcastCV.block(10)) {
4702             fail("expected no broadcast, but got CONNECTIVITY_ACTION broadcast");
4703         }
4704     }
4705 
4706     @Test
testDeprecatedAndUnsupportedOperations()4707     public void testDeprecatedAndUnsupportedOperations() throws Exception {
4708         final int TYPE_NONE = ConnectivityManager.TYPE_NONE;
4709         assertNull(mCm.getNetworkInfo(TYPE_NONE));
4710         assertNull(mCm.getNetworkForType(TYPE_NONE));
4711         assertNull(mCm.getLinkProperties(TYPE_NONE));
4712         assertFalse(mCm.isNetworkSupported(TYPE_NONE));
4713 
4714         assertThrows(IllegalArgumentException.class,
4715                 () -> mCm.networkCapabilitiesForType(TYPE_NONE));
4716 
4717         Class<UnsupportedOperationException> unsupported = UnsupportedOperationException.class;
4718         assertThrows(unsupported, () -> mCm.startUsingNetworkFeature(TYPE_WIFI, ""));
4719         assertThrows(unsupported, () -> mCm.stopUsingNetworkFeature(TYPE_WIFI, ""));
4720         // TODO: let test context have configuration application target sdk version
4721         // and test that pre-M requesting for TYPE_NONE sends back APN_REQUEST_FAILED
4722         assertThrows(unsupported, () -> mCm.startUsingNetworkFeature(TYPE_NONE, ""));
4723         assertThrows(unsupported, () -> mCm.stopUsingNetworkFeature(TYPE_NONE, ""));
4724         assertThrows(unsupported, () -> mCm.requestRouteToHostAddress(TYPE_NONE, null));
4725     }
4726 
4727     @Test
testLinkPropertiesEnsuresDirectlyConnectedRoutes()4728     public void testLinkPropertiesEnsuresDirectlyConnectedRoutes() throws Exception {
4729         final NetworkRequest networkRequest = new NetworkRequest.Builder()
4730                 .addTransportType(TRANSPORT_WIFI).build();
4731         final TestNetworkCallback networkCallback = new TestNetworkCallback();
4732         mCm.registerNetworkCallback(networkRequest, networkCallback);
4733 
4734         LinkProperties lp = new LinkProperties();
4735         lp.setInterfaceName(WIFI_IFNAME);
4736         LinkAddress myIpv4Address = new LinkAddress("192.168.12.3/24");
4737         RouteInfo myIpv4DefaultRoute = new RouteInfo((IpPrefix) null,
4738                 NetworkUtils.numericToInetAddress("192.168.12.1"), lp.getInterfaceName());
4739         lp.addLinkAddress(myIpv4Address);
4740         lp.addRoute(myIpv4DefaultRoute);
4741 
4742         // Verify direct routes are added when network agent is first registered in
4743         // ConnectivityService.
4744         TestNetworkAgentWrapper networkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, lp);
4745         networkAgent.connect(true);
4746         networkCallback.expectCallback(CallbackEntry.AVAILABLE, networkAgent);
4747         networkCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, networkAgent);
4748         CallbackEntry.LinkPropertiesChanged cbi =
4749                 networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED,
4750                 networkAgent);
4751         networkCallback.expectCallback(CallbackEntry.BLOCKED_STATUS, networkAgent);
4752         networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, networkAgent);
4753         networkCallback.assertNoCallback();
4754         checkDirectlyConnectedRoutes(cbi.getLp(), Arrays.asList(myIpv4Address),
4755                 Arrays.asList(myIpv4DefaultRoute));
4756         checkDirectlyConnectedRoutes(mCm.getLinkProperties(networkAgent.getNetwork()),
4757                 Arrays.asList(myIpv4Address), Arrays.asList(myIpv4DefaultRoute));
4758 
4759         // Verify direct routes are added during subsequent link properties updates.
4760         LinkProperties newLp = new LinkProperties(lp);
4761         LinkAddress myIpv6Address1 = new LinkAddress("fe80::cafe/64");
4762         LinkAddress myIpv6Address2 = new LinkAddress("2001:db8::2/64");
4763         newLp.addLinkAddress(myIpv6Address1);
4764         newLp.addLinkAddress(myIpv6Address2);
4765         networkAgent.sendLinkProperties(newLp);
4766         cbi = networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, networkAgent);
4767         networkCallback.assertNoCallback();
4768         checkDirectlyConnectedRoutes(cbi.getLp(),
4769                 Arrays.asList(myIpv4Address, myIpv6Address1, myIpv6Address2),
4770                 Arrays.asList(myIpv4DefaultRoute));
4771         mCm.unregisterNetworkCallback(networkCallback);
4772     }
4773 
4774     @Test
testStatsIfacesChanged()4775     public void testStatsIfacesChanged() throws Exception {
4776         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
4777         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4778 
4779         Network[] onlyCell = new Network[] {mCellNetworkAgent.getNetwork()};
4780         Network[] onlyWifi = new Network[] {mWiFiNetworkAgent.getNetwork()};
4781 
4782         LinkProperties cellLp = new LinkProperties();
4783         cellLp.setInterfaceName(MOBILE_IFNAME);
4784         LinkProperties wifiLp = new LinkProperties();
4785         wifiLp.setInterfaceName(WIFI_IFNAME);
4786 
4787         // Simple connection should have updated ifaces
4788         mCellNetworkAgent.connect(false);
4789         mCellNetworkAgent.sendLinkProperties(cellLp);
4790         waitForIdle();
4791         verify(mStatsService, atLeastOnce())
4792                 .forceUpdateIfaces(eq(onlyCell), any(NetworkState[].class), eq(MOBILE_IFNAME),
4793                         eq(new VpnInfo[0]));
4794         reset(mStatsService);
4795 
4796         // Default network switch should update ifaces.
4797         mWiFiNetworkAgent.connect(false);
4798         mWiFiNetworkAgent.sendLinkProperties(wifiLp);
4799         waitForIdle();
4800         assertEquals(wifiLp, mService.getActiveLinkProperties());
4801         verify(mStatsService, atLeastOnce())
4802                 .forceUpdateIfaces(eq(onlyWifi), any(NetworkState[].class), eq(WIFI_IFNAME),
4803                         eq(new VpnInfo[0]));
4804         reset(mStatsService);
4805 
4806         // Disconnect should update ifaces.
4807         mWiFiNetworkAgent.disconnect();
4808         waitForIdle();
4809         verify(mStatsService, atLeastOnce())
4810                 .forceUpdateIfaces(eq(onlyCell), any(NetworkState[].class),
4811                         eq(MOBILE_IFNAME), eq(new VpnInfo[0]));
4812         reset(mStatsService);
4813 
4814         // Metered change should update ifaces
4815         mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
4816         waitForIdle();
4817         verify(mStatsService, atLeastOnce())
4818                 .forceUpdateIfaces(eq(onlyCell), any(NetworkState[].class), eq(MOBILE_IFNAME),
4819                         eq(new VpnInfo[0]));
4820         reset(mStatsService);
4821 
4822         mCellNetworkAgent.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
4823         waitForIdle();
4824         verify(mStatsService, atLeastOnce())
4825                 .forceUpdateIfaces(eq(onlyCell), any(NetworkState[].class), eq(MOBILE_IFNAME),
4826                         eq(new VpnInfo[0]));
4827         reset(mStatsService);
4828 
4829         // Captive portal change shouldn't update ifaces
4830         mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL);
4831         waitForIdle();
4832         verify(mStatsService, never())
4833                 .forceUpdateIfaces(eq(onlyCell), any(NetworkState[].class), eq(MOBILE_IFNAME),
4834                         eq(new VpnInfo[0]));
4835         reset(mStatsService);
4836 
4837         // Roaming change should update ifaces
4838         mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING);
4839         waitForIdle();
4840         verify(mStatsService, atLeastOnce())
4841                 .forceUpdateIfaces(eq(onlyCell), any(NetworkState[].class), eq(MOBILE_IFNAME),
4842                         eq(new VpnInfo[0]));
4843         reset(mStatsService);
4844     }
4845 
4846     @Test
testBasicDnsConfigurationPushed()4847     public void testBasicDnsConfigurationPushed() throws Exception {
4848         setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
4849 
4850         // Clear any interactions that occur as a result of CS starting up.
4851         reset(mMockDnsResolver);
4852 
4853         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
4854         waitForIdle();
4855         verify(mMockDnsResolver, never()).setResolverConfiguration(any());
4856         verifyNoMoreInteractions(mMockDnsResolver);
4857 
4858         final LinkProperties cellLp = new LinkProperties();
4859         cellLp.setInterfaceName(MOBILE_IFNAME);
4860         // Add IPv4 and IPv6 default routes, because DNS-over-TLS code does
4861         // "is-reachable" testing in order to not program netd with unreachable
4862         // nameservers that it might try repeated to validate.
4863         cellLp.addLinkAddress(new LinkAddress("192.0.2.4/24"));
4864         cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("192.0.2.4"),
4865                 MOBILE_IFNAME));
4866         cellLp.addLinkAddress(new LinkAddress("2001:db8:1::1/64"));
4867         cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("2001:db8:1::1"),
4868                 MOBILE_IFNAME));
4869         mCellNetworkAgent.sendLinkProperties(cellLp);
4870         mCellNetworkAgent.connect(false);
4871         waitForIdle();
4872 
4873         verify(mMockDnsResolver, times(1)).createNetworkCache(
4874                 eq(mCellNetworkAgent.getNetwork().netId));
4875         // CS tells dnsresolver about the empty DNS config for this network.
4876         verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(any());
4877         reset(mMockDnsResolver);
4878 
4879         cellLp.addDnsServer(InetAddress.getByName("2001:db8::1"));
4880         mCellNetworkAgent.sendLinkProperties(cellLp);
4881         waitForIdle();
4882         verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
4883                 mResolverParamsParcelCaptor.capture());
4884         ResolverParamsParcel resolvrParams = mResolverParamsParcelCaptor.getValue();
4885         assertEquals(1, resolvrParams.servers.length);
4886         assertTrue(ArrayUtils.contains(resolvrParams.servers, "2001:db8::1"));
4887         // Opportunistic mode.
4888         assertTrue(ArrayUtils.contains(resolvrParams.tlsServers, "2001:db8::1"));
4889         reset(mMockDnsResolver);
4890 
4891         cellLp.addDnsServer(InetAddress.getByName("192.0.2.1"));
4892         mCellNetworkAgent.sendLinkProperties(cellLp);
4893         waitForIdle();
4894         verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
4895                 mResolverParamsParcelCaptor.capture());
4896         resolvrParams = mResolverParamsParcelCaptor.getValue();
4897         assertEquals(2, resolvrParams.servers.length);
4898         assertTrue(ArrayUtils.containsAll(resolvrParams.servers,
4899                 new String[]{"2001:db8::1", "192.0.2.1"}));
4900         // Opportunistic mode.
4901         assertEquals(2, resolvrParams.tlsServers.length);
4902         assertTrue(ArrayUtils.containsAll(resolvrParams.tlsServers,
4903                 new String[]{"2001:db8::1", "192.0.2.1"}));
4904         reset(mMockDnsResolver);
4905 
4906         final String TLS_SPECIFIER = "tls.example.com";
4907         final String TLS_SERVER6 = "2001:db8:53::53";
4908         final InetAddress[] TLS_IPS = new InetAddress[]{ InetAddress.getByName(TLS_SERVER6) };
4909         final String[] TLS_SERVERS = new String[]{ TLS_SERVER6 };
4910         mCellNetworkAgent.mNmCallbacks.notifyPrivateDnsConfigResolved(
4911                 new PrivateDnsConfig(TLS_SPECIFIER, TLS_IPS).toParcel());
4912 
4913         waitForIdle();
4914         verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
4915                 mResolverParamsParcelCaptor.capture());
4916         resolvrParams = mResolverParamsParcelCaptor.getValue();
4917         assertEquals(2, resolvrParams.servers.length);
4918         assertTrue(ArrayUtils.containsAll(resolvrParams.servers,
4919                 new String[]{"2001:db8::1", "192.0.2.1"}));
4920         reset(mMockDnsResolver);
4921     }
4922 
4923     @Test
testDnsConfigurationTransTypesPushed()4924     public void testDnsConfigurationTransTypesPushed() throws Exception {
4925         // Clear any interactions that occur as a result of CS starting up.
4926         reset(mMockDnsResolver);
4927 
4928         final NetworkRequest request = new NetworkRequest.Builder()
4929                 .clearCapabilities().addCapability(NET_CAPABILITY_INTERNET)
4930                 .build();
4931         final TestNetworkCallback callback = new TestNetworkCallback();
4932         mCm.registerNetworkCallback(request, callback);
4933 
4934         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4935         mWiFiNetworkAgent.connect(false);
4936         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
4937         verify(mMockDnsResolver, times(1)).createNetworkCache(
4938                 eq(mWiFiNetworkAgent.getNetwork().netId));
4939         verify(mMockDnsResolver, times(2)).setResolverConfiguration(
4940                 mResolverParamsParcelCaptor.capture());
4941         final ResolverParamsParcel resolverParams = mResolverParamsParcelCaptor.getValue();
4942         assertContainsExactly(resolverParams.transportTypes, TRANSPORT_WIFI);
4943         reset(mMockDnsResolver);
4944     }
4945 
4946     @Test
testPrivateDnsNotification()4947     public void testPrivateDnsNotification() throws Exception {
4948         NetworkRequest request = new NetworkRequest.Builder()
4949                 .clearCapabilities().addCapability(NET_CAPABILITY_INTERNET)
4950                 .build();
4951         TestNetworkCallback callback = new TestNetworkCallback();
4952         mCm.registerNetworkCallback(request, callback);
4953         // Bring up wifi.
4954         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4955         mWiFiNetworkAgent.connect(false);
4956         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
4957         // Private DNS resolution failed, checking if the notification will be shown or not.
4958         mWiFiNetworkAgent.setNetworkInvalid(true /* isStrictMode */);
4959         mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
4960         waitForIdle();
4961         // If network validation failed, NetworkMonitor will re-evaluate the network.
4962         // ConnectivityService should filter the redundant notification. This part is trying to
4963         // simulate that situation and check if ConnectivityService could filter that case.
4964         mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
4965         waitForIdle();
4966         verify(mNotificationManager, timeout(TIMEOUT_MS).times(1)).notifyAsUser(anyString(),
4967                 eq(NotificationType.PRIVATE_DNS_BROKEN.eventId), any(), eq(UserHandle.ALL));
4968         // If private DNS resolution successful, the PRIVATE_DNS_BROKEN notification shouldn't be
4969         // shown.
4970         mWiFiNetworkAgent.setNetworkValid(true /* isStrictMode */);
4971         mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
4972         waitForIdle();
4973         verify(mNotificationManager, timeout(TIMEOUT_MS).times(1)).cancelAsUser(anyString(),
4974                 eq(NotificationType.PRIVATE_DNS_BROKEN.eventId), eq(UserHandle.ALL));
4975         // If private DNS resolution failed again, the PRIVATE_DNS_BROKEN notification should be
4976         // shown again.
4977         mWiFiNetworkAgent.setNetworkInvalid(true /* isStrictMode */);
4978         mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
4979         waitForIdle();
4980         verify(mNotificationManager, timeout(TIMEOUT_MS).times(2)).notifyAsUser(anyString(),
4981                 eq(NotificationType.PRIVATE_DNS_BROKEN.eventId), any(), eq(UserHandle.ALL));
4982     }
4983 
4984     @Test
testPrivateDnsSettingsChange()4985     public void testPrivateDnsSettingsChange() throws Exception {
4986         // Clear any interactions that occur as a result of CS starting up.
4987         reset(mMockDnsResolver);
4988 
4989         // The default on Android is opportunistic mode ("Automatic").
4990         setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
4991 
4992         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
4993         final NetworkRequest cellRequest = new NetworkRequest.Builder()
4994                 .addTransportType(TRANSPORT_CELLULAR).build();
4995         mCm.requestNetwork(cellRequest, cellNetworkCallback);
4996 
4997         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
4998         waitForIdle();
4999         // CS tells netd about the empty DNS config for this network.
5000         verify(mMockDnsResolver, never()).setResolverConfiguration(any());
5001         verifyNoMoreInteractions(mMockDnsResolver);
5002 
5003         final LinkProperties cellLp = new LinkProperties();
5004         cellLp.setInterfaceName(MOBILE_IFNAME);
5005         // Add IPv4 and IPv6 default routes, because DNS-over-TLS code does
5006         // "is-reachable" testing in order to not program netd with unreachable
5007         // nameservers that it might try repeated to validate.
5008         cellLp.addLinkAddress(new LinkAddress("192.0.2.4/24"));
5009         cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("192.0.2.4"),
5010                 MOBILE_IFNAME));
5011         cellLp.addLinkAddress(new LinkAddress("2001:db8:1::1/64"));
5012         cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("2001:db8:1::1"),
5013                 MOBILE_IFNAME));
5014         cellLp.addDnsServer(InetAddress.getByName("2001:db8::1"));
5015         cellLp.addDnsServer(InetAddress.getByName("192.0.2.1"));
5016 
5017         mCellNetworkAgent.sendLinkProperties(cellLp);
5018         mCellNetworkAgent.connect(false);
5019         waitForIdle();
5020         verify(mMockDnsResolver, times(1)).createNetworkCache(
5021                 eq(mCellNetworkAgent.getNetwork().netId));
5022         verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
5023                 mResolverParamsParcelCaptor.capture());
5024         ResolverParamsParcel resolvrParams = mResolverParamsParcelCaptor.getValue();
5025         assertEquals(2, resolvrParams.tlsServers.length);
5026         assertTrue(ArrayUtils.containsAll(resolvrParams.tlsServers,
5027                 new String[] { "2001:db8::1", "192.0.2.1" }));
5028         // Opportunistic mode.
5029         assertEquals(2, resolvrParams.tlsServers.length);
5030         assertTrue(ArrayUtils.containsAll(resolvrParams.tlsServers,
5031                 new String[] { "2001:db8::1", "192.0.2.1" }));
5032         reset(mMockDnsResolver);
5033         cellNetworkCallback.expectCallback(CallbackEntry.AVAILABLE, mCellNetworkAgent);
5034         cellNetworkCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED,
5035                 mCellNetworkAgent);
5036         CallbackEntry.LinkPropertiesChanged cbi = cellNetworkCallback.expectCallback(
5037                 CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
5038         cellNetworkCallback.expectCallback(CallbackEntry.BLOCKED_STATUS, mCellNetworkAgent);
5039         cellNetworkCallback.assertNoCallback();
5040         assertFalse(cbi.getLp().isPrivateDnsActive());
5041         assertNull(cbi.getLp().getPrivateDnsServerName());
5042 
5043         setPrivateDnsSettings(PRIVATE_DNS_MODE_OFF, "ignored.example.com");
5044         verify(mMockDnsResolver, times(1)).setResolverConfiguration(
5045                 mResolverParamsParcelCaptor.capture());
5046         resolvrParams = mResolverParamsParcelCaptor.getValue();
5047         assertEquals(2, resolvrParams.servers.length);
5048         assertTrue(ArrayUtils.containsAll(resolvrParams.servers,
5049                 new String[] { "2001:db8::1", "192.0.2.1" }));
5050         reset(mMockDnsResolver);
5051         cellNetworkCallback.assertNoCallback();
5052 
5053         setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
5054         verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
5055                 mResolverParamsParcelCaptor.capture());
5056         resolvrParams = mResolverParamsParcelCaptor.getValue();
5057         assertEquals(2, resolvrParams.servers.length);
5058         assertTrue(ArrayUtils.containsAll(resolvrParams.servers,
5059                 new String[] { "2001:db8::1", "192.0.2.1" }));
5060         assertEquals(2, resolvrParams.tlsServers.length);
5061         assertTrue(ArrayUtils.containsAll(resolvrParams.tlsServers,
5062                 new String[] { "2001:db8::1", "192.0.2.1" }));
5063         reset(mMockDnsResolver);
5064         cellNetworkCallback.assertNoCallback();
5065 
5066         setPrivateDnsSettings(PRIVATE_DNS_MODE_PROVIDER_HOSTNAME, "strict.example.com");
5067         // Can't test dns configuration for strict mode without properly mocking
5068         // out the DNS lookups, but can test that LinkProperties is updated.
5069         cbi = cellNetworkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED,
5070                 mCellNetworkAgent);
5071         cellNetworkCallback.assertNoCallback();
5072         assertTrue(cbi.getLp().isPrivateDnsActive());
5073         assertEquals("strict.example.com", cbi.getLp().getPrivateDnsServerName());
5074     }
5075 
5076     @Test
testLinkPropertiesWithPrivateDnsValidationEvents()5077     public void testLinkPropertiesWithPrivateDnsValidationEvents() throws Exception {
5078         // The default on Android is opportunistic mode ("Automatic").
5079         setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
5080 
5081         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
5082         final NetworkRequest cellRequest = new NetworkRequest.Builder()
5083                 .addTransportType(TRANSPORT_CELLULAR).build();
5084         mCm.requestNetwork(cellRequest, cellNetworkCallback);
5085 
5086         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
5087         waitForIdle();
5088         LinkProperties lp = new LinkProperties();
5089         mCellNetworkAgent.sendLinkProperties(lp);
5090         mCellNetworkAgent.connect(false);
5091         waitForIdle();
5092         cellNetworkCallback.expectCallback(CallbackEntry.AVAILABLE, mCellNetworkAgent);
5093         cellNetworkCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED,
5094                 mCellNetworkAgent);
5095         CallbackEntry.LinkPropertiesChanged cbi = cellNetworkCallback.expectCallback(
5096                 CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
5097         cellNetworkCallback.expectCallback(CallbackEntry.BLOCKED_STATUS, mCellNetworkAgent);
5098         cellNetworkCallback.assertNoCallback();
5099         assertFalse(cbi.getLp().isPrivateDnsActive());
5100         assertNull(cbi.getLp().getPrivateDnsServerName());
5101         Set<InetAddress> dnsServers = new HashSet<>();
5102         checkDnsServers(cbi.getLp(), dnsServers);
5103 
5104         // Send a validation event for a server that is not part of the current
5105         // resolver config. The validation event should be ignored.
5106         mService.mNetdEventCallback.onPrivateDnsValidationEvent(
5107                 mCellNetworkAgent.getNetwork().netId, "", "145.100.185.18", true);
5108         cellNetworkCallback.assertNoCallback();
5109 
5110         // Add a dns server to the LinkProperties.
5111         LinkProperties lp2 = new LinkProperties(lp);
5112         lp2.addDnsServer(InetAddress.getByName("145.100.185.16"));
5113         mCellNetworkAgent.sendLinkProperties(lp2);
5114         cbi = cellNetworkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED,
5115                 mCellNetworkAgent);
5116         cellNetworkCallback.assertNoCallback();
5117         assertFalse(cbi.getLp().isPrivateDnsActive());
5118         assertNull(cbi.getLp().getPrivateDnsServerName());
5119         dnsServers.add(InetAddress.getByName("145.100.185.16"));
5120         checkDnsServers(cbi.getLp(), dnsServers);
5121 
5122         // Send a validation event containing a hostname that is not part of
5123         // the current resolver config. The validation event should be ignored.
5124         mService.mNetdEventCallback.onPrivateDnsValidationEvent(
5125                 mCellNetworkAgent.getNetwork().netId, "145.100.185.16", "hostname", true);
5126         cellNetworkCallback.assertNoCallback();
5127 
5128         // Send a validation event where validation failed.
5129         mService.mNetdEventCallback.onPrivateDnsValidationEvent(
5130                 mCellNetworkAgent.getNetwork().netId, "145.100.185.16", "", false);
5131         cellNetworkCallback.assertNoCallback();
5132 
5133         // Send a validation event where validation succeeded for a server in
5134         // the current resolver config. A LinkProperties callback with updated
5135         // private dns fields should be sent.
5136         mService.mNetdEventCallback.onPrivateDnsValidationEvent(
5137                 mCellNetworkAgent.getNetwork().netId, "145.100.185.16", "", true);
5138         cbi = cellNetworkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED,
5139                 mCellNetworkAgent);
5140         cellNetworkCallback.assertNoCallback();
5141         assertTrue(cbi.getLp().isPrivateDnsActive());
5142         assertNull(cbi.getLp().getPrivateDnsServerName());
5143         checkDnsServers(cbi.getLp(), dnsServers);
5144 
5145         // The private dns fields in LinkProperties should be preserved when
5146         // the network agent sends unrelated changes.
5147         LinkProperties lp3 = new LinkProperties(lp2);
5148         lp3.setMtu(1300);
5149         mCellNetworkAgent.sendLinkProperties(lp3);
5150         cbi = cellNetworkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED,
5151                 mCellNetworkAgent);
5152         cellNetworkCallback.assertNoCallback();
5153         assertTrue(cbi.getLp().isPrivateDnsActive());
5154         assertNull(cbi.getLp().getPrivateDnsServerName());
5155         checkDnsServers(cbi.getLp(), dnsServers);
5156         assertEquals(1300, cbi.getLp().getMtu());
5157 
5158         // Removing the only validated server should affect the private dns
5159         // fields in LinkProperties.
5160         LinkProperties lp4 = new LinkProperties(lp3);
5161         lp4.removeDnsServer(InetAddress.getByName("145.100.185.16"));
5162         mCellNetworkAgent.sendLinkProperties(lp4);
5163         cbi = cellNetworkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED,
5164                 mCellNetworkAgent);
5165         cellNetworkCallback.assertNoCallback();
5166         assertFalse(cbi.getLp().isPrivateDnsActive());
5167         assertNull(cbi.getLp().getPrivateDnsServerName());
5168         dnsServers.remove(InetAddress.getByName("145.100.185.16"));
5169         checkDnsServers(cbi.getLp(), dnsServers);
5170         assertEquals(1300, cbi.getLp().getMtu());
5171     }
5172 
checkDirectlyConnectedRoutes(Object callbackObj, Collection<LinkAddress> linkAddresses, Collection<RouteInfo> otherRoutes)5173     private void checkDirectlyConnectedRoutes(Object callbackObj,
5174             Collection<LinkAddress> linkAddresses, Collection<RouteInfo> otherRoutes) {
5175         assertTrue(callbackObj instanceof LinkProperties);
5176         LinkProperties lp = (LinkProperties) callbackObj;
5177 
5178         Set<RouteInfo> expectedRoutes = new ArraySet<>();
5179         expectedRoutes.addAll(otherRoutes);
5180         for (LinkAddress address : linkAddresses) {
5181             RouteInfo localRoute = new RouteInfo(address, null, lp.getInterfaceName());
5182             // Duplicates in linkAddresses are considered failures
5183             assertTrue(expectedRoutes.add(localRoute));
5184         }
5185         List<RouteInfo> observedRoutes = lp.getRoutes();
5186         assertEquals(expectedRoutes.size(), observedRoutes.size());
5187         assertTrue(observedRoutes.containsAll(expectedRoutes));
5188     }
5189 
checkDnsServers(Object callbackObj, Set<InetAddress> dnsServers)5190     private static void checkDnsServers(Object callbackObj, Set<InetAddress> dnsServers) {
5191         assertTrue(callbackObj instanceof LinkProperties);
5192         LinkProperties lp = (LinkProperties) callbackObj;
5193         assertEquals(dnsServers.size(), lp.getDnsServers().size());
5194         assertTrue(lp.getDnsServers().containsAll(dnsServers));
5195     }
5196 
5197     @Test
testVpnNetworkActive()5198     public void testVpnNetworkActive() throws Exception {
5199         final int uid = Process.myUid();
5200 
5201         final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback();
5202         final TestNetworkCallback genericNotVpnNetworkCallback = new TestNetworkCallback();
5203         final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
5204         final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
5205         final TestNetworkCallback defaultCallback = new TestNetworkCallback();
5206         final NetworkRequest genericNotVpnRequest = new NetworkRequest.Builder().build();
5207         final NetworkRequest genericRequest = new NetworkRequest.Builder()
5208                 .removeCapability(NET_CAPABILITY_NOT_VPN).build();
5209         final NetworkRequest wifiRequest = new NetworkRequest.Builder()
5210                 .addTransportType(TRANSPORT_WIFI).build();
5211         final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder()
5212                 .removeCapability(NET_CAPABILITY_NOT_VPN)
5213                 .addTransportType(TRANSPORT_VPN).build();
5214         mCm.registerNetworkCallback(genericRequest, genericNetworkCallback);
5215         mCm.registerNetworkCallback(genericNotVpnRequest, genericNotVpnNetworkCallback);
5216         mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
5217         mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
5218         mCm.registerDefaultNetworkCallback(defaultCallback);
5219         defaultCallback.assertNoCallback();
5220 
5221         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
5222         mWiFiNetworkAgent.connect(false);
5223 
5224         genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
5225         genericNotVpnNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
5226         wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
5227         defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
5228         vpnNetworkCallback.assertNoCallback();
5229         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
5230 
5231         final TestNetworkAgentWrapper
5232                 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
5233         final ArraySet<UidRange> ranges = new ArraySet<>();
5234         ranges.add(new UidRange(uid, uid));
5235         mMockVpn.setNetworkAgent(vpnNetworkAgent);
5236         mMockVpn.setUids(ranges);
5237         // VPN networks do not satisfy the default request and are automatically validated
5238         // by NetworkMonitor
5239         assertFalse(NetworkMonitorUtils.isValidationRequired(
5240                 vpnNetworkAgent.getNetworkCapabilities()));
5241         vpnNetworkAgent.setNetworkValid(false /* isStrictMode */);
5242 
5243         vpnNetworkAgent.connect(false);
5244         mMockVpn.connect();
5245         mMockVpn.setUnderlyingNetworks(new Network[0]);
5246 
5247         genericNetworkCallback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
5248         genericNotVpnNetworkCallback.assertNoCallback();
5249         wifiNetworkCallback.assertNoCallback();
5250         vpnNetworkCallback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
5251         defaultCallback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
5252         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
5253 
5254         genericNetworkCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, vpnNetworkAgent);
5255         genericNotVpnNetworkCallback.assertNoCallback();
5256         vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent, nc -> null == nc.getUids());
5257         defaultCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, vpnNetworkAgent);
5258         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
5259 
5260         ranges.clear();
5261         vpnNetworkAgent.setUids(ranges);
5262 
5263         genericNetworkCallback.expectCallback(CallbackEntry.LOST, vpnNetworkAgent);
5264         genericNotVpnNetworkCallback.assertNoCallback();
5265         wifiNetworkCallback.assertNoCallback();
5266         vpnNetworkCallback.expectCallback(CallbackEntry.LOST, vpnNetworkAgent);
5267 
5268         // TODO : The default network callback should actually get a LOST call here (also see the
5269         // comment below for AVAILABLE). This is because ConnectivityService does not look at UID
5270         // ranges at all when determining whether a network should be rematched. In practice, VPNs
5271         // can't currently update their UIDs without disconnecting, so this does not matter too
5272         // much, but that is the reason the test here has to check for an update to the
5273         // capabilities instead of the expected LOST then AVAILABLE.
5274         defaultCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, vpnNetworkAgent);
5275 
5276         ranges.add(new UidRange(uid, uid));
5277         mMockVpn.setUids(ranges);
5278         vpnNetworkAgent.setUids(ranges);
5279 
5280         genericNetworkCallback.expectAvailableCallbacksValidated(vpnNetworkAgent);
5281         genericNotVpnNetworkCallback.assertNoCallback();
5282         wifiNetworkCallback.assertNoCallback();
5283         vpnNetworkCallback.expectAvailableCallbacksValidated(vpnNetworkAgent);
5284         // TODO : Here like above, AVAILABLE would be correct, but because this can't actually
5285         // happen outside of the test, ConnectivityService does not rematch callbacks.
5286         defaultCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, vpnNetworkAgent);
5287 
5288         mWiFiNetworkAgent.disconnect();
5289 
5290         genericNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
5291         genericNotVpnNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
5292         wifiNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
5293         vpnNetworkCallback.assertNoCallback();
5294         defaultCallback.assertNoCallback();
5295 
5296         vpnNetworkAgent.disconnect();
5297 
5298         genericNetworkCallback.expectCallback(CallbackEntry.LOST, vpnNetworkAgent);
5299         genericNotVpnNetworkCallback.assertNoCallback();
5300         wifiNetworkCallback.assertNoCallback();
5301         vpnNetworkCallback.expectCallback(CallbackEntry.LOST, vpnNetworkAgent);
5302         defaultCallback.expectCallback(CallbackEntry.LOST, vpnNetworkAgent);
5303         assertEquals(null, mCm.getActiveNetwork());
5304 
5305         mCm.unregisterNetworkCallback(genericNetworkCallback);
5306         mCm.unregisterNetworkCallback(wifiNetworkCallback);
5307         mCm.unregisterNetworkCallback(vpnNetworkCallback);
5308         mCm.unregisterNetworkCallback(defaultCallback);
5309     }
5310 
5311     @Test
testVpnWithoutInternet()5312     public void testVpnWithoutInternet() throws Exception {
5313         final int uid = Process.myUid();
5314 
5315         final TestNetworkCallback defaultCallback = new TestNetworkCallback();
5316         mCm.registerDefaultNetworkCallback(defaultCallback);
5317 
5318         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
5319         mWiFiNetworkAgent.connect(true);
5320 
5321         defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
5322         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
5323 
5324         TestNetworkAgentWrapper
5325                 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
5326         final ArraySet<UidRange> ranges = new ArraySet<>();
5327         ranges.add(new UidRange(uid, uid));
5328         mMockVpn.setNetworkAgent(vpnNetworkAgent);
5329         mMockVpn.setUids(ranges);
5330         vpnNetworkAgent.connect(true /* validated */, false /* hasInternet */,
5331                 false /* isStrictMode */);
5332         mMockVpn.connect();
5333 
5334         defaultCallback.assertNoCallback();
5335         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
5336 
5337         vpnNetworkAgent.disconnect();
5338         defaultCallback.assertNoCallback();
5339 
5340         mCm.unregisterNetworkCallback(defaultCallback);
5341     }
5342 
5343     @Test
testVpnWithInternet()5344     public void testVpnWithInternet() throws Exception {
5345         final int uid = Process.myUid();
5346 
5347         final TestNetworkCallback defaultCallback = new TestNetworkCallback();
5348         mCm.registerDefaultNetworkCallback(defaultCallback);
5349 
5350         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
5351         mWiFiNetworkAgent.connect(true);
5352 
5353         defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
5354         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
5355 
5356         TestNetworkAgentWrapper
5357                 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
5358         final ArraySet<UidRange> ranges = new ArraySet<>();
5359         ranges.add(new UidRange(uid, uid));
5360         mMockVpn.setNetworkAgent(vpnNetworkAgent);
5361         mMockVpn.setUids(ranges);
5362         vpnNetworkAgent.connect(true /* validated */, true /* hasInternet */,
5363                 false /* isStrictMode */);
5364         mMockVpn.connect();
5365 
5366         defaultCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
5367         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
5368 
5369         vpnNetworkAgent.disconnect();
5370         defaultCallback.expectCallback(CallbackEntry.LOST, vpnNetworkAgent);
5371         defaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
5372 
5373         mCm.unregisterNetworkCallback(defaultCallback);
5374     }
5375 
5376     @Test
testVpnUnvalidated()5377     public void testVpnUnvalidated() throws Exception {
5378         final TestNetworkCallback callback = new TestNetworkCallback();
5379         mCm.registerDefaultNetworkCallback(callback);
5380 
5381         // Bring up Ethernet.
5382         mEthernetNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
5383         mEthernetNetworkAgent.connect(true);
5384         callback.expectAvailableThenValidatedCallbacks(mEthernetNetworkAgent);
5385         callback.assertNoCallback();
5386 
5387         // Bring up a VPN that has the INTERNET capability, initially unvalidated.
5388         final int uid = Process.myUid();
5389         final TestNetworkAgentWrapper
5390                 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
5391         final ArraySet<UidRange> ranges = new ArraySet<>();
5392         ranges.add(new UidRange(uid, uid));
5393         mMockVpn.setNetworkAgent(vpnNetworkAgent);
5394         mMockVpn.setUids(ranges);
5395         vpnNetworkAgent.connect(false /* validated */, true /* hasInternet */,
5396                 false /* isStrictMode */);
5397         mMockVpn.connect();
5398 
5399         // Even though the VPN is unvalidated, it becomes the default network for our app.
5400         callback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
5401         callback.assertNoCallback();
5402 
5403         assertTrue(vpnNetworkAgent.getScore() > mEthernetNetworkAgent.getScore());
5404         assertEquals(ConnectivityConstants.VPN_DEFAULT_SCORE, vpnNetworkAgent.getScore());
5405         assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
5406 
5407         NetworkCapabilities nc = mCm.getNetworkCapabilities(vpnNetworkAgent.getNetwork());
5408         assertFalse(nc.hasCapability(NET_CAPABILITY_VALIDATED));
5409         assertTrue(nc.hasCapability(NET_CAPABILITY_INTERNET));
5410 
5411         assertFalse(NetworkMonitorUtils.isValidationRequired(
5412                 vpnNetworkAgent.getNetworkCapabilities()));
5413         assertTrue(NetworkMonitorUtils.isPrivateDnsValidationRequired(
5414                 vpnNetworkAgent.getNetworkCapabilities()));
5415 
5416         // Pretend that the VPN network validates.
5417         vpnNetworkAgent.setNetworkValid(false /* isStrictMode */);
5418         vpnNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
5419         // Expect to see the validated capability, but no other changes, because the VPN is already
5420         // the default network for the app.
5421         callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, vpnNetworkAgent);
5422         callback.assertNoCallback();
5423 
5424         vpnNetworkAgent.disconnect();
5425         callback.expectCallback(CallbackEntry.LOST, vpnNetworkAgent);
5426         callback.expectAvailableCallbacksValidated(mEthernetNetworkAgent);
5427     }
5428 
5429     @Test
testVpnStartsWithUnderlyingCaps()5430     public void testVpnStartsWithUnderlyingCaps() throws Exception {
5431         final int uid = Process.myUid();
5432 
5433         final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
5434         final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder()
5435                 .removeCapability(NET_CAPABILITY_NOT_VPN)
5436                 .addTransportType(TRANSPORT_VPN)
5437                 .build();
5438         mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
5439         vpnNetworkCallback.assertNoCallback();
5440 
5441         // Connect cell. It will become the default network, and in the absence of setting
5442         // underlying networks explicitly it will become the sole underlying network for the vpn.
5443         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
5444         mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_SUSPENDED);
5445         mCellNetworkAgent.connect(true);
5446 
5447         final TestNetworkAgentWrapper vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
5448         final ArraySet<UidRange> ranges = new ArraySet<>();
5449         ranges.add(new UidRange(uid, uid));
5450         mMockVpn.setNetworkAgent(vpnNetworkAgent);
5451         mMockVpn.connect();
5452         mMockVpn.setUids(ranges);
5453         vpnNetworkAgent.connect(true /* validated */, false /* hasInternet */,
5454                 false /* isStrictMode */);
5455 
5456         vpnNetworkCallback.expectAvailableCallbacks(vpnNetworkAgent.getNetwork(),
5457                 false /* suspended */, false /* validated */, false /* blocked */, TIMEOUT_MS);
5458         vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent.getNetwork(), TIMEOUT_MS,
5459                 nc -> nc.hasCapability(NET_CAPABILITY_VALIDATED));
5460 
5461         final NetworkCapabilities nc = mCm.getNetworkCapabilities(vpnNetworkAgent.getNetwork());
5462         assertTrue(nc.hasTransport(TRANSPORT_VPN));
5463         assertTrue(nc.hasTransport(TRANSPORT_CELLULAR));
5464         assertFalse(nc.hasTransport(TRANSPORT_WIFI));
5465         assertTrue(nc.hasCapability(NET_CAPABILITY_VALIDATED));
5466         assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED));
5467         assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
5468     }
5469 
5470     @Test
testVpnSetUnderlyingNetworks()5471     public void testVpnSetUnderlyingNetworks() throws Exception {
5472         final int uid = Process.myUid();
5473 
5474         final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
5475         final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder()
5476                 .removeCapability(NET_CAPABILITY_NOT_VPN)
5477                 .addTransportType(TRANSPORT_VPN)
5478                 .build();
5479         NetworkCapabilities nc;
5480         mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
5481         vpnNetworkCallback.assertNoCallback();
5482 
5483         final TestNetworkAgentWrapper
5484                 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
5485         final ArraySet<UidRange> ranges = new ArraySet<>();
5486         ranges.add(new UidRange(uid, uid));
5487         mMockVpn.setNetworkAgent(vpnNetworkAgent);
5488         mMockVpn.connect();
5489         mMockVpn.setUids(ranges);
5490         vpnNetworkAgent.connect(true /* validated */, false /* hasInternet */,
5491                 false /* isStrictMode */);
5492 
5493         vpnNetworkCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
5494         nc = mCm.getNetworkCapabilities(vpnNetworkAgent.getNetwork());
5495         assertTrue(nc.hasTransport(TRANSPORT_VPN));
5496         assertFalse(nc.hasTransport(TRANSPORT_CELLULAR));
5497         assertFalse(nc.hasTransport(TRANSPORT_WIFI));
5498         // For safety reasons a VPN without underlying networks is considered metered.
5499         assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED));
5500         // A VPN without underlying networks is not suspended.
5501         assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
5502 
5503         // Connect cell and use it as an underlying network.
5504         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
5505         mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_SUSPENDED);
5506         mCellNetworkAgent.connect(true);
5507 
5508         mService.setUnderlyingNetworksForVpn(
5509                 new Network[] { mCellNetworkAgent.getNetwork() });
5510 
5511         vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
5512                 (caps) -> caps.hasTransport(TRANSPORT_VPN)
5513                 && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
5514                 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED)
5515                 && caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
5516 
5517         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
5518         mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5519         mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_SUSPENDED);
5520         mWiFiNetworkAgent.connect(true);
5521 
5522         mService.setUnderlyingNetworksForVpn(
5523                 new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() });
5524 
5525         vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
5526                 (caps) -> caps.hasTransport(TRANSPORT_VPN)
5527                 && caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
5528                 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED)
5529                 && caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
5530 
5531         // Don't disconnect, but note the VPN is not using wifi any more.
5532         mService.setUnderlyingNetworksForVpn(
5533                 new Network[] { mCellNetworkAgent.getNetwork() });
5534 
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 
5541         // Remove NOT_SUSPENDED from the only network and observe VPN is now suspended.
5542         mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_SUSPENDED);
5543         vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
5544                 (caps) -> caps.hasTransport(TRANSPORT_VPN)
5545                 && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
5546                 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED)
5547                 && !caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
5548         vpnNetworkCallback.expectCallback(CallbackEntry.SUSPENDED, vpnNetworkAgent);
5549 
5550         // Add NOT_SUSPENDED again and observe VPN is no longer suspended.
5551         mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_SUSPENDED);
5552         vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
5553                 (caps) -> caps.hasTransport(TRANSPORT_VPN)
5554                 && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
5555                 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED)
5556                 && caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
5557         vpnNetworkCallback.expectCallback(CallbackEntry.RESUMED, vpnNetworkAgent);
5558 
5559         // Use Wifi but not cell. Note the VPN is now unmetered and not suspended.
5560         mService.setUnderlyingNetworksForVpn(
5561                 new Network[] { mWiFiNetworkAgent.getNetwork() });
5562 
5563         vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
5564                 (caps) -> caps.hasTransport(TRANSPORT_VPN)
5565                 && !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
5566                 && caps.hasCapability(NET_CAPABILITY_NOT_METERED)
5567                 && caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
5568 
5569         // Use both again.
5570         mService.setUnderlyingNetworksForVpn(
5571                 new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() });
5572 
5573         vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
5574                 (caps) -> caps.hasTransport(TRANSPORT_VPN)
5575                 && caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
5576                 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED)
5577                 && caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
5578 
5579         // Cell is suspended again. As WiFi is not, this should not cause a callback.
5580         mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_SUSPENDED);
5581         vpnNetworkCallback.assertNoCallback();
5582 
5583         // Stop using WiFi. The VPN is suspended again.
5584         mService.setUnderlyingNetworksForVpn(
5585                 new Network[] { mCellNetworkAgent.getNetwork() });
5586         vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
5587                 (caps) -> caps.hasTransport(TRANSPORT_VPN)
5588                 && caps.hasTransport(TRANSPORT_CELLULAR)
5589                 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED)
5590                 && !caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
5591         // While the SUSPENDED callback should in theory be sent here, it is not. This is
5592         // a bug in ConnectivityService, but as the SUSPENDED and RESUMED callbacks have never
5593         // been public and are deprecated and slated for removal, there is no sense in spending
5594         // resources fixing this bug now.
5595 
5596         // Use both again.
5597         mService.setUnderlyingNetworksForVpn(
5598                 new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() });
5599 
5600         vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
5601                 (caps) -> caps.hasTransport(TRANSPORT_VPN)
5602                 && caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
5603                 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED)
5604                 && caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
5605         // As above, the RESUMED callback not being sent here is a bug, but not a bug that's
5606         // worth anybody's time to fix.
5607 
5608         // Disconnect cell. Receive update without even removing the dead network from the
5609         // underlying networks – it's dead anyway. Not metered any more.
5610         mCellNetworkAgent.disconnect();
5611         vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
5612                 (caps) -> caps.hasTransport(TRANSPORT_VPN)
5613                 && !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
5614                 && caps.hasCapability(NET_CAPABILITY_NOT_METERED));
5615 
5616         // Disconnect wifi too. No underlying networks means this is now metered.
5617         mWiFiNetworkAgent.disconnect();
5618         vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
5619                 (caps) -> caps.hasTransport(TRANSPORT_VPN)
5620                 && !caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
5621                 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED));
5622 
5623         mMockVpn.disconnect();
5624     }
5625 
5626     @Test
testNullUnderlyingNetworks()5627     public void testNullUnderlyingNetworks() throws Exception {
5628         final int uid = Process.myUid();
5629 
5630         final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
5631         final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder()
5632                 .removeCapability(NET_CAPABILITY_NOT_VPN)
5633                 .addTransportType(TRANSPORT_VPN)
5634                 .build();
5635         NetworkCapabilities nc;
5636         mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
5637         vpnNetworkCallback.assertNoCallback();
5638 
5639         final TestNetworkAgentWrapper
5640                 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
5641         final ArraySet<UidRange> ranges = new ArraySet<>();
5642         ranges.add(new UidRange(uid, uid));
5643         mMockVpn.setNetworkAgent(vpnNetworkAgent);
5644         mMockVpn.connect();
5645         mMockVpn.setUids(ranges);
5646         vpnNetworkAgent.connect(true /* validated */, false /* hasInternet */,
5647                 false /* isStrictMode */);
5648 
5649         vpnNetworkCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
5650         nc = mCm.getNetworkCapabilities(vpnNetworkAgent.getNetwork());
5651         assertTrue(nc.hasTransport(TRANSPORT_VPN));
5652         assertFalse(nc.hasTransport(TRANSPORT_CELLULAR));
5653         assertFalse(nc.hasTransport(TRANSPORT_WIFI));
5654         // By default, VPN is set to track default network (i.e. its underlying networks is null).
5655         // In case of no default network, VPN is considered metered.
5656         assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED));
5657 
5658         // Connect to Cell; Cell is the default network.
5659         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
5660         mCellNetworkAgent.connect(true);
5661 
5662         vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
5663                 (caps) -> caps.hasTransport(TRANSPORT_VPN)
5664                 && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
5665                 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED));
5666 
5667         // Connect to WiFi; WiFi is the new default.
5668         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
5669         mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5670         mWiFiNetworkAgent.connect(true);
5671 
5672         vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
5673                 (caps) -> caps.hasTransport(TRANSPORT_VPN)
5674                 && !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
5675                 && caps.hasCapability(NET_CAPABILITY_NOT_METERED));
5676 
5677         // Disconnect Cell. The default network did not change, so there shouldn't be any changes in
5678         // the capabilities.
5679         mCellNetworkAgent.disconnect();
5680 
5681         // Disconnect wifi too. Now we have no default network.
5682         mWiFiNetworkAgent.disconnect();
5683 
5684         vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
5685                 (caps) -> caps.hasTransport(TRANSPORT_VPN)
5686                 && !caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
5687                 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED));
5688 
5689         mMockVpn.disconnect();
5690     }
5691 
5692     @Test
testIsActiveNetworkMeteredOverWifi()5693     public void testIsActiveNetworkMeteredOverWifi() throws Exception {
5694         // Returns true by default when no network is available.
5695         assertTrue(mCm.isActiveNetworkMetered());
5696         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
5697         mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5698         mWiFiNetworkAgent.connect(true);
5699         waitForIdle();
5700 
5701         assertFalse(mCm.isActiveNetworkMetered());
5702     }
5703 
5704     @Test
testIsActiveNetworkMeteredOverCell()5705     public void testIsActiveNetworkMeteredOverCell() throws Exception {
5706         // Returns true by default when no network is available.
5707         assertTrue(mCm.isActiveNetworkMetered());
5708         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
5709         mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
5710         mCellNetworkAgent.connect(true);
5711         waitForIdle();
5712 
5713         assertTrue(mCm.isActiveNetworkMetered());
5714     }
5715 
5716     @Test
testIsActiveNetworkMeteredOverVpnTrackingPlatformDefault()5717     public void testIsActiveNetworkMeteredOverVpnTrackingPlatformDefault() throws Exception {
5718         // Returns true by default when no network is available.
5719         assertTrue(mCm.isActiveNetworkMetered());
5720         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
5721         mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
5722         mCellNetworkAgent.connect(true);
5723         waitForIdle();
5724         assertTrue(mCm.isActiveNetworkMetered());
5725 
5726         // Connect VPN network. By default it is using current default network (Cell).
5727         TestNetworkAgentWrapper
5728                 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
5729         final ArraySet<UidRange> ranges = new ArraySet<>();
5730         final int uid = Process.myUid();
5731         ranges.add(new UidRange(uid, uid));
5732         mMockVpn.setNetworkAgent(vpnNetworkAgent);
5733         mMockVpn.setUids(ranges);
5734         vpnNetworkAgent.connect(true);
5735         mMockVpn.connect();
5736         waitForIdle();
5737         // Ensure VPN is now the active network.
5738         assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
5739 
5740         // Expect VPN to be metered.
5741         assertTrue(mCm.isActiveNetworkMetered());
5742 
5743         // Connect WiFi.
5744         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
5745         mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5746         mWiFiNetworkAgent.connect(true);
5747         waitForIdle();
5748         // VPN should still be the active network.
5749         assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
5750 
5751         // Expect VPN to be unmetered as it should now be using WiFi (new default).
5752         assertFalse(mCm.isActiveNetworkMetered());
5753 
5754         // Disconnecting Cell should not affect VPN's meteredness.
5755         mCellNetworkAgent.disconnect();
5756         waitForIdle();
5757 
5758         assertFalse(mCm.isActiveNetworkMetered());
5759 
5760         // Disconnect WiFi; Now there is no platform default network.
5761         mWiFiNetworkAgent.disconnect();
5762         waitForIdle();
5763 
5764         // VPN without any underlying networks is treated as metered.
5765         assertTrue(mCm.isActiveNetworkMetered());
5766 
5767         vpnNetworkAgent.disconnect();
5768         mMockVpn.disconnect();
5769     }
5770 
5771    @Test
testIsActiveNetworkMeteredOverVpnSpecifyingUnderlyingNetworks()5772    public void testIsActiveNetworkMeteredOverVpnSpecifyingUnderlyingNetworks() throws Exception {
5773         // Returns true by default when no network is available.
5774         assertTrue(mCm.isActiveNetworkMetered());
5775         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
5776         mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
5777         mCellNetworkAgent.connect(true);
5778         waitForIdle();
5779         assertTrue(mCm.isActiveNetworkMetered());
5780 
5781         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
5782         mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5783         mWiFiNetworkAgent.connect(true);
5784         waitForIdle();
5785         assertFalse(mCm.isActiveNetworkMetered());
5786 
5787         // Connect VPN network.
5788         TestNetworkAgentWrapper
5789                 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
5790         final ArraySet<UidRange> ranges = new ArraySet<>();
5791         final int uid = Process.myUid();
5792         ranges.add(new UidRange(uid, uid));
5793         mMockVpn.setNetworkAgent(vpnNetworkAgent);
5794         mMockVpn.setUids(ranges);
5795         vpnNetworkAgent.connect(true);
5796         mMockVpn.connect();
5797         waitForIdle();
5798         // Ensure VPN is now the active network.
5799         assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
5800         // VPN is using Cell
5801         mService.setUnderlyingNetworksForVpn(
5802                 new Network[] { mCellNetworkAgent.getNetwork() });
5803         waitForIdle();
5804 
5805         // Expect VPN to be metered.
5806         assertTrue(mCm.isActiveNetworkMetered());
5807 
5808         // VPN is now using WiFi
5809         mService.setUnderlyingNetworksForVpn(
5810                 new Network[] { mWiFiNetworkAgent.getNetwork() });
5811         waitForIdle();
5812 
5813         // Expect VPN to be unmetered
5814         assertFalse(mCm.isActiveNetworkMetered());
5815 
5816         // VPN is using Cell | WiFi.
5817         mService.setUnderlyingNetworksForVpn(
5818                 new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() });
5819         waitForIdle();
5820 
5821         // Expect VPN to be metered.
5822         assertTrue(mCm.isActiveNetworkMetered());
5823 
5824         // VPN is using WiFi | Cell.
5825         mService.setUnderlyingNetworksForVpn(
5826                 new Network[] { mWiFiNetworkAgent.getNetwork(), mCellNetworkAgent.getNetwork() });
5827         waitForIdle();
5828 
5829         // Order should not matter and VPN should still be metered.
5830         assertTrue(mCm.isActiveNetworkMetered());
5831 
5832         // VPN is not using any underlying networks.
5833         mService.setUnderlyingNetworksForVpn(new Network[0]);
5834         waitForIdle();
5835 
5836         // VPN without underlying networks is treated as metered.
5837         assertTrue(mCm.isActiveNetworkMetered());
5838 
5839         vpnNetworkAgent.disconnect();
5840         mMockVpn.disconnect();
5841     }
5842 
5843     @Test
testIsActiveNetworkMeteredOverAlwaysMeteredVpn()5844     public void testIsActiveNetworkMeteredOverAlwaysMeteredVpn() throws Exception {
5845         // Returns true by default when no network is available.
5846         assertTrue(mCm.isActiveNetworkMetered());
5847         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
5848         mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5849         mWiFiNetworkAgent.connect(true);
5850         waitForIdle();
5851         assertFalse(mCm.isActiveNetworkMetered());
5852 
5853         // Connect VPN network.
5854         TestNetworkAgentWrapper
5855                 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
5856         final ArraySet<UidRange> ranges = new ArraySet<>();
5857         final int uid = Process.myUid();
5858         ranges.add(new UidRange(uid, uid));
5859         mMockVpn.setNetworkAgent(vpnNetworkAgent);
5860         mMockVpn.setUids(ranges);
5861         vpnNetworkAgent.connect(true);
5862         mMockVpn.connectAsAlwaysMetered();
5863         waitForIdle();
5864         assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
5865 
5866         // VPN is tracking current platform default (WiFi).
5867         mService.setUnderlyingNetworksForVpn(null);
5868         waitForIdle();
5869 
5870         // Despite VPN using WiFi (which is unmetered), VPN itself is marked as always metered.
5871         assertTrue(mCm.isActiveNetworkMetered());
5872 
5873         // VPN explicitly declares WiFi as its underlying network.
5874         mService.setUnderlyingNetworksForVpn(
5875                 new Network[] { mWiFiNetworkAgent.getNetwork() });
5876         waitForIdle();
5877 
5878         // Doesn't really matter whether VPN declares its underlying networks explicitly.
5879         assertTrue(mCm.isActiveNetworkMetered());
5880 
5881         // With WiFi lost, VPN is basically without any underlying networks. And in that case it is
5882         // anyways suppose to be metered.
5883         mWiFiNetworkAgent.disconnect();
5884         waitForIdle();
5885 
5886         assertTrue(mCm.isActiveNetworkMetered());
5887 
5888         vpnNetworkAgent.disconnect();
5889     }
5890 
5891     @Test
testNetworkBlockedStatus()5892     public void testNetworkBlockedStatus() throws Exception {
5893         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
5894         final NetworkRequest cellRequest = new NetworkRequest.Builder()
5895                 .addTransportType(TRANSPORT_CELLULAR)
5896                 .build();
5897         mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
5898 
5899         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
5900         mCellNetworkAgent.connect(true);
5901         cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
5902 
5903         setUidRulesChanged(RULE_REJECT_ALL);
5904         cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
5905 
5906         // ConnectivityService should cache it not to invoke the callback again.
5907         setUidRulesChanged(RULE_REJECT_METERED);
5908         cellNetworkCallback.assertNoCallback();
5909 
5910         setUidRulesChanged(RULE_NONE);
5911         cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
5912 
5913         setUidRulesChanged(RULE_REJECT_METERED);
5914         cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
5915 
5916         // Restrict the network based on UID rule and NOT_METERED capability change.
5917         mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5918         cellNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_NOT_METERED, mCellNetworkAgent);
5919         cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
5920         mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
5921         cellNetworkCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_METERED,
5922                 mCellNetworkAgent);
5923         cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
5924         setUidRulesChanged(RULE_ALLOW_METERED);
5925         cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
5926 
5927         setUidRulesChanged(RULE_NONE);
5928         cellNetworkCallback.assertNoCallback();
5929 
5930         // Restrict the network based on BackgroundRestricted.
5931         setRestrictBackgroundChanged(true);
5932         cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
5933         setRestrictBackgroundChanged(true);
5934         cellNetworkCallback.assertNoCallback();
5935         setRestrictBackgroundChanged(false);
5936         cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
5937         cellNetworkCallback.assertNoCallback();
5938 
5939         mCm.unregisterNetworkCallback(cellNetworkCallback);
5940     }
5941 
5942     @Test
testNetworkBlockedStatusBeforeAndAfterConnect()5943     public void testNetworkBlockedStatusBeforeAndAfterConnect() throws Exception {
5944         final TestNetworkCallback defaultCallback = new TestNetworkCallback();
5945         mCm.registerDefaultNetworkCallback(defaultCallback);
5946 
5947         // No Networkcallbacks invoked before any network is active.
5948         setUidRulesChanged(RULE_REJECT_ALL);
5949         setUidRulesChanged(RULE_NONE);
5950         setUidRulesChanged(RULE_REJECT_METERED);
5951         defaultCallback.assertNoCallback();
5952 
5953         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
5954         mCellNetworkAgent.connect(true);
5955         defaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mCellNetworkAgent);
5956         defaultCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mCellNetworkAgent);
5957 
5958         // Allow to use the network after switching to NOT_METERED network.
5959         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
5960         mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5961         mWiFiNetworkAgent.connect(true);
5962         defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
5963 
5964         // Switch to METERED network. Restrict the use of the network.
5965         mWiFiNetworkAgent.disconnect();
5966         defaultCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
5967         defaultCallback.expectAvailableCallbacksValidatedAndBlocked(mCellNetworkAgent);
5968 
5969         // Network becomes NOT_METERED.
5970         mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5971         defaultCallback.expectCapabilitiesWith(NET_CAPABILITY_NOT_METERED, mCellNetworkAgent);
5972         defaultCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
5973 
5974         // Verify there's no Networkcallbacks invoked after data saver on/off.
5975         setRestrictBackgroundChanged(true);
5976         setRestrictBackgroundChanged(false);
5977         defaultCallback.assertNoCallback();
5978 
5979         mCellNetworkAgent.disconnect();
5980         defaultCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
5981         defaultCallback.assertNoCallback();
5982 
5983         mCm.unregisterNetworkCallback(defaultCallback);
5984     }
5985 
5986     @Test
testLoseTrusted()5987     public final void testLoseTrusted() throws Exception {
5988         final NetworkRequest trustedRequest = new NetworkRequest.Builder()
5989                 .addCapability(NET_CAPABILITY_TRUSTED)
5990                 .build();
5991         final TestNetworkCallback trustedCallback = new TestNetworkCallback();
5992         mCm.requestNetwork(trustedRequest, trustedCallback);
5993 
5994         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
5995         mCellNetworkAgent.connect(true);
5996         trustedCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
5997         verify(mNetworkManagementService).setDefaultNetId(eq(mCellNetworkAgent.getNetwork().netId));
5998         reset(mNetworkManagementService);
5999 
6000         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
6001         mWiFiNetworkAgent.connect(true);
6002         trustedCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
6003         verify(mNetworkManagementService).setDefaultNetId(eq(mWiFiNetworkAgent.getNetwork().netId));
6004         reset(mNetworkManagementService);
6005 
6006         mWiFiNetworkAgent.removeCapability(NET_CAPABILITY_TRUSTED);
6007         trustedCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
6008         verify(mNetworkManagementService).setDefaultNetId(eq(mCellNetworkAgent.getNetwork().netId));
6009         reset(mNetworkManagementService);
6010 
6011         mCellNetworkAgent.removeCapability(NET_CAPABILITY_TRUSTED);
6012         trustedCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
6013         verify(mNetworkManagementService).clearDefaultNetId();
6014 
6015         mCm.unregisterNetworkCallback(trustedCallback);
6016     }
6017 
6018     @Ignore // 40%+ flakiness : figure out why and re-enable.
6019     @Test
testBatteryStatsNetworkType()6020     public final void testBatteryStatsNetworkType() throws Exception {
6021         final LinkProperties cellLp = new LinkProperties();
6022         cellLp.setInterfaceName("cell0");
6023         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
6024         mCellNetworkAgent.connect(true);
6025         waitForIdle();
6026         verify(mBatteryStatsService).noteNetworkInterfaceType(cellLp.getInterfaceName(),
6027                 TYPE_MOBILE);
6028         reset(mBatteryStatsService);
6029 
6030         final LinkProperties wifiLp = new LinkProperties();
6031         wifiLp.setInterfaceName("wifi0");
6032         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp);
6033         mWiFiNetworkAgent.connect(true);
6034         waitForIdle();
6035         verify(mBatteryStatsService).noteNetworkInterfaceType(wifiLp.getInterfaceName(),
6036                 TYPE_WIFI);
6037         reset(mBatteryStatsService);
6038 
6039         mCellNetworkAgent.disconnect();
6040 
6041         cellLp.setInterfaceName("wifi0");
6042         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
6043         mCellNetworkAgent.connect(true);
6044         waitForIdle();
6045         verify(mBatteryStatsService).noteNetworkInterfaceType(cellLp.getInterfaceName(),
6046                 TYPE_MOBILE);
6047     }
6048 
6049     /**
6050      * Make simulated InterfaceConfig for Nat464Xlat to query clat lower layer info.
6051      */
getClatInterfaceConfig(LinkAddress la)6052     private InterfaceConfiguration getClatInterfaceConfig(LinkAddress la) {
6053         InterfaceConfiguration cfg = new InterfaceConfiguration();
6054         cfg.setHardwareAddress("11:22:33:44:55:66");
6055         cfg.setLinkAddress(la);
6056         return cfg;
6057     }
6058 
6059     /**
6060      * Make expected stack link properties, copied from Nat464Xlat.
6061      */
makeClatLinkProperties(LinkAddress la)6062     private LinkProperties makeClatLinkProperties(LinkAddress la) {
6063         LinkAddress clatAddress = la;
6064         LinkProperties stacked = new LinkProperties();
6065         stacked.setInterfaceName(CLAT_PREFIX + MOBILE_IFNAME);
6066         RouteInfo ipv4Default = new RouteInfo(
6067                 new LinkAddress(Inet4Address.ANY, 0),
6068                 clatAddress.getAddress(), CLAT_PREFIX + MOBILE_IFNAME);
6069         stacked.addRoute(ipv4Default);
6070         stacked.addLinkAddress(clatAddress);
6071         return stacked;
6072     }
6073 
6074     @Test
testStackedLinkProperties()6075     public void testStackedLinkProperties() throws Exception {
6076         final LinkAddress myIpv4 = new LinkAddress("1.2.3.4/24");
6077         final LinkAddress myIpv6 = new LinkAddress("2001:db8:1::1/64");
6078         final String kNat64PrefixString = "2001:db8:64:64:64:64::";
6079         final IpPrefix kNat64Prefix = new IpPrefix(InetAddress.getByName(kNat64PrefixString), 96);
6080         final String kOtherNat64PrefixString = "64:ff9b::";
6081         final IpPrefix kOtherNat64Prefix = new IpPrefix(
6082                 InetAddress.getByName(kOtherNat64PrefixString), 96);
6083         final RouteInfo defaultRoute = new RouteInfo((IpPrefix) null, myIpv6.getAddress(),
6084                                                      MOBILE_IFNAME);
6085         final RouteInfo ipv6Subnet = new RouteInfo(myIpv6, null, MOBILE_IFNAME);
6086         final RouteInfo ipv4Subnet = new RouteInfo(myIpv4, null, MOBILE_IFNAME);
6087         final RouteInfo stackedDefault = new RouteInfo((IpPrefix) null, myIpv4.getAddress(),
6088                                                        CLAT_PREFIX + MOBILE_IFNAME);
6089 
6090         final NetworkRequest networkRequest = new NetworkRequest.Builder()
6091                 .addTransportType(TRANSPORT_CELLULAR)
6092                 .addCapability(NET_CAPABILITY_INTERNET)
6093                 .build();
6094         final TestNetworkCallback networkCallback = new TestNetworkCallback();
6095         mCm.registerNetworkCallback(networkRequest, networkCallback);
6096 
6097         // Prepare ipv6 only link properties.
6098         final LinkProperties cellLp = new LinkProperties();
6099         cellLp.setInterfaceName(MOBILE_IFNAME);
6100         cellLp.addLinkAddress(myIpv6);
6101         cellLp.addRoute(defaultRoute);
6102         cellLp.addRoute(ipv6Subnet);
6103         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
6104         reset(mNetworkManagementService);
6105         reset(mMockDnsResolver);
6106         reset(mMockNetd);
6107         reset(mBatteryStatsService);
6108 
6109         // Connect with ipv6 link properties. Expect prefix discovery to be started.
6110         mCellNetworkAgent.connect(true);
6111         final int cellNetId = mCellNetworkAgent.getNetwork().netId;
6112         waitForIdle();
6113 
6114         verify(mMockNetd, times(1)).networkCreatePhysical(eq(cellNetId), anyInt());
6115         assertRoutesAdded(cellNetId, ipv6Subnet, defaultRoute);
6116         verify(mMockDnsResolver, times(1)).createNetworkCache(eq(cellNetId));
6117         verify(mBatteryStatsService).noteNetworkInterfaceType(cellLp.getInterfaceName(),
6118                 TYPE_MOBILE);
6119 
6120         networkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
6121         verify(mMockDnsResolver, times(1)).startPrefix64Discovery(cellNetId);
6122 
6123         // Switching default network updates TCP buffer sizes.
6124         verifyTcpBufferSizeChange(ConnectivityService.DEFAULT_TCP_BUFFER_SIZES);
6125 
6126         // Add an IPv4 address. Expect prefix discovery to be stopped. Netd doesn't tell us that
6127         // the NAT64 prefix was removed because one was never discovered.
6128         cellLp.addLinkAddress(myIpv4);
6129         mCellNetworkAgent.sendLinkProperties(cellLp);
6130         networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
6131         assertRoutesAdded(cellNetId, ipv4Subnet);
6132         verify(mMockDnsResolver, times(1)).stopPrefix64Discovery(cellNetId);
6133         verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(any());
6134 
6135         // Make sure BatteryStats was not told about any v4- interfaces, as none should have
6136         // come online yet.
6137         waitForIdle();
6138         verify(mBatteryStatsService, never()).noteNetworkInterfaceType(startsWith("v4-"), anyInt());
6139 
6140         verifyNoMoreInteractions(mMockNetd);
6141         verifyNoMoreInteractions(mMockDnsResolver);
6142         reset(mNetworkManagementService);
6143         reset(mMockNetd);
6144         reset(mMockDnsResolver);
6145         when(mNetworkManagementService.getInterfaceConfig(CLAT_PREFIX + MOBILE_IFNAME))
6146                 .thenReturn(getClatInterfaceConfig(myIpv4));
6147 
6148         // Remove IPv4 address. Expect prefix discovery to be started again.
6149         cellLp.removeLinkAddress(myIpv4);
6150         mCellNetworkAgent.sendLinkProperties(cellLp);
6151         networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
6152         verify(mMockDnsResolver, times(1)).startPrefix64Discovery(cellNetId);
6153         assertRoutesRemoved(cellNetId, ipv4Subnet);
6154 
6155         // When NAT64 prefix discovery succeeds, LinkProperties are updated and clatd is started.
6156         Nat464Xlat clat = getNat464Xlat(mCellNetworkAgent);
6157         assertNull(mCm.getLinkProperties(mCellNetworkAgent.getNetwork()).getNat64Prefix());
6158         mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, true /* added */,
6159                 kNat64PrefixString, 96);
6160         LinkProperties lpBeforeClat = networkCallback.expectCallback(
6161                 CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent).getLp();
6162         assertEquals(0, lpBeforeClat.getStackedLinks().size());
6163         assertEquals(kNat64Prefix, lpBeforeClat.getNat64Prefix());
6164         verify(mMockNetd, times(1)).clatdStart(MOBILE_IFNAME, kNat64Prefix.toString());
6165 
6166         // Clat iface comes up. Expect stacked link to be added.
6167         clat.interfaceLinkStateChanged(CLAT_PREFIX + MOBILE_IFNAME, true);
6168         networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
6169         List<LinkProperties> stackedLps = mCm.getLinkProperties(mCellNetworkAgent.getNetwork())
6170                 .getStackedLinks();
6171         assertEquals(makeClatLinkProperties(myIpv4), stackedLps.get(0));
6172         assertRoutesAdded(cellNetId, stackedDefault);
6173 
6174         // Change trivial linkproperties and see if stacked link is preserved.
6175         cellLp.addDnsServer(InetAddress.getByName("8.8.8.8"));
6176         mCellNetworkAgent.sendLinkProperties(cellLp);
6177         networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
6178 
6179         List<LinkProperties> stackedLpsAfterChange =
6180                 mCm.getLinkProperties(mCellNetworkAgent.getNetwork()).getStackedLinks();
6181         assertNotEquals(stackedLpsAfterChange, Collections.EMPTY_LIST);
6182         assertEquals(makeClatLinkProperties(myIpv4), stackedLpsAfterChange.get(0));
6183 
6184         verify(mMockDnsResolver, times(1)).setResolverConfiguration(
6185                 mResolverParamsParcelCaptor.capture());
6186         ResolverParamsParcel resolvrParams = mResolverParamsParcelCaptor.getValue();
6187         assertEquals(1, resolvrParams.servers.length);
6188         assertTrue(ArrayUtils.contains(resolvrParams.servers, "8.8.8.8"));
6189 
6190         for (final LinkProperties stackedLp : stackedLpsAfterChange) {
6191             verify(mBatteryStatsService).noteNetworkInterfaceType(stackedLp.getInterfaceName(),
6192                     TYPE_MOBILE);
6193         }
6194         reset(mMockNetd);
6195 
6196         // Change the NAT64 prefix without first removing it.
6197         // Expect clatd to be stopped and started with the new prefix.
6198         mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, true /* added */,
6199                 kOtherNat64PrefixString, 96);
6200         networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
6201                 (lp) -> lp.getStackedLinks().size() == 0);
6202         verify(mMockNetd, times(1)).clatdStop(MOBILE_IFNAME);
6203         assertRoutesRemoved(cellNetId, stackedDefault);
6204 
6205         verify(mMockNetd, times(1)).clatdStart(MOBILE_IFNAME, kOtherNat64Prefix.toString());
6206         networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
6207                 (lp) -> lp.getNat64Prefix().equals(kOtherNat64Prefix));
6208         clat.interfaceLinkStateChanged(CLAT_PREFIX + MOBILE_IFNAME, true);
6209         networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
6210                 (lp) -> lp.getStackedLinks().size() == 1);
6211         assertRoutesAdded(cellNetId, stackedDefault);
6212         reset(mMockNetd);
6213 
6214         // Add ipv4 address, expect that clatd and prefix discovery are stopped and stacked
6215         // linkproperties are cleaned up.
6216         cellLp.addLinkAddress(myIpv4);
6217         cellLp.addRoute(ipv4Subnet);
6218         mCellNetworkAgent.sendLinkProperties(cellLp);
6219         networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
6220         assertRoutesAdded(cellNetId, ipv4Subnet);
6221         verify(mMockNetd, times(1)).clatdStop(MOBILE_IFNAME);
6222         verify(mMockDnsResolver, times(1)).stopPrefix64Discovery(cellNetId);
6223 
6224         // As soon as stop is called, the linkproperties lose the stacked interface.
6225         networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
6226         LinkProperties actualLpAfterIpv4 = mCm.getLinkProperties(mCellNetworkAgent.getNetwork());
6227         LinkProperties expected = new LinkProperties(cellLp);
6228         expected.setNat64Prefix(kOtherNat64Prefix);
6229         assertEquals(expected, actualLpAfterIpv4);
6230         assertEquals(0, actualLpAfterIpv4.getStackedLinks().size());
6231         assertRoutesRemoved(cellNetId, stackedDefault);
6232 
6233         // The interface removed callback happens but has no effect after stop is called.
6234         clat.interfaceRemoved(CLAT_PREFIX + MOBILE_IFNAME);
6235         networkCallback.assertNoCallback();
6236 
6237         verifyNoMoreInteractions(mMockNetd);
6238         verifyNoMoreInteractions(mMockDnsResolver);
6239         reset(mNetworkManagementService);
6240         reset(mMockNetd);
6241         reset(mMockDnsResolver);
6242         when(mNetworkManagementService.getInterfaceConfig(CLAT_PREFIX + MOBILE_IFNAME))
6243                 .thenReturn(getClatInterfaceConfig(myIpv4));
6244 
6245         // Stopping prefix discovery causes netd to tell us that the NAT64 prefix is gone.
6246         mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, false /* added */,
6247                 kOtherNat64PrefixString, 96);
6248         networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
6249                 (lp) -> lp.getNat64Prefix() == null);
6250 
6251         // Remove IPv4 address and expect prefix discovery and clatd to be started again.
6252         cellLp.removeLinkAddress(myIpv4);
6253         cellLp.removeRoute(new RouteInfo(myIpv4, null, MOBILE_IFNAME));
6254         cellLp.removeDnsServer(InetAddress.getByName("8.8.8.8"));
6255         mCellNetworkAgent.sendLinkProperties(cellLp);
6256         networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
6257         assertRoutesRemoved(cellNetId, ipv4Subnet);  // Directly-connected routes auto-added.
6258         verify(mMockDnsResolver, times(1)).startPrefix64Discovery(cellNetId);
6259         mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, true /* added */,
6260                 kNat64PrefixString, 96);
6261         networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
6262         verify(mMockNetd, times(1)).clatdStart(MOBILE_IFNAME, kNat64Prefix.toString());
6263 
6264         // Clat iface comes up. Expect stacked link to be added.
6265         clat.interfaceLinkStateChanged(CLAT_PREFIX + MOBILE_IFNAME, true);
6266         networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
6267                 (lp) -> lp.getStackedLinks().size() == 1 && lp.getNat64Prefix() != null);
6268         assertRoutesAdded(cellNetId, stackedDefault);
6269 
6270         // NAT64 prefix is removed. Expect that clat is stopped.
6271         mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, false /* added */,
6272                 kNat64PrefixString, 96);
6273         networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
6274                 (lp) -> lp.getStackedLinks().size() == 0 && lp.getNat64Prefix() == null);
6275         assertRoutesRemoved(cellNetId, ipv4Subnet, stackedDefault);
6276 
6277         // Stop has no effect because clat is already stopped.
6278         verify(mMockNetd, times(1)).clatdStop(MOBILE_IFNAME);
6279         networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
6280                 (lp) -> lp.getStackedLinks().size() == 0);
6281         verifyNoMoreInteractions(mMockNetd);
6282 
6283         // Clean up.
6284         mCellNetworkAgent.disconnect();
6285         networkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
6286         networkCallback.assertNoCallback();
6287         mCm.unregisterNetworkCallback(networkCallback);
6288     }
6289 
expectNat64PrefixChange(TestableNetworkCallback callback, TestNetworkAgentWrapper agent, IpPrefix prefix)6290     private void expectNat64PrefixChange(TestableNetworkCallback callback,
6291             TestNetworkAgentWrapper agent, IpPrefix prefix) {
6292         callback.expectLinkPropertiesThat(agent, x -> Objects.equals(x.getNat64Prefix(), prefix));
6293     }
6294 
6295     @Test
testNat64PrefixMultipleSources()6296     public void testNat64PrefixMultipleSources() throws Exception {
6297         final String iface = "wlan0";
6298         final String pref64FromRaStr = "64:ff9b::";
6299         final String pref64FromDnsStr = "2001:db8:64::";
6300         final IpPrefix pref64FromRa = new IpPrefix(InetAddress.getByName(pref64FromRaStr), 96);
6301         final IpPrefix pref64FromDns = new IpPrefix(InetAddress.getByName(pref64FromDnsStr), 96);
6302         final IpPrefix newPref64FromRa = new IpPrefix("2001:db8:64:64:64:64::/96");
6303 
6304         final NetworkRequest request = new NetworkRequest.Builder()
6305                 .addCapability(NET_CAPABILITY_INTERNET)
6306                 .build();
6307         final TestNetworkCallback callback = new TestNetworkCallback();
6308         mCm.registerNetworkCallback(request, callback);
6309 
6310         final LinkProperties baseLp = new LinkProperties();
6311         baseLp.setInterfaceName(iface);
6312         baseLp.addLinkAddress(new LinkAddress("2001:db8:1::1/64"));
6313         baseLp.addDnsServer(InetAddress.getByName("2001:4860:4860::6464"));
6314 
6315         reset(mMockNetd, mMockDnsResolver);
6316         InOrder inOrder = inOrder(mMockNetd, mMockDnsResolver);
6317 
6318         // If a network already has a NAT64 prefix on connect, clatd is started immediately and
6319         // prefix discovery is never started.
6320         LinkProperties lp = new LinkProperties(baseLp);
6321         lp.setNat64Prefix(pref64FromRa);
6322         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, lp);
6323         mCellNetworkAgent.connect(false);
6324         final Network network = mCellNetworkAgent.getNetwork();
6325         int netId = network.getNetId();
6326         callback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
6327         inOrder.verify(mMockNetd).clatdStart(iface, pref64FromRa.toString());
6328         inOrder.verify(mMockDnsResolver).setPrefix64(netId, pref64FromRa.toString());
6329         inOrder.verify(mMockDnsResolver, never()).startPrefix64Discovery(netId);
6330         callback.assertNoCallback();
6331         assertEquals(pref64FromRa, mCm.getLinkProperties(network).getNat64Prefix());
6332 
6333         // If the RA prefix is withdrawn, clatd is stopped and prefix discovery is started.
6334         lp.setNat64Prefix(null);
6335         mCellNetworkAgent.sendLinkProperties(lp);
6336         expectNat64PrefixChange(callback, mCellNetworkAgent, null);
6337         inOrder.verify(mMockNetd).clatdStop(iface);
6338         inOrder.verify(mMockDnsResolver).setPrefix64(netId, "");
6339         inOrder.verify(mMockDnsResolver).startPrefix64Discovery(netId);
6340 
6341         // If the RA prefix appears while DNS discovery is in progress, discovery is stopped and
6342         // clatd is started with the prefix from the RA.
6343         lp.setNat64Prefix(pref64FromRa);
6344         mCellNetworkAgent.sendLinkProperties(lp);
6345         expectNat64PrefixChange(callback, mCellNetworkAgent, pref64FromRa);
6346         inOrder.verify(mMockNetd).clatdStart(iface, pref64FromRa.toString());
6347         inOrder.verify(mMockDnsResolver).stopPrefix64Discovery(netId);
6348         inOrder.verify(mMockDnsResolver).setPrefix64(netId, pref64FromRa.toString());
6349 
6350         // Withdraw the RA prefix so we can test the case where an RA prefix appears after DNS
6351         // discovery has succeeded.
6352         lp.setNat64Prefix(null);
6353         mCellNetworkAgent.sendLinkProperties(lp);
6354         expectNat64PrefixChange(callback, mCellNetworkAgent, null);
6355         inOrder.verify(mMockNetd).clatdStop(iface);
6356         inOrder.verify(mMockDnsResolver).setPrefix64(netId, "");
6357         inOrder.verify(mMockDnsResolver).startPrefix64Discovery(netId);
6358 
6359         mService.mNetdEventCallback.onNat64PrefixEvent(netId, true /* added */,
6360                 pref64FromDnsStr, 96);
6361         expectNat64PrefixChange(callback, mCellNetworkAgent, pref64FromDns);
6362         inOrder.verify(mMockNetd).clatdStart(iface, pref64FromDns.toString());
6363 
6364         // If an RA advertises the same prefix that was discovered by DNS, nothing happens: prefix
6365         // discovery is not stopped, and there are no callbacks.
6366         lp.setNat64Prefix(pref64FromDns);
6367         mCellNetworkAgent.sendLinkProperties(lp);
6368         callback.assertNoCallback();
6369         inOrder.verify(mMockNetd, never()).clatdStop(iface);
6370         inOrder.verify(mMockNetd, never()).clatdStart(eq(iface), anyString());
6371         inOrder.verify(mMockDnsResolver, never()).stopPrefix64Discovery(netId);
6372         inOrder.verify(mMockDnsResolver, never()).startPrefix64Discovery(netId);
6373         inOrder.verify(mMockDnsResolver, never()).setPrefix64(eq(netId), anyString());
6374 
6375         // If the RA is later withdrawn, nothing happens again.
6376         lp.setNat64Prefix(null);
6377         mCellNetworkAgent.sendLinkProperties(lp);
6378         callback.assertNoCallback();
6379         inOrder.verify(mMockNetd, never()).clatdStop(iface);
6380         inOrder.verify(mMockNetd, never()).clatdStart(eq(iface), anyString());
6381         inOrder.verify(mMockDnsResolver, never()).stopPrefix64Discovery(netId);
6382         inOrder.verify(mMockDnsResolver, never()).startPrefix64Discovery(netId);
6383         inOrder.verify(mMockDnsResolver, never()).setPrefix64(eq(netId), anyString());
6384 
6385         // If the RA prefix changes, clatd is restarted and prefix discovery is stopped.
6386         lp.setNat64Prefix(pref64FromRa);
6387         mCellNetworkAgent.sendLinkProperties(lp);
6388         expectNat64PrefixChange(callback, mCellNetworkAgent, pref64FromRa);
6389         inOrder.verify(mMockNetd).clatdStop(iface);
6390         inOrder.verify(mMockDnsResolver).stopPrefix64Discovery(netId);
6391 
6392         // Stopping prefix discovery results in a prefix removed notification.
6393         mService.mNetdEventCallback.onNat64PrefixEvent(netId, false /* added */,
6394                 pref64FromDnsStr, 96);
6395 
6396         inOrder.verify(mMockNetd).clatdStart(iface, pref64FromRa.toString());
6397         inOrder.verify(mMockDnsResolver).setPrefix64(netId, pref64FromRa.toString());
6398         inOrder.verify(mMockDnsResolver, never()).startPrefix64Discovery(netId);
6399 
6400         // If the RA prefix changes, clatd is restarted and prefix discovery is not started.
6401         lp.setNat64Prefix(newPref64FromRa);
6402         mCellNetworkAgent.sendLinkProperties(lp);
6403         expectNat64PrefixChange(callback, mCellNetworkAgent, newPref64FromRa);
6404         inOrder.verify(mMockNetd).clatdStop(iface);
6405         inOrder.verify(mMockDnsResolver).setPrefix64(netId, "");
6406         inOrder.verify(mMockNetd).clatdStart(iface, newPref64FromRa.toString());
6407         inOrder.verify(mMockDnsResolver).setPrefix64(netId, newPref64FromRa.toString());
6408         inOrder.verify(mMockDnsResolver, never()).stopPrefix64Discovery(netId);
6409         inOrder.verify(mMockDnsResolver, never()).startPrefix64Discovery(netId);
6410 
6411         // If the RA prefix changes to the same value, nothing happens.
6412         lp.setNat64Prefix(newPref64FromRa);
6413         mCellNetworkAgent.sendLinkProperties(lp);
6414         callback.assertNoCallback();
6415         assertEquals(newPref64FromRa, mCm.getLinkProperties(network).getNat64Prefix());
6416         inOrder.verify(mMockNetd, never()).clatdStop(iface);
6417         inOrder.verify(mMockNetd, never()).clatdStart(eq(iface), anyString());
6418         inOrder.verify(mMockDnsResolver, never()).stopPrefix64Discovery(netId);
6419         inOrder.verify(mMockDnsResolver, never()).startPrefix64Discovery(netId);
6420         inOrder.verify(mMockDnsResolver, never()).setPrefix64(eq(netId), anyString());
6421 
6422         // The transition between no prefix and DNS prefix is tested in testStackedLinkProperties.
6423 
6424         // If the same prefix is learned first by DNS and then by RA, and clat is later stopped,
6425         // (e.g., because the network disconnects) setPrefix64(netid, "") is never called.
6426         lp.setNat64Prefix(null);
6427         mCellNetworkAgent.sendLinkProperties(lp);
6428         expectNat64PrefixChange(callback, mCellNetworkAgent, null);
6429         inOrder.verify(mMockNetd).clatdStop(iface);
6430         inOrder.verify(mMockDnsResolver).setPrefix64(netId, "");
6431         inOrder.verify(mMockDnsResolver).startPrefix64Discovery(netId);
6432         mService.mNetdEventCallback.onNat64PrefixEvent(netId, true /* added */,
6433                 pref64FromDnsStr, 96);
6434         expectNat64PrefixChange(callback, mCellNetworkAgent, pref64FromDns);
6435         inOrder.verify(mMockNetd).clatdStart(iface, pref64FromDns.toString());
6436         inOrder.verify(mMockDnsResolver, never()).setPrefix64(eq(netId), any());
6437 
6438         lp.setNat64Prefix(pref64FromDns);
6439         mCellNetworkAgent.sendLinkProperties(lp);
6440         callback.assertNoCallback();
6441         inOrder.verify(mMockNetd, never()).clatdStop(iface);
6442         inOrder.verify(mMockNetd, never()).clatdStart(eq(iface), anyString());
6443         inOrder.verify(mMockDnsResolver, never()).stopPrefix64Discovery(netId);
6444         inOrder.verify(mMockDnsResolver, never()).startPrefix64Discovery(netId);
6445         inOrder.verify(mMockDnsResolver, never()).setPrefix64(eq(netId), anyString());
6446 
6447         // When tearing down a network, clat state is only updated after CALLBACK_LOST is fired, but
6448         // before CONNECTIVITY_ACTION is sent. Wait for CONNECTIVITY_ACTION before verifying that
6449         // clat has been stopped, or the test will be flaky.
6450         ConditionVariable cv = registerConnectivityBroadcast(1);
6451         mCellNetworkAgent.disconnect();
6452         callback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
6453         waitFor(cv);
6454 
6455         inOrder.verify(mMockNetd).clatdStop(iface);
6456         inOrder.verify(mMockDnsResolver).stopPrefix64Discovery(netId);
6457         inOrder.verify(mMockDnsResolver, never()).setPrefix64(eq(netId), anyString());
6458 
6459         mCm.unregisterNetworkCallback(callback);
6460     }
6461 
6462     @Test
testDataActivityTracking()6463     public void testDataActivityTracking() throws Exception {
6464         final TestNetworkCallback networkCallback = new TestNetworkCallback();
6465         final NetworkRequest networkRequest = new NetworkRequest.Builder()
6466                 .addCapability(NET_CAPABILITY_INTERNET)
6467                 .build();
6468         mCm.registerNetworkCallback(networkRequest, networkCallback);
6469 
6470         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
6471         final LinkProperties cellLp = new LinkProperties();
6472         cellLp.setInterfaceName(MOBILE_IFNAME);
6473         mCellNetworkAgent.sendLinkProperties(cellLp);
6474         reset(mNetworkManagementService);
6475         mCellNetworkAgent.connect(true);
6476         networkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
6477         verify(mNetworkManagementService, times(1)).addIdleTimer(eq(MOBILE_IFNAME), anyInt(),
6478                 eq(ConnectivityManager.TYPE_MOBILE));
6479 
6480         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
6481         final LinkProperties wifiLp = new LinkProperties();
6482         wifiLp.setInterfaceName(WIFI_IFNAME);
6483         mWiFiNetworkAgent.sendLinkProperties(wifiLp);
6484 
6485         // Network switch
6486         reset(mNetworkManagementService);
6487         mWiFiNetworkAgent.connect(true);
6488         networkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
6489         networkCallback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
6490         networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
6491         verify(mNetworkManagementService, times(1)).addIdleTimer(eq(WIFI_IFNAME), anyInt(),
6492                 eq(ConnectivityManager.TYPE_WIFI));
6493         verify(mNetworkManagementService, times(1)).removeIdleTimer(eq(MOBILE_IFNAME));
6494 
6495         // Disconnect wifi and switch back to cell
6496         reset(mNetworkManagementService);
6497         mWiFiNetworkAgent.disconnect();
6498         networkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
6499         assertNoCallbacks(networkCallback);
6500         verify(mNetworkManagementService, times(1)).removeIdleTimer(eq(WIFI_IFNAME));
6501         verify(mNetworkManagementService, times(1)).addIdleTimer(eq(MOBILE_IFNAME), anyInt(),
6502                 eq(ConnectivityManager.TYPE_MOBILE));
6503 
6504         // reconnect wifi
6505         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
6506         wifiLp.setInterfaceName(WIFI_IFNAME);
6507         mWiFiNetworkAgent.sendLinkProperties(wifiLp);
6508         mWiFiNetworkAgent.connect(true);
6509         networkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
6510         networkCallback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
6511         networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
6512 
6513         // Disconnect cell
6514         reset(mNetworkManagementService);
6515         reset(mMockNetd);
6516         mCellNetworkAgent.disconnect();
6517         networkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
6518         // LOST callback is triggered earlier than removing idle timer. Broadcast should also be
6519         // sent as network being switched. Ensure rule removal for cell will not be triggered
6520         // unexpectedly before network being removed.
6521         waitForIdle();
6522         verify(mNetworkManagementService, times(0)).removeIdleTimer(eq(MOBILE_IFNAME));
6523         verify(mMockNetd, times(1)).networkDestroy(eq(mCellNetworkAgent.getNetwork().netId));
6524         verify(mMockDnsResolver, times(1))
6525                 .destroyNetworkCache(eq(mCellNetworkAgent.getNetwork().netId));
6526 
6527         // Disconnect wifi
6528         ConditionVariable cv = registerConnectivityBroadcast(1);
6529         reset(mNetworkManagementService);
6530         mWiFiNetworkAgent.disconnect();
6531         waitFor(cv);
6532         verify(mNetworkManagementService, times(1)).removeIdleTimer(eq(WIFI_IFNAME));
6533 
6534         // Clean up
6535         mCm.unregisterNetworkCallback(networkCallback);
6536     }
6537 
verifyTcpBufferSizeChange(String tcpBufferSizes)6538     private void verifyTcpBufferSizeChange(String tcpBufferSizes) throws Exception {
6539         String[] values = tcpBufferSizes.split(",");
6540         String rmemValues = String.join(" ", values[0], values[1], values[2]);
6541         String wmemValues = String.join(" ", values[3], values[4], values[5]);
6542         verify(mMockNetd, atLeastOnce()).setTcpRWmemorySize(rmemValues, wmemValues);
6543         reset(mMockNetd);
6544     }
6545 
6546     @Test
testTcpBufferReset()6547     public void testTcpBufferReset() throws Exception {
6548         final String testTcpBufferSizes = "1,2,3,4,5,6";
6549         final NetworkRequest networkRequest = new NetworkRequest.Builder()
6550                 .addTransportType(TRANSPORT_CELLULAR)
6551                 .addCapability(NET_CAPABILITY_INTERNET)
6552                 .build();
6553         final TestNetworkCallback networkCallback = new TestNetworkCallback();
6554         mCm.registerNetworkCallback(networkRequest, networkCallback);
6555 
6556         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
6557         reset(mMockNetd);
6558         // Switching default network updates TCP buffer sizes.
6559         mCellNetworkAgent.connect(false);
6560         networkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
6561         verifyTcpBufferSizeChange(ConnectivityService.DEFAULT_TCP_BUFFER_SIZES);
6562 
6563         // Change link Properties should have updated tcp buffer size.
6564         LinkProperties lp = new LinkProperties();
6565         lp.setTcpBufferSizes(testTcpBufferSizes);
6566         mCellNetworkAgent.sendLinkProperties(lp);
6567         networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
6568         verifyTcpBufferSizeChange(testTcpBufferSizes);
6569 
6570         // Clean up.
6571         mCellNetworkAgent.disconnect();
6572         networkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
6573         networkCallback.assertNoCallback();
6574         mCm.unregisterNetworkCallback(networkCallback);
6575     }
6576 
6577     @Test
testGetGlobalProxyForNetwork()6578     public void testGetGlobalProxyForNetwork() throws Exception {
6579         final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
6580         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
6581         final Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
6582         when(mService.mProxyTracker.getGlobalProxy()).thenReturn(testProxyInfo);
6583         assertEquals(testProxyInfo, mService.getProxyForNetwork(wifiNetwork));
6584     }
6585 
6586     @Test
testGetProxyForActiveNetwork()6587     public void testGetProxyForActiveNetwork() throws Exception {
6588         final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
6589         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
6590         mWiFiNetworkAgent.connect(true);
6591         waitForIdle();
6592         assertNull(mService.getProxyForNetwork(null));
6593 
6594         final LinkProperties testLinkProperties = new LinkProperties();
6595         testLinkProperties.setHttpProxy(testProxyInfo);
6596 
6597         mWiFiNetworkAgent.sendLinkProperties(testLinkProperties);
6598         waitForIdle();
6599 
6600         assertEquals(testProxyInfo, mService.getProxyForNetwork(null));
6601     }
6602 
6603     @Test
testGetProxyForVPN()6604     public void testGetProxyForVPN() throws Exception {
6605         final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
6606 
6607         // Set up a WiFi network with no proxy
6608         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
6609         mWiFiNetworkAgent.connect(true);
6610         waitForIdle();
6611         assertNull(mService.getProxyForNetwork(null));
6612 
6613         // Set up a VPN network with a proxy
6614         final int uid = Process.myUid();
6615         final TestNetworkAgentWrapper
6616                 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
6617         final ArraySet<UidRange> ranges = new ArraySet<>();
6618         ranges.add(new UidRange(uid, uid));
6619         mMockVpn.setUids(ranges);
6620         LinkProperties testLinkProperties = new LinkProperties();
6621         testLinkProperties.setHttpProxy(testProxyInfo);
6622         vpnNetworkAgent.sendLinkProperties(testLinkProperties);
6623         waitForIdle();
6624 
6625         // Connect to VPN with proxy
6626         mMockVpn.setNetworkAgent(vpnNetworkAgent);
6627         vpnNetworkAgent.connect(true);
6628         mMockVpn.connect();
6629         waitForIdle();
6630 
6631         // Test that the VPN network returns a proxy, and the WiFi does not.
6632         assertEquals(testProxyInfo, mService.getProxyForNetwork(vpnNetworkAgent.getNetwork()));
6633         assertEquals(testProxyInfo, mService.getProxyForNetwork(null));
6634         assertNull(mService.getProxyForNetwork(mWiFiNetworkAgent.getNetwork()));
6635 
6636         // Test that the VPN network returns no proxy when it is set to null.
6637         testLinkProperties.setHttpProxy(null);
6638         vpnNetworkAgent.sendLinkProperties(testLinkProperties);
6639         waitForIdle();
6640         assertNull(mService.getProxyForNetwork(vpnNetworkAgent.getNetwork()));
6641         assertNull(mService.getProxyForNetwork(null));
6642 
6643         // Set WiFi proxy and check that the vpn proxy is still null.
6644         testLinkProperties.setHttpProxy(testProxyInfo);
6645         mWiFiNetworkAgent.sendLinkProperties(testLinkProperties);
6646         waitForIdle();
6647         assertNull(mService.getProxyForNetwork(null));
6648 
6649         // Disconnect from VPN and check that the active network, which is now the WiFi, has the
6650         // correct proxy setting.
6651         vpnNetworkAgent.disconnect();
6652         waitForIdle();
6653         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
6654         assertEquals(testProxyInfo, mService.getProxyForNetwork(mWiFiNetworkAgent.getNetwork()));
6655         assertEquals(testProxyInfo, mService.getProxyForNetwork(null));
6656     }
6657 
6658     @Test
testFullyRoutedVpnResultsInInterfaceFilteringRules()6659     public void testFullyRoutedVpnResultsInInterfaceFilteringRules() throws Exception {
6660         LinkProperties lp = new LinkProperties();
6661         lp.setInterfaceName("tun0");
6662         lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
6663         lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), RTN_UNREACHABLE));
6664         // The uid range needs to cover the test app so the network is visible to it.
6665         final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(VPN_USER));
6666         final TestNetworkAgentWrapper vpnNetworkAgent = establishVpn(lp, VPN_UID, vpnRange);
6667 
6668         // Connected VPN should have interface rules set up. There are two expected invocations,
6669         // one during VPN uid update, one during VPN LinkProperties update
6670         ArgumentCaptor<int[]> uidCaptor = ArgumentCaptor.forClass(int[].class);
6671         verify(mMockNetd, times(2)).firewallAddUidInterfaceRules(eq("tun0"), uidCaptor.capture());
6672         assertContainsExactly(uidCaptor.getAllValues().get(0), APP1_UID, APP2_UID);
6673         assertContainsExactly(uidCaptor.getAllValues().get(1), APP1_UID, APP2_UID);
6674         assertTrue(mService.mPermissionMonitor.getVpnUidRanges("tun0").equals(vpnRange));
6675 
6676         vpnNetworkAgent.disconnect();
6677         waitForIdle();
6678 
6679         // Disconnected VPN should have interface rules removed
6680         verify(mMockNetd).firewallRemoveUidInterfaceRules(uidCaptor.capture());
6681         assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
6682         assertNull(mService.mPermissionMonitor.getVpnUidRanges("tun0"));
6683     }
6684 
6685     @Test
testLegacyVpnDoesNotResultInInterfaceFilteringRule()6686     public void testLegacyVpnDoesNotResultInInterfaceFilteringRule() throws Exception {
6687         LinkProperties lp = new LinkProperties();
6688         lp.setInterfaceName("tun0");
6689         lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
6690         lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
6691         // The uid range needs to cover the test app so the network is visible to it.
6692         final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(VPN_USER));
6693         final TestNetworkAgentWrapper vpnNetworkAgent = establishVpn(
6694                 lp, Process.SYSTEM_UID, vpnRange);
6695 
6696         // Legacy VPN should not have interface rules set up
6697         verify(mMockNetd, never()).firewallAddUidInterfaceRules(any(), any());
6698     }
6699 
6700     @Test
testLocalIpv4OnlyVpnDoesNotResultInInterfaceFilteringRule()6701     public void testLocalIpv4OnlyVpnDoesNotResultInInterfaceFilteringRule()
6702             throws Exception {
6703         LinkProperties lp = new LinkProperties();
6704         lp.setInterfaceName("tun0");
6705         lp.addRoute(new RouteInfo(new IpPrefix("192.0.2.0/24"), null, "tun0"));
6706         lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), RTN_UNREACHABLE));
6707         // The uid range needs to cover the test app so the network is visible to it.
6708         final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(VPN_USER));
6709         final TestNetworkAgentWrapper vpnNetworkAgent = establishVpn(
6710                 lp, Process.SYSTEM_UID, vpnRange);
6711 
6712         // IPv6 unreachable route should not be misinterpreted as a default route
6713         verify(mMockNetd, never()).firewallAddUidInterfaceRules(any(), any());
6714     }
6715 
6716     @Test
testVpnHandoverChangesInterfaceFilteringRule()6717     public void testVpnHandoverChangesInterfaceFilteringRule() throws Exception {
6718         LinkProperties lp = new LinkProperties();
6719         lp.setInterfaceName("tun0");
6720         lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
6721         lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
6722         // The uid range needs to cover the test app so the network is visible to it.
6723         final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(VPN_USER));
6724         final TestNetworkAgentWrapper vpnNetworkAgent = establishVpn(lp, VPN_UID, vpnRange);
6725 
6726         // Connected VPN should have interface rules set up. There are two expected invocations,
6727         // one during VPN uid update, one during VPN LinkProperties update
6728         ArgumentCaptor<int[]> uidCaptor = ArgumentCaptor.forClass(int[].class);
6729         verify(mMockNetd, times(2)).firewallAddUidInterfaceRules(eq("tun0"), uidCaptor.capture());
6730         assertContainsExactly(uidCaptor.getAllValues().get(0), APP1_UID, APP2_UID);
6731         assertContainsExactly(uidCaptor.getAllValues().get(1), APP1_UID, APP2_UID);
6732 
6733         reset(mMockNetd);
6734         InOrder inOrder = inOrder(mMockNetd);
6735         lp.setInterfaceName("tun1");
6736         vpnNetworkAgent.sendLinkProperties(lp);
6737         waitForIdle();
6738         // VPN handover (switch to a new interface) should result in rules being updated (old rules
6739         // removed first, then new rules added)
6740         inOrder.verify(mMockNetd).firewallRemoveUidInterfaceRules(uidCaptor.capture());
6741         assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
6742         inOrder.verify(mMockNetd).firewallAddUidInterfaceRules(eq("tun1"), uidCaptor.capture());
6743         assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
6744 
6745         reset(mMockNetd);
6746         lp = new LinkProperties();
6747         lp.setInterfaceName("tun1");
6748         lp.addRoute(new RouteInfo(new IpPrefix("192.0.2.0/24"), null, "tun1"));
6749         vpnNetworkAgent.sendLinkProperties(lp);
6750         waitForIdle();
6751         // VPN not routing everything should no longer have interface filtering rules
6752         verify(mMockNetd).firewallRemoveUidInterfaceRules(uidCaptor.capture());
6753         assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
6754 
6755         reset(mMockNetd);
6756         lp = new LinkProperties();
6757         lp.setInterfaceName("tun1");
6758         lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), RTN_UNREACHABLE));
6759         lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
6760         vpnNetworkAgent.sendLinkProperties(lp);
6761         waitForIdle();
6762         // Back to routing all IPv6 traffic should have filtering rules
6763         verify(mMockNetd).firewallAddUidInterfaceRules(eq("tun1"), uidCaptor.capture());
6764         assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
6765     }
6766 
6767     @Test
testUidUpdateChangesInterfaceFilteringRule()6768     public void testUidUpdateChangesInterfaceFilteringRule() throws Exception {
6769         LinkProperties lp = new LinkProperties();
6770         lp.setInterfaceName("tun0");
6771         lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), RTN_UNREACHABLE));
6772         lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
6773         // The uid range needs to cover the test app so the network is visible to it.
6774         final UidRange vpnRange = UidRange.createForUser(VPN_USER);
6775         final TestNetworkAgentWrapper vpnNetworkAgent = establishVpn(lp, VPN_UID,
6776                 Collections.singleton(vpnRange));
6777 
6778         reset(mMockNetd);
6779         InOrder inOrder = inOrder(mMockNetd);
6780 
6781         // Update to new range which is old range minus APP1, i.e. only APP2
6782         final Set<UidRange> newRanges = new HashSet<>(Arrays.asList(
6783                 new UidRange(vpnRange.start, APP1_UID - 1),
6784                 new UidRange(APP1_UID + 1, vpnRange.stop)));
6785         vpnNetworkAgent.setUids(newRanges);
6786         waitForIdle();
6787 
6788         ArgumentCaptor<int[]> uidCaptor = ArgumentCaptor.forClass(int[].class);
6789         // Verify old rules are removed before new rules are added
6790         inOrder.verify(mMockNetd).firewallRemoveUidInterfaceRules(uidCaptor.capture());
6791         assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
6792         inOrder.verify(mMockNetd).firewallAddUidInterfaceRules(eq("tun0"), uidCaptor.capture());
6793         assertContainsExactly(uidCaptor.getValue(), APP2_UID);
6794     }
6795 
6796     @Test
testLinkPropertiesWithWakeOnLanForActiveNetwork()6797     public void testLinkPropertiesWithWakeOnLanForActiveNetwork() throws Exception {
6798         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
6799 
6800         LinkProperties wifiLp = new LinkProperties();
6801         wifiLp.setInterfaceName(WIFI_WOL_IFNAME);
6802         wifiLp.setWakeOnLanSupported(false);
6803 
6804         // Default network switch should update ifaces.
6805         mWiFiNetworkAgent.connect(false);
6806         mWiFiNetworkAgent.sendLinkProperties(wifiLp);
6807         waitForIdle();
6808 
6809         // ConnectivityService should have changed the WakeOnLanSupported to true
6810         wifiLp.setWakeOnLanSupported(true);
6811         assertEquals(wifiLp, mService.getActiveLinkProperties());
6812     }
6813 
6814     @Test
testLegacyExtraInfoSentToNetworkMonitor()6815     public void testLegacyExtraInfoSentToNetworkMonitor() throws Exception {
6816         class TestNetworkAgent extends NetworkAgent {
6817             TestNetworkAgent(Context context, Looper looper, NetworkAgentConfig config) {
6818                 super(context, looper, "MockAgent", new NetworkCapabilities(),
6819                         new LinkProperties(), 40 , config, null /* provider */);
6820             }
6821         }
6822         final NetworkAgent naNoExtraInfo = new TestNetworkAgent(
6823                 mServiceContext, mCsHandlerThread.getLooper(), new NetworkAgentConfig());
6824         naNoExtraInfo.register();
6825         verify(mNetworkStack).makeNetworkMonitor(any(), isNull(String.class), any());
6826         naNoExtraInfo.unregister();
6827 
6828         reset(mNetworkStack);
6829         final NetworkAgentConfig config =
6830                 new NetworkAgentConfig.Builder().setLegacyExtraInfo("legacyinfo").build();
6831         final NetworkAgent naExtraInfo = new TestNetworkAgent(
6832                 mServiceContext, mCsHandlerThread.getLooper(), config);
6833         naExtraInfo.register();
6834         verify(mNetworkStack).makeNetworkMonitor(any(), eq("legacyinfo"), any());
6835         naExtraInfo.unregister();
6836     }
6837 
setupLocationPermissions( int targetSdk, boolean locationToggle, String op, String perm)6838     private void setupLocationPermissions(
6839             int targetSdk, boolean locationToggle, String op, String perm) throws Exception {
6840         final ApplicationInfo applicationInfo = new ApplicationInfo();
6841         applicationInfo.targetSdkVersion = targetSdk;
6842         when(mPackageManager.getApplicationInfoAsUser(anyString(), anyInt(), any()))
6843                 .thenReturn(applicationInfo);
6844 
6845         when(mLocationManager.isLocationEnabledForUser(any())).thenReturn(locationToggle);
6846 
6847         if (op != null) {
6848             when(mAppOpsManager.noteOp(eq(op), eq(Process.myUid()), eq(mContext.getPackageName())))
6849                 .thenReturn(AppOpsManager.MODE_ALLOWED);
6850         }
6851 
6852         if (perm != null) {
6853             mServiceContext.setPermission(perm, PERMISSION_GRANTED);
6854         }
6855     }
6856 
getOwnerUidNetCapsForCallerPermission(int ownerUid, int callerUid)6857     private int getOwnerUidNetCapsForCallerPermission(int ownerUid, int callerUid) {
6858         final NetworkCapabilities netCap = new NetworkCapabilities().setOwnerUid(ownerUid);
6859 
6860         return mService
6861                 .maybeSanitizeLocationInfoForCaller(netCap, callerUid, mContext.getPackageName())
6862                 .getOwnerUid();
6863     }
6864 
6865     @Test
testMaybeSanitizeLocationInfoForCallerWithFineLocationAfterQ()6866     public void testMaybeSanitizeLocationInfoForCallerWithFineLocationAfterQ() throws Exception {
6867         setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
6868                 Manifest.permission.ACCESS_FINE_LOCATION);
6869 
6870         final int myUid = Process.myUid();
6871         assertEquals(myUid, getOwnerUidNetCapsForCallerPermission(myUid, myUid));
6872     }
6873 
6874     @Test
testMaybeSanitizeLocationInfoForCallerWithCoarseLocationPreQ()6875     public void testMaybeSanitizeLocationInfoForCallerWithCoarseLocationPreQ() throws Exception {
6876         setupLocationPermissions(Build.VERSION_CODES.P, true, AppOpsManager.OPSTR_COARSE_LOCATION,
6877                 Manifest.permission.ACCESS_COARSE_LOCATION);
6878 
6879         final int myUid = Process.myUid();
6880         assertEquals(myUid, getOwnerUidNetCapsForCallerPermission(myUid, myUid));
6881     }
6882 
6883     @Test
testMaybeSanitizeLocationInfoForCallerLocationOff()6884     public void testMaybeSanitizeLocationInfoForCallerLocationOff() throws Exception {
6885         // Test that even with fine location permission, and UIDs matching, the UID is sanitized.
6886         setupLocationPermissions(Build.VERSION_CODES.Q, false, AppOpsManager.OPSTR_FINE_LOCATION,
6887                 Manifest.permission.ACCESS_FINE_LOCATION);
6888 
6889         final int myUid = Process.myUid();
6890         assertEquals(Process.INVALID_UID, getOwnerUidNetCapsForCallerPermission(myUid, myUid));
6891     }
6892 
6893     @Test
testMaybeSanitizeLocationInfoForCallerWrongUid()6894     public void testMaybeSanitizeLocationInfoForCallerWrongUid() throws Exception {
6895         // Test that even with fine location permission, not being the owner leads to sanitization.
6896         setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
6897                 Manifest.permission.ACCESS_FINE_LOCATION);
6898 
6899         final int myUid = Process.myUid();
6900         assertEquals(Process.INVALID_UID, getOwnerUidNetCapsForCallerPermission(myUid + 1, myUid));
6901     }
6902 
6903     @Test
testMaybeSanitizeLocationInfoForCallerWithCoarseLocationAfterQ()6904     public void testMaybeSanitizeLocationInfoForCallerWithCoarseLocationAfterQ() throws Exception {
6905         // Test that not having fine location permission leads to sanitization.
6906         setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_COARSE_LOCATION,
6907                 Manifest.permission.ACCESS_COARSE_LOCATION);
6908 
6909         // Test that without the location permission, the owner field is sanitized.
6910         final int myUid = Process.myUid();
6911         assertEquals(Process.INVALID_UID, getOwnerUidNetCapsForCallerPermission(myUid, myUid));
6912     }
6913 
6914     @Test
testMaybeSanitizeLocationInfoForCallerWithoutLocationPermission()6915     public void testMaybeSanitizeLocationInfoForCallerWithoutLocationPermission() throws Exception {
6916         setupLocationPermissions(Build.VERSION_CODES.Q, true, null /* op */, null /* perm */);
6917 
6918         // Test that without the location permission, the owner field is sanitized.
6919         final int myUid = Process.myUid();
6920         assertEquals(Process.INVALID_UID, getOwnerUidNetCapsForCallerPermission(myUid, myUid));
6921     }
6922 
setupConnectionOwnerUid(int vpnOwnerUid, @VpnManager.VpnType int vpnType)6923     private void setupConnectionOwnerUid(int vpnOwnerUid, @VpnManager.VpnType int vpnType)
6924             throws Exception {
6925         final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(VPN_USER));
6926         establishVpn(new LinkProperties(), vpnOwnerUid, vpnRange);
6927         mMockVpn.setVpnType(vpnType);
6928 
6929         final VpnInfo vpnInfo = new VpnInfo();
6930         vpnInfo.ownerUid = vpnOwnerUid;
6931         mMockVpn.setVpnInfo(vpnInfo);
6932     }
6933 
setupConnectionOwnerUidAsVpnApp(int vpnOwnerUid, @VpnManager.VpnType int vpnType)6934     private void setupConnectionOwnerUidAsVpnApp(int vpnOwnerUid, @VpnManager.VpnType int vpnType)
6935             throws Exception {
6936         setupConnectionOwnerUid(vpnOwnerUid, vpnType);
6937 
6938         // Test as VPN app
6939         mServiceContext.setPermission(android.Manifest.permission.NETWORK_STACK, PERMISSION_DENIED);
6940         mServiceContext.setPermission(
6941                 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, PERMISSION_DENIED);
6942     }
6943 
getTestConnectionInfo()6944     private ConnectionInfo getTestConnectionInfo() throws Exception {
6945         return new ConnectionInfo(
6946                 IPPROTO_TCP,
6947                 new InetSocketAddress(InetAddresses.parseNumericAddress("1.2.3.4"), 1234),
6948                 new InetSocketAddress(InetAddresses.parseNumericAddress("2.3.4.5"), 2345));
6949     }
6950 
6951     @Test
testGetConnectionOwnerUidPlatformVpn()6952     public void testGetConnectionOwnerUidPlatformVpn() throws Exception {
6953         final int myUid = Process.myUid();
6954         setupConnectionOwnerUidAsVpnApp(myUid, VpnManager.TYPE_VPN_PLATFORM);
6955 
6956         try {
6957             mService.getConnectionOwnerUid(getTestConnectionInfo());
6958             fail("Expected SecurityException for non-VpnService app");
6959         } catch (SecurityException expected) {
6960         }
6961     }
6962 
6963     @Test
testGetConnectionOwnerUidVpnServiceWrongUser()6964     public void testGetConnectionOwnerUidVpnServiceWrongUser() throws Exception {
6965         final int myUid = Process.myUid();
6966         setupConnectionOwnerUidAsVpnApp(myUid + 1, VpnManager.TYPE_VPN_SERVICE);
6967 
6968         try {
6969             mService.getConnectionOwnerUid(getTestConnectionInfo());
6970             fail("Expected SecurityException for non-VpnService app");
6971         } catch (SecurityException expected) {
6972         }
6973     }
6974 
6975     @Test
testGetConnectionOwnerUidVpnServiceDoesNotThrow()6976     public void testGetConnectionOwnerUidVpnServiceDoesNotThrow() throws Exception {
6977         final int myUid = Process.myUid();
6978         setupConnectionOwnerUidAsVpnApp(myUid, VpnManager.TYPE_VPN_SERVICE);
6979 
6980         // TODO: Test the returned UID
6981         mService.getConnectionOwnerUid(getTestConnectionInfo());
6982     }
6983 
6984     @Test
testGetConnectionOwnerUidVpnServiceNetworkStackDoesNotThrow()6985     public void testGetConnectionOwnerUidVpnServiceNetworkStackDoesNotThrow() throws Exception {
6986         final int myUid = Process.myUid();
6987         setupConnectionOwnerUid(myUid, VpnManager.TYPE_VPN_SERVICE);
6988         mServiceContext.setPermission(
6989                 android.Manifest.permission.NETWORK_STACK, PERMISSION_GRANTED);
6990 
6991         // TODO: Test the returned UID
6992         mService.getConnectionOwnerUid(getTestConnectionInfo());
6993     }
6994 
6995     @Test
testGetConnectionOwnerUidVpnServiceMainlineNetworkStackDoesNotThrow()6996     public void testGetConnectionOwnerUidVpnServiceMainlineNetworkStackDoesNotThrow()
6997             throws Exception {
6998         final int myUid = Process.myUid();
6999         setupConnectionOwnerUid(myUid, VpnManager.TYPE_VPN_SERVICE);
7000         mServiceContext.setPermission(
7001                 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, PERMISSION_GRANTED);
7002 
7003         // TODO: Test the returned UID
7004         mService.getConnectionOwnerUid(getTestConnectionInfo());
7005     }
7006 
establishVpn( LinkProperties lp, int ownerUid, Set<UidRange> vpnRange)7007     private TestNetworkAgentWrapper establishVpn(
7008             LinkProperties lp, int ownerUid, Set<UidRange> vpnRange) throws Exception {
7009         final TestNetworkAgentWrapper
7010                 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN, lp);
7011         vpnNetworkAgent.getNetworkCapabilities().setOwnerUid(ownerUid);
7012         mMockVpn.setNetworkAgent(vpnNetworkAgent);
7013         mMockVpn.connect();
7014         mMockVpn.setUids(vpnRange);
7015         vpnNetworkAgent.connect(true);
7016         waitForIdle();
7017         return vpnNetworkAgent;
7018     }
7019 
buildPackageInfo(boolean hasSystemPermission, int uid)7020     private static PackageInfo buildPackageInfo(boolean hasSystemPermission, int uid) {
7021         final PackageInfo packageInfo = new PackageInfo();
7022         if (hasSystemPermission) {
7023             packageInfo.requestedPermissions = new String[] {
7024                     CHANGE_NETWORK_STATE, CONNECTIVITY_USE_RESTRICTED_NETWORKS };
7025             packageInfo.requestedPermissionsFlags = new int[] {
7026                     REQUESTED_PERMISSION_GRANTED, REQUESTED_PERMISSION_GRANTED };
7027         } else {
7028             packageInfo.requestedPermissions = new String[0];
7029         }
7030         packageInfo.applicationInfo = new ApplicationInfo();
7031         packageInfo.applicationInfo.privateFlags = 0;
7032         packageInfo.applicationInfo.uid = UserHandle.getUid(UserHandle.USER_SYSTEM,
7033                 UserHandle.getAppId(uid));
7034         return packageInfo;
7035     }
7036 
7037     @Test
testRegisterConnectivityDiagnosticsCallbackInvalidRequest()7038     public void testRegisterConnectivityDiagnosticsCallbackInvalidRequest() throws Exception {
7039         final NetworkRequest request =
7040                 new NetworkRequest(
7041                         new NetworkCapabilities(), TYPE_ETHERNET, 0, NetworkRequest.Type.NONE);
7042         try {
7043             mService.registerConnectivityDiagnosticsCallback(
7044                     mConnectivityDiagnosticsCallback, request, mContext.getPackageName());
7045             fail("registerConnectivityDiagnosticsCallback should throw on invalid NetworkRequest");
7046         } catch (IllegalArgumentException expected) {
7047         }
7048     }
7049 
assertRouteInfoParcelMatches(RouteInfo route, RouteInfoParcel parcel)7050     private void assertRouteInfoParcelMatches(RouteInfo route, RouteInfoParcel parcel) {
7051         assertEquals(route.getDestination().toString(), parcel.destination);
7052         assertEquals(route.getInterface(), parcel.ifName);
7053         assertEquals(route.getMtu(), parcel.mtu);
7054 
7055         switch (route.getType()) {
7056             case RouteInfo.RTN_UNICAST:
7057                 if (route.hasGateway()) {
7058                     assertEquals(route.getGateway().getHostAddress(), parcel.nextHop);
7059                 } else {
7060                     assertEquals(INetd.NEXTHOP_NONE, parcel.nextHop);
7061                 }
7062                 break;
7063             case RouteInfo.RTN_UNREACHABLE:
7064                 assertEquals(INetd.NEXTHOP_UNREACHABLE, parcel.nextHop);
7065                 break;
7066             case RouteInfo.RTN_THROW:
7067                 assertEquals(INetd.NEXTHOP_THROW, parcel.nextHop);
7068                 break;
7069             default:
7070                 assertEquals(INetd.NEXTHOP_NONE, parcel.nextHop);
7071                 break;
7072         }
7073     }
7074 
assertRoutesAdded(int netId, RouteInfo... routes)7075     private void assertRoutesAdded(int netId, RouteInfo... routes) throws Exception {
7076         ArgumentCaptor<RouteInfoParcel> captor = ArgumentCaptor.forClass(RouteInfoParcel.class);
7077         verify(mMockNetd, times(routes.length)).networkAddRouteParcel(eq(netId), captor.capture());
7078         for (int i = 0; i < routes.length; i++) {
7079             assertRouteInfoParcelMatches(routes[i], captor.getAllValues().get(i));
7080         }
7081     }
7082 
assertRoutesRemoved(int netId, RouteInfo... routes)7083     private void assertRoutesRemoved(int netId, RouteInfo... routes) throws Exception {
7084         ArgumentCaptor<RouteInfoParcel> captor = ArgumentCaptor.forClass(RouteInfoParcel.class);
7085         verify(mMockNetd, times(routes.length)).networkRemoveRouteParcel(eq(netId),
7086                 captor.capture());
7087         for (int i = 0; i < routes.length; i++) {
7088             assertRouteInfoParcelMatches(routes[i], captor.getAllValues().get(i));
7089         }
7090     }
7091 
7092     @Test
testRegisterUnregisterConnectivityDiagnosticsCallback()7093     public void testRegisterUnregisterConnectivityDiagnosticsCallback() throws Exception {
7094         final NetworkRequest wifiRequest =
7095                 new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI).build();
7096         when(mConnectivityDiagnosticsCallback.asBinder()).thenReturn(mIBinder);
7097 
7098         mService.registerConnectivityDiagnosticsCallback(
7099                 mConnectivityDiagnosticsCallback, wifiRequest, mContext.getPackageName());
7100 
7101         // Block until all other events are done processing.
7102         HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
7103 
7104         verify(mIBinder).linkToDeath(any(ConnectivityDiagnosticsCallbackInfo.class), anyInt());
7105         verify(mConnectivityDiagnosticsCallback).asBinder();
7106         assertTrue(mService.mConnectivityDiagnosticsCallbacks.containsKey(mIBinder));
7107 
7108         mService.unregisterConnectivityDiagnosticsCallback(mConnectivityDiagnosticsCallback);
7109         verify(mIBinder, timeout(TIMEOUT_MS))
7110                 .unlinkToDeath(any(ConnectivityDiagnosticsCallbackInfo.class), anyInt());
7111         assertFalse(mService.mConnectivityDiagnosticsCallbacks.containsKey(mIBinder));
7112         verify(mConnectivityDiagnosticsCallback, atLeastOnce()).asBinder();
7113     }
7114 
7115     @Test
testRegisterDuplicateConnectivityDiagnosticsCallback()7116     public void testRegisterDuplicateConnectivityDiagnosticsCallback() throws Exception {
7117         final NetworkRequest wifiRequest =
7118                 new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI).build();
7119         when(mConnectivityDiagnosticsCallback.asBinder()).thenReturn(mIBinder);
7120 
7121         mService.registerConnectivityDiagnosticsCallback(
7122                 mConnectivityDiagnosticsCallback, wifiRequest, mContext.getPackageName());
7123 
7124         // Block until all other events are done processing.
7125         HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
7126 
7127         verify(mIBinder).linkToDeath(any(ConnectivityDiagnosticsCallbackInfo.class), anyInt());
7128         verify(mConnectivityDiagnosticsCallback).asBinder();
7129         assertTrue(mService.mConnectivityDiagnosticsCallbacks.containsKey(mIBinder));
7130 
7131         // Register the same callback again
7132         mService.registerConnectivityDiagnosticsCallback(
7133                 mConnectivityDiagnosticsCallback, wifiRequest, mContext.getPackageName());
7134 
7135         // Block until all other events are done processing.
7136         HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
7137 
7138         assertTrue(mService.mConnectivityDiagnosticsCallbacks.containsKey(mIBinder));
7139     }
7140 
7141     @Test
testCheckConnectivityDiagnosticsPermissionsNetworkStack()7142     public void testCheckConnectivityDiagnosticsPermissionsNetworkStack() throws Exception {
7143         final NetworkAgentInfo naiWithoutUid =
7144                 new NetworkAgentInfo(
7145                         null, null, null, null, null, new NetworkCapabilities(), 0,
7146                         mServiceContext, null, null, mService, null, null, null, 0, INVALID_UID);
7147 
7148         mServiceContext.setPermission(
7149                 android.Manifest.permission.NETWORK_STACK, PERMISSION_GRANTED);
7150         assertTrue(
7151                 "NetworkStack permission not applied",
7152                 mService.checkConnectivityDiagnosticsPermissions(
7153                         Process.myPid(), Process.myUid(), naiWithoutUid,
7154                         mContext.getOpPackageName()));
7155     }
7156 
7157     @Test
testCheckConnectivityDiagnosticsPermissionsWrongUidPackageName()7158     public void testCheckConnectivityDiagnosticsPermissionsWrongUidPackageName() throws Exception {
7159         final NetworkAgentInfo naiWithoutUid =
7160                 new NetworkAgentInfo(
7161                         null, null, null, null, null, new NetworkCapabilities(), 0,
7162                         mServiceContext, null, null, mService, null, null, null, 0, INVALID_UID);
7163 
7164         mServiceContext.setPermission(android.Manifest.permission.NETWORK_STACK, PERMISSION_DENIED);
7165 
7166         assertFalse(
7167                 "Mismatched uid/package name should not pass the location permission check",
7168                 mService.checkConnectivityDiagnosticsPermissions(
7169                         Process.myPid() + 1, Process.myUid() + 1, naiWithoutUid,
7170                         mContext.getOpPackageName()));
7171     }
7172 
7173     @Test
testCheckConnectivityDiagnosticsPermissionsNoLocationPermission()7174     public void testCheckConnectivityDiagnosticsPermissionsNoLocationPermission() throws Exception {
7175         final NetworkAgentInfo naiWithoutUid =
7176                 new NetworkAgentInfo(
7177                         null, null, null, null, null, new NetworkCapabilities(), 0,
7178                         mServiceContext, null, null, mService, null, null, null, 0, INVALID_UID);
7179 
7180         mServiceContext.setPermission(android.Manifest.permission.NETWORK_STACK, PERMISSION_DENIED);
7181 
7182         assertFalse(
7183                 "ACCESS_FINE_LOCATION permission necessary for Connectivity Diagnostics",
7184                 mService.checkConnectivityDiagnosticsPermissions(
7185                         Process.myPid(), Process.myUid(), naiWithoutUid,
7186                         mContext.getOpPackageName()));
7187     }
7188 
7189     @Test
testCheckConnectivityDiagnosticsPermissionsActiveVpn()7190     public void testCheckConnectivityDiagnosticsPermissionsActiveVpn() throws Exception {
7191         final Network network = new Network(NET_ID);
7192         final NetworkAgentInfo naiWithoutUid =
7193                 new NetworkAgentInfo(
7194                         null, null, network, null, null, new NetworkCapabilities(), 0,
7195                         mServiceContext, null, null, mService, null, null, null, 0, INVALID_UID);
7196 
7197         setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
7198                 Manifest.permission.ACCESS_FINE_LOCATION);
7199         mServiceContext.setPermission(android.Manifest.permission.NETWORK_STACK, PERMISSION_DENIED);
7200 
7201         // setUp() calls mockVpn() which adds a VPN with the Test Runner's uid. Configure it to be
7202         // active
7203         final VpnInfo info = new VpnInfo();
7204         info.ownerUid = Process.myUid();
7205         info.vpnIface = "interface";
7206         mMockVpn.setVpnInfo(info);
7207         mMockVpn.overrideUnderlyingNetworks(new Network[] {network});
7208         assertTrue(
7209                 "Active VPN permission not applied",
7210                 mService.checkConnectivityDiagnosticsPermissions(
7211                         Process.myPid(), Process.myUid(), naiWithoutUid,
7212                         mContext.getOpPackageName()));
7213 
7214         mMockVpn.overrideUnderlyingNetworks(null);
7215         assertFalse(
7216                 "VPN shouldn't receive callback on non-underlying network",
7217                 mService.checkConnectivityDiagnosticsPermissions(
7218                         Process.myPid(), Process.myUid(), naiWithoutUid,
7219                         mContext.getOpPackageName()));
7220     }
7221 
7222     @Test
testCheckConnectivityDiagnosticsPermissionsNetworkAdministrator()7223     public void testCheckConnectivityDiagnosticsPermissionsNetworkAdministrator() throws Exception {
7224         final NetworkCapabilities nc = new NetworkCapabilities();
7225         nc.setAdministratorUids(new int[] {Process.myUid()});
7226         final NetworkAgentInfo naiWithUid =
7227                 new NetworkAgentInfo(
7228                         null, null, null, null, null, nc, 0, mServiceContext, null, null,
7229                         mService, null, null, null, 0, INVALID_UID);
7230 
7231         setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
7232                 Manifest.permission.ACCESS_FINE_LOCATION);
7233         mServiceContext.setPermission(android.Manifest.permission.NETWORK_STACK, PERMISSION_DENIED);
7234 
7235         // Disconnect mock vpn so the uid check on NetworkAgentInfo is tested
7236         mMockVpn.disconnect();
7237         assertTrue(
7238                 "NetworkCapabilities administrator uid permission not applied",
7239                 mService.checkConnectivityDiagnosticsPermissions(
7240                         Process.myPid(), Process.myUid(), naiWithUid, mContext.getOpPackageName()));
7241     }
7242 
7243     @Test
testCheckConnectivityDiagnosticsPermissionsFails()7244     public void testCheckConnectivityDiagnosticsPermissionsFails() throws Exception {
7245         final NetworkCapabilities nc = new NetworkCapabilities();
7246         nc.setOwnerUid(Process.myUid());
7247         nc.setAdministratorUids(new int[] {Process.myUid()});
7248         final NetworkAgentInfo naiWithUid =
7249                 new NetworkAgentInfo(
7250                         null, null, null, null, null, nc, 0, mServiceContext, null, null,
7251                         mService, null, null, null, 0, INVALID_UID);
7252 
7253         setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
7254                 Manifest.permission.ACCESS_FINE_LOCATION);
7255         mServiceContext.setPermission(android.Manifest.permission.NETWORK_STACK, PERMISSION_DENIED);
7256 
7257         // Use wrong pid and uid
7258         assertFalse(
7259                 "Permissions allowed when they shouldn't be granted",
7260                 mService.checkConnectivityDiagnosticsPermissions(
7261                         Process.myPid() + 1, Process.myUid() + 1, naiWithUid,
7262                         mContext.getOpPackageName()));
7263     }
7264 
7265     @Test
testRegisterConnectivityDiagnosticsCallbackCallsOnConnectivityReport()7266     public void testRegisterConnectivityDiagnosticsCallbackCallsOnConnectivityReport()
7267             throws Exception {
7268         // Set up the Network, which leads to a ConnectivityReport being cached for the network.
7269         final TestNetworkCallback callback = new TestNetworkCallback();
7270         mCm.registerDefaultNetworkCallback(callback);
7271         final LinkProperties linkProperties = new LinkProperties();
7272         linkProperties.setInterfaceName(INTERFACE_NAME);
7273         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, linkProperties);
7274         mCellNetworkAgent.connect(true);
7275         callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
7276         callback.assertNoCallback();
7277 
7278         final NetworkRequest request = new NetworkRequest.Builder().build();
7279         when(mConnectivityDiagnosticsCallback.asBinder()).thenReturn(mIBinder);
7280 
7281         mServiceContext.setPermission(
7282                 android.Manifest.permission.NETWORK_STACK, PERMISSION_GRANTED);
7283 
7284         mService.registerConnectivityDiagnosticsCallback(
7285                 mConnectivityDiagnosticsCallback, request, mContext.getPackageName());
7286 
7287         // Block until all other events are done processing.
7288         HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
7289 
7290         verify(mConnectivityDiagnosticsCallback)
7291                 .onConnectivityReportAvailable(argThat(report -> {
7292                     return INTERFACE_NAME.equals(report.getLinkProperties().getInterfaceName())
7293                             && report.getNetworkCapabilities().hasTransport(TRANSPORT_CELLULAR);
7294                 }));
7295     }
7296 
setUpConnectivityDiagnosticsCallback()7297     private void setUpConnectivityDiagnosticsCallback() throws Exception {
7298         final NetworkRequest request = new NetworkRequest.Builder().build();
7299         when(mConnectivityDiagnosticsCallback.asBinder()).thenReturn(mIBinder);
7300 
7301         mServiceContext.setPermission(
7302                 android.Manifest.permission.NETWORK_STACK, PERMISSION_GRANTED);
7303 
7304         mService.registerConnectivityDiagnosticsCallback(
7305                 mConnectivityDiagnosticsCallback, request, mContext.getPackageName());
7306 
7307         // Block until all other events are done processing.
7308         HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
7309 
7310         // Connect the cell agent verify that it notifies TestNetworkCallback that it is available
7311         final TestNetworkCallback callback = new TestNetworkCallback();
7312         mCm.registerDefaultNetworkCallback(callback);
7313         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
7314         mCellNetworkAgent.connect(true);
7315         callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
7316         callback.assertNoCallback();
7317     }
7318 
7319     @Test
testConnectivityDiagnosticsCallbackOnConnectivityReportAvailable()7320     public void testConnectivityDiagnosticsCallbackOnConnectivityReportAvailable()
7321             throws Exception {
7322         setUpConnectivityDiagnosticsCallback();
7323 
7324         // Block until all other events are done processing.
7325         HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
7326 
7327         // Verify onConnectivityReport fired
7328         verify(mConnectivityDiagnosticsCallback).onConnectivityReportAvailable(
7329                 argThat(report -> {
7330                     final NetworkCapabilities nc = report.getNetworkCapabilities();
7331                     return nc.getUids() == null
7332                             && nc.getAdministratorUids().length == 0
7333                             && nc.getOwnerUid() == Process.INVALID_UID;
7334                 }));
7335     }
7336 
7337     @Test
testConnectivityDiagnosticsCallbackOnDataStallSuspected()7338     public void testConnectivityDiagnosticsCallbackOnDataStallSuspected() throws Exception {
7339         setUpConnectivityDiagnosticsCallback();
7340 
7341         // Trigger notifyDataStallSuspected() on the INetworkMonitorCallbacks instance in the
7342         // cellular network agent
7343         mCellNetworkAgent.notifyDataStallSuspected();
7344 
7345         // Block until all other events are done processing.
7346         HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
7347 
7348         // Verify onDataStallSuspected fired
7349         verify(mConnectivityDiagnosticsCallback).onDataStallSuspected(
7350                 argThat(report -> {
7351                     final NetworkCapabilities nc = report.getNetworkCapabilities();
7352                     return nc.getUids() == null
7353                             && nc.getAdministratorUids().length == 0
7354                             && nc.getOwnerUid() == Process.INVALID_UID;
7355                 }));
7356     }
7357 
7358     @Test
testConnectivityDiagnosticsCallbackOnConnectivityReported()7359     public void testConnectivityDiagnosticsCallbackOnConnectivityReported() throws Exception {
7360         setUpConnectivityDiagnosticsCallback();
7361 
7362         final Network n = mCellNetworkAgent.getNetwork();
7363         final boolean hasConnectivity = true;
7364         mService.reportNetworkConnectivity(n, hasConnectivity);
7365 
7366         // Block until all other events are done processing.
7367         HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
7368 
7369         // Verify onNetworkConnectivityReported fired
7370         verify(mConnectivityDiagnosticsCallback)
7371                 .onNetworkConnectivityReported(eq(n), eq(hasConnectivity));
7372 
7373         final boolean noConnectivity = false;
7374         mService.reportNetworkConnectivity(n, noConnectivity);
7375 
7376         // Block until all other events are done processing.
7377         HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
7378 
7379         // Wait for onNetworkConnectivityReported to fire
7380         verify(mConnectivityDiagnosticsCallback)
7381                 .onNetworkConnectivityReported(eq(n), eq(noConnectivity));
7382     }
7383 
7384     @Test
testRouteAddDeleteUpdate()7385     public void testRouteAddDeleteUpdate() throws Exception {
7386         final NetworkRequest request = new NetworkRequest.Builder().build();
7387         final TestNetworkCallback networkCallback = new TestNetworkCallback();
7388         mCm.registerNetworkCallback(request, networkCallback);
7389         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
7390         reset(mMockNetd);
7391         mCellNetworkAgent.connect(false);
7392         networkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
7393         final int netId = mCellNetworkAgent.getNetwork().netId;
7394 
7395         final String iface = "rmnet_data0";
7396         final InetAddress gateway = InetAddress.getByName("fe80::5678");
7397         RouteInfo direct = RouteInfo.makeHostRoute(gateway, iface);
7398         RouteInfo rio1 = new RouteInfo(new IpPrefix("2001:db8:1::/48"), gateway, iface);
7399         RouteInfo rio2 = new RouteInfo(new IpPrefix("2001:db8:2::/48"), gateway, iface);
7400         RouteInfo defaultRoute = new RouteInfo((IpPrefix) null, gateway, iface);
7401         RouteInfo defaultWithMtu = new RouteInfo(null, gateway, iface, RouteInfo.RTN_UNICAST,
7402                                                  1280 /* mtu */);
7403 
7404         // Send LinkProperties and check that we ask netd to add routes.
7405         LinkProperties lp = new LinkProperties();
7406         lp.setInterfaceName(iface);
7407         lp.addRoute(direct);
7408         lp.addRoute(rio1);
7409         lp.addRoute(defaultRoute);
7410         mCellNetworkAgent.sendLinkProperties(lp);
7411         networkCallback.expectLinkPropertiesThat(mCellNetworkAgent, x -> x.getRoutes().size() == 3);
7412 
7413         assertRoutesAdded(netId, direct, rio1, defaultRoute);
7414         reset(mMockNetd);
7415 
7416         // Send updated LinkProperties and check that we ask netd to add, remove, update routes.
7417         assertTrue(lp.getRoutes().contains(defaultRoute));
7418         lp.removeRoute(rio1);
7419         lp.addRoute(rio2);
7420         lp.addRoute(defaultWithMtu);
7421         // Ensure adding the same route with a different MTU replaces the previous route.
7422         assertFalse(lp.getRoutes().contains(defaultRoute));
7423         assertTrue(lp.getRoutes().contains(defaultWithMtu));
7424 
7425         mCellNetworkAgent.sendLinkProperties(lp);
7426         networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
7427                 x -> x.getRoutes().contains(rio2));
7428 
7429         assertRoutesRemoved(netId, rio1);
7430         assertRoutesAdded(netId, rio2);
7431 
7432         ArgumentCaptor<RouteInfoParcel> captor = ArgumentCaptor.forClass(RouteInfoParcel.class);
7433         verify(mMockNetd).networkUpdateRouteParcel(eq(netId), captor.capture());
7434         assertRouteInfoParcelMatches(defaultWithMtu, captor.getValue());
7435 
7436 
7437         mCm.unregisterNetworkCallback(networkCallback);
7438     }
7439 }
7440