• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2012 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.server;
18 
19 import static android.Manifest.permission.ACCESS_NETWORK_STATE;
20 import static android.Manifest.permission.CHANGE_NETWORK_STATE;
21 import static android.Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS;
22 import static android.Manifest.permission.CONTROL_OEM_PAID_NETWORK_PREFERENCE;
23 import static android.Manifest.permission.CREATE_USERS;
24 import static android.Manifest.permission.DUMP;
25 import static android.Manifest.permission.GET_INTENT_SENDER_INTENT;
26 import static android.Manifest.permission.LOCAL_MAC_ADDRESS;
27 import static android.Manifest.permission.MANAGE_TEST_NETWORKS;
28 import static android.Manifest.permission.NETWORK_FACTORY;
29 import static android.Manifest.permission.NETWORK_SETTINGS;
30 import static android.Manifest.permission.NETWORK_SETUP_WIZARD;
31 import static android.Manifest.permission.NETWORK_STACK;
32 import static android.Manifest.permission.PACKET_KEEPALIVE_OFFLOAD;
33 import static android.Manifest.permission.READ_DEVICE_CONFIG;
34 import static android.Manifest.permission.STATUS_BAR_SERVICE;
35 import static android.app.ActivityManager.UidFrozenStateChangedCallback.UID_FROZEN_STATE_FROZEN;
36 import static android.app.ActivityManager.UidFrozenStateChangedCallback.UID_FROZEN_STATE_UNFROZEN;
37 import static android.app.PendingIntent.FLAG_IMMUTABLE;
38 import static android.content.Intent.ACTION_PACKAGE_ADDED;
39 import static android.content.Intent.ACTION_PACKAGE_REMOVED;
40 import static android.content.Intent.ACTION_PACKAGE_REPLACED;
41 import static android.content.Intent.ACTION_USER_ADDED;
42 import static android.content.Intent.ACTION_USER_REMOVED;
43 import static android.content.pm.PackageInfo.REQUESTED_PERMISSION_GRANTED;
44 import static android.content.pm.PackageManager.FEATURE_ETHERNET;
45 import static android.content.pm.PackageManager.FEATURE_WIFI;
46 import static android.content.pm.PackageManager.FEATURE_WIFI_DIRECT;
47 import static android.content.pm.PackageManager.GET_PERMISSIONS;
48 import static android.content.pm.PackageManager.PERMISSION_DENIED;
49 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
50 import static android.net.ConnectivityManager.ACTION_CAPTIVE_PORTAL_SIGN_IN;
51 import static android.net.ConnectivityManager.ACTION_DATA_ACTIVITY_CHANGE;
52 import static android.net.ConnectivityManager.BLOCKED_METERED_REASON_DATA_SAVER;
53 import static android.net.ConnectivityManager.BLOCKED_METERED_REASON_MASK;
54 import static android.net.ConnectivityManager.BLOCKED_METERED_REASON_USER_RESTRICTED;
55 import static android.net.ConnectivityManager.BLOCKED_REASON_BATTERY_SAVER;
56 import static android.net.ConnectivityManager.BLOCKED_REASON_DOZE;
57 import static android.net.ConnectivityManager.BLOCKED_REASON_NONE;
58 import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
59 import static android.net.ConnectivityManager.EXTRA_DEVICE_TYPE;
60 import static android.net.ConnectivityManager.EXTRA_IS_ACTIVE;
61 import static android.net.ConnectivityManager.EXTRA_NETWORK_INFO;
62 import static android.net.ConnectivityManager.EXTRA_NETWORK_TYPE;
63 import static android.net.ConnectivityManager.EXTRA_REALTIME_NS;
64 import static android.net.ConnectivityManager.FIREWALL_CHAIN_BACKGROUND;
65 import static android.net.ConnectivityManager.FIREWALL_CHAIN_DOZABLE;
66 import static android.net.ConnectivityManager.FIREWALL_CHAIN_LOW_POWER_STANDBY;
67 import static android.net.ConnectivityManager.FIREWALL_CHAIN_METERED_ALLOW;
68 import static android.net.ConnectivityManager.FIREWALL_CHAIN_METERED_DENY_ADMIN;
69 import static android.net.ConnectivityManager.FIREWALL_CHAIN_METERED_DENY_USER;
70 import static android.net.ConnectivityManager.FIREWALL_CHAIN_OEM_DENY_1;
71 import static android.net.ConnectivityManager.FIREWALL_CHAIN_OEM_DENY_2;
72 import static android.net.ConnectivityManager.FIREWALL_CHAIN_OEM_DENY_3;
73 import static android.net.ConnectivityManager.FIREWALL_CHAIN_POWERSAVE;
74 import static android.net.ConnectivityManager.FIREWALL_CHAIN_RESTRICTED;
75 import static android.net.ConnectivityManager.FIREWALL_CHAIN_STANDBY;
76 import static android.net.ConnectivityManager.FIREWALL_RULE_ALLOW;
77 import static android.net.ConnectivityManager.FIREWALL_RULE_DEFAULT;
78 import static android.net.ConnectivityManager.FIREWALL_RULE_DENY;
79 import static android.net.ConnectivityManager.PROFILE_NETWORK_PREFERENCE_DEFAULT;
80 import static android.net.ConnectivityManager.PROFILE_NETWORK_PREFERENCE_ENTERPRISE;
81 import static android.net.ConnectivityManager.PROFILE_NETWORK_PREFERENCE_ENTERPRISE_BLOCKING;
82 import static android.net.ConnectivityManager.PROFILE_NETWORK_PREFERENCE_ENTERPRISE_NO_FALLBACK;
83 import static android.net.ConnectivityManager.TYPE_ETHERNET;
84 import static android.net.ConnectivityManager.TYPE_MOBILE;
85 import static android.net.ConnectivityManager.TYPE_MOBILE_SUPL;
86 import static android.net.ConnectivityManager.TYPE_VPN;
87 import static android.net.ConnectivityManager.TYPE_WIFI;
88 import static android.net.ConnectivitySettingsManager.PRIVATE_DNS_MODE_OFF;
89 import static android.net.ConnectivitySettingsManager.PRIVATE_DNS_MODE_OPPORTUNISTIC;
90 import static android.net.ConnectivitySettingsManager.PRIVATE_DNS_MODE_PROVIDER_HOSTNAME;
91 import static android.net.INetd.PERMISSION_INTERNET;
92 import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_DNS;
93 import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_FALLBACK;
94 import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_HTTP;
95 import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_HTTPS;
96 import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_PRIVDNS;
97 import static android.net.INetworkMonitor.NETWORK_VALIDATION_RESULT_PARTIAL;
98 import static android.net.INetworkMonitor.NETWORK_VALIDATION_RESULT_VALID;
99 import static android.net.NetworkCapabilities.NET_CAPABILITY_BIP;
100 import static android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL;
101 import static android.net.NetworkCapabilities.NET_CAPABILITY_CBS;
102 import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN;
103 import static android.net.NetworkCapabilities.NET_CAPABILITY_EIMS;
104 import static android.net.NetworkCapabilities.NET_CAPABILITY_ENTERPRISE;
105 import static android.net.NetworkCapabilities.NET_CAPABILITY_FOREGROUND;
106 import static android.net.NetworkCapabilities.NET_CAPABILITY_FOTA;
107 import static android.net.NetworkCapabilities.NET_CAPABILITY_IA;
108 import static android.net.NetworkCapabilities.NET_CAPABILITY_IMS;
109 import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
110 import static android.net.NetworkCapabilities.NET_CAPABILITY_MMS;
111 import static android.net.NetworkCapabilities.NET_CAPABILITY_MMTEL;
112 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED;
113 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
114 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
115 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING;
116 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED;
117 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED;
118 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN;
119 import static android.net.NetworkCapabilities.NET_CAPABILITY_OEM_PAID;
120 import static android.net.NetworkCapabilities.NET_CAPABILITY_OEM_PRIVATE;
121 import static android.net.NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVITY;
122 import static android.net.NetworkCapabilities.NET_CAPABILITY_RCS;
123 import static android.net.NetworkCapabilities.NET_CAPABILITY_SUPL;
124 import static android.net.NetworkCapabilities.NET_CAPABILITY_TEMPORARILY_NOT_METERED;
125 import static android.net.NetworkCapabilities.NET_CAPABILITY_TRUSTED;
126 import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
127 import static android.net.NetworkCapabilities.NET_CAPABILITY_VSIM;
128 import static android.net.NetworkCapabilities.NET_CAPABILITY_WIFI_P2P;
129 import static android.net.NetworkCapabilities.NET_CAPABILITY_XCAP;
130 import static android.net.NetworkCapabilities.NET_ENTERPRISE_ID_1;
131 import static android.net.NetworkCapabilities.NET_ENTERPRISE_ID_2;
132 import static android.net.NetworkCapabilities.NET_ENTERPRISE_ID_3;
133 import static android.net.NetworkCapabilities.NET_ENTERPRISE_ID_4;
134 import static android.net.NetworkCapabilities.NET_ENTERPRISE_ID_5;
135 import static android.net.NetworkCapabilities.REDACT_FOR_ACCESS_FINE_LOCATION;
136 import static android.net.NetworkCapabilities.REDACT_FOR_LOCAL_MAC_ADDRESS;
137 import static android.net.NetworkCapabilities.REDACT_FOR_NETWORK_SETTINGS;
138 import static android.net.NetworkCapabilities.REDACT_NONE;
139 import static android.net.NetworkCapabilities.TRANSPORT_BLUETOOTH;
140 import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
141 import static android.net.NetworkCapabilities.TRANSPORT_ETHERNET;
142 import static android.net.NetworkCapabilities.TRANSPORT_TEST;
143 import static android.net.NetworkCapabilities.TRANSPORT_VPN;
144 import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
145 import static android.net.NetworkCapabilities.TRANSPORT_WIFI_AWARE;
146 import static android.net.NetworkScore.KEEP_CONNECTED_FOR_HANDOVER;
147 import static android.net.OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PAID;
148 import static android.net.OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK;
149 import static android.net.OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY;
150 import static android.net.OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY;
151 import static android.net.OemNetworkPreferences.OEM_NETWORK_PREFERENCE_TEST;
152 import static android.net.OemNetworkPreferences.OEM_NETWORK_PREFERENCE_TEST_ONLY;
153 import static android.net.OemNetworkPreferences.OEM_NETWORK_PREFERENCE_UNINITIALIZED;
154 import static android.net.Proxy.PROXY_CHANGE_ACTION;
155 import static android.net.RouteInfo.RTN_UNREACHABLE;
156 import static android.net.connectivity.ConnectivityCompatChanges.NETWORK_BLOCKED_WITHOUT_INTERNET_PERMISSION;
157 import static android.net.resolv.aidl.IDnsResolverUnsolicitedEventListener.PREFIX_OPERATION_ADDED;
158 import static android.net.resolv.aidl.IDnsResolverUnsolicitedEventListener.PREFIX_OPERATION_REMOVED;
159 import static android.net.resolv.aidl.IDnsResolverUnsolicitedEventListener.VALIDATION_RESULT_FAILURE;
160 import static android.net.resolv.aidl.IDnsResolverUnsolicitedEventListener.VALIDATION_RESULT_SUCCESS;
161 import static android.os.Process.INVALID_UID;
162 import static android.system.OsConstants.IPPROTO_TCP;
163 import static android.telephony.DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH;
164 import static android.telephony.DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
165 
166 import static com.android.net.module.util.DeviceConfigUtils.TETHERING_MODULE_NAME;
167 import static com.android.server.ConnectivityService.MAX_NETWORK_REQUESTS_PER_SYSTEM_UID;
168 import static com.android.server.ConnectivityService.PREFERENCE_ORDER_MOBILE_DATA_PREFERERRED;
169 import static com.android.server.ConnectivityService.PREFERENCE_ORDER_OEM;
170 import static com.android.server.ConnectivityService.PREFERENCE_ORDER_PROFILE;
171 import static com.android.server.ConnectivityService.PREFERENCE_ORDER_VPN;
172 import static com.android.server.ConnectivityService.createDeliveryGroupKeyForConnectivityAction;
173 import static com.android.server.ConnectivityService.makeNflogPrefix;
174 import static com.android.server.ConnectivityServiceTestUtils.transportToLegacyType;
175 import static com.android.server.NetworkAgentWrapper.CallbackType.OnQosCallbackRegister;
176 import static com.android.server.NetworkAgentWrapper.CallbackType.OnQosCallbackUnregister;
177 import static com.android.testutils.Cleanup.testAndCleanup;
178 import static com.android.testutils.ConcurrentUtils.await;
179 import static com.android.testutils.ConcurrentUtils.durationOf;
180 import static com.android.testutils.DevSdkIgnoreRule.IgnoreAfter;
181 import static com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
182 import static com.android.testutils.DevSdkIgnoreRuleKt.SC_V2;
183 import static com.android.testutils.FunctionalUtils.ignoreExceptions;
184 import static com.android.testutils.HandlerUtils.visibleOnHandlerThread;
185 import static com.android.testutils.HandlerUtils.waitForIdleSerialExecutor;
186 import static com.android.testutils.MiscAsserts.assertContainsAll;
187 import static com.android.testutils.MiscAsserts.assertContainsExactly;
188 import static com.android.testutils.MiscAsserts.assertEmpty;
189 import static com.android.testutils.MiscAsserts.assertLength;
190 import static com.android.testutils.MiscAsserts.assertRunsInAtMost;
191 import static com.android.testutils.MiscAsserts.assertSameElements;
192 import static com.android.testutils.MiscAsserts.assertThrows;
193 import static com.android.testutils.RecorderCallback.CallbackEntry.AVAILABLE;
194 import static com.android.testutils.RecorderCallback.CallbackEntry.BLOCKED_STATUS;
195 import static com.android.testutils.RecorderCallback.CallbackEntry.BLOCKED_STATUS_INT;
196 import static com.android.testutils.RecorderCallback.CallbackEntry.LINK_PROPERTIES_CHANGED;
197 import static com.android.testutils.RecorderCallback.CallbackEntry.LOSING;
198 import static com.android.testutils.RecorderCallback.CallbackEntry.LOST;
199 import static com.android.testutils.RecorderCallback.CallbackEntry.NETWORK_CAPS_UPDATED;
200 import static com.android.testutils.RecorderCallback.CallbackEntry.RESUMED;
201 import static com.android.testutils.RecorderCallback.CallbackEntry.SUSPENDED;
202 import static com.android.testutils.RecorderCallback.CallbackEntry.UNAVAILABLE;
203 import static com.android.testutils.TestPermissionUtil.runAsShell;
204 
205 import static org.hamcrest.MatcherAssert.assertThat;
206 import static org.hamcrest.Matchers.containsString;
207 import static org.junit.Assert.assertEquals;
208 import static org.junit.Assert.assertFalse;
209 import static org.junit.Assert.assertNotEquals;
210 import static org.junit.Assert.assertNotNull;
211 import static org.junit.Assert.assertNull;
212 import static org.junit.Assert.assertTrue;
213 import static org.junit.Assert.fail;
214 import static org.junit.Assume.assumeFalse;
215 import static org.junit.Assume.assumeTrue;
216 import static org.mockito.AdditionalMatchers.aryEq;
217 import static org.mockito.ArgumentMatchers.anyBoolean;
218 import static org.mockito.ArgumentMatchers.anyLong;
219 import static org.mockito.ArgumentMatchers.anyString;
220 import static org.mockito.ArgumentMatchers.argThat;
221 import static org.mockito.ArgumentMatchers.eq;
222 import static org.mockito.ArgumentMatchers.isNull;
223 import static org.mockito.ArgumentMatchers.anyInt;
224 import static org.mockito.Mockito.any;
225 import static org.mockito.Mockito.atLeastOnce;
226 import static org.mockito.Mockito.clearInvocations;
227 import static org.mockito.Mockito.doAnswer;
228 import static org.mockito.Mockito.doNothing;
229 import static org.mockito.Mockito.doReturn;
230 import static org.mockito.Mockito.doThrow;
231 import static org.mockito.Mockito.inOrder;
232 import static org.mockito.Mockito.mock;
233 import static org.mockito.Mockito.never;
234 import static org.mockito.Mockito.reset;
235 import static org.mockito.Mockito.spy;
236 import static org.mockito.Mockito.timeout;
237 import static org.mockito.Mockito.times;
238 import static org.mockito.Mockito.verify;
239 import static org.mockito.Mockito.verifyNoMoreInteractions;
240 
241 import static java.util.Arrays.asList;
242 
243 import android.Manifest;
244 import android.annotation.NonNull;
245 import android.annotation.Nullable;
246 import android.app.ActivityManager;
247 import android.app.ActivityManager.UidFrozenStateChangedCallback;
248 import android.app.AlarmManager;
249 import android.app.AppOpsManager;
250 import android.app.BroadcastOptions;
251 import android.app.NotificationManager;
252 import android.app.PendingIntent;
253 import android.app.admin.DevicePolicyManager;
254 import android.app.usage.NetworkStatsManager;
255 import android.compat.testing.PlatformCompatChangeRule;
256 import android.content.BroadcastReceiver;
257 import android.content.ComponentName;
258 import android.content.ContentProvider;
259 import android.content.ContentResolver;
260 import android.content.Context;
261 import android.content.Intent;
262 import android.content.IntentFilter;
263 import android.content.pm.ApplicationInfo;
264 import android.content.pm.ModuleInfo;
265 import android.content.pm.PackageInfo;
266 import android.content.pm.PackageManager;
267 import android.content.pm.ResolveInfo;
268 import android.content.pm.ServiceInfo;
269 import android.content.pm.UserInfo;
270 import android.content.res.Resources;
271 import android.location.LocationManager;
272 import android.net.CaptivePortal;
273 import android.net.CaptivePortalData;
274 import android.net.ConnectionInfo;
275 import android.net.ConnectivityDiagnosticsManager.DataStallReport;
276 import android.net.ConnectivityManager;
277 import android.net.ConnectivityManager.NetworkCallback;
278 import android.net.ConnectivityManager.PacketKeepalive;
279 import android.net.ConnectivityManager.PacketKeepaliveCallback;
280 import android.net.ConnectivityManager.TooManyRequestsException;
281 import android.net.ConnectivitySettingsManager;
282 import android.net.ConnectivityThread;
283 import android.net.DataStallReportParcelable;
284 import android.net.EthernetManager;
285 import android.net.EthernetNetworkSpecifier;
286 import android.net.IConnectivityDiagnosticsCallback;
287 import android.net.IDnsResolver;
288 import android.net.INetd;
289 import android.net.INetworkMonitor;
290 import android.net.INetworkMonitorCallbacks;
291 import android.net.IOnCompleteListener;
292 import android.net.IQosCallback;
293 import android.net.InetAddresses;
294 import android.net.InterfaceConfigurationParcel;
295 import android.net.IpPrefix;
296 import android.net.IpSecManager;
297 import android.net.IpSecManager.UdpEncapsulationSocket;
298 import android.net.LinkAddress;
299 import android.net.LinkProperties;
300 import android.net.MatchAllNetworkSpecifier;
301 import android.net.NativeNetworkConfig;
302 import android.net.NativeNetworkType;
303 import android.net.Network;
304 import android.net.NetworkAgent;
305 import android.net.NetworkAgentConfig;
306 import android.net.NetworkCapabilities;
307 import android.net.NetworkFactory;
308 import android.net.NetworkInfo;
309 import android.net.NetworkInfo.DetailedState;
310 import android.net.NetworkPolicyManager;
311 import android.net.NetworkPolicyManager.NetworkPolicyCallback;
312 import android.net.NetworkProvider;
313 import android.net.NetworkRequest;
314 import android.net.NetworkScore;
315 import android.net.NetworkSpecifier;
316 import android.net.NetworkStack;
317 import android.net.NetworkStateSnapshot;
318 import android.net.NetworkTestResultParcelable;
319 import android.net.OemNetworkPreferences;
320 import android.net.PacProxyManager;
321 import android.net.ProfileNetworkPreference;
322 import android.net.Proxy;
323 import android.net.ProxyInfo;
324 import android.net.QosCallbackException;
325 import android.net.QosFilter;
326 import android.net.QosSession;
327 import android.net.ResolverParamsParcel;
328 import android.net.RouteInfo;
329 import android.net.RouteInfoParcel;
330 import android.net.SocketKeepalive;
331 import android.net.TelephonyNetworkSpecifier;
332 import android.net.TetheringManager;
333 import android.net.TransportInfo;
334 import android.net.UidRange;
335 import android.net.UidRangeParcel;
336 import android.net.UnderlyingNetworkInfo;
337 import android.net.Uri;
338 import android.net.VpnManager;
339 import android.net.VpnTransportInfo;
340 import android.net.connectivity.ConnectivityCompatChanges;
341 import android.net.metrics.IpConnectivityLog;
342 import android.net.netd.aidl.NativeUidRangeConfig;
343 import android.net.networkstack.NetworkStackClientBase;
344 import android.net.resolv.aidl.Nat64PrefixEventParcel;
345 import android.net.resolv.aidl.PrivateDnsValidationEventParcel;
346 import android.net.shared.PrivateDnsConfig;
347 import android.net.wifi.WifiInfo;
348 import android.os.BadParcelableException;
349 import android.os.BatteryStatsManager;
350 import android.os.Binder;
351 import android.os.Build;
352 import android.os.Bundle;
353 import android.os.ConditionVariable;
354 import android.os.Handler;
355 import android.os.HandlerThread;
356 import android.os.IBinder;
357 import android.os.INetworkManagementService;
358 import android.os.Looper;
359 import android.os.Messenger;
360 import android.os.Parcel;
361 import android.os.ParcelFileDescriptor;
362 import android.os.Parcelable;
363 import android.os.PersistableBundle;
364 import android.os.Process;
365 import android.os.RemoteException;
366 import android.os.ServiceSpecificException;
367 import android.os.SystemClock;
368 import android.os.SystemConfigManager;
369 import android.os.UserHandle;
370 import android.os.UserManager;
371 import android.provider.Settings;
372 import android.system.Os;
373 import android.telephony.SubscriptionManager;
374 import android.telephony.TelephonyManager;
375 import android.telephony.data.EpsBearerQosSessionAttributes;
376 import android.telephony.data.NrQosSessionAttributes;
377 import android.test.mock.MockContentResolver;
378 import android.text.TextUtils;
379 import android.util.ArraySet;
380 import android.util.Log;
381 import android.util.Pair;
382 import android.util.Range;
383 import android.util.SparseArray;
384 
385 import androidx.test.InstrumentationRegistry;
386 import androidx.test.filters.SmallTest;
387 
388 import com.android.connectivity.resources.R;
389 import com.android.internal.annotations.GuardedBy;
390 import com.android.internal.app.IBatteryStats;
391 import com.android.internal.net.VpnConfig;
392 import com.android.internal.util.WakeupMessage;
393 import com.android.internal.util.test.BroadcastInterceptingContext;
394 import com.android.internal.util.test.FakeSettingsProvider;
395 import com.android.modules.utils.build.SdkLevel;
396 import com.android.net.module.util.ArrayTrackRecord;
397 import com.android.net.module.util.BaseNetdUnsolicitedEventListener;
398 import com.android.net.module.util.CollectionUtils;
399 import com.android.net.module.util.LocationPermissionChecker;
400 import com.android.net.module.util.NetworkMonitorUtils;
401 import com.android.networkstack.apishim.ConstantsShim;
402 import com.android.networkstack.apishim.NetworkAgentConfigShimImpl;
403 import com.android.networkstack.apishim.common.BroadcastOptionsShim;
404 import com.android.networkstack.apishim.common.UnsupportedApiLevelException;
405 import com.android.server.ConnectivityService.ConnectivityDiagnosticsCallbackInfo;
406 import com.android.server.ConnectivityService.NetworkRequestInfo;
407 import com.android.server.ConnectivityServiceTest.ConnectivityServiceDependencies.DestroySocketsWrapper;
408 import com.android.server.ConnectivityServiceTest.ConnectivityServiceDependencies.ReportedInterfaces;
409 import com.android.server.L2capNetworkProvider;
410 import com.android.server.connectivity.ApplicationSelfCertifiedNetworkCapabilities;
411 import com.android.server.connectivity.AutomaticOnOffKeepaliveTracker;
412 import com.android.server.connectivity.CarrierPrivilegeAuthenticator;
413 import com.android.server.connectivity.ClatCoordinator;
414 import com.android.server.connectivity.ConnectivityFlags;
415 import com.android.server.connectivity.ConnectivityResources;
416 import com.android.server.connectivity.InterfaceTracker;
417 import com.android.server.connectivity.KeepaliveTracker;
418 import com.android.server.connectivity.MultinetworkPolicyTracker;
419 import com.android.server.connectivity.MultinetworkPolicyTrackerTestDependencies;
420 import com.android.server.connectivity.Nat464Xlat;
421 import com.android.server.connectivity.NetworkAgentInfo;
422 import com.android.server.connectivity.NetworkNotificationManager;
423 import com.android.server.connectivity.NetworkNotificationManager.NotificationType;
424 import com.android.server.connectivity.PermissionMonitor;
425 import com.android.server.connectivity.ProxyTracker;
426 import com.android.server.connectivity.QosCallbackTracker;
427 import com.android.server.connectivity.SatelliteAccessController;
428 import com.android.server.connectivity.TcpKeepaliveController;
429 import com.android.server.connectivity.UidRangeUtils;
430 import com.android.server.net.NetworkPinner;
431 import com.android.testutils.DevSdkIgnoreRule;
432 import com.android.testutils.DevSdkIgnoreRunner;
433 import com.android.testutils.FunctionalUtils.Function3;
434 import com.android.testutils.FunctionalUtils.ThrowingConsumer;
435 import com.android.testutils.FunctionalUtils.ThrowingRunnable;
436 import com.android.testutils.HandlerUtils;
437 import com.android.testutils.RecorderCallback.CallbackEntry;
438 import com.android.testutils.TestableNetworkCallback;
439 import com.android.testutils.TestableNetworkOfferCallback;
440 
441 import libcore.junit.util.compat.CoreCompatChangeRule.DisableCompatChanges;
442 import libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges;
443 
444 import org.junit.After;
445 import org.junit.Assert;
446 import org.junit.Before;
447 import org.junit.Ignore;
448 import org.junit.Rule;
449 import org.junit.Test;
450 import org.junit.runner.RunWith;
451 import org.mockito.AdditionalAnswers;
452 import org.mockito.ArgumentCaptor;
453 import org.mockito.InOrder;
454 import org.mockito.Mock;
455 import org.mockito.MockitoAnnotations;
456 import org.mockito.Spy;
457 import org.mockito.stubbing.Answer;
458 
459 import java.io.FileDescriptor;
460 import java.io.IOException;
461 import java.io.PrintWriter;
462 import java.io.StringWriter;
463 import java.lang.reflect.Method;
464 import java.net.DatagramSocket;
465 import java.net.Inet4Address;
466 import java.net.Inet6Address;
467 import java.net.InetAddress;
468 import java.net.InetSocketAddress;
469 import java.net.Socket;
470 import java.util.ArrayList;
471 import java.util.Arrays;
472 import java.util.Collection;
473 import java.util.Collections;
474 import java.util.Comparator;
475 import java.util.HashMap;
476 import java.util.HashSet;
477 import java.util.List;
478 import java.util.Map;
479 import java.util.Objects;
480 import java.util.Set;
481 import java.util.UUID;
482 import java.util.concurrent.CompletableFuture;
483 import java.util.concurrent.CountDownLatch;
484 import java.util.concurrent.Executor;
485 import java.util.concurrent.ExecutorService;
486 import java.util.concurrent.Executors;
487 import java.util.concurrent.LinkedBlockingQueue;
488 import java.util.concurrent.TimeUnit;
489 import java.util.concurrent.TimeoutException;
490 import java.util.concurrent.atomic.AtomicBoolean;
491 import java.util.concurrent.atomic.AtomicReference;
492 import java.util.function.BiConsumer;
493 import java.util.function.Consumer;
494 import java.util.function.Predicate;
495 import java.util.function.Supplier;
496 import java.util.regex.Matcher;
497 import java.util.regex.Pattern;
498 import java.util.stream.Collectors;
499 
500 /**
501  * Tests for {@link ConnectivityService}.
502  *
503  * Build, install and run with:
504  *  runtest frameworks-net -c com.android.server.ConnectivityServiceTest
505  */
506 // TODO : move methods from this test to smaller tests in the 'connectivityservice' directory
507 // to enable faster testing of smaller groups of functionality.
508 @RunWith(DevSdkIgnoreRunner.class)
509 @SmallTest
510 @DevSdkIgnoreRunner.MonitorThreadLeak
511 @DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
512 public class ConnectivityServiceTest {
513     private static final String TAG = "ConnectivityServiceTest";
514 
515     @Rule
516     public final DevSdkIgnoreRule ignoreRule = new DevSdkIgnoreRule();
517 
518     @Rule
519     public final PlatformCompatChangeRule compatChangeRule = new PlatformCompatChangeRule();
520 
521     private static final int TIMEOUT_MS = 2_000;
522     // Broadcasts can take a long time to be delivered. The test will not wait for that long unless
523     // there is a failure, so use a long timeout.
524     private static final int BROADCAST_TIMEOUT_MS = 30_000;
525     private static final int TEST_LINGER_DELAY_MS = 400;
526     private static final int TEST_NASCENT_DELAY_MS = 300;
527     // Chosen to be less than the linger and nascent timeout. This ensures that we can distinguish
528     // between a LOST callback that arrives immediately and a LOST callback that arrives after
529     // the linger/nascent timeout. For this, our assertions should run fast enough to leave
530     // less than (mService.mLingerDelayMs - TEST_CALLBACK_TIMEOUT_MS) between the time callbacks are
531     // supposedly fired, and the time we call expectCapChanged.
532     private static final int TEST_CALLBACK_TIMEOUT_MS = 250;
533     // Chosen to be less than TEST_CALLBACK_TIMEOUT_MS. This ensures that requests have time to
534     // complete before callbacks are verified.
535     private static final int TEST_REQUEST_TIMEOUT_MS = 150;
536 
537     private static final int UNREASONABLY_LONG_ALARM_WAIT_MS = 2_000;
538 
539     private static final long TIMESTAMP = 1234L;
540 
541     private static final int NET_ID = 110;
542     private static final int OEM_PREF_ANY_NET_ID = -1;
543     // Set a non-zero value to verify the flow to set tcp init rwnd value.
544     private static final int TEST_TCP_INIT_RWND = 60;
545 
546     // Used for testing the per-work-profile default network.
547     private static final int TEST_APP_ID = 103;
548     private static final int TEST_WORK_PROFILE_USER_ID = 2;
549     private static final int TEST_WORK_PROFILE_APP_UID =
550             UserHandle.getUid(TEST_WORK_PROFILE_USER_ID, TEST_APP_ID);
551     private static final int TEST_APP_ID_2 = 104;
552     private static final int TEST_WORK_PROFILE_APP_UID_2 =
553             UserHandle.getUid(TEST_WORK_PROFILE_USER_ID, TEST_APP_ID_2);
554     private static final int TEST_APP_ID_3 = 105;
555     private static final int TEST_APP_ID_4 = 106;
556     private static final int TEST_APP_ID_5 = 107;
557 
558     private static final String CLAT_PREFIX = "v4-";
559     private static final String MOBILE_IFNAME = "test_rmnet_data0";
560     private static final String CLAT_MOBILE_IFNAME = CLAT_PREFIX + MOBILE_IFNAME;
561     private static final String WIFI_IFNAME = "test_wlan0";
562     private static final String WIFI_WOL_IFNAME = "test_wlan_wol";
563     private static final String VPN_IFNAME = "tun10042";
564     private static final String ETHERNET_IFNAME = "eth0";
565     private static final String TEST_PACKAGE_NAME = "com.android.test.package";
566     private static final int TEST_PACKAGE_UID = 123;
567     private static final int TEST_PACKAGE_UID2 = 321;
568     private static final int TEST_PACKAGE_UID3 = 456;
569     private static final int NETWORK_ACTIVITY_NO_UID = -1;
570     private static final int TEST_SUBSCRIPTION_ID = 1;
571 
572     private static final int PACKET_WAKEUP_MARK_MASK = 0x80000000;
573 
574     private static final String ALWAYS_ON_PACKAGE = "com.android.test.alwaysonvpn";
575 
576     private static final String INTERFACE_NAME = "interface";
577 
578     private static final String TEST_VENUE_URL_NA_PASSPOINT = "https://android.com/";
579     private static final String TEST_VENUE_URL_NA_OTHER = "https://example.com/";
580     private static final String TEST_TERMS_AND_CONDITIONS_URL_NA_PASSPOINT =
581             "https://android.com/terms/";
582     private static final String TEST_TERMS_AND_CONDITIONS_URL_NA_OTHER =
583             "https://example.com/terms/";
584     private static final String TEST_VENUE_URL_CAPPORT = "https://android.com/capport/";
585     private static final String TEST_USER_PORTAL_API_URL_CAPPORT =
586             "https://android.com/user/api/capport/";
587     private static final String TEST_FRIENDLY_NAME = "Network friendly name";
588     private static final String TEST_REDIRECT_URL = "http://example.com/firstPath";
589     private static final String QUEUE_NETWORK_AGENT_EVENTS_IN_SYSTEM_SERVER =
590             "queue_network_agent_events_in_system_server";
591 
592     private boolean mShouldCreateNetworksImmediately;
593 
594     private MockContext mServiceContext;
595     private HandlerThread mCsHandlerThread;
596     private ConnectivityServiceDependencies mDeps;
597     private PermissionMonitorDependencies mPermDeps;
598     private AutomaticOnOffKeepaliveTrackerDependencies mAutoOnOffKeepaliveDependencies;
599     private ConnectivityService mService;
600     private WrappedConnectivityManager mCm;
601     private TestNetworkAgentWrapper mWiFiAgent;
602     private TestNetworkAgentWrapper mCellAgent;
603     private TestNetworkAgentWrapper mEthernetAgent;
604     private final List<TestNetworkAgentWrapper> mCreatedAgents = new ArrayList<>();
605     private MockVpn mMockVpn;
606     private Context mContext;
607     private NetworkPolicyCallback mPolicyCallback;
608     private WrappedMultinetworkPolicyTracker mPolicyTracker;
609     private ProxyTracker mProxyTracker;
610     private HandlerThread mAlarmManagerThread;
611     private TestNetIdManager mNetIdManager;
612     private QosCallbackMockHelper mQosCallbackMockHelper;
613     private QosCallbackTracker mQosCallbackTracker;
614     private TestNetworkCallback mDefaultNetworkCallback;
615     private TestNetworkCallback mSystemDefaultNetworkCallback;
616     private TestNetworkCallback mProfileDefaultNetworkCallback;
617     private TestNetworkCallback mTestPackageDefaultNetworkCallback;
618     private TestNetworkCallback mProfileDefaultNetworkCallbackAsAppUid2;
619     private TestNetworkCallback mTestPackageDefaultNetworkCallback2;
620 
621     // State variables required to emulate NetworkPolicyManagerService behaviour.
622     private int mBlockedReasons = BLOCKED_REASON_NONE;
623 
624     @Mock DeviceIdleInternal mDeviceIdleInternal;
625     @Mock INetworkManagementService mNetworkManagementService;
626     @Mock NetworkStatsManager mStatsManager;
627     @Mock IDnsResolver mMockDnsResolver;
628     @Mock INetd mMockNetd;
629     @Mock NetworkStackClientBase mNetworkStack;
630     @Mock PackageManager mPackageManager;
631     @Mock UserManager mUserManager;
632     @Mock NotificationManager mNotificationManager;
633     @Mock AlarmManager mAlarmManager;
634     @Mock IConnectivityDiagnosticsCallback mConnectivityDiagnosticsCallback;
635     @Mock IBinder mIBinder;
636     @Mock LocationManager mLocationManager;
637     @Mock AppOpsManager mAppOpsManager;
638     @Mock TelephonyManager mTelephonyManager;
639     @Mock EthernetManager mEthernetManager;
640     @Mock NetworkPolicyManager mNetworkPolicyManager;
641     @Mock SystemConfigManager mSystemConfigManager;
642     @Mock DevicePolicyManager mDevicePolicyManager;
643     @Mock Resources mResources;
644     @Mock ClatCoordinator mClatCoordinator;
645     @Mock PacProxyManager mPacProxyManager;
646     @Mock BpfNetMaps mBpfNetMaps;
647     @Mock CarrierPrivilegeAuthenticator mCarrierPrivilegeAuthenticator;
648     @Mock TetheringManager mTetheringManager;
649     @Mock BroadcastOptionsShim mBroadcastOptionsShim;
650     @Mock ActivityManager mActivityManager;
651     @Mock DestroySocketsWrapper mDestroySocketsWrapper;
652     @Mock SubscriptionManager mSubscriptionManager;
653     @Mock KeepaliveTracker.Dependencies mMockKeepaliveTrackerDependencies;
654     @Mock SatelliteAccessController mSatelliteAccessController;
655 
656     // BatteryStatsManager is final and cannot be mocked with regular mockito, so just mock the
657     // underlying binder calls.
658     final IBatteryStats mIBatteryStats = mock(IBatteryStats.class);
659     final BatteryStatsManager mBatteryStatsManager = new BatteryStatsManager(mIBatteryStats);
660 
661     private ArgumentCaptor<ResolverParamsParcel> mResolverParamsParcelCaptor =
662             ArgumentCaptor.forClass(ResolverParamsParcel.class);
663 
664     // This class exists to test bindProcessToNetwork and getBoundNetworkForProcess. These methods
665     // do not go through ConnectivityService but talk to netd directly, so they don't automatically
666     // reflect the state of our test ConnectivityService.
667     private class WrappedConnectivityManager extends ConnectivityManager {
668         private Network mFakeBoundNetwork;
669 
bindProcessToNetwork(Network network)670         public synchronized boolean bindProcessToNetwork(Network network) {
671             mFakeBoundNetwork = network;
672             return true;
673         }
674 
getBoundNetworkForProcess()675         public synchronized Network getBoundNetworkForProcess() {
676             return mFakeBoundNetwork;
677         }
678 
WrappedConnectivityManager(Context context, ConnectivityService service)679         public WrappedConnectivityManager(Context context, ConnectivityService service) {
680             super(context, service);
681         }
682     }
683 
684     private class MockContext extends BroadcastInterceptingContext {
685         private final MockContentResolver mContentResolver;
686 
687         @Spy private Resources mInternalResources;
688         private final LinkedBlockingQueue<Intent> mStartedActivities = new LinkedBlockingQueue<>();
689 
690         // Map of permission name -> PermissionManager.Permission_{GRANTED|DENIED} constant
691         // For permissions granted across the board, the key is only the permission name.
692         // For permissions only granted to a combination of uid/pid, the key
693         // is "<permission name>,<pid>,<uid>". PID+UID permissons have priority over generic ones.
694         private final HashMap<String, Integer> mMockedPermissions = new HashMap<>();
695 
mockStringResource(int resId)696         private void mockStringResource(int resId) {
697             doAnswer((inv) -> {
698                 return "Mock string resource ID=" + inv.getArgument(0);
699             }).when(mInternalResources).getString(resId);
700         }
701 
MockContext(Context base, ContentProvider settingsProvider)702         MockContext(Context base, ContentProvider settingsProvider) {
703             super(base);
704 
705             mInternalResources = spy(base.getResources());
706             doReturn(new String[] {
707                     "wifi,1,1,1,-1,true",
708                     "mobile,0,0,0,-1,true",
709                     "mobile_mms,2,0,2,60000,true",
710                     "mobile_supl,3,0,2,60000,true",
711             }).when(mInternalResources)
712                     .getStringArray(com.android.internal.R.array.networkAttributes);
713 
714             final int[] stringResourcesToMock = new int[] {
715                 com.android.internal.R.string.config_customVpnAlwaysOnDisconnectedDialogComponent,
716                 com.android.internal.R.string.vpn_lockdown_config,
717                 com.android.internal.R.string.vpn_lockdown_connected,
718                 com.android.internal.R.string.vpn_lockdown_connecting,
719                 com.android.internal.R.string.vpn_lockdown_disconnected,
720                 com.android.internal.R.string.vpn_lockdown_error,
721             };
722             for (int resId : stringResourcesToMock) {
723                 mockStringResource(resId);
724             }
725 
726             mContentResolver = new MockContentResolver();
727             mContentResolver.addProvider(Settings.AUTHORITY, settingsProvider);
728         }
729 
730         @Override
startActivityAsUser(Intent intent, UserHandle handle)731         public void startActivityAsUser(Intent intent, UserHandle handle) {
732             mStartedActivities.offer(intent);
733         }
734 
expectStartActivityIntent(int timeoutMs)735         public Intent expectStartActivityIntent(int timeoutMs) {
736             Intent intent = null;
737             try {
738                 intent = mStartedActivities.poll(timeoutMs, TimeUnit.MILLISECONDS);
739             } catch (InterruptedException e) {}
740             assertNotNull("Did not receive sign-in intent after " + timeoutMs + "ms", intent);
741             return intent;
742         }
743 
expectNoStartActivityIntent(int timeoutMs)744         public void expectNoStartActivityIntent(int timeoutMs) {
745             try {
746                 assertNull("Received unexpected Intent to start activity",
747                         mStartedActivities.poll(timeoutMs, TimeUnit.MILLISECONDS));
748             } catch (InterruptedException e) {}
749         }
750 
751         @Override
startService(Intent service)752         public ComponentName startService(Intent service) {
753             final String action = service.getAction();
754             if (!VpnConfig.SERVICE_INTERFACE.equals(action)
755                     && !ConstantsShim.ACTION_VPN_MANAGER_EVENT.equals(action)) {
756                 fail("Attempt to start unknown service, action=" + action);
757             }
758             return new ComponentName(service.getPackage(), "com.android.test.Service");
759         }
760 
761         @Override
getSystemService(String name)762         public Object getSystemService(String name) {
763             if (Context.CONNECTIVITY_SERVICE.equals(name)) return mCm;
764             if (Context.NOTIFICATION_SERVICE.equals(name)) return mNotificationManager;
765             if (Context.USER_SERVICE.equals(name)) return mUserManager;
766             if (Context.ALARM_SERVICE.equals(name)) return mAlarmManager;
767             if (Context.LOCATION_SERVICE.equals(name)) return mLocationManager;
768             if (Context.APP_OPS_SERVICE.equals(name)) return mAppOpsManager;
769             if (Context.TELEPHONY_SERVICE.equals(name)) return mTelephonyManager;
770             if (Context.ETHERNET_SERVICE.equals(name)) return mEthernetManager;
771             if (Context.NETWORK_POLICY_SERVICE.equals(name)) return mNetworkPolicyManager;
772             if (Context.DEVICE_POLICY_SERVICE.equals(name)) return mDevicePolicyManager;
773             if (Context.SYSTEM_CONFIG_SERVICE.equals(name)) return mSystemConfigManager;
774             if (Context.NETWORK_STATS_SERVICE.equals(name)) return mStatsManager;
775             if (Context.BATTERY_STATS_SERVICE.equals(name)) return mBatteryStatsManager;
776             if (Context.PAC_PROXY_SERVICE.equals(name)) return mPacProxyManager;
777             if (Context.TETHERING_SERVICE.equals(name)) return mTetheringManager;
778             if (Context.ACTIVITY_SERVICE.equals(name)) return mActivityManager;
779             if (Context.TELEPHONY_SUBSCRIPTION_SERVICE.equals(name)) return mSubscriptionManager;
780             // StatsManager is final and can't be mocked, and uses static methods for mostly
781             // everything. The simplest fix is to return null and not have metrics in tests.
782             if (Context.STATS_MANAGER.equals(name)) return null;
783             return super.getSystemService(name);
784         }
785 
786         final HashMap<UserHandle, UserManager> mUserManagers = new HashMap<>();
787         @Override
createContextAsUser(UserHandle user, int flags)788         public Context createContextAsUser(UserHandle user, int flags) {
789             final Context asUser = mock(Context.class, AdditionalAnswers.delegatesTo(this));
790             doReturn(user).when(asUser).getUser();
791             doAnswer((inv) -> {
792                 final UserManager um = mUserManagers.computeIfAbsent(user,
793                         u -> mock(UserManager.class, AdditionalAnswers.delegatesTo(mUserManager)));
794                 return um;
795             }).when(asUser).getSystemService(Context.USER_SERVICE);
796             return asUser;
797         }
798 
setWorkProfile(@onNull final UserHandle userHandle, boolean value)799         public void setWorkProfile(@NonNull final UserHandle userHandle, boolean value) {
800             // This relies on all contexts for a given user returning the same UM mock
801             final UserManager umMock = createContextAsUser(userHandle, 0 /* flags */)
802                     .getSystemService(UserManager.class);
803             doReturn(value).when(umMock).isManagedProfile();
804             doReturn(value).when(mUserManager).isManagedProfile(eq(userHandle.getIdentifier()));
805         }
806 
setDeviceOwner(@onNull final UserHandle userHandle, String value)807         public void setDeviceOwner(@NonNull final UserHandle userHandle, String value) {
808             // This relies on all contexts for a given user returning the same UM mock
809             final DevicePolicyManager dpmMock = createContextAsUser(userHandle, 0 /* flags */)
810                     .getSystemService(DevicePolicyManager.class);
811             ComponentName componentName = value == null
812                     ? null : new ComponentName(value, "deviceOwnerClass");
813             doReturn(componentName).when(dpmMock).getDeviceOwnerComponentOnAnyUser();
814             doReturn(componentName).when(mDevicePolicyManager).getDeviceOwnerComponentOnAnyUser();
815         }
816 
817         @Override
getContentResolver()818         public ContentResolver getContentResolver() {
819             return mContentResolver;
820         }
821 
822         @Override
getResources()823         public Resources getResources() {
824             return mInternalResources;
825         }
826 
827         @Override
getPackageManager()828         public PackageManager getPackageManager() {
829             return mPackageManager;
830         }
831 
checkMockedPermission(String permission, int pid, int uid, Function3<String, Integer, Integer, Integer> ifAbsent )832         private int checkMockedPermission(String permission, int pid, int uid,
833                 Function3<String, Integer, Integer, Integer> ifAbsent /* perm, uid, pid -> int */) {
834             final Integer granted = mMockedPermissions.get(permission + "," + pid + "," + uid);
835             if (null != granted) {
836                 return granted;
837             }
838             final Integer allGranted = mMockedPermissions.get(permission);
839             if (null != allGranted) {
840                 return allGranted;
841             }
842             return ifAbsent.apply(permission, pid, uid);
843         }
844 
845         @Override
checkPermission(String permission, int pid, int uid)846         public int checkPermission(String permission, int pid, int uid) {
847             return checkMockedPermission(permission, pid, uid,
848                     (perm, p, u) -> super.checkPermission(perm, p, u));
849         }
850 
851         @Override
checkCallingOrSelfPermission(String permission)852         public int checkCallingOrSelfPermission(String permission) {
853             return checkMockedPermission(permission, Process.myPid(), Process.myUid(),
854                     (perm, p, u) -> super.checkCallingOrSelfPermission(perm));
855         }
856 
857         @Override
enforceCallingOrSelfPermission(String permission, String message)858         public void enforceCallingOrSelfPermission(String permission, String message) {
859             final Integer granted = checkMockedPermission(permission,
860                     Process.myPid(), Process.myUid(),
861                     (perm, p, u) -> {
862                         super.enforceCallingOrSelfPermission(perm, message);
863                         // enforce will crash if the permission is not granted
864                         return PERMISSION_GRANTED;
865                     });
866 
867             if (!granted.equals(PERMISSION_GRANTED)) {
868                 throw new SecurityException("[Test] permission denied: " + permission);
869             }
870         }
871 
872         /**
873          * Mock checks for the specified permission, and have them behave as per {@code granted}.
874          *
875          * This will apply to all calls no matter what the checked UID and PID are.
876          *
877          * <p>Passing null reverts to default behavior, which does a real permission check on the
878          * test package.
879          * @param granted One of {@link PackageManager#PERMISSION_GRANTED} or
880          *                {@link PackageManager#PERMISSION_DENIED}.
881          */
setPermission(String permission, Integer granted)882         public void setPermission(String permission, Integer granted) {
883             mMockedPermissions.put(permission, granted);
884         }
885 
886         /**
887          * Mock checks for the specified permission, and have them behave as per {@code granted}.
888          *
889          * This will only apply to the passed UID and PID.
890          *
891          * <p>Passing null reverts to default behavior, which does a real permission check on the
892          * test package.
893          * @param granted One of {@link PackageManager#PERMISSION_GRANTED} or
894          *                {@link PackageManager#PERMISSION_DENIED}.
895          */
setPermission(String permission, int pid, int uid, Integer granted)896         public void setPermission(String permission, int pid, int uid, Integer granted) {
897             final String key = permission + "," + pid + "," + uid;
898             mMockedPermissions.put(key, granted);
899         }
900 
901         @Override
registerReceiverForAllUsers(@ullable BroadcastReceiver receiver, @NonNull IntentFilter filter, @Nullable String broadcastPermission, @Nullable Handler scheduler)902         public Intent registerReceiverForAllUsers(@Nullable BroadcastReceiver receiver,
903                 @NonNull IntentFilter filter, @Nullable String broadcastPermission,
904                 @Nullable Handler scheduler) {
905             // TODO: ensure MultinetworkPolicyTracker's BroadcastReceiver is tested; just returning
906             // null should not pass the test
907             return null;
908         }
909 
910         @Override
sendStickyBroadcast(Intent intent, Bundle options)911         public void sendStickyBroadcast(Intent intent, Bundle options) {
912             // Verify that delivery group policy APIs were used on U.
913             if (mDeps.isAtLeastU() && CONNECTIVITY_ACTION.equals(intent.getAction())) {
914                 final NetworkInfo ni = intent.getParcelableExtra(EXTRA_NETWORK_INFO,
915                         NetworkInfo.class);
916                 try {
917                     verify(mBroadcastOptionsShim).setDeliveryGroupPolicy(
918                             eq(ConstantsShim.DELIVERY_GROUP_POLICY_MOST_RECENT));
919                     verify(mBroadcastOptionsShim).setDeliveryGroupMatchingKey(
920                             eq(CONNECTIVITY_ACTION),
921                             eq(createDeliveryGroupKeyForConnectivityAction(ni)));
922                     verify(mBroadcastOptionsShim).setDeferralPolicy(
923                             eq(ConstantsShim.DEFERRAL_POLICY_UNTIL_ACTIVE));
924                 } catch (UnsupportedApiLevelException e) {
925                     throw new RuntimeException(e);
926                 }
927             }
928             super.sendStickyBroadcast(intent, options);
929         }
930 
931         private final ArrayTrackRecord<Intent>.ReadHead mOrderedBroadcastAsUserHistory =
932                 new ArrayTrackRecord<Intent>().newReadHead();
933 
expectDataActivityBroadcast(int deviceType, boolean isActive, long tsNanos)934         public void expectDataActivityBroadcast(int deviceType, boolean isActive, long tsNanos) {
935             assertNotNull(mOrderedBroadcastAsUserHistory.poll(BROADCAST_TIMEOUT_MS,
936                     intent -> intent.getAction().equals(ACTION_DATA_ACTIVITY_CHANGE)
937                             && intent.getIntExtra(EXTRA_DEVICE_TYPE, -1) == deviceType
938                             && intent.getBooleanExtra(EXTRA_IS_ACTIVE, !isActive) == isActive
939                             && intent.getLongExtra(EXTRA_REALTIME_NS, -1) == tsNanos
940             ));
941         }
942 
943         @Override
sendOrderedBroadcastAsUser(Intent intent, UserHandle user, String receiverPermission, BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData, Bundle initialExtras)944         public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user,
945                 String receiverPermission, BroadcastReceiver resultReceiver,
946                 Handler scheduler, int initialCode, String initialData, Bundle initialExtras) {
947             mOrderedBroadcastAsUserHistory.add(intent);
948         }
949     }
950 
951     // This was only added in the T SDK, but this test needs to build against the R+S SDKs, too.
toSdkSandboxUid(int appUid)952     private static int toSdkSandboxUid(int appUid) {
953         final int firstSdkSandboxUid = 20000;
954         return appUid + (firstSdkSandboxUid - Process.FIRST_APPLICATION_UID);
955     }
956 
957     // Create the list of ranges for the primary user (User 0), excluding excludedUids.
intRangesPrimaryExcludingUids(List<Integer> excludedUids)958     private static List<Range<Integer>> intRangesPrimaryExcludingUids(List<Integer> excludedUids) {
959         final List<Integer> excludedUidsList = new ArrayList<>(excludedUids);
960         // Uid 0 is always excluded
961         if (!excludedUidsList.contains(0)) {
962             excludedUidsList.add(0);
963         }
964         return intRangesExcludingUids(PRIMARY_USER, excludedUidsList);
965     }
966 
intRangesExcludingUids(int userId, List<Integer> excludedAppIds)967     private static List<Range<Integer>> intRangesExcludingUids(int userId,
968             List<Integer> excludedAppIds) {
969         final List<Integer> excludedUids = CollectionUtils.map(excludedAppIds,
970                 appId -> UserHandle.getUid(userId, appId));
971         final int userBase = userId * UserHandle.PER_USER_RANGE;
972         final int maxUid = userBase + UserHandle.PER_USER_RANGE - 1;
973 
974         int start = userBase;
975         Collections.sort(excludedUids);
976         final List<Range<Integer>> ranges = new ArrayList<>();
977         for (int excludedUid : excludedUids) {
978             if (excludedUid == start) {
979                 start++;
980             } else {
981                 ranges.add(new Range<>(start, excludedUid - 1));
982                 start = excludedUid + 1;
983             }
984         }
985         if (start <= maxUid) {
986             ranges.add(new Range<>(start, maxUid));
987         }
988 
989         return ranges;
990     }
991 
waitForIdle()992     private void waitForIdle() {
993         HandlerUtils.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
994         waitForIdle(mCellAgent, TIMEOUT_MS);
995         waitForIdle(mWiFiAgent, TIMEOUT_MS);
996         waitForIdle(mEthernetAgent, TIMEOUT_MS);
997         HandlerUtils.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
998         HandlerUtils.waitForIdle(ConnectivityThread.get(), TIMEOUT_MS);
999     }
1000 
waitForIdle(TestNetworkAgentWrapper agent, long timeoutMs)1001     private void waitForIdle(TestNetworkAgentWrapper agent, long timeoutMs) {
1002         if (agent == null) {
1003             return;
1004         }
1005         agent.waitForIdle(timeoutMs);
1006     }
1007 
1008     @Test
testWaitForIdle()1009     public void testWaitForIdle() throws Exception {
1010         final int attempts = 50;  // Causes the test to take about 200ms on bullhead-eng.
1011 
1012         // Tests that waitForIdle returns immediately if the service is already idle.
1013         for (int i = 0; i < attempts; i++) {
1014             waitForIdle();
1015         }
1016 
1017         // Bring up a network that we can use to send messages to ConnectivityService.
1018         ExpectedBroadcast b = expectConnectivityAction(TYPE_WIFI, DetailedState.CONNECTED);
1019         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
1020         mWiFiAgent.connect(false);
1021         b.expectBroadcast();
1022         Network n = mWiFiAgent.getNetwork();
1023         assertNotNull(n);
1024 
1025         // Tests that calling waitForIdle waits for messages to be processed.
1026         for (int i = 0; i < attempts; i++) {
1027             mWiFiAgent.setSignalStrength(i);
1028             waitForIdle();
1029             assertEquals(i, mCm.getNetworkCapabilities(n).getSignalStrength());
1030         }
1031     }
1032 
1033     // This test has an inherent race condition in it, and cannot be enabled for continuous testing
1034     // or presubmit tests. It is kept for manual runs and documentation purposes.
1035     @Ignore
verifyThatNotWaitingForIdleCausesRaceConditions()1036     public void verifyThatNotWaitingForIdleCausesRaceConditions() throws Exception {
1037         // Bring up a network that we can use to send messages to ConnectivityService.
1038         ExpectedBroadcast b = expectConnectivityAction(TYPE_WIFI, DetailedState.CONNECTED);
1039         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
1040         mWiFiAgent.connect(false);
1041         b.expectBroadcast();
1042         Network n = mWiFiAgent.getNetwork();
1043         assertNotNull(n);
1044 
1045         // Ensure that not calling waitForIdle causes a race condition.
1046         final int attempts = 50;  // Causes the test to take about 200ms on bullhead-eng.
1047         for (int i = 0; i < attempts; i++) {
1048             mWiFiAgent.setSignalStrength(i);
1049             if (i != mCm.getNetworkCapabilities(n).getSignalStrength()) {
1050                 // We hit a race condition, as expected. Pass the test.
1051                 return;
1052             }
1053         }
1054 
1055         // No race? There is a bug in this test.
1056         fail("expected race condition at least once in " + attempts + " attempts");
1057     }
1058 
1059     private class TestNetworkAgentWrapper extends NetworkAgentWrapper {
1060         // Note : Please do not add any new instrumentation here. If you need new instrumentation,
1061         // please add it in CSAgentWrapper and use subclasses of CSTest instead of adding more
1062         // tools in ConnectivityServiceTest.
1063         private static final int VALIDATION_RESULT_INVALID = 0;
1064 
1065         private static final long DATA_STALL_TIMESTAMP = 10L;
1066         private static final int DATA_STALL_DETECTION_METHOD = 1;
1067 
1068         private INetworkMonitor mNetworkMonitor;
1069         private INetworkMonitorCallbacks mNmCallbacks;
1070         private int mNmValidationResult = VALIDATION_RESULT_INVALID;
1071         private int mProbesCompleted;
1072         private int mProbesSucceeded;
1073         private String mNmValidationRedirectUrl = null;
1074         private boolean mNmProvNotificationRequested = false;
1075 
1076         private final ConditionVariable mNetworkStatusReceived = new ConditionVariable();
1077         // Contains the redirectUrl from networkStatus(). Before reading, wait for
1078         // mNetworkStatusReceived.
1079         private String mRedirectUrl;
1080 
TestNetworkAgentWrapper(int transport)1081         TestNetworkAgentWrapper(int transport) throws Exception {
1082             this(transport, new LinkProperties(), null /* ncTemplate */, null /* provider */, null);
1083         }
1084 
TestNetworkAgentWrapper(int transport, LinkProperties linkProperties)1085         TestNetworkAgentWrapper(int transport, LinkProperties linkProperties)
1086                 throws Exception {
1087             this(transport, linkProperties, null /* ncTemplate */, null /* provider */, null);
1088         }
1089 
TestNetworkAgentWrapper(int transport, LinkProperties linkProperties, NetworkCapabilities ncTemplate)1090         private TestNetworkAgentWrapper(int transport, LinkProperties linkProperties,
1091                 NetworkCapabilities ncTemplate) throws Exception {
1092             this(transport, linkProperties, ncTemplate, null /* provider */, null);
1093         }
1094 
TestNetworkAgentWrapper(int transport, LinkProperties linkProperties, NetworkCapabilities ncTemplate, NetworkProvider provider)1095         private TestNetworkAgentWrapper(int transport, LinkProperties linkProperties,
1096                 NetworkCapabilities ncTemplate, NetworkProvider provider) throws Exception {
1097             this(transport, linkProperties, ncTemplate, provider /* provider */, null);
1098         }
1099 
TestNetworkAgentWrapper(int transport, NetworkAgentWrapper.Callbacks callbacks)1100         private TestNetworkAgentWrapper(int transport, NetworkAgentWrapper.Callbacks callbacks)
1101                 throws Exception {
1102             this(transport, new LinkProperties(), null /* ncTemplate */, null /* provider */,
1103                     callbacks);
1104         }
1105 
TestNetworkAgentWrapper(int transport, LinkProperties linkProperties, NetworkCapabilities ncTemplate, NetworkProvider provider, NetworkAgentWrapper.Callbacks callbacks)1106         private TestNetworkAgentWrapper(int transport, LinkProperties linkProperties,
1107                 NetworkCapabilities ncTemplate, NetworkProvider provider,
1108                 NetworkAgentWrapper.Callbacks callbacks) throws Exception {
1109             super(transport, linkProperties, ncTemplate, provider, callbacks, mServiceContext);
1110             mCreatedAgents.add(this);
1111 
1112             // Waits for the NetworkAgent to be registered, which includes the creation of the
1113             // NetworkMonitor.
1114             waitForIdle(TIMEOUT_MS);
1115             HandlerUtils.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
1116             HandlerUtils.waitForIdle(ConnectivityThread.get(), TIMEOUT_MS);
1117         }
1118 
1119         class TestInstrumentedNetworkAgent extends InstrumentedNetworkAgent {
TestInstrumentedNetworkAgent(NetworkAgentWrapper wrapper, LinkProperties lp, NetworkAgentConfig nac, NetworkProvider provider)1120             TestInstrumentedNetworkAgent(NetworkAgentWrapper wrapper, LinkProperties lp,
1121                     NetworkAgentConfig nac, NetworkProvider provider) {
1122                 super(wrapper, lp, nac, provider);
1123             }
1124 
1125             @Override
networkStatus(int status, String redirectUrl)1126             public void networkStatus(int status, String redirectUrl) {
1127                 mRedirectUrl = redirectUrl;
1128                 mNetworkStatusReceived.open();
1129             }
1130 
1131         }
1132 
1133         @Override
makeNetworkAgent(LinkProperties linkProperties, NetworkAgentConfig nac, NetworkProvider provider)1134         protected InstrumentedNetworkAgent makeNetworkAgent(LinkProperties linkProperties,
1135                 NetworkAgentConfig nac, NetworkProvider provider) throws Exception {
1136             mNetworkMonitor = mock(INetworkMonitor.class);
1137 
1138             final Answer validateAnswer = inv -> {
1139                 new Thread(ignoreExceptions(this::onValidationRequested)).start();
1140                 return null;
1141             };
1142 
1143             doAnswer(validateAnswer).when(mNetworkMonitor).notifyNetworkConnected(any(), any());
1144             doAnswer(validateAnswer).when(mNetworkMonitor).notifyNetworkConnectedParcel(any());
1145             doAnswer(validateAnswer).when(mNetworkMonitor).forceReevaluation(anyInt());
1146 
1147             final ArgumentCaptor<Network> nmNetworkCaptor = ArgumentCaptor.forClass(Network.class);
1148             final ArgumentCaptor<INetworkMonitorCallbacks> nmCbCaptor =
1149                     ArgumentCaptor.forClass(INetworkMonitorCallbacks.class);
1150             doNothing().when(mNetworkStack).makeNetworkMonitor(
1151                     nmNetworkCaptor.capture(),
1152                     any() /* name */,
1153                     nmCbCaptor.capture());
1154 
1155             final InstrumentedNetworkAgent na =
1156                     new TestInstrumentedNetworkAgent(this, linkProperties, nac, provider);
1157 
1158             assertEquals(na.getNetwork().netId, nmNetworkCaptor.getValue().netId);
1159             mNmCallbacks = nmCbCaptor.getValue();
1160 
1161             mNmCallbacks.onNetworkMonitorCreated(mNetworkMonitor);
1162 
1163             return na;
1164         }
1165 
onValidationRequested()1166         private void onValidationRequested() throws Exception {
1167             if (mDeps.isAtLeastT()) {
1168                 verify(mNetworkMonitor).notifyNetworkConnectedParcel(any());
1169             } else {
1170                 verify(mNetworkMonitor).notifyNetworkConnected(any(), any());
1171             }
1172             if (mNmProvNotificationRequested
1173                     && ((mNmValidationResult & NETWORK_VALIDATION_RESULT_VALID) != 0)) {
1174                 mNmCallbacks.hideProvisioningNotification();
1175                 mNmProvNotificationRequested = false;
1176             }
1177 
1178             mNmCallbacks.notifyProbeStatusChanged(mProbesCompleted, mProbesSucceeded);
1179             final NetworkTestResultParcelable p = new NetworkTestResultParcelable();
1180             p.result = mNmValidationResult;
1181             p.probesAttempted = mProbesCompleted;
1182             p.probesSucceeded = mProbesSucceeded;
1183             p.redirectUrl = mNmValidationRedirectUrl;
1184             p.timestampMillis = TIMESTAMP;
1185             mNmCallbacks.notifyNetworkTestedWithExtras(p);
1186 
1187             if (mNmValidationRedirectUrl != null) {
1188                 mNmCallbacks.showProvisioningNotification(
1189                         "test_provisioning_notif_action", TEST_PACKAGE_NAME);
1190                 mNmProvNotificationRequested = true;
1191             }
1192         }
1193 
1194         /**
1195          * Connect without adding any internet capability.
1196          */
connectWithoutInternet()1197         public void connectWithoutInternet() {
1198             super.connect();
1199         }
1200 
1201         /**
1202          * Transition this NetworkAgent to CONNECTED state with NET_CAPABILITY_INTERNET.
1203          * @param validated Indicate if network should pretend to be validated.
1204          */
connect(boolean validated)1205         public void connect(boolean validated) {
1206             connect(validated, true, false /* privateDnsProbeSent */);
1207         }
1208 
1209         /**
1210          * Transition this NetworkAgent to CONNECTED state.
1211          *
1212          * @param validated Indicate if network should pretend to be validated.
1213          *                  Note that if this is true, this method will mock the NetworkMonitor
1214          *                  probes to pretend the network is invalid after it validated once,
1215          *                  so that subsequent attempts (with mNetworkMonitor.forceReevaluation)
1216          *                  will fail unless setNetworkValid is called again manually.
1217          * @param hasInternet Indicate if network should pretend to have NET_CAPABILITY_INTERNET.
1218          * @param privateDnsProbeSent whether the private DNS probe should be considered to have
1219          *                            been sent, assuming |validated| is true.
1220          *                            If |validated| is false, |privateDnsProbeSent| is not used.
1221          *                            If |validated| is true and |privateDnsProbeSent| is false,
1222          *                            the probe has not been sent.
1223          *                            If |validated| is true and |privateDnsProbeSent| is true,
1224          *                            the probe has been sent and has succeeded. When the NM probes
1225          *                            are mocked to be invalid, private DNS is the reason this
1226          *                            network is invalid ; see @param |validated|.
1227          */
connect(boolean validated, boolean hasInternet, boolean privateDnsProbeSent)1228         public void connect(boolean validated, boolean hasInternet,
1229                 boolean privateDnsProbeSent) {
1230             final ConditionVariable validatedCv = new ConditionVariable();
1231             final ConditionVariable capsChangedCv = new ConditionVariable();
1232             final NetworkRequest request = new NetworkRequest.Builder()
1233                     .addTransportType(getNetworkCapabilities().getTransportTypes()[0])
1234                     .clearCapabilities()
1235                     .build();
1236             if (validated) {
1237                 setNetworkValid(privateDnsProbeSent);
1238             }
1239             final NetworkCallback callback = new NetworkCallback() {
1240                 public void onCapabilitiesChanged(Network network,
1241                         NetworkCapabilities networkCapabilities) {
1242                     if (network.equals(getNetwork())) {
1243                         capsChangedCv.open();
1244                         if (networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED)) {
1245                             validatedCv.open();
1246                         }
1247                     }
1248                 }
1249             };
1250             mCm.registerNetworkCallback(request, callback);
1251 
1252             if (hasInternet) {
1253                 addCapability(NET_CAPABILITY_INTERNET);
1254             }
1255 
1256             connectWithoutInternet();
1257             waitFor(capsChangedCv);
1258 
1259             if (validated) {
1260                 // Wait for network to validate.
1261                 waitFor(validatedCv);
1262                 setNetworkInvalid(privateDnsProbeSent);
1263             }
1264             mCm.unregisterNetworkCallback(callback);
1265         }
1266 
connectWithCaptivePortal(String redirectUrl, boolean privateDnsProbeSent)1267         public void connectWithCaptivePortal(String redirectUrl,
1268                 boolean privateDnsProbeSent) {
1269             setNetworkPortal(redirectUrl, privateDnsProbeSent);
1270             connect(false, true /* hasInternet */, privateDnsProbeSent);
1271         }
1272 
connectWithPartialConnectivity()1273         public void connectWithPartialConnectivity() {
1274             setNetworkPartial();
1275             connect(false);
1276         }
1277 
connectWithPartialValidConnectivity(boolean privateDnsProbeSent)1278         public void connectWithPartialValidConnectivity(boolean privateDnsProbeSent) {
1279             setNetworkPartialValid(privateDnsProbeSent);
1280             connect(false, true /* hasInternet */, privateDnsProbeSent);
1281         }
1282 
setNetworkValid(boolean privateDnsProbeSent)1283         void setNetworkValid(boolean privateDnsProbeSent) {
1284             mNmValidationResult = NETWORK_VALIDATION_RESULT_VALID;
1285             mNmValidationRedirectUrl = null;
1286             int probesSucceeded = NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_HTTPS;
1287             if (privateDnsProbeSent) {
1288                 probesSucceeded |= NETWORK_VALIDATION_PROBE_PRIVDNS;
1289             }
1290             // The probesCompleted equals to probesSucceeded for the case of valid network, so put
1291             // the same value into two different parameter of the method.
1292             setProbesStatus(probesSucceeded, probesSucceeded);
1293         }
1294 
setNetworkInvalid(boolean invalidBecauseOfPrivateDns)1295         void setNetworkInvalid(boolean invalidBecauseOfPrivateDns) {
1296             mNmValidationResult = VALIDATION_RESULT_INVALID;
1297             mNmValidationRedirectUrl = null;
1298             int probesCompleted = NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_HTTPS
1299                     | NETWORK_VALIDATION_PROBE_HTTP;
1300             int probesSucceeded = 0;
1301             // If |invalidBecauseOfPrivateDns| is true, it means the network is invalid because
1302             // NetworkMonitor tried to validate the private DNS but failed. Therefore it
1303             // didn't get a chance to try the HTTP probe.
1304             if (invalidBecauseOfPrivateDns) {
1305                 probesCompleted &= ~NETWORK_VALIDATION_PROBE_HTTP;
1306                 probesSucceeded = probesCompleted;
1307                 probesCompleted |= NETWORK_VALIDATION_PROBE_PRIVDNS;
1308             }
1309             setProbesStatus(probesCompleted, probesSucceeded);
1310         }
1311 
setNetworkPortal(String redirectUrl, boolean privateDnsProbeSent)1312         void setNetworkPortal(String redirectUrl, boolean privateDnsProbeSent) {
1313             setNetworkInvalid(privateDnsProbeSent);
1314             mNmValidationRedirectUrl = redirectUrl;
1315             // Suppose the portal is found when NetworkMonitor probes NETWORK_VALIDATION_PROBE_HTTP
1316             // in the beginning, so the NETWORK_VALIDATION_PROBE_HTTPS hasn't probed yet.
1317             int probesCompleted = NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_HTTP;
1318             int probesSucceeded = VALIDATION_RESULT_INVALID;
1319             if (privateDnsProbeSent) {
1320                 probesCompleted |= NETWORK_VALIDATION_PROBE_PRIVDNS;
1321             }
1322             setProbesStatus(probesCompleted, probesSucceeded);
1323         }
1324 
setNetworkPartial()1325         void setNetworkPartial() {
1326             mNmValidationResult = NETWORK_VALIDATION_RESULT_PARTIAL;
1327             mNmValidationRedirectUrl = null;
1328             int probesCompleted = NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_HTTPS
1329                     | NETWORK_VALIDATION_PROBE_FALLBACK;
1330             int probesSucceeded = NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_FALLBACK;
1331             setProbesStatus(probesCompleted, probesSucceeded);
1332         }
1333 
setNetworkPartialValid(boolean privateDnsProbeSent)1334         void setNetworkPartialValid(boolean privateDnsProbeSent) {
1335             setNetworkPartial();
1336             mNmValidationResult |= NETWORK_VALIDATION_RESULT_VALID;
1337             mNmValidationRedirectUrl = null;
1338             int probesCompleted = NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_HTTPS
1339                     | NETWORK_VALIDATION_PROBE_HTTP;
1340             int probesSucceeded = NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_HTTP;
1341             // Assume the partial network cannot pass the private DNS validation as well, so only
1342             // add NETWORK_VALIDATION_PROBE_DNS in probesCompleted but not probesSucceeded.
1343             if (privateDnsProbeSent) {
1344                 probesCompleted |= NETWORK_VALIDATION_PROBE_PRIVDNS;
1345             }
1346             setProbesStatus(probesCompleted, probesSucceeded);
1347         }
1348 
setProbesStatus(int probesCompleted, int probesSucceeded)1349         void setProbesStatus(int probesCompleted, int probesSucceeded) {
1350             mProbesCompleted = probesCompleted;
1351             mProbesSucceeded = probesSucceeded;
1352         }
1353 
notifyCapportApiDataChanged(CaptivePortalData data)1354         void notifyCapportApiDataChanged(CaptivePortalData data) {
1355             try {
1356                 mNmCallbacks.notifyCaptivePortalDataChanged(data);
1357             } catch (RemoteException e) {
1358                 throw new AssertionError("This cannot happen", e);
1359             }
1360         }
1361 
waitForRedirectUrl()1362         public String waitForRedirectUrl() {
1363             assertTrue(mNetworkStatusReceived.block(TIMEOUT_MS));
1364             return mRedirectUrl;
1365         }
1366 
expectDisconnected()1367         public void expectDisconnected() {
1368             expectDisconnected(TIMEOUT_MS);
1369         }
1370 
expectPreventReconnectReceived()1371         public void expectPreventReconnectReceived() {
1372             expectPreventReconnectReceived(TIMEOUT_MS);
1373         }
1374 
notifyDataStallSuspected()1375         void notifyDataStallSuspected() throws Exception {
1376             final DataStallReportParcelable p = new DataStallReportParcelable();
1377             p.detectionMethod = DATA_STALL_DETECTION_METHOD;
1378             p.timestampMillis = DATA_STALL_TIMESTAMP;
1379             mNmCallbacks.notifyDataStallSuspected(p);
1380         }
1381     }
1382 
1383     /**
1384      * A NetworkFactory that allows to wait until any in-flight NetworkRequest add or remove
1385      * operations have been processed and test for them.
1386      */
1387     private static class MockNetworkFactory extends NetworkFactory {
1388         // Note : Please do not add any new instrumentation here. If you need new instrumentation,
1389         // please add it in CSTest and use subclasses of CSTest instead of adding more
1390         // tools in ConnectivityServiceTest.
1391         private final AtomicBoolean mNetworkStarted = new AtomicBoolean(false);
1392 
1393         static class RequestEntry {
1394             @NonNull
1395             public final NetworkRequest request;
1396 
RequestEntry(@onNull final NetworkRequest request)1397             RequestEntry(@NonNull final NetworkRequest request) {
1398                 this.request = request;
1399             }
1400 
1401             static final class Add extends RequestEntry {
Add(@onNull final NetworkRequest request)1402                 Add(@NonNull final NetworkRequest request) {
1403                     super(request);
1404                 }
1405             }
1406 
1407             static final class Remove extends RequestEntry {
Remove(@onNull final NetworkRequest request)1408                 Remove(@NonNull final NetworkRequest request) {
1409                     super(request);
1410                 }
1411             }
1412 
1413             @Override
toString()1414             public String toString() {
1415                 return "RequestEntry [ " + getClass().getName() + " : " + request + " ]";
1416             }
1417         }
1418 
1419         // History of received requests adds and removes.
1420         private final ArrayTrackRecord<RequestEntry>.ReadHead mRequestHistory =
1421                 new ArrayTrackRecord<RequestEntry>().newReadHead();
1422 
failIfNull(@ullable final T obj, @Nullable final String message)1423         private static <T> T failIfNull(@Nullable final T obj, @Nullable final String message) {
1424             if (null == obj) fail(null != message ? message : "Must not be null");
1425             return obj;
1426         }
1427 
expectRequestAdd()1428         public RequestEntry.Add expectRequestAdd() {
1429             return failIfNull((RequestEntry.Add) mRequestHistory.poll(TIMEOUT_MS,
1430                     it -> it instanceof RequestEntry.Add), "Expected request add");
1431         }
1432 
expectRequestAdds(final int count)1433         public void expectRequestAdds(final int count) {
1434             for (int i = count; i > 0; --i) {
1435                 expectRequestAdd();
1436             }
1437         }
1438 
expectRequestRemove()1439         public RequestEntry.Remove expectRequestRemove() {
1440             return failIfNull((RequestEntry.Remove) mRequestHistory.poll(TIMEOUT_MS,
1441                     it -> it instanceof RequestEntry.Remove), "Expected request remove");
1442         }
1443 
expectRequestRemoves(final int count)1444         public void expectRequestRemoves(final int count) {
1445             for (int i = count; i > 0; --i) {
1446                 expectRequestRemove();
1447             }
1448         }
1449 
1450         // Used to collect the networks requests managed by this factory. This is a duplicate of
1451         // the internal information stored in the NetworkFactory (which is private).
1452         private SparseArray<NetworkRequest> mNetworkRequests = new SparseArray<>();
1453         private final HandlerThread mHandlerSendingRequests;
1454 
MockNetworkFactory(Looper looper, Context context, String logTag, NetworkCapabilities filter, HandlerThread threadSendingRequests)1455         public MockNetworkFactory(Looper looper, Context context, String logTag,
1456                 NetworkCapabilities filter, HandlerThread threadSendingRequests) {
1457             super(looper, context, logTag, filter);
1458             mHandlerSendingRequests = threadSendingRequests;
1459         }
1460 
getMyRequestCount()1461         public int getMyRequestCount() {
1462             return getRequestCount();
1463         }
1464 
startNetwork()1465         protected void startNetwork() {
1466             mNetworkStarted.set(true);
1467         }
1468 
stopNetwork()1469         protected void stopNetwork() {
1470             mNetworkStarted.set(false);
1471         }
1472 
getMyStartRequested()1473         public boolean getMyStartRequested() {
1474             return mNetworkStarted.get();
1475         }
1476 
1477 
1478         @Override
needNetworkFor(NetworkRequest request)1479         protected void needNetworkFor(NetworkRequest request) {
1480             mNetworkRequests.put(request.requestId, request);
1481             super.needNetworkFor(request);
1482             mRequestHistory.add(new RequestEntry.Add(request));
1483         }
1484 
1485         @Override
releaseNetworkFor(NetworkRequest request)1486         protected void releaseNetworkFor(NetworkRequest request) {
1487             mNetworkRequests.remove(request.requestId);
1488             super.releaseNetworkFor(request);
1489             mRequestHistory.add(new RequestEntry.Remove(request));
1490         }
1491 
assertRequestCountEquals(final int count)1492         public void assertRequestCountEquals(final int count) {
1493             assertEquals(count, getMyRequestCount());
1494         }
1495 
1496         // Trigger releasing the request as unfulfillable
triggerUnfulfillable(NetworkRequest r)1497         public void triggerUnfulfillable(NetworkRequest r) {
1498             super.releaseRequestAsUnfulfillableByAnyFactory(r);
1499         }
1500 
assertNoRequestChanged()1501         public void assertNoRequestChanged() {
1502             // Make sure there are no remaining requests unaccounted for.
1503             HandlerUtils.waitForIdle(mHandlerSendingRequests, TIMEOUT_MS);
1504             assertNull(mRequestHistory.poll(0, r -> true));
1505         }
1506     }
1507 
uidRangesForUids(int... uids)1508     private Set<UidRange> uidRangesForUids(int... uids) {
1509         final ArraySet<UidRange> ranges = new ArraySet<>();
1510         for (final int uid : uids) {
1511             ranges.add(new UidRange(uid, uid));
1512         }
1513         return ranges;
1514     }
1515 
uidRangesForUids(Collection<Integer> uids)1516     private Set<UidRange> uidRangesForUids(Collection<Integer> uids) {
1517         return uidRangesForUids(CollectionUtils.toIntArray(uids));
1518     }
1519 
1520     // Helper class to mock vpn interaction.
1521     private class MockVpn implements TestableNetworkCallback.HasNetwork {
1522         // Note : Please do not add any new instrumentation here. If you need new instrumentation,
1523         // please add it in CSTest and use subclasses of CSTest instead of adding more
1524         // tools in ConnectivityServiceTest.
1525 
1526         // Careful ! This is different from mNetworkAgent, because MockNetworkAgent does
1527         // not inherit from NetworkAgent.
1528         private TestNetworkAgentWrapper mMockNetworkAgent;
1529         // Initialize a stored NetworkCapabilities following the defaults of VPN. The TransportInfo
1530         // should at least be updated to a valid VPN type before usage, see registerAgent(...).
1531         private NetworkCapabilities mNetworkCapabilities = new NetworkCapabilities.Builder()
1532                 .addTransportType(NetworkCapabilities.TRANSPORT_VPN)
1533                 .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN)
1534                 .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED)
1535                 .setTransportInfo(new VpnTransportInfo(
1536                         VpnManager.TYPE_VPN_NONE,
1537                         null /* sessionId */,
1538                         false /* bypassable */,
1539                         false /* longLivedTcpConnectionsExpensive */))
1540                 .build();
1541         private boolean mAgentRegistered = false;
1542 
1543         private int mVpnType = VpnManager.TYPE_VPN_SERVICE;
1544         private String mSessionKey;
1545 
setUids(Set<UidRange> uids)1546         public void setUids(Set<UidRange> uids) {
1547             mNetworkCapabilities.setUids(UidRange.toIntRanges(uids));
1548             if (mAgentRegistered) {
1549                 mMockNetworkAgent.setNetworkCapabilities(mNetworkCapabilities, true);
1550             }
1551         }
1552 
setVpnType(int vpnType)1553         public void setVpnType(int vpnType) {
1554             mVpnType = vpnType;
1555         }
1556 
getNetwork()1557         public Network getNetwork() {
1558             return (mMockNetworkAgent == null) ? null : mMockNetworkAgent.getNetwork();
1559         }
1560 
getNetworkAgentConfig()1561         public NetworkAgentConfig getNetworkAgentConfig() {
1562             return null == mMockNetworkAgent ? null : mMockNetworkAgent.getNetworkAgentConfig();
1563         }
1564 
getActiveVpnType()1565         public int getActiveVpnType() {
1566             return mVpnType;
1567         }
1568 
makeLinkProperties()1569         private LinkProperties makeLinkProperties() {
1570             final LinkProperties lp = new LinkProperties();
1571             lp.setInterfaceName(VPN_IFNAME);
1572             return lp;
1573         }
1574 
registerAgent(boolean isAlwaysMetered, Set<UidRange> uids, LinkProperties lp)1575         private void registerAgent(boolean isAlwaysMetered, Set<UidRange> uids, LinkProperties lp)
1576                 throws Exception {
1577             if (mAgentRegistered) throw new IllegalStateException("already registered");
1578             final String session = "MySession12345";
1579             setUids(uids);
1580             if (!isAlwaysMetered) mNetworkCapabilities.addCapability(NET_CAPABILITY_NOT_METERED);
1581             mNetworkCapabilities.setTransportInfo(new VpnTransportInfo(getActiveVpnType(),
1582                     session));
1583             mMockNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN, lp,
1584                     mNetworkCapabilities);
1585             mMockNetworkAgent.waitForIdle(TIMEOUT_MS);
1586 
1587             verify(mMockNetd, times(1)).networkAddUidRangesParcel(
1588                     new NativeUidRangeConfig(mMockVpn.getNetwork().getNetId(),
1589                             toUidRangeStableParcels(uids), PREFERENCE_ORDER_VPN));
1590             verify(mMockNetd, never()).networkRemoveUidRangesParcel(argThat(config ->
1591                     mMockVpn.getNetwork().getNetId() == config.netId
1592                             && PREFERENCE_ORDER_VPN == config.subPriority));
1593             mAgentRegistered = true;
1594             verify(mMockNetd).networkCreate(nativeNetworkConfigVpn(getNetwork().netId,
1595                     !mMockNetworkAgent.isBypassableVpn(), mVpnType));
1596             mNetworkCapabilities.set(mMockNetworkAgent.getNetworkCapabilities());
1597         }
1598 
registerAgent(Set<UidRange> uids)1599         private void registerAgent(Set<UidRange> uids) throws Exception {
1600             registerAgent(false /* isAlwaysMetered */, uids, makeLinkProperties());
1601         }
1602 
connect(boolean validated, boolean hasInternet, boolean privateDnsProbeSent)1603         private void connect(boolean validated, boolean hasInternet,
1604                 boolean privateDnsProbeSent) {
1605             mMockNetworkAgent.connect(validated, hasInternet, privateDnsProbeSent);
1606         }
1607 
connect(boolean validated)1608         private void connect(boolean validated) {
1609             mMockNetworkAgent.connect(validated);
1610         }
1611 
getAgent()1612         private TestNetworkAgentWrapper getAgent() {
1613             return mMockNetworkAgent;
1614         }
1615 
setOwnerAndAdminUid(int uid)1616         private void setOwnerAndAdminUid(int uid) throws Exception {
1617             mNetworkCapabilities.setOwnerUid(uid);
1618             mNetworkCapabilities.setAdministratorUids(new int[]{uid});
1619         }
1620 
establish(LinkProperties lp, int uid, Set<UidRange> ranges, boolean validated, boolean hasInternet, boolean privateDnsProbeSent)1621         public void establish(LinkProperties lp, int uid, Set<UidRange> ranges, boolean validated,
1622                 boolean hasInternet, boolean privateDnsProbeSent) throws Exception {
1623             setOwnerAndAdminUid(uid);
1624             registerAgent(false, ranges, lp);
1625             connect(validated, hasInternet, privateDnsProbeSent);
1626             waitForIdle();
1627         }
1628 
establish(LinkProperties lp, int uid, Set<UidRange> ranges)1629         public void establish(LinkProperties lp, int uid, Set<UidRange> ranges) throws Exception {
1630             establish(lp, uid, ranges, true, true, false);
1631         }
1632 
establishForMyUid(LinkProperties lp)1633         public void establishForMyUid(LinkProperties lp) throws Exception {
1634             final int uid = Process.myUid();
1635             establish(lp, uid, uidRangesForUids(uid), true, true, false);
1636         }
1637 
establishForMyUid(boolean validated, boolean hasInternet, boolean privateDnsProbeSent)1638         public void establishForMyUid(boolean validated, boolean hasInternet,
1639                 boolean privateDnsProbeSent) throws Exception {
1640             final int uid = Process.myUid();
1641             establish(makeLinkProperties(), uid, uidRangesForUids(uid), validated, hasInternet,
1642                     privateDnsProbeSent);
1643         }
1644 
establishForMyUid()1645         public void establishForMyUid() throws Exception {
1646             establishForMyUid(makeLinkProperties());
1647         }
1648 
sendLinkProperties(LinkProperties lp)1649         public void sendLinkProperties(LinkProperties lp) {
1650             mMockNetworkAgent.sendLinkProperties(lp);
1651         }
1652 
disconnect()1653         public void disconnect() {
1654             if (mMockNetworkAgent != null) {
1655                 mMockNetworkAgent.disconnect();
1656             }
1657             mAgentRegistered = false;
1658             setUids(null);
1659             // Remove NET_CAPABILITY_INTERNET or MockNetworkAgent will refuse to connect later on.
1660             mNetworkCapabilities.removeCapability(NET_CAPABILITY_INTERNET);
1661         }
1662 
startLegacyVpn()1663         private void startLegacyVpn() {
1664             // Do nothing.
1665         }
1666 
1667         // Mock the interaction of IkeV2VpnRunner start. In the context of ConnectivityService,
1668         // setVpnDefaultForUids() is the main interaction and a sessionKey is stored.
startPlatformVpn()1669         private void startPlatformVpn() {
1670             mSessionKey = UUID.randomUUID().toString();
1671             // Assuming no disallowed applications
1672             final Set<Range<Integer>> ranges = UidRange.toIntRanges(Set.of(PRIMARY_UIDRANGE));
1673             mCm.setVpnDefaultForUids(mSessionKey, ranges);
1674             // Wait for vpn network preference updates.
1675             waitForIdle();
1676         }
1677 
startLegacyVpnPrivileged(boolean isIkev2Vpn)1678         public void startLegacyVpnPrivileged(boolean isIkev2Vpn) {
1679             if (isIkev2Vpn) {
1680                 startPlatformVpn();
1681             } else {
1682                 startLegacyVpn();
1683             }
1684         }
1685 
stopVpnRunnerPrivileged()1686         public void stopVpnRunnerPrivileged() {
1687             if (mSessionKey != null) {
1688                 // Clear vpn network preference.
1689                 mCm.setVpnDefaultForUids(mSessionKey, Collections.EMPTY_LIST);
1690                 mSessionKey = null;
1691             }
1692             disconnect();
1693         }
1694 
setUnderlyingNetworks(@ullable Network[] networks)1695         public boolean setUnderlyingNetworks(@Nullable Network[] networks) {
1696             if (!mAgentRegistered) return false;
1697             mMockNetworkAgent.setUnderlyingNetworks(
1698                     (networks == null) ? null : Arrays.asList(networks));
1699             return true;
1700         }
1701     }
1702 
toUidRangeStableParcels(final @NonNull Set<UidRange> ranges)1703     private UidRangeParcel[] toUidRangeStableParcels(final @NonNull Set<UidRange> ranges) {
1704         return ranges.stream().map(
1705                 r -> new UidRangeParcel(r.start, r.stop)).toArray(UidRangeParcel[]::new);
1706     }
1707 
intToUidRangeStableParcels(final @NonNull Set<Integer> ranges)1708     private UidRangeParcel[] intToUidRangeStableParcels(final @NonNull Set<Integer> ranges) {
1709         return ranges.stream().map(r -> new UidRangeParcel(r, r)).toArray(UidRangeParcel[]::new);
1710     }
1711 
intToUidRangeStableParcels( final @NonNull List<Range<Integer>> ranges)1712     private static UidRangeParcel[] intToUidRangeStableParcels(
1713             final @NonNull List<Range<Integer>> ranges) {
1714         return ranges.stream().map(
1715                 r -> new UidRangeParcel(r.getLower(), r.getUpper())).toArray(UidRangeParcel[]::new);
1716     }
1717 
assertVpnTransportInfo(NetworkCapabilities nc, int type)1718     private void assertVpnTransportInfo(NetworkCapabilities nc, int type) {
1719         assertNotNull(nc);
1720         final TransportInfo ti = nc.getTransportInfo();
1721         assertTrue("VPN TransportInfo is not a VpnTransportInfo: " + ti,
1722                 ti instanceof VpnTransportInfo);
1723         assertEquals(type, ((VpnTransportInfo) ti).getType());
1724 
1725     }
1726 
processBroadcast(Intent intent)1727     private void processBroadcast(Intent intent) {
1728         mServiceContext.sendBroadcast(intent);
1729         waitForIdle();
1730     }
1731 
mockUidNetworkingBlocked()1732     private void mockUidNetworkingBlocked() {
1733         doAnswer(i -> isUidBlocked(mBlockedReasons, i.getArgument(1))
1734         ).when(mNetworkPolicyManager).isUidNetworkingBlocked(anyInt(), anyBoolean());
1735         doAnswer(i -> isUidBlocked(mBlockedReasons, i.getArgument(1))
1736         ).when(mBpfNetMaps).isUidNetworkingBlocked(anyInt(), anyBoolean());
1737     }
1738 
isUidBlocked(int blockedReasons, boolean meteredNetwork)1739     private boolean isUidBlocked(int blockedReasons, boolean meteredNetwork) {
1740         final int blockedOnAllNetworksReason = (blockedReasons & ~BLOCKED_METERED_REASON_MASK);
1741         if (blockedOnAllNetworksReason != BLOCKED_REASON_NONE) {
1742             return true;
1743         }
1744         if (meteredNetwork) {
1745             return blockedReasons != BLOCKED_REASON_NONE;
1746         }
1747         return false;
1748     }
1749 
setBlockedReasonChanged(int blockedReasons)1750     private void setBlockedReasonChanged(int blockedReasons) {
1751         mBlockedReasons = blockedReasons;
1752         if (mDeps.isAtLeastV()) {
1753             visibleOnHandlerThread(mCsHandlerThread.getThreadHandler(),
1754                     () -> mService.handleBlockedReasonsChanged(
1755                             List.of(new Pair<>(Process.myUid(), blockedReasons))
1756 
1757                     ));
1758         } else {
1759             mPolicyCallback.onUidBlockedReasonChanged(Process.myUid(), blockedReasons);
1760         }
1761     }
1762 
getNat464Xlat(NetworkAgentWrapper mna)1763     private Nat464Xlat getNat464Xlat(NetworkAgentWrapper mna) {
1764         return mService.getNetworkAgentInfoForNetwork(mna.getNetwork()).clatd;
1765     }
1766 
1767     private class WrappedMultinetworkPolicyTracker extends MultinetworkPolicyTracker {
1768         volatile int mConfigMeteredMultipathPreference;
1769 
WrappedMultinetworkPolicyTracker(Context c, Handler h, Runnable r)1770         WrappedMultinetworkPolicyTracker(Context c, Handler h, Runnable r) {
1771             super(c, h, r, new MultinetworkPolicyTrackerTestDependencies(mResources));
1772         }
1773 
1774         @Override
configMeteredMultipathPreference()1775         public int configMeteredMultipathPreference() {
1776             return mConfigMeteredMultipathPreference;
1777         }
1778     }
1779 
1780     /**
1781      * Wait up to TIMEOUT_MS for {@code conditionVariable} to open.
1782      * Fails if TIMEOUT_MS goes by before {@code conditionVariable} opens.
1783      */
waitFor(ConditionVariable conditionVariable)1784     static private void waitFor(ConditionVariable conditionVariable) {
1785         if (conditionVariable.block(TIMEOUT_MS)) {
1786             return;
1787         }
1788         fail("ConditionVariable was blocked for more than " + TIMEOUT_MS + "ms");
1789     }
1790 
doAsUid(final int uid, @NonNull final Supplier<T> what)1791     private <T> T doAsUid(final int uid, @NonNull final Supplier<T> what) {
1792         mDeps.setCallingUid(uid);
1793         try {
1794             return what.get();
1795         } finally {
1796             mDeps.setCallingUid(null);
1797         }
1798     }
1799 
doAsUid(final int uid, @NonNull final Runnable what)1800     private void doAsUid(final int uid, @NonNull final Runnable what) {
1801         doAsUid(uid, () -> {
1802             what.run(); return Void.TYPE;
1803         });
1804     }
1805 
registerNetworkCallbackAsUid(NetworkRequest request, NetworkCallback callback, int uid)1806     private void registerNetworkCallbackAsUid(NetworkRequest request, NetworkCallback callback,
1807             int uid) {
1808         doAsUid(uid, () -> {
1809             mCm.registerNetworkCallback(request, callback);
1810         });
1811     }
1812 
registerDefaultNetworkCallbackAsUid(@onNull final NetworkCallback callback, final int uid)1813     private void registerDefaultNetworkCallbackAsUid(@NonNull final NetworkCallback callback,
1814             final int uid) {
1815         doAsUid(uid, () -> {
1816             mCm.registerDefaultNetworkCallback(callback);
1817             waitForIdle();
1818         });
1819     }
1820 
withPermission(String permission, ThrowingRunnable r)1821     private void withPermission(String permission, ThrowingRunnable r) throws Exception {
1822         try {
1823             mServiceContext.setPermission(permission, PERMISSION_GRANTED);
1824             r.run();
1825         } finally {
1826             mServiceContext.setPermission(permission, null);
1827         }
1828     }
1829 
withPermission(String permission, int pid, int uid, ThrowingRunnable r)1830     private void withPermission(String permission, int pid, int uid, ThrowingRunnable r)
1831             throws Exception {
1832         try {
1833             mServiceContext.setPermission(permission, pid, uid, PERMISSION_GRANTED);
1834             r.run();
1835         } finally {
1836             mServiceContext.setPermission(permission, pid, uid, null);
1837         }
1838     }
1839 
1840     private static final int PRIMARY_USER = 0;
1841     private static final int SECONDARY_USER = 10;
1842     private static final int TERTIARY_USER = 11;
1843     private static final UidRange PRIMARY_UIDRANGE =
1844             UidRange.createForUser(UserHandle.of(PRIMARY_USER));
1845     private static final int APP1_UID = UserHandle.getUid(PRIMARY_USER, 10100);
1846     private static final int APP2_UID = UserHandle.getUid(PRIMARY_USER, 10101);
1847     private static final int VPN_UID = UserHandle.getUid(PRIMARY_USER, 10043);
1848     private static final UserInfo PRIMARY_USER_INFO = new UserInfo(PRIMARY_USER, "",
1849             UserInfo.FLAG_PRIMARY);
1850     private static final UserHandle PRIMARY_USER_HANDLE = new UserHandle(PRIMARY_USER);
1851     private static final UserHandle SECONDARY_USER_HANDLE = new UserHandle(SECONDARY_USER);
1852     private static final UserHandle TERTIARY_USER_HANDLE = new UserHandle(TERTIARY_USER);
1853 
1854     private static final int RESTRICTED_USER = 1;
1855     private static final UidRange RESTRICTED_USER_UIDRANGE =
1856             UidRange.createForUser(UserHandle.of(RESTRICTED_USER));
1857     private static final UserInfo RESTRICTED_USER_INFO = new UserInfo(RESTRICTED_USER, "",
1858             UserInfo.FLAG_RESTRICTED);
1859     static {
1860         RESTRICTED_USER_INFO.restrictedProfileParentId = PRIMARY_USER;
1861     }
1862 
1863     @Before
setUp()1864     public void setUp() throws Exception {
1865         mNetIdManager = new TestNetIdManager();
1866 
1867         mContext = InstrumentationRegistry.getContext();
1868 
1869         MockitoAnnotations.initMocks(this);
1870 
1871         // Note : Please do not add any new instrumentation here. If you need new instrumentation,
1872         // please add it in CSTest and use subclasses of CSTest instead of adding more
1873         // tools in ConnectivityServiceTest.
1874         doReturn(asList(PRIMARY_USER_INFO)).when(mUserManager).getAliveUsers();
1875         doReturn(asList(PRIMARY_USER_HANDLE)).when(mUserManager).getUserHandles(anyBoolean());
1876         doReturn(PRIMARY_USER_INFO).when(mUserManager).getUserInfo(PRIMARY_USER);
1877         // canHaveRestrictedProfile does not take a userId. It applies to the userId of the context
1878         // it was started from, i.e., PRIMARY_USER.
1879         doReturn(true).when(mUserManager).canHaveRestrictedProfile();
1880         doReturn(RESTRICTED_USER_INFO).when(mUserManager).getUserInfo(RESTRICTED_USER);
1881 
1882         final ApplicationInfo applicationInfo = new ApplicationInfo();
1883         applicationInfo.targetSdkVersion = Build.VERSION_CODES.Q;
1884         doReturn(applicationInfo).when(mPackageManager)
1885                 .getApplicationInfoAsUser(anyString(), anyInt(), any());
1886         doReturn(applicationInfo.targetSdkVersion).when(mPackageManager)
1887                 .getTargetSdkVersion(anyString());
1888         doReturn(new int[0]).when(mSystemConfigManager).getSystemPermissionUids(anyString());
1889 
1890         // InstrumentationTestRunner prepares a looper, but AndroidJUnitRunner does not.
1891         // http://b/25897652 .
1892         if (Looper.myLooper() == null) {
1893             Looper.prepare();
1894         }
1895         mockDefaultPackages();
1896         mockHasSystemFeature(FEATURE_WIFI, true);
1897         mockHasSystemFeature(FEATURE_WIFI_DIRECT, true);
1898         mockHasSystemFeature(FEATURE_ETHERNET, true);
1899         doReturn(true).when(mTelephonyManager).isDataCapable();
1900 
1901         FakeSettingsProvider.clearSettingsProvider();
1902         mServiceContext = new MockContext(InstrumentationRegistry.getContext(),
1903                 new FakeSettingsProvider());
1904         mServiceContext.setUseRegisteredHandlers(true);
1905         mServiceContext.setPermission(NETWORK_FACTORY, PERMISSION_GRANTED);
1906         mServiceContext.setPermission(NETWORK_STACK, PERMISSION_GRANTED);
1907         mServiceContext.setPermission(CONTROL_OEM_PAID_NETWORK_PREFERENCE, PERMISSION_GRANTED);
1908         mServiceContext.setPermission(PACKET_KEEPALIVE_OFFLOAD, PERMISSION_GRANTED);
1909         mServiceContext.setPermission(CONNECTIVITY_USE_RESTRICTED_NETWORKS, PERMISSION_GRANTED);
1910         mServiceContext.setPermission(READ_DEVICE_CONFIG, PERMISSION_GRANTED);
1911 
1912         mAlarmManagerThread = new HandlerThread("TestAlarmManager");
1913         mAlarmManagerThread.start();
1914         initAlarmManager(mAlarmManager, mAlarmManagerThread.getThreadHandler());
1915 
1916         mCsHandlerThread = new HandlerThread("TestConnectivityService");
1917         mProxyTracker = new ProxyTracker(mServiceContext, mock(Handler.class),
1918                 16 /* EVENT_PROXY_HAS_CHANGED */);
1919 
1920         initMockedResources();
1921         final Context mockResContext = mock(Context.class);
1922         doReturn(mResources).when(mockResContext).getResources();
1923         ConnectivityResources.setResourcesContextForTest(mockResContext);
1924         mDeps = new ConnectivityServiceDependencies(mockResContext);
1925         mPermDeps = new PermissionMonitorDependencies();
1926         doReturn(true).when(mMockKeepaliveTrackerDependencies)
1927                 .isAddressTranslationEnabled(mServiceContext);
1928         doReturn(new ConnectivityResources(mockResContext)).when(mMockKeepaliveTrackerDependencies)
1929                 .createConnectivityResources(mServiceContext);
1930         doReturn(new int[] {1, 3, 0, 0}).when(mMockKeepaliveTrackerDependencies)
1931                 .getSupportedKeepalives(mServiceContext);
1932         mAutoOnOffKeepaliveDependencies =
1933                 new AutomaticOnOffKeepaliveTrackerDependencies(mServiceContext);
1934         mService = new ConnectivityService(mServiceContext,
1935                 mMockDnsResolver,
1936                 mock(IpConnectivityLog.class),
1937                 mMockNetd,
1938                 mDeps, mPermDeps);
1939         mService.mLingerDelayMs = TEST_LINGER_DELAY_MS;
1940         mService.mNascentDelayMs = TEST_NASCENT_DELAY_MS;
1941 
1942         mShouldCreateNetworksImmediately = mService.isConnectivityServiceFeatureEnabledForTesting(
1943                 QUEUE_NETWORK_AGENT_EVENTS_IN_SYSTEM_SERVER);
1944 
1945         if (mDeps.isAtLeastV()) {
1946             verify(mNetworkPolicyManager, never()).registerNetworkPolicyCallback(any(), any());
1947             mPolicyCallback = null;
1948         } else {
1949             final ArgumentCaptor<NetworkPolicyCallback> policyCallbackCaptor =
1950                     ArgumentCaptor.forClass(NetworkPolicyCallback.class);
1951             verify(mNetworkPolicyManager).registerNetworkPolicyCallback(any(),
1952                     policyCallbackCaptor.capture());
1953             mPolicyCallback = policyCallbackCaptor.getValue();
1954         }
1955 
1956         // Create local CM before sending system ready so that we can answer
1957         // getSystemService() correctly.
1958         mCm = new WrappedConnectivityManager(InstrumentationRegistry.getContext(), mService);
1959         mService.systemReadyInternal();
1960         verify(mMockDnsResolver).registerUnsolicitedEventListener(any());
1961 
1962         mMockVpn = new MockVpn();
1963         mCm.bindProcessToNetwork(null);
1964         mQosCallbackTracker = mock(QosCallbackTracker.class);
1965 
1966         // Ensure that the default setting for Captive Portals is used for most tests
1967         setCaptivePortalMode(ConnectivitySettingsManager.CAPTIVE_PORTAL_MODE_PROMPT);
1968         setAlwaysOnNetworks(false);
1969         setPrivateDnsSettings(PRIVATE_DNS_MODE_OFF, "ignored.example.com");
1970 
1971         mDeps.setChangeIdEnabled(
1972                 true, NETWORK_BLOCKED_WITHOUT_INTERNET_PERMISSION, Process.myUid());
1973         doReturn(PERMISSION_INTERNET).when(mBpfNetMaps).getNetPermForUid(anyInt());
1974         // Note : Please do not add any new instrumentation here. If you need new instrumentation,
1975         // please add it in CSTest and use subclasses of CSTest instead of adding more
1976         // tools in ConnectivityServiceTest.
1977     }
1978 
initMockedResources()1979     private void initMockedResources() {
1980         doReturn(60000).when(mResources).getInteger(R.integer.config_networkTransitionTimeout);
1981         doReturn("").when(mResources).getString(R.string.config_networkCaptivePortalServerUrl);
1982         doReturn(new String[]{ WIFI_WOL_IFNAME }).when(mResources).getStringArray(
1983                 R.array.config_wakeonlan_supported_interfaces);
1984         doReturn(new String[] { "0,1", "1,3" }).when(mResources).getStringArray(
1985                 R.array.config_networkSupportedKeepaliveCount);
1986         doReturn(new String[0]).when(mResources).getStringArray(
1987                 R.array.config_networkNotifySwitches);
1988         doReturn(new int[]{10, 11, 12, 14, 15}).when(mResources).getIntArray(
1989                 R.array.config_protectedNetworks);
1990         // We don't test the actual notification value strings, so just return an empty array.
1991         // It doesn't matter what the values are as long as it's not null.
1992         doReturn(new String[0]).when(mResources)
1993                 .getStringArray(R.array.network_switch_type_name);
1994 
1995         doReturn(R.array.config_networkSupportedKeepaliveCount).when(mResources)
1996                 .getIdentifier(eq("config_networkSupportedKeepaliveCount"), eq("array"), any());
1997         doReturn(R.array.network_switch_type_name).when(mResources)
1998                 .getIdentifier(eq("network_switch_type_name"), eq("array"), any());
1999         doReturn(1).when(mResources).getInteger(R.integer.config_networkAvoidBadWifi);
2000         doReturn(0).when(mResources).getInteger(R.integer.config_activelyPreferBadWifi);
2001         doReturn(true).when(mResources)
2002                 .getBoolean(R.bool.config_cellular_radio_timesharing_capable);
2003         doReturn(PACKET_WAKEUP_MARK_MASK).when(mResources).getInteger(
2004                 R.integer.config_networkWakeupPacketMask);
2005         doReturn(PACKET_WAKEUP_MARK_MASK).when(mResources).getInteger(
2006                 R.integer.config_networkWakeupPacketMark);
2007     }
2008 
2009     class ConnectivityServiceDependencies extends ConnectivityService.Dependencies {
2010         final ConnectivityResources mConnRes;
2011         final ArraySet<Pair<Long, Integer>> mEnabledChangeIds = new ArraySet<>();
2012 
2013         // Note : Please do not add any new instrumentation here. If you need new instrumentation,
2014         // please add it in CSTest and use subclasses of CSTest instead of adding more
2015         // tools in ConnectivityServiceTest.
ConnectivityServiceDependencies(final Context mockResContext)2016         ConnectivityServiceDependencies(final Context mockResContext) {
2017             mConnRes = new ConnectivityResources(mockResContext);
2018         }
2019 
2020         @Override
makeHandlerThread(@onNull final String tag)2021         public HandlerThread makeHandlerThread(@NonNull final String tag) {
2022             return mCsHandlerThread;
2023         }
2024 
2025         @Override
getNetworkStack()2026         public NetworkStackClientBase getNetworkStack() {
2027             return mNetworkStack;
2028         }
2029 
2030         @Override
makeProxyTracker(final Context context, final Handler handler)2031         public ProxyTracker makeProxyTracker(final Context context, final Handler handler) {
2032             return mProxyTracker;
2033         }
2034 
2035         @Override
makeNetIdManager()2036         public NetIdManager makeNetIdManager() {
2037             return mNetIdManager;
2038         }
2039 
2040         @Override
queryUserAccess(final int uid, final Network network, final ConnectivityService cs)2041         public boolean queryUserAccess(final int uid, final Network network,
2042                 final ConnectivityService cs) {
2043             return true;
2044         }
2045 
2046         @Override
makeMultinetworkPolicyTracker(final Context c, final Handler h, final Runnable r)2047         public MultinetworkPolicyTracker makeMultinetworkPolicyTracker(final Context c,
2048                 final Handler h, final Runnable r) {
2049             if (null != mPolicyTracker) {
2050                 throw new IllegalStateException("Multinetwork policy tracker already initialized");
2051             }
2052             mPolicyTracker = new WrappedMultinetworkPolicyTracker(mServiceContext, h, r);
2053             return mPolicyTracker;
2054         }
2055 
2056         @Override
makeAutomaticOnOffKeepaliveTracker(final Context c, final Handler h)2057         public AutomaticOnOffKeepaliveTracker makeAutomaticOnOffKeepaliveTracker(final Context c,
2058                 final Handler h) {
2059             return new AutomaticOnOffKeepaliveTracker(c, h, mAutoOnOffKeepaliveDependencies);
2060         }
2061 
2062         @Override
getResources(final Context ctx)2063         public ConnectivityResources getResources(final Context ctx) {
2064             return mConnRes;
2065         }
2066 
2067         @Override
makeLocationPermissionChecker(final Context context)2068         public LocationPermissionChecker makeLocationPermissionChecker(final Context context) {
2069             return new LocationPermissionChecker(context) {
2070                 @Override
2071                 protected int getCurrentUser() {
2072                     return runAsShell(CREATE_USERS, () -> super.getCurrentUser());
2073                 }
2074             };
2075         }
2076 
2077         private BiConsumer<Integer, Integer> mCarrierPrivilegesLostListener;
2078 
2079         @Override
makeCarrierPrivilegeAuthenticator( @onNull final Context context, @NonNull final TelephonyManager tm, final boolean requestRestrictedWifiEnabled, BiConsumer<Integer, Integer> listener, @NonNull final Handler handler)2080         public CarrierPrivilegeAuthenticator makeCarrierPrivilegeAuthenticator(
2081                 @NonNull final Context context,
2082                 @NonNull final TelephonyManager tm,
2083                 final boolean requestRestrictedWifiEnabled,
2084                 BiConsumer<Integer, Integer> listener,
2085                 @NonNull final Handler handler) {
2086             mCarrierPrivilegesLostListener = listener;
2087             return mDeps.isAtLeastT() ? mCarrierPrivilegeAuthenticator : null;
2088         }
2089 
2090         @Override
makeSatelliteAccessController( @onNull final Context context, Consumer<Set<Integer>> updateSatelliteNetworkFallbackUidCallback, @NonNull final Handler connectivityServiceInternalHandler)2091         public SatelliteAccessController makeSatelliteAccessController(
2092                 @NonNull final Context context,
2093                 Consumer<Set<Integer>> updateSatelliteNetworkFallbackUidCallback,
2094                 @NonNull final Handler connectivityServiceInternalHandler) {
2095             return mSatelliteAccessController;
2096         }
2097 
2098         @Override
intentFilterEquals(final PendingIntent a, final PendingIntent b)2099         public boolean intentFilterEquals(final PendingIntent a, final PendingIntent b) {
2100             return runAsShell(GET_INTENT_SENDER_INTENT, () -> a.intentFilterEquals(b));
2101         }
2102 
2103         @GuardedBy("this")
2104         private Integer mCallingUid = null;
2105 
2106         @Override
getCallingUid()2107         public int getCallingUid() {
2108             synchronized (this) {
2109                 if (null != mCallingUid) return mCallingUid;
2110                 return super.getCallingUid();
2111             }
2112         }
2113 
2114         // Pass null for the real calling UID
setCallingUid(final Integer uid)2115         public void setCallingUid(final Integer uid) {
2116             synchronized (this) {
2117                 mCallingUid = uid;
2118             }
2119         }
2120 
2121         @GuardedBy("this")
2122         private boolean mCellular464XlatEnabled = true;
2123 
2124         @Override
getCellular464XlatEnabled()2125         public boolean getCellular464XlatEnabled() {
2126             synchronized (this) {
2127                 return mCellular464XlatEnabled;
2128             }
2129         }
2130 
setCellular464XlatEnabled(final boolean enabled)2131         public void setCellular464XlatEnabled(final boolean enabled) {
2132             synchronized (this) {
2133                 mCellular464XlatEnabled = enabled;
2134             }
2135         }
2136 
2137         @GuardedBy("this")
2138         private Integer mConnectionOwnerUid = null;
2139 
2140         @Override
getConnectionOwnerUid(final int protocol, final InetSocketAddress local, final InetSocketAddress remote)2141         public int getConnectionOwnerUid(final int protocol, final InetSocketAddress local,
2142                 final InetSocketAddress remote) {
2143             synchronized (this) {
2144                 if (null != mConnectionOwnerUid) return mConnectionOwnerUid;
2145                 return super.getConnectionOwnerUid(protocol, local, remote);
2146             }
2147         }
2148 
2149         // Pass null to get the production implementation of getConnectionOwnerUid
setConnectionOwnerUid(final Integer uid)2150         public void setConnectionOwnerUid(final Integer uid) {
2151             synchronized (this) {
2152                 mConnectionOwnerUid = uid;
2153             }
2154         }
2155 
2156         final class ReportedInterfaces {
2157             public final Context context;
2158             public final String iface;
2159             public final int[] transportTypes;
ReportedInterfaces(final Context c, final String i, final int[] t)2160             ReportedInterfaces(final Context c, final String i, final int[] t) {
2161                 context = c;
2162                 iface = i;
2163                 transportTypes = t;
2164             }
2165 
contentEquals(final Context c, final String i, final int[] t)2166             public boolean contentEquals(final Context c, final String i, final int[] t) {
2167                 return Objects.equals(context, c) && Objects.equals(iface, i)
2168                         && Arrays.equals(transportTypes, t);
2169             }
2170         }
2171 
2172         final ArrayTrackRecord<ReportedInterfaces> mReportedInterfaceHistory =
2173                 new ArrayTrackRecord<>();
2174 
2175         @Override
reportNetworkInterfaceForTransports(final Context context, final String iface, final int[] transportTypes)2176         public void reportNetworkInterfaceForTransports(final Context context, final String iface,
2177                 final int[] transportTypes) {
2178             mReportedInterfaceHistory.add(new ReportedInterfaces(context, iface, transportTypes));
2179             super.reportNetworkInterfaceForTransports(context, iface, transportTypes);
2180         }
2181 
2182         @Override
isFeatureEnabled(Context context, String name)2183         public boolean isFeatureEnabled(Context context, String name) {
2184             switch (name) {
2185                 case ConnectivityFlags.NO_REMATCH_ALL_REQUESTS_ON_REGISTER:
2186                 case ConnectivityFlags.CARRIER_SERVICE_CHANGED_USE_CALLBACK:
2187                 case ConnectivityFlags.REQUEST_RESTRICTED_WIFI:
2188                 case ConnectivityFlags.USE_DECLARED_METHODS_FOR_CALLBACKS:
2189                 case ConnectivityFlags.QUEUE_CALLBACKS_FOR_FROZEN_APPS:
2190                 case ConnectivityFlags.BACKGROUND_FIREWALL_CHAIN:
2191                 case ConnectivityService.KEY_DESTROY_FROZEN_SOCKETS_VERSION:
2192                     return true;
2193                 default:
2194                     // This is a unit test and must never depend on actual device flag values.
2195                     throw new UnsupportedOperationException("Unknown flag " + name
2196                             + ", update this test");
2197             }
2198         }
2199 
2200         @Override
isFeatureNotChickenedOut(Context context, String name)2201         public boolean isFeatureNotChickenedOut(Context context, String name) {
2202             switch (name) {
2203                 case ConnectivityService.ALLOW_SYSUI_CONNECTIVITY_REPORTS:
2204                 case ConnectivityService.ALLOW_SATALLITE_NETWORK_FALLBACK:
2205                 case ConnectivityFlags.INGRESS_TO_VPN_ADDRESS_FILTERING:
2206                 case ConnectivityFlags.BACKGROUND_FIREWALL_CHAIN:
2207                 case ConnectivityFlags.DELAY_DESTROY_SOCKETS:
2208                 case ConnectivityFlags.USE_DECLARED_METHODS_FOR_CALLBACKS:
2209                 case ConnectivityFlags.QUEUE_CALLBACKS_FOR_FROZEN_APPS:
2210                 case ConnectivityFlags.QUEUE_NETWORK_AGENT_EVENTS_IN_SYSTEM_SERVER:
2211                     return true;
2212                 default:
2213                     throw new UnsupportedOperationException("Unknown flag " + name
2214                             + ", update this test");
2215             }
2216         }
2217 
setChangeIdEnabled(final boolean enabled, final long changeId, final int uid)2218         public void setChangeIdEnabled(final boolean enabled, final long changeId, final int uid) {
2219             final Pair<Long, Integer> data = new Pair<>(changeId, uid);
2220             // mEnabledChangeIds is read on the handler thread and maybe the test thread, so
2221             // make sure both threads see it before continuing.
2222             visibleOnHandlerThread(mCsHandlerThread.getThreadHandler(), () -> {
2223                 if (enabled) {
2224                     mEnabledChangeIds.add(data);
2225                 } else {
2226                     mEnabledChangeIds.remove(data);
2227                 }
2228             });
2229         }
2230 
2231         @Override
isChangeEnabled(final long changeId, final int uid)2232         public boolean isChangeEnabled(final long changeId, final int uid) {
2233             return mEnabledChangeIds.contains(new Pair<>(changeId, uid));
2234         }
2235 
2236         // In AOSP, build version codes are all over the place (e.g. at the time of this writing
2237         // U == V). Define custom ones.
2238         private static final int VERSION_UNMOCKED = -1;
2239         private static final int VERSION_R = 1;
2240         private static final int VERSION_S = 2;
2241         private static final int VERSION_T = 3;
2242         private static final int VERSION_U = 4;
2243         private static final int VERSION_V = 5;
2244         private static final int VERSION_B = 6;
2245         private static final int VERSION_MAX = VERSION_B;
2246         private int mSdkLevel = VERSION_UNMOCKED;
2247 
setBuildSdk(final int sdkLevel)2248         private void setBuildSdk(final int sdkLevel) {
2249             if (sdkLevel > VERSION_MAX) {
2250                 throw new IllegalArgumentException("setBuildSdk must not be called with"
2251                         + " Build.VERSION constants but Dependencies.VERSION_* constants");
2252             }
2253             visibleOnHandlerThread(mCsHandlerThread.getThreadHandler(), () -> mSdkLevel = sdkLevel);
2254         }
2255 
2256         @Override
isAtLeastS()2257         public boolean isAtLeastS() {
2258             return mSdkLevel == VERSION_UNMOCKED ? super.isAtLeastS()
2259                     : mSdkLevel >= VERSION_S;
2260         }
2261 
2262         @Override
isAtLeastT()2263         public boolean isAtLeastT() {
2264             return mSdkLevel == VERSION_UNMOCKED ? super.isAtLeastT()
2265                     : mSdkLevel >= VERSION_T;
2266         }
2267 
2268         @Override
isAtLeastU()2269         public boolean isAtLeastU() {
2270             return mSdkLevel == VERSION_UNMOCKED ? super.isAtLeastU()
2271                     : mSdkLevel >= VERSION_U;
2272         }
2273 
2274         @Override
isAtLeastB()2275         public boolean isAtLeastB() {
2276             return mSdkLevel == VERSION_UNMOCKED ? super.isAtLeastB()
2277                     : mSdkLevel >= VERSION_B;
2278         }
2279 
2280         @Override
getBpfNetMaps(Context context, INetd netd, InterfaceTracker interfaceTracker)2281         public BpfNetMaps getBpfNetMaps(Context context, INetd netd,
2282                 InterfaceTracker interfaceTracker) {
2283             return mBpfNetMaps;
2284         }
2285 
2286         @Override
getClatCoordinator(INetd netd)2287         public ClatCoordinator getClatCoordinator(INetd netd) {
2288             return mClatCoordinator;
2289         }
2290 
2291         final ArrayTrackRecord<Pair<String, Long>> mRateLimitHistory = new ArrayTrackRecord<>();
2292         final Map<String, Long> mActiveRateLimit = new HashMap<>();
2293 
2294         @Override
enableIngressRateLimit(final String iface, final long rateInBytesPerSecond)2295         public void enableIngressRateLimit(final String iface, final long rateInBytesPerSecond) {
2296             mRateLimitHistory.add(new Pair<>(iface, rateInBytesPerSecond));
2297             // Due to a TC limitation, the rate limit needs to be removed before it can be
2298             // updated. Check that this happened.
2299             assertEquals(-1L, (long) mActiveRateLimit.getOrDefault(iface, -1L));
2300             mActiveRateLimit.put(iface, rateInBytesPerSecond);
2301             // verify that clsact qdisc has already been created, otherwise attaching a tc police
2302             // filter will fail.
2303             try {
2304                 verify(mMockNetd).networkAddInterface(anyInt(), eq(iface));
2305             } catch (RemoteException e) {
2306                 fail(e.getMessage());
2307             }
2308         }
2309 
2310         @Override
disableIngressRateLimit(final String iface)2311         public void disableIngressRateLimit(final String iface) {
2312             mRateLimitHistory.add(new Pair<>(iface, -1L));
2313             assertNotEquals(-1L, (long) mActiveRateLimit.getOrDefault(iface, -1L));
2314             mActiveRateLimit.put(iface, -1L);
2315         }
2316 
2317         @Override
getBpfProgramId(final int attachType)2318         public int getBpfProgramId(final int attachType) {
2319             return 0;
2320         }
2321 
2322         @Override
makeBroadcastOptionsShim(BroadcastOptions options)2323         public BroadcastOptionsShim makeBroadcastOptionsShim(BroadcastOptions options) {
2324             reset(mBroadcastOptionsShim);
2325             return mBroadcastOptionsShim;
2326         }
2327 
2328         @GuardedBy("this")
2329         private boolean mForceDisableCompatChangeCheck = true;
2330 
2331         /**
2332          * By default, the {@link #isChangeEnabled(long, String, UserHandle)} will always return
2333          * true as the mForceDisableCompatChangeCheck is true and compat change check logic is
2334          * never executed. The compat change check logic can be turned on by calling this method.
2335          * If this method is called, the
2336          * {@link libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges} or
2337          * {@link libcore.junit.util.compat.CoreCompatChangeRule.DisableCompatChanges} must be
2338          * used to turn on/off the compat change flag.
2339          */
enableCompatChangeCheck()2340         private void enableCompatChangeCheck() {
2341             synchronized (this) {
2342                 mForceDisableCompatChangeCheck = false;
2343             }
2344         }
2345 
2346         @Override
isChangeEnabled(long changeId, @NonNull final String packageName, @NonNull final UserHandle user)2347         public boolean isChangeEnabled(long changeId,
2348                 @NonNull final String packageName,
2349                 @NonNull final UserHandle user) {
2350             synchronized (this) {
2351                 if (mForceDisableCompatChangeCheck) {
2352                     return false;
2353                 } else {
2354                     return super.isChangeEnabled(changeId, packageName, user);
2355                 }
2356             }
2357         }
2358 
2359         // Class to be mocked and used to verify destroy sockets methods call
2360         public class DestroySocketsWrapper {
destroyLiveTcpSockets(final Set<Range<Integer>> ranges, final Set<Integer> exemptUids)2361             public void destroyLiveTcpSockets(final Set<Range<Integer>> ranges,
2362                     final Set<Integer> exemptUids){}
destroyLiveTcpSocketsByOwnerUids(final Set<Integer> ownerUids)2363             public void destroyLiveTcpSocketsByOwnerUids(final Set<Integer> ownerUids){}
2364         }
2365 
2366         @Override @SuppressWarnings("DirectInvocationOnMock")
destroyLiveTcpSockets(final Set<Range<Integer>> ranges, final Set<Integer> exemptUids)2367         public void destroyLiveTcpSockets(final Set<Range<Integer>> ranges,
2368                 final Set<Integer> exemptUids) {
2369             // Call mocked destroyLiveTcpSockets so that test can verify this method call
2370             mDestroySocketsWrapper.destroyLiveTcpSockets(ranges, exemptUids);
2371         }
2372 
2373         @Override @SuppressWarnings("DirectInvocationOnMock")
destroyLiveTcpSocketsByOwnerUids(final Set<Integer> ownerUids)2374         public void destroyLiveTcpSocketsByOwnerUids(final Set<Integer> ownerUids) {
2375             // Call mocked destroyLiveTcpSocketsByOwnerUids so that test can verify this method call
2376             // Create copy of ownerUids so that tests can verify the correct value even if the
2377             // ConnectivityService update the ownerUids after this method call.
2378             mDestroySocketsWrapper.destroyLiveTcpSocketsByOwnerUids(new ArraySet<>(ownerUids));
2379         }
2380 
2381         final ArrayTrackRecord<Pair<Integer, Long>>.ReadHead mScheduledEvaluationTimeouts =
2382                 new ArrayTrackRecord<Pair<Integer, Long>>().newReadHead();
2383         @Override
scheduleEvaluationTimeout(@onNull Handler handler, @NonNull final Network network, final long delayMs)2384         public void scheduleEvaluationTimeout(@NonNull Handler handler,
2385                 @NonNull final Network network, final long delayMs) {
2386             mScheduledEvaluationTimeouts.add(new Pair<>(network.netId, delayMs));
2387             super.scheduleEvaluationTimeout(handler, network, delayMs);
2388         }
2389 
2390         @Override
getDefaultCellularDataInactivityTimeout()2391         public int getDefaultCellularDataInactivityTimeout() {
2392             // Needed to mock out the dependency on DeviceConfig
2393             return 10;
2394         }
2395 
2396         @Override
getDefaultWifiDataInactivityTimeout()2397         public int getDefaultWifiDataInactivityTimeout() {
2398             // Needed to mock out the dependency on DeviceConfig
2399             return 15;
2400         }
2401 
2402         @Override
makeL2capNetworkProvider(Context context)2403         public L2capNetworkProvider makeL2capNetworkProvider(Context context) {
2404             return null;
2405         }
2406     }
2407 
2408     static class PermissionMonitorDependencies extends PermissionMonitor.Dependencies {
2409         @Override
2410         public boolean shouldEnforceLocalNetRestrictions(int uid) {
2411             return false;
2412         }
2413     }
2414 
2415     private class AutomaticOnOffKeepaliveTrackerDependencies
2416             extends AutomaticOnOffKeepaliveTracker.Dependencies {
2417         AutomaticOnOffKeepaliveTrackerDependencies(Context context) {
2418             super(context);
2419         }
2420 
2421         @Override
2422         public boolean isTetheringFeatureNotChickenedOut(@NonNull final String name) {
2423             // Tests for enabling the feature are verified in AutomaticOnOffKeepaliveTrackerTest.
2424             // Assuming enabled here to focus on ConnectivityService tests.
2425             return true;
2426         }
2427         public KeepaliveTracker newKeepaliveTracker(@NonNull Context context,
2428                 @NonNull Handler connectivityserviceHander) {
2429             return new KeepaliveTracker(context, connectivityserviceHander,
2430                     new TcpKeepaliveController(connectivityserviceHander),
2431                     mMockKeepaliveTrackerDependencies);
2432         }
2433     }
2434 
2435     private static void initAlarmManager(final AlarmManager am, final Handler alarmHandler) {
2436         doAnswer(inv -> {
2437             final long when = inv.getArgument(1);
2438             final WakeupMessage wakeupMsg = inv.getArgument(3);
2439             final Handler handler = inv.getArgument(4);
2440 
2441             long delayMs = when - SystemClock.elapsedRealtime();
2442             if (delayMs < 0) delayMs = 0;
2443             if (delayMs > UNREASONABLY_LONG_ALARM_WAIT_MS) {
2444                 fail("Attempting to send msg more than " + UNREASONABLY_LONG_ALARM_WAIT_MS
2445                         + "ms into the future: " + delayMs);
2446             }
2447             alarmHandler.postDelayed(() -> handler.post(wakeupMsg::onAlarm), wakeupMsg /* token */,
2448                     delayMs);
2449 
2450             return null;
2451         }).when(am).setExact(eq(AlarmManager.ELAPSED_REALTIME_WAKEUP), anyLong(), anyString(),
2452                 any(WakeupMessage.class), any());
2453 
2454         doAnswer(inv -> {
2455             final WakeupMessage wakeupMsg = inv.getArgument(0);
2456             alarmHandler.removeCallbacksAndMessages(wakeupMsg /* token */);
2457             return null;
2458         }).when(am).cancel(any(WakeupMessage.class));
2459     }
2460 
2461     @After
2462     public void tearDown() throws Exception {
2463         // Don't attempt to tear down if setUp didn't even get as far as creating the service.
2464         // Otherwise, exceptions here will mask the actual exception in setUp, making failures
2465         // harder to diagnose.
2466         if (mService == null) return;
2467         unregisterDefaultNetworkCallbacks();
2468         maybeTearDownEnterpriseNetwork();
2469         setAlwaysOnNetworks(false);
2470         if (mCellAgent != null) {
2471             mCellAgent.disconnect();
2472             mCellAgent = null;
2473         }
2474         if (mWiFiAgent != null) {
2475             mWiFiAgent.disconnect();
2476             mWiFiAgent = null;
2477         }
2478         if (mEthernetAgent != null) {
2479             mEthernetAgent.disconnect();
2480             mEthernetAgent = null;
2481         }
2482 
2483         if (mQosCallbackMockHelper != null) {
2484             mQosCallbackMockHelper.tearDown();
2485             mQosCallbackMockHelper = null;
2486         }
2487         mMockVpn.disconnect();
2488         waitForIdle();
2489 
2490         FakeSettingsProvider.clearSettingsProvider();
2491         ConnectivityResources.setResourcesContextForTest(null);
2492 
2493         for (TestNetworkAgentWrapper agent : mCreatedAgents) {
2494             agent.destroy();
2495         }
2496         mCreatedAgents.clear();
2497 
2498         mCsHandlerThread.quitSafely();
2499         mCsHandlerThread.join();
2500         mAlarmManagerThread.quitSafely();
2501         mAlarmManagerThread.join();
2502     }
2503 
2504     private void mockDefaultPackages() throws Exception {
2505         final String myPackageName = mContext.getPackageName();
2506         final PackageInfo myPackageInfo = mContext.getPackageManager().getPackageInfo(
2507                 myPackageName, PackageManager.GET_PERMISSIONS);
2508         myPackageInfo.setLongVersionCode(9_999_999L);
2509         doReturn(new String[] {myPackageName}).when(mPackageManager)
2510                 .getPackagesForUid(Binder.getCallingUid());
2511         doReturn(myPackageInfo).when(mPackageManager).getPackageInfoAsUser(
2512                 eq(myPackageName), anyInt(), eq(UserHandle.getCallingUserId()));
2513 
2514         doReturn(asList(new PackageInfo[] {
2515                 buildPackageInfo(/* SYSTEM */ false, APP1_UID),
2516                 buildPackageInfo(/* SYSTEM */ false, APP2_UID),
2517                 buildPackageInfo(/* SYSTEM */ false, VPN_UID)
2518         })).when(mPackageManager).getInstalledPackagesAsUser(eq(GET_PERMISSIONS), anyInt());
2519 
2520         final ModuleInfo moduleInfo = new ModuleInfo();
2521         moduleInfo.setPackageName(TETHERING_MODULE_NAME);
2522         doReturn(moduleInfo).when(mPackageManager)
2523                 .getModuleInfo(TETHERING_MODULE_NAME, PackageManager.MODULE_APEX_NAME);
2524         doReturn(myPackageInfo).when(mPackageManager)
2525                 .getPackageInfo(TETHERING_MODULE_NAME, PackageManager.MATCH_APEX);
2526 
2527         // Create a fake always-on VPN package.
2528         final int userId = UserHandle.getCallingUserId();
2529         final ApplicationInfo applicationInfo = new ApplicationInfo();
2530         applicationInfo.targetSdkVersion = Build.VERSION_CODES.R;  // Always-on supported in N+.
2531         doReturn(applicationInfo).when(mPackageManager).getApplicationInfoAsUser(
2532                 eq(ALWAYS_ON_PACKAGE), anyInt(), eq(userId));
2533 
2534         // Minimal mocking to keep Vpn#isAlwaysOnPackageSupported happy.
2535         ResolveInfo rInfo = new ResolveInfo();
2536         rInfo.serviceInfo = new ServiceInfo();
2537         rInfo.serviceInfo.metaData = new Bundle();
2538         final List<ResolveInfo> services = asList(new ResolveInfo[]{rInfo});
2539         doReturn(services).when(mPackageManager).queryIntentServicesAsUser(
2540                 any(), eq(PackageManager.GET_META_DATA), eq(userId));
2541         doReturn(Process.myUid()).when(mPackageManager).getPackageUidAsUser(
2542                 TEST_PACKAGE_NAME, userId);
2543         doReturn(VPN_UID).when(mPackageManager).getPackageUidAsUser(ALWAYS_ON_PACKAGE, userId);
2544     }
2545 
2546     private void verifyActiveNetwork(int transport) {
2547         // Test getActiveNetworkInfo()
2548         assertNotNull(mCm.getActiveNetworkInfo());
2549         assertEquals(transportToLegacyType(transport), mCm.getActiveNetworkInfo().getType());
2550         // Test getActiveNetwork()
2551         assertNotNull(mCm.getActiveNetwork());
2552         assertEquals(mCm.getActiveNetwork(), mCm.getActiveNetworkForUid(Process.myUid()));
2553         if (!NetworkCapabilities.isValidTransport(transport)) {
2554             throw new IllegalStateException("Unknown transport " + transport);
2555         }
2556         switch (transport) {
2557             case TRANSPORT_WIFI:
2558                 assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetwork());
2559                 break;
2560             case TRANSPORT_CELLULAR:
2561                 assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetwork());
2562                 break;
2563             case TRANSPORT_ETHERNET:
2564                 assertEquals(mEthernetAgent.getNetwork(), mCm.getActiveNetwork());
2565                 break;
2566             default:
2567                 break;
2568         }
2569         // Test getNetworkInfo(Network)
2570         assertNotNull(mCm.getNetworkInfo(mCm.getActiveNetwork()));
2571         assertEquals(transportToLegacyType(transport),
2572                 mCm.getNetworkInfo(mCm.getActiveNetwork()).getType());
2573         assertNotNull(mCm.getActiveNetworkInfoForUid(Process.myUid()));
2574         // Test getNetworkCapabilities(Network)
2575         assertNotNull(mCm.getNetworkCapabilities(mCm.getActiveNetwork()));
2576         assertTrue(mCm.getNetworkCapabilities(mCm.getActiveNetwork()).hasTransport(transport));
2577     }
2578 
2579     private void verifyNoNetwork() {
2580         waitForIdle();
2581         // Test getActiveNetworkInfo()
2582         assertNull(mCm.getActiveNetworkInfo());
2583         // Test getActiveNetwork()
2584         assertNull(mCm.getActiveNetwork());
2585         assertNull(mCm.getActiveNetworkForUid(Process.myUid()));
2586         // Test getAllNetworks()
2587         assertEmpty(mCm.getAllNetworks());
2588         assertEmpty(mCm.getAllNetworkStateSnapshots());
2589     }
2590 
2591     /**
2592      * Class to simplify expecting broadcasts using BroadcastInterceptingContext.
2593      * Ensures that the receiver is unregistered after the expected broadcast is received. This
2594      * cannot be done in the BroadcastReceiver itself because BroadcastInterceptingContext runs
2595      * the receivers' receive method while iterating over the list of receivers, and unregistering
2596      * the receiver during iteration throws ConcurrentModificationException.
2597      */
2598     private class ExpectedBroadcast extends CompletableFuture<Intent>  {
2599         private final BroadcastReceiver mReceiver;
2600 
2601         ExpectedBroadcast(BroadcastReceiver receiver) {
2602             mReceiver = receiver;
2603         }
2604 
2605         public Intent expectBroadcast(int timeoutMs) throws Exception {
2606             try {
2607                 return get(timeoutMs, TimeUnit.MILLISECONDS);
2608             } catch (TimeoutException e) {
2609                 fail("Expected broadcast not received after " + timeoutMs + " ms");
2610                 return null;
2611             } finally {
2612                 mServiceContext.unregisterReceiver(mReceiver);
2613             }
2614         }
2615 
2616         public Intent expectBroadcast() throws Exception {
2617             return expectBroadcast(BROADCAST_TIMEOUT_MS);
2618         }
2619 
2620         public void expectNoBroadcast(int timeoutMs) throws Exception {
2621             waitForIdle();
2622             try {
2623                 final Intent intent = get(timeoutMs, TimeUnit.MILLISECONDS);
2624                 fail("Unexpected broadcast: " + intent.getAction() + " " + intent.getExtras());
2625             } catch (TimeoutException expected) {
2626             } finally {
2627                 mServiceContext.unregisterReceiver(mReceiver);
2628             }
2629         }
2630     }
2631 
2632     private ExpectedBroadcast registerBroadcastReceiverThat(final String action, final int count,
2633             @NonNull final Predicate<Intent> filter) {
2634         final IntentFilter intentFilter = new IntentFilter(action);
2635         // AtomicReference allows receiver to access expected even though it is constructed later.
2636         final AtomicReference<ExpectedBroadcast> expectedRef = new AtomicReference<>();
2637         final BroadcastReceiver receiver = new BroadcastReceiver() {
2638             private int mRemaining = count;
2639             public void onReceive(Context context, Intent intent) {
2640                 logIntent(intent);
2641                 if (!filter.test(intent)) return;
2642                 if (--mRemaining == 0) {
2643                     expectedRef.get().complete(intent);
2644                 }
2645             }
2646         };
2647         final ExpectedBroadcast expected = new ExpectedBroadcast(receiver);
2648         expectedRef.set(expected);
2649         mServiceContext.registerReceiver(receiver, intentFilter);
2650         return expected;
2651     }
2652 
2653     private void logIntent(Intent intent) {
2654         final String action = intent.getAction();
2655         if (CONNECTIVITY_ACTION.equals(action)) {
2656             final int type = intent.getIntExtra(EXTRA_NETWORK_TYPE, -1);
2657             final NetworkInfo ni = intent.getParcelableExtra(EXTRA_NETWORK_INFO);
2658             Log.d(TAG, "Received " + action + ", type=" + type + " ni=" + ni);
2659         } else if (PROXY_CHANGE_ACTION.equals(action)) {
2660             final ProxyInfo proxy = (ProxyInfo) intent.getExtra(
2661                     Proxy.EXTRA_PROXY_INFO, ProxyInfo.buildPacProxy(Uri.EMPTY));
2662             Log.d(TAG, "Received " + action + ", proxy = " + proxy);
2663         } else {
2664             throw new IllegalArgumentException("Unsupported logging " + action);
2665         }
2666     }
2667 
2668     /** Expects that {@code count} CONNECTIVITY_ACTION broadcasts are received. */
2669     private ExpectedBroadcast expectConnectivityAction(final int count) {
2670         return registerBroadcastReceiverThat(CONNECTIVITY_ACTION, count, intent -> true);
2671     }
2672 
2673     private ExpectedBroadcast expectConnectivityAction(int type, NetworkInfo.DetailedState state) {
2674         return registerBroadcastReceiverThat(CONNECTIVITY_ACTION, 1, intent -> {
2675             final int actualType = intent.getIntExtra(EXTRA_NETWORK_TYPE, -1);
2676             final NetworkInfo ni = intent.getParcelableExtra(EXTRA_NETWORK_INFO);
2677             return type == actualType
2678                     && state == ni.getDetailedState()
2679                     && extraInfoInBroadcastHasExpectedNullness(ni);
2680         });
2681     }
2682 
2683     /** Expects that PROXY_CHANGE_ACTION broadcast is received. */
2684     private ExpectedBroadcast expectProxyChangeAction() {
2685         return registerBroadcastReceiverThat(PROXY_CHANGE_ACTION, 1, intent -> true);
2686     }
2687 
2688     private ExpectedBroadcast expectProxyChangeAction(ProxyInfo proxy) {
2689         return expectProxyChangeAction(actualProxy -> proxy.equals(actualProxy));
2690     }
2691 
2692     private ExpectedBroadcast expectProxyChangeAction(Predicate<ProxyInfo> tester) {
2693         return registerBroadcastReceiverThat(PROXY_CHANGE_ACTION, 1, intent -> {
2694             final ProxyInfo actualProxy = (ProxyInfo) intent.getExtra(Proxy.EXTRA_PROXY_INFO,
2695                     ProxyInfo.buildPacProxy(Uri.EMPTY));
2696             return tester.test(actualProxy);
2697         });
2698     }
2699 
2700     private boolean extraInfoInBroadcastHasExpectedNullness(NetworkInfo ni) {
2701         final DetailedState state = ni.getDetailedState();
2702         if (state == DetailedState.CONNECTED && ni.getExtraInfo() == null) return false;
2703         // Expect a null extraInfo if the network is CONNECTING, because a CONNECTIVITY_ACTION
2704         // broadcast with a state of CONNECTING only happens due to legacy VPN lockdown, which also
2705         // nulls out extraInfo.
2706         if (state == DetailedState.CONNECTING && ni.getExtraInfo() != null) return false;
2707         // Can't make any assertions about DISCONNECTED broadcasts. When a network actually
2708         // disconnects, disconnectAndDestroyNetwork sets its state to DISCONNECTED and its extraInfo
2709         // to null. But if the DISCONNECTED broadcast is just simulated by LegacyTypeTracker due to
2710         // a network switch, extraInfo will likely be populated.
2711         // This is likely a bug in CS, but likely not one we can fix without impacting apps.
2712         return true;
2713     }
2714 
2715     @Test
2716     public void testNetworkFeature() throws Exception {
2717         // Connect the cell agent and wait for the connected broadcast.
2718         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
2719         mCellAgent.addCapability(NET_CAPABILITY_SUPL);
2720         ExpectedBroadcast b = expectConnectivityAction(TYPE_MOBILE, DetailedState.CONNECTED);
2721         mCellAgent.connect(true);
2722         b.expectBroadcast();
2723 
2724         // Build legacy request for SUPL.
2725         final NetworkCapabilities legacyCaps = new NetworkCapabilities();
2726         legacyCaps.addTransportType(TRANSPORT_CELLULAR);
2727         legacyCaps.addCapability(NET_CAPABILITY_SUPL);
2728         final NetworkRequest legacyRequest = new NetworkRequest(legacyCaps, TYPE_MOBILE_SUPL,
2729                 ConnectivityManager.REQUEST_ID_UNSET, NetworkRequest.Type.REQUEST);
2730 
2731         // File request, withdraw it and make sure no broadcast is sent
2732         b = expectConnectivityAction(1);
2733         final TestNetworkCallback callback = new TestNetworkCallback();
2734         mCm.requestNetwork(legacyRequest, callback);
2735         callback.expect(AVAILABLE, mCellAgent);
2736         mCm.unregisterNetworkCallback(callback);
2737         b.expectNoBroadcast(800);  // 800ms long enough to at least flake if this is sent
2738 
2739         // Disconnect the network and expect mobile disconnected broadcast.
2740         b = expectConnectivityAction(TYPE_MOBILE, DetailedState.DISCONNECTED);
2741         mCellAgent.disconnect();
2742         b.expectBroadcast();
2743     }
2744 
2745     @Test
2746     public void testLingering() throws Exception {
2747         verifyNoNetwork();
2748         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
2749         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
2750         assertNull(mCm.getActiveNetworkInfo());
2751         assertNull(mCm.getActiveNetwork());
2752         // Test bringing up validated cellular.
2753         ExpectedBroadcast b = expectConnectivityAction(TYPE_MOBILE, DetailedState.CONNECTED);
2754         mCellAgent.connect(true);
2755         b.expectBroadcast();
2756         verifyActiveNetwork(TRANSPORT_CELLULAR);
2757         assertLength(2, mCm.getAllNetworks());
2758         assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork())
2759                 || mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork()));
2760         assertTrue(mCm.getAllNetworks()[0].equals(mWiFiAgent.getNetwork())
2761                 || mCm.getAllNetworks()[1].equals(mWiFiAgent.getNetwork()));
2762         // Test bringing up validated WiFi.
2763         b = expectConnectivityAction(2);
2764         mWiFiAgent.connect(true);
2765         b.expectBroadcast();
2766         verifyActiveNetwork(TRANSPORT_WIFI);
2767         assertLength(2, mCm.getAllNetworks());
2768         assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork())
2769                 || mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork()));
2770         assertTrue(mCm.getAllNetworks()[0].equals(mCellAgent.getNetwork())
2771                 || mCm.getAllNetworks()[1].equals(mCellAgent.getNetwork()));
2772         // Test cellular linger timeout.
2773         mCellAgent.expectDisconnected();
2774         waitForIdle();
2775         assertLength(1, mCm.getAllNetworks());
2776         verifyActiveNetwork(TRANSPORT_WIFI);
2777         assertLength(1, mCm.getAllNetworks());
2778         assertEquals(mCm.getAllNetworks()[0], mCm.getActiveNetwork());
2779         // Test WiFi disconnect.
2780         b = expectConnectivityAction(1);
2781         mWiFiAgent.disconnect();
2782         b.expectBroadcast();
2783         verifyNoNetwork();
2784     }
2785 
2786     /**
2787      * Verify a newly created network will be inactive instead of torn down even if no one is
2788      * requesting.
2789      */
2790     @Test
2791     public void testNewNetworkInactive() throws Exception {
2792         // Create a callback that monitoring the testing network.
2793         final TestNetworkCallback listenCallback = new TestNetworkCallback();
2794         mCm.registerNetworkCallback(new NetworkRequest.Builder().build(), listenCallback);
2795 
2796         // 1. Create a network that is not requested by anyone, and does not satisfy any of the
2797         // default requests. Verify that the network will be inactive instead of torn down.
2798         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
2799         mWiFiAgent.connectWithoutInternet();
2800         listenCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
2801         listenCallback.assertNoCallback();
2802 
2803         // Verify that the network will be torn down after nascent expiry. A small period of time
2804         // is added in case of flakiness.
2805         final int nascentTimeoutMs =
2806                 mService.mNascentDelayMs + mService.mNascentDelayMs / 4;
2807         listenCallback.expect(LOST, mWiFiAgent, nascentTimeoutMs);
2808 
2809         // 2. Create a network that is satisfied by a request comes later.
2810         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
2811         mWiFiAgent.connectWithoutInternet();
2812         listenCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
2813         final NetworkRequest wifiRequest = new NetworkRequest.Builder()
2814                 .addTransportType(TRANSPORT_WIFI).build();
2815         final TestNetworkCallback wifiCallback = new TestNetworkCallback();
2816         mCm.requestNetwork(wifiRequest, wifiCallback);
2817         wifiCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
2818 
2819         // Verify that the network will be kept since the request is still satisfied. And is able
2820         // to get disconnected as usual if the request is released after the nascent timer expires.
2821         listenCallback.assertNoCallback(nascentTimeoutMs);
2822         mCm.unregisterNetworkCallback(wifiCallback);
2823         listenCallback.expect(LOST, mWiFiAgent);
2824 
2825         // 3. Create a network that is satisfied by a request comes later.
2826         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
2827         mWiFiAgent.connectWithoutInternet();
2828         listenCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
2829         mCm.requestNetwork(wifiRequest, wifiCallback);
2830         wifiCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
2831 
2832         // Verify that the network will still be torn down after the request gets removed.
2833         mCm.unregisterNetworkCallback(wifiCallback);
2834         listenCallback.expect(LOST, mWiFiAgent);
2835 
2836         // There is no need to ensure that LOSING is never sent in the common case that the
2837         // network immediately satisfies a request that was already present, because it is already
2838         // verified anywhere whenever {@code TestNetworkCallback#expectAvailable*} is called.
2839 
2840         mCm.unregisterNetworkCallback(listenCallback);
2841     }
2842 
2843     /**
2844      * Verify a newly created network will be inactive and switch to background if only background
2845      * request is satisfied.
2846      */
2847     @Test
2848     public void testNewNetworkInactive_bgNetwork() throws Exception {
2849         // Create a callback that monitoring the wifi network.
2850         final TestNetworkCallback wifiListenCallback = new TestNetworkCallback();
2851         mCm.registerNetworkCallback(new NetworkRequest.Builder()
2852                 .addTransportType(TRANSPORT_WIFI).build(), wifiListenCallback);
2853 
2854         // Create callbacks that can monitor background and foreground mobile networks.
2855         // This is done by granting using background networks permission before registration. Thus,
2856         // the service will not add {@code NET_CAPABILITY_FOREGROUND} by default.
2857         grantUsingBackgroundNetworksPermissionForUid(Binder.getCallingUid());
2858         final TestNetworkCallback bgMobileListenCallback = new TestNetworkCallback();
2859         final TestNetworkCallback fgMobileListenCallback = new TestNetworkCallback();
2860         mCm.registerNetworkCallback(new NetworkRequest.Builder()
2861                 .addTransportType(TRANSPORT_CELLULAR).build(), bgMobileListenCallback);
2862         mCm.registerNetworkCallback(new NetworkRequest.Builder()
2863                 .addTransportType(TRANSPORT_CELLULAR)
2864                 .addCapability(NET_CAPABILITY_FOREGROUND).build(), fgMobileListenCallback);
2865 
2866         // Connect wifi, which satisfies default request.
2867         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
2868         mWiFiAgent.connect(true);
2869         wifiListenCallback.expectAvailableThenValidatedCallbacks(mWiFiAgent);
2870 
2871         // Connect a cellular network, verify that satisfies only the background callback.
2872         setAlwaysOnNetworks(true);
2873         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
2874         mCellAgent.connect(true);
2875         bgMobileListenCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
2876         fgMobileListenCallback.assertNoCallback();
2877         assertFalse(isForegroundNetwork(mCellAgent));
2878 
2879         mCellAgent.disconnect();
2880         bgMobileListenCallback.expect(LOST, mCellAgent);
2881         fgMobileListenCallback.assertNoCallback();
2882 
2883         mCm.unregisterNetworkCallback(wifiListenCallback);
2884         mCm.unregisterNetworkCallback(bgMobileListenCallback);
2885         mCm.unregisterNetworkCallback(fgMobileListenCallback);
2886     }
2887 
2888     @Test
2889     public void testBinderDeathAfterUnregister() throws Exception {
2890         final NetworkCapabilities caps = new NetworkCapabilities.Builder()
2891                 .addTransportType(TRANSPORT_WIFI)
2892                 .build();
2893         final Handler handler = new Handler(ConnectivityThread.getInstanceLooper());
2894         final Messenger messenger = new Messenger(handler);
2895         final CompletableFuture<Binder.DeathRecipient> deathRecipient = new CompletableFuture<>();
2896         final Binder binder = new Binder() {
2897             private DeathRecipient mDeathRecipient;
2898             @Override
2899             public void linkToDeath(@NonNull final DeathRecipient recipient, final int flags) {
2900                 synchronized (this) {
2901                     mDeathRecipient = recipient;
2902                 }
2903                 super.linkToDeath(recipient, flags);
2904                 deathRecipient.complete(recipient);
2905             }
2906 
2907             @Override
2908             public boolean unlinkToDeath(@NonNull final DeathRecipient recipient, final int flags) {
2909                 synchronized (this) {
2910                     if (null == mDeathRecipient) {
2911                         throw new IllegalStateException();
2912                     }
2913                     mDeathRecipient = null;
2914                 }
2915                 return super.unlinkToDeath(recipient, flags);
2916             }
2917         };
2918         final NetworkRequest request = mService.listenForNetwork(caps, messenger, binder,
2919                 NetworkCallback.FLAG_NONE, mContext.getOpPackageName(),
2920                 mContext.getAttributionTag(), ~0 /* declaredMethodsFlag */);
2921         mService.releaseNetworkRequest(request);
2922         deathRecipient.get().binderDied();
2923         // Wait for the release message to be processed.
2924         waitForIdle();
2925         // After waitForIdle(), the message was processed and the service didn't crash.
2926     }
2927 
2928     // TODO : migrate to @Parameterized
2929     @Test
2930     public void testValidatedCellularOutscoresUnvalidatedWiFi_CanTimeShare() throws Exception {
2931         // The behavior of this test should be the same whether the radio can time share or not.
2932         doTestValidatedCellularOutscoresUnvalidatedWiFi(true);
2933     }
2934 
2935     // TODO : migrate to @Parameterized
2936     @Test
2937     public void testValidatedCellularOutscoresUnvalidatedWiFi_CannotTimeShare() throws Exception {
2938         doTestValidatedCellularOutscoresUnvalidatedWiFi(false);
2939     }
2940 
2941     private void doTestValidatedCellularOutscoresUnvalidatedWiFi(
2942             final boolean cellRadioTimesharingCapable) throws Exception {
2943         mService.mCellularRadioTimesharingCapable = cellRadioTimesharingCapable;
2944         // Test bringing up unvalidated WiFi
2945         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
2946         ExpectedBroadcast b = expectConnectivityAction(1);
2947         mWiFiAgent.connect(false);
2948         b.expectBroadcast();
2949         verifyActiveNetwork(TRANSPORT_WIFI);
2950         // Test bringing up unvalidated cellular
2951         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
2952         mCellAgent.connect(false);
2953         waitForIdle();
2954         verifyActiveNetwork(TRANSPORT_WIFI);
2955         // Test cellular disconnect.
2956         mCellAgent.disconnect();
2957         waitForIdle();
2958         verifyActiveNetwork(TRANSPORT_WIFI);
2959         // Test bringing up validated cellular
2960         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
2961         b = expectConnectivityAction(2);
2962         mCellAgent.connect(true);
2963         b.expectBroadcast();
2964         verifyActiveNetwork(TRANSPORT_CELLULAR);
2965         // Test cellular disconnect.
2966         b = expectConnectivityAction(2);
2967         mCellAgent.disconnect();
2968         b.expectBroadcast();
2969         verifyActiveNetwork(TRANSPORT_WIFI);
2970         // Test WiFi disconnect.
2971         b = expectConnectivityAction(1);
2972         mWiFiAgent.disconnect();
2973         b.expectBroadcast();
2974         verifyNoNetwork();
2975     }
2976 
2977     // TODO : migrate to @Parameterized
2978     @Test
2979     public void testUnvalidatedWifiOutscoresUnvalidatedCellular_CanTimeShare() throws Exception {
2980         doTestUnvalidatedWifiOutscoresUnvalidatedCellular(true);
2981     }
2982 
2983     // TODO : migrate to @Parameterized
2984     @Test
2985     public void testUnvalidatedWifiOutscoresUnvalidatedCellular_CannotTimeShare() throws Exception {
2986         doTestUnvalidatedWifiOutscoresUnvalidatedCellular(false);
2987     }
2988 
2989     private void doTestUnvalidatedWifiOutscoresUnvalidatedCellular(
2990             final boolean cellRadioTimesharingCapable) throws Exception {
2991         mService.mCellularRadioTimesharingCapable = cellRadioTimesharingCapable;
2992         // Test bringing up unvalidated cellular.
2993         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
2994         ExpectedBroadcast b = expectConnectivityAction(1);
2995         mCellAgent.connect(false);
2996         b.expectBroadcast();
2997         verifyActiveNetwork(TRANSPORT_CELLULAR);
2998         // Test bringing up unvalidated WiFi.
2999         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3000         b = expectConnectivityAction(2);
3001         mWiFiAgent.connect(false);
3002         b.expectBroadcast();
3003         verifyActiveNetwork(TRANSPORT_WIFI);
3004         // Test WiFi disconnect.
3005         b = expectConnectivityAction(2);
3006         mWiFiAgent.disconnect();
3007         b.expectBroadcast();
3008         verifyActiveNetwork(TRANSPORT_CELLULAR);
3009         // Test cellular disconnect.
3010         b = expectConnectivityAction(1);
3011         mCellAgent.disconnect();
3012         b.expectBroadcast();
3013         verifyNoNetwork();
3014     }
3015 
3016     // TODO : migrate to @Parameterized
3017     @Test
3018     public void testUnlingeringDoesNotValidate_CanTimeShare() throws Exception {
3019         doTestUnlingeringDoesNotValidate(true);
3020     }
3021 
3022     // TODO : migrate to @Parameterized
3023     @Test
3024     public void testUnlingeringDoesNotValidate_CannotTimeShare() throws Exception {
3025         doTestUnlingeringDoesNotValidate(false);
3026     }
3027 
3028     private void doTestUnlingeringDoesNotValidate(
3029             final boolean cellRadioTimesharingCapable) throws Exception {
3030         mService.mCellularRadioTimesharingCapable = cellRadioTimesharingCapable;
3031         // Test bringing up unvalidated WiFi.
3032         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3033         ExpectedBroadcast b = expectConnectivityAction(1);
3034         mWiFiAgent.connect(false);
3035         b.expectBroadcast();
3036         verifyActiveNetwork(TRANSPORT_WIFI);
3037         assertFalse(mCm.getNetworkCapabilities(mWiFiAgent.getNetwork()).hasCapability(
3038                 NET_CAPABILITY_VALIDATED));
3039         // Test bringing up validated cellular.
3040         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
3041         b = expectConnectivityAction(2);
3042         mCellAgent.connect(true);
3043         b.expectBroadcast();
3044         verifyActiveNetwork(TRANSPORT_CELLULAR);
3045         assertFalse(mCm.getNetworkCapabilities(mWiFiAgent.getNetwork()).hasCapability(
3046                 NET_CAPABILITY_VALIDATED));
3047         // Test cellular disconnect.
3048         b = expectConnectivityAction(2);
3049         mCellAgent.disconnect();
3050         b.expectBroadcast();
3051         verifyActiveNetwork(TRANSPORT_WIFI);
3052         // Unlingering a network should not cause it to be marked as validated.
3053         assertFalse(mCm.getNetworkCapabilities(mWiFiAgent.getNetwork()).hasCapability(
3054                 NET_CAPABILITY_VALIDATED));
3055     }
3056 
3057     // TODO : migrate to @Parameterized
3058     @Test
3059     public void testRequestMigrationToSameTransport_CanTimeShare() throws Exception {
3060         // Simulate a device where the cell radio is capable of time sharing
3061         mService.mCellularRadioTimesharingCapable = true;
3062         doTestRequestMigrationToSameTransport(TRANSPORT_CELLULAR, true);
3063         doTestRequestMigrationToSameTransport(TRANSPORT_WIFI, true);
3064         doTestRequestMigrationToSameTransport(TRANSPORT_ETHERNET, true);
3065     }
3066 
3067     // TODO : migrate to @Parameterized
3068     @Test
3069     public void testRequestMigrationToSameTransport_CannotTimeShare() throws Exception {
3070         // Simulate a device where the cell radio is not capable of time sharing
3071         mService.mCellularRadioTimesharingCapable = false;
3072         doTestRequestMigrationToSameTransport(TRANSPORT_CELLULAR, false);
3073         doTestRequestMigrationToSameTransport(TRANSPORT_WIFI, true);
3074         doTestRequestMigrationToSameTransport(TRANSPORT_ETHERNET, true);
3075     }
3076 
3077     private void doTestRequestMigrationToSameTransport(final int transport,
3078             final boolean expectLingering) throws Exception {
3079         // To speed up tests the linger delay is very short by default in tests but this
3080         // test needs to make sure the delay is not incurred so a longer value is safer (it
3081         // reduces the risk that a bug exists but goes undetected). The alarm manager in the test
3082         // throws and crashes CS if this is set to anything more than the below constant though.
3083         mService.mLingerDelayMs = UNREASONABLY_LONG_ALARM_WAIT_MS;
3084 
3085         final TestNetworkCallback generalCb = new TestNetworkCallback();
3086         final TestNetworkCallback defaultCb = new TestNetworkCallback();
3087         mCm.registerNetworkCallback(
3088                 new NetworkRequest.Builder().addTransportType(transport).build(),
3089                 generalCb);
3090         mCm.registerDefaultNetworkCallback(defaultCb);
3091 
3092         // Bring up net agent 1
3093         final TestNetworkAgentWrapper net1 = new TestNetworkAgentWrapper(transport);
3094         net1.connect(true);
3095         // Make sure the default request is on net 1
3096         generalCb.expectAvailableThenValidatedCallbacks(net1);
3097         defaultCb.expectAvailableThenValidatedCallbacks(net1);
3098 
3099         // Bring up net 2 with primary and mms
3100         final TestNetworkAgentWrapper net2 = new TestNetworkAgentWrapper(transport);
3101         net2.addCapability(NET_CAPABILITY_MMS);
3102         net2.setScore(new NetworkScore.Builder().setTransportPrimary(true).build());
3103         net2.connect(true);
3104 
3105         // Make sure the default request goes to net 2
3106         generalCb.expectAvailableCallbacksUnvalidated(net2);
3107         if (expectLingering) {
3108             generalCb.expectLosing(net1);
3109         }
3110         if (mShouldCreateNetworksImmediately) {
3111             if (expectLingering) {
3112                 // Make sure cell 1 is unwanted immediately if the radio can't time share, but only
3113                 // after some delay if it can.
3114                 generalCb.expectCaps(net2, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
3115                 defaultCb.expectAvailableDoubleValidatedCallbacks(net2);
3116                 net1.assertNotDisconnected(TEST_CALLBACK_TIMEOUT_MS); // always incurs the timeout
3117                 generalCb.assertNoCallback();
3118                 // assertNotDisconnected waited for TEST_CALLBACK_TIMEOUT_MS, so waiting for the
3119                 // linger period gives TEST_CALLBACK_TIMEOUT_MS time for the event to process.
3120                 net1.expectDisconnected(UNREASONABLY_LONG_ALARM_WAIT_MS);
3121                 generalCb.expect(LOST, net1);
3122             } else {
3123                 net1.expectDisconnected(TEST_CALLBACK_TIMEOUT_MS);
3124                 net1.disconnect();
3125                 generalCb.expect(LOST, net1);
3126                 generalCb.expectCaps(net2, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
3127                 defaultCb.expectAvailableDoubleValidatedCallbacks(net2);
3128             }
3129         } else {
3130             generalCb.expectCaps(net2, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
3131             defaultCb.expectAvailableDoubleValidatedCallbacks(net2);
3132 
3133             // Make sure cell 1 is unwanted immediately if the radio can't time share, but only
3134             // after some delay if it can.
3135             if (expectLingering) {
3136                 net1.assertNotDisconnected(TEST_CALLBACK_TIMEOUT_MS); // always incurs the timeout
3137                 generalCb.assertNoCallback();
3138                 // assertNotDisconnected waited for TEST_CALLBACK_TIMEOUT_MS, so waiting for the
3139                 // linger period gives TEST_CALLBACK_TIMEOUT_MS time for the event to process.
3140                 net1.expectDisconnected(UNREASONABLY_LONG_ALARM_WAIT_MS);
3141             } else {
3142                 net1.expectDisconnected(TEST_CALLBACK_TIMEOUT_MS);
3143             }
3144             net1.disconnect();
3145             generalCb.expect(LOST, net1);
3146         }
3147 
3148         // Remove primary from net 2
3149         net2.setScore(new NetworkScore.Builder().build());
3150         // Request MMS
3151         final TestNetworkCallback mmsCallback = new TestNetworkCallback();
3152         mCm.requestNetwork(new NetworkRequest.Builder().addCapability(NET_CAPABILITY_MMS).build(),
3153                 mmsCallback);
3154         mmsCallback.expectAvailableCallbacksValidated(net2);
3155 
3156         // Bring up net 3 with primary but without MMS
3157         final TestNetworkAgentWrapper net3 = new TestNetworkAgentWrapper(transport);
3158         net3.setScore(new NetworkScore.Builder().setTransportPrimary(true).build());
3159         net3.connect(true);
3160 
3161         // Make sure default goes to net 3, but the MMS request doesn't
3162         generalCb.expectAvailableThenValidatedCallbacks(net3);
3163         defaultCb.expectAvailableDoubleValidatedCallbacks(net3);
3164         mmsCallback.assertNoCallback();
3165         net2.assertNotDisconnected(TEST_CALLBACK_TIMEOUT_MS); // Always incurs the timeout
3166 
3167         // Revoke MMS request and make sure net 2 is torn down with the appropriate delay
3168         mCm.unregisterNetworkCallback(mmsCallback);
3169         if (expectLingering) {
3170             // If the radio can time share, the linger delay hasn't elapsed yet, so apps will
3171             // get LOSING. If the radio can't time share, this is a hard loss, since the last
3172             // request keeping up this network has been removed and the network isn't lingering
3173             // for any other request.
3174             generalCb.expectLosing(net2);
3175             net2.assertNotDisconnected(TEST_CALLBACK_TIMEOUT_MS);
3176             // Timeout 0 because after a while LOST will actually arrive
3177             generalCb.assertNoCallback(0 /* timeoutMs */);
3178             net2.expectDisconnected(UNREASONABLY_LONG_ALARM_WAIT_MS);
3179         } else {
3180             net2.expectDisconnected(TEST_CALLBACK_TIMEOUT_MS);
3181         }
3182         net2.disconnect();
3183         generalCb.expect(LOST, net2);
3184         defaultCb.assertNoCallback();
3185 
3186         net3.disconnect();
3187         mCm.unregisterNetworkCallback(defaultCb);
3188         mCm.unregisterNetworkCallback(generalCb);
3189     }
3190 
3191     // TODO : migrate to @Parameterized
3192     @Test
3193     public void testCellularOutscoresWeakWifi_CanTimeShare() throws Exception {
3194         // The behavior of this test should be the same whether the radio can time share or not.
3195         doTestCellularOutscoresWeakWifi(true);
3196     }
3197 
3198     // TODO : migrate to @Parameterized
3199     @Test
3200     public void testCellularOutscoresWeakWifi_CannotTimeShare() throws Exception {
3201         doTestCellularOutscoresWeakWifi(false);
3202     }
3203 
3204     private void doTestCellularOutscoresWeakWifi(
3205             final boolean cellRadioTimesharingCapable) throws Exception {
3206         mService.mCellularRadioTimesharingCapable = cellRadioTimesharingCapable;
3207         // Test bringing up validated cellular.
3208         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
3209         ExpectedBroadcast b = expectConnectivityAction(1);
3210         mCellAgent.connect(true);
3211         b.expectBroadcast();
3212         verifyActiveNetwork(TRANSPORT_CELLULAR);
3213         // Test bringing up validated WiFi.
3214         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3215         b = expectConnectivityAction(2);
3216         mWiFiAgent.connect(true);
3217         b.expectBroadcast();
3218         verifyActiveNetwork(TRANSPORT_WIFI);
3219         // Test WiFi getting really weak.
3220         b = expectConnectivityAction(2);
3221         mWiFiAgent.adjustScore(-11);
3222         b.expectBroadcast();
3223         verifyActiveNetwork(TRANSPORT_CELLULAR);
3224         // Test WiFi restoring signal strength.
3225         b = expectConnectivityAction(2);
3226         mWiFiAgent.adjustScore(11);
3227         b.expectBroadcast();
3228         verifyActiveNetwork(TRANSPORT_WIFI);
3229     }
3230 
3231     // TODO : migrate to @Parameterized
3232     @Test
3233     public void testReapingNetwork_CanTimeShare() throws Exception {
3234         doTestReapingNetwork(true);
3235     }
3236 
3237     // TODO : migrate to @Parameterized
3238     @Test
3239     public void testReapingNetwork_CannotTimeShare() throws Exception {
3240         doTestReapingNetwork(false);
3241     }
3242 
3243     private void doTestReapingNetwork(
3244             final boolean cellRadioTimesharingCapable) throws Exception {
3245         mService.mCellularRadioTimesharingCapable = cellRadioTimesharingCapable;
3246         // Test bringing up WiFi without NET_CAPABILITY_INTERNET.
3247         // Expect it to be torn down immediately because it satisfies no requests.
3248         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3249         mWiFiAgent.connectWithoutInternet();
3250         mWiFiAgent.expectDisconnected();
3251         // Test bringing up cellular without NET_CAPABILITY_INTERNET.
3252         // Expect it to be torn down immediately because it satisfies no requests.
3253         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3254         mCellAgent.connectWithoutInternet();
3255         mCellAgent.expectDisconnected();
3256         // Test bringing up validated WiFi.
3257         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3258         final ExpectedBroadcast b = expectConnectivityAction(TYPE_WIFI, DetailedState.CONNECTED);
3259         mWiFiAgent.connect(true);
3260         b.expectBroadcast();
3261         verifyActiveNetwork(TRANSPORT_WIFI);
3262         // Test bringing up unvalidated cellular.
3263         // Expect it to be torn down because it could never be the highest scoring network
3264         // satisfying the default request even if it validated.
3265         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
3266         mCellAgent.connect(false);
3267         mCellAgent.expectDisconnected();
3268         verifyActiveNetwork(TRANSPORT_WIFI);
3269         mWiFiAgent.disconnect();
3270         mWiFiAgent.expectDisconnected();
3271     }
3272 
3273     // TODO : migrate to @Parameterized
3274     @Test
3275     public void testCellularFallback_CanTimeShare() throws Exception {
3276         doTestCellularFallback(true);
3277     }
3278 
3279     // TODO : migrate to @Parameterized
3280     @Test
3281     public void testCellularFallback_CannotTimeShare() throws Exception {
3282         doTestCellularFallback(false);
3283     }
3284 
3285     private void doTestCellularFallback(
3286             final boolean cellRadioTimesharingCapable) throws Exception {
3287         mService.mCellularRadioTimesharingCapable = cellRadioTimesharingCapable;
3288         // Test bringing up validated cellular.
3289         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
3290         ExpectedBroadcast b = expectConnectivityAction(1);
3291         mCellAgent.connect(true);
3292         b.expectBroadcast();
3293         verifyActiveNetwork(TRANSPORT_CELLULAR);
3294         // Test bringing up validated WiFi.
3295         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3296         b = expectConnectivityAction(2);
3297         mWiFiAgent.connect(true);
3298         b.expectBroadcast();
3299         verifyActiveNetwork(TRANSPORT_WIFI);
3300         // Reevaluate WiFi (it'll instantly fail DNS).
3301         b = expectConnectivityAction(2);
3302         assertTrue(mCm.getNetworkCapabilities(mWiFiAgent.getNetwork()).hasCapability(
3303                 NET_CAPABILITY_VALIDATED));
3304         mCm.reportBadNetwork(mWiFiAgent.getNetwork());
3305         // Should quickly fall back to Cellular.
3306         b.expectBroadcast();
3307         assertFalse(mCm.getNetworkCapabilities(mWiFiAgent.getNetwork()).hasCapability(
3308                 NET_CAPABILITY_VALIDATED));
3309         verifyActiveNetwork(TRANSPORT_CELLULAR);
3310         // Reevaluate cellular (it'll instantly fail DNS).
3311         b = expectConnectivityAction(2);
3312         assertTrue(mCm.getNetworkCapabilities(mCellAgent.getNetwork()).hasCapability(
3313                 NET_CAPABILITY_VALIDATED));
3314         mCm.reportBadNetwork(mCellAgent.getNetwork());
3315         // Should quickly fall back to WiFi.
3316         b.expectBroadcast();
3317         assertFalse(mCm.getNetworkCapabilities(mCellAgent.getNetwork()).hasCapability(
3318                 NET_CAPABILITY_VALIDATED));
3319         assertFalse(mCm.getNetworkCapabilities(mWiFiAgent.getNetwork()).hasCapability(
3320                 NET_CAPABILITY_VALIDATED));
3321         verifyActiveNetwork(TRANSPORT_WIFI);
3322     }
3323 
3324     // TODO : migrate to @Parameterized
3325     @Test
3326     public void testWiFiFallback_CanTimeShare() throws Exception {
3327         doTestWiFiFallback(true);
3328     }
3329 
3330     // TODO : migrate to @Parameterized
3331     @Test
3332     public void testWiFiFallback_CannotTimeShare() throws Exception {
3333         doTestWiFiFallback(false);
3334     }
3335 
3336     private void doTestWiFiFallback(
3337             final boolean cellRadioTimesharingCapable) throws Exception {
3338         mService.mCellularRadioTimesharingCapable = cellRadioTimesharingCapable;
3339         // Test bringing up unvalidated WiFi.
3340         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3341         ExpectedBroadcast b = expectConnectivityAction(1);
3342         mWiFiAgent.connect(false);
3343         b.expectBroadcast();
3344         verifyActiveNetwork(TRANSPORT_WIFI);
3345         // Test bringing up validated cellular.
3346         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
3347         b = expectConnectivityAction(2);
3348         mCellAgent.connect(true);
3349         b.expectBroadcast();
3350         verifyActiveNetwork(TRANSPORT_CELLULAR);
3351         // Reevaluate cellular (it'll instantly fail DNS).
3352         b = expectConnectivityAction(2);
3353         assertTrue(mCm.getNetworkCapabilities(mCellAgent.getNetwork()).hasCapability(
3354                 NET_CAPABILITY_VALIDATED));
3355         mCm.reportBadNetwork(mCellAgent.getNetwork());
3356         // Should quickly fall back to WiFi.
3357         b.expectBroadcast();
3358         assertFalse(mCm.getNetworkCapabilities(mCellAgent.getNetwork()).hasCapability(
3359                 NET_CAPABILITY_VALIDATED));
3360         verifyActiveNetwork(TRANSPORT_WIFI);
3361     }
3362 
3363     @Test
3364     public void testRequiresValidation() {
3365         assertTrue(NetworkMonitorUtils.isValidationRequired(false /* isDunValidationRequired */,
3366                 false /* isVpnValidationRequired */,
3367                 mCm.getDefaultRequest().networkCapabilities));
3368     }
3369 
3370     /**
3371      * Utility NetworkCallback for testing. The caller must explicitly test for all the callbacks
3372      * this class receives, by calling expect() exactly once each time a callback is
3373      * received. assertNoCallback may be called at any time.
3374      */
3375     private class TestNetworkCallback extends TestableNetworkCallback {
3376         TestNetworkCallback() {
3377             // In the context of this test, the testable network callbacks should use waitForIdle
3378             // before calling assertNoCallback in an effort to detect issues where a callback is
3379             // not yet sent but a message currently in the queue of a handler will cause it to
3380             // be sent soon.
3381             super(TEST_CALLBACK_TIMEOUT_MS, TEST_CALLBACK_TIMEOUT_MS,
3382                     ConnectivityServiceTest.this::waitForIdle);
3383         }
3384 
3385         public CallbackEntry.Losing expectLosing(final HasNetwork n, final long timeoutMs) {
3386             final CallbackEntry.Losing losing = expect(LOSING, n, timeoutMs);
3387             final int maxMsToLive = losing.getMaxMsToLive();
3388             if (maxMsToLive < 0 || maxMsToLive > mService.mLingerDelayMs) {
3389                 // maxMsToLive is the value that was received in the onLosing callback. That must
3390                 // not be negative, so check that.
3391                 // Also, maxMsToLive is the remaining time until the network expires.
3392                 // mService.mLingerDelayMs is how long the network takes from when it's first
3393                 // detected to be unneeded to when it expires, so maxMsToLive should never
3394                 // be greater than that.
3395                 fail(String.format("Invalid linger time value %d, must be between %d and %d",
3396                         maxMsToLive, 0, mService.mLingerDelayMs));
3397             }
3398             return losing;
3399         }
3400 
3401         public CallbackEntry.Losing expectLosing(final HasNetwork n) {
3402             return expectLosing(n, getDefaultTimeoutMs());
3403         }
3404     }
3405 
3406     // Can't be part of TestNetworkCallback because "cannot be declared static; static methods can
3407     // only be declared in a static or top level type".
3408     static void assertNoCallbacks(final long timeoutMs, TestNetworkCallback ... callbacks) {
3409         for (TestNetworkCallback c : callbacks) {
3410             c.assertNoCallback(timeoutMs);
3411         }
3412     }
3413 
3414     static void assertNoCallbacks(TestNetworkCallback ... callbacks) {
3415         for (TestNetworkCallback c : callbacks) {
3416             c.assertNoCallback(); // each callback uses its own timeout
3417         }
3418     }
3419 
3420     static void expectOnLost(TestNetworkAgentWrapper network, TestNetworkCallback ... callbacks) {
3421         for (TestNetworkCallback c : callbacks) {
3422             c.expect(LOST, network);
3423         }
3424     }
3425 
3426     static void expectAvailableCallbacksUnvalidatedWithSpecifier(TestNetworkAgentWrapper network,
3427             NetworkSpecifier specifier, TestNetworkCallback ... callbacks) {
3428         for (TestNetworkCallback c : callbacks) {
3429             c.expect(AVAILABLE, network);
3430             c.expectCaps(network, cb -> !cb.hasCapability(NET_CAPABILITY_VALIDATED)
3431                     && Objects.equals(specifier, cb.getNetworkSpecifier()));
3432             c.expect(LINK_PROPERTIES_CHANGED, network);
3433             c.expect(BLOCKED_STATUS, network);
3434         }
3435     }
3436 
3437     @Test
3438     public void testNetworkDoesntMatchRequestsUntilConnected() throws Exception {
3439         final TestNetworkCallback cb = new TestNetworkCallback();
3440         final NetworkRequest wifiRequest = new NetworkRequest.Builder()
3441                 .addTransportType(TRANSPORT_WIFI).build();
3442         mCm.requestNetwork(wifiRequest, cb);
3443         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3444         // Updating the score triggers a rematch.
3445         mWiFiAgent.setScore(new NetworkScore.Builder().build());
3446         cb.assertNoCallback();
3447         mWiFiAgent.connect(false);
3448         cb.expectAvailableCallbacksUnvalidated(mWiFiAgent);
3449         cb.assertNoCallback();
3450         mCm.unregisterNetworkCallback(cb);
3451     }
3452 
3453     @Test
3454     public void testNetworkNotVisibleUntilConnected() throws Exception {
3455         final TestNetworkCallback cb = new TestNetworkCallback();
3456         final NetworkRequest wifiRequest = new NetworkRequest.Builder()
3457                 .addTransportType(TRANSPORT_WIFI).build();
3458         mCm.registerNetworkCallback(wifiRequest, cb);
3459         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3460         final NetworkCapabilities nc = mWiFiAgent.getNetworkCapabilities();
3461         nc.addCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED);
3462         mWiFiAgent.setNetworkCapabilities(nc, true /* sendToConnectivityService */);
3463         cb.assertNoCallback();
3464         mWiFiAgent.connect(false);
3465         cb.expectAvailableCallbacksUnvalidated(mWiFiAgent);
3466         final CallbackEntry found = CollectionUtils.findLast(cb.getHistory(),
3467                 it -> it instanceof CallbackEntry.CapabilitiesChanged);
3468         assertTrue(((CallbackEntry.CapabilitiesChanged) found).getCaps()
3469                 .hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED));
3470         cb.assertNoCallback();
3471         mCm.unregisterNetworkCallback(cb);
3472     }
3473 
3474     @Test
3475     public void testStateChangeNetworkCallbacks() throws Exception {
3476         final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback();
3477         final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
3478         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
3479         final NetworkRequest genericRequest = new NetworkRequest.Builder()
3480                 .clearCapabilities().build();
3481         final NetworkRequest wifiRequest = new NetworkRequest.Builder()
3482                 .addTransportType(TRANSPORT_WIFI).build();
3483         final NetworkRequest cellRequest = new NetworkRequest.Builder()
3484                 .addTransportType(TRANSPORT_CELLULAR).build();
3485         mCm.registerNetworkCallback(genericRequest, genericNetworkCallback);
3486         mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
3487         mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
3488 
3489         // Test unvalidated networks
3490         ExpectedBroadcast b = expectConnectivityAction(1);
3491         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
3492         mCellAgent.connect(false);
3493         genericNetworkCallback.expectAvailableCallbacksUnvalidated(mCellAgent);
3494         cellNetworkCallback.expectAvailableCallbacksUnvalidated(mCellAgent);
3495         assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetwork());
3496         b.expectBroadcast();
3497         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
3498 
3499         // This should not trigger spurious onAvailable() callbacks, b/21762680.
3500         mCellAgent.adjustScore(-1);
3501         waitForIdle();
3502         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
3503         assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetwork());
3504 
3505         b = expectConnectivityAction(2);
3506         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3507         mWiFiAgent.connect(false);
3508         genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
3509         wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
3510         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetwork());
3511         b.expectBroadcast();
3512         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
3513 
3514         b = expectConnectivityAction(2);
3515         mWiFiAgent.disconnect();
3516         genericNetworkCallback.expect(CallbackEntry.LOST, mWiFiAgent);
3517         wifiNetworkCallback.expect(CallbackEntry.LOST, mWiFiAgent);
3518         cellNetworkCallback.assertNoCallback();
3519         b.expectBroadcast();
3520         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
3521 
3522         b = expectConnectivityAction(1);
3523         mCellAgent.disconnect();
3524         genericNetworkCallback.expect(CallbackEntry.LOST, mCellAgent);
3525         cellNetworkCallback.expect(CallbackEntry.LOST, mCellAgent);
3526         b.expectBroadcast();
3527         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
3528 
3529         // Test validated networks
3530         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
3531         mCellAgent.connect(true);
3532         genericNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
3533         cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
3534         assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetwork());
3535         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
3536 
3537         // This should not trigger spurious onAvailable() callbacks, b/21762680.
3538         mCellAgent.adjustScore(-1);
3539         waitForIdle();
3540         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
3541         assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetwork());
3542 
3543         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3544         mWiFiAgent.connect(true);
3545         genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
3546         genericNetworkCallback.expectLosing(mCellAgent);
3547         genericNetworkCallback.expectCaps(mWiFiAgent,
3548                 c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
3549         wifiNetworkCallback.expectAvailableThenValidatedCallbacks(mWiFiAgent);
3550         cellNetworkCallback.expectLosing(mCellAgent);
3551         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetwork());
3552         // Cell will disconnect after the lingering period. Before that elapses check that
3553         // there have been no callbacks.
3554         assertNoCallbacks(0 /* timeoutMs */,
3555                 genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
3556 
3557         mWiFiAgent.disconnect();
3558         genericNetworkCallback.expect(LOST, mWiFiAgent);
3559         wifiNetworkCallback.expect(LOST, mWiFiAgent);
3560         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
3561 
3562         mCellAgent.disconnect();
3563         genericNetworkCallback.expect(LOST, mCellAgent);
3564         cellNetworkCallback.expect(LOST, mCellAgent);
3565         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
3566     }
3567 
3568     private void doNetworkCallbacksSanitizationTest(boolean sanitized) throws Exception {
3569         final TestNetworkCallback callback = new TestNetworkCallback();
3570         final TestNetworkCallback defaultCallback = new TestNetworkCallback();
3571         final NetworkRequest wifiRequest = new NetworkRequest.Builder()
3572                 .addTransportType(TRANSPORT_WIFI).build();
3573         mCm.registerNetworkCallback(wifiRequest, callback);
3574         mCm.registerDefaultNetworkCallback(defaultCallback);
3575 
3576         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3577         mWiFiAgent.connect(false);
3578         callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
3579         defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
3580 
3581         final LinkProperties newLp = new LinkProperties();
3582         final Uri capportUrl = Uri.parse("https://capport.example.com/api");
3583         final CaptivePortalData capportData = new CaptivePortalData.Builder()
3584                 .setCaptive(true).build();
3585 
3586         final Uri expectedCapportUrl = sanitized ? null : capportUrl;
3587         newLp.setCaptivePortalApiUrl(capportUrl);
3588         mWiFiAgent.sendLinkProperties(newLp);
3589         callback.expect(LINK_PROPERTIES_CHANGED, mWiFiAgent, cb ->
3590                 Objects.equals(expectedCapportUrl, cb.getLp().getCaptivePortalApiUrl()));
3591         defaultCallback.expect(LINK_PROPERTIES_CHANGED, mWiFiAgent, cb ->
3592                 Objects.equals(expectedCapportUrl, cb.getLp().getCaptivePortalApiUrl()));
3593 
3594         final CaptivePortalData expectedCapportData = sanitized ? null : capportData;
3595         mWiFiAgent.notifyCapportApiDataChanged(capportData);
3596         callback.expect(LINK_PROPERTIES_CHANGED, mWiFiAgent, cb ->
3597                 Objects.equals(expectedCapportData, cb.getLp().getCaptivePortalData()));
3598         defaultCallback.expect(LINK_PROPERTIES_CHANGED, mWiFiAgent, cb ->
3599                 Objects.equals(expectedCapportData, cb.getLp().getCaptivePortalData()));
3600 
3601         final LinkProperties lp = mCm.getLinkProperties(mWiFiAgent.getNetwork());
3602         assertEquals(expectedCapportUrl, lp.getCaptivePortalApiUrl());
3603         assertEquals(expectedCapportData, lp.getCaptivePortalData());
3604     }
3605 
3606     @Test
3607     public void networkCallbacksSanitizationTest_Sanitize() throws Exception {
3608         mServiceContext.setPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
3609                 PERMISSION_DENIED);
3610         mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_DENIED);
3611         doNetworkCallbacksSanitizationTest(true /* sanitized */);
3612     }
3613 
3614     @Test
3615     public void networkCallbacksSanitizationTest_NoSanitize_NetworkStack() throws Exception {
3616         mServiceContext.setPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
3617                 PERMISSION_GRANTED);
3618         mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_DENIED);
3619         doNetworkCallbacksSanitizationTest(false /* sanitized */);
3620     }
3621 
3622     @Test
3623     public void networkCallbacksSanitizationTest_NoSanitize_Settings() throws Exception {
3624         mServiceContext.setPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
3625                 PERMISSION_DENIED);
3626         mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_GRANTED);
3627         doNetworkCallbacksSanitizationTest(false /* sanitized */);
3628     }
3629 
3630     @Test
3631     public void testOwnerUidCannotChange() throws Exception {
3632         final NetworkCapabilities ncTemplate = new NetworkCapabilities();
3633         final int originalOwnerUid = Process.myUid();
3634         ncTemplate.setOwnerUid(originalOwnerUid);
3635 
3636         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, new LinkProperties(), ncTemplate);
3637         mWiFiAgent.connect(false);
3638         waitForIdle();
3639 
3640         // Send ConnectivityService an update to the mWiFiAgent's capabilities that changes
3641         // the owner UID and an unrelated capability.
3642         NetworkCapabilities agentCapabilities = mWiFiAgent.getNetworkCapabilities();
3643         assertEquals(originalOwnerUid, agentCapabilities.getOwnerUid());
3644         agentCapabilities.setOwnerUid(42);
3645         assertFalse(agentCapabilities.hasCapability(NET_CAPABILITY_NOT_CONGESTED));
3646         agentCapabilities.addCapability(NET_CAPABILITY_NOT_CONGESTED);
3647         mWiFiAgent.setNetworkCapabilities(agentCapabilities, true);
3648         waitForIdle();
3649 
3650         // Owner UIDs are not visible without location permission.
3651         setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
3652                 Manifest.permission.ACCESS_FINE_LOCATION);
3653 
3654         // Check that the capability change has been applied but the owner UID is not modified.
3655         NetworkCapabilities nc = mCm.getNetworkCapabilities(mWiFiAgent.getNetwork());
3656         assertEquals(originalOwnerUid, nc.getOwnerUid());
3657         assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_CONGESTED));
3658     }
3659 
3660     @Test
3661     public void testMultipleLingering() throws Exception {
3662         // This test would be flaky with the default 120ms timer: that is short enough that
3663         // lingered networks are torn down before assertions can be run. We don't want to mock the
3664         // lingering timer to keep the WakeupMessage logic realistic: this has already proven useful
3665         // in detecting races. Furthermore, sometimes the test is running while Phenotype is running
3666         // so hot that the test doesn't get the CPU for multiple hundreds of milliseconds, so this
3667         // needs to be suitably long.
3668         mService.mLingerDelayMs = 2_000;
3669 
3670         NetworkRequest request = new NetworkRequest.Builder()
3671                 .clearCapabilities().addCapability(NET_CAPABILITY_NOT_METERED)
3672                 .build();
3673         TestNetworkCallback callback = new TestNetworkCallback();
3674         mCm.registerNetworkCallback(request, callback);
3675 
3676         TestNetworkCallback defaultCallback = new TestNetworkCallback();
3677         mCm.registerDefaultNetworkCallback(defaultCallback);
3678 
3679         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
3680         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3681         mEthernetAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
3682 
3683         mCellAgent.addCapability(NET_CAPABILITY_NOT_METERED);
3684         mWiFiAgent.addCapability(NET_CAPABILITY_NOT_METERED);
3685         mEthernetAgent.addCapability(NET_CAPABILITY_NOT_METERED);
3686 
3687         mCellAgent.connect(true);
3688         callback.expectAvailableThenValidatedCallbacks(mCellAgent);
3689         defaultCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
3690         assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetwork());
3691         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
3692 
3693         mWiFiAgent.connect(true);
3694         // We get AVAILABLE on wifi when wifi connects and satisfies our unmetered request.
3695         // We then get LOSING when wifi validates and cell is outscored.
3696         callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
3697         // TODO: Investigate sending validated before losing.
3698         callback.expectLosing(mCellAgent);
3699         callback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
3700         defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiAgent);
3701         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetwork());
3702         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
3703 
3704         mEthernetAgent.connect(true);
3705         callback.expectAvailableCallbacksUnvalidated(mEthernetAgent);
3706         // TODO: Investigate sending validated before losing.
3707         callback.expectLosing(mWiFiAgent);
3708         callback.expectCaps(mEthernetAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
3709         defaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetAgent);
3710         assertEquals(mEthernetAgent.getNetwork(), mCm.getActiveNetwork());
3711         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
3712 
3713         mEthernetAgent.disconnect();
3714         callback.expect(LOST, mEthernetAgent);
3715         defaultCallback.expect(LOST, mEthernetAgent);
3716         defaultCallback.expectAvailableCallbacksValidated(mWiFiAgent);
3717         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
3718 
3719         for (int i = 0; i < 4; i++) {
3720             TestNetworkAgentWrapper oldNetwork, newNetwork;
3721             if (i % 2 == 0) {
3722                 mWiFiAgent.adjustScore(-15);
3723                 oldNetwork = mWiFiAgent;
3724                 newNetwork = mCellAgent;
3725             } else {
3726                 mWiFiAgent.adjustScore(15);
3727                 oldNetwork = mCellAgent;
3728                 newNetwork = mWiFiAgent;
3729 
3730             }
3731             callback.expectLosing(oldNetwork);
3732             // TODO: should we send an AVAILABLE callback to newNetwork, to indicate that it is no
3733             // longer lingering?
3734             defaultCallback.expectAvailableCallbacksValidated(newNetwork);
3735             assertEquals(newNetwork.getNetwork(), mCm.getActiveNetwork());
3736         }
3737         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetwork());
3738 
3739         // Verify that if a network no longer satisfies a request, we send LOST and not LOSING, even
3740         // if the network is still up.
3741         mWiFiAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
3742         // We expect a notification about the capabilities change, and nothing else.
3743         defaultCallback.expectCaps(mWiFiAgent, c -> !c.hasCapability(NET_CAPABILITY_NOT_METERED));
3744         defaultCallback.assertNoCallback();
3745         callback.expect(LOST, mWiFiAgent);
3746         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
3747 
3748         // Wifi no longer satisfies our listen, which is for an unmetered network.
3749         // But because its score is 55, it's still up (and the default network).
3750         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetwork());
3751 
3752         // Disconnect our test networks.
3753         mWiFiAgent.disconnect();
3754         defaultCallback.expect(LOST, mWiFiAgent);
3755         defaultCallback.expectAvailableCallbacksValidated(mCellAgent);
3756         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
3757         mCellAgent.disconnect();
3758         defaultCallback.expect(LOST, mCellAgent);
3759         waitForIdle();
3760         assertEquals(null, mCm.getActiveNetwork());
3761 
3762         mCm.unregisterNetworkCallback(callback);
3763         waitForIdle();
3764 
3765         // Check that a network is only lingered or torn down if it would not satisfy a request even
3766         // if it validated.
3767         request = new NetworkRequest.Builder().clearCapabilities().build();
3768         callback = new TestNetworkCallback();
3769 
3770         mCm.registerNetworkCallback(request, callback);
3771 
3772         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
3773         mCellAgent.connect(false);   // Score: 10
3774         callback.expectAvailableCallbacksUnvalidated(mCellAgent);
3775         defaultCallback.expectAvailableCallbacksUnvalidated(mCellAgent);
3776         assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetwork());
3777         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
3778 
3779         // Bring up wifi with a score of 20.
3780         // Cell stays up because it would satisfy the default request if it validated.
3781         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3782         mWiFiAgent.connect(false);   // Score: 20
3783         callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
3784         defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
3785         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetwork());
3786         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
3787 
3788         mWiFiAgent.disconnect();
3789         callback.expect(LOST, mWiFiAgent);
3790         defaultCallback.expect(LOST, mWiFiAgent);
3791         defaultCallback.expectAvailableCallbacksUnvalidated(mCellAgent);
3792         assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetwork());
3793         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
3794 
3795         // Bring up wifi, then validate it. Previous versions would immediately tear down cell, but
3796         // it's arguably correct to linger it, since it was the default network before it validated.
3797         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3798         mWiFiAgent.connect(true);
3799         callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
3800         // TODO: Investigate sending validated before losing.
3801         callback.expectLosing(mCellAgent);
3802         callback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
3803         defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiAgent);
3804         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetwork());
3805         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
3806 
3807         mWiFiAgent.disconnect();
3808         callback.expect(LOST, mWiFiAgent);
3809         defaultCallback.expect(LOST, mWiFiAgent);
3810         defaultCallback.expectAvailableCallbacksUnvalidated(mCellAgent);
3811         mCellAgent.disconnect();
3812         callback.expect(LOST, mCellAgent);
3813         defaultCallback.expect(LOST, mCellAgent);
3814         waitForIdle();
3815         assertEquals(null, mCm.getActiveNetwork());
3816 
3817         // If a network is lingering, and we add and remove a request from it, resume lingering.
3818         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
3819         mCellAgent.connect(true);
3820         callback.expectAvailableThenValidatedCallbacks(mCellAgent);
3821         defaultCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
3822         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
3823         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3824         mWiFiAgent.connect(true);
3825         defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiAgent);
3826         callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
3827         // TODO: Investigate sending validated before losing.
3828         callback.expectLosing(mCellAgent);
3829         callback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
3830         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
3831 
3832         NetworkRequest cellRequest = new NetworkRequest.Builder()
3833                 .addTransportType(TRANSPORT_CELLULAR).build();
3834         NetworkCallback noopCallback = new NetworkCallback();
3835         mCm.requestNetwork(cellRequest, noopCallback);
3836         // TODO: should this cause an AVAILABLE callback, to indicate that the network is no longer
3837         // lingering?
3838         mCm.unregisterNetworkCallback(noopCallback);
3839         callback.expectLosing(mCellAgent);
3840 
3841         // Similar to the above: lingering can start even after the lingered request is removed.
3842         // Disconnect wifi and switch to cell.
3843         mWiFiAgent.disconnect();
3844         callback.expect(LOST, mWiFiAgent);
3845         defaultCallback.expect(LOST, mWiFiAgent);
3846         defaultCallback.expectAvailableCallbacksValidated(mCellAgent);
3847         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
3848 
3849         // Cell is now the default network. Pin it with a cell-specific request.
3850         noopCallback = new NetworkCallback();  // Can't reuse NetworkCallbacks. http://b/20701525
3851         mCm.requestNetwork(cellRequest, noopCallback);
3852 
3853         // Now connect wifi, and expect it to become the default network.
3854         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3855         mWiFiAgent.connect(true);
3856         callback.expectAvailableThenValidatedCallbacks(mWiFiAgent);
3857         defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiAgent);
3858         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
3859         // The default request is lingering on cell, but nothing happens to cell, and we send no
3860         // callbacks for it, because it's kept up by cellRequest.
3861         callback.assertNoCallback();
3862         // Now unregister cellRequest and expect cell to start lingering.
3863         mCm.unregisterNetworkCallback(noopCallback);
3864         callback.expectLosing(mCellAgent);
3865 
3866         // Let linger run its course.
3867         callback.assertNoCallback(0 /* timeoutMs */);
3868         final int lingerTimeoutMs = mService.mLingerDelayMs + mService.mLingerDelayMs / 4;
3869         callback.expect(LOST, mCellAgent, lingerTimeoutMs);
3870 
3871         // Register a TRACK_DEFAULT request and check that it does not affect lingering.
3872         TestNetworkCallback trackDefaultCallback = new TestNetworkCallback();
3873         mCm.registerDefaultNetworkCallback(trackDefaultCallback);
3874         trackDefaultCallback.expectAvailableCallbacksValidated(mWiFiAgent);
3875         mEthernetAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
3876         mEthernetAgent.connect(true);
3877         callback.expectAvailableCallbacksUnvalidated(mEthernetAgent);
3878         callback.expectLosing(mWiFiAgent);
3879         callback.expectCaps(mEthernetAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
3880         trackDefaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetAgent);
3881         defaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetAgent);
3882         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
3883 
3884         // Let linger run its course.
3885         callback.expect(LOST, mWiFiAgent, lingerTimeoutMs);
3886 
3887         // Clean up.
3888         mEthernetAgent.disconnect();
3889         callback.expect(LOST, mEthernetAgent);
3890         defaultCallback.expect(LOST, mEthernetAgent);
3891         trackDefaultCallback.expect(LOST, mEthernetAgent);
3892 
3893         mCm.unregisterNetworkCallback(callback);
3894         mCm.unregisterNetworkCallback(defaultCallback);
3895         mCm.unregisterNetworkCallback(trackDefaultCallback);
3896     }
3897 
3898     private void grantUsingBackgroundNetworksPermissionForUid(final int uid) throws Exception {
3899         grantUsingBackgroundNetworksPermissionForUid(uid, mContext.getPackageName());
3900     }
3901 
3902     private void grantUsingBackgroundNetworksPermissionForUid(
3903             final int uid, final String packageName) throws Exception {
3904         doReturn(buildPackageInfo(true /* hasSystemPermission */, uid)).when(mPackageManager)
3905                 .getPackageInfo(eq(packageName), eq(GET_PERMISSIONS));
3906 
3907         // Send a broadcast indicating a package was installed.
3908         final Intent addedIntent = new Intent(ACTION_PACKAGE_ADDED);
3909         addedIntent.putExtra(Intent.EXTRA_UID, uid);
3910         addedIntent.setData(Uri.parse("package:" + packageName));
3911         processBroadcast(addedIntent);
3912     }
3913 
3914     @Test
3915     public void testNetworkGoesIntoBackgroundAfterLinger() throws Exception {
3916         setAlwaysOnNetworks(true);
3917         grantUsingBackgroundNetworksPermissionForUid(Binder.getCallingUid());
3918         NetworkRequest request = new NetworkRequest.Builder()
3919                 .clearCapabilities()
3920                 .build();
3921         TestNetworkCallback callback = new TestNetworkCallback();
3922         mCm.registerNetworkCallback(request, callback);
3923 
3924         TestNetworkCallback defaultCallback = new TestNetworkCallback();
3925         mCm.registerDefaultNetworkCallback(defaultCallback);
3926 
3927         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
3928         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3929 
3930         mCellAgent.connect(true);
3931         callback.expectAvailableThenValidatedCallbacks(mCellAgent);
3932         defaultCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
3933 
3934         // Wifi comes up and cell lingers.
3935         mWiFiAgent.connect(true);
3936         defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiAgent);
3937         callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
3938         callback.expectLosing(mCellAgent);
3939         callback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
3940 
3941         // File a request for cellular, then release it.
3942         NetworkRequest cellRequest = new NetworkRequest.Builder()
3943                 .addTransportType(TRANSPORT_CELLULAR).build();
3944         NetworkCallback noopCallback = new NetworkCallback();
3945         mCm.requestNetwork(cellRequest, noopCallback);
3946         mCm.unregisterNetworkCallback(noopCallback);
3947         callback.expectLosing(mCellAgent);
3948 
3949         // Let linger run its course.
3950         callback.assertNoCallback();
3951         final int lingerTimeoutMs = TEST_LINGER_DELAY_MS + TEST_LINGER_DELAY_MS / 4;
3952         callback.expectCaps(mCellAgent, lingerTimeoutMs,
3953                 c -> !c.hasCapability(NET_CAPABILITY_FOREGROUND));
3954 
3955         // Clean up.
3956         mCm.unregisterNetworkCallback(defaultCallback);
3957         mCm.unregisterNetworkCallback(callback);
3958     }
3959 
3960     /** Expects the specified notification and returns the notification ID. */
3961     private int expectNotification(TestNetworkAgentWrapper agent, NotificationType type) {
3962         verify(mNotificationManager, timeout(TIMEOUT_MS)).notify(
3963                 eq(NetworkNotificationManager.tagFor(agent.getNetwork().netId)),
3964                 eq(type.eventId), any());
3965         return type.eventId;
3966     }
3967 
3968     private void expectNoNotification(@NonNull final TestNetworkAgentWrapper agent) {
3969         verify(mNotificationManager, never()).notifyAsUser(anyString(), anyInt(), any(), any());
3970     }
3971 
3972     /**
3973      * Expects the specified notification happens when the unvalidated prompt message arrives
3974      *
3975      * @return the notification ID.
3976      **/
3977     private int expectUnvalidationCheckWillNotify(TestNetworkAgentWrapper agent,
3978             NotificationType type) {
3979         mService.scheduleEvaluationTimeout(agent.getNetwork(), 0 /* delayMs */);
3980         waitForIdle();
3981         return expectNotification(agent, type);
3982     }
3983 
3984     /**
3985      * Expects that the notification for the specified network is cleared.
3986      *
3987      * This generally happens when the network disconnects or when the newtwork validates. During
3988      * normal usage the notification is also cleared by the system when the notification is tapped.
3989      */
3990     private void expectClearNotification(TestNetworkAgentWrapper agent, NotificationType type) {
3991         verify(mNotificationManager, timeout(TIMEOUT_MS)).cancel(
3992                 eq(NetworkNotificationManager.tagFor(agent.getNetwork().netId)), eq(type.eventId));
3993     }
3994 
3995     /**
3996      * Expects that no notification happens when the unvalidated prompt message arrives
3997      *
3998      * @return the notification ID.
3999      **/
4000     private void expectUnvalidationCheckWillNotNotify(TestNetworkAgentWrapper agent) {
4001         mService.scheduleEvaluationTimeout(agent.getNetwork(), 0 /*delayMs */);
4002         waitForIdle();
4003         expectNoNotification(agent);
4004     }
4005 
4006     private void expectDisconnectAndClearNotifications(TestNetworkCallback callback,
4007             TestNetworkAgentWrapper agent, NotificationType type) {
4008         callback.expect(LOST, agent);
4009         expectClearNotification(agent, type);
4010     }
4011 
4012     private NativeNetworkConfig nativeNetworkConfigPhysical(int netId, int permission) {
4013         return new NativeNetworkConfig(netId, NativeNetworkType.PHYSICAL, permission,
4014                 /*secure=*/ false, VpnManager.TYPE_VPN_NONE, /*excludeLocalRoutes=*/ false);
4015     }
4016 
4017     private NativeNetworkConfig nativeNetworkConfigVpn(int netId, boolean secure, int vpnType) {
4018         return new NativeNetworkConfig(netId, NativeNetworkType.VIRTUAL, INetd.PERMISSION_NONE,
4019                 secure, vpnType, /*excludeLocalRoutes=*/ false);
4020     }
4021 
4022     @Test
4023     public void testNetworkAgentCallbacks() throws Exception {
4024         // Keeps track of the order of events that happen in this test.
4025         final LinkedBlockingQueue<String> eventOrder = new LinkedBlockingQueue<>();
4026 
4027         final NetworkRequest request = new NetworkRequest.Builder()
4028                 .addTransportType(TRANSPORT_WIFI).build();
4029         final TestNetworkCallback callback = new TestNetworkCallback();
4030 
4031         // Expectations for state when various callbacks fire. These expectations run on the handler
4032         // thread and not on the test thread because they need to prevent the handler thread from
4033         // advancing while they examine state.
4034 
4035         // 1. When onCreated fires, netd has been told to create the network.
4036         final Consumer<NetworkAgent> onNetworkCreated = (agent) -> {
4037             eventOrder.offer("onNetworkCreated");
4038             try {
4039                 verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
4040                         agent.getNetwork().getNetId(), INetd.PERMISSION_NONE));
4041             } catch (RemoteException impossible) {
4042                 fail();
4043             }
4044         };
4045 
4046         // 2. onNetworkUnwanted isn't precisely ordered with respect to any particular events. Just
4047         //    check that it is fired at some point after disconnect.
4048         final Consumer<NetworkAgent> onNetworkUnwanted = (agent) -> {
4049             eventOrder.offer("onNetworkUnwanted");
4050         };
4051 
4052         // 3. While the teardown timer is running, connectivity APIs report the network is gone, but
4053         //    netd has not yet been told to destroy it.
4054         final Consumer<Network> duringTeardown = (network) -> {
4055             eventOrder.offer("timePasses");
4056             assertNull(mCm.getLinkProperties(network));
4057             try {
4058                 verify(mMockNetd, never()).networkDestroy(network.getNetId());
4059             } catch (RemoteException impossible) {
4060                 fail();
4061             }
4062         };
4063 
4064         // 4. After onNetworkDisconnected is called, connectivity APIs report the network is gone,
4065         // and netd has been told to destroy it.
4066         final Consumer<NetworkAgent> onNetworkDisconnected = (agent) -> {
4067             eventOrder.offer("onNetworkDisconnected");
4068             assertNull(mCm.getLinkProperties(agent.getNetwork()));
4069             try {
4070                 verify(mMockNetd).networkDestroy(agent.getNetwork().getNetId());
4071             } catch (RemoteException impossible) {
4072                 fail();
4073             }
4074         };
4075 
4076         final NetworkAgentWrapper.Callbacks callbacks = new NetworkAgentWrapper.Callbacks(
4077                 onNetworkCreated, onNetworkUnwanted, onNetworkDisconnected);
4078 
4079         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, callbacks);
4080 
4081         if (mService.shouldCreateNetworksImmediately(mWiFiAgent.getNetworkCapabilities())) {
4082             assertEquals("onNetworkCreated", eventOrder.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
4083         } else {
4084             assertNull(eventOrder.poll());
4085         }
4086 
4087         // Connect a network, and file a request for it after it has come up, to ensure the nascent
4088         // timer is cleared and the test does not have to wait for it. Filing the request after the
4089         // network has come up is necessary because ConnectivityService does not appear to clear the
4090         // nascent timer if the first request satisfied by the network was filed before the network
4091         // connected.
4092         // TODO: fix this bug, file the request before connecting, and remove the waitForIdle.
4093         mWiFiAgent.connectWithoutInternet();
4094         if (!mService.shouldCreateNetworksImmediately(mWiFiAgent.getNetworkCapabilities())) {
4095             assertEquals("onNetworkCreated", eventOrder.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
4096         } else {
4097             waitForIdle();
4098             assertNull(eventOrder.poll());
4099         }
4100         mCm.requestNetwork(request, callback);
4101         callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
4102 
4103         // Set teardown delay and make sure CS has processed it.
4104         mWiFiAgent.getNetworkAgent().setTeardownDelayMillis(300);
4105         waitForIdle();
4106 
4107         // Post the duringTeardown lambda to the handler so it fires while teardown is in progress.
4108         // The delay must be long enough it will run after the unregisterNetworkCallback has torn
4109         // down the network and started the teardown timer, and short enough that the lambda is
4110         // scheduled to run before the teardown timer.
4111         final Handler h = new Handler(mCsHandlerThread.getLooper());
4112         h.postDelayed(() -> duringTeardown.accept(mWiFiAgent.getNetwork()), 150);
4113 
4114         // Disconnect the network and check that events happened in the right order.
4115         mCm.unregisterNetworkCallback(callback);
4116         assertEquals("onNetworkUnwanted", eventOrder.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
4117         assertEquals("timePasses", eventOrder.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
4118         assertEquals("onNetworkDisconnected", eventOrder.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
4119 
4120         mCm.unregisterNetworkCallback(callback);
4121     }
4122 
4123     @Test
4124     public void testExplicitlySelected() throws Exception {
4125         final NetworkRequest request = new NetworkRequest.Builder()
4126                 .clearCapabilities().addCapability(NET_CAPABILITY_INTERNET)
4127                 .build();
4128         final TestNetworkCallback callback = new TestNetworkCallback();
4129         mCm.registerNetworkCallback(request, callback);
4130 
4131         // Bring up validated cell
4132         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
4133         mCellAgent.connect(true);
4134         callback.expectAvailableThenValidatedCallbacks(mCellAgent);
4135 
4136         // Bring up unvalidated wifi with explicitlySelected=true.
4137         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4138         mWiFiAgent.explicitlySelected(true, false);
4139         mWiFiAgent.connect(false);
4140         callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
4141 
4142         // Cell remains the default.
4143         assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetwork());
4144 
4145         // Expect a high-priority NO_INTERNET notification.
4146         expectUnvalidationCheckWillNotify(mWiFiAgent, NotificationType.NO_INTERNET);
4147 
4148         // Lower WiFi's score to lower than cell, and check that it doesn't disconnect because
4149         // it's explicitly selected.
4150         mWiFiAgent.adjustScore(-40);
4151         mWiFiAgent.adjustScore(40);
4152         callback.assertNoCallback();
4153 
4154         // If the user chooses yes on the "No Internet access, stay connected?" dialog, we switch to
4155         // wifi even though it's unvalidated.
4156         mCm.setAcceptUnvalidated(mWiFiAgent.getNetwork(), true, false);
4157         callback.expectLosing(mCellAgent);
4158         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetwork());
4159 
4160         // Disconnect wifi, and then reconnect, again with explicitlySelected=true.
4161         mWiFiAgent.disconnect();
4162         expectDisconnectAndClearNotifications(callback, mWiFiAgent, NotificationType.NO_INTERNET);
4163 
4164         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4165         mWiFiAgent.explicitlySelected(true, false);
4166         mWiFiAgent.connect(false);
4167         callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
4168 
4169         // Expect a high-priority NO_INTERNET notification.
4170         expectUnvalidationCheckWillNotify(mWiFiAgent, NotificationType.NO_INTERNET);
4171 
4172         // If the user chooses no on the "No Internet access, stay connected?" dialog, we ask the
4173         // network to disconnect.
4174         mCm.setAcceptUnvalidated(mWiFiAgent.getNetwork(), false, false);
4175         expectDisconnectAndClearNotifications(callback, mWiFiAgent, NotificationType.NO_INTERNET);
4176         reset(mNotificationManager);
4177 
4178         // Reconnect, again with explicitlySelected=true, but this time validate.
4179         // Expect no notifications.
4180         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4181         mWiFiAgent.explicitlySelected(true, false);
4182         mWiFiAgent.connect(true);
4183         callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
4184         callback.expectLosing(mCellAgent);
4185         callback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
4186         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetwork());
4187         expectUnvalidationCheckWillNotNotify(mWiFiAgent);
4188 
4189         // Now request cell so it doesn't disconnect during the test
4190         final NetworkRequest cellRequest = new NetworkRequest.Builder()
4191                 .clearCapabilities().addTransportType(TRANSPORT_CELLULAR).build();
4192         final TestNetworkCallback cellCallback = new TestNetworkCallback();
4193         mCm.requestNetwork(cellRequest, cellCallback);
4194 
4195         mEthernetAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
4196         mEthernetAgent.connect(true);
4197         callback.expectAvailableCallbacksUnvalidated(mEthernetAgent);
4198         callback.expectLosing(mWiFiAgent);
4199         callback.expectCaps(mEthernetAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
4200         assertEquals(mEthernetAgent.getNetwork(), mCm.getActiveNetwork());
4201         callback.assertNoCallback();
4202 
4203         // Disconnect wifi, and then reconnect as if the user had selected "yes, don't ask again"
4204         // (i.e., with explicitlySelected=true and acceptUnvalidated=true). Expect to switch to
4205         // wifi immediately.
4206         mWiFiAgent.disconnect();
4207         callback.expect(LOST, mWiFiAgent);
4208         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4209         mWiFiAgent.explicitlySelected(true, true);
4210         mWiFiAgent.connect(false);
4211         callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
4212         callback.expectLosing(mEthernetAgent);
4213         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetwork());
4214         mEthernetAgent.disconnect();
4215         callback.expect(LOST, mEthernetAgent);
4216         expectUnvalidationCheckWillNotNotify(mWiFiAgent);
4217 
4218         // Disconnect and reconnect with explicitlySelected=false and acceptUnvalidated=true.
4219         // Check that the network is not scored specially and that the device prefers cell data.
4220         mWiFiAgent.disconnect();
4221         callback.expect(LOST, mWiFiAgent);
4222 
4223         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4224         mWiFiAgent.explicitlySelected(false, true);
4225         mWiFiAgent.connect(false);
4226         callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
4227         assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetwork());
4228         expectUnvalidationCheckWillNotNotify(mWiFiAgent);
4229 
4230         // Clean up.
4231         mWiFiAgent.disconnect();
4232         mCellAgent.disconnect();
4233 
4234         callback.expect(LOST, mWiFiAgent);
4235         callback.expect(LOST, mCellAgent);
4236         mCm.unregisterNetworkCallback(cellCallback);
4237     }
4238 
4239     private void doTestFirstEvaluation(
4240             @NonNull final Consumer<TestNetworkAgentWrapper> doConnect,
4241             final boolean waitForSecondCaps,
4242             final boolean evaluatedByValidation)
4243             throws Exception {
4244         final NetworkRequest request = new NetworkRequest.Builder()
4245                 .addTransportType(TRANSPORT_WIFI)
4246                 .build();
4247         TestNetworkCallback callback = new TestNetworkCallback();
4248         mCm.registerNetworkCallback(request, callback);
4249 
4250         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4251         doConnect.accept(mWiFiAgent);
4252         // Expect the available callbacks, but don't require specific values for their arguments
4253         // since this method doesn't know how the network was connected.
4254         callback.expect(AVAILABLE, mWiFiAgent);
4255         callback.expect(NETWORK_CAPS_UPDATED, mWiFiAgent);
4256         callback.expect(LINK_PROPERTIES_CHANGED, mWiFiAgent);
4257         callback.expect(BLOCKED_STATUS, mWiFiAgent);
4258         if (waitForSecondCaps) {
4259             // This is necessary because of b/245893397, the same bug that happens where we use
4260             // expectAvailableDoubleValidatedCallbacks.
4261             callback.expect(NETWORK_CAPS_UPDATED, mWiFiAgent);
4262         }
4263         final NetworkAgentInfo nai =
4264                 mService.getNetworkAgentInfoForNetwork(mWiFiAgent.getNetwork());
4265         final long firstEvaluation = nai.getFirstEvaluationConcludedTime();
4266         if (evaluatedByValidation) {
4267             assertNotEquals(0L, firstEvaluation);
4268         } else {
4269             assertEquals(0L, firstEvaluation);
4270         }
4271         mService.scheduleEvaluationTimeout(mWiFiAgent.getNetwork(), 0L /* timeout */);
4272         waitForIdle();
4273         if (evaluatedByValidation) {
4274             assertEquals(firstEvaluation, nai.getFirstEvaluationConcludedTime());
4275         } else {
4276             assertNotEquals(0L, nai.getFirstEvaluationConcludedTime());
4277         }
4278         mWiFiAgent.disconnect();
4279         callback.expect(LOST, mWiFiAgent);
4280 
4281         mCm.unregisterNetworkCallback(callback);
4282     }
4283 
4284     @Test
4285     public void testEverEvaluated() throws Exception {
4286         doTestFirstEvaluation(naw -> naw.connect(true /* validated */),
4287                 true /* waitForSecondCaps */, true /* immediatelyEvaluated */);
4288         doTestFirstEvaluation(naw -> naw.connectWithPartialConnectivity(),
4289                 true /* waitForSecondCaps */, true /* immediatelyEvaluated */);
4290         doTestFirstEvaluation(naw -> naw.connectWithCaptivePortal(TEST_REDIRECT_URL, false),
4291                 true /* waitForSecondCaps */, true /* immediatelyEvaluated */);
4292         doTestFirstEvaluation(naw -> naw.connect(false /* validated */),
4293                 false /* waitForSecondCaps */, false /* immediatelyEvaluated */);
4294     }
4295 
4296     private void tryNetworkFactoryRequests(int capability) throws Exception {
4297         // Verify NOT_RESTRICTED is set appropriately
4298         final NetworkCapabilities nc = new NetworkRequest.Builder().addCapability(capability)
4299                 .build().networkCapabilities;
4300         if (capability == NET_CAPABILITY_CBS || capability == NET_CAPABILITY_DUN
4301                 || capability == NET_CAPABILITY_EIMS || capability == NET_CAPABILITY_FOTA
4302                 || capability == NET_CAPABILITY_IA || capability == NET_CAPABILITY_IMS
4303                 || capability == NET_CAPABILITY_RCS || capability == NET_CAPABILITY_XCAP
4304                 || capability == NET_CAPABILITY_VSIM || capability == NET_CAPABILITY_BIP
4305                 || capability == NET_CAPABILITY_ENTERPRISE || capability == NET_CAPABILITY_MMTEL) {
4306             assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
4307         } else {
4308             assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
4309         }
4310 
4311         NetworkCapabilities filter = new NetworkCapabilities();
4312         filter.addTransportType(TRANSPORT_CELLULAR);
4313         filter.addCapability(capability);
4314         // Add NOT_VCN_MANAGED capability into filter unconditionally since some requests will add
4315         // NOT_VCN_MANAGED automatically but not for NetworkCapabilities,
4316         // see {@code NetworkCapabilities#deduceNotVcnManagedCapability} for more details.
4317         filter.addCapability(NET_CAPABILITY_NOT_VCN_MANAGED);
4318         final HandlerThread handlerThread = new HandlerThread("testNetworkFactoryRequests");
4319         handlerThread.start();
4320         final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
4321                 mServiceContext, "testFactory", filter, mCsHandlerThread);
4322         testFactory.setScoreFilter(45);
4323         testFactory.register();
4324 
4325         final NetworkCallback networkCallback;
4326         if (capability != NET_CAPABILITY_INTERNET) {
4327             // If the capability passed in argument is part of the default request, then the
4328             // factory will see the default request. Otherwise the filter will prevent the
4329             // factory from seeing it. In that case, add a request so it can be tested.
4330             assertFalse(testFactory.getMyStartRequested());
4331             NetworkRequest request = new NetworkRequest.Builder().addCapability(capability).build();
4332             networkCallback = new NetworkCallback();
4333             mCm.requestNetwork(request, networkCallback);
4334         } else {
4335             networkCallback = null;
4336         }
4337         testFactory.expectRequestAdd();
4338         testFactory.assertRequestCountEquals(1);
4339         assertTrue(testFactory.getMyStartRequested());
4340 
4341         // Now bring in a higher scored network.
4342         TestNetworkAgentWrapper testAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
4343         // When testAgent connects, because of its score (50 legacy int / cell transport)
4344         // it will beat or equal the testFactory's offer, so the request will be removed.
4345         // Note the agent as validated only if the capability is INTERNET, as it's the only case
4346         // where it makes sense.
4347         testAgent.connect(NET_CAPABILITY_INTERNET == capability /* validated */);
4348         testAgent.addCapability(capability);
4349         testFactory.expectRequestRemove();
4350         testFactory.assertRequestCountEquals(0);
4351         assertFalse(testFactory.getMyStartRequested());
4352 
4353         // Add a request and make sure it's not sent to the factory, because the agent
4354         // is satisfying it better.
4355         final NetworkCallback cb = new ConnectivityManager.NetworkCallback();
4356         mCm.requestNetwork(new NetworkRequest.Builder().addCapability(capability).build(), cb);
4357         expectNoRequestChanged(testFactory);
4358         testFactory.assertRequestCountEquals(0);
4359         assertFalse(testFactory.getMyStartRequested());
4360 
4361         // If using legacy scores, make the test agent weak enough to have the exact same score as
4362         // the factory (50 for cell - 5 adjustment). Make sure the factory doesn't see the request.
4363         // If not using legacy score, this is a no-op and the "same score removes request" behavior
4364         // has already been tested above.
4365         testAgent.adjustScore(-5);
4366         expectNoRequestChanged(testFactory);
4367         assertFalse(testFactory.getMyStartRequested());
4368 
4369         // Make the test agent weak enough that the factory will see the two requests (the one that
4370         // was just sent, and either the default one or the one sent at the top of this test if
4371         // the default won't be seen).
4372         testAgent.setScore(new NetworkScore.Builder().setLegacyInt(2).setExiting(true).build());
4373         testFactory.expectRequestAdds(2);
4374         testFactory.assertRequestCountEquals(2);
4375         assertTrue(testFactory.getMyStartRequested());
4376 
4377         // Now unregister and make sure the request is removed.
4378         mCm.unregisterNetworkCallback(cb);
4379         testFactory.expectRequestRemove();
4380 
4381         // Bring in a bunch of requests.
4382         assertEquals(1, testFactory.getMyRequestCount());
4383         ConnectivityManager.NetworkCallback[] networkCallbacks =
4384                 new ConnectivityManager.NetworkCallback[10];
4385         for (int i = 0; i< networkCallbacks.length; i++) {
4386             networkCallbacks[i] = new ConnectivityManager.NetworkCallback();
4387             NetworkRequest.Builder builder = new NetworkRequest.Builder();
4388             builder.addCapability(capability);
4389             mCm.requestNetwork(builder.build(), networkCallbacks[i]);
4390         }
4391         testFactory.expectRequestAdds(10);
4392         testFactory.assertRequestCountEquals(11); // +1 for the default/test specific request
4393         assertTrue(testFactory.getMyStartRequested());
4394 
4395         // Remove the requests.
4396         for (int i = 0; i < networkCallbacks.length; i++) {
4397             mCm.unregisterNetworkCallback(networkCallbacks[i]);
4398         }
4399         testFactory.expectRequestRemoves(10);
4400         testFactory.assertRequestCountEquals(1);
4401         assertTrue(testFactory.getMyStartRequested());
4402 
4403         // Adjust the agent score up again. Expect the request to be withdrawn.
4404         testAgent.setScore(new NetworkScore.Builder().setLegacyInt(50).build());
4405         testFactory.expectRequestRemove();
4406         testFactory.assertRequestCountEquals(0);
4407         assertFalse(testFactory.getMyStartRequested());
4408 
4409         // Drop the higher scored network.
4410         testAgent.disconnect();
4411         testFactory.expectRequestAdd();
4412         testFactory.assertRequestCountEquals(1);
4413         assertEquals(1, testFactory.getMyRequestCount());
4414         assertTrue(testFactory.getMyStartRequested());
4415 
4416         testFactory.terminate();
4417         testFactory.assertNoRequestChanged();
4418         if (networkCallback != null) mCm.unregisterNetworkCallback(networkCallback);
4419 
4420         handlerThread.quitSafely();
4421         handlerThread.join();
4422     }
4423 
4424     @Test
4425     public void testNetworkFactoryRequests() throws Exception {
4426         tryNetworkFactoryRequests(NET_CAPABILITY_MMS);
4427         tryNetworkFactoryRequests(NET_CAPABILITY_SUPL);
4428         tryNetworkFactoryRequests(NET_CAPABILITY_DUN);
4429         tryNetworkFactoryRequests(NET_CAPABILITY_FOTA);
4430         tryNetworkFactoryRequests(NET_CAPABILITY_IMS);
4431         tryNetworkFactoryRequests(NET_CAPABILITY_CBS);
4432         tryNetworkFactoryRequests(NET_CAPABILITY_WIFI_P2P);
4433         tryNetworkFactoryRequests(NET_CAPABILITY_IA);
4434         tryNetworkFactoryRequests(NET_CAPABILITY_RCS);
4435         tryNetworkFactoryRequests(NET_CAPABILITY_MMTEL);
4436         tryNetworkFactoryRequests(NET_CAPABILITY_XCAP);
4437         tryNetworkFactoryRequests(NET_CAPABILITY_ENTERPRISE);
4438         tryNetworkFactoryRequests(NET_CAPABILITY_EIMS);
4439         tryNetworkFactoryRequests(NET_CAPABILITY_NOT_METERED);
4440         tryNetworkFactoryRequests(NET_CAPABILITY_INTERNET);
4441         tryNetworkFactoryRequests(NET_CAPABILITY_TRUSTED);
4442         tryNetworkFactoryRequests(NET_CAPABILITY_NOT_VPN);
4443         tryNetworkFactoryRequests(NET_CAPABILITY_VSIM);
4444         tryNetworkFactoryRequests(NET_CAPABILITY_BIP);
4445         // Skipping VALIDATED and CAPTIVE_PORTAL as they're disallowed.
4446     }
4447 
4448     @Test
4449     public void testRegisterIgnoringScore() throws Exception {
4450         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4451         mWiFiAgent.setScore(new NetworkScore.Builder().setLegacyInt(90).build());
4452         mWiFiAgent.connect(true /* validated */);
4453 
4454         // Make sure the factory sees the default network
4455         final NetworkCapabilities filter = new NetworkCapabilities();
4456         filter.addTransportType(TRANSPORT_CELLULAR);
4457         filter.addCapability(NET_CAPABILITY_INTERNET);
4458         filter.addCapability(NET_CAPABILITY_NOT_VCN_MANAGED);
4459         final HandlerThread handlerThread = new HandlerThread("testNetworkFactoryRequests");
4460         handlerThread.start();
4461         final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
4462                 mServiceContext, "testFactory", filter, mCsHandlerThread);
4463         testFactory.register();
4464 
4465         final MockNetworkFactory testFactoryAll = new MockNetworkFactory(handlerThread.getLooper(),
4466                 mServiceContext, "testFactoryAll", filter, mCsHandlerThread);
4467         testFactoryAll.registerIgnoringScore();
4468 
4469         // The regular test factory should not see the request, because WiFi is stronger than cell.
4470         expectNoRequestChanged(testFactory);
4471         // With ignoringScore though the request is seen.
4472         testFactoryAll.expectRequestAdd();
4473 
4474         // The legacy int will be ignored anyway, set the only other knob to true
4475         mWiFiAgent.setScore(new NetworkScore.Builder().setLegacyInt(110)
4476                 .setTransportPrimary(true).build());
4477 
4478         expectNoRequestChanged(testFactory); // still not seeing the request
4479         expectNoRequestChanged(testFactoryAll); // still seeing the request
4480 
4481         mWiFiAgent.disconnect();
4482         handlerThread.quitSafely();
4483         handlerThread.join();
4484     }
4485 
4486     @Test
4487     public void testNetworkFactoryUnregister() throws Exception {
4488         // Make sure the factory sees the default network
4489         final NetworkCapabilities filter = new NetworkCapabilities();
4490         filter.addCapability(NET_CAPABILITY_INTERNET);
4491         filter.addCapability(NET_CAPABILITY_NOT_VCN_MANAGED);
4492 
4493         final HandlerThread handlerThread = new HandlerThread("testNetworkFactoryRequests");
4494         handlerThread.start();
4495 
4496         // Checks that calling setScoreFilter on a NetworkFactory immediately before closing it
4497         // does not crash.
4498         for (int i = 0; i < 100; i++) {
4499             final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
4500                     mServiceContext, "testFactory", filter, mCsHandlerThread);
4501             // Register the factory and don't be surprised when the default request arrives.
4502             testFactory.register();
4503             testFactory.expectRequestAdd();
4504 
4505             testFactory.setScoreFilter(42);
4506             testFactory.terminate();
4507             testFactory.assertNoRequestChanged();
4508 
4509             if (i % 2 == 0) {
4510                 try {
4511                     testFactory.register();
4512                     fail("Re-registering terminated NetworkFactory should throw");
4513                 } catch (IllegalStateException expected) {
4514                 }
4515             }
4516         }
4517         handlerThread.quitSafely();
4518         handlerThread.join();
4519     }
4520 
4521     @Test
4522     public void testNoMutableNetworkRequests() throws Exception {
4523         final PendingIntent pendingIntent = PendingIntent.getBroadcast(
4524                 mContext, 0 /* requestCode */, new Intent("a"), FLAG_IMMUTABLE);
4525         final NetworkRequest request1 = new NetworkRequest.Builder()
4526                 .addCapability(NET_CAPABILITY_VALIDATED)
4527                 .build();
4528         final NetworkRequest request2 = new NetworkRequest.Builder()
4529                 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL)
4530                 .build();
4531 
4532         final Class<IllegalArgumentException> expected = IllegalArgumentException.class;
4533         assertThrows(expected, () -> mCm.requestNetwork(request1, new NetworkCallback()));
4534         assertThrows(expected, () -> mCm.requestNetwork(request1, pendingIntent));
4535         assertThrows(expected, () -> mCm.requestNetwork(request2, new NetworkCallback()));
4536         assertThrows(expected, () -> mCm.requestNetwork(request2, pendingIntent));
4537     }
4538 
4539     @Test
4540     public void testNoAllowedUidsInNetworkRequests() throws Exception {
4541         final PendingIntent pendingIntent = PendingIntent.getBroadcast(
4542                 mContext, 0 /* requestCode */, new Intent("a"), FLAG_IMMUTABLE);
4543         final NetworkRequest r = new NetworkRequest.Builder().build();
4544         final ArraySet<Integer> allowedUids = new ArraySet<>();
4545         allowedUids.add(6);
4546         allowedUids.add(9);
4547         r.networkCapabilities.setAllowedUids(allowedUids);
4548 
4549         final Handler handler = new Handler(ConnectivityThread.getInstanceLooper());
4550         final NetworkCallback cb = new NetworkCallback();
4551 
4552         final Class<IllegalArgumentException> expected = IllegalArgumentException.class;
4553         assertThrows(expected, () -> mCm.requestNetwork(r, cb));
4554         assertThrows(expected, () -> mCm.requestNetwork(r, pendingIntent));
4555         assertThrows(expected, () -> mCm.registerNetworkCallback(r, cb));
4556         assertThrows(expected, () -> mCm.registerNetworkCallback(r, cb, handler));
4557         assertThrows(expected, () -> mCm.registerNetworkCallback(r, pendingIntent));
4558         assertThrows(expected, () -> mCm.registerBestMatchingNetworkCallback(r, cb, handler));
4559 
4560         // Make sure that resetting the access UIDs to the empty set will allow calling
4561         // requestNetwork and registerNetworkCallback.
4562         r.networkCapabilities.setAllowedUids(Collections.emptySet());
4563         mCm.requestNetwork(r, cb);
4564         mCm.unregisterNetworkCallback(cb);
4565         mCm.registerNetworkCallback(r, cb);
4566         mCm.unregisterNetworkCallback(cb);
4567     }
4568 
4569     @Test
4570     public void testMMSonWiFi() throws Exception {
4571         // Test bringing up cellular without MMS NetworkRequest gets reaped
4572         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
4573         mCellAgent.addCapability(NET_CAPABILITY_MMS);
4574         mCellAgent.connectWithoutInternet();
4575         mCellAgent.expectDisconnected();
4576         waitForIdle();
4577         assertEmpty(mCm.getAllNetworks());
4578         verifyNoNetwork();
4579 
4580         // Test bringing up validated WiFi.
4581         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4582         final ExpectedBroadcast b = expectConnectivityAction(TYPE_WIFI, DetailedState.CONNECTED);
4583         mWiFiAgent.connect(true);
4584         b.expectBroadcast();
4585         verifyActiveNetwork(TRANSPORT_WIFI);
4586 
4587         // Register MMS NetworkRequest
4588         NetworkRequest.Builder builder = new NetworkRequest.Builder();
4589         builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
4590         final TestNetworkCallback networkCallback = new TestNetworkCallback();
4591         mCm.requestNetwork(builder.build(), networkCallback);
4592 
4593         // Test bringing up unvalidated cellular with MMS
4594         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
4595         mCellAgent.addCapability(NET_CAPABILITY_MMS);
4596         mCellAgent.connectWithoutInternet();
4597         networkCallback.expectAvailableCallbacksUnvalidated(mCellAgent);
4598         verifyActiveNetwork(TRANSPORT_WIFI);
4599 
4600         // Test releasing NetworkRequest disconnects cellular with MMS
4601         mCm.unregisterNetworkCallback(networkCallback);
4602         mCellAgent.expectDisconnected();
4603         verifyActiveNetwork(TRANSPORT_WIFI);
4604     }
4605 
4606     @Test
4607     public void testMMSonCell() throws Exception {
4608         // Test bringing up cellular without MMS
4609         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
4610         ExpectedBroadcast b = expectConnectivityAction(TYPE_MOBILE, DetailedState.CONNECTED);
4611         mCellAgent.connect(false);
4612         b.expectBroadcast();
4613         verifyActiveNetwork(TRANSPORT_CELLULAR);
4614 
4615         // Register MMS NetworkRequest
4616         NetworkRequest.Builder builder = new NetworkRequest.Builder();
4617         builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
4618         final TestNetworkCallback networkCallback = new TestNetworkCallback();
4619         mCm.requestNetwork(builder.build(), networkCallback);
4620 
4621         // Test bringing up MMS cellular network
4622         TestNetworkAgentWrapper
4623                 mmsNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
4624         mmsNetworkAgent.addCapability(NET_CAPABILITY_MMS);
4625         mmsNetworkAgent.connectWithoutInternet();
4626         networkCallback.expectAvailableCallbacksUnvalidated(mmsNetworkAgent);
4627         verifyActiveNetwork(TRANSPORT_CELLULAR);
4628 
4629         // Test releasing MMS NetworkRequest does not disconnect main cellular NetworkAgent
4630         mCm.unregisterNetworkCallback(networkCallback);
4631         mmsNetworkAgent.expectDisconnected();
4632         verifyActiveNetwork(TRANSPORT_CELLULAR);
4633     }
4634 
4635     @Test
4636     public void testPartialConnectivity() throws Exception {
4637         // Register network callback.
4638         NetworkRequest request = new NetworkRequest.Builder()
4639                 .clearCapabilities().addCapability(NET_CAPABILITY_INTERNET)
4640                 .build();
4641         TestNetworkCallback callback = new TestNetworkCallback();
4642         mCm.registerNetworkCallback(request, callback);
4643 
4644         // Bring up validated mobile data.
4645         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
4646         mCellAgent.connect(true);
4647         callback.expectAvailableThenValidatedCallbacks(mCellAgent);
4648 
4649         // Bring up wifi with partial connectivity.
4650         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4651         mWiFiAgent.connectWithPartialConnectivity();
4652         callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
4653         callback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY));
4654 
4655         // Mobile data should be the default network.
4656         assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetwork());
4657         callback.assertNoCallback();
4658 
4659         // Expect a PARTIAL_CONNECTIVITY notification. The notification appears as soon as partial
4660         // connectivity is detected, and is low priority because the network was not explicitly
4661         // selected by the user. This happens if we reconnect to a network where the user previously
4662         // accepted partial connectivity without checking "always".
4663         expectNotification(mWiFiAgent, NotificationType.PARTIAL_CONNECTIVITY);
4664 
4665         // With HTTPS probe disabled, NetworkMonitor should pass the network validation with http
4666         // probe.
4667         mWiFiAgent.setNetworkPartialValid(false /* privateDnsProbeSent */);
4668         // If the user chooses yes to use this partial connectivity wifi, switch the default
4669         // network to wifi and check if wifi becomes valid or not.
4670         mCm.setAcceptPartialConnectivity(mWiFiAgent.getNetwork(), true /* accept */,
4671                 false /* always */);
4672         // If user accepts partial connectivity network,
4673         // NetworkMonitor#setAcceptPartialConnectivity() should be called too.
4674         waitForIdle();
4675         verify(mWiFiAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
4676 
4677         // Need a trigger point to let NetworkMonitor tell ConnectivityService that the network is
4678         // validated.
4679         mCm.reportNetworkConnectivity(mWiFiAgent.getNetwork(), true);
4680         callback.expectLosing(mCellAgent);
4681         NetworkCapabilities nc =
4682                 callback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
4683         assertTrue(nc.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY));
4684         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetwork());
4685 
4686         // Once the network validates, the notification disappears.
4687         expectClearNotification(mWiFiAgent, NotificationType.PARTIAL_CONNECTIVITY);
4688 
4689         // Disconnect and reconnect wifi with partial connectivity again.
4690         mWiFiAgent.disconnect();
4691         callback.expect(LOST, mWiFiAgent);
4692 
4693         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4694         mWiFiAgent.connectWithPartialConnectivity();
4695         callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
4696         callback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY));
4697 
4698         // Mobile data should be the default network.
4699         assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetwork());
4700         waitForIdle();
4701 
4702         // Expect a low-priority PARTIAL_CONNECTIVITY notification as soon as partial connectivity
4703         // is detected.
4704         expectNotification(mWiFiAgent, NotificationType.PARTIAL_CONNECTIVITY);
4705 
4706         // If the user chooses no, disconnect wifi immediately.
4707         mCm.setAcceptPartialConnectivity(mWiFiAgent.getNetwork(), false /* accept */,
4708                 false /* always */);
4709         callback.expect(LOST, mWiFiAgent);
4710         expectClearNotification(mWiFiAgent, NotificationType.PARTIAL_CONNECTIVITY);
4711         reset(mNotificationManager);
4712 
4713         // If the user accepted partial connectivity before, and the device connects to that network
4714         // again, but now the network has full connectivity, then the network shouldn't contain
4715         // NET_CAPABILITY_PARTIAL_CONNECTIVITY.
4716         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4717         // acceptUnvalidated is also used as setting for accepting partial networks.
4718         mWiFiAgent.explicitlySelected(true /* explicitlySelected */, true /* acceptUnvalidated */);
4719         mWiFiAgent.connect(true);
4720         expectUnvalidationCheckWillNotNotify(mWiFiAgent);
4721 
4722         // If user accepted partial connectivity network before,
4723         // NetworkMonitor#setAcceptPartialConnectivity() will be called in
4724         // ConnectivityService#updateNetworkInfo().
4725         callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
4726         verify(mWiFiAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
4727         callback.expectLosing(mCellAgent);
4728         nc = callback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
4729         assertFalse(nc.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY));
4730 
4731         // Wifi should be the default network.
4732         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetwork());
4733         mWiFiAgent.disconnect();
4734         callback.expect(LOST, mWiFiAgent);
4735 
4736         // The user accepted partial connectivity and selected "don't ask again". Now the user
4737         // reconnects to the partial connectivity network. Switch to wifi as soon as partial
4738         // connectivity is detected.
4739         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4740         mWiFiAgent.explicitlySelected(true /* explicitlySelected */, true /* acceptUnvalidated */);
4741         mWiFiAgent.connectWithPartialConnectivity();
4742         // If user accepted partial connectivity network before,
4743         // NetworkMonitor#setAcceptPartialConnectivity() will be called in
4744         // ConnectivityService#updateNetworkInfo().
4745         callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
4746         verify(mWiFiAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
4747         callback.expectLosing(mCellAgent);
4748         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetwork());
4749         callback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY));
4750         expectUnvalidationCheckWillNotNotify(mWiFiAgent);
4751 
4752         mWiFiAgent.setNetworkValid(false /* privateDnsProbeSent */);
4753 
4754         // Need a trigger point to let NetworkMonitor tell ConnectivityService that the network is
4755         // validated.
4756         mCm.reportNetworkConnectivity(mWiFiAgent.getNetwork(), true);
4757         callback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
4758         mWiFiAgent.disconnect();
4759         callback.expect(LOST, mWiFiAgent);
4760 
4761         // If the user accepted partial connectivity, and the device auto-reconnects to the partial
4762         // connectivity network, it should contain both PARTIAL_CONNECTIVITY and VALIDATED.
4763         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4764         mWiFiAgent.explicitlySelected(false /* explicitlySelected */, true /* acceptUnvalidated */);
4765 
4766         // NetworkMonitor will immediately (once the HTTPS probe fails...) report the network as
4767         // valid, because ConnectivityService calls setAcceptPartialConnectivity before it calls
4768         // notifyNetworkConnected.
4769         mWiFiAgent.connectWithPartialValidConnectivity(false /* privateDnsProbeSent */);
4770         callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
4771         verify(mWiFiAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
4772         callback.expectLosing(mCellAgent);
4773         callback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY)
4774                 && c.hasCapability(NET_CAPABILITY_VALIDATED));
4775         expectUnvalidationCheckWillNotNotify(mWiFiAgent);
4776         mWiFiAgent.disconnect();
4777         callback.expect(LOST, mWiFiAgent);
4778         verifyNoMoreInteractions(mNotificationManager);
4779     }
4780 
4781     @Test
4782     public void testCaptivePortalOnPartialConnectivity() throws Exception {
4783         final TestNetworkCallback wifiCallback = new TestNetworkCallback();
4784         final NetworkRequest wifiRequest = new NetworkRequest.Builder()
4785                 .addTransportType(TRANSPORT_WIFI)
4786                 .build();
4787         mCm.registerNetworkCallback(wifiRequest, wifiCallback);
4788 
4789         final TestNetworkCallback validatedCallback = new TestNetworkCallback();
4790         final NetworkRequest validatedRequest = new NetworkRequest.Builder()
4791                 .addCapability(NET_CAPABILITY_VALIDATED).build();
4792         mCm.registerNetworkCallback(validatedRequest, validatedCallback);
4793 
4794         // Bring up a network with a captive portal.
4795         // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
4796         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4797         String redirectUrl = "http://android.com/path";
4798         mWiFiAgent.connectWithCaptivePortal(redirectUrl, false /* privateDnsProbeSent */);
4799         wifiCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
4800         assertEquals(mWiFiAgent.waitForRedirectUrl(), redirectUrl);
4801 
4802         // This is necessary because of b/245893397, the same bug that happens where we use
4803         // expectAvailableDoubleValidatedCallbacks.
4804         // TODO : fix b/245893397 and remove this.
4805         wifiCallback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_CAPTIVE_PORTAL));
4806 
4807         // Check that startCaptivePortalApp sends the expected command to NetworkMonitor.
4808         mCm.startCaptivePortalApp(mWiFiAgent.getNetwork());
4809         verify(mWiFiAgent.mNetworkMonitor, timeout(TIMEOUT_MS).times(1)).launchCaptivePortalApp();
4810 
4811         // Report that the captive portal is dismissed with partial connectivity, and check that
4812         // callbacks are fired with PARTIAL and without CAPTIVE_PORTAL.
4813         mWiFiAgent.setNetworkPartial();
4814         mCm.reportNetworkConnectivity(mWiFiAgent.getNetwork(), true);
4815         waitForIdle();
4816         wifiCallback.expectCaps(mWiFiAgent,
4817                 c -> c.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY)
4818                         && !c.hasCapability(NET_CAPABILITY_CAPTIVE_PORTAL));
4819 
4820         // Report partial connectivity is accepted.
4821         mWiFiAgent.setNetworkPartialValid(false /* privateDnsProbeSent */);
4822         mCm.setAcceptPartialConnectivity(mWiFiAgent.getNetwork(), true /* accept */,
4823                 false /* always */);
4824         waitForIdle();
4825         mCm.reportNetworkConnectivity(mWiFiAgent.getNetwork(), true);
4826         wifiCallback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
4827         validatedCallback.expectAvailableCallbacksValidated(mWiFiAgent);
4828         validatedCallback.expectCaps(mWiFiAgent,
4829                 c -> c.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY));
4830 
4831         mCm.unregisterNetworkCallback(wifiCallback);
4832         mCm.unregisterNetworkCallback(validatedCallback);
4833     }
4834 
4835     @Test
4836     public void testCaptivePortal() throws Exception {
4837         final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
4838         final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
4839                 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
4840         mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
4841 
4842         final TestNetworkCallback validatedCallback = new TestNetworkCallback();
4843         final NetworkRequest validatedRequest = new NetworkRequest.Builder()
4844                 .addCapability(NET_CAPABILITY_VALIDATED).build();
4845         mCm.registerNetworkCallback(validatedRequest, validatedCallback);
4846 
4847         // Bring up a network with a captive portal.
4848         // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
4849         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4850         String firstRedirectUrl = "http://example.com/firstPath";
4851         mWiFiAgent.connectWithCaptivePortal(firstRedirectUrl, false /* privateDnsProbeSent */);
4852         captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
4853         assertEquals(mWiFiAgent.waitForRedirectUrl(), firstRedirectUrl);
4854 
4855         // Take down network.
4856         // Expect onLost callback.
4857         mWiFiAgent.disconnect();
4858         captivePortalCallback.expect(LOST, mWiFiAgent);
4859 
4860         // Bring up a network with a captive portal.
4861         // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
4862         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4863         String secondRedirectUrl = "http://example.com/secondPath";
4864         mWiFiAgent.connectWithCaptivePortal(secondRedirectUrl, false /* privateDnsProbeSent */);
4865         captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
4866         assertEquals(mWiFiAgent.waitForRedirectUrl(), secondRedirectUrl);
4867 
4868         // Make captive portal disappear then revalidate.
4869         // Expect onLost callback because network no longer provides NET_CAPABILITY_CAPTIVE_PORTAL.
4870         mWiFiAgent.setNetworkValid(false /* privateDnsProbeSent */);
4871         mCm.reportNetworkConnectivity(mWiFiAgent.getNetwork(), true);
4872         captivePortalCallback.expect(LOST, mWiFiAgent);
4873 
4874         // Expect NET_CAPABILITY_VALIDATED onAvailable callback.
4875         validatedCallback.expectAvailableDoubleValidatedCallbacks(mWiFiAgent);
4876 
4877         // Break network connectivity.
4878         // Expect NET_CAPABILITY_VALIDATED onLost callback.
4879         mWiFiAgent.setNetworkInvalid(false /* invalidBecauseOfPrivateDns */);
4880         mCm.reportNetworkConnectivity(mWiFiAgent.getNetwork(), false);
4881         validatedCallback.expect(LOST, mWiFiAgent);
4882     }
4883 
4884     private Intent startCaptivePortalApp(TestNetworkAgentWrapper networkAgent) throws Exception {
4885         Network network = networkAgent.getNetwork();
4886         // Check that startCaptivePortalApp sends the expected command to NetworkMonitor.
4887         mCm.startCaptivePortalApp(network);
4888         waitForIdle();
4889         verify(networkAgent.mNetworkMonitor).launchCaptivePortalApp();
4890 
4891         // NetworkMonitor uses startCaptivePortal(Network, Bundle) (startCaptivePortalAppInternal)
4892         final Bundle testBundle = new Bundle();
4893         final String testKey = "testkey";
4894         final String testValue = "testvalue";
4895         testBundle.putString(testKey, testValue);
4896         mServiceContext.setPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
4897                 PERMISSION_GRANTED);
4898         mCm.startCaptivePortalApp(network, testBundle);
4899         final Intent signInIntent = mServiceContext.expectStartActivityIntent(TIMEOUT_MS);
4900         assertEquals(ACTION_CAPTIVE_PORTAL_SIGN_IN, signInIntent.getAction());
4901         assertEquals(testValue, signInIntent.getStringExtra(testKey));
4902         return signInIntent;
4903     }
4904 
4905     @Test
4906     public void testCaptivePortalApp() throws Exception {
4907         final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
4908         final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
4909                 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
4910         mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
4911 
4912         final TestNetworkCallback validatedCallback = new TestNetworkCallback();
4913         final NetworkRequest validatedRequest = new NetworkRequest.Builder()
4914                 .addCapability(NET_CAPABILITY_VALIDATED).build();
4915         mCm.registerNetworkCallback(validatedRequest, validatedCallback);
4916 
4917         // Bring up wifi.
4918         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4919         mWiFiAgent.connect(true);
4920         validatedCallback.expectAvailableDoubleValidatedCallbacks(mWiFiAgent);
4921         Network wifiNetwork = mWiFiAgent.getNetwork();
4922 
4923         // Check that calling startCaptivePortalApp does nothing.
4924         final int fastTimeoutMs = 100;
4925         mCm.startCaptivePortalApp(wifiNetwork);
4926         waitForIdle();
4927         verify(mWiFiAgent.mNetworkMonitor, never()).launchCaptivePortalApp();
4928         mServiceContext.expectNoStartActivityIntent(fastTimeoutMs);
4929 
4930         // Turn into a captive portal.
4931         mWiFiAgent.setNetworkPortal("http://example.com", false /* privateDnsProbeSent */);
4932         mCm.reportNetworkConnectivity(wifiNetwork, false);
4933         captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
4934         validatedCallback.expect(LOST, mWiFiAgent);
4935         // This is necessary because of b/245893397, the same bug that happens where we use
4936         // expectAvailableDoubleValidatedCallbacks.
4937         // TODO : fix b/245893397 and remove this.
4938         captivePortalCallback.expectCaps(mWiFiAgent);
4939 
4940         startCaptivePortalApp(mWiFiAgent);
4941 
4942         // Report that the captive portal is dismissed, and check that callbacks are fired
4943         mWiFiAgent.setNetworkValid(false /* privateDnsProbeSent */);
4944         mWiFiAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
4945         validatedCallback.expectAvailableCallbacksValidated(mWiFiAgent);
4946         captivePortalCallback.expect(LOST, mWiFiAgent);
4947 
4948         mCm.unregisterNetworkCallback(validatedCallback);
4949         mCm.unregisterNetworkCallback(captivePortalCallback);
4950     }
4951 
4952     @Test
4953     public void testCaptivePortalApp_IgnoreNetwork() throws Exception {
4954         final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
4955         final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
4956                 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
4957         mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
4958 
4959         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4960         mWiFiAgent.connectWithCaptivePortal(TEST_REDIRECT_URL, false);
4961         captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
4962 
4963         final Intent signInIntent = startCaptivePortalApp(mWiFiAgent);
4964         final CaptivePortal captivePortal = signInIntent
4965                 .getParcelableExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL);
4966 
4967         captivePortal.ignoreNetwork();
4968         waitForIdle();
4969 
4970         // Since network will disconnect, ensure no notification of response to NetworkMonitor
4971         verify(mWiFiAgent.mNetworkMonitor, never())
4972                 .notifyCaptivePortalAppFinished(CaptivePortal.APP_RETURN_UNWANTED);
4973 
4974         // Report that the network is disconnected
4975         mWiFiAgent.expectDisconnected();
4976         mWiFiAgent.expectPreventReconnectReceived();
4977         verify(mWiFiAgent.mNetworkMonitor).notifyNetworkDisconnected();
4978         captivePortalCallback.expect(LOST, mWiFiAgent);
4979 
4980         mCm.unregisterNetworkCallback(captivePortalCallback);
4981     }
4982 
4983     @Test
4984     public void testAvoidOrIgnoreCaptivePortals() throws Exception {
4985         final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
4986         final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
4987                 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
4988         mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
4989 
4990         final TestNetworkCallback validatedCallback = new TestNetworkCallback();
4991         final NetworkRequest validatedRequest = new NetworkRequest.Builder()
4992                 .addCapability(NET_CAPABILITY_VALIDATED).build();
4993         mCm.registerNetworkCallback(validatedRequest, validatedCallback);
4994 
4995         setCaptivePortalMode(ConnectivitySettingsManager.CAPTIVE_PORTAL_MODE_AVOID);
4996         // Bring up a network with a captive portal.
4997         // Expect it to fail to connect and not result in any callbacks.
4998         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4999         final String firstRedirectUrl = "http://example.com/firstPath";
5000 
5001         mWiFiAgent.connectWithCaptivePortal(firstRedirectUrl, false /* privateDnsProbeSent */);
5002         mWiFiAgent.expectDisconnected();
5003         mWiFiAgent.expectPreventReconnectReceived();
5004 
5005         assertNoCallbacks(captivePortalCallback, validatedCallback);
5006     }
5007 
5008     @Test
5009     public void testNoAvoidCaptivePortalOnWearProxy() throws Exception {
5010         // Bring up a BLUETOOTH network which is companion proxy on wear
5011         // then set captive portal.
5012         mockHasSystemFeature(PackageManager.FEATURE_WATCH, true);
5013         setCaptivePortalMode(ConnectivitySettingsManager.CAPTIVE_PORTAL_MODE_AVOID);
5014         TestNetworkAgentWrapper btAgent = new TestNetworkAgentWrapper(TRANSPORT_BLUETOOTH);
5015         final String firstRedirectUrl = "http://example.com/firstPath";
5016 
5017         btAgent.connectWithCaptivePortal(firstRedirectUrl, false /* privateDnsProbeSent */);
5018         btAgent.assertNotDisconnected(TIMEOUT_MS);
5019     }
5020 
5021     @Test
5022     public void testAvoidCaptivePortalOnBluetooth() throws Exception {
5023         // When not on Wear, BLUETOOTH is just regular network,
5024         // then set captive portal.
5025         mockHasSystemFeature(PackageManager.FEATURE_WATCH, false);
5026         setCaptivePortalMode(ConnectivitySettingsManager.CAPTIVE_PORTAL_MODE_AVOID);
5027         TestNetworkAgentWrapper btAgent = new TestNetworkAgentWrapper(TRANSPORT_BLUETOOTH);
5028         final String firstRedirectUrl = "http://example.com/firstPath";
5029 
5030         btAgent.connectWithCaptivePortal(firstRedirectUrl, false /* privateDnsProbeSent */);
5031 
5032         btAgent.expectDisconnected();
5033         btAgent.expectPreventReconnectReceived();
5034     }
5035 
5036     @Test
5037     public void testCaptivePortalApi() throws Exception {
5038         mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_GRANTED);
5039 
5040         final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
5041         final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
5042                 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
5043         mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
5044 
5045         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
5046         final String redirectUrl = "http://example.com/firstPath";
5047 
5048         mWiFiAgent.connectWithCaptivePortal(redirectUrl,
5049                 false /* privateDnsProbeSent */);
5050         captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
5051 
5052         final CaptivePortalData testData = new CaptivePortalData.Builder()
5053                 .setUserPortalUrl(Uri.parse(redirectUrl))
5054                 .setBytesRemaining(12345L)
5055                 .build();
5056 
5057         mWiFiAgent.notifyCapportApiDataChanged(testData);
5058 
5059         captivePortalCallback.expect(LINK_PROPERTIES_CHANGED, mWiFiAgent,
5060                 cb -> testData.equals(cb.getLp().getCaptivePortalData()));
5061 
5062         final LinkProperties newLps = new LinkProperties();
5063         newLps.setMtu(1234);
5064         mWiFiAgent.sendLinkProperties(newLps);
5065         // CaptivePortalData is not lost and unchanged when LPs are received from the NetworkAgent
5066         captivePortalCallback.expect(LINK_PROPERTIES_CHANGED, mWiFiAgent,
5067                 cb -> testData.equals(cb.getLp().getCaptivePortalData())
5068                         && cb.getLp().getMtu() == 1234);
5069     }
5070 
5071     private TestNetworkCallback setupNetworkCallbackAndConnectToWifi() throws Exception {
5072         // Grant NETWORK_SETTINGS permission to be able to receive LinkProperties change callbacks
5073         // with sensitive (captive portal) data
5074         mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_GRANTED);
5075 
5076         final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
5077         final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
5078                 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
5079         mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
5080 
5081         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
5082 
5083         mWiFiAgent.connectWithCaptivePortal(TEST_REDIRECT_URL,
5084                 false /* privateDnsProbeSent */);
5085         captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
5086         return captivePortalCallback;
5087     }
5088 
5089     private class CaptivePortalTestData {
5090         CaptivePortalTestData(CaptivePortalData naPasspointData, CaptivePortalData capportData,
5091                 CaptivePortalData naOtherData, CaptivePortalData expectedMergedPasspointData,
5092                 CaptivePortalData expectedMergedOtherData) {
5093             mNaPasspointData = naPasspointData;
5094             mCapportData = capportData;
5095             mNaOtherData = naOtherData;
5096             mExpectedMergedPasspointData = expectedMergedPasspointData;
5097             mExpectedMergedOtherData = expectedMergedOtherData;
5098         }
5099 
5100         public final CaptivePortalData mNaPasspointData;
5101         public final CaptivePortalData mCapportData;
5102         public final CaptivePortalData mNaOtherData;
5103         public final CaptivePortalData mExpectedMergedPasspointData;
5104         public final CaptivePortalData mExpectedMergedOtherData;
5105 
5106     }
5107 
5108     private CaptivePortalTestData setupCaptivePortalData() {
5109         final CaptivePortalData capportData = new CaptivePortalData.Builder()
5110                 .setUserPortalUrl(Uri.parse(TEST_REDIRECT_URL))
5111                 .setVenueInfoUrl(Uri.parse(TEST_VENUE_URL_CAPPORT))
5112                 .setUserPortalUrl(Uri.parse(TEST_USER_PORTAL_API_URL_CAPPORT))
5113                 .setExpiryTime(1000000L)
5114                 .setBytesRemaining(12345L)
5115                 .build();
5116 
5117         final CaptivePortalData naPasspointData = new CaptivePortalData.Builder()
5118                 .setBytesRemaining(80802L)
5119                 .setVenueInfoUrl(Uri.parse(TEST_VENUE_URL_NA_PASSPOINT),
5120                         CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_PASSPOINT)
5121                 .setUserPortalUrl(Uri.parse(TEST_TERMS_AND_CONDITIONS_URL_NA_PASSPOINT),
5122                         CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_PASSPOINT)
5123                 .setVenueFriendlyName(TEST_FRIENDLY_NAME).build();
5124 
5125         final CaptivePortalData naOtherData = new CaptivePortalData.Builder()
5126                 .setBytesRemaining(80802L)
5127                 .setVenueInfoUrl(Uri.parse(TEST_VENUE_URL_NA_OTHER),
5128                         CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_OTHER)
5129                 .setUserPortalUrl(Uri.parse(TEST_TERMS_AND_CONDITIONS_URL_NA_OTHER),
5130                         CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_OTHER)
5131                 .setVenueFriendlyName(TEST_FRIENDLY_NAME).build();
5132 
5133         final CaptivePortalData expectedMergedPasspointData = new CaptivePortalData.Builder()
5134                 .setUserPortalUrl(Uri.parse(TEST_REDIRECT_URL))
5135                 .setBytesRemaining(12345L)
5136                 .setExpiryTime(1000000L)
5137                 .setVenueInfoUrl(Uri.parse(TEST_VENUE_URL_NA_PASSPOINT),
5138                         CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_PASSPOINT)
5139                 .setUserPortalUrl(Uri.parse(TEST_TERMS_AND_CONDITIONS_URL_NA_PASSPOINT),
5140                         CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_PASSPOINT)
5141                 .setVenueFriendlyName(TEST_FRIENDLY_NAME).build();
5142 
5143         final CaptivePortalData expectedMergedOtherData = new CaptivePortalData.Builder()
5144                 .setUserPortalUrl(Uri.parse(TEST_REDIRECT_URL))
5145                 .setBytesRemaining(12345L)
5146                 .setExpiryTime(1000000L)
5147                 .setVenueInfoUrl(Uri.parse(TEST_VENUE_URL_CAPPORT))
5148                 .setUserPortalUrl(Uri.parse(TEST_USER_PORTAL_API_URL_CAPPORT))
5149                 .setVenueFriendlyName(TEST_FRIENDLY_NAME).build();
5150         return new CaptivePortalTestData(naPasspointData, capportData, naOtherData,
5151                 expectedMergedPasspointData, expectedMergedOtherData);
5152     }
5153 
5154     @Test
5155     public void testMergeCaptivePortalApiWithFriendlyNameAndVenueUrl() throws Exception {
5156         final TestNetworkCallback captivePortalCallback = setupNetworkCallbackAndConnectToWifi();
5157         final CaptivePortalTestData captivePortalTestData = setupCaptivePortalData();
5158 
5159         // Baseline capport data
5160         mWiFiAgent.notifyCapportApiDataChanged(captivePortalTestData.mCapportData);
5161 
5162         captivePortalCallback.expect(LINK_PROPERTIES_CHANGED, mWiFiAgent,
5163                 cb -> captivePortalTestData.mCapportData.equals(cb.getLp().getCaptivePortalData()));
5164 
5165         // Venue URL, T&C URL and friendly name from Network agent with Passpoint source, confirm
5166         // that API data gets precedence on the bytes remaining.
5167         final LinkProperties linkProperties = new LinkProperties();
5168         linkProperties.setCaptivePortalData(captivePortalTestData.mNaPasspointData);
5169         mWiFiAgent.sendLinkProperties(linkProperties);
5170 
5171         // Make sure that the capport data is merged
5172         captivePortalCallback.expect(LINK_PROPERTIES_CHANGED, mWiFiAgent,
5173                 cb -> captivePortalTestData.mExpectedMergedPasspointData.equals(
5174                         cb.getLp().getCaptivePortalData()));
5175 
5176         // Now send this information from non-Passpoint source, confirm that Capport data takes
5177         // precedence
5178         linkProperties.setCaptivePortalData(captivePortalTestData.mNaOtherData);
5179         mWiFiAgent.sendLinkProperties(linkProperties);
5180 
5181         // Make sure that the capport data is merged
5182         captivePortalCallback.expect(LINK_PROPERTIES_CHANGED, mWiFiAgent,
5183                 cb -> captivePortalTestData.mExpectedMergedOtherData.equals(
5184                         cb.getLp().getCaptivePortalData()));
5185 
5186         // Create a new LP with no Network agent capport data
5187         final LinkProperties newLps = new LinkProperties();
5188         newLps.setMtu(1234);
5189         mWiFiAgent.sendLinkProperties(newLps);
5190         // CaptivePortalData is not lost and has the original values when LPs are received from the
5191         // NetworkAgent
5192         captivePortalCallback.expect(LINK_PROPERTIES_CHANGED, mWiFiAgent,
5193                 cb -> captivePortalTestData.mCapportData.equals(cb.getLp().getCaptivePortalData())
5194                         && cb.getLp().getMtu() == 1234);
5195 
5196         // Now send capport data only from the Network agent
5197         mWiFiAgent.notifyCapportApiDataChanged(null);
5198         captivePortalCallback.expect(LINK_PROPERTIES_CHANGED, mWiFiAgent,
5199                 cb -> cb.getLp().getCaptivePortalData() == null);
5200 
5201         newLps.setCaptivePortalData(captivePortalTestData.mNaPasspointData);
5202         mWiFiAgent.sendLinkProperties(newLps);
5203 
5204         // Make sure that only the network agent capport data is available
5205         captivePortalCallback.expect(LINK_PROPERTIES_CHANGED, mWiFiAgent,
5206                 cb -> captivePortalTestData.mNaPasspointData.equals(
5207                         cb.getLp().getCaptivePortalData()));
5208     }
5209 
5210     @Test
5211     public void testMergeCaptivePortalDataFromNetworkAgentFirstThenCapport() throws Exception {
5212         final TestNetworkCallback captivePortalCallback = setupNetworkCallbackAndConnectToWifi();
5213         final CaptivePortalTestData captivePortalTestData = setupCaptivePortalData();
5214 
5215         // Venue URL and friendly name from Network agent, confirm that API data gets precedence
5216         // on the bytes remaining.
5217         final LinkProperties linkProperties = new LinkProperties();
5218         linkProperties.setCaptivePortalData(captivePortalTestData.mNaPasspointData);
5219         mWiFiAgent.sendLinkProperties(linkProperties);
5220 
5221         // Make sure that the data is saved correctly
5222         captivePortalCallback.expect(LINK_PROPERTIES_CHANGED, mWiFiAgent,
5223                 cb -> captivePortalTestData.mNaPasspointData.equals(
5224                         cb.getLp().getCaptivePortalData()));
5225 
5226         // Expected merged data: Network agent data is preferred, and values that are not used by
5227         // it are merged from capport data
5228         mWiFiAgent.notifyCapportApiDataChanged(captivePortalTestData.mCapportData);
5229 
5230         // Make sure that the Capport data is merged correctly
5231         captivePortalCallback.expect(LINK_PROPERTIES_CHANGED, mWiFiAgent,
5232                 cb -> captivePortalTestData.mExpectedMergedPasspointData.equals(
5233                         cb.getLp().getCaptivePortalData()));
5234 
5235         // Now set the naData to null
5236         linkProperties.setCaptivePortalData(null);
5237         mWiFiAgent.sendLinkProperties(linkProperties);
5238 
5239         // Make sure that the Capport data is retained correctly
5240         captivePortalCallback.expect(LINK_PROPERTIES_CHANGED, mWiFiAgent,
5241                 cb -> captivePortalTestData.mCapportData.equals(cb.getLp().getCaptivePortalData()));
5242     }
5243 
5244     @Test
5245     public void testMergeCaptivePortalDataFromNetworkAgentOtherSourceFirstThenCapport()
5246             throws Exception {
5247         final TestNetworkCallback captivePortalCallback = setupNetworkCallbackAndConnectToWifi();
5248         final CaptivePortalTestData captivePortalTestData = setupCaptivePortalData();
5249 
5250         // Venue URL and friendly name from Network agent, confirm that API data gets precedence
5251         // on the bytes remaining.
5252         final LinkProperties linkProperties = new LinkProperties();
5253         linkProperties.setCaptivePortalData(captivePortalTestData.mNaOtherData);
5254         mWiFiAgent.sendLinkProperties(linkProperties);
5255 
5256         // Make sure that the data is saved correctly
5257         captivePortalCallback.expect(LINK_PROPERTIES_CHANGED, mWiFiAgent,
5258                 cb -> captivePortalTestData.mNaOtherData.equals(cb.getLp().getCaptivePortalData()));
5259 
5260         // Expected merged data: Network agent data is preferred, and values that are not used by
5261         // it are merged from capport data
5262         mWiFiAgent.notifyCapportApiDataChanged(captivePortalTestData.mCapportData);
5263 
5264         // Make sure that the Capport data is merged correctly
5265         captivePortalCallback.expect(LINK_PROPERTIES_CHANGED, mWiFiAgent,
5266                 cb -> captivePortalTestData.mExpectedMergedOtherData.equals(
5267                         cb.getLp().getCaptivePortalData()));
5268     }
5269 
5270     private NetworkRequest.Builder newWifiRequestBuilder() {
5271         return new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI);
5272     }
5273 
5274     // A NetworkSpecifier subclass that matches all networks but must not be visible to apps.
5275     static class ConfidentialMatchAllNetworkSpecifier extends NetworkSpecifier implements
5276             Parcelable {
5277         public static final Parcelable.Creator<ConfidentialMatchAllNetworkSpecifier> CREATOR =
5278                 new Parcelable.Creator<ConfidentialMatchAllNetworkSpecifier>() {
5279                     public ConfidentialMatchAllNetworkSpecifier createFromParcel(Parcel in) {
5280                         return new ConfidentialMatchAllNetworkSpecifier();
5281                     }
5282 
5283                     public ConfidentialMatchAllNetworkSpecifier[] newArray(int size) {
5284                         return new ConfidentialMatchAllNetworkSpecifier[size];
5285                     }
5286                 };
5287         @Override
5288         public boolean canBeSatisfiedBy(NetworkSpecifier other) {
5289             return true;
5290         }
5291 
5292         @Override
5293         public int describeContents() {
5294             return 0;
5295         }
5296 
5297         @Override
5298         public void writeToParcel(Parcel dest, int flags) {}
5299 
5300         @Override
5301         public NetworkSpecifier redact() {
5302             return null;
5303         }
5304     }
5305 
5306     // A network specifier that matches either another LocalNetworkSpecifier with the same
5307     // string or a ConfidentialMatchAllNetworkSpecifier, and can be passed to apps as is.
5308     static class LocalStringNetworkSpecifier extends NetworkSpecifier implements Parcelable {
5309         public static final Parcelable.Creator<LocalStringNetworkSpecifier> CREATOR =
5310                 new Parcelable.Creator<LocalStringNetworkSpecifier>() {
5311                     public LocalStringNetworkSpecifier createFromParcel(Parcel in) {
5312                         return new LocalStringNetworkSpecifier(in);
5313                     }
5314 
5315                     public LocalStringNetworkSpecifier[] newArray(int size) {
5316                         return new LocalStringNetworkSpecifier[size];
5317                     }
5318                 };
5319         private String mString;
5320 
5321         LocalStringNetworkSpecifier(String string) {
5322             mString = string;
5323         }
5324 
5325         LocalStringNetworkSpecifier(Parcel in) {
5326             mString = in.readString();
5327         }
5328 
5329         @Override
5330         public boolean canBeSatisfiedBy(NetworkSpecifier other) {
5331             if (other instanceof LocalStringNetworkSpecifier) {
5332                 return TextUtils.equals(mString,
5333                         ((LocalStringNetworkSpecifier) other).mString);
5334             }
5335             if (other instanceof ConfidentialMatchAllNetworkSpecifier) return true;
5336             return false;
5337         }
5338 
5339         @Override
5340         public int describeContents() {
5341             return 0;
5342         }
5343         @Override
5344         public void writeToParcel(Parcel dest, int flags) {
5345             dest.writeString(mString);
5346         }
5347     }
5348 
5349     /**
5350      * Verify request matching behavior with network specifiers.
5351      *
5352      * This test does not check updating the specifier on a live network because the specifier is
5353      * immutable and this triggers a WTF in
5354      * {@link ConnectivityService#mixInCapabilities(NetworkAgentInfo, NetworkCapabilities)}.
5355      */
5356     @Test
5357     public void testNetworkSpecifier() throws Exception {
5358         NetworkRequest rEmpty1 = newWifiRequestBuilder().build();
5359         NetworkRequest rEmpty2 = newWifiRequestBuilder().setNetworkSpecifier((String) null).build();
5360         NetworkRequest rEmpty3 = newWifiRequestBuilder().setNetworkSpecifier("").build();
5361         NetworkRequest rEmpty4 = newWifiRequestBuilder().setNetworkSpecifier(
5362             (NetworkSpecifier) null).build();
5363         NetworkRequest rFoo = newWifiRequestBuilder().setNetworkSpecifier(
5364                 new LocalStringNetworkSpecifier("foo")).build();
5365         NetworkRequest rBar = newWifiRequestBuilder().setNetworkSpecifier(
5366                 new LocalStringNetworkSpecifier("bar")).build();
5367 
5368         TestNetworkCallback cEmpty1 = new TestNetworkCallback();
5369         TestNetworkCallback cEmpty2 = new TestNetworkCallback();
5370         TestNetworkCallback cEmpty3 = new TestNetworkCallback();
5371         TestNetworkCallback cEmpty4 = new TestNetworkCallback();
5372         TestNetworkCallback cFoo = new TestNetworkCallback();
5373         TestNetworkCallback cBar = new TestNetworkCallback();
5374         TestNetworkCallback[] emptyCallbacks = new TestNetworkCallback[] {
5375                 cEmpty1, cEmpty2, cEmpty3, cEmpty4 };
5376 
5377         mCm.registerNetworkCallback(rEmpty1, cEmpty1);
5378         mCm.registerNetworkCallback(rEmpty2, cEmpty2);
5379         mCm.registerNetworkCallback(rEmpty3, cEmpty3);
5380         mCm.registerNetworkCallback(rEmpty4, cEmpty4);
5381         mCm.registerNetworkCallback(rFoo, cFoo);
5382         mCm.registerNetworkCallback(rBar, cBar);
5383 
5384         LocalStringNetworkSpecifier nsFoo = new LocalStringNetworkSpecifier("foo");
5385         LocalStringNetworkSpecifier nsBar = new LocalStringNetworkSpecifier("bar");
5386 
5387         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
5388         mWiFiAgent.connect(false);
5389         expectAvailableCallbacksUnvalidatedWithSpecifier(mWiFiAgent, null /* specifier */,
5390                 cEmpty1, cEmpty2, cEmpty3, cEmpty4);
5391         assertNoCallbacks(cFoo, cBar);
5392 
5393         mWiFiAgent.disconnect();
5394         expectOnLost(mWiFiAgent, cEmpty1, cEmpty2, cEmpty3, cEmpty4);
5395 
5396         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
5397         mWiFiAgent.setNetworkSpecifier(nsFoo);
5398         mWiFiAgent.connect(false);
5399         expectAvailableCallbacksUnvalidatedWithSpecifier(mWiFiAgent, nsFoo,
5400                 cEmpty1, cEmpty2, cEmpty3, cEmpty4, cFoo);
5401         cBar.assertNoCallback();
5402         assertEquals(nsFoo,
5403                 mCm.getNetworkCapabilities(mWiFiAgent.getNetwork()).getNetworkSpecifier());
5404         assertNoCallbacks(cEmpty1, cEmpty2, cEmpty3, cEmpty4, cFoo);
5405 
5406         mWiFiAgent.disconnect();
5407         expectOnLost(mWiFiAgent, cEmpty1, cEmpty2, cEmpty3, cEmpty4, cFoo);
5408 
5409         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
5410         mWiFiAgent.setNetworkSpecifier(nsBar);
5411         mWiFiAgent.connect(false);
5412         expectAvailableCallbacksUnvalidatedWithSpecifier(mWiFiAgent, nsBar,
5413                 cEmpty1, cEmpty2, cEmpty3, cEmpty4, cBar);
5414         cFoo.assertNoCallback();
5415         assertEquals(nsBar,
5416                 mCm.getNetworkCapabilities(mWiFiAgent.getNetwork()).getNetworkSpecifier());
5417 
5418         mWiFiAgent.disconnect();
5419         expectOnLost(mWiFiAgent, cEmpty1, cEmpty2, cEmpty3, cEmpty4, cBar);
5420         cFoo.assertNoCallback();
5421 
5422         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
5423         mWiFiAgent.setNetworkSpecifier(new ConfidentialMatchAllNetworkSpecifier());
5424         mWiFiAgent.connect(false);
5425         expectAvailableCallbacksUnvalidatedWithSpecifier(mWiFiAgent, null /* specifier */,
5426                 cEmpty1, cEmpty2, cEmpty3, cEmpty4, cFoo, cBar);
5427         assertNull(mCm.getNetworkCapabilities(mWiFiAgent.getNetwork()).getNetworkSpecifier());
5428 
5429         mWiFiAgent.disconnect();
5430         expectOnLost(mWiFiAgent, cEmpty1, cEmpty2, cEmpty3, cEmpty4, cFoo, cBar);
5431     }
5432 
5433     /**
5434      * @return the context's attribution tag
5435      */
5436     private String getAttributionTag() {
5437         return mContext.getAttributionTag();
5438     }
5439 
5440     static class NonParcelableSpecifier extends NetworkSpecifier {
5441         @Override
5442         public boolean canBeSatisfiedBy(NetworkSpecifier other) {
5443             return false;
5444         }
5445     }
5446     static class ParcelableSpecifier extends NonParcelableSpecifier implements Parcelable {
5447         public static final Parcelable.Creator<NonParcelableSpecifier> CREATOR =
5448                 new Parcelable.Creator<NonParcelableSpecifier>() {
5449                     public NonParcelableSpecifier createFromParcel(Parcel in) {
5450                         return new NonParcelableSpecifier();
5451                     }
5452 
5453                     public NonParcelableSpecifier[] newArray(int size) {
5454                         return new NonParcelableSpecifier[size];
5455                     }
5456                 };
5457         @Override public int describeContents() {
5458             return 0;
5459         }
5460         @Override public void writeToParcel(Parcel p, int flags) {}
5461     }
5462 
5463     @Test
5464     public void testInvalidNetworkSpecifier() {
5465         assertThrows(IllegalArgumentException.class, () -> {
5466             NetworkRequest.Builder builder = new NetworkRequest.Builder();
5467             builder.setNetworkSpecifier(new MatchAllNetworkSpecifier());
5468         });
5469 
5470         assertThrows(IllegalArgumentException.class, () -> {
5471             NetworkCapabilities networkCapabilities = new NetworkCapabilities();
5472             networkCapabilities.addTransportType(TRANSPORT_WIFI)
5473                     .setNetworkSpecifier(new MatchAllNetworkSpecifier());
5474             mService.requestNetwork(Process.INVALID_UID, networkCapabilities,
5475                     NetworkRequest.Type.REQUEST.ordinal(), null, 0, null,
5476                     ConnectivityManager.TYPE_WIFI, NetworkCallback.FLAG_NONE,
5477                     mContext.getPackageName(), getAttributionTag(), ~0 /* declaredMethodsFlag */);
5478         });
5479 
5480         final NetworkRequest.Builder builder =
5481                 new NetworkRequest.Builder().addTransportType(TRANSPORT_ETHERNET);
5482         assertThrows(ClassCastException.class, () -> {
5483             builder.setNetworkSpecifier(new NonParcelableSpecifier());
5484             Parcel parcelW = Parcel.obtain();
5485             builder.build().writeToParcel(parcelW, 0);
5486         });
5487 
5488         final NetworkRequest nr =
5489                 new NetworkRequest.Builder().addTransportType(TRANSPORT_ETHERNET)
5490                 .setNetworkSpecifier(new ParcelableSpecifier())
5491                 .build();
5492         assertNotNull(nr);
5493 
5494         assertThrows(BadParcelableException.class, () -> {
5495             Parcel parcelW = Parcel.obtain();
5496             nr.writeToParcel(parcelW, 0);
5497             byte[] bytes = parcelW.marshall();
5498             parcelW.recycle();
5499 
5500             Parcel parcelR = Parcel.obtain();
5501             parcelR.unmarshall(bytes, 0, bytes.length);
5502             parcelR.setDataPosition(0);
5503             NetworkRequest rereadNr = NetworkRequest.CREATOR.createFromParcel(parcelR);
5504         });
5505     }
5506 
5507     @Test
5508     public void testNetworkRequestUidSpoofSecurityException() throws Exception {
5509         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
5510         mWiFiAgent.connect(false);
5511         NetworkRequest networkRequest = newWifiRequestBuilder().build();
5512         TestNetworkCallback networkCallback = new TestNetworkCallback();
5513         doThrow(new SecurityException()).when(mAppOpsManager).checkPackage(anyInt(), anyString());
5514         assertThrows(SecurityException.class, () -> {
5515             mCm.requestNetwork(networkRequest, networkCallback);
5516         });
5517     }
5518 
5519     @Test
5520     public void testInvalidSignalStrength() {
5521         NetworkRequest r = new NetworkRequest.Builder()
5522                 .addCapability(NET_CAPABILITY_INTERNET)
5523                 .addTransportType(TRANSPORT_WIFI)
5524                 .setSignalStrength(-75)
5525                 .build();
5526         // Registering a NetworkCallback with signal strength but w/o NETWORK_SIGNAL_STRENGTH_WAKEUP
5527         // permission should get SecurityException.
5528         assertThrows(SecurityException.class, () ->
5529                 mCm.registerNetworkCallback(r, new NetworkCallback()));
5530 
5531         assertThrows(SecurityException.class, () ->
5532                 mCm.registerNetworkCallback(r, PendingIntent.getService(
5533                         mServiceContext, 0 /* requestCode */, new Intent(), FLAG_IMMUTABLE)));
5534 
5535         // Requesting a Network with signal strength should get IllegalArgumentException.
5536         assertThrows(IllegalArgumentException.class, () ->
5537                 mCm.requestNetwork(r, new NetworkCallback()));
5538 
5539         assertThrows(IllegalArgumentException.class, () ->
5540                 mCm.requestNetwork(r, PendingIntent.getService(
5541                         mServiceContext, 0 /* requestCode */, new Intent(), FLAG_IMMUTABLE)));
5542     }
5543 
5544     @Test
5545     public void testRegisterDefaultNetworkCallback() throws Exception {
5546         final TestNetworkCallback defaultNetworkCallback = new TestNetworkCallback();
5547         mCm.registerDefaultNetworkCallback(defaultNetworkCallback);
5548         defaultNetworkCallback.assertNoCallback();
5549 
5550         final Handler handler = new Handler(ConnectivityThread.getInstanceLooper());
5551         final TestNetworkCallback systemDefaultCallback = new TestNetworkCallback();
5552         mCm.registerSystemDefaultNetworkCallback(systemDefaultCallback, handler);
5553         systemDefaultCallback.assertNoCallback();
5554 
5555         // Create a TRANSPORT_CELLULAR request to keep the mobile interface up
5556         // whenever Wi-Fi is up. Without this, the mobile network agent is
5557         // reaped before any other activity can take place.
5558         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
5559         final NetworkRequest cellRequest = new NetworkRequest.Builder()
5560                 .addTransportType(TRANSPORT_CELLULAR).build();
5561         mCm.requestNetwork(cellRequest, cellNetworkCallback);
5562         cellNetworkCallback.assertNoCallback();
5563 
5564         // Bring up cell and expect CALLBACK_AVAILABLE.
5565         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
5566         mCellAgent.connect(true);
5567         cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
5568         defaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
5569         systemDefaultCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
5570         assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
5571         assertEquals(systemDefaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
5572 
5573         // Bring up wifi and expect CALLBACK_AVAILABLE.
5574         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
5575         mWiFiAgent.connect(true);
5576         cellNetworkCallback.assertNoCallback();
5577         defaultNetworkCallback.expectAvailableDoubleValidatedCallbacks(mWiFiAgent);
5578         systemDefaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiAgent);
5579         assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
5580         assertEquals(systemDefaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
5581 
5582         // Bring down cell. Expect no default network callback, since it wasn't the default.
5583         mCellAgent.disconnect();
5584         cellNetworkCallback.expect(LOST, mCellAgent);
5585         defaultNetworkCallback.assertNoCallback();
5586         systemDefaultCallback.assertNoCallback();
5587         assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
5588         assertEquals(systemDefaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
5589 
5590         // Bring up cell. Expect no default network callback, since it won't be the default.
5591         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
5592         mCellAgent.connect(true);
5593         cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
5594         defaultNetworkCallback.assertNoCallback();
5595         systemDefaultCallback.assertNoCallback();
5596         assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
5597         assertEquals(systemDefaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
5598 
5599         // Bring down wifi. Expect the default network callback to notified of LOST wifi
5600         // followed by AVAILABLE cell.
5601         mWiFiAgent.disconnect();
5602         cellNetworkCallback.assertNoCallback();
5603         defaultNetworkCallback.expect(LOST, mWiFiAgent);
5604         defaultNetworkCallback.expectAvailableCallbacksValidated(mCellAgent);
5605         systemDefaultCallback.expect(LOST, mWiFiAgent);
5606         systemDefaultCallback.expectAvailableCallbacksValidated(mCellAgent);
5607         mCellAgent.disconnect();
5608         cellNetworkCallback.expect(LOST, mCellAgent);
5609         defaultNetworkCallback.expect(LOST, mCellAgent);
5610         systemDefaultCallback.expect(LOST, mCellAgent);
5611         waitForIdle();
5612         assertEquals(null, mCm.getActiveNetwork());
5613 
5614         mMockVpn.establishForMyUid();
5615         assertUidRangesUpdatedForMyUid(true);
5616         defaultNetworkCallback.expectAvailableThenValidatedCallbacks(mMockVpn);
5617         systemDefaultCallback.assertNoCallback();
5618         assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
5619         assertEquals(null, systemDefaultCallback.getLastAvailableNetwork());
5620 
5621         mMockVpn.disconnect();
5622         defaultNetworkCallback.expect(LOST, mMockVpn);
5623         systemDefaultCallback.assertNoCallback();
5624         waitForIdle();
5625         assertEquals(null, mCm.getActiveNetwork());
5626     }
5627 
5628     @Test
5629     public void testAdditionalStateCallbacks() throws Exception {
5630         // File a network request for mobile.
5631         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
5632         final NetworkRequest cellRequest = new NetworkRequest.Builder()
5633                 .addTransportType(TRANSPORT_CELLULAR).build();
5634         mCm.requestNetwork(cellRequest, cellNetworkCallback);
5635 
5636         // Bring up the mobile network.
5637         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
5638         mCellAgent.connect(true);
5639 
5640         // We should get onAvailable(), onCapabilitiesChanged(), and
5641         // onLinkPropertiesChanged() in rapid succession. Additionally, we
5642         // should get onCapabilitiesChanged() when the mobile network validates.
5643         cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
5644         cellNetworkCallback.assertNoCallback();
5645 
5646         // Update LinkProperties.
5647         final LinkProperties lp = new LinkProperties();
5648         lp.setInterfaceName("foonet_data0");
5649         mCellAgent.sendLinkProperties(lp);
5650         // We should get onLinkPropertiesChanged().
5651         cellNetworkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent);
5652         cellNetworkCallback.assertNoCallback();
5653 
5654         // Suspend the network.
5655         mCellAgent.suspend();
5656         cellNetworkCallback.expectCaps(mCellAgent,
5657                 c -> !c.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
5658         cellNetworkCallback.expect(SUSPENDED, mCellAgent);
5659         cellNetworkCallback.assertNoCallback();
5660         assertEquals(NetworkInfo.State.SUSPENDED, mCm.getActiveNetworkInfo().getState());
5661 
5662         // Register a garden variety default network request.
5663         TestNetworkCallback dfltNetworkCallback = new TestNetworkCallback();
5664         mCm.registerDefaultNetworkCallback(dfltNetworkCallback);
5665         // We should get onAvailable(), onCapabilitiesChanged(), onLinkPropertiesChanged(),
5666         // as well as onNetworkSuspended() in rapid succession.
5667         dfltNetworkCallback.expectAvailableAndSuspendedCallbacks(mCellAgent, true);
5668         dfltNetworkCallback.assertNoCallback();
5669         mCm.unregisterNetworkCallback(dfltNetworkCallback);
5670 
5671         mCellAgent.resume();
5672         cellNetworkCallback.expectCaps(mCellAgent,
5673                 c -> c.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
5674         cellNetworkCallback.expect(RESUMED, mCellAgent);
5675         cellNetworkCallback.assertNoCallback();
5676         assertEquals(NetworkInfo.State.CONNECTED, mCm.getActiveNetworkInfo().getState());
5677 
5678         dfltNetworkCallback = new TestNetworkCallback();
5679         mCm.registerDefaultNetworkCallback(dfltNetworkCallback);
5680         // This time onNetworkSuspended should not be called.
5681         dfltNetworkCallback.expectAvailableCallbacksValidated(mCellAgent);
5682         dfltNetworkCallback.assertNoCallback();
5683 
5684         mCm.unregisterNetworkCallback(dfltNetworkCallback);
5685         mCm.unregisterNetworkCallback(cellNetworkCallback);
5686     }
5687 
5688     @Test
5689     public void testRegisterPrivilegedDefaultCallbacksRequirePermissions() throws Exception {
5690         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
5691         mCellAgent.connect(false /* validated */);
5692         mServiceContext.setPermission(CONNECTIVITY_USE_RESTRICTED_NETWORKS, PERMISSION_DENIED);
5693 
5694         final Handler handler = new Handler(ConnectivityThread.getInstanceLooper());
5695         final TestNetworkCallback callback = new TestNetworkCallback();
5696         assertThrows(SecurityException.class,
5697                 () -> mCm.registerSystemDefaultNetworkCallback(callback, handler));
5698         callback.assertNoCallback();
5699         assertThrows(SecurityException.class,
5700                 () -> mCm.registerDefaultNetworkCallbackForUid(APP1_UID, callback, handler));
5701         callback.assertNoCallback();
5702 
5703         mServiceContext.setPermission(CONNECTIVITY_USE_RESTRICTED_NETWORKS, PERMISSION_GRANTED);
5704         mCm.registerSystemDefaultNetworkCallback(callback, handler);
5705         mServiceContext.setPermission(CONNECTIVITY_USE_RESTRICTED_NETWORKS, PERMISSION_DENIED);
5706         callback.expectAvailableCallbacksUnvalidated(mCellAgent);
5707         mCm.unregisterNetworkCallback(callback);
5708 
5709         mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_GRANTED);
5710         mCm.registerSystemDefaultNetworkCallback(callback, handler);
5711         callback.expectAvailableCallbacksUnvalidated(mCellAgent);
5712         mCm.unregisterNetworkCallback(callback);
5713 
5714         mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_DENIED);
5715         mServiceContext.setPermission(NETWORK_SETUP_WIZARD, PERMISSION_GRANTED);
5716         mCm.registerSystemDefaultNetworkCallback(callback, handler);
5717         callback.expectAvailableCallbacksUnvalidated(mCellAgent);
5718         mCm.unregisterNetworkCallback(callback);
5719 
5720         mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_GRANTED);
5721         mCm.registerDefaultNetworkCallbackForUid(APP1_UID, callback, handler);
5722         callback.expectAvailableCallbacksUnvalidated(mCellAgent);
5723         mCm.unregisterNetworkCallback(callback);
5724     }
5725 
5726     @Test
5727     public void testNetworkCallbackWithNullUids() throws Exception {
5728         final NetworkRequest request = new NetworkRequest.Builder()
5729                 .removeCapability(NET_CAPABILITY_NOT_VPN)
5730                 .build();
5731         final TestNetworkCallback callback = new TestNetworkCallback();
5732         mCm.registerNetworkCallback(request, callback);
5733 
5734         // Attempt to file a callback for networks applying to another UID. This does not actually
5735         // work, because this code does not currently have permission to do so. The callback behaves
5736         // exactly the same as the one registered just above.
5737         final int otherUid = UserHandle.getUid(RESTRICTED_USER, VPN_UID);
5738         final NetworkRequest otherUidRequest = new NetworkRequest.Builder()
5739                 .removeCapability(NET_CAPABILITY_NOT_VPN)
5740                 .setUids(UidRange.toIntRanges(uidRangesForUids(otherUid)))
5741                 .build();
5742         final TestNetworkCallback otherUidCallback = new TestNetworkCallback();
5743         mCm.registerNetworkCallback(otherUidRequest, otherUidCallback);
5744 
5745         final NetworkRequest includeOtherUidsRequest = new NetworkRequest.Builder()
5746                 .removeCapability(NET_CAPABILITY_NOT_VPN)
5747                 .setIncludeOtherUidNetworks(true)
5748                 .build();
5749         final TestNetworkCallback includeOtherUidsCallback = new TestNetworkCallback();
5750         mCm.registerNetworkCallback(includeOtherUidsRequest, includeOtherUidsCallback);
5751 
5752         // Both callbacks see a network with no specifier that applies to their UID.
5753         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
5754         mWiFiAgent.connect(false /* validated */);
5755         callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
5756         otherUidCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
5757         includeOtherUidsCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
5758         mWiFiAgent.disconnect();
5759         callback.expect(LOST, mWiFiAgent);
5760         otherUidCallback.expect(LOST, mWiFiAgent);
5761         includeOtherUidsCallback.expect(LOST, mWiFiAgent);
5762 
5763         // Only the includeOtherUidsCallback sees a VPN that does not apply to its UID.
5764         final UidRange range = UidRange.createForUser(UserHandle.of(RESTRICTED_USER));
5765         final Set<UidRange> vpnRanges = Collections.singleton(range);
5766         mMockVpn.establish(new LinkProperties(), VPN_UID, vpnRanges);
5767         includeOtherUidsCallback.expectAvailableThenValidatedCallbacks(mMockVpn);
5768         callback.assertNoCallback();
5769         otherUidCallback.assertNoCallback();
5770 
5771         mMockVpn.disconnect();
5772         includeOtherUidsCallback.expect(LOST, mMockVpn);
5773         callback.assertNoCallback();
5774         otherUidCallback.assertNoCallback();
5775     }
5776 
5777     private static class RedactableNetworkSpecifier extends NetworkSpecifier {
5778         public static final int ID_INVALID = -1;
5779 
5780         public final int networkId;
5781 
5782         RedactableNetworkSpecifier(int networkId) {
5783             this.networkId = networkId;
5784         }
5785 
5786         @Override
5787         public boolean canBeSatisfiedBy(NetworkSpecifier other) {
5788             return other instanceof RedactableNetworkSpecifier
5789                     && this.networkId == ((RedactableNetworkSpecifier) other).networkId;
5790         }
5791 
5792         @Override
5793         public NetworkSpecifier redact() {
5794             return new RedactableNetworkSpecifier(ID_INVALID);
5795         }
5796     }
5797 
5798     @Test
5799     public void testNetworkCallbackWithNullUidsRedactsSpecifier() throws Exception {
5800         final RedactableNetworkSpecifier specifier = new RedactableNetworkSpecifier(42);
5801         final NetworkRequest request = new NetworkRequest.Builder()
5802                 .addCapability(NET_CAPABILITY_INTERNET)
5803                 .addTransportType(TRANSPORT_WIFI)
5804                 .setNetworkSpecifier(specifier)
5805                 .build();
5806         final TestNetworkCallback callback = new TestNetworkCallback();
5807         mCm.registerNetworkCallback(request, callback);
5808 
5809         // Attempt to file a callback for networks applying to another UID. This does not actually
5810         // work, because this code does not currently have permission to do so. The callback behaves
5811         // exactly the same as the one registered just above.
5812         final int otherUid = UserHandle.getUid(RESTRICTED_USER, VPN_UID);
5813         final NetworkRequest otherUidRequest = new NetworkRequest.Builder()
5814                 .addCapability(NET_CAPABILITY_INTERNET)
5815                 .addTransportType(TRANSPORT_WIFI)
5816                 .setNetworkSpecifier(specifier)
5817                 .setUids(UidRange.toIntRanges(uidRangesForUids(otherUid)))
5818                 .build();
5819         final TestNetworkCallback otherUidCallback = new TestNetworkCallback();
5820         mCm.registerNetworkCallback(otherUidRequest, otherUidCallback);
5821 
5822         final NetworkRequest includeOtherUidsRequest = new NetworkRequest.Builder()
5823                 .addCapability(NET_CAPABILITY_INTERNET)
5824                 .addTransportType(TRANSPORT_WIFI)
5825                 .setNetworkSpecifier(specifier)
5826                 .setIncludeOtherUidNetworks(true)
5827                 .build();
5828         final TestNetworkCallback includeOtherUidsCallback = new TestNetworkCallback();
5829         mCm.registerNetworkCallback(includeOtherUidsRequest, callback);
5830 
5831         // Only the regular callback sees the network, because callbacks filed with no UID have
5832         // their specifiers redacted.
5833         final LinkProperties emptyLp = new LinkProperties();
5834         final NetworkCapabilities ncTemplate = new NetworkCapabilities()
5835                 .addTransportType(TRANSPORT_WIFI)
5836                 .setNetworkSpecifier(specifier);
5837         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, emptyLp, ncTemplate);
5838         mWiFiAgent.connect(false /* validated */);
5839         callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
5840         otherUidCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
5841         includeOtherUidsCallback.assertNoCallback();
5842     }
5843 
5844     private void setCaptivePortalMode(int mode) {
5845         ContentResolver cr = mServiceContext.getContentResolver();
5846         Settings.Global.putInt(cr, ConnectivitySettingsManager.CAPTIVE_PORTAL_MODE, mode);
5847     }
5848 
5849     private void setAlwaysOnNetworks(boolean enable) {
5850         ContentResolver cr = mServiceContext.getContentResolver();
5851         Settings.Global.putInt(cr, ConnectivitySettingsManager.MOBILE_DATA_ALWAYS_ON,
5852                 enable ? 1 : 0);
5853         mService.updateAlwaysOnNetworks();
5854         waitForIdle();
5855     }
5856 
5857     private void setPrivateDnsSettings(int mode, String specifier) {
5858         ConnectivitySettingsManager.setPrivateDnsMode(mServiceContext, mode);
5859         ConnectivitySettingsManager.setPrivateDnsHostname(mServiceContext, specifier);
5860         mService.updatePrivateDnsSettings();
5861         waitForIdle();
5862     }
5863 
5864     private void setIngressRateLimit(int rateLimitInBytesPerSec) {
5865         ConnectivitySettingsManager.setIngressRateLimitInBytesPerSecond(mServiceContext,
5866                 rateLimitInBytesPerSec);
5867         mService.updateIngressRateLimit();
5868         waitForIdle();
5869     }
5870 
5871     private boolean isForegroundNetwork(TestNetworkAgentWrapper network) {
5872         NetworkCapabilities nc = mCm.getNetworkCapabilities(network.getNetwork());
5873         assertNotNull(nc);
5874         return nc.hasCapability(NET_CAPABILITY_FOREGROUND);
5875     }
5876 
5877     @Test
5878     public void testBackgroundNetworks() throws Exception {
5879         // Create a cellular background request.
5880         grantUsingBackgroundNetworksPermissionForUid(Binder.getCallingUid());
5881         final TestNetworkCallback cellBgCallback = new TestNetworkCallback();
5882         mCm.requestBackgroundNetwork(new NetworkRequest.Builder()
5883                 .addTransportType(TRANSPORT_CELLULAR).build(),
5884                 cellBgCallback, mCsHandlerThread.getThreadHandler());
5885 
5886         // Make callbacks for monitoring.
5887         final NetworkRequest request = new NetworkRequest.Builder().build();
5888         final NetworkRequest fgRequest = new NetworkRequest.Builder()
5889                 .addCapability(NET_CAPABILITY_FOREGROUND).build();
5890         final TestNetworkCallback callback = new TestNetworkCallback();
5891         final TestNetworkCallback fgCallback = new TestNetworkCallback();
5892         mCm.registerNetworkCallback(request, callback);
5893         mCm.registerNetworkCallback(fgRequest, fgCallback);
5894 
5895         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
5896         mCellAgent.connect(true);
5897         callback.expectAvailableThenValidatedCallbacks(mCellAgent);
5898         fgCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
5899         assertTrue(isForegroundNetwork(mCellAgent));
5900 
5901         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
5902         mWiFiAgent.connect(true);
5903 
5904         // When wifi connects, cell lingers.
5905         callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
5906         callback.expectLosing(mCellAgent);
5907         callback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
5908         fgCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
5909         fgCallback.expectLosing(mCellAgent);
5910         fgCallback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
5911         assertTrue(isForegroundNetwork(mCellAgent));
5912         assertTrue(isForegroundNetwork(mWiFiAgent));
5913 
5914         // When lingering is complete, cell is still there but is now in the background.
5915         waitForIdle();
5916         int timeoutMs = TEST_LINGER_DELAY_MS + TEST_LINGER_DELAY_MS / 4;
5917         fgCallback.expect(LOST, mCellAgent, timeoutMs);
5918         // Expect a network capabilities update sans FOREGROUND.
5919         callback.expectCaps(mCellAgent, c -> !c.hasCapability(NET_CAPABILITY_FOREGROUND));
5920         assertFalse(isForegroundNetwork(mCellAgent));
5921         assertTrue(isForegroundNetwork(mWiFiAgent));
5922 
5923         // File a cell request and check that cell comes into the foreground.
5924         final NetworkRequest cellRequest = new NetworkRequest.Builder()
5925                 .addTransportType(TRANSPORT_CELLULAR).build();
5926         final TestNetworkCallback cellCallback = new TestNetworkCallback();
5927         mCm.requestNetwork(cellRequest, cellCallback);
5928         cellCallback.expectAvailableCallbacksValidated(mCellAgent);
5929         fgCallback.expectAvailableCallbacksValidated(mCellAgent);
5930         // Expect a network capabilities update with FOREGROUND, because the most recent
5931         // request causes its state to change.
5932         cellCallback.expectCaps(mCellAgent, c -> c.hasCapability(NET_CAPABILITY_FOREGROUND));
5933         callback.expectCaps(mCellAgent, c -> c.hasCapability(NET_CAPABILITY_FOREGROUND));
5934         assertTrue(isForegroundNetwork(mCellAgent));
5935         assertTrue(isForegroundNetwork(mWiFiAgent));
5936 
5937         // Release the request. The network immediately goes into the background, since it was not
5938         // lingering.
5939         mCm.unregisterNetworkCallback(cellCallback);
5940         fgCallback.expect(LOST, mCellAgent);
5941         // Expect a network capabilities update sans FOREGROUND.
5942         callback.expectCaps(mCellAgent, c -> !c.hasCapability(NET_CAPABILITY_FOREGROUND));
5943         assertFalse(isForegroundNetwork(mCellAgent));
5944         assertTrue(isForegroundNetwork(mWiFiAgent));
5945 
5946         // Disconnect wifi and check that cell is foreground again.
5947         mWiFiAgent.disconnect();
5948         callback.expect(LOST, mWiFiAgent);
5949         fgCallback.expect(LOST, mWiFiAgent);
5950         fgCallback.expectAvailableCallbacksValidated(mCellAgent);
5951         assertTrue(isForegroundNetwork(mCellAgent));
5952 
5953         mCm.unregisterNetworkCallback(callback);
5954         mCm.unregisterNetworkCallback(fgCallback);
5955         mCm.unregisterNetworkCallback(cellBgCallback);
5956     }
5957 
5958     @Ignore // This test has instrinsic chances of spurious failures: ignore for continuous testing.
5959     public void benchmarkRequestRegistrationAndCallbackDispatch() throws Exception {
5960         // TODO: turn this unit test into a real benchmarking test.
5961         // Benchmarks connecting and switching performance in the presence of a large number of
5962         // NetworkRequests.
5963         // 1. File NUM_REQUESTS requests.
5964         // 2. Have a network connect. Wait for NUM_REQUESTS onAvailable callbacks to fire.
5965         // 3. Have a new network connect and outscore the previous. Wait for NUM_REQUESTS onLosing
5966         //    and NUM_REQUESTS onAvailable callbacks to fire.
5967         // See how long it took.
5968         final int NUM_REQUESTS = 90;
5969         final int REGISTER_TIME_LIMIT_MS = 200;
5970         final int CONNECT_TIME_LIMIT_MS = 60;
5971         final int SWITCH_TIME_LIMIT_MS = 60;
5972         final int UNREGISTER_TIME_LIMIT_MS = 20;
5973 
5974         final NetworkRequest request = new NetworkRequest.Builder().clearCapabilities().build();
5975         final NetworkCallback[] callbacks = new NetworkCallback[NUM_REQUESTS];
5976         final CountDownLatch availableLatch = new CountDownLatch(NUM_REQUESTS);
5977         final CountDownLatch losingLatch = new CountDownLatch(NUM_REQUESTS);
5978 
5979         for (int i = 0; i < NUM_REQUESTS; i++) {
5980             callbacks[i] = new NetworkCallback() {
5981                 @Override public void onAvailable(Network n) { availableLatch.countDown(); }
5982                 @Override public void onLosing(Network n, int t) { losingLatch.countDown(); }
5983             };
5984         }
5985 
5986         assertRunsInAtMost("Registering callbacks", REGISTER_TIME_LIMIT_MS, () -> {
5987             for (NetworkCallback cb : callbacks) {
5988                 mCm.registerNetworkCallback(request, cb);
5989             }
5990         });
5991 
5992         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
5993         // Don't request that the network validate, because otherwise connect() will block until
5994         // the network gets NET_CAPABILITY_VALIDATED, after all the callbacks below have fired,
5995         // and we won't actually measure anything.
5996         mCellAgent.connect(false);
5997 
5998         long onAvailableDispatchingDuration = durationOf(() -> {
5999             await(availableLatch, 10 * CONNECT_TIME_LIMIT_MS);
6000         });
6001         Log.d(TAG, String.format("Dispatched %d of %d onAvailable callbacks in %dms",
6002                 NUM_REQUESTS - availableLatch.getCount(), NUM_REQUESTS,
6003                 onAvailableDispatchingDuration));
6004         assertTrue(String.format("Dispatching %d onAvailable callbacks in %dms, expected %dms",
6005                 NUM_REQUESTS, onAvailableDispatchingDuration, CONNECT_TIME_LIMIT_MS),
6006                 onAvailableDispatchingDuration <= CONNECT_TIME_LIMIT_MS);
6007 
6008         // Give wifi a high enough score that we'll linger cell when wifi comes up.
6009         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
6010         mWiFiAgent.adjustScore(40);
6011         mWiFiAgent.connect(false);
6012 
6013         long onLostDispatchingDuration = durationOf(() -> {
6014             await(losingLatch, 10 * SWITCH_TIME_LIMIT_MS);
6015         });
6016         Log.d(TAG, String.format("Dispatched %d of %d onLosing callbacks in %dms",
6017                 NUM_REQUESTS - losingLatch.getCount(), NUM_REQUESTS, onLostDispatchingDuration));
6018         assertTrue(String.format("Dispatching %d onLosing callbacks in %dms, expected %dms",
6019                 NUM_REQUESTS, onLostDispatchingDuration, SWITCH_TIME_LIMIT_MS),
6020                 onLostDispatchingDuration <= SWITCH_TIME_LIMIT_MS);
6021 
6022         assertRunsInAtMost("Unregistering callbacks", UNREGISTER_TIME_LIMIT_MS, () -> {
6023             for (NetworkCallback cb : callbacks) {
6024                 mCm.unregisterNetworkCallback(cb);
6025             }
6026         });
6027     }
6028 
6029     @Test
6030     public void testMobileDataAlwaysOn() throws Exception {
6031         grantUsingBackgroundNetworksPermissionForUid(Binder.getCallingUid());
6032         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
6033         final NetworkRequest cellRequest = new NetworkRequest.Builder()
6034                 .addTransportType(TRANSPORT_CELLULAR).build();
6035         mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
6036 
6037         final HandlerThread handlerThread = new HandlerThread("MobileDataAlwaysOnFactory");
6038         handlerThread.start();
6039         NetworkCapabilities filter = new NetworkCapabilities()
6040                 .addTransportType(TRANSPORT_CELLULAR)
6041                 .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
6042                 .addCapability(NET_CAPABILITY_INTERNET);
6043         final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
6044                 mServiceContext, "testFactory", filter, mCsHandlerThread);
6045         testFactory.setScoreFilter(40);
6046 
6047         // Register the factory and expect it to start looking for a network.
6048         testFactory.register();
6049 
6050         try {
6051             // Expect the factory to receive the default network request.
6052             testFactory.expectRequestAdd();
6053             testFactory.assertRequestCountEquals(1);
6054             assertTrue(testFactory.getMyStartRequested());
6055 
6056             // Bring up wifi. The factory stops looking for a network.
6057             mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
6058             // Score 60 - 40 penalty for not validated yet, then 60 when it validates
6059             mWiFiAgent.connect(true);
6060             // The network connects with a low score, so the offer can still beat it and
6061             // nothing happens. Then the network validates, and the offer with its filter score
6062             // of 40 can no longer beat it and the request is removed.
6063             testFactory.expectRequestRemove();
6064             testFactory.assertRequestCountEquals(0);
6065 
6066             assertFalse(testFactory.getMyStartRequested());
6067 
6068             // Turn on mobile data always on. This request will not match the wifi request, so
6069             // it will be sent to the test factory whose filters allow to see it.
6070             setAlwaysOnNetworks(true);
6071             testFactory.expectRequestAdd();
6072             testFactory.assertRequestCountEquals(1);
6073 
6074             assertTrue(testFactory.getMyStartRequested());
6075 
6076             // Bring up cell data and check that the factory stops looking.
6077             assertLength(1, mCm.getAllNetworks());
6078             mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
6079             mCellAgent.connect(false);
6080             cellNetworkCallback.expectAvailableCallbacks(mCellAgent, false, false, false,
6081                     TEST_CALLBACK_TIMEOUT_MS);
6082             // When cell connects, it will satisfy the "mobile always on request" right away
6083             // by virtue of being the only network that can satisfy the request. However, its
6084             // score is low (50 - 40 = 10) so the test factory can still hope to beat it.
6085             expectNoRequestChanged(testFactory);
6086 
6087             // Next, cell validates. This gives it a score of 50 and the test factory can't
6088             // hope to beat that according to its filters. It will see the message that its
6089             // offer is now unnecessary.
6090             mCellAgent.setNetworkValid(true);
6091             // Need a trigger point to let NetworkMonitor tell ConnectivityService that network is
6092             // validated – see testPartialConnectivity.
6093             mCm.reportNetworkConnectivity(mCellAgent.getNetwork(), true);
6094             cellNetworkCallback.expectCaps(mCellAgent,
6095                     c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
6096             testFactory.expectRequestRemove();
6097             testFactory.assertRequestCountEquals(0);
6098             // Accordingly, the factory shouldn't be started.
6099             assertFalse(testFactory.getMyStartRequested());
6100 
6101             // Check that cell data stays up.
6102             waitForIdle();
6103             verifyActiveNetwork(TRANSPORT_WIFI);
6104             assertLength(2, mCm.getAllNetworks());
6105 
6106             // Cell disconnects. There is still the "mobile data always on" request outstanding,
6107             // and the test factory should see it now that it isn't hopelessly outscored.
6108             mCellAgent.disconnect();
6109             cellNetworkCallback.expect(LOST, mCellAgent);
6110             // Wait for the network to be removed from internal structures before
6111             // calling synchronous getter
6112             waitForIdle();
6113             assertLength(1, mCm.getAllNetworks());
6114             testFactory.expectRequestAdd();
6115             testFactory.assertRequestCountEquals(1);
6116 
6117             // Reconnect cell validated, see the request disappear again. Then withdraw the
6118             // mobile always on request. This will tear down cell, and there shouldn't be a
6119             // blip where the test factory briefly sees the request or anything.
6120             mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
6121             mCellAgent.connect(true);
6122             cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
6123             waitForIdle();
6124             assertLength(2, mCm.getAllNetworks());
6125             testFactory.expectRequestRemove();
6126             testFactory.assertRequestCountEquals(0);
6127             setAlwaysOnNetworks(false);
6128             expectNoRequestChanged(testFactory);
6129             testFactory.assertRequestCountEquals(0);
6130             assertFalse(testFactory.getMyStartRequested());
6131             // ...  and cell data to be torn down immediately since it is no longer nascent.
6132             cellNetworkCallback.expect(LOST, mCellAgent);
6133             waitForIdle();
6134             assertLength(1, mCm.getAllNetworks());
6135             testFactory.terminate();
6136             testFactory.assertNoRequestChanged();
6137         } finally {
6138             mCm.unregisterNetworkCallback(cellNetworkCallback);
6139             handlerThread.quitSafely();
6140             handlerThread.join();
6141         }
6142     }
6143 
6144     @Test
6145     public void testSetAllowBadWifiUntil() throws Exception {
6146         runAsShell(NETWORK_SETTINGS,
6147                 () -> mService.setTestAllowBadWifiUntil(System.currentTimeMillis() + 5_000L));
6148         waitForIdle();
6149         testAvoidBadWifiConfig_controlledBySettings();
6150 
6151         runAsShell(NETWORK_SETTINGS,
6152                 () -> mService.setTestAllowBadWifiUntil(System.currentTimeMillis() - 5_000L));
6153         waitForIdle();
6154         testAvoidBadWifiConfig_ignoreSettings();
6155     }
6156 
6157     private void testAvoidBadWifiConfig_controlledBySettings() {
6158         final ContentResolver cr = mServiceContext.getContentResolver();
6159         final String settingName = ConnectivitySettingsManager.NETWORK_AVOID_BAD_WIFI;
6160 
6161         Settings.Global.putString(cr, settingName, "0");
6162         mPolicyTracker.reevaluate();
6163         waitForIdle();
6164         assertFalse(mService.avoidBadWifi());
6165         assertFalse(mPolicyTracker.shouldNotifyWifiUnvalidated());
6166 
6167         Settings.Global.putString(cr, settingName, "1");
6168         mPolicyTracker.reevaluate();
6169         waitForIdle();
6170         assertTrue(mService.avoidBadWifi());
6171         assertFalse(mPolicyTracker.shouldNotifyWifiUnvalidated());
6172 
6173         Settings.Global.putString(cr, settingName, null);
6174         mPolicyTracker.reevaluate();
6175         waitForIdle();
6176         assertFalse(mService.avoidBadWifi());
6177         assertTrue(mPolicyTracker.shouldNotifyWifiUnvalidated());
6178     }
6179 
6180     private void testAvoidBadWifiConfig_ignoreSettings() {
6181         final ContentResolver cr = mServiceContext.getContentResolver();
6182         final String settingName = ConnectivitySettingsManager.NETWORK_AVOID_BAD_WIFI;
6183 
6184         String[] values = new String[] {null, "0", "1"};
6185         for (int i = 0; i < values.length; i++) {
6186             Settings.Global.putString(cr, settingName, values[i]);
6187             mPolicyTracker.reevaluate();
6188             waitForIdle();
6189             String msg = String.format("config=false, setting=%s", values[i]);
6190             assertTrue(mService.avoidBadWifi());
6191             assertFalse(msg, mPolicyTracker.shouldNotifyWifiUnvalidated());
6192         }
6193     }
6194 
6195     @Test
6196     public void testAvoidBadWifiSetting() throws Exception {
6197         doReturn(1).when(mResources).getInteger(R.integer.config_networkAvoidBadWifi);
6198         testAvoidBadWifiConfig_ignoreSettings();
6199 
6200         doReturn(0).when(mResources).getInteger(R.integer.config_networkAvoidBadWifi);
6201         testAvoidBadWifiConfig_controlledBySettings();
6202     }
6203 
6204     @Test
6205     public void testActivelyPreferBadWifiSetting() throws Exception {
6206         doReturn(1).when(mResources).getInteger(R.integer.config_activelyPreferBadWifi);
6207         mPolicyTracker.reevaluate();
6208         waitForIdle();
6209         assertTrue(mService.mNetworkRanker.getConfiguration().activelyPreferBadWifi());
6210 
6211         doReturn(0).when(mResources).getInteger(R.integer.config_activelyPreferBadWifi);
6212         mPolicyTracker.reevaluate();
6213         waitForIdle();
6214         if (mDeps.isAtLeastU()) {
6215             // U+ ignore the setting and always actively prefers bad wifi
6216             assertTrue(mService.mNetworkRanker.getConfiguration().activelyPreferBadWifi());
6217         } else {
6218             assertFalse(mService.mNetworkRanker.getConfiguration().activelyPreferBadWifi());
6219         }
6220     }
6221 
6222     @Test
6223     public void testOffersAvoidsBadWifi() throws Exception {
6224         // Normal mode : the carrier doesn't restrict moving away from bad wifi.
6225         // This has getAvoidBadWifi return true.
6226         doReturn(1).when(mResources).getInteger(R.integer.config_networkAvoidBadWifi);
6227         // Don't request cell separately for the purposes of this test.
6228         setAlwaysOnNetworks(false);
6229 
6230         final NetworkProvider cellProvider = new NetworkProvider(mServiceContext,
6231                 mCsHandlerThread.getLooper(), "Cell provider");
6232         final NetworkProvider wifiProvider = new NetworkProvider(mServiceContext,
6233                 mCsHandlerThread.getLooper(), "Wifi provider");
6234 
6235         mCm.registerNetworkProvider(cellProvider);
6236         mCm.registerNetworkProvider(wifiProvider);
6237 
6238         final NetworkScore cellScore = new NetworkScore.Builder().build();
6239         final NetworkScore wifiScore = new NetworkScore.Builder().build();
6240         final NetworkCapabilities defaultCaps = new NetworkCapabilities.Builder()
6241                 .addCapability(NET_CAPABILITY_INTERNET)
6242                 .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
6243                 .build();
6244         final NetworkCapabilities cellCaps = new NetworkCapabilities.Builder()
6245                 .addTransportType(TRANSPORT_CELLULAR)
6246                 .addCapability(NET_CAPABILITY_INTERNET)
6247                 .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
6248                 .build();
6249         final NetworkCapabilities wifiCaps = new NetworkCapabilities.Builder()
6250                 .addTransportType(TRANSPORT_WIFI)
6251                 .addCapability(NET_CAPABILITY_INTERNET)
6252                 .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
6253                 .build();
6254         final TestableNetworkOfferCallback cellCallback = new TestableNetworkOfferCallback(
6255                 TIMEOUT_MS /* timeout */, TEST_CALLBACK_TIMEOUT_MS /* noCallbackTimeout */);
6256         final TestableNetworkOfferCallback wifiCallback = new TestableNetworkOfferCallback(
6257                 TIMEOUT_MS /* timeout */, TEST_CALLBACK_TIMEOUT_MS /* noCallbackTimeout */);
6258 
6259         // Offer callbacks will run on the CS handler thread in this test.
6260         cellProvider.registerNetworkOffer(cellScore, cellCaps, r -> r.run(), cellCallback);
6261         wifiProvider.registerNetworkOffer(wifiScore, wifiCaps, r -> r.run(), wifiCallback);
6262 
6263         // Both providers see the default request.
6264         cellCallback.expectOnNetworkNeeded(defaultCaps);
6265         wifiCallback.expectOnNetworkNeeded(defaultCaps);
6266 
6267         // Listen to cell and wifi to know when agents are finished processing
6268         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
6269         final NetworkRequest cellRequest = new NetworkRequest.Builder()
6270                 .addTransportType(TRANSPORT_CELLULAR).build();
6271         mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
6272         final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
6273         final NetworkRequest wifiRequest = new NetworkRequest.Builder()
6274                 .addTransportType(TRANSPORT_WIFI).build();
6275         mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
6276 
6277         // Cell connects and validates.
6278         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR,
6279                 new LinkProperties(), null /* ncTemplate */, cellProvider);
6280         mCellAgent.connect(true);
6281         cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
6282         cellCallback.assertNoCallback();
6283         wifiCallback.assertNoCallback();
6284 
6285         // Bring up wifi. At first it's invalidated, so cell is still needed.
6286         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI,
6287                 new LinkProperties(), null /* ncTemplate */, wifiProvider);
6288         mWiFiAgent.connect(false);
6289         wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
6290         cellCallback.assertNoCallback();
6291         wifiCallback.assertNoCallback();
6292 
6293         // Wifi validates. Cell is no longer needed, because it's outscored.
6294         mWiFiAgent.setNetworkValid(true /* privateDnsProbeSent */);
6295         // Have CS reconsider the network (see testPartialConnectivity)
6296         mCm.reportNetworkConnectivity(mWiFiAgent.getNetwork(), true);
6297         wifiNetworkCallback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
6298         cellCallback.expectOnNetworkUnneeded(defaultCaps);
6299         wifiCallback.assertNoCallback();
6300 
6301         // Wifi is no longer validated. Cell is needed again.
6302         mWiFiAgent.setNetworkInvalid(true /* invalidBecauseOfPrivateDns */);
6303         mCm.reportNetworkConnectivity(mWiFiAgent.getNetwork(), false);
6304         wifiNetworkCallback.expectCaps(mWiFiAgent,
6305                 c -> !c.hasCapability(NET_CAPABILITY_VALIDATED));
6306         cellCallback.expectOnNetworkNeeded(defaultCaps);
6307         wifiCallback.assertNoCallback();
6308 
6309         // Disconnect wifi and pretend the carrier restricts moving away from bad wifi.
6310         mWiFiAgent.disconnect();
6311         wifiNetworkCallback.expect(LOST, mWiFiAgent);
6312         // This has getAvoidBadWifi return false. This test doesn't change the value of the
6313         // associated setting.
6314         doReturn(0).when(mResources).getInteger(R.integer.config_networkAvoidBadWifi);
6315         mPolicyTracker.reevaluate();
6316         waitForIdle();
6317 
6318         // Connect wifi again, cell is needed until wifi validates.
6319         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI,
6320                 new LinkProperties(), null /* ncTemplate */, wifiProvider);
6321         mWiFiAgent.connect(false);
6322         wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
6323         cellCallback.assertNoCallback();
6324         wifiCallback.assertNoCallback();
6325         mWiFiAgent.setNetworkValid(true /* privateDnsProbeSent */);
6326         mCm.reportNetworkConnectivity(mWiFiAgent.getNetwork(), true);
6327         wifiNetworkCallback.expectCaps(mWiFiAgent,
6328                 c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
6329         cellCallback.expectOnNetworkUnneeded(defaultCaps);
6330         wifiCallback.assertNoCallback();
6331 
6332         // Wifi loses validation. Because the device doesn't avoid bad wifis, cell is
6333         // not needed.
6334         mWiFiAgent.setNetworkInvalid(true /* invalidBecauseOfPrivateDns */);
6335         mCm.reportNetworkConnectivity(mWiFiAgent.getNetwork(), false);
6336         wifiNetworkCallback.expectCaps(mWiFiAgent,
6337                 c -> !c.hasCapability(NET_CAPABILITY_VALIDATED));
6338         cellCallback.assertNoCallback();
6339         wifiCallback.assertNoCallback();
6340     }
6341 
6342     public void doTestPreferBadWifi(final boolean avoidBadWifi,
6343             final boolean preferBadWifi, final boolean explicitlySelected,
6344             @NonNull Predicate<Long> checkUnvalidationTimeout) throws Exception {
6345         // Pretend we're on a carrier that restricts switching away from bad wifi, and
6346         // depending on the parameter one that may indeed prefer bad wifi.
6347         doReturn(avoidBadWifi ? 1 : 0).when(mResources)
6348                 .getInteger(R.integer.config_networkAvoidBadWifi);
6349         doReturn(preferBadWifi ? 1 : 0).when(mResources)
6350                 .getInteger(R.integer.config_activelyPreferBadWifi);
6351         mPolicyTracker.reevaluate();
6352 
6353         registerDefaultNetworkCallbacks();
6354         final NetworkRequest wifiRequest = new NetworkRequest.Builder()
6355                 .clearCapabilities()
6356                 .addTransportType(TRANSPORT_WIFI)
6357                 .build();
6358         final TestNetworkCallback wifiCallback = new TestNetworkCallback();
6359         mCm.registerNetworkCallback(wifiRequest, wifiCallback);
6360 
6361         // Bring up validated cell and unvalidated wifi.
6362         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
6363         mCellAgent.connect(true);
6364         mDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
6365 
6366         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
6367         mWiFiAgent.explicitlySelected(explicitlySelected, false /* acceptUnvalidated */);
6368         mWiFiAgent.connect(false);
6369         wifiCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
6370 
6371         assertNotNull(mDeps.mScheduledEvaluationTimeouts.poll(TIMEOUT_MS,
6372                 t -> t.first == mWiFiAgent.getNetwork().netId
6373                         && checkUnvalidationTimeout.test(t.second)));
6374 
6375         if (!avoidBadWifi && preferBadWifi) {
6376             expectUnvalidationCheckWillNotify(mWiFiAgent, NotificationType.LOST_INTERNET);
6377             mDefaultNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
6378         } else {
6379             expectUnvalidationCheckWillNotNotify(mWiFiAgent);
6380             mDefaultNetworkCallback.assertNoCallback();
6381         }
6382     }
6383 
6384     @Test
6385     public void testPreferBadWifi_doNotAvoid_doNotPrefer() throws Exception {
6386         // Starting with U this mode is no longer supported and can't actually be tested
6387         assumeFalse(mDeps.isAtLeastU());
6388         doTestPreferBadWifi(false /* avoidBadWifi */, false /* preferBadWifi */,
6389                 false /* explicitlySelected */, timeout -> timeout < 14_000);
6390     }
6391 
6392     @Test
6393     public void testPreferBadWifi_doNotAvoid_doPrefer_notExplicit() throws Exception {
6394         doTestPreferBadWifi(false /* avoidBadWifi */, true /* preferBadWifi */,
6395                 false /* explicitlySelected */, timeout -> timeout > 14_000);
6396     }
6397 
6398     @Test
6399     public void testPreferBadWifi_doNotAvoid_doPrefer_explicitlySelected() throws Exception {
6400         doTestPreferBadWifi(false /* avoidBadWifi */, true /* preferBadWifi */,
6401                 true /* explicitlySelected */, timeout -> timeout < 14_000);
6402     }
6403 
6404     @Test
6405     public void testPreferBadWifi_doAvoid_doNotPrefer() throws Exception {
6406         // If avoidBadWifi=true, then preferBadWifi should be irrelevant. Test anyway.
6407         doTestPreferBadWifi(true /* avoidBadWifi */, false /* preferBadWifi */,
6408                 false /* explicitlySelected */, timeout -> timeout < 14_000);
6409     }
6410 
6411     @Test
6412     public void testPreferBadWifi_doAvoid_doPrefer() throws Exception {
6413         // If avoidBadWifi=true, then preferBadWifi should be irrelevant. Test anyway.
6414         doTestPreferBadWifi(true /* avoidBadWifi */, true /* preferBadWifi */,
6415                 false /* explicitlySelected */, timeout -> timeout < 14_000);
6416     }
6417 
6418     @Test
6419     public void testAvoidBadWifi() throws Exception {
6420         final ContentResolver cr = mServiceContext.getContentResolver();
6421 
6422         // Pretend we're on a carrier that restricts switching away from bad wifi.
6423         doReturn(0).when(mResources).getInteger(R.integer.config_networkAvoidBadWifi);
6424 
6425         // File a request for cell to ensure it doesn't go down.
6426         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
6427         final NetworkRequest cellRequest = new NetworkRequest.Builder()
6428                 .addTransportType(TRANSPORT_CELLULAR).build();
6429         mCm.requestNetwork(cellRequest, cellNetworkCallback);
6430 
6431         TestNetworkCallback defaultCallback = new TestNetworkCallback();
6432         mCm.registerDefaultNetworkCallback(defaultCallback);
6433 
6434         NetworkRequest validatedWifiRequest = new NetworkRequest.Builder()
6435                 .addTransportType(TRANSPORT_WIFI)
6436                 .addCapability(NET_CAPABILITY_VALIDATED)
6437                 .build();
6438         TestNetworkCallback validatedWifiCallback = new TestNetworkCallback();
6439         mCm.registerNetworkCallback(validatedWifiRequest, validatedWifiCallback);
6440 
6441         // Prompt mode, so notifications can be tested
6442         Settings.Global.putString(cr, ConnectivitySettingsManager.NETWORK_AVOID_BAD_WIFI, null);
6443         mPolicyTracker.reevaluate();
6444 
6445         // Bring up validated cell.
6446         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
6447         mCellAgent.connect(true);
6448         cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
6449         defaultCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
6450         Network cellNetwork = mCellAgent.getNetwork();
6451 
6452         // Bring up validated wifi.
6453         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
6454         mWiFiAgent.connect(true);
6455         defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiAgent);
6456         validatedWifiCallback.expectAvailableDoubleValidatedCallbacks(mWiFiAgent);
6457         Network wifiNetwork = mWiFiAgent.getNetwork();
6458 
6459         // Fail validation on wifi.
6460         mWiFiAgent.setNetworkInvalid(false /* invalidBecauseOfPrivateDns */);
6461         mCm.reportNetworkConnectivity(wifiNetwork, false);
6462         defaultCallback.expectCaps(mWiFiAgent, c -> !c.hasCapability(NET_CAPABILITY_VALIDATED));
6463         validatedWifiCallback.expect(LOST, mWiFiAgent);
6464         expectNotification(mWiFiAgent, NotificationType.LOST_INTERNET);
6465 
6466         // Because avoid bad wifi is off, we don't switch to cellular.
6467         defaultCallback.assertNoCallback();
6468         assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
6469                 NET_CAPABILITY_VALIDATED));
6470         assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
6471                 NET_CAPABILITY_VALIDATED));
6472         assertEquals(mCm.getActiveNetwork(), wifiNetwork);
6473 
6474         // Simulate switching to a carrier that does not restrict avoiding bad wifi, and expect
6475         // that we switch back to cell.
6476         doReturn(1).when(mResources).getInteger(R.integer.config_networkAvoidBadWifi);
6477         mPolicyTracker.reevaluate();
6478         defaultCallback.expectAvailableCallbacksValidated(mCellAgent);
6479         assertEquals(mCm.getActiveNetwork(), cellNetwork);
6480         expectClearNotification(mWiFiAgent, NotificationType.LOST_INTERNET);
6481 
6482         // Switch back to a restrictive carrier.
6483         doReturn(0).when(mResources).getInteger(R.integer.config_networkAvoidBadWifi);
6484         mPolicyTracker.reevaluate();
6485         defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
6486         assertEquals(mCm.getActiveNetwork(), wifiNetwork);
6487         // A notification was already shown for this very network.
6488         expectNoNotification(mWiFiAgent);
6489 
6490         // Simulate the user selecting "switch" on the dialog, and check that we switch to cell.
6491         // In principle this is a little bit unrealistic because the switch to a less restrictive
6492         // carrier above should have remove the notification but this doesn't matter for the
6493         // purposes of this test.
6494         mCm.setAvoidUnvalidated(wifiNetwork);
6495         defaultCallback.expectAvailableCallbacksValidated(mCellAgent);
6496         assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
6497                 NET_CAPABILITY_VALIDATED));
6498         assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
6499                 NET_CAPABILITY_VALIDATED));
6500         assertEquals(mCm.getActiveNetwork(), cellNetwork);
6501 
6502         // Disconnect and reconnect wifi to clear the one-time switch above.
6503         mWiFiAgent.disconnect();
6504         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
6505         mWiFiAgent.connect(true);
6506         defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiAgent);
6507         validatedWifiCallback.expectAvailableDoubleValidatedCallbacks(mWiFiAgent);
6508         wifiNetwork = mWiFiAgent.getNetwork();
6509 
6510         // Fail validation on wifi and expect the dialog to appear.
6511         mWiFiAgent.setNetworkInvalid(false /* invalidBecauseOfPrivateDns */);
6512         mCm.reportNetworkConnectivity(wifiNetwork, false);
6513         defaultCallback.expectCaps(mWiFiAgent, c -> !c.hasCapability(NET_CAPABILITY_VALIDATED));
6514         validatedWifiCallback.expect(LOST, mWiFiAgent);
6515         expectNotification(mWiFiAgent, NotificationType.LOST_INTERNET);
6516 
6517         // Simulate the user selecting "switch" and checking the don't ask again checkbox.
6518         Settings.Global.putInt(cr, ConnectivitySettingsManager.NETWORK_AVOID_BAD_WIFI, 1);
6519         mPolicyTracker.reevaluate();
6520 
6521         // We now switch to cell.
6522         defaultCallback.expectAvailableCallbacksValidated(mCellAgent);
6523         assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
6524                 NET_CAPABILITY_VALIDATED));
6525         assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
6526                 NET_CAPABILITY_VALIDATED));
6527         assertEquals(mCm.getActiveNetwork(), cellNetwork);
6528         expectClearNotification(mWiFiAgent, NotificationType.LOST_INTERNET);
6529 
6530         // Simulate the user turning the cellular fallback setting off and then on.
6531         // We switch to wifi and then to cell.
6532         Settings.Global.putString(cr, ConnectivitySettingsManager.NETWORK_AVOID_BAD_WIFI, null);
6533         mPolicyTracker.reevaluate();
6534         defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
6535         assertEquals(mCm.getActiveNetwork(), wifiNetwork);
6536         // Notification is cleared again because CS doesn't particularly remember that it has
6537         // cleared it before, and if it hasn't cleared it before then it should do so now.
6538         expectClearNotification(mWiFiAgent, NotificationType.LOST_INTERNET);
6539         Settings.Global.putInt(cr, ConnectivitySettingsManager.NETWORK_AVOID_BAD_WIFI, 1);
6540         mPolicyTracker.reevaluate();
6541         defaultCallback.expectAvailableCallbacksValidated(mCellAgent);
6542         assertEquals(mCm.getActiveNetwork(), cellNetwork);
6543 
6544         // If cell goes down, we switch to wifi.
6545         mCellAgent.disconnect();
6546         defaultCallback.expect(LOST, mCellAgent);
6547         defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
6548         validatedWifiCallback.assertNoCallback();
6549         // Notification is cleared yet again because the device switched to wifi.
6550         expectClearNotification(mWiFiAgent, NotificationType.LOST_INTERNET);
6551 
6552         mCm.unregisterNetworkCallback(cellNetworkCallback);
6553         mCm.unregisterNetworkCallback(validatedWifiCallback);
6554         mCm.unregisterNetworkCallback(defaultCallback);
6555     }
6556 
6557     @Test
6558     public void testMeteredMultipathPreferenceSetting() throws Exception {
6559         final ContentResolver cr = mServiceContext.getContentResolver();
6560         final String settingName = ConnectivitySettingsManager.NETWORK_METERED_MULTIPATH_PREFERENCE;
6561 
6562         for (int config : asList(0, 3, 2)) {
6563             for (String setting: asList(null, "0", "2", "1")) {
6564                 mPolicyTracker.mConfigMeteredMultipathPreference = config;
6565                 Settings.Global.putString(cr, settingName, setting);
6566                 mPolicyTracker.reevaluate();
6567                 waitForIdle();
6568 
6569                 final int expected = (setting != null) ? Integer.parseInt(setting) : config;
6570                 String msg = String.format("config=%d, setting=%s", config, setting);
6571                 assertEquals(msg, expected, mCm.getMultipathPreference(null));
6572             }
6573         }
6574     }
6575 
6576     /**
6577      * Validate that a satisfied network request does not trigger onUnavailable() once the
6578      * time-out period expires.
6579      */
6580     @Test
6581     public void testSatisfiedNetworkRequestDoesNotTriggerOnUnavailable() throws Exception {
6582         NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
6583                 NetworkCapabilities.TRANSPORT_WIFI).build();
6584         final TestNetworkCallback networkCallback = new TestNetworkCallback();
6585         mCm.requestNetwork(nr, networkCallback, TEST_REQUEST_TIMEOUT_MS);
6586 
6587         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
6588         mWiFiAgent.connect(false);
6589         networkCallback.expectAvailableCallbacks(mWiFiAgent, false, false, false,
6590                 TEST_CALLBACK_TIMEOUT_MS);
6591 
6592         // pass timeout and validate that UNAVAILABLE is not called
6593         networkCallback.assertNoCallback();
6594     }
6595 
6596     /**
6597      * Validate that a satisfied network request followed by a disconnected (lost) network does
6598      * not trigger onUnavailable() once the time-out period expires.
6599      */
6600     @Test
6601     public void testSatisfiedThenLostNetworkRequestDoesNotTriggerOnUnavailable() throws Exception {
6602         NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
6603                 NetworkCapabilities.TRANSPORT_WIFI).build();
6604         final TestNetworkCallback networkCallback = new TestNetworkCallback();
6605         mCm.requestNetwork(nr, networkCallback, TEST_REQUEST_TIMEOUT_MS);
6606 
6607         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
6608         mWiFiAgent.connect(false);
6609         networkCallback.expectAvailableCallbacks(mWiFiAgent, false, false, false,
6610                 TEST_CALLBACK_TIMEOUT_MS);
6611         mWiFiAgent.disconnect();
6612         networkCallback.expect(LOST, mWiFiAgent);
6613 
6614         // Validate that UNAVAILABLE is not called
6615         networkCallback.assertNoCallback();
6616     }
6617 
6618     /**
6619      * Validate that when a time-out is specified for a network request the onUnavailable()
6620      * callback is called when time-out expires. Then validate that if network request is
6621      * (somehow) satisfied - the callback isn't called later.
6622      */
6623     @Test
6624     public void testTimedoutNetworkRequest() throws Exception {
6625         NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
6626                 NetworkCapabilities.TRANSPORT_WIFI).build();
6627         final TestNetworkCallback networkCallback = new TestNetworkCallback();
6628         final int timeoutMs = 10;
6629         mCm.requestNetwork(nr, networkCallback, timeoutMs);
6630 
6631         // pass timeout and validate that UNAVAILABLE is called
6632         networkCallback.expect(UNAVAILABLE);
6633 
6634         // create a network satisfying request - validate that request not triggered
6635         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
6636         mWiFiAgent.connect(false);
6637         networkCallback.assertNoCallback();
6638     }
6639 
6640     /**
6641      * Validate that when a network request is unregistered (cancelled), no posterior event can
6642      * trigger the callback.
6643      */
6644     @Test
6645     public void testNoCallbackAfterUnregisteredNetworkRequest() throws Exception {
6646         NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
6647                 NetworkCapabilities.TRANSPORT_WIFI).build();
6648         final TestNetworkCallback networkCallback = new TestNetworkCallback();
6649         final int timeoutMs = 10;
6650 
6651         mCm.requestNetwork(nr, networkCallback, timeoutMs);
6652         mCm.unregisterNetworkCallback(networkCallback);
6653         // Regardless of the timeout, unregistering the callback in ConnectivityManager ensures
6654         // that this callback will not be called.
6655         networkCallback.assertNoCallback();
6656 
6657         // create a network satisfying request - validate that request not triggered
6658         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
6659         mWiFiAgent.connect(false);
6660         networkCallback.assertNoCallback();
6661     }
6662 
6663     @Test
6664     public void testUnfulfillableNetworkRequest() throws Exception {
6665         runUnfulfillableNetworkRequest(false);
6666     }
6667 
6668     @Test
6669     public void testUnfulfillableNetworkRequestAfterUnregister() throws Exception {
6670         runUnfulfillableNetworkRequest(true);
6671     }
6672 
6673     /**
6674      * Validate the callback flow for a factory releasing a request as unfulfillable.
6675      */
6676     private void runUnfulfillableNetworkRequest(boolean preUnregister) throws Exception {
6677         NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
6678                 NetworkCapabilities.TRANSPORT_WIFI).build();
6679         final TestNetworkCallback networkCallback = new TestNetworkCallback();
6680 
6681         final HandlerThread handlerThread = new HandlerThread("testUnfulfillableNetworkRequest");
6682         handlerThread.start();
6683         NetworkCapabilities filter = new NetworkCapabilities()
6684                 .addTransportType(TRANSPORT_WIFI)
6685                 .addCapability(NET_CAPABILITY_INTERNET)
6686                 .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED);
6687         final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
6688                 mServiceContext, "testFactory", filter, mCsHandlerThread);
6689         testFactory.setScoreFilter(40);
6690 
6691         // Register the factory and expect it to receive the default request.
6692         testFactory.register();
6693         testFactory.expectRequestAdd();
6694 
6695         try {
6696             // Now file the test request and expect it.
6697             mCm.requestNetwork(nr, networkCallback);
6698             final NetworkRequest newRequest = testFactory.expectRequestAdd().request;
6699 
6700             if (preUnregister) {
6701                 mCm.unregisterNetworkCallback(networkCallback);
6702 
6703                 // The request has been released : the factory should see it removed
6704                 // immediately.
6705                 testFactory.expectRequestRemove();
6706 
6707                 // Simulate the factory releasing the request as unfulfillable: no-op since
6708                 // the callback has already been unregistered (but a test that no exceptions are
6709                 // thrown).
6710                 testFactory.triggerUnfulfillable(newRequest);
6711             } else {
6712                 // Simulate the factory releasing the request as unfulfillable and expect
6713                 // onUnavailable!
6714                 testFactory.triggerUnfulfillable(newRequest);
6715 
6716                 networkCallback.expect(UNAVAILABLE);
6717 
6718                 // Declaring a request unfulfillable releases it automatically.
6719                 testFactory.expectRequestRemove();
6720 
6721                 // unregister network callback - a no-op (since already freed by the
6722                 // on-unavailable), but should not fail or throw exceptions.
6723                 mCm.unregisterNetworkCallback(networkCallback);
6724 
6725                 // The factory should not see any further removal, as this request has
6726                 // already been removed.
6727             }
6728         } finally {
6729             testFactory.terminate();
6730             handlerThread.quitSafely();
6731             handlerThread.join();
6732         }
6733     }
6734 
6735     @Test
6736     @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
6737     @DisableCompatChanges(ConnectivityCompatChanges.ENABLE_SELF_CERTIFIED_CAPABILITIES_DECLARATION)
6738     public void testSelfCertifiedCapabilitiesDisabled()
6739             throws Exception {
6740         mDeps.enableCompatChangeCheck();
6741         final NetworkRequest networkRequest = new NetworkRequest.Builder()
6742                 .addCapability(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_LATENCY)
6743                 .addCapability(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_BANDWIDTH)
6744                 .build();
6745         final TestNetworkCallback cb = new TestNetworkCallback();
6746         mCm.requestNetwork(networkRequest, cb);
6747         mCm.unregisterNetworkCallback(cb);
6748     }
6749 
6750     /** Set the networkSliceResourceId to 0 will result in NameNotFoundException be thrown. */
6751     private void setupMockForNetworkCapabilitiesResources(int networkSliceResourceId)
6752             throws PackageManager.NameNotFoundException {
6753         if (networkSliceResourceId == 0) {
6754             doThrow(new PackageManager.NameNotFoundException()).when(mPackageManager).getProperty(
6755                     ConstantsShim.PROPERTY_SELF_CERTIFIED_NETWORK_CAPABILITIES,
6756                     mContext.getPackageName());
6757         } else {
6758             final PackageManager.Property property = new PackageManager.Property(
6759                     ConstantsShim.PROPERTY_SELF_CERTIFIED_NETWORK_CAPABILITIES,
6760                     networkSliceResourceId,
6761                     true /* isResource */,
6762                     mContext.getPackageName(),
6763                     "dummyClass"
6764             );
6765             doReturn(property).when(mPackageManager).getProperty(
6766                     ConstantsShim.PROPERTY_SELF_CERTIFIED_NETWORK_CAPABILITIES,
6767                     mContext.getPackageName());
6768             doReturn(mContext.getResources()).when(mPackageManager).getResourcesForApplication(
6769                     mContext.getPackageName());
6770         }
6771     }
6772 
6773     @Test
6774     @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
6775     @EnableCompatChanges(ConnectivityCompatChanges.ENABLE_SELF_CERTIFIED_CAPABILITIES_DECLARATION)
6776     public void requestNetwork_withoutPrioritizeBandwidthDeclaration_shouldThrowException()
6777             throws Exception {
6778         mDeps.enableCompatChangeCheck();
6779         setupMockForNetworkCapabilitiesResources(
6780                 com.android.frameworks.tests.net.R.xml.self_certified_capabilities_latency);
6781         final NetworkRequest networkRequest = new NetworkRequest.Builder()
6782                 .addCapability(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_BANDWIDTH)
6783                 .build();
6784         final TestNetworkCallback cb = new TestNetworkCallback();
6785         final Exception e = assertThrows(SecurityException.class,
6786                 () -> mCm.requestNetwork(networkRequest, cb));
6787         assertThat(e.getMessage(),
6788                 containsString(ApplicationSelfCertifiedNetworkCapabilities.PRIORITIZE_BANDWIDTH));
6789     }
6790 
6791     @Test
6792     @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
6793     @EnableCompatChanges(ConnectivityCompatChanges.ENABLE_SELF_CERTIFIED_CAPABILITIES_DECLARATION)
6794     public void requestNetwork_withoutPrioritizeLatencyDeclaration_shouldThrowException()
6795             throws Exception {
6796         mDeps.enableCompatChangeCheck();
6797         setupMockForNetworkCapabilitiesResources(
6798                 com.android.frameworks.tests.net.R.xml.self_certified_capabilities_bandwidth);
6799         final NetworkRequest networkRequest = new NetworkRequest.Builder()
6800                 .addCapability(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_LATENCY)
6801                 .build();
6802         final TestNetworkCallback cb = new TestNetworkCallback();
6803         final Exception e = assertThrows(SecurityException.class,
6804                 () -> mCm.requestNetwork(networkRequest, cb));
6805         assertThat(e.getMessage(),
6806                 containsString(ApplicationSelfCertifiedNetworkCapabilities.PRIORITIZE_LATENCY));
6807     }
6808 
6809     @Test
6810     @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
6811     @EnableCompatChanges(ConnectivityCompatChanges.ENABLE_SELF_CERTIFIED_CAPABILITIES_DECLARATION)
6812     public void requestNetwork_withoutNetworkSliceProperty_shouldThrowException() throws Exception {
6813         mDeps.enableCompatChangeCheck();
6814         setupMockForNetworkCapabilitiesResources(0 /* networkSliceResourceId */);
6815         final NetworkRequest networkRequest = new NetworkRequest.Builder()
6816                 .addCapability(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_LATENCY)
6817                 .addCapability(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_BANDWIDTH)
6818                 .build();
6819         final TestNetworkCallback cb = new TestNetworkCallback();
6820         final Exception e = assertThrows(SecurityException.class,
6821                 () -> mCm.requestNetwork(networkRequest, cb));
6822         assertThat(e.getMessage(),
6823                 containsString(ConstantsShim.PROPERTY_SELF_CERTIFIED_NETWORK_CAPABILITIES));
6824     }
6825 
6826     @Test
6827     @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
6828     @EnableCompatChanges(ConnectivityCompatChanges.ENABLE_SELF_CERTIFIED_CAPABILITIES_DECLARATION)
6829     public void requestNetwork_withNetworkSliceDeclaration_shouldSucceed() throws Exception {
6830         mDeps.enableCompatChangeCheck();
6831         setupMockForNetworkCapabilitiesResources(
6832                 com.android.frameworks.tests.net.R.xml.self_certified_capabilities_both);
6833 
6834         final NetworkRequest networkRequest = new NetworkRequest.Builder()
6835                 .addCapability(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_LATENCY)
6836                 .addCapability(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_BANDWIDTH)
6837                 .build();
6838         final TestNetworkCallback cb = new TestNetworkCallback();
6839         mCm.requestNetwork(networkRequest, cb);
6840         mCm.unregisterNetworkCallback(cb);
6841     }
6842 
6843     @Test
6844     @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
6845     @EnableCompatChanges(ConnectivityCompatChanges.ENABLE_SELF_CERTIFIED_CAPABILITIES_DECLARATION)
6846     public void requestNetwork_withNetworkSliceDeclaration_shouldUseCache() throws Exception {
6847         mDeps.enableCompatChangeCheck();
6848         setupMockForNetworkCapabilitiesResources(
6849                 com.android.frameworks.tests.net.R.xml.self_certified_capabilities_both);
6850 
6851         final NetworkRequest networkRequest = new NetworkRequest.Builder()
6852                 .addCapability(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_LATENCY)
6853                 .addCapability(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_BANDWIDTH)
6854                 .build();
6855         final TestNetworkCallback cb = new TestNetworkCallback();
6856         mCm.requestNetwork(networkRequest, cb);
6857         mCm.unregisterNetworkCallback(cb);
6858 
6859         // Second call should use caches
6860         mCm.requestNetwork(networkRequest, cb);
6861         mCm.unregisterNetworkCallback(cb);
6862 
6863         // PackageManager's API only called once because the second call is using cache.
6864         verify(mPackageManager, times(1)).getProperty(
6865                 ConstantsShim.PROPERTY_SELF_CERTIFIED_NETWORK_CAPABILITIES,
6866                 mContext.getPackageName());
6867         verify(mPackageManager, times(1)).getResourcesForApplication(
6868                 mContext.getPackageName());
6869     }
6870 
6871     /**
6872      * Validate the service throws if request with CBS but without carrier privilege.
6873      */
6874     @Test
6875     public void testCBSRequestWithoutCarrierPrivilege() throws Exception {
6876         final NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
6877                 TRANSPORT_CELLULAR).addCapability(NET_CAPABILITY_CBS).build();
6878         final TestNetworkCallback networkCallback = new TestNetworkCallback();
6879 
6880         mServiceContext.setPermission(CONNECTIVITY_USE_RESTRICTED_NETWORKS, PERMISSION_DENIED);
6881         // Now file the test request and expect the service throws.
6882         assertThrows(SecurityException.class, () -> mCm.requestNetwork(nr, networkCallback));
6883     }
6884 
6885     private static class TestKeepaliveCallback extends PacketKeepaliveCallback {
6886 
6887         public enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR }
6888 
6889         private class CallbackValue {
6890             public CallbackType callbackType;
6891             public int error;
6892 
6893             public CallbackValue(CallbackType type) {
6894                 this.callbackType = type;
6895                 this.error = PacketKeepalive.SUCCESS;
6896                 assertTrue("onError callback must have error", type != CallbackType.ON_ERROR);
6897             }
6898 
6899             public CallbackValue(CallbackType type, int error) {
6900                 this.callbackType = type;
6901                 this.error = error;
6902                 assertEquals("error can only be set for onError", type, CallbackType.ON_ERROR);
6903             }
6904 
6905             @Override
6906             public boolean equals(Object o) {
6907                 return o instanceof CallbackValue &&
6908                         this.callbackType == ((CallbackValue) o).callbackType &&
6909                         this.error == ((CallbackValue) o).error;
6910             }
6911 
6912             @Override
6913             public String toString() {
6914                 return String.format("%s(%s, %d)", getClass().getSimpleName(), callbackType, error);
6915             }
6916         }
6917 
6918         private final LinkedBlockingQueue<CallbackValue> mCallbacks = new LinkedBlockingQueue<>();
6919 
6920         @Override
6921         public void onStarted() {
6922             mCallbacks.add(new CallbackValue(CallbackType.ON_STARTED));
6923         }
6924 
6925         @Override
6926         public void onStopped() {
6927             mCallbacks.add(new CallbackValue(CallbackType.ON_STOPPED));
6928         }
6929 
6930         @Override
6931         public void onError(int error) {
6932             mCallbacks.add(new CallbackValue(CallbackType.ON_ERROR, error));
6933         }
6934 
6935         private void expect(CallbackValue callbackValue) throws InterruptedException {
6936             assertEquals(callbackValue, mCallbacks.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
6937         }
6938 
6939         public void expectStarted() throws Exception {
6940             expect(new CallbackValue(CallbackType.ON_STARTED));
6941         }
6942 
6943         public void expectStopped() throws Exception {
6944             expect(new CallbackValue(CallbackType.ON_STOPPED));
6945         }
6946 
6947         public void expectError(int error) throws Exception {
6948             expect(new CallbackValue(CallbackType.ON_ERROR, error));
6949         }
6950     }
6951 
6952     private static class TestSocketKeepaliveCallback extends SocketKeepalive.Callback {
6953 
6954         public enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR };
6955 
6956         private class CallbackValue {
6957             public CallbackType callbackType;
6958             public int error;
6959 
6960             CallbackValue(CallbackType type) {
6961                 this.callbackType = type;
6962                 this.error = SocketKeepalive.SUCCESS;
6963                 assertTrue("onError callback must have error", type != CallbackType.ON_ERROR);
6964             }
6965 
6966             CallbackValue(CallbackType type, int error) {
6967                 this.callbackType = type;
6968                 this.error = error;
6969                 assertEquals("error can only be set for onError", type, CallbackType.ON_ERROR);
6970             }
6971 
6972             @Override
6973             public boolean equals(Object o) {
6974                 return o instanceof CallbackValue
6975                         && this.callbackType == ((CallbackValue) o).callbackType
6976                         && this.error == ((CallbackValue) o).error;
6977             }
6978 
6979             @Override
6980             public String toString() {
6981                 return String.format("%s(%s, %d)", getClass().getSimpleName(), callbackType,
6982                         error);
6983             }
6984         }
6985 
6986         private LinkedBlockingQueue<CallbackValue> mCallbacks = new LinkedBlockingQueue<>();
6987         private final Executor mExecutor;
6988 
6989         TestSocketKeepaliveCallback(@NonNull Executor executor) {
6990             mExecutor = executor;
6991         }
6992 
6993         @Override
6994         public void onStarted() {
6995             mCallbacks.add(new CallbackValue(CallbackType.ON_STARTED));
6996         }
6997 
6998         @Override
6999         public void onStopped() {
7000             mCallbacks.add(new CallbackValue(CallbackType.ON_STOPPED));
7001         }
7002 
7003         @Override
7004         public void onError(int error) {
7005             mCallbacks.add(new CallbackValue(CallbackType.ON_ERROR, error));
7006         }
7007 
7008         private void expect(CallbackValue callbackValue) throws InterruptedException {
7009             assertEquals(callbackValue, mCallbacks.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
7010 
7011         }
7012 
7013         public void expectStarted() throws InterruptedException {
7014             expect(new CallbackValue(CallbackType.ON_STARTED));
7015         }
7016 
7017         public void expectStopped() throws InterruptedException {
7018             expect(new CallbackValue(CallbackType.ON_STOPPED));
7019         }
7020 
7021         public void expectError(int error) throws InterruptedException {
7022             expect(new CallbackValue(CallbackType.ON_ERROR, error));
7023         }
7024 
7025         public void assertNoCallback() {
7026             waitForIdleSerialExecutor(mExecutor, TIMEOUT_MS);
7027             CallbackValue cv = mCallbacks.peek();
7028             assertNull("Unexpected callback: " + cv, cv);
7029         }
7030     }
7031 
7032     private Network connectKeepaliveNetwork(LinkProperties lp) throws Exception {
7033         // Ensure the network is disconnected before anything else occurs
7034         if (mWiFiAgent != null) {
7035             assertNull(mCm.getNetworkCapabilities(mWiFiAgent.getNetwork()));
7036         }
7037 
7038         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
7039         ExpectedBroadcast b = expectConnectivityAction(TYPE_WIFI, DetailedState.CONNECTED);
7040         mWiFiAgent.connect(true);
7041         b.expectBroadcast();
7042         verifyActiveNetwork(TRANSPORT_WIFI);
7043         mWiFiAgent.sendLinkProperties(lp);
7044         waitForIdle();
7045         return mWiFiAgent.getNetwork();
7046     }
7047 
7048     @Test
7049     public void testPacketKeepalives() throws Exception {
7050         final LinkAddress v4Addr = new LinkAddress("192.0.2.129/24");
7051         final InetAddress myIPv4 = v4Addr.getAddress();
7052         InetAddress notMyIPv4 = InetAddress.getByName("192.0.2.35");
7053         InetAddress myIPv6 = InetAddress.getByName("2001:db8::1");
7054         InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8");
7055         InetAddress dstIPv6 = InetAddress.getByName("2001:4860:4860::8888");
7056         doReturn(getClatInterfaceConfigParcel(v4Addr)).when(mMockNetd)
7057                 .interfaceGetCfg(CLAT_MOBILE_IFNAME);
7058         final int validKaInterval = 15;
7059         final int invalidKaInterval = 9;
7060 
7061         LinkProperties lp = new LinkProperties();
7062         lp.setInterfaceName(MOBILE_IFNAME);
7063         lp.addLinkAddress(new LinkAddress(myIPv6, 64));
7064         lp.addLinkAddress(new LinkAddress(myIPv4, 25));
7065         lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
7066         lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
7067 
7068         Network notMyNet = new Network(61234);
7069         Network myNet = connectKeepaliveNetwork(lp);
7070 
7071         TestKeepaliveCallback callback = new TestKeepaliveCallback();
7072         PacketKeepalive ka;
7073 
7074         // Attempt to start keepalives with invalid parameters and check for errors.
7075         ka = mCm.startNattKeepalive(notMyNet, validKaInterval, callback, myIPv4, 1234, dstIPv4);
7076         callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK);
7077 
7078         ka = mCm.startNattKeepalive(myNet, invalidKaInterval, callback, myIPv4, 1234, dstIPv4);
7079         callback.expectError(PacketKeepalive.ERROR_INVALID_INTERVAL);
7080 
7081         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 1234, dstIPv6);
7082         callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
7083 
7084         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv6, 1234, dstIPv4);
7085         callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
7086 
7087         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 123456, dstIPv4);
7088         callback.expectError(PacketKeepalive.ERROR_INVALID_PORT);
7089 
7090         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 123456, dstIPv4);
7091         callback.expectError(PacketKeepalive.ERROR_INVALID_PORT);
7092 
7093         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
7094         callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
7095 
7096         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
7097         callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
7098 
7099         // Check that a started keepalive can be stopped.
7100         mWiFiAgent.setStartKeepaliveEvent(PacketKeepalive.SUCCESS);
7101         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
7102         callback.expectStarted();
7103         mWiFiAgent.setStopKeepaliveEvent(PacketKeepalive.SUCCESS);
7104         ka.stop();
7105         callback.expectStopped();
7106 
7107         // Check that deleting the IP address stops the keepalive.
7108         LinkProperties bogusLp = new LinkProperties(lp);
7109         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
7110         callback.expectStarted();
7111         bogusLp.removeLinkAddress(new LinkAddress(myIPv4, 25));
7112         bogusLp.addLinkAddress(new LinkAddress(notMyIPv4, 25));
7113         mWiFiAgent.sendLinkProperties(bogusLp);
7114         callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
7115         mWiFiAgent.sendLinkProperties(lp);
7116 
7117         // Check that a started keepalive is stopped correctly when the network disconnects.
7118         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
7119         callback.expectStarted();
7120         mWiFiAgent.disconnect();
7121         mWiFiAgent.expectDisconnected();
7122         callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK);
7123 
7124         // ... and that stopping it after that has no adverse effects.
7125         waitForIdle();
7126         final Network myNetAlias = myNet;
7127         assertNull(mCm.getNetworkCapabilities(myNetAlias));
7128         ka.stop();
7129 
7130         // Reconnect.
7131         myNet = connectKeepaliveNetwork(lp);
7132         mWiFiAgent.setStartKeepaliveEvent(PacketKeepalive.SUCCESS);
7133 
7134         // Check that keepalive slots start from 1 and increment. The first one gets slot 1.
7135         mWiFiAgent.setExpectedKeepaliveSlot(1);
7136         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
7137         callback.expectStarted();
7138 
7139         // The second one gets slot 2.
7140         mWiFiAgent.setExpectedKeepaliveSlot(2);
7141         TestKeepaliveCallback callback2 = new TestKeepaliveCallback();
7142         PacketKeepalive ka2 = mCm.startNattKeepalive(
7143                 myNet, validKaInterval, callback2, myIPv4, 6789, dstIPv4);
7144         callback2.expectStarted();
7145 
7146         // Now stop the first one and create a third. This also gets slot 1.
7147         ka.stop();
7148         callback.expectStopped();
7149 
7150         mWiFiAgent.setExpectedKeepaliveSlot(1);
7151         TestKeepaliveCallback callback3 = new TestKeepaliveCallback();
7152         PacketKeepalive ka3 = mCm.startNattKeepalive(
7153                 myNet, validKaInterval, callback3, myIPv4, 9876, dstIPv4);
7154         callback3.expectStarted();
7155 
7156         ka2.stop();
7157         callback2.expectStopped();
7158 
7159         ka3.stop();
7160         callback3.expectStopped();
7161     }
7162 
7163     // Helper method to prepare the executor and run test
7164     private void runTestWithSerialExecutors(ThrowingConsumer<Executor> functor)
7165             throws Exception {
7166         final ExecutorService executorSingleThread = Executors.newSingleThreadExecutor();
7167         final Executor executorInline = (Runnable r) -> r.run();
7168         functor.accept(executorSingleThread);
7169         executorSingleThread.shutdown();
7170         functor.accept(executorInline);
7171     }
7172 
7173     @Test
7174     public void testNattSocketKeepalives() throws Exception {
7175         runTestWithSerialExecutors(executor -> doTestNattSocketKeepalivesWithExecutor(executor));
7176         runTestWithSerialExecutors(executor -> doTestNattSocketKeepalivesFdWithExecutor(executor));
7177     }
7178 
7179     private void doTestNattSocketKeepalivesWithExecutor(Executor executor) throws Exception {
7180         // TODO: 1. Move this outside of ConnectivityServiceTest.
7181         //       2. Make test to verify that Nat-T keepalive socket is created by IpSecService.
7182         //       3. Mock ipsec service.
7183         final InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
7184         final InetAddress notMyIPv4 = InetAddress.getByName("192.0.2.35");
7185         final InetAddress myIPv6 = InetAddress.getByName("2001:db8::1");
7186         final InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8");
7187         final InetAddress dstIPv6 = InetAddress.getByName("2001:4860:4860::8888");
7188 
7189         final int validKaInterval = 15;
7190         final int invalidKaInterval = 9;
7191 
7192         final IpSecManager mIpSec = (IpSecManager) mContext.getSystemService(Context.IPSEC_SERVICE);
7193         final UdpEncapsulationSocket testSocket = mIpSec.openUdpEncapsulationSocket();
7194         final int srcPort = testSocket.getPort();
7195 
7196         LinkProperties lp = new LinkProperties();
7197         lp.setInterfaceName("wlan12");
7198         lp.addLinkAddress(new LinkAddress(myIPv6, 64));
7199         lp.addLinkAddress(new LinkAddress(myIPv4, 25));
7200         lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
7201         lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
7202 
7203         Network notMyNet = new Network(61234);
7204         Network myNet = connectKeepaliveNetwork(lp);
7205 
7206         TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback(executor);
7207 
7208         // Attempt to start keepalives with invalid parameters and check for errors.
7209         // Invalid network.
7210         try (SocketKeepalive ka = mCm.createSocketKeepalive(
7211                 notMyNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
7212             ka.start(validKaInterval);
7213             callback.expectError(SocketKeepalive.ERROR_INVALID_NETWORK);
7214         }
7215 
7216         // Invalid interval.
7217         try (SocketKeepalive ka = mCm.createSocketKeepalive(
7218                 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
7219             ka.start(invalidKaInterval);
7220             callback.expectError(SocketKeepalive.ERROR_INVALID_INTERVAL);
7221         }
7222 
7223         // Invalid destination.
7224         try (SocketKeepalive ka = mCm.createSocketKeepalive(
7225                 myNet, testSocket, myIPv4, dstIPv6, executor, callback)) {
7226             ka.start(validKaInterval);
7227             callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
7228         }
7229 
7230         // Invalid source;
7231         try (SocketKeepalive ka = mCm.createSocketKeepalive(
7232                 myNet, testSocket, myIPv6, dstIPv4, executor, callback)) {
7233             ka.start(validKaInterval);
7234             callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
7235         }
7236 
7237         // Basic check before testing started keepalive.
7238         try (SocketKeepalive ka = mCm.createSocketKeepalive(
7239                 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
7240             ka.start(validKaInterval);
7241             callback.expectError(SocketKeepalive.ERROR_UNSUPPORTED);
7242         }
7243 
7244         // Check that a started keepalive can be stopped.
7245         mWiFiAgent.setStartKeepaliveEvent(SocketKeepalive.SUCCESS);
7246         try (SocketKeepalive ka = mCm.createSocketKeepalive(
7247                 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
7248             ka.start(validKaInterval);
7249             callback.expectStarted();
7250             mWiFiAgent.setStopKeepaliveEvent(SocketKeepalive.SUCCESS);
7251             ka.stop();
7252             callback.expectStopped();
7253 
7254             // Check that keepalive could be restarted.
7255             ka.start(validKaInterval);
7256             callback.expectStarted();
7257             ka.stop();
7258             callback.expectStopped();
7259 
7260             // Check that keepalive can be restarted without waiting for callback.
7261             ka.start(validKaInterval);
7262             callback.expectStarted();
7263             ka.stop();
7264             ka.start(validKaInterval);
7265             callback.expectStopped();
7266             callback.expectStarted();
7267             ka.stop();
7268             callback.expectStopped();
7269         }
7270 
7271         // Check that deleting the IP address stops the keepalive.
7272         LinkProperties bogusLp = new LinkProperties(lp);
7273         try (SocketKeepalive ka = mCm.createSocketKeepalive(
7274                 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
7275             ka.start(validKaInterval);
7276             callback.expectStarted();
7277             bogusLp.removeLinkAddress(new LinkAddress(myIPv4, 25));
7278             bogusLp.addLinkAddress(new LinkAddress(notMyIPv4, 25));
7279             mWiFiAgent.sendLinkProperties(bogusLp);
7280             callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
7281             mWiFiAgent.sendLinkProperties(lp);
7282         }
7283 
7284         // Check that a started keepalive is stopped correctly when the network disconnects.
7285         try (SocketKeepalive ka = mCm.createSocketKeepalive(
7286                 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
7287             ka.start(validKaInterval);
7288             callback.expectStarted();
7289             mWiFiAgent.disconnect();
7290             mWiFiAgent.expectDisconnected();
7291             callback.expectError(SocketKeepalive.ERROR_INVALID_NETWORK);
7292 
7293             // ... and that stopping it after that has no adverse effects.
7294             waitForIdle();
7295             assertNull(mCm.getNetworkCapabilities(myNet));
7296             ka.stop();
7297             callback.assertNoCallback();
7298         }
7299 
7300         // Reconnect.
7301         myNet = connectKeepaliveNetwork(lp);
7302         mWiFiAgent.setStartKeepaliveEvent(SocketKeepalive.SUCCESS);
7303 
7304         // Check that a stop followed by network disconnects does not result in crash.
7305         try (SocketKeepalive ka = mCm.createSocketKeepalive(
7306                 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
7307             ka.start(validKaInterval);
7308             callback.expectStarted();
7309             // Delay the response of keepalive events in networkAgent long enough to make sure
7310             // the follow-up network disconnection will be processed first.
7311             mWiFiAgent.setKeepaliveResponseDelay(3 * TIMEOUT_MS);
7312             ka.stop();
7313             // Call stop() twice shouldn't result in crash, b/182586681.
7314             ka.stop();
7315 
7316             // Make sure the stop has been processed. Wait for executor idle is needed to prevent
7317             // flaky since the actual stop call to the service is delegated to executor thread.
7318             waitForIdleSerialExecutor(executor, TIMEOUT_MS);
7319             waitForIdle();
7320 
7321             mWiFiAgent.disconnect();
7322             mWiFiAgent.expectDisconnected();
7323             callback.expectStopped();
7324             callback.assertNoCallback();
7325         }
7326 
7327         // Reconnect.
7328         waitForIdle();
7329         myNet = connectKeepaliveNetwork(lp);
7330         mWiFiAgent.setStartKeepaliveEvent(SocketKeepalive.SUCCESS);
7331 
7332         // Check that keepalive slots start from 1 and increment. The first one gets slot 1.
7333         mWiFiAgent.setExpectedKeepaliveSlot(1);
7334         try (SocketKeepalive ka = mCm.createSocketKeepalive(
7335                 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
7336             ka.start(validKaInterval);
7337             callback.expectStarted();
7338 
7339             // The second one gets slot 2.
7340             mWiFiAgent.setExpectedKeepaliveSlot(2);
7341             final UdpEncapsulationSocket testSocket2 = mIpSec.openUdpEncapsulationSocket();
7342             TestSocketKeepaliveCallback callback2 = new TestSocketKeepaliveCallback(executor);
7343             try (SocketKeepalive ka2 = mCm.createSocketKeepalive(
7344                     myNet, testSocket2, myIPv4, dstIPv4, executor, callback2)) {
7345                 ka2.start(validKaInterval);
7346                 callback2.expectStarted();
7347 
7348                 ka.stop();
7349                 callback.expectStopped();
7350 
7351                 ka2.stop();
7352                 callback2.expectStopped();
7353 
7354                 testSocket.close();
7355                 testSocket2.close();
7356             }
7357         }
7358 
7359         // Check that there is no port leaked after all keepalives and sockets are closed.
7360         // TODO: enable this check after ensuring a valid free port. See b/129512753#comment7.
7361         // assertFalse(isUdpPortInUse(srcPort));
7362         // assertFalse(isUdpPortInUse(srcPort2));
7363 
7364         mWiFiAgent.disconnect();
7365         mWiFiAgent.expectDisconnected();
7366         mWiFiAgent = null;
7367     }
7368 
7369     @Test
7370     public void testTcpSocketKeepalives() throws Exception {
7371         runTestWithSerialExecutors(executor -> doTestTcpSocketKeepalivesWithExecutor(executor));
7372     }
7373 
7374     private void doTestTcpSocketKeepalivesWithExecutor(Executor executor) throws Exception {
7375         final int srcPortV4 = 12345;
7376         final int srcPortV6 = 23456;
7377         final InetAddress myIPv4 = InetAddress.getByName("127.0.0.1");
7378         final InetAddress myIPv6 = InetAddress.getByName("::1");
7379 
7380         final int validKaInterval = 15;
7381 
7382         final LinkProperties lp = new LinkProperties();
7383         lp.setInterfaceName("wlan12");
7384         lp.addLinkAddress(new LinkAddress(myIPv6, 64));
7385         lp.addLinkAddress(new LinkAddress(myIPv4, 25));
7386         lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
7387         lp.addRoute(new RouteInfo(InetAddress.getByName("127.0.0.254")));
7388 
7389         final Network notMyNet = new Network(61234);
7390         final Network myNet = connectKeepaliveNetwork(lp);
7391 
7392         final Socket testSocketV4 = new Socket();
7393         final Socket testSocketV6 = new Socket();
7394 
7395         TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback(executor);
7396 
7397         // Attempt to start Tcp keepalives with invalid parameters and check for errors.
7398         // Invalid network.
7399         try (SocketKeepalive ka = mCm.createSocketKeepalive(
7400             notMyNet, testSocketV4, executor, callback)) {
7401             ka.start(validKaInterval);
7402             callback.expectError(SocketKeepalive.ERROR_INVALID_NETWORK);
7403         }
7404 
7405         // Invalid Socket (socket is not bound with IPv4 address).
7406         try (SocketKeepalive ka = mCm.createSocketKeepalive(
7407             myNet, testSocketV4, executor, callback)) {
7408             ka.start(validKaInterval);
7409             callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
7410         }
7411 
7412         // Invalid Socket (socket is not bound with IPv6 address).
7413         try (SocketKeepalive ka = mCm.createSocketKeepalive(
7414             myNet, testSocketV6, executor, callback)) {
7415             ka.start(validKaInterval);
7416             callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
7417         }
7418 
7419         // Bind the socket address
7420         testSocketV4.bind(new InetSocketAddress(myIPv4, srcPortV4));
7421         testSocketV6.bind(new InetSocketAddress(myIPv6, srcPortV6));
7422 
7423         // Invalid Socket (socket is bound with IPv4 address).
7424         try (SocketKeepalive ka = mCm.createSocketKeepalive(
7425             myNet, testSocketV4, executor, callback)) {
7426             ka.start(validKaInterval);
7427             callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
7428         }
7429 
7430         // Invalid Socket (socket is bound with IPv6 address).
7431         try (SocketKeepalive ka = mCm.createSocketKeepalive(
7432             myNet, testSocketV6, executor, callback)) {
7433             ka.start(validKaInterval);
7434             callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
7435         }
7436 
7437         testSocketV4.close();
7438         testSocketV6.close();
7439 
7440         mWiFiAgent.disconnect();
7441         mWiFiAgent.expectDisconnected();
7442         mWiFiAgent = null;
7443     }
7444 
7445     private void doTestNattSocketKeepalivesFdWithExecutor(Executor executor) throws Exception {
7446         final InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
7447         final InetAddress anyIPv4 = InetAddress.getByName("0.0.0.0");
7448         final InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8");
7449         final int validKaInterval = 15;
7450 
7451         // Prepare the target network.
7452         LinkProperties lp = new LinkProperties();
7453         lp.setInterfaceName("wlan12");
7454         lp.addLinkAddress(new LinkAddress(myIPv4, 25));
7455         lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
7456         Network myNet = connectKeepaliveNetwork(lp);
7457         mWiFiAgent.setStartKeepaliveEvent(SocketKeepalive.SUCCESS);
7458         mWiFiAgent.setStopKeepaliveEvent(SocketKeepalive.SUCCESS);
7459 
7460         TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback(executor);
7461 
7462         // Prepare the target file descriptor, keep only one instance.
7463         final IpSecManager mIpSec = (IpSecManager) mContext.getSystemService(Context.IPSEC_SERVICE);
7464         final UdpEncapsulationSocket testSocket = mIpSec.openUdpEncapsulationSocket();
7465         final int srcPort = testSocket.getPort();
7466         final ParcelFileDescriptor testPfd =
7467                 ParcelFileDescriptor.dup(testSocket.getFileDescriptor());
7468         testSocket.close();
7469         assertTrue(isUdpPortInUse(srcPort));
7470 
7471         // Start keepalive and explicit make the variable goes out of scope with try-with-resources
7472         // block.
7473         try (SocketKeepalive ka = mCm.createNattKeepalive(
7474                 myNet, testPfd, myIPv4, dstIPv4, executor, callback)) {
7475             ka.start(validKaInterval);
7476             callback.expectStarted();
7477             ka.stop();
7478             callback.expectStopped();
7479         }
7480 
7481         // Check that the ParcelFileDescriptor is still valid after keepalive stopped,
7482         // ErrnoException with EBADF will be thrown if the socket is closed when checking local
7483         // address.
7484         assertTrue(isUdpPortInUse(srcPort));
7485         final InetSocketAddress sa =
7486                 (InetSocketAddress) Os.getsockname(testPfd.getFileDescriptor());
7487         assertEquals(anyIPv4, sa.getAddress());
7488 
7489         testPfd.close();
7490         // TODO: enable this check after ensuring a valid free port. See b/129512753#comment7.
7491         // assertFalse(isUdpPortInUse(srcPort));
7492 
7493         mWiFiAgent.disconnect();
7494         mWiFiAgent.expectDisconnected();
7495         mWiFiAgent = null;
7496     }
7497 
7498     private static boolean isUdpPortInUse(int port) {
7499         try (DatagramSocket ignored = new DatagramSocket(port)) {
7500             return false;
7501         } catch (IOException alreadyInUse) {
7502             return true;
7503         }
7504     }
7505 
7506     @Test
7507     public void testGetCaptivePortalServerUrl() throws Exception {
7508         String url = mCm.getCaptivePortalServerUrl();
7509         assertEquals("http://connectivitycheck.gstatic.com/generate_204", url);
7510     }
7511 
7512     private static class TestNetworkPinner extends NetworkPinner {
7513         public static boolean awaitPin(int timeoutMs) throws InterruptedException {
7514             synchronized(sLock) {
7515                 if (sNetwork == null) {
7516                     sLock.wait(timeoutMs);
7517                 }
7518                 return sNetwork != null;
7519             }
7520         }
7521 
7522         public static boolean awaitUnpin(int timeoutMs) throws InterruptedException {
7523             synchronized(sLock) {
7524                 if (sNetwork != null) {
7525                     sLock.wait(timeoutMs);
7526                 }
7527                 return sNetwork == null;
7528             }
7529         }
7530     }
7531 
7532     private void assertPinnedToWifiWithCellDefault() {
7533         assertEquals(mWiFiAgent.getNetwork(), mCm.getBoundNetworkForProcess());
7534         assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetwork());
7535     }
7536 
7537     private void assertPinnedToWifiWithWifiDefault() {
7538         assertEquals(mWiFiAgent.getNetwork(), mCm.getBoundNetworkForProcess());
7539         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetwork());
7540     }
7541 
7542     private void assertNotPinnedToWifi() {
7543         assertNull(mCm.getBoundNetworkForProcess());
7544         assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetwork());
7545     }
7546 
7547     @Test
7548     public void testNetworkPinner() throws Exception {
7549         NetworkRequest wifiRequest = new NetworkRequest.Builder()
7550                 .addTransportType(TRANSPORT_WIFI)
7551                 .build();
7552         assertNull(mCm.getBoundNetworkForProcess());
7553 
7554         TestNetworkPinner.pin(mServiceContext, wifiRequest);
7555         assertNull(mCm.getBoundNetworkForProcess());
7556 
7557         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
7558         mCellAgent.connect(true);
7559         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
7560         mWiFiAgent.connect(false);
7561 
7562         // When wi-fi connects, expect to be pinned.
7563         assertTrue(TestNetworkPinner.awaitPin(100));
7564         assertPinnedToWifiWithCellDefault();
7565 
7566         // Disconnect and expect the pin to drop.
7567         mWiFiAgent.disconnect();
7568         assertTrue(TestNetworkPinner.awaitUnpin(100));
7569         assertNotPinnedToWifi();
7570 
7571         // Reconnecting does not cause the pin to come back.
7572         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
7573         mWiFiAgent.connect(false);
7574         assertFalse(TestNetworkPinner.awaitPin(100));
7575         assertNotPinnedToWifi();
7576 
7577         // Pinning while connected causes the pin to take effect immediately.
7578         TestNetworkPinner.pin(mServiceContext, wifiRequest);
7579         assertTrue(TestNetworkPinner.awaitPin(100));
7580         assertPinnedToWifiWithCellDefault();
7581 
7582         // Explicitly unpin and expect to use the default network again.
7583         TestNetworkPinner.unpin();
7584         assertNotPinnedToWifi();
7585 
7586         // Disconnect cell and wifi.
7587         ExpectedBroadcast b = expectConnectivityAction(3);  // cell down, wifi up, wifi down.
7588         mCellAgent.disconnect();
7589         mWiFiAgent.disconnect();
7590         b.expectBroadcast();
7591 
7592         // Pinning takes effect even if the pinned network is the default when the pin is set...
7593         TestNetworkPinner.pin(mServiceContext, wifiRequest);
7594         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
7595         mWiFiAgent.connect(false);
7596         assertTrue(TestNetworkPinner.awaitPin(100));
7597         assertPinnedToWifiWithWifiDefault();
7598 
7599         // ... and is maintained even when that network is no longer the default.
7600         b = expectConnectivityAction(1);
7601         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
7602         mCellAgent.connect(true);
7603         b.expectBroadcast();
7604         assertPinnedToWifiWithCellDefault();
7605     }
7606 
7607     @Test
7608     public void testNetworkCallbackMaximum() throws Exception {
7609         final int MAX_REQUESTS = 100;
7610         final int CALLBACKS = 88;
7611         final int DIFF_INTENTS = 10;
7612         final int SAME_INTENTS = 10;
7613         final int SYSTEM_ONLY_MAX_REQUESTS = 250;
7614         // CALLBACKS + DIFF_INTENTS + 1 (same intent)
7615         // = MAX_REQUESTS - 1, since the capacity is MAX_REQUEST - 1.
7616         assertEquals(MAX_REQUESTS - 1, CALLBACKS + DIFF_INTENTS + 1);
7617 
7618         NetworkRequest networkRequest = new NetworkRequest.Builder().build();
7619         ArrayList<Object> registered = new ArrayList<>();
7620 
7621         for (int j = 0; j < CALLBACKS; j++) {
7622             final NetworkCallback cb = new NetworkCallback();
7623             if (j < CALLBACKS / 2) {
7624                 mCm.requestNetwork(networkRequest, cb);
7625             } else {
7626                 mCm.registerNetworkCallback(networkRequest, cb);
7627             }
7628             registered.add(cb);
7629         }
7630 
7631         // Since ConnectivityService will de-duplicate the request with the same intent,
7632         // register multiple times does not really increase multiple requests.
7633         final PendingIntent same_pi = PendingIntent.getBroadcast(mContext, 0 /* requestCode */,
7634                 new Intent("same"), FLAG_IMMUTABLE);
7635         for (int j = 0; j < SAME_INTENTS; j++) {
7636             mCm.registerNetworkCallback(networkRequest, same_pi);
7637             // Wait for the requests with the same intent to be de-duplicated. Because
7638             // ConnectivityService side incrementCountOrThrow in binder, decrementCount in handler
7639             // thread, waitForIdle is needed to ensure decrementCount being invoked for same intent
7640             // requests before doing further tests.
7641             waitForIdle();
7642         }
7643         for (int j = 0; j < SAME_INTENTS; j++) {
7644             mCm.requestNetwork(networkRequest, same_pi);
7645             // Wait for the requests with the same intent to be de-duplicated.
7646             // Refer to the reason above.
7647             waitForIdle();
7648         }
7649         registered.add(same_pi);
7650 
7651         for (int j = 0; j < DIFF_INTENTS; j++) {
7652             if (j < DIFF_INTENTS / 2) {
7653                 final PendingIntent pi = PendingIntent.getBroadcast(mContext, 0 /* requestCode */,
7654                         new Intent("a" + j), FLAG_IMMUTABLE);
7655                 mCm.requestNetwork(networkRequest, pi);
7656                 registered.add(pi);
7657             } else {
7658                 final PendingIntent pi = PendingIntent.getBroadcast(mContext, 0 /* requestCode */,
7659                         new Intent("b" + j), FLAG_IMMUTABLE);
7660                 mCm.registerNetworkCallback(networkRequest, pi);
7661                 registered.add(pi);
7662             }
7663         }
7664 
7665         // Test that the limit is enforced when MAX_REQUESTS simultaneous requests are added.
7666         assertThrows(TooManyRequestsException.class, () ->
7667                 mCm.requestNetwork(networkRequest, new NetworkCallback())
7668         );
7669         assertThrows(TooManyRequestsException.class, () ->
7670                 mCm.registerNetworkCallback(networkRequest, new NetworkCallback())
7671         );
7672         assertThrows(TooManyRequestsException.class, () ->
7673                 mCm.requestNetwork(networkRequest,
7674                         PendingIntent.getBroadcast(mContext, 0 /* requestCode */,
7675                                 new Intent("c"), FLAG_IMMUTABLE))
7676         );
7677         assertThrows(TooManyRequestsException.class, () ->
7678                 mCm.registerNetworkCallback(networkRequest,
7679                         PendingIntent.getBroadcast(mContext, 0 /* requestCode */,
7680                                 new Intent("d"), FLAG_IMMUTABLE))
7681         );
7682 
7683         // The system gets another SYSTEM_ONLY_MAX_REQUESTS slots.
7684         final Handler handler = new Handler(ConnectivityThread.getInstanceLooper());
7685         withPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, () -> {
7686             ArrayList<NetworkCallback> systemRegistered = new ArrayList<>();
7687             for (int i = 0; i < SYSTEM_ONLY_MAX_REQUESTS - 1; i++) {
7688                 NetworkCallback cb = new NetworkCallback();
7689                 if (i % 2 == 0) {
7690                     mCm.registerDefaultNetworkCallbackForUid(1000000 + i, cb, handler);
7691                 } else {
7692                     mCm.registerNetworkCallback(networkRequest, cb);
7693                 }
7694                 systemRegistered.add(cb);
7695             }
7696             waitForIdle();
7697 
7698             assertThrows(TooManyRequestsException.class, () ->
7699                     mCm.registerDefaultNetworkCallbackForUid(1001042, new NetworkCallback(),
7700                             handler));
7701             assertThrows(TooManyRequestsException.class, () ->
7702                     mCm.registerNetworkCallback(networkRequest, new NetworkCallback()));
7703 
7704             for (NetworkCallback callback : systemRegistered) {
7705                 mCm.unregisterNetworkCallback(callback);
7706             }
7707             waitForIdle();  // Wait for requests to be unregistered before giving up the permission.
7708         });
7709 
7710         for (Object o : registered) {
7711             if (o instanceof NetworkCallback) {
7712                 mCm.unregisterNetworkCallback((NetworkCallback) o);
7713             }
7714             if (o instanceof PendingIntent) {
7715                 mCm.unregisterNetworkCallback((PendingIntent) o);
7716             }
7717         }
7718         waitForIdle();
7719 
7720         // Test that the limit is not hit when MAX_REQUESTS requests are added and removed.
7721         for (int i = 0; i < MAX_REQUESTS; i++) {
7722             NetworkCallback networkCallback = new NetworkCallback();
7723             mCm.requestNetwork(networkRequest, networkCallback);
7724             mCm.unregisterNetworkCallback(networkCallback);
7725             // While requestNetwork increases the count synchronously, unregister decreases it
7726             // asynchronously on a handler, so unregistering doesn't immediately free up
7727             // a slot : calling unregister-register when max requests are registered throws.
7728             // Potential fix : ConnectivityService catches TooManyRequestsException once when
7729             // creating NetworkRequestInfo and waits for handler thread (see
7730             // https://r.android.com/2707373 for impl). However, this complexity is not equal to
7731             // the issue ; the purpose of having "max requests" is only to help apps detect leaks.
7732             // Apps relying on exact enforcement or rapid request registration should reconsider.
7733             //
7734             // In this test, test thread registering all before handler thread decrements can cause
7735             // flakes. A single waitForIdle at (e.g.) MAX_REQUESTS / 2 processes decrements up to
7736             // that point, fixing the flake.
7737             if (MAX_REQUESTS / 2 == i) waitForIdle();
7738         }
7739         waitForIdle();
7740 
7741         for (int i = 0; i < MAX_REQUESTS; i++) {
7742             NetworkCallback networkCallback = new NetworkCallback();
7743             mCm.registerNetworkCallback(networkRequest, networkCallback);
7744             mCm.unregisterNetworkCallback(networkCallback);
7745             // See comment above for the reasons for this wait.
7746             if (MAX_REQUESTS / 2 == i) waitForIdle();
7747         }
7748         waitForIdle();
7749 
7750         for (int i = 0; i < MAX_REQUESTS; i++) {
7751             NetworkCallback networkCallback = new NetworkCallback();
7752             mCm.registerDefaultNetworkCallback(networkCallback);
7753             mCm.unregisterNetworkCallback(networkCallback);
7754             // See comment above for the reasons for this wait.
7755             if (MAX_REQUESTS / 2 == i) waitForIdle();
7756         }
7757         waitForIdle();
7758 
7759         for (int i = 0; i < MAX_REQUESTS; i++) {
7760             NetworkCallback networkCallback = new NetworkCallback();
7761             mCm.registerDefaultNetworkCallback(networkCallback);
7762             mCm.unregisterNetworkCallback(networkCallback);
7763             // See comment above for the reasons for this wait.
7764             if (MAX_REQUESTS / 2 == i) waitForIdle();
7765         }
7766         waitForIdle();
7767 
7768         withPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, () -> {
7769             for (int i = 0; i < MAX_REQUESTS; i++) {
7770                 NetworkCallback networkCallback = new NetworkCallback();
7771                 mCm.registerDefaultNetworkCallbackForUid(1000000 + i, networkCallback,
7772                         new Handler(ConnectivityThread.getInstanceLooper()));
7773                 mCm.unregisterNetworkCallback(networkCallback);
7774                 // See comment above for the reasons for this wait.
7775                 if (MAX_REQUESTS / 2 == i) waitForIdle();
7776             }
7777         });
7778         waitForIdle();
7779 
7780         for (int i = 0; i < MAX_REQUESTS; i++) {
7781             final PendingIntent pendingIntent = PendingIntent.getBroadcast(
7782                     mContext, 0 /* requestCode */, new Intent("e" + i), FLAG_IMMUTABLE);
7783             mCm.requestNetwork(networkRequest, pendingIntent);
7784             mCm.unregisterNetworkCallback(pendingIntent);
7785             // See comment above for the reasons for this wait.
7786             if (MAX_REQUESTS / 2 == i) waitForIdle();
7787         }
7788         waitForIdle();
7789 
7790         for (int i = 0; i < MAX_REQUESTS; i++) {
7791             final PendingIntent pendingIntent = PendingIntent.getBroadcast(
7792                     mContext, 0 /* requestCode */, new Intent("f" + i), FLAG_IMMUTABLE);
7793             mCm.registerNetworkCallback(networkRequest, pendingIntent);
7794             mCm.unregisterNetworkCallback(pendingIntent);
7795             // See comment above for the reasons for this wait.
7796             if (MAX_REQUESTS / 2 == i) waitForIdle();
7797         }
7798     }
7799 
7800     @Test
7801     public void testNetworkInfoOfTypeNone() throws Exception {
7802         ExpectedBroadcast b = expectConnectivityAction(1);
7803 
7804         verifyNoNetwork();
7805         TestNetworkAgentWrapper wifiAware = new TestNetworkAgentWrapper(TRANSPORT_WIFI_AWARE);
7806         assertNull(mCm.getActiveNetworkInfo());
7807 
7808         Network[] allNetworks = mCm.getAllNetworks();
7809         assertLength(1, allNetworks);
7810         Network network = allNetworks[0];
7811         NetworkCapabilities capabilities = mCm.getNetworkCapabilities(network);
7812         assertTrue(capabilities.hasTransport(TRANSPORT_WIFI_AWARE));
7813 
7814         final NetworkRequest request =
7815                 new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI_AWARE).build();
7816         final TestNetworkCallback callback = new TestNetworkCallback();
7817         mCm.registerNetworkCallback(request, callback);
7818 
7819         // Bring up wifi aware network.
7820         wifiAware.connect(false, false, false /* privateDnsProbeSent */);
7821         callback.expectAvailableCallbacksUnvalidated(wifiAware);
7822 
7823         assertNull(mCm.getActiveNetworkInfo());
7824         assertNull(mCm.getActiveNetwork());
7825         // TODO: getAllNetworkInfo is dirty and returns a non-empty array right from the start
7826         // of this test. Fix it and uncomment the assert below.
7827         //assertEmpty(mCm.getAllNetworkInfo());
7828 
7829         // Disconnect wifi aware network.
7830         wifiAware.disconnect();
7831         callback.expect(LOST, TIMEOUT_MS);
7832         mCm.unregisterNetworkCallback(callback);
7833 
7834         verifyNoNetwork();
7835         b.expectNoBroadcast(10);
7836     }
7837 
7838     @Test
7839     public void testDeprecatedAndUnsupportedOperations() throws Exception {
7840         final int TYPE_NONE = ConnectivityManager.TYPE_NONE;
7841         assertNull(mCm.getNetworkInfo(TYPE_NONE));
7842         assertNull(mCm.getNetworkForType(TYPE_NONE));
7843         assertNull(mCm.getLinkProperties(TYPE_NONE));
7844         assertFalse(mCm.isNetworkSupported(TYPE_NONE));
7845 
7846         assertThrows(IllegalArgumentException.class,
7847                 () -> mCm.networkCapabilitiesForType(TYPE_NONE));
7848 
7849         Class<UnsupportedOperationException> unsupported = UnsupportedOperationException.class;
7850         assertThrows(unsupported, () -> mCm.startUsingNetworkFeature(TYPE_WIFI, ""));
7851         assertThrows(unsupported, () -> mCm.stopUsingNetworkFeature(TYPE_WIFI, ""));
7852         // TODO: let test context have configuration application target sdk version
7853         // and test that pre-M requesting for TYPE_NONE sends back APN_REQUEST_FAILED
7854         assertThrows(unsupported, () -> mCm.startUsingNetworkFeature(TYPE_NONE, ""));
7855         assertThrows(unsupported, () -> mCm.stopUsingNetworkFeature(TYPE_NONE, ""));
7856         assertThrows(unsupported, () -> mCm.requestRouteToHostAddress(TYPE_NONE, null));
7857     }
7858 
7859     @Test
7860     public void testLinkPropertiesEnsuresDirectlyConnectedRoutes() throws Exception {
7861         final NetworkRequest networkRequest = new NetworkRequest.Builder()
7862                 .addTransportType(TRANSPORT_WIFI).build();
7863         final TestNetworkCallback networkCallback = new TestNetworkCallback();
7864         mCm.registerNetworkCallback(networkRequest, networkCallback);
7865 
7866         LinkProperties lp = new LinkProperties();
7867         lp.setInterfaceName(WIFI_IFNAME);
7868         LinkAddress myIpv4Address = new LinkAddress("192.168.12.3/24");
7869         RouteInfo myIpv4DefaultRoute = new RouteInfo((IpPrefix) null,
7870                 InetAddresses.parseNumericAddress("192.168.12.1"), lp.getInterfaceName());
7871         lp.addLinkAddress(myIpv4Address);
7872         lp.addRoute(myIpv4DefaultRoute);
7873 
7874         // Verify direct routes are added when network agent is first registered in
7875         // ConnectivityService.
7876         TestNetworkAgentWrapper networkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, lp);
7877         networkAgent.connect(true);
7878         networkCallback.expect(AVAILABLE, networkAgent);
7879         networkCallback.expect(NETWORK_CAPS_UPDATED, networkAgent);
7880         CallbackEntry.LinkPropertiesChanged cbi =
7881                 networkCallback.expect(LINK_PROPERTIES_CHANGED, networkAgent);
7882         networkCallback.expect(BLOCKED_STATUS, networkAgent);
7883         networkCallback.expectCaps(networkAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
7884         networkCallback.assertNoCallback();
7885         checkDirectlyConnectedRoutes(cbi.getLp(), asList(myIpv4Address),
7886                 asList(myIpv4DefaultRoute));
7887         checkDirectlyConnectedRoutes(mCm.getLinkProperties(networkAgent.getNetwork()),
7888                 asList(myIpv4Address), asList(myIpv4DefaultRoute));
7889 
7890         // Verify direct routes are added during subsequent link properties updates.
7891         LinkProperties newLp = new LinkProperties(lp);
7892         LinkAddress myIpv6Address1 = new LinkAddress("fe80::cafe/64");
7893         LinkAddress myIpv6Address2 = new LinkAddress("2001:db8::2/64");
7894         newLp.addLinkAddress(myIpv6Address1);
7895         newLp.addLinkAddress(myIpv6Address2);
7896         networkAgent.sendLinkProperties(newLp);
7897         cbi = networkCallback.expect(LINK_PROPERTIES_CHANGED, networkAgent);
7898         networkCallback.assertNoCallback();
7899         checkDirectlyConnectedRoutes(cbi.getLp(),
7900                 asList(myIpv4Address, myIpv6Address1, myIpv6Address2),
7901                 asList(myIpv4DefaultRoute));
7902         mCm.unregisterNetworkCallback(networkCallback);
7903     }
7904 
7905     private void expectNotifyNetworkStatus(List<Network> allNetworks, List<Network> defaultNetworks,
7906             String defaultIface, Integer vpnUid, String vpnIfname, List<String> underlyingIfaces)
7907             throws Exception {
7908         ArgumentCaptor<List<Network>> defaultNetworksCaptor = ArgumentCaptor.forClass(List.class);
7909         ArgumentCaptor<List<UnderlyingNetworkInfo>> vpnInfosCaptor =
7910                 ArgumentCaptor.forClass(List.class);
7911         ArgumentCaptor<List<NetworkStateSnapshot>> snapshotsCaptor =
7912                 ArgumentCaptor.forClass(List.class);
7913 
7914         verify(mStatsManager, atLeastOnce()).notifyNetworkStatus(defaultNetworksCaptor.capture(),
7915                 snapshotsCaptor.capture(), eq(defaultIface), vpnInfosCaptor.capture());
7916 
7917         assertSameElements(defaultNetworks, defaultNetworksCaptor.getValue());
7918 
7919         List<Network> snapshotNetworks = new ArrayList<Network>();
7920         for (NetworkStateSnapshot ns : snapshotsCaptor.getValue()) {
7921             snapshotNetworks.add(ns.getNetwork());
7922         }
7923         assertSameElements(allNetworks, snapshotNetworks);
7924 
7925         if (defaultIface != null) {
7926             assertNotNull(
7927                     "Did not find interface " + defaultIface + " in call to notifyNetworkStatus",
7928                     CollectionUtils.findFirst(snapshotsCaptor.getValue(), (ns) -> {
7929                         final LinkProperties lp = ns.getLinkProperties();
7930                         if (lp != null && TextUtils.equals(defaultIface, lp.getInterfaceName())) {
7931                             return true;
7932                         }
7933                         return false;
7934                     }));
7935         }
7936 
7937         List<UnderlyingNetworkInfo> infos = vpnInfosCaptor.getValue();
7938         if (vpnUid != null) {
7939             assertEquals("Should have exactly one VPN:", 1, infos.size());
7940             UnderlyingNetworkInfo info = infos.get(0);
7941             assertEquals("Unexpected VPN owner:", (int) vpnUid, info.getOwnerUid());
7942             assertEquals("Unexpected VPN interface:", vpnIfname, info.getInterface());
7943             assertSameElements(underlyingIfaces, info.getUnderlyingInterfaces());
7944         } else {
7945             assertEquals(0, infos.size());
7946             return;
7947         }
7948     }
7949 
7950     private void expectNotifyNetworkStatus(
7951             List<Network> allNetworks, List<Network> defaultNetworks, String defaultIface)
7952             throws Exception {
7953         expectNotifyNetworkStatus(allNetworks, defaultNetworks, defaultIface, null, null,
7954                 List.of());
7955     }
7956 
7957     private List<Network> onlyCell() {
7958         return List.of(mCellAgent.getNetwork());
7959     }
7960 
7961     private List<Network> onlyWifi() {
7962         return List.of(mWiFiAgent.getNetwork());
7963     }
7964 
7965     private List<Network> cellAndWifi() {
7966         return List.of(mCellAgent.getNetwork(), mWiFiAgent.getNetwork());
7967     }
7968 
7969     @Test
7970     public void testStatsIfacesChanged() throws Exception {
7971         LinkProperties cellLp = new LinkProperties();
7972         cellLp.setInterfaceName(MOBILE_IFNAME);
7973         LinkProperties wifiLp = new LinkProperties();
7974         wifiLp.setInterfaceName(WIFI_IFNAME);
7975 
7976         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
7977         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
7978 
7979         // Simple connection with initial LP should have updated ifaces.
7980         mCellAgent.connect(false);
7981         waitForIdle();
7982         List<Network> allNetworks = mService.shouldCreateNetworksImmediately(
7983                 mCellAgent.getNetworkCapabilities()) ? cellAndWifi() : onlyCell();
7984         expectNotifyNetworkStatus(allNetworks, onlyCell(), MOBILE_IFNAME);
7985         reset(mStatsManager);
7986 
7987         // Verify change fields other than interfaces does not trigger a notification to NSS.
7988         cellLp.addLinkAddress(new LinkAddress("192.0.2.4/24"));
7989         cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("192.0.2.4"),
7990                 MOBILE_IFNAME));
7991         cellLp.setDnsServers(List.of(InetAddress.getAllByName("8.8.8.8")));
7992         mCellAgent.sendLinkProperties(cellLp);
7993         verifyNoMoreInteractions(mStatsManager);
7994         reset(mStatsManager);
7995 
7996         // Default network switch should update ifaces.
7997         mWiFiAgent.connect(false);
7998         mWiFiAgent.sendLinkProperties(wifiLp);
7999         waitForIdle();
8000         assertEquals(wifiLp, mService.getActiveLinkProperties());
8001         expectNotifyNetworkStatus(cellAndWifi(), onlyWifi(), WIFI_IFNAME);
8002         reset(mStatsManager);
8003 
8004         // Disconnecting a network updates ifaces again. The soon-to-be disconnected interface is
8005         // still in the list to ensure that stats are counted on that interface.
8006         // TODO: this means that if anything else uses that interface for any other reason before
8007         // notifyNetworkStatus is called again, traffic on that interface will be accounted to the
8008         // disconnected network. This is likely a bug in ConnectivityService; it should probably
8009         // call notifyNetworkStatus again without the disconnected network.
8010         mCellAgent.disconnect();
8011         waitForIdle();
8012         expectNotifyNetworkStatus(cellAndWifi(), onlyWifi(), WIFI_IFNAME);
8013         verifyNoMoreInteractions(mStatsManager);
8014         reset(mStatsManager);
8015 
8016         // Connecting a network updates ifaces even if the network doesn't become default.
8017         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
8018         mCellAgent.connect(false);
8019         waitForIdle();
8020         expectNotifyNetworkStatus(cellAndWifi(), onlyWifi(), WIFI_IFNAME);
8021         reset(mStatsManager);
8022 
8023         // Disconnect should update ifaces.
8024         mWiFiAgent.disconnect();
8025         waitForIdle();
8026         expectNotifyNetworkStatus(onlyCell(), onlyCell(), MOBILE_IFNAME);
8027         reset(mStatsManager);
8028 
8029         // Metered change should update ifaces
8030         mCellAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
8031         waitForIdle();
8032         expectNotifyNetworkStatus(onlyCell(), onlyCell(), MOBILE_IFNAME);
8033         reset(mStatsManager);
8034 
8035         mCellAgent.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
8036         waitForIdle();
8037         expectNotifyNetworkStatus(onlyCell(), onlyCell(), MOBILE_IFNAME);
8038         reset(mStatsManager);
8039 
8040         // Temp metered change shouldn't update ifaces
8041         mCellAgent.addCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED);
8042         waitForIdle();
8043         verify(mStatsManager, never()).notifyNetworkStatus(eq(onlyCell()),
8044                 any(List.class), eq(MOBILE_IFNAME), any(List.class));
8045         reset(mStatsManager);
8046 
8047         // Congested change shouldn't update ifaces
8048         mCellAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED);
8049         waitForIdle();
8050         verify(mStatsManager, never()).notifyNetworkStatus(eq(onlyCell()),
8051                 any(List.class), eq(MOBILE_IFNAME), any(List.class));
8052         reset(mStatsManager);
8053 
8054         // Roaming change should update ifaces
8055         mCellAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING);
8056         waitForIdle();
8057         expectNotifyNetworkStatus(onlyCell(), onlyCell(), MOBILE_IFNAME);
8058         reset(mStatsManager);
8059 
8060         // Test VPNs.
8061         final LinkProperties lp = new LinkProperties();
8062         lp.setInterfaceName(VPN_IFNAME);
8063 
8064         mMockVpn.establishForMyUid(lp);
8065         assertUidRangesUpdatedForMyUid(true);
8066 
8067         final List<Network> cellAndVpn = List.of(mCellAgent.getNetwork(), mMockVpn.getNetwork());
8068 
8069         // A VPN with default (null) underlying networks sets the underlying network's interfaces...
8070         expectNotifyNetworkStatus(cellAndVpn, cellAndVpn, MOBILE_IFNAME, Process.myUid(),
8071                 VPN_IFNAME, List.of(MOBILE_IFNAME));
8072 
8073         // ...and updates them as the default network switches.
8074         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
8075         mWiFiAgent.connect(false);
8076         mWiFiAgent.sendLinkProperties(wifiLp);
8077         final Network[] onlyNull = new Network[]{null};
8078         final List<Network> wifiAndVpn = List.of(mWiFiAgent.getNetwork(), mMockVpn.getNetwork());
8079         final List<Network> cellWifiAndVpn = List.of(mCellAgent.getNetwork(),
8080                 mWiFiAgent.getNetwork(), mMockVpn.getNetwork());
8081         final Network[] cellNullAndWifi =
8082                 new Network[] { mCellAgent.getNetwork(), null, mWiFiAgent.getNetwork() };
8083 
8084         waitForIdle();
8085         assertEquals(wifiLp, mService.getActiveLinkProperties());
8086         expectNotifyNetworkStatus(cellWifiAndVpn, wifiAndVpn, WIFI_IFNAME, Process.myUid(),
8087                 VPN_IFNAME, List.of(WIFI_IFNAME));
8088         reset(mStatsManager);
8089 
8090         // A VPN that sets its underlying networks passes the underlying interfaces, and influences
8091         // the default interface sent to NetworkStatsService by virtue of applying to the system
8092         // server UID (or, in this test, to the test's UID). This is the reason for sending
8093         // MOBILE_IFNAME even though the default network is wifi.
8094         // TODO: fix this to pass in the actual default network interface. Whether or not the VPN
8095         // applies to the system server UID should not have any bearing on network stats.
8096         mMockVpn.setUnderlyingNetworks(onlyCell().toArray(new Network[0]));
8097         waitForIdle();
8098         expectNotifyNetworkStatus(cellWifiAndVpn, wifiAndVpn, MOBILE_IFNAME, Process.myUid(),
8099                 VPN_IFNAME, List.of(MOBILE_IFNAME));
8100         reset(mStatsManager);
8101 
8102         mMockVpn.setUnderlyingNetworks(cellAndWifi().toArray(new Network[0]));
8103         waitForIdle();
8104         expectNotifyNetworkStatus(cellWifiAndVpn, wifiAndVpn, MOBILE_IFNAME, Process.myUid(),
8105                 VPN_IFNAME,  List.of(MOBILE_IFNAME, WIFI_IFNAME));
8106         reset(mStatsManager);
8107 
8108         // Null underlying networks are ignored.
8109         mMockVpn.setUnderlyingNetworks(cellNullAndWifi);
8110         waitForIdle();
8111         expectNotifyNetworkStatus(cellWifiAndVpn, wifiAndVpn, MOBILE_IFNAME, Process.myUid(),
8112                 VPN_IFNAME,  List.of(MOBILE_IFNAME, WIFI_IFNAME));
8113         reset(mStatsManager);
8114 
8115         // If an underlying network disconnects, that interface should no longer be underlying.
8116         // This doesn't actually work because disconnectAndDestroyNetwork only notifies
8117         // NetworkStatsService before the underlying network is actually removed. So the underlying
8118         // network will only be removed if notifyIfacesChangedForNetworkStats is called again. This
8119         // could result in incorrect data usage measurements if the interface used by the
8120         // disconnected network is reused by a system component that does not register an agent for
8121         // it (e.g., tethering).
8122         mCellAgent.disconnect();
8123         waitForIdle();
8124         assertNull(mService.getLinkProperties(mCellAgent.getNetwork()));
8125         expectNotifyNetworkStatus(cellWifiAndVpn, wifiAndVpn, MOBILE_IFNAME, Process.myUid(),
8126                 VPN_IFNAME, List.of(MOBILE_IFNAME, WIFI_IFNAME));
8127 
8128         // Confirm that we never tell NetworkStatsService that cell is no longer the underlying
8129         // network for the VPN...
8130         verify(mStatsManager, never()).notifyNetworkStatus(any(List.class),
8131                 any(List.class), any() /* anyString() doesn't match null */,
8132                 argThat(infos -> infos.get(0).getUnderlyingInterfaces().size() == 1
8133                         && WIFI_IFNAME.equals(infos.get(0).getUnderlyingInterfaces().get(0))));
8134         verifyNoMoreInteractions(mStatsManager);
8135         reset(mStatsManager);
8136 
8137         // ... but if something else happens that causes notifyIfacesChangedForNetworkStats to be
8138         // called again, it does. For example, connect Ethernet, but with a low score, such that it
8139         // does not become the default network.
8140         mEthernetAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
8141         mEthernetAgent.setScore(
8142                 new NetworkScore.Builder().setLegacyInt(30).setExiting(true).build());
8143         mEthernetAgent.connect(false);
8144         waitForIdle();
8145         verify(mStatsManager).notifyNetworkStatus(any(List.class),
8146                 any(List.class), any() /* anyString() doesn't match null */,
8147                 argThat(vpnInfos -> vpnInfos.get(0).getUnderlyingInterfaces().size() == 1
8148                         && WIFI_IFNAME.equals(vpnInfos.get(0).getUnderlyingInterfaces().get(0))));
8149         mEthernetAgent.disconnect();
8150         waitForIdle();
8151         reset(mStatsManager);
8152 
8153         // When a VPN declares no underlying networks (i.e., no connectivity), getAllVpnInfo
8154         // does not return the VPN, so CS does not pass it to NetworkStatsService. This causes
8155         // NetworkStatsFactory#adjustForTunAnd464Xlat not to attempt any VPN data migration, which
8156         // is probably a performance improvement (though it's very unlikely that a VPN would declare
8157         // no underlying networks).
8158         // Also, for the same reason as above, the active interface passed in is null.
8159         mMockVpn.setUnderlyingNetworks(new Network[0]);
8160         waitForIdle();
8161         expectNotifyNetworkStatus(wifiAndVpn, wifiAndVpn, null);
8162         reset(mStatsManager);
8163 
8164         // Specifying only a null underlying network is the same as no networks.
8165         mMockVpn.setUnderlyingNetworks(onlyNull);
8166         waitForIdle();
8167         expectNotifyNetworkStatus(wifiAndVpn, wifiAndVpn, null);
8168         reset(mStatsManager);
8169 
8170         // Specifying networks that are all disconnected is the same as specifying no networks.
8171         mMockVpn.setUnderlyingNetworks(onlyCell().toArray(new Network[0]));
8172         waitForIdle();
8173         expectNotifyNetworkStatus(wifiAndVpn, wifiAndVpn, null);
8174         reset(mStatsManager);
8175 
8176         // Passing in null again means follow the default network again.
8177         mMockVpn.setUnderlyingNetworks(null);
8178         waitForIdle();
8179         expectNotifyNetworkStatus(wifiAndVpn, wifiAndVpn, WIFI_IFNAME, Process.myUid(), VPN_IFNAME,
8180                 List.of(WIFI_IFNAME));
8181         reset(mStatsManager);
8182     }
8183 
8184     @Test
8185     public void testAdminUidsRedacted() throws Exception {
8186         final int[] adminUids = new int[] {Process.myUid() + 1};
8187         final NetworkCapabilities ncTemplate = new NetworkCapabilities();
8188         ncTemplate.setAdministratorUids(adminUids);
8189         mCellAgent =
8190                 new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, new LinkProperties(), ncTemplate);
8191         mCellAgent.connect(false /* validated */);
8192 
8193         // Verify case where caller has permission
8194         mServiceContext.setPermission(
8195                 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, PERMISSION_GRANTED);
8196         TestNetworkCallback callback = new TestNetworkCallback();
8197         mCm.registerDefaultNetworkCallback(callback);
8198         callback.expect(AVAILABLE, mCellAgent);
8199         callback.expectCaps(mCellAgent, c -> Arrays.equals(adminUids, c.getAdministratorUids()));
8200         mCm.unregisterNetworkCallback(callback);
8201 
8202         // Verify case where caller does NOT have permission
8203         mServiceContext.setPermission(
8204                 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, PERMISSION_DENIED);
8205         mServiceContext.setPermission(NETWORK_STACK, PERMISSION_DENIED);
8206         callback = new TestNetworkCallback();
8207         mCm.registerDefaultNetworkCallback(callback);
8208         callback.expect(AVAILABLE, mCellAgent);
8209         callback.expectCaps(mCellAgent, c -> c.getAdministratorUids().length == 0);
8210     }
8211 
8212     @Test
8213     public void testNonVpnUnderlyingNetworks() throws Exception {
8214         // Ensure wifi and cellular are not torn down.
8215         for (int transport : new int[]{TRANSPORT_CELLULAR, TRANSPORT_WIFI}) {
8216             final NetworkRequest request = new NetworkRequest.Builder()
8217                     .addTransportType(transport)
8218                     .removeCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
8219                     .build();
8220             mCm.requestNetwork(request, new NetworkCallback());
8221         }
8222 
8223         // Connect a VCN-managed wifi network.
8224         final LinkProperties wifiLp = new LinkProperties();
8225         wifiLp.setInterfaceName(WIFI_IFNAME);
8226         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp);
8227         mWiFiAgent.removeCapability(NET_CAPABILITY_NOT_VCN_MANAGED);
8228         mWiFiAgent.addCapability(NET_CAPABILITY_NOT_METERED);
8229         mWiFiAgent.connect(true /* validated */);
8230 
8231         final List<Network> none = List.of();
8232         expectNotifyNetworkStatus(onlyWifi(), none, null);  // Wifi is not the default network
8233 
8234         // Create a virtual network based on the wifi network.
8235         final int ownerUid = 10042;
8236         NetworkCapabilities nc = new NetworkCapabilities.Builder()
8237                 .setOwnerUid(ownerUid)
8238                 .setAdministratorUids(new int[]{ownerUid})
8239                 .build();
8240         final String vcnIface = "ipsec42";
8241         final LinkProperties lp = new LinkProperties();
8242         lp.setInterfaceName(vcnIface);
8243         final TestNetworkAgentWrapper vcn = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, lp, nc);
8244         vcn.setUnderlyingNetworks(List.of(mWiFiAgent.getNetwork()));
8245         vcn.connect(false /* validated */);
8246 
8247         final TestNetworkCallback callback = new TestNetworkCallback();
8248         mCm.registerDefaultNetworkCallback(callback);
8249         callback.expectAvailableCallbacksUnvalidated(vcn);
8250 
8251         // The underlying wifi network's capabilities are not propagated to the virtual network,
8252         // but NetworkStatsService is informed of the underlying interface.
8253         nc = mCm.getNetworkCapabilities(vcn.getNetwork());
8254         assertFalse(nc.hasTransport(TRANSPORT_WIFI));
8255         assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED));
8256         final List<Network> onlyVcn = List.of(vcn.getNetwork());
8257         final List<Network> vcnAndWifi = List.of(vcn.getNetwork(), mWiFiAgent.getNetwork());
8258         expectNotifyNetworkStatus(vcnAndWifi, onlyVcn, vcnIface, ownerUid, vcnIface,
8259                 List.of(WIFI_IFNAME));
8260 
8261         // Add NOT_METERED to the underlying network, check that it is not propagated.
8262         mWiFiAgent.addCapability(NET_CAPABILITY_NOT_METERED);
8263         callback.assertNoCallback();
8264         nc = mCm.getNetworkCapabilities(vcn.getNetwork());
8265         assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED));
8266 
8267         // Switch underlying networks.
8268         final LinkProperties cellLp = new LinkProperties();
8269         cellLp.setInterfaceName(MOBILE_IFNAME);
8270         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
8271         mCellAgent.removeCapability(NET_CAPABILITY_NOT_VCN_MANAGED);
8272         mCellAgent.addCapability(NET_CAPABILITY_NOT_ROAMING);
8273         mCellAgent.connect(false /* validated */);
8274         vcn.setUnderlyingNetworks(List.of(mCellAgent.getNetwork()));
8275 
8276         // The underlying capability changes do not propagate to the virtual network, but
8277         // NetworkStatsService is informed of the new underlying interface.
8278         callback.assertNoCallback();
8279         nc = mCm.getNetworkCapabilities(vcn.getNetwork());
8280         assertFalse(nc.hasTransport(TRANSPORT_WIFI));
8281         assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_ROAMING));
8282         final List<Network> vcnWifiAndCell = List.of(vcn.getNetwork(),
8283                 mWiFiAgent.getNetwork(), mCellAgent.getNetwork());
8284         expectNotifyNetworkStatus(vcnWifiAndCell, onlyVcn, vcnIface, ownerUid, vcnIface,
8285                 List.of(MOBILE_IFNAME));
8286     }
8287 
8288     @Test
8289     public void testBasicDnsConfigurationPushed() throws Exception {
8290         setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
8291 
8292         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
8293         final int netId = mCellAgent.getNetwork().netId;
8294         waitForIdle();
8295         if (mService.shouldCreateNetworksImmediately(mCellAgent.getNetworkCapabilities())) {
8296             verify(mMockDnsResolver, times(1)).createNetworkCache(netId);
8297         } else {
8298             verify(mMockDnsResolver, never()).setResolverConfiguration(any());
8299         }
8300 
8301         final LinkProperties cellLp = new LinkProperties();
8302         cellLp.setInterfaceName(MOBILE_IFNAME);
8303         // Add IPv4 and IPv6 default routes, because DNS-over-TLS code does
8304         // "is-reachable" testing in order to not program netd with unreachable
8305         // nameservers that it might try repeated to validate.
8306         cellLp.addLinkAddress(new LinkAddress("192.0.2.4/24"));
8307         cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("192.0.2.4"),
8308                 MOBILE_IFNAME));
8309         cellLp.addLinkAddress(new LinkAddress("2001:db8:1::1/64"));
8310         cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("2001:db8:1::1"),
8311                 MOBILE_IFNAME));
8312         mCellAgent.sendLinkProperties(cellLp);
8313         mCellAgent.connect(false);
8314         waitForIdle();
8315         if (!mService.shouldCreateNetworksImmediately(mCellAgent.getNetworkCapabilities())) {
8316             // CS tells dnsresolver about the empty DNS config for this network.
8317             verify(mMockDnsResolver, times(1)).createNetworkCache(netId);
8318         }
8319         verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(any());
8320 
8321         verifyNoMoreInteractions(mMockDnsResolver);
8322         reset(mMockDnsResolver);
8323 
8324         cellLp.addDnsServer(InetAddress.getByName("2001:db8::1"));
8325         mCellAgent.sendLinkProperties(cellLp);
8326         waitForIdle();
8327         verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
8328                 mResolverParamsParcelCaptor.capture());
8329         ResolverParamsParcel resolvrParams = mResolverParamsParcelCaptor.getValue();
8330         assertEquals(1, resolvrParams.servers.length);
8331         assertTrue(CollectionUtils.contains(resolvrParams.servers, "2001:db8::1"));
8332         // Opportunistic mode.
8333         assertTrue(CollectionUtils.contains(resolvrParams.tlsServers, "2001:db8::1"));
8334         reset(mMockDnsResolver);
8335 
8336         cellLp.addDnsServer(InetAddress.getByName("192.0.2.1"));
8337         mCellAgent.sendLinkProperties(cellLp);
8338         waitForIdle();
8339         verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
8340                 mResolverParamsParcelCaptor.capture());
8341         resolvrParams = mResolverParamsParcelCaptor.getValue();
8342         assertEquals(2, resolvrParams.servers.length);
8343         assertTrue(new ArraySet<>(resolvrParams.servers).containsAll(
8344                 asList("2001:db8::1", "192.0.2.1")));
8345         // Opportunistic mode.
8346         assertEquals(2, resolvrParams.tlsServers.length);
8347         assertTrue(new ArraySet<>(resolvrParams.tlsServers).containsAll(
8348                 asList("2001:db8::1", "192.0.2.1")));
8349         reset(mMockDnsResolver);
8350 
8351         final String TLS_SPECIFIER = "tls.example.com";
8352         final String TLS_SERVER6 = "2001:db8:53::53";
8353         final InetAddress[] TLS_IPS = new InetAddress[]{ InetAddress.getByName(TLS_SERVER6) };
8354         final String[] TLS_SERVERS = new String[]{ TLS_SERVER6 };
8355         mCellAgent.mNmCallbacks.notifyPrivateDnsConfigResolved(
8356                 new PrivateDnsConfig(TLS_SPECIFIER, TLS_IPS).toParcel());
8357 
8358         waitForIdle();
8359         verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
8360                 mResolverParamsParcelCaptor.capture());
8361         resolvrParams = mResolverParamsParcelCaptor.getValue();
8362         assertEquals(2, resolvrParams.servers.length);
8363         assertTrue(new ArraySet<>(resolvrParams.servers).containsAll(
8364                 asList("2001:db8::1", "192.0.2.1")));
8365         reset(mMockDnsResolver);
8366     }
8367 
8368     @Test
8369     public void testDnsConfigurationTransTypesPushed() throws Exception {
8370         final NetworkRequest request = new NetworkRequest.Builder()
8371                 .clearCapabilities().addCapability(NET_CAPABILITY_INTERNET)
8372                 .build();
8373         final TestNetworkCallback callback = new TestNetworkCallback();
8374         mCm.registerNetworkCallback(request, callback);
8375 
8376         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
8377         mWiFiAgent.connect(false);
8378         callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
8379         verify(mMockDnsResolver, times(1)).createNetworkCache(eq(mWiFiAgent.getNetwork().netId));
8380         verify(mMockDnsResolver, times(2)).setResolverConfiguration(
8381                 mResolverParamsParcelCaptor.capture());
8382         final ResolverParamsParcel resolverParams = mResolverParamsParcelCaptor.getValue();
8383         assertContainsExactly(resolverParams.transportTypes, TRANSPORT_WIFI);
8384         reset(mMockDnsResolver);
8385     }
8386 
8387     @Test
8388     public void testPrivateDnsNotification() throws Exception {
8389         NetworkRequest request = new NetworkRequest.Builder()
8390                 .clearCapabilities().addCapability(NET_CAPABILITY_INTERNET)
8391                 .build();
8392         TestNetworkCallback callback = new TestNetworkCallback();
8393         mCm.registerNetworkCallback(request, callback);
8394         // Bring up wifi.
8395         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
8396         mWiFiAgent.connect(false);
8397         callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
8398         // Private DNS resolution failed, checking if the notification will be shown or not.
8399         mWiFiAgent.setNetworkInvalid(true /* invalidBecauseOfPrivateDns */);
8400         mWiFiAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
8401         waitForIdle();
8402         // If network validation failed, NetworkMonitor will re-evaluate the network.
8403         // ConnectivityService should filter the redundant notification. This part is trying to
8404         // simulate that situation and check if ConnectivityService could filter that case.
8405         mWiFiAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
8406         waitForIdle();
8407         verify(mNotificationManager, timeout(TIMEOUT_MS).times(1)).notify(anyString(),
8408                 eq(NotificationType.PRIVATE_DNS_BROKEN.eventId), any());
8409         // If private DNS resolution successful, the PRIVATE_DNS_BROKEN notification shouldn't be
8410         // shown.
8411         mWiFiAgent.setNetworkValid(true /* privateDnsProbeSent */);
8412         mWiFiAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
8413         waitForIdle();
8414         verify(mNotificationManager, timeout(TIMEOUT_MS).times(1)).cancel(anyString(),
8415                 eq(NotificationType.PRIVATE_DNS_BROKEN.eventId));
8416         // If private DNS resolution failed again, the PRIVATE_DNS_BROKEN notification should be
8417         // shown again.
8418         mWiFiAgent.setNetworkInvalid(true /* invalidBecauseOfPrivateDns */);
8419         mWiFiAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
8420         waitForIdle();
8421         verify(mNotificationManager, timeout(TIMEOUT_MS).times(2)).notify(anyString(),
8422                 eq(NotificationType.PRIVATE_DNS_BROKEN.eventId), any());
8423     }
8424 
8425     @Test
8426     public void testPrivateDnsSettingsChange() throws Exception {
8427         // The default on Android is opportunistic mode ("Automatic").
8428         setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
8429 
8430         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
8431         final NetworkRequest cellRequest = new NetworkRequest.Builder()
8432                 .addTransportType(TRANSPORT_CELLULAR).build();
8433         mCm.requestNetwork(cellRequest, cellNetworkCallback);
8434 
8435         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
8436         final int netId = mCellAgent.getNetwork().netId;
8437         waitForIdle();
8438         if (mService.shouldCreateNetworksImmediately(mCellAgent.getNetworkCapabilities())) {
8439             verify(mMockDnsResolver, times(1)).createNetworkCache(netId);
8440         } else {
8441             verify(mMockDnsResolver, never()).setResolverConfiguration(any());
8442         }
8443 
8444         final LinkProperties cellLp = new LinkProperties();
8445         cellLp.setInterfaceName(MOBILE_IFNAME);
8446         // Add IPv4 and IPv6 default routes, because DNS-over-TLS code does
8447         // "is-reachable" testing in order to not program netd with unreachable
8448         // nameservers that it might try repeated to validate.
8449         cellLp.addLinkAddress(new LinkAddress("192.0.2.4/24"));
8450         cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("192.0.2.4"),
8451                 MOBILE_IFNAME));
8452         cellLp.addLinkAddress(new LinkAddress("2001:db8:1::1/64"));
8453         cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("2001:db8:1::1"),
8454                 MOBILE_IFNAME));
8455         cellLp.addDnsServer(InetAddress.getByName("2001:db8::1"));
8456         cellLp.addDnsServer(InetAddress.getByName("192.0.2.1"));
8457 
8458         mCellAgent.sendLinkProperties(cellLp);
8459         mCellAgent.connect(false);
8460         waitForIdle();
8461         if (!mService.shouldCreateNetworksImmediately(mCellAgent.getNetworkCapabilities())) {
8462             verify(mMockDnsResolver, times(1)).createNetworkCache(netId);
8463         }
8464         verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
8465                 mResolverParamsParcelCaptor.capture());
8466         ResolverParamsParcel resolvrParams = mResolverParamsParcelCaptor.getValue();
8467         assertEquals(2, resolvrParams.tlsServers.length);
8468         assertTrue(new ArraySet<>(resolvrParams.tlsServers).containsAll(
8469                 asList("2001:db8::1", "192.0.2.1")));
8470         // Opportunistic mode.
8471         assertEquals(2, resolvrParams.tlsServers.length);
8472         assertTrue(new ArraySet<>(resolvrParams.tlsServers).containsAll(
8473                 asList("2001:db8::1", "192.0.2.1")));
8474         verifyNoMoreInteractions(mMockDnsResolver);
8475         reset(mMockDnsResolver);
8476         cellNetworkCallback.expect(AVAILABLE, mCellAgent);
8477         cellNetworkCallback.expect(NETWORK_CAPS_UPDATED, mCellAgent);
8478         CallbackEntry.LinkPropertiesChanged cbi = cellNetworkCallback.expect(
8479                 LINK_PROPERTIES_CHANGED, mCellAgent);
8480         cellNetworkCallback.expect(BLOCKED_STATUS, mCellAgent);
8481         cellNetworkCallback.assertNoCallback();
8482         assertFalse(cbi.getLp().isPrivateDnsActive());
8483         assertNull(cbi.getLp().getPrivateDnsServerName());
8484 
8485         setPrivateDnsSettings(PRIVATE_DNS_MODE_OFF, "ignored.example.com");
8486         verify(mMockDnsResolver, times(1)).setResolverConfiguration(
8487                 mResolverParamsParcelCaptor.capture());
8488         resolvrParams = mResolverParamsParcelCaptor.getValue();
8489         assertEquals(2, resolvrParams.servers.length);
8490         assertTrue(new ArraySet<>(resolvrParams.servers).containsAll(
8491                 asList("2001:db8::1", "192.0.2.1")));
8492         reset(mMockDnsResolver);
8493         cellNetworkCallback.assertNoCallback();
8494 
8495         setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
8496         verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
8497                 mResolverParamsParcelCaptor.capture());
8498         resolvrParams = mResolverParamsParcelCaptor.getValue();
8499         assertEquals(2, resolvrParams.servers.length);
8500         assertTrue(new ArraySet<>(resolvrParams.servers).containsAll(
8501                 asList("2001:db8::1", "192.0.2.1")));
8502         assertEquals(2, resolvrParams.tlsServers.length);
8503         assertTrue(new ArraySet<>(resolvrParams.tlsServers).containsAll(
8504                 asList("2001:db8::1", "192.0.2.1")));
8505         reset(mMockDnsResolver);
8506         cellNetworkCallback.assertNoCallback();
8507 
8508         setPrivateDnsSettings(PRIVATE_DNS_MODE_PROVIDER_HOSTNAME, "strict.example.com");
8509         // Can't test dns configuration for strict mode without properly mocking
8510         // out the DNS lookups, but can test that LinkProperties is updated.
8511         cbi = cellNetworkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent);
8512         cellNetworkCallback.assertNoCallback();
8513         assertTrue(cbi.getLp().isPrivateDnsActive());
8514         assertEquals("strict.example.com", cbi.getLp().getPrivateDnsServerName());
8515     }
8516 
8517     private PrivateDnsValidationEventParcel makePrivateDnsValidationEvent(
8518             final int netId, final String ipAddress, final String hostname, final int validation) {
8519         final PrivateDnsValidationEventParcel event = new PrivateDnsValidationEventParcel();
8520         event.netId = netId;
8521         event.ipAddress = ipAddress;
8522         event.hostname = hostname;
8523         event.validation = validation;
8524         return event;
8525     }
8526 
8527     @Test
8528     public void testLinkPropertiesWithPrivateDnsValidationEvents() throws Exception {
8529         // The default on Android is opportunistic mode ("Automatic").
8530         setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
8531 
8532         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
8533         final NetworkRequest cellRequest = new NetworkRequest.Builder()
8534                 .addTransportType(TRANSPORT_CELLULAR).build();
8535         mCm.requestNetwork(cellRequest, cellNetworkCallback);
8536 
8537         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
8538         waitForIdle();
8539         LinkProperties lp = new LinkProperties();
8540         mCellAgent.sendLinkProperties(lp);
8541         mCellAgent.connect(false);
8542         waitForIdle();
8543         cellNetworkCallback.expect(AVAILABLE, mCellAgent);
8544         cellNetworkCallback.expect(NETWORK_CAPS_UPDATED, mCellAgent);
8545         CallbackEntry.LinkPropertiesChanged cbi = cellNetworkCallback.expect(
8546                 LINK_PROPERTIES_CHANGED, mCellAgent);
8547         cellNetworkCallback.expect(BLOCKED_STATUS, mCellAgent);
8548         cellNetworkCallback.assertNoCallback();
8549         assertFalse(cbi.getLp().isPrivateDnsActive());
8550         assertNull(cbi.getLp().getPrivateDnsServerName());
8551         Set<InetAddress> dnsServers = new HashSet<>();
8552         checkDnsServers(cbi.getLp(), dnsServers);
8553 
8554         // Send a validation event for a server that is not part of the current
8555         // resolver config. The validation event should be ignored.
8556         mService.mResolverUnsolEventCallback.onPrivateDnsValidationEvent(
8557                 makePrivateDnsValidationEvent(mCellAgent.getNetwork().netId, "",
8558                         "145.100.185.18", VALIDATION_RESULT_SUCCESS));
8559         cellNetworkCallback.assertNoCallback();
8560 
8561         // Add a dns server to the LinkProperties.
8562         LinkProperties lp2 = new LinkProperties(lp);
8563         lp2.addDnsServer(InetAddress.getByName("145.100.185.16"));
8564         mCellAgent.sendLinkProperties(lp2);
8565         cbi = cellNetworkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent);
8566         cellNetworkCallback.assertNoCallback();
8567         assertFalse(cbi.getLp().isPrivateDnsActive());
8568         assertNull(cbi.getLp().getPrivateDnsServerName());
8569         dnsServers.add(InetAddress.getByName("145.100.185.16"));
8570         checkDnsServers(cbi.getLp(), dnsServers);
8571 
8572         // Send a validation event containing a hostname that is not part of
8573         // the current resolver config. The validation event should be ignored.
8574         mService.mResolverUnsolEventCallback.onPrivateDnsValidationEvent(
8575                 makePrivateDnsValidationEvent(mCellAgent.getNetwork().netId,
8576                         "145.100.185.16", "hostname", VALIDATION_RESULT_SUCCESS));
8577         cellNetworkCallback.assertNoCallback();
8578 
8579         // Send a validation event where validation failed.
8580         mService.mResolverUnsolEventCallback.onPrivateDnsValidationEvent(
8581                 makePrivateDnsValidationEvent(mCellAgent.getNetwork().netId,
8582                         "145.100.185.16", "", VALIDATION_RESULT_FAILURE));
8583         cellNetworkCallback.assertNoCallback();
8584 
8585         // Send a validation event where validation succeeded for a server in
8586         // the current resolver config. A LinkProperties callback with updated
8587         // private dns fields should be sent.
8588         mService.mResolverUnsolEventCallback.onPrivateDnsValidationEvent(
8589                 makePrivateDnsValidationEvent(mCellAgent.getNetwork().netId,
8590                         "145.100.185.16", "", VALIDATION_RESULT_SUCCESS));
8591         cbi = cellNetworkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent);
8592         cellNetworkCallback.assertNoCallback();
8593         assertTrue(cbi.getLp().isPrivateDnsActive());
8594         assertNull(cbi.getLp().getPrivateDnsServerName());
8595         checkDnsServers(cbi.getLp(), dnsServers);
8596 
8597         // The private dns fields in LinkProperties should be preserved when
8598         // the network agent sends unrelated changes.
8599         LinkProperties lp3 = new LinkProperties(lp2);
8600         lp3.setMtu(1300);
8601         mCellAgent.sendLinkProperties(lp3);
8602         cbi = cellNetworkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent);
8603         cellNetworkCallback.assertNoCallback();
8604         assertTrue(cbi.getLp().isPrivateDnsActive());
8605         assertNull(cbi.getLp().getPrivateDnsServerName());
8606         checkDnsServers(cbi.getLp(), dnsServers);
8607         assertEquals(1300, cbi.getLp().getMtu());
8608 
8609         // Removing the only validated server should affect the private dns
8610         // fields in LinkProperties.
8611         LinkProperties lp4 = new LinkProperties(lp3);
8612         lp4.removeDnsServer(InetAddress.getByName("145.100.185.16"));
8613         mCellAgent.sendLinkProperties(lp4);
8614         cbi = cellNetworkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent);
8615         cellNetworkCallback.assertNoCallback();
8616         assertFalse(cbi.getLp().isPrivateDnsActive());
8617         assertNull(cbi.getLp().getPrivateDnsServerName());
8618         dnsServers.remove(InetAddress.getByName("145.100.185.16"));
8619         checkDnsServers(cbi.getLp(), dnsServers);
8620         assertEquals(1300, cbi.getLp().getMtu());
8621     }
8622 
8623     private void checkDirectlyConnectedRoutes(Object callbackObj,
8624             Collection<LinkAddress> linkAddresses, Collection<RouteInfo> otherRoutes) {
8625         assertTrue(callbackObj instanceof LinkProperties);
8626         LinkProperties lp = (LinkProperties) callbackObj;
8627 
8628         Set<RouteInfo> expectedRoutes = new ArraySet<>();
8629         expectedRoutes.addAll(otherRoutes);
8630         for (LinkAddress address : linkAddresses) {
8631             RouteInfo localRoute = new RouteInfo(address, null, lp.getInterfaceName());
8632             // Duplicates in linkAddresses are considered failures
8633             assertTrue(expectedRoutes.add(localRoute));
8634         }
8635         List<RouteInfo> observedRoutes = lp.getRoutes();
8636         assertEquals(expectedRoutes.size(), observedRoutes.size());
8637         assertTrue(observedRoutes.containsAll(expectedRoutes));
8638     }
8639 
8640     private static void checkDnsServers(Object callbackObj, Set<InetAddress> dnsServers) {
8641         assertTrue(callbackObj instanceof LinkProperties);
8642         LinkProperties lp = (LinkProperties) callbackObj;
8643         assertEquals(dnsServers.size(), lp.getDnsServers().size());
8644         assertTrue(lp.getDnsServers().containsAll(dnsServers));
8645     }
8646 
8647     @Test
8648     public void testApplyUnderlyingCapabilities() throws Exception {
8649         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
8650         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
8651         mCellAgent.connect(false /* validated */);
8652         mWiFiAgent.connect(false /* validated */);
8653 
8654         final NetworkCapabilities cellNc = new NetworkCapabilities()
8655                 .addTransportType(TRANSPORT_CELLULAR)
8656                 .addCapability(NET_CAPABILITY_INTERNET)
8657                 .addCapability(NET_CAPABILITY_NOT_CONGESTED)
8658                 .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
8659                 .setLinkDownstreamBandwidthKbps(10);
8660         final NetworkCapabilities wifiNc = new NetworkCapabilities()
8661                 .addTransportType(TRANSPORT_WIFI)
8662                 .addCapability(NET_CAPABILITY_INTERNET)
8663                 .addCapability(NET_CAPABILITY_NOT_METERED)
8664                 .addCapability(NET_CAPABILITY_NOT_ROAMING)
8665                 .addCapability(NET_CAPABILITY_NOT_CONGESTED)
8666                 .addCapability(NET_CAPABILITY_NOT_SUSPENDED)
8667                 .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
8668                 .setLinkUpstreamBandwidthKbps(20);
8669         mCellAgent.setNetworkCapabilities(cellNc, true /* sendToConnectivityService */);
8670         mWiFiAgent.setNetworkCapabilities(wifiNc, true /* sendToConnectivityService */);
8671         waitForIdle();
8672 
8673         final Network mobile = mCellAgent.getNetwork();
8674         final Network wifi = mWiFiAgent.getNetwork();
8675 
8676         final NetworkCapabilities initialCaps = new NetworkCapabilities();
8677         initialCaps.addTransportType(TRANSPORT_VPN);
8678         initialCaps.addCapability(NET_CAPABILITY_INTERNET);
8679         initialCaps.removeCapability(NET_CAPABILITY_NOT_VPN);
8680         final ArrayList<Network> emptyUnderlyingNetworks = new ArrayList<Network>();
8681         final ArrayList<Network> underlyingNetworksContainMobile = new ArrayList<Network>();
8682         underlyingNetworksContainMobile.add(mobile);
8683         final ArrayList<Network> underlyingNetworksContainWifi = new ArrayList<Network>();
8684         underlyingNetworksContainWifi.add(wifi);
8685         final ArrayList<Network> underlyingNetworksContainMobileAndMobile =
8686                 new ArrayList<Network>();
8687         underlyingNetworksContainMobileAndMobile.add(mobile);
8688         underlyingNetworksContainMobileAndMobile.add(wifi);
8689 
8690         final NetworkCapabilities withNoUnderlying = new NetworkCapabilities();
8691         withNoUnderlying.addCapability(NET_CAPABILITY_INTERNET);
8692         withNoUnderlying.addCapability(NET_CAPABILITY_NOT_CONGESTED);
8693         withNoUnderlying.addCapability(NET_CAPABILITY_NOT_ROAMING);
8694         withNoUnderlying.addCapability(NET_CAPABILITY_NOT_SUSPENDED);
8695         withNoUnderlying.addTransportType(TRANSPORT_VPN);
8696         withNoUnderlying.removeCapability(NET_CAPABILITY_NOT_VPN);
8697         withNoUnderlying.setUnderlyingNetworks(emptyUnderlyingNetworks);
8698 
8699         final NetworkCapabilities withMobileUnderlying = new NetworkCapabilities(withNoUnderlying);
8700         withMobileUnderlying.addTransportType(TRANSPORT_CELLULAR);
8701         withMobileUnderlying.removeCapability(NET_CAPABILITY_NOT_ROAMING);
8702         withMobileUnderlying.removeCapability(NET_CAPABILITY_NOT_SUSPENDED);
8703         withMobileUnderlying.setLinkDownstreamBandwidthKbps(10);
8704         withMobileUnderlying.setUnderlyingNetworks(underlyingNetworksContainMobile);
8705 
8706         final NetworkCapabilities withWifiUnderlying = new NetworkCapabilities(withNoUnderlying);
8707         withWifiUnderlying.addTransportType(TRANSPORT_WIFI);
8708         withWifiUnderlying.addCapability(NET_CAPABILITY_NOT_METERED);
8709         withWifiUnderlying.setLinkUpstreamBandwidthKbps(20);
8710         withWifiUnderlying.setUnderlyingNetworks(underlyingNetworksContainWifi);
8711 
8712         final NetworkCapabilities withWifiAndMobileUnderlying =
8713                 new NetworkCapabilities(withNoUnderlying);
8714         withWifiAndMobileUnderlying.addTransportType(TRANSPORT_CELLULAR);
8715         withWifiAndMobileUnderlying.addTransportType(TRANSPORT_WIFI);
8716         withWifiAndMobileUnderlying.removeCapability(NET_CAPABILITY_NOT_METERED);
8717         withWifiAndMobileUnderlying.removeCapability(NET_CAPABILITY_NOT_ROAMING);
8718         withWifiAndMobileUnderlying.setLinkDownstreamBandwidthKbps(10);
8719         withWifiAndMobileUnderlying.setLinkUpstreamBandwidthKbps(20);
8720         withWifiAndMobileUnderlying.setUnderlyingNetworks(underlyingNetworksContainMobileAndMobile);
8721 
8722         final NetworkCapabilities initialCapsNotMetered = new NetworkCapabilities(initialCaps);
8723         initialCapsNotMetered.addCapability(NET_CAPABILITY_NOT_METERED);
8724 
8725         NetworkCapabilities caps = new NetworkCapabilities(initialCaps);
8726         mService.applyUnderlyingCapabilities(new Network[]{}, initialCapsNotMetered, caps);
8727         assertEquals(withNoUnderlying, caps);
8728         assertEquals(0, new ArrayList<>(caps.getUnderlyingNetworks()).size());
8729 
8730         caps = new NetworkCapabilities(initialCaps);
8731         mService.applyUnderlyingCapabilities(new Network[]{null}, initialCapsNotMetered, caps);
8732         assertEquals(withNoUnderlying, caps);
8733         assertEquals(0, new ArrayList<>(caps.getUnderlyingNetworks()).size());
8734 
8735         caps = new NetworkCapabilities(initialCaps);
8736         mService.applyUnderlyingCapabilities(new Network[]{mobile}, initialCapsNotMetered, caps);
8737         assertEquals(withMobileUnderlying, caps);
8738         assertEquals(1, new ArrayList<>(caps.getUnderlyingNetworks()).size());
8739         assertEquals(mobile, new ArrayList<>(caps.getUnderlyingNetworks()).get(0));
8740 
8741         caps = new NetworkCapabilities(initialCaps);
8742         mService.applyUnderlyingCapabilities(new Network[]{wifi}, initialCapsNotMetered, caps);
8743         assertEquals(withWifiUnderlying, caps);
8744         assertEquals(1, new ArrayList<>(caps.getUnderlyingNetworks()).size());
8745         assertEquals(wifi, new ArrayList<>(caps.getUnderlyingNetworks()).get(0));
8746 
8747         withWifiUnderlying.removeCapability(NET_CAPABILITY_NOT_METERED);
8748         caps = new NetworkCapabilities(initialCaps);
8749         mService.applyUnderlyingCapabilities(new Network[]{wifi}, initialCaps, caps);
8750         assertEquals(withWifiUnderlying, caps);
8751         assertEquals(1, new ArrayList<>(caps.getUnderlyingNetworks()).size());
8752         assertEquals(wifi, new ArrayList<>(caps.getUnderlyingNetworks()).get(0));
8753 
8754         caps = new NetworkCapabilities(initialCaps);
8755         mService.applyUnderlyingCapabilities(new Network[]{mobile, wifi}, initialCaps, caps);
8756         assertEquals(withWifiAndMobileUnderlying, caps);
8757         assertEquals(2, new ArrayList<>(caps.getUnderlyingNetworks()).size());
8758         assertEquals(mobile, new ArrayList<>(caps.getUnderlyingNetworks()).get(0));
8759         assertEquals(wifi, new ArrayList<>(caps.getUnderlyingNetworks()).get(1));
8760 
8761         withWifiUnderlying.addCapability(NET_CAPABILITY_NOT_METERED);
8762         caps = new NetworkCapabilities(initialCaps);
8763         mService.applyUnderlyingCapabilities(new Network[]{null, mobile, null, wifi},
8764                 initialCapsNotMetered, caps);
8765         assertEquals(withWifiAndMobileUnderlying, caps);
8766         assertEquals(2, new ArrayList<>(caps.getUnderlyingNetworks()).size());
8767         assertEquals(mobile, new ArrayList<>(caps.getUnderlyingNetworks()).get(0));
8768         assertEquals(wifi, new ArrayList<>(caps.getUnderlyingNetworks()).get(1));
8769 
8770         caps = new NetworkCapabilities(initialCaps);
8771         mService.applyUnderlyingCapabilities(new Network[]{null, mobile, null, wifi},
8772                 initialCapsNotMetered, caps);
8773         assertEquals(withWifiAndMobileUnderlying, caps);
8774         assertEquals(2, new ArrayList<>(caps.getUnderlyingNetworks()).size());
8775         assertEquals(mobile, new ArrayList<>(caps.getUnderlyingNetworks()).get(0));
8776         assertEquals(wifi, new ArrayList<>(caps.getUnderlyingNetworks()).get(1));
8777 
8778         caps = new NetworkCapabilities(initialCaps);
8779         mService.applyUnderlyingCapabilities(null, initialCapsNotMetered, caps);
8780         assertEquals(withWifiUnderlying, caps);
8781         assertEquals(1, new ArrayList<>(caps.getUnderlyingNetworks()).size());
8782         assertEquals(wifi, new ArrayList<>(caps.getUnderlyingNetworks()).get(0));
8783     }
8784 
8785     @Test
8786     public void testVpnConnectDisconnectUnderlyingNetwork() throws Exception {
8787         final TestNetworkCallback callback = new TestNetworkCallback();
8788         final NetworkRequest request = new NetworkRequest.Builder()
8789                 .removeCapability(NET_CAPABILITY_NOT_VPN).build();
8790 
8791         runAsShell(NETWORK_SETTINGS, () -> {
8792             mCm.registerNetworkCallback(request, callback);
8793 
8794             // Bring up a VPN that specifies an underlying network that does not exist yet.
8795             // Note: it's sort of meaningless for a VPN app to declare a network that doesn't exist
8796             // yet, (and doing so is difficult without using reflection) but it's good to test that
8797             // the code behaves approximately correctly.
8798             mMockVpn.establishForMyUid(false, true, false);
8799             callback.expectAvailableCallbacksUnvalidated(mMockVpn);
8800             assertUidRangesUpdatedForMyUid(true);
8801             final Network wifiNetwork = new Network(mNetIdManager.peekNextNetId());
8802             mMockVpn.setUnderlyingNetworks(new Network[]{wifiNetwork});
8803             // onCapabilitiesChanged() should be called because
8804             // NetworkCapabilities#mUnderlyingNetworks is updated.
8805             final NetworkCapabilities vpnNc1 = callback.expectCaps(mMockVpn);
8806             // Since the wifi network hasn't brought up,
8807             // ConnectivityService#applyUnderlyingCapabilities cannot find it. Update
8808             // NetworkCapabilities#mUnderlyingNetworks to an empty array, and it will be updated to
8809             // the correct underlying networks once the wifi network brings up. But this case
8810             // shouldn't happen in reality since no one could get the network which hasn't brought
8811             // up. For the empty array of underlying networks, it should be happened for 2 cases,
8812             // the first one is that the VPN app declares an empty array for its underlying
8813             // networks, the second one is that the underlying networks are torn down.
8814             //
8815             // It shouldn't be null since the null value means the underlying networks of this
8816             // network should follow the default network.
8817             final ArrayList<Network> underlyingNetwork = new ArrayList<>();
8818             assertEquals(underlyingNetwork, vpnNc1.getUnderlyingNetworks());
8819             // Since the wifi network isn't exist, applyUnderlyingCapabilities()
8820             assertTrue(mCm.getNetworkCapabilities(mMockVpn.getNetwork())
8821                     .hasTransport(TRANSPORT_VPN));
8822             assertFalse(mCm.getNetworkCapabilities(mMockVpn.getNetwork())
8823                     .hasTransport(TRANSPORT_WIFI));
8824 
8825             // Make that underlying network connect, and expect to see its capabilities immediately
8826             // reflected in the VPN's capabilities.
8827             mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
8828             assertEquals(wifiNetwork, mWiFiAgent.getNetwork());
8829             mWiFiAgent.connect(false);
8830             // TODO: the callback for the VPN happens before any callbacks are called for the wifi
8831             // network that has just connected. There appear to be two issues here:
8832             // 1. The VPN code will accept an underlying network as soon as getNetworkCapabilities()
8833             //    for it returns non-null (which happens very early, during
8834             //    handleRegisterNetworkAgent).
8835             //    This is not correct because that that point the network is not connected and
8836             //    cannot pass any traffic.
8837             // 2. When a network connects, updateNetworkInfo propagates underlying network
8838             //    capabilities before rematching networks.
8839             // Given that this scenario can't really happen, this is probably fine for now.
8840             final NetworkCapabilities vpnNc2 = callback.expectCaps(mMockVpn);
8841             // The wifi network is brought up, NetworkCapabilities#mUnderlyingNetworks is updated to
8842             // it.
8843             underlyingNetwork.add(wifiNetwork);
8844             assertEquals(underlyingNetwork, vpnNc2.getUnderlyingNetworks());
8845             callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
8846             assertTrue(mCm.getNetworkCapabilities(mMockVpn.getNetwork())
8847                     .hasTransport(TRANSPORT_VPN));
8848             assertTrue(mCm.getNetworkCapabilities(mMockVpn.getNetwork())
8849                     .hasTransport(TRANSPORT_WIFI));
8850 
8851             // Disconnect the network, and expect to see the VPN capabilities change accordingly.
8852             mWiFiAgent.disconnect();
8853             callback.expect(LOST, mWiFiAgent);
8854             callback.expectCaps(mMockVpn, c -> c.getTransportTypes().length == 1
8855                             && c.hasTransport(TRANSPORT_VPN));
8856 
8857             mMockVpn.disconnect();
8858             mCm.unregisterNetworkCallback(callback);
8859         });
8860     }
8861 
8862     private void assertGetNetworkInfoOfGetActiveNetworkIsConnected(boolean expectedConnectivity) {
8863         // What Chromium used to do before https://chromium-review.googlesource.com/2605304
8864         assertEquals("Unexpected result for getActiveNetworkInfo(getActiveNetwork())",
8865                 expectedConnectivity, mCm.getNetworkInfo(mCm.getActiveNetwork()).isConnected());
8866     }
8867 
8868     @Test
8869     public void testVpnUnderlyingNetworkSuspended() throws Exception {
8870         final TestNetworkCallback callback = new TestNetworkCallback();
8871         mCm.registerDefaultNetworkCallback(callback);
8872 
8873         // Connect a VPN.
8874         mMockVpn.establishForMyUid(false /* validated */, true /* hasInternet */,
8875                 false /* privateDnsProbeSent */);
8876         callback.expectAvailableCallbacksUnvalidated(mMockVpn);
8877 
8878         // Connect cellular data.
8879         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
8880         mCellAgent.connect(false /* validated */);
8881         callback.expectCaps(mMockVpn, c -> c.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)
8882                 && c.hasTransport(TRANSPORT_CELLULAR));
8883         callback.assertNoCallback();
8884 
8885         assertTrue(mCm.getNetworkCapabilities(mMockVpn.getNetwork())
8886                 .hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
8887         assertNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
8888         assertNetworkInfo(TYPE_WIFI, DetailedState.DISCONNECTED);
8889         assertNetworkInfo(TYPE_VPN, DetailedState.CONNECTED);
8890         assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
8891         assertGetNetworkInfoOfGetActiveNetworkIsConnected(true);
8892 
8893         // Suspend the cellular network and expect the VPN to be suspended.
8894         mCellAgent.suspend();
8895         callback.expectCaps(mMockVpn, c -> !c.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)
8896                 && c.hasTransport(TRANSPORT_CELLULAR));
8897         callback.expect(SUSPENDED, mMockVpn);
8898         callback.assertNoCallback();
8899 
8900         assertFalse(mCm.getNetworkCapabilities(mMockVpn.getNetwork())
8901                 .hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
8902         assertNetworkInfo(TYPE_MOBILE, DetailedState.SUSPENDED);
8903         assertNetworkInfo(TYPE_WIFI, DetailedState.DISCONNECTED);
8904         assertNetworkInfo(TYPE_VPN, DetailedState.SUSPENDED);
8905         assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.SUSPENDED);
8906         // VPN's main underlying network is suspended, so no connectivity.
8907         assertGetNetworkInfoOfGetActiveNetworkIsConnected(false);
8908 
8909         // Switch to another network. The VPN should no longer be suspended.
8910         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
8911         mWiFiAgent.connect(false /* validated */);
8912         callback.expectCaps(mMockVpn, c -> c.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)
8913                 && c.hasTransport(TRANSPORT_WIFI));
8914         callback.expect(RESUMED, mMockVpn);
8915         callback.assertNoCallback();
8916 
8917         assertTrue(mCm.getNetworkCapabilities(mMockVpn.getNetwork())
8918                 .hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
8919         assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED);
8920         assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
8921         assertNetworkInfo(TYPE_VPN, DetailedState.CONNECTED);
8922         assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
8923         assertGetNetworkInfoOfGetActiveNetworkIsConnected(true);
8924 
8925         // Unsuspend cellular and then switch back to it. The VPN remains not suspended.
8926         mCellAgent.resume();
8927         callback.assertNoCallback();
8928         mWiFiAgent.disconnect();
8929         callback.expectCaps(mMockVpn, c -> c.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)
8930                 && c.hasTransport(TRANSPORT_CELLULAR));
8931         // Spurious double callback?
8932         callback.expectCaps(mMockVpn, c -> c.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)
8933                 && c.hasTransport(TRANSPORT_CELLULAR));
8934         callback.assertNoCallback();
8935 
8936         assertTrue(mCm.getNetworkCapabilities(mMockVpn.getNetwork())
8937                 .hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
8938         assertNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
8939         assertNetworkInfo(TYPE_WIFI, DetailedState.DISCONNECTED);
8940         assertNetworkInfo(TYPE_VPN, DetailedState.CONNECTED);
8941         assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
8942         assertGetNetworkInfoOfGetActiveNetworkIsConnected(true);
8943 
8944         // Suspend cellular and expect no connectivity.
8945         mCellAgent.suspend();
8946         callback.expectCaps(mMockVpn, c -> !c.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)
8947                 && c.hasTransport(TRANSPORT_CELLULAR));
8948         callback.expect(SUSPENDED, mMockVpn);
8949         callback.assertNoCallback();
8950 
8951         assertFalse(mCm.getNetworkCapabilities(mMockVpn.getNetwork())
8952                 .hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
8953         assertNetworkInfo(TYPE_MOBILE, DetailedState.SUSPENDED);
8954         assertNetworkInfo(TYPE_WIFI, DetailedState.DISCONNECTED);
8955         assertNetworkInfo(TYPE_VPN, DetailedState.SUSPENDED);
8956         assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.SUSPENDED);
8957         assertGetNetworkInfoOfGetActiveNetworkIsConnected(false);
8958 
8959         // Resume cellular and expect that connectivity comes back.
8960         mCellAgent.resume();
8961         callback.expectCaps(mMockVpn, c -> c.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)
8962                 && c.hasTransport(TRANSPORT_CELLULAR));
8963         callback.expect(RESUMED, mMockVpn);
8964         callback.assertNoCallback();
8965 
8966         assertTrue(mCm.getNetworkCapabilities(mMockVpn.getNetwork())
8967                 .hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
8968         assertNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
8969         assertNetworkInfo(TYPE_WIFI, DetailedState.DISCONNECTED);
8970         assertNetworkInfo(TYPE_VPN, DetailedState.CONNECTED);
8971         assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
8972         assertGetNetworkInfoOfGetActiveNetworkIsConnected(true);
8973     }
8974 
8975     @Test
8976     public void testVpnNetworkActive() throws Exception {
8977         final int uid = Process.myUid();
8978 
8979         final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback();
8980         final TestNetworkCallback genericNotVpnNetworkCallback = new TestNetworkCallback();
8981         final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
8982         final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
8983         final TestNetworkCallback defaultCallback = new TestNetworkCallback();
8984         final TestNetworkCallback systemDefaultCallback = new TestNetworkCallback();
8985         final NetworkRequest genericNotVpnRequest = new NetworkRequest.Builder().build();
8986         final NetworkRequest genericRequest = new NetworkRequest.Builder()
8987                 .removeCapability(NET_CAPABILITY_NOT_VPN).build();
8988         final NetworkRequest wifiRequest = new NetworkRequest.Builder()
8989                 .addTransportType(TRANSPORT_WIFI).build();
8990         final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder()
8991                 .removeCapability(NET_CAPABILITY_NOT_VPN)
8992                 .addTransportType(TRANSPORT_VPN).build();
8993         mCm.registerNetworkCallback(genericRequest, genericNetworkCallback);
8994         mCm.registerNetworkCallback(genericNotVpnRequest, genericNotVpnNetworkCallback);
8995         mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
8996         mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
8997         mCm.registerDefaultNetworkCallback(defaultCallback);
8998         mCm.registerSystemDefaultNetworkCallback(systemDefaultCallback,
8999                 new Handler(ConnectivityThread.getInstanceLooper()));
9000         defaultCallback.assertNoCallback();
9001 
9002         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
9003         mWiFiAgent.connect(false);
9004 
9005         genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
9006         genericNotVpnNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
9007         wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
9008         defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
9009         systemDefaultCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
9010         vpnNetworkCallback.assertNoCallback();
9011         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
9012 
9013         final Set<UidRange> ranges = uidRangesForUids(uid);
9014         mMockVpn.registerAgent(ranges);
9015         mMockVpn.setUnderlyingNetworks(new Network[0]);
9016 
9017         // VPN networks do not satisfy the default request and are automatically validated
9018         // by NetworkMonitor
9019         assertFalse(NetworkMonitorUtils.isValidationRequired(
9020                 false /* isDunValidationRequired */,
9021                 NetworkAgentConfigShimImpl.newInstance(mMockVpn.getNetworkAgentConfig())
9022                         .isVpnValidationRequired(),
9023                 mMockVpn.getAgent().getNetworkCapabilities()));
9024         mMockVpn.getAgent().setNetworkValid(false /* privateDnsProbeSent */);
9025 
9026         mMockVpn.connect(false);
9027 
9028         genericNetworkCallback.expectAvailableThenValidatedCallbacks(mMockVpn);
9029         genericNotVpnNetworkCallback.assertNoCallback();
9030         wifiNetworkCallback.assertNoCallback();
9031         vpnNetworkCallback.expectAvailableThenValidatedCallbacks(mMockVpn);
9032         defaultCallback.expectAvailableThenValidatedCallbacks(mMockVpn);
9033         systemDefaultCallback.assertNoCallback();
9034         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
9035         assertEquals(mWiFiAgent.getNetwork(), systemDefaultCallback.getLastAvailableNetwork());
9036 
9037         ranges.clear();
9038         mMockVpn.setUids(ranges);
9039 
9040         genericNetworkCallback.expect(LOST, mMockVpn);
9041         genericNotVpnNetworkCallback.assertNoCallback();
9042         wifiNetworkCallback.assertNoCallback();
9043         vpnNetworkCallback.expect(LOST, mMockVpn);
9044 
9045         // TODO : The default network callback should actually get a LOST call here (also see the
9046         // comment below for AVAILABLE). This is because ConnectivityService does not look at UID
9047         // ranges at all when determining whether a network should be rematched. In practice, VPNs
9048         // can't currently update their UIDs without disconnecting, so this does not matter too
9049         // much, but that is the reason the test here has to check for an update to the
9050         // capabilities instead of the expected LOST then AVAILABLE.
9051         defaultCallback.expectCaps(mMockVpn);
9052         systemDefaultCallback.assertNoCallback();
9053 
9054         ranges.add(new UidRange(uid, uid));
9055         mMockVpn.setUids(ranges);
9056 
9057         genericNetworkCallback.expectAvailableCallbacksValidated(mMockVpn);
9058         genericNotVpnNetworkCallback.assertNoCallback();
9059         wifiNetworkCallback.assertNoCallback();
9060         vpnNetworkCallback.expectAvailableCallbacksValidated(mMockVpn);
9061         // TODO : Here like above, AVAILABLE would be correct, but because this can't actually
9062         // happen outside of the test, ConnectivityService does not rematch callbacks.
9063         defaultCallback.expectCaps(mMockVpn);
9064         systemDefaultCallback.assertNoCallback();
9065 
9066         mWiFiAgent.disconnect();
9067 
9068         genericNetworkCallback.expect(LOST, mWiFiAgent);
9069         genericNotVpnNetworkCallback.expect(LOST, mWiFiAgent);
9070         wifiNetworkCallback.expect(LOST, mWiFiAgent);
9071         vpnNetworkCallback.assertNoCallback();
9072         defaultCallback.assertNoCallback();
9073         systemDefaultCallback.expect(LOST, mWiFiAgent);
9074 
9075         mMockVpn.disconnect();
9076 
9077         genericNetworkCallback.expect(LOST, mMockVpn);
9078         genericNotVpnNetworkCallback.assertNoCallback();
9079         wifiNetworkCallback.assertNoCallback();
9080         vpnNetworkCallback.expect(LOST, mMockVpn);
9081         defaultCallback.expect(LOST, mMockVpn);
9082         systemDefaultCallback.assertNoCallback();
9083         assertEquals(null, mCm.getActiveNetwork());
9084 
9085         mCm.unregisterNetworkCallback(genericNetworkCallback);
9086         mCm.unregisterNetworkCallback(wifiNetworkCallback);
9087         mCm.unregisterNetworkCallback(vpnNetworkCallback);
9088         mCm.unregisterNetworkCallback(defaultCallback);
9089         mCm.unregisterNetworkCallback(systemDefaultCallback);
9090     }
9091 
9092     @Test
9093     public void testVpnWithoutInternet() throws Exception {
9094         final int uid = Process.myUid();
9095 
9096         final TestNetworkCallback defaultCallback = new TestNetworkCallback();
9097         mCm.registerDefaultNetworkCallback(defaultCallback);
9098 
9099         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
9100         mWiFiAgent.connect(true);
9101 
9102         defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiAgent);
9103         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
9104 
9105         mMockVpn.establishForMyUid(true /* validated */, false /* hasInternet */,
9106                 false /* privateDnsProbeSent */);
9107         assertUidRangesUpdatedForMyUid(true);
9108 
9109         defaultCallback.assertNoCallback();
9110         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
9111 
9112         mMockVpn.disconnect();
9113         defaultCallback.assertNoCallback();
9114 
9115         mCm.unregisterNetworkCallback(defaultCallback);
9116     }
9117 
9118     @Test
9119     public void testVpnWithInternet() throws Exception {
9120         final int uid = Process.myUid();
9121 
9122         final TestNetworkCallback defaultCallback = new TestNetworkCallback();
9123         mCm.registerDefaultNetworkCallback(defaultCallback);
9124 
9125         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
9126         mWiFiAgent.connect(true);
9127 
9128         defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiAgent);
9129         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
9130 
9131         mMockVpn.establishForMyUid(true /* validated */, true /* hasInternet */,
9132                 false /* privateDnsProbeSent */);
9133         assertUidRangesUpdatedForMyUid(true);
9134 
9135         defaultCallback.expectAvailableThenValidatedCallbacks(mMockVpn);
9136         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
9137 
9138         mMockVpn.disconnect();
9139         defaultCallback.expect(LOST, mMockVpn);
9140         defaultCallback.expectAvailableCallbacksValidated(mWiFiAgent);
9141 
9142         mCm.unregisterNetworkCallback(defaultCallback);
9143     }
9144 
9145     @Test
9146     public void testVpnUnvalidated() throws Exception {
9147         final TestNetworkCallback callback = new TestNetworkCallback();
9148         mCm.registerDefaultNetworkCallback(callback);
9149 
9150         // Bring up Ethernet.
9151         mEthernetAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
9152         mEthernetAgent.connect(true);
9153         callback.expectAvailableThenValidatedCallbacks(mEthernetAgent);
9154         callback.assertNoCallback();
9155 
9156         // Bring up a VPN that has the INTERNET capability, initially unvalidated.
9157         mMockVpn.establishForMyUid(false /* validated */, true /* hasInternet */,
9158                 false /* privateDnsProbeSent */);
9159         assertUidRangesUpdatedForMyUid(true);
9160 
9161         // Even though the VPN is unvalidated, it becomes the default network for our app.
9162         callback.expectAvailableCallbacksUnvalidated(mMockVpn);
9163         callback.assertNoCallback();
9164 
9165         assertEquals(mMockVpn.getNetwork(), mCm.getActiveNetwork());
9166 
9167         NetworkCapabilities nc = mCm.getNetworkCapabilities(mMockVpn.getNetwork());
9168         assertFalse(nc.hasCapability(NET_CAPABILITY_VALIDATED));
9169         assertTrue(nc.hasCapability(NET_CAPABILITY_INTERNET));
9170 
9171         assertFalse(NetworkMonitorUtils.isValidationRequired(
9172                 false /* isDunValidationRequired */,
9173                 NetworkAgentConfigShimImpl.newInstance(mMockVpn.getNetworkAgentConfig())
9174                         .isVpnValidationRequired(),
9175                 mMockVpn.getAgent().getNetworkCapabilities()));
9176         assertTrue(NetworkMonitorUtils.isPrivateDnsValidationRequired(
9177                 mMockVpn.getAgent().getNetworkCapabilities()));
9178 
9179         // Pretend that the VPN network validates.
9180         mMockVpn.getAgent().setNetworkValid(false /* privateDnsProbeSent */);
9181         mMockVpn.getAgent().mNetworkMonitor.forceReevaluation(Process.myUid());
9182         // Expect to see the validated capability, but no other changes, because the VPN is already
9183         // the default network for the app.
9184         callback.expectCaps(mMockVpn, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
9185         callback.assertNoCallback();
9186 
9187         mMockVpn.disconnect();
9188         callback.expect(LOST, mMockVpn);
9189         callback.expectAvailableCallbacksValidated(mEthernetAgent);
9190     }
9191 
9192     @Test
9193     public void testVpnStartsWithUnderlyingCaps() throws Exception {
9194         final int uid = Process.myUid();
9195 
9196         final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
9197         final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder()
9198                 .removeCapability(NET_CAPABILITY_NOT_VPN)
9199                 .addTransportType(TRANSPORT_VPN)
9200                 .build();
9201         mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
9202         vpnNetworkCallback.assertNoCallback();
9203 
9204         // Connect cell. It will become the default network, and in the absence of setting
9205         // underlying networks explicitly it will become the sole underlying network for the vpn.
9206         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
9207         mCellAgent.addCapability(NET_CAPABILITY_NOT_SUSPENDED);
9208         mCellAgent.connect(true);
9209 
9210         mMockVpn.establishForMyUid(true /* validated */, false /* hasInternet */,
9211                 false /* privateDnsProbeSent */);
9212         assertUidRangesUpdatedForMyUid(true);
9213 
9214         vpnNetworkCallback.expectAvailableCallbacks(mMockVpn.getNetwork(),
9215                 false /* suspended */, false /* validated */, false /* blocked */, TIMEOUT_MS);
9216         vpnNetworkCallback.expectCaps(mMockVpn.getNetwork(), TIMEOUT_MS,
9217                 c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
9218 
9219         final NetworkCapabilities nc = mCm.getNetworkCapabilities(mMockVpn.getNetwork());
9220         assertTrue(nc.hasTransport(TRANSPORT_VPN));
9221         assertTrue(nc.hasTransport(TRANSPORT_CELLULAR));
9222         assertFalse(nc.hasTransport(TRANSPORT_WIFI));
9223         assertTrue(nc.hasCapability(NET_CAPABILITY_VALIDATED));
9224         assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED));
9225         assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
9226 
9227         assertVpnTransportInfo(nc, VpnManager.TYPE_VPN_SERVICE);
9228     }
9229 
9230     private void assertDefaultNetworkCapabilities(int userId, NetworkAgentWrapper... networks) {
9231         final NetworkCapabilities[] defaultCaps = mService.getDefaultNetworkCapabilitiesForUser(
9232                 userId, "com.android.calling.package", "com.test");
9233         final String defaultCapsString = Arrays.toString(defaultCaps);
9234         assertEquals(defaultCapsString, defaultCaps.length, networks.length);
9235         final Set<NetworkCapabilities> defaultCapsSet = new ArraySet<>(defaultCaps);
9236         for (NetworkAgentWrapper network : networks) {
9237             final NetworkCapabilities nc = mCm.getNetworkCapabilities(network.getNetwork());
9238             final String msg = "Did not find " + nc + " in " + Arrays.toString(defaultCaps);
9239             assertTrue(msg, defaultCapsSet.contains(nc));
9240         }
9241     }
9242 
9243     @Test
9244     public void testVpnSetUnderlyingNetworks() throws Exception {
9245         final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
9246         final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder()
9247                 .removeCapability(NET_CAPABILITY_NOT_VPN)
9248                 .addTransportType(TRANSPORT_VPN)
9249                 .build();
9250         NetworkCapabilities nc;
9251         mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
9252         vpnNetworkCallback.assertNoCallback();
9253 
9254         // Lingering timer is short and cell might be disconnected if the device is particularly
9255         // slow running the test, unless it's requested. Make sure the networks the test needs
9256         // are all requested.
9257         final NetworkCallback cellCallback = new NetworkCallback() {};
9258         final NetworkCallback wifiCallback = new NetworkCallback() {};
9259         mCm.requestNetwork(
9260                 new NetworkRequest.Builder().addTransportType(TRANSPORT_CELLULAR).build(),
9261                 cellCallback);
9262         mCm.requestNetwork(
9263                 new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI).build(),
9264                 wifiCallback);
9265 
9266         mMockVpn.establishForMyUid(true /* validated */, false /* hasInternet */,
9267                 false /* privateDnsProbeSent */);
9268         assertUidRangesUpdatedForMyUid(true);
9269 
9270         vpnNetworkCallback.expectAvailableThenValidatedCallbacks(mMockVpn);
9271         nc = mCm.getNetworkCapabilities(mMockVpn.getNetwork());
9272         assertTrue(nc.hasTransport(TRANSPORT_VPN));
9273         assertFalse(nc.hasTransport(TRANSPORT_CELLULAR));
9274         assertFalse(nc.hasTransport(TRANSPORT_WIFI));
9275         // For safety reasons a VPN without underlying networks is considered metered.
9276         assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED));
9277         // A VPN without underlying networks is not suspended.
9278         assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
9279         assertVpnTransportInfo(nc, VpnManager.TYPE_VPN_SERVICE);
9280 
9281         final int userId = UserHandle.getUserId(Process.myUid());
9282         assertDefaultNetworkCapabilities(userId /* no networks */);
9283 
9284         // Connect cell and use it as an underlying network.
9285         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
9286         mCellAgent.addCapability(NET_CAPABILITY_NOT_SUSPENDED);
9287         mCellAgent.connect(true);
9288 
9289         mMockVpn.setUnderlyingNetworks(new Network[] { mCellAgent.getNetwork() });
9290 
9291         vpnNetworkCallback.expectCaps(mMockVpn,
9292                 c -> c.hasTransport(TRANSPORT_VPN)
9293                         && c.hasTransport(TRANSPORT_CELLULAR)
9294                         && !c.hasTransport(TRANSPORT_WIFI)
9295                         && !c.hasCapability(NET_CAPABILITY_NOT_METERED)
9296                         && c.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
9297         assertDefaultNetworkCapabilities(userId, mCellAgent);
9298 
9299         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
9300         mWiFiAgent.addCapability(NET_CAPABILITY_NOT_METERED);
9301         mWiFiAgent.addCapability(NET_CAPABILITY_NOT_SUSPENDED);
9302         mWiFiAgent.connect(true);
9303 
9304         mMockVpn.setUnderlyingNetworks(
9305                 new Network[] { mCellAgent.getNetwork(), mWiFiAgent.getNetwork() });
9306 
9307         vpnNetworkCallback.expectCaps(mMockVpn,
9308                 c -> c.hasTransport(TRANSPORT_VPN)
9309                         && c.hasTransport(TRANSPORT_CELLULAR)
9310                         && c.hasTransport(TRANSPORT_WIFI)
9311                         && !c.hasCapability(NET_CAPABILITY_NOT_METERED)
9312                         && c.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
9313         assertDefaultNetworkCapabilities(userId, mCellAgent, mWiFiAgent);
9314 
9315         // Don't disconnect, but note the VPN is not using wifi any more.
9316         mMockVpn.setUnderlyingNetworks(new Network[] { mCellAgent.getNetwork() });
9317 
9318         vpnNetworkCallback.expectCaps(mMockVpn,
9319                 c -> c.hasTransport(TRANSPORT_VPN)
9320                         && c.hasTransport(TRANSPORT_CELLULAR)
9321                         && !c.hasTransport(TRANSPORT_WIFI)
9322                         && !c.hasCapability(NET_CAPABILITY_NOT_METERED)
9323                         && c.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
9324         // The return value of getDefaultNetworkCapabilitiesForUser always includes the default
9325         // network (wifi) as well as the underlying networks (cell).
9326         assertDefaultNetworkCapabilities(userId, mCellAgent, mWiFiAgent);
9327 
9328         // Remove NOT_SUSPENDED from the only network and observe VPN is now suspended.
9329         mCellAgent.removeCapability(NET_CAPABILITY_NOT_SUSPENDED);
9330         vpnNetworkCallback.expectCaps(mMockVpn,
9331                 c -> c.hasTransport(TRANSPORT_VPN)
9332                         && c.hasTransport(TRANSPORT_CELLULAR)
9333                         && !c.hasTransport(TRANSPORT_WIFI)
9334                         && !c.hasCapability(NET_CAPABILITY_NOT_METERED)
9335                         && !c.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
9336         vpnNetworkCallback.expect(SUSPENDED, mMockVpn);
9337 
9338         // Add NOT_SUSPENDED again and observe VPN is no longer suspended.
9339         mCellAgent.addCapability(NET_CAPABILITY_NOT_SUSPENDED);
9340         vpnNetworkCallback.expectCaps(mMockVpn,
9341                 c -> c.hasTransport(TRANSPORT_VPN)
9342                         && c.hasTransport(TRANSPORT_CELLULAR)
9343                         && !c.hasTransport(TRANSPORT_WIFI)
9344                         && !c.hasCapability(NET_CAPABILITY_NOT_METERED)
9345                         && c.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
9346         vpnNetworkCallback.expect(RESUMED, mMockVpn);
9347 
9348         // Use Wifi but not cell. Note the VPN is now unmetered and not suspended.
9349         mMockVpn.setUnderlyingNetworks(new Network[] { mWiFiAgent.getNetwork() });
9350 
9351         vpnNetworkCallback.expectCaps(mMockVpn,
9352                 c -> c.hasTransport(TRANSPORT_VPN)
9353                         && !c.hasTransport(TRANSPORT_CELLULAR)
9354                         && c.hasTransport(TRANSPORT_WIFI)
9355                         && c.hasCapability(NET_CAPABILITY_NOT_METERED)
9356                         && c.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
9357         assertDefaultNetworkCapabilities(userId, mWiFiAgent);
9358 
9359         // Use both again.
9360         mMockVpn.setUnderlyingNetworks(
9361                 new Network[] { mCellAgent.getNetwork(), mWiFiAgent.getNetwork() });
9362 
9363         vpnNetworkCallback.expectCaps(mMockVpn,
9364                 c -> c.hasTransport(TRANSPORT_VPN)
9365                         && c.hasTransport(TRANSPORT_CELLULAR)
9366                         && c.hasTransport(TRANSPORT_WIFI)
9367                         && !c.hasCapability(NET_CAPABILITY_NOT_METERED)
9368                         && c.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
9369         assertDefaultNetworkCapabilities(userId, mCellAgent, mWiFiAgent);
9370 
9371         // Cell is suspended again. As WiFi is not, this should not cause a callback.
9372         mCellAgent.removeCapability(NET_CAPABILITY_NOT_SUSPENDED);
9373         vpnNetworkCallback.assertNoCallback();
9374 
9375         // Stop using WiFi. The VPN is suspended again.
9376         mMockVpn.setUnderlyingNetworks(new Network[] { mCellAgent.getNetwork() });
9377         vpnNetworkCallback.expectCaps(mMockVpn,
9378                 c -> c.hasTransport(TRANSPORT_VPN)
9379                         && c.hasTransport(TRANSPORT_CELLULAR)
9380                         && !c.hasCapability(NET_CAPABILITY_NOT_METERED)
9381                         && !c.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
9382         vpnNetworkCallback.expect(SUSPENDED, mMockVpn);
9383         assertDefaultNetworkCapabilities(userId, mCellAgent, mWiFiAgent);
9384 
9385         // Use both again.
9386         mMockVpn.setUnderlyingNetworks(
9387                 new Network[] { mCellAgent.getNetwork(), mWiFiAgent.getNetwork() });
9388 
9389         vpnNetworkCallback.expectCaps(mMockVpn,
9390                 c -> c.hasTransport(TRANSPORT_VPN)
9391                         && c.hasTransport(TRANSPORT_CELLULAR)
9392                         && c.hasTransport(TRANSPORT_WIFI)
9393                         && !c.hasCapability(NET_CAPABILITY_NOT_METERED)
9394                         && c.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
9395         vpnNetworkCallback.expect(RESUMED, mMockVpn);
9396         assertDefaultNetworkCapabilities(userId, mCellAgent, mWiFiAgent);
9397 
9398         // Disconnect cell. Receive update without even removing the dead network from the
9399         // underlying networks – it's dead anyway. Not metered any more.
9400         mCellAgent.disconnect();
9401         vpnNetworkCallback.expectCaps(mMockVpn,
9402                 c -> c.hasTransport(TRANSPORT_VPN)
9403                         && !c.hasTransport(TRANSPORT_CELLULAR)
9404                         && c.hasTransport(TRANSPORT_WIFI)
9405                         && c.hasCapability(NET_CAPABILITY_NOT_METERED));
9406         assertDefaultNetworkCapabilities(userId, mWiFiAgent);
9407 
9408         // Disconnect wifi too. No underlying networks means this is now metered.
9409         mWiFiAgent.disconnect();
9410         vpnNetworkCallback.expectCaps(mMockVpn,
9411                 c -> c.hasTransport(TRANSPORT_VPN)
9412                         && !c.hasTransport(TRANSPORT_CELLULAR)
9413                         && !c.hasTransport(TRANSPORT_WIFI)
9414                         && !c.hasCapability(NET_CAPABILITY_NOT_METERED));
9415         // When a network disconnects, the callbacks are fired before all state is updated, so for a
9416         // short time, synchronous calls will behave as if the network is still connected. Wait for
9417         // things to settle.
9418         waitForIdle();
9419         assertDefaultNetworkCapabilities(userId /* no networks */);
9420 
9421         mMockVpn.disconnect();
9422         mCm.unregisterNetworkCallback(cellCallback);
9423         mCm.unregisterNetworkCallback(wifiCallback);
9424     }
9425 
9426     @Test
9427     public void testNullUnderlyingNetworks() throws Exception {
9428         final int uid = Process.myUid();
9429 
9430         final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
9431         final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder()
9432                 .removeCapability(NET_CAPABILITY_NOT_VPN)
9433                 .addTransportType(TRANSPORT_VPN)
9434                 .build();
9435         NetworkCapabilities nc;
9436         mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
9437         vpnNetworkCallback.assertNoCallback();
9438 
9439         mMockVpn.establishForMyUid(true /* validated */, false /* hasInternet */,
9440                 false /* privateDnsProbeSent */);
9441         assertUidRangesUpdatedForMyUid(true);
9442 
9443         vpnNetworkCallback.expectAvailableThenValidatedCallbacks(mMockVpn);
9444         nc = mCm.getNetworkCapabilities(mMockVpn.getNetwork());
9445         assertTrue(nc.hasTransport(TRANSPORT_VPN));
9446         assertFalse(nc.hasTransport(TRANSPORT_CELLULAR));
9447         assertFalse(nc.hasTransport(TRANSPORT_WIFI));
9448         // By default, VPN is set to track default network (i.e. its underlying networks is null).
9449         // In case of no default network, VPN is considered metered.
9450         assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED));
9451         assertVpnTransportInfo(nc, VpnManager.TYPE_VPN_SERVICE);
9452 
9453         // Connect to Cell; Cell is the default network.
9454         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
9455         mCellAgent.connect(true);
9456 
9457         vpnNetworkCallback.expectCaps(mMockVpn,
9458                 c -> c.hasTransport(TRANSPORT_VPN)
9459                         && c.hasTransport(TRANSPORT_CELLULAR)
9460                         && !c.hasTransport(TRANSPORT_WIFI)
9461                         && !c.hasCapability(NET_CAPABILITY_NOT_METERED));
9462 
9463         // Connect to WiFi; WiFi is the new default.
9464         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
9465         mWiFiAgent.addCapability(NET_CAPABILITY_NOT_METERED);
9466         mWiFiAgent.connect(true);
9467 
9468         vpnNetworkCallback.expectCaps(mMockVpn,
9469                 c -> c.hasTransport(TRANSPORT_VPN)
9470                         && !c.hasTransport(TRANSPORT_CELLULAR)
9471                         && c.hasTransport(TRANSPORT_WIFI)
9472                         && c.hasCapability(NET_CAPABILITY_NOT_METERED));
9473 
9474         // Disconnect Cell. The default network did not change, so there shouldn't be any changes in
9475         // the capabilities.
9476         mCellAgent.disconnect();
9477 
9478         // Disconnect wifi too. Now we have no default network.
9479         mWiFiAgent.disconnect();
9480 
9481         vpnNetworkCallback.expectCaps(mMockVpn,
9482                 c -> c.hasTransport(TRANSPORT_VPN)
9483                         && !c.hasTransport(TRANSPORT_CELLULAR)
9484                         && !c.hasTransport(TRANSPORT_WIFI)
9485                         && !c.hasCapability(NET_CAPABILITY_NOT_METERED));
9486 
9487         mMockVpn.disconnect();
9488     }
9489 
9490     @Test
9491     public void testRestrictedProfileAffectsVpnUidRanges() throws Exception {
9492         // NETWORK_SETTINGS is necessary to see the UID ranges in NetworkCapabilities.
9493         mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_GRANTED);
9494 
9495         final NetworkRequest request = new NetworkRequest.Builder()
9496                 .removeCapability(NET_CAPABILITY_NOT_VPN)
9497                 .build();
9498         final TestNetworkCallback callback = new TestNetworkCallback();
9499         mCm.registerNetworkCallback(request, callback);
9500 
9501         // File a VPN request to prevent VPN network being lingered.
9502         final NetworkRequest vpnRequest = new NetworkRequest.Builder()
9503                 .addTransportType(TRANSPORT_VPN)
9504                 .removeCapability(NET_CAPABILITY_NOT_VPN)
9505                 .build();
9506         final TestNetworkCallback vpnCallback = new TestNetworkCallback();
9507         mCm.requestNetwork(vpnRequest, vpnCallback);
9508 
9509         // Bring up a VPN
9510         mMockVpn.establishForMyUid();
9511         assertUidRangesUpdatedForMyUid(true);
9512         callback.expectAvailableThenValidatedCallbacks(mMockVpn);
9513         callback.assertNoCallback();
9514 
9515         final int uid = Process.myUid();
9516         NetworkCapabilities nc = mCm.getNetworkCapabilities(mMockVpn.getNetwork());
9517         assertNotNull("nc=" + nc, nc.getUids());
9518         assertEquals(nc.getUids(), UidRange.toIntRanges(uidRangesForUids(uid)));
9519         assertVpnTransportInfo(nc, VpnManager.TYPE_VPN_SERVICE);
9520 
9521         // Set an underlying network and expect to see the VPN transports change.
9522         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
9523         mWiFiAgent.connect(true);
9524         callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
9525         callback.expectCaps(mMockVpn, c -> c.hasTransport(TRANSPORT_VPN)
9526                         && c.hasTransport(TRANSPORT_WIFI));
9527         callback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
9528 
9529         // New user added, this updates the Vpn uids, coverage in VpnTest.
9530         // This is equivalent to `mMockVpn.onUserAdded(RESTRICTED_USER);`
9531         final Set<UidRange> ranges = uidRangesForUids(uid);
9532         ranges.add(RESTRICTED_USER_UIDRANGE);
9533         mMockVpn.setUids(ranges);
9534 
9535         // Expect that the VPN UID ranges contain both |uid| and the UID range for the newly-added
9536         // restricted user.
9537         final UidRange rRange = UidRange.createForUser(UserHandle.of(RESTRICTED_USER));
9538         final Range<Integer> restrictUidRange = new Range<>(rRange.start, rRange.stop);
9539         final Range<Integer> singleUidRange = new Range<>(uid, uid);
9540         callback.expectCaps(mMockVpn, c ->
9541                 c.getUids().size() == 2
9542                 && c.getUids().contains(singleUidRange)
9543                 && c.getUids().contains(restrictUidRange)
9544                 && c.hasTransport(TRANSPORT_VPN)
9545                 && c.hasTransport(TRANSPORT_WIFI));
9546 
9547         // Change the VPN's capabilities somehow (specifically, disconnect wifi).
9548         mWiFiAgent.disconnect();
9549         callback.expect(LOST, mWiFiAgent);
9550         callback.expectCaps(mMockVpn, c ->
9551                 c.getUids().size() == 2
9552                 && c.getUids().contains(singleUidRange)
9553                 && c.getUids().contains(restrictUidRange)
9554                 && c.hasTransport(TRANSPORT_VPN)
9555                 && !c.hasTransport(TRANSPORT_WIFI));
9556 
9557         // User removed and expect to lose the UID range for the restricted user.
9558         // This updates the Vpn uids, coverage in VpnTest.
9559         // This is equivalent to `mMockVpn.onUserRemoved(RESTRICTED_USER);`
9560         mMockVpn.setUids(uidRangesForUids(uid));
9561 
9562         // Expect that the VPN gains the UID range for the restricted user, and that the capability
9563         // change made just before that (i.e., loss of TRANSPORT_WIFI) is preserved.
9564         callback.expectCaps(mMockVpn, c ->
9565                 c.getUids().size() == 1
9566                 && c.getUids().contains(singleUidRange)
9567                 && c.hasTransport(TRANSPORT_VPN)
9568                 && !c.hasTransport(TRANSPORT_WIFI));
9569 
9570         mCm.unregisterNetworkCallback(callback);
9571         mCm.unregisterNetworkCallback(vpnCallback);
9572     }
9573 
9574     @Test
9575     public void testLockdownVpnWithRestrictedProfiles() throws Exception {
9576         // For ConnectivityService#setAlwaysOnVpnPackage.
9577         mServiceContext.setPermission(
9578                 Manifest.permission.CONTROL_ALWAYS_ON_VPN, PERMISSION_GRANTED);
9579         // For call Vpn#setAlwaysOnPackage.
9580         mServiceContext.setPermission(
9581                 Manifest.permission.CONTROL_VPN, PERMISSION_GRANTED);
9582         // Necessary to see the UID ranges in NetworkCapabilities.
9583         mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_GRANTED);
9584 
9585         final NetworkRequest request = new NetworkRequest.Builder()
9586                 .removeCapability(NET_CAPABILITY_NOT_VPN)
9587                 .build();
9588         final TestNetworkCallback callback = new TestNetworkCallback();
9589         mCm.registerNetworkCallback(request, callback);
9590 
9591         final int uid = Process.myUid();
9592 
9593         // Connect wifi and check that UIDs in the main and restricted profiles have network access.
9594         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
9595         mWiFiAgent.connect(true /* validated */);
9596         final int restrictedUid = UserHandle.getUid(RESTRICTED_USER, 42 /* appId */);
9597         assertNotNull(mCm.getActiveNetworkForUid(uid));
9598         assertNotNull(mCm.getActiveNetworkForUid(restrictedUid));
9599 
9600         // Enable always-on VPN lockdown. The main user loses network access because no VPN is up.
9601         // Coverage in VpnTest.
9602         final List<Integer> excludedUids = new ArrayList<>();
9603         excludedUids.add(VPN_UID);
9604         if (mDeps.isAtLeastT()) {
9605             // On T onwards, the corresponding SDK sandbox UID should also be excluded
9606             excludedUids.add(toSdkSandboxUid(VPN_UID));
9607         }
9608         final List<Range<Integer>> primaryRanges = intRangesPrimaryExcludingUids(excludedUids);
9609         mCm.setRequireVpnForUids(true, primaryRanges);
9610 
9611         waitForIdle();
9612         assertNull(mCm.getActiveNetworkForUid(uid));
9613         // This is arguably overspecified: a UID that is not running doesn't have an active network.
9614         // But it's useful to check that non-default users do not lose network access, and to prove
9615         // that the loss of connectivity below is indeed due to the restricted profile coming up.
9616         assertNotNull(mCm.getActiveNetworkForUid(restrictedUid));
9617 
9618         // Start the restricted profile, and check that the UID within it loses network access.
9619         // TODO: check that VPN app within restricted profile still has access, etc.
9620         // Add a restricted user.
9621         // This is equivalent to `mMockVpn.onUserAdded(RESTRICTED_USER);`, coverage in VpnTest.
9622         final List<Range<Integer>> restrictedRanges =
9623                 intRangesExcludingUids(RESTRICTED_USER, excludedUids);
9624         mCm.setRequireVpnForUids(true, restrictedRanges);
9625         waitForIdle();
9626 
9627         assertNull(mCm.getActiveNetworkForUid(uid));
9628         assertNull(mCm.getActiveNetworkForUid(restrictedUid));
9629 
9630         // Stop the restricted profile, and check that the UID within it has network access again.
9631         // Remove the restricted user.
9632         // This is equivalent to `mMockVpn.onUserRemoved(RESTRICTED_USER);`, coverage in VpnTest.
9633         mCm.setRequireVpnForUids(false, restrictedRanges);
9634         waitForIdle();
9635 
9636         assertNull(mCm.getActiveNetworkForUid(uid));
9637         assertNotNull(mCm.getActiveNetworkForUid(restrictedUid));
9638 
9639         mCm.setRequireVpnForUids(false, primaryRanges);
9640 
9641         waitForIdle();
9642     }
9643 
9644     @Test
9645     public void testIsActiveNetworkMeteredOverWifi() throws Exception {
9646         // Returns true by default when no network is available.
9647         assertTrue(mCm.isActiveNetworkMetered());
9648         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
9649         mWiFiAgent.addCapability(NET_CAPABILITY_NOT_METERED);
9650         mWiFiAgent.connect(true);
9651         waitForIdle();
9652 
9653         assertFalse(mCm.isActiveNetworkMetered());
9654     }
9655 
9656     @Test
9657     public void testIsActiveNetworkMeteredOverCell() throws Exception {
9658         // Returns true by default when no network is available.
9659         assertTrue(mCm.isActiveNetworkMetered());
9660         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
9661         mCellAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
9662         mCellAgent.connect(true);
9663         waitForIdle();
9664 
9665         assertTrue(mCm.isActiveNetworkMetered());
9666     }
9667 
9668     @Test
9669     public void testIsActiveNetworkMeteredOverVpnTrackingPlatformDefault() throws Exception {
9670         // Returns true by default when no network is available.
9671         assertTrue(mCm.isActiveNetworkMetered());
9672         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
9673         mCellAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
9674         mCellAgent.connect(true);
9675         waitForIdle();
9676         assertTrue(mCm.isActiveNetworkMetered());
9677 
9678         // Connect VPN network. By default it is using current default network (Cell).
9679         mMockVpn.establishForMyUid();
9680         assertUidRangesUpdatedForMyUid(true);
9681 
9682         // Ensure VPN is now the active network.
9683         assertEquals(mMockVpn.getNetwork(), mCm.getActiveNetwork());
9684 
9685         // Expect VPN to be metered.
9686         assertTrue(mCm.isActiveNetworkMetered());
9687 
9688         // Connect WiFi.
9689         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
9690         mWiFiAgent.addCapability(NET_CAPABILITY_NOT_METERED);
9691         mWiFiAgent.connect(true);
9692         waitForIdle();
9693         // VPN should still be the active network.
9694         assertEquals(mMockVpn.getNetwork(), mCm.getActiveNetwork());
9695 
9696         // Expect VPN to be unmetered as it should now be using WiFi (new default).
9697         assertFalse(mCm.isActiveNetworkMetered());
9698 
9699         // Disconnecting Cell should not affect VPN's meteredness.
9700         mCellAgent.disconnect();
9701         waitForIdle();
9702 
9703         assertFalse(mCm.isActiveNetworkMetered());
9704 
9705         // Disconnect WiFi; Now there is no platform default network.
9706         mWiFiAgent.disconnect();
9707         waitForIdle();
9708 
9709         // VPN without any underlying networks is treated as metered.
9710         assertTrue(mCm.isActiveNetworkMetered());
9711 
9712         mMockVpn.disconnect();
9713     }
9714 
9715     @Test
9716     public void testIsActiveNetworkMeteredOverVpnSpecifyingUnderlyingNetworks() throws Exception {
9717         // Returns true by default when no network is available.
9718         assertTrue(mCm.isActiveNetworkMetered());
9719         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
9720         mCellAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
9721         mCellAgent.connect(true);
9722         waitForIdle();
9723         assertTrue(mCm.isActiveNetworkMetered());
9724 
9725         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
9726         mWiFiAgent.addCapability(NET_CAPABILITY_NOT_METERED);
9727         mWiFiAgent.connect(true);
9728         waitForIdle();
9729         assertFalse(mCm.isActiveNetworkMetered());
9730 
9731         // Connect VPN network.
9732         mMockVpn.establishForMyUid();
9733         assertUidRangesUpdatedForMyUid(true);
9734 
9735         // Ensure VPN is now the active network.
9736         assertEquals(mMockVpn.getNetwork(), mCm.getActiveNetwork());
9737         // VPN is using Cell
9738         mMockVpn.setUnderlyingNetworks(new Network[] { mCellAgent.getNetwork() });
9739         waitForIdle();
9740 
9741         // Expect VPN to be metered.
9742         assertTrue(mCm.isActiveNetworkMetered());
9743 
9744         // VPN is now using WiFi
9745         mMockVpn.setUnderlyingNetworks(new Network[] { mWiFiAgent.getNetwork() });
9746         waitForIdle();
9747 
9748         // Expect VPN to be unmetered
9749         assertFalse(mCm.isActiveNetworkMetered());
9750 
9751         // VPN is using Cell | WiFi.
9752         mMockVpn.setUnderlyingNetworks(
9753                 new Network[] { mCellAgent.getNetwork(), mWiFiAgent.getNetwork() });
9754         waitForIdle();
9755 
9756         // Expect VPN to be metered.
9757         assertTrue(mCm.isActiveNetworkMetered());
9758 
9759         // VPN is using WiFi | Cell.
9760         mMockVpn.setUnderlyingNetworks(
9761                 new Network[] { mWiFiAgent.getNetwork(), mCellAgent.getNetwork() });
9762         waitForIdle();
9763 
9764         // Order should not matter and VPN should still be metered.
9765         assertTrue(mCm.isActiveNetworkMetered());
9766 
9767         // VPN is not using any underlying networks.
9768         mMockVpn.setUnderlyingNetworks(new Network[0]);
9769         waitForIdle();
9770 
9771         // VPN without underlying networks is treated as metered.
9772         assertTrue(mCm.isActiveNetworkMetered());
9773 
9774         mMockVpn.disconnect();
9775     }
9776 
9777     @Test
9778     public void testIsActiveNetworkMeteredOverAlwaysMeteredVpn() throws Exception {
9779         // Returns true by default when no network is available.
9780         assertTrue(mCm.isActiveNetworkMetered());
9781         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
9782         mWiFiAgent.addCapability(NET_CAPABILITY_NOT_METERED);
9783         mWiFiAgent.connect(true);
9784         waitForIdle();
9785         assertFalse(mCm.isActiveNetworkMetered());
9786 
9787         // Connect VPN network.
9788         mMockVpn.registerAgent(true /* isAlwaysMetered */, uidRangesForUids(Process.myUid()),
9789                 new LinkProperties());
9790         mMockVpn.connect(true);
9791         waitForIdle();
9792         assertEquals(mMockVpn.getNetwork(), mCm.getActiveNetwork());
9793 
9794         // VPN is tracking current platform default (WiFi).
9795         mMockVpn.setUnderlyingNetworks(null);
9796         waitForIdle();
9797 
9798         // Despite VPN using WiFi (which is unmetered), VPN itself is marked as always metered.
9799         assertTrue(mCm.isActiveNetworkMetered());
9800 
9801 
9802         // VPN explicitly declares WiFi as its underlying network.
9803         mMockVpn.setUnderlyingNetworks(new Network[] { mWiFiAgent.getNetwork() });
9804         waitForIdle();
9805 
9806         // Doesn't really matter whether VPN declares its underlying networks explicitly.
9807         assertTrue(mCm.isActiveNetworkMetered());
9808 
9809         // With WiFi lost, VPN is basically without any underlying networks. And in that case it is
9810         // anyways suppose to be metered.
9811         mWiFiAgent.disconnect();
9812         waitForIdle();
9813 
9814         assertTrue(mCm.isActiveNetworkMetered());
9815 
9816         mMockVpn.disconnect();
9817     }
9818 
9819     private class DetailedBlockedStatusCallback extends TestNetworkCallback {
9820         public void expectAvailableThenValidatedCallbacks(HasNetwork n, int blockedStatus) {
9821             super.expectAvailableThenValidatedCallbacks(n.getNetwork(), blockedStatus, TIMEOUT_MS);
9822         }
9823         public void onBlockedStatusChanged(Network network, int blockedReasons) {
9824             getHistory().add(new CallbackEntry.BlockedStatusInt(network, blockedReasons));
9825         }
9826     }
9827 
9828     @Test
9829     public void testNetworkBlockedStatus() throws Exception {
9830         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
9831         final NetworkRequest cellRequest = new NetworkRequest.Builder()
9832                 .addTransportType(TRANSPORT_CELLULAR)
9833                 .build();
9834         mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
9835         final DetailedBlockedStatusCallback detailedCallback = new DetailedBlockedStatusCallback();
9836         mCm.registerNetworkCallback(cellRequest, detailedCallback);
9837 
9838         mockUidNetworkingBlocked();
9839 
9840         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
9841         mCellAgent.connect(true);
9842         cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
9843         detailedCallback.expectAvailableThenValidatedCallbacks(mCellAgent, BLOCKED_REASON_NONE);
9844         assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetwork());
9845         assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
9846         assertNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
9847         assertExtraInfoFromCmPresent(mCellAgent);
9848 
9849         setBlockedReasonChanged(BLOCKED_REASON_BATTERY_SAVER);
9850         cellNetworkCallback.expect(BLOCKED_STATUS, mCellAgent, cb -> cb.getBlocked());
9851         detailedCallback.expect(BLOCKED_STATUS_INT, mCellAgent,
9852                 cb -> cb.getReason() == BLOCKED_REASON_BATTERY_SAVER);
9853         assertNull(mCm.getActiveNetwork());
9854         assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
9855         assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
9856         assertExtraInfoFromCmBlocked(mCellAgent);
9857 
9858         // If blocked state does not change but blocked reason does, the boolean callback is called.
9859         // TODO: investigate de-duplicating.
9860         setBlockedReasonChanged(BLOCKED_METERED_REASON_USER_RESTRICTED);
9861         cellNetworkCallback.expect(BLOCKED_STATUS, mCellAgent, cb -> cb.getBlocked());
9862         detailedCallback.expect(BLOCKED_STATUS_INT, mCellAgent,
9863                 cb -> cb.getReason() == BLOCKED_METERED_REASON_USER_RESTRICTED);
9864 
9865         setBlockedReasonChanged(BLOCKED_REASON_NONE);
9866         cellNetworkCallback.expect(BLOCKED_STATUS, mCellAgent, cb -> !cb.getBlocked());
9867         detailedCallback.expect(BLOCKED_STATUS_INT, mCellAgent,
9868                 cb -> cb.getReason() == BLOCKED_REASON_NONE);
9869         assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetwork());
9870         assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
9871         assertNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
9872         assertExtraInfoFromCmPresent(mCellAgent);
9873 
9874         setBlockedReasonChanged(BLOCKED_METERED_REASON_DATA_SAVER);
9875         cellNetworkCallback.expect(BLOCKED_STATUS, mCellAgent, cb -> cb.getBlocked());
9876         detailedCallback.expect(BLOCKED_STATUS_INT, mCellAgent,
9877                 cb -> cb.getReason() == BLOCKED_METERED_REASON_DATA_SAVER);
9878         assertNull(mCm.getActiveNetwork());
9879         assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
9880         assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
9881         assertExtraInfoFromCmBlocked(mCellAgent);
9882 
9883         // Restrict the network based on UID rule and NOT_METERED capability change.
9884         mCellAgent.addCapability(NET_CAPABILITY_NOT_METERED);
9885         cellNetworkCallback.expectCaps(mCellAgent,
9886                 c -> c.hasCapability(NET_CAPABILITY_NOT_METERED));
9887         cellNetworkCallback.expect(BLOCKED_STATUS, mCellAgent, cb -> !cb.getBlocked());
9888         detailedCallback.expectCaps(mCellAgent, c -> c.hasCapability(NET_CAPABILITY_NOT_METERED));
9889         detailedCallback.expect(BLOCKED_STATUS_INT, mCellAgent,
9890                 cb -> cb.getReason() == BLOCKED_REASON_NONE);
9891         assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetwork());
9892         assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
9893         assertNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
9894         assertExtraInfoFromCmPresent(mCellAgent);
9895 
9896         mCellAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
9897         cellNetworkCallback.expectCaps(mCellAgent,
9898                 c -> !c.hasCapability(NET_CAPABILITY_NOT_METERED));
9899         cellNetworkCallback.expect(BLOCKED_STATUS, mCellAgent, cb -> cb.getBlocked());
9900         detailedCallback.expectCaps(mCellAgent,
9901                 c -> !c.hasCapability(NET_CAPABILITY_NOT_METERED));
9902         detailedCallback.expect(BLOCKED_STATUS_INT, mCellAgent,
9903                 cb -> cb.getReason() == BLOCKED_METERED_REASON_DATA_SAVER);
9904         assertNull(mCm.getActiveNetwork());
9905         assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
9906         assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
9907         assertExtraInfoFromCmBlocked(mCellAgent);
9908 
9909         setBlockedReasonChanged(BLOCKED_REASON_NONE);
9910         cellNetworkCallback.expect(BLOCKED_STATUS, mCellAgent, cb -> !cb.getBlocked());
9911         detailedCallback.expect(BLOCKED_STATUS_INT, mCellAgent,
9912                 cb -> cb.getReason() == BLOCKED_REASON_NONE);
9913         assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetwork());
9914         assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
9915         assertNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
9916         assertExtraInfoFromCmPresent(mCellAgent);
9917 
9918         setBlockedReasonChanged(BLOCKED_REASON_NONE);
9919         cellNetworkCallback.assertNoCallback();
9920         detailedCallback.assertNoCallback();
9921 
9922         // Restrict background data. Networking is not blocked because the network is unmetered.
9923         setBlockedReasonChanged(BLOCKED_METERED_REASON_DATA_SAVER);
9924         cellNetworkCallback.expect(BLOCKED_STATUS, mCellAgent, cb -> cb.getBlocked());
9925         detailedCallback.expect(BLOCKED_STATUS_INT, mCellAgent,
9926                 cb -> cb.getReason() == BLOCKED_METERED_REASON_DATA_SAVER);
9927         assertNull(mCm.getActiveNetwork());
9928         assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
9929         assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
9930         assertExtraInfoFromCmBlocked(mCellAgent);
9931         setBlockedReasonChanged(BLOCKED_METERED_REASON_DATA_SAVER);
9932         cellNetworkCallback.assertNoCallback();
9933 
9934         setBlockedReasonChanged(BLOCKED_REASON_NONE);
9935         cellNetworkCallback.expect(BLOCKED_STATUS, mCellAgent, cb -> !cb.getBlocked());
9936         detailedCallback.expect(BLOCKED_STATUS_INT, mCellAgent,
9937                 cb -> cb.getReason() == BLOCKED_REASON_NONE);
9938         assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
9939         assertNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
9940         assertExtraInfoFromCmPresent(mCellAgent);
9941 
9942         setBlockedReasonChanged(BLOCKED_REASON_NONE);
9943         cellNetworkCallback.assertNoCallback();
9944         detailedCallback.assertNoCallback();
9945         assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetwork());
9946         assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
9947         assertNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
9948         assertExtraInfoFromCmPresent(mCellAgent);
9949 
9950         // Remove PERMISSION_INTERNET and disable NETWORK_BLOCKED_WITHOUT_INTERNET_PERMISSION
9951         doReturn(INetd.PERMISSION_NONE).when(mBpfNetMaps).getNetPermForUid(Process.myUid());
9952         mDeps.setChangeIdEnabled(false,
9953                 NETWORK_BLOCKED_WITHOUT_INTERNET_PERMISSION, Process.myUid());
9954 
9955         setBlockedReasonChanged(BLOCKED_REASON_DOZE);
9956         if (mDeps.isAtLeastV()) {
9957             // On V+, network access from app that does not have INTERNET permission is considered
9958             // not blocked if NETWORK_BLOCKED_WITHOUT_INTERNET_PERMISSION is disabled.
9959             // So blocked status does not change from BLOCKED_REASON_NONE
9960             cellNetworkCallback.assertNoCallback();
9961             detailedCallback.assertNoCallback();
9962         } else {
9963             // On U-, onBlockedStatusChanged callback is called with blocked reasons CS receives
9964             // from NPMS callback regardless of permission app has.
9965             // Note that this cannot actually happen because on U-, NPMS will never notify any
9966             // blocked reasons for apps that don't have the INTERNET permission.
9967             cellNetworkCallback.expect(BLOCKED_STATUS, mCellAgent, cb -> cb.getBlocked());
9968             detailedCallback.expect(BLOCKED_STATUS_INT, mCellAgent,
9969                     cb -> cb.getReason() == BLOCKED_REASON_DOZE);
9970         }
9971 
9972         mCm.unregisterNetworkCallback(cellNetworkCallback);
9973     }
9974 
9975     @Test
9976     public void testNetworkBlockedStatusBeforeAndAfterConnect() throws Exception {
9977         final TestNetworkCallback defaultCallback = new TestNetworkCallback();
9978         mCm.registerDefaultNetworkCallback(defaultCallback);
9979         mockUidNetworkingBlocked();
9980 
9981         // No Networkcallbacks invoked before any network is active.
9982         setBlockedReasonChanged(BLOCKED_REASON_BATTERY_SAVER);
9983         setBlockedReasonChanged(BLOCKED_REASON_NONE);
9984         setBlockedReasonChanged(BLOCKED_METERED_REASON_DATA_SAVER);
9985         defaultCallback.assertNoCallback();
9986 
9987         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
9988         mCellAgent.connect(true);
9989         defaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mCellAgent);
9990         defaultCallback.expectCaps(mCellAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
9991 
9992         // Allow to use the network after switching to NOT_METERED network.
9993         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
9994         mWiFiAgent.addCapability(NET_CAPABILITY_NOT_METERED);
9995         mWiFiAgent.connect(true);
9996         defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiAgent);
9997 
9998         // Switch to METERED network. Restrict the use of the network.
9999         mWiFiAgent.disconnect();
10000         defaultCallback.expect(LOST, mWiFiAgent);
10001         defaultCallback.expectAvailableCallbacksValidatedAndBlocked(mCellAgent);
10002 
10003         // Network becomes NOT_METERED.
10004         mCellAgent.addCapability(NET_CAPABILITY_NOT_METERED);
10005         defaultCallback.expectCaps(mCellAgent, c -> c.hasCapability(NET_CAPABILITY_NOT_METERED));
10006         defaultCallback.expect(BLOCKED_STATUS, mCellAgent, cb -> !cb.getBlocked());
10007 
10008         // Verify there's no Networkcallbacks invoked after data saver on/off.
10009         setBlockedReasonChanged(BLOCKED_METERED_REASON_DATA_SAVER);
10010         setBlockedReasonChanged(BLOCKED_REASON_NONE);
10011         defaultCallback.assertNoCallback();
10012 
10013         mCellAgent.disconnect();
10014         defaultCallback.expect(LOST, mCellAgent);
10015         defaultCallback.assertNoCallback();
10016 
10017         mCm.unregisterNetworkCallback(defaultCallback);
10018     }
10019 
10020     private void expectNetworkRejectNonSecureVpn(InOrder inOrder, boolean add,
10021             UidRangeParcel... expected) throws Exception {
10022         inOrder.verify(mMockNetd).networkRejectNonSecureVpn(eq(add), aryEq(expected));
10023     }
10024 
10025     private void checkNetworkInfo(NetworkInfo ni, int type, DetailedState state) {
10026         assertNotNull(ni);
10027         assertEquals(type, ni.getType());
10028         assertEquals(ConnectivityManager.getNetworkTypeName(type), state, ni.getDetailedState());
10029         if (state == DetailedState.CONNECTED || state == DetailedState.SUSPENDED) {
10030             assertNotNull(ni.getExtraInfo());
10031         } else {
10032             // Technically speaking, a network that's in CONNECTING state will generally have a
10033             // non-null extraInfo. This doesn't actually happen in this test because it never calls
10034             // a legacy API while a network is connecting. When a network is in CONNECTING state
10035             // because of legacy lockdown VPN, its extraInfo is always null.
10036             assertNull(ni.getExtraInfo());
10037         }
10038     }
10039 
10040     private void assertActiveNetworkInfo(int type, DetailedState state) {
10041         checkNetworkInfo(mCm.getActiveNetworkInfo(), type, state);
10042     }
10043     private void assertNetworkInfo(int type, DetailedState state) {
10044         checkNetworkInfo(mCm.getNetworkInfo(type), type, state);
10045     }
10046 
10047     private void assertExtraInfoFromCm(TestNetworkAgentWrapper network, boolean present) {
10048         final NetworkInfo niForNetwork = mCm.getNetworkInfo(network.getNetwork());
10049         final NetworkInfo niForType = mCm.getNetworkInfo(network.getLegacyType());
10050         if (present) {
10051             assertEquals(network.getExtraInfo(), niForNetwork.getExtraInfo());
10052             assertEquals(network.getExtraInfo(), niForType.getExtraInfo());
10053         } else {
10054             assertNull(niForNetwork.getExtraInfo());
10055             assertNull(niForType.getExtraInfo());
10056         }
10057     }
10058 
10059     private void assertExtraInfoFromCmBlocked(TestNetworkAgentWrapper network) {
10060         assertExtraInfoFromCm(network, false);
10061     }
10062 
10063     private void assertExtraInfoFromCmPresent(TestNetworkAgentWrapper network) {
10064         assertExtraInfoFromCm(network, true);
10065     }
10066 
10067     // Checks that each of the |agents| receive a blocked status change callback with the specified
10068     // |blocked| value, in any order. This is needed because when an event affects multiple
10069     // networks, ConnectivityService does not guarantee the order in which callbacks are fired.
10070     private void assertBlockedCallbackInAnyOrder(TestNetworkCallback callback, boolean blocked,
10071             TestNetworkAgentWrapper... agents) {
10072         final List<Network> expectedNetworks = asList(agents).stream()
10073                 .map((agent) -> agent.getNetwork())
10074                 .collect(Collectors.toList());
10075 
10076         // Expect exactly one blocked callback for each agent.
10077         for (int i = 0; i < agents.length; i++) {
10078             final CallbackEntry e = callback.expect(BLOCKED_STATUS, TIMEOUT_MS,
10079                     c -> c.getBlocked() == blocked);
10080             final Network network = e.getNetwork();
10081             assertTrue("Received unexpected blocked callback for network " + network,
10082                     expectedNetworks.remove(network));
10083         }
10084     }
10085 
10086     @Test
10087     public void testNetworkBlockedStatusAlwaysOnVpn() throws Exception {
10088         mServiceContext.setPermission(
10089                 Manifest.permission.CONTROL_ALWAYS_ON_VPN, PERMISSION_GRANTED);
10090         mServiceContext.setPermission(
10091                 Manifest.permission.CONTROL_VPN, PERMISSION_GRANTED);
10092         mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_GRANTED);
10093 
10094         final TestNetworkCallback callback = new TestNetworkCallback();
10095         final NetworkRequest request = new NetworkRequest.Builder()
10096                 .removeCapability(NET_CAPABILITY_NOT_VPN)
10097                 .build();
10098         mCm.registerNetworkCallback(request, callback);
10099 
10100         final TestNetworkCallback defaultCallback = new TestNetworkCallback();
10101         mCm.registerDefaultNetworkCallback(defaultCallback);
10102 
10103         final TestNetworkCallback vpnUidCallback = new TestNetworkCallback();
10104         final NetworkRequest vpnUidRequest = new NetworkRequest.Builder().build();
10105         registerNetworkCallbackAsUid(vpnUidRequest, vpnUidCallback, VPN_UID);
10106 
10107         final TestNetworkCallback vpnUidDefaultCallback = new TestNetworkCallback();
10108         registerDefaultNetworkCallbackAsUid(vpnUidDefaultCallback, VPN_UID);
10109 
10110         final TestNetworkCallback vpnDefaultCallbackAsUid = new TestNetworkCallback();
10111         mCm.registerDefaultNetworkCallbackForUid(VPN_UID, vpnDefaultCallbackAsUid,
10112                 new Handler(ConnectivityThread.getInstanceLooper()));
10113 
10114         final int uid = Process.myUid();
10115 
10116         // Enable always-on VPN lockdown, coverage in VpnTest.
10117         final List<Integer> excludedUids = new ArrayList<Integer>();
10118         excludedUids.add(VPN_UID);
10119         if (mDeps.isAtLeastT()) {
10120             // On T onwards, the corresponding SDK sandbox UID should also be excluded
10121             excludedUids.add(toSdkSandboxUid(VPN_UID));
10122         }
10123 
10124         final List<Range<Integer>> primaryRanges = intRangesPrimaryExcludingUids(excludedUids);
10125         mCm.setRequireVpnForUids(true, primaryRanges);
10126         waitForIdle();
10127 
10128         final UidRangeParcel[] uidRangeParcels = intToUidRangeStableParcels(primaryRanges);
10129         InOrder inOrder = inOrder(mMockNetd);
10130         expectNetworkRejectNonSecureVpn(inOrder, true, uidRangeParcels);
10131 
10132         // Connect a network when lockdown is active, expect to see it blocked.
10133         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
10134         mWiFiAgent.connect(false /* validated */);
10135         callback.expectAvailableCallbacksUnvalidatedAndBlocked(mWiFiAgent);
10136         defaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mWiFiAgent);
10137         vpnUidCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
10138         vpnUidDefaultCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
10139         vpnDefaultCallbackAsUid.expectAvailableCallbacksUnvalidated(mWiFiAgent);
10140         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
10141         assertNull(mCm.getActiveNetwork());
10142         assertActiveNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED);
10143         // Mobile is BLOCKED even though it's not actually connected.
10144         assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
10145         assertNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED);
10146 
10147         // Disable lockdown, expect to see the network unblocked.
10148         mCm.setRequireVpnForUids(false, primaryRanges);
10149         waitForIdle();
10150         callback.expect(BLOCKED_STATUS, mWiFiAgent, cb -> !cb.getBlocked());
10151         defaultCallback.expect(BLOCKED_STATUS, mWiFiAgent, cb -> !cb.getBlocked());
10152         vpnUidCallback.assertNoCallback();
10153         vpnUidDefaultCallback.assertNoCallback();
10154         vpnDefaultCallbackAsUid.assertNoCallback();
10155         expectNetworkRejectNonSecureVpn(inOrder, false, uidRangeParcels);
10156         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
10157         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetwork());
10158         assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
10159         assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED);
10160         assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
10161 
10162         // Add our UID to the allowlist, expect network is not blocked. Coverage in VpnTest.
10163         excludedUids.add(uid);
10164         if (mDeps.isAtLeastT()) {
10165             // On T onwards, the corresponding SDK sandbox UID should also be excluded
10166             excludedUids.add(toSdkSandboxUid(uid));
10167         }
10168         final List<Range<Integer>> primaryRangesExcludingUid =
10169                 intRangesPrimaryExcludingUids(excludedUids);
10170         mCm.setRequireVpnForUids(true, primaryRangesExcludingUid);
10171         waitForIdle();
10172 
10173         callback.assertNoCallback();
10174         defaultCallback.assertNoCallback();
10175         vpnUidCallback.assertNoCallback();
10176         vpnUidDefaultCallback.assertNoCallback();
10177         vpnDefaultCallbackAsUid.assertNoCallback();
10178 
10179         final UidRangeParcel[] uidRangeParcelsAlsoExcludingUs =
10180                 intToUidRangeStableParcels(primaryRangesExcludingUid);
10181         expectNetworkRejectNonSecureVpn(inOrder, true, uidRangeParcelsAlsoExcludingUs);
10182         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
10183         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetwork());
10184         assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
10185         assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED);
10186         assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
10187 
10188         // Connect a new network, expect it to be unblocked.
10189         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
10190         mCellAgent.connect(false /* validated */);
10191         callback.expectAvailableCallbacksUnvalidated(mCellAgent);
10192         defaultCallback.assertNoCallback();
10193         vpnUidCallback.expectAvailableCallbacksUnvalidated(mCellAgent);
10194         vpnUidDefaultCallback.assertNoCallback();
10195         vpnDefaultCallbackAsUid.assertNoCallback();
10196         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
10197         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetwork());
10198         assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
10199         // Cellular is DISCONNECTED because it's not the default and there are no requests for it.
10200         assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED);
10201         assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
10202 
10203         // Disable lockdown
10204         mCm.setRequireVpnForUids(false, primaryRangesExcludingUid);
10205         waitForIdle();
10206         expectNetworkRejectNonSecureVpn(inOrder, false, uidRangeParcelsAlsoExcludingUs);
10207         // Remove our UID from the allowlist, and re-enable lockdown.
10208         mCm.setRequireVpnForUids(true, primaryRanges);
10209         waitForIdle();
10210         expectNetworkRejectNonSecureVpn(inOrder, true, uidRangeParcels);
10211         // Everything should now be blocked.
10212         defaultCallback.expect(BLOCKED_STATUS, mWiFiAgent, cb -> cb.getBlocked());
10213         assertBlockedCallbackInAnyOrder(callback, true, mWiFiAgent, mCellAgent);
10214         vpnUidCallback.assertNoCallback();
10215         vpnUidDefaultCallback.assertNoCallback();
10216         vpnDefaultCallbackAsUid.assertNoCallback();
10217         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
10218         assertNull(mCm.getActiveNetwork());
10219         assertActiveNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED);
10220         assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
10221         assertNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED);
10222 
10223         // Disable lockdown. Everything is unblocked.
10224         mCm.setRequireVpnForUids(false, primaryRanges);
10225         defaultCallback.expect(BLOCKED_STATUS, mWiFiAgent, cb -> !cb.getBlocked());
10226         assertBlockedCallbackInAnyOrder(callback, false, mWiFiAgent, mCellAgent);
10227         vpnUidCallback.assertNoCallback();
10228         vpnUidDefaultCallback.assertNoCallback();
10229         vpnDefaultCallbackAsUid.assertNoCallback();
10230         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
10231         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetwork());
10232         assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
10233         assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED);
10234         assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
10235 
10236         // Enable lockdown and connect a VPN. The VPN is not blocked.
10237         mCm.setRequireVpnForUids(true, primaryRanges);
10238         defaultCallback.expect(BLOCKED_STATUS, mWiFiAgent, cb -> cb.getBlocked());
10239         assertBlockedCallbackInAnyOrder(callback, true, mWiFiAgent, mCellAgent);
10240         vpnUidCallback.assertNoCallback();
10241         vpnUidDefaultCallback.assertNoCallback();
10242         vpnDefaultCallbackAsUid.assertNoCallback();
10243         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
10244         assertNull(mCm.getActiveNetwork());
10245         assertActiveNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED);
10246         assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
10247         assertNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED);
10248 
10249         mMockVpn.establishForMyUid();
10250         assertUidRangesUpdatedForMyUid(true);
10251         defaultCallback.expectAvailableThenValidatedCallbacks(mMockVpn);
10252         vpnUidCallback.assertNoCallback();  // vpnUidCallback has NOT_VPN capability.
10253         vpnUidDefaultCallback.assertNoCallback();  // VPN does not apply to VPN_UID
10254         vpnDefaultCallbackAsUid.assertNoCallback();
10255         assertEquals(mMockVpn.getNetwork(), mCm.getActiveNetwork());
10256         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
10257         assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
10258         assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED);
10259         assertNetworkInfo(TYPE_VPN, DetailedState.CONNECTED);
10260         assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
10261 
10262         mMockVpn.disconnect();
10263         defaultCallback.expect(LOST, mMockVpn);
10264         defaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mWiFiAgent);
10265         vpnUidCallback.assertNoCallback();
10266         vpnUidDefaultCallback.assertNoCallback();
10267         vpnDefaultCallbackAsUid.assertNoCallback();
10268         assertNull(mCm.getActiveNetwork());
10269 
10270         mCm.unregisterNetworkCallback(callback);
10271         mCm.unregisterNetworkCallback(defaultCallback);
10272         mCm.unregisterNetworkCallback(vpnUidCallback);
10273         mCm.unregisterNetworkCallback(vpnUidDefaultCallback);
10274         mCm.unregisterNetworkCallback(vpnDefaultCallbackAsUid);
10275     }
10276 
10277     @Test
10278     public void testVpnExcludesOwnUid() throws Exception {
10279         // required for registerDefaultNetworkCallbackForUid.
10280         mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_GRANTED);
10281 
10282         // Connect Wi-Fi.
10283         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
10284         mWiFiAgent.connect(true /* validated */);
10285 
10286         // Connect a VPN that excludes its UID from its UID ranges.
10287         final LinkProperties lp = new LinkProperties();
10288         lp.setInterfaceName(VPN_IFNAME);
10289         final int myUid = Process.myUid();
10290         final Set<UidRange> ranges = new ArraySet<>();
10291         ranges.add(new UidRange(0, myUid - 1));
10292         ranges.add(new UidRange(myUid + 1, UserHandle.PER_USER_RANGE - 1));
10293         mMockVpn.setUnderlyingNetworks(new Network[] { mWiFiAgent.getNetwork() });
10294         mMockVpn.establish(lp, myUid, ranges);
10295 
10296         // Wait for validation before registering callbacks.
10297         waitForIdle();
10298 
10299         final int otherUid = myUid + 1;
10300         final Handler h = new Handler(ConnectivityThread.getInstanceLooper());
10301         final TestNetworkCallback otherUidCb = new TestNetworkCallback();
10302         final TestNetworkCallback defaultCb = new TestNetworkCallback();
10303         final TestNetworkCallback perUidCb = new TestNetworkCallback();
10304         registerDefaultNetworkCallbackAsUid(otherUidCb, otherUid);
10305         mCm.registerDefaultNetworkCallback(defaultCb, h);
10306         doAsUid(Process.SYSTEM_UID,
10307                 () -> mCm.registerDefaultNetworkCallbackForUid(myUid, perUidCb, h));
10308 
10309         otherUidCb.expectAvailableCallbacksValidated(mMockVpn);
10310         // BUG (b/195265065): the default network for the VPN app is actually Wi-Fi, not the VPN.
10311         defaultCb.expectAvailableCallbacksValidated(mMockVpn);
10312         perUidCb.expectAvailableCallbacksValidated(mMockVpn);
10313         // getActiveNetwork is not affected by this bug.
10314         assertEquals(mMockVpn.getNetwork(), mCm.getActiveNetworkForUid(myUid + 1));
10315         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetwork());
10316         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetworkForUid(myUid));
10317 
10318         doAsUid(otherUid, () -> mCm.unregisterNetworkCallback(otherUidCb));
10319         mCm.unregisterNetworkCallback(defaultCb);
10320         doAsUid(Process.SYSTEM_UID, () -> mCm.unregisterNetworkCallback(perUidCb));
10321     }
10322 
10323     private void establishLegacyLockdownVpn(Network underlying) throws Exception {
10324         // The legacy lockdown VPN only supports userId 0, and must have an underlying network.
10325         assertNotNull(underlying);
10326         mMockVpn.setVpnType(VpnManager.TYPE_VPN_LEGACY);
10327         // The legacy lockdown VPN only supports userId 0.
10328         final Set<UidRange> ranges = Collections.singleton(PRIMARY_UIDRANGE);
10329         mMockVpn.registerAgent(ranges);
10330         mMockVpn.setUnderlyingNetworks(new Network[]{underlying});
10331         mMockVpn.connect(true);
10332     }
10333 
10334     private void doTestLockdownVpn(boolean isIkev2Vpn)
10335             throws Exception {
10336         mServiceContext.setPermission(
10337                 Manifest.permission.CONTROL_VPN, PERMISSION_GRANTED);
10338 
10339         final NetworkRequest request = new NetworkRequest.Builder().clearCapabilities().build();
10340         final TestNetworkCallback callback = new TestNetworkCallback();
10341         mCm.registerNetworkCallback(request, callback);
10342 
10343         final TestNetworkCallback defaultCallback = new TestNetworkCallback();
10344         mCm.registerDefaultNetworkCallback(defaultCallback);
10345 
10346         final TestNetworkCallback systemDefaultCallback = new TestNetworkCallback();
10347         mCm.registerSystemDefaultNetworkCallback(systemDefaultCallback,
10348                 new Handler(ConnectivityThread.getInstanceLooper()));
10349 
10350         // Init lockdown state to simulate LockdownVpnTracker behavior.
10351         mCm.setLegacyLockdownVpnEnabled(true);
10352         final List<Range<Integer>> ranges =
10353                 intRangesPrimaryExcludingUids(Collections.EMPTY_LIST /* excludedeUids */);
10354         mCm.setRequireVpnForUids(true /* requireVpn */, ranges);
10355 
10356         // Bring up a network.
10357         final LinkProperties cellLp = new LinkProperties();
10358         cellLp.setInterfaceName("rmnet0");
10359         cellLp.addLinkAddress(new LinkAddress("192.0.2.2/25"));
10360         cellLp.addRoute(new RouteInfo(new IpPrefix("0.0.0.0/0"), null, "rmnet0"));
10361         // When lockdown VPN is active, the NetworkInfo state in CONNECTIVITY_ACTION is overwritten
10362         // with the state of the VPN network. So expect a CONNECTING broadcast.
10363         final ExpectedBroadcast b = expectConnectivityAction(TYPE_MOBILE, DetailedState.CONNECTING);
10364         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
10365         mCellAgent.connect(false /* validated */);
10366         callback.expectAvailableCallbacksUnvalidatedAndBlocked(mCellAgent);
10367         defaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mCellAgent);
10368         systemDefaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mCellAgent);
10369         b.expectBroadcast();
10370         // Simulate LockdownVpnTracker attempting to start the VPN since it received the
10371         // systemDefault callback.
10372         mMockVpn.startLegacyVpnPrivileged(isIkev2Vpn);
10373         if (isIkev2Vpn) {
10374             // setVpnDefaultForUids() releases the original network request and creates a VPN
10375             // request so LOST callback is received.
10376             defaultCallback.expect(LOST, mCellAgent);
10377             // Due to the VPN default request, getActiveNetworkInfo() gets the mNoServiceNetwork
10378             // as the network satisfier.
10379             assertNull(mCm.getActiveNetworkInfo());
10380         } else {
10381             assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
10382         }
10383         assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
10384         assertNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED);
10385         assertNetworkInfo(TYPE_VPN, DetailedState.BLOCKED);
10386         assertExtraInfoFromCmBlocked(mCellAgent);
10387 
10388         final ExpectedBroadcast b2 = expectConnectivityAction(TYPE_VPN, DetailedState.CONNECTED);
10389         final ExpectedBroadcast b3 = expectConnectivityAction(TYPE_MOBILE, DetailedState.CONNECTED);
10390         establishLegacyLockdownVpn(mCellAgent.getNetwork());
10391         callback.expectAvailableThenValidatedCallbacks(mMockVpn);
10392         defaultCallback.expectAvailableThenValidatedCallbacks(mMockVpn);
10393         systemDefaultCallback.assertNoCallback();
10394         final NetworkCapabilities vpnNc = mCm.getNetworkCapabilities(mMockVpn.getNetwork());
10395         b2.expectBroadcast();
10396         b3.expectBroadcast();
10397         if (isIkev2Vpn) {
10398             // Due to the VPN default request, getActiveNetworkInfo() gets the VPN network as the
10399             // network satisfier which has TYPE_VPN.
10400             assertActiveNetworkInfo(TYPE_VPN, DetailedState.CONNECTED);
10401         } else {
10402             // LegacyVpnRunner does not call setVpnDefaultsForUids(), which means
10403             // getActiveNetworkInfo() can only return the info for the system-wide default instead.
10404             // This should be fixed, but LegacyVpnRunner will be removed soon anyway.
10405             assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
10406         }
10407         assertNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
10408         assertNetworkInfo(TYPE_WIFI, DetailedState.DISCONNECTED);
10409         assertNetworkInfo(TYPE_VPN, DetailedState.CONNECTED);
10410         assertExtraInfoFromCmPresent(mCellAgent);
10411         assertTrue(vpnNc.hasTransport(TRANSPORT_VPN));
10412         assertTrue(vpnNc.hasTransport(TRANSPORT_CELLULAR));
10413         assertFalse(vpnNc.hasTransport(TRANSPORT_WIFI));
10414         assertFalse(vpnNc.hasCapability(NET_CAPABILITY_NOT_METERED));
10415         assertVpnTransportInfo(vpnNc, VpnManager.TYPE_VPN_LEGACY);
10416 
10417         // Switch default network from cell to wifi. Expect VPN to disconnect and reconnect.
10418         final LinkProperties wifiLp = new LinkProperties();
10419         wifiLp.setInterfaceName("wlan0");
10420         wifiLp.addLinkAddress(new LinkAddress("192.0.2.163/25"));
10421         wifiLp.addRoute(new RouteInfo(new IpPrefix("0.0.0.0/0"), null, "wlan0"));
10422         final NetworkCapabilities wifiNc = new NetworkCapabilities();
10423         wifiNc.addTransportType(TRANSPORT_WIFI);
10424         wifiNc.addCapability(NET_CAPABILITY_NOT_METERED);
10425         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp, wifiNc);
10426 
10427         final ExpectedBroadcast b4 =
10428                 expectConnectivityAction(TYPE_MOBILE, DetailedState.DISCONNECTED);
10429         // Wifi is CONNECTING because the VPN isn't up yet.
10430         final ExpectedBroadcast b5 = expectConnectivityAction(TYPE_WIFI, DetailedState.CONNECTING);
10431         mWiFiAgent.connect(false /* validated */);
10432         // Wifi is not blocked since VPN network is still connected.
10433         callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
10434         defaultCallback.assertNoCallback();
10435         systemDefaultCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
10436         b4.expectBroadcast();
10437         b5.expectBroadcast();
10438 
10439         // Simulate LockdownVpnTracker restarting the VPN since it received the systemDefault
10440         // callback with different network.
10441         final ExpectedBroadcast b6 = expectConnectivityAction(TYPE_VPN, DetailedState.DISCONNECTED);
10442         mMockVpn.stopVpnRunnerPrivileged();
10443 
10444         mMockVpn.startLegacyVpnPrivileged(isIkev2Vpn);
10445         // VPN network is disconnected (to restart)
10446         callback.expect(LOST, mMockVpn);
10447         defaultCallback.expect(LOST, mMockVpn);
10448         // The network preference is cleared when VPN is disconnected so it receives callbacks for
10449         // the system-wide default.
10450         defaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mWiFiAgent);
10451         if (isIkev2Vpn) {
10452             // setVpnDefaultForUids() releases the original network request and creates a VPN
10453             // request so LOST callback is received.
10454             defaultCallback.expect(LOST, mWiFiAgent);
10455         }
10456         systemDefaultCallback.assertNoCallback();
10457         b6.expectBroadcast();
10458 
10459         // While the VPN is reconnecting on the new network, everything is blocked.
10460         if (isIkev2Vpn) {
10461             // Due to the VPN default request, getActiveNetworkInfo() gets the mNoServiceNetwork
10462             // as the network satisfier.
10463             assertNull(mCm.getActiveNetworkInfo());
10464         } else {
10465             assertActiveNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED);
10466         }
10467         assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
10468         assertNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED);
10469         assertNetworkInfo(TYPE_VPN, DetailedState.BLOCKED);
10470         assertExtraInfoFromCmBlocked(mWiFiAgent);
10471 
10472         // The VPN comes up again on wifi.
10473         final ExpectedBroadcast b7 = expectConnectivityAction(TYPE_VPN, DetailedState.CONNECTED);
10474         final ExpectedBroadcast b8 = expectConnectivityAction(TYPE_WIFI, DetailedState.CONNECTED);
10475         establishLegacyLockdownVpn(mWiFiAgent.getNetwork());
10476         callback.expectAvailableThenValidatedCallbacks(mMockVpn);
10477         defaultCallback.expectAvailableThenValidatedCallbacks(mMockVpn);
10478         systemDefaultCallback.assertNoCallback();
10479         b7.expectBroadcast();
10480         b8.expectBroadcast();
10481         if (isIkev2Vpn) {
10482             // Due to the VPN default request, getActiveNetworkInfo() gets the VPN network as the
10483             // network satisfier which has TYPE_VPN.
10484             assertActiveNetworkInfo(TYPE_VPN, DetailedState.CONNECTED);
10485         } else {
10486             // LegacyVpnRunner does not call setVpnDefaultsForUids(), which means
10487             // getActiveNetworkInfo() can only return the info for the system-wide default instead.
10488             // This should be fixed, but LegacyVpnRunner will be removed soon anyway.
10489             assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
10490         }
10491         assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED);
10492         assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
10493         assertNetworkInfo(TYPE_VPN, DetailedState.CONNECTED);
10494         assertExtraInfoFromCmPresent(mWiFiAgent);
10495         final NetworkCapabilities vpnNc2 = mCm.getNetworkCapabilities(mMockVpn.getNetwork());
10496         assertTrue(vpnNc2.hasTransport(TRANSPORT_VPN));
10497         assertTrue(vpnNc2.hasTransport(TRANSPORT_WIFI));
10498         assertFalse(vpnNc2.hasTransport(TRANSPORT_CELLULAR));
10499         assertTrue(vpnNc2.hasCapability(NET_CAPABILITY_NOT_METERED));
10500 
10501         // Disconnect cell. Nothing much happens since it's not the default network.
10502         mCellAgent.disconnect();
10503         callback.expect(LOST, mCellAgent);
10504         defaultCallback.assertNoCallback();
10505         systemDefaultCallback.assertNoCallback();
10506 
10507         if (isIkev2Vpn) {
10508             // Due to the VPN default request, getActiveNetworkInfo() gets the VPN network as the
10509             // network satisfier which has TYPE_VPN.
10510             assertActiveNetworkInfo(TYPE_VPN, DetailedState.CONNECTED);
10511         } else {
10512             // LegacyVpnRunner does not call setVpnDefaultsForUids(), which means
10513             // getActiveNetworkInfo() can only return the info for the system-wide default instead.
10514             // This should be fixed, but LegacyVpnRunner will be removed soon anyway.
10515             assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
10516         }
10517         assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED);
10518         assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
10519         assertNetworkInfo(TYPE_VPN, DetailedState.CONNECTED);
10520         assertExtraInfoFromCmPresent(mWiFiAgent);
10521 
10522         final ExpectedBroadcast b9 =
10523                 expectConnectivityAction(TYPE_WIFI, DetailedState.DISCONNECTED);
10524         final ExpectedBroadcast b10 =
10525                 expectConnectivityAction(TYPE_VPN, DetailedState.DISCONNECTED);
10526         mWiFiAgent.disconnect();
10527         callback.expect(LOST, mWiFiAgent);
10528         callback.expectCaps(mMockVpn, c -> !c.hasTransport(TRANSPORT_WIFI));
10529         defaultCallback.expectCaps(mMockVpn, c -> !c.hasTransport(TRANSPORT_WIFI));
10530         systemDefaultCallback.expect(LOST, mWiFiAgent);
10531         // TODO: There should only be one LOST callback. Since the WIFI network is underlying a VPN
10532         // network, ConnectivityService#propagateUnderlyingNetworkCapabilities() causes a rematch to
10533         // occur. Notably, this happens before setting the satisfiers of its network requests to
10534         // null. Since the satisfiers are set to null in the rematch, an extra LOST callback is
10535         // called.
10536         systemDefaultCallback.expect(LOST, mWiFiAgent);
10537         b9.expectBroadcast();
10538         mMockVpn.stopVpnRunnerPrivileged();
10539         callback.expect(LOST, mMockVpn);
10540         defaultCallback.expect(LOST, mMockVpn);
10541         b10.expectBroadcast();
10542 
10543         assertNoCallbacks(callback, defaultCallback, systemDefaultCallback);
10544     }
10545 
10546     @Test
10547     public void testLockdownVpn_LegacyVpnRunner() throws Exception {
10548         doTestLockdownVpn(false /* isIkev2Vpn */);
10549     }
10550 
10551     @Test
10552     public void testLockdownVpn_Ikev2VpnRunner() throws Exception {
10553         doTestLockdownVpn(true /* isIkev2Vpn */);
10554     }
10555 
10556     @Test @IgnoreUpTo(Build.VERSION_CODES.S_V2)
10557     public void testLockdownSetFirewallUidRule() throws Exception {
10558         final List<Range<Integer>> lockdownRange =
10559                 intRangesPrimaryExcludingUids(Collections.EMPTY_LIST /* excludedeUids */);
10560         // Enable Lockdown
10561         mCm.setRequireVpnForUids(true /* requireVpn */, lockdownRange);
10562         waitForIdle();
10563 
10564         // Lockdown rule is set to apps uids
10565         verify(mBpfNetMaps, times(3)).updateUidLockdownRule(anyInt(), eq(true) /* add */);
10566         verify(mBpfNetMaps).updateUidLockdownRule(APP1_UID, true /* add */);
10567         verify(mBpfNetMaps).updateUidLockdownRule(APP2_UID, true /* add */);
10568         verify(mBpfNetMaps).updateUidLockdownRule(VPN_UID, true /* add */);
10569 
10570         reset(mBpfNetMaps);
10571 
10572         // Disable lockdown
10573         mCm.setRequireVpnForUids(false /* requireVPN */, lockdownRange);
10574         waitForIdle();
10575 
10576         // Lockdown rule is removed from apps uids
10577         verify(mBpfNetMaps, times(3)).updateUidLockdownRule(anyInt(), eq(false) /* add */);
10578         verify(mBpfNetMaps).updateUidLockdownRule(APP1_UID, false /* add */);
10579         verify(mBpfNetMaps).updateUidLockdownRule(APP2_UID, false /* add */);
10580         verify(mBpfNetMaps).updateUidLockdownRule(VPN_UID, false /* add */);
10581 
10582         // Interface rules are not changed by Lockdown mode enable/disable
10583         verify(mBpfNetMaps, never()).addUidInterfaceRules(any(), any());
10584         verify(mBpfNetMaps, never()).removeUidInterfaceRules(any());
10585     }
10586 
10587     private void doTestSetUidFirewallRule(final int chain, final int defaultRule) {
10588         final int uid = 1001;
10589         mCm.setUidFirewallRule(chain, uid, FIREWALL_RULE_ALLOW);
10590         verify(mBpfNetMaps).setUidRule(chain, uid, FIREWALL_RULE_ALLOW);
10591         reset(mBpfNetMaps);
10592 
10593         mCm.setUidFirewallRule(chain, uid, FIREWALL_RULE_DENY);
10594         verify(mBpfNetMaps).setUidRule(chain, uid, FIREWALL_RULE_DENY);
10595         reset(mBpfNetMaps);
10596 
10597         mCm.setUidFirewallRule(chain, uid, FIREWALL_RULE_DEFAULT);
10598         verify(mBpfNetMaps).setUidRule(chain, uid, defaultRule);
10599         reset(mBpfNetMaps);
10600     }
10601 
10602     @Test @IgnoreUpTo(SC_V2)
10603     public void testSetUidFirewallRule() throws Exception {
10604         doTestSetUidFirewallRule(FIREWALL_CHAIN_DOZABLE, FIREWALL_RULE_DENY);
10605         doTestSetUidFirewallRule(FIREWALL_CHAIN_STANDBY, FIREWALL_RULE_ALLOW);
10606         doTestSetUidFirewallRule(FIREWALL_CHAIN_POWERSAVE, FIREWALL_RULE_DENY);
10607         doTestSetUidFirewallRule(FIREWALL_CHAIN_RESTRICTED, FIREWALL_RULE_DENY);
10608         doTestSetUidFirewallRule(FIREWALL_CHAIN_LOW_POWER_STANDBY, FIREWALL_RULE_DENY);
10609         if (SdkLevel.isAtLeastV()) {
10610             // FIREWALL_CHAIN_BACKGROUND is only available on V+.
10611             doTestSetUidFirewallRule(FIREWALL_CHAIN_BACKGROUND, FIREWALL_RULE_DENY);
10612         }
10613         doTestSetUidFirewallRule(FIREWALL_CHAIN_OEM_DENY_1, FIREWALL_RULE_ALLOW);
10614         doTestSetUidFirewallRule(FIREWALL_CHAIN_OEM_DENY_2, FIREWALL_RULE_ALLOW);
10615         doTestSetUidFirewallRule(FIREWALL_CHAIN_OEM_DENY_3, FIREWALL_RULE_ALLOW);
10616         doTestSetUidFirewallRule(FIREWALL_CHAIN_METERED_ALLOW, FIREWALL_RULE_DENY);
10617         doTestSetUidFirewallRule(FIREWALL_CHAIN_METERED_DENY_USER, FIREWALL_RULE_ALLOW);
10618         doTestSetUidFirewallRule(FIREWALL_CHAIN_METERED_DENY_ADMIN, FIREWALL_RULE_ALLOW);
10619     }
10620 
10621     @Test @IgnoreUpTo(SC_V2)
10622     public void testSetFirewallChainEnabled() throws Exception {
10623         final List<Integer> firewallChains = new ArrayList<>(Arrays.asList(
10624                 FIREWALL_CHAIN_DOZABLE,
10625                 FIREWALL_CHAIN_STANDBY,
10626                 FIREWALL_CHAIN_POWERSAVE,
10627                 FIREWALL_CHAIN_RESTRICTED,
10628                 FIREWALL_CHAIN_LOW_POWER_STANDBY,
10629                 FIREWALL_CHAIN_OEM_DENY_1,
10630                 FIREWALL_CHAIN_OEM_DENY_2,
10631                 FIREWALL_CHAIN_OEM_DENY_3));
10632         if (SdkLevel.isAtLeastV()) {
10633             // FIREWALL_CHAIN_BACKGROUND is only available on V+.
10634             firewallChains.add(FIREWALL_CHAIN_BACKGROUND);
10635         }
10636         for (final int chain: firewallChains) {
10637             mCm.setFirewallChainEnabled(chain, true /* enabled */);
10638             verify(mBpfNetMaps).setChildChain(chain, true /* enable */);
10639             reset(mBpfNetMaps);
10640 
10641             mCm.setFirewallChainEnabled(chain, false /* enabled */);
10642             verify(mBpfNetMaps).setChildChain(chain, false /* enable */);
10643             reset(mBpfNetMaps);
10644         }
10645     }
10646 
10647     private void doTestSetFirewallChainEnabledCloseSocket(final int chain,
10648             final boolean isAllowList) throws Exception {
10649         reset(mDestroySocketsWrapper);
10650 
10651         mCm.setFirewallChainEnabled(chain, true /* enabled */);
10652         final Set<Integer> uids =
10653                 new ArraySet<>(List.of(TEST_PACKAGE_UID, TEST_PACKAGE_UID2));
10654         if (isAllowList) {
10655             final Set<Range<Integer>> range = new ArraySet<>(
10656                     List.of(new Range<>(Process.FIRST_APPLICATION_UID, Integer.MAX_VALUE)));
10657             verify(mDestroySocketsWrapper).destroyLiveTcpSockets(range, uids);
10658         } else {
10659             verify(mDestroySocketsWrapper).destroyLiveTcpSocketsByOwnerUids(uids);
10660         }
10661 
10662         mCm.setFirewallChainEnabled(chain, false /* enabled */);
10663         verifyNoMoreInteractions(mDestroySocketsWrapper);
10664     }
10665 
10666     @Test @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
10667     public void testSetFirewallChainEnabledCloseSocket() throws Exception {
10668         doReturn(new ArraySet<>(Arrays.asList(TEST_PACKAGE_UID, TEST_PACKAGE_UID2)))
10669                 .when(mBpfNetMaps)
10670                 .getUidsWithDenyRuleOnDenyListChain(anyInt());
10671         doReturn(new ArraySet<>(Arrays.asList(TEST_PACKAGE_UID, TEST_PACKAGE_UID2)))
10672                 .when(mBpfNetMaps)
10673                 .getUidsWithAllowRuleOnAllowListChain(anyInt());
10674 
10675         final boolean allowlist = true;
10676         final boolean denylist = false;
10677 
10678         doTestSetFirewallChainEnabledCloseSocket(FIREWALL_CHAIN_DOZABLE, allowlist);
10679         doTestSetFirewallChainEnabledCloseSocket(FIREWALL_CHAIN_POWERSAVE, allowlist);
10680         doTestSetFirewallChainEnabledCloseSocket(FIREWALL_CHAIN_RESTRICTED, allowlist);
10681         doTestSetFirewallChainEnabledCloseSocket(FIREWALL_CHAIN_LOW_POWER_STANDBY, allowlist);
10682         if (SdkLevel.isAtLeastV()) {
10683             // FIREWALL_CHAIN_BACKGROUND is only available on V+.
10684             doTestSetFirewallChainEnabledCloseSocket(FIREWALL_CHAIN_BACKGROUND, allowlist);
10685         }
10686 
10687         doTestSetFirewallChainEnabledCloseSocket(FIREWALL_CHAIN_STANDBY, denylist);
10688         doTestSetFirewallChainEnabledCloseSocket(FIREWALL_CHAIN_OEM_DENY_1, denylist);
10689         doTestSetFirewallChainEnabledCloseSocket(FIREWALL_CHAIN_OEM_DENY_2, denylist);
10690         doTestSetFirewallChainEnabledCloseSocket(FIREWALL_CHAIN_OEM_DENY_3, denylist);
10691     }
10692 
10693     private void doTestReplaceFirewallChain(final int chain) {
10694         final int[] uids = new int[] {1001, 1002};
10695         mCm.replaceFirewallChain(chain, uids);
10696         verify(mBpfNetMaps).replaceUidChain(chain, uids);
10697         reset(mBpfNetMaps);
10698     }
10699 
10700     @Test @IgnoreUpTo(SC_V2)
10701     public void testReplaceFirewallChain() {
10702         doTestReplaceFirewallChain(FIREWALL_CHAIN_DOZABLE);
10703         doTestReplaceFirewallChain(FIREWALL_CHAIN_STANDBY);
10704         doTestReplaceFirewallChain(FIREWALL_CHAIN_POWERSAVE);
10705         doTestReplaceFirewallChain(FIREWALL_CHAIN_RESTRICTED);
10706         doTestReplaceFirewallChain(FIREWALL_CHAIN_LOW_POWER_STANDBY);
10707         if (SdkLevel.isAtLeastV()) {
10708             // FIREWALL_CHAIN_BACKGROUND is only available on V+.
10709             doTestReplaceFirewallChain(FIREWALL_CHAIN_BACKGROUND);
10710         }
10711         doTestReplaceFirewallChain(FIREWALL_CHAIN_OEM_DENY_1);
10712         doTestReplaceFirewallChain(FIREWALL_CHAIN_OEM_DENY_2);
10713         doTestReplaceFirewallChain(FIREWALL_CHAIN_OEM_DENY_3);
10714     }
10715 
10716     @Test @IgnoreUpTo(SC_V2)
10717     public void testInvalidFirewallChain() throws Exception {
10718         final int uid = 1001;
10719         final Class<IllegalArgumentException> expected = IllegalArgumentException.class;
10720         assertThrows(expected,
10721                 () -> mCm.setUidFirewallRule(-1 /* chain */, uid, FIREWALL_RULE_ALLOW));
10722         assertThrows(expected,
10723                 () -> mCm.setUidFirewallRule(100 /* chain */, uid, FIREWALL_RULE_ALLOW));
10724     }
10725 
10726     @Test @IgnoreUpTo(SC_V2)
10727     public void testInvalidFirewallRule() throws Exception {
10728         final Class<IllegalArgumentException> expected = IllegalArgumentException.class;
10729         assertThrows(expected,
10730                 () -> mCm.setUidFirewallRule(FIREWALL_CHAIN_DOZABLE,
10731                         1001 /* uid */, -1 /* rule */));
10732         assertThrows(expected,
10733                 () -> mCm.setUidFirewallRule(FIREWALL_CHAIN_DOZABLE,
10734                         1001 /* uid */, 100 /* rule */));
10735     }
10736 
10737     /**
10738      * Test mutable and requestable network capabilities such as
10739      * {@link NetworkCapabilities#NET_CAPABILITY_TRUSTED} and
10740      * {@link NetworkCapabilities#NET_CAPABILITY_NOT_VCN_MANAGED}. Verify that the
10741      * {@code ConnectivityService} re-assign the networks accordingly.
10742      */
10743     @Test
10744     public final void testLoseMutableAndRequestableCaps() throws Exception {
10745         final int[] testCaps = new int [] {
10746                 NET_CAPABILITY_TRUSTED,
10747                 NET_CAPABILITY_NOT_VCN_MANAGED
10748         };
10749         for (final int testCap : testCaps) {
10750             // Create requests with and without the testing capability.
10751             final TestNetworkCallback callbackWithCap = new TestNetworkCallback();
10752             final TestNetworkCallback callbackWithoutCap = new TestNetworkCallback();
10753             mCm.requestNetwork(new NetworkRequest.Builder().addCapability(testCap).build(),
10754                     callbackWithCap);
10755             mCm.requestNetwork(new NetworkRequest.Builder().removeCapability(testCap).build(),
10756                     callbackWithoutCap);
10757 
10758             // Setup networks with testing capability and verify the default network changes.
10759             mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
10760             mCellAgent.addCapability(testCap);
10761             mCellAgent.connect(true);
10762             callbackWithCap.expectAvailableThenValidatedCallbacks(mCellAgent);
10763             callbackWithoutCap.expectAvailableThenValidatedCallbacks(mCellAgent);
10764             verify(mMockNetd).networkSetDefault(eq(mCellAgent.getNetwork().netId));
10765             reset(mMockNetd);
10766 
10767             mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
10768             mWiFiAgent.addCapability(testCap);
10769             mWiFiAgent.connect(true);
10770             callbackWithCap.expectAvailableDoubleValidatedCallbacks(mWiFiAgent);
10771             callbackWithoutCap.expectAvailableDoubleValidatedCallbacks(mWiFiAgent);
10772             verify(mMockNetd).networkSetDefault(eq(mWiFiAgent.getNetwork().netId));
10773             reset(mMockNetd);
10774 
10775             // Remove the testing capability on wifi, verify the callback and default network
10776             // changes back to cellular.
10777             mWiFiAgent.removeCapability(testCap);
10778             callbackWithCap.expectAvailableCallbacksValidated(mCellAgent);
10779             callbackWithoutCap.expectCaps(mWiFiAgent, c -> !c.hasCapability(testCap));
10780             verify(mMockNetd).networkSetDefault(eq(mCellAgent.getNetwork().netId));
10781             reset(mMockNetd);
10782 
10783             mCellAgent.removeCapability(testCap);
10784             callbackWithCap.expect(LOST, mCellAgent);
10785             callbackWithoutCap.assertNoCallback();
10786             verify(mMockNetd).networkClearDefault();
10787 
10788             mCm.unregisterNetworkCallback(callbackWithCap);
10789             mCm.unregisterNetworkCallback(callbackWithoutCap);
10790         }
10791     }
10792 
10793     @Test
10794     public final void testBatteryStatsNetworkType() throws Exception {
10795         final LinkProperties cellLp = new LinkProperties();
10796         cellLp.setInterfaceName("cell0");
10797         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
10798         mCellAgent.connect(true);
10799         waitForIdle();
10800         final ArrayTrackRecord<ReportedInterfaces>.ReadHead readHead =
10801                 mDeps.mReportedInterfaceHistory.newReadHead();
10802         assertNotNull(readHead.poll(TIMEOUT_MS, ri -> ri.contentEquals(mServiceContext,
10803                 cellLp.getInterfaceName(),
10804                 new int[] { TRANSPORT_CELLULAR })));
10805 
10806         final LinkProperties wifiLp = new LinkProperties();
10807         wifiLp.setInterfaceName("wifi0");
10808         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp);
10809         mWiFiAgent.connect(true);
10810         waitForIdle();
10811         assertNotNull(readHead.poll(TIMEOUT_MS, ri -> ri.contentEquals(mServiceContext,
10812                 wifiLp.getInterfaceName(),
10813                 new int[] { TRANSPORT_WIFI })));
10814 
10815         mCellAgent.disconnect();
10816         mWiFiAgent.disconnect();
10817 
10818         cellLp.setInterfaceName("wifi0");
10819         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
10820         mCellAgent.connect(true);
10821         waitForIdle();
10822         assertNotNull(readHead.poll(TIMEOUT_MS, ri -> ri.contentEquals(mServiceContext,
10823                 cellLp.getInterfaceName(),
10824                 new int[] { TRANSPORT_CELLULAR })));
10825         mCellAgent.disconnect();
10826     }
10827 
10828     /**
10829      * Make simulated InterfaceConfigParcel for Nat464Xlat to query clat lower layer info.
10830      */
10831     private InterfaceConfigurationParcel getClatInterfaceConfigParcel(LinkAddress la) {
10832         final InterfaceConfigurationParcel cfg = new InterfaceConfigurationParcel();
10833         cfg.hwAddr = "11:22:33:44:55:66";
10834         cfg.ipv4Addr = la.getAddress().getHostAddress();
10835         cfg.prefixLength = la.getPrefixLength();
10836         return cfg;
10837     }
10838 
10839     /**
10840      * Make expected stack link properties, copied from Nat464Xlat.
10841      */
10842     private LinkProperties makeClatLinkProperties(LinkAddress la) {
10843         LinkAddress clatAddress = la;
10844         LinkProperties stacked = new LinkProperties();
10845         stacked.setInterfaceName(CLAT_MOBILE_IFNAME);
10846         RouteInfo ipv4Default = new RouteInfo(
10847                 new LinkAddress(Inet4Address.ANY, 0),
10848                 clatAddress.getAddress(), CLAT_MOBILE_IFNAME);
10849         stacked.addRoute(ipv4Default);
10850         stacked.addLinkAddress(clatAddress);
10851         return stacked;
10852     }
10853 
10854     private Nat64PrefixEventParcel makeNat64PrefixEvent(final int netId, final int prefixOperation,
10855             final String prefixAddress, final int prefixLength) {
10856         final Nat64PrefixEventParcel event = new Nat64PrefixEventParcel();
10857         event.netId = netId;
10858         event.prefixOperation = prefixOperation;
10859         event.prefixAddress = prefixAddress;
10860         event.prefixLength = prefixLength;
10861         return event;
10862     }
10863 
10864     private void verifyWakeupModifyInterface(String iface, boolean add) throws RemoteException {
10865         if (add) {
10866             verify(mMockNetd).wakeupAddInterface(eq(iface), anyString(), anyInt(),
10867                     anyInt());
10868         } else {
10869             verify(mMockNetd).wakeupDelInterface(eq(iface), anyString(), anyInt(),
10870                     anyInt());
10871         }
10872     }
10873 
10874     private <T> T verifyWithOrder(@Nullable InOrder inOrder, @NonNull T t) {
10875         if (inOrder != null) {
10876             return inOrder.verify(t);
10877         } else {
10878             // times(1) for consistency with the above. InOrder#verify always implies times(1).
10879             return verify(t, times(1));
10880         }
10881     }
10882 
10883     private <T> T verifyNeverWithOrder(@Nullable InOrder inOrder, @NonNull T t) {
10884         if (inOrder != null) {
10885             return inOrder.verify(t, never());
10886         } else {
10887             return verify(t, never());
10888         }
10889     }
10890 
10891     private void verifyClatdStart(@Nullable InOrder inOrder, @NonNull String iface, int netId,
10892             @NonNull String nat64Prefix) throws Exception {
10893         if (mDeps.isAtLeastT()) {
10894             verifyWithOrder(inOrder, mClatCoordinator)
10895                 .clatStart(eq(iface), eq(netId), eq(new IpPrefix(nat64Prefix)));
10896         } else {
10897             verifyWithOrder(inOrder, mMockNetd).clatdStart(eq(iface), eq(nat64Prefix));
10898         }
10899     }
10900 
10901     private void verifyNeverClatdStart(@Nullable InOrder inOrder, @NonNull String iface)
10902             throws Exception {
10903         if (mDeps.isAtLeastT()) {
10904             verifyNeverWithOrder(inOrder, mClatCoordinator).clatStart(eq(iface), anyInt(), any());
10905         } else {
10906             verifyNeverWithOrder(inOrder, mMockNetd).clatdStart(eq(iface), anyString());
10907         }
10908     }
10909 
10910     private void verifyClatdStop(@Nullable InOrder inOrder, @NonNull String iface)
10911             throws Exception {
10912         if (mDeps.isAtLeastT()) {
10913             verifyWithOrder(inOrder, mClatCoordinator).clatStop();
10914         } else {
10915             verifyWithOrder(inOrder, mMockNetd).clatdStop(eq(iface));
10916         }
10917     }
10918 
10919     private void verifyNeverClatdStop(@Nullable InOrder inOrder, @NonNull String iface)
10920             throws Exception {
10921         if (mDeps.isAtLeastT()) {
10922             verifyNeverWithOrder(inOrder, mClatCoordinator).clatStop();
10923         } else {
10924             verifyNeverWithOrder(inOrder, mMockNetd).clatdStop(eq(iface));
10925         }
10926     }
10927 
10928     private void expectNativeNetworkCreated(int netId, int permission, String iface,
10929             InOrder inOrder) throws Exception {
10930         verifyWithOrder(inOrder, mMockNetd).networkCreate(nativeNetworkConfigPhysical(netId,
10931                 permission));
10932         verifyWithOrder(inOrder, mMockDnsResolver).createNetworkCache(eq(netId));
10933         if (iface != null) {
10934             verifyWithOrder(inOrder, mMockNetd).networkAddInterface(netId, iface);
10935         }
10936     }
10937 
10938     private void expectNativeNetworkCreated(int netId, int permission, String iface)
10939             throws Exception {
10940         expectNativeNetworkCreated(netId, permission, iface, null /* inOrder */);
10941     }
10942 
10943     private int getIdleTimerLabel(int netId, int transportType) {
10944         return ConnectivityService.LegacyNetworkActivityTracker.getIdleTimerLabel(
10945                 mDeps.isAtLeastV(), netId, transportType);
10946     }
10947 
10948     @Test
10949     public void testStackedLinkProperties() throws Exception {
10950         final LinkAddress myIpv4 = new LinkAddress("1.2.3.4/24");
10951         final LinkAddress myIpv6 = new LinkAddress("2001:db8:1::1/64");
10952         final String kNat64PrefixString = "2001:db8:64:64:64:64::";
10953         final IpPrefix kNat64Prefix = new IpPrefix(InetAddress.getByName(kNat64PrefixString), 96);
10954         final String kOtherNat64PrefixString = "64:ff9b::";
10955         final IpPrefix kOtherNat64Prefix = new IpPrefix(
10956                 InetAddress.getByName(kOtherNat64PrefixString), 96);
10957         final RouteInfo ipv6Default =
10958                 new RouteInfo((IpPrefix) null, myIpv6.getAddress(), MOBILE_IFNAME);
10959         final RouteInfo ipv6Subnet = new RouteInfo(myIpv6, null, MOBILE_IFNAME);
10960         final RouteInfo ipv4Subnet = new RouteInfo(myIpv4, null, MOBILE_IFNAME);
10961         final RouteInfo stackedDefault =
10962                 new RouteInfo((IpPrefix) null, myIpv4.getAddress(), CLAT_MOBILE_IFNAME);
10963         final BaseNetdUnsolicitedEventListener netdUnsolicitedListener =
10964                 getRegisteredNetdUnsolicitedEventListener();
10965 
10966         final NetworkRequest networkRequest = new NetworkRequest.Builder()
10967                 .addTransportType(TRANSPORT_CELLULAR)
10968                 .addCapability(NET_CAPABILITY_INTERNET)
10969                 .build();
10970         final TestNetworkCallback networkCallback = new TestNetworkCallback();
10971         mCm.registerNetworkCallback(networkRequest, networkCallback);
10972 
10973         // Prepare ipv6 only link properties.
10974         final LinkProperties cellLp = new LinkProperties();
10975         cellLp.setInterfaceName(MOBILE_IFNAME);
10976         cellLp.addLinkAddress(myIpv6);
10977         cellLp.addRoute(ipv6Default);
10978         cellLp.addRoute(ipv6Subnet);
10979         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
10980         reset(mClatCoordinator);
10981 
10982         // Connect with ipv6 link properties. Expect prefix discovery to be started.
10983         mCellAgent.connect(true);
10984         int cellNetId = mCellAgent.getNetwork().netId;
10985         waitForIdle();
10986 
10987         expectNativeNetworkCreated(cellNetId, INetd.PERMISSION_NONE, MOBILE_IFNAME);
10988         assertRoutesAdded(cellNetId, ipv6Subnet, ipv6Default);
10989         final ArrayTrackRecord<ReportedInterfaces>.ReadHead readHead =
10990                 mDeps.mReportedInterfaceHistory.newReadHead();
10991         assertNotNull(readHead.poll(TIMEOUT_MS, ri -> ri.contentEquals(mServiceContext,
10992                 cellLp.getInterfaceName(),
10993                 new int[] { TRANSPORT_CELLULAR })));
10994 
10995         networkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
10996         verify(mMockDnsResolver, times(1)).startPrefix64Discovery(cellNetId);
10997 
10998         // Switching default network updates TCP buffer sizes.
10999         verifyTcpBufferSizeChange(ConnectivityService.DEFAULT_TCP_BUFFER_SIZES);
11000         // Add an IPv4 address. Expect prefix discovery to be stopped. Netd doesn't tell us that
11001         // the NAT64 prefix was removed because one was never discovered.
11002         cellLp.addLinkAddress(myIpv4);
11003         mCellAgent.sendLinkProperties(cellLp);
11004         networkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent);
11005         assertRoutesAdded(cellNetId, ipv4Subnet);
11006         verify(mMockDnsResolver, times(1)).stopPrefix64Discovery(cellNetId);
11007         verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(any());
11008 
11009         // Make sure BatteryStats was not told about any v4- interfaces, as none should have
11010         // come online yet.
11011         waitForIdle();
11012         assertNull(readHead.poll(0 /* timeout */, ri -> mServiceContext.equals(ri.context)
11013                 && ri.iface != null && ri.iface.startsWith("v4-")));
11014 
11015         verifyNoMoreInteractions(mMockNetd);
11016         verifyNoMoreInteractions(mClatCoordinator);
11017         verifyNoMoreInteractions(mMockDnsResolver);
11018         reset(mMockNetd);
11019         reset(mClatCoordinator);
11020         reset(mMockDnsResolver);
11021         doReturn(getClatInterfaceConfigParcel(myIpv4)).when(mMockNetd)
11022                 .interfaceGetCfg(CLAT_MOBILE_IFNAME);
11023 
11024         // Remove IPv4 address. Expect prefix discovery to be started again.
11025         cellLp.removeLinkAddress(myIpv4);
11026         mCellAgent.sendLinkProperties(cellLp);
11027         networkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent);
11028         verify(mMockDnsResolver, times(1)).startPrefix64Discovery(cellNetId);
11029         assertRoutesRemoved(cellNetId, ipv4Subnet);
11030 
11031         // When NAT64 prefix discovery succeeds, LinkProperties are updated and clatd is started.
11032         assertNull(mCm.getLinkProperties(mCellAgent.getNetwork()).getNat64Prefix());
11033         mService.mResolverUnsolEventCallback.onNat64PrefixEvent(
11034                 makeNat64PrefixEvent(cellNetId, PREFIX_OPERATION_ADDED, kNat64PrefixString, 96));
11035         LinkProperties lpBeforeClat = networkCallback.expect(
11036                 LINK_PROPERTIES_CHANGED, mCellAgent).getLp();
11037         assertEquals(0, lpBeforeClat.getStackedLinks().size());
11038         assertEquals(kNat64Prefix, lpBeforeClat.getNat64Prefix());
11039         verifyClatdStart(null /* inOrder */, MOBILE_IFNAME, cellNetId, kNat64Prefix.toString());
11040 
11041         // Clat iface comes up. Expect stacked link to be added.
11042         netdUnsolicitedListener.onInterfaceLinkStateChanged(
11043                 CLAT_MOBILE_IFNAME, true);
11044         networkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent);
11045         List<LinkProperties> stackedLps = mCm.getLinkProperties(mCellAgent.getNetwork())
11046                 .getStackedLinks();
11047         assertEquals(makeClatLinkProperties(myIpv4), stackedLps.get(0));
11048         assertRoutesAdded(cellNetId, stackedDefault);
11049         verify(mMockNetd, times(1)).networkAddInterface(cellNetId, CLAT_MOBILE_IFNAME);
11050         // Change trivial linkproperties and see if stacked link is preserved.
11051         cellLp.addDnsServer(InetAddress.getByName("8.8.8.8"));
11052         mCellAgent.sendLinkProperties(cellLp);
11053         networkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent);
11054 
11055         List<LinkProperties> stackedLpsAfterChange =
11056                 mCm.getLinkProperties(mCellAgent.getNetwork()).getStackedLinks();
11057         assertNotEquals(stackedLpsAfterChange, Collections.EMPTY_LIST);
11058         assertEquals(makeClatLinkProperties(myIpv4), stackedLpsAfterChange.get(0));
11059 
11060         verify(mMockDnsResolver, times(1)).setResolverConfiguration(
11061                 mResolverParamsParcelCaptor.capture());
11062         ResolverParamsParcel resolvrParams = mResolverParamsParcelCaptor.getValue();
11063         assertEquals(1, resolvrParams.servers.length);
11064         assertTrue(CollectionUtils.contains(resolvrParams.servers, "8.8.8.8"));
11065 
11066         for (final LinkProperties stackedLp : stackedLpsAfterChange) {
11067             assertNotNull(readHead.poll(TIMEOUT_MS, ri -> ri.contentEquals(mServiceContext,
11068                     stackedLp.getInterfaceName(),
11069                     new int[] { TRANSPORT_CELLULAR })));
11070         }
11071         reset(mMockNetd);
11072         reset(mClatCoordinator);
11073         doReturn(getClatInterfaceConfigParcel(myIpv4)).when(mMockNetd)
11074                 .interfaceGetCfg(CLAT_MOBILE_IFNAME);
11075         // Change the NAT64 prefix without first removing it.
11076         // Expect clatd to be stopped and started with the new prefix.
11077         mService.mResolverUnsolEventCallback.onNat64PrefixEvent(makeNat64PrefixEvent(
11078                 cellNetId, PREFIX_OPERATION_ADDED, kOtherNat64PrefixString, 96));
11079         networkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent,
11080                 cb -> cb.getLp().getStackedLinks().size() == 0);
11081         verifyClatdStop(null /* inOrder */, MOBILE_IFNAME);
11082         assertRoutesRemoved(cellNetId, stackedDefault);
11083         verify(mMockNetd, times(1)).networkRemoveInterface(cellNetId, CLAT_MOBILE_IFNAME);
11084 
11085         verifyClatdStart(null /* inOrder */, MOBILE_IFNAME, cellNetId,
11086                 kOtherNat64Prefix.toString());
11087         networkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent,
11088                 cb -> cb.getLp().getNat64Prefix().equals(kOtherNat64Prefix));
11089         netdUnsolicitedListener.onInterfaceLinkStateChanged(CLAT_MOBILE_IFNAME, true);
11090         networkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent,
11091                 cb -> cb.getLp().getStackedLinks().size() == 1);
11092         assertRoutesAdded(cellNetId, stackedDefault);
11093         verify(mMockNetd, times(1)).networkAddInterface(cellNetId, CLAT_MOBILE_IFNAME);
11094         reset(mMockNetd);
11095         reset(mClatCoordinator);
11096 
11097         // Add ipv4 address, expect that clatd and prefix discovery are stopped and stacked
11098         // linkproperties are cleaned up.
11099         cellLp.addLinkAddress(myIpv4);
11100         cellLp.addRoute(ipv4Subnet);
11101         mCellAgent.sendLinkProperties(cellLp);
11102         networkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent);
11103         assertRoutesAdded(cellNetId, ipv4Subnet);
11104         verifyClatdStop(null /* inOrder */, MOBILE_IFNAME);
11105         verify(mMockDnsResolver, times(1)).stopPrefix64Discovery(cellNetId);
11106 
11107         // As soon as stop is called, the linkproperties lose the stacked interface.
11108         networkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent);
11109         LinkProperties actualLpAfterIpv4 = mCm.getLinkProperties(mCellAgent.getNetwork());
11110         LinkProperties expected = new LinkProperties(cellLp);
11111         expected.setNat64Prefix(kOtherNat64Prefix);
11112         assertEquals(expected, actualLpAfterIpv4);
11113         assertEquals(0, actualLpAfterIpv4.getStackedLinks().size());
11114         assertRoutesRemoved(cellNetId, stackedDefault);
11115 
11116         // The interface removed callback happens but has no effect after stop is called.
11117         netdUnsolicitedListener.onInterfaceRemoved(CLAT_MOBILE_IFNAME);
11118         networkCallback.assertNoCallback();
11119         verify(mMockNetd, times(1)).networkRemoveInterface(cellNetId, CLAT_MOBILE_IFNAME);
11120 
11121         if (mDeps.isAtLeastU()) {
11122             verifyWakeupModifyInterface(CLAT_MOBILE_IFNAME, false);
11123         }
11124 
11125         verifyNoMoreInteractions(mMockNetd);
11126         verifyNoMoreInteractions(mClatCoordinator);
11127         verifyNoMoreInteractions(mMockDnsResolver);
11128         reset(mMockNetd);
11129         reset(mClatCoordinator);
11130         reset(mMockDnsResolver);
11131         doReturn(getClatInterfaceConfigParcel(myIpv4)).when(mMockNetd)
11132                 .interfaceGetCfg(CLAT_MOBILE_IFNAME);
11133 
11134         // Stopping prefix discovery causes netd to tell us that the NAT64 prefix is gone.
11135         mService.mResolverUnsolEventCallback.onNat64PrefixEvent(makeNat64PrefixEvent(
11136                 cellNetId, PREFIX_OPERATION_REMOVED, kOtherNat64PrefixString, 96));
11137         networkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent,
11138                 cb -> cb.getLp().getNat64Prefix() == null);
11139 
11140         // Remove IPv4 address and expect prefix discovery and clatd to be started again.
11141         cellLp.removeLinkAddress(myIpv4);
11142         cellLp.removeRoute(new RouteInfo(myIpv4, null, MOBILE_IFNAME));
11143         cellLp.removeDnsServer(InetAddress.getByName("8.8.8.8"));
11144         mCellAgent.sendLinkProperties(cellLp);
11145         networkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent);
11146         assertRoutesRemoved(cellNetId, ipv4Subnet);  // Directly-connected routes auto-added.
11147         verify(mMockDnsResolver, times(1)).startPrefix64Discovery(cellNetId);
11148         mService.mResolverUnsolEventCallback.onNat64PrefixEvent(makeNat64PrefixEvent(
11149                 cellNetId, PREFIX_OPERATION_ADDED, kNat64PrefixString, 96));
11150         networkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent);
11151         verifyClatdStart(null /* inOrder */, MOBILE_IFNAME, cellNetId, kNat64Prefix.toString());
11152 
11153         // Clat iface comes up. Expect stacked link to be added.
11154         netdUnsolicitedListener.onInterfaceLinkStateChanged(CLAT_MOBILE_IFNAME, true);
11155         networkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent,
11156                 cb -> cb.getLp().getStackedLinks().size() == 1
11157                         && cb.getLp().getNat64Prefix() != null);
11158         assertRoutesAdded(cellNetId, stackedDefault);
11159         verify(mMockNetd, times(1)).networkAddInterface(cellNetId, CLAT_MOBILE_IFNAME);
11160 
11161         if (mDeps.isAtLeastU()) {
11162             verifyWakeupModifyInterface(CLAT_MOBILE_IFNAME, true);
11163         }
11164 
11165         // NAT64 prefix is removed. Expect that clat is stopped.
11166         mService.mResolverUnsolEventCallback.onNat64PrefixEvent(makeNat64PrefixEvent(
11167                 cellNetId, PREFIX_OPERATION_REMOVED, kNat64PrefixString, 96));
11168         networkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent,
11169                 cb -> cb.getLp().getStackedLinks().size() == 0
11170                         && cb.getLp().getNat64Prefix() == null);
11171         assertRoutesRemoved(cellNetId, ipv4Subnet, stackedDefault);
11172 
11173         // Stop has no effect because clat is already stopped.
11174         verifyClatdStop(null /* inOrder */, MOBILE_IFNAME);
11175         networkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent,
11176                 cb -> cb.getLp().getStackedLinks().size() == 0);
11177         verify(mMockNetd, times(1)).networkRemoveInterface(cellNetId, CLAT_MOBILE_IFNAME);
11178         verify(mMockNetd, times(1)).interfaceGetCfg(CLAT_MOBILE_IFNAME);
11179 
11180         if (mDeps.isAtLeastU()) {
11181             verifyWakeupModifyInterface(CLAT_MOBILE_IFNAME, false);
11182         }
11183 
11184         // Clean up.
11185         mCellAgent.disconnect();
11186         networkCallback.expect(LOST, mCellAgent);
11187         networkCallback.assertNoCallback();
11188         verify(mMockNetd, times(1)).idletimerRemoveInterface(eq(MOBILE_IFNAME), anyInt(),
11189                 eq(Integer.toString(getIdleTimerLabel(cellNetId, TRANSPORT_CELLULAR))));
11190         verify(mMockNetd).networkDestroy(cellNetId);
11191         if (mDeps.isAtLeastU()) {
11192             verify(mMockNetd).setNetworkAllowlist(any());
11193         } else {
11194             verify(mMockNetd, never()).setNetworkAllowlist(any());
11195         }
11196 
11197         if (mDeps.isAtLeastU()) {
11198             verifyWakeupModifyInterface(MOBILE_IFNAME, false);
11199         }
11200 
11201         verifyNoMoreInteractions(mMockNetd);
11202         verifyNoMoreInteractions(mClatCoordinator);
11203         reset(mMockNetd);
11204         reset(mClatCoordinator);
11205 
11206         // Test disconnecting a network that is running 464xlat.
11207 
11208         // Connect a network with a NAT64 prefix.
11209         doReturn(getClatInterfaceConfigParcel(myIpv4)).when(mMockNetd)
11210                 .interfaceGetCfg(CLAT_MOBILE_IFNAME);
11211         cellLp.setNat64Prefix(kNat64Prefix);
11212         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
11213         mCellAgent.connect(false /* validated */);
11214         networkCallback.expectAvailableCallbacksUnvalidated(mCellAgent);
11215         cellNetId = mCellAgent.getNetwork().netId;
11216         verify(mMockNetd, times(1)).networkCreate(nativeNetworkConfigPhysical(cellNetId,
11217                 INetd.PERMISSION_NONE));
11218         assertRoutesAdded(cellNetId, ipv6Subnet, ipv6Default);
11219 
11220         // Clatd is started and clat iface comes up. Expect stacked link to be added.
11221         verifyClatdStart(null /* inOrder */, MOBILE_IFNAME, cellNetId, kNat64Prefix.toString());
11222         netdUnsolicitedListener.onInterfaceLinkStateChanged(CLAT_MOBILE_IFNAME, true /* up */);
11223         networkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent,
11224                 cb -> cb.getLp().getStackedLinks().size() == 1
11225                         && cb.getLp().getNat64Prefix().equals(kNat64Prefix));
11226         verify(mMockNetd).networkAddInterface(cellNetId, CLAT_MOBILE_IFNAME);
11227         // assertRoutesAdded sees all calls since last mMockNetd reset, so expect IPv6 routes again.
11228         assertRoutesAdded(cellNetId, ipv6Subnet, ipv6Default, stackedDefault);
11229 
11230         if (mDeps.isAtLeastU()) {
11231             verifyWakeupModifyInterface(MOBILE_IFNAME, true);
11232         }
11233 
11234         reset(mMockNetd);
11235         reset(mClatCoordinator);
11236 
11237         // Disconnect the network. clat is stopped and the network is destroyed.
11238         mCellAgent.disconnect();
11239         networkCallback.expect(LOST, mCellAgent);
11240         networkCallback.assertNoCallback();
11241         verifyClatdStop(null /* inOrder */, MOBILE_IFNAME);
11242 
11243         if (mDeps.isAtLeastU()) {
11244             verifyWakeupModifyInterface(CLAT_MOBILE_IFNAME, false);
11245         }
11246 
11247         verify(mMockNetd).idletimerRemoveInterface(eq(MOBILE_IFNAME), anyInt(),
11248                 eq(Integer.toString(getIdleTimerLabel(cellNetId, TRANSPORT_CELLULAR))));
11249         verify(mMockNetd).networkDestroy(cellNetId);
11250         if (mDeps.isAtLeastU()) {
11251             verify(mMockNetd).setNetworkAllowlist(any());
11252         } else {
11253             verify(mMockNetd, never()).setNetworkAllowlist(any());
11254         }
11255 
11256         if (mDeps.isAtLeastU()) {
11257             verifyWakeupModifyInterface(MOBILE_IFNAME, false);
11258         }
11259 
11260         verifyNoMoreInteractions(mMockNetd);
11261         verifyNoMoreInteractions(mClatCoordinator);
11262 
11263         mCm.unregisterNetworkCallback(networkCallback);
11264     }
11265 
11266     private void expectNat64PrefixChange(TestNetworkCallback callback,
11267             TestNetworkAgentWrapper agent, IpPrefix prefix) {
11268         callback.expect(LINK_PROPERTIES_CHANGED, agent,
11269                 x -> Objects.equals(x.getLp().getNat64Prefix(), prefix));
11270     }
11271 
11272     @Test
11273     public void testNat64PrefixMultipleSources() throws Exception {
11274         final String iface = "wlan0";
11275         final String pref64FromRaStr = "64:ff9b::";
11276         final String pref64FromDnsStr = "2001:db8:64::";
11277         final IpPrefix pref64FromRa = new IpPrefix(InetAddress.getByName(pref64FromRaStr), 96);
11278         final IpPrefix pref64FromDns = new IpPrefix(InetAddress.getByName(pref64FromDnsStr), 96);
11279         final IpPrefix newPref64FromRa = new IpPrefix("2001:db8:64:64:64:64::/96");
11280 
11281         final NetworkRequest request = new NetworkRequest.Builder()
11282                 .addCapability(NET_CAPABILITY_INTERNET)
11283                 .build();
11284         final TestNetworkCallback callback = new TestNetworkCallback();
11285         mCm.registerNetworkCallback(request, callback);
11286 
11287         final LinkProperties baseLp = new LinkProperties();
11288         baseLp.setInterfaceName(iface);
11289         baseLp.addLinkAddress(new LinkAddress("2001:db8:1::1/64"));
11290         baseLp.addDnsServer(InetAddress.getByName("2001:4860:4860::6464"));
11291 
11292         reset(mMockNetd, mMockDnsResolver);
11293         InOrder inOrder = inOrder(mMockNetd, mMockDnsResolver, mClatCoordinator);
11294 
11295         // If a network already has a NAT64 prefix on connect, clatd is started immediately and
11296         // prefix discovery is never started.
11297         LinkProperties lp = new LinkProperties(baseLp);
11298         lp.setNat64Prefix(pref64FromRa);
11299         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, lp);
11300         mWiFiAgent.connect(false);
11301         final Network network = mWiFiAgent.getNetwork();
11302         int netId = network.getNetId();
11303         callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
11304         verifyClatdStart(inOrder, iface, netId, pref64FromRa.toString());
11305         inOrder.verify(mMockDnsResolver).setPrefix64(netId, pref64FromRa.toString());
11306         inOrder.verify(mMockDnsResolver, never()).startPrefix64Discovery(netId);
11307         callback.assertNoCallback();
11308         assertEquals(pref64FromRa, mCm.getLinkProperties(network).getNat64Prefix());
11309 
11310         // If the RA prefix is withdrawn, clatd is stopped and prefix discovery is started.
11311         lp.setNat64Prefix(null);
11312         mWiFiAgent.sendLinkProperties(lp);
11313         expectNat64PrefixChange(callback, mWiFiAgent, null);
11314         verifyClatdStop(inOrder, iface);
11315         inOrder.verify(mMockDnsResolver).setPrefix64(netId, "");
11316         inOrder.verify(mMockDnsResolver).startPrefix64Discovery(netId);
11317 
11318         // If the RA prefix appears while DNS discovery is in progress, discovery is stopped and
11319         // clatd is started with the prefix from the RA.
11320         lp.setNat64Prefix(pref64FromRa);
11321         mWiFiAgent.sendLinkProperties(lp);
11322         expectNat64PrefixChange(callback, mWiFiAgent, pref64FromRa);
11323         verifyClatdStart(inOrder, iface, netId, pref64FromRa.toString());
11324         inOrder.verify(mMockDnsResolver).stopPrefix64Discovery(netId);
11325         inOrder.verify(mMockDnsResolver).setPrefix64(netId, pref64FromRa.toString());
11326 
11327         // Withdraw the RA prefix so we can test the case where an RA prefix appears after DNS
11328         // discovery has succeeded.
11329         lp.setNat64Prefix(null);
11330         mWiFiAgent.sendLinkProperties(lp);
11331         expectNat64PrefixChange(callback, mWiFiAgent, null);
11332         verifyClatdStop(inOrder, iface);
11333         inOrder.verify(mMockDnsResolver).setPrefix64(netId, "");
11334         inOrder.verify(mMockDnsResolver).startPrefix64Discovery(netId);
11335 
11336         mService.mResolverUnsolEventCallback.onNat64PrefixEvent(
11337                 makeNat64PrefixEvent(netId, PREFIX_OPERATION_ADDED, pref64FromDnsStr, 96));
11338         expectNat64PrefixChange(callback, mWiFiAgent, pref64FromDns);
11339         verifyClatdStart(inOrder, iface, netId, pref64FromDns.toString());
11340 
11341         // If an RA advertises the same prefix that was discovered by DNS, nothing happens: prefix
11342         // discovery is not stopped, and there are no callbacks.
11343         lp.setNat64Prefix(pref64FromDns);
11344         mWiFiAgent.sendLinkProperties(lp);
11345         callback.assertNoCallback();
11346         verifyNeverClatdStop(inOrder, iface);
11347         verifyNeverClatdStart(inOrder, iface);
11348         inOrder.verify(mMockDnsResolver, never()).stopPrefix64Discovery(netId);
11349         inOrder.verify(mMockDnsResolver, never()).startPrefix64Discovery(netId);
11350         inOrder.verify(mMockDnsResolver, never()).setPrefix64(eq(netId), anyString());
11351 
11352         // If the RA is later withdrawn, nothing happens again.
11353         lp.setNat64Prefix(null);
11354         mWiFiAgent.sendLinkProperties(lp);
11355         callback.assertNoCallback();
11356         verifyNeverClatdStop(inOrder, iface);
11357         verifyNeverClatdStart(inOrder, iface);
11358         inOrder.verify(mMockDnsResolver, never()).stopPrefix64Discovery(netId);
11359         inOrder.verify(mMockDnsResolver, never()).startPrefix64Discovery(netId);
11360         inOrder.verify(mMockDnsResolver, never()).setPrefix64(eq(netId), anyString());
11361 
11362         // If the RA prefix changes, clatd is restarted and prefix discovery is stopped.
11363         lp.setNat64Prefix(pref64FromRa);
11364         mWiFiAgent.sendLinkProperties(lp);
11365         expectNat64PrefixChange(callback, mWiFiAgent, pref64FromRa);
11366         verifyClatdStop(inOrder, iface);
11367         inOrder.verify(mMockDnsResolver).stopPrefix64Discovery(netId);
11368 
11369         // Stopping prefix discovery results in a prefix removed notification.
11370         mService.mResolverUnsolEventCallback.onNat64PrefixEvent(
11371                 makeNat64PrefixEvent(netId, PREFIX_OPERATION_REMOVED, pref64FromDnsStr, 96));
11372 
11373         verifyClatdStart(inOrder, iface, netId, pref64FromRa.toString());
11374         inOrder.verify(mMockDnsResolver).setPrefix64(netId, pref64FromRa.toString());
11375         inOrder.verify(mMockDnsResolver, never()).startPrefix64Discovery(netId);
11376 
11377         // If the RA prefix changes, clatd is restarted and prefix discovery is not started.
11378         lp.setNat64Prefix(newPref64FromRa);
11379         mWiFiAgent.sendLinkProperties(lp);
11380         expectNat64PrefixChange(callback, mWiFiAgent, newPref64FromRa);
11381         verifyClatdStop(inOrder, iface);
11382         inOrder.verify(mMockDnsResolver).setPrefix64(netId, "");
11383         verifyClatdStart(inOrder, iface, netId, newPref64FromRa.toString());
11384         inOrder.verify(mMockDnsResolver).setPrefix64(netId, newPref64FromRa.toString());
11385         inOrder.verify(mMockDnsResolver, never()).stopPrefix64Discovery(netId);
11386         inOrder.verify(mMockDnsResolver, never()).startPrefix64Discovery(netId);
11387 
11388         // If the RA prefix changes to the same value, nothing happens.
11389         lp.setNat64Prefix(newPref64FromRa);
11390         mWiFiAgent.sendLinkProperties(lp);
11391         callback.assertNoCallback();
11392         assertEquals(newPref64FromRa, mCm.getLinkProperties(network).getNat64Prefix());
11393         verifyNeverClatdStop(inOrder, iface);
11394         verifyNeverClatdStart(inOrder, iface);
11395         inOrder.verify(mMockDnsResolver, never()).stopPrefix64Discovery(netId);
11396         inOrder.verify(mMockDnsResolver, never()).startPrefix64Discovery(netId);
11397         inOrder.verify(mMockDnsResolver, never()).setPrefix64(eq(netId), anyString());
11398 
11399         // The transition between no prefix and DNS prefix is tested in testStackedLinkProperties.
11400 
11401         // If the same prefix is learned first by DNS and then by RA, and clat is later stopped,
11402         // (e.g., because the network disconnects) setPrefix64(netid, "") is never called.
11403         lp.setNat64Prefix(null);
11404         mWiFiAgent.sendLinkProperties(lp);
11405         expectNat64PrefixChange(callback, mWiFiAgent, null);
11406         verifyClatdStop(inOrder, iface);
11407         inOrder.verify(mMockDnsResolver).setPrefix64(netId, "");
11408         inOrder.verify(mMockDnsResolver).startPrefix64Discovery(netId);
11409         mService.mResolverUnsolEventCallback.onNat64PrefixEvent(
11410                 makeNat64PrefixEvent(netId, PREFIX_OPERATION_ADDED, pref64FromDnsStr, 96));
11411         expectNat64PrefixChange(callback, mWiFiAgent, pref64FromDns);
11412         verifyClatdStart(inOrder, iface, netId, pref64FromDns.toString());
11413         inOrder.verify(mMockDnsResolver, never()).setPrefix64(eq(netId), any());
11414 
11415         lp.setNat64Prefix(pref64FromDns);
11416         mWiFiAgent.sendLinkProperties(lp);
11417         callback.assertNoCallback();
11418         verifyNeverClatdStop(inOrder, iface);
11419         verifyNeverClatdStart(inOrder, iface);
11420         inOrder.verify(mMockDnsResolver, never()).stopPrefix64Discovery(netId);
11421         inOrder.verify(mMockDnsResolver, never()).startPrefix64Discovery(netId);
11422         inOrder.verify(mMockDnsResolver, never()).setPrefix64(eq(netId), anyString());
11423 
11424         // When tearing down a network, clat state is only updated after CALLBACK_LOST is fired, but
11425         // before CONNECTIVITY_ACTION is sent. Wait for CONNECTIVITY_ACTION before verifying that
11426         // clat has been stopped, or the test will be flaky.
11427         ExpectedBroadcast b = expectConnectivityAction(TYPE_WIFI, DetailedState.DISCONNECTED);
11428         mWiFiAgent.disconnect();
11429         callback.expect(LOST, mWiFiAgent);
11430         b.expectBroadcast();
11431 
11432         verifyClatdStop(inOrder, iface);
11433         inOrder.verify(mMockDnsResolver).stopPrefix64Discovery(netId);
11434         inOrder.verify(mMockDnsResolver, never()).setPrefix64(eq(netId), anyString());
11435 
11436         mCm.unregisterNetworkCallback(callback);
11437     }
11438 
11439     @Test
11440     public void testWith464XlatDisable() throws Exception {
11441         mDeps.setCellular464XlatEnabled(false);
11442 
11443         final TestNetworkCallback callback = new TestNetworkCallback();
11444         final TestNetworkCallback defaultCallback = new TestNetworkCallback();
11445         final NetworkRequest networkRequest = new NetworkRequest.Builder()
11446                 .addCapability(NET_CAPABILITY_INTERNET)
11447                 .build();
11448         mCm.registerNetworkCallback(networkRequest, callback);
11449         mCm.registerDefaultNetworkCallback(defaultCallback);
11450 
11451         // Bring up validated cell.
11452         final LinkProperties cellLp = new LinkProperties();
11453         cellLp.setInterfaceName(MOBILE_IFNAME);
11454         cellLp.addLinkAddress(new LinkAddress("2001:db8:1::1/64"));
11455         cellLp.addRoute(new RouteInfo(new IpPrefix("::/0"), null, MOBILE_IFNAME));
11456         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
11457 
11458         mCellAgent.sendLinkProperties(cellLp);
11459         mCellAgent.connect(true);
11460         callback.expectAvailableThenValidatedCallbacks(mCellAgent);
11461         defaultCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
11462         final int cellNetId = mCellAgent.getNetwork().netId;
11463         waitForIdle();
11464 
11465         verify(mMockDnsResolver, never()).startPrefix64Discovery(cellNetId);
11466         Nat464Xlat clat = getNat464Xlat(mCellAgent);
11467         assertTrue("Nat464Xlat was not IDLE", !clat.isStarted());
11468 
11469         // This cannot happen because prefix discovery cannot succeed if it is never started.
11470         mService.mResolverUnsolEventCallback.onNat64PrefixEvent(
11471                 makeNat64PrefixEvent(cellNetId, PREFIX_OPERATION_ADDED, "64:ff9b::", 96));
11472 
11473         // ... but still, check that even if it did, clatd would not be started.
11474         verify(mMockNetd, never()).clatdStart(anyString(), anyString());
11475         assertTrue("Nat464Xlat was not IDLE", !clat.isStarted());
11476     }
11477 
11478     final String transportToTestIfaceName(int transport) {
11479         switch (transport) {
11480             case TRANSPORT_WIFI:
11481                 return WIFI_IFNAME;
11482             case TRANSPORT_CELLULAR:
11483                 return MOBILE_IFNAME;
11484             case TRANSPORT_ETHERNET:
11485                 return ETHERNET_IFNAME;
11486             default:
11487                 throw new AssertionError("Unsupported transport type");
11488         }
11489     }
11490 
11491     private void doTestInterfaceClassActivityChanged(final int transportType) throws Exception {
11492         final BaseNetdUnsolicitedEventListener netdUnsolicitedEventListener =
11493                 getRegisteredNetdUnsolicitedEventListener();
11494 
11495         final int legacyType = transportToLegacyType(transportType);
11496         final LinkProperties lp = new LinkProperties();
11497         lp.setInterfaceName(transportToTestIfaceName(transportType));
11498         final TestNetworkAgentWrapper agent = new TestNetworkAgentWrapper(transportType, lp);
11499 
11500         final ConditionVariable onNetworkActiveCv = new ConditionVariable();
11501         final ConnectivityManager.OnNetworkActiveListener listener = onNetworkActiveCv::open;
11502 
11503         TestNetworkCallback defaultCallback = new TestNetworkCallback();
11504 
11505         testAndCleanup(() -> {
11506             mCm.registerDefaultNetworkCallback(defaultCallback);
11507             agent.connect(true);
11508             defaultCallback.expectAvailableThenValidatedCallbacks(agent);
11509             if (transportType == TRANSPORT_CELLULAR) {
11510                 verify(mIBatteryStats).noteMobileRadioPowerState(eq(DC_POWER_STATE_HIGH),
11511                         anyLong() /* timestampNs */, eq(NETWORK_ACTIVITY_NO_UID));
11512             } else if (transportType == TRANSPORT_WIFI) {
11513                 verify(mIBatteryStats).noteWifiRadioPowerState(eq(DC_POWER_STATE_HIGH),
11514                         anyLong() /* timestampNs */, eq(NETWORK_ACTIVITY_NO_UID));
11515             }
11516             clearInvocations(mIBatteryStats);
11517             final int idleTimerLabel = getIdleTimerLabel(agent.getNetwork().netId, transportType);
11518 
11519             // Network is considered active when the network becomes the default network.
11520             assertTrue(mCm.isDefaultNetworkActive());
11521 
11522             mCm.addDefaultNetworkActiveListener(listener);
11523 
11524             // Interface goes to inactive state
11525             netdUnsolicitedEventListener.onInterfaceClassActivityChanged(false /* isActive */,
11526                     idleTimerLabel, TIMESTAMP, NETWORK_ACTIVITY_NO_UID);
11527             mServiceContext.expectDataActivityBroadcast(legacyType, false /* isActive */,
11528                     TIMESTAMP);
11529             assertFalse(onNetworkActiveCv.block(TEST_CALLBACK_TIMEOUT_MS));
11530             assertFalse(mCm.isDefaultNetworkActive());
11531             if (mDeps.isAtLeastV()) {
11532                 if (transportType == TRANSPORT_CELLULAR) {
11533                     verify(mIBatteryStats).noteMobileRadioPowerState(eq(DC_POWER_STATE_LOW),
11534                             anyLong() /* timestampNs */, eq(NETWORK_ACTIVITY_NO_UID));
11535                 } else if (transportType == TRANSPORT_WIFI) {
11536                     verify(mIBatteryStats).noteWifiRadioPowerState(eq(DC_POWER_STATE_LOW),
11537                             anyLong() /* timestampNs */, eq(NETWORK_ACTIVITY_NO_UID));
11538                 }
11539             } else {
11540                 // If TrackMultiNetworks is disabled, LegacyNetworkActivityTracker does not call
11541                 // BatteryStats API by the netd activity change callback since BatteryStatsService
11542                 // listen to netd callback via NetworkManagementService and update battery stats by
11543                 // itself.
11544                 verify(mIBatteryStats, never())
11545                         .noteMobileRadioPowerState(anyInt(), anyLong(), anyInt());
11546                 verify(mIBatteryStats, never())
11547                         .noteWifiRadioPowerState(anyInt(), anyLong(), anyInt());
11548             }
11549 
11550             // Interface goes to active state
11551             netdUnsolicitedEventListener.onInterfaceClassActivityChanged(true /* isActive */,
11552                     idleTimerLabel, TIMESTAMP, TEST_PACKAGE_UID);
11553             mServiceContext.expectDataActivityBroadcast(legacyType, true /* isActive */, TIMESTAMP);
11554             assertTrue(onNetworkActiveCv.block(TEST_CALLBACK_TIMEOUT_MS));
11555             assertTrue(mCm.isDefaultNetworkActive());
11556             if (mDeps.isAtLeastV()) {
11557                 if (transportType == TRANSPORT_CELLULAR) {
11558                     verify(mIBatteryStats).noteMobileRadioPowerState(eq(DC_POWER_STATE_HIGH),
11559                             anyLong() /* timestampNs */, eq(TEST_PACKAGE_UID));
11560                 } else if (transportType == TRANSPORT_WIFI) {
11561                     verify(mIBatteryStats).noteWifiRadioPowerState(eq(DC_POWER_STATE_HIGH),
11562                             anyLong() /* timestampNs */, eq(TEST_PACKAGE_UID));
11563                 }
11564             } else {
11565                 // If TrackMultiNetworks is disabled, LegacyNetworkActivityTracker does not call
11566                 // BatteryStats API by the netd activity change callback since BatteryStatsService
11567                 // listen to netd callback via NetworkManagementService and update battery stats by
11568                 // itself.
11569                 verify(mIBatteryStats, never())
11570                         .noteMobileRadioPowerState(anyInt(), anyLong(), anyInt());
11571                 verify(mIBatteryStats, never())
11572                         .noteWifiRadioPowerState(anyInt(), anyLong(), anyInt());
11573             }
11574         }, () -> { // Cleanup
11575                 mCm.unregisterNetworkCallback(defaultCallback);
11576             }, () -> { // Cleanup
11577                 mCm.removeDefaultNetworkActiveListener(listener);
11578             }, () -> { // Cleanup
11579                 agent.disconnect();
11580             });
11581     }
11582 
11583     @Test
11584     public void testInterfaceClassActivityChangedWifi() throws Exception {
11585         doTestInterfaceClassActivityChanged(TRANSPORT_WIFI);
11586     }
11587 
11588     @Test
11589     public void testInterfaceClassActivityChangedCellular() throws Exception {
11590         doTestInterfaceClassActivityChanged(TRANSPORT_CELLULAR);
11591     }
11592 
11593     private void doTestOnNetworkActive_NewNetworkConnects(int transportType, boolean expectCapChanged)
11594             throws Exception {
11595         final ConditionVariable onNetworkActiveCv = new ConditionVariable();
11596         final ConnectivityManager.OnNetworkActiveListener listener = onNetworkActiveCv::open;
11597 
11598         final LinkProperties lp = new LinkProperties();
11599         lp.setInterfaceName(transportToTestIfaceName(transportType));
11600         final TestNetworkAgentWrapper agent = new TestNetworkAgentWrapper(transportType, lp);
11601 
11602         testAndCleanup(() -> {
11603             mCm.addDefaultNetworkActiveListener(listener);
11604             agent.connect(true);
11605             if (expectCapChanged) {
11606                 assertTrue(onNetworkActiveCv.block(TEST_CALLBACK_TIMEOUT_MS));
11607             } else {
11608                 assertFalse(onNetworkActiveCv.block(TEST_CALLBACK_TIMEOUT_MS));
11609             }
11610             assertTrue(mCm.isDefaultNetworkActive());
11611         }, () -> { // Cleanup
11612                 mCm.removeDefaultNetworkActiveListener(listener);
11613             }, () -> { // Cleanup
11614                 agent.disconnect();
11615             });
11616     }
11617 
11618     @Test
11619     public void testOnNetworkActive_NewCellConnects_CallbackCalled() throws Exception {
11620         doTestOnNetworkActive_NewNetworkConnects(TRANSPORT_CELLULAR, true /* expectCapChanged */);
11621     }
11622 
11623     @Test
11624     public void testOnNetworkActive_NewEthernetConnects_Callback() throws Exception {
11625         // On pre-V devices, LegacyNetworkActivityTracker calls onNetworkActive callback only for
11626         // networks that tracker adds the idle timer to. And the tracker does not set the idle timer
11627         // for the ethernet network.
11628         // So onNetworkActive is not called when the ethernet becomes the default network
11629         final boolean expectCapChanged = mDeps.isAtLeastV();
11630         doTestOnNetworkActive_NewNetworkConnects(TRANSPORT_ETHERNET, expectCapChanged);
11631     }
11632 
11633     @Test
11634     public void testIsDefaultNetworkActiveNoDefaultNetwork() throws Exception {
11635         // isDefaultNetworkActive returns true if there is no default network, which is known issue.
11636         assertTrue(mCm.isDefaultNetworkActive());
11637 
11638         final LinkProperties cellLp = new LinkProperties();
11639         cellLp.setInterfaceName(MOBILE_IFNAME);
11640         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
11641         mCellAgent.connect(true);
11642         // Network is considered active when the network becomes the default network.
11643         assertTrue(mCm.isDefaultNetworkActive());
11644 
11645         mCellAgent.disconnect();
11646         waitForIdle();
11647 
11648         assertTrue(mCm.isDefaultNetworkActive());
11649     }
11650 
11651     @Test
11652     public void testDataActivityTracking() throws Exception {
11653         final TestNetworkCallback networkCallback = new TestNetworkCallback();
11654         final NetworkRequest networkRequest = new NetworkRequest.Builder()
11655                 .addCapability(NET_CAPABILITY_INTERNET)
11656                 .build();
11657         mCm.registerNetworkCallback(networkRequest, networkCallback);
11658 
11659         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
11660         final String cellIdleTimerLabel = Integer.toString(getIdleTimerLabel(
11661                 mCellAgent.getNetwork().netId, TRANSPORT_CELLULAR));
11662         final LinkProperties cellLp = new LinkProperties();
11663         cellLp.setInterfaceName(MOBILE_IFNAME);
11664         mCellAgent.sendLinkProperties(cellLp);
11665         mCellAgent.connect(true);
11666         networkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
11667         verify(mMockNetd, times(1)).idletimerAddInterface(eq(MOBILE_IFNAME), anyInt(),
11668                 eq(cellIdleTimerLabel));
11669 
11670         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
11671         String wifiIdleTimerLabel = Integer.toString(getIdleTimerLabel(
11672                 mWiFiAgent.getNetwork().netId, TRANSPORT_WIFI));
11673         final LinkProperties wifiLp = new LinkProperties();
11674         wifiLp.setInterfaceName(WIFI_IFNAME);
11675         mWiFiAgent.sendLinkProperties(wifiLp);
11676 
11677         // Network switch
11678         mWiFiAgent.connect(true);
11679         networkCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
11680         networkCallback.expectLosing(mCellAgent);
11681         networkCallback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
11682         verify(mMockNetd, times(1)).idletimerAddInterface(eq(WIFI_IFNAME), anyInt(),
11683                 eq(wifiIdleTimerLabel));
11684         if (mDeps.isAtLeastV()) {
11685             // V+ devices add idleTimer when the network is first connected and remove when the
11686             // network is disconnected.
11687             verify(mMockNetd, never()).idletimerRemoveInterface(eq(MOBILE_IFNAME), anyInt(),
11688                     eq(Integer.toString(mCellAgent.getNetwork().netId)));
11689         } else {
11690             // pre V devices add idleTimer when the network becomes the default network and remove
11691             // when the network becomes no longer the default network.
11692             verify(mMockNetd, times(1)).idletimerRemoveInterface(eq(MOBILE_IFNAME), anyInt(),
11693                     eq(Integer.toString(TRANSPORT_CELLULAR)));
11694         }
11695 
11696         // Disconnect wifi and switch back to cell
11697         reset(mMockNetd);
11698         mWiFiAgent.disconnect();
11699         networkCallback.expect(LOST, mWiFiAgent);
11700         assertNoCallbacks(networkCallback);
11701         verify(mMockNetd, times(1)).idletimerRemoveInterface(eq(WIFI_IFNAME), anyInt(),
11702                 eq(wifiIdleTimerLabel));
11703         if (mDeps.isAtLeastV()) {
11704             verify(mMockNetd, never()).idletimerAddInterface(eq(MOBILE_IFNAME), anyInt(),
11705                     eq(Integer.toString(mCellAgent.getNetwork().netId)));
11706         } else {
11707             verify(mMockNetd, times(1)).idletimerAddInterface(eq(MOBILE_IFNAME), anyInt(),
11708                     eq(Integer.toString(TRANSPORT_CELLULAR)));
11709         }
11710 
11711         // reconnect wifi
11712         reset(mMockNetd);
11713         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
11714         wifiIdleTimerLabel = Integer.toString(getIdleTimerLabel(
11715                 mWiFiAgent.getNetwork().netId, TRANSPORT_WIFI));
11716         wifiLp.setInterfaceName(WIFI_IFNAME);
11717         mWiFiAgent.sendLinkProperties(wifiLp);
11718         mWiFiAgent.connect(true);
11719         networkCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
11720         networkCallback.expectLosing(mCellAgent);
11721         networkCallback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
11722         verify(mMockNetd, times(1)).idletimerAddInterface(eq(WIFI_IFNAME), anyInt(),
11723                 eq(wifiIdleTimerLabel));
11724         if (mDeps.isAtLeastV()) {
11725             verify(mMockNetd, never()).idletimerRemoveInterface(eq(MOBILE_IFNAME), anyInt(),
11726                     eq(Integer.toString(mCellAgent.getNetwork().netId)));
11727         } else {
11728             verify(mMockNetd, times(1)).idletimerRemoveInterface(eq(MOBILE_IFNAME), anyInt(),
11729                     eq(Integer.toString(TRANSPORT_CELLULAR)));
11730         }
11731 
11732         // Disconnect cell
11733         reset(mMockNetd);
11734         mCellAgent.disconnect();
11735         networkCallback.expect(LOST, mCellAgent);
11736         waitForIdle();
11737         if (mDeps.isAtLeastV()) {
11738             verify(mMockNetd, times(1)).idletimerRemoveInterface(eq(MOBILE_IFNAME), anyInt(),
11739                     eq(Integer.toString(mCellAgent.getNetwork().netId)));
11740         }  else {
11741             // LOST callback is triggered earlier than removing idle timer. Broadcast should also be
11742             // sent as network being switched. Ensure rule removal for cell will not be triggered
11743             // unexpectedly before network being removed.
11744             verify(mMockNetd, times(0)).idletimerRemoveInterface(eq(MOBILE_IFNAME), anyInt(),
11745                     eq(Integer.toString(TRANSPORT_CELLULAR)));
11746         }
11747         verify(mMockNetd, times(1)).networkDestroy(eq(mCellAgent.getNetwork().netId));
11748         verify(mMockDnsResolver, times(1)).destroyNetworkCache(eq(mCellAgent.getNetwork().netId));
11749 
11750         // Disconnect wifi
11751         ExpectedBroadcast b = expectConnectivityAction(TYPE_WIFI, DetailedState.DISCONNECTED);
11752         mWiFiAgent.disconnect();
11753         b.expectBroadcast();
11754         verify(mMockNetd, times(1)).idletimerRemoveInterface(eq(WIFI_IFNAME), anyInt(),
11755                 eq(wifiIdleTimerLabel));
11756 
11757         // Clean up
11758         mCm.unregisterNetworkCallback(networkCallback);
11759     }
11760 
11761     @Test
11762     public void testDataActivityTracking_VpnNetwork() throws Exception {
11763         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
11764         mWiFiAgent.connect(true /* validated */);
11765         mMockVpn.setUnderlyingNetworks(new Network[] { mWiFiAgent.getNetwork() });
11766 
11767         final LinkProperties lp = new LinkProperties();
11768         lp.setInterfaceName(VPN_IFNAME);
11769         mMockVpn.establishForMyUid(lp);
11770 
11771         // NetworkActivityTracker should not track the VPN network since VPN can change the
11772         // underlying network without disconnect.
11773         verify(mMockNetd, never()).idletimerAddInterface(eq(VPN_IFNAME), anyInt(), any());
11774     }
11775 
11776     private void verifyTcpBufferSizeChange(String tcpBufferSizes) throws Exception {
11777         String[] values = tcpBufferSizes.split(",");
11778         String rmemValues = String.join(" ", values[0], values[1], values[2]);
11779         String wmemValues = String.join(" ", values[3], values[4], values[5]);
11780         verify(mMockNetd, atLeastOnce()).setTcpRWmemorySize(rmemValues, wmemValues);
11781         reset(mMockNetd);
11782     }
11783 
11784     @Test
11785     public void testTcpBufferReset() throws Exception {
11786         final String testTcpBufferSizes = "1,2,3,4,5,6";
11787         final NetworkRequest networkRequest = new NetworkRequest.Builder()
11788                 .addTransportType(TRANSPORT_CELLULAR)
11789                 .addCapability(NET_CAPABILITY_INTERNET)
11790                 .build();
11791         final TestNetworkCallback networkCallback = new TestNetworkCallback();
11792         mCm.registerNetworkCallback(networkRequest, networkCallback);
11793 
11794         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
11795         reset(mMockNetd);
11796         // Switching default network updates TCP buffer sizes.
11797         mCellAgent.connect(false);
11798         networkCallback.expectAvailableCallbacksUnvalidated(mCellAgent);
11799         verifyTcpBufferSizeChange(ConnectivityService.DEFAULT_TCP_BUFFER_SIZES);
11800         // Change link Properties should have updated tcp buffer size.
11801         LinkProperties lp = new LinkProperties();
11802         lp.setTcpBufferSizes(testTcpBufferSizes);
11803         mCellAgent.sendLinkProperties(lp);
11804         networkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent);
11805         verifyTcpBufferSizeChange(testTcpBufferSizes);
11806         // Clean up.
11807         mCellAgent.disconnect();
11808         networkCallback.expect(LOST, mCellAgent);
11809         networkCallback.assertNoCallback();
11810         mCm.unregisterNetworkCallback(networkCallback);
11811     }
11812 
11813     @Test
11814     public void testGetGlobalProxyForNetwork() throws Exception {
11815         final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
11816         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
11817         final Network wifiNetwork = mWiFiAgent.getNetwork();
11818         mProxyTracker.setGlobalProxy(testProxyInfo);
11819         assertEquals(testProxyInfo, mService.getProxyForNetwork(wifiNetwork));
11820     }
11821 
11822     @Test
11823     public void testGetProxyForActiveNetwork() throws Exception {
11824         final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
11825         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
11826         mWiFiAgent.connect(true);
11827         waitForIdle();
11828         assertNull(mService.getProxyForNetwork(null));
11829 
11830         final LinkProperties testLinkProperties = new LinkProperties();
11831         testLinkProperties.setHttpProxy(testProxyInfo);
11832 
11833         mWiFiAgent.sendLinkProperties(testLinkProperties);
11834         waitForIdle();
11835 
11836         assertEquals(testProxyInfo, mService.getProxyForNetwork(null));
11837     }
11838 
11839     /*
11840      * Note for maintainers about how PAC proxies are implemented in Android.
11841      *
11842      * Generally, a proxy is just a hostname and a port to which requests are sent, instead of
11843      * sending them directly. Most HTTP libraries know to use this protocol, and the Java
11844      * language has properties to help handling these :
11845      *   https://docs.oracle.com/javase/8/docs/technotes/guides/net/proxies.html
11846      * Unfortunately these properties are very old and do not take multi-networking into account.
11847      *
11848      * A PAC proxy consists of a javascript file stored on a server, and the client is expected to
11849      * download the file and interpret the javascript for each HTTP request to know where to direct
11850      * it. The device must therefore run code (namely, a javascript interpreter) to interpret the
11851      * PAC file correctly. Most HTTP libraries do not know how to do this, since they do not
11852      * embark a javascript interpreter (and it would be generally unreasonable for them to do
11853      * so). Some apps, notably browsers, do know how to do this, but they are the exception rather
11854      * than the rule.
11855      * So to support most apps, Android embarks the javascript interpreter. When a network is
11856      * configured to have a PAC proxy, Android will first set the ProxyInfo object to an object
11857      * that contains the PAC URL (to communicate that to apps that know how to use it), then
11858      * download the PAC file and start a native process which will open a server on localhost,
11859      * and uses the interpreter inside WebView to interpret the PAC file. This server takes
11860      * a little bit of time to start and will listen on a random port. When the port is known,
11861      * the framework receives a notification and it updates the ProxyInfo in LinkProperties
11862      * as well as send a broadcast to inform apps. This new ProxyInfo still contains the PAC URL,
11863      * but it also contains "localhost" as the host and the port that the server listens to as
11864      * the port. This will let HTTP libraries that don't have a javascript interpreter work,
11865      * because they'll send the requests to this server running on localhost on the correct port,
11866      * and this server will do what is appropriate with each request according to the PAC file.
11867      *
11868      * Note that at the time of this writing, Android does not support starting multiple local
11869      * PAC servers, though this would be possible in theory by just starting multiple instances
11870      * of this process running their server on different ports. As a stopgap measure, Android
11871      * keeps one local server which is always the one for the default network. If a non-default
11872      * network has a PAC proxy, it will have a LinkProperties with a port of -1, which means it
11873      * could still be used by apps that know how to use the PAC URL directly, but not by HTTP
11874      * libs that don't know how to do that. When a network with a PAC proxy becomes the default,
11875      * the local server is started. When a network without a PAC proxy becomes the default, the
11876      * local server is stopped if it is running (and the LP for the old default network should
11877      * be reset to have a port of -1).
11878      *
11879      * In principle, each network can be configured with a different proxy (typically in the
11880      * network settings for a Wi-Fi network). These end up exposed in the LinkProperties of the
11881      * relevant network.
11882      * Android also exposes ConnectivityManager#getDefaultProxy, which is simply the proxy for
11883      * the default network. This was retrofitted from a time where Android did not support multiple
11884      * concurrent networks, hence the difficult architecture.
11885      * Note that there is also a "global" proxy that can be set by the DPM. When this is set,
11886      * it overrides the proxy settings for every single network at the same time – that is, the
11887      * system behaves as if the global proxy is the configured proxy for each network.
11888      *
11889      * Generally there are four ways for apps to look up the proxy.
11890      * - Looking up the ProxyInfo in the LinkProperties for a network.
11891      * - Listening to the PROXY_CHANGED_ACTION broadcast
11892      * - Calling ConnectivityManager#getDefaultProxy, or ConnectivityManager#getProxyForNetwork
11893      *   which can be used to retrieve the proxy for any given network or the default network by
11894      *   passing null.
11895      * - Reading the standard JVM properties (http{s,}.proxy{Host,Port}). See the Java
11896      *   distribution documentation for details on how these are supposed to work :
11897      *    https://docs.oracle.com/javase/8/docs/technotes/guides/net/proxies.html
11898      *   In Android, these are set by ActivityThread in each process in response to the broadcast.
11899      *   Many apps actually use these, and it's important they work because it's part of the
11900      *   Java standard, meaning they need to be set for existing Java libs to work on Android.
11901      */
11902     @Test
11903     public void testPacProxy() throws Exception {
11904         final Uri pacUrl = Uri.parse("https://pac-url");
11905 
11906         final TestNetworkCallback cellCallback = new TestNetworkCallback();
11907         final NetworkRequest cellRequest = new NetworkRequest.Builder()
11908                 .addTransportType(TRANSPORT_CELLULAR).build();
11909         // Request cell to make sure it doesn't disconnect at an arbitrary point in the test,
11910         // which would make testing the callbacks on it difficult.
11911         mCm.requestNetwork(cellRequest, cellCallback);
11912         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
11913         mCellAgent.connect(true);
11914         cellCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
11915 
11916         final TestNetworkCallback wifiCallback = new TestNetworkCallback();
11917         final NetworkRequest wifiRequest = new NetworkRequest.Builder()
11918                 .addTransportType(TRANSPORT_WIFI).build();
11919         mCm.registerNetworkCallback(wifiRequest, wifiCallback);
11920 
11921         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
11922         mWiFiAgent.connect(true);
11923         wifiCallback.expectAvailableThenValidatedCallbacks(mWiFiAgent);
11924         cellCallback.assertNoCallback();
11925 
11926         final ProxyInfo initialProxyInfo = ProxyInfo.buildPacProxy(pacUrl);
11927         final LinkProperties testLinkProperties = new LinkProperties();
11928         testLinkProperties.setHttpProxy(initialProxyInfo);
11929         mWiFiAgent.sendLinkProperties(testLinkProperties);
11930         wifiCallback.expect(CallbackEntry.LINK_PROPERTIES_CHANGED, mWiFiAgent);
11931         cellCallback.assertNoCallback();
11932 
11933         // At first the local PAC proxy server is unstarted (see the description of what the local
11934         // server is in the comment at the top of this method). It will contain the PAC URL and a
11935         // port of -1 because it is unstarted. Check that all ways of getting that proxy info
11936         // returns the same object that was initially created.
11937         final ProxyInfo unstartedDefaultProxyInfo = mService.getProxyForNetwork(null);
11938         final ProxyInfo unstartedWifiProxyInfo = mService.getProxyForNetwork(
11939                 mWiFiAgent.getNetwork());
11940         final LinkProperties unstartedLp =
11941                 mService.getLinkProperties(mWiFiAgent.getNetwork());
11942 
11943         assertEquals(initialProxyInfo, unstartedDefaultProxyInfo);
11944         assertEquals(initialProxyInfo, unstartedWifiProxyInfo);
11945         assertEquals(initialProxyInfo, unstartedLp.getHttpProxy());
11946 
11947         // Make sure the cell network is unaffected. The LP are per-network and each network has
11948         // its own configuration. The default proxy and broadcast are system-wide, and the JVM
11949         // properties are per-process, and therefore can have only one value at any given time,
11950         // so the code sets them to the proxy of the default network (TODO : really, since the
11951         // default process is per-network, the JVM properties (http.proxyHost family – see
11952         // the comment at the top of the method for details about these) also should be per-network
11953         // and even the broadcast contents should be but none of this is implemented). The LP are
11954         // still per-network, and a process that wants to use a non-default network is supposed to
11955         // look up the proxy in its LP and it has to be correct.
11956         assertNull(mService.getLinkProperties(mCellAgent.getNetwork()).getHttpProxy());
11957         assertNull(mService.getProxyForNetwork(mCellAgent.getNetwork()));
11958 
11959         // Simulate PacManager sending the notification that the local server has started
11960         final ProxyInfo servingProxyInfo = new ProxyInfo(pacUrl, 2097);
11961         final ExpectedBroadcast servingProxyBroadcast = expectProxyChangeAction(servingProxyInfo);
11962         mService.simulateUpdateProxyInfo(mWiFiAgent.getNetwork(), servingProxyInfo);
11963         wifiCallback.expect(CallbackEntry.LINK_PROPERTIES_CHANGED, mWiFiAgent);
11964         cellCallback.assertNoCallback();
11965         servingProxyBroadcast.expectBroadcast();
11966 
11967         final ProxyInfo startedDefaultProxyInfo = mService.getProxyForNetwork(null);
11968         final ProxyInfo startedWifiProxyInfo = mService.getProxyForNetwork(
11969                 mWiFiAgent.getNetwork());
11970         final LinkProperties startedLp = mService.getLinkProperties(mWiFiAgent.getNetwork());
11971         assertEquals(servingProxyInfo, startedDefaultProxyInfo);
11972         assertEquals(servingProxyInfo, startedWifiProxyInfo);
11973         assertEquals(servingProxyInfo, startedLp.getHttpProxy());
11974         // Make sure the cell network is still unaffected
11975         assertNull(mService.getLinkProperties(mCellAgent.getNetwork()).getHttpProxy());
11976         assertNull(mService.getProxyForNetwork(mCellAgent.getNetwork()));
11977 
11978         // Start an ethernet network which will become the default, in order to test what happens
11979         // to the proxy of wifi while manipulating the proxy of ethernet.
11980         final Uri ethPacUrl = Uri.parse("https://ethernet-pac-url");
11981         final TestableNetworkCallback ethernetCallback = new TestableNetworkCallback();
11982         final NetworkRequest ethernetRequest = new NetworkRequest.Builder()
11983                 .addTransportType(TRANSPORT_ETHERNET).build();
11984         mEthernetAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
11985         mCm.registerNetworkCallback(ethernetRequest, ethernetCallback);
11986         mEthernetAgent.connect(true);
11987         ethernetCallback.expectAvailableThenValidatedCallbacks(mEthernetAgent);
11988 
11989         // Wifi is no longer the default, so it should get a callback to LP changed with a PAC
11990         // proxy but a port of -1 (since the local proxy doesn't serve wifi now)
11991         wifiCallback.expect(LINK_PROPERTIES_CHANGED, mWiFiAgent,
11992                 lp -> lp.getLp().getHttpProxy().getPort() == -1
11993                         && lp.getLp().getHttpProxy().isPacProxy());
11994         // Wifi is lingered as it was the default but is no longer serving any request.
11995         wifiCallback.expect(CallbackEntry.LOSING, mWiFiAgent);
11996 
11997         // Now arrange for Ethernet to have a PAC proxy.
11998         final ProxyInfo ethProxy = ProxyInfo.buildPacProxy(ethPacUrl);
11999         final LinkProperties ethLinkProperties = new LinkProperties();
12000         ethLinkProperties.setHttpProxy(ethProxy);
12001         mEthernetAgent.sendLinkProperties(ethLinkProperties);
12002         ethernetCallback.expect(CallbackEntry.LINK_PROPERTIES_CHANGED, mEthernetAgent);
12003         // Default network is Ethernet
12004         assertEquals(ethProxy, mService.getProxyForNetwork(null));
12005         assertEquals(ethProxy, mService.getProxyForNetwork(mEthernetAgent.getNetwork()));
12006         // Proxy info for WiFi ideally should be the old one with the old server still running,
12007         // but as the PAC code only handles one server at any given time, this can't work. Wifi
12008         // having null as a proxy also won't work (apps using WiFi will try to access the network
12009         // without proxy) but is not as bad as having the new proxy (that would send requests
12010         // over the default network).
12011         assertEquals(initialProxyInfo, mService.getProxyForNetwork(mWiFiAgent.getNetwork()));
12012         assertNull(mService.getProxyForNetwork(mCellAgent.getNetwork()));
12013 
12014         // Expect the local PAC proxy server starts to serve the proxy on Ethernet. Use
12015         // simulateUpdateProxyInfo to simulate this, and check that the callback is called to
12016         // inform apps of the port and that the various networks have the expected proxies in
12017         // their link properties.
12018         final ProxyInfo servingEthProxy = new ProxyInfo(ethPacUrl, 2099);
12019         final ExpectedBroadcast servingEthProxyBroadcast = expectProxyChangeAction(servingEthProxy);
12020         final ExpectedBroadcast servingProxyBroadcast2 = expectProxyChangeAction(servingProxyInfo);
12021         mService.simulateUpdateProxyInfo(mEthernetAgent.getNetwork(), servingEthProxy);
12022         ethernetCallback.expect(CallbackEntry.LINK_PROPERTIES_CHANGED, mEthernetAgent);
12023         assertEquals(servingEthProxy, mService.getProxyForNetwork(null));
12024         assertEquals(servingEthProxy, mService.getProxyForNetwork(mEthernetAgent.getNetwork()));
12025         assertEquals(initialProxyInfo, mService.getProxyForNetwork(mWiFiAgent.getNetwork()));
12026         assertNull(mService.getProxyForNetwork(mCellAgent.getNetwork()));
12027         servingEthProxyBroadcast.expectBroadcast();
12028 
12029         // Ethernet disconnects, back to WiFi
12030         mEthernetAgent.disconnect();
12031         ethernetCallback.expect(CallbackEntry.LOST, mEthernetAgent);
12032 
12033         // WiFi is now the default network again. However, the local proxy server does not serve
12034         // WiFi at this time, so at this time a proxy with port -1 is still the correct value.
12035         // In time, the local proxy server for ethernet will be downed and the local proxy server
12036         // for WiFi will be restarted, and WiFi will see an update to its LP with the new port,
12037         // but in this test this won't happen until the test simulates the local proxy starting
12038         // up for WiFi (which is done just a few lines below). This is therefore the perfect place
12039         // to check that WiFi is unaffected until the new local proxy starts up.
12040         wifiCallback.assertNoCallback();
12041         assertEquals(initialProxyInfo, mService.getProxyForNetwork(null));
12042         assertEquals(initialProxyInfo, mService.getProxyForNetwork(mWiFiAgent.getNetwork()));
12043         assertNull(mService.getProxyForNetwork(mCellAgent.getNetwork()));
12044         // Note : strictly speaking, for correctness here apps should expect a broadcast with a
12045         // port of -1, since that's the current default proxy. The code does not send this
12046         // broadcast. In practice though, not sending it is more useful since the new proxy will
12047         // start momentarily, so broadcasting and getting all apps to update and retry once now
12048         // and again in 250ms is kind of counter-productive, so don't fix this bug.
12049 
12050         // After a while the PAC file for wifi is resolved again and the local proxy server
12051         // starts up. This should cause a LP event to inform clients of the port to access the
12052         // proxy server for wifi.
12053         mService.simulateUpdateProxyInfo(mWiFiAgent.getNetwork(), servingProxyInfo);
12054         wifiCallback.expect(CallbackEntry.LINK_PROPERTIES_CHANGED, mWiFiAgent);
12055         assertEquals(servingProxyInfo, mService.getProxyForNetwork(null));
12056         assertEquals(servingProxyInfo, mService.getProxyForNetwork(mWiFiAgent.getNetwork()));
12057         assertNull(mService.getProxyForNetwork(mCellAgent.getNetwork()));
12058         servingProxyBroadcast2.expectBroadcast();
12059 
12060         // Expect a broadcast for an empty proxy after wifi disconnected, because cell is now
12061         // the default network and it doesn't have a proxy. Whether "no proxy" is a null pointer
12062         // or a ProxyInfo with an empty host doesn't matter because both are correct, so this test
12063         // accepts both.
12064         final ExpectedBroadcast emptyProxyBroadcast = expectProxyChangeAction(
12065                 proxy -> proxy == null || TextUtils.isEmpty(proxy.getHost()));
12066         mWiFiAgent.disconnect();
12067         emptyProxyBroadcast.expectBroadcast();
12068         wifiCallback.expect(CallbackEntry.LOST, mWiFiAgent);
12069         assertNull(mService.getProxyForNetwork(null));
12070         assertNull(mService.getLinkProperties(mCellAgent.getNetwork()).getHttpProxy());
12071         assertNull(mService.getGlobalProxy());
12072 
12073         mCm.unregisterNetworkCallback(cellCallback);
12074     }
12075 
12076     @Test
12077     public void testPacProxy_NetworkDisconnects_BroadcastSent() throws Exception {
12078         // Make a WiFi network with a PAC URI.
12079         final Uri pacUrl = Uri.parse("https://pac-url");
12080         final ProxyInfo initialProxyInfo = ProxyInfo.buildPacProxy(pacUrl);
12081         final LinkProperties testLinkProperties = new LinkProperties();
12082         testLinkProperties.setHttpProxy(initialProxyInfo);
12083 
12084         final TestNetworkCallback wifiCallback = new TestNetworkCallback();
12085         final NetworkRequest wifiRequest = new NetworkRequest.Builder()
12086                 .addTransportType(TRANSPORT_WIFI).build();
12087         mCm.registerNetworkCallback(wifiRequest, wifiCallback);
12088 
12089         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, testLinkProperties);
12090         mWiFiAgent.connect(true);
12091         // Wifi is up, but the local proxy server hasn't started yet.
12092         wifiCallback.expectAvailableThenValidatedCallbacks(mWiFiAgent);
12093 
12094         // Simulate PacManager sending the notification that the local server has started
12095         final ProxyInfo servingProxyInfo = new ProxyInfo(pacUrl, 2097);
12096         final ExpectedBroadcast servingProxyBroadcast = expectProxyChangeAction(servingProxyInfo);
12097         mService.simulateUpdateProxyInfo(mWiFiAgent.getNetwork(), servingProxyInfo);
12098         wifiCallback.expect(CallbackEntry.LINK_PROPERTIES_CHANGED, mWiFiAgent);
12099         servingProxyBroadcast.expectBroadcast();
12100 
12101         // Now disconnect Wi-Fi and make sure there is a broadcast for some empty proxy. Whether
12102         // the "empty" proxy is a null pointer or a ProxyInfo with an empty host doesn't matter
12103         // because both are correct, so this test accepts both.
12104         final ExpectedBroadcast emptyProxyBroadcast = expectProxyChangeAction(
12105                 proxy -> proxy == null || TextUtils.isEmpty(proxy.getHost()));
12106         mWiFiAgent.disconnect();
12107         wifiCallback.expect(CallbackEntry.LOST, mWiFiAgent);
12108         emptyProxyBroadcast.expectBroadcast();
12109     }
12110 
12111     @Test
12112     public void testGetProxyForVPN() throws Exception {
12113         final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
12114 
12115         // Set up a WiFi network with no proxy
12116         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
12117         mWiFiAgent.connect(true);
12118         waitForIdle();
12119         assertNull(mService.getProxyForNetwork(null));
12120 
12121         // Connect a VPN network with a proxy.
12122         LinkProperties testLinkProperties = new LinkProperties();
12123         testLinkProperties.setHttpProxy(testProxyInfo);
12124         mMockVpn.establishForMyUid(testLinkProperties);
12125         assertUidRangesUpdatedForMyUid(true);
12126 
12127         // Test that the VPN network returns a proxy, and the WiFi does not.
12128         assertEquals(testProxyInfo, mService.getProxyForNetwork(mMockVpn.getNetwork()));
12129         assertEquals(testProxyInfo, mService.getProxyForNetwork(null));
12130         assertNull(mService.getProxyForNetwork(mWiFiAgent.getNetwork()));
12131 
12132         // Test that the VPN network returns no proxy when it is set to null.
12133         testLinkProperties.setHttpProxy(null);
12134         mMockVpn.sendLinkProperties(testLinkProperties);
12135         waitForIdle();
12136         assertNull(mService.getProxyForNetwork(mMockVpn.getNetwork()));
12137         assertNull(mService.getProxyForNetwork(null));
12138 
12139         // Set WiFi proxy and check that the vpn proxy is still null.
12140         testLinkProperties.setHttpProxy(testProxyInfo);
12141         mWiFiAgent.sendLinkProperties(testLinkProperties);
12142         waitForIdle();
12143         assertNull(mService.getProxyForNetwork(null));
12144 
12145         // Disconnect from VPN and check that the active network, which is now the WiFi, has the
12146         // correct proxy setting.
12147         mMockVpn.disconnect();
12148         waitForIdle();
12149         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetwork());
12150         assertEquals(testProxyInfo, mService.getProxyForNetwork(mWiFiAgent.getNetwork()));
12151         assertEquals(testProxyInfo, mService.getProxyForNetwork(null));
12152     }
12153 
12154     @Test
12155     public void testFullyRoutedVpnResultsInInterfaceFilteringRules() throws Exception {
12156         LinkProperties lp = new LinkProperties();
12157         lp.setInterfaceName("tun0");
12158         lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
12159         lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), RTN_UNREACHABLE));
12160         // The uid range needs to cover the test app so the network is visible to it.
12161         final Set<UidRange> vpnRange = Collections.singleton(PRIMARY_UIDRANGE);
12162         mMockVpn.establish(lp, VPN_UID, vpnRange);
12163         assertVpnUidRangesUpdated(true, vpnRange, VPN_UID);
12164 
12165         // A connected VPN should have interface rules set up. There are two expected invocations,
12166         // one during the VPN initial connection, one during the VPN LinkProperties update.
12167         ArgumentCaptor<int[]> uidCaptor = ArgumentCaptor.forClass(int[].class);
12168         verify(mBpfNetMaps, times(2)).addUidInterfaceRules(eq("tun0"), uidCaptor.capture());
12169         assertContainsExactly(uidCaptor.getAllValues().get(0), APP1_UID, APP2_UID);
12170         assertContainsExactly(uidCaptor.getAllValues().get(1), APP1_UID, APP2_UID);
12171 
12172         mMockVpn.disconnect();
12173         waitForIdle();
12174 
12175         // Disconnected VPN should have interface rules removed
12176         verify(mBpfNetMaps).removeUidInterfaceRules(uidCaptor.capture());
12177         assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
12178     }
12179 
12180     private void checkInterfaceFilteringRuleWithNullInterface(final LinkProperties lp,
12181             final int uid) throws Exception {
12182         // The uid range needs to cover the test app so the network is visible to it.
12183         final Set<UidRange> vpnRange = Collections.singleton(PRIMARY_UIDRANGE);
12184         mMockVpn.establish(lp, uid, vpnRange);
12185         assertVpnUidRangesUpdated(true, vpnRange, uid);
12186 
12187         if (mDeps.isAtLeastT()) {
12188             // On T and above, VPN should have rules for null interface. Null Interface is a
12189             // wildcard and this accepts traffic from all the interfaces.
12190             // There are two expected invocations, one during the VPN initial
12191             // connection, one during the VPN LinkProperties update.
12192             ArgumentCaptor<int[]> uidCaptor = ArgumentCaptor.forClass(int[].class);
12193             verify(mBpfNetMaps, times(2)).addUidInterfaceRules(
12194                     eq(null) /* iface */, uidCaptor.capture());
12195             if (uid == VPN_UID) {
12196                 assertContainsExactly(uidCaptor.getAllValues().get(0), APP1_UID, APP2_UID);
12197                 assertContainsExactly(uidCaptor.getAllValues().get(1), APP1_UID, APP2_UID);
12198             } else {
12199                 assertContainsExactly(uidCaptor.getAllValues().get(0), APP1_UID, APP2_UID, VPN_UID);
12200                 assertContainsExactly(uidCaptor.getAllValues().get(1), APP1_UID, APP2_UID, VPN_UID);
12201             }
12202 
12203             mMockVpn.disconnect();
12204             waitForIdle();
12205 
12206             // Disconnected VPN should have interface rules removed
12207             verify(mBpfNetMaps).removeUidInterfaceRules(uidCaptor.capture());
12208             if (uid == VPN_UID) {
12209                 assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
12210             } else {
12211                 assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID, VPN_UID);
12212             }
12213         } else {
12214             // Before T, rules are not configured for null interface.
12215             verify(mBpfNetMaps, never()).addUidInterfaceRules(any(), any());
12216         }
12217     }
12218 
12219     @Test
12220     public void testLegacyVpnInterfaceFilteringRule() throws Exception {
12221         LinkProperties lp = new LinkProperties();
12222         lp.setInterfaceName("tun0");
12223         lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
12224         lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
12225         // Legacy VPN should have interface filtering with null interface.
12226         checkInterfaceFilteringRuleWithNullInterface(lp, Process.SYSTEM_UID);
12227     }
12228 
12229     @Test
12230     public void testLocalIpv4OnlyVpnInterfaceFilteringRule() throws Exception {
12231         LinkProperties lp = new LinkProperties();
12232         lp.setInterfaceName("tun0");
12233         lp.addRoute(new RouteInfo(new IpPrefix("192.0.2.0/24"), null, "tun0"));
12234         lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), RTN_UNREACHABLE));
12235         // VPN that does not provide a default route should have interface filtering with null
12236         // interface.
12237         checkInterfaceFilteringRuleWithNullInterface(lp, VPN_UID);
12238     }
12239 
12240     @Test
12241     public void testVpnHandoverChangesInterfaceFilteringRule() throws Exception {
12242         LinkProperties lp = new LinkProperties();
12243         lp.setInterfaceName("tun0");
12244         lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
12245         lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
12246         // The uid range needs to cover the test app so the network is visible to it.
12247         final Set<UidRange> vpnRange = Collections.singleton(PRIMARY_UIDRANGE);
12248         mMockVpn.establish(lp, VPN_UID, vpnRange);
12249         assertVpnUidRangesUpdated(true, vpnRange, VPN_UID);
12250 
12251         // Connected VPN should have interface rules set up. There are two expected invocations,
12252         // one during VPN uid update, one during VPN LinkProperties update
12253         ArgumentCaptor<int[]> uidCaptor = ArgumentCaptor.forClass(int[].class);
12254         verify(mBpfNetMaps, times(2)).addUidInterfaceRules(eq("tun0"), uidCaptor.capture());
12255         assertContainsExactly(uidCaptor.getAllValues().get(0), APP1_UID, APP2_UID);
12256         assertContainsExactly(uidCaptor.getAllValues().get(1), APP1_UID, APP2_UID);
12257 
12258         reset(mBpfNetMaps);
12259         InOrder inOrder = inOrder(mBpfNetMaps);
12260         lp.setInterfaceName("tun1");
12261         mMockVpn.sendLinkProperties(lp);
12262         waitForIdle();
12263         // VPN handover (switch to a new interface) should result in rules being updated (old rules
12264         // removed first, then new rules added)
12265         inOrder.verify(mBpfNetMaps).removeUidInterfaceRules(uidCaptor.capture());
12266         assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
12267         inOrder.verify(mBpfNetMaps).addUidInterfaceRules(eq("tun1"), uidCaptor.capture());
12268         assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
12269 
12270         reset(mBpfNetMaps);
12271         lp = new LinkProperties();
12272         lp.setInterfaceName("tun1");
12273         lp.addRoute(new RouteInfo(new IpPrefix("192.0.2.0/24"), null, "tun1"));
12274         mMockVpn.sendLinkProperties(lp);
12275         waitForIdle();
12276         // VPN not routing everything should no longer have interface filtering rules
12277         verify(mBpfNetMaps).removeUidInterfaceRules(uidCaptor.capture());
12278         assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
12279 
12280         reset(mBpfNetMaps);
12281         lp = new LinkProperties();
12282         lp.setInterfaceName("tun1");
12283         lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), RTN_UNREACHABLE));
12284         lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
12285         mMockVpn.sendLinkProperties(lp);
12286         waitForIdle();
12287         // Back to routing all IPv6 traffic should have filtering rules
12288         verify(mBpfNetMaps).addUidInterfaceRules(eq("tun1"), uidCaptor.capture());
12289         assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
12290     }
12291 
12292     @Test
12293     public void testUidUpdateChangesInterfaceFilteringRule() throws Exception {
12294         LinkProperties lp = new LinkProperties();
12295         lp.setInterfaceName("tun0");
12296         lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), RTN_UNREACHABLE));
12297         lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
12298         // The uid range needs to cover the test app so the network is visible to it.
12299         final UidRange vpnRange = PRIMARY_UIDRANGE;
12300         final Set<UidRange> vpnRanges = Collections.singleton(vpnRange);
12301         mMockVpn.establish(lp, VPN_UID, vpnRanges);
12302         assertVpnUidRangesUpdated(true, vpnRanges, VPN_UID);
12303 
12304         reset(mBpfNetMaps);
12305         InOrder inOrder = inOrder(mBpfNetMaps);
12306 
12307         // Update to new range which is old range minus APP1, i.e. only APP2
12308         final Set<UidRange> newRanges = new HashSet<>(asList(
12309                 new UidRange(vpnRange.start, APP1_UID - 1),
12310                 new UidRange(APP1_UID + 1, vpnRange.stop)));
12311         mMockVpn.setUids(newRanges);
12312         waitForIdle();
12313 
12314         ArgumentCaptor<int[]> uidCaptor = ArgumentCaptor.forClass(int[].class);
12315         // Verify old rules are removed before new rules are added
12316         inOrder.verify(mBpfNetMaps).removeUidInterfaceRules(uidCaptor.capture());
12317         assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
12318         inOrder.verify(mBpfNetMaps).addUidInterfaceRules(eq("tun0"), uidCaptor.capture());
12319         assertContainsExactly(uidCaptor.getValue(), APP2_UID);
12320     }
12321 
12322     @Test
12323     public void testLinkPropertiesWithWakeOnLanForActiveNetwork() throws Exception {
12324         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
12325 
12326         LinkProperties wifiLp = new LinkProperties();
12327         wifiLp.setInterfaceName(WIFI_WOL_IFNAME);
12328         wifiLp.setWakeOnLanSupported(false);
12329 
12330         // Default network switch should update ifaces.
12331         mWiFiAgent.connect(false);
12332         mWiFiAgent.sendLinkProperties(wifiLp);
12333         waitForIdle();
12334 
12335         // ConnectivityService should have changed the WakeOnLanSupported to true
12336         wifiLp.setWakeOnLanSupported(true);
12337         assertEquals(wifiLp, mService.getActiveLinkProperties());
12338     }
12339 
12340     @Test
12341     public void testLegacyExtraInfoSentToNetworkMonitor() throws Exception {
12342         class TestNetworkAgent extends NetworkAgent {
12343             TestNetworkAgent(Context context, Looper looper, NetworkAgentConfig config) {
12344                 super(context, looper, "MockAgent", new NetworkCapabilities(),
12345                         new LinkProperties(), 40 , config, null /* provider */);
12346             }
12347         }
12348         final NetworkAgent naNoExtraInfo = new TestNetworkAgent(
12349                 mServiceContext, mCsHandlerThread.getLooper(), new NetworkAgentConfig());
12350         naNoExtraInfo.register();
12351         verify(mNetworkStack).makeNetworkMonitor(any(), isNull(), any());
12352         naNoExtraInfo.unregister();
12353 
12354         reset(mNetworkStack);
12355         final NetworkAgentConfig config =
12356                 new NetworkAgentConfig.Builder().setLegacyExtraInfo("legacyinfo").build();
12357         final NetworkAgent naExtraInfo = new TestNetworkAgent(
12358                 mServiceContext, mCsHandlerThread.getLooper(), config);
12359         naExtraInfo.register();
12360         verify(mNetworkStack).makeNetworkMonitor(any(), eq("legacyinfo"), any());
12361         naExtraInfo.unregister();
12362     }
12363 
12364     // To avoid granting location permission bypass.
12365     private void denyAllLocationPrivilegedPermissions() {
12366         mServiceContext.setPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
12367                 PERMISSION_DENIED);
12368         mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_DENIED);
12369         mServiceContext.setPermission(NETWORK_STACK, PERMISSION_DENIED);
12370         mServiceContext.setPermission(Manifest.permission.NETWORK_SETUP_WIZARD,
12371                 PERMISSION_DENIED);
12372     }
12373 
12374     private void setupLocationPermissions(
12375             int targetSdk, boolean locationToggle, String op, String perm) throws Exception {
12376         denyAllLocationPrivilegedPermissions();
12377 
12378         final ApplicationInfo applicationInfo = new ApplicationInfo();
12379         applicationInfo.targetSdkVersion = targetSdk;
12380         doReturn(applicationInfo).when(mPackageManager)
12381                 .getApplicationInfoAsUser(anyString(), anyInt(), any());
12382         doReturn(targetSdk).when(mPackageManager).getTargetSdkVersion(any());
12383 
12384         doReturn(locationToggle).when(mLocationManager).isLocationEnabledForUser(any());
12385 
12386         if (op != null) {
12387             doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOpsManager).noteOp(
12388                     eq(op), eq(Process.myUid()), eq(mContext.getPackageName()),
12389                     eq(getAttributionTag()), anyString());
12390         }
12391 
12392         if (perm != null) {
12393             mServiceContext.setPermission(perm, PERMISSION_GRANTED);
12394         }
12395     }
12396 
12397     private int getOwnerUidNetCapsPermission(int ownerUid, int callerUid,
12398             boolean includeLocationSensitiveInfo) {
12399         final NetworkCapabilities netCap = new NetworkCapabilities().setOwnerUid(ownerUid);
12400 
12401         return mService.createWithLocationInfoSanitizedIfNecessaryWhenParceled(
12402                 netCap, includeLocationSensitiveInfo, Process.myUid(), callerUid,
12403                 mContext.getPackageName(), getAttributionTag())
12404                 .getOwnerUid();
12405     }
12406 
12407     private void verifyTransportInfoCopyNetCapsPermission(
12408             int callerUid, boolean includeLocationSensitiveInfo,
12409             boolean shouldMakeCopyWithLocationSensitiveFieldsParcelable) {
12410         final TransportInfo transportInfo = mock(TransportInfo.class);
12411         doReturn(REDACT_FOR_ACCESS_FINE_LOCATION).when(transportInfo).getApplicableRedactions();
12412         final NetworkCapabilities netCap =
12413                 new NetworkCapabilities().setTransportInfo(transportInfo);
12414 
12415         mService.createWithLocationInfoSanitizedIfNecessaryWhenParceled(
12416                 netCap, includeLocationSensitiveInfo, Process.myPid(), callerUid,
12417                 mContext.getPackageName(), getAttributionTag());
12418         if (shouldMakeCopyWithLocationSensitiveFieldsParcelable) {
12419             verify(transportInfo).makeCopy(REDACT_NONE);
12420         } else {
12421             verify(transportInfo).makeCopy(REDACT_FOR_ACCESS_FINE_LOCATION);
12422         }
12423     }
12424 
12425     private void verifyOwnerUidAndTransportInfoNetCapsPermission(
12426             boolean shouldInclLocationSensitiveOwnerUidWithoutIncludeFlag,
12427             boolean shouldInclLocationSensitiveOwnerUidWithIncludeFlag,
12428             boolean shouldInclLocationSensitiveTransportInfoWithoutIncludeFlag,
12429             boolean shouldInclLocationSensitiveTransportInfoWithIncludeFlag) {
12430         final int myUid = Process.myUid();
12431 
12432         final int expectedOwnerUidWithoutIncludeFlag =
12433                 shouldInclLocationSensitiveOwnerUidWithoutIncludeFlag
12434                         ? myUid : INVALID_UID;
12435         assertEquals(expectedOwnerUidWithoutIncludeFlag, getOwnerUidNetCapsPermission(
12436                 myUid, myUid, false /* includeLocationSensitiveInfo */));
12437 
12438         final int expectedOwnerUidWithIncludeFlag =
12439                 shouldInclLocationSensitiveOwnerUidWithIncludeFlag ? myUid : INVALID_UID;
12440         assertEquals(expectedOwnerUidWithIncludeFlag, getOwnerUidNetCapsPermission(
12441                 myUid, myUid, true /* includeLocationSensitiveInfo */));
12442 
12443         verifyTransportInfoCopyNetCapsPermission(myUid,
12444                 false, /* includeLocationSensitiveInfo */
12445                 shouldInclLocationSensitiveTransportInfoWithoutIncludeFlag);
12446 
12447         verifyTransportInfoCopyNetCapsPermission(myUid,
12448                 true, /* includeLocationSensitiveInfo */
12449                 shouldInclLocationSensitiveTransportInfoWithIncludeFlag);
12450 
12451     }
12452 
12453     private void verifyOwnerUidAndTransportInfoNetCapsPermissionPreS() {
12454         verifyOwnerUidAndTransportInfoNetCapsPermission(
12455                 // Ensure that owner uid is included even if the request asks to remove it (which is
12456                 // the default) since the app has necessary permissions and targetSdk < S.
12457                 true, /* shouldInclLocationSensitiveOwnerUidWithoutIncludeFlag */
12458                 true, /* shouldInclLocationSensitiveOwnerUidWithIncludeFlag */
12459                 // Ensure that location info is removed if the request asks to remove it even if the
12460                 // app has necessary permissions.
12461                 false, /* shouldInclLocationSensitiveTransportInfoWithoutIncludeFlag */
12462                 true /* shouldInclLocationSensitiveTransportInfoWithIncludeFlag */
12463         );
12464     }
12465 
12466     @Test
12467     public void testCreateWithLocationInfoSanitizedWithFineLocationAfterQPreS()
12468             throws Exception {
12469         setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
12470                 Manifest.permission.ACCESS_FINE_LOCATION);
12471 
12472         verifyOwnerUidAndTransportInfoNetCapsPermissionPreS();
12473     }
12474 
12475     @Test
12476     public void testCreateWithLocationInfoSanitizedWithFineLocationPreSWithAndWithoutCallbackFlag()
12477             throws Exception {
12478         setupLocationPermissions(Build.VERSION_CODES.R, true, AppOpsManager.OPSTR_FINE_LOCATION,
12479                 Manifest.permission.ACCESS_FINE_LOCATION);
12480 
12481         verifyOwnerUidAndTransportInfoNetCapsPermissionPreS();
12482     }
12483 
12484     @Test
12485     public void
12486             testCreateWithLocationInfoSanitizedWithFineLocationAfterSWithAndWithoutCallbackFlag()
12487             throws Exception {
12488         setupLocationPermissions(Build.VERSION_CODES.S, true, AppOpsManager.OPSTR_FINE_LOCATION,
12489                 Manifest.permission.ACCESS_FINE_LOCATION);
12490 
12491         verifyOwnerUidAndTransportInfoNetCapsPermission(
12492                 // Ensure that the owner UID is removed if the request asks us to remove it even
12493                 // if the app has necessary permissions since targetSdk >= S.
12494                 false, /* shouldInclLocationSensitiveOwnerUidWithoutIncludeFlag */
12495                 true, /* shouldInclLocationSensitiveOwnerUidWithIncludeFlag */
12496                 // Ensure that location info is removed if the request asks to remove it even if the
12497                 // app has necessary permissions.
12498                 false, /* shouldInclLocationSensitiveTransportInfoWithoutIncludeFlag */
12499                 true /* shouldInclLocationSensitiveTransportInfoWithIncludeFlag */
12500         );
12501     }
12502 
12503     @Test
12504     public void testCreateWithLocationInfoSanitizedWithCoarseLocationPreQ()
12505             throws Exception {
12506         setupLocationPermissions(Build.VERSION_CODES.P, true, AppOpsManager.OPSTR_COARSE_LOCATION,
12507                 Manifest.permission.ACCESS_COARSE_LOCATION);
12508 
12509         verifyOwnerUidAndTransportInfoNetCapsPermissionPreS();
12510     }
12511 
12512     private void verifyOwnerUidAndTransportInfoNetCapsNotIncluded() {
12513         verifyOwnerUidAndTransportInfoNetCapsPermission(
12514                 false, /* shouldInclLocationSensitiveOwnerUidWithoutIncludeFlag */
12515                 false, /* shouldInclLocationSensitiveOwnerUidWithIncludeFlag */
12516                 false, /* shouldInclLocationSensitiveTransportInfoWithoutIncludeFlag */
12517                 false /* shouldInclLocationSensitiveTransportInfoWithIncludeFlag */
12518         );
12519     }
12520 
12521     @Test
12522     public void testCreateWithLocationInfoSanitizedLocationOff() throws Exception {
12523         // Test that even with fine location permission, and UIDs matching, the UID is sanitized.
12524         setupLocationPermissions(Build.VERSION_CODES.Q, false, AppOpsManager.OPSTR_FINE_LOCATION,
12525                 Manifest.permission.ACCESS_FINE_LOCATION);
12526 
12527         verifyOwnerUidAndTransportInfoNetCapsNotIncluded();
12528     }
12529 
12530     @Test
12531     public void testCreateWithLocationInfoSanitizedWrongUid() throws Exception {
12532         // Test that even with fine location permission, not being the owner leads to sanitization.
12533         setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
12534                 Manifest.permission.ACCESS_FINE_LOCATION);
12535 
12536         final int myUid = Process.myUid();
12537         assertEquals(Process.INVALID_UID,
12538                 getOwnerUidNetCapsPermission(myUid + 1, myUid,
12539                         true /* includeLocationSensitiveInfo */));
12540     }
12541 
12542     @Test
12543     public void testCreateWithLocationInfoSanitizedWithCoarseLocationAfterQ()
12544             throws Exception {
12545         // Test that not having fine location permission leads to sanitization.
12546         setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_COARSE_LOCATION,
12547                 Manifest.permission.ACCESS_COARSE_LOCATION);
12548 
12549         verifyOwnerUidAndTransportInfoNetCapsNotIncluded();
12550     }
12551 
12552     @Test
12553     public void testCreateWithLocationInfoSanitizedWithCoarseLocationAfterS()
12554             throws Exception {
12555         // Test that not having fine location permission leads to sanitization.
12556         setupLocationPermissions(Build.VERSION_CODES.S, true, AppOpsManager.OPSTR_COARSE_LOCATION,
12557                 Manifest.permission.ACCESS_COARSE_LOCATION);
12558 
12559         verifyOwnerUidAndTransportInfoNetCapsNotIncluded();
12560     }
12561 
12562     @Test
12563     public void testCreateForCallerWithLocalMacAddressSanitizedWithLocalMacAddressPermission()
12564             throws Exception {
12565         mServiceContext.setPermission(Manifest.permission.LOCAL_MAC_ADDRESS, PERMISSION_GRANTED);
12566 
12567         final TransportInfo transportInfo = mock(TransportInfo.class);
12568         doReturn(REDACT_FOR_ACCESS_FINE_LOCATION | REDACT_FOR_LOCAL_MAC_ADDRESS)
12569                 .when(transportInfo).getApplicableRedactions();
12570         final NetworkCapabilities netCap =
12571                 new NetworkCapabilities().setTransportInfo(transportInfo);
12572 
12573         mService.createWithLocationInfoSanitizedIfNecessaryWhenParceled(
12574                 netCap, false /* includeLocationSensitiveInfoInTransportInfo */,
12575                 Process.myPid(), Process.myUid(),
12576                 mContext.getPackageName(), getAttributionTag());
12577         // don't redact MAC_ADDRESS fields, only location sensitive fields.
12578         verify(transportInfo).makeCopy(REDACT_FOR_ACCESS_FINE_LOCATION);
12579     }
12580 
12581     @Test
12582     public void testCreateForCallerWithLocalMacAddressSanitizedWithoutLocalMacAddressPermission()
12583             throws Exception {
12584         mServiceContext.setPermission(Manifest.permission.LOCAL_MAC_ADDRESS, PERMISSION_DENIED);
12585 
12586         final TransportInfo transportInfo = mock(TransportInfo.class);
12587         doReturn(REDACT_FOR_ACCESS_FINE_LOCATION | REDACT_FOR_LOCAL_MAC_ADDRESS)
12588                 .when(transportInfo).getApplicableRedactions();
12589         final NetworkCapabilities netCap =
12590                 new NetworkCapabilities().setTransportInfo(transportInfo);
12591 
12592         mService.createWithLocationInfoSanitizedIfNecessaryWhenParceled(
12593                 netCap, false /* includeLocationSensitiveInfoInTransportInfo */,
12594                 Process.myPid(), Process.myUid(),
12595                 mContext.getPackageName(), getAttributionTag());
12596         // redact both MAC_ADDRESS & location sensitive fields.
12597         verify(transportInfo).makeCopy(REDACT_FOR_ACCESS_FINE_LOCATION
12598                 | REDACT_FOR_LOCAL_MAC_ADDRESS);
12599     }
12600 
12601     @Test
12602     public void testCreateForCallerWithLocalMacAddressSanitizedWithSettingsPermission()
12603             throws Exception {
12604         mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_GRANTED);
12605 
12606         final TransportInfo transportInfo = mock(TransportInfo.class);
12607         doReturn(REDACT_FOR_ACCESS_FINE_LOCATION | REDACT_FOR_NETWORK_SETTINGS)
12608                 .when(transportInfo).getApplicableRedactions();
12609         final NetworkCapabilities netCap =
12610                 new NetworkCapabilities().setTransportInfo(transportInfo);
12611 
12612         mService.createWithLocationInfoSanitizedIfNecessaryWhenParceled(
12613                 netCap, false /* includeLocationSensitiveInfoInTransportInfo */,
12614                 Process.myPid(), Process.myUid(),
12615                 mContext.getPackageName(), getAttributionTag());
12616         // don't redact NETWORK_SETTINGS fields, only location sensitive fields.
12617         verify(transportInfo).makeCopy(REDACT_FOR_ACCESS_FINE_LOCATION);
12618     }
12619 
12620     @Test
12621     public void testCreateForCallerWithLocalMacAddressSanitizedWithoutSettingsPermission()
12622             throws Exception {
12623         mServiceContext.setPermission(Manifest.permission.LOCAL_MAC_ADDRESS, PERMISSION_DENIED);
12624 
12625         final TransportInfo transportInfo = mock(TransportInfo.class);
12626         doReturn(REDACT_FOR_ACCESS_FINE_LOCATION | REDACT_FOR_NETWORK_SETTINGS)
12627                 .when(transportInfo).getApplicableRedactions();
12628         final NetworkCapabilities netCap =
12629                 new NetworkCapabilities().setTransportInfo(transportInfo);
12630 
12631         mService.createWithLocationInfoSanitizedIfNecessaryWhenParceled(
12632                 netCap, false /* includeLocationSensitiveInfoInTransportInfo */,
12633                 Process.myPid(), Process.myUid(),
12634                 mContext.getPackageName(), getAttributionTag());
12635         // redact both NETWORK_SETTINGS & location sensitive fields.
12636         verify(transportInfo).makeCopy(
12637                 REDACT_FOR_ACCESS_FINE_LOCATION | REDACT_FOR_NETWORK_SETTINGS);
12638     }
12639 
12640     /**
12641      * Test TransportInfo to verify redaction mechanism.
12642      */
12643     private static class TestTransportInfo implements TransportInfo {
12644         public final boolean locationRedacted;
12645         public final boolean localMacAddressRedacted;
12646         public final boolean settingsRedacted;
12647 
12648         TestTransportInfo() {
12649             locationRedacted = false;
12650             localMacAddressRedacted = false;
12651             settingsRedacted = false;
12652         }
12653 
12654         TestTransportInfo(boolean locationRedacted, boolean localMacAddressRedacted,
12655                 boolean settingsRedacted) {
12656             this.locationRedacted = locationRedacted;
12657             this.localMacAddressRedacted =
12658                     localMacAddressRedacted;
12659             this.settingsRedacted = settingsRedacted;
12660         }
12661 
12662         @Override
12663         public TransportInfo makeCopy(@NetworkCapabilities.RedactionType long redactions) {
12664             return new TestTransportInfo(
12665                     locationRedacted | (redactions & REDACT_FOR_ACCESS_FINE_LOCATION) != 0,
12666                     localMacAddressRedacted | (redactions & REDACT_FOR_LOCAL_MAC_ADDRESS) != 0,
12667                     settingsRedacted | (redactions & REDACT_FOR_NETWORK_SETTINGS) != 0
12668             );
12669         }
12670 
12671         @Override
12672         public @NetworkCapabilities.RedactionType long getApplicableRedactions() {
12673             return REDACT_FOR_ACCESS_FINE_LOCATION | REDACT_FOR_LOCAL_MAC_ADDRESS
12674                     | REDACT_FOR_NETWORK_SETTINGS;
12675         }
12676 
12677         @Override
12678         public boolean equals(Object other) {
12679             if (!(other instanceof TestTransportInfo)) return false;
12680             TestTransportInfo that = (TestTransportInfo) other;
12681             return that.locationRedacted == this.locationRedacted
12682                     && that.localMacAddressRedacted == this.localMacAddressRedacted
12683                     && that.settingsRedacted == this.settingsRedacted;
12684         }
12685 
12686         @Override
12687         public int hashCode() {
12688             return Objects.hash(locationRedacted, localMacAddressRedacted, settingsRedacted);
12689         }
12690 
12691         @Override
12692         public String toString() {
12693             return String.format(
12694                     "TestTransportInfo{locationRedacted=%s macRedacted=%s settingsRedacted=%s}",
12695                     locationRedacted, localMacAddressRedacted, settingsRedacted);
12696         }
12697     }
12698 
12699     private TestTransportInfo getTestTransportInfo(NetworkCapabilities nc) {
12700         return (TestTransportInfo) nc.getTransportInfo();
12701     }
12702 
12703     private TestTransportInfo getTestTransportInfo(TestNetworkAgentWrapper n) {
12704         final NetworkCapabilities nc = mCm.getNetworkCapabilities(n.getNetwork());
12705         assertNotNull(nc);
12706         return getTestTransportInfo(nc);
12707     }
12708 
12709 
12710     private void verifyNetworkCallbackLocationDataInclusionUsingTransportInfoAndOwnerUidInNetCaps(
12711             @NonNull TestNetworkCallback wifiNetworkCallback, int actualOwnerUid,
12712             @NonNull TransportInfo actualTransportInfo, int expectedOwnerUid,
12713             @NonNull TransportInfo expectedTransportInfo) throws Exception {
12714         doReturn(Build.VERSION_CODES.S).when(mPackageManager).getTargetSdkVersion(anyString());
12715         final NetworkCapabilities ncTemplate =
12716                 new NetworkCapabilities()
12717                         .addTransportType(TRANSPORT_WIFI)
12718                         .setOwnerUid(actualOwnerUid);
12719 
12720         final NetworkRequest wifiRequest = new NetworkRequest.Builder()
12721                 .addTransportType(TRANSPORT_WIFI).build();
12722         mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
12723 
12724         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, new LinkProperties(),
12725                 ncTemplate);
12726         mWiFiAgent.connect(false);
12727 
12728         wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
12729 
12730         // Send network capabilities update with TransportInfo to trigger capabilities changed
12731         // callback.
12732         mWiFiAgent.setNetworkCapabilities(ncTemplate.setTransportInfo(actualTransportInfo), true);
12733 
12734         wifiNetworkCallback.expectCaps(mWiFiAgent,
12735                 c -> Objects.equals(expectedOwnerUid, c.getOwnerUid())
12736                         && Objects.equals(expectedTransportInfo, c.getTransportInfo()));
12737     }
12738 
12739     @Test
12740     public void testVerifyLocationDataIsNotIncludedWhenInclFlagNotSet() throws Exception {
12741         final TestNetworkCallback wifiNetworkCallack = new TestNetworkCallback();
12742         final int ownerUid = Process.myUid();
12743         final TransportInfo transportInfo = new TestTransportInfo();
12744         // Even though the test uid holds privileged permissions, mask location fields since
12745         // the callback did not explicitly opt-in to get location data.
12746         final TransportInfo sanitizedTransportInfo = new TestTransportInfo(
12747                 true, /* locationRedacted */
12748                 true, /* localMacAddressRedacted */
12749                 true /* settingsRedacted */
12750         );
12751         // Should not expect location data since the callback does not set the flag for including
12752         // location data.
12753         verifyNetworkCallbackLocationDataInclusionUsingTransportInfoAndOwnerUidInNetCaps(
12754                 wifiNetworkCallack, ownerUid, transportInfo, INVALID_UID, sanitizedTransportInfo);
12755     }
12756 
12757     @Test
12758     public void testTransportInfoRedactionInSynchronousCalls() throws Exception {
12759         final NetworkCapabilities ncTemplate = new NetworkCapabilities()
12760                 .addTransportType(TRANSPORT_WIFI)
12761                 .setTransportInfo(new TestTransportInfo());
12762 
12763         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, new LinkProperties(), ncTemplate);
12764         mWiFiAgent.connect(true /* validated; waits for callback */);
12765 
12766         // NETWORK_SETTINGS redaction is controlled by the NETWORK_SETTINGS permission
12767         assertTrue(getTestTransportInfo(mWiFiAgent).settingsRedacted);
12768         withPermission(NETWORK_SETTINGS, () -> {
12769             assertFalse(getTestTransportInfo(mWiFiAgent).settingsRedacted);
12770         });
12771         assertTrue(getTestTransportInfo(mWiFiAgent).settingsRedacted);
12772 
12773         // LOCAL_MAC_ADDRESS redaction is controlled by the LOCAL_MAC_ADDRESS permission
12774         assertTrue(getTestTransportInfo(mWiFiAgent).localMacAddressRedacted);
12775         withPermission(LOCAL_MAC_ADDRESS, () -> {
12776             assertFalse(getTestTransportInfo(mWiFiAgent).localMacAddressRedacted);
12777         });
12778         assertTrue(getTestTransportInfo(mWiFiAgent).localMacAddressRedacted);
12779 
12780         // Synchronous getNetworkCapabilities calls never return unredacted location-sensitive
12781         // information.
12782         assertTrue(getTestTransportInfo(mWiFiAgent).locationRedacted);
12783         setupLocationPermissions(Build.VERSION_CODES.S, true, AppOpsManager.OPSTR_FINE_LOCATION,
12784                 Manifest.permission.ACCESS_FINE_LOCATION);
12785         assertTrue(getTestTransportInfo(mWiFiAgent).locationRedacted);
12786         denyAllLocationPrivilegedPermissions();
12787         assertTrue(getTestTransportInfo(mWiFiAgent).locationRedacted);
12788     }
12789 
12790     private void setupConnectionOwnerUid(int vpnOwnerUid, @VpnManager.VpnType int vpnType)
12791             throws Exception {
12792         final Set<UidRange> vpnRange = Collections.singleton(PRIMARY_UIDRANGE);
12793         mMockVpn.setVpnType(vpnType);
12794         mMockVpn.establish(new LinkProperties(), vpnOwnerUid, vpnRange);
12795         assertVpnUidRangesUpdated(true, vpnRange, vpnOwnerUid);
12796 
12797         mDeps.setConnectionOwnerUid(42);
12798     }
12799 
12800     private void setupConnectionOwnerUidAsVpnApp(int vpnOwnerUid, @VpnManager.VpnType int vpnType)
12801             throws Exception {
12802         setupConnectionOwnerUid(vpnOwnerUid, vpnType);
12803 
12804         // Test as VPN app
12805         mServiceContext.setPermission(NETWORK_STACK, PERMISSION_DENIED);
12806         mServiceContext.setPermission(
12807                 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, PERMISSION_DENIED);
12808     }
12809 
12810     private ConnectionInfo getTestConnectionInfo() throws Exception {
12811         return new ConnectionInfo(
12812                 IPPROTO_TCP,
12813                 new InetSocketAddress(InetAddresses.parseNumericAddress("1.2.3.4"), 1234),
12814                 new InetSocketAddress(InetAddresses.parseNumericAddress("2.3.4.5"), 2345));
12815     }
12816 
12817     @Test
12818     public void testGetConnectionOwnerUidPlatformVpn() throws Exception {
12819         final int myUid = Process.myUid();
12820         setupConnectionOwnerUidAsVpnApp(myUid, VpnManager.TYPE_VPN_PLATFORM);
12821 
12822         assertEquals(INVALID_UID, mService.getConnectionOwnerUid(getTestConnectionInfo()));
12823     }
12824 
12825     @Test
12826     public void testGetConnectionOwnerUidVpnServiceWrongUser() throws Exception {
12827         final int myUid = Process.myUid();
12828         setupConnectionOwnerUidAsVpnApp(myUid + 1, VpnManager.TYPE_VPN_SERVICE);
12829 
12830         assertEquals(INVALID_UID, mService.getConnectionOwnerUid(getTestConnectionInfo()));
12831     }
12832 
12833     @Test
12834     public void testGetConnectionOwnerUidVpnServiceDoesNotThrow() throws Exception {
12835         final int myUid = Process.myUid();
12836         setupConnectionOwnerUidAsVpnApp(myUid, VpnManager.TYPE_VPN_SERVICE);
12837 
12838         assertEquals(42, mService.getConnectionOwnerUid(getTestConnectionInfo()));
12839     }
12840 
12841     @Test
12842     public void testGetConnectionOwnerUidVpnServiceNetworkStackDoesNotThrow() throws Exception {
12843         final int myUid = Process.myUid();
12844         setupConnectionOwnerUid(myUid, VpnManager.TYPE_VPN_SERVICE);
12845         mServiceContext.setPermission(NETWORK_STACK, PERMISSION_GRANTED);
12846 
12847         assertEquals(42, mService.getConnectionOwnerUid(getTestConnectionInfo()));
12848     }
12849 
12850     @Test
12851     public void testGetConnectionOwnerUidVpnServiceMainlineNetworkStackDoesNotThrow()
12852             throws Exception {
12853         final int myUid = Process.myUid();
12854         setupConnectionOwnerUid(myUid, VpnManager.TYPE_VPN_SERVICE);
12855         mServiceContext.setPermission(
12856                 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, PERMISSION_GRANTED);
12857 
12858         assertEquals(42, mService.getConnectionOwnerUid(getTestConnectionInfo()));
12859     }
12860 
12861     private static PackageInfo buildPackageInfo(boolean hasSystemPermission, int uid) {
12862         final PackageInfo packageInfo = new PackageInfo();
12863         if (hasSystemPermission) {
12864             packageInfo.requestedPermissions = new String[] {
12865                     CHANGE_NETWORK_STATE, CONNECTIVITY_USE_RESTRICTED_NETWORKS };
12866             packageInfo.requestedPermissionsFlags = new int[] {
12867                     REQUESTED_PERMISSION_GRANTED, REQUESTED_PERMISSION_GRANTED };
12868         } else {
12869             packageInfo.requestedPermissions = new String[0];
12870         }
12871         packageInfo.applicationInfo = new ApplicationInfo();
12872         packageInfo.applicationInfo.privateFlags = 0;
12873         packageInfo.applicationInfo.uid = UserHandle.getUid(UserHandle.USER_SYSTEM,
12874                 UserHandle.getAppId(uid));
12875         return packageInfo;
12876     }
12877 
12878     @Test
12879     public void testRegisterConnectivityDiagnosticsCallbackInvalidRequest() throws Exception {
12880         final NetworkRequest request =
12881                 new NetworkRequest(
12882                         new NetworkCapabilities(), TYPE_ETHERNET, 0, NetworkRequest.Type.NONE);
12883         try {
12884             mService.registerConnectivityDiagnosticsCallback(
12885                     mConnectivityDiagnosticsCallback, request, mContext.getPackageName());
12886             fail("registerConnectivityDiagnosticsCallback should throw on invalid NetworkRequest");
12887         } catch (IllegalArgumentException expected) {
12888         }
12889     }
12890 
12891     private void assertRouteInfoParcelMatches(RouteInfo route, RouteInfoParcel parcel) {
12892         assertEquals(route.getDestination().toString(), parcel.destination);
12893         assertEquals(route.getInterface(), parcel.ifName);
12894         assertEquals(route.getMtu(), parcel.mtu);
12895 
12896         switch (route.getType()) {
12897             case RouteInfo.RTN_UNICAST:
12898                 if (route.hasGateway()) {
12899                     assertEquals(route.getGateway().getHostAddress(), parcel.nextHop);
12900                 } else {
12901                     assertEquals(INetd.NEXTHOP_NONE, parcel.nextHop);
12902                 }
12903                 break;
12904             case RouteInfo.RTN_UNREACHABLE:
12905                 assertEquals(INetd.NEXTHOP_UNREACHABLE, parcel.nextHop);
12906                 break;
12907             case RouteInfo.RTN_THROW:
12908                 assertEquals(INetd.NEXTHOP_THROW, parcel.nextHop);
12909                 break;
12910             default:
12911                 assertEquals(INetd.NEXTHOP_NONE, parcel.nextHop);
12912                 break;
12913         }
12914     }
12915 
12916     private void assertRoutesAdded(int netId, RouteInfo... routes) throws Exception {
12917         // TODO: add @JavaDerive(equals=true) to RouteInfoParcel, use eq() directly, and delete
12918         // assertRouteInfoParcelMatches above.
12919         ArgumentCaptor<RouteInfoParcel> captor = ArgumentCaptor.forClass(RouteInfoParcel.class);
12920         verify(mMockNetd, times(routes.length)).networkAddRouteParcel(eq(netId), captor.capture());
12921         for (int i = 0; i < routes.length; i++) {
12922             assertRouteInfoParcelMatches(routes[i], captor.getAllValues().get(i));
12923         }
12924     }
12925 
12926     private void assertRoutesRemoved(int netId, RouteInfo... routes) throws Exception {
12927         ArgumentCaptor<RouteInfoParcel> captor = ArgumentCaptor.forClass(RouteInfoParcel.class);
12928         verify(mMockNetd, times(routes.length)).networkRemoveRouteParcel(eq(netId),
12929                 captor.capture());
12930         for (int i = 0; i < routes.length; i++) {
12931             assertRouteInfoParcelMatches(routes[i], captor.getAllValues().get(i));
12932         }
12933     }
12934 
12935     @Test
12936     public void testRegisterUnregisterConnectivityDiagnosticsCallback() throws Exception {
12937         final NetworkRequest wifiRequest =
12938                 new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI).build();
12939         doReturn(mIBinder).when(mConnectivityDiagnosticsCallback).asBinder();
12940 
12941         mService.registerConnectivityDiagnosticsCallback(
12942                 mConnectivityDiagnosticsCallback, wifiRequest, mContext.getPackageName());
12943 
12944         // Block until all other events are done processing.
12945         HandlerUtils.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
12946 
12947         verify(mIBinder).linkToDeath(any(ConnectivityDiagnosticsCallbackInfo.class), anyInt());
12948         verify(mConnectivityDiagnosticsCallback).asBinder();
12949         assertTrue(mService.mConnectivityDiagnosticsCallbacks.containsKey(mIBinder));
12950 
12951         mService.unregisterConnectivityDiagnosticsCallback(mConnectivityDiagnosticsCallback);
12952         verify(mIBinder, timeout(TIMEOUT_MS))
12953                 .unlinkToDeath(any(ConnectivityDiagnosticsCallbackInfo.class), anyInt());
12954         assertFalse(mService.mConnectivityDiagnosticsCallbacks.containsKey(mIBinder));
12955         verify(mConnectivityDiagnosticsCallback, atLeastOnce()).asBinder();
12956     }
12957 
12958     @Test
12959     public void testRegisterDuplicateConnectivityDiagnosticsCallback() throws Exception {
12960         final NetworkRequest wifiRequest =
12961                 new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI).build();
12962         doReturn(mIBinder).when(mConnectivityDiagnosticsCallback).asBinder();
12963 
12964         mService.registerConnectivityDiagnosticsCallback(
12965                 mConnectivityDiagnosticsCallback, wifiRequest, mContext.getPackageName());
12966 
12967         // Block until all other events are done processing.
12968         HandlerUtils.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
12969 
12970         verify(mIBinder).linkToDeath(any(ConnectivityDiagnosticsCallbackInfo.class), anyInt());
12971         verify(mConnectivityDiagnosticsCallback).asBinder();
12972         assertTrue(mService.mConnectivityDiagnosticsCallbacks.containsKey(mIBinder));
12973 
12974         // Register the same callback again
12975         mService.registerConnectivityDiagnosticsCallback(
12976                 mConnectivityDiagnosticsCallback, wifiRequest, mContext.getPackageName());
12977 
12978         // Block until all other events are done processing.
12979         HandlerUtils.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
12980 
12981         assertTrue(mService.mConnectivityDiagnosticsCallbacks.containsKey(mIBinder));
12982     }
12983 
12984     @Test(expected = NullPointerException.class)
12985     public void testRegisterConnectivityDiagnosticsCallbackNullCallback() {
12986         mService.registerConnectivityDiagnosticsCallback(
12987                 null /* callback */,
12988                 new NetworkRequest.Builder().build(),
12989                 mContext.getPackageName());
12990     }
12991 
12992     @Test(expected = NullPointerException.class)
12993     public void testRegisterConnectivityDiagnosticsCallbackNullNetworkRequest() {
12994         mService.registerConnectivityDiagnosticsCallback(
12995                 mConnectivityDiagnosticsCallback,
12996                 null /* request */,
12997                 mContext.getPackageName());
12998     }
12999 
13000     @Test(expected = NullPointerException.class)
13001     public void testRegisterConnectivityDiagnosticsCallbackNullPackageName() {
13002         mService.registerConnectivityDiagnosticsCallback(
13003                 mConnectivityDiagnosticsCallback,
13004                 new NetworkRequest.Builder().build(),
13005                 null /* callingPackageName */);
13006     }
13007 
13008     @Test(expected = NullPointerException.class)
13009     public void testUnregisterConnectivityDiagnosticsCallbackNullPackageName() {
13010         mService.unregisterConnectivityDiagnosticsCallback(null /* callback */);
13011     }
13012 
13013     public NetworkAgentInfo fakeMobileNai(NetworkCapabilities nc) {
13014         final NetworkCapabilities cellNc = new NetworkCapabilities.Builder(nc)
13015                 .addTransportType(TRANSPORT_CELLULAR).build();
13016         final NetworkInfo info = new NetworkInfo(TYPE_MOBILE, TelephonyManager.NETWORK_TYPE_LTE,
13017                 ConnectivityManager.getNetworkTypeName(TYPE_MOBILE),
13018                 TelephonyManager.getNetworkTypeName(TelephonyManager.NETWORK_TYPE_LTE));
13019         return fakeNai(cellNc, info);
13020     }
13021 
13022     private NetworkAgentInfo fakeWifiNai(NetworkCapabilities nc) {
13023         final NetworkCapabilities wifiNc = new NetworkCapabilities.Builder(nc)
13024                 .addTransportType(TRANSPORT_WIFI).build();
13025         final NetworkInfo info = new NetworkInfo(TYPE_WIFI, 0 /* subtype */,
13026                 ConnectivityManager.getNetworkTypeName(TYPE_WIFI), "" /* subtypeName */);
13027         return fakeNai(wifiNc, info);
13028     }
13029 
13030     private NetworkAgentInfo fakeVpnNai(NetworkCapabilities nc) {
13031         final NetworkCapabilities vpnNc = new NetworkCapabilities.Builder(nc)
13032                 .addTransportType(TRANSPORT_VPN).build();
13033         final NetworkInfo info = new NetworkInfo(TYPE_VPN, 0 /* subtype */,
13034                 ConnectivityManager.getNetworkTypeName(TYPE_VPN), "" /* subtypeName */);
13035         return fakeNai(vpnNc, info);
13036     }
13037 
13038     private NetworkAgentInfo fakeNai(NetworkCapabilities nc, NetworkInfo networkInfo) {
13039         return new NetworkAgentInfo(null, new Network(NET_ID), networkInfo, new LinkProperties(),
13040                 nc, null /* localNetworkConfig */,
13041                 new NetworkScore.Builder().setLegacyInt(0).build(),
13042                 mServiceContext, null, new NetworkAgentConfig(), mService, null, null, 0,
13043                 INVALID_UID, TEST_LINGER_DELAY_MS, mQosCallbackTracker,
13044                 new ConnectivityService.Dependencies());
13045     }
13046 
13047     @Test
13048     public void testCheckConnectivityDiagnosticsPermissionsNetworkStack() throws Exception {
13049         final NetworkAgentInfo naiWithoutUid = fakeMobileNai(new NetworkCapabilities());
13050 
13051         mServiceContext.setPermission(NETWORK_STACK, PERMISSION_GRANTED);
13052         assertTrue(
13053                 "NetworkStack permission not applied",
13054                 mService.hasConnectivityDiagnosticsPermissions(
13055                         Process.myPid(), Process.myUid(), naiWithoutUid,
13056                         mContext.getOpPackageName()));
13057     }
13058 
13059     @Test
13060     public void testCheckConnectivityDiagnosticsPermissionsSysUi() throws Exception {
13061         final NetworkAgentInfo naiWithoutUid = fakeMobileNai(new NetworkCapabilities());
13062 
13063         mServiceContext.setPermission(STATUS_BAR_SERVICE, PERMISSION_GRANTED);
13064         assertTrue(
13065                 "SysUi permission (STATUS_BAR_SERVICE) not applied",
13066                 mService.hasConnectivityDiagnosticsPermissions(
13067                         Process.myPid(), Process.myUid(), naiWithoutUid,
13068                         mContext.getOpPackageName()));
13069     }
13070 
13071     @Test
13072     public void testCheckConnectivityDiagnosticsPermissionsWrongUidPackageName() throws Exception {
13073         final int wrongUid = Process.myUid() + 1;
13074 
13075         final NetworkCapabilities nc = new NetworkCapabilities();
13076         nc.setAdministratorUids(new int[] {wrongUid});
13077         final NetworkAgentInfo naiWithUid = fakeWifiNai(nc);
13078 
13079         mServiceContext.setPermission(NETWORK_STACK, PERMISSION_DENIED);
13080 
13081         assertFalse(
13082                 "Mismatched uid/package name should not pass the location permission check",
13083                 mService.hasConnectivityDiagnosticsPermissions(
13084                         Process.myPid() + 1, wrongUid, naiWithUid, mContext.getOpPackageName()));
13085     }
13086 
13087     private void verifyConnectivityDiagnosticsPermissionsWithNetworkAgentInfo(
13088             NetworkAgentInfo info, boolean expectPermission) {
13089         mServiceContext.setPermission(NETWORK_STACK, PERMISSION_DENIED);
13090 
13091         assertEquals(
13092                 "Unexpected ConnDiags permission",
13093                 expectPermission,
13094                 mService.hasConnectivityDiagnosticsPermissions(
13095                         Process.myPid(), Process.myUid(), info, mContext.getOpPackageName()));
13096     }
13097 
13098     @Test
13099     public void testCheckConnectivityDiagnosticsPermissionsCellularNoLocationPermission()
13100             throws Exception {
13101         final NetworkCapabilities nc = new NetworkCapabilities();
13102         nc.setAdministratorUids(new int[] {Process.myUid()});
13103         final NetworkAgentInfo naiWithUid = fakeMobileNai(nc);
13104 
13105         verifyConnectivityDiagnosticsPermissionsWithNetworkAgentInfo(naiWithUid,
13106                 true /* expectPermission */);
13107     }
13108 
13109     @Test
13110     public void testCheckConnectivityDiagnosticsPermissionsWifiNoLocationPermission()
13111             throws Exception {
13112         final NetworkCapabilities nc = new NetworkCapabilities();
13113         nc.setAdministratorUids(new int[] {Process.myUid()});
13114         final NetworkAgentInfo naiWithUid = fakeWifiNai(nc);
13115 
13116         verifyConnectivityDiagnosticsPermissionsWithNetworkAgentInfo(naiWithUid,
13117                 false /* expectPermission */);
13118     }
13119 
13120     @Test
13121     public void testCheckConnectivityDiagnosticsPermissionsActiveVpn() throws Exception {
13122         final NetworkAgentInfo naiWithoutUid = fakeMobileNai(new NetworkCapabilities());
13123 
13124         mMockVpn.establishForMyUid();
13125         assertUidRangesUpdatedForMyUid(true);
13126 
13127         // Wait for networks to connect and broadcasts to be sent before removing permissions.
13128         waitForIdle();
13129         setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
13130                 Manifest.permission.ACCESS_FINE_LOCATION);
13131 
13132         assertTrue(mMockVpn.setUnderlyingNetworks(new Network[] {naiWithoutUid.network}));
13133         waitForIdle();
13134         assertTrue(
13135                 "Active VPN permission not applied",
13136                 mService.hasConnectivityDiagnosticsPermissions(
13137                         Process.myPid(), Process.myUid(), naiWithoutUid,
13138                         mContext.getOpPackageName()));
13139 
13140         assertTrue(mMockVpn.setUnderlyingNetworks(null));
13141         waitForIdle();
13142         assertFalse(
13143                 "VPN shouldn't receive callback on non-underlying network",
13144                 mService.hasConnectivityDiagnosticsPermissions(
13145                         Process.myPid(), Process.myUid(), naiWithoutUid,
13146                         mContext.getOpPackageName()));
13147     }
13148 
13149     @Test
13150     public void testCheckConnectivityDiagnosticsPermissionsNetworkAdministrator() throws Exception {
13151         final NetworkCapabilities nc = new NetworkCapabilities();
13152         nc.setAdministratorUids(new int[] {Process.myUid()});
13153         final NetworkAgentInfo naiWithUid = fakeMobileNai(nc);
13154 
13155         setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
13156                 Manifest.permission.ACCESS_FINE_LOCATION);
13157         mServiceContext.setPermission(NETWORK_STACK, PERMISSION_DENIED);
13158 
13159         assertTrue(
13160                 "NetworkCapabilities administrator uid permission not applied",
13161                 mService.hasConnectivityDiagnosticsPermissions(
13162                         Process.myPid(), Process.myUid(), naiWithUid, mContext.getOpPackageName()));
13163     }
13164 
13165     @Test
13166     public void testCheckConnectivityDiagnosticsPermissionsFails() throws Exception {
13167         final NetworkCapabilities nc = new NetworkCapabilities();
13168         nc.setOwnerUid(Process.myUid());
13169         nc.setAdministratorUids(new int[] {Process.myUid()});
13170         final NetworkAgentInfo naiWithUid = fakeMobileNai(nc);
13171 
13172         setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
13173                 Manifest.permission.ACCESS_FINE_LOCATION);
13174         mServiceContext.setPermission(NETWORK_STACK, PERMISSION_DENIED);
13175 
13176         // Use wrong pid and uid
13177         assertFalse(
13178                 "Permissions allowed when they shouldn't be granted",
13179                 mService.hasConnectivityDiagnosticsPermissions(
13180                         Process.myPid() + 1, Process.myUid() + 1, naiWithUid,
13181                         mContext.getOpPackageName()));
13182     }
13183 
13184     @Test
13185     public void testUnderlyingNetworksWillBeSetInNetworkAgentInfoConstructor() throws Exception {
13186         assumeTrue(mDeps.isAtLeastT());
13187         final Network network1 = new Network(100);
13188         final Network network2 = new Network(101);
13189         final List<Network> underlyingNetworks = new ArrayList<>();
13190         final NetworkCapabilities ncWithEmptyUnderlyingNetworks = new NetworkCapabilities.Builder()
13191                 .setUnderlyingNetworks(underlyingNetworks)
13192                 .build();
13193         final NetworkAgentInfo vpnNaiWithEmptyUnderlyingNetworks =
13194                 fakeVpnNai(ncWithEmptyUnderlyingNetworks);
13195         assertEquals(underlyingNetworks,
13196                 Arrays.asList(vpnNaiWithEmptyUnderlyingNetworks.declaredUnderlyingNetworks));
13197 
13198         underlyingNetworks.add(network1);
13199         underlyingNetworks.add(network2);
13200         final NetworkCapabilities ncWithUnderlyingNetworks = new NetworkCapabilities.Builder()
13201                 .setUnderlyingNetworks(underlyingNetworks)
13202                 .build();
13203         final NetworkAgentInfo vpnNaiWithUnderlyingNetwokrs = fakeVpnNai(ncWithUnderlyingNetworks);
13204         assertEquals(underlyingNetworks,
13205                 Arrays.asList(vpnNaiWithUnderlyingNetwokrs.declaredUnderlyingNetworks));
13206 
13207         final NetworkCapabilities ncWithoutUnderlyingNetworks = new NetworkCapabilities.Builder()
13208                 .build();
13209         final NetworkAgentInfo vpnNaiWithoutUnderlyingNetwokrs =
13210                 fakeVpnNai(ncWithoutUnderlyingNetworks);
13211         assertNull(vpnNaiWithoutUnderlyingNetwokrs.declaredUnderlyingNetworks);
13212     }
13213 
13214     @Test
13215     public void testRegisterConnectivityDiagnosticsCallbackCallsOnConnectivityReport()
13216             throws Exception {
13217         // Set up the Network, which leads to a ConnectivityReport being cached for the network.
13218         final TestNetworkCallback callback = new TestNetworkCallback();
13219         mCm.registerDefaultNetworkCallback(callback);
13220         final LinkProperties linkProperties = new LinkProperties();
13221         linkProperties.setInterfaceName(INTERFACE_NAME);
13222         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, linkProperties);
13223         mCellAgent.connect(true);
13224         callback.expectAvailableThenValidatedCallbacks(mCellAgent);
13225         callback.assertNoCallback();
13226 
13227         final NetworkRequest request = new NetworkRequest.Builder().build();
13228         doReturn(mIBinder).when(mConnectivityDiagnosticsCallback).asBinder();
13229 
13230         mServiceContext.setPermission(NETWORK_STACK, PERMISSION_GRANTED);
13231 
13232         mService.registerConnectivityDiagnosticsCallback(
13233                 mConnectivityDiagnosticsCallback, request, mContext.getPackageName());
13234 
13235         verify(mConnectivityDiagnosticsCallback, timeout(TIMEOUT_MS))
13236                 .onConnectivityReportAvailable(argThat(report -> {
13237                     return INTERFACE_NAME.equals(report.getLinkProperties().getInterfaceName())
13238                             && report.getNetworkCapabilities().hasTransport(TRANSPORT_CELLULAR);
13239                 }));
13240     }
13241 
13242     private void setUpConnectivityDiagnosticsCallback() throws Exception {
13243         final NetworkRequest request = new NetworkRequest.Builder().build();
13244         doReturn(mIBinder).when(mConnectivityDiagnosticsCallback).asBinder();
13245 
13246         mServiceContext.setPermission(NETWORK_STACK, PERMISSION_GRANTED);
13247 
13248         mService.registerConnectivityDiagnosticsCallback(
13249                 mConnectivityDiagnosticsCallback, request, mContext.getPackageName());
13250 
13251         // Block until all other events are done processing.
13252         HandlerUtils.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
13253 
13254         // Connect the cell agent verify that it notifies TestNetworkCallback that it is available
13255         final TestNetworkCallback callback = new TestNetworkCallback();
13256         mCm.registerDefaultNetworkCallback(callback);
13257 
13258         final NetworkCapabilities ncTemplate = new NetworkCapabilities()
13259                 .addTransportType(TRANSPORT_CELLULAR)
13260                 .setTransportInfo(new TestTransportInfo());
13261         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, new LinkProperties(),
13262                 ncTemplate);
13263         mCellAgent.connect(true);
13264         callback.expectAvailableThenValidatedCallbacks(mCellAgent);
13265         callback.assertNoCallback();
13266 
13267         // Make sure a report is sent and that the caps are suitably redacted.
13268         verify(mConnectivityDiagnosticsCallback, timeout(TIMEOUT_MS))
13269                 .onConnectivityReportAvailable(argThat(report ->
13270                         areConnDiagCapsRedacted(report.getNetworkCapabilities())));
13271         reset(mConnectivityDiagnosticsCallback);
13272     }
13273 
13274     private boolean areConnDiagCapsRedacted(NetworkCapabilities nc) {
13275         TestTransportInfo ti = getTestTransportInfo(nc);
13276         return nc.getUids() == null
13277                 && nc.getAdministratorUids().length == 0
13278                 && nc.getOwnerUid() == Process.INVALID_UID
13279                 && ti.locationRedacted
13280                 && ti.localMacAddressRedacted
13281                 && ti.settingsRedacted;
13282     }
13283 
13284     @Test
13285     public void testConnectivityDiagnosticsCallbackOnDataStallSuspected() throws Exception {
13286         setUpConnectivityDiagnosticsCallback();
13287 
13288         // Trigger notifyDataStallSuspected() on the INetworkMonitorCallbacks instance in the
13289         // cellular network agent
13290         mCellAgent.notifyDataStallSuspected();
13291 
13292         // Verify onDataStallSuspected fired
13293         verify(mConnectivityDiagnosticsCallback, timeout(TIMEOUT_MS)).onDataStallSuspected(
13294                 argThat(report -> areConnDiagCapsRedacted(report.getNetworkCapabilities())));
13295     }
13296 
13297     @Test
13298     public void testConnectivityDiagnosticsCallbackOnConnectivityReported() throws Exception {
13299         setUpConnectivityDiagnosticsCallback();
13300 
13301         final Network n = mCellAgent.getNetwork();
13302         final boolean hasConnectivity = true;
13303         mService.reportNetworkConnectivity(n, hasConnectivity);
13304 
13305         // Verify onNetworkConnectivityReported fired
13306         verify(mConnectivityDiagnosticsCallback, timeout(TIMEOUT_MS))
13307                 .onNetworkConnectivityReported(eq(n), eq(hasConnectivity));
13308         verify(mConnectivityDiagnosticsCallback, timeout(TIMEOUT_MS))
13309                 .onConnectivityReportAvailable(
13310                         argThat(report ->
13311                                 areConnDiagCapsRedacted(report.getNetworkCapabilities())));
13312 
13313         final boolean noConnectivity = false;
13314         mService.reportNetworkConnectivity(n, noConnectivity);
13315 
13316         // Wait for onNetworkConnectivityReported to fire
13317         verify(mConnectivityDiagnosticsCallback, timeout(TIMEOUT_MS))
13318                 .onNetworkConnectivityReported(eq(n), eq(noConnectivity));
13319 
13320         // Also expect a ConnectivityReport after NetworkMonitor asynchronously re-validates
13321         verify(mConnectivityDiagnosticsCallback, timeout(TIMEOUT_MS).times(2))
13322                 .onConnectivityReportAvailable(
13323                         argThat(report ->
13324                                 areConnDiagCapsRedacted(report.getNetworkCapabilities())));
13325     }
13326 
13327     @Test
13328     public void testConnectivityDiagnosticsCallbackOnConnectivityReportedSeparateUid()
13329             throws Exception {
13330         setUpConnectivityDiagnosticsCallback();
13331 
13332         // report known Connectivity from a different uid. Verify that network is not re-validated
13333         // and this callback is not notified.
13334         final Network n = mCellAgent.getNetwork();
13335         final boolean hasConnectivity = true;
13336         doAsUid(Process.myUid() + 1, () -> mService.reportNetworkConnectivity(n, hasConnectivity));
13337 
13338         // Block until all other events are done processing.
13339         HandlerUtils.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
13340 
13341         // Verify onNetworkConnectivityReported did not fire
13342         verify(mConnectivityDiagnosticsCallback, never())
13343                 .onNetworkConnectivityReported(any(), anyBoolean());
13344         verify(mConnectivityDiagnosticsCallback, never())
13345                 .onConnectivityReportAvailable(any());
13346 
13347         // report different Connectivity from a different uid. Verify that network is re-validated
13348         // and that this callback is notified.
13349         final boolean noConnectivity = false;
13350         doAsUid(Process.myUid() + 1, () -> mService.reportNetworkConnectivity(n, noConnectivity));
13351 
13352         // Wait for onNetworkConnectivityReported to fire
13353         verify(mConnectivityDiagnosticsCallback, timeout(TIMEOUT_MS))
13354                 .onNetworkConnectivityReported(eq(n), eq(noConnectivity));
13355 
13356         // Also expect a ConnectivityReport after NetworkMonitor asynchronously re-validates
13357         verify(mConnectivityDiagnosticsCallback, timeout(TIMEOUT_MS))
13358                 .onConnectivityReportAvailable(
13359                         argThat(report ->
13360                                 areConnDiagCapsRedacted(report.getNetworkCapabilities())));
13361     }
13362 
13363     @Test(expected = NullPointerException.class)
13364     public void testSimulateDataStallNullNetwork() {
13365         mService.simulateDataStall(
13366                 DataStallReport.DETECTION_METHOD_DNS_EVENTS,
13367                 0L /* timestampMillis */,
13368                 null /* network */,
13369                 new PersistableBundle());
13370     }
13371 
13372     @Test(expected = NullPointerException.class)
13373     public void testSimulateDataStallNullPersistableBundle() {
13374         mService.simulateDataStall(
13375                 DataStallReport.DETECTION_METHOD_DNS_EVENTS,
13376                 0L /* timestampMillis */,
13377                 mock(Network.class),
13378                 null /* extras */);
13379     }
13380 
13381     @Test
13382     public void testRouteAddDeleteUpdate() throws Exception {
13383         final NetworkRequest request = new NetworkRequest.Builder().build();
13384         final TestNetworkCallback networkCallback = new TestNetworkCallback();
13385         mCm.registerNetworkCallback(request, networkCallback);
13386         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
13387         reset(mMockNetd);
13388         mCellAgent.connect(false);
13389         networkCallback.expectAvailableCallbacksUnvalidated(mCellAgent);
13390         final int netId = mCellAgent.getNetwork().netId;
13391 
13392         final String iface = "rmnet_data0";
13393         final InetAddress gateway = InetAddress.getByName("fe80::5678");
13394         RouteInfo direct = RouteInfo.makeHostRoute(gateway, iface);
13395         RouteInfo rio1 = new RouteInfo(new IpPrefix("2001:db8:1::/48"), gateway, iface);
13396         RouteInfo rio2 = new RouteInfo(new IpPrefix("2001:db8:2::/48"), gateway, iface);
13397         RouteInfo defaultRoute = new RouteInfo((IpPrefix) null, gateway, iface);
13398         RouteInfo defaultWithMtu = new RouteInfo(null, gateway, iface, RouteInfo.RTN_UNICAST,
13399                                                  1280 /* mtu */);
13400 
13401         // Send LinkProperties and check that we ask netd to add routes.
13402         LinkProperties lp = new LinkProperties();
13403         lp.setInterfaceName(iface);
13404         lp.addRoute(direct);
13405         lp.addRoute(rio1);
13406         lp.addRoute(defaultRoute);
13407         mCellAgent.sendLinkProperties(lp);
13408         networkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent,
13409                 x -> x.getLp().getRoutes().size() == 3);
13410 
13411         assertRoutesAdded(netId, direct, rio1, defaultRoute);
13412         reset(mMockNetd);
13413 
13414         // Send updated LinkProperties and check that we ask netd to add, remove, update routes.
13415         assertTrue(lp.getRoutes().contains(defaultRoute));
13416         lp.removeRoute(rio1);
13417         lp.addRoute(rio2);
13418         lp.addRoute(defaultWithMtu);
13419         // Ensure adding the same route with a different MTU replaces the previous route.
13420         assertFalse(lp.getRoutes().contains(defaultRoute));
13421         assertTrue(lp.getRoutes().contains(defaultWithMtu));
13422 
13423         mCellAgent.sendLinkProperties(lp);
13424         networkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent,
13425                 x -> x.getLp().getRoutes().contains(rio2));
13426 
13427         assertRoutesRemoved(netId, rio1);
13428         assertRoutesAdded(netId, rio2);
13429 
13430         ArgumentCaptor<RouteInfoParcel> captor = ArgumentCaptor.forClass(RouteInfoParcel.class);
13431         verify(mMockNetd).networkUpdateRouteParcel(eq(netId), captor.capture());
13432         assertRouteInfoParcelMatches(defaultWithMtu, captor.getValue());
13433 
13434 
13435         mCm.unregisterNetworkCallback(networkCallback);
13436     }
13437 
13438     private void verifyDump(String[] args) {
13439         final StringWriter stringWriter = new StringWriter();
13440         mService.dump(new FileDescriptor(), new PrintWriter(stringWriter), args);
13441         assertFalse(stringWriter.toString().isEmpty());
13442     }
13443 
13444     @Test
13445     public void testDumpDoesNotCrash() throws Exception {
13446         mServiceContext.setPermission(DUMP, PERMISSION_GRANTED);
13447         // Filing a couple requests prior to testing the dump.
13448         final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback();
13449         final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
13450         final NetworkRequest genericRequest = new NetworkRequest.Builder()
13451                 .clearCapabilities().build();
13452         final NetworkRequest wifiRequest = new NetworkRequest.Builder()
13453                 .addTransportType(TRANSPORT_WIFI).build();
13454         mCm.registerNetworkCallback(genericRequest, genericNetworkCallback);
13455         mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
13456 
13457         // NetworkProvider
13458         final NetworkProvider wifiProvider = new NetworkProvider(mServiceContext,
13459                 mCsHandlerThread.getLooper(), "Wifi provider");
13460         mCm.registerNetworkProvider(wifiProvider);
13461 
13462         // NetworkAgent
13463         final LinkProperties wifiLp = new LinkProperties();
13464         wifiLp.setInterfaceName(WIFI_IFNAME);
13465         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp);
13466         mWiFiAgent.connect(true);
13467 
13468         // NetworkOffer
13469         final NetworkScore wifiScore = new NetworkScore.Builder().build();
13470         final NetworkCapabilities wifiCaps = new NetworkCapabilities.Builder()
13471                 .addTransportType(TRANSPORT_WIFI)
13472                 .addCapability(NET_CAPABILITY_INTERNET)
13473                 .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
13474                 .build();
13475         final TestableNetworkOfferCallback wifiCallback = new TestableNetworkOfferCallback(
13476                 TIMEOUT_MS /* timeout */, TEST_CALLBACK_TIMEOUT_MS /* noCallbackTimeout */);
13477         wifiProvider.registerNetworkOffer(wifiScore, wifiCaps, r -> r.run(), wifiCallback);
13478 
13479         // Profile preferences
13480         final UserHandle testHandle = setupEnterpriseNetwork();
13481         final TestNetworkAgentWrapper workAgent = makeEnterpriseNetworkAgent();
13482         workAgent.connect(true);
13483         mCm.setProfileNetworkPreference(testHandle, PROFILE_NETWORK_PREFERENCE_ENTERPRISE,
13484                 null /* executor */, null /* listener */);
13485 
13486         // OEM preferences
13487         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
13488                 OEM_NETWORK_PREFERENCE_OEM_PAID;
13489         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true);
13490         setOemNetworkPreference(networkPref, TEST_PACKAGE_NAME);
13491 
13492         // Mobile data preferred UIDs
13493         setAndUpdateMobileDataPreferredUids(Set.of(TEST_PACKAGE_UID));
13494 
13495         verifyDump(new String[0]);
13496 
13497         // Verify dump with arguments.
13498         final String dumpPrio = "--dump-priority";
13499         final String[] dumpArgs = {dumpPrio};
13500         verifyDump(dumpArgs);
13501 
13502         final String[] highDumpArgs = {dumpPrio, "HIGH"};
13503         verifyDump(highDumpArgs);
13504 
13505         final String[] normalDumpArgs = {dumpPrio, "NORMAL"};
13506         verifyDump(normalDumpArgs);
13507 
13508         // Invalid args should do dumpNormal w/o exception
13509         final String[] unknownDumpArgs = {dumpPrio, "UNKNOWN"};
13510         verifyDump(unknownDumpArgs);
13511 
13512         final String[] invalidDumpArgs = {"UNKNOWN"};
13513         verifyDump(invalidDumpArgs);
13514     }
13515 
13516     @Test
13517     public void testRequestsSortedByIdSortsCorrectly() {
13518         final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback();
13519         final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
13520         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
13521         final NetworkRequest genericRequest = new NetworkRequest.Builder()
13522                 .clearCapabilities().build();
13523         final NetworkRequest wifiRequest = new NetworkRequest.Builder()
13524                 .addTransportType(TRANSPORT_WIFI).build();
13525         final NetworkRequest cellRequest = new NetworkRequest.Builder()
13526                 .addTransportType(TRANSPORT_CELLULAR).build();
13527         mCm.registerNetworkCallback(genericRequest, genericNetworkCallback);
13528         mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
13529         mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
13530         waitForIdle();
13531 
13532         final NetworkRequestInfo[] nriOutput = mService.requestsSortedById();
13533 
13534         assertTrue(nriOutput.length > 1);
13535         for (int i = 0; i < nriOutput.length - 1; i++) {
13536             final boolean isRequestIdInOrder =
13537                     nriOutput[i].mRequests.get(0).requestId
13538                             < nriOutput[i + 1].mRequests.get(0).requestId;
13539             assertTrue(isRequestIdInOrder);
13540         }
13541     }
13542 
13543     private void assertUidRangesUpdatedForMyUid(boolean add) throws Exception {
13544         final int uid = Process.myUid();
13545         assertVpnUidRangesUpdated(add, uidRangesForUids(uid), uid);
13546     }
13547 
13548     private void assertVpnUidRangesUpdated(boolean add, Set<UidRange> vpnRanges, int exemptUid)
13549             throws Exception {
13550         InOrder inOrder = inOrder(mMockNetd, mDestroySocketsWrapper);
13551         final Set<Integer> exemptUidSet = new ArraySet<>(List.of(exemptUid, Process.VPN_UID));
13552         ArgumentCaptor<int[]> exemptUidCaptor = ArgumentCaptor.forClass(int[].class);
13553 
13554         if (mDeps.isAtLeastU()) {
13555             inOrder.verify(mDestroySocketsWrapper).destroyLiveTcpSockets(
13556                     UidRange.toIntRanges(vpnRanges), exemptUidSet);
13557         } else {
13558             inOrder.verify(mMockNetd).socketDestroy(eq(toUidRangeStableParcels(vpnRanges)),
13559                     exemptUidCaptor.capture());
13560             assertContainsExactly(exemptUidCaptor.getValue(), Process.VPN_UID, exemptUid);
13561         }
13562 
13563         if (add) {
13564             inOrder.verify(mMockNetd, times(1)).networkAddUidRangesParcel(
13565                     new NativeUidRangeConfig(mMockVpn.getNetwork().getNetId(),
13566                             toUidRangeStableParcels(vpnRanges), PREFERENCE_ORDER_VPN));
13567         } else {
13568             inOrder.verify(mMockNetd, times(1)).networkRemoveUidRangesParcel(
13569                     new NativeUidRangeConfig(mMockVpn.getNetwork().getNetId(),
13570                             toUidRangeStableParcels(vpnRanges), PREFERENCE_ORDER_VPN));
13571         }
13572 
13573         if (mDeps.isAtLeastU()) {
13574             inOrder.verify(mDestroySocketsWrapper).destroyLiveTcpSockets(
13575                     UidRange.toIntRanges(vpnRanges), exemptUidSet);
13576         } else {
13577             inOrder.verify(mMockNetd).socketDestroy(eq(toUidRangeStableParcels(vpnRanges)),
13578                     exemptUidCaptor.capture());
13579             assertContainsExactly(exemptUidCaptor.getValue(), Process.VPN_UID, exemptUid);
13580         }
13581     }
13582 
13583     @Test
13584     public void testVpnUidRangesUpdate() throws Exception {
13585         // Set up a WiFi network without proxy.
13586         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
13587         mWiFiAgent.connect(true);
13588         assertNull(mService.getProxyForNetwork(null));
13589         assertNull(mCm.getDefaultProxy());
13590 
13591         final ExpectedBroadcast b1 = expectProxyChangeAction();
13592         final LinkProperties lp = new LinkProperties();
13593         lp.setInterfaceName("tun0");
13594         lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
13595         lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
13596         final UidRange vpnRange = PRIMARY_UIDRANGE;
13597         final Set<UidRange> vpnRanges = Collections.singleton(vpnRange);
13598         mMockVpn.establish(lp, VPN_UID, vpnRanges);
13599         assertVpnUidRangesUpdated(true, vpnRanges, VPN_UID);
13600         // VPN is connected but proxy is not set, so there is no need to send proxy broadcast.
13601         b1.expectNoBroadcast(500);
13602 
13603         // Update to new range which is old range minus APP1, i.e. only APP2
13604         final ExpectedBroadcast b2 = expectProxyChangeAction();
13605         final Set<UidRange> newRanges = new HashSet<>(asList(
13606                 new UidRange(vpnRange.start, APP1_UID - 1),
13607                 new UidRange(APP1_UID + 1, vpnRange.stop)));
13608         mMockVpn.setUids(newRanges);
13609         waitForIdle();
13610 
13611         assertVpnUidRangesUpdated(true, newRanges, VPN_UID);
13612         assertVpnUidRangesUpdated(false, vpnRanges, VPN_UID);
13613 
13614         // Uid has changed but proxy is not set, so there is no need to send proxy broadcast.
13615         b2.expectNoBroadcast(500);
13616 
13617         final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
13618         final ExpectedBroadcast b3 = expectProxyChangeAction();
13619         lp.setHttpProxy(testProxyInfo);
13620         mMockVpn.sendLinkProperties(lp);
13621         waitForIdle();
13622         // Proxy is set, so send a proxy broadcast.
13623         b3.expectBroadcast();
13624 
13625         final ExpectedBroadcast b4 = expectProxyChangeAction();
13626         mMockVpn.setUids(vpnRanges);
13627         waitForIdle();
13628         // Uid has changed and proxy is already set, so send a proxy broadcast.
13629         b4.expectBroadcast();
13630 
13631         final ExpectedBroadcast b5 = expectProxyChangeAction();
13632         // Proxy is removed, send a proxy broadcast.
13633         lp.setHttpProxy(null);
13634         mMockVpn.sendLinkProperties(lp);
13635         waitForIdle();
13636         b5.expectBroadcast();
13637 
13638         // Proxy is added in WiFi(default network), setDefaultProxy will be called.
13639         final LinkProperties wifiLp = mCm.getLinkProperties(mWiFiAgent.getNetwork());
13640         assertNotNull(wifiLp);
13641         final ExpectedBroadcast b6 = expectProxyChangeAction(testProxyInfo);
13642         wifiLp.setHttpProxy(testProxyInfo);
13643         mWiFiAgent.sendLinkProperties(wifiLp);
13644         waitForIdle();
13645         b6.expectBroadcast();
13646     }
13647 
13648     @Test
13649     public void testProxyBroadcastWillBeSentWhenVpnHasProxyAndConnects() throws Exception {
13650         // Set up a WiFi network without proxy.
13651         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
13652         mWiFiAgent.connect(true);
13653         assertNull(mService.getProxyForNetwork(null));
13654         assertNull(mCm.getDefaultProxy());
13655 
13656         final LinkProperties lp = new LinkProperties();
13657         lp.setInterfaceName("tun0");
13658         lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
13659         lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
13660         final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
13661         lp.setHttpProxy(testProxyInfo);
13662         final UidRange vpnRange = PRIMARY_UIDRANGE;
13663         final Set<UidRange> vpnRanges = Collections.singleton(vpnRange);
13664         final ExpectedBroadcast b1 = expectProxyChangeAction();
13665         mMockVpn.setOwnerAndAdminUid(VPN_UID);
13666         mMockVpn.registerAgent(false, vpnRanges, lp);
13667         // In any case, the proxy broadcast won't be sent before VPN goes into CONNECTED state.
13668         // Otherwise, the app that calls ConnectivityManager#getDefaultProxy() when it receives the
13669         // proxy broadcast will get null.
13670         b1.expectNoBroadcast(500);
13671 
13672         final ExpectedBroadcast b2 = expectProxyChangeAction();
13673         mMockVpn.connect(true /* validated */, true /* hasInternet */,
13674                 false /* privateDnsProbeSent */);
13675         waitForIdle();
13676         assertVpnUidRangesUpdated(true, vpnRanges, VPN_UID);
13677         // Vpn is connected with proxy, so the proxy broadcast will be sent to inform the apps to
13678         // update their proxy data.
13679         b2.expectBroadcast();
13680     }
13681 
13682     @Test
13683     public void testProxyBroadcastWillBeSentWhenTheProxyOfNonDefaultNetworkHasChanged()
13684             throws Exception {
13685         // Set up a CELLULAR network without proxy.
13686         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
13687         mCellAgent.connect(true);
13688         assertNull(mService.getProxyForNetwork(null));
13689         assertNull(mCm.getDefaultProxy());
13690         // CELLULAR network should be the default network.
13691         assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetwork());
13692 
13693         // Set up a WiFi network without proxy.
13694         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
13695         mWiFiAgent.connect(true);
13696         assertNull(mService.getProxyForNetwork(null));
13697         assertNull(mCm.getDefaultProxy());
13698         // WiFi network should be the default network.
13699         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetwork());
13700         // CELLULAR network is not the default network.
13701         assertNotEquals(mCellAgent.getNetwork(), mCm.getActiveNetwork());
13702 
13703         // CELLULAR network is not the system default network, but it might be a per-app default
13704         // network. The proxy broadcast should be sent once its proxy has changed.
13705         final LinkProperties cellularLp = new LinkProperties();
13706         cellularLp.setInterfaceName(MOBILE_IFNAME);
13707         final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
13708         final ExpectedBroadcast b = expectProxyChangeAction();
13709         cellularLp.setHttpProxy(testProxyInfo);
13710         mCellAgent.sendLinkProperties(cellularLp);
13711         b.expectBroadcast();
13712     }
13713 
13714     @Test
13715     public void testInvalidRequestTypes() {
13716         final int[] invalidReqTypeInts = new int[]{-1, NetworkRequest.Type.NONE.ordinal(),
13717                 NetworkRequest.Type.LISTEN.ordinal(), NetworkRequest.Type.values().length};
13718         final NetworkCapabilities nc = new NetworkCapabilities().addTransportType(TRANSPORT_WIFI);
13719 
13720         for (int reqTypeInt : invalidReqTypeInts) {
13721             assertThrows("Expect throws for invalid request type " + reqTypeInt,
13722                     IllegalArgumentException.class,
13723                     () -> mService.requestNetwork(Process.INVALID_UID, nc, reqTypeInt, null, 0,
13724                             null, ConnectivityManager.TYPE_NONE, NetworkCallback.FLAG_NONE,
13725                             mContext.getPackageName(), getAttributionTag(),
13726                             ~0 /* declaredMethodsFlag */)
13727             );
13728         }
13729     }
13730 
13731     @Test
13732     public void testKeepConnected() throws Exception {
13733         setAlwaysOnNetworks(false);
13734         registerDefaultNetworkCallbacks();
13735         final TestNetworkCallback allNetworksCb = new TestNetworkCallback();
13736         final NetworkRequest allNetworksRequest = new NetworkRequest.Builder().clearCapabilities()
13737                 .build();
13738         mCm.registerNetworkCallback(allNetworksRequest, allNetworksCb);
13739 
13740         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
13741         mCellAgent.connect(true /* validated */);
13742 
13743         mDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
13744         allNetworksCb.expectAvailableThenValidatedCallbacks(mCellAgent);
13745 
13746         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
13747         mWiFiAgent.connect(true /* validated */);
13748 
13749         mDefaultNetworkCallback.expectAvailableDoubleValidatedCallbacks(mWiFiAgent);
13750         // While the default callback doesn't see the network before it's validated, the listen
13751         // sees the network come up and validate later
13752         allNetworksCb.expectAvailableCallbacksUnvalidated(mWiFiAgent);
13753         allNetworksCb.expectLosing(mCellAgent);
13754         allNetworksCb.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
13755         allNetworksCb.expect(LOST, mCellAgent, TEST_LINGER_DELAY_MS * 2);
13756 
13757         // The cell network has disconnected (see LOST above) because it was outscored and
13758         // had no requests (see setAlwaysOnNetworks(false) above)
13759         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
13760         final NetworkScore score = new NetworkScore.Builder().setLegacyInt(30).build();
13761         mCellAgent.setScore(score);
13762         mCellAgent.connect(false /* validated */);
13763 
13764         // The cell network gets torn down right away.
13765         allNetworksCb.expectAvailableCallbacksUnvalidated(mCellAgent);
13766         allNetworksCb.expect(LOST, mCellAgent, TEST_NASCENT_DELAY_MS * 2);
13767         allNetworksCb.assertNoCallback();
13768 
13769         // Now create a cell network with KEEP_CONNECTED_FOR_HANDOVER and make sure it's
13770         // not disconnected immediately when outscored.
13771         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
13772         final NetworkScore scoreKeepup = new NetworkScore.Builder().setLegacyInt(30)
13773                 .setKeepConnectedReason(KEEP_CONNECTED_FOR_HANDOVER).build();
13774         mCellAgent.setScore(scoreKeepup);
13775         mCellAgent.connect(true /* validated */);
13776 
13777         allNetworksCb.expectAvailableThenValidatedCallbacks(mCellAgent);
13778         mDefaultNetworkCallback.assertNoCallback();
13779 
13780         mWiFiAgent.disconnect();
13781 
13782         allNetworksCb.expect(LOST, mWiFiAgent);
13783         mDefaultNetworkCallback.expect(LOST, mWiFiAgent);
13784         mDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellAgent);
13785 
13786         // Reconnect a WiFi network and make sure the cell network is still not torn down.
13787         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
13788         mWiFiAgent.connect(true /* validated */);
13789 
13790         allNetworksCb.expectAvailableThenValidatedCallbacks(mWiFiAgent);
13791         mDefaultNetworkCallback.expectAvailableDoubleValidatedCallbacks(mWiFiAgent);
13792 
13793         // Now remove the reason to keep connected and make sure the network lingers and is
13794         // torn down.
13795         mCellAgent.setScore(new NetworkScore.Builder().setLegacyInt(30).build());
13796         allNetworksCb.expectLosing(mCellAgent, TEST_NASCENT_DELAY_MS * 2);
13797         allNetworksCb.expect(LOST, mCellAgent, TEST_LINGER_DELAY_MS * 2);
13798         mDefaultNetworkCallback.assertNoCallback();
13799 
13800         mCm.unregisterNetworkCallback(allNetworksCb);
13801         // mDefaultNetworkCallback will be unregistered by tearDown()
13802     }
13803 
13804     private class QosCallbackMockHelper {
13805         @NonNull public final QosFilter mFilter;
13806         @NonNull public final IQosCallback mCallback;
13807         @NonNull public final TestNetworkAgentWrapper mAgentWrapper;
13808         @NonNull private final List<IQosCallback> mCallbacks = new ArrayList();
13809 
13810         QosCallbackMockHelper() throws Exception {
13811             Log.d(TAG, "QosCallbackMockHelper: ");
13812             mFilter = mock(QosFilter.class);
13813 
13814             // Ensure the network is disconnected before anything else occurs
13815             assertNull(mCellAgent);
13816 
13817             mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
13818             mCellAgent.connect(true);
13819 
13820             verifyActiveNetwork(TRANSPORT_CELLULAR);
13821             waitForIdle();
13822             final Network network = mCellAgent.getNetwork();
13823 
13824             final Pair<IQosCallback, IBinder> pair = createQosCallback();
13825             mCallback = pair.first;
13826 
13827             doReturn(network).when(mFilter).getNetwork();
13828             doReturn(QosCallbackException.EX_TYPE_FILTER_NONE).when(mFilter).validate();
13829             mAgentWrapper = mCellAgent;
13830         }
13831 
13832         void registerQosCallback(@NonNull final QosFilter filter,
13833                 @NonNull final IQosCallback callback) {
13834             mCallbacks.add(callback);
13835             final NetworkAgentInfo nai =
13836                     mService.getNetworkAgentInfoForNetwork(filter.getNetwork());
13837             mService.registerQosCallbackInternal(filter, callback, nai);
13838         }
13839 
13840         void tearDown() {
13841             for (int i = 0; i < mCallbacks.size(); i++) {
13842                 mService.unregisterQosCallback(mCallbacks.get(i));
13843             }
13844         }
13845     }
13846 
13847     private Pair<IQosCallback, IBinder> createQosCallback() {
13848         final IQosCallback callback = mock(IQosCallback.class);
13849         final IBinder binder = mock(Binder.class);
13850         doReturn(binder).when(callback).asBinder();
13851         doReturn(true).when(binder).isBinderAlive();
13852         return new Pair<>(callback, binder);
13853     }
13854 
13855 
13856     @Test
13857     public void testQosCallbackRegistration() throws Exception {
13858         mQosCallbackMockHelper = new QosCallbackMockHelper();
13859         final NetworkAgentWrapper wrapper = mQosCallbackMockHelper.mAgentWrapper;
13860 
13861         doReturn(QosCallbackException.EX_TYPE_FILTER_NONE)
13862                 .when(mQosCallbackMockHelper.mFilter).validate();
13863         mQosCallbackMockHelper.registerQosCallback(
13864                 mQosCallbackMockHelper.mFilter, mQosCallbackMockHelper.mCallback);
13865 
13866         final OnQosCallbackRegister cbRegister1 =
13867                 (OnQosCallbackRegister) wrapper.getCallbackHistory().poll(1000, x -> true);
13868         assertNotNull(cbRegister1);
13869 
13870         final int registerCallbackId = cbRegister1.mQosCallbackId;
13871         mService.unregisterQosCallback(mQosCallbackMockHelper.mCallback);
13872         final OnQosCallbackUnregister cbUnregister =
13873                 (OnQosCallbackUnregister) wrapper.getCallbackHistory().poll(1000, x -> true);
13874         assertNotNull(cbUnregister);
13875         assertEquals(registerCallbackId, cbUnregister.mQosCallbackId);
13876         assertNull(wrapper.getCallbackHistory().poll(200, x -> true));
13877     }
13878 
13879     @Test
13880     public void testQosCallbackNoRegistrationOnValidationError() throws Exception {
13881         mQosCallbackMockHelper = new QosCallbackMockHelper();
13882 
13883         doReturn(QosCallbackException.EX_TYPE_FILTER_NETWORK_RELEASED)
13884                 .when(mQosCallbackMockHelper.mFilter).validate();
13885         mQosCallbackMockHelper.registerQosCallback(
13886                 mQosCallbackMockHelper.mFilter, mQosCallbackMockHelper.mCallback);
13887         waitForIdle();
13888         verify(mQosCallbackMockHelper.mCallback)
13889                 .onError(eq(QosCallbackException.EX_TYPE_FILTER_NETWORK_RELEASED));
13890     }
13891 
13892     @Test
13893     public void testQosCallbackAvailableAndLost() throws Exception {
13894         mQosCallbackMockHelper = new QosCallbackMockHelper();
13895         final int sessionId = 10;
13896         final int qosCallbackId = 1;
13897 
13898         doReturn(QosCallbackException.EX_TYPE_FILTER_NONE)
13899                 .when(mQosCallbackMockHelper.mFilter).validate();
13900         mQosCallbackMockHelper.registerQosCallback(
13901                 mQosCallbackMockHelper.mFilter, mQosCallbackMockHelper.mCallback);
13902         waitForIdle();
13903 
13904         final EpsBearerQosSessionAttributes attributes = new EpsBearerQosSessionAttributes(
13905                 1, 2, 3, 4, 5, new ArrayList<>());
13906         mQosCallbackMockHelper.mAgentWrapper.getNetworkAgent()
13907                 .sendQosSessionAvailable(qosCallbackId, sessionId, attributes);
13908         waitForIdle();
13909 
13910         verify(mQosCallbackMockHelper.mCallback).onQosEpsBearerSessionAvailable(argThat(session ->
13911                 session.getSessionId() == sessionId
13912                         && session.getSessionType() == QosSession.TYPE_EPS_BEARER), eq(attributes));
13913 
13914         mQosCallbackMockHelper.mAgentWrapper.getNetworkAgent()
13915                 .sendQosSessionLost(qosCallbackId, sessionId, QosSession.TYPE_EPS_BEARER);
13916         waitForIdle();
13917         verify(mQosCallbackMockHelper.mCallback).onQosSessionLost(argThat(session ->
13918                 session.getSessionId() == sessionId
13919                         && session.getSessionType() == QosSession.TYPE_EPS_BEARER));
13920     }
13921 
13922     @Test
13923     public void testNrQosCallbackAvailableAndLost() throws Exception {
13924         mQosCallbackMockHelper = new QosCallbackMockHelper();
13925         final int sessionId = 10;
13926         final int qosCallbackId = 1;
13927 
13928         doReturn(QosCallbackException.EX_TYPE_FILTER_NONE)
13929                 .when(mQosCallbackMockHelper.mFilter).validate();
13930         mQosCallbackMockHelper.registerQosCallback(
13931                 mQosCallbackMockHelper.mFilter, mQosCallbackMockHelper.mCallback);
13932         waitForIdle();
13933 
13934         final NrQosSessionAttributes attributes = new NrQosSessionAttributes(
13935                 1, 2, 3, 4, 5, 6, 7, new ArrayList<>());
13936         mQosCallbackMockHelper.mAgentWrapper.getNetworkAgent()
13937                 .sendQosSessionAvailable(qosCallbackId, sessionId, attributes);
13938         waitForIdle();
13939 
13940         verify(mQosCallbackMockHelper.mCallback).onNrQosSessionAvailable(argThat(session ->
13941                 session.getSessionId() == sessionId
13942                         && session.getSessionType() == QosSession.TYPE_NR_BEARER), eq(attributes));
13943 
13944         mQosCallbackMockHelper.mAgentWrapper.getNetworkAgent()
13945                 .sendQosSessionLost(qosCallbackId, sessionId, QosSession.TYPE_NR_BEARER);
13946         waitForIdle();
13947         verify(mQosCallbackMockHelper.mCallback).onQosSessionLost(argThat(session ->
13948                 session.getSessionId() == sessionId
13949                         && session.getSessionType() == QosSession.TYPE_NR_BEARER));
13950     }
13951 
13952     @Test @IgnoreUpTo(SC_V2)
13953     public void testQosCallbackAvailableOnValidationError() throws Exception {
13954         mQosCallbackMockHelper = new QosCallbackMockHelper();
13955         final NetworkAgentWrapper wrapper = mQosCallbackMockHelper.mAgentWrapper;
13956         final int sessionId = 10;
13957         final int qosCallbackId = 1;
13958 
13959         doReturn(QosCallbackException.EX_TYPE_FILTER_NONE)
13960                 .when(mQosCallbackMockHelper.mFilter).validate();
13961         mQosCallbackMockHelper.registerQosCallback(
13962                 mQosCallbackMockHelper.mFilter, mQosCallbackMockHelper.mCallback);
13963         OnQosCallbackRegister cbRegister1 =
13964                 (OnQosCallbackRegister) wrapper.getCallbackHistory().poll(1000, x -> true);
13965         assertNotNull(cbRegister1);
13966         final int registerCallbackId = cbRegister1.mQosCallbackId;
13967 
13968         waitForIdle();
13969 
13970         doReturn(QosCallbackException.EX_TYPE_FILTER_SOCKET_REMOTE_ADDRESS_CHANGED)
13971                 .when(mQosCallbackMockHelper.mFilter).validate();
13972         final EpsBearerQosSessionAttributes attributes = new EpsBearerQosSessionAttributes(
13973                 1, 2, 3, 4, 5, new ArrayList<>());
13974         mQosCallbackMockHelper.mAgentWrapper.getNetworkAgent()
13975                 .sendQosSessionAvailable(qosCallbackId, sessionId, attributes);
13976         waitForIdle();
13977 
13978         final NetworkAgentWrapper.CallbackType.OnQosCallbackUnregister cbUnregister;
13979         cbUnregister = (NetworkAgentWrapper.CallbackType.OnQosCallbackUnregister)
13980                 wrapper.getCallbackHistory().poll(1000, x -> true);
13981         assertNotNull(cbUnregister);
13982         assertEquals(registerCallbackId, cbUnregister.mQosCallbackId);
13983         waitForIdle();
13984         verify(mQosCallbackMockHelper.mCallback)
13985                 .onError(eq(QosCallbackException.EX_TYPE_FILTER_SOCKET_REMOTE_ADDRESS_CHANGED));
13986     }
13987 
13988     @Test @IgnoreUpTo(SC_V2)
13989     public void testQosCallbackLostOnValidationError() throws Exception {
13990         mQosCallbackMockHelper = new QosCallbackMockHelper();
13991         final int sessionId = 10;
13992         final int qosCallbackId = 1;
13993 
13994         doReturn(QosCallbackException.EX_TYPE_FILTER_NONE)
13995                 .when(mQosCallbackMockHelper.mFilter).validate();
13996         mQosCallbackMockHelper.registerQosCallback(
13997                 mQosCallbackMockHelper.mFilter, mQosCallbackMockHelper.mCallback);
13998         waitForIdle();
13999         EpsBearerQosSessionAttributes attributes =
14000                 sendQosSessionEvent(qosCallbackId, sessionId, true);
14001         waitForIdle();
14002 
14003         verify(mQosCallbackMockHelper.mCallback).onQosEpsBearerSessionAvailable(argThat(session ->
14004                 session.getSessionId() == sessionId
14005                         && session.getSessionType() == QosSession.TYPE_EPS_BEARER), eq(attributes));
14006 
14007         doReturn(QosCallbackException.EX_TYPE_FILTER_SOCKET_REMOTE_ADDRESS_CHANGED)
14008                 .when(mQosCallbackMockHelper.mFilter).validate();
14009 
14010         sendQosSessionEvent(qosCallbackId, sessionId, false);
14011         waitForIdle();
14012         verify(mQosCallbackMockHelper.mCallback)
14013                 .onError(eq(QosCallbackException.EX_TYPE_FILTER_SOCKET_REMOTE_ADDRESS_CHANGED));
14014     }
14015 
14016     private EpsBearerQosSessionAttributes sendQosSessionEvent(
14017             int qosCallbackId, int sessionId, boolean available) {
14018         if (available) {
14019             final EpsBearerQosSessionAttributes attributes = new EpsBearerQosSessionAttributes(
14020                     1, 2, 3, 4, 5, new ArrayList<>());
14021             mQosCallbackMockHelper.mAgentWrapper.getNetworkAgent()
14022                     .sendQosSessionAvailable(qosCallbackId, sessionId, attributes);
14023             return attributes;
14024         } else {
14025             mQosCallbackMockHelper.mAgentWrapper.getNetworkAgent()
14026                     .sendQosSessionLost(qosCallbackId, sessionId, QosSession.TYPE_EPS_BEARER);
14027             return null;
14028         }
14029 
14030     }
14031 
14032     @Test
14033     public void testQosCallbackTooManyRequests() throws Exception {
14034         mQosCallbackMockHelper = new QosCallbackMockHelper();
14035 
14036         doReturn(QosCallbackException.EX_TYPE_FILTER_NONE)
14037                 .when(mQosCallbackMockHelper.mFilter).validate();
14038         for (int i = 0; i < 100; i++) {
14039             final Pair<IQosCallback, IBinder> pair = createQosCallback();
14040 
14041             try {
14042                 mQosCallbackMockHelper.registerQosCallback(
14043                         mQosCallbackMockHelper.mFilter, pair.first);
14044             } catch (ServiceSpecificException e) {
14045                 assertEquals(e.errorCode, ConnectivityManager.Errors.TOO_MANY_REQUESTS);
14046                 if (i < 50) {
14047                     fail("TOO_MANY_REQUESTS thrown too early, the count is " + i);
14048                 }
14049 
14050                 // As long as there is at least 50 requests, it is safe to assume it works.
14051                 // Note: The count isn't being tested precisely against 100 because the counter
14052                 // is shared with request network.
14053                 return;
14054             }
14055         }
14056         fail("TOO_MANY_REQUESTS never thrown");
14057     }
14058 
14059     private void mockGetApplicationInfo(@NonNull final String packageName, final int uid) {
14060         mockGetApplicationInfo(packageName, uid, PRIMARY_USER_HANDLE);
14061     }
14062 
14063     private void mockGetApplicationInfo(@NonNull final String packageName, final int uid,
14064             @NonNull final UserHandle user) {
14065         final ApplicationInfo applicationInfo = new ApplicationInfo();
14066         applicationInfo.uid = uid;
14067         try {
14068             doReturn(applicationInfo).when(mPackageManager).getApplicationInfoAsUser(
14069                     eq(packageName), anyInt(), eq(user));
14070         } catch (Exception e) {
14071             fail(e.getMessage());
14072         }
14073     }
14074 
14075     private void mockGetApplicationInfoThrowsNameNotFound(@NonNull final String packageName,
14076             @NonNull final UserHandle user)
14077             throws Exception {
14078         doThrow(new PackageManager.NameNotFoundException(packageName)).when(
14079                 mPackageManager).getApplicationInfoAsUser(eq(packageName), anyInt(), eq(user));
14080     }
14081 
14082     private void mockHasSystemFeature(@NonNull final String featureName, final boolean hasFeature) {
14083         doReturn(hasFeature).when(mPackageManager).hasSystemFeature(eq(featureName));
14084     }
14085 
14086     private Range<Integer> getNriFirstUidRange(@NonNull final NetworkRequestInfo nri) {
14087         return nri.mRequests.get(0).networkCapabilities.getUids().iterator().next();
14088     }
14089 
14090     private OemNetworkPreferences createDefaultOemNetworkPreferences(
14091             @OemNetworkPreferences.OemNetworkPreference final int preference) {
14092         // Arrange PackageManager mocks
14093         mockGetApplicationInfo(TEST_PACKAGE_NAME, TEST_PACKAGE_UID);
14094 
14095         // Build OemNetworkPreferences object
14096         return new OemNetworkPreferences.Builder()
14097                 .addNetworkPreference(TEST_PACKAGE_NAME, preference)
14098                 .build();
14099     }
14100 
14101     @Test
14102     public void testOemNetworkRequestFactoryPreferenceUninitializedThrowsError() {
14103         @OemNetworkPreferences.OemNetworkPreference final int prefToTest =
14104                 OEM_NETWORK_PREFERENCE_UNINITIALIZED;
14105 
14106         // Act on OemNetworkRequestFactory.createNrisFromOemNetworkPreferences()
14107         assertThrows(IllegalArgumentException.class,
14108                 () -> mService.new OemNetworkRequestFactory()
14109                         .createNrisFromOemNetworkPreferences(
14110                                 createDefaultOemNetworkPreferences(prefToTest)));
14111     }
14112 
14113     @Test
14114     public void testOemNetworkRequestFactoryPreferenceOemPaid()
14115             throws Exception {
14116         // Expectations
14117         final int expectedNumOfNris = 1;
14118         final int expectedNumOfRequests = 3;
14119 
14120         @OemNetworkPreferences.OemNetworkPreference final int prefToTest =
14121                 OEM_NETWORK_PREFERENCE_OEM_PAID;
14122 
14123         // Act on OemNetworkRequestFactory.createNrisFromOemNetworkPreferences()
14124         final ArraySet<NetworkRequestInfo> nris =
14125                 mService.new OemNetworkRequestFactory()
14126                         .createNrisFromOemNetworkPreferences(
14127                                 createDefaultOemNetworkPreferences(prefToTest));
14128         final NetworkRequestInfo nri = nris.iterator().next();
14129         assertEquals(PREFERENCE_ORDER_OEM, nri.mPreferenceOrder);
14130         final List<NetworkRequest> mRequests = nri.mRequests;
14131         assertEquals(expectedNumOfNris, nris.size());
14132         assertEquals(expectedNumOfRequests, mRequests.size());
14133         assertTrue(mRequests.get(0).isListen());
14134         assertTrue(mRequests.get(0).hasCapability(NET_CAPABILITY_NOT_METERED));
14135         assertTrue(mRequests.get(0).hasCapability(NET_CAPABILITY_VALIDATED));
14136         assertTrue(mRequests.get(1).isRequest());
14137         assertTrue(mRequests.get(1).hasCapability(NET_CAPABILITY_OEM_PAID));
14138         assertEquals(NetworkRequest.Type.TRACK_DEFAULT, mRequests.get(2).type);
14139         assertTrue(mService.getDefaultRequest().networkCapabilities.equalsNetCapabilities(
14140                 mRequests.get(2).networkCapabilities));
14141     }
14142 
14143     @Test
14144     public void testOemNetworkRequestFactoryPreferenceOemPaidNoFallback()
14145             throws Exception {
14146         // Expectations
14147         final int expectedNumOfNris = 1;
14148         final int expectedNumOfRequests = 2;
14149 
14150         @OemNetworkPreferences.OemNetworkPreference final int prefToTest =
14151                 OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK;
14152 
14153         // Act on OemNetworkRequestFactory.createNrisFromOemNetworkPreferences()
14154         final ArraySet<NetworkRequestInfo> nris =
14155                 mService.new OemNetworkRequestFactory()
14156                         .createNrisFromOemNetworkPreferences(
14157                                 createDefaultOemNetworkPreferences(prefToTest));
14158         final NetworkRequestInfo nri = nris.iterator().next();
14159         assertEquals(PREFERENCE_ORDER_OEM, nri.mPreferenceOrder);
14160         final List<NetworkRequest> mRequests = nri.mRequests;
14161         assertEquals(expectedNumOfNris, nris.size());
14162         assertEquals(expectedNumOfRequests, mRequests.size());
14163         assertTrue(mRequests.get(0).isListen());
14164         assertTrue(mRequests.get(0).hasCapability(NET_CAPABILITY_NOT_METERED));
14165         assertTrue(mRequests.get(0).hasCapability(NET_CAPABILITY_VALIDATED));
14166         assertTrue(mRequests.get(1).isRequest());
14167         assertTrue(mRequests.get(1).hasCapability(NET_CAPABILITY_OEM_PAID));
14168     }
14169 
14170     @Test
14171     public void testOemNetworkRequestFactoryPreferenceOemPaidOnly()
14172             throws Exception {
14173         // Expectations
14174         final int expectedNumOfNris = 1;
14175         final int expectedNumOfRequests = 1;
14176 
14177         @OemNetworkPreferences.OemNetworkPreference final int prefToTest =
14178                 OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY;
14179 
14180         // Act on OemNetworkRequestFactory.createNrisFromOemNetworkPreferences()
14181         final ArraySet<NetworkRequestInfo> nris =
14182                 mService.new OemNetworkRequestFactory()
14183                         .createNrisFromOemNetworkPreferences(
14184                                 createDefaultOemNetworkPreferences(prefToTest));
14185         final NetworkRequestInfo nri = nris.iterator().next();
14186         assertEquals(PREFERENCE_ORDER_OEM, nri.mPreferenceOrder);
14187         final List<NetworkRequest> mRequests = nri.mRequests;
14188         assertEquals(expectedNumOfNris, nris.size());
14189         assertEquals(expectedNumOfRequests, mRequests.size());
14190         assertTrue(mRequests.get(0).isRequest());
14191         assertTrue(mRequests.get(0).hasCapability(NET_CAPABILITY_OEM_PAID));
14192     }
14193 
14194     @Test
14195     public void testOemNetworkRequestFactoryPreferenceOemPrivateOnly()
14196             throws Exception {
14197         // Expectations
14198         final int expectedNumOfNris = 1;
14199         final int expectedNumOfRequests = 1;
14200 
14201         @OemNetworkPreferences.OemNetworkPreference final int prefToTest =
14202                 OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY;
14203 
14204         // Act on OemNetworkRequestFactory.createNrisFromOemNetworkPreferences()
14205         final ArraySet<NetworkRequestInfo> nris =
14206                 mService.new OemNetworkRequestFactory()
14207                         .createNrisFromOemNetworkPreferences(
14208                                 createDefaultOemNetworkPreferences(prefToTest));
14209         final NetworkRequestInfo nri = nris.iterator().next();
14210         assertEquals(PREFERENCE_ORDER_OEM, nri.mPreferenceOrder);
14211         final List<NetworkRequest> mRequests = nri.mRequests;
14212         assertEquals(expectedNumOfNris, nris.size());
14213         assertEquals(expectedNumOfRequests, mRequests.size());
14214         assertTrue(mRequests.get(0).isRequest());
14215         assertTrue(mRequests.get(0).hasCapability(NET_CAPABILITY_OEM_PRIVATE));
14216         assertFalse(mRequests.get(0).hasCapability(NET_CAPABILITY_OEM_PAID));
14217     }
14218 
14219     @Test
14220     public void testOemNetworkRequestFactoryCreatesCorrectNumOfNris()
14221             throws Exception {
14222         // Expectations
14223         final int expectedNumOfNris = 2;
14224 
14225         // Arrange PackageManager mocks
14226         final String testPackageName2 = "com.google.apps.dialer";
14227         mockGetApplicationInfo(TEST_PACKAGE_NAME, TEST_PACKAGE_UID);
14228         mockGetApplicationInfo(testPackageName2, TEST_PACKAGE_UID);
14229 
14230         // Build OemNetworkPreferences object
14231         final int testOemPref = OEM_NETWORK_PREFERENCE_OEM_PAID;
14232         final int testOemPref2 = OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK;
14233         final OemNetworkPreferences pref = new OemNetworkPreferences.Builder()
14234                 .addNetworkPreference(TEST_PACKAGE_NAME, testOemPref)
14235                 .addNetworkPreference(testPackageName2, testOemPref2)
14236                 .build();
14237 
14238         // Act on OemNetworkRequestFactory.createNrisFromOemNetworkPreferences()
14239         final ArraySet<NetworkRequestInfo> nris =
14240                 mService.new OemNetworkRequestFactory().createNrisFromOemNetworkPreferences(pref);
14241 
14242         assertNotNull(nris);
14243         assertEquals(expectedNumOfNris, nris.size());
14244     }
14245 
14246     @Test
14247     public void testOemNetworkRequestFactoryMultiplePrefsCorrectlySetsUids()
14248             throws Exception {
14249         // Arrange PackageManager mocks
14250         final String testPackageName2 = "com.google.apps.dialer";
14251         final int testPackageNameUid2 = 456;
14252         mockGetApplicationInfo(TEST_PACKAGE_NAME, TEST_PACKAGE_UID);
14253         mockGetApplicationInfo(testPackageName2, testPackageNameUid2);
14254 
14255         // Build OemNetworkPreferences object
14256         final int testOemPref = OEM_NETWORK_PREFERENCE_OEM_PAID;
14257         final int testOemPref2 = OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK;
14258         final OemNetworkPreferences pref = new OemNetworkPreferences.Builder()
14259                 .addNetworkPreference(TEST_PACKAGE_NAME, testOemPref)
14260                 .addNetworkPreference(testPackageName2, testOemPref2)
14261                 .build();
14262 
14263         // Act on OemNetworkRequestFactory.createNrisFromOemNetworkPreferences()
14264         final List<NetworkRequestInfo> nris =
14265                 new ArrayList<>(
14266                         mService.new OemNetworkRequestFactory().createNrisFromOemNetworkPreferences(
14267                                 pref));
14268 
14269         // Sort by uid to access nris by index
14270         nris.sort(Comparator.comparingInt(nri -> getNriFirstUidRange(nri).getLower()));
14271         assertEquals(TEST_PACKAGE_UID, (int) getNriFirstUidRange(nris.get(0)).getLower());
14272         assertEquals(TEST_PACKAGE_UID, (int) getNriFirstUidRange(nris.get(0)).getUpper());
14273         assertEquals(testPackageNameUid2, (int) getNriFirstUidRange(nris.get(1)).getLower());
14274         assertEquals(testPackageNameUid2, (int) getNriFirstUidRange(nris.get(1)).getUpper());
14275     }
14276 
14277     @Test
14278     public void testOemNetworkRequestFactoryMultipleUsersSetsUids()
14279             throws Exception {
14280         // Arrange users
14281         final int secondUserTestPackageUid = UserHandle.getUid(SECONDARY_USER, TEST_PACKAGE_UID);
14282         final int thirdUserTestPackageUid = UserHandle.getUid(TERTIARY_USER, TEST_PACKAGE_UID);
14283         doReturn(asList(PRIMARY_USER_HANDLE, SECONDARY_USER_HANDLE, TERTIARY_USER_HANDLE))
14284                 .when(mUserManager).getUserHandles(anyBoolean());
14285 
14286         // Arrange PackageManager mocks testing for users who have and don't have a package.
14287         mockGetApplicationInfoThrowsNameNotFound(TEST_PACKAGE_NAME, PRIMARY_USER_HANDLE);
14288         mockGetApplicationInfo(TEST_PACKAGE_NAME, secondUserTestPackageUid, SECONDARY_USER_HANDLE);
14289         mockGetApplicationInfo(TEST_PACKAGE_NAME, thirdUserTestPackageUid, TERTIARY_USER_HANDLE);
14290 
14291         // Build OemNetworkPreferences object
14292         final int testOemPref = OEM_NETWORK_PREFERENCE_OEM_PAID;
14293         final OemNetworkPreferences pref = new OemNetworkPreferences.Builder()
14294                 .addNetworkPreference(TEST_PACKAGE_NAME, testOemPref)
14295                 .build();
14296 
14297         // Act on OemNetworkRequestFactory.createNrisFromOemNetworkPreferences()
14298         final List<NetworkRequestInfo> nris =
14299                 new ArrayList<>(
14300                         mService.new OemNetworkRequestFactory().createNrisFromOemNetworkPreferences(
14301                                 pref));
14302 
14303         // UIDs for users with installed packages should be present.
14304         // Three users exist, but only two have the test package installed.
14305         final int expectedUidSize = 2;
14306         final List<Range<Integer>> uids =
14307                 new ArrayList<>(nris.get(0).mRequests.get(0).networkCapabilities.getUids());
14308         assertEquals(expectedUidSize, uids.size());
14309 
14310         // Sort by uid to access nris by index
14311         uids.sort(Comparator.comparingInt(uid -> uid.getLower()));
14312         assertEquals(secondUserTestPackageUid, (int) uids.get(0).getLower());
14313         assertEquals(secondUserTestPackageUid, (int) uids.get(0).getUpper());
14314         assertEquals(thirdUserTestPackageUid, (int) uids.get(1).getLower());
14315         assertEquals(thirdUserTestPackageUid, (int) uids.get(1).getUpper());
14316     }
14317 
14318     @Test
14319     public void testOemNetworkRequestFactoryAddsPackagesToCorrectPreference()
14320             throws Exception {
14321         // Expectations
14322         final int expectedNumOfNris = 1;
14323         final int expectedNumOfAppUids = 2;
14324 
14325         // Arrange PackageManager mocks
14326         final String testPackageName2 = "com.google.apps.dialer";
14327         final int testPackageNameUid2 = 456;
14328         mockGetApplicationInfo(TEST_PACKAGE_NAME, TEST_PACKAGE_UID);
14329         mockGetApplicationInfo(testPackageName2, testPackageNameUid2);
14330 
14331         // Build OemNetworkPreferences object
14332         final int testOemPref = OEM_NETWORK_PREFERENCE_OEM_PAID;
14333         final OemNetworkPreferences pref = new OemNetworkPreferences.Builder()
14334                 .addNetworkPreference(TEST_PACKAGE_NAME, testOemPref)
14335                 .addNetworkPreference(testPackageName2, testOemPref)
14336                 .build();
14337 
14338         // Act on OemNetworkRequestFactory.createNrisFromOemNetworkPreferences()
14339         final ArraySet<NetworkRequestInfo> nris =
14340                 mService.new OemNetworkRequestFactory().createNrisFromOemNetworkPreferences(pref);
14341 
14342         assertEquals(expectedNumOfNris, nris.size());
14343         assertEquals(expectedNumOfAppUids,
14344                 nris.iterator().next().mRequests.get(0).networkCapabilities.getUids().size());
14345     }
14346 
14347     @Test
14348     public void testSetOemNetworkPreferenceNullListenerAndPrefParamThrowsNpe() {
14349         mockHasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, true);
14350 
14351         // Act on ConnectivityService.setOemNetworkPreference()
14352         assertThrows(NullPointerException.class,
14353                 () -> mService.setOemNetworkPreference(
14354                         null,
14355                         null));
14356     }
14357 
14358     @Test
14359     public void testSetOemNetworkPreferenceFailsForNonAutomotive()
14360             throws Exception {
14361         mockHasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, false);
14362         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
14363                 OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY;
14364 
14365         // Act on ConnectivityService.setOemNetworkPreference()
14366         assertThrows(UnsupportedOperationException.class,
14367                 () -> mService.setOemNetworkPreference(
14368                         createDefaultOemNetworkPreferences(networkPref),
14369                         null));
14370     }
14371 
14372     @Test
14373     public void testSetOemNetworkPreferenceFailsForTestRequestWithoutPermission() {
14374         // Calling setOemNetworkPreference() with a test pref requires the permission
14375         // MANAGE_TEST_NETWORKS.
14376         mockHasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, false);
14377         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
14378                 OEM_NETWORK_PREFERENCE_TEST;
14379 
14380         // Act on ConnectivityService.setOemNetworkPreference()
14381         assertThrows(SecurityException.class,
14382                 () -> mService.setOemNetworkPreference(
14383                         createDefaultOemNetworkPreferences(networkPref),
14384                         null));
14385     }
14386 
14387     @Test
14388     public void testSetOemNetworkPreferenceFailsForInvalidTestRequest() {
14389         assertSetOemNetworkPreferenceFailsForInvalidTestRequest(OEM_NETWORK_PREFERENCE_TEST);
14390     }
14391 
14392     @Test
14393     public void testSetOemNetworkPreferenceFailsForInvalidTestOnlyRequest() {
14394         assertSetOemNetworkPreferenceFailsForInvalidTestRequest(OEM_NETWORK_PREFERENCE_TEST_ONLY);
14395     }
14396 
14397     private void assertSetOemNetworkPreferenceFailsForInvalidTestRequest(
14398             @OemNetworkPreferences.OemNetworkPreference final int oemNetworkPreferenceForTest) {
14399         mockHasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, true);
14400         final String secondPackage = "does.not.matter";
14401 
14402         // A valid test request would only have a single mapping.
14403         final OemNetworkPreferences pref = new OemNetworkPreferences.Builder()
14404                 .addNetworkPreference(TEST_PACKAGE_NAME, oemNetworkPreferenceForTest)
14405                 .addNetworkPreference(secondPackage, oemNetworkPreferenceForTest)
14406                 .build();
14407 
14408         // Act on ConnectivityService.setOemNetworkPreference()
14409         assertThrows(IllegalArgumentException.class,
14410                 () -> mService.setOemNetworkPreference(pref, null));
14411     }
14412 
14413     private void setOemNetworkPreferenceAgentConnected(final int transportType,
14414             final boolean connectAgent) throws Exception {
14415         switch(transportType) {
14416             // Corresponds to a metered cellular network. Will be used for the default network.
14417             case TRANSPORT_CELLULAR:
14418                 if (!connectAgent) {
14419                     mCellAgent.disconnect();
14420                     break;
14421                 }
14422                 mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
14423                 mCellAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
14424                 mCellAgent.connect(true);
14425                 break;
14426             // Corresponds to a restricted ethernet network with OEM_PAID/OEM_PRIVATE.
14427             case TRANSPORT_ETHERNET:
14428                 if (!connectAgent) {
14429                     stopOemManagedNetwork();
14430                     break;
14431                 }
14432                 startOemManagedNetwork(true);
14433                 break;
14434             // Corresponds to unmetered Wi-Fi.
14435             case TRANSPORT_WIFI:
14436                 if (!connectAgent) {
14437                     mWiFiAgent.disconnect();
14438                     break;
14439                 }
14440                 mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
14441                 mWiFiAgent.addCapability(NET_CAPABILITY_NOT_METERED);
14442                 mWiFiAgent.connect(true);
14443                 break;
14444             default:
14445                 throw new AssertionError("Unsupported transport type passed in.");
14446 
14447         }
14448         waitForIdle();
14449     }
14450 
14451     private void startOemManagedNetwork(final boolean isOemPaid) throws Exception {
14452         mEthernetAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
14453         mEthernetAgent.addCapability(
14454                 isOemPaid ? NET_CAPABILITY_OEM_PAID : NET_CAPABILITY_OEM_PRIVATE);
14455         mEthernetAgent.removeCapability(NET_CAPABILITY_NOT_RESTRICTED);
14456         mEthernetAgent.connect(true);
14457     }
14458 
14459     private void stopOemManagedNetwork() {
14460         mEthernetAgent.disconnect();
14461         waitForIdle();
14462     }
14463 
14464     private void verifyMultipleDefaultNetworksTracksCorrectly(
14465             final int expectedOemRequestsSize,
14466             @NonNull final Network expectedDefaultNetwork,
14467             @NonNull final Network expectedPerAppNetwork) {
14468         // The current test setup assumes two tracked default network requests; one for the default
14469         // network and the other for the OEM network preference being tested. This will be validated
14470         // each time to confirm it doesn't change under test.
14471         final int expectedDefaultNetworkRequestsSize = 2;
14472         assertEquals(expectedDefaultNetworkRequestsSize, mService.mDefaultNetworkRequests.size());
14473         for (final NetworkRequestInfo defaultRequest : mService.mDefaultNetworkRequests) {
14474             final Network defaultNetwork = defaultRequest.getSatisfier() == null
14475                     ? null : defaultRequest.getSatisfier().network();
14476             // If this is the default request.
14477             if (defaultRequest == mService.mDefaultRequest) {
14478                 assertEquals(
14479                         expectedDefaultNetwork,
14480                         defaultNetwork);
14481                 // Make sure this value doesn't change.
14482                 assertEquals(1, defaultRequest.mRequests.size());
14483                 continue;
14484             }
14485             assertEquals(expectedPerAppNetwork, defaultNetwork);
14486             assertEquals(expectedOemRequestsSize, defaultRequest.mRequests.size());
14487         }
14488         verifyMultipleDefaultCallbacks(expectedDefaultNetwork, expectedPerAppNetwork);
14489     }
14490 
14491     /**
14492      * Verify default callbacks for 'available' fire as expected. This will only run if
14493      * registerDefaultNetworkCallbacks() was executed prior and will only be different if the
14494      * setOemNetworkPreference() per-app API was used for the current process.
14495      * @param expectedSystemDefault the expected network for the system default.
14496      * @param expectedPerAppDefault the expected network for the current process's default.
14497      */
14498     private void verifyMultipleDefaultCallbacks(
14499             @NonNull final Network expectedSystemDefault,
14500             @NonNull final Network expectedPerAppDefault) {
14501         if (null != mSystemDefaultNetworkCallback && null != expectedSystemDefault
14502                 && mService.mNoServiceNetwork.network() != expectedSystemDefault) {
14503             // getLastAvailableNetwork() is used as this method can be called successively with
14504             // the same network to validate therefore expectAvailableThenValidatedCallbacks
14505             // can't be used.
14506             assertEquals(mSystemDefaultNetworkCallback.getLastAvailableNetwork(),
14507                     expectedSystemDefault);
14508         }
14509         if (null != mDefaultNetworkCallback && null != expectedPerAppDefault
14510                 && mService.mNoServiceNetwork.network() != expectedPerAppDefault) {
14511             assertEquals(mDefaultNetworkCallback.getLastAvailableNetwork(),
14512                     expectedPerAppDefault);
14513         }
14514     }
14515 
14516     private void registerDefaultNetworkCallbacks() {
14517         if (mSystemDefaultNetworkCallback != null || mDefaultNetworkCallback != null
14518                 || mProfileDefaultNetworkCallback != null
14519                 || mProfileDefaultNetworkCallbackAsAppUid2 != null
14520                 || mTestPackageDefaultNetworkCallback2 != null
14521                 || mTestPackageDefaultNetworkCallback != null) {
14522             throw new IllegalStateException("Default network callbacks already registered");
14523         }
14524 
14525         mSystemDefaultNetworkCallback = new TestNetworkCallback();
14526         mDefaultNetworkCallback = new TestNetworkCallback();
14527         mProfileDefaultNetworkCallback = new TestNetworkCallback();
14528         mTestPackageDefaultNetworkCallback = new TestNetworkCallback();
14529         mProfileDefaultNetworkCallbackAsAppUid2 = new TestNetworkCallback();
14530         mTestPackageDefaultNetworkCallback2 = new TestNetworkCallback();
14531         mCm.registerSystemDefaultNetworkCallback(mSystemDefaultNetworkCallback,
14532                 new Handler(ConnectivityThread.getInstanceLooper()));
14533         mCm.registerDefaultNetworkCallback(mDefaultNetworkCallback);
14534         registerDefaultNetworkCallbackAsUid(mProfileDefaultNetworkCallback,
14535                 TEST_WORK_PROFILE_APP_UID);
14536         registerDefaultNetworkCallbackAsUid(mTestPackageDefaultNetworkCallback, TEST_PACKAGE_UID);
14537         registerDefaultNetworkCallbackAsUid(mProfileDefaultNetworkCallbackAsAppUid2,
14538                 TEST_WORK_PROFILE_APP_UID_2);
14539         registerDefaultNetworkCallbackAsUid(mTestPackageDefaultNetworkCallback2,
14540                 TEST_PACKAGE_UID2);
14541         // TODO: test using ConnectivityManager#registerDefaultNetworkCallbackAsUid as well.
14542         mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_DENIED);
14543     }
14544 
14545     private void unregisterDefaultNetworkCallbacks() {
14546         if (null != mDefaultNetworkCallback) {
14547             mCm.unregisterNetworkCallback(mDefaultNetworkCallback);
14548         }
14549         if (null != mSystemDefaultNetworkCallback) {
14550             mCm.unregisterNetworkCallback(mSystemDefaultNetworkCallback);
14551         }
14552         if (null != mProfileDefaultNetworkCallback) {
14553             mCm.unregisterNetworkCallback(mProfileDefaultNetworkCallback);
14554         }
14555         if (null != mTestPackageDefaultNetworkCallback) {
14556             mCm.unregisterNetworkCallback(mTestPackageDefaultNetworkCallback);
14557         }
14558         if (null != mProfileDefaultNetworkCallbackAsAppUid2) {
14559             mCm.unregisterNetworkCallback(mProfileDefaultNetworkCallbackAsAppUid2);
14560         }
14561         if (null != mTestPackageDefaultNetworkCallback2) {
14562             mCm.unregisterNetworkCallback(mTestPackageDefaultNetworkCallback2);
14563         }
14564         mSystemDefaultNetworkCallback = null;
14565         mDefaultNetworkCallback = null;
14566         mProfileDefaultNetworkCallback = null;
14567         mTestPackageDefaultNetworkCallback = null;
14568         mProfileDefaultNetworkCallbackAsAppUid2 = null;
14569         mTestPackageDefaultNetworkCallback2 = null;
14570     }
14571 
14572     private void setupMultipleDefaultNetworksForOemNetworkPreferenceNotCurrentUidTest(
14573             @OemNetworkPreferences.OemNetworkPreference final int networkPrefToSetup)
14574             throws Exception {
14575         final int testPackageNameUid = TEST_PACKAGE_UID;
14576         final String testPackageName = "per.app.defaults.package";
14577         setupMultipleDefaultNetworksForOemNetworkPreferenceTest(
14578                 networkPrefToSetup, testPackageNameUid, testPackageName);
14579     }
14580 
14581     private void setupMultipleDefaultNetworksForOemNetworkPreferenceCurrentUidTest(
14582             @OemNetworkPreferences.OemNetworkPreference final int networkPrefToSetup)
14583             throws Exception {
14584         final int testPackageNameUid = Process.myUid();
14585         final String testPackageName = "per.app.defaults.package";
14586         setupMultipleDefaultNetworksForOemNetworkPreferenceTest(
14587                 networkPrefToSetup, testPackageNameUid, testPackageName);
14588     }
14589 
14590     private void setupMultipleDefaultNetworksForOemNetworkPreferenceTest(
14591             @OemNetworkPreferences.OemNetworkPreference final int networkPrefToSetup,
14592             final int testPackageUid, @NonNull final String testPackageName) throws Exception {
14593         // Only the default request should be included at start.
14594         assertEquals(1, mService.mDefaultNetworkRequests.size());
14595 
14596         final UidRangeParcel[] uidRanges =
14597                 toUidRangeStableParcels(uidRangesForUids(testPackageUid));
14598         setupSetOemNetworkPreferenceForPreferenceTest(
14599                 networkPrefToSetup, uidRanges, testPackageName);
14600     }
14601 
14602     private void setupSetOemNetworkPreferenceForPreferenceTest(
14603             @OemNetworkPreferences.OemNetworkPreference final int networkPrefToSetup,
14604             @NonNull final UidRangeParcel[] uidRanges,
14605             @NonNull final String testPackageName) throws Exception {
14606         setupSetOemNetworkPreferenceForPreferenceTest(networkPrefToSetup, uidRanges,
14607                 testPackageName, PRIMARY_USER_HANDLE, true /* hasAutomotiveFeature */);
14608     }
14609 
14610     private void setupSetOemNetworkPreferenceForPreferenceTest(
14611             @OemNetworkPreferences.OemNetworkPreference final int networkPrefToSetup,
14612             @NonNull final UidRangeParcel[] uidRanges,
14613             @NonNull final String testPackageName,
14614             @NonNull final UserHandle user) throws Exception {
14615         setupSetOemNetworkPreferenceForPreferenceTest(networkPrefToSetup, uidRanges,
14616                 testPackageName, user, true /* hasAutomotiveFeature */);
14617     }
14618 
14619     private void setupSetOemNetworkPreferenceForPreferenceTest(
14620             @OemNetworkPreferences.OemNetworkPreference final int networkPrefToSetup,
14621             @NonNull final UidRangeParcel[] uidRanges,
14622             @NonNull final String testPackageName,
14623             @NonNull final UserHandle user,
14624             final boolean hasAutomotiveFeature) throws Exception {
14625         mockHasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, hasAutomotiveFeature);
14626 
14627         // These tests work off a single UID therefore using 'start' is valid.
14628         mockGetApplicationInfo(testPackageName, uidRanges[0].start, user);
14629 
14630         setOemNetworkPreference(networkPrefToSetup, testPackageName);
14631     }
14632 
14633     private void setOemNetworkPreference(final int networkPrefToSetup,
14634             @NonNull final String... testPackageNames)
14635             throws Exception {
14636         mockHasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, true);
14637 
14638         // Build OemNetworkPreferences object
14639         final OemNetworkPreferences.Builder builder = new OemNetworkPreferences.Builder();
14640         for (final String packageName : testPackageNames) {
14641             builder.addNetworkPreference(packageName, networkPrefToSetup);
14642         }
14643         final OemNetworkPreferences pref = builder.build();
14644 
14645         // Act on ConnectivityService.setOemNetworkPreference()
14646         final TestOemListenerCallback oemPrefListener = new TestOemListenerCallback();
14647         mService.setOemNetworkPreference(pref, oemPrefListener);
14648 
14649         // Verify call returned successfully
14650         oemPrefListener.expectOnComplete();
14651     }
14652 
14653     private static class TestOemListenerCallback implements IOnCompleteListener {
14654         final CompletableFuture<Object> mDone = new CompletableFuture<>();
14655 
14656         @Override
14657         public void onComplete() {
14658             mDone.complete(new Object());
14659         }
14660 
14661         void expectOnComplete() {
14662             try {
14663                 mDone.get(TIMEOUT_MS, TimeUnit.MILLISECONDS);
14664             } catch (TimeoutException e) {
14665                 fail("Expected onComplete() not received after " + TIMEOUT_MS + " ms");
14666             } catch (Exception e) {
14667                 fail(e.getMessage());
14668             }
14669         }
14670 
14671         @Override
14672         public IBinder asBinder() {
14673             return null;
14674         }
14675     }
14676 
14677     @Test
14678     public void testMultiDefaultGetActiveNetworkIsCorrect() throws Exception {
14679         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
14680                 OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY;
14681         final int expectedOemPrefRequestSize = 1;
14682         registerDefaultNetworkCallbacks();
14683 
14684         // Setup the test process to use networkPref for their default network.
14685         setupMultipleDefaultNetworksForOemNetworkPreferenceCurrentUidTest(networkPref);
14686 
14687         // Bring up ethernet with OEM_PAID. This will satisfy NET_CAPABILITY_OEM_PAID.
14688         // The active network for the default should be null at this point as this is a retricted
14689         // network.
14690         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, true);
14691         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
14692                 null,
14693                 mEthernetAgent.getNetwork());
14694 
14695         // Verify that the active network is correct
14696         verifyActiveNetwork(TRANSPORT_ETHERNET);
14697         // default NCs will be unregistered in tearDown
14698     }
14699 
14700     @Test
14701     public void testMultiDefaultIsActiveNetworkMeteredIsCorrect() throws Exception {
14702         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
14703                 OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY;
14704         final int expectedOemPrefRequestSize = 1;
14705         registerDefaultNetworkCallbacks();
14706 
14707         // Setup the test process to use networkPref for their default network.
14708         setupMultipleDefaultNetworksForOemNetworkPreferenceCurrentUidTest(networkPref);
14709 
14710         // Returns true by default when no network is available.
14711         assertTrue(mCm.isActiveNetworkMetered());
14712 
14713         // Connect to an unmetered restricted network that will only be available to the OEM pref.
14714         mEthernetAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
14715         mEthernetAgent.addCapability(NET_CAPABILITY_OEM_PAID);
14716         mEthernetAgent.addCapability(NET_CAPABILITY_NOT_METERED);
14717         mEthernetAgent.removeCapability(NET_CAPABILITY_NOT_RESTRICTED);
14718         mEthernetAgent.connect(true);
14719         waitForIdle();
14720 
14721         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
14722                 null,
14723                 mEthernetAgent.getNetwork());
14724 
14725         assertFalse(mCm.isActiveNetworkMetered());
14726         // default NCs will be unregistered in tearDown
14727     }
14728 
14729     @Test
14730     public void testPerAppDefaultRegisterDefaultNetworkCallback() throws Exception {
14731         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
14732                 OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY;
14733         final int expectedOemPrefRequestSize = 1;
14734         final TestNetworkCallback defaultNetworkCallback = new TestNetworkCallback();
14735 
14736         // Register the default network callback before the pref is already set. This means that
14737         // the policy will be applied to the callback on setOemNetworkPreference().
14738         mCm.registerDefaultNetworkCallback(defaultNetworkCallback);
14739         defaultNetworkCallback.assertNoCallback();
14740 
14741         final TestNetworkCallback otherUidDefaultCallback = new TestNetworkCallback();
14742         withPermission(NETWORK_SETTINGS, () ->
14743                 mCm.registerDefaultNetworkCallbackForUid(TEST_PACKAGE_UID, otherUidDefaultCallback,
14744                         new Handler(ConnectivityThread.getInstanceLooper())));
14745 
14746         // Setup the test process to use networkPref for their default network.
14747         setupMultipleDefaultNetworksForOemNetworkPreferenceCurrentUidTest(networkPref);
14748 
14749         // Bring up ethernet with OEM_PAID. This will satisfy NET_CAPABILITY_OEM_PAID.
14750         // The active nai for the default is null at this point as this is a restricted network.
14751         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, true);
14752         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
14753                 null,
14754                 mEthernetAgent.getNetwork());
14755 
14756         // At this point with a restricted network used, the available callback should trigger.
14757         defaultNetworkCallback.expectAvailableThenValidatedCallbacks(mEthernetAgent);
14758         assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mEthernetAgent.getNetwork());
14759         otherUidDefaultCallback.assertNoCallback();
14760 
14761         // Now bring down the default network which should trigger a LOST callback.
14762         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, false);
14763 
14764         // At this point, with no network is available, the lost callback should trigger
14765         defaultNetworkCallback.expect(LOST, mEthernetAgent);
14766         otherUidDefaultCallback.assertNoCallback();
14767 
14768         // Confirm we can unregister without issues.
14769         mCm.unregisterNetworkCallback(defaultNetworkCallback);
14770         mCm.unregisterNetworkCallback(otherUidDefaultCallback);
14771     }
14772 
14773     @Test
14774     public void testPerAppDefaultRegisterDefaultNetworkCallbackAfterPrefSet() throws Exception {
14775         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
14776                 OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY;
14777         final int expectedOemPrefRequestSize = 1;
14778         final TestNetworkCallback defaultNetworkCallback = new TestNetworkCallback();
14779 
14780         // Setup the test process to use networkPref for their default network.
14781         setupMultipleDefaultNetworksForOemNetworkPreferenceCurrentUidTest(networkPref);
14782 
14783         // Register the default network callback after the pref is already set. This means that
14784         // the policy will be applied to the callback on requestNetwork().
14785         mCm.registerDefaultNetworkCallback(defaultNetworkCallback);
14786         defaultNetworkCallback.assertNoCallback();
14787 
14788         final TestNetworkCallback otherUidDefaultCallback = new TestNetworkCallback();
14789         withPermission(NETWORK_SETTINGS, () ->
14790                 mCm.registerDefaultNetworkCallbackForUid(TEST_PACKAGE_UID, otherUidDefaultCallback,
14791                         new Handler(ConnectivityThread.getInstanceLooper())));
14792 
14793         // Bring up ethernet with OEM_PAID. This will satisfy NET_CAPABILITY_OEM_PAID.
14794         // The active nai for the default is null at this point as this is a restricted network.
14795         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, true);
14796         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
14797                 null,
14798                 mEthernetAgent.getNetwork());
14799 
14800         // At this point with a restricted network used, the available callback should trigger
14801         defaultNetworkCallback.expectAvailableThenValidatedCallbacks(mEthernetAgent);
14802         assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mEthernetAgent.getNetwork());
14803         otherUidDefaultCallback.assertNoCallback();
14804 
14805         // Now bring down the default network which should trigger a LOST callback.
14806         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, false);
14807         otherUidDefaultCallback.assertNoCallback();
14808 
14809         // At this point, with no network is available, the lost callback should trigger
14810         defaultNetworkCallback.expect(LOST, mEthernetAgent);
14811         otherUidDefaultCallback.assertNoCallback();
14812 
14813         // Confirm we can unregister without issues.
14814         mCm.unregisterNetworkCallback(defaultNetworkCallback);
14815         mCm.unregisterNetworkCallback(otherUidDefaultCallback);
14816     }
14817 
14818     @Test
14819     public void testPerAppDefaultRegisterDefaultNetworkCallbackDoesNotFire() throws Exception {
14820         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
14821                 OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY;
14822         final int expectedOemPrefRequestSize = 1;
14823         final TestNetworkCallback defaultNetworkCallback = new TestNetworkCallback();
14824         final int userId = UserHandle.getUserId(Process.myUid());
14825 
14826         mCm.registerDefaultNetworkCallback(defaultNetworkCallback);
14827         defaultNetworkCallback.assertNoCallback();
14828 
14829         final TestNetworkCallback otherUidDefaultCallback = new TestNetworkCallback();
14830         withPermission(NETWORK_SETTINGS, () ->
14831                 mCm.registerDefaultNetworkCallbackForUid(TEST_PACKAGE_UID, otherUidDefaultCallback,
14832                         new Handler(ConnectivityThread.getInstanceLooper())));
14833 
14834         // Setup a process different than the test process to use the default network. This means
14835         // that the defaultNetworkCallback won't be tracked by the per-app policy.
14836         setupMultipleDefaultNetworksForOemNetworkPreferenceNotCurrentUidTest(networkPref);
14837 
14838         // Bring up ethernet with OEM_PAID. This will satisfy NET_CAPABILITY_OEM_PAID.
14839         // The active nai for the default is null at this point as this is a restricted network.
14840         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, true);
14841         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
14842                 null,
14843                 mEthernetAgent.getNetwork());
14844 
14845         // As this callback does not have access to the OEM_PAID network, it will not fire.
14846         defaultNetworkCallback.assertNoCallback();
14847         assertDefaultNetworkCapabilities(userId /* no networks */);
14848 
14849         // The other UID does have access, and gets a callback.
14850         otherUidDefaultCallback.expectAvailableThenValidatedCallbacks(mEthernetAgent);
14851 
14852         // Bring up unrestricted cellular. This should now satisfy the default network.
14853         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true);
14854         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
14855                 mCellAgent.getNetwork(),
14856                 mEthernetAgent.getNetwork());
14857 
14858         // At this point with an unrestricted network used, the available callback should trigger
14859         // The other UID is unaffected and remains on the paid network.
14860         defaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
14861         assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCellAgent.getNetwork());
14862         assertDefaultNetworkCapabilities(userId, mCellAgent);
14863         otherUidDefaultCallback.assertNoCallback();
14864 
14865         // Now bring down the per-app network.
14866         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, false);
14867 
14868         // Since the callback didn't use the per-app network, only the other UID gets a callback.
14869         // Because the preference specifies no fallback, it does not switch to cellular.
14870         defaultNetworkCallback.assertNoCallback();
14871         otherUidDefaultCallback.expect(LOST, mEthernetAgent);
14872 
14873         // Now bring down the default network.
14874         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, false);
14875 
14876         // As this callback was tracking the default, this should now trigger.
14877         defaultNetworkCallback.expect(LOST, mCellAgent);
14878         otherUidDefaultCallback.assertNoCallback();
14879 
14880         // Confirm we can unregister without issues.
14881         mCm.unregisterNetworkCallback(defaultNetworkCallback);
14882         mCm.unregisterNetworkCallback(otherUidDefaultCallback);
14883     }
14884 
14885     /**
14886      * This method assumes that the same uidRanges input will be used to verify that dependencies
14887      * are called as expected.
14888      */
14889     private void verifySetOemNetworkPreferenceForPreference(
14890             @NonNull final UidRangeParcel[] uidRanges,
14891             final int addUidRangesNetId,
14892             final int addUidRangesTimes,
14893             final int removeUidRangesNetId,
14894             final int removeUidRangesTimes,
14895             final boolean shouldDestroyNetwork) throws RemoteException {
14896         verifySetOemNetworkPreferenceForPreference(uidRanges, uidRanges,
14897                 addUidRangesNetId, addUidRangesTimes, removeUidRangesNetId, removeUidRangesTimes,
14898                 shouldDestroyNetwork);
14899     }
14900 
14901     private void verifySetOemNetworkPreferenceForPreference(
14902             @NonNull final UidRangeParcel[] addedUidRanges,
14903             @NonNull final UidRangeParcel[] removedUidRanges,
14904             final int addUidRangesNetId,
14905             final int addUidRangesTimes,
14906             final int removeUidRangesNetId,
14907             final int removeUidRangesTimes,
14908             final boolean shouldDestroyNetwork) throws RemoteException {
14909         final boolean useAnyIdForAdd = OEM_PREF_ANY_NET_ID == addUidRangesNetId;
14910         final boolean useAnyIdForRemove = OEM_PREF_ANY_NET_ID == removeUidRangesNetId;
14911 
14912         // Validate that add/remove uid range (with oem priority) to/from netd.
14913         verify(mMockNetd, times(addUidRangesTimes)).networkAddUidRangesParcel(argThat(config ->
14914                 (useAnyIdForAdd ? true : addUidRangesNetId == config.netId)
14915                         && Arrays.equals(addedUidRanges, config.uidRanges)
14916                         && PREFERENCE_ORDER_OEM == config.subPriority));
14917         verify(mMockNetd, times(removeUidRangesTimes)).networkRemoveUidRangesParcel(
14918                 argThat(config -> (useAnyIdForRemove ? true : removeUidRangesNetId == config.netId)
14919                         && Arrays.equals(removedUidRanges, config.uidRanges)
14920                         && PREFERENCE_ORDER_OEM == config.subPriority));
14921         if (shouldDestroyNetwork) {
14922             verify(mMockNetd, times(1))
14923                     .networkDestroy((useAnyIdForRemove ? anyInt() : eq(removeUidRangesNetId)));
14924         }
14925         reset(mMockNetd);
14926     }
14927 
14928     /**
14929      * Test the tracked default requests allows test requests without standard setup.
14930      */
14931     @Test
14932     public void testSetOemNetworkPreferenceAllowsValidTestRequestWithoutChecks() throws Exception {
14933         @OemNetworkPreferences.OemNetworkPreference int networkPref =
14934                 OEM_NETWORK_PREFERENCE_TEST;
14935         validateSetOemNetworkPreferenceAllowsValidTestPrefRequest(networkPref);
14936     }
14937 
14938     /**
14939      * Test the tracked default requests allows test only requests without standard setup.
14940      */
14941     @Test
14942     public void testSetOemNetworkPreferenceAllowsValidTestOnlyRequestWithoutChecks()
14943             throws Exception {
14944         @OemNetworkPreferences.OemNetworkPreference int networkPref =
14945                 OEM_NETWORK_PREFERENCE_TEST_ONLY;
14946         validateSetOemNetworkPreferenceAllowsValidTestPrefRequest(networkPref);
14947     }
14948 
14949     private void validateSetOemNetworkPreferenceAllowsValidTestPrefRequest(int networkPref)
14950             throws Exception {
14951         // The caller must have the MANAGE_TEST_NETWORKS permission.
14952         final int testPackageUid = 123;
14953         final String validTestPackageName = "does.not.matter";
14954         final UidRangeParcel[] uidRanges =
14955                 toUidRangeStableParcels(uidRangesForUids(testPackageUid));
14956         mServiceContext.setPermission(
14957                 Manifest.permission.MANAGE_TEST_NETWORKS, PERMISSION_GRANTED);
14958 
14959         // Put the system into a state in which setOemNetworkPreference() would normally fail. This
14960         // will confirm that a valid test request can bypass these checks.
14961         mockHasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, false);
14962         mServiceContext.setPermission(
14963                 Manifest.permission.CONTROL_OEM_PAID_NETWORK_PREFERENCE, PERMISSION_DENIED);
14964 
14965         // Validate the starting requests only includes the system default request.
14966         assertEquals(1, mService.mDefaultNetworkRequests.size());
14967 
14968         // Add an OEM default network request to track.
14969         setupSetOemNetworkPreferenceForPreferenceTest(
14970                 networkPref, uidRanges, validTestPackageName, PRIMARY_USER_HANDLE,
14971                 false /* hasAutomotiveFeature */);
14972 
14973         // Two requests should now exist; the system default and the test request.
14974         assertEquals(2, mService.mDefaultNetworkRequests.size());
14975     }
14976 
14977     /**
14978      * Test the tracked default requests clear previous OEM requests on setOemNetworkPreference().
14979      */
14980     @Test
14981     public void testSetOemNetworkPreferenceClearPreviousOemValues() throws Exception {
14982         @OemNetworkPreferences.OemNetworkPreference int networkPref =
14983                 OEM_NETWORK_PREFERENCE_OEM_PAID;
14984         final int testPackageUid = 123;
14985         final String testPackageName = "com.google.apps.contacts";
14986         final UidRangeParcel[] uidRanges =
14987                 toUidRangeStableParcels(uidRangesForUids(testPackageUid));
14988 
14989         // Validate the starting requests only includes the system default request.
14990         assertEquals(1, mService.mDefaultNetworkRequests.size());
14991 
14992         // Add an OEM default network request to track.
14993         setupSetOemNetworkPreferenceForPreferenceTest(networkPref, uidRanges, testPackageName);
14994 
14995         // Two requests should exist, one for the fallback and one for the pref.
14996         assertEquals(2, mService.mDefaultNetworkRequests.size());
14997 
14998         networkPref = OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY;
14999         setupSetOemNetworkPreferenceForPreferenceTest(networkPref, uidRanges, testPackageName);
15000 
15001         // Two requests should still exist validating the previous per-app request was replaced.
15002         assertEquals(2, mService.mDefaultNetworkRequests.size());
15003     }
15004 
15005     /**
15006      * Test network priority for preference OEM_NETWORK_PREFERENCE_OEM_PAID in the following order:
15007      * NET_CAPABILITY_NOT_METERED -> NET_CAPABILITY_OEM_PAID -> fallback
15008      */
15009     @Test
15010     public void testMultilayerForPreferenceOemPaidEvaluatesCorrectly()
15011             throws Exception {
15012         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
15013                 OEM_NETWORK_PREFERENCE_OEM_PAID;
15014 
15015         // Arrange PackageManager mocks
15016         final UidRangeParcel[] uidRanges =
15017                 toUidRangeStableParcels(uidRangesForUids(TEST_PACKAGE_UID));
15018         setupSetOemNetworkPreferenceForPreferenceTest(networkPref, uidRanges, TEST_PACKAGE_NAME);
15019 
15020         // Verify the starting state. No networks should be connected.
15021         verifySetOemNetworkPreferenceForPreference(uidRanges,
15022                 OEM_PREF_ANY_NET_ID, 0 /* times */,
15023                 OEM_PREF_ANY_NET_ID, 0 /* times */,
15024                 false /* shouldDestroyNetwork */);
15025 
15026         // Test lowest to highest priority requests.
15027         // Bring up metered cellular. This will satisfy the fallback network.
15028         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true);
15029         verifySetOemNetworkPreferenceForPreference(uidRanges,
15030                 mCellAgent.getNetwork().netId, 1 /* times */,
15031                 OEM_PREF_ANY_NET_ID, 0 /* times */,
15032                 false /* shouldDestroyNetwork */);
15033 
15034         // Bring up ethernet with OEM_PAID. This will satisfy NET_CAPABILITY_OEM_PAID.
15035         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, true);
15036         verifySetOemNetworkPreferenceForPreference(uidRanges,
15037                 mEthernetAgent.getNetwork().netId, 1 /* times */,
15038                 mCellAgent.getNetwork().netId, 1 /* times */,
15039                 false /* shouldDestroyNetwork */);
15040 
15041         // Bring up unmetered Wi-Fi. This will satisfy NET_CAPABILITY_NOT_METERED.
15042         setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, true);
15043         verifySetOemNetworkPreferenceForPreference(uidRanges,
15044                 mWiFiAgent.getNetwork().netId, 1 /* times */,
15045                 mEthernetAgent.getNetwork().netId, 1 /* times */,
15046                 false /* shouldDestroyNetwork */);
15047 
15048         // Disconnecting OEM_PAID should have no effect as it is lower in priority then unmetered.
15049         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, false);
15050         // netd should not be called as default networks haven't changed.
15051         verifySetOemNetworkPreferenceForPreference(uidRanges,
15052                 OEM_PREF_ANY_NET_ID, 0 /* times */,
15053                 OEM_PREF_ANY_NET_ID, 0 /* times */,
15054                 false /* shouldDestroyNetwork */);
15055 
15056         // Disconnecting unmetered should put PANS on lowest priority fallback request.
15057         setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, false);
15058         verifySetOemNetworkPreferenceForPreference(uidRanges,
15059                 mCellAgent.getNetwork().netId, 1 /* times */,
15060                 mWiFiAgent.getNetwork().netId, 0 /* times */,
15061                 true /* shouldDestroyNetwork */);
15062 
15063         // Disconnecting the fallback network should result in no connectivity.
15064         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, false);
15065         verifySetOemNetworkPreferenceForPreference(uidRanges,
15066                 OEM_PREF_ANY_NET_ID, 0 /* times */,
15067                 mCellAgent.getNetwork().netId, 0 /* times */,
15068                 true /* shouldDestroyNetwork */);
15069     }
15070 
15071     /**
15072      * Test network priority for OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK in the following order:
15073      * NET_CAPABILITY_NOT_METERED -> NET_CAPABILITY_OEM_PAID
15074      */
15075     @Test
15076     public void testMultilayerForPreferenceOemPaidNoFallbackEvaluatesCorrectly()
15077             throws Exception {
15078         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
15079                 OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK;
15080 
15081         // Arrange PackageManager mocks
15082         final UidRangeParcel[] uidRanges =
15083                 toUidRangeStableParcels(uidRangesForUids(TEST_PACKAGE_UID));
15084         setupSetOemNetworkPreferenceForPreferenceTest(networkPref, uidRanges, TEST_PACKAGE_NAME);
15085 
15086         // Verify the starting state. This preference doesn't support using the fallback network
15087         // therefore should be on the disconnected network as it has no networks to connect to.
15088         verifySetOemNetworkPreferenceForPreference(uidRanges,
15089                 mService.mNoServiceNetwork.network.getNetId(), 1 /* times */,
15090                 OEM_PREF_ANY_NET_ID, 0 /* times */,
15091                 false /* shouldDestroyNetwork */);
15092 
15093         // Test lowest to highest priority requests.
15094         // Bring up metered cellular. This will satisfy the fallback network.
15095         // This preference should not use this network as it doesn't support fallback usage.
15096         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true);
15097         verifySetOemNetworkPreferenceForPreference(uidRanges,
15098                 OEM_PREF_ANY_NET_ID, 0 /* times */,
15099                 OEM_PREF_ANY_NET_ID, 0 /* times */,
15100                 false /* shouldDestroyNetwork */);
15101 
15102         // Bring up ethernet with OEM_PAID. This will satisfy NET_CAPABILITY_OEM_PAID.
15103         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, true);
15104         verifySetOemNetworkPreferenceForPreference(uidRanges,
15105                 mEthernetAgent.getNetwork().netId, 1 /* times */,
15106                 mService.mNoServiceNetwork.network.getNetId(), 1 /* times */,
15107                 false /* shouldDestroyNetwork */);
15108 
15109         // Bring up unmetered Wi-Fi. This will satisfy NET_CAPABILITY_NOT_METERED.
15110         setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, true);
15111         verifySetOemNetworkPreferenceForPreference(uidRanges,
15112                 mWiFiAgent.getNetwork().netId, 1 /* times */,
15113                 mEthernetAgent.getNetwork().netId, 1 /* times */,
15114                 false /* shouldDestroyNetwork */);
15115 
15116         // Disconnecting unmetered should put PANS on OEM_PAID.
15117         setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, false);
15118         verifySetOemNetworkPreferenceForPreference(uidRanges,
15119                 mEthernetAgent.getNetwork().netId, 1 /* times */,
15120                 mWiFiAgent.getNetwork().netId, 0 /* times */,
15121                 true /* shouldDestroyNetwork */);
15122 
15123         // Disconnecting OEM_PAID should result in no connectivity.
15124         // OEM_PAID_NO_FALLBACK not supporting a fallback now uses the disconnected network.
15125         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, false);
15126         verifySetOemNetworkPreferenceForPreference(uidRanges,
15127                 mService.mNoServiceNetwork.network.getNetId(), 1 /* times */,
15128                 mEthernetAgent.getNetwork().netId, 0 /* times */,
15129                 true /* shouldDestroyNetwork */);
15130     }
15131 
15132     /**
15133      * Test network priority for OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY in the following order:
15134      * NET_CAPABILITY_OEM_PAID
15135      * This preference should only apply to OEM_PAID networks.
15136      */
15137     @Test
15138     public void testMultilayerForPreferenceOemPaidOnlyEvaluatesCorrectly()
15139             throws Exception {
15140         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
15141                 OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY;
15142 
15143         // Arrange PackageManager mocks
15144         final UidRangeParcel[] uidRanges =
15145                 toUidRangeStableParcels(uidRangesForUids(TEST_PACKAGE_UID));
15146         setupSetOemNetworkPreferenceForPreferenceTest(networkPref, uidRanges, TEST_PACKAGE_NAME);
15147 
15148         // Verify the starting state. This preference doesn't support using the fallback network
15149         // therefore should be on the disconnected network as it has no networks to connect to.
15150         verifySetOemNetworkPreferenceForPreference(uidRanges,
15151                 mService.mNoServiceNetwork.network.getNetId(), 1 /* times */,
15152                 OEM_PREF_ANY_NET_ID, 0 /* times */,
15153                 false /* shouldDestroyNetwork */);
15154 
15155         // Bring up metered cellular. This should not apply to this preference.
15156         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true);
15157         verifySetOemNetworkPreferenceForPreference(uidRanges,
15158                 OEM_PREF_ANY_NET_ID, 0 /* times */,
15159                 OEM_PREF_ANY_NET_ID, 0 /* times */,
15160                 false /* shouldDestroyNetwork */);
15161 
15162         // Bring up unmetered Wi-Fi. This should not apply to this preference.
15163         setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, true);
15164         verifySetOemNetworkPreferenceForPreference(uidRanges,
15165                 OEM_PREF_ANY_NET_ID, 0 /* times */,
15166                 OEM_PREF_ANY_NET_ID, 0 /* times */,
15167                 false /* shouldDestroyNetwork */);
15168 
15169         // Bring up ethernet with OEM_PAID. This will satisfy NET_CAPABILITY_OEM_PAID.
15170         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, true);
15171         verifySetOemNetworkPreferenceForPreference(uidRanges,
15172                 mEthernetAgent.getNetwork().netId, 1 /* times */,
15173                 mService.mNoServiceNetwork.network.getNetId(), 1 /* times */,
15174                 false /* shouldDestroyNetwork */);
15175 
15176         // Disconnecting OEM_PAID should result in no connectivity.
15177         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, false);
15178         verifySetOemNetworkPreferenceForPreference(uidRanges,
15179                 mService.mNoServiceNetwork.network.getNetId(), 1 /* times */,
15180                 mEthernetAgent.getNetwork().netId, 0 /* times */,
15181                 true /* shouldDestroyNetwork */);
15182     }
15183 
15184     /**
15185      * Test network priority for OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY in the following order:
15186      * NET_CAPABILITY_OEM_PRIVATE
15187      * This preference should only apply to OEM_PRIVATE networks.
15188      */
15189     @Test
15190     public void testMultilayerForPreferenceOemPrivateOnlyEvaluatesCorrectly()
15191             throws Exception {
15192         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
15193                 OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY;
15194 
15195         // Arrange PackageManager mocks
15196         final UidRangeParcel[] uidRanges =
15197                 toUidRangeStableParcels(uidRangesForUids(TEST_PACKAGE_UID));
15198         setupSetOemNetworkPreferenceForPreferenceTest(networkPref, uidRanges, TEST_PACKAGE_NAME);
15199 
15200         // Verify the starting state. This preference doesn't support using the fallback network
15201         // therefore should be on the disconnected network as it has no networks to connect to.
15202         verifySetOemNetworkPreferenceForPreference(uidRanges,
15203                 mService.mNoServiceNetwork.network.getNetId(), 1 /* times */,
15204                 OEM_PREF_ANY_NET_ID, 0 /* times */,
15205                 false /* shouldDestroyNetwork */);
15206 
15207         // Bring up metered cellular. This should not apply to this preference.
15208         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true);
15209         verifySetOemNetworkPreferenceForPreference(uidRanges,
15210                 OEM_PREF_ANY_NET_ID, 0 /* times */,
15211                 OEM_PREF_ANY_NET_ID, 0 /* times */,
15212                 false /* shouldDestroyNetwork */);
15213 
15214         // Bring up unmetered Wi-Fi. This should not apply to this preference.
15215         setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, true);
15216         verifySetOemNetworkPreferenceForPreference(uidRanges,
15217                 OEM_PREF_ANY_NET_ID, 0 /* times */,
15218                 OEM_PREF_ANY_NET_ID, 0 /* times */,
15219                 false /* shouldDestroyNetwork */);
15220 
15221         // Bring up ethernet with OEM_PRIVATE. This will satisfy NET_CAPABILITY_OEM_PRIVATE.
15222         startOemManagedNetwork(false);
15223         verifySetOemNetworkPreferenceForPreference(uidRanges,
15224                 mEthernetAgent.getNetwork().netId, 1 /* times */,
15225                 mService.mNoServiceNetwork.network.getNetId(), 1 /* times */,
15226                 false /* shouldDestroyNetwork */);
15227 
15228         // Disconnecting OEM_PRIVATE should result in no connectivity.
15229         stopOemManagedNetwork();
15230         verifySetOemNetworkPreferenceForPreference(uidRanges,
15231                 mService.mNoServiceNetwork.network.getNetId(), 1 /* times */,
15232                 mEthernetAgent.getNetwork().netId, 0 /* times */,
15233                 true /* shouldDestroyNetwork */);
15234     }
15235 
15236     @Test
15237     public void testMultilayerForMultipleUsersEvaluatesCorrectly()
15238             throws Exception {
15239         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
15240                 OEM_NETWORK_PREFERENCE_OEM_PAID;
15241 
15242         // Arrange users
15243         final int secondUser = 10;
15244         final UserHandle secondUserHandle = new UserHandle(secondUser);
15245         doReturn(asList(PRIMARY_USER_HANDLE, secondUserHandle)).when(mUserManager)
15246                 .getUserHandles(anyBoolean());
15247 
15248         // Arrange PackageManager mocks
15249         final int secondUserTestPackageUid = UserHandle.getUid(secondUser, TEST_PACKAGE_UID);
15250         final UidRangeParcel[] uidRanges =
15251                 toUidRangeStableParcels(
15252                         uidRangesForUids(TEST_PACKAGE_UID, secondUserTestPackageUid));
15253         mockGetApplicationInfo(TEST_PACKAGE_NAME, secondUserTestPackageUid, secondUserHandle);
15254         setupSetOemNetworkPreferenceForPreferenceTest(networkPref, uidRanges, TEST_PACKAGE_NAME);
15255 
15256         // Verify the starting state. No networks should be connected.
15257         verifySetOemNetworkPreferenceForPreference(uidRanges,
15258                 OEM_PREF_ANY_NET_ID, 0 /* times */,
15259                 OEM_PREF_ANY_NET_ID, 0 /* times */,
15260                 false /* shouldDestroyNetwork */);
15261 
15262         // Test that we correctly add the expected values for multiple users.
15263         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true);
15264         verifySetOemNetworkPreferenceForPreference(uidRanges,
15265                 mCellAgent.getNetwork().netId, 1 /* times */,
15266                 OEM_PREF_ANY_NET_ID, 0 /* times */,
15267                 false /* shouldDestroyNetwork */);
15268 
15269         // Test that we correctly remove the expected values for multiple users.
15270         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, false);
15271         verifySetOemNetworkPreferenceForPreference(uidRanges,
15272                 OEM_PREF_ANY_NET_ID, 0 /* times */,
15273                 mCellAgent.getNetwork().netId, 0 /* times */,
15274                 true /* shouldDestroyNetwork */);
15275     }
15276 
15277     @Test
15278     public void testMultilayerForBroadcastedUsersEvaluatesCorrectly()
15279             throws Exception {
15280         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
15281                 OEM_NETWORK_PREFERENCE_OEM_PAID;
15282 
15283         // Arrange users
15284         final int secondUser = 10;
15285         final UserHandle secondUserHandle = new UserHandle(secondUser);
15286         doReturn(asList(PRIMARY_USER_HANDLE)).when(mUserManager).getUserHandles(anyBoolean());
15287 
15288         // Arrange PackageManager mocks
15289         final int secondUserTestPackageUid = UserHandle.getUid(secondUser, TEST_PACKAGE_UID);
15290         final UidRangeParcel[] uidRangesSingleUser =
15291                 toUidRangeStableParcels(uidRangesForUids(TEST_PACKAGE_UID));
15292         final UidRangeParcel[] uidRangesBothUsers =
15293                 toUidRangeStableParcels(
15294                         uidRangesForUids(TEST_PACKAGE_UID, secondUserTestPackageUid));
15295         mockGetApplicationInfo(TEST_PACKAGE_NAME, secondUserTestPackageUid, secondUserHandle);
15296         setupSetOemNetworkPreferenceForPreferenceTest(
15297                 networkPref, uidRangesSingleUser, TEST_PACKAGE_NAME);
15298 
15299         // Verify the starting state. No networks should be connected.
15300         verifySetOemNetworkPreferenceForPreference(uidRangesSingleUser,
15301                 OEM_PREF_ANY_NET_ID, 0 /* times */,
15302                 OEM_PREF_ANY_NET_ID, 0 /* times */,
15303                 false /* shouldDestroyNetwork */);
15304 
15305         // Test that we correctly add the expected values for multiple users.
15306         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true);
15307         verifySetOemNetworkPreferenceForPreference(uidRangesSingleUser,
15308                 mCellAgent.getNetwork().netId, 1 /* times */,
15309                 OEM_PREF_ANY_NET_ID, 0 /* times */,
15310                 false /* shouldDestroyNetwork */);
15311 
15312         // Send a broadcast indicating a user was added.
15313         doReturn(asList(PRIMARY_USER_HANDLE, secondUserHandle)).when(mUserManager)
15314                 .getUserHandles(anyBoolean());
15315         final Intent addedIntent = new Intent(ACTION_USER_ADDED);
15316         addedIntent.putExtra(Intent.EXTRA_USER, UserHandle.of(secondUser));
15317         processBroadcast(addedIntent);
15318 
15319         // Test that we correctly add values for all users and remove for the single user.
15320         verifySetOemNetworkPreferenceForPreference(uidRangesBothUsers, uidRangesSingleUser,
15321                 mCellAgent.getNetwork().netId, 1 /* times */,
15322                 mCellAgent.getNetwork().netId, 1 /* times */,
15323                 false /* shouldDestroyNetwork */);
15324 
15325         // Send a broadcast indicating a user was removed.
15326         doReturn(asList(PRIMARY_USER_HANDLE)).when(mUserManager).getUserHandles(anyBoolean());
15327         final Intent removedIntent = new Intent(ACTION_USER_REMOVED);
15328         removedIntent.putExtra(Intent.EXTRA_USER, UserHandle.of(secondUser));
15329         processBroadcast(removedIntent);
15330 
15331         // Test that we correctly add values for the single user and remove for the all users.
15332         verifySetOemNetworkPreferenceForPreference(uidRangesSingleUser, uidRangesBothUsers,
15333                 mCellAgent.getNetwork().netId, 1 /* times */,
15334                 mCellAgent.getNetwork().netId, 1 /* times */,
15335                 false /* shouldDestroyNetwork */);
15336     }
15337 
15338     @Test
15339     public void testMultilayerForPackageChangesEvaluatesCorrectly()
15340             throws Exception {
15341         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
15342                 OEM_NETWORK_PREFERENCE_OEM_PAID;
15343         final String packageScheme = "package:";
15344 
15345         // Arrange PackageManager mocks
15346         final String packageToInstall = "package.to.install";
15347         final int packageToInstallUid = 81387;
15348         final UidRangeParcel[] uidRangesSinglePackage =
15349                 toUidRangeStableParcels(uidRangesForUids(TEST_PACKAGE_UID));
15350         mockGetApplicationInfo(TEST_PACKAGE_NAME, TEST_PACKAGE_UID);
15351         mockGetApplicationInfoThrowsNameNotFound(packageToInstall, PRIMARY_USER_HANDLE);
15352         setOemNetworkPreference(networkPref, TEST_PACKAGE_NAME, packageToInstall);
15353         grantUsingBackgroundNetworksPermissionForUid(Binder.getCallingUid(), packageToInstall);
15354 
15355         // Verify the starting state. No networks should be connected.
15356         verifySetOemNetworkPreferenceForPreference(uidRangesSinglePackage,
15357                 OEM_PREF_ANY_NET_ID, 0 /* times */,
15358                 OEM_PREF_ANY_NET_ID, 0 /* times */,
15359                 false /* shouldDestroyNetwork */);
15360 
15361         // Test that we correctly add the expected values for installed packages.
15362         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true);
15363         verifySetOemNetworkPreferenceForPreference(uidRangesSinglePackage,
15364                 mCellAgent.getNetwork().netId, 1 /* times */,
15365                 OEM_PREF_ANY_NET_ID, 0 /* times */,
15366                 false /* shouldDestroyNetwork */);
15367 
15368         // Set the system to recognize the package to be installed
15369         mockGetApplicationInfo(packageToInstall, packageToInstallUid);
15370         final UidRangeParcel[] uidRangesAllPackages =
15371                 toUidRangeStableParcels(uidRangesForUids(TEST_PACKAGE_UID, packageToInstallUid));
15372 
15373         // Send a broadcast indicating a package was installed.
15374         final Intent addedIntent = new Intent(ACTION_PACKAGE_ADDED);
15375         addedIntent.setData(Uri.parse(packageScheme + packageToInstall));
15376         processBroadcast(addedIntent);
15377 
15378         // Test the single package is removed and the combined packages are added.
15379         verifySetOemNetworkPreferenceForPreference(uidRangesAllPackages, uidRangesSinglePackage,
15380                 mCellAgent.getNetwork().netId, 1 /* times */,
15381                 mCellAgent.getNetwork().netId, 1 /* times */,
15382                 false /* shouldDestroyNetwork */);
15383 
15384         // Set the system to no longer recognize the package to be installed
15385         mockGetApplicationInfoThrowsNameNotFound(packageToInstall, PRIMARY_USER_HANDLE);
15386 
15387         // Send a broadcast indicating a package was removed.
15388         final Intent removedIntent = new Intent(ACTION_PACKAGE_REMOVED);
15389         removedIntent.setData(Uri.parse(packageScheme + packageToInstall));
15390         processBroadcast(removedIntent);
15391 
15392         // Test the combined packages are removed and the single package is added.
15393         verifySetOemNetworkPreferenceForPreference(uidRangesSinglePackage, uidRangesAllPackages,
15394                 mCellAgent.getNetwork().netId, 1 /* times */,
15395                 mCellAgent.getNetwork().netId, 1 /* times */,
15396                 false /* shouldDestroyNetwork */);
15397 
15398         // Set the system to change the installed package's uid
15399         final int replacedTestPackageUid = TEST_PACKAGE_UID + 1;
15400         mockGetApplicationInfo(TEST_PACKAGE_NAME, replacedTestPackageUid);
15401         final UidRangeParcel[] uidRangesReplacedPackage =
15402                 toUidRangeStableParcels(uidRangesForUids(replacedTestPackageUid));
15403 
15404         // Send a broadcast indicating a package was replaced.
15405         final Intent replacedIntent = new Intent(ACTION_PACKAGE_REPLACED);
15406         replacedIntent.setData(Uri.parse(packageScheme + TEST_PACKAGE_NAME));
15407         processBroadcast(replacedIntent);
15408 
15409         // Test the original uid is removed and is replaced with the new uid.
15410         verifySetOemNetworkPreferenceForPreference(uidRangesReplacedPackage, uidRangesSinglePackage,
15411                 mCellAgent.getNetwork().netId, 1 /* times */,
15412                 mCellAgent.getNetwork().netId, 1 /* times */,
15413                 false /* shouldDestroyNetwork */);
15414     }
15415 
15416     /**
15417      * Test network priority for preference OEM_NETWORK_PREFERENCE_OEM_PAID in the following order:
15418      * NET_CAPABILITY_NOT_METERED -> NET_CAPABILITY_OEM_PAID -> fallback
15419      */
15420     @Test
15421     public void testMultipleDefaultNetworksTracksOemNetworkPreferenceOemPaidCorrectly()
15422             throws Exception {
15423         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
15424                 OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PAID;
15425         setupMultipleDefaultNetworksForOemNetworkPreferenceCurrentUidTest(networkPref);
15426         final int expectedDefaultRequestSize = 2;
15427         final int expectedOemPrefRequestSize = 3;
15428         registerDefaultNetworkCallbacks();
15429 
15430         // The fallback as well as the OEM preference should now be tracked.
15431         assertEquals(expectedDefaultRequestSize, mService.mDefaultNetworkRequests.size());
15432 
15433         // Test lowest to highest priority requests.
15434         // Bring up metered cellular. This will satisfy the fallback network.
15435         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true);
15436         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
15437                 mCellAgent.getNetwork(),
15438                 mCellAgent.getNetwork());
15439 
15440         // Bring up ethernet with OEM_PAID. This will satisfy NET_CAPABILITY_OEM_PAID.
15441         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, true);
15442         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
15443                 mCellAgent.getNetwork(),
15444                 mEthernetAgent.getNetwork());
15445 
15446         // Bring up unmetered Wi-Fi. This will satisfy NET_CAPABILITY_NOT_METERED.
15447         setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, true);
15448         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
15449                 mWiFiAgent.getNetwork(),
15450                 mWiFiAgent.getNetwork());
15451 
15452         // Disconnecting unmetered Wi-Fi will put the pref on OEM_PAID and fallback on cellular.
15453         setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, false);
15454         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
15455                 mCellAgent.getNetwork(),
15456                 mEthernetAgent.getNetwork());
15457 
15458         // Disconnecting cellular should keep OEM network on OEM_PAID and fallback will be null.
15459         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, false);
15460         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
15461                 null,
15462                 mEthernetAgent.getNetwork());
15463 
15464         // Disconnecting OEM_PAID will put both on null as it is the last network.
15465         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, false);
15466         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
15467                 null,
15468                 null);
15469 
15470         // default callbacks will be unregistered in tearDown
15471     }
15472 
15473     @Test
15474     public void testNetworkFactoryRequestsWithMultilayerRequest()
15475             throws Exception {
15476         // First use OEM_PAID preference to create a multi-layer request : 1. listen for
15477         // unmetered, 2. request network with cap OEM_PAID, 3, request the default network for
15478         // fallback.
15479         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
15480                 OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PAID;
15481         setupMultipleDefaultNetworksForOemNetworkPreferenceCurrentUidTest(networkPref);
15482 
15483         final HandlerThread handlerThread = new HandlerThread("MockFactory");
15484         handlerThread.start();
15485         NetworkCapabilities internetFilter = new NetworkCapabilities()
15486                 .addCapability(NET_CAPABILITY_INTERNET)
15487                 .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED);
15488         final MockNetworkFactory internetFactory = new MockNetworkFactory(handlerThread.getLooper(),
15489                 mServiceContext, "internetFactory", internetFilter, mCsHandlerThread);
15490         internetFactory.setScoreFilter(40);
15491         internetFactory.register();
15492         // Default internet request only. The unmetered request is never sent to factories (it's a
15493         // LISTEN, not requestable). The 3rd (fallback) request in OEM_PAID NRI is TRACK_DEFAULT
15494         // which is also not sent to factories. Finally, the OEM_PAID request doesn't match the
15495         // internetFactory filter.
15496         internetFactory.expectRequestAdds(1);
15497         internetFactory.assertRequestCountEquals(1);
15498 
15499         NetworkCapabilities oemPaidFilter = new NetworkCapabilities()
15500                 .addCapability(NET_CAPABILITY_INTERNET)
15501                 .addCapability(NET_CAPABILITY_OEM_PAID)
15502                 .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
15503                 .removeCapability(NET_CAPABILITY_NOT_RESTRICTED);
15504         final MockNetworkFactory oemPaidFactory = new MockNetworkFactory(handlerThread.getLooper(),
15505                 mServiceContext, "oemPaidFactory", oemPaidFilter, mCsHandlerThread);
15506         oemPaidFactory.setScoreFilter(40);
15507         oemPaidFactory.register();
15508         oemPaidFactory.expectRequestAdd(); // Because nobody satisfies the request
15509 
15510         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
15511         mCellAgent.connect(true);
15512 
15513         // A network connected that satisfies the default internet request. For the OEM_PAID
15514         // preference, this is not as good as an OEM_PAID network, so even if the score of
15515         // the network is better than the factory announced, it still should try to bring up
15516         // the network.
15517         expectNoRequestChanged(oemPaidFactory);
15518         oemPaidFactory.assertRequestCountEquals(1);
15519         // The internet factory however is outscored, and should lose its requests.
15520         internetFactory.expectRequestRemove();
15521         internetFactory.assertRequestCountEquals(0);
15522 
15523         final NetworkCapabilities oemPaidNc = new NetworkCapabilities();
15524         oemPaidNc.addCapability(NET_CAPABILITY_OEM_PAID);
15525         oemPaidNc.removeCapability(NET_CAPABILITY_NOT_RESTRICTED);
15526         final TestNetworkAgentWrapper oemPaidAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR,
15527                 new LinkProperties(), oemPaidNc);
15528         oemPaidAgent.connect(true);
15529 
15530         // The oemPaidAgent has score 50/cell transport, so it beats what the oemPaidFactory can
15531         // provide, therefore it loses the request.
15532         oemPaidFactory.expectRequestRemove();
15533         oemPaidFactory.assertRequestCountEquals(0);
15534         expectNoRequestChanged(internetFactory);
15535         internetFactory.assertRequestCountEquals(0);
15536 
15537         oemPaidAgent.setScore(new NetworkScore.Builder().setLegacyInt(20).setExiting(true).build());
15538         // Now the that the agent is weak, the oemPaidFactory can beat the existing network for the
15539         // OEM_PAID request. The internet factory however can't beat a network that has OEM_PAID
15540         // for the preference request, so it doesn't see the request.
15541         oemPaidFactory.expectRequestAdd();
15542         oemPaidFactory.assertRequestCountEquals(1);
15543         expectNoRequestChanged(internetFactory);
15544         internetFactory.assertRequestCountEquals(0);
15545 
15546         mCellAgent.disconnect();
15547         // The network satisfying the default internet request has disconnected, so the
15548         // internetFactory sees the default request again. However there is a network with OEM_PAID
15549         // connected, so the 2nd OEM_PAID req is already satisfied, so the oemPaidFactory doesn't
15550         // care about networks that don't have OEM_PAID.
15551         expectNoRequestChanged(oemPaidFactory);
15552         oemPaidFactory.assertRequestCountEquals(1);
15553         internetFactory.expectRequestAdd();
15554         internetFactory.assertRequestCountEquals(1);
15555 
15556         // Cell connects again, still with score 50. Back to the previous state.
15557         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
15558         mCellAgent.connect(true);
15559         expectNoRequestChanged(oemPaidFactory);
15560         oemPaidFactory.assertRequestCountEquals(1);
15561         internetFactory.expectRequestRemove();
15562         internetFactory.assertRequestCountEquals(0);
15563 
15564         // Create a request that holds the upcoming wifi network.
15565         final TestNetworkCallback wifiCallback = new TestNetworkCallback();
15566         mCm.requestNetwork(new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI).build(),
15567                 wifiCallback);
15568 
15569         // Now WiFi connects and it's unmetered, but it's weaker than cell.
15570         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
15571         mWiFiAgent.addCapability(NET_CAPABILITY_NOT_METERED);
15572         mWiFiAgent.setScore(new NetworkScore.Builder().setLegacyInt(30).setExiting(true)
15573                 .build()); // Not the best Internet network, but unmetered
15574         mWiFiAgent.connect(true);
15575 
15576         // The OEM_PAID preference prefers an unmetered network to an OEM_PAID network, so
15577         // the oemPaidFactory can't beat wifi no matter how high its score.
15578         oemPaidFactory.expectRequestRemove();
15579         expectNoRequestChanged(internetFactory);
15580 
15581         mCellAgent.disconnect();
15582         // Now that the best internet network (cell, with its 50 score compared to 30 for WiFi
15583         // at this point), the default internet request is satisfied by a network worse than
15584         // the internetFactory announced, so it gets the request. However, there is still an
15585         // unmetered network, so the oemPaidNetworkFactory still can't beat this.
15586         expectNoRequestChanged(oemPaidFactory);
15587         internetFactory.expectRequestAdd();
15588         mCm.unregisterNetworkCallback(wifiCallback);
15589         handlerThread.quitSafely();
15590         handlerThread.join();
15591     }
15592 
15593     /**
15594      * Test network priority for OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK in the following order:
15595      * NET_CAPABILITY_NOT_METERED -> NET_CAPABILITY_OEM_PAID
15596      */
15597     @Test
15598     public void testMultipleDefaultNetworksTracksOemNetworkPreferenceOemPaidNoFallbackCorrectly()
15599             throws Exception {
15600         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
15601                 OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK;
15602         setupMultipleDefaultNetworksForOemNetworkPreferenceCurrentUidTest(networkPref);
15603         final int expectedDefaultRequestSize = 2;
15604         final int expectedOemPrefRequestSize = 2;
15605         registerDefaultNetworkCallbacks();
15606 
15607         // The fallback as well as the OEM preference should now be tracked.
15608         assertEquals(expectedDefaultRequestSize, mService.mDefaultNetworkRequests.size());
15609 
15610         // Test lowest to highest priority requests.
15611         // Bring up metered cellular. This will satisfy the fallback network but not the pref.
15612         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true);
15613         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
15614                 mCellAgent.getNetwork(),
15615                 mService.mNoServiceNetwork.network());
15616 
15617         // Bring up ethernet with OEM_PAID. This will satisfy NET_CAPABILITY_OEM_PAID.
15618         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, true);
15619         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
15620                 mCellAgent.getNetwork(),
15621                 mEthernetAgent.getNetwork());
15622 
15623         // Bring up unmetered Wi-Fi. This will satisfy NET_CAPABILITY_NOT_METERED.
15624         setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, true);
15625         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
15626                 mWiFiAgent.getNetwork(),
15627                 mWiFiAgent.getNetwork());
15628 
15629         // Disconnecting unmetered Wi-Fi will put the OEM pref on OEM_PAID and fallback on cellular.
15630         setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, false);
15631         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
15632                 mCellAgent.getNetwork(),
15633                 mEthernetAgent.getNetwork());
15634 
15635         // Disconnecting cellular should keep OEM network on OEM_PAID and fallback will be null.
15636         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, false);
15637         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
15638                 null,
15639                 mEthernetAgent.getNetwork());
15640 
15641         // Disconnecting OEM_PAID puts the fallback on null and the pref on the disconnected net.
15642         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, false);
15643         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
15644                 null,
15645                 mService.mNoServiceNetwork.network());
15646 
15647         // default callbacks will be unregistered in tearDown
15648     }
15649 
15650     /**
15651      * Test network priority for OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY in the following order:
15652      * NET_CAPABILITY_OEM_PAID
15653      * This preference should only apply to OEM_PAID networks.
15654      */
15655     @Test
15656     public void testMultipleDefaultNetworksTracksOemNetworkPreferenceOemPaidOnlyCorrectly()
15657             throws Exception {
15658         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
15659                 OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY;
15660         setupMultipleDefaultNetworksForOemNetworkPreferenceCurrentUidTest(networkPref);
15661         final int expectedDefaultRequestSize = 2;
15662         final int expectedOemPrefRequestSize = 1;
15663         registerDefaultNetworkCallbacks();
15664 
15665         // The fallback as well as the OEM preference should now be tracked.
15666         assertEquals(expectedDefaultRequestSize, mService.mDefaultNetworkRequests.size());
15667 
15668         // Test lowest to highest priority requests.
15669         // Bring up metered cellular. This will satisfy the fallback network.
15670         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true);
15671         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
15672                 mCellAgent.getNetwork(),
15673                 mService.mNoServiceNetwork.network());
15674 
15675         // Bring up ethernet with OEM_PAID. This will satisfy NET_CAPABILITY_OEM_PAID.
15676         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, true);
15677         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
15678                 mCellAgent.getNetwork(),
15679                 mEthernetAgent.getNetwork());
15680 
15681         // Bring up unmetered Wi-Fi. The OEM network shouldn't change, the fallback will take Wi-Fi.
15682         setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, true);
15683         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
15684                 mWiFiAgent.getNetwork(),
15685                 mEthernetAgent.getNetwork());
15686 
15687         // Disconnecting unmetered Wi-Fi shouldn't change the OEM network with fallback on cellular.
15688         setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, false);
15689         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
15690                 mCellAgent.getNetwork(),
15691                 mEthernetAgent.getNetwork());
15692 
15693         // Disconnecting OEM_PAID will keep the fallback on cellular and nothing for OEM_PAID.
15694         // OEM_PAID_ONLY not supporting a fallback now uses the disconnected network.
15695         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, false);
15696         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
15697                 mCellAgent.getNetwork(),
15698                 mService.mNoServiceNetwork.network());
15699 
15700         // Disconnecting cellular will put the fallback on null and the pref on disconnected.
15701         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, false);
15702         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
15703                 null,
15704                 mService.mNoServiceNetwork.network());
15705 
15706         // default callbacks will be unregistered in tearDown
15707     }
15708 
15709     /**
15710      * Test network priority for OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY in the following order:
15711      * NET_CAPABILITY_OEM_PRIVATE
15712      * This preference should only apply to OEM_PRIVATE networks.
15713      */
15714     @Test
15715     public void testMultipleDefaultNetworksTracksOemNetworkPreferenceOemPrivateOnlyCorrectly()
15716             throws Exception {
15717         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
15718                 OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY;
15719         setupMultipleDefaultNetworksForOemNetworkPreferenceCurrentUidTest(networkPref);
15720         final int expectedDefaultRequestSize = 2;
15721         final int expectedOemPrefRequestSize = 1;
15722         registerDefaultNetworkCallbacks();
15723 
15724         // The fallback as well as the OEM preference should now be tracked.
15725         assertEquals(expectedDefaultRequestSize, mService.mDefaultNetworkRequests.size());
15726 
15727         // Test lowest to highest priority requests.
15728         // Bring up metered cellular. This will satisfy the fallback network.
15729         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true);
15730         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
15731                 mCellAgent.getNetwork(),
15732                 mService.mNoServiceNetwork.network());
15733 
15734         // Bring up ethernet with OEM_PRIVATE. This will satisfy NET_CAPABILITY_OEM_PRIVATE.
15735         startOemManagedNetwork(false);
15736         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
15737                 mCellAgent.getNetwork(),
15738                 mEthernetAgent.getNetwork());
15739 
15740         // Bring up unmetered Wi-Fi. The OEM network shouldn't change, the fallback will take Wi-Fi.
15741         setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, true);
15742         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
15743                 mWiFiAgent.getNetwork(),
15744                 mEthernetAgent.getNetwork());
15745 
15746         // Disconnecting unmetered Wi-Fi shouldn't change the OEM network with fallback on cellular.
15747         setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, false);
15748         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
15749                 mCellAgent.getNetwork(),
15750                 mEthernetAgent.getNetwork());
15751 
15752         // Disconnecting OEM_PRIVATE will keep the fallback on cellular.
15753         // OEM_PRIVATE_ONLY not supporting a fallback now uses to the disconnected network.
15754         stopOemManagedNetwork();
15755         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
15756                 mCellAgent.getNetwork(),
15757                 mService.mNoServiceNetwork.network());
15758 
15759         // Disconnecting cellular will put the fallback on null and pref on disconnected.
15760         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, false);
15761         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
15762                 null,
15763                 mService.mNoServiceNetwork.network());
15764 
15765         // default callbacks will be unregistered in tearDown
15766     }
15767 
15768     @Test
15769     public void testCapabilityWithOemNetworkPreference() throws Exception {
15770         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
15771                 OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY;
15772         setupMultipleDefaultNetworksForOemNetworkPreferenceNotCurrentUidTest(networkPref);
15773         registerDefaultNetworkCallbacks();
15774 
15775         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true);
15776 
15777         mSystemDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
15778         mDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
15779 
15780         mCellAgent.addCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED);
15781         mSystemDefaultNetworkCallback.expectCaps(mCellAgent,
15782                 c -> c.hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED));
15783         mDefaultNetworkCallback.expectCaps(mCellAgent,
15784                 c -> c.hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED));
15785 
15786         // default callbacks will be unregistered in tearDown
15787     }
15788 
15789     @Test
15790     public void testSetOemNetworkPreferenceLogsRequest() throws Exception {
15791         mServiceContext.setPermission(DUMP, PERMISSION_GRANTED);
15792         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
15793                 OEM_NETWORK_PREFERENCE_OEM_PAID;
15794         final StringWriter stringWriter = new StringWriter();
15795         final String logIdentifier = "UPDATE INITIATED: OemNetworkPreferences";
15796         final Pattern pattern = Pattern.compile(logIdentifier);
15797 
15798         final int expectedNumLogs = 2;
15799         final UidRangeParcel[] uidRanges =
15800                 toUidRangeStableParcels(uidRangesForUids(TEST_PACKAGE_UID));
15801 
15802         // Call twice to generate two logs.
15803         setupSetOemNetworkPreferenceForPreferenceTest(networkPref, uidRanges, TEST_PACKAGE_NAME);
15804         setupSetOemNetworkPreferenceForPreferenceTest(networkPref, uidRanges, TEST_PACKAGE_NAME);
15805         mService.dump(new FileDescriptor(), new PrintWriter(stringWriter), new String[0]);
15806 
15807         final String dumpOutput = stringWriter.toString();
15808         final Matcher matcher = pattern.matcher(dumpOutput);
15809         int count = 0;
15810         while (matcher.find()) {
15811             count++;
15812         }
15813         assertEquals(expectedNumLogs, count);
15814     }
15815 
15816     @Test
15817     public void testGetAllNetworkStateSnapshots() throws Exception {
15818         verifyNoNetwork();
15819 
15820         // Setup test cellular network with specified LinkProperties and NetworkCapabilities,
15821         // verify the content of the snapshot matches.
15822         final LinkProperties cellLp = new LinkProperties();
15823         final LinkAddress myIpv4Addr = new LinkAddress(InetAddress.getByName("192.0.2.129"), 25);
15824         final LinkAddress myIpv6Addr = new LinkAddress(InetAddress.getByName("2001:db8::1"), 64);
15825         cellLp.setInterfaceName("test01");
15826         cellLp.addLinkAddress(myIpv4Addr);
15827         cellLp.addLinkAddress(myIpv6Addr);
15828         cellLp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
15829         cellLp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
15830         cellLp.addRoute(new RouteInfo(myIpv4Addr, null));
15831         cellLp.addRoute(new RouteInfo(myIpv6Addr, null));
15832         final NetworkCapabilities cellNcTemplate = new NetworkCapabilities.Builder()
15833                 .addTransportType(TRANSPORT_CELLULAR).addCapability(NET_CAPABILITY_MMS).build();
15834 
15835         final TestNetworkCallback cellCb = new TestNetworkCallback();
15836         mCm.requestNetwork(new NetworkRequest.Builder().addCapability(NET_CAPABILITY_MMS).build(),
15837                 cellCb);
15838         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp, cellNcTemplate);
15839         mCellAgent.connect(true);
15840         cellCb.expectAvailableCallbacksUnvalidated(mCellAgent);
15841         List<NetworkStateSnapshot> snapshots = mCm.getAllNetworkStateSnapshots();
15842         assertLength(1, snapshots);
15843 
15844         // Compose the expected cellular snapshot for verification.
15845         final NetworkCapabilities cellNc =
15846                 mCm.getNetworkCapabilities(mCellAgent.getNetwork());
15847         final NetworkStateSnapshot cellSnapshot = new NetworkStateSnapshot(
15848                 mCellAgent.getNetwork(), cellNc, cellLp,
15849                 null, ConnectivityManager.TYPE_MOBILE);
15850         assertEquals(cellSnapshot, snapshots.get(0));
15851 
15852         // Connect wifi and verify the snapshots.
15853         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
15854         mWiFiAgent.connect(true);
15855         waitForIdle();
15856         // Compose the expected wifi snapshot for verification.
15857         final NetworkCapabilities wifiNc =
15858                 mCm.getNetworkCapabilities(mWiFiAgent.getNetwork());
15859         final NetworkStateSnapshot wifiSnapshot = new NetworkStateSnapshot(
15860                 mWiFiAgent.getNetwork(), wifiNc, new LinkProperties(), null,
15861                 ConnectivityManager.TYPE_WIFI);
15862 
15863         snapshots = mCm.getAllNetworkStateSnapshots();
15864         assertLength(2, snapshots);
15865         assertContainsAll(snapshots, cellSnapshot, wifiSnapshot);
15866 
15867         // Set cellular as suspended, verify the snapshots will contain suspended networks.
15868         mCellAgent.suspend();
15869         waitForIdle();
15870         final NetworkCapabilities cellSuspendedNc =
15871                 mCm.getNetworkCapabilities(mCellAgent.getNetwork());
15872         assertFalse(cellSuspendedNc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
15873         final NetworkStateSnapshot cellSuspendedSnapshot = new NetworkStateSnapshot(
15874                 mCellAgent.getNetwork(), cellSuspendedNc, cellLp,
15875                 null, ConnectivityManager.TYPE_MOBILE);
15876         snapshots = mCm.getAllNetworkStateSnapshots();
15877         assertLength(2, snapshots);
15878         assertContainsAll(snapshots, cellSuspendedSnapshot, wifiSnapshot);
15879 
15880         // Disconnect wifi, verify the snapshots contain only cellular.
15881         mWiFiAgent.disconnect();
15882         waitForIdle();
15883         snapshots = mCm.getAllNetworkStateSnapshots();
15884         assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetwork());
15885         assertLength(1, snapshots);
15886         assertEquals(cellSuspendedSnapshot, snapshots.get(0));
15887 
15888         mCellAgent.resume();
15889         waitForIdle();
15890         snapshots = mCm.getAllNetworkStateSnapshots();
15891         assertLength(1, snapshots);
15892         assertEquals(cellSnapshot, snapshots.get(0));
15893 
15894         mCellAgent.disconnect();
15895         waitForIdle();
15896         verifyNoNetwork();
15897         mCm.unregisterNetworkCallback(cellCb);
15898     }
15899 
15900     // Cannot be part of MockNetworkFactory since it requires method of the test.
15901     private void expectNoRequestChanged(@NonNull MockNetworkFactory factory) {
15902         waitForIdle();
15903         factory.assertNoRequestChanged();
15904     }
15905 
15906     @Test
15907     public void testRegisterBestMatchingNetworkCallback_noIssueToFactory() throws Exception {
15908         // Prepare mock mms factory.
15909         final HandlerThread handlerThread = new HandlerThread("MockCellularFactory");
15910         handlerThread.start();
15911         NetworkCapabilities filter = new NetworkCapabilities()
15912                 .addTransportType(TRANSPORT_CELLULAR)
15913                 .addCapability(NET_CAPABILITY_MMS);
15914         final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
15915                 mServiceContext, "testFactory", filter, mCsHandlerThread);
15916         testFactory.setScoreFilter(40);
15917 
15918         try {
15919             // Register the factory. It doesn't see the default request because its filter does
15920             // not include INTERNET.
15921             testFactory.register();
15922             expectNoRequestChanged(testFactory);
15923             testFactory.assertRequestCountEquals(0);
15924             // The factory won't try to start the network since the default request doesn't
15925             // match the filter (no INTERNET capability).
15926             assertFalse(testFactory.getMyStartRequested());
15927 
15928             // Register callback for listening best matching network. Verify that the request won't
15929             // be sent to factory.
15930             final TestNetworkCallback bestMatchingCb = new TestNetworkCallback();
15931             mCm.registerBestMatchingNetworkCallback(
15932                     new NetworkRequest.Builder().addCapability(NET_CAPABILITY_MMS).build(),
15933                     bestMatchingCb, mCsHandlerThread.getThreadHandler());
15934             bestMatchingCb.assertNoCallback();
15935             expectNoRequestChanged(testFactory);
15936             testFactory.assertRequestCountEquals(0);
15937             assertFalse(testFactory.getMyStartRequested());
15938 
15939             // Fire a normal mms request, verify the factory will only see the request.
15940             final TestNetworkCallback mmsNetworkCallback = new TestNetworkCallback();
15941             final NetworkRequest mmsRequest = new NetworkRequest.Builder()
15942                     .addCapability(NET_CAPABILITY_MMS).build();
15943             mCm.requestNetwork(mmsRequest, mmsNetworkCallback);
15944             testFactory.expectRequestAdd();
15945             testFactory.assertRequestCountEquals(1);
15946             assertTrue(testFactory.getMyStartRequested());
15947 
15948             // Unregister best matching callback, verify factory see no change.
15949             mCm.unregisterNetworkCallback(bestMatchingCb);
15950             expectNoRequestChanged(testFactory);
15951             testFactory.assertRequestCountEquals(1);
15952             assertTrue(testFactory.getMyStartRequested());
15953         } finally {
15954             testFactory.terminate();
15955             handlerThread.quitSafely();
15956             handlerThread.join();
15957         }
15958     }
15959 
15960     @Test
15961     public void testRegisterBestMatchingNetworkCallback_trackBestNetwork() throws Exception {
15962         final TestNetworkCallback bestMatchingCb = new TestNetworkCallback();
15963         mCm.registerBestMatchingNetworkCallback(
15964                 new NetworkRequest.Builder().addCapability(NET_CAPABILITY_TRUSTED).build(),
15965                 bestMatchingCb, mCsHandlerThread.getThreadHandler());
15966 
15967         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
15968         mCellAgent.connect(true);
15969         bestMatchingCb.expectAvailableThenValidatedCallbacks(mCellAgent);
15970 
15971         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
15972         mWiFiAgent.connect(true);
15973         bestMatchingCb.expectAvailableDoubleValidatedCallbacks(mWiFiAgent);
15974 
15975         // Change something on cellular to trigger capabilities changed, since the callback
15976         // only cares about the best network, verify it received nothing from cellular.
15977         mCellAgent.addCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED);
15978         bestMatchingCb.assertNoCallback();
15979 
15980         // Make cellular the best network again, verify the callback now tracks cellular.
15981         mWiFiAgent.adjustScore(-50);
15982         bestMatchingCb.expectAvailableCallbacksValidated(mCellAgent);
15983 
15984         // Make cellular temporary non-trusted, which will not satisfying the request.
15985         // Verify the callback switch from/to the other network accordingly.
15986         mCellAgent.removeCapability(NET_CAPABILITY_TRUSTED);
15987         bestMatchingCb.expectAvailableCallbacksValidated(mWiFiAgent);
15988         mCellAgent.addCapability(NET_CAPABILITY_TRUSTED);
15989         bestMatchingCb.expectAvailableDoubleValidatedCallbacks(mCellAgent);
15990 
15991         // Verify the callback doesn't care about wifi disconnect.
15992         mWiFiAgent.disconnect();
15993         bestMatchingCb.assertNoCallback();
15994         mCellAgent.disconnect();
15995         bestMatchingCb.expect(LOST, mCellAgent);
15996     }
15997 
15998     private UidRangeParcel[] uidRangeFor(final UserHandle handle) {
15999         final UidRange range = UidRange.createForUser(handle);
16000         return new UidRangeParcel[] { new UidRangeParcel(range.start, range.stop) };
16001     }
16002 
16003     private UidRangeParcel[] uidRangeFor(final UserHandle handle,
16004             ProfileNetworkPreference profileNetworkPreference) {
16005         final Set<UidRange> uidRangeSet;
16006         UidRange range = UidRange.createForUser(handle);
16007         if (profileNetworkPreference.getIncludedUids().length != 0) {
16008             uidRangeSet = UidRangeUtils.convertArrayToUidRange(
16009                     profileNetworkPreference.getIncludedUids());
16010 
16011         } else if (profileNetworkPreference.getExcludedUids().length != 0)  {
16012             uidRangeSet = UidRangeUtils.removeRangeSetFromUidRange(
16013                     range, UidRangeUtils.convertArrayToUidRange(
16014                             profileNetworkPreference.getExcludedUids()));
16015         } else {
16016             uidRangeSet = new ArraySet<>();
16017             uidRangeSet.add(range);
16018         }
16019         UidRangeParcel[] uidRangeParcels = new UidRangeParcel[uidRangeSet.size()];
16020         int i = 0;
16021         for (UidRange range1 : uidRangeSet) {
16022             uidRangeParcels[i] = new UidRangeParcel(range1.start, range1.stop);
16023             i++;
16024         }
16025         return uidRangeParcels;
16026     }
16027 
16028     private static class TestOnCompleteListener implements Runnable {
16029         final class OnComplete {}
16030         final ArrayTrackRecord<OnComplete>.ReadHead mHistory =
16031                 new ArrayTrackRecord<OnComplete>().newReadHead();
16032 
16033         @Override
16034         public void run() {
16035             mHistory.add(new OnComplete());
16036         }
16037 
16038         public void expectOnComplete() {
16039             assertNotNull(mHistory.poll(TIMEOUT_MS, it -> true));
16040         }
16041     }
16042 
16043     private TestNetworkAgentWrapper makeEnterpriseNetworkAgent() throws Exception {
16044         final NetworkCapabilities workNc = new NetworkCapabilities();
16045         workNc.addCapability(NET_CAPABILITY_ENTERPRISE);
16046         workNc.removeCapability(NET_CAPABILITY_NOT_RESTRICTED);
16047         return new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, new LinkProperties(), workNc);
16048     }
16049 
16050     private TestNetworkAgentWrapper makeEnterpriseNetworkAgent(int enterpriseId) throws Exception {
16051         final NetworkCapabilities workNc = new NetworkCapabilities();
16052         workNc.addCapability(NET_CAPABILITY_ENTERPRISE);
16053         workNc.removeCapability(NET_CAPABILITY_NOT_RESTRICTED);
16054         workNc.addEnterpriseId(enterpriseId);
16055         return new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, new LinkProperties(), workNc);
16056     }
16057 
16058     private TestNetworkCallback mEnterpriseCallback;
16059     private UserHandle setupEnterpriseNetwork() {
16060         final UserHandle userHandle = UserHandle.of(TEST_WORK_PROFILE_USER_ID);
16061         mServiceContext.setWorkProfile(userHandle, true);
16062 
16063         // File a request to avoid the enterprise network being disconnected as soon as the default
16064         // request goes away – it would make impossible to test that networkRemoveUidRanges
16065         // is called, as the network would disconnect first for lack of a request.
16066         mEnterpriseCallback = new TestNetworkCallback();
16067         final NetworkRequest keepUpRequest = new NetworkRequest.Builder()
16068                 .addCapability(NET_CAPABILITY_ENTERPRISE)
16069                 .build();
16070         mCm.requestNetwork(keepUpRequest, mEnterpriseCallback);
16071         return userHandle;
16072     }
16073 
16074     private void maybeTearDownEnterpriseNetwork() {
16075         if (null != mEnterpriseCallback) {
16076             mCm.unregisterNetworkCallback(mEnterpriseCallback);
16077         }
16078     }
16079 
16080     /**
16081      * Make sure per profile network preferences behave as expected for a given
16082      * profile network preference.
16083      */
16084     private void doTestPreferenceForUserNetworkUpDownForGivenPreference(
16085             ProfileNetworkPreference profileNetworkPreference,
16086             boolean connectWorkProfileAgentAhead,
16087             UserHandle testHandle,
16088             TestNetworkCallback profileDefaultNetworkCallback,
16089             TestNetworkCallback disAllowProfileDefaultNetworkCallback) throws Exception {
16090         final InOrder inOrder = inOrder(mMockNetd, mMockDnsResolver);
16091 
16092         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
16093         mCellAgent.connect(true);
16094 
16095         mSystemDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
16096         mDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
16097         profileDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
16098         if (disAllowProfileDefaultNetworkCallback != null) {
16099             disAllowProfileDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
16100         }
16101         inOrder.verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
16102                 mCellAgent.getNetwork().netId, INetd.PERMISSION_NONE));
16103 
16104         final TestNetworkAgentWrapper workAgent =
16105                 makeEnterpriseNetworkAgent(profileNetworkPreference.getPreferenceEnterpriseId());
16106         if (mService.shouldCreateNetworksImmediately(workAgent.getNetworkCapabilities())) {
16107             expectNativeNetworkCreated(workAgent.getNetwork().netId, INetd.PERMISSION_SYSTEM,
16108                     null /* iface */, inOrder);
16109         }
16110         if (connectWorkProfileAgentAhead) {
16111             workAgent.connect(false);
16112             if (!mService.shouldCreateNetworksImmediately(workAgent.getNetworkCapabilities())) {
16113                 expectNativeNetworkCreated(workAgent.getNetwork().netId, INetd.PERMISSION_SYSTEM,
16114                         null /* iface */, inOrder);
16115             }
16116         }
16117 
16118         final TestOnCompleteListener listener = new TestOnCompleteListener();
16119         mCm.setProfileNetworkPreferences(testHandle, List.of(profileNetworkPreference),
16120                 r -> r.run(), listener);
16121         listener.expectOnComplete();
16122         boolean allowFallback = true;
16123         if (profileNetworkPreference.getPreference()
16124                 == PROFILE_NETWORK_PREFERENCE_ENTERPRISE_NO_FALLBACK) {
16125             allowFallback = false;
16126         }
16127         if (allowFallback && !connectWorkProfileAgentAhead) {
16128             // Setting a network preference for this user will create a new set of routing rules for
16129             // the UID range that corresponds to this user, inorder to define the default network
16130             // for these apps separately. This is true because the multi-layer request relevant to
16131             // this UID range contains a TRACK_DEFAULT, so the range will be moved through
16132             // UID-specific rules to the correct network – in this case the system default network.
16133             // The case where the default network for the profile happens to be the same as the
16134             // system default is not handled specially, the rules are always active as long as
16135             // a preference is set.
16136             inOrder.verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
16137                     mCellAgent.getNetwork().netId,
16138                     uidRangeFor(testHandle, profileNetworkPreference),
16139                     PREFERENCE_ORDER_PROFILE));
16140         }
16141 
16142         // The enterprise network is not ready yet.
16143         assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback);
16144         if (allowFallback && !connectWorkProfileAgentAhead) {
16145             assertNoCallbacks(profileDefaultNetworkCallback);
16146         } else if (!connectWorkProfileAgentAhead) {
16147             profileDefaultNetworkCallback.expect(LOST, mCellAgent);
16148             if (disAllowProfileDefaultNetworkCallback != null) {
16149                 assertNoCallbacks(disAllowProfileDefaultNetworkCallback);
16150             }
16151         }
16152 
16153         if (!connectWorkProfileAgentAhead) {
16154             workAgent.connect(false);
16155             if (!mService.shouldCreateNetworksImmediately(workAgent.getNetworkCapabilities())) {
16156                 inOrder.verify(mMockNetd).networkCreate(
16157                         nativeNetworkConfigPhysical(workAgent.getNetwork().netId,
16158                                 INetd.PERMISSION_SYSTEM));
16159             }
16160         }
16161 
16162         profileDefaultNetworkCallback.expectAvailableCallbacksUnvalidated(workAgent);
16163         if (disAllowProfileDefaultNetworkCallback != null) {
16164             disAllowProfileDefaultNetworkCallback.assertNoCallback();
16165         }
16166         mSystemDefaultNetworkCallback.assertNoCallback();
16167         mDefaultNetworkCallback.assertNoCallback();
16168         inOrder.verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
16169                 workAgent.getNetwork().netId,
16170                 uidRangeFor(testHandle, profileNetworkPreference),
16171                 PREFERENCE_ORDER_PROFILE));
16172 
16173         if (allowFallback && !connectWorkProfileAgentAhead) {
16174             inOrder.verify(mMockNetd).networkRemoveUidRangesParcel(new NativeUidRangeConfig(
16175                     mCellAgent.getNetwork().netId,
16176                     uidRangeFor(testHandle, profileNetworkPreference),
16177                     PREFERENCE_ORDER_PROFILE));
16178         }
16179 
16180         // Make sure changes to the work agent send callbacks to the app in the work profile, but
16181         // not to the other apps.
16182         workAgent.setNetworkValid(true /* privateDnsProbeSent */);
16183         workAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
16184         profileDefaultNetworkCallback.expectCaps(workAgent,
16185                 c -> c.hasCapability(NET_CAPABILITY_VALIDATED)
16186                         && c.hasCapability(NET_CAPABILITY_ENTERPRISE)
16187                         && c.hasEnterpriseId(profileNetworkPreference.getPreferenceEnterpriseId())
16188                         && c.getEnterpriseIds().length == 1);
16189         if (disAllowProfileDefaultNetworkCallback != null) {
16190             assertNoCallbacks(disAllowProfileDefaultNetworkCallback);
16191         }
16192         assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback);
16193 
16194         workAgent.addCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED);
16195         profileDefaultNetworkCallback.expectCaps(workAgent,
16196                 c -> c.hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED));
16197         if (disAllowProfileDefaultNetworkCallback != null) {
16198             assertNoCallbacks(disAllowProfileDefaultNetworkCallback);
16199         }
16200         assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback);
16201 
16202         // Conversely, change a capability on the system-wide default network and make sure
16203         // that only the apps outside of the work profile receive the callbacks.
16204         mCellAgent.addCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED);
16205         mSystemDefaultNetworkCallback.expectCaps(mCellAgent,
16206                 c -> c.hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED));
16207         mDefaultNetworkCallback.expectCaps(mCellAgent,
16208                 c -> c.hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED));
16209         if (disAllowProfileDefaultNetworkCallback != null) {
16210             disAllowProfileDefaultNetworkCallback.expectCaps(mCellAgent,
16211                     c -> c.hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED));
16212         }
16213         profileDefaultNetworkCallback.assertNoCallback();
16214 
16215         // Disconnect and reconnect the system-wide default network and make sure that the
16216         // apps on this network see the appropriate callbacks, and the app on the work profile
16217         // doesn't because it continues to use the enterprise network.
16218         mCellAgent.disconnect();
16219         mSystemDefaultNetworkCallback.expect(LOST, mCellAgent);
16220         mDefaultNetworkCallback.expect(LOST, mCellAgent);
16221         if (disAllowProfileDefaultNetworkCallback != null) {
16222             disAllowProfileDefaultNetworkCallback.expect(LOST, mCellAgent);
16223         }
16224         profileDefaultNetworkCallback.assertNoCallback();
16225         inOrder.verify(mMockNetd).networkDestroy(mCellAgent.getNetwork().netId);
16226 
16227         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
16228         mCellAgent.connect(true);
16229         mSystemDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
16230         mDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
16231         if (disAllowProfileDefaultNetworkCallback != null) {
16232             disAllowProfileDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
16233 
16234         }
16235         profileDefaultNetworkCallback.assertNoCallback();
16236         inOrder.verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
16237                 mCellAgent.getNetwork().netId, INetd.PERMISSION_NONE));
16238 
16239         // When the agent disconnects, test that the app on the work profile falls back to the
16240         // default network.
16241         workAgent.disconnect();
16242         profileDefaultNetworkCallback.expect(LOST, workAgent);
16243         if (allowFallback) {
16244             profileDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellAgent);
16245             if (disAllowProfileDefaultNetworkCallback != null) {
16246                 assertNoCallbacks(disAllowProfileDefaultNetworkCallback);
16247             }
16248         }
16249         assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback);
16250         if (allowFallback) {
16251             inOrder.verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
16252                     mCellAgent.getNetwork().netId,
16253                     uidRangeFor(testHandle, profileNetworkPreference),
16254                     PREFERENCE_ORDER_PROFILE));
16255         }
16256         inOrder.verify(mMockNetd).networkDestroy(workAgent.getNetwork().netId);
16257 
16258         mCellAgent.disconnect();
16259         mSystemDefaultNetworkCallback.expect(LOST, mCellAgent);
16260         mDefaultNetworkCallback.expect(LOST, mCellAgent);
16261         if (disAllowProfileDefaultNetworkCallback != null) {
16262             disAllowProfileDefaultNetworkCallback.expect(LOST, mCellAgent);
16263         }
16264         if (allowFallback) {
16265             profileDefaultNetworkCallback.expect(LOST, mCellAgent);
16266         }
16267 
16268         // Waiting for the handler to be idle before checking for networkDestroy is necessary
16269         // here because ConnectivityService calls onLost before the network is fully torn down.
16270         waitForIdle();
16271         inOrder.verify(mMockNetd).networkDestroy(mCellAgent.getNetwork().netId);
16272 
16273         // If the control comes here, callbacks seem to behave correctly in the presence of
16274         // a default network when the enterprise network goes up and down. Now, make sure they
16275         // also behave correctly in the absence of a system-wide default network.
16276         final TestNetworkAgentWrapper workAgent2 =
16277                 makeEnterpriseNetworkAgent(profileNetworkPreference.getPreferenceEnterpriseId());
16278         workAgent2.connect(false);
16279 
16280         profileDefaultNetworkCallback.expectAvailableCallbacksUnvalidated(workAgent2);
16281         if (disAllowProfileDefaultNetworkCallback != null) {
16282             assertNoCallbacks(disAllowProfileDefaultNetworkCallback);
16283         }
16284         assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback);
16285         inOrder.verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
16286                 workAgent2.getNetwork().netId, INetd.PERMISSION_SYSTEM));
16287         inOrder.verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
16288                 workAgent2.getNetwork().netId,
16289                 uidRangeFor(testHandle, profileNetworkPreference), PREFERENCE_ORDER_PROFILE));
16290 
16291         workAgent2.setNetworkValid(true /* privateDnsProbeSent */);
16292         workAgent2.mNetworkMonitor.forceReevaluation(Process.myUid());
16293         profileDefaultNetworkCallback.expectCaps(workAgent2,
16294                 c -> c.hasCapability(NET_CAPABILITY_ENTERPRISE)
16295                         && !c.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)
16296                         && c.hasEnterpriseId(profileNetworkPreference.getPreferenceEnterpriseId())
16297                         && c.getEnterpriseIds().length == 1);
16298         if (disAllowProfileDefaultNetworkCallback != null) {
16299             assertNoCallbacks(disAllowProfileDefaultNetworkCallback);
16300         }
16301         assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback);
16302         inOrder.verify(mMockNetd, never()).networkAddUidRangesParcel(any());
16303 
16304         // When the agent disconnects, test that the app on the work profile fall back to the
16305         // default network.
16306         workAgent2.disconnect();
16307         profileDefaultNetworkCallback.expect(LOST, workAgent2);
16308         if (disAllowProfileDefaultNetworkCallback != null) {
16309             assertNoCallbacks(disAllowProfileDefaultNetworkCallback);
16310         }
16311         assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback);
16312         inOrder.verify(mMockNetd).networkDestroy(workAgent2.getNetwork().netId);
16313 
16314         assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback,
16315                 profileDefaultNetworkCallback);
16316 
16317         // Callbacks will be unregistered by tearDown()
16318     }
16319 
16320     /**
16321      * Make sure per-profile networking preference behaves as expected when the enterprise network
16322      * goes up and down while the preference is active. Make sure they behave as expected whether
16323      * there is a general default network or not.
16324      */
16325     @Test
16326     public void testPreferenceForUserNetworkUpDown() throws Exception {
16327         final UserHandle testHandle = setupEnterpriseNetwork();
16328         registerDefaultNetworkCallbacks();
16329         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder =
16330                 new ProfileNetworkPreference.Builder();
16331         profileNetworkPreferenceBuilder.setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE);
16332         profileNetworkPreferenceBuilder.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1);
16333         doTestPreferenceForUserNetworkUpDownForGivenPreference(
16334                 profileNetworkPreferenceBuilder.build(), false,
16335                 testHandle, mProfileDefaultNetworkCallback, null);
16336     }
16337 
16338     /**
16339      * Make sure per-profile networking preference behaves as expected when the enterprise network
16340      * goes up and down while the preference is active. Make sure they behave as expected whether
16341      * there is a general default network or not when configured to not fallback to default network.
16342      */
16343     @Test
16344     public void testPreferenceForUserNetworkUpDownWithNoFallback() throws Exception {
16345         final UserHandle testHandle = setupEnterpriseNetwork();
16346         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder =
16347                 new ProfileNetworkPreference.Builder();
16348         profileNetworkPreferenceBuilder.setPreference(
16349                 PROFILE_NETWORK_PREFERENCE_ENTERPRISE_NO_FALLBACK);
16350         profileNetworkPreferenceBuilder.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1);
16351         registerDefaultNetworkCallbacks();
16352         doTestPreferenceForUserNetworkUpDownForGivenPreference(
16353                 profileNetworkPreferenceBuilder.build(), false,
16354                 testHandle, mProfileDefaultNetworkCallback, null);
16355     }
16356 
16357     /**
16358      * Make sure per-profile networking preference behaves as expected when the enterprise network
16359      * goes up and down while the preference is active. Make sure they behave as expected whether
16360      * there is a general default network or not when configured to not fallback to default network
16361      * along with already connected enterprise work agent
16362      */
16363     @Test
16364     public void testPreferenceForUserNetworkUpDownWithNoFallbackWithAlreadyConnectedWorkAgent()
16365             throws Exception {
16366         final UserHandle testHandle = setupEnterpriseNetwork();
16367         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder =
16368                 new ProfileNetworkPreference.Builder();
16369         profileNetworkPreferenceBuilder.setPreference(
16370                 PROFILE_NETWORK_PREFERENCE_ENTERPRISE_NO_FALLBACK);
16371         profileNetworkPreferenceBuilder.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1);
16372         registerDefaultNetworkCallbacks();
16373         doTestPreferenceForUserNetworkUpDownForGivenPreference(
16374                 profileNetworkPreferenceBuilder.build(), true, testHandle,
16375                 mProfileDefaultNetworkCallback, null);
16376     }
16377 
16378     /**
16379      * Make sure per-profile networking preference for specific uid of test handle
16380      * behaves as expected
16381      */
16382     @Test
16383     public void testPreferenceForDefaultUidOfTestHandle() throws Exception {
16384         final UserHandle testHandle = setupEnterpriseNetwork();
16385         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder =
16386                 new ProfileNetworkPreference.Builder();
16387         profileNetworkPreferenceBuilder.setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE);
16388         profileNetworkPreferenceBuilder.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1);
16389         profileNetworkPreferenceBuilder.setIncludedUids(
16390                 new int[]{testHandle.getUid(TEST_WORK_PROFILE_APP_UID)});
16391         registerDefaultNetworkCallbacks();
16392         doTestPreferenceForUserNetworkUpDownForGivenPreference(
16393                 profileNetworkPreferenceBuilder.build(), false, testHandle,
16394                 mProfileDefaultNetworkCallback, null);
16395     }
16396 
16397     /**
16398      * Make sure per-profile networking preference for specific uid of test handle
16399      * behaves as expected
16400      */
16401     @Test
16402     public void testPreferenceForSpecificUidOfOnlyOneApp() throws Exception {
16403         final UserHandle testHandle = setupEnterpriseNetwork();
16404         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder =
16405                 new ProfileNetworkPreference.Builder();
16406         profileNetworkPreferenceBuilder.setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE);
16407         profileNetworkPreferenceBuilder.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1);
16408         profileNetworkPreferenceBuilder.setIncludedUids(
16409                 new int[]{testHandle.getUid(TEST_WORK_PROFILE_APP_UID_2)});
16410         registerDefaultNetworkCallbacks();
16411         doTestPreferenceForUserNetworkUpDownForGivenPreference(
16412                 profileNetworkPreferenceBuilder.build(), false,
16413                 testHandle, mProfileDefaultNetworkCallbackAsAppUid2, null);
16414     }
16415 
16416     /**
16417      * Make sure per-profile networking preference for specific uid of test handle
16418      * behaves as expected
16419      */
16420     @Test
16421     public void testPreferenceForDisallowSpecificUidOfApp() throws Exception {
16422         final UserHandle testHandle = setupEnterpriseNetwork();
16423         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder =
16424                 new ProfileNetworkPreference.Builder();
16425         profileNetworkPreferenceBuilder.setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE);
16426         profileNetworkPreferenceBuilder.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1);
16427         profileNetworkPreferenceBuilder.setExcludedUids(
16428                 new int[]{testHandle.getUid(TEST_WORK_PROFILE_APP_UID_2)});
16429         registerDefaultNetworkCallbacks();
16430         doTestPreferenceForUserNetworkUpDownForGivenPreference(
16431                 profileNetworkPreferenceBuilder.build(), false,
16432                 testHandle, mProfileDefaultNetworkCallback,
16433                 mProfileDefaultNetworkCallbackAsAppUid2);
16434     }
16435 
16436     /**
16437      * Make sure per-profile networking preference for specific uid of test handle
16438      * invalid uid inputs
16439      */
16440     @Test
16441     public void testPreferenceForInvalidUids() throws Exception {
16442         final UserHandle testHandle = setupEnterpriseNetwork();
16443         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder =
16444                 new ProfileNetworkPreference.Builder();
16445         profileNetworkPreferenceBuilder.setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE);
16446         profileNetworkPreferenceBuilder.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1);
16447         profileNetworkPreferenceBuilder.setExcludedUids(
16448                 new int[]{testHandle.getUid(0) - 1});
16449         final TestOnCompleteListener listener = new TestOnCompleteListener();
16450         Assert.assertThrows(IllegalArgumentException.class, () -> mCm.setProfileNetworkPreferences(
16451                 testHandle, List.of(profileNetworkPreferenceBuilder.build()),
16452                 r -> r.run(), listener));
16453 
16454         profileNetworkPreferenceBuilder.setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE);
16455         profileNetworkPreferenceBuilder.setIncludedUids(
16456                 new int[]{testHandle.getUid(0) - 1});
16457         Assert.assertThrows(IllegalArgumentException.class,
16458                 () -> mCm.setProfileNetworkPreferences(
16459                         testHandle, List.of(profileNetworkPreferenceBuilder.build()),
16460                         r -> r.run(), listener));
16461 
16462 
16463         profileNetworkPreferenceBuilder.setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE);
16464         profileNetworkPreferenceBuilder.setIncludedUids(
16465                 new int[]{testHandle.getUid(0) - 1});
16466         profileNetworkPreferenceBuilder.setExcludedUids(
16467                 new int[]{testHandle.getUid(TEST_WORK_PROFILE_APP_UID_2)});
16468         Assert.assertThrows(IllegalArgumentException.class,
16469                 () -> mCm.setProfileNetworkPreferences(
16470                         testHandle, List.of(profileNetworkPreferenceBuilder.build()),
16471                         r -> r.run(), listener));
16472 
16473         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder2 =
16474                 new ProfileNetworkPreference.Builder();
16475         profileNetworkPreferenceBuilder2.setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE);
16476         profileNetworkPreferenceBuilder2.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1);
16477         profileNetworkPreferenceBuilder2.setIncludedUids(
16478                 new int[]{testHandle.getUid(TEST_WORK_PROFILE_APP_UID_2)});
16479         profileNetworkPreferenceBuilder.setIncludedUids(
16480                 new int[]{testHandle.getUid(TEST_WORK_PROFILE_APP_UID_2)});
16481         Assert.assertThrows(IllegalArgumentException.class,
16482                 () -> mCm.setProfileNetworkPreferences(
16483                         testHandle, List.of(profileNetworkPreferenceBuilder.build(),
16484                                 profileNetworkPreferenceBuilder2.build()),
16485                         r -> r.run(), listener));
16486 
16487         profileNetworkPreferenceBuilder2.setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE);
16488         profileNetworkPreferenceBuilder2.setExcludedUids(
16489                 new int[]{testHandle.getUid(TEST_WORK_PROFILE_APP_UID_2)});
16490         profileNetworkPreferenceBuilder.setExcludedUids(
16491                 new int[]{testHandle.getUid(TEST_WORK_PROFILE_APP_UID_2)});
16492         Assert.assertThrows(IllegalArgumentException.class,
16493                 () -> mCm.setProfileNetworkPreferences(
16494                         testHandle, List.of(profileNetworkPreferenceBuilder.build(),
16495                                 profileNetworkPreferenceBuilder2.build()),
16496                         r -> r.run(), listener));
16497 
16498         profileNetworkPreferenceBuilder2.setPreference(
16499                 PROFILE_NETWORK_PREFERENCE_ENTERPRISE_NO_FALLBACK);
16500         profileNetworkPreferenceBuilder2.setExcludedUids(
16501                 new int[]{testHandle.getUid(TEST_WORK_PROFILE_APP_UID_2)});
16502         profileNetworkPreferenceBuilder.setExcludedUids(
16503                 new int[]{testHandle.getUid(TEST_WORK_PROFILE_APP_UID_2)});
16504         Assert.assertThrows(IllegalArgumentException.class,
16505                 () -> mCm.setProfileNetworkPreferences(
16506                         testHandle, List.of(profileNetworkPreferenceBuilder.build(),
16507                                 profileNetworkPreferenceBuilder2.build()),
16508                         r -> r.run(), listener));
16509     }
16510 
16511     /**
16512      * Make sure per-profile networking preference behaves as expected when the enterprise network
16513      * goes up and down while the preference is active. Make sure they behave as expected whether
16514      * there is a general default network or not when configured to fallback to default network
16515      * along with already connected enterprise work agent
16516      */
16517     @Test
16518     public void testPreferenceForUserNetworkUpDownWithFallbackWithAlreadyConnectedWorkAgent()
16519             throws Exception {
16520         final UserHandle testHandle = setupEnterpriseNetwork();
16521         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder =
16522                 new ProfileNetworkPreference.Builder();
16523         profileNetworkPreferenceBuilder.setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE);
16524         profileNetworkPreferenceBuilder.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1);
16525         registerDefaultNetworkCallbacks();
16526         doTestPreferenceForUserNetworkUpDownForGivenPreference(
16527                 profileNetworkPreferenceBuilder.build(), true,
16528                 testHandle, mProfileDefaultNetworkCallback,
16529                 null);
16530     }
16531 
16532     /**
16533      * Make sure per-profile networking preference behaves as expected when the enterprise network
16534      * goes up and down while the preference is active for a given enterprise identifier
16535      */
16536     @Test
16537     public void testPreferenceForUserNetworkUpDownWithDefaultEnterpriseId()
16538             throws Exception {
16539         final UserHandle testHandle = setupEnterpriseNetwork();
16540         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder =
16541                 new ProfileNetworkPreference.Builder();
16542         profileNetworkPreferenceBuilder.setPreference(
16543                 PROFILE_NETWORK_PREFERENCE_ENTERPRISE_NO_FALLBACK);
16544         profileNetworkPreferenceBuilder.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1);
16545         registerDefaultNetworkCallbacks();
16546         doTestPreferenceForUserNetworkUpDownForGivenPreference(
16547                 profileNetworkPreferenceBuilder.build(), true,
16548                 testHandle, mProfileDefaultNetworkCallback,
16549                 null);
16550     }
16551 
16552     /**
16553      * Make sure per-profile networking preference behaves as expected when the enterprise network
16554      * goes up and down while the preference is active for a given enterprise identifier
16555      */
16556     @Test
16557     public void testPreferenceForUserNetworkUpDownWithId2()
16558             throws Exception {
16559         final UserHandle testHandle = setupEnterpriseNetwork();
16560         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder =
16561                 new ProfileNetworkPreference.Builder();
16562         profileNetworkPreferenceBuilder.setPreference(
16563                 PROFILE_NETWORK_PREFERENCE_ENTERPRISE_NO_FALLBACK);
16564         profileNetworkPreferenceBuilder.setPreferenceEnterpriseId(
16565                 NET_ENTERPRISE_ID_2);
16566         registerDefaultNetworkCallbacks();
16567         doTestPreferenceForUserNetworkUpDownForGivenPreference(
16568                 profileNetworkPreferenceBuilder.build(), true,
16569                 testHandle, mProfileDefaultNetworkCallback, null);
16570     }
16571 
16572     /**
16573      * Make sure per-profile networking preference behaves as expected when the enterprise network
16574      * goes up and down while the preference is active for a given enterprise identifier
16575      */
16576     @Test
16577     public void testPreferenceForUserNetworkUpDownWithInvalidId()
16578             throws Exception {
16579         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder =
16580                 new ProfileNetworkPreference.Builder();
16581         profileNetworkPreferenceBuilder.setPreference(
16582                 PROFILE_NETWORK_PREFERENCE_ENTERPRISE_NO_FALLBACK);
16583         profileNetworkPreferenceBuilder.setPreferenceEnterpriseId(0);
16584         registerDefaultNetworkCallbacks();
16585         assertThrows("Should not be able to set invalid enterprise id",
16586                 IllegalStateException.class, () -> profileNetworkPreferenceBuilder.build());
16587     }
16588 
16589     /**
16590      * Make sure per-profile networking preference throws exception when default preference
16591      * is set along with enterprise preference.
16592      */
16593     @Test
16594     public void testPreferenceWithInvalidPreferenceDefaultAndEnterpriseTogether()
16595             throws Exception {
16596         final UserHandle testHandle = setupEnterpriseNetwork();
16597         mServiceContext.setWorkProfile(testHandle, true);
16598 
16599         final int testWorkProfileAppUid1 =
16600                 UserHandle.getUid(testHandle.getIdentifier(), TEST_APP_ID);
16601         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder1 =
16602                 new ProfileNetworkPreference.Builder();
16603         profileNetworkPreferenceBuilder1.setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE);
16604         profileNetworkPreferenceBuilder1.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1);
16605         profileNetworkPreferenceBuilder1.setIncludedUids(new int[]{testWorkProfileAppUid1});
16606 
16607         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder2 =
16608                 new ProfileNetworkPreference.Builder();
16609         profileNetworkPreferenceBuilder2.setPreference(PROFILE_NETWORK_PREFERENCE_DEFAULT);
16610         final TestOnCompleteListener listener = new TestOnCompleteListener();
16611         Assert.assertThrows(IllegalArgumentException.class,
16612                 () -> mCm.setProfileNetworkPreferences(
16613                         testHandle, List.of(profileNetworkPreferenceBuilder1.build(),
16614                                 profileNetworkPreferenceBuilder2.build()),
16615                         r -> r.run(), listener));
16616         Assert.assertThrows(IllegalArgumentException.class,
16617                 () -> mCm.setProfileNetworkPreferences(
16618                         testHandle, List.of(profileNetworkPreferenceBuilder2.build(),
16619                                 profileNetworkPreferenceBuilder1.build()),
16620                         r -> r.run(), listener));
16621     }
16622 
16623     /**
16624      * Make sure per profile network preferences behave as expected when two slices with
16625      * two different apps within same user profile is configured
16626      * Make sure per profile network preferences overrides with latest preference when
16627      * same user preference is set twice
16628      */
16629     @Test
16630     public void testSetPreferenceWithOverridingPreference()
16631             throws Exception {
16632         final InOrder inOrder = inOrder(mMockNetd);
16633         final UserHandle testHandle = setupEnterpriseNetwork();
16634         mServiceContext.setWorkProfile(testHandle, true);
16635         registerDefaultNetworkCallbacks();
16636 
16637         final TestNetworkCallback appCb1 = new TestNetworkCallback();
16638         final TestNetworkCallback appCb2 = new TestNetworkCallback();
16639         final TestNetworkCallback appCb3 = new TestNetworkCallback();
16640 
16641         final int testWorkProfileAppUid1 =
16642                 UserHandle.getUid(testHandle.getIdentifier(), TEST_APP_ID);
16643         final int testWorkProfileAppUid2 =
16644                 UserHandle.getUid(testHandle.getIdentifier(), TEST_APP_ID_2);
16645         final int testWorkProfileAppUid3 =
16646                 UserHandle.getUid(testHandle.getIdentifier(), TEST_APP_ID_3);
16647 
16648         registerDefaultNetworkCallbackAsUid(appCb1, testWorkProfileAppUid1);
16649         registerDefaultNetworkCallbackAsUid(appCb2, testWorkProfileAppUid2);
16650         registerDefaultNetworkCallbackAsUid(appCb3, testWorkProfileAppUid3);
16651 
16652         // Connect both a regular cell agent and an enterprise network first.
16653         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
16654         mCellAgent.connect(true);
16655 
16656         final TestNetworkAgentWrapper workAgent1 = makeEnterpriseNetworkAgent(NET_ENTERPRISE_ID_1);
16657         final TestNetworkAgentWrapper workAgent2 = makeEnterpriseNetworkAgent(NET_ENTERPRISE_ID_2);
16658         workAgent1.connect(true);
16659         workAgent2.connect(true);
16660 
16661         mSystemDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
16662         mDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
16663 
16664         appCb1.expectAvailableThenValidatedCallbacks(mCellAgent);
16665         appCb2.expectAvailableThenValidatedCallbacks(mCellAgent);
16666         appCb3.expectAvailableThenValidatedCallbacks(mCellAgent);
16667 
16668         verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
16669                 mCellAgent.getNetwork().netId, INetd.PERMISSION_NONE));
16670         verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
16671                 workAgent1.getNetwork().netId, INetd.PERMISSION_SYSTEM));
16672         verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
16673                 workAgent2.getNetwork().netId, INetd.PERMISSION_SYSTEM));
16674 
16675         final TestOnCompleteListener listener = new TestOnCompleteListener();
16676 
16677         // Set preferences for testHandle to map testWorkProfileAppUid1 to
16678         // NET_ENTERPRISE_ID_1 and testWorkProfileAppUid2 to NET_ENTERPRISE_ID_2.
16679         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder1 =
16680                 new ProfileNetworkPreference.Builder();
16681         profileNetworkPreferenceBuilder1.setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE);
16682         profileNetworkPreferenceBuilder1.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1);
16683         profileNetworkPreferenceBuilder1.setIncludedUids(new int[]{testWorkProfileAppUid1});
16684 
16685         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder2 =
16686                 new ProfileNetworkPreference.Builder();
16687         profileNetworkPreferenceBuilder2.setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE);
16688         profileNetworkPreferenceBuilder2.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_2);
16689         profileNetworkPreferenceBuilder2.setIncludedUids(new int[]{testWorkProfileAppUid2});
16690 
16691         mCm.setProfileNetworkPreferences(testHandle,
16692                 List.of(profileNetworkPreferenceBuilder1.build(),
16693                         profileNetworkPreferenceBuilder2.build()),
16694                 r -> r.run(), listener);
16695         listener.expectOnComplete();
16696         verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
16697                 workAgent2.getNetwork().netId,
16698                 uidRangeFor(testHandle, profileNetworkPreferenceBuilder2.build()),
16699                 PREFERENCE_ORDER_PROFILE));
16700         verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
16701                 workAgent1.getNetwork().netId,
16702                 uidRangeFor(testHandle, profileNetworkPreferenceBuilder1.build()),
16703                 PREFERENCE_ORDER_PROFILE));
16704 
16705         assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback);
16706         appCb1.expectAvailableCallbacksValidated(workAgent1);
16707         appCb2.expectAvailableCallbacksValidated(workAgent2);
16708 
16709         // Set preferences for testHandle to map testWorkProfileAppUid3 to
16710         // to NET_ENTERPRISE_ID_1.
16711         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder3 =
16712                 new ProfileNetworkPreference.Builder();
16713         profileNetworkPreferenceBuilder3.setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE);
16714         profileNetworkPreferenceBuilder3.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1);
16715         profileNetworkPreferenceBuilder3.setIncludedUids(new int[]{testWorkProfileAppUid3});
16716 
16717         mCm.setProfileNetworkPreferences(testHandle,
16718                 List.of(profileNetworkPreferenceBuilder3.build()),
16719                 r -> r.run(), listener);
16720         listener.expectOnComplete();
16721         verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
16722                 workAgent1.getNetwork().netId,
16723                 uidRangeFor(testHandle, profileNetworkPreferenceBuilder3.build()),
16724                 PREFERENCE_ORDER_PROFILE));
16725         verify(mMockNetd).networkRemoveUidRangesParcel(new NativeUidRangeConfig(
16726                 workAgent2.getNetwork().netId,
16727                 uidRangeFor(testHandle, profileNetworkPreferenceBuilder2.build()),
16728                 PREFERENCE_ORDER_PROFILE));
16729         verify(mMockNetd).networkRemoveUidRangesParcel(new NativeUidRangeConfig(
16730                 workAgent1.getNetwork().netId,
16731                 uidRangeFor(testHandle, profileNetworkPreferenceBuilder1.build()),
16732                 PREFERENCE_ORDER_PROFILE));
16733 
16734         assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback);
16735         appCb3.expectAvailableCallbacksValidated(workAgent1);
16736         appCb2.expectAvailableCallbacksValidated(mCellAgent);
16737         appCb1.expectAvailableCallbacksValidated(mCellAgent);
16738 
16739         // Set the preferences for testHandle to default.
16740         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder =
16741                 new ProfileNetworkPreference.Builder();
16742         profileNetworkPreferenceBuilder.setPreference(PROFILE_NETWORK_PREFERENCE_DEFAULT);
16743 
16744         mCm.setProfileNetworkPreferences(testHandle,
16745                 List.of(profileNetworkPreferenceBuilder.build()),
16746                 r -> r.run(), listener);
16747         listener.expectOnComplete();
16748         verify(mMockNetd).networkRemoveUidRangesParcel(new NativeUidRangeConfig(
16749                 workAgent1.getNetwork().netId,
16750                 uidRangeFor(testHandle, profileNetworkPreferenceBuilder3.build()),
16751                 PREFERENCE_ORDER_PROFILE));
16752 
16753         assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback, appCb1, appCb2);
16754         appCb3.expectAvailableCallbacksValidated(mCellAgent);
16755         workAgent2.disconnect();
16756         mCellAgent.disconnect();
16757 
16758         mCm.unregisterNetworkCallback(appCb1);
16759         mCm.unregisterNetworkCallback(appCb2);
16760         mCm.unregisterNetworkCallback(appCb3);
16761         // Other callbacks will be unregistered by tearDown()
16762     }
16763 
16764     private NetworkCallback requestForEnterpriseId(@NetworkCapabilities.EnterpriseId final int id) {
16765         final NetworkCapabilities nc = new NetworkCapabilities.Builder()
16766                 .addCapability(NET_CAPABILITY_ENTERPRISE).addEnterpriseId(id).build();
16767         final NetworkRequest req = new NetworkRequest.Builder().setCapabilities(nc).build();
16768         final NetworkCallback cb = new TestableNetworkCallback();
16769         mCm.requestNetwork(req, cb);
16770         return cb;
16771     }
16772 
16773     /**
16774      * Make sure per profile network preferences behave as expected when multiple slices with
16775      * multiple different apps within same user profile is configured.
16776      */
16777     @Test
16778     public void testSetPreferenceWithMultiplePreferences()
16779             throws Exception {
16780         final UserHandle testHandle = setupEnterpriseNetwork();
16781         mServiceContext.setWorkProfile(testHandle, true);
16782         registerDefaultNetworkCallbacks();
16783 
16784         final TestNetworkCallback appCb1 = new TestNetworkCallback();
16785         final TestNetworkCallback appCb2 = new TestNetworkCallback();
16786         final TestNetworkCallback appCb3 = new TestNetworkCallback();
16787         final TestNetworkCallback appCb4 = new TestNetworkCallback();
16788         final TestNetworkCallback appCb5 = new TestNetworkCallback();
16789 
16790         final int testWorkProfileAppUid1 =
16791                 UserHandle.getUid(testHandle.getIdentifier(), TEST_APP_ID);
16792         final int testWorkProfileAppUid2 =
16793                 UserHandle.getUid(testHandle.getIdentifier(), TEST_APP_ID_2);
16794         final int testWorkProfileAppUid3 =
16795                 UserHandle.getUid(testHandle.getIdentifier(), TEST_APP_ID_3);
16796         final int testWorkProfileAppUid4 =
16797                 UserHandle.getUid(testHandle.getIdentifier(), TEST_APP_ID_4);
16798         final int testWorkProfileAppUid5 =
16799                 UserHandle.getUid(testHandle.getIdentifier(), TEST_APP_ID_5);
16800 
16801         registerDefaultNetworkCallbackAsUid(appCb1, testWorkProfileAppUid1);
16802         registerDefaultNetworkCallbackAsUid(appCb2, testWorkProfileAppUid2);
16803         registerDefaultNetworkCallbackAsUid(appCb3, testWorkProfileAppUid3);
16804         registerDefaultNetworkCallbackAsUid(appCb4, testWorkProfileAppUid4);
16805         registerDefaultNetworkCallbackAsUid(appCb5, testWorkProfileAppUid5);
16806 
16807         // Connect both a regular cell agent and an enterprise network first.
16808         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
16809         mCellAgent.connect(true);
16810 
16811         final TestNetworkAgentWrapper workAgent1 = makeEnterpriseNetworkAgent(NET_ENTERPRISE_ID_1);
16812         final TestNetworkAgentWrapper workAgent2 = makeEnterpriseNetworkAgent(NET_ENTERPRISE_ID_2);
16813         final TestNetworkAgentWrapper workAgent3 = makeEnterpriseNetworkAgent(NET_ENTERPRISE_ID_3);
16814         final TestNetworkAgentWrapper workAgent4 = makeEnterpriseNetworkAgent(NET_ENTERPRISE_ID_4);
16815         final TestNetworkAgentWrapper workAgent5 = makeEnterpriseNetworkAgent(NET_ENTERPRISE_ID_5);
16816 
16817         final NetworkCallback keepupCb1 = requestForEnterpriseId(NET_ENTERPRISE_ID_1);
16818         final NetworkCallback keepupCb2 = requestForEnterpriseId(NET_ENTERPRISE_ID_2);
16819         final NetworkCallback keepupCb3 = requestForEnterpriseId(NET_ENTERPRISE_ID_3);
16820         final NetworkCallback keepupCb4 = requestForEnterpriseId(NET_ENTERPRISE_ID_4);
16821         final NetworkCallback keepupCb5 = requestForEnterpriseId(NET_ENTERPRISE_ID_5);
16822 
16823         workAgent1.connect(true);
16824         workAgent2.connect(true);
16825         workAgent3.connect(true);
16826         workAgent4.connect(true);
16827         workAgent5.connect(true);
16828 
16829         mSystemDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
16830         mDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
16831         appCb1.expectAvailableThenValidatedCallbacks(mCellAgent);
16832         appCb2.expectAvailableThenValidatedCallbacks(mCellAgent);
16833         appCb3.expectAvailableThenValidatedCallbacks(mCellAgent);
16834         appCb4.expectAvailableThenValidatedCallbacks(mCellAgent);
16835         appCb5.expectAvailableThenValidatedCallbacks(mCellAgent);
16836 
16837         verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
16838                 mCellAgent.getNetwork().netId, INetd.PERMISSION_NONE));
16839         verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
16840                 workAgent1.getNetwork().netId, INetd.PERMISSION_SYSTEM));
16841         verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
16842                 workAgent2.getNetwork().netId, INetd.PERMISSION_SYSTEM));
16843         verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
16844                 workAgent3.getNetwork().netId, INetd.PERMISSION_SYSTEM));
16845         verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
16846                 workAgent4.getNetwork().netId, INetd.PERMISSION_SYSTEM));
16847         verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
16848                 workAgent5.getNetwork().netId, INetd.PERMISSION_SYSTEM));
16849 
16850         final TestOnCompleteListener listener = new TestOnCompleteListener();
16851 
16852         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder1 =
16853                 new ProfileNetworkPreference.Builder();
16854         profileNetworkPreferenceBuilder1.setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE);
16855         profileNetworkPreferenceBuilder1.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1);
16856         profileNetworkPreferenceBuilder1.setIncludedUids(new int[]{testWorkProfileAppUid1});
16857 
16858         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder2 =
16859                 new ProfileNetworkPreference.Builder();
16860         profileNetworkPreferenceBuilder2.setPreference(
16861                 PROFILE_NETWORK_PREFERENCE_ENTERPRISE_NO_FALLBACK);
16862         profileNetworkPreferenceBuilder2.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_2);
16863         profileNetworkPreferenceBuilder2.setIncludedUids(new int[]{testWorkProfileAppUid2});
16864 
16865         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder3 =
16866                 new ProfileNetworkPreference.Builder();
16867         profileNetworkPreferenceBuilder3.setPreference(
16868                 PROFILE_NETWORK_PREFERENCE_ENTERPRISE);
16869         profileNetworkPreferenceBuilder3.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_3);
16870         profileNetworkPreferenceBuilder3.setIncludedUids(new int[]{testWorkProfileAppUid3});
16871 
16872         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder4 =
16873                 new ProfileNetworkPreference.Builder();
16874         profileNetworkPreferenceBuilder4.setPreference(
16875                 PROFILE_NETWORK_PREFERENCE_ENTERPRISE_NO_FALLBACK);
16876         profileNetworkPreferenceBuilder4.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_4);
16877         profileNetworkPreferenceBuilder4.setIncludedUids(new int[]{testWorkProfileAppUid4});
16878 
16879         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder5 =
16880                 new ProfileNetworkPreference.Builder();
16881         profileNetworkPreferenceBuilder5.setPreference(
16882                 PROFILE_NETWORK_PREFERENCE_ENTERPRISE);
16883         profileNetworkPreferenceBuilder5.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_5);
16884         profileNetworkPreferenceBuilder5.setIncludedUids(new int[]{testWorkProfileAppUid5});
16885 
16886         mCm.setProfileNetworkPreferences(testHandle,
16887                 List.of(profileNetworkPreferenceBuilder1.build(),
16888                         profileNetworkPreferenceBuilder2.build(),
16889                         profileNetworkPreferenceBuilder3.build(),
16890                         profileNetworkPreferenceBuilder4.build(),
16891                         profileNetworkPreferenceBuilder5.build()),
16892                 r -> r.run(), listener);
16893 
16894         listener.expectOnComplete();
16895 
16896         verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
16897                 workAgent1.getNetwork().netId,
16898                 uidRangeFor(testHandle, profileNetworkPreferenceBuilder1.build()),
16899                 PREFERENCE_ORDER_PROFILE));
16900         verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
16901                 workAgent2.getNetwork().netId,
16902                 uidRangeFor(testHandle, profileNetworkPreferenceBuilder2.build()),
16903                 PREFERENCE_ORDER_PROFILE));
16904         verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
16905                 workAgent3.getNetwork().netId,
16906                 uidRangeFor(testHandle, profileNetworkPreferenceBuilder3.build()),
16907                 PREFERENCE_ORDER_PROFILE));
16908         verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
16909                 workAgent4.getNetwork().netId,
16910                 uidRangeFor(testHandle, profileNetworkPreferenceBuilder4.build()),
16911                 PREFERENCE_ORDER_PROFILE));
16912         verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
16913                 workAgent5.getNetwork().netId,
16914                 uidRangeFor(testHandle, profileNetworkPreferenceBuilder5.build()),
16915                 PREFERENCE_ORDER_PROFILE));
16916 
16917         assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback);
16918         appCb1.expectAvailableCallbacksValidated(workAgent1);
16919         appCb2.expectAvailableCallbacksValidated(workAgent2);
16920         appCb3.expectAvailableCallbacksValidated(workAgent3);
16921         appCb4.expectAvailableCallbacksValidated(workAgent4);
16922         appCb5.expectAvailableCallbacksValidated(workAgent5);
16923 
16924         workAgent1.disconnect();
16925         workAgent2.disconnect();
16926         workAgent3.disconnect();
16927         workAgent4.disconnect();
16928         workAgent5.disconnect();
16929 
16930         appCb1.expect(LOST, workAgent1);
16931         appCb2.expect(LOST, workAgent2);
16932         appCb3.expect(LOST, workAgent3);
16933         appCb4.expect(LOST, workAgent4);
16934         appCb5.expect(LOST, workAgent5);
16935 
16936         appCb1.expectAvailableCallbacksValidated(mCellAgent);
16937         appCb2.assertNoCallback();
16938         appCb3.expectAvailableCallbacksValidated(mCellAgent);
16939         appCb4.assertNoCallback();
16940         appCb5.expectAvailableCallbacksValidated(mCellAgent);
16941 
16942         verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
16943                 mCellAgent.getNetwork().netId,
16944                 uidRangeFor(testHandle, profileNetworkPreferenceBuilder1.build()),
16945                 PREFERENCE_ORDER_PROFILE));
16946         verify(mMockNetd, never()).networkAddUidRangesParcel(new NativeUidRangeConfig(
16947                 mCellAgent.getNetwork().netId,
16948                 uidRangeFor(testHandle, profileNetworkPreferenceBuilder2.build()),
16949                 PREFERENCE_ORDER_PROFILE));
16950         verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
16951                 mCellAgent.getNetwork().netId,
16952                 uidRangeFor(testHandle, profileNetworkPreferenceBuilder3.build()),
16953                 PREFERENCE_ORDER_PROFILE));
16954         verify(mMockNetd, never()).networkAddUidRangesParcel(new NativeUidRangeConfig(
16955                 mCellAgent.getNetwork().netId,
16956                 uidRangeFor(testHandle, profileNetworkPreferenceBuilder4.build()),
16957                 PREFERENCE_ORDER_PROFILE));
16958         verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
16959                 mCellAgent.getNetwork().netId,
16960                 uidRangeFor(testHandle, profileNetworkPreferenceBuilder5.build()),
16961                 PREFERENCE_ORDER_PROFILE));
16962 
16963         mSystemDefaultNetworkCallback.assertNoCallback();
16964         mDefaultNetworkCallback.assertNoCallback();
16965 
16966         // Set the preferences for testHandle to default.
16967         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder =
16968                 new ProfileNetworkPreference.Builder();
16969         profileNetworkPreferenceBuilder.setPreference(PROFILE_NETWORK_PREFERENCE_DEFAULT);
16970 
16971         mCm.setProfileNetworkPreferences(testHandle,
16972                 List.of(profileNetworkPreferenceBuilder.build()),
16973                 r -> r.run(), listener);
16974         listener.expectOnComplete();
16975         assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback, appCb1, appCb3,
16976                 appCb5);
16977         appCb2.expectAvailableCallbacksValidated(mCellAgent);
16978         appCb4.expectAvailableCallbacksValidated(mCellAgent);
16979         mCellAgent.disconnect();
16980 
16981         mCm.unregisterNetworkCallback(keepupCb1);
16982         mCm.unregisterNetworkCallback(keepupCb2);
16983         mCm.unregisterNetworkCallback(keepupCb3);
16984         mCm.unregisterNetworkCallback(keepupCb4);
16985         mCm.unregisterNetworkCallback(keepupCb5);
16986 
16987         mCm.unregisterNetworkCallback(appCb1);
16988         mCm.unregisterNetworkCallback(appCb2);
16989         mCm.unregisterNetworkCallback(appCb3);
16990         mCm.unregisterNetworkCallback(appCb4);
16991         mCm.unregisterNetworkCallback(appCb5);
16992         // Other callbacks will be unregistered by tearDown()
16993     }
16994 
16995     /**
16996      * Test that, in a given networking context, calling setPreferenceForUser to set per-profile
16997      * defaults on then off works as expected.
16998      */
16999     @Test
17000     public void testSetPreferenceForUserOnOff() throws Exception {
17001         final InOrder inOrder = inOrder(mMockNetd);
17002         final UserHandle testHandle = setupEnterpriseNetwork();
17003 
17004         // Connect both a regular cell agent and an enterprise network first.
17005         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
17006         mCellAgent.connect(true);
17007 
17008         final TestNetworkAgentWrapper workAgent = makeEnterpriseNetworkAgent();
17009         workAgent.connect(true);
17010 
17011         final TestOnCompleteListener listener = new TestOnCompleteListener();
17012         mCm.setProfileNetworkPreference(testHandle, PROFILE_NETWORK_PREFERENCE_ENTERPRISE,
17013                 r -> r.run(), listener);
17014         listener.expectOnComplete();
17015         inOrder.verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
17016                 mCellAgent.getNetwork().netId, INetd.PERMISSION_NONE));
17017         inOrder.verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
17018                 workAgent.getNetwork().netId, uidRangeFor(testHandle), PREFERENCE_ORDER_PROFILE));
17019 
17020         registerDefaultNetworkCallbacks();
17021 
17022         mSystemDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellAgent);
17023         mDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellAgent);
17024         mProfileDefaultNetworkCallback.expectAvailableCallbacksValidated(workAgent);
17025 
17026         mCm.setProfileNetworkPreference(testHandle, PROFILE_NETWORK_PREFERENCE_DEFAULT,
17027                 r -> r.run(), listener);
17028         listener.expectOnComplete();
17029 
17030         mProfileDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellAgent);
17031         assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback);
17032         inOrder.verify(mMockNetd).networkRemoveUidRangesParcel(new NativeUidRangeConfig(
17033                 workAgent.getNetwork().netId, uidRangeFor(testHandle), PREFERENCE_ORDER_PROFILE));
17034 
17035         workAgent.disconnect();
17036         mCellAgent.disconnect();
17037 
17038         // Callbacks will be unregistered by tearDown()
17039     }
17040 
17041     /**
17042      * Test per-profile default networks for two different profiles concurrently.
17043      */
17044     @Test
17045     public void testSetPreferenceForTwoProfiles() throws Exception {
17046         final InOrder inOrder = inOrder(mMockNetd);
17047         final UserHandle testHandle2 = setupEnterpriseNetwork();
17048         final UserHandle testHandle4 = UserHandle.of(TEST_WORK_PROFILE_USER_ID + 2);
17049         mServiceContext.setWorkProfile(testHandle4, true);
17050         registerDefaultNetworkCallbacks();
17051 
17052         final TestNetworkCallback app4Cb = new TestNetworkCallback();
17053         final int testWorkProfileAppUid4 =
17054                 UserHandle.getUid(testHandle4.getIdentifier(), TEST_APP_ID);
17055         registerDefaultNetworkCallbackAsUid(app4Cb, testWorkProfileAppUid4);
17056 
17057         // Connect both a regular cell agent and an enterprise network first.
17058         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
17059         mCellAgent.connect(true);
17060 
17061         final TestNetworkAgentWrapper workAgent = makeEnterpriseNetworkAgent();
17062         workAgent.connect(true);
17063 
17064         mSystemDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
17065         mDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
17066         mProfileDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
17067         app4Cb.expectAvailableThenValidatedCallbacks(mCellAgent);
17068         inOrder.verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
17069                 mCellAgent.getNetwork().netId, INetd.PERMISSION_NONE));
17070         inOrder.verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
17071                 workAgent.getNetwork().netId, INetd.PERMISSION_SYSTEM));
17072 
17073         final TestOnCompleteListener listener = new TestOnCompleteListener();
17074         mCm.setProfileNetworkPreference(testHandle2, PROFILE_NETWORK_PREFERENCE_ENTERPRISE,
17075                 r -> r.run(), listener);
17076         listener.expectOnComplete();
17077         inOrder.verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
17078                 workAgent.getNetwork().netId, uidRangeFor(testHandle2), PREFERENCE_ORDER_PROFILE));
17079 
17080         mProfileDefaultNetworkCallback.expectAvailableCallbacksValidated(workAgent);
17081         assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback,
17082                 app4Cb);
17083 
17084         mCm.setProfileNetworkPreference(testHandle4, PROFILE_NETWORK_PREFERENCE_ENTERPRISE,
17085                 r -> r.run(), listener);
17086         listener.expectOnComplete();
17087         inOrder.verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
17088                 workAgent.getNetwork().netId, uidRangeFor(testHandle4), PREFERENCE_ORDER_PROFILE));
17089 
17090         app4Cb.expectAvailableCallbacksValidated(workAgent);
17091         assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback,
17092                 mProfileDefaultNetworkCallback);
17093 
17094         mCm.setProfileNetworkPreference(testHandle2, PROFILE_NETWORK_PREFERENCE_DEFAULT,
17095                 r -> r.run(), listener);
17096         listener.expectOnComplete();
17097         inOrder.verify(mMockNetd).networkRemoveUidRangesParcel(new NativeUidRangeConfig(
17098                 workAgent.getNetwork().netId, uidRangeFor(testHandle2), PREFERENCE_ORDER_PROFILE));
17099 
17100         mProfileDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellAgent);
17101         assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback,
17102                 app4Cb);
17103 
17104         workAgent.disconnect();
17105         mCellAgent.disconnect();
17106 
17107         mCm.unregisterNetworkCallback(app4Cb);
17108         // Other callbacks will be unregistered by tearDown()
17109     }
17110 
17111     @Test
17112     public void testProfilePreferenceRemovedUponUserRemoved() throws Exception {
17113         final InOrder inOrder = inOrder(mMockNetd);
17114         final UserHandle testHandle = setupEnterpriseNetwork();
17115 
17116         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
17117         mCellAgent.connect(true);
17118 
17119         final TestOnCompleteListener listener = new TestOnCompleteListener();
17120         mCm.setProfileNetworkPreference(testHandle, PROFILE_NETWORK_PREFERENCE_ENTERPRISE,
17121                 r -> r.run(), listener);
17122         listener.expectOnComplete();
17123         inOrder.verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
17124                 mCellAgent.getNetwork().netId, INetd.PERMISSION_NONE));
17125         inOrder.verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
17126                 mCellAgent.getNetwork().netId, uidRangeFor(testHandle),
17127                 PREFERENCE_ORDER_PROFILE));
17128 
17129         final Intent removedIntent = new Intent(ACTION_USER_REMOVED);
17130         removedIntent.putExtra(Intent.EXTRA_USER, testHandle);
17131         processBroadcast(removedIntent);
17132 
17133         inOrder.verify(mMockNetd).networkRemoveUidRangesParcel(new NativeUidRangeConfig(
17134                 mCellAgent.getNetwork().netId, uidRangeFor(testHandle),
17135                 PREFERENCE_ORDER_PROFILE));
17136     }
17137 
17138     @Test
17139     public void testProfileNetworkPreferenceBlocking_addUser() throws Exception {
17140         final InOrder inOrder = inOrder(mMockNetd);
17141         doReturn(asList(PRIMARY_USER_HANDLE)).when(mUserManager).getUserHandles(anyBoolean());
17142 
17143         // Only one network
17144         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
17145         mCellAgent.connect(true);
17146 
17147         // Verify uid ranges 0~99999 are allowed
17148         final ArraySet<UidRange> allowedRanges = new ArraySet<>();
17149         allowedRanges.add(PRIMARY_UIDRANGE);
17150         final NativeUidRangeConfig config1User = new NativeUidRangeConfig(
17151                 mCellAgent.getNetwork().netId,
17152                 toUidRangeStableParcels(allowedRanges),
17153                 0 /* subPriority */);
17154         if (mDeps.isAtLeastU()) {
17155             inOrder.verify(mMockNetd).setNetworkAllowlist(new NativeUidRangeConfig[]{config1User});
17156         } else {
17157             inOrder.verify(mMockNetd, never()).setNetworkAllowlist(any());
17158         }
17159 
17160         doReturn(asList(PRIMARY_USER_HANDLE, SECONDARY_USER_HANDLE))
17161                 .when(mUserManager).getUserHandles(anyBoolean());
17162         final Intent addedIntent = new Intent(ACTION_USER_ADDED);
17163         addedIntent.putExtra(Intent.EXTRA_USER, UserHandle.of(SECONDARY_USER));
17164         processBroadcast(addedIntent);
17165 
17166         // Make sure the allow list has been updated.
17167         allowedRanges.add(UidRange.createForUser(SECONDARY_USER_HANDLE));
17168         final NativeUidRangeConfig config2Users = new NativeUidRangeConfig(
17169                 mCellAgent.getNetwork().netId,
17170                 toUidRangeStableParcels(allowedRanges),
17171                 0 /* subPriority */);
17172         if (mDeps.isAtLeastU()) {
17173             inOrder.verify(mMockNetd).setNetworkAllowlist(new NativeUidRangeConfig[]{config2Users});
17174         } else {
17175             inOrder.verify(mMockNetd, never()).setNetworkAllowlist(any());
17176         }
17177     }
17178 
17179     @Test
17180     public void testProfileNetworkPreferenceBlocking_changePreference() throws Exception {
17181         final InOrder inOrder = inOrder(mMockNetd);
17182         final UserHandle testHandle = setupEnterpriseNetwork();
17183         doReturn(asList(PRIMARY_USER_HANDLE, testHandle))
17184                 .when(mUserManager).getUserHandles(anyBoolean());
17185 
17186         // Start with 1 default network and 1 enterprise network, both networks should
17187         // not be restricted since the blocking preference is not set yet.
17188         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
17189         mCellAgent.connect(true);
17190 
17191         // Verify uid ranges 0~99999, 200000~299999 are all allowed for cellular.
17192         final UidRange profileUidRange =
17193                 UidRange.createForUser(UserHandle.of(TEST_WORK_PROFILE_USER_ID));
17194         ArraySet<UidRange> allowedAllUidRanges = new ArraySet<>();
17195         allowedAllUidRanges.add(PRIMARY_UIDRANGE);
17196         allowedAllUidRanges.add(profileUidRange);
17197         final UidRangeParcel[] allowAllUidRangesParcel = toUidRangeStableParcels(
17198                 allowedAllUidRanges);
17199         final NativeUidRangeConfig cellAllAllowedConfig = new NativeUidRangeConfig(
17200                 mCellAgent.getNetwork().netId,
17201                 allowAllUidRangesParcel,
17202                 0 /* subPriority */);
17203         if (mDeps.isAtLeastU()) {
17204             inOrder.verify(mMockNetd).setNetworkAllowlist(
17205                     new NativeUidRangeConfig[]{cellAllAllowedConfig});
17206         } else {
17207             inOrder.verify(mMockNetd, never()).setNetworkAllowlist(any());
17208         }
17209 
17210         // Verify the same uid ranges are also applied for enterprise network.
17211         final TestNetworkAgentWrapper enterpriseAgent = makeEnterpriseNetworkAgent(
17212                 NET_ENTERPRISE_ID_1);
17213         enterpriseAgent.connect(true);
17214         final NativeUidRangeConfig enterpriseAllAllowedConfig = new NativeUidRangeConfig(
17215                 enterpriseAgent.getNetwork().netId,
17216                 allowAllUidRangesParcel,
17217                 0 /* subPriority */);
17218         // Network agents are stored in an ArraySet which does not guarantee the order and
17219         // making the order of the list undeterministic. Thus, verify this in order insensitive way.
17220         final ArgumentCaptor<NativeUidRangeConfig[]> configsCaptor = ArgumentCaptor.forClass(
17221                 NativeUidRangeConfig[].class);
17222         if (mDeps.isAtLeastU()) {
17223             inOrder.verify(mMockNetd).setNetworkAllowlist(configsCaptor.capture());
17224             assertContainsAll(List.of(configsCaptor.getValue()),
17225                     List.of(cellAllAllowedConfig, enterpriseAllAllowedConfig));
17226         } else {
17227             inOrder.verify(mMockNetd, never()).setNetworkAllowlist(any());
17228         }
17229 
17230         // Setup profile preference which only applies to test app uid on the managed profile.
17231         ProfileNetworkPreference.Builder prefBuilder = new ProfileNetworkPreference.Builder();
17232         prefBuilder.setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE_BLOCKING)
17233                 .setIncludedUids(new int[]{testHandle.getUid(TEST_WORK_PROFILE_APP_UID)})
17234                 .setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1);
17235         final TestOnCompleteListener listener = new TestOnCompleteListener();
17236         mCm.setProfileNetworkPreferences(testHandle,
17237                 List.of(prefBuilder.build()),
17238                 r -> r.run(), listener);
17239         listener.expectOnComplete();
17240 
17241         // Verify Netd is called for the preferences changed.
17242         // Cell: 0~99999, 200000~TEST_APP_UID-1, TEST_APP_UID+1~299999
17243         // Enterprise: 0~99999, 200000~299999
17244         final ArraySet<UidRange> excludeAppRanges = new ArraySet<>();
17245         excludeAppRanges.add(PRIMARY_UIDRANGE);
17246         excludeAppRanges.addAll(UidRangeUtils.removeRangeSetFromUidRange(
17247                 profileUidRange,
17248                 new ArraySet(new UidRange[]{
17249                         (new UidRange(TEST_WORK_PROFILE_APP_UID, TEST_WORK_PROFILE_APP_UID))})
17250         ));
17251         final UidRangeParcel[] excludeAppRangesParcel = toUidRangeStableParcels(excludeAppRanges);
17252         final NativeUidRangeConfig cellExcludeAppConfig = new NativeUidRangeConfig(
17253                 mCellAgent.getNetwork().netId,
17254                 excludeAppRangesParcel,
17255                 0 /* subPriority */);
17256         if (mDeps.isAtLeastU()) {
17257             inOrder.verify(mMockNetd).setNetworkAllowlist(configsCaptor.capture());
17258             assertContainsAll(List.of(configsCaptor.getValue()),
17259                     List.of(cellExcludeAppConfig, enterpriseAllAllowedConfig));
17260         } else {
17261             inOrder.verify(mMockNetd, never()).setNetworkAllowlist(any());
17262         }
17263 
17264         // Verify unset by giving all allowed set for all users when the preference got removed.
17265         mCm.setProfileNetworkPreference(testHandle, PROFILE_NETWORK_PREFERENCE_ENTERPRISE,
17266                 r -> r.run(), listener);
17267         listener.expectOnComplete();
17268         if (mDeps.isAtLeastU()) {
17269             inOrder.verify(mMockNetd).setNetworkAllowlist(configsCaptor.capture());
17270             assertContainsAll(List.of(configsCaptor.getValue()),
17271                     List.of(cellAllAllowedConfig, enterpriseAllAllowedConfig));
17272         } else {
17273             inOrder.verify(mMockNetd, never()).setNetworkAllowlist(any());
17274         }
17275 
17276         // Verify issuing with cellular set only when a network with enterprise capability
17277         // disconnects.
17278         enterpriseAgent.disconnect();
17279         waitForIdle();
17280         if (mDeps.isAtLeastU()) {
17281             inOrder.verify(mMockNetd).setNetworkAllowlist(
17282                     new NativeUidRangeConfig[]{cellAllAllowedConfig});
17283         } else {
17284             inOrder.verify(mMockNetd, never()).setNetworkAllowlist(any());
17285         }
17286     }
17287 
17288     @Test
17289     public void testProfileNetworkPreferenceBlocking_networkChanges() throws Exception {
17290         final InOrder inOrder = inOrder(mMockNetd);
17291         final UserHandle testHandle = setupEnterpriseNetwork();
17292         doReturn(asList(PRIMARY_USER_HANDLE, testHandle))
17293                 .when(mUserManager).getUserHandles(anyBoolean());
17294 
17295         // Setup profile preference which only applies to test app uid on the managed profile.
17296         ProfileNetworkPreference.Builder prefBuilder = new ProfileNetworkPreference.Builder();
17297         prefBuilder.setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE_BLOCKING)
17298                 .setIncludedUids(new int[]{testHandle.getUid(TEST_WORK_PROFILE_APP_UID)})
17299                 .setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1);
17300         final TestOnCompleteListener listener = new TestOnCompleteListener();
17301         mCm.setProfileNetworkPreferences(testHandle,
17302                 List.of(prefBuilder.build()),
17303                 r -> r.run(), listener);
17304         listener.expectOnComplete();
17305         if (mDeps.isAtLeastU()) {
17306             inOrder.verify(mMockNetd).setNetworkAllowlist(new NativeUidRangeConfig[]{});
17307         } else {
17308             inOrder.verify(mMockNetd, never()).setNetworkAllowlist(any());
17309         }
17310 
17311         // Start with 1 default network, which should be restricted since the blocking
17312         // preference is already set.
17313         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
17314         mCellAgent.connect(true);
17315 
17316         // Verify cellular network applies to the allow list.
17317         // Cell: 0~99999, 200000~TEST_APP_UID-1, TEST_APP_UID+1~299999
17318         // Enterprise: 0~99999, 200000~299999
17319         final ArraySet<UidRange> excludeAppRanges = new ArraySet<>();
17320         final UidRange profileUidRange =
17321                 UidRange.createForUser(UserHandle.of(TEST_WORK_PROFILE_USER_ID));
17322         excludeAppRanges.add(PRIMARY_UIDRANGE);
17323         excludeAppRanges.addAll(UidRangeUtils.removeRangeSetFromUidRange(
17324                 profileUidRange,
17325                 new ArraySet(new UidRange[]{
17326                         (new UidRange(TEST_WORK_PROFILE_APP_UID, TEST_WORK_PROFILE_APP_UID))})
17327         ));
17328         final UidRangeParcel[] excludeAppRangesParcel = toUidRangeStableParcels(excludeAppRanges);
17329         final NativeUidRangeConfig cellExcludeAppConfig = new NativeUidRangeConfig(
17330                 mCellAgent.getNetwork().netId,
17331                 excludeAppRangesParcel,
17332                 0 /* subPriority */);
17333         if (mDeps.isAtLeastU()) {
17334             inOrder.verify(mMockNetd).setNetworkAllowlist(
17335                     new NativeUidRangeConfig[]{cellExcludeAppConfig});
17336         } else {
17337             inOrder.verify(mMockNetd, never()).setNetworkAllowlist(any());
17338         }
17339 
17340         // Verify enterprise network is not blocked for test app.
17341         final TestNetworkAgentWrapper enterpriseAgent = makeEnterpriseNetworkAgent(
17342                 NET_ENTERPRISE_ID_1);
17343         enterpriseAgent.connect(true);
17344         ArraySet<UidRange> allowedAllUidRanges = new ArraySet<>();
17345         allowedAllUidRanges.add(PRIMARY_UIDRANGE);
17346         allowedAllUidRanges.add(profileUidRange);
17347         final UidRangeParcel[] allowAllUidRangesParcel = toUidRangeStableParcels(
17348                 allowedAllUidRanges);
17349         final NativeUidRangeConfig enterpriseAllAllowedConfig = new NativeUidRangeConfig(
17350                 enterpriseAgent.getNetwork().netId,
17351                 allowAllUidRangesParcel,
17352                 0 /* subPriority */);
17353         // Network agents are stored in an ArraySet which does not guarantee the order and
17354         // making the order of the list undeterministic. Thus, verify this in order insensitive way.
17355         final ArgumentCaptor<NativeUidRangeConfig[]> configsCaptor = ArgumentCaptor.forClass(
17356                 NativeUidRangeConfig[].class);
17357         if (mDeps.isAtLeastU()) {
17358             inOrder.verify(mMockNetd).setNetworkAllowlist(configsCaptor.capture());
17359             assertContainsAll(List.of(configsCaptor.getValue()),
17360                     List.of(enterpriseAllAllowedConfig, cellExcludeAppConfig));
17361         } else {
17362             inOrder.verify(mMockNetd, never()).setNetworkAllowlist(any());
17363         }
17364 
17365         // Verify issuing with cellular set only when enterprise network disconnects.
17366         enterpriseAgent.disconnect();
17367         waitForIdle();
17368         if (mDeps.isAtLeastU()) {
17369             inOrder.verify(mMockNetd).setNetworkAllowlist(
17370                     new NativeUidRangeConfig[]{cellExcludeAppConfig});
17371         } else {
17372             inOrder.verify(mMockNetd, never()).setNetworkAllowlist(any());
17373         }
17374 
17375         mCellAgent.disconnect();
17376         waitForIdle();
17377         if (mDeps.isAtLeastU()) {
17378             inOrder.verify(mMockNetd).setNetworkAllowlist(new NativeUidRangeConfig[]{});
17379         } else {
17380             inOrder.verify(mMockNetd, never()).setNetworkAllowlist(any());
17381         }
17382     }
17383 
17384     /**
17385      * Make sure wrong preferences for per-profile default networking are rejected.
17386      */
17387     @Test
17388     public void testProfileNetworkPrefWrongPreference() throws Exception {
17389         final UserHandle testHandle = UserHandle.of(TEST_WORK_PROFILE_USER_ID);
17390         mServiceContext.setWorkProfile(testHandle, true);
17391         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder =
17392                 new ProfileNetworkPreference.Builder();
17393         profileNetworkPreferenceBuilder.setPreference(
17394                 PROFILE_NETWORK_PREFERENCE_ENTERPRISE_BLOCKING + 1);
17395         profileNetworkPreferenceBuilder.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1);
17396         assertThrows("Should not be able to set an illegal preference",
17397                 IllegalArgumentException.class,
17398                 () -> mCm.setProfileNetworkPreferences(testHandle,
17399                         List.of(profileNetworkPreferenceBuilder.build()),
17400                         null, null));
17401     }
17402 
17403     /**
17404      * Make sure requests for per-profile default networking for a non-work profile are
17405      * rejected
17406      */
17407     @Test
17408     public void testProfileNetworkPrefWrongProfile() throws Exception {
17409         final UserHandle testHandle = UserHandle.of(TEST_WORK_PROFILE_USER_ID);
17410         mServiceContext.setWorkProfile(testHandle, false);
17411         mServiceContext.setDeviceOwner(testHandle, null);
17412         assertThrows("Should not be able to set a user pref for a non-work profile "
17413                 + "and non device owner",
17414                 IllegalArgumentException.class , () ->
17415                         mCm.setProfileNetworkPreference(testHandle,
17416                                 PROFILE_NETWORK_PREFERENCE_ENTERPRISE, null, null));
17417     }
17418 
17419     /**
17420      * Make sure requests for per-profile default networking for a device owner is
17421      * accepted on T and not accepted on S
17422      */
17423     @Test
17424     public void testProfileNetworkDeviceOwner() throws Exception {
17425         final UserHandle testHandle = UserHandle.of(TEST_WORK_PROFILE_USER_ID);
17426         mServiceContext.setWorkProfile(testHandle, false);
17427         mServiceContext.setDeviceOwner(testHandle, "deviceOwnerPackage");
17428         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder =
17429                 new ProfileNetworkPreference.Builder();
17430         profileNetworkPreferenceBuilder.setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE);
17431         profileNetworkPreferenceBuilder.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1);
17432         final TestOnCompleteListener listener = new TestOnCompleteListener();
17433         if (mDeps.isAtLeastT()) {
17434             mCm.setProfileNetworkPreferences(testHandle,
17435                     List.of(profileNetworkPreferenceBuilder.build()),
17436                     r -> r.run(), listener);
17437         } else {
17438             // S should not allow setting preference on device owner
17439             assertThrows("Should not be able to set a user pref for a non-work profile on S",
17440                     IllegalArgumentException.class , () ->
17441                             mCm.setProfileNetworkPreferences(testHandle,
17442                                     List.of(profileNetworkPreferenceBuilder.build()),
17443                                     r -> r.run(), listener));
17444         }
17445     }
17446 
17447     @Test
17448     public void testSubIdsExist() throws Exception {
17449         final Set<Integer> subIds = Collections.singleton(Process.myUid());
17450         final NetworkCapabilities nc = new NetworkCapabilities();
17451         nc.setSubscriptionIds(subIds);
17452 
17453         final NetworkCapabilities result =
17454                 mService.networkCapabilitiesRestrictedForCallerPermissions(
17455                         nc, Process.myPid(), Process.myUid());
17456         assertEquals(subIds, result.getSubscriptionIds());
17457     }
17458 
17459     private NetworkRequest getRequestWithSubIds() {
17460         return new NetworkRequest.Builder()
17461                 .setSubscriptionIds(Collections.singleton(Process.myUid()))
17462                 .build();
17463     }
17464 
17465     private NetworkRequest getRestrictedRequestForWifiWithSubIds() {
17466         return new NetworkRequest.Builder()
17467             .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
17468             .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
17469             .setSubscriptionIds(Collections.singleton(TEST_SUBSCRIPTION_ID))
17470             .build();
17471     }
17472 
17473     @Test
17474     public void testNetworkRequestWithSubIds() throws Exception {
17475         final PendingIntent pendingIntent = PendingIntent.getBroadcast(
17476                 mContext, 0 /* requestCode */, new Intent("a"), FLAG_IMMUTABLE);
17477         final NetworkCallback networkCallback1 = new NetworkCallback();
17478         final NetworkCallback networkCallback2 = new NetworkCallback();
17479 
17480         mCm.requestNetwork(getRequestWithSubIds(), networkCallback1);
17481         mCm.requestNetwork(getRequestWithSubIds(), pendingIntent);
17482         mCm.registerNetworkCallback(getRequestWithSubIds(), networkCallback2);
17483 
17484         mCm.unregisterNetworkCallback(networkCallback1);
17485         mCm.releaseNetworkRequest(pendingIntent);
17486         mCm.unregisterNetworkCallback(networkCallback2);
17487     }
17488 
17489     @Test
17490     @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
17491     public void testCarrierConfigAppSendNetworkRequestForRestrictedWifi() throws Exception {
17492         mServiceContext.setPermission(CONNECTIVITY_USE_RESTRICTED_NETWORKS, PERMISSION_DENIED);
17493         doReturn(true).when(mCarrierPrivilegeAuthenticator)
17494                 .isCarrierServiceUidForNetworkCapabilities(anyInt(), any());
17495         final PendingIntent pendingIntent = PendingIntent.getBroadcast(
17496                 mContext, 0 /* requestCode */, new Intent("a"), FLAG_IMMUTABLE);
17497         final NetworkCallback networkCallback1 = new NetworkCallback();
17498         final NetworkCallback networkCallback2 = new NetworkCallback();
17499 
17500         mCm.requestNetwork(
17501                 getRestrictedRequestForWifiWithSubIds(), networkCallback1);
17502         mCm.requestNetwork(
17503                 getRestrictedRequestForWifiWithSubIds(), pendingIntent);
17504         mCm.registerNetworkCallback(
17505                 getRestrictedRequestForWifiWithSubIds(), networkCallback2);
17506 
17507         mCm.unregisterNetworkCallback(networkCallback1);
17508         mCm.releaseNetworkRequest(pendingIntent);
17509         mCm.unregisterNetworkCallback(networkCallback2);
17510     }
17511 
17512     private void doTestNetworkRequestWithCarrierPrivilegesLost(
17513             boolean shouldGrantRestrictedNetworkPermission,
17514             int lostPrivilegeUid,
17515             int lostPrivilegeSubId,
17516             boolean expectUnavailable,
17517             boolean expectCapChanged) throws Exception {
17518         if (shouldGrantRestrictedNetworkPermission) {
17519             mServiceContext.setPermission(CONNECTIVITY_USE_RESTRICTED_NETWORKS, PERMISSION_GRANTED);
17520         } else {
17521             mServiceContext.setPermission(CONNECTIVITY_USE_RESTRICTED_NETWORKS, PERMISSION_DENIED);
17522         }
17523 
17524         NetworkCapabilities filter =
17525                 getRestrictedRequestForWifiWithSubIds().networkCapabilities;
17526         final HandlerThread handlerThread = new HandlerThread("testRestrictedFactoryRequests");
17527         handlerThread.start();
17528 
17529         final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
17530                 mServiceContext, "testFactory", filter, mCsHandlerThread);
17531         testFactory.register();
17532         testFactory.assertRequestCountEquals(0);
17533 
17534         doReturn(true).when(mCarrierPrivilegeAuthenticator)
17535                 .isCarrierServiceUidForNetworkCapabilities(eq(Process.myUid()), any());
17536         final TestNetworkCallback networkCallback = new TestNetworkCallback();
17537         final NetworkRequest networkrequest =
17538                 getRestrictedRequestForWifiWithSubIds();
17539         mCm.requestNetwork(networkrequest, networkCallback);
17540         testFactory.expectRequestAdd();
17541         testFactory.assertRequestCountEquals(1);
17542 
17543         NetworkCapabilities nc = new NetworkCapabilities.Builder(filter)
17544                 .setAllowedUids(Set.of(Process.myUid()))
17545                 .build();
17546         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, new LinkProperties(), nc);
17547         mWiFiAgent.connect(false);
17548         networkCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
17549         final NetworkAgentInfo nai = mService.getNetworkAgentInfoForNetwork(
17550                 mWiFiAgent.getNetwork());
17551 
17552         doReturn(false).when(mCarrierPrivilegeAuthenticator)
17553                 .isCarrierServiceUidForNetworkCapabilities(eq(Process.myUid()), any());
17554         doReturn(TEST_SUBSCRIPTION_ID).when(mCarrierPrivilegeAuthenticator)
17555                 .getSubIdFromNetworkCapabilities(any());
17556 
17557         visibleOnHandlerThread(mCsHandlerThread.getThreadHandler(), () -> {
17558             mDeps.mCarrierPrivilegesLostListener.accept(lostPrivilegeUid, lostPrivilegeSubId);
17559         });
17560         waitForIdle();
17561 
17562         if (expectCapChanged) {
17563             networkCallback.expect(NETWORK_CAPS_UPDATED);
17564         }
17565         if (expectUnavailable) {
17566             networkCallback.expect(UNAVAILABLE);
17567         }
17568         if (!expectCapChanged && !expectUnavailable) {
17569             networkCallback.assertNoCallback();
17570         }
17571 
17572         mWiFiAgent.disconnect();
17573 
17574         if (expectUnavailable) {
17575             testFactory.expectRequestRemove();
17576             testFactory.assertRequestCountEquals(0);
17577         } else {
17578             testFactory.expectRequestAdd();
17579             testFactory.assertRequestCountEquals(1);
17580         }
17581 
17582         handlerThread.quitSafely();
17583         handlerThread.join();
17584     }
17585 
17586     @Test
17587     @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
17588     public void testRestrictedRequestRemovedDueToCarrierPrivilegesLost() throws Exception {
17589         doTestNetworkRequestWithCarrierPrivilegesLost(
17590                 false /* shouldGrantRestrictedNetworkPermission */,
17591                 Process.myUid(),
17592                 TEST_SUBSCRIPTION_ID,
17593                 true /* expectUnavailable */,
17594                 true /* expectCapChanged */);
17595     }
17596 
17597     @Test
17598     @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
17599     public void testRequestNotRemoved_MismatchSubId() throws Exception {
17600         doTestNetworkRequestWithCarrierPrivilegesLost(
17601                 false /* shouldGrantRestrictedNetworkPermission */,
17602                 Process.myUid(),
17603                 TEST_SUBSCRIPTION_ID + 1,
17604                 false /* expectUnavailable */,
17605                 false /* expectCapChanged */);
17606     }
17607     @Test
17608     @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
17609     public void testRequestNotRemoved_MismatchUid() throws Exception {
17610         doTestNetworkRequestWithCarrierPrivilegesLost(
17611                 false /* shouldGrantRestrictedNetworkPermission */,
17612                 Process.myUid() + 1,
17613                 TEST_SUBSCRIPTION_ID,
17614                 false /* expectUnavailable */,
17615                 false /* expectCapChanged */);
17616     }
17617 
17618     @Test
17619     @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
17620     public void testRequestNotRemoved_HasRestrictedNetworkPermission() throws Exception {
17621         doTestNetworkRequestWithCarrierPrivilegesLost(
17622                 true /* shouldGrantRestrictedNetworkPermission */,
17623                 Process.myUid(),
17624                 TEST_SUBSCRIPTION_ID,
17625                 false /* expectUnavailable */,
17626                 true /* expectCapChanged */);
17627     }
17628 
17629     @Test
17630     public void testAllowedUidsExistWithoutNetworkFactoryPermission() throws Exception {
17631         // Make sure NETWORK_FACTORY permission is not granted.
17632         mServiceContext.setPermission(NETWORK_FACTORY, PERMISSION_DENIED);
17633         mServiceContext.setPermission(MANAGE_TEST_NETWORKS, PERMISSION_GRANTED);
17634         final TestNetworkCallback cb = new TestNetworkCallback();
17635         mCm.requestNetwork(new NetworkRequest.Builder()
17636                         .clearCapabilities()
17637                         .addTransportType(TRANSPORT_TEST)
17638                         .addTransportType(TRANSPORT_CELLULAR)
17639                         .build(),
17640                 cb);
17641 
17642         final ArraySet<Integer> uids = new ArraySet<>();
17643         uids.add(200);
17644         final NetworkCapabilities nc = new NetworkCapabilities.Builder()
17645                 .addTransportType(TRANSPORT_TEST)
17646                 .removeCapability(NET_CAPABILITY_NOT_RESTRICTED)
17647                 .setAllowedUids(uids)
17648                 .setOwnerUid(Process.myUid())
17649                 .setAdministratorUids(new int[] {Process.myUid()})
17650                 .build();
17651         final TestNetworkAgentWrapper agent = new TestNetworkAgentWrapper(TRANSPORT_TEST,
17652                 new LinkProperties(), nc);
17653         agent.connect(true);
17654         cb.expectAvailableThenValidatedCallbacks(agent);
17655 
17656         uids.add(300);
17657         uids.add(400);
17658         nc.setAllowedUids(uids);
17659         agent.setNetworkCapabilities(nc, true /* sendToConnectivityService */);
17660         if (mDeps.isAtLeastT()) {
17661             // AllowedUids is not cleared even without the NETWORK_FACTORY permission
17662             // because the caller is the owner of the network.
17663             cb.expectCaps(agent, c -> c.getAllowedUids().equals(uids));
17664         } else {
17665             cb.assertNoCallback();
17666         }
17667     }
17668 
17669     @Test
17670     public void testAllowedUids() throws Exception {
17671         final int preferenceOrder =
17672                 ConnectivityService.PREFERENCE_ORDER_IRRELEVANT_BECAUSE_NOT_DEFAULT;
17673         mServiceContext.setPermission(NETWORK_FACTORY, PERMISSION_GRANTED);
17674         mServiceContext.setPermission(MANAGE_TEST_NETWORKS, PERMISSION_GRANTED);
17675         final TestNetworkCallback cb = new TestNetworkCallback();
17676         mCm.requestNetwork(new NetworkRequest.Builder()
17677                         .clearCapabilities()
17678                         .addTransportType(TRANSPORT_TEST)
17679                         .addTransportType(TRANSPORT_CELLULAR)
17680                         .build(),
17681                 cb);
17682 
17683         final ArraySet<Integer> uids = new ArraySet<>();
17684         uids.add(200);
17685         final NetworkCapabilities nc = new NetworkCapabilities.Builder()
17686                 .addTransportType(TRANSPORT_TEST)
17687                 .removeCapability(NET_CAPABILITY_NOT_RESTRICTED)
17688                 .setAllowedUids(uids)
17689                 .build();
17690         final TestNetworkAgentWrapper agent = new TestNetworkAgentWrapper(TRANSPORT_TEST,
17691                 new LinkProperties(), nc);
17692         agent.connect(true);
17693         cb.expectAvailableThenValidatedCallbacks(agent);
17694 
17695         final InOrder inOrder = inOrder(mMockNetd);
17696         final NativeUidRangeConfig uids200Parcel = new NativeUidRangeConfig(
17697                 agent.getNetwork().getNetId(),
17698                 intToUidRangeStableParcels(uids),
17699                 preferenceOrder);
17700         if (mDeps.isAtLeastT()) {
17701             inOrder.verify(mMockNetd, times(1)).networkAddUidRangesParcel(uids200Parcel);
17702         }
17703 
17704         uids.add(300);
17705         uids.add(400);
17706         nc.setAllowedUids(uids);
17707         agent.setNetworkCapabilities(nc, true /* sendToConnectivityService */);
17708         if (mDeps.isAtLeastT()) {
17709             cb.expectCaps(agent, c -> c.getAllowedUids().equals(uids));
17710         } else {
17711             cb.assertNoCallback();
17712         }
17713 
17714         uids.remove(200);
17715         final NativeUidRangeConfig uids300400Parcel = new NativeUidRangeConfig(
17716                 agent.getNetwork().getNetId(),
17717                 intToUidRangeStableParcels(uids),
17718                 preferenceOrder);
17719         if (mDeps.isAtLeastT()) {
17720             inOrder.verify(mMockNetd, times(1)).networkAddUidRangesParcel(uids300400Parcel);
17721         }
17722 
17723         nc.setAllowedUids(uids);
17724         agent.setNetworkCapabilities(nc, true /* sendToConnectivityService */);
17725         if (mDeps.isAtLeastT()) {
17726             cb.expectCaps(agent, c -> c.getAllowedUids().equals(uids));
17727             inOrder.verify(mMockNetd, times(1)).networkRemoveUidRangesParcel(uids200Parcel);
17728         } else {
17729             cb.assertNoCallback();
17730         }
17731 
17732         uids.clear();
17733         uids.add(600);
17734         nc.setAllowedUids(uids);
17735         agent.setNetworkCapabilities(nc, true /* sendToConnectivityService */);
17736         if (mDeps.isAtLeastT()) {
17737             cb.expectCaps(agent, c -> c.getAllowedUids().equals(uids));
17738         } else {
17739             cb.assertNoCallback();
17740         }
17741         final NativeUidRangeConfig uids600Parcel = new NativeUidRangeConfig(
17742                 agent.getNetwork().getNetId(),
17743                 intToUidRangeStableParcels(uids),
17744                 preferenceOrder);
17745         if (mDeps.isAtLeastT()) {
17746             inOrder.verify(mMockNetd, times(1)).networkAddUidRangesParcel(uids600Parcel);
17747             inOrder.verify(mMockNetd, times(1)).networkRemoveUidRangesParcel(uids300400Parcel);
17748         }
17749 
17750         uids.clear();
17751         nc.setAllowedUids(uids);
17752         agent.setNetworkCapabilities(nc, true /* sendToConnectivityService */);
17753         if (mDeps.isAtLeastT()) {
17754             cb.expectCaps(agent, c -> c.getAllowedUids().isEmpty());
17755             inOrder.verify(mMockNetd, times(1)).networkRemoveUidRangesParcel(uids600Parcel);
17756         } else {
17757             cb.assertNoCallback();
17758             verify(mMockNetd, never()).networkAddUidRangesParcel(any());
17759             verify(mMockNetd, never()).networkRemoveUidRangesParcel(any());
17760         }
17761 
17762     }
17763 
17764     @Test
17765     public void testAutomotiveEthernetAllowedUids() throws Exception {
17766         mServiceContext.setPermission(NETWORK_FACTORY, PERMISSION_GRANTED);
17767         mServiceContext.setPermission(MANAGE_TEST_NETWORKS, PERMISSION_GRANTED);
17768 
17769         // Has automotive feature.
17770         validateAutomotiveEthernetAllowedUids(true);
17771 
17772         // No automotive feature.
17773         validateAutomotiveEthernetAllowedUids(false);
17774     }
17775 
17776     private void validateAutomotiveEthernetAllowedUids(final boolean hasAutomotiveFeature)
17777             throws Exception {
17778         mockHasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, hasAutomotiveFeature);
17779 
17780         // Simulate a restricted ethernet network.
17781         final NetworkCapabilities.Builder ncb = new NetworkCapabilities.Builder()
17782                 .addTransportType(TRANSPORT_ETHERNET)
17783                 .addCapability(NET_CAPABILITY_INTERNET)
17784                 .addCapability(NET_CAPABILITY_NOT_SUSPENDED)
17785                 .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
17786                 .removeCapability(NET_CAPABILITY_NOT_RESTRICTED);
17787 
17788         mEthernetAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET,
17789                 new LinkProperties(), ncb.build());
17790 
17791         final ArraySet<Integer> serviceUidSet = new ArraySet<>();
17792         serviceUidSet.add(TEST_PACKAGE_UID);
17793 
17794         final TestNetworkCallback cb = new TestNetworkCallback();
17795 
17796         mCm.requestNetwork(new NetworkRequest.Builder()
17797                 .addTransportType(TRANSPORT_ETHERNET)
17798                 .removeCapability(NET_CAPABILITY_NOT_RESTRICTED)
17799                 .build(), cb);
17800         mEthernetAgent.connect(true);
17801         cb.expectAvailableThenValidatedCallbacks(mEthernetAgent);
17802 
17803         // Cell gets to set the service UID as access UID
17804         ncb.setAllowedUids(serviceUidSet);
17805         mEthernetAgent.setNetworkCapabilities(ncb.build(), true /* sendToCS */);
17806         if (mDeps.isAtLeastT() && hasAutomotiveFeature) {
17807             cb.expectCaps(mEthernetAgent, c -> c.getAllowedUids().equals(serviceUidSet));
17808         } else {
17809             // S and no automotive feature must ignore access UIDs.
17810             cb.assertNoCallback(TEST_CALLBACK_TIMEOUT_MS);
17811         }
17812 
17813         mEthernetAgent.disconnect();
17814         cb.expect(LOST, mEthernetAgent);
17815         mCm.unregisterNetworkCallback(cb);
17816     }
17817 
17818     @Test
17819     public void testCbsAllowedUids() throws Exception {
17820         mServiceContext.setPermission(NETWORK_FACTORY, PERMISSION_GRANTED);
17821         mServiceContext.setPermission(MANAGE_TEST_NETWORKS, PERMISSION_GRANTED);
17822 
17823         // In this test TEST_PACKAGE_UID will be the UID of the carrier service UID.
17824         doReturn(true).when(mCarrierPrivilegeAuthenticator)
17825                 .isCarrierServiceUidForNetworkCapabilities(eq(TEST_PACKAGE_UID), any());
17826 
17827         // Simulate a restricted telephony network. The telephony factory is entitled to set
17828         // the access UID to the service package on any of its restricted networks.
17829         final NetworkCapabilities.Builder ncb = new NetworkCapabilities.Builder()
17830                 .addTransportType(TRANSPORT_CELLULAR)
17831                 .addCapability(NET_CAPABILITY_INTERNET)
17832                 .addCapability(NET_CAPABILITY_NOT_SUSPENDED)
17833                 .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
17834                 .removeCapability(NET_CAPABILITY_NOT_RESTRICTED)
17835                 .setNetworkSpecifier(new TelephonyNetworkSpecifier(1 /* subid */));
17836 
17837         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR,
17838                 new LinkProperties(), ncb.build());
17839 
17840         final ArraySet<Integer> serviceUidSet = new ArraySet<>();
17841         serviceUidSet.add(TEST_PACKAGE_UID);
17842         final ArraySet<Integer> nonServiceUidSet = new ArraySet<>();
17843         nonServiceUidSet.add(TEST_PACKAGE_UID2);
17844         final ArraySet<Integer> serviceUidSetPlus = new ArraySet<>();
17845         serviceUidSetPlus.add(TEST_PACKAGE_UID);
17846         serviceUidSetPlus.add(TEST_PACKAGE_UID2);
17847 
17848         final TestNetworkCallback cb = new TestNetworkCallback();
17849 
17850         // Cell gets to set the service UID as access UID
17851         mCm.requestNetwork(new NetworkRequest.Builder()
17852                 .addTransportType(TRANSPORT_CELLULAR)
17853                 .removeCapability(NET_CAPABILITY_NOT_RESTRICTED)
17854                 .build(), cb);
17855         mCellAgent.connect(true);
17856         cb.expectAvailableThenValidatedCallbacks(mCellAgent);
17857         ncb.setAllowedUids(serviceUidSet);
17858         mCellAgent.setNetworkCapabilities(ncb.build(), true /* sendToCS */);
17859         if (mDeps.isAtLeastT()) {
17860             cb.expectCaps(mCellAgent, c -> c.getAllowedUids().equals(serviceUidSet));
17861         } else {
17862             // S must ignore access UIDs.
17863             cb.assertNoCallback(TEST_CALLBACK_TIMEOUT_MS);
17864         }
17865 
17866         // ...but not to some other UID. Rejection sets UIDs to the empty set
17867         ncb.setAllowedUids(nonServiceUidSet);
17868         mCellAgent.setNetworkCapabilities(ncb.build(), true /* sendToCS */);
17869         if (mDeps.isAtLeastT()) {
17870             cb.expectCaps(mCellAgent, c -> c.getAllowedUids().isEmpty());
17871         } else {
17872             // S must ignore access UIDs.
17873             cb.assertNoCallback(TEST_CALLBACK_TIMEOUT_MS);
17874         }
17875 
17876         // ...and also not to multiple UIDs even including the service UID
17877         ncb.setAllowedUids(serviceUidSetPlus);
17878         mCellAgent.setNetworkCapabilities(ncb.build(), true /* sendToCS */);
17879         cb.assertNoCallback(TEST_CALLBACK_TIMEOUT_MS);
17880 
17881         mCellAgent.disconnect();
17882         cb.expect(LOST, mCellAgent);
17883         mCm.unregisterNetworkCallback(cb);
17884 
17885         // Must be unset before touching the transports, because remove and add transport types
17886         // check the specifier on the builder immediately, contradicting normal builder semantics
17887         // TODO : fix the builder
17888         ncb.setNetworkSpecifier(null);
17889         ncb.removeTransportType(TRANSPORT_CELLULAR);
17890         ncb.addTransportType(TRANSPORT_BLUETOOTH);
17891         // Wifi does not get to set access UID, even to the correct UID
17892         mCm.requestNetwork(new NetworkRequest.Builder()
17893                 .addTransportType(TRANSPORT_BLUETOOTH)
17894                 .removeCapability(NET_CAPABILITY_NOT_RESTRICTED)
17895                 .build(), cb);
17896         final TestNetworkAgentWrapper bluetoothAgent = new TestNetworkAgentWrapper(
17897                 TRANSPORT_BLUETOOTH, new LinkProperties(), ncb.build());
17898         bluetoothAgent.connect(true);
17899         cb.expectAvailableThenValidatedCallbacks(bluetoothAgent);
17900         ncb.setAllowedUids(serviceUidSet);
17901         bluetoothAgent.setNetworkCapabilities(ncb.build(), true /* sendToCS */);
17902         cb.assertNoCallback(TEST_CALLBACK_TIMEOUT_MS);
17903         mCm.unregisterNetworkCallback(cb);
17904     }
17905 
17906     @Test
17907     public void testSanitizedCapabilitiesFromAgentDoesNotMutateArgument()
17908             throws Exception {
17909         // This NetworkCapabilities builds an usual object to maximize the chance that this requires
17910         // sanitization, so we have a high chance to detect any changes to the original.
17911         final NetworkCapabilities unsanitized = new NetworkCapabilities.Builder()
17912                 .withoutDefaultCapabilities()
17913                 .addTransportType(TRANSPORT_WIFI)
17914                 .addCapability(NET_CAPABILITY_INTERNET)
17915                 .setOwnerUid(12345)
17916                 .setAdministratorUids(new int[] {12345, 23456, 34567})
17917                 .setLinkUpstreamBandwidthKbps(20)
17918                 .setLinkDownstreamBandwidthKbps(10)
17919                 .setNetworkSpecifier(new EthernetNetworkSpecifier("foobar"))
17920                 .setTransportInfo(new WifiInfo.Builder().setBssid("AA:AA:AA:AA:AA:AA").build())
17921                 .setSignalStrength(-75)
17922                 .setSsid("SSID1")
17923                 .setRequestorUid(98765)
17924                 .setRequestorPackageName("TestPackage")
17925                 .setSubscriptionIds(Collections.singleton(Process.myUid()))
17926                 .setUids(UidRange.toIntRanges(uidRangesForUids(
17927                         UserHandle.getUid(PRIMARY_USER, 10100),
17928                         UserHandle.getUid(SECONDARY_USER, 10101),
17929                         UserHandle.getUid(TERTIARY_USER, 10043))))
17930                 .setAllowedUids(Set.of(45678, 56789, 65432))
17931                 .setUnderlyingNetworks(List.of(new Network(99999)))
17932                 .build();
17933         final NetworkCapabilities copyOfUnsanitized = new NetworkCapabilities(unsanitized);
17934         final NetworkInfo info = new NetworkInfo(TYPE_MOBILE, TelephonyManager.NETWORK_TYPE_LTE,
17935                 ConnectivityManager.getNetworkTypeName(TYPE_MOBILE),
17936                 TelephonyManager.getNetworkTypeName(TelephonyManager.NETWORK_TYPE_LTE));
17937         final NetworkAgentInfo agent = fakeNai(unsanitized, info);
17938         agent.setDeclaredCapabilities(unsanitized);
17939         final NetworkCapabilities sanitized = agent.getDeclaredCapabilitiesSanitized(
17940                 null /* carrierPrivilegeAuthenticator */);
17941         assertEquals(copyOfUnsanitized, unsanitized);
17942         assertNotEquals(sanitized, unsanitized);
17943     }
17944 
17945     /**
17946      * Validate request counts are counted accurately on setProfileNetworkPreference on set/replace.
17947      */
17948     @Test
17949     public void testProfileNetworkPrefCountsRequestsCorrectlyOnSet() throws Exception {
17950         final UserHandle testHandle = setupEnterpriseNetwork();
17951         final TestOnCompleteListener listener = new TestOnCompleteListener();
17952         // Leave one request available so the profile preference can be set.
17953         withRequestCountersAcquired(1 /* countToLeaveAvailable */, () -> {
17954             withPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
17955                     Process.myPid(), Process.myUid(), () -> {
17956                         // Set initially to test the limit prior to having existing requests.
17957                         mCm.setProfileNetworkPreference(testHandle,
17958                                 PROFILE_NETWORK_PREFERENCE_ENTERPRISE,
17959                                 Runnable::run, listener);
17960                     });
17961             listener.expectOnComplete();
17962 
17963             // Simulate filing requests as some app on the work profile
17964             final int otherAppUid = UserHandle.getUid(TEST_WORK_PROFILE_USER_ID,
17965                     UserHandle.getAppId(Process.myUid() + 1));
17966             final int remainingCount = ConnectivityService.MAX_NETWORK_REQUESTS_PER_UID
17967                     - mService.mNetworkRequestCounter.get(otherAppUid)
17968                     - 1;
17969             final NetworkCallback[] callbacks = new NetworkCallback[remainingCount];
17970             doAsUid(otherAppUid, () -> {
17971                 for (int i = 0; i < remainingCount; ++i) {
17972                     callbacks[i] = new TestNetworkCallback();
17973                     mCm.registerDefaultNetworkCallback(callbacks[i]);
17974                 }
17975             });
17976 
17977             withPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
17978                     Process.myPid(), Process.myUid(), () -> {
17979                         // re-set so as to test the limit as part of replacing existing requests.
17980                         mCm.setProfileNetworkPreference(testHandle,
17981                                 PROFILE_NETWORK_PREFERENCE_ENTERPRISE, Runnable::run, listener);
17982                     });
17983             listener.expectOnComplete();
17984 
17985             doAsUid(otherAppUid, () -> {
17986                 for (final NetworkCallback callback : callbacks) {
17987                     mCm.unregisterNetworkCallback(callback);
17988                 }
17989             });
17990         });
17991     }
17992 
17993     /**
17994      * Validate request counts are counted accurately on setOemNetworkPreference on set/replace.
17995      */
17996     @Test
17997     public void testSetOemNetworkPreferenceCountsRequestsCorrectlyOnSet() throws Exception {
17998         mockHasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, true);
17999         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
18000                 OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY;
18001         // Leave one request available so the OEM preference can be set.
18002         withRequestCountersAcquired(1 /* countToLeaveAvailable */, () ->
18003                 withPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, () -> {
18004                     // Set initially to test the limit prior to having existing requests.
18005                     final TestOemListenerCallback listener = new TestOemListenerCallback();
18006                     mService.setOemNetworkPreference(
18007                             createDefaultOemNetworkPreferences(networkPref), listener);
18008                     listener.expectOnComplete();
18009 
18010                     // re-set so as to test the limit as part of replacing existing requests.
18011                     mService.setOemNetworkPreference(
18012                             createDefaultOemNetworkPreferences(networkPref), listener);
18013                     listener.expectOnComplete();
18014                 }));
18015     }
18016 
18017     private void withRequestCountersAcquired(final int countToLeaveAvailable,
18018             @NonNull final ThrowingRunnable r) throws Exception {
18019         final ArraySet<TestNetworkCallback> callbacks = new ArraySet<>();
18020         try {
18021             final int requestCount = mService.mSystemNetworkRequestCounter.get(Process.myUid());
18022             // The limit is hit when total requests = limit - 1, and exceeded with a crash when
18023             // total requests >= limit.
18024             final int countToFile =
18025                     MAX_NETWORK_REQUESTS_PER_SYSTEM_UID - requestCount - countToLeaveAvailable;
18026             // Need permission so registerDefaultNetworkCallback uses mSystemNetworkRequestCounter
18027             withPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, () -> {
18028                 for (int i = 1; i < countToFile; i++) {
18029                     final TestNetworkCallback cb = new TestNetworkCallback();
18030                     mCm.registerDefaultNetworkCallback(cb);
18031                     callbacks.add(cb);
18032                 }
18033                 assertEquals(MAX_NETWORK_REQUESTS_PER_SYSTEM_UID - 1 - countToLeaveAvailable,
18034                         mService.mSystemNetworkRequestCounter.get(Process.myUid()));
18035             });
18036             // Code to run to check if it triggers a max request count limit error.
18037             r.run();
18038         } finally {
18039             for (final TestNetworkCallback cb : callbacks) {
18040                 mCm.unregisterNetworkCallback(cb);
18041             }
18042         }
18043     }
18044 
18045     private void assertCreateNrisFromMobileDataPreferredUids(Set<Integer> uids) {
18046         final Set<NetworkRequestInfo> nris =
18047                 mService.createNrisFromMobileDataPreferredUids(uids);
18048         final NetworkRequestInfo nri = nris.iterator().next();
18049         // Verify that one NRI is created with multilayer requests. Because one NRI can contain
18050         // multiple uid ranges, so it only need create one NRI here.
18051         assertEquals(1, nris.size());
18052         assertTrue(nri.isMultilayerRequest());
18053         assertEquals(nri.getUids(), uidRangesForUids(uids));
18054         assertEquals(PREFERENCE_ORDER_MOBILE_DATA_PREFERERRED, nri.mPreferenceOrder);
18055     }
18056 
18057     /**
18058      * Test createNrisFromMobileDataPreferredUids returns correct NetworkRequestInfo.
18059      */
18060     @Test
18061     public void testCreateNrisFromMobileDataPreferredUids() {
18062         // Verify that empty uid set should not create any NRI for it.
18063         final Set<NetworkRequestInfo> nrisNoUid =
18064                 mService.createNrisFromMobileDataPreferredUids(new ArraySet<>());
18065         assertEquals(0, nrisNoUid.size());
18066 
18067         final int uid1 = PRIMARY_USER_HANDLE.getUid(TEST_PACKAGE_UID);
18068         final int uid2 = PRIMARY_USER_HANDLE.getUid(TEST_PACKAGE_UID2);
18069         final int uid3 = SECONDARY_USER_HANDLE.getUid(TEST_PACKAGE_UID);
18070         assertCreateNrisFromMobileDataPreferredUids(Set.of(uid1));
18071         assertCreateNrisFromMobileDataPreferredUids(Set.of(uid1, uid3));
18072         assertCreateNrisFromMobileDataPreferredUids(Set.of(uid1, uid2));
18073     }
18074 
18075     private void setAndUpdateMobileDataPreferredUids(Set<Integer> uids) {
18076         ConnectivitySettingsManager.setMobileDataPreferredUids(mServiceContext, uids);
18077         mService.updateMobileDataPreferredUids();
18078         waitForIdle();
18079     }
18080 
18081     /**
18082      * Test that MOBILE_DATA_PREFERRED_UIDS changes will send correct net id and uid ranges to netd.
18083      */
18084     @Test
18085     public void testMobileDataPreferredUidsChanged() throws Exception {
18086         final InOrder inorder = inOrder(mMockNetd);
18087         registerDefaultNetworkCallbacks();
18088         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
18089         mCellAgent.connect(true);
18090         mDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
18091         mTestPackageDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
18092 
18093         final int cellNetId = mCellAgent.getNetwork().netId;
18094         inorder.verify(mMockNetd, times(1)).networkCreate(nativeNetworkConfigPhysical(
18095                 cellNetId, INetd.PERMISSION_NONE));
18096 
18097         // Initial mobile data preferred uids status.
18098         setAndUpdateMobileDataPreferredUids(Set.of());
18099         inorder.verify(mMockNetd, never()).networkAddUidRangesParcel(any());
18100         inorder.verify(mMockNetd, never()).networkRemoveUidRangesParcel(any());
18101 
18102         // Set MOBILE_DATA_PREFERRED_UIDS setting and verify that net id and uid ranges send to netd
18103         final Set<Integer> uids1 = Set.of(PRIMARY_USER_HANDLE.getUid(TEST_PACKAGE_UID));
18104         final UidRangeParcel[] uidRanges1 = toUidRangeStableParcels(uidRangesForUids(uids1));
18105         final NativeUidRangeConfig config1 = new NativeUidRangeConfig(cellNetId, uidRanges1,
18106                 PREFERENCE_ORDER_MOBILE_DATA_PREFERERRED);
18107         setAndUpdateMobileDataPreferredUids(uids1);
18108         inorder.verify(mMockNetd, times(1)).networkAddUidRangesParcel(config1);
18109         inorder.verify(mMockNetd, never()).networkRemoveUidRangesParcel(any());
18110 
18111         // Set MOBILE_DATA_PREFERRED_UIDS setting again and verify that old rules are removed and
18112         // new rules are added.
18113         final Set<Integer> uids2 = Set.of(PRIMARY_USER_HANDLE.getUid(TEST_PACKAGE_UID),
18114                 PRIMARY_USER_HANDLE.getUid(TEST_PACKAGE_UID2),
18115                 SECONDARY_USER_HANDLE.getUid(TEST_PACKAGE_UID));
18116         final UidRangeParcel[] uidRanges2 = toUidRangeStableParcels(uidRangesForUids(uids2));
18117         final NativeUidRangeConfig config2 = new NativeUidRangeConfig(cellNetId, uidRanges2,
18118                 PREFERENCE_ORDER_MOBILE_DATA_PREFERERRED);
18119         setAndUpdateMobileDataPreferredUids(uids2);
18120         inorder.verify(mMockNetd, times(1)).networkRemoveUidRangesParcel(config1);
18121         inorder.verify(mMockNetd, times(1)).networkAddUidRangesParcel(config2);
18122 
18123         // Clear MOBILE_DATA_PREFERRED_UIDS setting again and verify that old rules are removed and
18124         // new rules are not added.
18125         setAndUpdateMobileDataPreferredUids(Set.of());
18126         inorder.verify(mMockNetd, times(1)).networkRemoveUidRangesParcel(config2);
18127         inorder.verify(mMockNetd, never()).networkAddUidRangesParcel(any());
18128     }
18129 
18130     /**
18131      * Make sure mobile data preferred uids feature behaves as expected when the mobile network
18132      * goes up and down while the uids is set. Make sure they behave as expected whether
18133      * there is a general default network or not.
18134      */
18135     @Test
18136     public void testMobileDataPreferenceForMobileNetworkUpDown() throws Exception {
18137         final InOrder inorder = inOrder(mMockNetd);
18138         // File a request for cell to ensure it doesn't go down.
18139         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
18140         final NetworkRequest cellRequest = new NetworkRequest.Builder()
18141                 .addTransportType(TRANSPORT_CELLULAR).build();
18142         mCm.requestNetwork(cellRequest, cellNetworkCallback);
18143         cellNetworkCallback.assertNoCallback();
18144 
18145         registerDefaultNetworkCallbacks();
18146         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
18147         mWiFiAgent.connect(true);
18148         mDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mWiFiAgent);
18149         mTestPackageDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mWiFiAgent);
18150         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_PACKAGE_UID));
18151 
18152         final int wifiNetId = mWiFiAgent.getNetwork().netId;
18153         inorder.verify(mMockNetd, times(1)).networkCreate(nativeNetworkConfigPhysical(
18154                 wifiNetId, INetd.PERMISSION_NONE));
18155 
18156         // Initial mobile data preferred uids status.
18157         setAndUpdateMobileDataPreferredUids(Set.of());
18158         inorder.verify(mMockNetd, never()).networkAddUidRangesParcel(any());
18159         inorder.verify(mMockNetd, never()).networkRemoveUidRangesParcel(any());
18160 
18161         // Set MOBILE_DATA_PREFERRED_UIDS setting and verify that wifi net id and uid ranges send to
18162         // netd.
18163         final Set<Integer> uids = Set.of(PRIMARY_USER_HANDLE.getUid(TEST_PACKAGE_UID));
18164         final UidRangeParcel[] uidRanges = toUidRangeStableParcels(uidRangesForUids(uids));
18165         final NativeUidRangeConfig wifiConfig = new NativeUidRangeConfig(wifiNetId, uidRanges,
18166                 PREFERENCE_ORDER_MOBILE_DATA_PREFERERRED);
18167         setAndUpdateMobileDataPreferredUids(uids);
18168         inorder.verify(mMockNetd, times(1)).networkAddUidRangesParcel(wifiConfig);
18169         inorder.verify(mMockNetd, never()).networkRemoveUidRangesParcel(any());
18170 
18171         // Cellular network connected. mTestPackageDefaultNetworkCallback should receive
18172         // callback with cellular network and net id and uid ranges should be updated to netd.
18173         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
18174         mCellAgent.connect(true);
18175         cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
18176         mDefaultNetworkCallback.assertNoCallback();
18177         mTestPackageDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
18178         assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_PACKAGE_UID));
18179 
18180         final int cellNetId = mCellAgent.getNetwork().netId;
18181         final NativeUidRangeConfig cellConfig = new NativeUidRangeConfig(cellNetId, uidRanges,
18182                 PREFERENCE_ORDER_MOBILE_DATA_PREFERERRED);
18183         inorder.verify(mMockNetd, times(1)).networkCreate(nativeNetworkConfigPhysical(
18184                 cellNetId, INetd.PERMISSION_NONE));
18185         inorder.verify(mMockNetd, times(1)).networkAddUidRangesParcel(cellConfig);
18186         inorder.verify(mMockNetd, times(1)).networkRemoveUidRangesParcel(wifiConfig);
18187 
18188         // Cellular network disconnected. mTestPackageDefaultNetworkCallback should receive
18189         // callback with wifi network from fallback request.
18190         mCellAgent.disconnect();
18191         mDefaultNetworkCallback.assertNoCallback();
18192         cellNetworkCallback.expect(LOST, mCellAgent);
18193         mTestPackageDefaultNetworkCallback.expect(LOST, mCellAgent);
18194         mTestPackageDefaultNetworkCallback.expectAvailableCallbacksValidated(mWiFiAgent);
18195         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_PACKAGE_UID));
18196         inorder.verify(mMockNetd, times(1)).networkAddUidRangesParcel(wifiConfig);
18197         inorder.verify(mMockNetd, never()).networkRemoveUidRangesParcel(any());
18198         inorder.verify(mMockNetd).networkDestroy(cellNetId);
18199 
18200         // Cellular network comes back. mTestPackageDefaultNetworkCallback should receive
18201         // callback with cellular network.
18202         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
18203         mCellAgent.connect(true);
18204         cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
18205         mDefaultNetworkCallback.assertNoCallback();
18206         mTestPackageDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
18207         assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_PACKAGE_UID));
18208 
18209         final int cellNetId2 = mCellAgent.getNetwork().netId;
18210         final NativeUidRangeConfig cellConfig2 = new NativeUidRangeConfig(cellNetId2, uidRanges,
18211                 PREFERENCE_ORDER_MOBILE_DATA_PREFERERRED);
18212         inorder.verify(mMockNetd, times(1)).networkCreate(nativeNetworkConfigPhysical(
18213                 cellNetId2, INetd.PERMISSION_NONE));
18214         inorder.verify(mMockNetd, times(1)).networkAddUidRangesParcel(cellConfig2);
18215         inorder.verify(mMockNetd, times(1)).networkRemoveUidRangesParcel(wifiConfig);
18216 
18217         // Wifi network disconnected. mTestPackageDefaultNetworkCallback should not receive
18218         // any callback.
18219         mWiFiAgent.disconnect();
18220         mDefaultNetworkCallback.expect(LOST, mWiFiAgent);
18221         mDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellAgent);
18222         mTestPackageDefaultNetworkCallback.assertNoCallback();
18223         assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_PACKAGE_UID));
18224         waitForIdle();
18225         inorder.verify(mMockNetd, never()).networkAddUidRangesParcel(any());
18226         inorder.verify(mMockNetd, never()).networkRemoveUidRangesParcel(any());
18227         inorder.verify(mMockNetd).networkDestroy(wifiNetId);
18228 
18229         mCm.unregisterNetworkCallback(cellNetworkCallback);
18230     }
18231 
18232     @Test
18233     public void testMultilayerRequestsOfSetMobileDataPreferredUids() throws Exception {
18234         // First set mobile data preferred uid to create a multi-layer requests: 1. request for
18235         // cellular, 2. track the default network for fallback.
18236         setAndUpdateMobileDataPreferredUids(
18237                 Set.of(PRIMARY_USER_HANDLE.getUid(TEST_PACKAGE_UID)));
18238 
18239         final HandlerThread handlerThread = new HandlerThread("MockFactory");
18240         handlerThread.start();
18241         final NetworkCapabilities cellFilter = new NetworkCapabilities()
18242                 .addTransportType(TRANSPORT_CELLULAR)
18243                 .addCapability(NET_CAPABILITY_INTERNET)
18244                 .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED);
18245         final MockNetworkFactory cellFactory = new MockNetworkFactory(handlerThread.getLooper(),
18246                 mServiceContext, "cellFactory", cellFilter, mCsHandlerThread);
18247         cellFactory.setScoreFilter(40);
18248 
18249         try {
18250             cellFactory.register();
18251             // Default internet request and the mobile data preferred request.
18252             cellFactory.expectRequestAdds(2);
18253             cellFactory.assertRequestCountEquals(2);
18254 
18255             mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
18256             mWiFiAgent.connect(true);
18257 
18258             // The cellFactory however is outscored, and should lose default internet request.
18259             // But it should still see mobile data preferred request.
18260             cellFactory.expectRequestRemove();
18261             cellFactory.assertRequestCountEquals(1);
18262 
18263             mWiFiAgent.disconnect();
18264             // The network satisfying the default internet request has disconnected, so the
18265             // cellFactory sees the default internet requests again.
18266             cellFactory.expectRequestAdd();
18267             cellFactory.assertRequestCountEquals(2);
18268         } finally {
18269             cellFactory.terminate();
18270             handlerThread.quitSafely();
18271             handlerThread.join();
18272         }
18273     }
18274 
18275     /**
18276      * Validate request counts are counted accurately on MOBILE_DATA_PREFERRED_UIDS change
18277      * on set/replace.
18278      */
18279     @Test
18280     public void testMobileDataPreferredUidsChangedCountsRequestsCorrectlyOnSet() throws Exception {
18281         ConnectivitySettingsManager.setMobileDataPreferredUids(mServiceContext,
18282                 Set.of(PRIMARY_USER_HANDLE.getUid(TEST_PACKAGE_UID)));
18283         // Leave one request available so MDO preference set up above can be set.
18284         withRequestCountersAcquired(1 /* countToLeaveAvailable */, () ->
18285                 withPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
18286                         Process.myPid(), Process.myUid(), () -> {
18287                             // Set initially to test the limit prior to having existing requests.
18288                             mService.updateMobileDataPreferredUids();
18289                             waitForIdle();
18290 
18291                             // re-set so as to test the limit as part of replacing existing requests
18292                             mService.updateMobileDataPreferredUids();
18293                             waitForIdle();
18294                         }));
18295     }
18296 
18297     @Test
18298     public void testAllNetworkPreferencesCanCoexist()
18299             throws Exception {
18300         final InOrder inorder = inOrder(mMockNetd);
18301         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
18302                 OEM_NETWORK_PREFERENCE_OEM_PAID;
18303         final UserHandle testHandle = setupEnterpriseNetwork();
18304 
18305         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true);
18306         final int cellNetId = mCellAgent.getNetwork().netId;
18307         inorder.verify(mMockNetd, times(1)).networkCreate(nativeNetworkConfigPhysical(
18308                 cellNetId, INetd.PERMISSION_NONE));
18309 
18310         // Set oem network preference
18311         final int[] uids1 = new int[] { PRIMARY_USER_HANDLE.getUid(TEST_PACKAGE_UID) };
18312         final UidRangeParcel[] uidRanges1 = toUidRangeStableParcels(uidRangesForUids(uids1));
18313         final NativeUidRangeConfig config1 = new NativeUidRangeConfig(cellNetId, uidRanges1,
18314                 PREFERENCE_ORDER_OEM);
18315         setupSetOemNetworkPreferenceForPreferenceTest(networkPref, uidRanges1, TEST_PACKAGE_NAME);
18316         inorder.verify(mMockNetd, times(1)).networkAddUidRangesParcel(config1);
18317         inorder.verify(mMockNetd, never()).networkRemoveUidRangesParcel(any());
18318 
18319         // Set user profile network preference
18320         final TestNetworkAgentWrapper workAgent = makeEnterpriseNetworkAgent();
18321         workAgent.connect(true);
18322 
18323         final TestOnCompleteListener listener = new TestOnCompleteListener();
18324         mCm.setProfileNetworkPreference(testHandle, PROFILE_NETWORK_PREFERENCE_ENTERPRISE,
18325                 r -> r.run(), listener);
18326         listener.expectOnComplete();
18327         final NativeUidRangeConfig config2 = new NativeUidRangeConfig(workAgent.getNetwork().netId,
18328                 uidRangeFor(testHandle), PREFERENCE_ORDER_PROFILE);
18329         inorder.verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
18330                 workAgent.getNetwork().netId, INetd.PERMISSION_SYSTEM));
18331         inorder.verify(mMockNetd, never()).networkRemoveUidRangesParcel(any());
18332         inorder.verify(mMockNetd).networkAddUidRangesParcel(config2);
18333 
18334         // Set MOBILE_DATA_PREFERRED_UIDS setting
18335         final Set<Integer> uids2 = Set.of(PRIMARY_USER_HANDLE.getUid(TEST_PACKAGE_UID2));
18336         final UidRangeParcel[] uidRanges2 = toUidRangeStableParcels(uidRangesForUids(uids2));
18337         final NativeUidRangeConfig config3 = new NativeUidRangeConfig(cellNetId, uidRanges2,
18338                 PREFERENCE_ORDER_MOBILE_DATA_PREFERERRED);
18339         setAndUpdateMobileDataPreferredUids(uids2);
18340         inorder.verify(mMockNetd, never()).networkRemoveUidRangesParcel(any());
18341         inorder.verify(mMockNetd, times(1)).networkAddUidRangesParcel(config3);
18342 
18343         // Set oem network preference again with different uid.
18344         final Set<Integer> uids3 = Set.of(PRIMARY_USER_HANDLE.getUid(TEST_PACKAGE_UID3));
18345         final UidRangeParcel[] uidRanges3 = toUidRangeStableParcels(uidRangesForUids(uids3));
18346         final NativeUidRangeConfig config4 = new NativeUidRangeConfig(cellNetId, uidRanges3,
18347                 PREFERENCE_ORDER_OEM);
18348         setupSetOemNetworkPreferenceForPreferenceTest(networkPref, uidRanges3, "com.android.test");
18349         inorder.verify(mMockNetd, times(1)).networkRemoveUidRangesParcel(config1);
18350         inorder.verify(mMockNetd, times(1)).networkAddUidRangesParcel(config4);
18351 
18352         // Remove user profile network preference
18353         mCm.setProfileNetworkPreference(testHandle, PROFILE_NETWORK_PREFERENCE_DEFAULT,
18354                 r -> r.run(), listener);
18355         listener.expectOnComplete();
18356         inorder.verify(mMockNetd, times(1)).networkRemoveUidRangesParcel(config2);
18357         inorder.verify(mMockNetd, never()).networkAddUidRangesParcel(any());
18358 
18359         // Set MOBILE_DATA_PREFERRED_UIDS setting again with same uid as oem network preference.
18360         final NativeUidRangeConfig config6 = new NativeUidRangeConfig(cellNetId, uidRanges3,
18361                 PREFERENCE_ORDER_MOBILE_DATA_PREFERERRED);
18362         setAndUpdateMobileDataPreferredUids(uids3);
18363         inorder.verify(mMockNetd, times(1)).networkRemoveUidRangesParcel(config3);
18364         inorder.verify(mMockNetd, times(1)).networkAddUidRangesParcel(config6);
18365     }
18366 
18367     @Test
18368     public void testNetworkCallbackAndActiveNetworkForUid_AllNetworkPreferencesEnabled()
18369             throws Exception {
18370         // File a request for cell to ensure it doesn't go down.
18371         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
18372         final NetworkRequest cellRequest = new NetworkRequest.Builder()
18373                 .addTransportType(TRANSPORT_CELLULAR).build();
18374         mCm.requestNetwork(cellRequest, cellNetworkCallback);
18375         cellNetworkCallback.assertNoCallback();
18376 
18377         // Register callbacks and have wifi network as default network.
18378         registerDefaultNetworkCallbacks();
18379         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
18380         mWiFiAgent.connect(true);
18381         mDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mWiFiAgent);
18382         mProfileDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mWiFiAgent);
18383         mTestPackageDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mWiFiAgent);
18384         assertEquals(mWiFiAgent.getNetwork(),
18385                 mCm.getActiveNetworkForUid(TEST_WORK_PROFILE_APP_UID));
18386         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_PACKAGE_UID));
18387 
18388         // Set MOBILE_DATA_PREFERRED_UIDS setting with TEST_WORK_PROFILE_APP_UID and
18389         // TEST_PACKAGE_UID. Both mProfileDefaultNetworkCallback and
18390         // mTestPackageDefaultNetworkCallback should receive callback with cell network.
18391         setAndUpdateMobileDataPreferredUids(Set.of(TEST_WORK_PROFILE_APP_UID, TEST_PACKAGE_UID));
18392         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
18393         mCellAgent.connect(true);
18394         cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
18395         mDefaultNetworkCallback.assertNoCallback();
18396         mProfileDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
18397         mTestPackageDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
18398         assertEquals(mCellAgent.getNetwork(),
18399                 mCm.getActiveNetworkForUid(TEST_WORK_PROFILE_APP_UID));
18400         assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_PACKAGE_UID));
18401 
18402         // Set user profile network preference with test profile. mProfileDefaultNetworkCallback
18403         // should receive callback with higher priority network preference (enterprise network).
18404         // The others should have no callbacks.
18405         final UserHandle testHandle = setupEnterpriseNetwork();
18406         final TestNetworkAgentWrapper workAgent = makeEnterpriseNetworkAgent();
18407         workAgent.connect(true);
18408         final TestOnCompleteListener listener = new TestOnCompleteListener();
18409         mCm.setProfileNetworkPreference(testHandle, PROFILE_NETWORK_PREFERENCE_ENTERPRISE,
18410                 r -> r.run(), listener);
18411         listener.expectOnComplete();
18412         assertNoCallbacks(mDefaultNetworkCallback, mTestPackageDefaultNetworkCallback);
18413         mProfileDefaultNetworkCallback.expectAvailableCallbacksValidated(workAgent);
18414         assertEquals(workAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_WORK_PROFILE_APP_UID));
18415         assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_PACKAGE_UID));
18416 
18417         // Set oem network preference with TEST_PACKAGE_UID. mTestPackageDefaultNetworkCallback
18418         // should receive callback with higher priority network preference (current default network)
18419         // and the others should have no callbacks.
18420         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
18421                 OEM_NETWORK_PREFERENCE_OEM_PAID;
18422         final int[] uids1 = new int[] { TEST_PACKAGE_UID };
18423         final UidRangeParcel[] uidRanges1 = toUidRangeStableParcels(uidRangesForUids(uids1));
18424         setupSetOemNetworkPreferenceForPreferenceTest(networkPref, uidRanges1, TEST_PACKAGE_NAME);
18425         assertNoCallbacks(mDefaultNetworkCallback, mProfileDefaultNetworkCallback);
18426         mTestPackageDefaultNetworkCallback.expectAvailableCallbacksValidated(mWiFiAgent);
18427         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_PACKAGE_UID));
18428         assertEquals(workAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_WORK_PROFILE_APP_UID));
18429 
18430         // Set oem network preference with TEST_WORK_PROFILE_APP_UID. Both
18431         // mProfileDefaultNetworkCallback and mTestPackageDefaultNetworkCallback should receive
18432         // callback.
18433         final int[] uids2 = new int[] { TEST_WORK_PROFILE_APP_UID };
18434         final UidRangeParcel[] uidRanges2 = toUidRangeStableParcels(uidRangesForUids(uids2));
18435         doReturn(Arrays.asList(testHandle)).when(mUserManager).getUserHandles(anyBoolean());
18436         setupSetOemNetworkPreferenceForPreferenceTest(
18437                 networkPref, uidRanges2, "com.android.test", testHandle);
18438         mDefaultNetworkCallback.assertNoCallback();
18439         mProfileDefaultNetworkCallback.expectAvailableCallbacksValidated(mWiFiAgent);
18440         mTestPackageDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellAgent);
18441         assertEquals(mWiFiAgent.getNetwork(),
18442                 mCm.getActiveNetworkForUid(TEST_WORK_PROFILE_APP_UID));
18443         assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_PACKAGE_UID));
18444 
18445         // Remove oem network preference, mProfileDefaultNetworkCallback should receive callback
18446         // with current highest priority network preference (enterprise network) and the others
18447         // should have no callbacks.
18448         final TestOemListenerCallback oemPrefListener = new TestOemListenerCallback();
18449         mService.setOemNetworkPreference(
18450                 new OemNetworkPreferences.Builder().build(), oemPrefListener);
18451         oemPrefListener.expectOnComplete();
18452         assertNoCallbacks(mDefaultNetworkCallback, mTestPackageDefaultNetworkCallback);
18453         mProfileDefaultNetworkCallback.expectAvailableCallbacksValidated(workAgent);
18454         assertEquals(workAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_WORK_PROFILE_APP_UID));
18455         assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_PACKAGE_UID));
18456 
18457         // Remove user profile network preference.
18458         mCm.setProfileNetworkPreference(testHandle, PROFILE_NETWORK_PREFERENCE_DEFAULT,
18459                 r -> r.run(), listener);
18460         listener.expectOnComplete();
18461         assertNoCallbacks(mDefaultNetworkCallback, mTestPackageDefaultNetworkCallback);
18462         mProfileDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellAgent);
18463         assertEquals(mCellAgent.getNetwork(),
18464                 mCm.getActiveNetworkForUid(TEST_WORK_PROFILE_APP_UID));
18465         assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_PACKAGE_UID));
18466 
18467         // Disconnect wifi
18468         mWiFiAgent.disconnect();
18469         assertNoCallbacks(mProfileDefaultNetworkCallback, mTestPackageDefaultNetworkCallback);
18470         mDefaultNetworkCallback.expect(LOST, mWiFiAgent);
18471         mDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellAgent);
18472     }
18473 
18474     @Test
18475     public void testRequestRouteToHostAddress_PackageDoesNotBelongToCaller() {
18476         assertThrows(SecurityException.class, () -> mService.requestRouteToHostAddress(
18477                 ConnectivityManager.TYPE_NONE, null /* hostAddress */, "com.not.package.owner",
18478                 null /* callingAttributionTag */));
18479     }
18480 
18481     @Test @IgnoreUpTo(SC_V2)
18482     public void testUpdateRateLimit_EnableDisable() throws Exception {
18483         final LinkProperties wifiLp = new LinkProperties();
18484         wifiLp.setInterfaceName(WIFI_IFNAME);
18485         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp);
18486         mWiFiAgent.connect(true);
18487 
18488         final LinkProperties cellLp = new LinkProperties();
18489         cellLp.setInterfaceName(MOBILE_IFNAME);
18490         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
18491         mCellAgent.connect(false);
18492 
18493         waitForIdle();
18494 
18495         final ArrayTrackRecord<Pair<String, Long>>.ReadHead readHeadWifi =
18496                 mDeps.mRateLimitHistory.newReadHead();
18497         final ArrayTrackRecord<Pair<String, Long>>.ReadHead readHeadCell =
18498                 mDeps.mRateLimitHistory.newReadHead();
18499 
18500         // set rate limit to 8MBit/s => 1MB/s
18501         final int rateLimitInBytesPerSec = 1 * 1000 * 1000;
18502         setIngressRateLimit(rateLimitInBytesPerSec);
18503 
18504         assertNotNull(readHeadWifi.poll(TIMEOUT_MS,
18505                 it -> it.first == wifiLp.getInterfaceName()
18506                         && it.second == rateLimitInBytesPerSec));
18507         assertNotNull(readHeadCell.poll(TIMEOUT_MS,
18508                 it -> it.first == cellLp.getInterfaceName()
18509                         && it.second == rateLimitInBytesPerSec));
18510 
18511         // disable rate limiting
18512         setIngressRateLimit(-1);
18513 
18514         assertNotNull(readHeadWifi.poll(TIMEOUT_MS,
18515                 it -> it.first == wifiLp.getInterfaceName() && it.second == -1));
18516         assertNotNull(readHeadCell.poll(TIMEOUT_MS,
18517                 it -> it.first == cellLp.getInterfaceName() && it.second == -1));
18518     }
18519 
18520     @Test @IgnoreUpTo(SC_V2)
18521     public void testUpdateRateLimit_WhenNewNetworkIsAdded() throws Exception {
18522         final LinkProperties wifiLp = new LinkProperties();
18523         wifiLp.setInterfaceName(WIFI_IFNAME);
18524         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp);
18525         mWiFiAgent.connect(true);
18526 
18527         waitForIdle();
18528 
18529         final ArrayTrackRecord<Pair<String, Long>>.ReadHead readHead =
18530                 mDeps.mRateLimitHistory.newReadHead();
18531 
18532         // set rate limit to 8MBit/s => 1MB/s
18533         final int rateLimitInBytesPerSec = 1 * 1000 * 1000;
18534         setIngressRateLimit(rateLimitInBytesPerSec);
18535         assertNotNull(readHead.poll(TIMEOUT_MS, it -> it.first == wifiLp.getInterfaceName()
18536                 && it.second == rateLimitInBytesPerSec));
18537 
18538         final LinkProperties cellLp = new LinkProperties();
18539         cellLp.setInterfaceName(MOBILE_IFNAME);
18540         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
18541         mCellAgent.connect(false);
18542         assertNotNull(readHead.poll(TIMEOUT_MS, it -> it.first == cellLp.getInterfaceName()
18543                 && it.second == rateLimitInBytesPerSec));
18544     }
18545 
18546     @Test @IgnoreUpTo(SC_V2)
18547     public void testUpdateRateLimit_OnlyAffectsInternetCapableNetworks() throws Exception {
18548         final LinkProperties wifiLp = new LinkProperties();
18549         wifiLp.setInterfaceName(WIFI_IFNAME);
18550 
18551         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp);
18552         mWiFiAgent.connectWithoutInternet();
18553 
18554         waitForIdle();
18555 
18556         setIngressRateLimit(1000);
18557         setIngressRateLimit(-1);
18558 
18559         final ArrayTrackRecord<Pair<String, Long>>.ReadHead readHeadWifi =
18560                 mDeps.mRateLimitHistory.newReadHead();
18561         assertNull(readHeadWifi.poll(TIMEOUT_MS, it -> it.first == wifiLp.getInterfaceName()));
18562     }
18563 
18564     @Test @IgnoreUpTo(SC_V2)
18565     public void testUpdateRateLimit_DisconnectingResetsRateLimit()
18566             throws Exception {
18567         // Steps:
18568         // - connect network
18569         // - set rate limit
18570         // - disconnect network (interface still exists)
18571         // - disable rate limit
18572         // - connect network
18573         // - ensure network interface is not rate limited
18574         final LinkProperties wifiLp = new LinkProperties();
18575         wifiLp.setInterfaceName(WIFI_IFNAME);
18576         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp);
18577         mWiFiAgent.connect(true);
18578         waitForIdle();
18579 
18580         final ArrayTrackRecord<Pair<String, Long>>.ReadHead readHeadWifi =
18581                 mDeps.mRateLimitHistory.newReadHead();
18582 
18583         int rateLimitInBytesPerSec = 1000;
18584         setIngressRateLimit(rateLimitInBytesPerSec);
18585         assertNotNull(readHeadWifi.poll(TIMEOUT_MS,
18586                 it -> it.first == wifiLp.getInterfaceName()
18587                         && it.second == rateLimitInBytesPerSec));
18588 
18589         mWiFiAgent.disconnect();
18590         assertNotNull(readHeadWifi.poll(TIMEOUT_MS,
18591                 it -> it.first == wifiLp.getInterfaceName() && it.second == -1));
18592 
18593         setIngressRateLimit(-1);
18594 
18595         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp);
18596         mWiFiAgent.connect(true);
18597         assertNull(readHeadWifi.poll(TIMEOUT_MS, it -> it.first == wifiLp.getInterfaceName()));
18598     }
18599 
18600     @Test @IgnoreUpTo(SC_V2)
18601     public void testUpdateRateLimit_UpdateExistingRateLimit() throws Exception {
18602         final LinkProperties wifiLp = new LinkProperties();
18603         wifiLp.setInterfaceName(WIFI_IFNAME);
18604         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp);
18605         mWiFiAgent.connect(true);
18606         waitForIdle();
18607 
18608         final ArrayTrackRecord<Pair<String, Long>>.ReadHead readHeadWifi =
18609                 mDeps.mRateLimitHistory.newReadHead();
18610 
18611         // update an active ingress rate limit
18612         setIngressRateLimit(1000);
18613         setIngressRateLimit(2000);
18614 
18615         // verify the following order of execution:
18616         // 1. ingress rate limit set to 1000.
18617         // 2. ingress rate limit disabled (triggered by updating active rate limit).
18618         // 3. ingress rate limit set to 2000.
18619         assertNotNull(readHeadWifi.poll(TIMEOUT_MS,
18620                 it -> it.first == wifiLp.getInterfaceName()
18621                         && it.second == 1000));
18622         assertNotNull(readHeadWifi.poll(TIMEOUT_MS,
18623                 it -> it.first == wifiLp.getInterfaceName()
18624                         && it.second == -1));
18625         assertNotNull(readHeadWifi.poll(TIMEOUT_MS,
18626                 it -> it.first == wifiLp.getInterfaceName()
18627                         && it.second == 2000));
18628     }
18629 
18630     @Test @IgnoreAfter(SC_V2)
18631     public void testUpdateRateLimit_DoesNothingBeforeT() throws Exception {
18632         final LinkProperties wifiLp = new LinkProperties();
18633         wifiLp.setInterfaceName(WIFI_IFNAME);
18634         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp);
18635         mWiFiAgent.connect(true);
18636         waitForIdle();
18637 
18638         final ArrayTrackRecord<Pair<String, Long>>.ReadHead readHead =
18639                 mDeps.mRateLimitHistory.newReadHead();
18640 
18641         setIngressRateLimit(1000);
18642         waitForIdle();
18643 
18644         assertNull(readHead.poll(TEST_CALLBACK_TIMEOUT_MS, it -> true));
18645     }
18646 
18647     @Test
18648     public void testOfferNetwork_ChecksArgumentsOutsideOfHandler() throws Exception {
18649         final TestableNetworkOfferCallback callback = new TestableNetworkOfferCallback(
18650                 TIMEOUT_MS /* timeout */, TEST_CALLBACK_TIMEOUT_MS /* noCallbackTimeout */);
18651         final NetworkProvider testProvider = new NetworkProvider(mServiceContext,
18652                 mCsHandlerThread.getLooper(), "Test provider");
18653         final NetworkCapabilities caps = new NetworkCapabilities.Builder()
18654                 .addCapability(NET_CAPABILITY_INTERNET)
18655                 .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
18656                 .build();
18657 
18658         final NetworkScore score = new NetworkScore.Builder().build();
18659         testProvider.registerNetworkOffer(score, caps, r -> r.run(), callback);
18660         testProvider.unregisterNetworkOffer(callback);
18661 
18662         assertThrows(NullPointerException.class,
18663                 () -> mService.offerNetwork(100, score, caps, null));
18664         assertThrows(NullPointerException.class, () -> mService.unofferNetwork(null));
18665     }
18666 
18667     public void doTestIgnoreValidationAfterRoam(int resValue, final boolean enabled)
18668             throws Exception {
18669         doReturn(resValue).when(mResources)
18670                 .getInteger(R.integer.config_validationFailureAfterRoamIgnoreTimeMillis);
18671 
18672         final String bssid1 = "AA:AA:AA:AA:AA:AA";
18673         final String bssid2 = "BB:BB:BB:BB:BB:BB";
18674         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
18675         mCellAgent.connect(true);
18676         NetworkCapabilities wifiNc1 = new NetworkCapabilities()
18677                 .addCapability(NET_CAPABILITY_INTERNET)
18678                 .addCapability(NET_CAPABILITY_NOT_VPN)
18679                 .addCapability(NET_CAPABILITY_NOT_RESTRICTED)
18680                 .addCapability(NET_CAPABILITY_TRUSTED)
18681                 .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
18682                 .addTransportType(TRANSPORT_WIFI)
18683                 .setTransportInfo(new WifiInfo.Builder().setBssid(bssid1).build());
18684         NetworkCapabilities wifiNc2 = new NetworkCapabilities(wifiNc1)
18685                 .setTransportInfo(new WifiInfo.Builder().setBssid(bssid2).build());
18686         final LinkProperties wifiLp = new LinkProperties();
18687         wifiLp.setInterfaceName(WIFI_IFNAME);
18688         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp, wifiNc1);
18689         mWiFiAgent.connect(true);
18690 
18691         // The default network will be switching to Wi-Fi Network.
18692         final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
18693         final NetworkRequest wifiRequest = new NetworkRequest.Builder()
18694                 .addTransportType(TRANSPORT_WIFI).build();
18695         mCm.requestNetwork(wifiRequest, wifiNetworkCallback);
18696         wifiNetworkCallback.expectAvailableCallbacksValidated(mWiFiAgent);
18697         registerDefaultNetworkCallbacks();
18698         mDefaultNetworkCallback.expectAvailableCallbacksValidated(mWiFiAgent);
18699 
18700         // There is a bug in the current code where ignoring validation after roam will not
18701         // correctly change the default network if the result if the validation is partial or
18702         // captive portal. TODO : fix the bug and reinstate this code.
18703         if (false) {
18704             // Wi-Fi roaming from wifiNc1 to wifiNc2 but the network is now behind a captive portal.
18705             mWiFiAgent.setNetworkCapabilities(wifiNc2, true /* sendToConnectivityService */);
18706             // The only thing changed in this CAPS is the BSSID, which can't be tested for in this
18707             // test because it's redacted.
18708             wifiNetworkCallback.expectCaps(mWiFiAgent);
18709             mDefaultNetworkCallback.expectCaps(mWiFiAgent);
18710             mWiFiAgent.setNetworkPortal(TEST_REDIRECT_URL, false /* privateDnsProbeSent */);
18711             mCm.reportNetworkConnectivity(mWiFiAgent.getNetwork(), false);
18712             // Wi-Fi is now detected to have a portal : cell should become the default network.
18713             mDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellAgent);
18714             wifiNetworkCallback.expectCaps(mWiFiAgent,
18715                     c -> !c.hasCapability(NET_CAPABILITY_VALIDATED));
18716             wifiNetworkCallback.expectCaps(mWiFiAgent,
18717                     c -> c.hasCapability(NET_CAPABILITY_CAPTIVE_PORTAL));
18718 
18719             // Wi-Fi becomes valid again. The default network goes back to Wi-Fi.
18720             mWiFiAgent.setNetworkValid(false /* privateDnsProbeSent */);
18721             mCm.reportNetworkConnectivity(mWiFiAgent.getNetwork(), true);
18722             mDefaultNetworkCallback.expectAvailableCallbacksValidated(mWiFiAgent);
18723             wifiNetworkCallback.expectCaps(mWiFiAgent,
18724                     c -> !c.hasCapability(NET_CAPABILITY_CAPTIVE_PORTAL));
18725 
18726             // Wi-Fi roaming from wifiNc2 to wifiNc1, and the network now has partial connectivity.
18727             mWiFiAgent.setNetworkCapabilities(wifiNc1, true);
18728             wifiNetworkCallback.expectCaps(mWiFiAgent);
18729             mDefaultNetworkCallback.expectCaps(mWiFiAgent);
18730             mWiFiAgent.setNetworkPartial();
18731             mCm.reportNetworkConnectivity(mWiFiAgent.getNetwork(), false);
18732             // Wi-Fi now only offers partial connectivity, so in the absence of accepting partial
18733             // connectivity explicitly for this network, it loses default status to cell.
18734             mDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellAgent);
18735             wifiNetworkCallback.expectCaps(mWiFiAgent,
18736                     c -> c.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY));
18737 
18738             // Wi-Fi becomes valid again. The default network goes back to Wi-Fi.
18739             mWiFiAgent.setNetworkValid(false /* privateDnsProbeSent */);
18740             mCm.reportNetworkConnectivity(mWiFiAgent.getNetwork(), true);
18741             mDefaultNetworkCallback.expectAvailableCallbacksValidated(mWiFiAgent);
18742             wifiNetworkCallback.expectCaps(mWiFiAgent,
18743                     c -> !c.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY));
18744         }
18745         mCm.unregisterNetworkCallback(wifiNetworkCallback);
18746 
18747         // Wi-Fi roams from wifiNc1 to wifiNc2, and now becomes really invalid. If validation
18748         // failures after roam are not ignored, this will cause cell to become the default network.
18749         // If they are ignored, this will not cause a switch until later.
18750         mWiFiAgent.setNetworkCapabilities(wifiNc2, true);
18751         mDefaultNetworkCallback.expectCaps(mWiFiAgent);
18752         mWiFiAgent.setNetworkInvalid(false /* invalidBecauseOfPrivateDns */);
18753         mCm.reportNetworkConnectivity(mWiFiAgent.getNetwork(), false);
18754 
18755         if (enabled) {
18756             // Network validation failed, but the result will be ignored.
18757             assertTrue(mCm.getNetworkCapabilities(mWiFiAgent.getNetwork()).hasCapability(
18758                     NET_CAPABILITY_VALIDATED));
18759             mWiFiAgent.setNetworkValid(false);
18760 
18761             // Behavior of after config_validationFailureAfterRoamIgnoreTimeMillis
18762             ConditionVariable waitForValidationBlock = new ConditionVariable();
18763             doReturn(50).when(mResources)
18764                     .getInteger(R.integer.config_validationFailureAfterRoamIgnoreTimeMillis);
18765             // Wi-Fi roaming from wifiNc2 to wifiNc1.
18766             mWiFiAgent.setNetworkCapabilities(wifiNc1, true);
18767             mWiFiAgent.setNetworkInvalid(false);
18768             waitForValidationBlock.block(150);
18769             mCm.reportNetworkConnectivity(mWiFiAgent.getNetwork(), false);
18770             mDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellAgent);
18771         } else {
18772             mDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellAgent);
18773         }
18774 
18775         // Wi-Fi is still connected and would become the default network if cell were to
18776         // disconnect. This assertion ensures that the switch to cellular was not caused by
18777         // Wi-Fi disconnecting (e.g., because the capability change to wifiNc2 caused it
18778         // to stop satisfying the default request).
18779         mCellAgent.disconnect();
18780         mDefaultNetworkCallback.expect(LOST, mCellAgent);
18781         mDefaultNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
18782 
18783     }
18784 
18785     @Test
18786     public void testIgnoreValidationAfterRoamDisabled() throws Exception {
18787         doTestIgnoreValidationAfterRoam(-1, false /* enabled */);
18788     }
18789 
18790     @Test
18791     public void testIgnoreValidationAfterRoamEnabled() throws Exception {
18792         final boolean enabled = !mDeps.isAtLeastT();
18793         doTestIgnoreValidationAfterRoam(5_000, enabled);
18794     }
18795 
18796     @Test
18797     public void testShouldIgnoreValidationFailureAfterRoam() {
18798         // Always disabled on T+.
18799         assumeFalse(mDeps.isAtLeastT());
18800 
18801         NetworkAgentInfo nai = fakeWifiNai(new NetworkCapabilities());
18802 
18803         // Enabled, but never roamed.
18804         doReturn(5_000).when(mResources)
18805                 .getInteger(R.integer.config_validationFailureAfterRoamIgnoreTimeMillis);
18806         assertEquals(0, nai.lastRoamTime);
18807         assertFalse(mService.shouldIgnoreValidationFailureAfterRoam(nai));
18808 
18809         // Roamed recently.
18810         nai.lastRoamTime = SystemClock.elapsedRealtime() - 500 /* ms */;
18811         assertTrue(mService.shouldIgnoreValidationFailureAfterRoam(nai));
18812 
18813         // Disabled due to invalid setting (maximum is 10 seconds).
18814         doReturn(15_000).when(mResources)
18815                 .getInteger(R.integer.config_validationFailureAfterRoamIgnoreTimeMillis);
18816         assertFalse(mService.shouldIgnoreValidationFailureAfterRoam(nai));
18817 
18818         // Disabled.
18819         doReturn(-1).when(mResources)
18820                 .getInteger(R.integer.config_validationFailureAfterRoamIgnoreTimeMillis);
18821         assertFalse(mService.shouldIgnoreValidationFailureAfterRoam(nai));
18822     }
18823 
18824 
18825     @Test
18826     public void testLegacyTetheringApiGuardWithProperPermission() throws Exception {
18827         final String testIface = "test0";
18828         mServiceContext.setPermission(ACCESS_NETWORK_STATE, PERMISSION_DENIED);
18829         assertThrows(SecurityException.class, () -> mService.getLastTetherError(testIface));
18830         assertThrows(SecurityException.class, () -> mService.getTetherableIfaces());
18831         assertThrows(SecurityException.class, () -> mService.getTetheredIfaces());
18832         assertThrows(SecurityException.class, () -> mService.getTetheringErroredIfaces());
18833         assertThrows(SecurityException.class, () -> mService.getTetherableUsbRegexs());
18834         assertThrows(SecurityException.class, () -> mService.getTetherableWifiRegexs());
18835 
18836         withPermission(ACCESS_NETWORK_STATE, () -> {
18837             mService.getLastTetherError(testIface);
18838             verify(mTetheringManager).getLastTetherError(testIface);
18839 
18840             mService.getTetherableIfaces();
18841             verify(mTetheringManager).getTetherableIfaces();
18842 
18843             mService.getTetheredIfaces();
18844             verify(mTetheringManager).getTetheredIfaces();
18845 
18846             mService.getTetheringErroredIfaces();
18847             verify(mTetheringManager).getTetheringErroredIfaces();
18848 
18849             mService.getTetherableUsbRegexs();
18850             verify(mTetheringManager).getTetherableUsbRegexs();
18851 
18852             mService.getTetherableWifiRegexs();
18853             verify(mTetheringManager).getTetherableWifiRegexs();
18854         });
18855     }
18856 
18857     private void verifyMtuSetOnWifiInterface(int mtu) throws Exception {
18858         verify(mMockNetd, times(1)).interfaceSetMtu(WIFI_IFNAME, mtu);
18859     }
18860 
18861     private void verifyMtuNeverSetOnWifiInterface() throws Exception {
18862         verify(mMockNetd, never()).interfaceSetMtu(eq(WIFI_IFNAME), anyInt());
18863     }
18864 
18865     private void verifyMtuSetOnWifiInterfaceOnlyUpToT(int mtu) throws Exception {
18866         if (!mService.shouldCreateNetworksImmediately(mWiFiAgent.getNetworkCapabilities())) {
18867             verify(mMockNetd, times(1)).interfaceSetMtu(WIFI_IFNAME, mtu);
18868         } else {
18869             verify(mMockNetd, never()).interfaceSetMtu(eq(WIFI_IFNAME), anyInt());
18870         }
18871     }
18872 
18873     private void verifyMtuSetOnWifiInterfaceOnlyStartingFromU(int mtu) throws Exception {
18874         if (mService.shouldCreateNetworksImmediately(mWiFiAgent.getNetworkCapabilities())) {
18875             verify(mMockNetd, times(1)).interfaceSetMtu(WIFI_IFNAME, mtu);
18876         } else {
18877             verify(mMockNetd, never()).interfaceSetMtu(eq(WIFI_IFNAME), anyInt());
18878         }
18879     }
18880 
18881     @Test
18882     public void testSendLinkPropertiesSetInterfaceMtuBeforeConnect() throws Exception {
18883         final int mtu = 1281;
18884         LinkProperties lp = new LinkProperties();
18885         lp.setInterfaceName(WIFI_IFNAME);
18886         lp.setMtu(mtu);
18887 
18888         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
18889         mWiFiAgent.sendLinkProperties(lp);
18890         waitForIdle();
18891         verifyMtuSetOnWifiInterface(mtu);
18892         reset(mMockNetd);
18893 
18894         mWiFiAgent.connect(false /* validated */);
18895         // Before U, the MTU is always (re-)applied when the network connects.
18896         verifyMtuSetOnWifiInterfaceOnlyUpToT(mtu);
18897     }
18898 
18899     @Test
18900     public void testSendLinkPropertiesUpdateInterfaceMtuBeforeConnect() throws Exception {
18901         final int mtu = 1327;
18902         LinkProperties lp = new LinkProperties();
18903         lp.setInterfaceName(WIFI_IFNAME);
18904         lp.setMtu(mtu);
18905 
18906         // Registering an agent with an MTU only sets the MTU on U+.
18907         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, lp);
18908         waitForIdle();
18909         verifyMtuSetOnWifiInterfaceOnlyStartingFromU(mtu);
18910         reset(mMockNetd);
18911 
18912         // Future updates with the same MTU don't set the MTU even on T when it's not set initially.
18913         mWiFiAgent.sendLinkProperties(lp);
18914         waitForIdle();
18915         verifyMtuNeverSetOnWifiInterface();
18916 
18917         // Updating with a different MTU does work.
18918         lp.setMtu(mtu + 1);
18919         mWiFiAgent.sendLinkProperties(lp);
18920         waitForIdle();
18921         verifyMtuSetOnWifiInterface(mtu + 1);
18922         reset(mMockNetd);
18923 
18924         mWiFiAgent.connect(false /* validated */);
18925         // Before U, the MTU is always (re-)applied when the network connects.
18926         verifyMtuSetOnWifiInterfaceOnlyUpToT(mtu + 1);
18927     }
18928 
18929     @Test
18930     public void testSendLinkPropertiesUpdateInterfaceMtuAfterConnect() throws Exception {
18931         final int mtu = 1327;
18932         LinkProperties lp = new LinkProperties();
18933         lp.setInterfaceName(WIFI_IFNAME);
18934         lp.setMtu(mtu);
18935 
18936         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
18937         mWiFiAgent.connect(false /* validated */);
18938         verifyMtuNeverSetOnWifiInterface();
18939 
18940         mWiFiAgent.sendLinkProperties(lp);
18941         waitForIdle();
18942         // The MTU is always (re-)applied when the network connects.
18943         verifyMtuSetOnWifiInterface(mtu);
18944     }
18945 
18946     @Test
18947     public void testSendLinkPropertiesSetInterfaceMtu_DifferentMtu() throws Exception {
18948         final int mtu = 1328, mtu2 = 1500;
18949         LinkProperties lp = new LinkProperties();
18950         lp.setInterfaceName(WIFI_IFNAME);
18951         lp.setMtu(mtu);
18952 
18953         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, lp);
18954         mWiFiAgent.connect(false /* validated */);
18955         verifyMtuSetOnWifiInterface(mtu);
18956         reset(mMockNetd);
18957 
18958         LinkProperties lp2 = new LinkProperties(lp);
18959         lp2.setMtu(mtu2);
18960         mWiFiAgent.sendLinkProperties(lp2);
18961         waitForIdle();
18962         verifyMtuSetOnWifiInterface(mtu2);
18963     }
18964 
18965     @Test
18966     public void testSendLinkPropertiesSetInterfaceMtu_IdenticalMtuAndIface() throws Exception {
18967         final int mtu = 1329;
18968         LinkProperties lp = new LinkProperties();
18969         lp.setInterfaceName(WIFI_IFNAME);
18970         lp.setMtu(mtu);
18971 
18972         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, lp);
18973         mWiFiAgent.connect(false /* validated */);
18974         verifyMtuSetOnWifiInterface(mtu);
18975         reset(mMockNetd);
18976 
18977         mWiFiAgent.sendLinkProperties(new LinkProperties(lp));
18978         waitForIdle();
18979         verifyMtuNeverSetOnWifiInterface();
18980     }
18981 
18982     @Test
18983     public void testSendLinkPropertiesSetInterfaceMtu_IdenticalMtuAndNullIface() throws Exception {
18984         final int mtu = 1330;
18985         LinkProperties lp = new LinkProperties();
18986         lp.setInterfaceName(WIFI_IFNAME);
18987         lp.setMtu(mtu);
18988 
18989         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, lp);
18990         mWiFiAgent.connect(false /* validated */);
18991         verifyMtuSetOnWifiInterface(mtu);
18992         reset(mMockNetd);
18993 
18994         LinkProperties lp2 = new LinkProperties(lp);
18995         lp2.setInterfaceName(null);
18996         mWiFiAgent.sendLinkProperties(new LinkProperties(lp2));
18997         waitForIdle();
18998         verifyMtuNeverSetOnWifiInterface();
18999     }
19000 
19001     @Test
19002     public void testSendLinkPropertiesSetInterfaceMtu_IdenticalMtuDiffIface() throws Exception {
19003         final int mtu = 1331;
19004         LinkProperties lp = new LinkProperties();
19005         lp.setInterfaceName(WIFI_IFNAME);
19006         lp.setMtu(mtu);
19007 
19008         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, lp);
19009         mWiFiAgent.connect(false /* validated */);
19010         verifyMtuSetOnWifiInterface(mtu);
19011         reset(mMockNetd);
19012 
19013         final String ifaceName2 = WIFI_IFNAME + "_2";
19014         LinkProperties lp2 = new LinkProperties(lp);
19015         lp2.setInterfaceName(ifaceName2);
19016 
19017         mWiFiAgent.sendLinkProperties(new LinkProperties(lp2));
19018         waitForIdle();
19019         verify(mMockNetd, times(1)).interfaceSetMtu(eq(ifaceName2), eq(mtu));
19020         verifyMtuNeverSetOnWifiInterface();
19021     }
19022 
19023     @Test
19024     public void testCreateDeliveryGroupKeyForConnectivityAction() throws Exception {
19025         final NetworkInfo info = new NetworkInfo(0 /* type */, 2 /* subtype */,
19026                 "MOBILE" /* typeName */, "LTE" /* subtypeName */);
19027         assertEquals("0;2;null", createDeliveryGroupKeyForConnectivityAction(info));
19028 
19029         info.setExtraInfo("test_info");
19030         assertEquals("0;2;test_info", createDeliveryGroupKeyForConnectivityAction(info));
19031     }
19032 
19033     @Test
19034     public void testNetdWakeupAddInterfaceForWifiTransport() throws Exception {
19035         final LinkProperties wifiLp = new LinkProperties();
19036         wifiLp.setInterfaceName(WIFI_IFNAME);
19037         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp);
19038         mWiFiAgent.connect(false /* validated */);
19039 
19040         final String expectedPrefix = makeNflogPrefix(WIFI_IFNAME,
19041                 mWiFiAgent.getNetwork().getNetworkHandle());
19042         verify(mMockNetd).wakeupAddInterface(WIFI_IFNAME, expectedPrefix, PACKET_WAKEUP_MARK_MASK,
19043                 PACKET_WAKEUP_MARK_MASK);
19044     }
19045 
19046     @Test
19047     public void testNetdWakeupAddInterfaceForCellularTransport() throws Exception {
19048         final LinkProperties cellLp = new LinkProperties();
19049         cellLp.setInterfaceName(MOBILE_IFNAME);
19050         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
19051         mCellAgent.connect(false /* validated */);
19052 
19053         if (mDeps.isAtLeastU()) {
19054             final String expectedPrefix = makeNflogPrefix(MOBILE_IFNAME,
19055                     mCellAgent.getNetwork().getNetworkHandle());
19056             verify(mMockNetd).wakeupAddInterface(MOBILE_IFNAME, expectedPrefix,
19057                     PACKET_WAKEUP_MARK_MASK, PACKET_WAKEUP_MARK_MASK);
19058         } else {
19059             verify(mMockNetd, never()).wakeupAddInterface(eq(MOBILE_IFNAME), anyString(), anyInt(),
19060                     anyInt());
19061         }
19062     }
19063 
19064     @Test
19065     public void testNetdWakeupAddInterfaceForEthernetTransport() throws Exception {
19066         final String ethernetIface = "eth42";
19067 
19068         final LinkProperties ethLp = new LinkProperties();
19069         ethLp.setInterfaceName(ethernetIface);
19070         mEthernetAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET, ethLp);
19071         mEthernetAgent.connect(false /* validated */);
19072 
19073         verify(mMockNetd, never()).wakeupAddInterface(eq(ethernetIface), anyString(), anyInt(),
19074                 anyInt());
19075     }
19076 
19077     // UidFrozenStateChangedCallback is added in U API.
19078     // Returning UidFrozenStateChangedCallback directly makes the test fail on T- devices since
19079     // AndroidJUnit4ClassRunner iterates all declared methods and tries to resolve the return type.
19080     // Solve this by wrapping it in an AtomicReference. Because of erasure, this removes the
19081     // resolving problem as the type isn't seen dynamically.
19082     private AtomicReference<UidFrozenStateChangedCallback> getUidFrozenStateChangedCallback() {
19083         ArgumentCaptor<UidFrozenStateChangedCallback> activityManagerCallbackCaptor =
19084                 ArgumentCaptor.forClass(UidFrozenStateChangedCallback.class);
19085         verify(mActivityManager).registerUidFrozenStateChangedCallback(any(),
19086                 activityManagerCallbackCaptor.capture());
19087         return new AtomicReference<>(activityManagerCallbackCaptor.getValue());
19088     }
19089 
19090     private BaseNetdUnsolicitedEventListener getRegisteredNetdUnsolicitedEventListener()
19091             throws RemoteException {
19092         ArgumentCaptor<BaseNetdUnsolicitedEventListener> netdCallbackCaptor =
19093                 ArgumentCaptor.forClass(BaseNetdUnsolicitedEventListener.class);
19094         verify(mMockNetd).registerUnsolicitedEventListener(netdCallbackCaptor.capture());
19095         return netdCallbackCaptor.getValue();
19096     }
19097 
19098     private static final int TEST_FROZEN_UID = 1000;
19099     private static final int TEST_UNFROZEN_UID = 2000;
19100 
19101     /**
19102      * Send a UidFrozenStateChanged message to ConnectivityService. Verify that only the frozen UID
19103      * gets passed to socketDestroy().
19104      */
19105     @Test
19106     @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
19107     public void testFrozenUidSocketDestroy() throws Exception {
19108         final UidFrozenStateChangedCallback callback =
19109                 getUidFrozenStateChangedCallback().get();
19110 
19111         final int[] uids = {TEST_FROZEN_UID, TEST_UNFROZEN_UID};
19112         final int[] frozenStates = {UID_FROZEN_STATE_FROZEN, UID_FROZEN_STATE_UNFROZEN};
19113 
19114         callback.onUidFrozenStateChanged(uids, frozenStates);
19115 
19116         waitForIdle();
19117 
19118         verify(mDestroySocketsWrapper).destroyLiveTcpSocketsByOwnerUids(Set.of(TEST_FROZEN_UID));
19119     }
19120 
19121     private void doTestDelayFrozenUidSocketDestroy(int transportType,
19122             boolean freezeWithNetworkInactive, boolean expectDelay) throws Exception {
19123         final TestNetworkCallback defaultCallback = new TestNetworkCallback();
19124         final LinkProperties lp = new LinkProperties();
19125         lp.setInterfaceName(transportToTestIfaceName(transportType));
19126         final TestNetworkAgentWrapper agent = new TestNetworkAgentWrapper(transportType, lp);
19127         final int idleTimerLabel = getIdleTimerLabel(agent.getNetwork().netId, transportType);
19128         testAndCleanup(() -> {
19129             final UidFrozenStateChangedCallback uidFrozenStateChangedCallback =
19130                     getUidFrozenStateChangedCallback().get();
19131             final BaseNetdUnsolicitedEventListener netdUnsolicitedEventListener =
19132                     getRegisteredNetdUnsolicitedEventListener();
19133 
19134             mCm.registerDefaultNetworkCallback(defaultCallback);
19135             agent.connect(true);
19136             defaultCallback.expectAvailableThenValidatedCallbacks(agent);
19137             if (freezeWithNetworkInactive) {
19138                 // Make network inactive
19139                 netdUnsolicitedEventListener.onInterfaceClassActivityChanged(false /* isActive */,
19140                         idleTimerLabel, TIMESTAMP, NETWORK_ACTIVITY_NO_UID);
19141             }
19142 
19143             // Freeze TEST_FROZEN_UID and TEST_UNFROZEN_UID
19144             final int[] uids1 = {TEST_FROZEN_UID, TEST_UNFROZEN_UID};
19145             final int[] frozenStates1 = {UID_FROZEN_STATE_FROZEN, UID_FROZEN_STATE_FROZEN};
19146             uidFrozenStateChangedCallback.onUidFrozenStateChanged(uids1, frozenStates1);
19147             waitForIdle();
19148 
19149             if (expectDelay) {
19150                 verify(mDestroySocketsWrapper, never()).destroyLiveTcpSocketsByOwnerUids(any());
19151             } else {
19152                 verify(mDestroySocketsWrapper).destroyLiveTcpSocketsByOwnerUids(
19153                         Set.of(TEST_FROZEN_UID, TEST_UNFROZEN_UID));
19154                 clearInvocations(mDestroySocketsWrapper);
19155             }
19156 
19157             // Unfreeze TEST_UNFROZEN_UID
19158             final int[] uids2 = {TEST_UNFROZEN_UID};
19159             final int[] frozenStates2 = {UID_FROZEN_STATE_UNFROZEN};
19160             uidFrozenStateChangedCallback.onUidFrozenStateChanged(uids2, frozenStates2);
19161 
19162             // Make network active
19163             netdUnsolicitedEventListener.onInterfaceClassActivityChanged(true /* isActive */,
19164                     idleTimerLabel, TIMESTAMP, TEST_PACKAGE_UID);
19165             waitForIdle();
19166 
19167             if (expectDelay) {
19168                 verify(mDestroySocketsWrapper).destroyLiveTcpSocketsByOwnerUids(
19169                         Set.of(TEST_FROZEN_UID));
19170             } else {
19171                 verify(mDestroySocketsWrapper, never()).destroyLiveTcpSocketsByOwnerUids(any());
19172             }
19173         }, () -> { // Cleanup
19174                 agent.disconnect();
19175             }, () -> {
19176                 mCm.unregisterNetworkCallback(defaultCallback);
19177             });
19178     }
19179 
19180     @Test
19181     @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
19182     public void testDelayFrozenUidSocketDestroy_ActiveCellular() throws Exception {
19183         doTestDelayFrozenUidSocketDestroy(TRANSPORT_CELLULAR, false /* freezeWithNetworkInactive */,
19184                 false /* expectDelay */);
19185     }
19186 
19187     @Test
19188     @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
19189     public void testDelayFrozenUidSocketDestroy_InactiveCellular() throws Exception {
19190         // When the default network is cellular and cellular network is inactive, closing socket
19191         // is delayed.
19192         doTestDelayFrozenUidSocketDestroy(TRANSPORT_CELLULAR, true /* freezeWithNetworkInactive */,
19193                 true /* expectDelay */);
19194     }
19195 
19196     @Test
19197     @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
19198     public void testDelayFrozenUidSocketDestroy_ActiveWifi() throws Exception {
19199         doTestDelayFrozenUidSocketDestroy(TRANSPORT_WIFI, false /* freezeWithNetworkInactive */,
19200                 false /* expectDelay */);
19201     }
19202 
19203     @Test
19204     @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
19205     public void testDelayFrozenUidSocketDestroy_InactiveWifi() throws Exception {
19206         doTestDelayFrozenUidSocketDestroy(TRANSPORT_WIFI, true /* freezeWithNetworkInactive */,
19207                 false /* expectDelay */);
19208     }
19209 
19210     /**
19211      * @param switchToWifi if true, simulate a migration of the default network to wifi
19212      *                     if false, simulate a cell disconnection
19213      */
19214     private void doTestLoseCellDefaultNetwork_ClosePendingFrozenSockets(final boolean switchToWifi)
19215             throws Exception {
19216         final UidFrozenStateChangedCallback uidFrozenStateChangedCallback =
19217                 getUidFrozenStateChangedCallback().get();
19218         final BaseNetdUnsolicitedEventListener netdUnsolicitedEventListener =
19219                 getRegisteredNetdUnsolicitedEventListener();
19220 
19221         final LinkProperties wifiLp = new LinkProperties();
19222         wifiLp.setInterfaceName(WIFI_IFNAME);
19223         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp);
19224 
19225         final LinkProperties cellLp = new LinkProperties();
19226         cellLp.setInterfaceName(MOBILE_IFNAME);
19227         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
19228         final int idleTimerLabel =
19229                 getIdleTimerLabel(mCellAgent.getNetwork().netId, TRANSPORT_CELLULAR);
19230 
19231         final TestNetworkCallback defaultCallback = new TestNetworkCallback();
19232         mCm.registerDefaultNetworkCallback(defaultCallback);
19233         try {
19234             mCellAgent.connect(true);
19235             defaultCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
19236 
19237             // Make cell network inactive
19238             netdUnsolicitedEventListener.onInterfaceClassActivityChanged(false /* isActive */,
19239                     idleTimerLabel, TIMESTAMP, NETWORK_ACTIVITY_NO_UID);
19240 
19241             // Freeze TEST_FROZEN_UID
19242             final int[] uids = {TEST_FROZEN_UID};
19243             final int[] frozenStates = {UID_FROZEN_STATE_FROZEN};
19244             uidFrozenStateChangedCallback.onUidFrozenStateChanged(uids, frozenStates);
19245             waitForIdle();
19246 
19247             // Closing frozen sockets should be delayed since the default network is cellular
19248             // and cellular network is inactive.
19249             verify(mDestroySocketsWrapper, never()).destroyLiveTcpSocketsByOwnerUids(any());
19250 
19251             if (switchToWifi) {
19252                 mWiFiAgent.connect(true);
19253                 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiAgent);
19254             } else {
19255                 mCellAgent.disconnect();
19256                 waitForIdle();
19257             }
19258 
19259             // Pending frozen sockets should be closed since the cellular network is no longer the
19260             // default network.
19261             verify(mDestroySocketsWrapper)
19262                     .destroyLiveTcpSocketsByOwnerUids(Set.of(TEST_FROZEN_UID));
19263         } finally {
19264             mCm.unregisterNetworkCallback(defaultCallback);
19265         }
19266     }
19267 
19268     @Test
19269     @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
19270     public void testLoseCellDefaultNetwork_SwitchToWifi_ClosePendingFrozenSockets()
19271             throws Exception {
19272         doTestLoseCellDefaultNetwork_ClosePendingFrozenSockets(true /* switchToWifi */);
19273     }
19274 
19275     @Test
19276     @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
19277     public void testLoseCellDefaultNetwork_NoDefaultNetwork_ClosePendingFrozenSockets()
19278             throws Exception {
19279         doTestLoseCellDefaultNetwork_ClosePendingFrozenSockets(false /* switchToWifi */);
19280     }
19281 
19282     @Test
19283     public void testDisconnectSuspendedNetworkStopClatd() throws Exception {
19284         final TestNetworkCallback networkCallback = new TestNetworkCallback();
19285         final NetworkRequest networkRequest = new NetworkRequest.Builder()
19286                 .addCapability(NET_CAPABILITY_DUN)
19287                 .build();
19288         mCm.requestNetwork(networkRequest, networkCallback);
19289 
19290         final IpPrefix nat64Prefix = new IpPrefix(InetAddress.getByName("64:ff9b::"), 96);
19291         NetworkCapabilities nc = new NetworkCapabilities().addCapability(NET_CAPABILITY_DUN);
19292         final LinkProperties lp = new LinkProperties();
19293         lp.setInterfaceName(MOBILE_IFNAME);
19294         lp.addLinkAddress(new LinkAddress("2001:db8:1::1/64"));
19295         lp.setNat64Prefix(nat64Prefix);
19296         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, lp, nc);
19297         mCellAgent.connect(true /* validated */, false /* hasInternet */,
19298                 false /* privateDnsProbeSent */);
19299 
19300         verifyClatdStart(null /* inOrder */, MOBILE_IFNAME, mCellAgent.getNetwork().netId,
19301                 nat64Prefix.toString());
19302 
19303         mCellAgent.suspend();
19304         mCm.unregisterNetworkCallback(networkCallback);
19305         mCellAgent.expectDisconnected();
19306         waitForIdle();
19307 
19308         verifyClatdStop(null /* inOrder */, MOBILE_IFNAME);
19309     }
19310 
19311     private static final int EXPECTED_TEST_METHOD_COUNT = 332;
19312 
19313     @Test
19314     public void testTestMethodCount() {
19315         final Class<?> testClass = this.getClass();
19316 
19317         int actualTestMethodCount = 0;
19318         for (final Method method : testClass.getDeclaredMethods()) {
19319             if (method.isAnnotationPresent(Test.class)) {
19320                 actualTestMethodCount++;
19321             }
19322         }
19323 
19324         assertEquals("Adding tests in ConnectivityServiceTest is deprecated, "
19325                 + "as it is too big for maintenance. Please consider adding new tests "
19326                 + "in subclasses of CSTest instead.",
19327                 EXPECTED_TEST_METHOD_COUNT, actualTestMethodCount);
19328     }
19329 
19330     // Note : adding tests in ConnectivityServiceTest is deprecated, as it is too big for
19331     // maintenance. Please consider adding new tests in subclasses of CSTest instead.
19332 }
19333