• 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.server.ConnectivityService.ALLOW_SATALLITE_NETWORK_FALLBACK;
167 import static com.android.net.module.util.DeviceConfigUtils.TETHERING_MODULE_NAME;
168 import static com.android.server.ConnectivityService.ALLOW_SYSUI_CONNECTIVITY_REPORTS;
169 import static com.android.server.ConnectivityService.KEY_DESTROY_FROZEN_SOCKETS_VERSION;
170 import static com.android.server.ConnectivityService.MAX_NETWORK_REQUESTS_PER_SYSTEM_UID;
171 import static com.android.server.ConnectivityService.PREFERENCE_ORDER_MOBILE_DATA_PREFERERRED;
172 import static com.android.server.ConnectivityService.PREFERENCE_ORDER_OEM;
173 import static com.android.server.ConnectivityService.PREFERENCE_ORDER_PROFILE;
174 import static com.android.server.ConnectivityService.PREFERENCE_ORDER_VPN;
175 import static com.android.server.ConnectivityService.createDeliveryGroupKeyForConnectivityAction;
176 import static com.android.server.ConnectivityService.makeNflogPrefix;
177 import static com.android.server.ConnectivityServiceTestUtils.transportToLegacyType;
178 import static com.android.server.NetworkAgentWrapper.CallbackType.OnQosCallbackRegister;
179 import static com.android.server.NetworkAgentWrapper.CallbackType.OnQosCallbackUnregister;
180 import static com.android.server.connectivity.ConnectivityFlags.BACKGROUND_FIREWALL_CHAIN;
181 import static com.android.server.connectivity.ConnectivityFlags.DELAY_DESTROY_SOCKETS;
182 import static com.android.server.connectivity.ConnectivityFlags.INGRESS_TO_VPN_ADDRESS_FILTERING;
183 import static com.android.testutils.Cleanup.testAndCleanup;
184 import static com.android.testutils.ConcurrentUtils.await;
185 import static com.android.testutils.ConcurrentUtils.durationOf;
186 import static com.android.testutils.DevSdkIgnoreRule.IgnoreAfter;
187 import static com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
188 import static com.android.testutils.DevSdkIgnoreRuleKt.SC_V2;
189 import static com.android.testutils.FunctionalUtils.ignoreExceptions;
190 import static com.android.testutils.HandlerUtils.visibleOnHandlerThread;
191 import static com.android.testutils.HandlerUtils.waitForIdleSerialExecutor;
192 import static com.android.testutils.MiscAsserts.assertContainsAll;
193 import static com.android.testutils.MiscAsserts.assertContainsExactly;
194 import static com.android.testutils.MiscAsserts.assertEmpty;
195 import static com.android.testutils.MiscAsserts.assertLength;
196 import static com.android.testutils.MiscAsserts.assertRunsInAtMost;
197 import static com.android.testutils.MiscAsserts.assertSameElements;
198 import static com.android.testutils.MiscAsserts.assertThrows;
199 import static com.android.testutils.RecorderCallback.CallbackEntry.AVAILABLE;
200 import static com.android.testutils.RecorderCallback.CallbackEntry.BLOCKED_STATUS;
201 import static com.android.testutils.RecorderCallback.CallbackEntry.BLOCKED_STATUS_INT;
202 import static com.android.testutils.RecorderCallback.CallbackEntry.LINK_PROPERTIES_CHANGED;
203 import static com.android.testutils.RecorderCallback.CallbackEntry.LOSING;
204 import static com.android.testutils.RecorderCallback.CallbackEntry.LOST;
205 import static com.android.testutils.RecorderCallback.CallbackEntry.NETWORK_CAPS_UPDATED;
206 import static com.android.testutils.RecorderCallback.CallbackEntry.RESUMED;
207 import static com.android.testutils.RecorderCallback.CallbackEntry.SUSPENDED;
208 import static com.android.testutils.RecorderCallback.CallbackEntry.UNAVAILABLE;
209 import static com.android.testutils.TestPermissionUtil.runAsShell;
210 
211 import static org.hamcrest.MatcherAssert.assertThat;
212 import static org.hamcrest.Matchers.containsString;
213 import static org.junit.Assert.assertEquals;
214 import static org.junit.Assert.assertFalse;
215 import static org.junit.Assert.assertNotEquals;
216 import static org.junit.Assert.assertNotNull;
217 import static org.junit.Assert.assertNull;
218 import static org.junit.Assert.assertTrue;
219 import static org.junit.Assert.fail;
220 import static org.junit.Assume.assumeFalse;
221 import static org.junit.Assume.assumeTrue;
222 import static org.mockito.AdditionalMatchers.aryEq;
223 import static org.mockito.ArgumentMatchers.anyBoolean;
224 import static org.mockito.ArgumentMatchers.anyLong;
225 import static org.mockito.ArgumentMatchers.anyString;
226 import static org.mockito.ArgumentMatchers.argThat;
227 import static org.mockito.ArgumentMatchers.eq;
228 import static org.mockito.ArgumentMatchers.isNull;
229 import static org.mockito.Matchers.anyInt;
230 import static org.mockito.Mockito.any;
231 import static org.mockito.Mockito.atLeastOnce;
232 import static org.mockito.Mockito.clearInvocations;
233 import static org.mockito.Mockito.doAnswer;
234 import static org.mockito.Mockito.doNothing;
235 import static org.mockito.Mockito.doReturn;
236 import static org.mockito.Mockito.doThrow;
237 import static org.mockito.Mockito.inOrder;
238 import static org.mockito.Mockito.mock;
239 import static org.mockito.Mockito.never;
240 import static org.mockito.Mockito.reset;
241 import static org.mockito.Mockito.spy;
242 import static org.mockito.Mockito.timeout;
243 import static org.mockito.Mockito.times;
244 import static org.mockito.Mockito.verify;
245 import static org.mockito.Mockito.verifyNoMoreInteractions;
246 
247 import static java.util.Arrays.asList;
248 
249 import android.Manifest;
250 import android.annotation.NonNull;
251 import android.annotation.Nullable;
252 import android.app.ActivityManager;
253 import android.app.ActivityManager.UidFrozenStateChangedCallback;
254 import android.app.AlarmManager;
255 import android.app.AppOpsManager;
256 import android.app.BroadcastOptions;
257 import android.app.NotificationManager;
258 import android.app.PendingIntent;
259 import android.app.admin.DevicePolicyManager;
260 import android.app.usage.NetworkStatsManager;
261 import android.compat.testing.PlatformCompatChangeRule;
262 import android.content.BroadcastReceiver;
263 import android.content.ComponentName;
264 import android.content.ContentProvider;
265 import android.content.ContentResolver;
266 import android.content.Context;
267 import android.content.Intent;
268 import android.content.IntentFilter;
269 import android.content.pm.ApplicationInfo;
270 import android.content.pm.ModuleInfo;
271 import android.content.pm.PackageInfo;
272 import android.content.pm.PackageManager;
273 import android.content.pm.ResolveInfo;
274 import android.content.pm.ServiceInfo;
275 import android.content.pm.UserInfo;
276 import android.content.res.Resources;
277 import android.location.LocationManager;
278 import android.net.CaptivePortal;
279 import android.net.CaptivePortalData;
280 import android.net.ConnectionInfo;
281 import android.net.ConnectivityDiagnosticsManager.DataStallReport;
282 import android.net.ConnectivityManager;
283 import android.net.ConnectivityManager.NetworkCallback;
284 import android.net.ConnectivityManager.PacketKeepalive;
285 import android.net.ConnectivityManager.PacketKeepaliveCallback;
286 import android.net.ConnectivityManager.TooManyRequestsException;
287 import android.net.ConnectivitySettingsManager;
288 import android.net.ConnectivityThread;
289 import android.net.DataStallReportParcelable;
290 import android.net.EthernetManager;
291 import android.net.EthernetNetworkSpecifier;
292 import android.net.IConnectivityDiagnosticsCallback;
293 import android.net.IDnsResolver;
294 import android.net.INetd;
295 import android.net.INetworkMonitor;
296 import android.net.INetworkMonitorCallbacks;
297 import android.net.IOnCompleteListener;
298 import android.net.IQosCallback;
299 import android.net.InetAddresses;
300 import android.net.InterfaceConfigurationParcel;
301 import android.net.IpPrefix;
302 import android.net.IpSecManager;
303 import android.net.IpSecManager.UdpEncapsulationSocket;
304 import android.net.LinkAddress;
305 import android.net.LinkProperties;
306 import android.net.MatchAllNetworkSpecifier;
307 import android.net.NativeNetworkConfig;
308 import android.net.NativeNetworkType;
309 import android.net.Network;
310 import android.net.NetworkAgent;
311 import android.net.NetworkAgentConfig;
312 import android.net.NetworkCapabilities;
313 import android.net.NetworkFactory;
314 import android.net.NetworkInfo;
315 import android.net.NetworkInfo.DetailedState;
316 import android.net.NetworkPolicyManager;
317 import android.net.NetworkPolicyManager.NetworkPolicyCallback;
318 import android.net.NetworkProvider;
319 import android.net.NetworkRequest;
320 import android.net.NetworkScore;
321 import android.net.NetworkSpecifier;
322 import android.net.NetworkStack;
323 import android.net.NetworkStateSnapshot;
324 import android.net.NetworkTestResultParcelable;
325 import android.net.OemNetworkPreferences;
326 import android.net.PacProxyManager;
327 import android.net.ProfileNetworkPreference;
328 import android.net.Proxy;
329 import android.net.ProxyInfo;
330 import android.net.QosCallbackException;
331 import android.net.QosFilter;
332 import android.net.QosSession;
333 import android.net.ResolverParamsParcel;
334 import android.net.RouteInfo;
335 import android.net.RouteInfoParcel;
336 import android.net.SocketKeepalive;
337 import android.net.TelephonyNetworkSpecifier;
338 import android.net.TetheringManager;
339 import android.net.TransportInfo;
340 import android.net.UidRange;
341 import android.net.UidRangeParcel;
342 import android.net.UnderlyingNetworkInfo;
343 import android.net.Uri;
344 import android.net.VpnManager;
345 import android.net.VpnTransportInfo;
346 import android.net.connectivity.ConnectivityCompatChanges;
347 import android.net.metrics.IpConnectivityLog;
348 import android.net.netd.aidl.NativeUidRangeConfig;
349 import android.net.networkstack.NetworkStackClientBase;
350 import android.net.resolv.aidl.Nat64PrefixEventParcel;
351 import android.net.resolv.aidl.PrivateDnsValidationEventParcel;
352 import android.net.shared.PrivateDnsConfig;
353 import android.net.wifi.WifiInfo;
354 import android.os.BadParcelableException;
355 import android.os.BatteryStatsManager;
356 import android.os.Binder;
357 import android.os.Build;
358 import android.os.Bundle;
359 import android.os.ConditionVariable;
360 import android.os.Handler;
361 import android.os.HandlerThread;
362 import android.os.IBinder;
363 import android.os.INetworkManagementService;
364 import android.os.Looper;
365 import android.os.Messenger;
366 import android.os.Parcel;
367 import android.os.ParcelFileDescriptor;
368 import android.os.Parcelable;
369 import android.os.PersistableBundle;
370 import android.os.Process;
371 import android.os.RemoteException;
372 import android.os.ServiceSpecificException;
373 import android.os.SystemClock;
374 import android.os.SystemConfigManager;
375 import android.os.UserHandle;
376 import android.os.UserManager;
377 import android.provider.Settings;
378 import android.system.Os;
379 import android.telephony.SubscriptionManager;
380 import android.telephony.TelephonyManager;
381 import android.telephony.data.EpsBearerQosSessionAttributes;
382 import android.telephony.data.NrQosSessionAttributes;
383 import android.test.mock.MockContentResolver;
384 import android.text.TextUtils;
385 import android.util.ArraySet;
386 import android.util.Log;
387 import android.util.Pair;
388 import android.util.Range;
389 import android.util.SparseArray;
390 
391 import androidx.test.InstrumentationRegistry;
392 import androidx.test.filters.SmallTest;
393 
394 import com.android.connectivity.resources.R;
395 import com.android.internal.annotations.GuardedBy;
396 import com.android.internal.app.IBatteryStats;
397 import com.android.internal.net.VpnConfig;
398 import com.android.internal.util.WakeupMessage;
399 import com.android.internal.util.test.BroadcastInterceptingContext;
400 import com.android.internal.util.test.FakeSettingsProvider;
401 import com.android.modules.utils.build.SdkLevel;
402 import com.android.net.module.util.ArrayTrackRecord;
403 import com.android.net.module.util.BaseNetdUnsolicitedEventListener;
404 import com.android.net.module.util.CollectionUtils;
405 import com.android.net.module.util.LocationPermissionChecker;
406 import com.android.net.module.util.NetworkMonitorUtils;
407 import com.android.networkstack.apishim.ConstantsShim;
408 import com.android.networkstack.apishim.NetworkAgentConfigShimImpl;
409 import com.android.networkstack.apishim.common.BroadcastOptionsShim;
410 import com.android.networkstack.apishim.common.UnsupportedApiLevelException;
411 import com.android.server.ConnectivityService.ConnectivityDiagnosticsCallbackInfo;
412 import com.android.server.ConnectivityService.NetworkRequestInfo;
413 import com.android.server.ConnectivityServiceTest.ConnectivityServiceDependencies.DestroySocketsWrapper;
414 import com.android.server.ConnectivityServiceTest.ConnectivityServiceDependencies.ReportedInterfaces;
415 import com.android.server.connectivity.ApplicationSelfCertifiedNetworkCapabilities;
416 import com.android.server.connectivity.AutomaticOnOffKeepaliveTracker;
417 import com.android.server.connectivity.CarrierPrivilegeAuthenticator;
418 import com.android.server.connectivity.ClatCoordinator;
419 import com.android.server.connectivity.ConnectivityFlags;
420 import com.android.server.connectivity.ConnectivityResources;
421 import com.android.server.connectivity.KeepaliveTracker;
422 import com.android.server.connectivity.MultinetworkPolicyTracker;
423 import com.android.server.connectivity.MultinetworkPolicyTrackerTestDependencies;
424 import com.android.server.connectivity.Nat464Xlat;
425 import com.android.server.connectivity.NetworkAgentInfo;
426 import com.android.server.connectivity.NetworkNotificationManager;
427 import com.android.server.connectivity.NetworkNotificationManager.NotificationType;
428 import com.android.server.connectivity.ProxyTracker;
429 import com.android.server.connectivity.QosCallbackTracker;
430 import com.android.server.connectivity.SatelliteAccessController;
431 import com.android.server.connectivity.TcpKeepaliveController;
432 import com.android.server.connectivity.UidRangeUtils;
433 import com.android.server.net.NetworkPinner;
434 import com.android.testutils.DevSdkIgnoreRule;
435 import com.android.testutils.DevSdkIgnoreRunner;
436 import com.android.testutils.FunctionalUtils.Function3;
437 import com.android.testutils.FunctionalUtils.ThrowingConsumer;
438 import com.android.testutils.FunctionalUtils.ThrowingRunnable;
439 import com.android.testutils.HandlerUtils;
440 import com.android.testutils.RecorderCallback.CallbackEntry;
441 import com.android.testutils.TestableNetworkCallback;
442 import com.android.testutils.TestableNetworkOfferCallback;
443 
444 import libcore.junit.util.compat.CoreCompatChangeRule.DisableCompatChanges;
445 import libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges;
446 
447 import org.junit.After;
448 import org.junit.Assert;
449 import org.junit.Before;
450 import org.junit.Ignore;
451 import org.junit.Rule;
452 import org.junit.Test;
453 import org.junit.runner.RunWith;
454 import org.mockito.AdditionalAnswers;
455 import org.mockito.ArgumentCaptor;
456 import org.mockito.InOrder;
457 import org.mockito.Mock;
458 import org.mockito.MockitoAnnotations;
459 import org.mockito.Spy;
460 import org.mockito.stubbing.Answer;
461 
462 import java.io.FileDescriptor;
463 import java.io.IOException;
464 import java.io.PrintWriter;
465 import java.io.StringWriter;
466 import java.lang.reflect.Method;
467 import java.net.DatagramSocket;
468 import java.net.Inet4Address;
469 import java.net.Inet6Address;
470 import java.net.InetAddress;
471 import java.net.InetSocketAddress;
472 import java.net.Socket;
473 import java.util.ArrayList;
474 import java.util.Arrays;
475 import java.util.Collection;
476 import java.util.Collections;
477 import java.util.Comparator;
478 import java.util.HashMap;
479 import java.util.HashSet;
480 import java.util.List;
481 import java.util.Map;
482 import java.util.Objects;
483 import java.util.Set;
484 import java.util.UUID;
485 import java.util.concurrent.CompletableFuture;
486 import java.util.concurrent.CountDownLatch;
487 import java.util.concurrent.Executor;
488 import java.util.concurrent.ExecutorService;
489 import java.util.concurrent.Executors;
490 import java.util.concurrent.LinkedBlockingQueue;
491 import java.util.concurrent.TimeUnit;
492 import java.util.concurrent.TimeoutException;
493 import java.util.concurrent.atomic.AtomicBoolean;
494 import java.util.concurrent.atomic.AtomicReference;
495 import java.util.function.BiConsumer;
496 import java.util.function.Consumer;
497 import java.util.function.Predicate;
498 import java.util.function.Supplier;
499 import java.util.regex.Matcher;
500 import java.util.regex.Pattern;
501 import java.util.stream.Collectors;
502 
503 /**
504  * Tests for {@link ConnectivityService}.
505  *
506  * Build, install and run with:
507  *  runtest frameworks-net -c com.android.server.ConnectivityServiceTest
508  */
509 // TODO : move methods from this test to smaller tests in the 'connectivityservice' directory
510 // to enable faster testing of smaller groups of functionality.
511 @RunWith(DevSdkIgnoreRunner.class)
512 @SmallTest
513 @DevSdkIgnoreRunner.MonitorThreadLeak
514 @DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
515 public class ConnectivityServiceTest {
516     private static final String TAG = "ConnectivityServiceTest";
517 
518     @Rule
519     public final DevSdkIgnoreRule ignoreRule = new DevSdkIgnoreRule();
520 
521     @Rule
522     public final PlatformCompatChangeRule compatChangeRule = new PlatformCompatChangeRule();
523 
524     private static final int TIMEOUT_MS = 2_000;
525     // Broadcasts can take a long time to be delivered. The test will not wait for that long unless
526     // there is a failure, so use a long timeout.
527     private static final int BROADCAST_TIMEOUT_MS = 30_000;
528     private static final int TEST_LINGER_DELAY_MS = 400;
529     private static final int TEST_NASCENT_DELAY_MS = 300;
530     // Chosen to be less than the linger and nascent timeout. This ensures that we can distinguish
531     // between a LOST callback that arrives immediately and a LOST callback that arrives after
532     // the linger/nascent timeout. For this, our assertions should run fast enough to leave
533     // less than (mService.mLingerDelayMs - TEST_CALLBACK_TIMEOUT_MS) between the time callbacks are
534     // supposedly fired, and the time we call expectCapChanged.
535     private static final int TEST_CALLBACK_TIMEOUT_MS = 250;
536     // Chosen to be less than TEST_CALLBACK_TIMEOUT_MS. This ensures that requests have time to
537     // complete before callbacks are verified.
538     private static final int TEST_REQUEST_TIMEOUT_MS = 150;
539 
540     private static final int UNREASONABLY_LONG_ALARM_WAIT_MS = 2_000;
541 
542     private static final long TIMESTAMP = 1234L;
543 
544     private static final int NET_ID = 110;
545     private static final int OEM_PREF_ANY_NET_ID = -1;
546     // Set a non-zero value to verify the flow to set tcp init rwnd value.
547     private static final int TEST_TCP_INIT_RWND = 60;
548 
549     // Used for testing the per-work-profile default network.
550     private static final int TEST_APP_ID = 103;
551     private static final int TEST_WORK_PROFILE_USER_ID = 2;
552     private static final int TEST_WORK_PROFILE_APP_UID =
553             UserHandle.getUid(TEST_WORK_PROFILE_USER_ID, TEST_APP_ID);
554     private static final int TEST_APP_ID_2 = 104;
555     private static final int TEST_WORK_PROFILE_APP_UID_2 =
556             UserHandle.getUid(TEST_WORK_PROFILE_USER_ID, TEST_APP_ID_2);
557     private static final int TEST_APP_ID_3 = 105;
558     private static final int TEST_APP_ID_4 = 106;
559     private static final int TEST_APP_ID_5 = 107;
560 
561     private static final String CLAT_PREFIX = "v4-";
562     private static final String MOBILE_IFNAME = "test_rmnet_data0";
563     private static final String CLAT_MOBILE_IFNAME = CLAT_PREFIX + MOBILE_IFNAME;
564     private static final String WIFI_IFNAME = "test_wlan0";
565     private static final String WIFI_WOL_IFNAME = "test_wlan_wol";
566     private static final String VPN_IFNAME = "tun10042";
567     private static final String ETHERNET_IFNAME = "eth0";
568     private static final String TEST_PACKAGE_NAME = "com.android.test.package";
569     private static final int TEST_PACKAGE_UID = 123;
570     private static final int TEST_PACKAGE_UID2 = 321;
571     private static final int TEST_PACKAGE_UID3 = 456;
572     private static final int NETWORK_ACTIVITY_NO_UID = -1;
573     private static final int TEST_SUBSCRIPTION_ID = 1;
574 
575     private static final int PACKET_WAKEUP_MARK_MASK = 0x80000000;
576 
577     private static final String ALWAYS_ON_PACKAGE = "com.android.test.alwaysonvpn";
578 
579     private static final String INTERFACE_NAME = "interface";
580 
581     private static final String TEST_VENUE_URL_NA_PASSPOINT = "https://android.com/";
582     private static final String TEST_VENUE_URL_NA_OTHER = "https://example.com/";
583     private static final String TEST_TERMS_AND_CONDITIONS_URL_NA_PASSPOINT =
584             "https://android.com/terms/";
585     private static final String TEST_TERMS_AND_CONDITIONS_URL_NA_OTHER =
586             "https://example.com/terms/";
587     private static final String TEST_VENUE_URL_CAPPORT = "https://android.com/capport/";
588     private static final String TEST_USER_PORTAL_API_URL_CAPPORT =
589             "https://android.com/user/api/capport/";
590     private static final String TEST_FRIENDLY_NAME = "Network friendly name";
591     private static final String TEST_REDIRECT_URL = "http://example.com/firstPath";
592 
593     private MockContext mServiceContext;
594     private HandlerThread mCsHandlerThread;
595     private ConnectivityServiceDependencies mDeps;
596     private AutomaticOnOffKeepaliveTrackerDependencies mAutoOnOffKeepaliveDependencies;
597     private ConnectivityService mService;
598     private WrappedConnectivityManager mCm;
599     private TestNetworkAgentWrapper mWiFiAgent;
600     private TestNetworkAgentWrapper mCellAgent;
601     private TestNetworkAgentWrapper mEthernetAgent;
602     private final List<TestNetworkAgentWrapper> mCreatedAgents = new ArrayList<>();
603     private MockVpn mMockVpn;
604     private Context mContext;
605     private NetworkPolicyCallback mPolicyCallback;
606     private WrappedMultinetworkPolicyTracker mPolicyTracker;
607     private ProxyTracker mProxyTracker;
608     private HandlerThread mAlarmManagerThread;
609     private TestNetIdManager mNetIdManager;
610     private QosCallbackMockHelper mQosCallbackMockHelper;
611     private QosCallbackTracker mQosCallbackTracker;
612     private TestNetworkCallback mDefaultNetworkCallback;
613     private TestNetworkCallback mSystemDefaultNetworkCallback;
614     private TestNetworkCallback mProfileDefaultNetworkCallback;
615     private TestNetworkCallback mTestPackageDefaultNetworkCallback;
616     private TestNetworkCallback mProfileDefaultNetworkCallbackAsAppUid2;
617     private TestNetworkCallback mTestPackageDefaultNetworkCallback2;
618 
619     // State variables required to emulate NetworkPolicyManagerService behaviour.
620     private int mBlockedReasons = BLOCKED_REASON_NONE;
621 
622     @Mock DeviceIdleInternal mDeviceIdleInternal;
623     @Mock INetworkManagementService mNetworkManagementService;
624     @Mock NetworkStatsManager mStatsManager;
625     @Mock IDnsResolver mMockDnsResolver;
626     @Mock INetd mMockNetd;
627     @Mock NetworkStackClientBase mNetworkStack;
628     @Mock PackageManager mPackageManager;
629     @Mock UserManager mUserManager;
630     @Mock NotificationManager mNotificationManager;
631     @Mock AlarmManager mAlarmManager;
632     @Mock IConnectivityDiagnosticsCallback mConnectivityDiagnosticsCallback;
633     @Mock IBinder mIBinder;
634     @Mock LocationManager mLocationManager;
635     @Mock AppOpsManager mAppOpsManager;
636     @Mock TelephonyManager mTelephonyManager;
637     @Mock EthernetManager mEthernetManager;
638     @Mock NetworkPolicyManager mNetworkPolicyManager;
639     @Mock SystemConfigManager mSystemConfigManager;
640     @Mock DevicePolicyManager mDevicePolicyManager;
641     @Mock Resources mResources;
642     @Mock ClatCoordinator mClatCoordinator;
643     @Mock PacProxyManager mPacProxyManager;
644     @Mock BpfNetMaps mBpfNetMaps;
645     @Mock CarrierPrivilegeAuthenticator mCarrierPrivilegeAuthenticator;
646     @Mock TetheringManager mTetheringManager;
647     @Mock BroadcastOptionsShim mBroadcastOptionsShim;
648     @Mock ActivityManager mActivityManager;
649     @Mock DestroySocketsWrapper mDestroySocketsWrapper;
650     @Mock SubscriptionManager mSubscriptionManager;
651     @Mock KeepaliveTracker.Dependencies mMockKeepaliveTrackerDependencies;
652     @Mock SatelliteAccessController mSatelliteAccessController;
653 
654     // BatteryStatsManager is final and cannot be mocked with regular mockito, so just mock the
655     // underlying binder calls.
656     final IBatteryStats mIBatteryStats = mock(IBatteryStats.class);
657     final BatteryStatsManager mBatteryStatsManager = new BatteryStatsManager(mIBatteryStats);
658 
659     private ArgumentCaptor<ResolverParamsParcel> mResolverParamsParcelCaptor =
660             ArgumentCaptor.forClass(ResolverParamsParcel.class);
661 
662     // This class exists to test bindProcessToNetwork and getBoundNetworkForProcess. These methods
663     // do not go through ConnectivityService but talk to netd directly, so they don't automatically
664     // reflect the state of our test ConnectivityService.
665     private class WrappedConnectivityManager extends ConnectivityManager {
666         private Network mFakeBoundNetwork;
667 
bindProcessToNetwork(Network network)668         public synchronized boolean bindProcessToNetwork(Network network) {
669             mFakeBoundNetwork = network;
670             return true;
671         }
672 
getBoundNetworkForProcess()673         public synchronized Network getBoundNetworkForProcess() {
674             return mFakeBoundNetwork;
675         }
676 
WrappedConnectivityManager(Context context, ConnectivityService service)677         public WrappedConnectivityManager(Context context, ConnectivityService service) {
678             super(context, service);
679         }
680     }
681 
682     private class MockContext extends BroadcastInterceptingContext {
683         private final MockContentResolver mContentResolver;
684 
685         @Spy private Resources mInternalResources;
686         private final LinkedBlockingQueue<Intent> mStartedActivities = new LinkedBlockingQueue<>();
687 
688         // Map of permission name -> PermissionManager.Permission_{GRANTED|DENIED} constant
689         // For permissions granted across the board, the key is only the permission name.
690         // For permissions only granted to a combination of uid/pid, the key
691         // is "<permission name>,<pid>,<uid>". PID+UID permissons have priority over generic ones.
692         private final HashMap<String, Integer> mMockedPermissions = new HashMap<>();
693 
mockStringResource(int resId)694         private void mockStringResource(int resId) {
695             doAnswer((inv) -> {
696                 return "Mock string resource ID=" + inv.getArgument(0);
697             }).when(mInternalResources).getString(resId);
698         }
699 
MockContext(Context base, ContentProvider settingsProvider)700         MockContext(Context base, ContentProvider settingsProvider) {
701             super(base);
702 
703             mInternalResources = spy(base.getResources());
704             doReturn(new String[] {
705                     "wifi,1,1,1,-1,true",
706                     "mobile,0,0,0,-1,true",
707                     "mobile_mms,2,0,2,60000,true",
708                     "mobile_supl,3,0,2,60000,true",
709             }).when(mInternalResources)
710                     .getStringArray(com.android.internal.R.array.networkAttributes);
711 
712             final int[] stringResourcesToMock = new int[] {
713                 com.android.internal.R.string.config_customVpnAlwaysOnDisconnectedDialogComponent,
714                 com.android.internal.R.string.vpn_lockdown_config,
715                 com.android.internal.R.string.vpn_lockdown_connected,
716                 com.android.internal.R.string.vpn_lockdown_connecting,
717                 com.android.internal.R.string.vpn_lockdown_disconnected,
718                 com.android.internal.R.string.vpn_lockdown_error,
719             };
720             for (int resId : stringResourcesToMock) {
721                 mockStringResource(resId);
722             }
723 
724             mContentResolver = new MockContentResolver();
725             mContentResolver.addProvider(Settings.AUTHORITY, settingsProvider);
726         }
727 
728         @Override
startActivityAsUser(Intent intent, UserHandle handle)729         public void startActivityAsUser(Intent intent, UserHandle handle) {
730             mStartedActivities.offer(intent);
731         }
732 
expectStartActivityIntent(int timeoutMs)733         public Intent expectStartActivityIntent(int timeoutMs) {
734             Intent intent = null;
735             try {
736                 intent = mStartedActivities.poll(timeoutMs, TimeUnit.MILLISECONDS);
737             } catch (InterruptedException e) {}
738             assertNotNull("Did not receive sign-in intent after " + timeoutMs + "ms", intent);
739             return intent;
740         }
741 
expectNoStartActivityIntent(int timeoutMs)742         public void expectNoStartActivityIntent(int timeoutMs) {
743             try {
744                 assertNull("Received unexpected Intent to start activity",
745                         mStartedActivities.poll(timeoutMs, TimeUnit.MILLISECONDS));
746             } catch (InterruptedException e) {}
747         }
748 
749         @Override
startService(Intent service)750         public ComponentName startService(Intent service) {
751             final String action = service.getAction();
752             if (!VpnConfig.SERVICE_INTERFACE.equals(action)
753                     && !ConstantsShim.ACTION_VPN_MANAGER_EVENT.equals(action)) {
754                 fail("Attempt to start unknown service, action=" + action);
755             }
756             return new ComponentName(service.getPackage(), "com.android.test.Service");
757         }
758 
759         @Override
getSystemService(String name)760         public Object getSystemService(String name) {
761             if (Context.CONNECTIVITY_SERVICE.equals(name)) return mCm;
762             if (Context.NOTIFICATION_SERVICE.equals(name)) return mNotificationManager;
763             if (Context.USER_SERVICE.equals(name)) return mUserManager;
764             if (Context.ALARM_SERVICE.equals(name)) return mAlarmManager;
765             if (Context.LOCATION_SERVICE.equals(name)) return mLocationManager;
766             if (Context.APP_OPS_SERVICE.equals(name)) return mAppOpsManager;
767             if (Context.TELEPHONY_SERVICE.equals(name)) return mTelephonyManager;
768             if (Context.ETHERNET_SERVICE.equals(name)) return mEthernetManager;
769             if (Context.NETWORK_POLICY_SERVICE.equals(name)) return mNetworkPolicyManager;
770             if (Context.DEVICE_POLICY_SERVICE.equals(name)) return mDevicePolicyManager;
771             if (Context.SYSTEM_CONFIG_SERVICE.equals(name)) return mSystemConfigManager;
772             if (Context.NETWORK_STATS_SERVICE.equals(name)) return mStatsManager;
773             if (Context.BATTERY_STATS_SERVICE.equals(name)) return mBatteryStatsManager;
774             if (Context.PAC_PROXY_SERVICE.equals(name)) return mPacProxyManager;
775             if (Context.TETHERING_SERVICE.equals(name)) return mTetheringManager;
776             if (Context.ACTIVITY_SERVICE.equals(name)) return mActivityManager;
777             if (Context.TELEPHONY_SUBSCRIPTION_SERVICE.equals(name)) return mSubscriptionManager;
778             // StatsManager is final and can't be mocked, and uses static methods for mostly
779             // everything. The simplest fix is to return null and not have metrics in tests.
780             if (Context.STATS_MANAGER.equals(name)) return null;
781             return super.getSystemService(name);
782         }
783 
784         final HashMap<UserHandle, UserManager> mUserManagers = new HashMap<>();
785         @Override
createContextAsUser(UserHandle user, int flags)786         public Context createContextAsUser(UserHandle user, int flags) {
787             final Context asUser = mock(Context.class, AdditionalAnswers.delegatesTo(this));
788             doReturn(user).when(asUser).getUser();
789             doAnswer((inv) -> {
790                 final UserManager um = mUserManagers.computeIfAbsent(user,
791                         u -> mock(UserManager.class, AdditionalAnswers.delegatesTo(mUserManager)));
792                 return um;
793             }).when(asUser).getSystemService(Context.USER_SERVICE);
794             return asUser;
795         }
796 
setWorkProfile(@onNull final UserHandle userHandle, boolean value)797         public void setWorkProfile(@NonNull final UserHandle userHandle, boolean value) {
798             // This relies on all contexts for a given user returning the same UM mock
799             final UserManager umMock = createContextAsUser(userHandle, 0 /* flags */)
800                     .getSystemService(UserManager.class);
801             doReturn(value).when(umMock).isManagedProfile();
802             doReturn(value).when(mUserManager).isManagedProfile(eq(userHandle.getIdentifier()));
803         }
804 
setDeviceOwner(@onNull final UserHandle userHandle, String value)805         public void setDeviceOwner(@NonNull final UserHandle userHandle, String value) {
806             // This relies on all contexts for a given user returning the same UM mock
807             final DevicePolicyManager dpmMock = createContextAsUser(userHandle, 0 /* flags */)
808                     .getSystemService(DevicePolicyManager.class);
809             ComponentName componentName = value == null
810                     ? null : new ComponentName(value, "deviceOwnerClass");
811             doReturn(componentName).when(dpmMock).getDeviceOwnerComponentOnAnyUser();
812             doReturn(componentName).when(mDevicePolicyManager).getDeviceOwnerComponentOnAnyUser();
813         }
814 
815         @Override
getContentResolver()816         public ContentResolver getContentResolver() {
817             return mContentResolver;
818         }
819 
820         @Override
getResources()821         public Resources getResources() {
822             return mInternalResources;
823         }
824 
825         @Override
getPackageManager()826         public PackageManager getPackageManager() {
827             return mPackageManager;
828         }
829 
checkMockedPermission(String permission, int pid, int uid, Function3<String, Integer, Integer, Integer> ifAbsent )830         private int checkMockedPermission(String permission, int pid, int uid,
831                 Function3<String, Integer, Integer, Integer> ifAbsent /* perm, uid, pid -> int */) {
832             final Integer granted = mMockedPermissions.get(permission + "," + pid + "," + uid);
833             if (null != granted) {
834                 return granted;
835             }
836             final Integer allGranted = mMockedPermissions.get(permission);
837             if (null != allGranted) {
838                 return allGranted;
839             }
840             return ifAbsent.apply(permission, pid, uid);
841         }
842 
843         @Override
checkPermission(String permission, int pid, int uid)844         public int checkPermission(String permission, int pid, int uid) {
845             return checkMockedPermission(permission, pid, uid,
846                     (perm, p, u) -> super.checkPermission(perm, p, u));
847         }
848 
849         @Override
checkCallingOrSelfPermission(String permission)850         public int checkCallingOrSelfPermission(String permission) {
851             return checkMockedPermission(permission, Process.myPid(), Process.myUid(),
852                     (perm, p, u) -> super.checkCallingOrSelfPermission(perm));
853         }
854 
855         @Override
enforceCallingOrSelfPermission(String permission, String message)856         public void enforceCallingOrSelfPermission(String permission, String message) {
857             final Integer granted = checkMockedPermission(permission,
858                     Process.myPid(), Process.myUid(),
859                     (perm, p, u) -> {
860                         super.enforceCallingOrSelfPermission(perm, message);
861                         // enforce will crash if the permission is not granted
862                         return PERMISSION_GRANTED;
863                     });
864 
865             if (!granted.equals(PERMISSION_GRANTED)) {
866                 throw new SecurityException("[Test] permission denied: " + permission);
867             }
868         }
869 
870         /**
871          * Mock checks for the specified permission, and have them behave as per {@code granted}.
872          *
873          * This will apply to all calls no matter what the checked UID and PID are.
874          *
875          * <p>Passing null reverts to default behavior, which does a real permission check on the
876          * test package.
877          * @param granted One of {@link PackageManager#PERMISSION_GRANTED} or
878          *                {@link PackageManager#PERMISSION_DENIED}.
879          */
setPermission(String permission, Integer granted)880         public void setPermission(String permission, Integer granted) {
881             mMockedPermissions.put(permission, granted);
882         }
883 
884         /**
885          * Mock checks for the specified permission, and have them behave as per {@code granted}.
886          *
887          * This will only apply to the passed UID and PID.
888          *
889          * <p>Passing null reverts to default behavior, which does a real permission check on the
890          * test package.
891          * @param granted One of {@link PackageManager#PERMISSION_GRANTED} or
892          *                {@link PackageManager#PERMISSION_DENIED}.
893          */
setPermission(String permission, int pid, int uid, Integer granted)894         public void setPermission(String permission, int pid, int uid, Integer granted) {
895             final String key = permission + "," + pid + "," + uid;
896             mMockedPermissions.put(key, granted);
897         }
898 
899         @Override
registerReceiverForAllUsers(@ullable BroadcastReceiver receiver, @NonNull IntentFilter filter, @Nullable String broadcastPermission, @Nullable Handler scheduler)900         public Intent registerReceiverForAllUsers(@Nullable BroadcastReceiver receiver,
901                 @NonNull IntentFilter filter, @Nullable String broadcastPermission,
902                 @Nullable Handler scheduler) {
903             // TODO: ensure MultinetworkPolicyTracker's BroadcastReceiver is tested; just returning
904             // null should not pass the test
905             return null;
906         }
907 
908         @Override
sendStickyBroadcast(Intent intent, Bundle options)909         public void sendStickyBroadcast(Intent intent, Bundle options) {
910             // Verify that delivery group policy APIs were used on U.
911             if (mDeps.isAtLeastU() && CONNECTIVITY_ACTION.equals(intent.getAction())) {
912                 final NetworkInfo ni = intent.getParcelableExtra(EXTRA_NETWORK_INFO,
913                         NetworkInfo.class);
914                 try {
915                     verify(mBroadcastOptionsShim).setDeliveryGroupPolicy(
916                             eq(ConstantsShim.DELIVERY_GROUP_POLICY_MOST_RECENT));
917                     verify(mBroadcastOptionsShim).setDeliveryGroupMatchingKey(
918                             eq(CONNECTIVITY_ACTION),
919                             eq(createDeliveryGroupKeyForConnectivityAction(ni)));
920                     verify(mBroadcastOptionsShim).setDeferralPolicy(
921                             eq(ConstantsShim.DEFERRAL_POLICY_UNTIL_ACTIVE));
922                 } catch (UnsupportedApiLevelException e) {
923                     throw new RuntimeException(e);
924                 }
925             }
926             super.sendStickyBroadcast(intent, options);
927         }
928 
929         private final ArrayTrackRecord<Intent>.ReadHead mOrderedBroadcastAsUserHistory =
930                 new ArrayTrackRecord<Intent>().newReadHead();
931 
expectDataActivityBroadcast(int deviceType, boolean isActive, long tsNanos)932         public void expectDataActivityBroadcast(int deviceType, boolean isActive, long tsNanos) {
933             assertNotNull(mOrderedBroadcastAsUserHistory.poll(BROADCAST_TIMEOUT_MS,
934                     intent -> intent.getAction().equals(ACTION_DATA_ACTIVITY_CHANGE)
935                             && intent.getIntExtra(EXTRA_DEVICE_TYPE, -1) == deviceType
936                             && intent.getBooleanExtra(EXTRA_IS_ACTIVE, !isActive) == isActive
937                             && intent.getLongExtra(EXTRA_REALTIME_NS, -1) == tsNanos
938             ));
939         }
940 
941         @Override
sendOrderedBroadcastAsUser(Intent intent, UserHandle user, String receiverPermission, BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData, Bundle initialExtras)942         public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user,
943                 String receiverPermission, BroadcastReceiver resultReceiver,
944                 Handler scheduler, int initialCode, String initialData, Bundle initialExtras) {
945             mOrderedBroadcastAsUserHistory.add(intent);
946         }
947     }
948 
949     // This was only added in the T SDK, but this test needs to build against the R+S SDKs, too.
toSdkSandboxUid(int appUid)950     private static int toSdkSandboxUid(int appUid) {
951         final int firstSdkSandboxUid = 20000;
952         return appUid + (firstSdkSandboxUid - Process.FIRST_APPLICATION_UID);
953     }
954 
955     // Create the list of ranges for the primary user (User 0), excluding excludedUids.
intRangesPrimaryExcludingUids(List<Integer> excludedUids)956     private static List<Range<Integer>> intRangesPrimaryExcludingUids(List<Integer> excludedUids) {
957         final List<Integer> excludedUidsList = new ArrayList<>(excludedUids);
958         // Uid 0 is always excluded
959         if (!excludedUidsList.contains(0)) {
960             excludedUidsList.add(0);
961         }
962         return intRangesExcludingUids(PRIMARY_USER, excludedUidsList);
963     }
964 
intRangesExcludingUids(int userId, List<Integer> excludedAppIds)965     private static List<Range<Integer>> intRangesExcludingUids(int userId,
966             List<Integer> excludedAppIds) {
967         final List<Integer> excludedUids = CollectionUtils.map(excludedAppIds,
968                 appId -> UserHandle.getUid(userId, appId));
969         final int userBase = userId * UserHandle.PER_USER_RANGE;
970         final int maxUid = userBase + UserHandle.PER_USER_RANGE - 1;
971 
972         int start = userBase;
973         Collections.sort(excludedUids);
974         final List<Range<Integer>> ranges = new ArrayList<>();
975         for (int excludedUid : excludedUids) {
976             if (excludedUid == start) {
977                 start++;
978             } else {
979                 ranges.add(new Range<>(start, excludedUid - 1));
980                 start = excludedUid + 1;
981             }
982         }
983         if (start <= maxUid) {
984             ranges.add(new Range<>(start, maxUid));
985         }
986 
987         return ranges;
988     }
989 
waitForIdle()990     private void waitForIdle() {
991         HandlerUtils.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
992         waitForIdle(mCellAgent, TIMEOUT_MS);
993         waitForIdle(mWiFiAgent, TIMEOUT_MS);
994         waitForIdle(mEthernetAgent, TIMEOUT_MS);
995         HandlerUtils.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
996         HandlerUtils.waitForIdle(ConnectivityThread.get(), TIMEOUT_MS);
997     }
998 
waitForIdle(TestNetworkAgentWrapper agent, long timeoutMs)999     private void waitForIdle(TestNetworkAgentWrapper agent, long timeoutMs) {
1000         if (agent == null) {
1001             return;
1002         }
1003         agent.waitForIdle(timeoutMs);
1004     }
1005 
1006     @Test
testWaitForIdle()1007     public void testWaitForIdle() throws Exception {
1008         final int attempts = 50;  // Causes the test to take about 200ms on bullhead-eng.
1009 
1010         // Tests that waitForIdle returns immediately if the service is already idle.
1011         for (int i = 0; i < attempts; i++) {
1012             waitForIdle();
1013         }
1014 
1015         // Bring up a network that we can use to send messages to ConnectivityService.
1016         ExpectedBroadcast b = expectConnectivityAction(TYPE_WIFI, DetailedState.CONNECTED);
1017         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
1018         mWiFiAgent.connect(false);
1019         b.expectBroadcast();
1020         Network n = mWiFiAgent.getNetwork();
1021         assertNotNull(n);
1022 
1023         // Tests that calling waitForIdle waits for messages to be processed.
1024         for (int i = 0; i < attempts; i++) {
1025             mWiFiAgent.setSignalStrength(i);
1026             waitForIdle();
1027             assertEquals(i, mCm.getNetworkCapabilities(n).getSignalStrength());
1028         }
1029     }
1030 
1031     // This test has an inherent race condition in it, and cannot be enabled for continuous testing
1032     // or presubmit tests. It is kept for manual runs and documentation purposes.
1033     @Ignore
verifyThatNotWaitingForIdleCausesRaceConditions()1034     public void verifyThatNotWaitingForIdleCausesRaceConditions() throws Exception {
1035         // Bring up a network that we can use to send messages to ConnectivityService.
1036         ExpectedBroadcast b = expectConnectivityAction(TYPE_WIFI, DetailedState.CONNECTED);
1037         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
1038         mWiFiAgent.connect(false);
1039         b.expectBroadcast();
1040         Network n = mWiFiAgent.getNetwork();
1041         assertNotNull(n);
1042 
1043         // Ensure that not calling waitForIdle causes a race condition.
1044         final int attempts = 50;  // Causes the test to take about 200ms on bullhead-eng.
1045         for (int i = 0; i < attempts; i++) {
1046             mWiFiAgent.setSignalStrength(i);
1047             if (i != mCm.getNetworkCapabilities(n).getSignalStrength()) {
1048                 // We hit a race condition, as expected. Pass the test.
1049                 return;
1050             }
1051         }
1052 
1053         // No race? There is a bug in this test.
1054         fail("expected race condition at least once in " + attempts + " attempts");
1055     }
1056 
1057     private class TestNetworkAgentWrapper extends NetworkAgentWrapper {
1058         // Note : Please do not add any new instrumentation here. If you need new instrumentation,
1059         // please add it in CSAgentWrapper and use subclasses of CSTest instead of adding more
1060         // tools in ConnectivityServiceTest.
1061         private static final int VALIDATION_RESULT_INVALID = 0;
1062 
1063         private static final long DATA_STALL_TIMESTAMP = 10L;
1064         private static final int DATA_STALL_DETECTION_METHOD = 1;
1065 
1066         private INetworkMonitor mNetworkMonitor;
1067         private INetworkMonitorCallbacks mNmCallbacks;
1068         private int mNmValidationResult = VALIDATION_RESULT_INVALID;
1069         private int mProbesCompleted;
1070         private int mProbesSucceeded;
1071         private String mNmValidationRedirectUrl = null;
1072         private boolean mNmProvNotificationRequested = false;
1073 
1074         private final ConditionVariable mNetworkStatusReceived = new ConditionVariable();
1075         // Contains the redirectUrl from networkStatus(). Before reading, wait for
1076         // mNetworkStatusReceived.
1077         private String mRedirectUrl;
1078 
TestNetworkAgentWrapper(int transport)1079         TestNetworkAgentWrapper(int transport) throws Exception {
1080             this(transport, new LinkProperties(), null /* ncTemplate */, null /* provider */, null);
1081         }
1082 
TestNetworkAgentWrapper(int transport, LinkProperties linkProperties)1083         TestNetworkAgentWrapper(int transport, LinkProperties linkProperties)
1084                 throws Exception {
1085             this(transport, linkProperties, null /* ncTemplate */, null /* provider */, null);
1086         }
1087 
TestNetworkAgentWrapper(int transport, LinkProperties linkProperties, NetworkCapabilities ncTemplate)1088         private TestNetworkAgentWrapper(int transport, LinkProperties linkProperties,
1089                 NetworkCapabilities ncTemplate) throws Exception {
1090             this(transport, linkProperties, ncTemplate, null /* provider */, null);
1091         }
1092 
TestNetworkAgentWrapper(int transport, LinkProperties linkProperties, NetworkCapabilities ncTemplate, NetworkProvider provider)1093         private TestNetworkAgentWrapper(int transport, LinkProperties linkProperties,
1094                 NetworkCapabilities ncTemplate, NetworkProvider provider) throws Exception {
1095             this(transport, linkProperties, ncTemplate, provider /* provider */, null);
1096         }
1097 
TestNetworkAgentWrapper(int transport, NetworkAgentWrapper.Callbacks callbacks)1098         private TestNetworkAgentWrapper(int transport, NetworkAgentWrapper.Callbacks callbacks)
1099                 throws Exception {
1100             this(transport, new LinkProperties(), null /* ncTemplate */, null /* provider */,
1101                     callbacks);
1102         }
1103 
TestNetworkAgentWrapper(int transport, LinkProperties linkProperties, NetworkCapabilities ncTemplate, NetworkProvider provider, NetworkAgentWrapper.Callbacks callbacks)1104         private TestNetworkAgentWrapper(int transport, LinkProperties linkProperties,
1105                 NetworkCapabilities ncTemplate, NetworkProvider provider,
1106                 NetworkAgentWrapper.Callbacks callbacks) throws Exception {
1107             super(transport, linkProperties, ncTemplate, provider, callbacks, mServiceContext);
1108             mCreatedAgents.add(this);
1109 
1110             // Waits for the NetworkAgent to be registered, which includes the creation of the
1111             // NetworkMonitor.
1112             waitForIdle(TIMEOUT_MS);
1113             HandlerUtils.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
1114             HandlerUtils.waitForIdle(ConnectivityThread.get(), TIMEOUT_MS);
1115         }
1116 
1117         class TestInstrumentedNetworkAgent extends InstrumentedNetworkAgent {
TestInstrumentedNetworkAgent(NetworkAgentWrapper wrapper, LinkProperties lp, NetworkAgentConfig nac, NetworkProvider provider)1118             TestInstrumentedNetworkAgent(NetworkAgentWrapper wrapper, LinkProperties lp,
1119                     NetworkAgentConfig nac, NetworkProvider provider) {
1120                 super(wrapper, lp, nac, provider);
1121             }
1122 
1123             @Override
networkStatus(int status, String redirectUrl)1124             public void networkStatus(int status, String redirectUrl) {
1125                 mRedirectUrl = redirectUrl;
1126                 mNetworkStatusReceived.open();
1127             }
1128 
1129         }
1130 
1131         @Override
makeNetworkAgent(LinkProperties linkProperties, NetworkAgentConfig nac, NetworkProvider provider)1132         protected InstrumentedNetworkAgent makeNetworkAgent(LinkProperties linkProperties,
1133                 NetworkAgentConfig nac, NetworkProvider provider) throws Exception {
1134             mNetworkMonitor = mock(INetworkMonitor.class);
1135 
1136             final Answer validateAnswer = inv -> {
1137                 new Thread(ignoreExceptions(this::onValidationRequested)).start();
1138                 return null;
1139             };
1140 
1141             doAnswer(validateAnswer).when(mNetworkMonitor).notifyNetworkConnected(any(), any());
1142             doAnswer(validateAnswer).when(mNetworkMonitor).notifyNetworkConnectedParcel(any());
1143             doAnswer(validateAnswer).when(mNetworkMonitor).forceReevaluation(anyInt());
1144 
1145             final ArgumentCaptor<Network> nmNetworkCaptor = ArgumentCaptor.forClass(Network.class);
1146             final ArgumentCaptor<INetworkMonitorCallbacks> nmCbCaptor =
1147                     ArgumentCaptor.forClass(INetworkMonitorCallbacks.class);
1148             doNothing().when(mNetworkStack).makeNetworkMonitor(
1149                     nmNetworkCaptor.capture(),
1150                     any() /* name */,
1151                     nmCbCaptor.capture());
1152 
1153             final InstrumentedNetworkAgent na =
1154                     new TestInstrumentedNetworkAgent(this, linkProperties, nac, provider);
1155 
1156             assertEquals(na.getNetwork().netId, nmNetworkCaptor.getValue().netId);
1157             mNmCallbacks = nmCbCaptor.getValue();
1158 
1159             mNmCallbacks.onNetworkMonitorCreated(mNetworkMonitor);
1160 
1161             return na;
1162         }
1163 
onValidationRequested()1164         private void onValidationRequested() throws Exception {
1165             if (mDeps.isAtLeastT()) {
1166                 verify(mNetworkMonitor).notifyNetworkConnectedParcel(any());
1167             } else {
1168                 verify(mNetworkMonitor).notifyNetworkConnected(any(), any());
1169             }
1170             if (mNmProvNotificationRequested
1171                     && ((mNmValidationResult & NETWORK_VALIDATION_RESULT_VALID) != 0)) {
1172                 mNmCallbacks.hideProvisioningNotification();
1173                 mNmProvNotificationRequested = false;
1174             }
1175 
1176             mNmCallbacks.notifyProbeStatusChanged(mProbesCompleted, mProbesSucceeded);
1177             final NetworkTestResultParcelable p = new NetworkTestResultParcelable();
1178             p.result = mNmValidationResult;
1179             p.probesAttempted = mProbesCompleted;
1180             p.probesSucceeded = mProbesSucceeded;
1181             p.redirectUrl = mNmValidationRedirectUrl;
1182             p.timestampMillis = TIMESTAMP;
1183             mNmCallbacks.notifyNetworkTestedWithExtras(p);
1184 
1185             if (mNmValidationRedirectUrl != null) {
1186                 mNmCallbacks.showProvisioningNotification(
1187                         "test_provisioning_notif_action", TEST_PACKAGE_NAME);
1188                 mNmProvNotificationRequested = true;
1189             }
1190         }
1191 
1192         /**
1193          * Connect without adding any internet capability.
1194          */
connectWithoutInternet()1195         public void connectWithoutInternet() {
1196             super.connect();
1197         }
1198 
1199         /**
1200          * Transition this NetworkAgent to CONNECTED state with NET_CAPABILITY_INTERNET.
1201          * @param validated Indicate if network should pretend to be validated.
1202          */
connect(boolean validated)1203         public void connect(boolean validated) {
1204             connect(validated, true, false /* privateDnsProbeSent */);
1205         }
1206 
1207         /**
1208          * Transition this NetworkAgent to CONNECTED state.
1209          *
1210          * @param validated Indicate if network should pretend to be validated.
1211          *                  Note that if this is true, this method will mock the NetworkMonitor
1212          *                  probes to pretend the network is invalid after it validated once,
1213          *                  so that subsequent attempts (with mNetworkMonitor.forceReevaluation)
1214          *                  will fail unless setNetworkValid is called again manually.
1215          * @param hasInternet Indicate if network should pretend to have NET_CAPABILITY_INTERNET.
1216          * @param privateDnsProbeSent whether the private DNS probe should be considered to have
1217          *                            been sent, assuming |validated| is true.
1218          *                            If |validated| is false, |privateDnsProbeSent| is not used.
1219          *                            If |validated| is true and |privateDnsProbeSent| is false,
1220          *                            the probe has not been sent.
1221          *                            If |validated| is true and |privateDnsProbeSent| is true,
1222          *                            the probe has been sent and has succeeded. When the NM probes
1223          *                            are mocked to be invalid, private DNS is the reason this
1224          *                            network is invalid ; see @param |validated|.
1225          */
connect(boolean validated, boolean hasInternet, boolean privateDnsProbeSent)1226         public void connect(boolean validated, boolean hasInternet,
1227                 boolean privateDnsProbeSent) {
1228             final ConditionVariable validatedCv = new ConditionVariable();
1229             final ConditionVariable capsChangedCv = new ConditionVariable();
1230             final NetworkRequest request = new NetworkRequest.Builder()
1231                     .addTransportType(getNetworkCapabilities().getTransportTypes()[0])
1232                     .clearCapabilities()
1233                     .build();
1234             if (validated) {
1235                 setNetworkValid(privateDnsProbeSent);
1236             }
1237             final NetworkCallback callback = new NetworkCallback() {
1238                 public void onCapabilitiesChanged(Network network,
1239                         NetworkCapabilities networkCapabilities) {
1240                     if (network.equals(getNetwork())) {
1241                         capsChangedCv.open();
1242                         if (networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED)) {
1243                             validatedCv.open();
1244                         }
1245                     }
1246                 }
1247             };
1248             mCm.registerNetworkCallback(request, callback);
1249 
1250             if (hasInternet) {
1251                 addCapability(NET_CAPABILITY_INTERNET);
1252             }
1253 
1254             connectWithoutInternet();
1255             waitFor(capsChangedCv);
1256 
1257             if (validated) {
1258                 // Wait for network to validate.
1259                 waitFor(validatedCv);
1260                 setNetworkInvalid(privateDnsProbeSent);
1261             }
1262             mCm.unregisterNetworkCallback(callback);
1263         }
1264 
connectWithCaptivePortal(String redirectUrl, boolean privateDnsProbeSent)1265         public void connectWithCaptivePortal(String redirectUrl,
1266                 boolean privateDnsProbeSent) {
1267             setNetworkPortal(redirectUrl, privateDnsProbeSent);
1268             connect(false, true /* hasInternet */, privateDnsProbeSent);
1269         }
1270 
connectWithPartialConnectivity()1271         public void connectWithPartialConnectivity() {
1272             setNetworkPartial();
1273             connect(false);
1274         }
1275 
connectWithPartialValidConnectivity(boolean privateDnsProbeSent)1276         public void connectWithPartialValidConnectivity(boolean privateDnsProbeSent) {
1277             setNetworkPartialValid(privateDnsProbeSent);
1278             connect(false, true /* hasInternet */, privateDnsProbeSent);
1279         }
1280 
setNetworkValid(boolean privateDnsProbeSent)1281         void setNetworkValid(boolean privateDnsProbeSent) {
1282             mNmValidationResult = NETWORK_VALIDATION_RESULT_VALID;
1283             mNmValidationRedirectUrl = null;
1284             int probesSucceeded = NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_HTTPS;
1285             if (privateDnsProbeSent) {
1286                 probesSucceeded |= NETWORK_VALIDATION_PROBE_PRIVDNS;
1287             }
1288             // The probesCompleted equals to probesSucceeded for the case of valid network, so put
1289             // the same value into two different parameter of the method.
1290             setProbesStatus(probesSucceeded, probesSucceeded);
1291         }
1292 
setNetworkInvalid(boolean invalidBecauseOfPrivateDns)1293         void setNetworkInvalid(boolean invalidBecauseOfPrivateDns) {
1294             mNmValidationResult = VALIDATION_RESULT_INVALID;
1295             mNmValidationRedirectUrl = null;
1296             int probesCompleted = NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_HTTPS
1297                     | NETWORK_VALIDATION_PROBE_HTTP;
1298             int probesSucceeded = 0;
1299             // If |invalidBecauseOfPrivateDns| is true, it means the network is invalid because
1300             // NetworkMonitor tried to validate the private DNS but failed. Therefore it
1301             // didn't get a chance to try the HTTP probe.
1302             if (invalidBecauseOfPrivateDns) {
1303                 probesCompleted &= ~NETWORK_VALIDATION_PROBE_HTTP;
1304                 probesSucceeded = probesCompleted;
1305                 probesCompleted |= NETWORK_VALIDATION_PROBE_PRIVDNS;
1306             }
1307             setProbesStatus(probesCompleted, probesSucceeded);
1308         }
1309 
setNetworkPortal(String redirectUrl, boolean privateDnsProbeSent)1310         void setNetworkPortal(String redirectUrl, boolean privateDnsProbeSent) {
1311             setNetworkInvalid(privateDnsProbeSent);
1312             mNmValidationRedirectUrl = redirectUrl;
1313             // Suppose the portal is found when NetworkMonitor probes NETWORK_VALIDATION_PROBE_HTTP
1314             // in the beginning, so the NETWORK_VALIDATION_PROBE_HTTPS hasn't probed yet.
1315             int probesCompleted = NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_HTTP;
1316             int probesSucceeded = VALIDATION_RESULT_INVALID;
1317             if (privateDnsProbeSent) {
1318                 probesCompleted |= NETWORK_VALIDATION_PROBE_PRIVDNS;
1319             }
1320             setProbesStatus(probesCompleted, probesSucceeded);
1321         }
1322 
setNetworkPartial()1323         void setNetworkPartial() {
1324             mNmValidationResult = NETWORK_VALIDATION_RESULT_PARTIAL;
1325             mNmValidationRedirectUrl = null;
1326             int probesCompleted = NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_HTTPS
1327                     | NETWORK_VALIDATION_PROBE_FALLBACK;
1328             int probesSucceeded = NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_FALLBACK;
1329             setProbesStatus(probesCompleted, probesSucceeded);
1330         }
1331 
setNetworkPartialValid(boolean privateDnsProbeSent)1332         void setNetworkPartialValid(boolean privateDnsProbeSent) {
1333             setNetworkPartial();
1334             mNmValidationResult |= NETWORK_VALIDATION_RESULT_VALID;
1335             mNmValidationRedirectUrl = null;
1336             int probesCompleted = NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_HTTPS
1337                     | NETWORK_VALIDATION_PROBE_HTTP;
1338             int probesSucceeded = NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_HTTP;
1339             // Assume the partial network cannot pass the private DNS validation as well, so only
1340             // add NETWORK_VALIDATION_PROBE_DNS in probesCompleted but not probesSucceeded.
1341             if (privateDnsProbeSent) {
1342                 probesCompleted |= NETWORK_VALIDATION_PROBE_PRIVDNS;
1343             }
1344             setProbesStatus(probesCompleted, probesSucceeded);
1345         }
1346 
setProbesStatus(int probesCompleted, int probesSucceeded)1347         void setProbesStatus(int probesCompleted, int probesSucceeded) {
1348             mProbesCompleted = probesCompleted;
1349             mProbesSucceeded = probesSucceeded;
1350         }
1351 
notifyCapportApiDataChanged(CaptivePortalData data)1352         void notifyCapportApiDataChanged(CaptivePortalData data) {
1353             try {
1354                 mNmCallbacks.notifyCaptivePortalDataChanged(data);
1355             } catch (RemoteException e) {
1356                 throw new AssertionError("This cannot happen", e);
1357             }
1358         }
1359 
waitForRedirectUrl()1360         public String waitForRedirectUrl() {
1361             assertTrue(mNetworkStatusReceived.block(TIMEOUT_MS));
1362             return mRedirectUrl;
1363         }
1364 
expectDisconnected()1365         public void expectDisconnected() {
1366             expectDisconnected(TIMEOUT_MS);
1367         }
1368 
expectPreventReconnectReceived()1369         public void expectPreventReconnectReceived() {
1370             expectPreventReconnectReceived(TIMEOUT_MS);
1371         }
1372 
notifyDataStallSuspected()1373         void notifyDataStallSuspected() throws Exception {
1374             final DataStallReportParcelable p = new DataStallReportParcelable();
1375             p.detectionMethod = DATA_STALL_DETECTION_METHOD;
1376             p.timestampMillis = DATA_STALL_TIMESTAMP;
1377             mNmCallbacks.notifyDataStallSuspected(p);
1378         }
1379     }
1380 
1381     /**
1382      * A NetworkFactory that allows to wait until any in-flight NetworkRequest add or remove
1383      * operations have been processed and test for them.
1384      */
1385     private static class MockNetworkFactory extends NetworkFactory {
1386         // Note : Please do not add any new instrumentation here. If you need new instrumentation,
1387         // please add it in CSTest and use subclasses of CSTest instead of adding more
1388         // tools in ConnectivityServiceTest.
1389         private final AtomicBoolean mNetworkStarted = new AtomicBoolean(false);
1390 
1391         static class RequestEntry {
1392             @NonNull
1393             public final NetworkRequest request;
1394 
RequestEntry(@onNull final NetworkRequest request)1395             RequestEntry(@NonNull final NetworkRequest request) {
1396                 this.request = request;
1397             }
1398 
1399             static final class Add extends RequestEntry {
Add(@onNull final NetworkRequest request)1400                 Add(@NonNull final NetworkRequest request) {
1401                     super(request);
1402                 }
1403             }
1404 
1405             static final class Remove extends RequestEntry {
Remove(@onNull final NetworkRequest request)1406                 Remove(@NonNull final NetworkRequest request) {
1407                     super(request);
1408                 }
1409             }
1410 
1411             @Override
toString()1412             public String toString() {
1413                 return "RequestEntry [ " + getClass().getName() + " : " + request + " ]";
1414             }
1415         }
1416 
1417         // History of received requests adds and removes.
1418         private final ArrayTrackRecord<RequestEntry>.ReadHead mRequestHistory =
1419                 new ArrayTrackRecord<RequestEntry>().newReadHead();
1420 
failIfNull(@ullable final T obj, @Nullable final String message)1421         private static <T> T failIfNull(@Nullable final T obj, @Nullable final String message) {
1422             if (null == obj) fail(null != message ? message : "Must not be null");
1423             return obj;
1424         }
1425 
expectRequestAdd()1426         public RequestEntry.Add expectRequestAdd() {
1427             return failIfNull((RequestEntry.Add) mRequestHistory.poll(TIMEOUT_MS,
1428                     it -> it instanceof RequestEntry.Add), "Expected request add");
1429         }
1430 
expectRequestAdds(final int count)1431         public void expectRequestAdds(final int count) {
1432             for (int i = count; i > 0; --i) {
1433                 expectRequestAdd();
1434             }
1435         }
1436 
expectRequestRemove()1437         public RequestEntry.Remove expectRequestRemove() {
1438             return failIfNull((RequestEntry.Remove) mRequestHistory.poll(TIMEOUT_MS,
1439                     it -> it instanceof RequestEntry.Remove), "Expected request remove");
1440         }
1441 
expectRequestRemoves(final int count)1442         public void expectRequestRemoves(final int count) {
1443             for (int i = count; i > 0; --i) {
1444                 expectRequestRemove();
1445             }
1446         }
1447 
1448         // Used to collect the networks requests managed by this factory. This is a duplicate of
1449         // the internal information stored in the NetworkFactory (which is private).
1450         private SparseArray<NetworkRequest> mNetworkRequests = new SparseArray<>();
1451         private final HandlerThread mHandlerSendingRequests;
1452 
MockNetworkFactory(Looper looper, Context context, String logTag, NetworkCapabilities filter, HandlerThread threadSendingRequests)1453         public MockNetworkFactory(Looper looper, Context context, String logTag,
1454                 NetworkCapabilities filter, HandlerThread threadSendingRequests) {
1455             super(looper, context, logTag, filter);
1456             mHandlerSendingRequests = threadSendingRequests;
1457         }
1458 
getMyRequestCount()1459         public int getMyRequestCount() {
1460             return getRequestCount();
1461         }
1462 
startNetwork()1463         protected void startNetwork() {
1464             mNetworkStarted.set(true);
1465         }
1466 
stopNetwork()1467         protected void stopNetwork() {
1468             mNetworkStarted.set(false);
1469         }
1470 
getMyStartRequested()1471         public boolean getMyStartRequested() {
1472             return mNetworkStarted.get();
1473         }
1474 
1475 
1476         @Override
needNetworkFor(NetworkRequest request)1477         protected void needNetworkFor(NetworkRequest request) {
1478             mNetworkRequests.put(request.requestId, request);
1479             super.needNetworkFor(request);
1480             mRequestHistory.add(new RequestEntry.Add(request));
1481         }
1482 
1483         @Override
releaseNetworkFor(NetworkRequest request)1484         protected void releaseNetworkFor(NetworkRequest request) {
1485             mNetworkRequests.remove(request.requestId);
1486             super.releaseNetworkFor(request);
1487             mRequestHistory.add(new RequestEntry.Remove(request));
1488         }
1489 
assertRequestCountEquals(final int count)1490         public void assertRequestCountEquals(final int count) {
1491             assertEquals(count, getMyRequestCount());
1492         }
1493 
1494         // Trigger releasing the request as unfulfillable
triggerUnfulfillable(NetworkRequest r)1495         public void triggerUnfulfillable(NetworkRequest r) {
1496             super.releaseRequestAsUnfulfillableByAnyFactory(r);
1497         }
1498 
assertNoRequestChanged()1499         public void assertNoRequestChanged() {
1500             // Make sure there are no remaining requests unaccounted for.
1501             HandlerUtils.waitForIdle(mHandlerSendingRequests, TIMEOUT_MS);
1502             assertNull(mRequestHistory.poll(0, r -> true));
1503         }
1504     }
1505 
uidRangesForUids(int... uids)1506     private Set<UidRange> uidRangesForUids(int... uids) {
1507         final ArraySet<UidRange> ranges = new ArraySet<>();
1508         for (final int uid : uids) {
1509             ranges.add(new UidRange(uid, uid));
1510         }
1511         return ranges;
1512     }
1513 
uidRangesForUids(Collection<Integer> uids)1514     private Set<UidRange> uidRangesForUids(Collection<Integer> uids) {
1515         return uidRangesForUids(CollectionUtils.toIntArray(uids));
1516     }
1517 
1518     // Helper class to mock vpn interaction.
1519     private class MockVpn implements TestableNetworkCallback.HasNetwork {
1520         // Note : Please do not add any new instrumentation here. If you need new instrumentation,
1521         // please add it in CSTest and use subclasses of CSTest instead of adding more
1522         // tools in ConnectivityServiceTest.
1523 
1524         // Careful ! This is different from mNetworkAgent, because MockNetworkAgent does
1525         // not inherit from NetworkAgent.
1526         private TestNetworkAgentWrapper mMockNetworkAgent;
1527         // Initialize a stored NetworkCapabilities following the defaults of VPN. The TransportInfo
1528         // should at least be updated to a valid VPN type before usage, see registerAgent(...).
1529         private NetworkCapabilities mNetworkCapabilities = new NetworkCapabilities.Builder()
1530                 .addTransportType(NetworkCapabilities.TRANSPORT_VPN)
1531                 .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN)
1532                 .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED)
1533                 .setTransportInfo(new VpnTransportInfo(
1534                         VpnManager.TYPE_VPN_NONE,
1535                         null /* sessionId */,
1536                         false /* bypassable */,
1537                         false /* longLivedTcpConnectionsExpensive */))
1538                 .build();
1539         private boolean mAgentRegistered = false;
1540 
1541         private int mVpnType = VpnManager.TYPE_VPN_SERVICE;
1542         private String mSessionKey;
1543 
setUids(Set<UidRange> uids)1544         public void setUids(Set<UidRange> uids) {
1545             mNetworkCapabilities.setUids(UidRange.toIntRanges(uids));
1546             if (mAgentRegistered) {
1547                 mMockNetworkAgent.setNetworkCapabilities(mNetworkCapabilities, true);
1548             }
1549         }
1550 
setVpnType(int vpnType)1551         public void setVpnType(int vpnType) {
1552             mVpnType = vpnType;
1553         }
1554 
getNetwork()1555         public Network getNetwork() {
1556             return (mMockNetworkAgent == null) ? null : mMockNetworkAgent.getNetwork();
1557         }
1558 
getNetworkAgentConfig()1559         public NetworkAgentConfig getNetworkAgentConfig() {
1560             return null == mMockNetworkAgent ? null : mMockNetworkAgent.getNetworkAgentConfig();
1561         }
1562 
getActiveVpnType()1563         public int getActiveVpnType() {
1564             return mVpnType;
1565         }
1566 
makeLinkProperties()1567         private LinkProperties makeLinkProperties() {
1568             final LinkProperties lp = new LinkProperties();
1569             lp.setInterfaceName(VPN_IFNAME);
1570             return lp;
1571         }
1572 
registerAgent(boolean isAlwaysMetered, Set<UidRange> uids, LinkProperties lp)1573         private void registerAgent(boolean isAlwaysMetered, Set<UidRange> uids, LinkProperties lp)
1574                 throws Exception {
1575             if (mAgentRegistered) throw new IllegalStateException("already registered");
1576             final String session = "MySession12345";
1577             setUids(uids);
1578             if (!isAlwaysMetered) mNetworkCapabilities.addCapability(NET_CAPABILITY_NOT_METERED);
1579             mNetworkCapabilities.setTransportInfo(new VpnTransportInfo(getActiveVpnType(),
1580                     session));
1581             mMockNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN, lp,
1582                     mNetworkCapabilities);
1583             mMockNetworkAgent.waitForIdle(TIMEOUT_MS);
1584 
1585             verify(mMockNetd, times(1)).networkAddUidRangesParcel(
1586                     new NativeUidRangeConfig(mMockVpn.getNetwork().getNetId(),
1587                             toUidRangeStableParcels(uids), PREFERENCE_ORDER_VPN));
1588             verify(mMockNetd, never()).networkRemoveUidRangesParcel(argThat(config ->
1589                     mMockVpn.getNetwork().getNetId() == config.netId
1590                             && PREFERENCE_ORDER_VPN == config.subPriority));
1591             mAgentRegistered = true;
1592             verify(mMockNetd).networkCreate(nativeNetworkConfigVpn(getNetwork().netId,
1593                     !mMockNetworkAgent.isBypassableVpn(), mVpnType));
1594             mNetworkCapabilities.set(mMockNetworkAgent.getNetworkCapabilities());
1595         }
1596 
registerAgent(Set<UidRange> uids)1597         private void registerAgent(Set<UidRange> uids) throws Exception {
1598             registerAgent(false /* isAlwaysMetered */, uids, makeLinkProperties());
1599         }
1600 
connect(boolean validated, boolean hasInternet, boolean privateDnsProbeSent)1601         private void connect(boolean validated, boolean hasInternet,
1602                 boolean privateDnsProbeSent) {
1603             mMockNetworkAgent.connect(validated, hasInternet, privateDnsProbeSent);
1604         }
1605 
connect(boolean validated)1606         private void connect(boolean validated) {
1607             mMockNetworkAgent.connect(validated);
1608         }
1609 
getAgent()1610         private TestNetworkAgentWrapper getAgent() {
1611             return mMockNetworkAgent;
1612         }
1613 
setOwnerAndAdminUid(int uid)1614         private void setOwnerAndAdminUid(int uid) throws Exception {
1615             mNetworkCapabilities.setOwnerUid(uid);
1616             mNetworkCapabilities.setAdministratorUids(new int[]{uid});
1617         }
1618 
establish(LinkProperties lp, int uid, Set<UidRange> ranges, boolean validated, boolean hasInternet, boolean privateDnsProbeSent)1619         public void establish(LinkProperties lp, int uid, Set<UidRange> ranges, boolean validated,
1620                 boolean hasInternet, boolean privateDnsProbeSent) throws Exception {
1621             setOwnerAndAdminUid(uid);
1622             registerAgent(false, ranges, lp);
1623             connect(validated, hasInternet, privateDnsProbeSent);
1624             waitForIdle();
1625         }
1626 
establish(LinkProperties lp, int uid, Set<UidRange> ranges)1627         public void establish(LinkProperties lp, int uid, Set<UidRange> ranges) throws Exception {
1628             establish(lp, uid, ranges, true, true, false);
1629         }
1630 
establishForMyUid(LinkProperties lp)1631         public void establishForMyUid(LinkProperties lp) throws Exception {
1632             final int uid = Process.myUid();
1633             establish(lp, uid, uidRangesForUids(uid), true, true, false);
1634         }
1635 
establishForMyUid(boolean validated, boolean hasInternet, boolean privateDnsProbeSent)1636         public void establishForMyUid(boolean validated, boolean hasInternet,
1637                 boolean privateDnsProbeSent) throws Exception {
1638             final int uid = Process.myUid();
1639             establish(makeLinkProperties(), uid, uidRangesForUids(uid), validated, hasInternet,
1640                     privateDnsProbeSent);
1641         }
1642 
establishForMyUid()1643         public void establishForMyUid() throws Exception {
1644             establishForMyUid(makeLinkProperties());
1645         }
1646 
sendLinkProperties(LinkProperties lp)1647         public void sendLinkProperties(LinkProperties lp) {
1648             mMockNetworkAgent.sendLinkProperties(lp);
1649         }
1650 
disconnect()1651         public void disconnect() {
1652             if (mMockNetworkAgent != null) {
1653                 mMockNetworkAgent.disconnect();
1654             }
1655             mAgentRegistered = false;
1656             setUids(null);
1657             // Remove NET_CAPABILITY_INTERNET or MockNetworkAgent will refuse to connect later on.
1658             mNetworkCapabilities.removeCapability(NET_CAPABILITY_INTERNET);
1659         }
1660 
startLegacyVpn()1661         private void startLegacyVpn() {
1662             // Do nothing.
1663         }
1664 
1665         // Mock the interaction of IkeV2VpnRunner start. In the context of ConnectivityService,
1666         // setVpnDefaultForUids() is the main interaction and a sessionKey is stored.
startPlatformVpn()1667         private void startPlatformVpn() {
1668             mSessionKey = UUID.randomUUID().toString();
1669             // Assuming no disallowed applications
1670             final Set<Range<Integer>> ranges = UidRange.toIntRanges(Set.of(PRIMARY_UIDRANGE));
1671             mCm.setVpnDefaultForUids(mSessionKey, ranges);
1672             // Wait for vpn network preference updates.
1673             waitForIdle();
1674         }
1675 
startLegacyVpnPrivileged(boolean isIkev2Vpn)1676         public void startLegacyVpnPrivileged(boolean isIkev2Vpn) {
1677             if (isIkev2Vpn) {
1678                 startPlatformVpn();
1679             } else {
1680                 startLegacyVpn();
1681             }
1682         }
1683 
stopVpnRunnerPrivileged()1684         public void stopVpnRunnerPrivileged() {
1685             if (mSessionKey != null) {
1686                 // Clear vpn network preference.
1687                 mCm.setVpnDefaultForUids(mSessionKey, Collections.EMPTY_LIST);
1688                 mSessionKey = null;
1689             }
1690             disconnect();
1691         }
1692 
setUnderlyingNetworks(@ullable Network[] networks)1693         public boolean setUnderlyingNetworks(@Nullable Network[] networks) {
1694             if (!mAgentRegistered) return false;
1695             mMockNetworkAgent.setUnderlyingNetworks(
1696                     (networks == null) ? null : Arrays.asList(networks));
1697             return true;
1698         }
1699     }
1700 
toUidRangeStableParcels(final @NonNull Set<UidRange> ranges)1701     private UidRangeParcel[] toUidRangeStableParcels(final @NonNull Set<UidRange> ranges) {
1702         return ranges.stream().map(
1703                 r -> new UidRangeParcel(r.start, r.stop)).toArray(UidRangeParcel[]::new);
1704     }
1705 
intToUidRangeStableParcels(final @NonNull Set<Integer> ranges)1706     private UidRangeParcel[] intToUidRangeStableParcels(final @NonNull Set<Integer> ranges) {
1707         return ranges.stream().map(r -> new UidRangeParcel(r, r)).toArray(UidRangeParcel[]::new);
1708     }
1709 
intToUidRangeStableParcels( final @NonNull List<Range<Integer>> ranges)1710     private static UidRangeParcel[] intToUidRangeStableParcels(
1711             final @NonNull List<Range<Integer>> ranges) {
1712         return ranges.stream().map(
1713                 r -> new UidRangeParcel(r.getLower(), r.getUpper())).toArray(UidRangeParcel[]::new);
1714     }
1715 
assertVpnTransportInfo(NetworkCapabilities nc, int type)1716     private void assertVpnTransportInfo(NetworkCapabilities nc, int type) {
1717         assertNotNull(nc);
1718         final TransportInfo ti = nc.getTransportInfo();
1719         assertTrue("VPN TransportInfo is not a VpnTransportInfo: " + ti,
1720                 ti instanceof VpnTransportInfo);
1721         assertEquals(type, ((VpnTransportInfo) ti).getType());
1722 
1723     }
1724 
processBroadcast(Intent intent)1725     private void processBroadcast(Intent intent) {
1726         mServiceContext.sendBroadcast(intent);
1727         waitForIdle();
1728     }
1729 
mockUidNetworkingBlocked()1730     private void mockUidNetworkingBlocked() {
1731         doAnswer(i -> isUidBlocked(mBlockedReasons, i.getArgument(1))
1732         ).when(mNetworkPolicyManager).isUidNetworkingBlocked(anyInt(), anyBoolean());
1733         doAnswer(i -> isUidBlocked(mBlockedReasons, i.getArgument(1))
1734         ).when(mBpfNetMaps).isUidNetworkingBlocked(anyInt(), anyBoolean());
1735     }
1736 
isUidBlocked(int blockedReasons, boolean meteredNetwork)1737     private boolean isUidBlocked(int blockedReasons, boolean meteredNetwork) {
1738         final int blockedOnAllNetworksReason = (blockedReasons & ~BLOCKED_METERED_REASON_MASK);
1739         if (blockedOnAllNetworksReason != BLOCKED_REASON_NONE) {
1740             return true;
1741         }
1742         if (meteredNetwork) {
1743             return blockedReasons != BLOCKED_REASON_NONE;
1744         }
1745         return false;
1746     }
1747 
setBlockedReasonChanged(int blockedReasons)1748     private void setBlockedReasonChanged(int blockedReasons) {
1749         mBlockedReasons = blockedReasons;
1750         if (mDeps.isAtLeastV()) {
1751             visibleOnHandlerThread(mCsHandlerThread.getThreadHandler(),
1752                     () -> mService.handleBlockedReasonsChanged(
1753                             List.of(new Pair<>(Process.myUid(), blockedReasons))
1754 
1755                     ));
1756         } else {
1757             mPolicyCallback.onUidBlockedReasonChanged(Process.myUid(), blockedReasons);
1758         }
1759     }
1760 
getNat464Xlat(NetworkAgentWrapper mna)1761     private Nat464Xlat getNat464Xlat(NetworkAgentWrapper mna) {
1762         return mService.getNetworkAgentInfoForNetwork(mna.getNetwork()).clatd;
1763     }
1764 
1765     private class WrappedMultinetworkPolicyTracker extends MultinetworkPolicyTracker {
1766         volatile int mConfigMeteredMultipathPreference;
1767 
WrappedMultinetworkPolicyTracker(Context c, Handler h, Runnable r)1768         WrappedMultinetworkPolicyTracker(Context c, Handler h, Runnable r) {
1769             super(c, h, r, new MultinetworkPolicyTrackerTestDependencies(mResources));
1770         }
1771 
1772         @Override
configMeteredMultipathPreference()1773         public int configMeteredMultipathPreference() {
1774             return mConfigMeteredMultipathPreference;
1775         }
1776     }
1777 
1778     /**
1779      * Wait up to TIMEOUT_MS for {@code conditionVariable} to open.
1780      * Fails if TIMEOUT_MS goes by before {@code conditionVariable} opens.
1781      */
waitFor(ConditionVariable conditionVariable)1782     static private void waitFor(ConditionVariable conditionVariable) {
1783         if (conditionVariable.block(TIMEOUT_MS)) {
1784             return;
1785         }
1786         fail("ConditionVariable was blocked for more than " + TIMEOUT_MS + "ms");
1787     }
1788 
doAsUid(final int uid, @NonNull final Supplier<T> what)1789     private <T> T doAsUid(final int uid, @NonNull final Supplier<T> what) {
1790         mDeps.setCallingUid(uid);
1791         try {
1792             return what.get();
1793         } finally {
1794             mDeps.setCallingUid(null);
1795         }
1796     }
1797 
doAsUid(final int uid, @NonNull final Runnable what)1798     private void doAsUid(final int uid, @NonNull final Runnable what) {
1799         doAsUid(uid, () -> {
1800             what.run(); return Void.TYPE;
1801         });
1802     }
1803 
registerNetworkCallbackAsUid(NetworkRequest request, NetworkCallback callback, int uid)1804     private void registerNetworkCallbackAsUid(NetworkRequest request, NetworkCallback callback,
1805             int uid) {
1806         doAsUid(uid, () -> {
1807             mCm.registerNetworkCallback(request, callback);
1808         });
1809     }
1810 
registerDefaultNetworkCallbackAsUid(@onNull final NetworkCallback callback, final int uid)1811     private void registerDefaultNetworkCallbackAsUid(@NonNull final NetworkCallback callback,
1812             final int uid) {
1813         doAsUid(uid, () -> {
1814             mCm.registerDefaultNetworkCallback(callback);
1815             waitForIdle();
1816         });
1817     }
1818 
withPermission(String permission, ThrowingRunnable r)1819     private void withPermission(String permission, ThrowingRunnable r) throws Exception {
1820         try {
1821             mServiceContext.setPermission(permission, PERMISSION_GRANTED);
1822             r.run();
1823         } finally {
1824             mServiceContext.setPermission(permission, null);
1825         }
1826     }
1827 
withPermission(String permission, int pid, int uid, ThrowingRunnable r)1828     private void withPermission(String permission, int pid, int uid, ThrowingRunnable r)
1829             throws Exception {
1830         try {
1831             mServiceContext.setPermission(permission, pid, uid, PERMISSION_GRANTED);
1832             r.run();
1833         } finally {
1834             mServiceContext.setPermission(permission, pid, uid, null);
1835         }
1836     }
1837 
1838     private static final int PRIMARY_USER = 0;
1839     private static final int SECONDARY_USER = 10;
1840     private static final int TERTIARY_USER = 11;
1841     private static final UidRange PRIMARY_UIDRANGE =
1842             UidRange.createForUser(UserHandle.of(PRIMARY_USER));
1843     private static final int APP1_UID = UserHandle.getUid(PRIMARY_USER, 10100);
1844     private static final int APP2_UID = UserHandle.getUid(PRIMARY_USER, 10101);
1845     private static final int VPN_UID = UserHandle.getUid(PRIMARY_USER, 10043);
1846     private static final UserInfo PRIMARY_USER_INFO = new UserInfo(PRIMARY_USER, "",
1847             UserInfo.FLAG_PRIMARY);
1848     private static final UserHandle PRIMARY_USER_HANDLE = new UserHandle(PRIMARY_USER);
1849     private static final UserHandle SECONDARY_USER_HANDLE = new UserHandle(SECONDARY_USER);
1850     private static final UserHandle TERTIARY_USER_HANDLE = new UserHandle(TERTIARY_USER);
1851 
1852     private static final int RESTRICTED_USER = 1;
1853     private static final UidRange RESTRICTED_USER_UIDRANGE =
1854             UidRange.createForUser(UserHandle.of(RESTRICTED_USER));
1855     private static final UserInfo RESTRICTED_USER_INFO = new UserInfo(RESTRICTED_USER, "",
1856             UserInfo.FLAG_RESTRICTED);
1857     static {
1858         RESTRICTED_USER_INFO.restrictedProfileParentId = PRIMARY_USER;
1859     }
1860 
1861     @Before
setUp()1862     public void setUp() throws Exception {
1863         mNetIdManager = new TestNetIdManager();
1864 
1865         mContext = InstrumentationRegistry.getContext();
1866 
1867         MockitoAnnotations.initMocks(this);
1868 
1869         // Note : Please do not add any new instrumentation here. If you need new instrumentation,
1870         // please add it in CSTest and use subclasses of CSTest instead of adding more
1871         // tools in ConnectivityServiceTest.
1872         doReturn(asList(PRIMARY_USER_INFO)).when(mUserManager).getAliveUsers();
1873         doReturn(asList(PRIMARY_USER_HANDLE)).when(mUserManager).getUserHandles(anyBoolean());
1874         doReturn(PRIMARY_USER_INFO).when(mUserManager).getUserInfo(PRIMARY_USER);
1875         // canHaveRestrictedProfile does not take a userId. It applies to the userId of the context
1876         // it was started from, i.e., PRIMARY_USER.
1877         doReturn(true).when(mUserManager).canHaveRestrictedProfile();
1878         doReturn(RESTRICTED_USER_INFO).when(mUserManager).getUserInfo(RESTRICTED_USER);
1879 
1880         final ApplicationInfo applicationInfo = new ApplicationInfo();
1881         applicationInfo.targetSdkVersion = Build.VERSION_CODES.Q;
1882         doReturn(applicationInfo).when(mPackageManager)
1883                 .getApplicationInfoAsUser(anyString(), anyInt(), any());
1884         doReturn(applicationInfo.targetSdkVersion).when(mPackageManager)
1885                 .getTargetSdkVersion(anyString());
1886         doReturn(new int[0]).when(mSystemConfigManager).getSystemPermissionUids(anyString());
1887 
1888         // InstrumentationTestRunner prepares a looper, but AndroidJUnitRunner does not.
1889         // http://b/25897652 .
1890         if (Looper.myLooper() == null) {
1891             Looper.prepare();
1892         }
1893         mockDefaultPackages();
1894         mockHasSystemFeature(FEATURE_WIFI, true);
1895         mockHasSystemFeature(FEATURE_WIFI_DIRECT, true);
1896         mockHasSystemFeature(FEATURE_ETHERNET, true);
1897         doReturn(true).when(mTelephonyManager).isDataCapable();
1898 
1899         FakeSettingsProvider.clearSettingsProvider();
1900         mServiceContext = new MockContext(InstrumentationRegistry.getContext(),
1901                 new FakeSettingsProvider());
1902         mServiceContext.setUseRegisteredHandlers(true);
1903         mServiceContext.setPermission(NETWORK_FACTORY, PERMISSION_GRANTED);
1904         mServiceContext.setPermission(NETWORK_STACK, PERMISSION_GRANTED);
1905         mServiceContext.setPermission(CONTROL_OEM_PAID_NETWORK_PREFERENCE, PERMISSION_GRANTED);
1906         mServiceContext.setPermission(PACKET_KEEPALIVE_OFFLOAD, PERMISSION_GRANTED);
1907         mServiceContext.setPermission(CONNECTIVITY_USE_RESTRICTED_NETWORKS, PERMISSION_GRANTED);
1908         mServiceContext.setPermission(READ_DEVICE_CONFIG, PERMISSION_GRANTED);
1909 
1910         mAlarmManagerThread = new HandlerThread("TestAlarmManager");
1911         mAlarmManagerThread.start();
1912         initAlarmManager(mAlarmManager, mAlarmManagerThread.getThreadHandler());
1913 
1914         mCsHandlerThread = new HandlerThread("TestConnectivityService");
1915         mProxyTracker = new ProxyTracker(mServiceContext, mock(Handler.class),
1916                 16 /* EVENT_PROXY_HAS_CHANGED */);
1917 
1918         initMockedResources();
1919         final Context mockResContext = mock(Context.class);
1920         doReturn(mResources).when(mockResContext).getResources();
1921         ConnectivityResources.setResourcesContextForTest(mockResContext);
1922         mDeps = new ConnectivityServiceDependencies(mockResContext);
1923         doReturn(true).when(mMockKeepaliveTrackerDependencies)
1924                 .isAddressTranslationEnabled(mServiceContext);
1925         doReturn(new ConnectivityResources(mockResContext)).when(mMockKeepaliveTrackerDependencies)
1926                 .createConnectivityResources(mServiceContext);
1927         doReturn(new int[] {1, 3, 0, 0}).when(mMockKeepaliveTrackerDependencies)
1928                 .getSupportedKeepalives(mServiceContext);
1929         mAutoOnOffKeepaliveDependencies =
1930                 new AutomaticOnOffKeepaliveTrackerDependencies(mServiceContext);
1931         mService = new ConnectivityService(mServiceContext,
1932                 mMockDnsResolver,
1933                 mock(IpConnectivityLog.class),
1934                 mMockNetd,
1935                 mDeps);
1936         mService.mLingerDelayMs = TEST_LINGER_DELAY_MS;
1937         mService.mNascentDelayMs = TEST_NASCENT_DELAY_MS;
1938 
1939         if (mDeps.isAtLeastV()) {
1940             verify(mNetworkPolicyManager, never()).registerNetworkPolicyCallback(any(), any());
1941             mPolicyCallback = null;
1942         } else {
1943             final ArgumentCaptor<NetworkPolicyCallback> policyCallbackCaptor =
1944                     ArgumentCaptor.forClass(NetworkPolicyCallback.class);
1945             verify(mNetworkPolicyManager).registerNetworkPolicyCallback(any(),
1946                     policyCallbackCaptor.capture());
1947             mPolicyCallback = policyCallbackCaptor.getValue();
1948         }
1949 
1950         // Create local CM before sending system ready so that we can answer
1951         // getSystemService() correctly.
1952         mCm = new WrappedConnectivityManager(InstrumentationRegistry.getContext(), mService);
1953         mService.systemReadyInternal();
1954         verify(mMockDnsResolver).registerUnsolicitedEventListener(any());
1955 
1956         mMockVpn = new MockVpn();
1957         mCm.bindProcessToNetwork(null);
1958         mQosCallbackTracker = mock(QosCallbackTracker.class);
1959 
1960         // Ensure that the default setting for Captive Portals is used for most tests
1961         setCaptivePortalMode(ConnectivitySettingsManager.CAPTIVE_PORTAL_MODE_PROMPT);
1962         setAlwaysOnNetworks(false);
1963         setPrivateDnsSettings(PRIVATE_DNS_MODE_OFF, "ignored.example.com");
1964 
1965         mDeps.setChangeIdEnabled(
1966                 true, NETWORK_BLOCKED_WITHOUT_INTERNET_PERMISSION, Process.myUid());
1967         doReturn(PERMISSION_INTERNET).when(mBpfNetMaps).getNetPermForUid(anyInt());
1968         // Note : Please do not add any new instrumentation here. If you need new instrumentation,
1969         // please add it in CSTest and use subclasses of CSTest instead of adding more
1970         // tools in ConnectivityServiceTest.
1971     }
1972 
initMockedResources()1973     private void initMockedResources() {
1974         doReturn(60000).when(mResources).getInteger(R.integer.config_networkTransitionTimeout);
1975         doReturn("").when(mResources).getString(R.string.config_networkCaptivePortalServerUrl);
1976         doReturn(new String[]{ WIFI_WOL_IFNAME }).when(mResources).getStringArray(
1977                 R.array.config_wakeonlan_supported_interfaces);
1978         doReturn(new String[] { "0,1", "1,3" }).when(mResources).getStringArray(
1979                 R.array.config_networkSupportedKeepaliveCount);
1980         doReturn(new String[0]).when(mResources).getStringArray(
1981                 R.array.config_networkNotifySwitches);
1982         doReturn(new int[]{10, 11, 12, 14, 15}).when(mResources).getIntArray(
1983                 R.array.config_protectedNetworks);
1984         // We don't test the actual notification value strings, so just return an empty array.
1985         // It doesn't matter what the values are as long as it's not null.
1986         doReturn(new String[0]).when(mResources)
1987                 .getStringArray(R.array.network_switch_type_name);
1988 
1989         doReturn(R.array.config_networkSupportedKeepaliveCount).when(mResources)
1990                 .getIdentifier(eq("config_networkSupportedKeepaliveCount"), eq("array"), any());
1991         doReturn(R.array.network_switch_type_name).when(mResources)
1992                 .getIdentifier(eq("network_switch_type_name"), eq("array"), any());
1993         doReturn(1).when(mResources).getInteger(R.integer.config_networkAvoidBadWifi);
1994         doReturn(0).when(mResources).getInteger(R.integer.config_activelyPreferBadWifi);
1995         doReturn(true).when(mResources)
1996                 .getBoolean(R.bool.config_cellular_radio_timesharing_capable);
1997         doReturn(PACKET_WAKEUP_MARK_MASK).when(mResources).getInteger(
1998                 R.integer.config_networkWakeupPacketMask);
1999         doReturn(PACKET_WAKEUP_MARK_MASK).when(mResources).getInteger(
2000                 R.integer.config_networkWakeupPacketMark);
2001     }
2002 
2003     class ConnectivityServiceDependencies extends ConnectivityService.Dependencies {
2004         final ConnectivityResources mConnRes;
2005         final ArraySet<Pair<Long, Integer>> mEnabledChangeIds = new ArraySet<>();
2006 
2007         // Note : Please do not add any new instrumentation here. If you need new instrumentation,
2008         // please add it in CSTest and use subclasses of CSTest instead of adding more
2009         // tools in ConnectivityServiceTest.
ConnectivityServiceDependencies(final Context mockResContext)2010         ConnectivityServiceDependencies(final Context mockResContext) {
2011             mConnRes = new ConnectivityResources(mockResContext);
2012         }
2013 
2014         @Override
makeHandlerThread(@onNull final String tag)2015         public HandlerThread makeHandlerThread(@NonNull final String tag) {
2016             return mCsHandlerThread;
2017         }
2018 
2019         @Override
getNetworkStack()2020         public NetworkStackClientBase getNetworkStack() {
2021             return mNetworkStack;
2022         }
2023 
2024         @Override
makeProxyTracker(final Context context, final Handler handler)2025         public ProxyTracker makeProxyTracker(final Context context, final Handler handler) {
2026             return mProxyTracker;
2027         }
2028 
2029         @Override
makeNetIdManager()2030         public NetIdManager makeNetIdManager() {
2031             return mNetIdManager;
2032         }
2033 
2034         @Override
queryUserAccess(final int uid, final Network network, final ConnectivityService cs)2035         public boolean queryUserAccess(final int uid, final Network network,
2036                 final ConnectivityService cs) {
2037             return true;
2038         }
2039 
2040         @Override
makeMultinetworkPolicyTracker(final Context c, final Handler h, final Runnable r)2041         public MultinetworkPolicyTracker makeMultinetworkPolicyTracker(final Context c,
2042                 final Handler h, final Runnable r) {
2043             if (null != mPolicyTracker) {
2044                 throw new IllegalStateException("Multinetwork policy tracker already initialized");
2045             }
2046             mPolicyTracker = new WrappedMultinetworkPolicyTracker(mServiceContext, h, r);
2047             return mPolicyTracker;
2048         }
2049 
2050         @Override
makeAutomaticOnOffKeepaliveTracker(final Context c, final Handler h)2051         public AutomaticOnOffKeepaliveTracker makeAutomaticOnOffKeepaliveTracker(final Context c,
2052                 final Handler h) {
2053             return new AutomaticOnOffKeepaliveTracker(c, h, mAutoOnOffKeepaliveDependencies);
2054         }
2055 
2056         @Override
getResources(final Context ctx)2057         public ConnectivityResources getResources(final Context ctx) {
2058             return mConnRes;
2059         }
2060 
2061         @Override
makeLocationPermissionChecker(final Context context)2062         public LocationPermissionChecker makeLocationPermissionChecker(final Context context) {
2063             return new LocationPermissionChecker(context) {
2064                 @Override
2065                 protected int getCurrentUser() {
2066                     return runAsShell(CREATE_USERS, () -> super.getCurrentUser());
2067                 }
2068             };
2069         }
2070 
2071         private BiConsumer<Integer, Integer> mCarrierPrivilegesLostListener;
2072 
2073         @Override
makeCarrierPrivilegeAuthenticator( @onNull final Context context, @NonNull final TelephonyManager tm, final boolean requestRestrictedWifiEnabled, BiConsumer<Integer, Integer> listener, @NonNull final Handler handler)2074         public CarrierPrivilegeAuthenticator makeCarrierPrivilegeAuthenticator(
2075                 @NonNull final Context context,
2076                 @NonNull final TelephonyManager tm,
2077                 final boolean requestRestrictedWifiEnabled,
2078                 BiConsumer<Integer, Integer> listener,
2079                 @NonNull final Handler handler) {
2080             mCarrierPrivilegesLostListener = listener;
2081             return mDeps.isAtLeastT() ? mCarrierPrivilegeAuthenticator : null;
2082         }
2083 
2084         @Override
makeSatelliteAccessController( @onNull final Context context, Consumer<Set<Integer>> updateSatelliteNetworkFallbackUidCallback, @NonNull final Handler connectivityServiceInternalHandler)2085         public SatelliteAccessController makeSatelliteAccessController(
2086                 @NonNull final Context context,
2087                 Consumer<Set<Integer>> updateSatelliteNetworkFallbackUidCallback,
2088                 @NonNull final Handler connectivityServiceInternalHandler) {
2089             return mSatelliteAccessController;
2090         }
2091 
2092         @Override
intentFilterEquals(final PendingIntent a, final PendingIntent b)2093         public boolean intentFilterEquals(final PendingIntent a, final PendingIntent b) {
2094             return runAsShell(GET_INTENT_SENDER_INTENT, () -> a.intentFilterEquals(b));
2095         }
2096 
2097         @GuardedBy("this")
2098         private Integer mCallingUid = null;
2099 
2100         @Override
getCallingUid()2101         public int getCallingUid() {
2102             synchronized (this) {
2103                 if (null != mCallingUid) return mCallingUid;
2104                 return super.getCallingUid();
2105             }
2106         }
2107 
2108         // Pass null for the real calling UID
setCallingUid(final Integer uid)2109         public void setCallingUid(final Integer uid) {
2110             synchronized (this) {
2111                 mCallingUid = uid;
2112             }
2113         }
2114 
2115         @GuardedBy("this")
2116         private boolean mCellular464XlatEnabled = true;
2117 
2118         @Override
getCellular464XlatEnabled()2119         public boolean getCellular464XlatEnabled() {
2120             synchronized (this) {
2121                 return mCellular464XlatEnabled;
2122             }
2123         }
2124 
setCellular464XlatEnabled(final boolean enabled)2125         public void setCellular464XlatEnabled(final boolean enabled) {
2126             synchronized (this) {
2127                 mCellular464XlatEnabled = enabled;
2128             }
2129         }
2130 
2131         @GuardedBy("this")
2132         private Integer mConnectionOwnerUid = null;
2133 
2134         @Override
getConnectionOwnerUid(final int protocol, final InetSocketAddress local, final InetSocketAddress remote)2135         public int getConnectionOwnerUid(final int protocol, final InetSocketAddress local,
2136                 final InetSocketAddress remote) {
2137             synchronized (this) {
2138                 if (null != mConnectionOwnerUid) return mConnectionOwnerUid;
2139                 return super.getConnectionOwnerUid(protocol, local, remote);
2140             }
2141         }
2142 
2143         // Pass null to get the production implementation of getConnectionOwnerUid
setConnectionOwnerUid(final Integer uid)2144         public void setConnectionOwnerUid(final Integer uid) {
2145             synchronized (this) {
2146                 mConnectionOwnerUid = uid;
2147             }
2148         }
2149 
2150         final class ReportedInterfaces {
2151             public final Context context;
2152             public final String iface;
2153             public final int[] transportTypes;
ReportedInterfaces(final Context c, final String i, final int[] t)2154             ReportedInterfaces(final Context c, final String i, final int[] t) {
2155                 context = c;
2156                 iface = i;
2157                 transportTypes = t;
2158             }
2159 
contentEquals(final Context c, final String i, final int[] t)2160             public boolean contentEquals(final Context c, final String i, final int[] t) {
2161                 return Objects.equals(context, c) && Objects.equals(iface, i)
2162                         && Arrays.equals(transportTypes, t);
2163             }
2164         }
2165 
2166         final ArrayTrackRecord<ReportedInterfaces> mReportedInterfaceHistory =
2167                 new ArrayTrackRecord<>();
2168 
2169         @Override
reportNetworkInterfaceForTransports(final Context context, final String iface, final int[] transportTypes)2170         public void reportNetworkInterfaceForTransports(final Context context, final String iface,
2171                 final int[] transportTypes) {
2172             mReportedInterfaceHistory.add(new ReportedInterfaces(context, iface, transportTypes));
2173             super.reportNetworkInterfaceForTransports(context, iface, transportTypes);
2174         }
2175 
2176         @Override
isFeatureEnabled(Context context, String name)2177         public boolean isFeatureEnabled(Context context, String name) {
2178             switch (name) {
2179                 case ConnectivityFlags.NO_REMATCH_ALL_REQUESTS_ON_REGISTER:
2180                 case ConnectivityFlags.CARRIER_SERVICE_CHANGED_USE_CALLBACK:
2181                 case ConnectivityFlags.REQUEST_RESTRICTED_WIFI:
2182                 case ConnectivityFlags.USE_DECLARED_METHODS_FOR_CALLBACKS:
2183                 case KEY_DESTROY_FROZEN_SOCKETS_VERSION:
2184                     return true;
2185                 default:
2186                     return super.isFeatureEnabled(context, name);
2187             }
2188         }
2189 
2190         @Override
isFeatureNotChickenedOut(Context context, String name)2191         public boolean isFeatureNotChickenedOut(Context context, String name) {
2192             switch (name) {
2193                 case ALLOW_SYSUI_CONNECTIVITY_REPORTS:
2194                     return true;
2195                 case ALLOW_SATALLITE_NETWORK_FALLBACK:
2196                     return true;
2197                 case INGRESS_TO_VPN_ADDRESS_FILTERING:
2198                     return true;
2199                 case BACKGROUND_FIREWALL_CHAIN:
2200                     return true;
2201                 case DELAY_DESTROY_SOCKETS:
2202                     return true;
2203                 default:
2204                     return super.isFeatureNotChickenedOut(context, name);
2205             }
2206         }
2207 
setChangeIdEnabled(final boolean enabled, final long changeId, final int uid)2208         public void setChangeIdEnabled(final boolean enabled, final long changeId, final int uid) {
2209             final Pair<Long, Integer> data = new Pair<>(changeId, uid);
2210             // mEnabledChangeIds is read on the handler thread and maybe the test thread, so
2211             // make sure both threads see it before continuing.
2212             visibleOnHandlerThread(mCsHandlerThread.getThreadHandler(), () -> {
2213                 if (enabled) {
2214                     mEnabledChangeIds.add(data);
2215                 } else {
2216                     mEnabledChangeIds.remove(data);
2217                 }
2218             });
2219         }
2220 
2221         @Override
isChangeEnabled(final long changeId, final int uid)2222         public boolean isChangeEnabled(final long changeId, final int uid) {
2223             return mEnabledChangeIds.contains(new Pair<>(changeId, uid));
2224         }
2225 
2226         // In AOSP, build version codes are all over the place (e.g. at the time of this writing
2227         // U == V). Define custom ones.
2228         private static final int VERSION_UNMOCKED = -1;
2229         private static final int VERSION_R = 1;
2230         private static final int VERSION_S = 2;
2231         private static final int VERSION_T = 3;
2232         private static final int VERSION_U = 4;
2233         private static final int VERSION_V = 5;
2234         private static final int VERSION_MAX = VERSION_V;
2235         private int mSdkLevel = VERSION_UNMOCKED;
2236 
setBuildSdk(final int sdkLevel)2237         private void setBuildSdk(final int sdkLevel) {
2238             if (sdkLevel > VERSION_MAX) {
2239                 throw new IllegalArgumentException("setBuildSdk must not be called with"
2240                         + " Build.VERSION constants but Dependencies.VERSION_* constants");
2241             }
2242             visibleOnHandlerThread(mCsHandlerThread.getThreadHandler(), () -> mSdkLevel = sdkLevel);
2243         }
2244 
2245         @Override
isAtLeastS()2246         public boolean isAtLeastS() {
2247             return mSdkLevel == VERSION_UNMOCKED ? super.isAtLeastS()
2248                     : mSdkLevel >= VERSION_S;
2249         }
2250 
2251         @Override
isAtLeastT()2252         public boolean isAtLeastT() {
2253             return mSdkLevel == VERSION_UNMOCKED ? super.isAtLeastT()
2254                     : mSdkLevel >= VERSION_T;
2255         }
2256 
2257         @Override
isAtLeastU()2258         public boolean isAtLeastU() {
2259             return mSdkLevel == VERSION_UNMOCKED ? super.isAtLeastU()
2260                     : mSdkLevel >= VERSION_U;
2261         }
2262 
2263         @Override
getBpfNetMaps(Context context, INetd netd)2264         public BpfNetMaps getBpfNetMaps(Context context, INetd netd) {
2265             return mBpfNetMaps;
2266         }
2267 
2268         @Override
getClatCoordinator(INetd netd)2269         public ClatCoordinator getClatCoordinator(INetd netd) {
2270             return mClatCoordinator;
2271         }
2272 
2273         final ArrayTrackRecord<Pair<String, Long>> mRateLimitHistory = new ArrayTrackRecord<>();
2274         final Map<String, Long> mActiveRateLimit = new HashMap<>();
2275 
2276         @Override
enableIngressRateLimit(final String iface, final long rateInBytesPerSecond)2277         public void enableIngressRateLimit(final String iface, final long rateInBytesPerSecond) {
2278             mRateLimitHistory.add(new Pair<>(iface, rateInBytesPerSecond));
2279             // Due to a TC limitation, the rate limit needs to be removed before it can be
2280             // updated. Check that this happened.
2281             assertEquals(-1L, (long) mActiveRateLimit.getOrDefault(iface, -1L));
2282             mActiveRateLimit.put(iface, rateInBytesPerSecond);
2283             // verify that clsact qdisc has already been created, otherwise attaching a tc police
2284             // filter will fail.
2285             try {
2286                 verify(mMockNetd).networkAddInterface(anyInt(), eq(iface));
2287             } catch (RemoteException e) {
2288                 fail(e.getMessage());
2289             }
2290         }
2291 
2292         @Override
disableIngressRateLimit(final String iface)2293         public void disableIngressRateLimit(final String iface) {
2294             mRateLimitHistory.add(new Pair<>(iface, -1L));
2295             assertNotEquals(-1L, (long) mActiveRateLimit.getOrDefault(iface, -1L));
2296             mActiveRateLimit.put(iface, -1L);
2297         }
2298 
2299         @Override
getBpfProgramId(final int attachType)2300         public int getBpfProgramId(final int attachType) {
2301             return 0;
2302         }
2303 
2304         @Override
makeBroadcastOptionsShim(BroadcastOptions options)2305         public BroadcastOptionsShim makeBroadcastOptionsShim(BroadcastOptions options) {
2306             reset(mBroadcastOptionsShim);
2307             return mBroadcastOptionsShim;
2308         }
2309 
2310         @GuardedBy("this")
2311         private boolean mForceDisableCompatChangeCheck = true;
2312 
2313         /**
2314          * By default, the {@link #isChangeEnabled(long, String, UserHandle)} will always return
2315          * true as the mForceDisableCompatChangeCheck is true and compat change check logic is
2316          * never executed. The compat change check logic can be turned on by calling this method.
2317          * If this method is called, the
2318          * {@link libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges} or
2319          * {@link libcore.junit.util.compat.CoreCompatChangeRule.DisableCompatChanges} must be
2320          * used to turn on/off the compat change flag.
2321          */
enableCompatChangeCheck()2322         private void enableCompatChangeCheck() {
2323             synchronized (this) {
2324                 mForceDisableCompatChangeCheck = false;
2325             }
2326         }
2327 
2328         @Override
isChangeEnabled(long changeId, @NonNull final String packageName, @NonNull final UserHandle user)2329         public boolean isChangeEnabled(long changeId,
2330                 @NonNull final String packageName,
2331                 @NonNull final UserHandle user) {
2332             synchronized (this) {
2333                 if (mForceDisableCompatChangeCheck) {
2334                     return false;
2335                 } else {
2336                     return super.isChangeEnabled(changeId, packageName, user);
2337                 }
2338             }
2339         }
2340 
2341         // Class to be mocked and used to verify destroy sockets methods call
2342         public class DestroySocketsWrapper {
destroyLiveTcpSockets(final Set<Range<Integer>> ranges, final Set<Integer> exemptUids)2343             public void destroyLiveTcpSockets(final Set<Range<Integer>> ranges,
2344                     final Set<Integer> exemptUids){}
destroyLiveTcpSocketsByOwnerUids(final Set<Integer> ownerUids)2345             public void destroyLiveTcpSocketsByOwnerUids(final Set<Integer> ownerUids){}
2346         }
2347 
2348         @Override @SuppressWarnings("DirectInvocationOnMock")
destroyLiveTcpSockets(final Set<Range<Integer>> ranges, final Set<Integer> exemptUids)2349         public void destroyLiveTcpSockets(final Set<Range<Integer>> ranges,
2350                 final Set<Integer> exemptUids) {
2351             // Call mocked destroyLiveTcpSockets so that test can verify this method call
2352             mDestroySocketsWrapper.destroyLiveTcpSockets(ranges, exemptUids);
2353         }
2354 
2355         @Override @SuppressWarnings("DirectInvocationOnMock")
destroyLiveTcpSocketsByOwnerUids(final Set<Integer> ownerUids)2356         public void destroyLiveTcpSocketsByOwnerUids(final Set<Integer> ownerUids) {
2357             // Call mocked destroyLiveTcpSocketsByOwnerUids so that test can verify this method call
2358             // Create copy of ownerUids so that tests can verify the correct value even if the
2359             // ConnectivityService update the ownerUids after this method call.
2360             mDestroySocketsWrapper.destroyLiveTcpSocketsByOwnerUids(new ArraySet<>(ownerUids));
2361         }
2362 
2363         final ArrayTrackRecord<Pair<Integer, Long>>.ReadHead mScheduledEvaluationTimeouts =
2364                 new ArrayTrackRecord<Pair<Integer, Long>>().newReadHead();
2365         @Override
scheduleEvaluationTimeout(@onNull Handler handler, @NonNull final Network network, final long delayMs)2366         public void scheduleEvaluationTimeout(@NonNull Handler handler,
2367                 @NonNull final Network network, final long delayMs) {
2368             mScheduledEvaluationTimeouts.add(new Pair<>(network.netId, delayMs));
2369             super.scheduleEvaluationTimeout(handler, network, delayMs);
2370         }
2371     }
2372 
2373     private class AutomaticOnOffKeepaliveTrackerDependencies
2374             extends AutomaticOnOffKeepaliveTracker.Dependencies {
2375         AutomaticOnOffKeepaliveTrackerDependencies(Context context) {
2376             super(context);
2377         }
2378 
2379         @Override
2380         public boolean isTetheringFeatureNotChickenedOut(@NonNull final String name) {
2381             // Tests for enabling the feature are verified in AutomaticOnOffKeepaliveTrackerTest.
2382             // Assuming enabled here to focus on ConnectivityService tests.
2383             return true;
2384         }
2385         public KeepaliveTracker newKeepaliveTracker(@NonNull Context context,
2386                 @NonNull Handler connectivityserviceHander) {
2387             return new KeepaliveTracker(context, connectivityserviceHander,
2388                     new TcpKeepaliveController(connectivityserviceHander),
2389                     mMockKeepaliveTrackerDependencies);
2390         }
2391     }
2392 
2393     private static void initAlarmManager(final AlarmManager am, final Handler alarmHandler) {
2394         doAnswer(inv -> {
2395             final long when = inv.getArgument(1);
2396             final WakeupMessage wakeupMsg = inv.getArgument(3);
2397             final Handler handler = inv.getArgument(4);
2398 
2399             long delayMs = when - SystemClock.elapsedRealtime();
2400             if (delayMs < 0) delayMs = 0;
2401             if (delayMs > UNREASONABLY_LONG_ALARM_WAIT_MS) {
2402                 fail("Attempting to send msg more than " + UNREASONABLY_LONG_ALARM_WAIT_MS
2403                         + "ms into the future: " + delayMs);
2404             }
2405             alarmHandler.postDelayed(() -> handler.post(wakeupMsg::onAlarm), wakeupMsg /* token */,
2406                     delayMs);
2407 
2408             return null;
2409         }).when(am).setExact(eq(AlarmManager.ELAPSED_REALTIME_WAKEUP), anyLong(), anyString(),
2410                 any(WakeupMessage.class), any());
2411 
2412         doAnswer(inv -> {
2413             final WakeupMessage wakeupMsg = inv.getArgument(0);
2414             alarmHandler.removeCallbacksAndMessages(wakeupMsg /* token */);
2415             return null;
2416         }).when(am).cancel(any(WakeupMessage.class));
2417     }
2418 
2419     @After
2420     public void tearDown() throws Exception {
2421         unregisterDefaultNetworkCallbacks();
2422         maybeTearDownEnterpriseNetwork();
2423         setAlwaysOnNetworks(false);
2424         if (mCellAgent != null) {
2425             mCellAgent.disconnect();
2426             mCellAgent = null;
2427         }
2428         if (mWiFiAgent != null) {
2429             mWiFiAgent.disconnect();
2430             mWiFiAgent = null;
2431         }
2432         if (mEthernetAgent != null) {
2433             mEthernetAgent.disconnect();
2434             mEthernetAgent = null;
2435         }
2436 
2437         if (mQosCallbackMockHelper != null) {
2438             mQosCallbackMockHelper.tearDown();
2439             mQosCallbackMockHelper = null;
2440         }
2441         mMockVpn.disconnect();
2442         waitForIdle();
2443 
2444         FakeSettingsProvider.clearSettingsProvider();
2445         ConnectivityResources.setResourcesContextForTest(null);
2446 
2447         for (TestNetworkAgentWrapper agent : mCreatedAgents) {
2448             agent.destroy();
2449         }
2450         mCreatedAgents.clear();
2451 
2452         mCsHandlerThread.quitSafely();
2453         mCsHandlerThread.join();
2454         mAlarmManagerThread.quitSafely();
2455         mAlarmManagerThread.join();
2456     }
2457 
2458     private void mockDefaultPackages() throws Exception {
2459         final String myPackageName = mContext.getPackageName();
2460         final PackageInfo myPackageInfo = mContext.getPackageManager().getPackageInfo(
2461                 myPackageName, PackageManager.GET_PERMISSIONS);
2462         myPackageInfo.setLongVersionCode(9_999_999L);
2463         doReturn(new String[] {myPackageName}).when(mPackageManager)
2464                 .getPackagesForUid(Binder.getCallingUid());
2465         doReturn(myPackageInfo).when(mPackageManager).getPackageInfoAsUser(
2466                 eq(myPackageName), anyInt(), eq(UserHandle.getCallingUserId()));
2467 
2468         doReturn(asList(new PackageInfo[] {
2469                 buildPackageInfo(/* SYSTEM */ false, APP1_UID),
2470                 buildPackageInfo(/* SYSTEM */ false, APP2_UID),
2471                 buildPackageInfo(/* SYSTEM */ false, VPN_UID)
2472         })).when(mPackageManager).getInstalledPackagesAsUser(eq(GET_PERMISSIONS), anyInt());
2473 
2474         final ModuleInfo moduleInfo = new ModuleInfo();
2475         moduleInfo.setPackageName(TETHERING_MODULE_NAME);
2476         doReturn(moduleInfo).when(mPackageManager)
2477                 .getModuleInfo(TETHERING_MODULE_NAME, PackageManager.MODULE_APEX_NAME);
2478         doReturn(myPackageInfo).when(mPackageManager)
2479                 .getPackageInfo(TETHERING_MODULE_NAME, PackageManager.MATCH_APEX);
2480 
2481         // Create a fake always-on VPN package.
2482         final int userId = UserHandle.getCallingUserId();
2483         final ApplicationInfo applicationInfo = new ApplicationInfo();
2484         applicationInfo.targetSdkVersion = Build.VERSION_CODES.R;  // Always-on supported in N+.
2485         doReturn(applicationInfo).when(mPackageManager).getApplicationInfoAsUser(
2486                 eq(ALWAYS_ON_PACKAGE), anyInt(), eq(userId));
2487 
2488         // Minimal mocking to keep Vpn#isAlwaysOnPackageSupported happy.
2489         ResolveInfo rInfo = new ResolveInfo();
2490         rInfo.serviceInfo = new ServiceInfo();
2491         rInfo.serviceInfo.metaData = new Bundle();
2492         final List<ResolveInfo> services = asList(new ResolveInfo[]{rInfo});
2493         doReturn(services).when(mPackageManager).queryIntentServicesAsUser(
2494                 any(), eq(PackageManager.GET_META_DATA), eq(userId));
2495         doReturn(Process.myUid()).when(mPackageManager).getPackageUidAsUser(
2496                 TEST_PACKAGE_NAME, userId);
2497         doReturn(VPN_UID).when(mPackageManager).getPackageUidAsUser(ALWAYS_ON_PACKAGE, userId);
2498     }
2499 
2500     private void verifyActiveNetwork(int transport) {
2501         // Test getActiveNetworkInfo()
2502         assertNotNull(mCm.getActiveNetworkInfo());
2503         assertEquals(transportToLegacyType(transport), mCm.getActiveNetworkInfo().getType());
2504         // Test getActiveNetwork()
2505         assertNotNull(mCm.getActiveNetwork());
2506         assertEquals(mCm.getActiveNetwork(), mCm.getActiveNetworkForUid(Process.myUid()));
2507         if (!NetworkCapabilities.isValidTransport(transport)) {
2508             throw new IllegalStateException("Unknown transport " + transport);
2509         }
2510         switch (transport) {
2511             case TRANSPORT_WIFI:
2512                 assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetwork());
2513                 break;
2514             case TRANSPORT_CELLULAR:
2515                 assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetwork());
2516                 break;
2517             case TRANSPORT_ETHERNET:
2518                 assertEquals(mEthernetAgent.getNetwork(), mCm.getActiveNetwork());
2519                 break;
2520             default:
2521                 break;
2522         }
2523         // Test getNetworkInfo(Network)
2524         assertNotNull(mCm.getNetworkInfo(mCm.getActiveNetwork()));
2525         assertEquals(transportToLegacyType(transport),
2526                 mCm.getNetworkInfo(mCm.getActiveNetwork()).getType());
2527         assertNotNull(mCm.getActiveNetworkInfoForUid(Process.myUid()));
2528         // Test getNetworkCapabilities(Network)
2529         assertNotNull(mCm.getNetworkCapabilities(mCm.getActiveNetwork()));
2530         assertTrue(mCm.getNetworkCapabilities(mCm.getActiveNetwork()).hasTransport(transport));
2531     }
2532 
2533     private void verifyNoNetwork() {
2534         waitForIdle();
2535         // Test getActiveNetworkInfo()
2536         assertNull(mCm.getActiveNetworkInfo());
2537         // Test getActiveNetwork()
2538         assertNull(mCm.getActiveNetwork());
2539         assertNull(mCm.getActiveNetworkForUid(Process.myUid()));
2540         // Test getAllNetworks()
2541         assertEmpty(mCm.getAllNetworks());
2542         assertEmpty(mCm.getAllNetworkStateSnapshots());
2543     }
2544 
2545     /**
2546      * Class to simplify expecting broadcasts using BroadcastInterceptingContext.
2547      * Ensures that the receiver is unregistered after the expected broadcast is received. This
2548      * cannot be done in the BroadcastReceiver itself because BroadcastInterceptingContext runs
2549      * the receivers' receive method while iterating over the list of receivers, and unregistering
2550      * the receiver during iteration throws ConcurrentModificationException.
2551      */
2552     private class ExpectedBroadcast extends CompletableFuture<Intent>  {
2553         private final BroadcastReceiver mReceiver;
2554 
2555         ExpectedBroadcast(BroadcastReceiver receiver) {
2556             mReceiver = receiver;
2557         }
2558 
2559         public Intent expectBroadcast(int timeoutMs) throws Exception {
2560             try {
2561                 return get(timeoutMs, TimeUnit.MILLISECONDS);
2562             } catch (TimeoutException e) {
2563                 fail("Expected broadcast not received after " + timeoutMs + " ms");
2564                 return null;
2565             } finally {
2566                 mServiceContext.unregisterReceiver(mReceiver);
2567             }
2568         }
2569 
2570         public Intent expectBroadcast() throws Exception {
2571             return expectBroadcast(BROADCAST_TIMEOUT_MS);
2572         }
2573 
2574         public void expectNoBroadcast(int timeoutMs) throws Exception {
2575             waitForIdle();
2576             try {
2577                 final Intent intent = get(timeoutMs, TimeUnit.MILLISECONDS);
2578                 fail("Unexpected broadcast: " + intent.getAction() + " " + intent.getExtras());
2579             } catch (TimeoutException expected) {
2580             } finally {
2581                 mServiceContext.unregisterReceiver(mReceiver);
2582             }
2583         }
2584     }
2585 
2586     private ExpectedBroadcast registerBroadcastReceiverThat(final String action, final int count,
2587             @NonNull final Predicate<Intent> filter) {
2588         final IntentFilter intentFilter = new IntentFilter(action);
2589         // AtomicReference allows receiver to access expected even though it is constructed later.
2590         final AtomicReference<ExpectedBroadcast> expectedRef = new AtomicReference<>();
2591         final BroadcastReceiver receiver = new BroadcastReceiver() {
2592             private int mRemaining = count;
2593             public void onReceive(Context context, Intent intent) {
2594                 logIntent(intent);
2595                 if (!filter.test(intent)) return;
2596                 if (--mRemaining == 0) {
2597                     expectedRef.get().complete(intent);
2598                 }
2599             }
2600         };
2601         final ExpectedBroadcast expected = new ExpectedBroadcast(receiver);
2602         expectedRef.set(expected);
2603         mServiceContext.registerReceiver(receiver, intentFilter);
2604         return expected;
2605     }
2606 
2607     private void logIntent(Intent intent) {
2608         final String action = intent.getAction();
2609         if (CONNECTIVITY_ACTION.equals(action)) {
2610             final int type = intent.getIntExtra(EXTRA_NETWORK_TYPE, -1);
2611             final NetworkInfo ni = intent.getParcelableExtra(EXTRA_NETWORK_INFO);
2612             Log.d(TAG, "Received " + action + ", type=" + type + " ni=" + ni);
2613         } else if (PROXY_CHANGE_ACTION.equals(action)) {
2614             final ProxyInfo proxy = (ProxyInfo) intent.getExtra(
2615                     Proxy.EXTRA_PROXY_INFO, ProxyInfo.buildPacProxy(Uri.EMPTY));
2616             Log.d(TAG, "Received " + action + ", proxy = " + proxy);
2617         } else {
2618             throw new IllegalArgumentException("Unsupported logging " + action);
2619         }
2620     }
2621 
2622     /** Expects that {@code count} CONNECTIVITY_ACTION broadcasts are received. */
2623     private ExpectedBroadcast expectConnectivityAction(final int count) {
2624         return registerBroadcastReceiverThat(CONNECTIVITY_ACTION, count, intent -> true);
2625     }
2626 
2627     private ExpectedBroadcast expectConnectivityAction(int type, NetworkInfo.DetailedState state) {
2628         return registerBroadcastReceiverThat(CONNECTIVITY_ACTION, 1, intent -> {
2629             final int actualType = intent.getIntExtra(EXTRA_NETWORK_TYPE, -1);
2630             final NetworkInfo ni = intent.getParcelableExtra(EXTRA_NETWORK_INFO);
2631             return type == actualType
2632                     && state == ni.getDetailedState()
2633                     && extraInfoInBroadcastHasExpectedNullness(ni);
2634         });
2635     }
2636 
2637     /** Expects that PROXY_CHANGE_ACTION broadcast is received. */
2638     private ExpectedBroadcast expectProxyChangeAction() {
2639         return registerBroadcastReceiverThat(PROXY_CHANGE_ACTION, 1, intent -> true);
2640     }
2641 
2642     private ExpectedBroadcast expectProxyChangeAction(ProxyInfo proxy) {
2643         return expectProxyChangeAction(actualProxy -> proxy.equals(actualProxy));
2644     }
2645 
2646     private ExpectedBroadcast expectProxyChangeAction(Predicate<ProxyInfo> tester) {
2647         return registerBroadcastReceiverThat(PROXY_CHANGE_ACTION, 1, intent -> {
2648             final ProxyInfo actualProxy = (ProxyInfo) intent.getExtra(Proxy.EXTRA_PROXY_INFO,
2649                     ProxyInfo.buildPacProxy(Uri.EMPTY));
2650             return tester.test(actualProxy);
2651         });
2652     }
2653 
2654     private boolean extraInfoInBroadcastHasExpectedNullness(NetworkInfo ni) {
2655         final DetailedState state = ni.getDetailedState();
2656         if (state == DetailedState.CONNECTED && ni.getExtraInfo() == null) return false;
2657         // Expect a null extraInfo if the network is CONNECTING, because a CONNECTIVITY_ACTION
2658         // broadcast with a state of CONNECTING only happens due to legacy VPN lockdown, which also
2659         // nulls out extraInfo.
2660         if (state == DetailedState.CONNECTING && ni.getExtraInfo() != null) return false;
2661         // Can't make any assertions about DISCONNECTED broadcasts. When a network actually
2662         // disconnects, disconnectAndDestroyNetwork sets its state to DISCONNECTED and its extraInfo
2663         // to null. But if the DISCONNECTED broadcast is just simulated by LegacyTypeTracker due to
2664         // a network switch, extraInfo will likely be populated.
2665         // This is likely a bug in CS, but likely not one we can fix without impacting apps.
2666         return true;
2667     }
2668 
2669     @Test
2670     public void testNetworkFeature() throws Exception {
2671         // Connect the cell agent and wait for the connected broadcast.
2672         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
2673         mCellAgent.addCapability(NET_CAPABILITY_SUPL);
2674         ExpectedBroadcast b = expectConnectivityAction(TYPE_MOBILE, DetailedState.CONNECTED);
2675         mCellAgent.connect(true);
2676         b.expectBroadcast();
2677 
2678         // Build legacy request for SUPL.
2679         final NetworkCapabilities legacyCaps = new NetworkCapabilities();
2680         legacyCaps.addTransportType(TRANSPORT_CELLULAR);
2681         legacyCaps.addCapability(NET_CAPABILITY_SUPL);
2682         final NetworkRequest legacyRequest = new NetworkRequest(legacyCaps, TYPE_MOBILE_SUPL,
2683                 ConnectivityManager.REQUEST_ID_UNSET, NetworkRequest.Type.REQUEST);
2684 
2685         // File request, withdraw it and make sure no broadcast is sent
2686         b = expectConnectivityAction(1);
2687         final TestNetworkCallback callback = new TestNetworkCallback();
2688         mCm.requestNetwork(legacyRequest, callback);
2689         callback.expect(AVAILABLE, mCellAgent);
2690         mCm.unregisterNetworkCallback(callback);
2691         b.expectNoBroadcast(800);  // 800ms long enough to at least flake if this is sent
2692 
2693         // Disconnect the network and expect mobile disconnected broadcast.
2694         b = expectConnectivityAction(TYPE_MOBILE, DetailedState.DISCONNECTED);
2695         mCellAgent.disconnect();
2696         b.expectBroadcast();
2697     }
2698 
2699     @Test
2700     public void testLingering() throws Exception {
2701         verifyNoNetwork();
2702         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
2703         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
2704         assertNull(mCm.getActiveNetworkInfo());
2705         assertNull(mCm.getActiveNetwork());
2706         // Test bringing up validated cellular.
2707         ExpectedBroadcast b = expectConnectivityAction(TYPE_MOBILE, DetailedState.CONNECTED);
2708         mCellAgent.connect(true);
2709         b.expectBroadcast();
2710         verifyActiveNetwork(TRANSPORT_CELLULAR);
2711         assertLength(2, mCm.getAllNetworks());
2712         assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork())
2713                 || mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork()));
2714         assertTrue(mCm.getAllNetworks()[0].equals(mWiFiAgent.getNetwork())
2715                 || mCm.getAllNetworks()[1].equals(mWiFiAgent.getNetwork()));
2716         // Test bringing up validated WiFi.
2717         b = expectConnectivityAction(2);
2718         mWiFiAgent.connect(true);
2719         b.expectBroadcast();
2720         verifyActiveNetwork(TRANSPORT_WIFI);
2721         assertLength(2, mCm.getAllNetworks());
2722         assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork())
2723                 || mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork()));
2724         assertTrue(mCm.getAllNetworks()[0].equals(mCellAgent.getNetwork())
2725                 || mCm.getAllNetworks()[1].equals(mCellAgent.getNetwork()));
2726         // Test cellular linger timeout.
2727         mCellAgent.expectDisconnected();
2728         waitForIdle();
2729         assertLength(1, mCm.getAllNetworks());
2730         verifyActiveNetwork(TRANSPORT_WIFI);
2731         assertLength(1, mCm.getAllNetworks());
2732         assertEquals(mCm.getAllNetworks()[0], mCm.getActiveNetwork());
2733         // Test WiFi disconnect.
2734         b = expectConnectivityAction(1);
2735         mWiFiAgent.disconnect();
2736         b.expectBroadcast();
2737         verifyNoNetwork();
2738     }
2739 
2740     /**
2741      * Verify a newly created network will be inactive instead of torn down even if no one is
2742      * requesting.
2743      */
2744     @Test
2745     public void testNewNetworkInactive() throws Exception {
2746         // Create a callback that monitoring the testing network.
2747         final TestNetworkCallback listenCallback = new TestNetworkCallback();
2748         mCm.registerNetworkCallback(new NetworkRequest.Builder().build(), listenCallback);
2749 
2750         // 1. Create a network that is not requested by anyone, and does not satisfy any of the
2751         // default requests. Verify that the network will be inactive instead of torn down.
2752         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
2753         mWiFiAgent.connectWithoutInternet();
2754         listenCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
2755         listenCallback.assertNoCallback();
2756 
2757         // Verify that the network will be torn down after nascent expiry. A small period of time
2758         // is added in case of flakiness.
2759         final int nascentTimeoutMs =
2760                 mService.mNascentDelayMs + mService.mNascentDelayMs / 4;
2761         listenCallback.expect(LOST, mWiFiAgent, nascentTimeoutMs);
2762 
2763         // 2. Create a network that is satisfied by a request comes later.
2764         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
2765         mWiFiAgent.connectWithoutInternet();
2766         listenCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
2767         final NetworkRequest wifiRequest = new NetworkRequest.Builder()
2768                 .addTransportType(TRANSPORT_WIFI).build();
2769         final TestNetworkCallback wifiCallback = new TestNetworkCallback();
2770         mCm.requestNetwork(wifiRequest, wifiCallback);
2771         wifiCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
2772 
2773         // Verify that the network will be kept since the request is still satisfied. And is able
2774         // to get disconnected as usual if the request is released after the nascent timer expires.
2775         listenCallback.assertNoCallback(nascentTimeoutMs);
2776         mCm.unregisterNetworkCallback(wifiCallback);
2777         listenCallback.expect(LOST, mWiFiAgent);
2778 
2779         // 3. Create a network that is satisfied by a request comes later.
2780         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
2781         mWiFiAgent.connectWithoutInternet();
2782         listenCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
2783         mCm.requestNetwork(wifiRequest, wifiCallback);
2784         wifiCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
2785 
2786         // Verify that the network will still be torn down after the request gets removed.
2787         mCm.unregisterNetworkCallback(wifiCallback);
2788         listenCallback.expect(LOST, mWiFiAgent);
2789 
2790         // There is no need to ensure that LOSING is never sent in the common case that the
2791         // network immediately satisfies a request that was already present, because it is already
2792         // verified anywhere whenever {@code TestNetworkCallback#expectAvailable*} is called.
2793 
2794         mCm.unregisterNetworkCallback(listenCallback);
2795     }
2796 
2797     /**
2798      * Verify a newly created network will be inactive and switch to background if only background
2799      * request is satisfied.
2800      */
2801     @Test
2802     public void testNewNetworkInactive_bgNetwork() throws Exception {
2803         // Create a callback that monitoring the wifi network.
2804         final TestNetworkCallback wifiListenCallback = new TestNetworkCallback();
2805         mCm.registerNetworkCallback(new NetworkRequest.Builder()
2806                 .addTransportType(TRANSPORT_WIFI).build(), wifiListenCallback);
2807 
2808         // Create callbacks that can monitor background and foreground mobile networks.
2809         // This is done by granting using background networks permission before registration. Thus,
2810         // the service will not add {@code NET_CAPABILITY_FOREGROUND} by default.
2811         grantUsingBackgroundNetworksPermissionForUid(Binder.getCallingUid());
2812         final TestNetworkCallback bgMobileListenCallback = new TestNetworkCallback();
2813         final TestNetworkCallback fgMobileListenCallback = new TestNetworkCallback();
2814         mCm.registerNetworkCallback(new NetworkRequest.Builder()
2815                 .addTransportType(TRANSPORT_CELLULAR).build(), bgMobileListenCallback);
2816         mCm.registerNetworkCallback(new NetworkRequest.Builder()
2817                 .addTransportType(TRANSPORT_CELLULAR)
2818                 .addCapability(NET_CAPABILITY_FOREGROUND).build(), fgMobileListenCallback);
2819 
2820         // Connect wifi, which satisfies default request.
2821         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
2822         mWiFiAgent.connect(true);
2823         wifiListenCallback.expectAvailableThenValidatedCallbacks(mWiFiAgent);
2824 
2825         // Connect a cellular network, verify that satisfies only the background callback.
2826         setAlwaysOnNetworks(true);
2827         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
2828         mCellAgent.connect(true);
2829         bgMobileListenCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
2830         fgMobileListenCallback.assertNoCallback();
2831         assertFalse(isForegroundNetwork(mCellAgent));
2832 
2833         mCellAgent.disconnect();
2834         bgMobileListenCallback.expect(LOST, mCellAgent);
2835         fgMobileListenCallback.assertNoCallback();
2836 
2837         mCm.unregisterNetworkCallback(wifiListenCallback);
2838         mCm.unregisterNetworkCallback(bgMobileListenCallback);
2839         mCm.unregisterNetworkCallback(fgMobileListenCallback);
2840     }
2841 
2842     @Test
2843     public void testBinderDeathAfterUnregister() throws Exception {
2844         final NetworkCapabilities caps = new NetworkCapabilities.Builder()
2845                 .addTransportType(TRANSPORT_WIFI)
2846                 .build();
2847         final Handler handler = new Handler(ConnectivityThread.getInstanceLooper());
2848         final Messenger messenger = new Messenger(handler);
2849         final CompletableFuture<Binder.DeathRecipient> deathRecipient = new CompletableFuture<>();
2850         final Binder binder = new Binder() {
2851             private DeathRecipient mDeathRecipient;
2852             @Override
2853             public void linkToDeath(@NonNull final DeathRecipient recipient, final int flags) {
2854                 synchronized (this) {
2855                     mDeathRecipient = recipient;
2856                 }
2857                 super.linkToDeath(recipient, flags);
2858                 deathRecipient.complete(recipient);
2859             }
2860 
2861             @Override
2862             public boolean unlinkToDeath(@NonNull final DeathRecipient recipient, final int flags) {
2863                 synchronized (this) {
2864                     if (null == mDeathRecipient) {
2865                         throw new IllegalStateException();
2866                     }
2867                     mDeathRecipient = null;
2868                 }
2869                 return super.unlinkToDeath(recipient, flags);
2870             }
2871         };
2872         final NetworkRequest request = mService.listenForNetwork(caps, messenger, binder,
2873                 NetworkCallback.FLAG_NONE, mContext.getOpPackageName(),
2874                 mContext.getAttributionTag());
2875         mService.releaseNetworkRequest(request);
2876         deathRecipient.get().binderDied();
2877         // Wait for the release message to be processed.
2878         waitForIdle();
2879         // After waitForIdle(), the message was processed and the service didn't crash.
2880     }
2881 
2882     // TODO : migrate to @Parameterized
2883     @Test
2884     public void testValidatedCellularOutscoresUnvalidatedWiFi_CanTimeShare() throws Exception {
2885         // The behavior of this test should be the same whether the radio can time share or not.
2886         doTestValidatedCellularOutscoresUnvalidatedWiFi(true);
2887     }
2888 
2889     // TODO : migrate to @Parameterized
2890     @Test
2891     public void testValidatedCellularOutscoresUnvalidatedWiFi_CannotTimeShare() throws Exception {
2892         doTestValidatedCellularOutscoresUnvalidatedWiFi(false);
2893     }
2894 
2895     private void doTestValidatedCellularOutscoresUnvalidatedWiFi(
2896             final boolean cellRadioTimesharingCapable) throws Exception {
2897         mService.mCellularRadioTimesharingCapable = cellRadioTimesharingCapable;
2898         // Test bringing up unvalidated WiFi
2899         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
2900         ExpectedBroadcast b = expectConnectivityAction(1);
2901         mWiFiAgent.connect(false);
2902         b.expectBroadcast();
2903         verifyActiveNetwork(TRANSPORT_WIFI);
2904         // Test bringing up unvalidated cellular
2905         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
2906         mCellAgent.connect(false);
2907         waitForIdle();
2908         verifyActiveNetwork(TRANSPORT_WIFI);
2909         // Test cellular disconnect.
2910         mCellAgent.disconnect();
2911         waitForIdle();
2912         verifyActiveNetwork(TRANSPORT_WIFI);
2913         // Test bringing up validated cellular
2914         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
2915         b = expectConnectivityAction(2);
2916         mCellAgent.connect(true);
2917         b.expectBroadcast();
2918         verifyActiveNetwork(TRANSPORT_CELLULAR);
2919         // Test cellular disconnect.
2920         b = expectConnectivityAction(2);
2921         mCellAgent.disconnect();
2922         b.expectBroadcast();
2923         verifyActiveNetwork(TRANSPORT_WIFI);
2924         // Test WiFi disconnect.
2925         b = expectConnectivityAction(1);
2926         mWiFiAgent.disconnect();
2927         b.expectBroadcast();
2928         verifyNoNetwork();
2929     }
2930 
2931     // TODO : migrate to @Parameterized
2932     @Test
2933     public void testUnvalidatedWifiOutscoresUnvalidatedCellular_CanTimeShare() throws Exception {
2934         doTestUnvalidatedWifiOutscoresUnvalidatedCellular(true);
2935     }
2936 
2937     // TODO : migrate to @Parameterized
2938     @Test
2939     public void testUnvalidatedWifiOutscoresUnvalidatedCellular_CannotTimeShare() throws Exception {
2940         doTestUnvalidatedWifiOutscoresUnvalidatedCellular(false);
2941     }
2942 
2943     private void doTestUnvalidatedWifiOutscoresUnvalidatedCellular(
2944             final boolean cellRadioTimesharingCapable) throws Exception {
2945         mService.mCellularRadioTimesharingCapable = cellRadioTimesharingCapable;
2946         // Test bringing up unvalidated cellular.
2947         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
2948         ExpectedBroadcast b = expectConnectivityAction(1);
2949         mCellAgent.connect(false);
2950         b.expectBroadcast();
2951         verifyActiveNetwork(TRANSPORT_CELLULAR);
2952         // Test bringing up unvalidated WiFi.
2953         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
2954         b = expectConnectivityAction(2);
2955         mWiFiAgent.connect(false);
2956         b.expectBroadcast();
2957         verifyActiveNetwork(TRANSPORT_WIFI);
2958         // Test WiFi disconnect.
2959         b = expectConnectivityAction(2);
2960         mWiFiAgent.disconnect();
2961         b.expectBroadcast();
2962         verifyActiveNetwork(TRANSPORT_CELLULAR);
2963         // Test cellular disconnect.
2964         b = expectConnectivityAction(1);
2965         mCellAgent.disconnect();
2966         b.expectBroadcast();
2967         verifyNoNetwork();
2968     }
2969 
2970     // TODO : migrate to @Parameterized
2971     @Test
2972     public void testUnlingeringDoesNotValidate_CanTimeShare() throws Exception {
2973         doTestUnlingeringDoesNotValidate(true);
2974     }
2975 
2976     // TODO : migrate to @Parameterized
2977     @Test
2978     public void testUnlingeringDoesNotValidate_CannotTimeShare() throws Exception {
2979         doTestUnlingeringDoesNotValidate(false);
2980     }
2981 
2982     private void doTestUnlingeringDoesNotValidate(
2983             final boolean cellRadioTimesharingCapable) throws Exception {
2984         mService.mCellularRadioTimesharingCapable = cellRadioTimesharingCapable;
2985         // Test bringing up unvalidated WiFi.
2986         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
2987         ExpectedBroadcast b = expectConnectivityAction(1);
2988         mWiFiAgent.connect(false);
2989         b.expectBroadcast();
2990         verifyActiveNetwork(TRANSPORT_WIFI);
2991         assertFalse(mCm.getNetworkCapabilities(mWiFiAgent.getNetwork()).hasCapability(
2992                 NET_CAPABILITY_VALIDATED));
2993         // Test bringing up validated cellular.
2994         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
2995         b = expectConnectivityAction(2);
2996         mCellAgent.connect(true);
2997         b.expectBroadcast();
2998         verifyActiveNetwork(TRANSPORT_CELLULAR);
2999         assertFalse(mCm.getNetworkCapabilities(mWiFiAgent.getNetwork()).hasCapability(
3000                 NET_CAPABILITY_VALIDATED));
3001         // Test cellular disconnect.
3002         b = expectConnectivityAction(2);
3003         mCellAgent.disconnect();
3004         b.expectBroadcast();
3005         verifyActiveNetwork(TRANSPORT_WIFI);
3006         // Unlingering a network should not cause it to be marked as validated.
3007         assertFalse(mCm.getNetworkCapabilities(mWiFiAgent.getNetwork()).hasCapability(
3008                 NET_CAPABILITY_VALIDATED));
3009     }
3010 
3011     // TODO : migrate to @Parameterized
3012     @Test
3013     public void testRequestMigrationToSameTransport_CanTimeShare() throws Exception {
3014         // Simulate a device where the cell radio is capable of time sharing
3015         mService.mCellularRadioTimesharingCapable = true;
3016         doTestRequestMigrationToSameTransport(TRANSPORT_CELLULAR, true);
3017         doTestRequestMigrationToSameTransport(TRANSPORT_WIFI, true);
3018         doTestRequestMigrationToSameTransport(TRANSPORT_ETHERNET, true);
3019     }
3020 
3021     // TODO : migrate to @Parameterized
3022     @Test
3023     public void testRequestMigrationToSameTransport_CannotTimeShare() throws Exception {
3024         // Simulate a device where the cell radio is not capable of time sharing
3025         mService.mCellularRadioTimesharingCapable = false;
3026         doTestRequestMigrationToSameTransport(TRANSPORT_CELLULAR, false);
3027         doTestRequestMigrationToSameTransport(TRANSPORT_WIFI, true);
3028         doTestRequestMigrationToSameTransport(TRANSPORT_ETHERNET, true);
3029     }
3030 
3031     private void doTestRequestMigrationToSameTransport(final int transport,
3032             final boolean expectLingering) throws Exception {
3033         // To speed up tests the linger delay is very short by default in tests but this
3034         // test needs to make sure the delay is not incurred so a longer value is safer (it
3035         // reduces the risk that a bug exists but goes undetected). The alarm manager in the test
3036         // throws and crashes CS if this is set to anything more than the below constant though.
3037         mService.mLingerDelayMs = UNREASONABLY_LONG_ALARM_WAIT_MS;
3038 
3039         final TestNetworkCallback generalCb = new TestNetworkCallback();
3040         final TestNetworkCallback defaultCb = new TestNetworkCallback();
3041         mCm.registerNetworkCallback(
3042                 new NetworkRequest.Builder().addTransportType(transport).build(),
3043                 generalCb);
3044         mCm.registerDefaultNetworkCallback(defaultCb);
3045 
3046         // Bring up net agent 1
3047         final TestNetworkAgentWrapper net1 = new TestNetworkAgentWrapper(transport);
3048         net1.connect(true);
3049         // Make sure the default request is on net 1
3050         generalCb.expectAvailableThenValidatedCallbacks(net1);
3051         defaultCb.expectAvailableThenValidatedCallbacks(net1);
3052 
3053         // Bring up net 2 with primary and mms
3054         final TestNetworkAgentWrapper net2 = new TestNetworkAgentWrapper(transport);
3055         net2.addCapability(NET_CAPABILITY_MMS);
3056         net2.setScore(new NetworkScore.Builder().setTransportPrimary(true).build());
3057         net2.connect(true);
3058 
3059         // Make sure the default request goes to net 2
3060         generalCb.expectAvailableCallbacksUnvalidated(net2);
3061         if (expectLingering) {
3062             generalCb.expectLosing(net1);
3063         }
3064         generalCb.expectCaps(net2, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
3065         defaultCb.expectAvailableDoubleValidatedCallbacks(net2);
3066 
3067         // Make sure cell 1 is unwanted immediately if the radio can't time share, but only
3068         // after some delay if it can.
3069         if (expectLingering) {
3070             net1.assertNotDisconnected(TEST_CALLBACK_TIMEOUT_MS); // always incurs the timeout
3071             generalCb.assertNoCallback();
3072             // assertNotDisconnected waited for TEST_CALLBACK_TIMEOUT_MS, so waiting for the
3073             // linger period gives TEST_CALLBACK_TIMEOUT_MS time for the event to process.
3074             net1.expectDisconnected(UNREASONABLY_LONG_ALARM_WAIT_MS);
3075         } else {
3076             net1.expectDisconnected(TEST_CALLBACK_TIMEOUT_MS);
3077         }
3078         net1.disconnect();
3079         generalCb.expect(LOST, net1);
3080 
3081         // Remove primary from net 2
3082         net2.setScore(new NetworkScore.Builder().build());
3083         // Request MMS
3084         final TestNetworkCallback mmsCallback = new TestNetworkCallback();
3085         mCm.requestNetwork(new NetworkRequest.Builder().addCapability(NET_CAPABILITY_MMS).build(),
3086                 mmsCallback);
3087         mmsCallback.expectAvailableCallbacksValidated(net2);
3088 
3089         // Bring up net 3 with primary but without MMS
3090         final TestNetworkAgentWrapper net3 = new TestNetworkAgentWrapper(transport);
3091         net3.setScore(new NetworkScore.Builder().setTransportPrimary(true).build());
3092         net3.connect(true);
3093 
3094         // Make sure default goes to net 3, but the MMS request doesn't
3095         generalCb.expectAvailableThenValidatedCallbacks(net3);
3096         defaultCb.expectAvailableDoubleValidatedCallbacks(net3);
3097         mmsCallback.assertNoCallback();
3098         net2.assertNotDisconnected(TEST_CALLBACK_TIMEOUT_MS); // Always incurs the timeout
3099 
3100         // Revoke MMS request and make sure net 2 is torn down with the appropriate delay
3101         mCm.unregisterNetworkCallback(mmsCallback);
3102         if (expectLingering) {
3103             // If the radio can time share, the linger delay hasn't elapsed yet, so apps will
3104             // get LOSING. If the radio can't time share, this is a hard loss, since the last
3105             // request keeping up this network has been removed and the network isn't lingering
3106             // for any other request.
3107             generalCb.expectLosing(net2);
3108             net2.assertNotDisconnected(TEST_CALLBACK_TIMEOUT_MS);
3109             // Timeout 0 because after a while LOST will actually arrive
3110             generalCb.assertNoCallback(0 /* timeoutMs */);
3111             net2.expectDisconnected(UNREASONABLY_LONG_ALARM_WAIT_MS);
3112         } else {
3113             net2.expectDisconnected(TEST_CALLBACK_TIMEOUT_MS);
3114         }
3115         net2.disconnect();
3116         generalCb.expect(LOST, net2);
3117         defaultCb.assertNoCallback();
3118 
3119         net3.disconnect();
3120         mCm.unregisterNetworkCallback(defaultCb);
3121         mCm.unregisterNetworkCallback(generalCb);
3122     }
3123 
3124     // TODO : migrate to @Parameterized
3125     @Test
3126     public void testCellularOutscoresWeakWifi_CanTimeShare() throws Exception {
3127         // The behavior of this test should be the same whether the radio can time share or not.
3128         doTestCellularOutscoresWeakWifi(true);
3129     }
3130 
3131     // TODO : migrate to @Parameterized
3132     @Test
3133     public void testCellularOutscoresWeakWifi_CannotTimeShare() throws Exception {
3134         doTestCellularOutscoresWeakWifi(false);
3135     }
3136 
3137     private void doTestCellularOutscoresWeakWifi(
3138             final boolean cellRadioTimesharingCapable) throws Exception {
3139         mService.mCellularRadioTimesharingCapable = cellRadioTimesharingCapable;
3140         // Test bringing up validated cellular.
3141         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
3142         ExpectedBroadcast b = expectConnectivityAction(1);
3143         mCellAgent.connect(true);
3144         b.expectBroadcast();
3145         verifyActiveNetwork(TRANSPORT_CELLULAR);
3146         // Test bringing up validated WiFi.
3147         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3148         b = expectConnectivityAction(2);
3149         mWiFiAgent.connect(true);
3150         b.expectBroadcast();
3151         verifyActiveNetwork(TRANSPORT_WIFI);
3152         // Test WiFi getting really weak.
3153         b = expectConnectivityAction(2);
3154         mWiFiAgent.adjustScore(-11);
3155         b.expectBroadcast();
3156         verifyActiveNetwork(TRANSPORT_CELLULAR);
3157         // Test WiFi restoring signal strength.
3158         b = expectConnectivityAction(2);
3159         mWiFiAgent.adjustScore(11);
3160         b.expectBroadcast();
3161         verifyActiveNetwork(TRANSPORT_WIFI);
3162     }
3163 
3164     // TODO : migrate to @Parameterized
3165     @Test
3166     public void testReapingNetwork_CanTimeShare() throws Exception {
3167         doTestReapingNetwork(true);
3168     }
3169 
3170     // TODO : migrate to @Parameterized
3171     @Test
3172     public void testReapingNetwork_CannotTimeShare() throws Exception {
3173         doTestReapingNetwork(false);
3174     }
3175 
3176     private void doTestReapingNetwork(
3177             final boolean cellRadioTimesharingCapable) throws Exception {
3178         mService.mCellularRadioTimesharingCapable = cellRadioTimesharingCapable;
3179         // Test bringing up WiFi without NET_CAPABILITY_INTERNET.
3180         // Expect it to be torn down immediately because it satisfies no requests.
3181         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3182         mWiFiAgent.connectWithoutInternet();
3183         mWiFiAgent.expectDisconnected();
3184         // Test bringing up cellular without NET_CAPABILITY_INTERNET.
3185         // Expect it to be torn down immediately because it satisfies no requests.
3186         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3187         mCellAgent.connectWithoutInternet();
3188         mCellAgent.expectDisconnected();
3189         // Test bringing up validated WiFi.
3190         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3191         final ExpectedBroadcast b = expectConnectivityAction(TYPE_WIFI, DetailedState.CONNECTED);
3192         mWiFiAgent.connect(true);
3193         b.expectBroadcast();
3194         verifyActiveNetwork(TRANSPORT_WIFI);
3195         // Test bringing up unvalidated cellular.
3196         // Expect it to be torn down because it could never be the highest scoring network
3197         // satisfying the default request even if it validated.
3198         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
3199         mCellAgent.connect(false);
3200         mCellAgent.expectDisconnected();
3201         verifyActiveNetwork(TRANSPORT_WIFI);
3202         mWiFiAgent.disconnect();
3203         mWiFiAgent.expectDisconnected();
3204     }
3205 
3206     // TODO : migrate to @Parameterized
3207     @Test
3208     public void testCellularFallback_CanTimeShare() throws Exception {
3209         doTestCellularFallback(true);
3210     }
3211 
3212     // TODO : migrate to @Parameterized
3213     @Test
3214     public void testCellularFallback_CannotTimeShare() throws Exception {
3215         doTestCellularFallback(false);
3216     }
3217 
3218     private void doTestCellularFallback(
3219             final boolean cellRadioTimesharingCapable) throws Exception {
3220         mService.mCellularRadioTimesharingCapable = cellRadioTimesharingCapable;
3221         // Test bringing up validated cellular.
3222         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
3223         ExpectedBroadcast b = expectConnectivityAction(1);
3224         mCellAgent.connect(true);
3225         b.expectBroadcast();
3226         verifyActiveNetwork(TRANSPORT_CELLULAR);
3227         // Test bringing up validated WiFi.
3228         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3229         b = expectConnectivityAction(2);
3230         mWiFiAgent.connect(true);
3231         b.expectBroadcast();
3232         verifyActiveNetwork(TRANSPORT_WIFI);
3233         // Reevaluate WiFi (it'll instantly fail DNS).
3234         b = expectConnectivityAction(2);
3235         assertTrue(mCm.getNetworkCapabilities(mWiFiAgent.getNetwork()).hasCapability(
3236                 NET_CAPABILITY_VALIDATED));
3237         mCm.reportBadNetwork(mWiFiAgent.getNetwork());
3238         // Should quickly fall back to Cellular.
3239         b.expectBroadcast();
3240         assertFalse(mCm.getNetworkCapabilities(mWiFiAgent.getNetwork()).hasCapability(
3241                 NET_CAPABILITY_VALIDATED));
3242         verifyActiveNetwork(TRANSPORT_CELLULAR);
3243         // Reevaluate cellular (it'll instantly fail DNS).
3244         b = expectConnectivityAction(2);
3245         assertTrue(mCm.getNetworkCapabilities(mCellAgent.getNetwork()).hasCapability(
3246                 NET_CAPABILITY_VALIDATED));
3247         mCm.reportBadNetwork(mCellAgent.getNetwork());
3248         // Should quickly fall back to WiFi.
3249         b.expectBroadcast();
3250         assertFalse(mCm.getNetworkCapabilities(mCellAgent.getNetwork()).hasCapability(
3251                 NET_CAPABILITY_VALIDATED));
3252         assertFalse(mCm.getNetworkCapabilities(mWiFiAgent.getNetwork()).hasCapability(
3253                 NET_CAPABILITY_VALIDATED));
3254         verifyActiveNetwork(TRANSPORT_WIFI);
3255     }
3256 
3257     // TODO : migrate to @Parameterized
3258     @Test
3259     public void testWiFiFallback_CanTimeShare() throws Exception {
3260         doTestWiFiFallback(true);
3261     }
3262 
3263     // TODO : migrate to @Parameterized
3264     @Test
3265     public void testWiFiFallback_CannotTimeShare() throws Exception {
3266         doTestWiFiFallback(false);
3267     }
3268 
3269     private void doTestWiFiFallback(
3270             final boolean cellRadioTimesharingCapable) throws Exception {
3271         mService.mCellularRadioTimesharingCapable = cellRadioTimesharingCapable;
3272         // Test bringing up unvalidated WiFi.
3273         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3274         ExpectedBroadcast b = expectConnectivityAction(1);
3275         mWiFiAgent.connect(false);
3276         b.expectBroadcast();
3277         verifyActiveNetwork(TRANSPORT_WIFI);
3278         // Test bringing up validated cellular.
3279         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
3280         b = expectConnectivityAction(2);
3281         mCellAgent.connect(true);
3282         b.expectBroadcast();
3283         verifyActiveNetwork(TRANSPORT_CELLULAR);
3284         // Reevaluate cellular (it'll instantly fail DNS).
3285         b = expectConnectivityAction(2);
3286         assertTrue(mCm.getNetworkCapabilities(mCellAgent.getNetwork()).hasCapability(
3287                 NET_CAPABILITY_VALIDATED));
3288         mCm.reportBadNetwork(mCellAgent.getNetwork());
3289         // Should quickly fall back to WiFi.
3290         b.expectBroadcast();
3291         assertFalse(mCm.getNetworkCapabilities(mCellAgent.getNetwork()).hasCapability(
3292                 NET_CAPABILITY_VALIDATED));
3293         verifyActiveNetwork(TRANSPORT_WIFI);
3294     }
3295 
3296     @Test
3297     public void testRequiresValidation() {
3298         assertTrue(NetworkMonitorUtils.isValidationRequired(false /* isDunValidationRequired */,
3299                 false /* isVpnValidationRequired */,
3300                 mCm.getDefaultRequest().networkCapabilities));
3301     }
3302 
3303     /**
3304      * Utility NetworkCallback for testing. The caller must explicitly test for all the callbacks
3305      * this class receives, by calling expect() exactly once each time a callback is
3306      * received. assertNoCallback may be called at any time.
3307      */
3308     private class TestNetworkCallback extends TestableNetworkCallback {
3309         TestNetworkCallback() {
3310             // In the context of this test, the testable network callbacks should use waitForIdle
3311             // before calling assertNoCallback in an effort to detect issues where a callback is
3312             // not yet sent but a message currently in the queue of a handler will cause it to
3313             // be sent soon.
3314             super(TEST_CALLBACK_TIMEOUT_MS, TEST_CALLBACK_TIMEOUT_MS,
3315                     ConnectivityServiceTest.this::waitForIdle);
3316         }
3317 
3318         public CallbackEntry.Losing expectLosing(final HasNetwork n, final long timeoutMs) {
3319             final CallbackEntry.Losing losing = expect(LOSING, n, timeoutMs);
3320             final int maxMsToLive = losing.getMaxMsToLive();
3321             if (maxMsToLive < 0 || maxMsToLive > mService.mLingerDelayMs) {
3322                 // maxMsToLive is the value that was received in the onLosing callback. That must
3323                 // not be negative, so check that.
3324                 // Also, maxMsToLive is the remaining time until the network expires.
3325                 // mService.mLingerDelayMs is how long the network takes from when it's first
3326                 // detected to be unneeded to when it expires, so maxMsToLive should never
3327                 // be greater than that.
3328                 fail(String.format("Invalid linger time value %d, must be between %d and %d",
3329                         maxMsToLive, 0, mService.mLingerDelayMs));
3330             }
3331             return losing;
3332         }
3333 
3334         public CallbackEntry.Losing expectLosing(final HasNetwork n) {
3335             return expectLosing(n, getDefaultTimeoutMs());
3336         }
3337     }
3338 
3339     // Can't be part of TestNetworkCallback because "cannot be declared static; static methods can
3340     // only be declared in a static or top level type".
3341     static void assertNoCallbacks(final long timeoutMs, TestNetworkCallback ... callbacks) {
3342         for (TestNetworkCallback c : callbacks) {
3343             c.assertNoCallback(timeoutMs);
3344         }
3345     }
3346 
3347     static void assertNoCallbacks(TestNetworkCallback ... callbacks) {
3348         for (TestNetworkCallback c : callbacks) {
3349             c.assertNoCallback(); // each callback uses its own timeout
3350         }
3351     }
3352 
3353     static void expectOnLost(TestNetworkAgentWrapper network, TestNetworkCallback ... callbacks) {
3354         for (TestNetworkCallback c : callbacks) {
3355             c.expect(LOST, network);
3356         }
3357     }
3358 
3359     static void expectAvailableCallbacksUnvalidatedWithSpecifier(TestNetworkAgentWrapper network,
3360             NetworkSpecifier specifier, TestNetworkCallback ... callbacks) {
3361         for (TestNetworkCallback c : callbacks) {
3362             c.expect(AVAILABLE, network);
3363             c.expectCaps(network, cb -> !cb.hasCapability(NET_CAPABILITY_VALIDATED)
3364                     && Objects.equals(specifier, cb.getNetworkSpecifier()));
3365             c.expect(LINK_PROPERTIES_CHANGED, network);
3366             c.expect(BLOCKED_STATUS, network);
3367         }
3368     }
3369 
3370     @Test
3371     public void testNetworkDoesntMatchRequestsUntilConnected() throws Exception {
3372         final TestNetworkCallback cb = new TestNetworkCallback();
3373         final NetworkRequest wifiRequest = new NetworkRequest.Builder()
3374                 .addTransportType(TRANSPORT_WIFI).build();
3375         mCm.requestNetwork(wifiRequest, cb);
3376         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3377         // Updating the score triggers a rematch.
3378         mWiFiAgent.setScore(new NetworkScore.Builder().build());
3379         cb.assertNoCallback();
3380         mWiFiAgent.connect(false);
3381         cb.expectAvailableCallbacksUnvalidated(mWiFiAgent);
3382         cb.assertNoCallback();
3383         mCm.unregisterNetworkCallback(cb);
3384     }
3385 
3386     @Test
3387     public void testNetworkNotVisibleUntilConnected() throws Exception {
3388         final TestNetworkCallback cb = new TestNetworkCallback();
3389         final NetworkRequest wifiRequest = new NetworkRequest.Builder()
3390                 .addTransportType(TRANSPORT_WIFI).build();
3391         mCm.registerNetworkCallback(wifiRequest, cb);
3392         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3393         final NetworkCapabilities nc = mWiFiAgent.getNetworkCapabilities();
3394         nc.addCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED);
3395         mWiFiAgent.setNetworkCapabilities(nc, true /* sendToConnectivityService */);
3396         cb.assertNoCallback();
3397         mWiFiAgent.connect(false);
3398         cb.expectAvailableCallbacksUnvalidated(mWiFiAgent);
3399         final CallbackEntry found = CollectionUtils.findLast(cb.getHistory(),
3400                 it -> it instanceof CallbackEntry.CapabilitiesChanged);
3401         assertTrue(((CallbackEntry.CapabilitiesChanged) found).getCaps()
3402                 .hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED));
3403         cb.assertNoCallback();
3404         mCm.unregisterNetworkCallback(cb);
3405     }
3406 
3407     @Test
3408     public void testStateChangeNetworkCallbacks() throws Exception {
3409         final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback();
3410         final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
3411         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
3412         final NetworkRequest genericRequest = new NetworkRequest.Builder()
3413                 .clearCapabilities().build();
3414         final NetworkRequest wifiRequest = new NetworkRequest.Builder()
3415                 .addTransportType(TRANSPORT_WIFI).build();
3416         final NetworkRequest cellRequest = new NetworkRequest.Builder()
3417                 .addTransportType(TRANSPORT_CELLULAR).build();
3418         mCm.registerNetworkCallback(genericRequest, genericNetworkCallback);
3419         mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
3420         mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
3421 
3422         // Test unvalidated networks
3423         ExpectedBroadcast b = expectConnectivityAction(1);
3424         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
3425         mCellAgent.connect(false);
3426         genericNetworkCallback.expectAvailableCallbacksUnvalidated(mCellAgent);
3427         cellNetworkCallback.expectAvailableCallbacksUnvalidated(mCellAgent);
3428         assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetwork());
3429         b.expectBroadcast();
3430         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
3431 
3432         // This should not trigger spurious onAvailable() callbacks, b/21762680.
3433         mCellAgent.adjustScore(-1);
3434         waitForIdle();
3435         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
3436         assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetwork());
3437 
3438         b = expectConnectivityAction(2);
3439         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3440         mWiFiAgent.connect(false);
3441         genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
3442         wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
3443         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetwork());
3444         b.expectBroadcast();
3445         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
3446 
3447         b = expectConnectivityAction(2);
3448         mWiFiAgent.disconnect();
3449         genericNetworkCallback.expect(CallbackEntry.LOST, mWiFiAgent);
3450         wifiNetworkCallback.expect(CallbackEntry.LOST, mWiFiAgent);
3451         cellNetworkCallback.assertNoCallback();
3452         b.expectBroadcast();
3453         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
3454 
3455         b = expectConnectivityAction(1);
3456         mCellAgent.disconnect();
3457         genericNetworkCallback.expect(CallbackEntry.LOST, mCellAgent);
3458         cellNetworkCallback.expect(CallbackEntry.LOST, mCellAgent);
3459         b.expectBroadcast();
3460         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
3461 
3462         // Test validated networks
3463         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
3464         mCellAgent.connect(true);
3465         genericNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
3466         cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
3467         assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetwork());
3468         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
3469 
3470         // This should not trigger spurious onAvailable() callbacks, b/21762680.
3471         mCellAgent.adjustScore(-1);
3472         waitForIdle();
3473         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
3474         assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetwork());
3475 
3476         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3477         mWiFiAgent.connect(true);
3478         genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
3479         genericNetworkCallback.expectLosing(mCellAgent);
3480         genericNetworkCallback.expectCaps(mWiFiAgent,
3481                 c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
3482         wifiNetworkCallback.expectAvailableThenValidatedCallbacks(mWiFiAgent);
3483         cellNetworkCallback.expectLosing(mCellAgent);
3484         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetwork());
3485         // Cell will disconnect after the lingering period. Before that elapses check that
3486         // there have been no callbacks.
3487         assertNoCallbacks(0 /* timeoutMs */,
3488                 genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
3489 
3490         mWiFiAgent.disconnect();
3491         genericNetworkCallback.expect(LOST, mWiFiAgent);
3492         wifiNetworkCallback.expect(LOST, mWiFiAgent);
3493         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
3494 
3495         mCellAgent.disconnect();
3496         genericNetworkCallback.expect(LOST, mCellAgent);
3497         cellNetworkCallback.expect(LOST, mCellAgent);
3498         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
3499     }
3500 
3501     private void doNetworkCallbacksSanitizationTest(boolean sanitized) throws Exception {
3502         final TestNetworkCallback callback = new TestNetworkCallback();
3503         final TestNetworkCallback defaultCallback = new TestNetworkCallback();
3504         final NetworkRequest wifiRequest = new NetworkRequest.Builder()
3505                 .addTransportType(TRANSPORT_WIFI).build();
3506         mCm.registerNetworkCallback(wifiRequest, callback);
3507         mCm.registerDefaultNetworkCallback(defaultCallback);
3508 
3509         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3510         mWiFiAgent.connect(false);
3511         callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
3512         defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
3513 
3514         final LinkProperties newLp = new LinkProperties();
3515         final Uri capportUrl = Uri.parse("https://capport.example.com/api");
3516         final CaptivePortalData capportData = new CaptivePortalData.Builder()
3517                 .setCaptive(true).build();
3518 
3519         final Uri expectedCapportUrl = sanitized ? null : capportUrl;
3520         newLp.setCaptivePortalApiUrl(capportUrl);
3521         mWiFiAgent.sendLinkProperties(newLp);
3522         callback.expect(LINK_PROPERTIES_CHANGED, mWiFiAgent, cb ->
3523                 Objects.equals(expectedCapportUrl, cb.getLp().getCaptivePortalApiUrl()));
3524         defaultCallback.expect(LINK_PROPERTIES_CHANGED, mWiFiAgent, cb ->
3525                 Objects.equals(expectedCapportUrl, cb.getLp().getCaptivePortalApiUrl()));
3526 
3527         final CaptivePortalData expectedCapportData = sanitized ? null : capportData;
3528         mWiFiAgent.notifyCapportApiDataChanged(capportData);
3529         callback.expect(LINK_PROPERTIES_CHANGED, mWiFiAgent, cb ->
3530                 Objects.equals(expectedCapportData, cb.getLp().getCaptivePortalData()));
3531         defaultCallback.expect(LINK_PROPERTIES_CHANGED, mWiFiAgent, cb ->
3532                 Objects.equals(expectedCapportData, cb.getLp().getCaptivePortalData()));
3533 
3534         final LinkProperties lp = mCm.getLinkProperties(mWiFiAgent.getNetwork());
3535         assertEquals(expectedCapportUrl, lp.getCaptivePortalApiUrl());
3536         assertEquals(expectedCapportData, lp.getCaptivePortalData());
3537     }
3538 
3539     @Test
3540     public void networkCallbacksSanitizationTest_Sanitize() throws Exception {
3541         mServiceContext.setPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
3542                 PERMISSION_DENIED);
3543         mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_DENIED);
3544         doNetworkCallbacksSanitizationTest(true /* sanitized */);
3545     }
3546 
3547     @Test
3548     public void networkCallbacksSanitizationTest_NoSanitize_NetworkStack() throws Exception {
3549         mServiceContext.setPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
3550                 PERMISSION_GRANTED);
3551         mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_DENIED);
3552         doNetworkCallbacksSanitizationTest(false /* sanitized */);
3553     }
3554 
3555     @Test
3556     public void networkCallbacksSanitizationTest_NoSanitize_Settings() throws Exception {
3557         mServiceContext.setPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
3558                 PERMISSION_DENIED);
3559         mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_GRANTED);
3560         doNetworkCallbacksSanitizationTest(false /* sanitized */);
3561     }
3562 
3563     @Test
3564     public void testOwnerUidCannotChange() throws Exception {
3565         final NetworkCapabilities ncTemplate = new NetworkCapabilities();
3566         final int originalOwnerUid = Process.myUid();
3567         ncTemplate.setOwnerUid(originalOwnerUid);
3568 
3569         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, new LinkProperties(), ncTemplate);
3570         mWiFiAgent.connect(false);
3571         waitForIdle();
3572 
3573         // Send ConnectivityService an update to the mWiFiAgent's capabilities that changes
3574         // the owner UID and an unrelated capability.
3575         NetworkCapabilities agentCapabilities = mWiFiAgent.getNetworkCapabilities();
3576         assertEquals(originalOwnerUid, agentCapabilities.getOwnerUid());
3577         agentCapabilities.setOwnerUid(42);
3578         assertFalse(agentCapabilities.hasCapability(NET_CAPABILITY_NOT_CONGESTED));
3579         agentCapabilities.addCapability(NET_CAPABILITY_NOT_CONGESTED);
3580         mWiFiAgent.setNetworkCapabilities(agentCapabilities, true);
3581         waitForIdle();
3582 
3583         // Owner UIDs are not visible without location permission.
3584         setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
3585                 Manifest.permission.ACCESS_FINE_LOCATION);
3586 
3587         // Check that the capability change has been applied but the owner UID is not modified.
3588         NetworkCapabilities nc = mCm.getNetworkCapabilities(mWiFiAgent.getNetwork());
3589         assertEquals(originalOwnerUid, nc.getOwnerUid());
3590         assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_CONGESTED));
3591     }
3592 
3593     @Test
3594     public void testMultipleLingering() throws Exception {
3595         // This test would be flaky with the default 120ms timer: that is short enough that
3596         // lingered networks are torn down before assertions can be run. We don't want to mock the
3597         // lingering timer to keep the WakeupMessage logic realistic: this has already proven useful
3598         // in detecting races. Furthermore, sometimes the test is running while Phenotype is running
3599         // so hot that the test doesn't get the CPU for multiple hundreds of milliseconds, so this
3600         // needs to be suitably long.
3601         mService.mLingerDelayMs = 2_000;
3602 
3603         NetworkRequest request = new NetworkRequest.Builder()
3604                 .clearCapabilities().addCapability(NET_CAPABILITY_NOT_METERED)
3605                 .build();
3606         TestNetworkCallback callback = new TestNetworkCallback();
3607         mCm.registerNetworkCallback(request, callback);
3608 
3609         TestNetworkCallback defaultCallback = new TestNetworkCallback();
3610         mCm.registerDefaultNetworkCallback(defaultCallback);
3611 
3612         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
3613         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3614         mEthernetAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
3615 
3616         mCellAgent.addCapability(NET_CAPABILITY_NOT_METERED);
3617         mWiFiAgent.addCapability(NET_CAPABILITY_NOT_METERED);
3618         mEthernetAgent.addCapability(NET_CAPABILITY_NOT_METERED);
3619 
3620         mCellAgent.connect(true);
3621         callback.expectAvailableThenValidatedCallbacks(mCellAgent);
3622         defaultCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
3623         assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetwork());
3624         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
3625 
3626         mWiFiAgent.connect(true);
3627         // We get AVAILABLE on wifi when wifi connects and satisfies our unmetered request.
3628         // We then get LOSING when wifi validates and cell is outscored.
3629         callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
3630         // TODO: Investigate sending validated before losing.
3631         callback.expectLosing(mCellAgent);
3632         callback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
3633         defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiAgent);
3634         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetwork());
3635         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
3636 
3637         mEthernetAgent.connect(true);
3638         callback.expectAvailableCallbacksUnvalidated(mEthernetAgent);
3639         // TODO: Investigate sending validated before losing.
3640         callback.expectLosing(mWiFiAgent);
3641         callback.expectCaps(mEthernetAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
3642         defaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetAgent);
3643         assertEquals(mEthernetAgent.getNetwork(), mCm.getActiveNetwork());
3644         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
3645 
3646         mEthernetAgent.disconnect();
3647         callback.expect(LOST, mEthernetAgent);
3648         defaultCallback.expect(LOST, mEthernetAgent);
3649         defaultCallback.expectAvailableCallbacksValidated(mWiFiAgent);
3650         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
3651 
3652         for (int i = 0; i < 4; i++) {
3653             TestNetworkAgentWrapper oldNetwork, newNetwork;
3654             if (i % 2 == 0) {
3655                 mWiFiAgent.adjustScore(-15);
3656                 oldNetwork = mWiFiAgent;
3657                 newNetwork = mCellAgent;
3658             } else {
3659                 mWiFiAgent.adjustScore(15);
3660                 oldNetwork = mCellAgent;
3661                 newNetwork = mWiFiAgent;
3662 
3663             }
3664             callback.expectLosing(oldNetwork);
3665             // TODO: should we send an AVAILABLE callback to newNetwork, to indicate that it is no
3666             // longer lingering?
3667             defaultCallback.expectAvailableCallbacksValidated(newNetwork);
3668             assertEquals(newNetwork.getNetwork(), mCm.getActiveNetwork());
3669         }
3670         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetwork());
3671 
3672         // Verify that if a network no longer satisfies a request, we send LOST and not LOSING, even
3673         // if the network is still up.
3674         mWiFiAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
3675         // We expect a notification about the capabilities change, and nothing else.
3676         defaultCallback.expectCaps(mWiFiAgent, c -> !c.hasCapability(NET_CAPABILITY_NOT_METERED));
3677         defaultCallback.assertNoCallback();
3678         callback.expect(LOST, mWiFiAgent);
3679         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
3680 
3681         // Wifi no longer satisfies our listen, which is for an unmetered network.
3682         // But because its score is 55, it's still up (and the default network).
3683         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetwork());
3684 
3685         // Disconnect our test networks.
3686         mWiFiAgent.disconnect();
3687         defaultCallback.expect(LOST, mWiFiAgent);
3688         defaultCallback.expectAvailableCallbacksValidated(mCellAgent);
3689         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
3690         mCellAgent.disconnect();
3691         defaultCallback.expect(LOST, mCellAgent);
3692         waitForIdle();
3693         assertEquals(null, mCm.getActiveNetwork());
3694 
3695         mCm.unregisterNetworkCallback(callback);
3696         waitForIdle();
3697 
3698         // Check that a network is only lingered or torn down if it would not satisfy a request even
3699         // if it validated.
3700         request = new NetworkRequest.Builder().clearCapabilities().build();
3701         callback = new TestNetworkCallback();
3702 
3703         mCm.registerNetworkCallback(request, callback);
3704 
3705         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
3706         mCellAgent.connect(false);   // Score: 10
3707         callback.expectAvailableCallbacksUnvalidated(mCellAgent);
3708         defaultCallback.expectAvailableCallbacksUnvalidated(mCellAgent);
3709         assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetwork());
3710         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
3711 
3712         // Bring up wifi with a score of 20.
3713         // Cell stays up because it would satisfy the default request if it validated.
3714         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3715         mWiFiAgent.connect(false);   // Score: 20
3716         callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
3717         defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
3718         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetwork());
3719         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
3720 
3721         mWiFiAgent.disconnect();
3722         callback.expect(LOST, mWiFiAgent);
3723         defaultCallback.expect(LOST, mWiFiAgent);
3724         defaultCallback.expectAvailableCallbacksUnvalidated(mCellAgent);
3725         assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetwork());
3726         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
3727 
3728         // Bring up wifi, then validate it. Previous versions would immediately tear down cell, but
3729         // it's arguably correct to linger it, since it was the default network before it validated.
3730         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3731         mWiFiAgent.connect(true);
3732         callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
3733         // TODO: Investigate sending validated before losing.
3734         callback.expectLosing(mCellAgent);
3735         callback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
3736         defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiAgent);
3737         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetwork());
3738         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
3739 
3740         mWiFiAgent.disconnect();
3741         callback.expect(LOST, mWiFiAgent);
3742         defaultCallback.expect(LOST, mWiFiAgent);
3743         defaultCallback.expectAvailableCallbacksUnvalidated(mCellAgent);
3744         mCellAgent.disconnect();
3745         callback.expect(LOST, mCellAgent);
3746         defaultCallback.expect(LOST, mCellAgent);
3747         waitForIdle();
3748         assertEquals(null, mCm.getActiveNetwork());
3749 
3750         // If a network is lingering, and we add and remove a request from it, resume lingering.
3751         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
3752         mCellAgent.connect(true);
3753         callback.expectAvailableThenValidatedCallbacks(mCellAgent);
3754         defaultCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
3755         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
3756         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3757         mWiFiAgent.connect(true);
3758         defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiAgent);
3759         callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
3760         // TODO: Investigate sending validated before losing.
3761         callback.expectLosing(mCellAgent);
3762         callback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
3763         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
3764 
3765         NetworkRequest cellRequest = new NetworkRequest.Builder()
3766                 .addTransportType(TRANSPORT_CELLULAR).build();
3767         NetworkCallback noopCallback = new NetworkCallback();
3768         mCm.requestNetwork(cellRequest, noopCallback);
3769         // TODO: should this cause an AVAILABLE callback, to indicate that the network is no longer
3770         // lingering?
3771         mCm.unregisterNetworkCallback(noopCallback);
3772         callback.expectLosing(mCellAgent);
3773 
3774         // Similar to the above: lingering can start even after the lingered request is removed.
3775         // Disconnect wifi and switch to cell.
3776         mWiFiAgent.disconnect();
3777         callback.expect(LOST, mWiFiAgent);
3778         defaultCallback.expect(LOST, mWiFiAgent);
3779         defaultCallback.expectAvailableCallbacksValidated(mCellAgent);
3780         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
3781 
3782         // Cell is now the default network. Pin it with a cell-specific request.
3783         noopCallback = new NetworkCallback();  // Can't reuse NetworkCallbacks. http://b/20701525
3784         mCm.requestNetwork(cellRequest, noopCallback);
3785 
3786         // Now connect wifi, and expect it to become the default network.
3787         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3788         mWiFiAgent.connect(true);
3789         callback.expectAvailableThenValidatedCallbacks(mWiFiAgent);
3790         defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiAgent);
3791         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
3792         // The default request is lingering on cell, but nothing happens to cell, and we send no
3793         // callbacks for it, because it's kept up by cellRequest.
3794         callback.assertNoCallback();
3795         // Now unregister cellRequest and expect cell to start lingering.
3796         mCm.unregisterNetworkCallback(noopCallback);
3797         callback.expectLosing(mCellAgent);
3798 
3799         // Let linger run its course.
3800         callback.assertNoCallback(0 /* timeoutMs */);
3801         final int lingerTimeoutMs = mService.mLingerDelayMs + mService.mLingerDelayMs / 4;
3802         callback.expect(LOST, mCellAgent, lingerTimeoutMs);
3803 
3804         // Register a TRACK_DEFAULT request and check that it does not affect lingering.
3805         TestNetworkCallback trackDefaultCallback = new TestNetworkCallback();
3806         mCm.registerDefaultNetworkCallback(trackDefaultCallback);
3807         trackDefaultCallback.expectAvailableCallbacksValidated(mWiFiAgent);
3808         mEthernetAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
3809         mEthernetAgent.connect(true);
3810         callback.expectAvailableCallbacksUnvalidated(mEthernetAgent);
3811         callback.expectLosing(mWiFiAgent);
3812         callback.expectCaps(mEthernetAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
3813         trackDefaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetAgent);
3814         defaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetAgent);
3815         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
3816 
3817         // Let linger run its course.
3818         callback.expect(LOST, mWiFiAgent, lingerTimeoutMs);
3819 
3820         // Clean up.
3821         mEthernetAgent.disconnect();
3822         callback.expect(LOST, mEthernetAgent);
3823         defaultCallback.expect(LOST, mEthernetAgent);
3824         trackDefaultCallback.expect(LOST, mEthernetAgent);
3825 
3826         mCm.unregisterNetworkCallback(callback);
3827         mCm.unregisterNetworkCallback(defaultCallback);
3828         mCm.unregisterNetworkCallback(trackDefaultCallback);
3829     }
3830 
3831     private void grantUsingBackgroundNetworksPermissionForUid(final int uid) throws Exception {
3832         grantUsingBackgroundNetworksPermissionForUid(uid, mContext.getPackageName());
3833     }
3834 
3835     private void grantUsingBackgroundNetworksPermissionForUid(
3836             final int uid, final String packageName) throws Exception {
3837         doReturn(buildPackageInfo(true /* hasSystemPermission */, uid)).when(mPackageManager)
3838                 .getPackageInfo(eq(packageName), eq(GET_PERMISSIONS));
3839 
3840         // Send a broadcast indicating a package was installed.
3841         final Intent addedIntent = new Intent(ACTION_PACKAGE_ADDED);
3842         addedIntent.putExtra(Intent.EXTRA_UID, uid);
3843         addedIntent.setData(Uri.parse("package:" + packageName));
3844         processBroadcast(addedIntent);
3845     }
3846 
3847     @Test
3848     public void testNetworkGoesIntoBackgroundAfterLinger() throws Exception {
3849         setAlwaysOnNetworks(true);
3850         grantUsingBackgroundNetworksPermissionForUid(Binder.getCallingUid());
3851         NetworkRequest request = new NetworkRequest.Builder()
3852                 .clearCapabilities()
3853                 .build();
3854         TestNetworkCallback callback = new TestNetworkCallback();
3855         mCm.registerNetworkCallback(request, callback);
3856 
3857         TestNetworkCallback defaultCallback = new TestNetworkCallback();
3858         mCm.registerDefaultNetworkCallback(defaultCallback);
3859 
3860         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
3861         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3862 
3863         mCellAgent.connect(true);
3864         callback.expectAvailableThenValidatedCallbacks(mCellAgent);
3865         defaultCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
3866 
3867         // Wifi comes up and cell lingers.
3868         mWiFiAgent.connect(true);
3869         defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiAgent);
3870         callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
3871         callback.expectLosing(mCellAgent);
3872         callback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
3873 
3874         // File a request for cellular, then release it.
3875         NetworkRequest cellRequest = new NetworkRequest.Builder()
3876                 .addTransportType(TRANSPORT_CELLULAR).build();
3877         NetworkCallback noopCallback = new NetworkCallback();
3878         mCm.requestNetwork(cellRequest, noopCallback);
3879         mCm.unregisterNetworkCallback(noopCallback);
3880         callback.expectLosing(mCellAgent);
3881 
3882         // Let linger run its course.
3883         callback.assertNoCallback();
3884         final int lingerTimeoutMs = TEST_LINGER_DELAY_MS + TEST_LINGER_DELAY_MS / 4;
3885         callback.expectCaps(mCellAgent, lingerTimeoutMs,
3886                 c -> !c.hasCapability(NET_CAPABILITY_FOREGROUND));
3887 
3888         // Clean up.
3889         mCm.unregisterNetworkCallback(defaultCallback);
3890         mCm.unregisterNetworkCallback(callback);
3891     }
3892 
3893     /** Expects the specified notification and returns the notification ID. */
3894     private int expectNotification(TestNetworkAgentWrapper agent, NotificationType type) {
3895         verify(mNotificationManager, timeout(TIMEOUT_MS)).notify(
3896                 eq(NetworkNotificationManager.tagFor(agent.getNetwork().netId)),
3897                 eq(type.eventId), any());
3898         return type.eventId;
3899     }
3900 
3901     private void expectNoNotification(@NonNull final TestNetworkAgentWrapper agent) {
3902         verify(mNotificationManager, never()).notifyAsUser(anyString(), anyInt(), any(), any());
3903     }
3904 
3905     /**
3906      * Expects the specified notification happens when the unvalidated prompt message arrives
3907      *
3908      * @return the notification ID.
3909      **/
3910     private int expectUnvalidationCheckWillNotify(TestNetworkAgentWrapper agent,
3911             NotificationType type) {
3912         mService.scheduleEvaluationTimeout(agent.getNetwork(), 0 /* delayMs */);
3913         waitForIdle();
3914         return expectNotification(agent, type);
3915     }
3916 
3917     /**
3918      * Expects that the notification for the specified network is cleared.
3919      *
3920      * This generally happens when the network disconnects or when the newtwork validates. During
3921      * normal usage the notification is also cleared by the system when the notification is tapped.
3922      */
3923     private void expectClearNotification(TestNetworkAgentWrapper agent, NotificationType type) {
3924         verify(mNotificationManager, timeout(TIMEOUT_MS)).cancel(
3925                 eq(NetworkNotificationManager.tagFor(agent.getNetwork().netId)), eq(type.eventId));
3926     }
3927 
3928     /**
3929      * Expects that no notification happens when the unvalidated prompt message arrives
3930      *
3931      * @return the notification ID.
3932      **/
3933     private void expectUnvalidationCheckWillNotNotify(TestNetworkAgentWrapper agent) {
3934         mService.scheduleEvaluationTimeout(agent.getNetwork(), 0 /*delayMs */);
3935         waitForIdle();
3936         expectNoNotification(agent);
3937     }
3938 
3939     private void expectDisconnectAndClearNotifications(TestNetworkCallback callback,
3940             TestNetworkAgentWrapper agent, NotificationType type) {
3941         callback.expect(LOST, agent);
3942         expectClearNotification(agent, type);
3943     }
3944 
3945     private NativeNetworkConfig nativeNetworkConfigPhysical(int netId, int permission) {
3946         return new NativeNetworkConfig(netId, NativeNetworkType.PHYSICAL, permission,
3947                 /*secure=*/ false, VpnManager.TYPE_VPN_NONE, /*excludeLocalRoutes=*/ false);
3948     }
3949 
3950     private NativeNetworkConfig nativeNetworkConfigVpn(int netId, boolean secure, int vpnType) {
3951         return new NativeNetworkConfig(netId, NativeNetworkType.VIRTUAL, INetd.PERMISSION_NONE,
3952                 secure, vpnType, /*excludeLocalRoutes=*/ false);
3953     }
3954 
3955     @Test
3956     public void testNetworkAgentCallbacks() throws Exception {
3957         // Keeps track of the order of events that happen in this test.
3958         final LinkedBlockingQueue<String> eventOrder = new LinkedBlockingQueue<>();
3959 
3960         final NetworkRequest request = new NetworkRequest.Builder()
3961                 .addTransportType(TRANSPORT_WIFI).build();
3962         final TestNetworkCallback callback = new TestNetworkCallback();
3963 
3964         // Expectations for state when various callbacks fire. These expectations run on the handler
3965         // thread and not on the test thread because they need to prevent the handler thread from
3966         // advancing while they examine state.
3967 
3968         // 1. When onCreated fires, netd has been told to create the network.
3969         final Consumer<NetworkAgent> onNetworkCreated = (agent) -> {
3970             eventOrder.offer("onNetworkCreated");
3971             try {
3972                 verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
3973                         agent.getNetwork().getNetId(), INetd.PERMISSION_NONE));
3974             } catch (RemoteException impossible) {
3975                 fail();
3976             }
3977         };
3978 
3979         // 2. onNetworkUnwanted isn't precisely ordered with respect to any particular events. Just
3980         //    check that it is fired at some point after disconnect.
3981         final Consumer<NetworkAgent> onNetworkUnwanted = (agent) -> {
3982             eventOrder.offer("onNetworkUnwanted");
3983         };
3984 
3985         // 3. While the teardown timer is running, connectivity APIs report the network is gone, but
3986         //    netd has not yet been told to destroy it.
3987         final Consumer<Network> duringTeardown = (network) -> {
3988             eventOrder.offer("timePasses");
3989             assertNull(mCm.getLinkProperties(network));
3990             try {
3991                 verify(mMockNetd, never()).networkDestroy(network.getNetId());
3992             } catch (RemoteException impossible) {
3993                 fail();
3994             }
3995         };
3996 
3997         // 4. After onNetworkDisconnected is called, connectivity APIs report the network is gone,
3998         // and netd has been told to destroy it.
3999         final Consumer<NetworkAgent> onNetworkDisconnected = (agent) -> {
4000             eventOrder.offer("onNetworkDisconnected");
4001             assertNull(mCm.getLinkProperties(agent.getNetwork()));
4002             try {
4003                 verify(mMockNetd).networkDestroy(agent.getNetwork().getNetId());
4004             } catch (RemoteException impossible) {
4005                 fail();
4006             }
4007         };
4008 
4009         final NetworkAgentWrapper.Callbacks callbacks = new NetworkAgentWrapper.Callbacks(
4010                 onNetworkCreated, onNetworkUnwanted, onNetworkDisconnected);
4011 
4012         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, callbacks);
4013 
4014         if (mService.shouldCreateNetworksImmediately()) {
4015             assertEquals("onNetworkCreated", eventOrder.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
4016         } else {
4017             assertNull(eventOrder.poll());
4018         }
4019 
4020         // Connect a network, and file a request for it after it has come up, to ensure the nascent
4021         // timer is cleared and the test does not have to wait for it. Filing the request after the
4022         // network has come up is necessary because ConnectivityService does not appear to clear the
4023         // nascent timer if the first request satisfied by the network was filed before the network
4024         // connected.
4025         // TODO: fix this bug, file the request before connecting, and remove the waitForIdle.
4026         mWiFiAgent.connectWithoutInternet();
4027         if (!mService.shouldCreateNetworksImmediately()) {
4028             assertEquals("onNetworkCreated", eventOrder.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
4029         } else {
4030             waitForIdle();
4031             assertNull(eventOrder.poll());
4032         }
4033         mCm.requestNetwork(request, callback);
4034         callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
4035 
4036         // Set teardown delay and make sure CS has processed it.
4037         mWiFiAgent.getNetworkAgent().setTeardownDelayMillis(300);
4038         waitForIdle();
4039 
4040         // Post the duringTeardown lambda to the handler so it fires while teardown is in progress.
4041         // The delay must be long enough it will run after the unregisterNetworkCallback has torn
4042         // down the network and started the teardown timer, and short enough that the lambda is
4043         // scheduled to run before the teardown timer.
4044         final Handler h = new Handler(mCsHandlerThread.getLooper());
4045         h.postDelayed(() -> duringTeardown.accept(mWiFiAgent.getNetwork()), 150);
4046 
4047         // Disconnect the network and check that events happened in the right order.
4048         mCm.unregisterNetworkCallback(callback);
4049         assertEquals("onNetworkUnwanted", eventOrder.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
4050         assertEquals("timePasses", eventOrder.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
4051         assertEquals("onNetworkDisconnected", eventOrder.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
4052 
4053         mCm.unregisterNetworkCallback(callback);
4054     }
4055 
4056     @Test
4057     public void testExplicitlySelected() throws Exception {
4058         final NetworkRequest request = new NetworkRequest.Builder()
4059                 .clearCapabilities().addCapability(NET_CAPABILITY_INTERNET)
4060                 .build();
4061         final TestNetworkCallback callback = new TestNetworkCallback();
4062         mCm.registerNetworkCallback(request, callback);
4063 
4064         // Bring up validated cell
4065         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
4066         mCellAgent.connect(true);
4067         callback.expectAvailableThenValidatedCallbacks(mCellAgent);
4068 
4069         // Bring up unvalidated wifi with explicitlySelected=true.
4070         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4071         mWiFiAgent.explicitlySelected(true, false);
4072         mWiFiAgent.connect(false);
4073         callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
4074 
4075         // Cell remains the default.
4076         assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetwork());
4077 
4078         // Expect a high-priority NO_INTERNET notification.
4079         expectUnvalidationCheckWillNotify(mWiFiAgent, NotificationType.NO_INTERNET);
4080 
4081         // Lower WiFi's score to lower than cell, and check that it doesn't disconnect because
4082         // it's explicitly selected.
4083         mWiFiAgent.adjustScore(-40);
4084         mWiFiAgent.adjustScore(40);
4085         callback.assertNoCallback();
4086 
4087         // If the user chooses yes on the "No Internet access, stay connected?" dialog, we switch to
4088         // wifi even though it's unvalidated.
4089         mCm.setAcceptUnvalidated(mWiFiAgent.getNetwork(), true, false);
4090         callback.expectLosing(mCellAgent);
4091         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetwork());
4092 
4093         // Disconnect wifi, and then reconnect, again with explicitlySelected=true.
4094         mWiFiAgent.disconnect();
4095         expectDisconnectAndClearNotifications(callback, mWiFiAgent, NotificationType.NO_INTERNET);
4096 
4097         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4098         mWiFiAgent.explicitlySelected(true, false);
4099         mWiFiAgent.connect(false);
4100         callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
4101 
4102         // Expect a high-priority NO_INTERNET notification.
4103         expectUnvalidationCheckWillNotify(mWiFiAgent, NotificationType.NO_INTERNET);
4104 
4105         // If the user chooses no on the "No Internet access, stay connected?" dialog, we ask the
4106         // network to disconnect.
4107         mCm.setAcceptUnvalidated(mWiFiAgent.getNetwork(), false, false);
4108         expectDisconnectAndClearNotifications(callback, mWiFiAgent, NotificationType.NO_INTERNET);
4109         reset(mNotificationManager);
4110 
4111         // Reconnect, again with explicitlySelected=true, but this time validate.
4112         // Expect no notifications.
4113         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4114         mWiFiAgent.explicitlySelected(true, false);
4115         mWiFiAgent.connect(true);
4116         callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
4117         callback.expectLosing(mCellAgent);
4118         callback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
4119         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetwork());
4120         expectUnvalidationCheckWillNotNotify(mWiFiAgent);
4121 
4122         // Now request cell so it doesn't disconnect during the test
4123         final NetworkRequest cellRequest = new NetworkRequest.Builder()
4124                 .clearCapabilities().addTransportType(TRANSPORT_CELLULAR).build();
4125         final TestNetworkCallback cellCallback = new TestNetworkCallback();
4126         mCm.requestNetwork(cellRequest, cellCallback);
4127 
4128         mEthernetAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
4129         mEthernetAgent.connect(true);
4130         callback.expectAvailableCallbacksUnvalidated(mEthernetAgent);
4131         callback.expectLosing(mWiFiAgent);
4132         callback.expectCaps(mEthernetAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
4133         assertEquals(mEthernetAgent.getNetwork(), mCm.getActiveNetwork());
4134         callback.assertNoCallback();
4135 
4136         // Disconnect wifi, and then reconnect as if the user had selected "yes, don't ask again"
4137         // (i.e., with explicitlySelected=true and acceptUnvalidated=true). Expect to switch to
4138         // wifi immediately.
4139         mWiFiAgent.disconnect();
4140         callback.expect(LOST, mWiFiAgent);
4141         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4142         mWiFiAgent.explicitlySelected(true, true);
4143         mWiFiAgent.connect(false);
4144         callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
4145         callback.expectLosing(mEthernetAgent);
4146         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetwork());
4147         mEthernetAgent.disconnect();
4148         callback.expect(LOST, mEthernetAgent);
4149         expectUnvalidationCheckWillNotNotify(mWiFiAgent);
4150 
4151         // Disconnect and reconnect with explicitlySelected=false and acceptUnvalidated=true.
4152         // Check that the network is not scored specially and that the device prefers cell data.
4153         mWiFiAgent.disconnect();
4154         callback.expect(LOST, mWiFiAgent);
4155 
4156         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4157         mWiFiAgent.explicitlySelected(false, true);
4158         mWiFiAgent.connect(false);
4159         callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
4160         assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetwork());
4161         expectUnvalidationCheckWillNotNotify(mWiFiAgent);
4162 
4163         // Clean up.
4164         mWiFiAgent.disconnect();
4165         mCellAgent.disconnect();
4166 
4167         callback.expect(LOST, mWiFiAgent);
4168         callback.expect(LOST, mCellAgent);
4169         mCm.unregisterNetworkCallback(cellCallback);
4170     }
4171 
4172     private void doTestFirstEvaluation(
4173             @NonNull final Consumer<TestNetworkAgentWrapper> doConnect,
4174             final boolean waitForSecondCaps,
4175             final boolean evaluatedByValidation)
4176             throws Exception {
4177         final NetworkRequest request = new NetworkRequest.Builder()
4178                 .addTransportType(TRANSPORT_WIFI)
4179                 .build();
4180         TestNetworkCallback callback = new TestNetworkCallback();
4181         mCm.registerNetworkCallback(request, callback);
4182 
4183         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4184         doConnect.accept(mWiFiAgent);
4185         // Expect the available callbacks, but don't require specific values for their arguments
4186         // since this method doesn't know how the network was connected.
4187         callback.expect(AVAILABLE, mWiFiAgent);
4188         callback.expect(NETWORK_CAPS_UPDATED, mWiFiAgent);
4189         callback.expect(LINK_PROPERTIES_CHANGED, mWiFiAgent);
4190         callback.expect(BLOCKED_STATUS, mWiFiAgent);
4191         if (waitForSecondCaps) {
4192             // This is necessary because of b/245893397, the same bug that happens where we use
4193             // expectAvailableDoubleValidatedCallbacks.
4194             callback.expect(NETWORK_CAPS_UPDATED, mWiFiAgent);
4195         }
4196         final NetworkAgentInfo nai =
4197                 mService.getNetworkAgentInfoForNetwork(mWiFiAgent.getNetwork());
4198         final long firstEvaluation = nai.getFirstEvaluationConcludedTime();
4199         if (evaluatedByValidation) {
4200             assertNotEquals(0L, firstEvaluation);
4201         } else {
4202             assertEquals(0L, firstEvaluation);
4203         }
4204         mService.scheduleEvaluationTimeout(mWiFiAgent.getNetwork(), 0L /* timeout */);
4205         waitForIdle();
4206         if (evaluatedByValidation) {
4207             assertEquals(firstEvaluation, nai.getFirstEvaluationConcludedTime());
4208         } else {
4209             assertNotEquals(0L, nai.getFirstEvaluationConcludedTime());
4210         }
4211         mWiFiAgent.disconnect();
4212         callback.expect(LOST, mWiFiAgent);
4213 
4214         mCm.unregisterNetworkCallback(callback);
4215     }
4216 
4217     @Test
4218     public void testEverEvaluated() throws Exception {
4219         doTestFirstEvaluation(naw -> naw.connect(true /* validated */),
4220                 true /* waitForSecondCaps */, true /* immediatelyEvaluated */);
4221         doTestFirstEvaluation(naw -> naw.connectWithPartialConnectivity(),
4222                 true /* waitForSecondCaps */, true /* immediatelyEvaluated */);
4223         doTestFirstEvaluation(naw -> naw.connectWithCaptivePortal(TEST_REDIRECT_URL, false),
4224                 true /* waitForSecondCaps */, true /* immediatelyEvaluated */);
4225         doTestFirstEvaluation(naw -> naw.connect(false /* validated */),
4226                 false /* waitForSecondCaps */, false /* immediatelyEvaluated */);
4227     }
4228 
4229     private void tryNetworkFactoryRequests(int capability) throws Exception {
4230         // Verify NOT_RESTRICTED is set appropriately
4231         final NetworkCapabilities nc = new NetworkRequest.Builder().addCapability(capability)
4232                 .build().networkCapabilities;
4233         if (capability == NET_CAPABILITY_CBS || capability == NET_CAPABILITY_DUN
4234                 || capability == NET_CAPABILITY_EIMS || capability == NET_CAPABILITY_FOTA
4235                 || capability == NET_CAPABILITY_IA || capability == NET_CAPABILITY_IMS
4236                 || capability == NET_CAPABILITY_RCS || capability == NET_CAPABILITY_XCAP
4237                 || capability == NET_CAPABILITY_VSIM || capability == NET_CAPABILITY_BIP
4238                 || capability == NET_CAPABILITY_ENTERPRISE || capability == NET_CAPABILITY_MMTEL) {
4239             assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
4240         } else {
4241             assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
4242         }
4243 
4244         NetworkCapabilities filter = new NetworkCapabilities();
4245         filter.addTransportType(TRANSPORT_CELLULAR);
4246         filter.addCapability(capability);
4247         // Add NOT_VCN_MANAGED capability into filter unconditionally since some requests will add
4248         // NOT_VCN_MANAGED automatically but not for NetworkCapabilities,
4249         // see {@code NetworkCapabilities#deduceNotVcnManagedCapability} for more details.
4250         filter.addCapability(NET_CAPABILITY_NOT_VCN_MANAGED);
4251         final HandlerThread handlerThread = new HandlerThread("testNetworkFactoryRequests");
4252         handlerThread.start();
4253         final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
4254                 mServiceContext, "testFactory", filter, mCsHandlerThread);
4255         testFactory.setScoreFilter(45);
4256         testFactory.register();
4257 
4258         final NetworkCallback networkCallback;
4259         if (capability != NET_CAPABILITY_INTERNET) {
4260             // If the capability passed in argument is part of the default request, then the
4261             // factory will see the default request. Otherwise the filter will prevent the
4262             // factory from seeing it. In that case, add a request so it can be tested.
4263             assertFalse(testFactory.getMyStartRequested());
4264             NetworkRequest request = new NetworkRequest.Builder().addCapability(capability).build();
4265             networkCallback = new NetworkCallback();
4266             mCm.requestNetwork(request, networkCallback);
4267         } else {
4268             networkCallback = null;
4269         }
4270         testFactory.expectRequestAdd();
4271         testFactory.assertRequestCountEquals(1);
4272         assertTrue(testFactory.getMyStartRequested());
4273 
4274         // Now bring in a higher scored network.
4275         TestNetworkAgentWrapper testAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
4276         // When testAgent connects, because of its score (50 legacy int / cell transport)
4277         // it will beat or equal the testFactory's offer, so the request will be removed.
4278         // Note the agent as validated only if the capability is INTERNET, as it's the only case
4279         // where it makes sense.
4280         testAgent.connect(NET_CAPABILITY_INTERNET == capability /* validated */);
4281         testAgent.addCapability(capability);
4282         testFactory.expectRequestRemove();
4283         testFactory.assertRequestCountEquals(0);
4284         assertFalse(testFactory.getMyStartRequested());
4285 
4286         // Add a request and make sure it's not sent to the factory, because the agent
4287         // is satisfying it better.
4288         final NetworkCallback cb = new ConnectivityManager.NetworkCallback();
4289         mCm.requestNetwork(new NetworkRequest.Builder().addCapability(capability).build(), cb);
4290         expectNoRequestChanged(testFactory);
4291         testFactory.assertRequestCountEquals(0);
4292         assertFalse(testFactory.getMyStartRequested());
4293 
4294         // If using legacy scores, make the test agent weak enough to have the exact same score as
4295         // the factory (50 for cell - 5 adjustment). Make sure the factory doesn't see the request.
4296         // If not using legacy score, this is a no-op and the "same score removes request" behavior
4297         // has already been tested above.
4298         testAgent.adjustScore(-5);
4299         expectNoRequestChanged(testFactory);
4300         assertFalse(testFactory.getMyStartRequested());
4301 
4302         // Make the test agent weak enough that the factory will see the two requests (the one that
4303         // was just sent, and either the default one or the one sent at the top of this test if
4304         // the default won't be seen).
4305         testAgent.setScore(new NetworkScore.Builder().setLegacyInt(2).setExiting(true).build());
4306         testFactory.expectRequestAdds(2);
4307         testFactory.assertRequestCountEquals(2);
4308         assertTrue(testFactory.getMyStartRequested());
4309 
4310         // Now unregister and make sure the request is removed.
4311         mCm.unregisterNetworkCallback(cb);
4312         testFactory.expectRequestRemove();
4313 
4314         // Bring in a bunch of requests.
4315         assertEquals(1, testFactory.getMyRequestCount());
4316         ConnectivityManager.NetworkCallback[] networkCallbacks =
4317                 new ConnectivityManager.NetworkCallback[10];
4318         for (int i = 0; i< networkCallbacks.length; i++) {
4319             networkCallbacks[i] = new ConnectivityManager.NetworkCallback();
4320             NetworkRequest.Builder builder = new NetworkRequest.Builder();
4321             builder.addCapability(capability);
4322             mCm.requestNetwork(builder.build(), networkCallbacks[i]);
4323         }
4324         testFactory.expectRequestAdds(10);
4325         testFactory.assertRequestCountEquals(11); // +1 for the default/test specific request
4326         assertTrue(testFactory.getMyStartRequested());
4327 
4328         // Remove the requests.
4329         for (int i = 0; i < networkCallbacks.length; i++) {
4330             mCm.unregisterNetworkCallback(networkCallbacks[i]);
4331         }
4332         testFactory.expectRequestRemoves(10);
4333         testFactory.assertRequestCountEquals(1);
4334         assertTrue(testFactory.getMyStartRequested());
4335 
4336         // Adjust the agent score up again. Expect the request to be withdrawn.
4337         testAgent.setScore(new NetworkScore.Builder().setLegacyInt(50).build());
4338         testFactory.expectRequestRemove();
4339         testFactory.assertRequestCountEquals(0);
4340         assertFalse(testFactory.getMyStartRequested());
4341 
4342         // Drop the higher scored network.
4343         testAgent.disconnect();
4344         testFactory.expectRequestAdd();
4345         testFactory.assertRequestCountEquals(1);
4346         assertEquals(1, testFactory.getMyRequestCount());
4347         assertTrue(testFactory.getMyStartRequested());
4348 
4349         testFactory.terminate();
4350         testFactory.assertNoRequestChanged();
4351         if (networkCallback != null) mCm.unregisterNetworkCallback(networkCallback);
4352 
4353         handlerThread.quitSafely();
4354         handlerThread.join();
4355     }
4356 
4357     @Test
4358     public void testNetworkFactoryRequests() throws Exception {
4359         tryNetworkFactoryRequests(NET_CAPABILITY_MMS);
4360         tryNetworkFactoryRequests(NET_CAPABILITY_SUPL);
4361         tryNetworkFactoryRequests(NET_CAPABILITY_DUN);
4362         tryNetworkFactoryRequests(NET_CAPABILITY_FOTA);
4363         tryNetworkFactoryRequests(NET_CAPABILITY_IMS);
4364         tryNetworkFactoryRequests(NET_CAPABILITY_CBS);
4365         tryNetworkFactoryRequests(NET_CAPABILITY_WIFI_P2P);
4366         tryNetworkFactoryRequests(NET_CAPABILITY_IA);
4367         tryNetworkFactoryRequests(NET_CAPABILITY_RCS);
4368         tryNetworkFactoryRequests(NET_CAPABILITY_MMTEL);
4369         tryNetworkFactoryRequests(NET_CAPABILITY_XCAP);
4370         tryNetworkFactoryRequests(NET_CAPABILITY_ENTERPRISE);
4371         tryNetworkFactoryRequests(NET_CAPABILITY_EIMS);
4372         tryNetworkFactoryRequests(NET_CAPABILITY_NOT_METERED);
4373         tryNetworkFactoryRequests(NET_CAPABILITY_INTERNET);
4374         tryNetworkFactoryRequests(NET_CAPABILITY_TRUSTED);
4375         tryNetworkFactoryRequests(NET_CAPABILITY_NOT_VPN);
4376         tryNetworkFactoryRequests(NET_CAPABILITY_VSIM);
4377         tryNetworkFactoryRequests(NET_CAPABILITY_BIP);
4378         // Skipping VALIDATED and CAPTIVE_PORTAL as they're disallowed.
4379     }
4380 
4381     @Test
4382     public void testRegisterIgnoringScore() throws Exception {
4383         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4384         mWiFiAgent.setScore(new NetworkScore.Builder().setLegacyInt(90).build());
4385         mWiFiAgent.connect(true /* validated */);
4386 
4387         // Make sure the factory sees the default network
4388         final NetworkCapabilities filter = new NetworkCapabilities();
4389         filter.addTransportType(TRANSPORT_CELLULAR);
4390         filter.addCapability(NET_CAPABILITY_INTERNET);
4391         filter.addCapability(NET_CAPABILITY_NOT_VCN_MANAGED);
4392         final HandlerThread handlerThread = new HandlerThread("testNetworkFactoryRequests");
4393         handlerThread.start();
4394         final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
4395                 mServiceContext, "testFactory", filter, mCsHandlerThread);
4396         testFactory.register();
4397 
4398         final MockNetworkFactory testFactoryAll = new MockNetworkFactory(handlerThread.getLooper(),
4399                 mServiceContext, "testFactoryAll", filter, mCsHandlerThread);
4400         testFactoryAll.registerIgnoringScore();
4401 
4402         // The regular test factory should not see the request, because WiFi is stronger than cell.
4403         expectNoRequestChanged(testFactory);
4404         // With ignoringScore though the request is seen.
4405         testFactoryAll.expectRequestAdd();
4406 
4407         // The legacy int will be ignored anyway, set the only other knob to true
4408         mWiFiAgent.setScore(new NetworkScore.Builder().setLegacyInt(110)
4409                 .setTransportPrimary(true).build());
4410 
4411         expectNoRequestChanged(testFactory); // still not seeing the request
4412         expectNoRequestChanged(testFactoryAll); // still seeing the request
4413 
4414         mWiFiAgent.disconnect();
4415         handlerThread.quitSafely();
4416         handlerThread.join();
4417     }
4418 
4419     @Test
4420     public void testNetworkFactoryUnregister() throws Exception {
4421         // Make sure the factory sees the default network
4422         final NetworkCapabilities filter = new NetworkCapabilities();
4423         filter.addCapability(NET_CAPABILITY_INTERNET);
4424         filter.addCapability(NET_CAPABILITY_NOT_VCN_MANAGED);
4425 
4426         final HandlerThread handlerThread = new HandlerThread("testNetworkFactoryRequests");
4427         handlerThread.start();
4428 
4429         // Checks that calling setScoreFilter on a NetworkFactory immediately before closing it
4430         // does not crash.
4431         for (int i = 0; i < 100; i++) {
4432             final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
4433                     mServiceContext, "testFactory", filter, mCsHandlerThread);
4434             // Register the factory and don't be surprised when the default request arrives.
4435             testFactory.register();
4436             testFactory.expectRequestAdd();
4437 
4438             testFactory.setScoreFilter(42);
4439             testFactory.terminate();
4440             testFactory.assertNoRequestChanged();
4441 
4442             if (i % 2 == 0) {
4443                 try {
4444                     testFactory.register();
4445                     fail("Re-registering terminated NetworkFactory should throw");
4446                 } catch (IllegalStateException expected) {
4447                 }
4448             }
4449         }
4450         handlerThread.quitSafely();
4451         handlerThread.join();
4452     }
4453 
4454     @Test
4455     public void testNoMutableNetworkRequests() throws Exception {
4456         final PendingIntent pendingIntent = PendingIntent.getBroadcast(
4457                 mContext, 0 /* requestCode */, new Intent("a"), FLAG_IMMUTABLE);
4458         final NetworkRequest request1 = new NetworkRequest.Builder()
4459                 .addCapability(NET_CAPABILITY_VALIDATED)
4460                 .build();
4461         final NetworkRequest request2 = new NetworkRequest.Builder()
4462                 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL)
4463                 .build();
4464 
4465         final Class<IllegalArgumentException> expected = IllegalArgumentException.class;
4466         assertThrows(expected, () -> mCm.requestNetwork(request1, new NetworkCallback()));
4467         assertThrows(expected, () -> mCm.requestNetwork(request1, pendingIntent));
4468         assertThrows(expected, () -> mCm.requestNetwork(request2, new NetworkCallback()));
4469         assertThrows(expected, () -> mCm.requestNetwork(request2, pendingIntent));
4470     }
4471 
4472     @Test
4473     public void testNoAllowedUidsInNetworkRequests() throws Exception {
4474         final PendingIntent pendingIntent = PendingIntent.getBroadcast(
4475                 mContext, 0 /* requestCode */, new Intent("a"), FLAG_IMMUTABLE);
4476         final NetworkRequest r = new NetworkRequest.Builder().build();
4477         final ArraySet<Integer> allowedUids = new ArraySet<>();
4478         allowedUids.add(6);
4479         allowedUids.add(9);
4480         r.networkCapabilities.setAllowedUids(allowedUids);
4481 
4482         final Handler handler = new Handler(ConnectivityThread.getInstanceLooper());
4483         final NetworkCallback cb = new NetworkCallback();
4484 
4485         final Class<IllegalArgumentException> expected = IllegalArgumentException.class;
4486         assertThrows(expected, () -> mCm.requestNetwork(r, cb));
4487         assertThrows(expected, () -> mCm.requestNetwork(r, pendingIntent));
4488         assertThrows(expected, () -> mCm.registerNetworkCallback(r, cb));
4489         assertThrows(expected, () -> mCm.registerNetworkCallback(r, cb, handler));
4490         assertThrows(expected, () -> mCm.registerNetworkCallback(r, pendingIntent));
4491         assertThrows(expected, () -> mCm.registerBestMatchingNetworkCallback(r, cb, handler));
4492 
4493         // Make sure that resetting the access UIDs to the empty set will allow calling
4494         // requestNetwork and registerNetworkCallback.
4495         r.networkCapabilities.setAllowedUids(Collections.emptySet());
4496         mCm.requestNetwork(r, cb);
4497         mCm.unregisterNetworkCallback(cb);
4498         mCm.registerNetworkCallback(r, cb);
4499         mCm.unregisterNetworkCallback(cb);
4500     }
4501 
4502     @Test
4503     public void testMMSonWiFi() throws Exception {
4504         // Test bringing up cellular without MMS NetworkRequest gets reaped
4505         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
4506         mCellAgent.addCapability(NET_CAPABILITY_MMS);
4507         mCellAgent.connectWithoutInternet();
4508         mCellAgent.expectDisconnected();
4509         waitForIdle();
4510         assertEmpty(mCm.getAllNetworks());
4511         verifyNoNetwork();
4512 
4513         // Test bringing up validated WiFi.
4514         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4515         final ExpectedBroadcast b = expectConnectivityAction(TYPE_WIFI, DetailedState.CONNECTED);
4516         mWiFiAgent.connect(true);
4517         b.expectBroadcast();
4518         verifyActiveNetwork(TRANSPORT_WIFI);
4519 
4520         // Register MMS NetworkRequest
4521         NetworkRequest.Builder builder = new NetworkRequest.Builder();
4522         builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
4523         final TestNetworkCallback networkCallback = new TestNetworkCallback();
4524         mCm.requestNetwork(builder.build(), networkCallback);
4525 
4526         // Test bringing up unvalidated cellular with MMS
4527         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
4528         mCellAgent.addCapability(NET_CAPABILITY_MMS);
4529         mCellAgent.connectWithoutInternet();
4530         networkCallback.expectAvailableCallbacksUnvalidated(mCellAgent);
4531         verifyActiveNetwork(TRANSPORT_WIFI);
4532 
4533         // Test releasing NetworkRequest disconnects cellular with MMS
4534         mCm.unregisterNetworkCallback(networkCallback);
4535         mCellAgent.expectDisconnected();
4536         verifyActiveNetwork(TRANSPORT_WIFI);
4537     }
4538 
4539     @Test
4540     public void testMMSonCell() throws Exception {
4541         // Test bringing up cellular without MMS
4542         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
4543         ExpectedBroadcast b = expectConnectivityAction(TYPE_MOBILE, DetailedState.CONNECTED);
4544         mCellAgent.connect(false);
4545         b.expectBroadcast();
4546         verifyActiveNetwork(TRANSPORT_CELLULAR);
4547 
4548         // Register MMS NetworkRequest
4549         NetworkRequest.Builder builder = new NetworkRequest.Builder();
4550         builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
4551         final TestNetworkCallback networkCallback = new TestNetworkCallback();
4552         mCm.requestNetwork(builder.build(), networkCallback);
4553 
4554         // Test bringing up MMS cellular network
4555         TestNetworkAgentWrapper
4556                 mmsNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
4557         mmsNetworkAgent.addCapability(NET_CAPABILITY_MMS);
4558         mmsNetworkAgent.connectWithoutInternet();
4559         networkCallback.expectAvailableCallbacksUnvalidated(mmsNetworkAgent);
4560         verifyActiveNetwork(TRANSPORT_CELLULAR);
4561 
4562         // Test releasing MMS NetworkRequest does not disconnect main cellular NetworkAgent
4563         mCm.unregisterNetworkCallback(networkCallback);
4564         mmsNetworkAgent.expectDisconnected();
4565         verifyActiveNetwork(TRANSPORT_CELLULAR);
4566     }
4567 
4568     @Test
4569     public void testPartialConnectivity() throws Exception {
4570         // Register network callback.
4571         NetworkRequest request = new NetworkRequest.Builder()
4572                 .clearCapabilities().addCapability(NET_CAPABILITY_INTERNET)
4573                 .build();
4574         TestNetworkCallback callback = new TestNetworkCallback();
4575         mCm.registerNetworkCallback(request, callback);
4576 
4577         // Bring up validated mobile data.
4578         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
4579         mCellAgent.connect(true);
4580         callback.expectAvailableThenValidatedCallbacks(mCellAgent);
4581 
4582         // Bring up wifi with partial connectivity.
4583         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4584         mWiFiAgent.connectWithPartialConnectivity();
4585         callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
4586         callback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY));
4587 
4588         // Mobile data should be the default network.
4589         assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetwork());
4590         callback.assertNoCallback();
4591 
4592         // Expect a PARTIAL_CONNECTIVITY notification. The notification appears as soon as partial
4593         // connectivity is detected, and is low priority because the network was not explicitly
4594         // selected by the user. This happens if we reconnect to a network where the user previously
4595         // accepted partial connectivity without checking "always".
4596         expectNotification(mWiFiAgent, NotificationType.PARTIAL_CONNECTIVITY);
4597 
4598         // With HTTPS probe disabled, NetworkMonitor should pass the network validation with http
4599         // probe.
4600         mWiFiAgent.setNetworkPartialValid(false /* privateDnsProbeSent */);
4601         // If the user chooses yes to use this partial connectivity wifi, switch the default
4602         // network to wifi and check if wifi becomes valid or not.
4603         mCm.setAcceptPartialConnectivity(mWiFiAgent.getNetwork(), true /* accept */,
4604                 false /* always */);
4605         // If user accepts partial connectivity network,
4606         // NetworkMonitor#setAcceptPartialConnectivity() should be called too.
4607         waitForIdle();
4608         verify(mWiFiAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
4609 
4610         // Need a trigger point to let NetworkMonitor tell ConnectivityService that the network is
4611         // validated.
4612         mCm.reportNetworkConnectivity(mWiFiAgent.getNetwork(), true);
4613         callback.expectLosing(mCellAgent);
4614         NetworkCapabilities nc =
4615                 callback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
4616         assertTrue(nc.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY));
4617         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetwork());
4618 
4619         // Once the network validates, the notification disappears.
4620         expectClearNotification(mWiFiAgent, NotificationType.PARTIAL_CONNECTIVITY);
4621 
4622         // Disconnect and reconnect wifi with partial connectivity again.
4623         mWiFiAgent.disconnect();
4624         callback.expect(LOST, mWiFiAgent);
4625 
4626         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4627         mWiFiAgent.connectWithPartialConnectivity();
4628         callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
4629         callback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY));
4630 
4631         // Mobile data should be the default network.
4632         assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetwork());
4633         waitForIdle();
4634 
4635         // Expect a low-priority PARTIAL_CONNECTIVITY notification as soon as partial connectivity
4636         // is detected.
4637         expectNotification(mWiFiAgent, NotificationType.PARTIAL_CONNECTIVITY);
4638 
4639         // If the user chooses no, disconnect wifi immediately.
4640         mCm.setAcceptPartialConnectivity(mWiFiAgent.getNetwork(), false /* accept */,
4641                 false /* always */);
4642         callback.expect(LOST, mWiFiAgent);
4643         expectClearNotification(mWiFiAgent, NotificationType.PARTIAL_CONNECTIVITY);
4644         reset(mNotificationManager);
4645 
4646         // If the user accepted partial connectivity before, and the device connects to that network
4647         // again, but now the network has full connectivity, then the network shouldn't contain
4648         // NET_CAPABILITY_PARTIAL_CONNECTIVITY.
4649         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4650         // acceptUnvalidated is also used as setting for accepting partial networks.
4651         mWiFiAgent.explicitlySelected(true /* explicitlySelected */, true /* acceptUnvalidated */);
4652         mWiFiAgent.connect(true);
4653         expectUnvalidationCheckWillNotNotify(mWiFiAgent);
4654 
4655         // If user accepted partial connectivity network before,
4656         // NetworkMonitor#setAcceptPartialConnectivity() will be called in
4657         // ConnectivityService#updateNetworkInfo().
4658         callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
4659         verify(mWiFiAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
4660         callback.expectLosing(mCellAgent);
4661         nc = callback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
4662         assertFalse(nc.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY));
4663 
4664         // Wifi should be the default network.
4665         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetwork());
4666         mWiFiAgent.disconnect();
4667         callback.expect(LOST, mWiFiAgent);
4668 
4669         // The user accepted partial connectivity and selected "don't ask again". Now the user
4670         // reconnects to the partial connectivity network. Switch to wifi as soon as partial
4671         // connectivity is detected.
4672         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4673         mWiFiAgent.explicitlySelected(true /* explicitlySelected */, true /* acceptUnvalidated */);
4674         mWiFiAgent.connectWithPartialConnectivity();
4675         // If user accepted partial connectivity network before,
4676         // NetworkMonitor#setAcceptPartialConnectivity() will be called in
4677         // ConnectivityService#updateNetworkInfo().
4678         callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
4679         verify(mWiFiAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
4680         callback.expectLosing(mCellAgent);
4681         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetwork());
4682         callback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY));
4683         expectUnvalidationCheckWillNotNotify(mWiFiAgent);
4684 
4685         mWiFiAgent.setNetworkValid(false /* privateDnsProbeSent */);
4686 
4687         // Need a trigger point to let NetworkMonitor tell ConnectivityService that the network is
4688         // validated.
4689         mCm.reportNetworkConnectivity(mWiFiAgent.getNetwork(), true);
4690         callback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
4691         mWiFiAgent.disconnect();
4692         callback.expect(LOST, mWiFiAgent);
4693 
4694         // If the user accepted partial connectivity, and the device auto-reconnects to the partial
4695         // connectivity network, it should contain both PARTIAL_CONNECTIVITY and VALIDATED.
4696         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4697         mWiFiAgent.explicitlySelected(false /* explicitlySelected */, true /* acceptUnvalidated */);
4698 
4699         // NetworkMonitor will immediately (once the HTTPS probe fails...) report the network as
4700         // valid, because ConnectivityService calls setAcceptPartialConnectivity before it calls
4701         // notifyNetworkConnected.
4702         mWiFiAgent.connectWithPartialValidConnectivity(false /* privateDnsProbeSent */);
4703         callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
4704         verify(mWiFiAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
4705         callback.expectLosing(mCellAgent);
4706         callback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY)
4707                 && c.hasCapability(NET_CAPABILITY_VALIDATED));
4708         expectUnvalidationCheckWillNotNotify(mWiFiAgent);
4709         mWiFiAgent.disconnect();
4710         callback.expect(LOST, mWiFiAgent);
4711         verifyNoMoreInteractions(mNotificationManager);
4712     }
4713 
4714     @Test
4715     public void testCaptivePortalOnPartialConnectivity() throws Exception {
4716         final TestNetworkCallback wifiCallback = new TestNetworkCallback();
4717         final NetworkRequest wifiRequest = new NetworkRequest.Builder()
4718                 .addTransportType(TRANSPORT_WIFI)
4719                 .build();
4720         mCm.registerNetworkCallback(wifiRequest, wifiCallback);
4721 
4722         final TestNetworkCallback validatedCallback = new TestNetworkCallback();
4723         final NetworkRequest validatedRequest = new NetworkRequest.Builder()
4724                 .addCapability(NET_CAPABILITY_VALIDATED).build();
4725         mCm.registerNetworkCallback(validatedRequest, validatedCallback);
4726 
4727         // Bring up a network with a captive portal.
4728         // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
4729         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4730         String redirectUrl = "http://android.com/path";
4731         mWiFiAgent.connectWithCaptivePortal(redirectUrl, false /* privateDnsProbeSent */);
4732         wifiCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
4733         assertEquals(mWiFiAgent.waitForRedirectUrl(), redirectUrl);
4734 
4735         // This is necessary because of b/245893397, the same bug that happens where we use
4736         // expectAvailableDoubleValidatedCallbacks.
4737         // TODO : fix b/245893397 and remove this.
4738         wifiCallback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_CAPTIVE_PORTAL));
4739 
4740         // Check that startCaptivePortalApp sends the expected command to NetworkMonitor.
4741         mCm.startCaptivePortalApp(mWiFiAgent.getNetwork());
4742         verify(mWiFiAgent.mNetworkMonitor, timeout(TIMEOUT_MS).times(1)).launchCaptivePortalApp();
4743 
4744         // Report that the captive portal is dismissed with partial connectivity, and check that
4745         // callbacks are fired with PARTIAL and without CAPTIVE_PORTAL.
4746         mWiFiAgent.setNetworkPartial();
4747         mCm.reportNetworkConnectivity(mWiFiAgent.getNetwork(), true);
4748         waitForIdle();
4749         wifiCallback.expectCaps(mWiFiAgent,
4750                 c -> c.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY)
4751                         && !c.hasCapability(NET_CAPABILITY_CAPTIVE_PORTAL));
4752 
4753         // Report partial connectivity is accepted.
4754         mWiFiAgent.setNetworkPartialValid(false /* privateDnsProbeSent */);
4755         mCm.setAcceptPartialConnectivity(mWiFiAgent.getNetwork(), true /* accept */,
4756                 false /* always */);
4757         waitForIdle();
4758         mCm.reportNetworkConnectivity(mWiFiAgent.getNetwork(), true);
4759         wifiCallback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
4760         validatedCallback.expectAvailableCallbacksValidated(mWiFiAgent);
4761         validatedCallback.expectCaps(mWiFiAgent,
4762                 c -> c.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY));
4763 
4764         mCm.unregisterNetworkCallback(wifiCallback);
4765         mCm.unregisterNetworkCallback(validatedCallback);
4766     }
4767 
4768     @Test
4769     public void testCaptivePortal() throws Exception {
4770         final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
4771         final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
4772                 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
4773         mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
4774 
4775         final TestNetworkCallback validatedCallback = new TestNetworkCallback();
4776         final NetworkRequest validatedRequest = new NetworkRequest.Builder()
4777                 .addCapability(NET_CAPABILITY_VALIDATED).build();
4778         mCm.registerNetworkCallback(validatedRequest, validatedCallback);
4779 
4780         // Bring up a network with a captive portal.
4781         // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
4782         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4783         String firstRedirectUrl = "http://example.com/firstPath";
4784         mWiFiAgent.connectWithCaptivePortal(firstRedirectUrl, false /* privateDnsProbeSent */);
4785         captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
4786         assertEquals(mWiFiAgent.waitForRedirectUrl(), firstRedirectUrl);
4787 
4788         // Take down network.
4789         // Expect onLost callback.
4790         mWiFiAgent.disconnect();
4791         captivePortalCallback.expect(LOST, mWiFiAgent);
4792 
4793         // Bring up a network with a captive portal.
4794         // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
4795         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4796         String secondRedirectUrl = "http://example.com/secondPath";
4797         mWiFiAgent.connectWithCaptivePortal(secondRedirectUrl, false /* privateDnsProbeSent */);
4798         captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
4799         assertEquals(mWiFiAgent.waitForRedirectUrl(), secondRedirectUrl);
4800 
4801         // Make captive portal disappear then revalidate.
4802         // Expect onLost callback because network no longer provides NET_CAPABILITY_CAPTIVE_PORTAL.
4803         mWiFiAgent.setNetworkValid(false /* privateDnsProbeSent */);
4804         mCm.reportNetworkConnectivity(mWiFiAgent.getNetwork(), true);
4805         captivePortalCallback.expect(LOST, mWiFiAgent);
4806 
4807         // Expect NET_CAPABILITY_VALIDATED onAvailable callback.
4808         validatedCallback.expectAvailableDoubleValidatedCallbacks(mWiFiAgent);
4809 
4810         // Break network connectivity.
4811         // Expect NET_CAPABILITY_VALIDATED onLost callback.
4812         mWiFiAgent.setNetworkInvalid(false /* invalidBecauseOfPrivateDns */);
4813         mCm.reportNetworkConnectivity(mWiFiAgent.getNetwork(), false);
4814         validatedCallback.expect(LOST, mWiFiAgent);
4815     }
4816 
4817     private Intent startCaptivePortalApp(TestNetworkAgentWrapper networkAgent) throws Exception {
4818         Network network = networkAgent.getNetwork();
4819         // Check that startCaptivePortalApp sends the expected command to NetworkMonitor.
4820         mCm.startCaptivePortalApp(network);
4821         waitForIdle();
4822         verify(networkAgent.mNetworkMonitor).launchCaptivePortalApp();
4823 
4824         // NetworkMonitor uses startCaptivePortal(Network, Bundle) (startCaptivePortalAppInternal)
4825         final Bundle testBundle = new Bundle();
4826         final String testKey = "testkey";
4827         final String testValue = "testvalue";
4828         testBundle.putString(testKey, testValue);
4829         mServiceContext.setPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
4830                 PERMISSION_GRANTED);
4831         mCm.startCaptivePortalApp(network, testBundle);
4832         final Intent signInIntent = mServiceContext.expectStartActivityIntent(TIMEOUT_MS);
4833         assertEquals(ACTION_CAPTIVE_PORTAL_SIGN_IN, signInIntent.getAction());
4834         assertEquals(testValue, signInIntent.getStringExtra(testKey));
4835         return signInIntent;
4836     }
4837 
4838     @Test
4839     public void testCaptivePortalApp() throws Exception {
4840         final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
4841         final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
4842                 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
4843         mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
4844 
4845         final TestNetworkCallback validatedCallback = new TestNetworkCallback();
4846         final NetworkRequest validatedRequest = new NetworkRequest.Builder()
4847                 .addCapability(NET_CAPABILITY_VALIDATED).build();
4848         mCm.registerNetworkCallback(validatedRequest, validatedCallback);
4849 
4850         // Bring up wifi.
4851         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4852         mWiFiAgent.connect(true);
4853         validatedCallback.expectAvailableDoubleValidatedCallbacks(mWiFiAgent);
4854         Network wifiNetwork = mWiFiAgent.getNetwork();
4855 
4856         // Check that calling startCaptivePortalApp does nothing.
4857         final int fastTimeoutMs = 100;
4858         mCm.startCaptivePortalApp(wifiNetwork);
4859         waitForIdle();
4860         verify(mWiFiAgent.mNetworkMonitor, never()).launchCaptivePortalApp();
4861         mServiceContext.expectNoStartActivityIntent(fastTimeoutMs);
4862 
4863         // Turn into a captive portal.
4864         mWiFiAgent.setNetworkPortal("http://example.com", false /* privateDnsProbeSent */);
4865         mCm.reportNetworkConnectivity(wifiNetwork, false);
4866         captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
4867         validatedCallback.expect(LOST, mWiFiAgent);
4868         // This is necessary because of b/245893397, the same bug that happens where we use
4869         // expectAvailableDoubleValidatedCallbacks.
4870         // TODO : fix b/245893397 and remove this.
4871         captivePortalCallback.expectCaps(mWiFiAgent);
4872 
4873         startCaptivePortalApp(mWiFiAgent);
4874 
4875         // Report that the captive portal is dismissed, and check that callbacks are fired
4876         mWiFiAgent.setNetworkValid(false /* privateDnsProbeSent */);
4877         mWiFiAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
4878         validatedCallback.expectAvailableCallbacksValidated(mWiFiAgent);
4879         captivePortalCallback.expect(LOST, mWiFiAgent);
4880 
4881         mCm.unregisterNetworkCallback(validatedCallback);
4882         mCm.unregisterNetworkCallback(captivePortalCallback);
4883     }
4884 
4885     @Test
4886     public void testCaptivePortalApp_IgnoreNetwork() throws Exception {
4887         final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
4888         final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
4889                 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
4890         mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
4891 
4892         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4893         mWiFiAgent.connectWithCaptivePortal(TEST_REDIRECT_URL, false);
4894         captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
4895 
4896         final Intent signInIntent = startCaptivePortalApp(mWiFiAgent);
4897         final CaptivePortal captivePortal = signInIntent
4898                 .getParcelableExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL);
4899 
4900         captivePortal.ignoreNetwork();
4901         waitForIdle();
4902 
4903         // Since network will disconnect, ensure no notification of response to NetworkMonitor
4904         verify(mWiFiAgent.mNetworkMonitor, never())
4905                 .notifyCaptivePortalAppFinished(CaptivePortal.APP_RETURN_UNWANTED);
4906 
4907         // Report that the network is disconnected
4908         mWiFiAgent.expectDisconnected();
4909         mWiFiAgent.expectPreventReconnectReceived();
4910         verify(mWiFiAgent.mNetworkMonitor).notifyNetworkDisconnected();
4911         captivePortalCallback.expect(LOST, mWiFiAgent);
4912 
4913         mCm.unregisterNetworkCallback(captivePortalCallback);
4914     }
4915 
4916     @Test
4917     public void testAvoidOrIgnoreCaptivePortals() throws Exception {
4918         final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
4919         final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
4920                 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
4921         mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
4922 
4923         final TestNetworkCallback validatedCallback = new TestNetworkCallback();
4924         final NetworkRequest validatedRequest = new NetworkRequest.Builder()
4925                 .addCapability(NET_CAPABILITY_VALIDATED).build();
4926         mCm.registerNetworkCallback(validatedRequest, validatedCallback);
4927 
4928         setCaptivePortalMode(ConnectivitySettingsManager.CAPTIVE_PORTAL_MODE_AVOID);
4929         // Bring up a network with a captive portal.
4930         // Expect it to fail to connect and not result in any callbacks.
4931         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4932         final String firstRedirectUrl = "http://example.com/firstPath";
4933 
4934         mWiFiAgent.connectWithCaptivePortal(firstRedirectUrl, false /* privateDnsProbeSent */);
4935         mWiFiAgent.expectDisconnected();
4936         mWiFiAgent.expectPreventReconnectReceived();
4937 
4938         assertNoCallbacks(captivePortalCallback, validatedCallback);
4939     }
4940 
4941     @Test
4942     public void testNoAvoidCaptivePortalOnWearProxy() throws Exception {
4943         // Bring up a BLUETOOTH network which is companion proxy on wear
4944         // then set captive portal.
4945         mockHasSystemFeature(PackageManager.FEATURE_WATCH, true);
4946         setCaptivePortalMode(ConnectivitySettingsManager.CAPTIVE_PORTAL_MODE_AVOID);
4947         TestNetworkAgentWrapper btAgent = new TestNetworkAgentWrapper(TRANSPORT_BLUETOOTH);
4948         final String firstRedirectUrl = "http://example.com/firstPath";
4949 
4950         btAgent.connectWithCaptivePortal(firstRedirectUrl, false /* privateDnsProbeSent */);
4951         btAgent.assertNotDisconnected(TIMEOUT_MS);
4952     }
4953 
4954     @Test
4955     public void testAvoidCaptivePortalOnBluetooth() throws Exception {
4956         // When not on Wear, BLUETOOTH is just regular network,
4957         // then set captive portal.
4958         mockHasSystemFeature(PackageManager.FEATURE_WATCH, false);
4959         setCaptivePortalMode(ConnectivitySettingsManager.CAPTIVE_PORTAL_MODE_AVOID);
4960         TestNetworkAgentWrapper btAgent = new TestNetworkAgentWrapper(TRANSPORT_BLUETOOTH);
4961         final String firstRedirectUrl = "http://example.com/firstPath";
4962 
4963         btAgent.connectWithCaptivePortal(firstRedirectUrl, false /* privateDnsProbeSent */);
4964 
4965         btAgent.expectDisconnected();
4966         btAgent.expectPreventReconnectReceived();
4967     }
4968 
4969     @Test
4970     public void testCaptivePortalApi() throws Exception {
4971         mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_GRANTED);
4972 
4973         final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
4974         final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
4975                 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
4976         mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
4977 
4978         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4979         final String redirectUrl = "http://example.com/firstPath";
4980 
4981         mWiFiAgent.connectWithCaptivePortal(redirectUrl,
4982                 false /* privateDnsProbeSent */);
4983         captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
4984 
4985         final CaptivePortalData testData = new CaptivePortalData.Builder()
4986                 .setUserPortalUrl(Uri.parse(redirectUrl))
4987                 .setBytesRemaining(12345L)
4988                 .build();
4989 
4990         mWiFiAgent.notifyCapportApiDataChanged(testData);
4991 
4992         captivePortalCallback.expect(LINK_PROPERTIES_CHANGED, mWiFiAgent,
4993                 cb -> testData.equals(cb.getLp().getCaptivePortalData()));
4994 
4995         final LinkProperties newLps = new LinkProperties();
4996         newLps.setMtu(1234);
4997         mWiFiAgent.sendLinkProperties(newLps);
4998         // CaptivePortalData is not lost and unchanged when LPs are received from the NetworkAgent
4999         captivePortalCallback.expect(LINK_PROPERTIES_CHANGED, mWiFiAgent,
5000                 cb -> testData.equals(cb.getLp().getCaptivePortalData())
5001                         && cb.getLp().getMtu() == 1234);
5002     }
5003 
5004     private TestNetworkCallback setupNetworkCallbackAndConnectToWifi() throws Exception {
5005         // Grant NETWORK_SETTINGS permission to be able to receive LinkProperties change callbacks
5006         // with sensitive (captive portal) data
5007         mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_GRANTED);
5008 
5009         final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
5010         final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
5011                 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
5012         mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
5013 
5014         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
5015 
5016         mWiFiAgent.connectWithCaptivePortal(TEST_REDIRECT_URL,
5017                 false /* privateDnsProbeSent */);
5018         captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
5019         return captivePortalCallback;
5020     }
5021 
5022     private class CaptivePortalTestData {
5023         CaptivePortalTestData(CaptivePortalData naPasspointData, CaptivePortalData capportData,
5024                 CaptivePortalData naOtherData, CaptivePortalData expectedMergedPasspointData,
5025                 CaptivePortalData expectedMergedOtherData) {
5026             mNaPasspointData = naPasspointData;
5027             mCapportData = capportData;
5028             mNaOtherData = naOtherData;
5029             mExpectedMergedPasspointData = expectedMergedPasspointData;
5030             mExpectedMergedOtherData = expectedMergedOtherData;
5031         }
5032 
5033         public final CaptivePortalData mNaPasspointData;
5034         public final CaptivePortalData mCapportData;
5035         public final CaptivePortalData mNaOtherData;
5036         public final CaptivePortalData mExpectedMergedPasspointData;
5037         public final CaptivePortalData mExpectedMergedOtherData;
5038 
5039     }
5040 
5041     private CaptivePortalTestData setupCaptivePortalData() {
5042         final CaptivePortalData capportData = new CaptivePortalData.Builder()
5043                 .setUserPortalUrl(Uri.parse(TEST_REDIRECT_URL))
5044                 .setVenueInfoUrl(Uri.parse(TEST_VENUE_URL_CAPPORT))
5045                 .setUserPortalUrl(Uri.parse(TEST_USER_PORTAL_API_URL_CAPPORT))
5046                 .setExpiryTime(1000000L)
5047                 .setBytesRemaining(12345L)
5048                 .build();
5049 
5050         final CaptivePortalData naPasspointData = new CaptivePortalData.Builder()
5051                 .setBytesRemaining(80802L)
5052                 .setVenueInfoUrl(Uri.parse(TEST_VENUE_URL_NA_PASSPOINT),
5053                         CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_PASSPOINT)
5054                 .setUserPortalUrl(Uri.parse(TEST_TERMS_AND_CONDITIONS_URL_NA_PASSPOINT),
5055                         CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_PASSPOINT)
5056                 .setVenueFriendlyName(TEST_FRIENDLY_NAME).build();
5057 
5058         final CaptivePortalData naOtherData = new CaptivePortalData.Builder()
5059                 .setBytesRemaining(80802L)
5060                 .setVenueInfoUrl(Uri.parse(TEST_VENUE_URL_NA_OTHER),
5061                         CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_OTHER)
5062                 .setUserPortalUrl(Uri.parse(TEST_TERMS_AND_CONDITIONS_URL_NA_OTHER),
5063                         CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_OTHER)
5064                 .setVenueFriendlyName(TEST_FRIENDLY_NAME).build();
5065 
5066         final CaptivePortalData expectedMergedPasspointData = new CaptivePortalData.Builder()
5067                 .setUserPortalUrl(Uri.parse(TEST_REDIRECT_URL))
5068                 .setBytesRemaining(12345L)
5069                 .setExpiryTime(1000000L)
5070                 .setVenueInfoUrl(Uri.parse(TEST_VENUE_URL_NA_PASSPOINT),
5071                         CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_PASSPOINT)
5072                 .setUserPortalUrl(Uri.parse(TEST_TERMS_AND_CONDITIONS_URL_NA_PASSPOINT),
5073                         CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_PASSPOINT)
5074                 .setVenueFriendlyName(TEST_FRIENDLY_NAME).build();
5075 
5076         final CaptivePortalData expectedMergedOtherData = new CaptivePortalData.Builder()
5077                 .setUserPortalUrl(Uri.parse(TEST_REDIRECT_URL))
5078                 .setBytesRemaining(12345L)
5079                 .setExpiryTime(1000000L)
5080                 .setVenueInfoUrl(Uri.parse(TEST_VENUE_URL_CAPPORT))
5081                 .setUserPortalUrl(Uri.parse(TEST_USER_PORTAL_API_URL_CAPPORT))
5082                 .setVenueFriendlyName(TEST_FRIENDLY_NAME).build();
5083         return new CaptivePortalTestData(naPasspointData, capportData, naOtherData,
5084                 expectedMergedPasspointData, expectedMergedOtherData);
5085     }
5086 
5087     @Test
5088     public void testMergeCaptivePortalApiWithFriendlyNameAndVenueUrl() throws Exception {
5089         final TestNetworkCallback captivePortalCallback = setupNetworkCallbackAndConnectToWifi();
5090         final CaptivePortalTestData captivePortalTestData = setupCaptivePortalData();
5091 
5092         // Baseline capport data
5093         mWiFiAgent.notifyCapportApiDataChanged(captivePortalTestData.mCapportData);
5094 
5095         captivePortalCallback.expect(LINK_PROPERTIES_CHANGED, mWiFiAgent,
5096                 cb -> captivePortalTestData.mCapportData.equals(cb.getLp().getCaptivePortalData()));
5097 
5098         // Venue URL, T&C URL and friendly name from Network agent with Passpoint source, confirm
5099         // that API data gets precedence on the bytes remaining.
5100         final LinkProperties linkProperties = new LinkProperties();
5101         linkProperties.setCaptivePortalData(captivePortalTestData.mNaPasspointData);
5102         mWiFiAgent.sendLinkProperties(linkProperties);
5103 
5104         // Make sure that the capport data is merged
5105         captivePortalCallback.expect(LINK_PROPERTIES_CHANGED, mWiFiAgent,
5106                 cb -> captivePortalTestData.mExpectedMergedPasspointData.equals(
5107                         cb.getLp().getCaptivePortalData()));
5108 
5109         // Now send this information from non-Passpoint source, confirm that Capport data takes
5110         // precedence
5111         linkProperties.setCaptivePortalData(captivePortalTestData.mNaOtherData);
5112         mWiFiAgent.sendLinkProperties(linkProperties);
5113 
5114         // Make sure that the capport data is merged
5115         captivePortalCallback.expect(LINK_PROPERTIES_CHANGED, mWiFiAgent,
5116                 cb -> captivePortalTestData.mExpectedMergedOtherData.equals(
5117                         cb.getLp().getCaptivePortalData()));
5118 
5119         // Create a new LP with no Network agent capport data
5120         final LinkProperties newLps = new LinkProperties();
5121         newLps.setMtu(1234);
5122         mWiFiAgent.sendLinkProperties(newLps);
5123         // CaptivePortalData is not lost and has the original values when LPs are received from the
5124         // NetworkAgent
5125         captivePortalCallback.expect(LINK_PROPERTIES_CHANGED, mWiFiAgent,
5126                 cb -> captivePortalTestData.mCapportData.equals(cb.getLp().getCaptivePortalData())
5127                         && cb.getLp().getMtu() == 1234);
5128 
5129         // Now send capport data only from the Network agent
5130         mWiFiAgent.notifyCapportApiDataChanged(null);
5131         captivePortalCallback.expect(LINK_PROPERTIES_CHANGED, mWiFiAgent,
5132                 cb -> cb.getLp().getCaptivePortalData() == null);
5133 
5134         newLps.setCaptivePortalData(captivePortalTestData.mNaPasspointData);
5135         mWiFiAgent.sendLinkProperties(newLps);
5136 
5137         // Make sure that only the network agent capport data is available
5138         captivePortalCallback.expect(LINK_PROPERTIES_CHANGED, mWiFiAgent,
5139                 cb -> captivePortalTestData.mNaPasspointData.equals(
5140                         cb.getLp().getCaptivePortalData()));
5141     }
5142 
5143     @Test
5144     public void testMergeCaptivePortalDataFromNetworkAgentFirstThenCapport() throws Exception {
5145         final TestNetworkCallback captivePortalCallback = setupNetworkCallbackAndConnectToWifi();
5146         final CaptivePortalTestData captivePortalTestData = setupCaptivePortalData();
5147 
5148         // Venue URL and friendly name from Network agent, confirm that API data gets precedence
5149         // on the bytes remaining.
5150         final LinkProperties linkProperties = new LinkProperties();
5151         linkProperties.setCaptivePortalData(captivePortalTestData.mNaPasspointData);
5152         mWiFiAgent.sendLinkProperties(linkProperties);
5153 
5154         // Make sure that the data is saved correctly
5155         captivePortalCallback.expect(LINK_PROPERTIES_CHANGED, mWiFiAgent,
5156                 cb -> captivePortalTestData.mNaPasspointData.equals(
5157                         cb.getLp().getCaptivePortalData()));
5158 
5159         // Expected merged data: Network agent data is preferred, and values that are not used by
5160         // it are merged from capport data
5161         mWiFiAgent.notifyCapportApiDataChanged(captivePortalTestData.mCapportData);
5162 
5163         // Make sure that the Capport data is merged correctly
5164         captivePortalCallback.expect(LINK_PROPERTIES_CHANGED, mWiFiAgent,
5165                 cb -> captivePortalTestData.mExpectedMergedPasspointData.equals(
5166                         cb.getLp().getCaptivePortalData()));
5167 
5168         // Now set the naData to null
5169         linkProperties.setCaptivePortalData(null);
5170         mWiFiAgent.sendLinkProperties(linkProperties);
5171 
5172         // Make sure that the Capport data is retained correctly
5173         captivePortalCallback.expect(LINK_PROPERTIES_CHANGED, mWiFiAgent,
5174                 cb -> captivePortalTestData.mCapportData.equals(cb.getLp().getCaptivePortalData()));
5175     }
5176 
5177     @Test
5178     public void testMergeCaptivePortalDataFromNetworkAgentOtherSourceFirstThenCapport()
5179             throws Exception {
5180         final TestNetworkCallback captivePortalCallback = setupNetworkCallbackAndConnectToWifi();
5181         final CaptivePortalTestData captivePortalTestData = setupCaptivePortalData();
5182 
5183         // Venue URL and friendly name from Network agent, confirm that API data gets precedence
5184         // on the bytes remaining.
5185         final LinkProperties linkProperties = new LinkProperties();
5186         linkProperties.setCaptivePortalData(captivePortalTestData.mNaOtherData);
5187         mWiFiAgent.sendLinkProperties(linkProperties);
5188 
5189         // Make sure that the data is saved correctly
5190         captivePortalCallback.expect(LINK_PROPERTIES_CHANGED, mWiFiAgent,
5191                 cb -> captivePortalTestData.mNaOtherData.equals(cb.getLp().getCaptivePortalData()));
5192 
5193         // Expected merged data: Network agent data is preferred, and values that are not used by
5194         // it are merged from capport data
5195         mWiFiAgent.notifyCapportApiDataChanged(captivePortalTestData.mCapportData);
5196 
5197         // Make sure that the Capport data is merged correctly
5198         captivePortalCallback.expect(LINK_PROPERTIES_CHANGED, mWiFiAgent,
5199                 cb -> captivePortalTestData.mExpectedMergedOtherData.equals(
5200                         cb.getLp().getCaptivePortalData()));
5201     }
5202 
5203     private NetworkRequest.Builder newWifiRequestBuilder() {
5204         return new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI);
5205     }
5206 
5207     // A NetworkSpecifier subclass that matches all networks but must not be visible to apps.
5208     static class ConfidentialMatchAllNetworkSpecifier extends NetworkSpecifier implements
5209             Parcelable {
5210         public static final Parcelable.Creator<ConfidentialMatchAllNetworkSpecifier> CREATOR =
5211                 new Parcelable.Creator<ConfidentialMatchAllNetworkSpecifier>() {
5212                     public ConfidentialMatchAllNetworkSpecifier createFromParcel(Parcel in) {
5213                         return new ConfidentialMatchAllNetworkSpecifier();
5214                     }
5215 
5216                     public ConfidentialMatchAllNetworkSpecifier[] newArray(int size) {
5217                         return new ConfidentialMatchAllNetworkSpecifier[size];
5218                     }
5219                 };
5220         @Override
5221         public boolean canBeSatisfiedBy(NetworkSpecifier other) {
5222             return true;
5223         }
5224 
5225         @Override
5226         public int describeContents() {
5227             return 0;
5228         }
5229 
5230         @Override
5231         public void writeToParcel(Parcel dest, int flags) {}
5232 
5233         @Override
5234         public NetworkSpecifier redact() {
5235             return null;
5236         }
5237     }
5238 
5239     // A network specifier that matches either another LocalNetworkSpecifier with the same
5240     // string or a ConfidentialMatchAllNetworkSpecifier, and can be passed to apps as is.
5241     static class LocalStringNetworkSpecifier extends NetworkSpecifier implements Parcelable {
5242         public static final Parcelable.Creator<LocalStringNetworkSpecifier> CREATOR =
5243                 new Parcelable.Creator<LocalStringNetworkSpecifier>() {
5244                     public LocalStringNetworkSpecifier createFromParcel(Parcel in) {
5245                         return new LocalStringNetworkSpecifier(in);
5246                     }
5247 
5248                     public LocalStringNetworkSpecifier[] newArray(int size) {
5249                         return new LocalStringNetworkSpecifier[size];
5250                     }
5251                 };
5252         private String mString;
5253 
5254         LocalStringNetworkSpecifier(String string) {
5255             mString = string;
5256         }
5257 
5258         LocalStringNetworkSpecifier(Parcel in) {
5259             mString = in.readString();
5260         }
5261 
5262         @Override
5263         public boolean canBeSatisfiedBy(NetworkSpecifier other) {
5264             if (other instanceof LocalStringNetworkSpecifier) {
5265                 return TextUtils.equals(mString,
5266                         ((LocalStringNetworkSpecifier) other).mString);
5267             }
5268             if (other instanceof ConfidentialMatchAllNetworkSpecifier) return true;
5269             return false;
5270         }
5271 
5272         @Override
5273         public int describeContents() {
5274             return 0;
5275         }
5276         @Override
5277         public void writeToParcel(Parcel dest, int flags) {
5278             dest.writeString(mString);
5279         }
5280     }
5281 
5282     /**
5283      * Verify request matching behavior with network specifiers.
5284      *
5285      * This test does not check updating the specifier on a live network because the specifier is
5286      * immutable and this triggers a WTF in
5287      * {@link ConnectivityService#mixInCapabilities(NetworkAgentInfo, NetworkCapabilities)}.
5288      */
5289     @Test
5290     public void testNetworkSpecifier() throws Exception {
5291         NetworkRequest rEmpty1 = newWifiRequestBuilder().build();
5292         NetworkRequest rEmpty2 = newWifiRequestBuilder().setNetworkSpecifier((String) null).build();
5293         NetworkRequest rEmpty3 = newWifiRequestBuilder().setNetworkSpecifier("").build();
5294         NetworkRequest rEmpty4 = newWifiRequestBuilder().setNetworkSpecifier(
5295             (NetworkSpecifier) null).build();
5296         NetworkRequest rFoo = newWifiRequestBuilder().setNetworkSpecifier(
5297                 new LocalStringNetworkSpecifier("foo")).build();
5298         NetworkRequest rBar = newWifiRequestBuilder().setNetworkSpecifier(
5299                 new LocalStringNetworkSpecifier("bar")).build();
5300 
5301         TestNetworkCallback cEmpty1 = new TestNetworkCallback();
5302         TestNetworkCallback cEmpty2 = new TestNetworkCallback();
5303         TestNetworkCallback cEmpty3 = new TestNetworkCallback();
5304         TestNetworkCallback cEmpty4 = new TestNetworkCallback();
5305         TestNetworkCallback cFoo = new TestNetworkCallback();
5306         TestNetworkCallback cBar = new TestNetworkCallback();
5307         TestNetworkCallback[] emptyCallbacks = new TestNetworkCallback[] {
5308                 cEmpty1, cEmpty2, cEmpty3, cEmpty4 };
5309 
5310         mCm.registerNetworkCallback(rEmpty1, cEmpty1);
5311         mCm.registerNetworkCallback(rEmpty2, cEmpty2);
5312         mCm.registerNetworkCallback(rEmpty3, cEmpty3);
5313         mCm.registerNetworkCallback(rEmpty4, cEmpty4);
5314         mCm.registerNetworkCallback(rFoo, cFoo);
5315         mCm.registerNetworkCallback(rBar, cBar);
5316 
5317         LocalStringNetworkSpecifier nsFoo = new LocalStringNetworkSpecifier("foo");
5318         LocalStringNetworkSpecifier nsBar = new LocalStringNetworkSpecifier("bar");
5319 
5320         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
5321         mWiFiAgent.connect(false);
5322         expectAvailableCallbacksUnvalidatedWithSpecifier(mWiFiAgent, null /* specifier */,
5323                 cEmpty1, cEmpty2, cEmpty3, cEmpty4);
5324         assertNoCallbacks(cFoo, cBar);
5325 
5326         mWiFiAgent.disconnect();
5327         expectOnLost(mWiFiAgent, cEmpty1, cEmpty2, cEmpty3, cEmpty4);
5328 
5329         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
5330         mWiFiAgent.setNetworkSpecifier(nsFoo);
5331         mWiFiAgent.connect(false);
5332         expectAvailableCallbacksUnvalidatedWithSpecifier(mWiFiAgent, nsFoo,
5333                 cEmpty1, cEmpty2, cEmpty3, cEmpty4, cFoo);
5334         cBar.assertNoCallback();
5335         assertEquals(nsFoo,
5336                 mCm.getNetworkCapabilities(mWiFiAgent.getNetwork()).getNetworkSpecifier());
5337         assertNoCallbacks(cEmpty1, cEmpty2, cEmpty3, cEmpty4, cFoo);
5338 
5339         mWiFiAgent.disconnect();
5340         expectOnLost(mWiFiAgent, cEmpty1, cEmpty2, cEmpty3, cEmpty4, cFoo);
5341 
5342         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
5343         mWiFiAgent.setNetworkSpecifier(nsBar);
5344         mWiFiAgent.connect(false);
5345         expectAvailableCallbacksUnvalidatedWithSpecifier(mWiFiAgent, nsBar,
5346                 cEmpty1, cEmpty2, cEmpty3, cEmpty4, cBar);
5347         cFoo.assertNoCallback();
5348         assertEquals(nsBar,
5349                 mCm.getNetworkCapabilities(mWiFiAgent.getNetwork()).getNetworkSpecifier());
5350 
5351         mWiFiAgent.disconnect();
5352         expectOnLost(mWiFiAgent, cEmpty1, cEmpty2, cEmpty3, cEmpty4, cBar);
5353         cFoo.assertNoCallback();
5354 
5355         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
5356         mWiFiAgent.setNetworkSpecifier(new ConfidentialMatchAllNetworkSpecifier());
5357         mWiFiAgent.connect(false);
5358         expectAvailableCallbacksUnvalidatedWithSpecifier(mWiFiAgent, null /* specifier */,
5359                 cEmpty1, cEmpty2, cEmpty3, cEmpty4, cFoo, cBar);
5360         assertNull(mCm.getNetworkCapabilities(mWiFiAgent.getNetwork()).getNetworkSpecifier());
5361 
5362         mWiFiAgent.disconnect();
5363         expectOnLost(mWiFiAgent, cEmpty1, cEmpty2, cEmpty3, cEmpty4, cFoo, cBar);
5364     }
5365 
5366     /**
5367      * @return the context's attribution tag
5368      */
5369     private String getAttributionTag() {
5370         return mContext.getAttributionTag();
5371     }
5372 
5373     static class NonParcelableSpecifier extends NetworkSpecifier {
5374         @Override
5375         public boolean canBeSatisfiedBy(NetworkSpecifier other) {
5376             return false;
5377         }
5378     }
5379     static class ParcelableSpecifier extends NonParcelableSpecifier implements Parcelable {
5380         public static final Parcelable.Creator<NonParcelableSpecifier> CREATOR =
5381                 new Parcelable.Creator<NonParcelableSpecifier>() {
5382                     public NonParcelableSpecifier createFromParcel(Parcel in) {
5383                         return new NonParcelableSpecifier();
5384                     }
5385 
5386                     public NonParcelableSpecifier[] newArray(int size) {
5387                         return new NonParcelableSpecifier[size];
5388                     }
5389                 };
5390         @Override public int describeContents() {
5391             return 0;
5392         }
5393         @Override public void writeToParcel(Parcel p, int flags) {}
5394     }
5395 
5396     @Test
5397     public void testInvalidNetworkSpecifier() {
5398         assertThrows(IllegalArgumentException.class, () -> {
5399             NetworkRequest.Builder builder = new NetworkRequest.Builder();
5400             builder.setNetworkSpecifier(new MatchAllNetworkSpecifier());
5401         });
5402 
5403         assertThrows(IllegalArgumentException.class, () -> {
5404             NetworkCapabilities networkCapabilities = new NetworkCapabilities();
5405             networkCapabilities.addTransportType(TRANSPORT_WIFI)
5406                     .setNetworkSpecifier(new MatchAllNetworkSpecifier());
5407             mService.requestNetwork(Process.INVALID_UID, networkCapabilities,
5408                     NetworkRequest.Type.REQUEST.ordinal(), null, 0, null,
5409                     ConnectivityManager.TYPE_WIFI, NetworkCallback.FLAG_NONE,
5410                     mContext.getPackageName(), getAttributionTag());
5411         });
5412 
5413         final NetworkRequest.Builder builder =
5414                 new NetworkRequest.Builder().addTransportType(TRANSPORT_ETHERNET);
5415         assertThrows(ClassCastException.class, () -> {
5416             builder.setNetworkSpecifier(new NonParcelableSpecifier());
5417             Parcel parcelW = Parcel.obtain();
5418             builder.build().writeToParcel(parcelW, 0);
5419         });
5420 
5421         final NetworkRequest nr =
5422                 new NetworkRequest.Builder().addTransportType(TRANSPORT_ETHERNET)
5423                 .setNetworkSpecifier(new ParcelableSpecifier())
5424                 .build();
5425         assertNotNull(nr);
5426 
5427         assertThrows(BadParcelableException.class, () -> {
5428             Parcel parcelW = Parcel.obtain();
5429             nr.writeToParcel(parcelW, 0);
5430             byte[] bytes = parcelW.marshall();
5431             parcelW.recycle();
5432 
5433             Parcel parcelR = Parcel.obtain();
5434             parcelR.unmarshall(bytes, 0, bytes.length);
5435             parcelR.setDataPosition(0);
5436             NetworkRequest rereadNr = NetworkRequest.CREATOR.createFromParcel(parcelR);
5437         });
5438     }
5439 
5440     @Test
5441     public void testNetworkRequestUidSpoofSecurityException() throws Exception {
5442         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
5443         mWiFiAgent.connect(false);
5444         NetworkRequest networkRequest = newWifiRequestBuilder().build();
5445         TestNetworkCallback networkCallback = new TestNetworkCallback();
5446         doThrow(new SecurityException()).when(mAppOpsManager).checkPackage(anyInt(), anyString());
5447         assertThrows(SecurityException.class, () -> {
5448             mCm.requestNetwork(networkRequest, networkCallback);
5449         });
5450     }
5451 
5452     @Test
5453     public void testInvalidSignalStrength() {
5454         NetworkRequest r = new NetworkRequest.Builder()
5455                 .addCapability(NET_CAPABILITY_INTERNET)
5456                 .addTransportType(TRANSPORT_WIFI)
5457                 .setSignalStrength(-75)
5458                 .build();
5459         // Registering a NetworkCallback with signal strength but w/o NETWORK_SIGNAL_STRENGTH_WAKEUP
5460         // permission should get SecurityException.
5461         assertThrows(SecurityException.class, () ->
5462                 mCm.registerNetworkCallback(r, new NetworkCallback()));
5463 
5464         assertThrows(SecurityException.class, () ->
5465                 mCm.registerNetworkCallback(r, PendingIntent.getService(
5466                         mServiceContext, 0 /* requestCode */, new Intent(), FLAG_IMMUTABLE)));
5467 
5468         // Requesting a Network with signal strength should get IllegalArgumentException.
5469         assertThrows(IllegalArgumentException.class, () ->
5470                 mCm.requestNetwork(r, new NetworkCallback()));
5471 
5472         assertThrows(IllegalArgumentException.class, () ->
5473                 mCm.requestNetwork(r, PendingIntent.getService(
5474                         mServiceContext, 0 /* requestCode */, new Intent(), FLAG_IMMUTABLE)));
5475     }
5476 
5477     @Test
5478     public void testRegisterDefaultNetworkCallback() throws Exception {
5479         final TestNetworkCallback defaultNetworkCallback = new TestNetworkCallback();
5480         mCm.registerDefaultNetworkCallback(defaultNetworkCallback);
5481         defaultNetworkCallback.assertNoCallback();
5482 
5483         final Handler handler = new Handler(ConnectivityThread.getInstanceLooper());
5484         final TestNetworkCallback systemDefaultCallback = new TestNetworkCallback();
5485         mCm.registerSystemDefaultNetworkCallback(systemDefaultCallback, handler);
5486         systemDefaultCallback.assertNoCallback();
5487 
5488         // Create a TRANSPORT_CELLULAR request to keep the mobile interface up
5489         // whenever Wi-Fi is up. Without this, the mobile network agent is
5490         // reaped before any other activity can take place.
5491         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
5492         final NetworkRequest cellRequest = new NetworkRequest.Builder()
5493                 .addTransportType(TRANSPORT_CELLULAR).build();
5494         mCm.requestNetwork(cellRequest, cellNetworkCallback);
5495         cellNetworkCallback.assertNoCallback();
5496 
5497         // Bring up cell and expect CALLBACK_AVAILABLE.
5498         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
5499         mCellAgent.connect(true);
5500         cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
5501         defaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
5502         systemDefaultCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
5503         assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
5504         assertEquals(systemDefaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
5505 
5506         // Bring up wifi and expect CALLBACK_AVAILABLE.
5507         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
5508         mWiFiAgent.connect(true);
5509         cellNetworkCallback.assertNoCallback();
5510         defaultNetworkCallback.expectAvailableDoubleValidatedCallbacks(mWiFiAgent);
5511         systemDefaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiAgent);
5512         assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
5513         assertEquals(systemDefaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
5514 
5515         // Bring down cell. Expect no default network callback, since it wasn't the default.
5516         mCellAgent.disconnect();
5517         cellNetworkCallback.expect(LOST, mCellAgent);
5518         defaultNetworkCallback.assertNoCallback();
5519         systemDefaultCallback.assertNoCallback();
5520         assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
5521         assertEquals(systemDefaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
5522 
5523         // Bring up cell. Expect no default network callback, since it won't be the default.
5524         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
5525         mCellAgent.connect(true);
5526         cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
5527         defaultNetworkCallback.assertNoCallback();
5528         systemDefaultCallback.assertNoCallback();
5529         assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
5530         assertEquals(systemDefaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
5531 
5532         // Bring down wifi. Expect the default network callback to notified of LOST wifi
5533         // followed by AVAILABLE cell.
5534         mWiFiAgent.disconnect();
5535         cellNetworkCallback.assertNoCallback();
5536         defaultNetworkCallback.expect(LOST, mWiFiAgent);
5537         defaultNetworkCallback.expectAvailableCallbacksValidated(mCellAgent);
5538         systemDefaultCallback.expect(LOST, mWiFiAgent);
5539         systemDefaultCallback.expectAvailableCallbacksValidated(mCellAgent);
5540         mCellAgent.disconnect();
5541         cellNetworkCallback.expect(LOST, mCellAgent);
5542         defaultNetworkCallback.expect(LOST, mCellAgent);
5543         systemDefaultCallback.expect(LOST, mCellAgent);
5544         waitForIdle();
5545         assertEquals(null, mCm.getActiveNetwork());
5546 
5547         mMockVpn.establishForMyUid();
5548         assertUidRangesUpdatedForMyUid(true);
5549         defaultNetworkCallback.expectAvailableThenValidatedCallbacks(mMockVpn);
5550         systemDefaultCallback.assertNoCallback();
5551         assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
5552         assertEquals(null, systemDefaultCallback.getLastAvailableNetwork());
5553 
5554         mMockVpn.disconnect();
5555         defaultNetworkCallback.expect(LOST, mMockVpn);
5556         systemDefaultCallback.assertNoCallback();
5557         waitForIdle();
5558         assertEquals(null, mCm.getActiveNetwork());
5559     }
5560 
5561     @Test
5562     public void testAdditionalStateCallbacks() throws Exception {
5563         // File a network request for mobile.
5564         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
5565         final NetworkRequest cellRequest = new NetworkRequest.Builder()
5566                 .addTransportType(TRANSPORT_CELLULAR).build();
5567         mCm.requestNetwork(cellRequest, cellNetworkCallback);
5568 
5569         // Bring up the mobile network.
5570         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
5571         mCellAgent.connect(true);
5572 
5573         // We should get onAvailable(), onCapabilitiesChanged(), and
5574         // onLinkPropertiesChanged() in rapid succession. Additionally, we
5575         // should get onCapabilitiesChanged() when the mobile network validates.
5576         cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
5577         cellNetworkCallback.assertNoCallback();
5578 
5579         // Update LinkProperties.
5580         final LinkProperties lp = new LinkProperties();
5581         lp.setInterfaceName("foonet_data0");
5582         mCellAgent.sendLinkProperties(lp);
5583         // We should get onLinkPropertiesChanged().
5584         cellNetworkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent);
5585         cellNetworkCallback.assertNoCallback();
5586 
5587         // Suspend the network.
5588         mCellAgent.suspend();
5589         cellNetworkCallback.expectCaps(mCellAgent,
5590                 c -> !c.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
5591         cellNetworkCallback.expect(SUSPENDED, mCellAgent);
5592         cellNetworkCallback.assertNoCallback();
5593         assertEquals(NetworkInfo.State.SUSPENDED, mCm.getActiveNetworkInfo().getState());
5594 
5595         // Register a garden variety default network request.
5596         TestNetworkCallback dfltNetworkCallback = new TestNetworkCallback();
5597         mCm.registerDefaultNetworkCallback(dfltNetworkCallback);
5598         // We should get onAvailable(), onCapabilitiesChanged(), onLinkPropertiesChanged(),
5599         // as well as onNetworkSuspended() in rapid succession.
5600         dfltNetworkCallback.expectAvailableAndSuspendedCallbacks(mCellAgent, true);
5601         dfltNetworkCallback.assertNoCallback();
5602         mCm.unregisterNetworkCallback(dfltNetworkCallback);
5603 
5604         mCellAgent.resume();
5605         cellNetworkCallback.expectCaps(mCellAgent,
5606                 c -> c.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
5607         cellNetworkCallback.expect(RESUMED, mCellAgent);
5608         cellNetworkCallback.assertNoCallback();
5609         assertEquals(NetworkInfo.State.CONNECTED, mCm.getActiveNetworkInfo().getState());
5610 
5611         dfltNetworkCallback = new TestNetworkCallback();
5612         mCm.registerDefaultNetworkCallback(dfltNetworkCallback);
5613         // This time onNetworkSuspended should not be called.
5614         dfltNetworkCallback.expectAvailableCallbacksValidated(mCellAgent);
5615         dfltNetworkCallback.assertNoCallback();
5616 
5617         mCm.unregisterNetworkCallback(dfltNetworkCallback);
5618         mCm.unregisterNetworkCallback(cellNetworkCallback);
5619     }
5620 
5621     @Test
5622     public void testRegisterPrivilegedDefaultCallbacksRequirePermissions() throws Exception {
5623         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
5624         mCellAgent.connect(false /* validated */);
5625         mServiceContext.setPermission(CONNECTIVITY_USE_RESTRICTED_NETWORKS, PERMISSION_DENIED);
5626 
5627         final Handler handler = new Handler(ConnectivityThread.getInstanceLooper());
5628         final TestNetworkCallback callback = new TestNetworkCallback();
5629         assertThrows(SecurityException.class,
5630                 () -> mCm.registerSystemDefaultNetworkCallback(callback, handler));
5631         callback.assertNoCallback();
5632         assertThrows(SecurityException.class,
5633                 () -> mCm.registerDefaultNetworkCallbackForUid(APP1_UID, callback, handler));
5634         callback.assertNoCallback();
5635 
5636         mServiceContext.setPermission(CONNECTIVITY_USE_RESTRICTED_NETWORKS, PERMISSION_GRANTED);
5637         mCm.registerSystemDefaultNetworkCallback(callback, handler);
5638         mServiceContext.setPermission(CONNECTIVITY_USE_RESTRICTED_NETWORKS, PERMISSION_DENIED);
5639         callback.expectAvailableCallbacksUnvalidated(mCellAgent);
5640         mCm.unregisterNetworkCallback(callback);
5641 
5642         mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_GRANTED);
5643         mCm.registerSystemDefaultNetworkCallback(callback, handler);
5644         callback.expectAvailableCallbacksUnvalidated(mCellAgent);
5645         mCm.unregisterNetworkCallback(callback);
5646 
5647         mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_DENIED);
5648         mServiceContext.setPermission(NETWORK_SETUP_WIZARD, PERMISSION_GRANTED);
5649         mCm.registerSystemDefaultNetworkCallback(callback, handler);
5650         callback.expectAvailableCallbacksUnvalidated(mCellAgent);
5651         mCm.unregisterNetworkCallback(callback);
5652 
5653         mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_GRANTED);
5654         mCm.registerDefaultNetworkCallbackForUid(APP1_UID, callback, handler);
5655         callback.expectAvailableCallbacksUnvalidated(mCellAgent);
5656         mCm.unregisterNetworkCallback(callback);
5657     }
5658 
5659     @Test
5660     public void testNetworkCallbackWithNullUids() throws Exception {
5661         final NetworkRequest request = new NetworkRequest.Builder()
5662                 .removeCapability(NET_CAPABILITY_NOT_VPN)
5663                 .build();
5664         final TestNetworkCallback callback = new TestNetworkCallback();
5665         mCm.registerNetworkCallback(request, callback);
5666 
5667         // Attempt to file a callback for networks applying to another UID. This does not actually
5668         // work, because this code does not currently have permission to do so. The callback behaves
5669         // exactly the same as the one registered just above.
5670         final int otherUid = UserHandle.getUid(RESTRICTED_USER, VPN_UID);
5671         final NetworkRequest otherUidRequest = new NetworkRequest.Builder()
5672                 .removeCapability(NET_CAPABILITY_NOT_VPN)
5673                 .setUids(UidRange.toIntRanges(uidRangesForUids(otherUid)))
5674                 .build();
5675         final TestNetworkCallback otherUidCallback = new TestNetworkCallback();
5676         mCm.registerNetworkCallback(otherUidRequest, otherUidCallback);
5677 
5678         final NetworkRequest includeOtherUidsRequest = new NetworkRequest.Builder()
5679                 .removeCapability(NET_CAPABILITY_NOT_VPN)
5680                 .setIncludeOtherUidNetworks(true)
5681                 .build();
5682         final TestNetworkCallback includeOtherUidsCallback = new TestNetworkCallback();
5683         mCm.registerNetworkCallback(includeOtherUidsRequest, includeOtherUidsCallback);
5684 
5685         // Both callbacks see a network with no specifier that applies to their UID.
5686         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
5687         mWiFiAgent.connect(false /* validated */);
5688         callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
5689         otherUidCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
5690         includeOtherUidsCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
5691         mWiFiAgent.disconnect();
5692         callback.expect(LOST, mWiFiAgent);
5693         otherUidCallback.expect(LOST, mWiFiAgent);
5694         includeOtherUidsCallback.expect(LOST, mWiFiAgent);
5695 
5696         // Only the includeOtherUidsCallback sees a VPN that does not apply to its UID.
5697         final UidRange range = UidRange.createForUser(UserHandle.of(RESTRICTED_USER));
5698         final Set<UidRange> vpnRanges = Collections.singleton(range);
5699         mMockVpn.establish(new LinkProperties(), VPN_UID, vpnRanges);
5700         includeOtherUidsCallback.expectAvailableThenValidatedCallbacks(mMockVpn);
5701         callback.assertNoCallback();
5702         otherUidCallback.assertNoCallback();
5703 
5704         mMockVpn.disconnect();
5705         includeOtherUidsCallback.expect(LOST, mMockVpn);
5706         callback.assertNoCallback();
5707         otherUidCallback.assertNoCallback();
5708     }
5709 
5710     private static class RedactableNetworkSpecifier extends NetworkSpecifier {
5711         public static final int ID_INVALID = -1;
5712 
5713         public final int networkId;
5714 
5715         RedactableNetworkSpecifier(int networkId) {
5716             this.networkId = networkId;
5717         }
5718 
5719         @Override
5720         public boolean canBeSatisfiedBy(NetworkSpecifier other) {
5721             return other instanceof RedactableNetworkSpecifier
5722                     && this.networkId == ((RedactableNetworkSpecifier) other).networkId;
5723         }
5724 
5725         @Override
5726         public NetworkSpecifier redact() {
5727             return new RedactableNetworkSpecifier(ID_INVALID);
5728         }
5729     }
5730 
5731     @Test
5732     public void testNetworkCallbackWithNullUidsRedactsSpecifier() throws Exception {
5733         final RedactableNetworkSpecifier specifier = new RedactableNetworkSpecifier(42);
5734         final NetworkRequest request = new NetworkRequest.Builder()
5735                 .addCapability(NET_CAPABILITY_INTERNET)
5736                 .addTransportType(TRANSPORT_WIFI)
5737                 .setNetworkSpecifier(specifier)
5738                 .build();
5739         final TestNetworkCallback callback = new TestNetworkCallback();
5740         mCm.registerNetworkCallback(request, callback);
5741 
5742         // Attempt to file a callback for networks applying to another UID. This does not actually
5743         // work, because this code does not currently have permission to do so. The callback behaves
5744         // exactly the same as the one registered just above.
5745         final int otherUid = UserHandle.getUid(RESTRICTED_USER, VPN_UID);
5746         final NetworkRequest otherUidRequest = new NetworkRequest.Builder()
5747                 .addCapability(NET_CAPABILITY_INTERNET)
5748                 .addTransportType(TRANSPORT_WIFI)
5749                 .setNetworkSpecifier(specifier)
5750                 .setUids(UidRange.toIntRanges(uidRangesForUids(otherUid)))
5751                 .build();
5752         final TestNetworkCallback otherUidCallback = new TestNetworkCallback();
5753         mCm.registerNetworkCallback(otherUidRequest, otherUidCallback);
5754 
5755         final NetworkRequest includeOtherUidsRequest = new NetworkRequest.Builder()
5756                 .addCapability(NET_CAPABILITY_INTERNET)
5757                 .addTransportType(TRANSPORT_WIFI)
5758                 .setNetworkSpecifier(specifier)
5759                 .setIncludeOtherUidNetworks(true)
5760                 .build();
5761         final TestNetworkCallback includeOtherUidsCallback = new TestNetworkCallback();
5762         mCm.registerNetworkCallback(includeOtherUidsRequest, callback);
5763 
5764         // Only the regular callback sees the network, because callbacks filed with no UID have
5765         // their specifiers redacted.
5766         final LinkProperties emptyLp = new LinkProperties();
5767         final NetworkCapabilities ncTemplate = new NetworkCapabilities()
5768                 .addTransportType(TRANSPORT_WIFI)
5769                 .setNetworkSpecifier(specifier);
5770         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, emptyLp, ncTemplate);
5771         mWiFiAgent.connect(false /* validated */);
5772         callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
5773         otherUidCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
5774         includeOtherUidsCallback.assertNoCallback();
5775     }
5776 
5777     private void setCaptivePortalMode(int mode) {
5778         ContentResolver cr = mServiceContext.getContentResolver();
5779         Settings.Global.putInt(cr, ConnectivitySettingsManager.CAPTIVE_PORTAL_MODE, mode);
5780     }
5781 
5782     private void setAlwaysOnNetworks(boolean enable) {
5783         ContentResolver cr = mServiceContext.getContentResolver();
5784         Settings.Global.putInt(cr, ConnectivitySettingsManager.MOBILE_DATA_ALWAYS_ON,
5785                 enable ? 1 : 0);
5786         mService.updateAlwaysOnNetworks();
5787         waitForIdle();
5788     }
5789 
5790     private void setPrivateDnsSettings(int mode, String specifier) {
5791         ConnectivitySettingsManager.setPrivateDnsMode(mServiceContext, mode);
5792         ConnectivitySettingsManager.setPrivateDnsHostname(mServiceContext, specifier);
5793         mService.updatePrivateDnsSettings();
5794         waitForIdle();
5795     }
5796 
5797     private void setIngressRateLimit(int rateLimitInBytesPerSec) {
5798         ConnectivitySettingsManager.setIngressRateLimitInBytesPerSecond(mServiceContext,
5799                 rateLimitInBytesPerSec);
5800         mService.updateIngressRateLimit();
5801         waitForIdle();
5802     }
5803 
5804     private boolean isForegroundNetwork(TestNetworkAgentWrapper network) {
5805         NetworkCapabilities nc = mCm.getNetworkCapabilities(network.getNetwork());
5806         assertNotNull(nc);
5807         return nc.hasCapability(NET_CAPABILITY_FOREGROUND);
5808     }
5809 
5810     @Test
5811     public void testBackgroundNetworks() throws Exception {
5812         // Create a cellular background request.
5813         grantUsingBackgroundNetworksPermissionForUid(Binder.getCallingUid());
5814         final TestNetworkCallback cellBgCallback = new TestNetworkCallback();
5815         mCm.requestBackgroundNetwork(new NetworkRequest.Builder()
5816                 .addTransportType(TRANSPORT_CELLULAR).build(),
5817                 cellBgCallback, mCsHandlerThread.getThreadHandler());
5818 
5819         // Make callbacks for monitoring.
5820         final NetworkRequest request = new NetworkRequest.Builder().build();
5821         final NetworkRequest fgRequest = new NetworkRequest.Builder()
5822                 .addCapability(NET_CAPABILITY_FOREGROUND).build();
5823         final TestNetworkCallback callback = new TestNetworkCallback();
5824         final TestNetworkCallback fgCallback = new TestNetworkCallback();
5825         mCm.registerNetworkCallback(request, callback);
5826         mCm.registerNetworkCallback(fgRequest, fgCallback);
5827 
5828         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
5829         mCellAgent.connect(true);
5830         callback.expectAvailableThenValidatedCallbacks(mCellAgent);
5831         fgCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
5832         assertTrue(isForegroundNetwork(mCellAgent));
5833 
5834         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
5835         mWiFiAgent.connect(true);
5836 
5837         // When wifi connects, cell lingers.
5838         callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
5839         callback.expectLosing(mCellAgent);
5840         callback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
5841         fgCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
5842         fgCallback.expectLosing(mCellAgent);
5843         fgCallback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
5844         assertTrue(isForegroundNetwork(mCellAgent));
5845         assertTrue(isForegroundNetwork(mWiFiAgent));
5846 
5847         // When lingering is complete, cell is still there but is now in the background.
5848         waitForIdle();
5849         int timeoutMs = TEST_LINGER_DELAY_MS + TEST_LINGER_DELAY_MS / 4;
5850         fgCallback.expect(LOST, mCellAgent, timeoutMs);
5851         // Expect a network capabilities update sans FOREGROUND.
5852         callback.expectCaps(mCellAgent, c -> !c.hasCapability(NET_CAPABILITY_FOREGROUND));
5853         assertFalse(isForegroundNetwork(mCellAgent));
5854         assertTrue(isForegroundNetwork(mWiFiAgent));
5855 
5856         // File a cell request and check that cell comes into the foreground.
5857         final NetworkRequest cellRequest = new NetworkRequest.Builder()
5858                 .addTransportType(TRANSPORT_CELLULAR).build();
5859         final TestNetworkCallback cellCallback = new TestNetworkCallback();
5860         mCm.requestNetwork(cellRequest, cellCallback);
5861         cellCallback.expectAvailableCallbacksValidated(mCellAgent);
5862         fgCallback.expectAvailableCallbacksValidated(mCellAgent);
5863         // Expect a network capabilities update with FOREGROUND, because the most recent
5864         // request causes its state to change.
5865         cellCallback.expectCaps(mCellAgent, c -> c.hasCapability(NET_CAPABILITY_FOREGROUND));
5866         callback.expectCaps(mCellAgent, c -> c.hasCapability(NET_CAPABILITY_FOREGROUND));
5867         assertTrue(isForegroundNetwork(mCellAgent));
5868         assertTrue(isForegroundNetwork(mWiFiAgent));
5869 
5870         // Release the request. The network immediately goes into the background, since it was not
5871         // lingering.
5872         mCm.unregisterNetworkCallback(cellCallback);
5873         fgCallback.expect(LOST, mCellAgent);
5874         // Expect a network capabilities update sans FOREGROUND.
5875         callback.expectCaps(mCellAgent, c -> !c.hasCapability(NET_CAPABILITY_FOREGROUND));
5876         assertFalse(isForegroundNetwork(mCellAgent));
5877         assertTrue(isForegroundNetwork(mWiFiAgent));
5878 
5879         // Disconnect wifi and check that cell is foreground again.
5880         mWiFiAgent.disconnect();
5881         callback.expect(LOST, mWiFiAgent);
5882         fgCallback.expect(LOST, mWiFiAgent);
5883         fgCallback.expectAvailableCallbacksValidated(mCellAgent);
5884         assertTrue(isForegroundNetwork(mCellAgent));
5885 
5886         mCm.unregisterNetworkCallback(callback);
5887         mCm.unregisterNetworkCallback(fgCallback);
5888         mCm.unregisterNetworkCallback(cellBgCallback);
5889     }
5890 
5891     @Ignore // This test has instrinsic chances of spurious failures: ignore for continuous testing.
5892     public void benchmarkRequestRegistrationAndCallbackDispatch() throws Exception {
5893         // TODO: turn this unit test into a real benchmarking test.
5894         // Benchmarks connecting and switching performance in the presence of a large number of
5895         // NetworkRequests.
5896         // 1. File NUM_REQUESTS requests.
5897         // 2. Have a network connect. Wait for NUM_REQUESTS onAvailable callbacks to fire.
5898         // 3. Have a new network connect and outscore the previous. Wait for NUM_REQUESTS onLosing
5899         //    and NUM_REQUESTS onAvailable callbacks to fire.
5900         // See how long it took.
5901         final int NUM_REQUESTS = 90;
5902         final int REGISTER_TIME_LIMIT_MS = 200;
5903         final int CONNECT_TIME_LIMIT_MS = 60;
5904         final int SWITCH_TIME_LIMIT_MS = 60;
5905         final int UNREGISTER_TIME_LIMIT_MS = 20;
5906 
5907         final NetworkRequest request = new NetworkRequest.Builder().clearCapabilities().build();
5908         final NetworkCallback[] callbacks = new NetworkCallback[NUM_REQUESTS];
5909         final CountDownLatch availableLatch = new CountDownLatch(NUM_REQUESTS);
5910         final CountDownLatch losingLatch = new CountDownLatch(NUM_REQUESTS);
5911 
5912         for (int i = 0; i < NUM_REQUESTS; i++) {
5913             callbacks[i] = new NetworkCallback() {
5914                 @Override public void onAvailable(Network n) { availableLatch.countDown(); }
5915                 @Override public void onLosing(Network n, int t) { losingLatch.countDown(); }
5916             };
5917         }
5918 
5919         assertRunsInAtMost("Registering callbacks", REGISTER_TIME_LIMIT_MS, () -> {
5920             for (NetworkCallback cb : callbacks) {
5921                 mCm.registerNetworkCallback(request, cb);
5922             }
5923         });
5924 
5925         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
5926         // Don't request that the network validate, because otherwise connect() will block until
5927         // the network gets NET_CAPABILITY_VALIDATED, after all the callbacks below have fired,
5928         // and we won't actually measure anything.
5929         mCellAgent.connect(false);
5930 
5931         long onAvailableDispatchingDuration = durationOf(() -> {
5932             await(availableLatch, 10 * CONNECT_TIME_LIMIT_MS);
5933         });
5934         Log.d(TAG, String.format("Dispatched %d of %d onAvailable callbacks in %dms",
5935                 NUM_REQUESTS - availableLatch.getCount(), NUM_REQUESTS,
5936                 onAvailableDispatchingDuration));
5937         assertTrue(String.format("Dispatching %d onAvailable callbacks in %dms, expected %dms",
5938                 NUM_REQUESTS, onAvailableDispatchingDuration, CONNECT_TIME_LIMIT_MS),
5939                 onAvailableDispatchingDuration <= CONNECT_TIME_LIMIT_MS);
5940 
5941         // Give wifi a high enough score that we'll linger cell when wifi comes up.
5942         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
5943         mWiFiAgent.adjustScore(40);
5944         mWiFiAgent.connect(false);
5945 
5946         long onLostDispatchingDuration = durationOf(() -> {
5947             await(losingLatch, 10 * SWITCH_TIME_LIMIT_MS);
5948         });
5949         Log.d(TAG, String.format("Dispatched %d of %d onLosing callbacks in %dms",
5950                 NUM_REQUESTS - losingLatch.getCount(), NUM_REQUESTS, onLostDispatchingDuration));
5951         assertTrue(String.format("Dispatching %d onLosing callbacks in %dms, expected %dms",
5952                 NUM_REQUESTS, onLostDispatchingDuration, SWITCH_TIME_LIMIT_MS),
5953                 onLostDispatchingDuration <= SWITCH_TIME_LIMIT_MS);
5954 
5955         assertRunsInAtMost("Unregistering callbacks", UNREGISTER_TIME_LIMIT_MS, () -> {
5956             for (NetworkCallback cb : callbacks) {
5957                 mCm.unregisterNetworkCallback(cb);
5958             }
5959         });
5960     }
5961 
5962     @Test
5963     public void testMobileDataAlwaysOn() throws Exception {
5964         grantUsingBackgroundNetworksPermissionForUid(Binder.getCallingUid());
5965         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
5966         final NetworkRequest cellRequest = new NetworkRequest.Builder()
5967                 .addTransportType(TRANSPORT_CELLULAR).build();
5968         mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
5969 
5970         final HandlerThread handlerThread = new HandlerThread("MobileDataAlwaysOnFactory");
5971         handlerThread.start();
5972         NetworkCapabilities filter = new NetworkCapabilities()
5973                 .addTransportType(TRANSPORT_CELLULAR)
5974                 .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
5975                 .addCapability(NET_CAPABILITY_INTERNET);
5976         final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
5977                 mServiceContext, "testFactory", filter, mCsHandlerThread);
5978         testFactory.setScoreFilter(40);
5979 
5980         // Register the factory and expect it to start looking for a network.
5981         testFactory.register();
5982 
5983         try {
5984             // Expect the factory to receive the default network request.
5985             testFactory.expectRequestAdd();
5986             testFactory.assertRequestCountEquals(1);
5987             assertTrue(testFactory.getMyStartRequested());
5988 
5989             // Bring up wifi. The factory stops looking for a network.
5990             mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
5991             // Score 60 - 40 penalty for not validated yet, then 60 when it validates
5992             mWiFiAgent.connect(true);
5993             // The network connects with a low score, so the offer can still beat it and
5994             // nothing happens. Then the network validates, and the offer with its filter score
5995             // of 40 can no longer beat it and the request is removed.
5996             testFactory.expectRequestRemove();
5997             testFactory.assertRequestCountEquals(0);
5998 
5999             assertFalse(testFactory.getMyStartRequested());
6000 
6001             // Turn on mobile data always on. This request will not match the wifi request, so
6002             // it will be sent to the test factory whose filters allow to see it.
6003             setAlwaysOnNetworks(true);
6004             testFactory.expectRequestAdd();
6005             testFactory.assertRequestCountEquals(1);
6006 
6007             assertTrue(testFactory.getMyStartRequested());
6008 
6009             // Bring up cell data and check that the factory stops looking.
6010             assertLength(1, mCm.getAllNetworks());
6011             mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
6012             mCellAgent.connect(false);
6013             cellNetworkCallback.expectAvailableCallbacks(mCellAgent, false, false, false,
6014                     TEST_CALLBACK_TIMEOUT_MS);
6015             // When cell connects, it will satisfy the "mobile always on request" right away
6016             // by virtue of being the only network that can satisfy the request. However, its
6017             // score is low (50 - 40 = 10) so the test factory can still hope to beat it.
6018             expectNoRequestChanged(testFactory);
6019 
6020             // Next, cell validates. This gives it a score of 50 and the test factory can't
6021             // hope to beat that according to its filters. It will see the message that its
6022             // offer is now unnecessary.
6023             mCellAgent.setNetworkValid(true);
6024             // Need a trigger point to let NetworkMonitor tell ConnectivityService that network is
6025             // validated – see testPartialConnectivity.
6026             mCm.reportNetworkConnectivity(mCellAgent.getNetwork(), true);
6027             cellNetworkCallback.expectCaps(mCellAgent,
6028                     c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
6029             testFactory.expectRequestRemove();
6030             testFactory.assertRequestCountEquals(0);
6031             // Accordingly, the factory shouldn't be started.
6032             assertFalse(testFactory.getMyStartRequested());
6033 
6034             // Check that cell data stays up.
6035             waitForIdle();
6036             verifyActiveNetwork(TRANSPORT_WIFI);
6037             assertLength(2, mCm.getAllNetworks());
6038 
6039             // Cell disconnects. There is still the "mobile data always on" request outstanding,
6040             // and the test factory should see it now that it isn't hopelessly outscored.
6041             mCellAgent.disconnect();
6042             cellNetworkCallback.expect(LOST, mCellAgent);
6043             // Wait for the network to be removed from internal structures before
6044             // calling synchronous getter
6045             waitForIdle();
6046             assertLength(1, mCm.getAllNetworks());
6047             testFactory.expectRequestAdd();
6048             testFactory.assertRequestCountEquals(1);
6049 
6050             // Reconnect cell validated, see the request disappear again. Then withdraw the
6051             // mobile always on request. This will tear down cell, and there shouldn't be a
6052             // blip where the test factory briefly sees the request or anything.
6053             mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
6054             mCellAgent.connect(true);
6055             cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
6056             waitForIdle();
6057             assertLength(2, mCm.getAllNetworks());
6058             testFactory.expectRequestRemove();
6059             testFactory.assertRequestCountEquals(0);
6060             setAlwaysOnNetworks(false);
6061             expectNoRequestChanged(testFactory);
6062             testFactory.assertRequestCountEquals(0);
6063             assertFalse(testFactory.getMyStartRequested());
6064             // ...  and cell data to be torn down immediately since it is no longer nascent.
6065             cellNetworkCallback.expect(LOST, mCellAgent);
6066             waitForIdle();
6067             assertLength(1, mCm.getAllNetworks());
6068             testFactory.terminate();
6069             testFactory.assertNoRequestChanged();
6070         } finally {
6071             mCm.unregisterNetworkCallback(cellNetworkCallback);
6072             handlerThread.quitSafely();
6073             handlerThread.join();
6074         }
6075     }
6076 
6077     @Test
6078     public void testSetAllowBadWifiUntil() throws Exception {
6079         runAsShell(NETWORK_SETTINGS,
6080                 () -> mService.setTestAllowBadWifiUntil(System.currentTimeMillis() + 5_000L));
6081         waitForIdle();
6082         testAvoidBadWifiConfig_controlledBySettings();
6083 
6084         runAsShell(NETWORK_SETTINGS,
6085                 () -> mService.setTestAllowBadWifiUntil(System.currentTimeMillis() - 5_000L));
6086         waitForIdle();
6087         testAvoidBadWifiConfig_ignoreSettings();
6088     }
6089 
6090     private void testAvoidBadWifiConfig_controlledBySettings() {
6091         final ContentResolver cr = mServiceContext.getContentResolver();
6092         final String settingName = ConnectivitySettingsManager.NETWORK_AVOID_BAD_WIFI;
6093 
6094         Settings.Global.putString(cr, settingName, "0");
6095         mPolicyTracker.reevaluate();
6096         waitForIdle();
6097         assertFalse(mService.avoidBadWifi());
6098         assertFalse(mPolicyTracker.shouldNotifyWifiUnvalidated());
6099 
6100         Settings.Global.putString(cr, settingName, "1");
6101         mPolicyTracker.reevaluate();
6102         waitForIdle();
6103         assertTrue(mService.avoidBadWifi());
6104         assertFalse(mPolicyTracker.shouldNotifyWifiUnvalidated());
6105 
6106         Settings.Global.putString(cr, settingName, null);
6107         mPolicyTracker.reevaluate();
6108         waitForIdle();
6109         assertFalse(mService.avoidBadWifi());
6110         assertTrue(mPolicyTracker.shouldNotifyWifiUnvalidated());
6111     }
6112 
6113     private void testAvoidBadWifiConfig_ignoreSettings() {
6114         final ContentResolver cr = mServiceContext.getContentResolver();
6115         final String settingName = ConnectivitySettingsManager.NETWORK_AVOID_BAD_WIFI;
6116 
6117         String[] values = new String[] {null, "0", "1"};
6118         for (int i = 0; i < values.length; i++) {
6119             Settings.Global.putString(cr, settingName, values[i]);
6120             mPolicyTracker.reevaluate();
6121             waitForIdle();
6122             String msg = String.format("config=false, setting=%s", values[i]);
6123             assertTrue(mService.avoidBadWifi());
6124             assertFalse(msg, mPolicyTracker.shouldNotifyWifiUnvalidated());
6125         }
6126     }
6127 
6128     @Test
6129     public void testAvoidBadWifiSetting() throws Exception {
6130         doReturn(1).when(mResources).getInteger(R.integer.config_networkAvoidBadWifi);
6131         testAvoidBadWifiConfig_ignoreSettings();
6132 
6133         doReturn(0).when(mResources).getInteger(R.integer.config_networkAvoidBadWifi);
6134         testAvoidBadWifiConfig_controlledBySettings();
6135     }
6136 
6137     @Test
6138     public void testActivelyPreferBadWifiSetting() throws Exception {
6139         doReturn(1).when(mResources).getInteger(R.integer.config_activelyPreferBadWifi);
6140         mPolicyTracker.reevaluate();
6141         waitForIdle();
6142         assertTrue(mService.mNetworkRanker.getConfiguration().activelyPreferBadWifi());
6143 
6144         doReturn(0).when(mResources).getInteger(R.integer.config_activelyPreferBadWifi);
6145         mPolicyTracker.reevaluate();
6146         waitForIdle();
6147         if (mDeps.isAtLeastU()) {
6148             // U+ ignore the setting and always actively prefers bad wifi
6149             assertTrue(mService.mNetworkRanker.getConfiguration().activelyPreferBadWifi());
6150         } else {
6151             assertFalse(mService.mNetworkRanker.getConfiguration().activelyPreferBadWifi());
6152         }
6153     }
6154 
6155     @Test
6156     public void testOffersAvoidsBadWifi() throws Exception {
6157         // Normal mode : the carrier doesn't restrict moving away from bad wifi.
6158         // This has getAvoidBadWifi return true.
6159         doReturn(1).when(mResources).getInteger(R.integer.config_networkAvoidBadWifi);
6160         // Don't request cell separately for the purposes of this test.
6161         setAlwaysOnNetworks(false);
6162 
6163         final NetworkProvider cellProvider = new NetworkProvider(mServiceContext,
6164                 mCsHandlerThread.getLooper(), "Cell provider");
6165         final NetworkProvider wifiProvider = new NetworkProvider(mServiceContext,
6166                 mCsHandlerThread.getLooper(), "Wifi provider");
6167 
6168         mCm.registerNetworkProvider(cellProvider);
6169         mCm.registerNetworkProvider(wifiProvider);
6170 
6171         final NetworkScore cellScore = new NetworkScore.Builder().build();
6172         final NetworkScore wifiScore = new NetworkScore.Builder().build();
6173         final NetworkCapabilities defaultCaps = new NetworkCapabilities.Builder()
6174                 .addCapability(NET_CAPABILITY_INTERNET)
6175                 .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
6176                 .build();
6177         final NetworkCapabilities cellCaps = new NetworkCapabilities.Builder()
6178                 .addTransportType(TRANSPORT_CELLULAR)
6179                 .addCapability(NET_CAPABILITY_INTERNET)
6180                 .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
6181                 .build();
6182         final NetworkCapabilities wifiCaps = new NetworkCapabilities.Builder()
6183                 .addTransportType(TRANSPORT_WIFI)
6184                 .addCapability(NET_CAPABILITY_INTERNET)
6185                 .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
6186                 .build();
6187         final TestableNetworkOfferCallback cellCallback = new TestableNetworkOfferCallback(
6188                 TIMEOUT_MS /* timeout */, TEST_CALLBACK_TIMEOUT_MS /* noCallbackTimeout */);
6189         final TestableNetworkOfferCallback wifiCallback = new TestableNetworkOfferCallback(
6190                 TIMEOUT_MS /* timeout */, TEST_CALLBACK_TIMEOUT_MS /* noCallbackTimeout */);
6191 
6192         // Offer callbacks will run on the CS handler thread in this test.
6193         cellProvider.registerNetworkOffer(cellScore, cellCaps, r -> r.run(), cellCallback);
6194         wifiProvider.registerNetworkOffer(wifiScore, wifiCaps, r -> r.run(), wifiCallback);
6195 
6196         // Both providers see the default request.
6197         cellCallback.expectOnNetworkNeeded(defaultCaps);
6198         wifiCallback.expectOnNetworkNeeded(defaultCaps);
6199 
6200         // Listen to cell and wifi to know when agents are finished processing
6201         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
6202         final NetworkRequest cellRequest = new NetworkRequest.Builder()
6203                 .addTransportType(TRANSPORT_CELLULAR).build();
6204         mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
6205         final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
6206         final NetworkRequest wifiRequest = new NetworkRequest.Builder()
6207                 .addTransportType(TRANSPORT_WIFI).build();
6208         mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
6209 
6210         // Cell connects and validates.
6211         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR,
6212                 new LinkProperties(), null /* ncTemplate */, cellProvider);
6213         mCellAgent.connect(true);
6214         cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
6215         cellCallback.assertNoCallback();
6216         wifiCallback.assertNoCallback();
6217 
6218         // Bring up wifi. At first it's invalidated, so cell is still needed.
6219         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI,
6220                 new LinkProperties(), null /* ncTemplate */, wifiProvider);
6221         mWiFiAgent.connect(false);
6222         wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
6223         cellCallback.assertNoCallback();
6224         wifiCallback.assertNoCallback();
6225 
6226         // Wifi validates. Cell is no longer needed, because it's outscored.
6227         mWiFiAgent.setNetworkValid(true /* privateDnsProbeSent */);
6228         // Have CS reconsider the network (see testPartialConnectivity)
6229         mCm.reportNetworkConnectivity(mWiFiAgent.getNetwork(), true);
6230         wifiNetworkCallback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
6231         cellCallback.expectOnNetworkUnneeded(defaultCaps);
6232         wifiCallback.assertNoCallback();
6233 
6234         // Wifi is no longer validated. Cell is needed again.
6235         mWiFiAgent.setNetworkInvalid(true /* invalidBecauseOfPrivateDns */);
6236         mCm.reportNetworkConnectivity(mWiFiAgent.getNetwork(), false);
6237         wifiNetworkCallback.expectCaps(mWiFiAgent,
6238                 c -> !c.hasCapability(NET_CAPABILITY_VALIDATED));
6239         cellCallback.expectOnNetworkNeeded(defaultCaps);
6240         wifiCallback.assertNoCallback();
6241 
6242         // Disconnect wifi and pretend the carrier restricts moving away from bad wifi.
6243         mWiFiAgent.disconnect();
6244         wifiNetworkCallback.expect(LOST, mWiFiAgent);
6245         // This has getAvoidBadWifi return false. This test doesn't change the value of the
6246         // associated setting.
6247         doReturn(0).when(mResources).getInteger(R.integer.config_networkAvoidBadWifi);
6248         mPolicyTracker.reevaluate();
6249         waitForIdle();
6250 
6251         // Connect wifi again, cell is needed until wifi validates.
6252         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI,
6253                 new LinkProperties(), null /* ncTemplate */, wifiProvider);
6254         mWiFiAgent.connect(false);
6255         wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
6256         cellCallback.assertNoCallback();
6257         wifiCallback.assertNoCallback();
6258         mWiFiAgent.setNetworkValid(true /* privateDnsProbeSent */);
6259         mCm.reportNetworkConnectivity(mWiFiAgent.getNetwork(), true);
6260         wifiNetworkCallback.expectCaps(mWiFiAgent,
6261                 c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
6262         cellCallback.expectOnNetworkUnneeded(defaultCaps);
6263         wifiCallback.assertNoCallback();
6264 
6265         // Wifi loses validation. Because the device doesn't avoid bad wifis, cell is
6266         // not needed.
6267         mWiFiAgent.setNetworkInvalid(true /* invalidBecauseOfPrivateDns */);
6268         mCm.reportNetworkConnectivity(mWiFiAgent.getNetwork(), false);
6269         wifiNetworkCallback.expectCaps(mWiFiAgent,
6270                 c -> !c.hasCapability(NET_CAPABILITY_VALIDATED));
6271         cellCallback.assertNoCallback();
6272         wifiCallback.assertNoCallback();
6273     }
6274 
6275     public void doTestPreferBadWifi(final boolean avoidBadWifi,
6276             final boolean preferBadWifi, final boolean explicitlySelected,
6277             @NonNull Predicate<Long> checkUnvalidationTimeout) throws Exception {
6278         // Pretend we're on a carrier that restricts switching away from bad wifi, and
6279         // depending on the parameter one that may indeed prefer bad wifi.
6280         doReturn(avoidBadWifi ? 1 : 0).when(mResources)
6281                 .getInteger(R.integer.config_networkAvoidBadWifi);
6282         doReturn(preferBadWifi ? 1 : 0).when(mResources)
6283                 .getInteger(R.integer.config_activelyPreferBadWifi);
6284         mPolicyTracker.reevaluate();
6285 
6286         registerDefaultNetworkCallbacks();
6287         final NetworkRequest wifiRequest = new NetworkRequest.Builder()
6288                 .clearCapabilities()
6289                 .addTransportType(TRANSPORT_WIFI)
6290                 .build();
6291         final TestNetworkCallback wifiCallback = new TestNetworkCallback();
6292         mCm.registerNetworkCallback(wifiRequest, wifiCallback);
6293 
6294         // Bring up validated cell and unvalidated wifi.
6295         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
6296         mCellAgent.connect(true);
6297         mDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
6298 
6299         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
6300         mWiFiAgent.explicitlySelected(explicitlySelected, false /* acceptUnvalidated */);
6301         mWiFiAgent.connect(false);
6302         wifiCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
6303 
6304         assertNotNull(mDeps.mScheduledEvaluationTimeouts.poll(TIMEOUT_MS,
6305                 t -> t.first == mWiFiAgent.getNetwork().netId
6306                         && checkUnvalidationTimeout.test(t.second)));
6307 
6308         if (!avoidBadWifi && preferBadWifi) {
6309             expectUnvalidationCheckWillNotify(mWiFiAgent, NotificationType.LOST_INTERNET);
6310             mDefaultNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
6311         } else {
6312             expectUnvalidationCheckWillNotNotify(mWiFiAgent);
6313             mDefaultNetworkCallback.assertNoCallback();
6314         }
6315     }
6316 
6317     @Test
6318     public void testPreferBadWifi_doNotAvoid_doNotPrefer() throws Exception {
6319         // Starting with U this mode is no longer supported and can't actually be tested
6320         assumeFalse(mDeps.isAtLeastU());
6321         doTestPreferBadWifi(false /* avoidBadWifi */, false /* preferBadWifi */,
6322                 false /* explicitlySelected */, timeout -> timeout < 14_000);
6323     }
6324 
6325     @Test
6326     public void testPreferBadWifi_doNotAvoid_doPrefer_notExplicit() throws Exception {
6327         doTestPreferBadWifi(false /* avoidBadWifi */, true /* preferBadWifi */,
6328                 false /* explicitlySelected */, timeout -> timeout > 14_000);
6329     }
6330 
6331     @Test
6332     public void testPreferBadWifi_doNotAvoid_doPrefer_explicitlySelected() throws Exception {
6333         doTestPreferBadWifi(false /* avoidBadWifi */, true /* preferBadWifi */,
6334                 true /* explicitlySelected */, timeout -> timeout < 14_000);
6335     }
6336 
6337     @Test
6338     public void testPreferBadWifi_doAvoid_doNotPrefer() throws Exception {
6339         // If avoidBadWifi=true, then preferBadWifi should be irrelevant. Test anyway.
6340         doTestPreferBadWifi(true /* avoidBadWifi */, false /* preferBadWifi */,
6341                 false /* explicitlySelected */, timeout -> timeout < 14_000);
6342     }
6343 
6344     @Test
6345     public void testPreferBadWifi_doAvoid_doPrefer() throws Exception {
6346         // If avoidBadWifi=true, then preferBadWifi should be irrelevant. Test anyway.
6347         doTestPreferBadWifi(true /* avoidBadWifi */, true /* preferBadWifi */,
6348                 false /* explicitlySelected */, timeout -> timeout < 14_000);
6349     }
6350 
6351     @Test
6352     public void testAvoidBadWifi() throws Exception {
6353         final ContentResolver cr = mServiceContext.getContentResolver();
6354 
6355         // Pretend we're on a carrier that restricts switching away from bad wifi.
6356         doReturn(0).when(mResources).getInteger(R.integer.config_networkAvoidBadWifi);
6357 
6358         // File a request for cell to ensure it doesn't go down.
6359         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
6360         final NetworkRequest cellRequest = new NetworkRequest.Builder()
6361                 .addTransportType(TRANSPORT_CELLULAR).build();
6362         mCm.requestNetwork(cellRequest, cellNetworkCallback);
6363 
6364         TestNetworkCallback defaultCallback = new TestNetworkCallback();
6365         mCm.registerDefaultNetworkCallback(defaultCallback);
6366 
6367         NetworkRequest validatedWifiRequest = new NetworkRequest.Builder()
6368                 .addTransportType(TRANSPORT_WIFI)
6369                 .addCapability(NET_CAPABILITY_VALIDATED)
6370                 .build();
6371         TestNetworkCallback validatedWifiCallback = new TestNetworkCallback();
6372         mCm.registerNetworkCallback(validatedWifiRequest, validatedWifiCallback);
6373 
6374         // Prompt mode, so notifications can be tested
6375         Settings.Global.putString(cr, ConnectivitySettingsManager.NETWORK_AVOID_BAD_WIFI, null);
6376         mPolicyTracker.reevaluate();
6377 
6378         // Bring up validated cell.
6379         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
6380         mCellAgent.connect(true);
6381         cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
6382         defaultCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
6383         Network cellNetwork = mCellAgent.getNetwork();
6384 
6385         // Bring up validated wifi.
6386         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
6387         mWiFiAgent.connect(true);
6388         defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiAgent);
6389         validatedWifiCallback.expectAvailableDoubleValidatedCallbacks(mWiFiAgent);
6390         Network wifiNetwork = mWiFiAgent.getNetwork();
6391 
6392         // Fail validation on wifi.
6393         mWiFiAgent.setNetworkInvalid(false /* invalidBecauseOfPrivateDns */);
6394         mCm.reportNetworkConnectivity(wifiNetwork, false);
6395         defaultCallback.expectCaps(mWiFiAgent, c -> !c.hasCapability(NET_CAPABILITY_VALIDATED));
6396         validatedWifiCallback.expect(LOST, mWiFiAgent);
6397         expectNotification(mWiFiAgent, NotificationType.LOST_INTERNET);
6398 
6399         // Because avoid bad wifi is off, we don't switch to cellular.
6400         defaultCallback.assertNoCallback();
6401         assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
6402                 NET_CAPABILITY_VALIDATED));
6403         assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
6404                 NET_CAPABILITY_VALIDATED));
6405         assertEquals(mCm.getActiveNetwork(), wifiNetwork);
6406 
6407         // Simulate switching to a carrier that does not restrict avoiding bad wifi, and expect
6408         // that we switch back to cell.
6409         doReturn(1).when(mResources).getInteger(R.integer.config_networkAvoidBadWifi);
6410         mPolicyTracker.reevaluate();
6411         defaultCallback.expectAvailableCallbacksValidated(mCellAgent);
6412         assertEquals(mCm.getActiveNetwork(), cellNetwork);
6413         expectClearNotification(mWiFiAgent, NotificationType.LOST_INTERNET);
6414 
6415         // Switch back to a restrictive carrier.
6416         doReturn(0).when(mResources).getInteger(R.integer.config_networkAvoidBadWifi);
6417         mPolicyTracker.reevaluate();
6418         defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
6419         assertEquals(mCm.getActiveNetwork(), wifiNetwork);
6420         // A notification was already shown for this very network.
6421         expectNoNotification(mWiFiAgent);
6422 
6423         // Simulate the user selecting "switch" on the dialog, and check that we switch to cell.
6424         // In principle this is a little bit unrealistic because the switch to a less restrictive
6425         // carrier above should have remove the notification but this doesn't matter for the
6426         // purposes of this test.
6427         mCm.setAvoidUnvalidated(wifiNetwork);
6428         defaultCallback.expectAvailableCallbacksValidated(mCellAgent);
6429         assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
6430                 NET_CAPABILITY_VALIDATED));
6431         assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
6432                 NET_CAPABILITY_VALIDATED));
6433         assertEquals(mCm.getActiveNetwork(), cellNetwork);
6434 
6435         // Disconnect and reconnect wifi to clear the one-time switch above.
6436         mWiFiAgent.disconnect();
6437         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
6438         mWiFiAgent.connect(true);
6439         defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiAgent);
6440         validatedWifiCallback.expectAvailableDoubleValidatedCallbacks(mWiFiAgent);
6441         wifiNetwork = mWiFiAgent.getNetwork();
6442 
6443         // Fail validation on wifi and expect the dialog to appear.
6444         mWiFiAgent.setNetworkInvalid(false /* invalidBecauseOfPrivateDns */);
6445         mCm.reportNetworkConnectivity(wifiNetwork, false);
6446         defaultCallback.expectCaps(mWiFiAgent, c -> !c.hasCapability(NET_CAPABILITY_VALIDATED));
6447         validatedWifiCallback.expect(LOST, mWiFiAgent);
6448         expectNotification(mWiFiAgent, NotificationType.LOST_INTERNET);
6449 
6450         // Simulate the user selecting "switch" and checking the don't ask again checkbox.
6451         Settings.Global.putInt(cr, ConnectivitySettingsManager.NETWORK_AVOID_BAD_WIFI, 1);
6452         mPolicyTracker.reevaluate();
6453 
6454         // We now switch to cell.
6455         defaultCallback.expectAvailableCallbacksValidated(mCellAgent);
6456         assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
6457                 NET_CAPABILITY_VALIDATED));
6458         assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
6459                 NET_CAPABILITY_VALIDATED));
6460         assertEquals(mCm.getActiveNetwork(), cellNetwork);
6461         expectClearNotification(mWiFiAgent, NotificationType.LOST_INTERNET);
6462 
6463         // Simulate the user turning the cellular fallback setting off and then on.
6464         // We switch to wifi and then to cell.
6465         Settings.Global.putString(cr, ConnectivitySettingsManager.NETWORK_AVOID_BAD_WIFI, null);
6466         mPolicyTracker.reevaluate();
6467         defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
6468         assertEquals(mCm.getActiveNetwork(), wifiNetwork);
6469         // Notification is cleared again because CS doesn't particularly remember that it has
6470         // cleared it before, and if it hasn't cleared it before then it should do so now.
6471         expectClearNotification(mWiFiAgent, NotificationType.LOST_INTERNET);
6472         Settings.Global.putInt(cr, ConnectivitySettingsManager.NETWORK_AVOID_BAD_WIFI, 1);
6473         mPolicyTracker.reevaluate();
6474         defaultCallback.expectAvailableCallbacksValidated(mCellAgent);
6475         assertEquals(mCm.getActiveNetwork(), cellNetwork);
6476 
6477         // If cell goes down, we switch to wifi.
6478         mCellAgent.disconnect();
6479         defaultCallback.expect(LOST, mCellAgent);
6480         defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
6481         validatedWifiCallback.assertNoCallback();
6482         // Notification is cleared yet again because the device switched to wifi.
6483         expectClearNotification(mWiFiAgent, NotificationType.LOST_INTERNET);
6484 
6485         mCm.unregisterNetworkCallback(cellNetworkCallback);
6486         mCm.unregisterNetworkCallback(validatedWifiCallback);
6487         mCm.unregisterNetworkCallback(defaultCallback);
6488     }
6489 
6490     @Test
6491     public void testMeteredMultipathPreferenceSetting() throws Exception {
6492         final ContentResolver cr = mServiceContext.getContentResolver();
6493         final String settingName = ConnectivitySettingsManager.NETWORK_METERED_MULTIPATH_PREFERENCE;
6494 
6495         for (int config : asList(0, 3, 2)) {
6496             for (String setting: asList(null, "0", "2", "1")) {
6497                 mPolicyTracker.mConfigMeteredMultipathPreference = config;
6498                 Settings.Global.putString(cr, settingName, setting);
6499                 mPolicyTracker.reevaluate();
6500                 waitForIdle();
6501 
6502                 final int expected = (setting != null) ? Integer.parseInt(setting) : config;
6503                 String msg = String.format("config=%d, setting=%s", config, setting);
6504                 assertEquals(msg, expected, mCm.getMultipathPreference(null));
6505             }
6506         }
6507     }
6508 
6509     /**
6510      * Validate that a satisfied network request does not trigger onUnavailable() once the
6511      * time-out period expires.
6512      */
6513     @Test
6514     public void testSatisfiedNetworkRequestDoesNotTriggerOnUnavailable() throws Exception {
6515         NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
6516                 NetworkCapabilities.TRANSPORT_WIFI).build();
6517         final TestNetworkCallback networkCallback = new TestNetworkCallback();
6518         mCm.requestNetwork(nr, networkCallback, TEST_REQUEST_TIMEOUT_MS);
6519 
6520         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
6521         mWiFiAgent.connect(false);
6522         networkCallback.expectAvailableCallbacks(mWiFiAgent, false, false, false,
6523                 TEST_CALLBACK_TIMEOUT_MS);
6524 
6525         // pass timeout and validate that UNAVAILABLE is not called
6526         networkCallback.assertNoCallback();
6527     }
6528 
6529     /**
6530      * Validate that a satisfied network request followed by a disconnected (lost) network does
6531      * not trigger onUnavailable() once the time-out period expires.
6532      */
6533     @Test
6534     public void testSatisfiedThenLostNetworkRequestDoesNotTriggerOnUnavailable() throws Exception {
6535         NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
6536                 NetworkCapabilities.TRANSPORT_WIFI).build();
6537         final TestNetworkCallback networkCallback = new TestNetworkCallback();
6538         mCm.requestNetwork(nr, networkCallback, TEST_REQUEST_TIMEOUT_MS);
6539 
6540         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
6541         mWiFiAgent.connect(false);
6542         networkCallback.expectAvailableCallbacks(mWiFiAgent, false, false, false,
6543                 TEST_CALLBACK_TIMEOUT_MS);
6544         mWiFiAgent.disconnect();
6545         networkCallback.expect(LOST, mWiFiAgent);
6546 
6547         // Validate that UNAVAILABLE is not called
6548         networkCallback.assertNoCallback();
6549     }
6550 
6551     /**
6552      * Validate that when a time-out is specified for a network request the onUnavailable()
6553      * callback is called when time-out expires. Then validate that if network request is
6554      * (somehow) satisfied - the callback isn't called later.
6555      */
6556     @Test
6557     public void testTimedoutNetworkRequest() throws Exception {
6558         NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
6559                 NetworkCapabilities.TRANSPORT_WIFI).build();
6560         final TestNetworkCallback networkCallback = new TestNetworkCallback();
6561         final int timeoutMs = 10;
6562         mCm.requestNetwork(nr, networkCallback, timeoutMs);
6563 
6564         // pass timeout and validate that UNAVAILABLE is called
6565         networkCallback.expect(UNAVAILABLE);
6566 
6567         // create a network satisfying request - validate that request not triggered
6568         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
6569         mWiFiAgent.connect(false);
6570         networkCallback.assertNoCallback();
6571     }
6572 
6573     /**
6574      * Validate that when a network request is unregistered (cancelled), no posterior event can
6575      * trigger the callback.
6576      */
6577     @Test
6578     public void testNoCallbackAfterUnregisteredNetworkRequest() throws Exception {
6579         NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
6580                 NetworkCapabilities.TRANSPORT_WIFI).build();
6581         final TestNetworkCallback networkCallback = new TestNetworkCallback();
6582         final int timeoutMs = 10;
6583 
6584         mCm.requestNetwork(nr, networkCallback, timeoutMs);
6585         mCm.unregisterNetworkCallback(networkCallback);
6586         // Regardless of the timeout, unregistering the callback in ConnectivityManager ensures
6587         // that this callback will not be called.
6588         networkCallback.assertNoCallback();
6589 
6590         // create a network satisfying request - validate that request not triggered
6591         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
6592         mWiFiAgent.connect(false);
6593         networkCallback.assertNoCallback();
6594     }
6595 
6596     @Test
6597     public void testUnfulfillableNetworkRequest() throws Exception {
6598         runUnfulfillableNetworkRequest(false);
6599     }
6600 
6601     @Test
6602     public void testUnfulfillableNetworkRequestAfterUnregister() throws Exception {
6603         runUnfulfillableNetworkRequest(true);
6604     }
6605 
6606     /**
6607      * Validate the callback flow for a factory releasing a request as unfulfillable.
6608      */
6609     private void runUnfulfillableNetworkRequest(boolean preUnregister) throws Exception {
6610         NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
6611                 NetworkCapabilities.TRANSPORT_WIFI).build();
6612         final TestNetworkCallback networkCallback = new TestNetworkCallback();
6613 
6614         final HandlerThread handlerThread = new HandlerThread("testUnfulfillableNetworkRequest");
6615         handlerThread.start();
6616         NetworkCapabilities filter = new NetworkCapabilities()
6617                 .addTransportType(TRANSPORT_WIFI)
6618                 .addCapability(NET_CAPABILITY_INTERNET)
6619                 .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED);
6620         final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
6621                 mServiceContext, "testFactory", filter, mCsHandlerThread);
6622         testFactory.setScoreFilter(40);
6623 
6624         // Register the factory and expect it to receive the default request.
6625         testFactory.register();
6626         testFactory.expectRequestAdd();
6627 
6628         try {
6629             // Now file the test request and expect it.
6630             mCm.requestNetwork(nr, networkCallback);
6631             final NetworkRequest newRequest = testFactory.expectRequestAdd().request;
6632 
6633             if (preUnregister) {
6634                 mCm.unregisterNetworkCallback(networkCallback);
6635 
6636                 // The request has been released : the factory should see it removed
6637                 // immediately.
6638                 testFactory.expectRequestRemove();
6639 
6640                 // Simulate the factory releasing the request as unfulfillable: no-op since
6641                 // the callback has already been unregistered (but a test that no exceptions are
6642                 // thrown).
6643                 testFactory.triggerUnfulfillable(newRequest);
6644             } else {
6645                 // Simulate the factory releasing the request as unfulfillable and expect
6646                 // onUnavailable!
6647                 testFactory.triggerUnfulfillable(newRequest);
6648 
6649                 networkCallback.expect(UNAVAILABLE);
6650 
6651                 // Declaring a request unfulfillable releases it automatically.
6652                 testFactory.expectRequestRemove();
6653 
6654                 // unregister network callback - a no-op (since already freed by the
6655                 // on-unavailable), but should not fail or throw exceptions.
6656                 mCm.unregisterNetworkCallback(networkCallback);
6657 
6658                 // The factory should not see any further removal, as this request has
6659                 // already been removed.
6660             }
6661         } finally {
6662             testFactory.terminate();
6663             handlerThread.quitSafely();
6664             handlerThread.join();
6665         }
6666     }
6667 
6668     @Test
6669     @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
6670     @DisableCompatChanges(ConnectivityCompatChanges.ENABLE_SELF_CERTIFIED_CAPABILITIES_DECLARATION)
6671     public void testSelfCertifiedCapabilitiesDisabled()
6672             throws Exception {
6673         mDeps.enableCompatChangeCheck();
6674         final NetworkRequest networkRequest = new NetworkRequest.Builder()
6675                 .addCapability(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_LATENCY)
6676                 .addCapability(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_BANDWIDTH)
6677                 .build();
6678         final TestNetworkCallback cb = new TestNetworkCallback();
6679         mCm.requestNetwork(networkRequest, cb);
6680         mCm.unregisterNetworkCallback(cb);
6681     }
6682 
6683     /** Set the networkSliceResourceId to 0 will result in NameNotFoundException be thrown. */
6684     private void setupMockForNetworkCapabilitiesResources(int networkSliceResourceId)
6685             throws PackageManager.NameNotFoundException {
6686         if (networkSliceResourceId == 0) {
6687             doThrow(new PackageManager.NameNotFoundException()).when(mPackageManager).getProperty(
6688                     ConstantsShim.PROPERTY_SELF_CERTIFIED_NETWORK_CAPABILITIES,
6689                     mContext.getPackageName());
6690         } else {
6691             final PackageManager.Property property = new PackageManager.Property(
6692                     ConstantsShim.PROPERTY_SELF_CERTIFIED_NETWORK_CAPABILITIES,
6693                     networkSliceResourceId,
6694                     true /* isResource */,
6695                     mContext.getPackageName(),
6696                     "dummyClass"
6697             );
6698             doReturn(property).when(mPackageManager).getProperty(
6699                     ConstantsShim.PROPERTY_SELF_CERTIFIED_NETWORK_CAPABILITIES,
6700                     mContext.getPackageName());
6701             doReturn(mContext.getResources()).when(mPackageManager).getResourcesForApplication(
6702                     mContext.getPackageName());
6703         }
6704     }
6705 
6706     @Test
6707     @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
6708     @EnableCompatChanges(ConnectivityCompatChanges.ENABLE_SELF_CERTIFIED_CAPABILITIES_DECLARATION)
6709     public void requestNetwork_withoutPrioritizeBandwidthDeclaration_shouldThrowException()
6710             throws Exception {
6711         mDeps.enableCompatChangeCheck();
6712         setupMockForNetworkCapabilitiesResources(
6713                 com.android.frameworks.tests.net.R.xml.self_certified_capabilities_latency);
6714         final NetworkRequest networkRequest = new NetworkRequest.Builder()
6715                 .addCapability(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_BANDWIDTH)
6716                 .build();
6717         final TestNetworkCallback cb = new TestNetworkCallback();
6718         final Exception e = assertThrows(SecurityException.class,
6719                 () -> mCm.requestNetwork(networkRequest, cb));
6720         assertThat(e.getMessage(),
6721                 containsString(ApplicationSelfCertifiedNetworkCapabilities.PRIORITIZE_BANDWIDTH));
6722     }
6723 
6724     @Test
6725     @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
6726     @EnableCompatChanges(ConnectivityCompatChanges.ENABLE_SELF_CERTIFIED_CAPABILITIES_DECLARATION)
6727     public void requestNetwork_withoutPrioritizeLatencyDeclaration_shouldThrowException()
6728             throws Exception {
6729         mDeps.enableCompatChangeCheck();
6730         setupMockForNetworkCapabilitiesResources(
6731                 com.android.frameworks.tests.net.R.xml.self_certified_capabilities_bandwidth);
6732         final NetworkRequest networkRequest = new NetworkRequest.Builder()
6733                 .addCapability(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_LATENCY)
6734                 .build();
6735         final TestNetworkCallback cb = new TestNetworkCallback();
6736         final Exception e = assertThrows(SecurityException.class,
6737                 () -> mCm.requestNetwork(networkRequest, cb));
6738         assertThat(e.getMessage(),
6739                 containsString(ApplicationSelfCertifiedNetworkCapabilities.PRIORITIZE_LATENCY));
6740     }
6741 
6742     @Test
6743     @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
6744     @EnableCompatChanges(ConnectivityCompatChanges.ENABLE_SELF_CERTIFIED_CAPABILITIES_DECLARATION)
6745     public void requestNetwork_withoutNetworkSliceProperty_shouldThrowException() throws Exception {
6746         mDeps.enableCompatChangeCheck();
6747         setupMockForNetworkCapabilitiesResources(0 /* networkSliceResourceId */);
6748         final NetworkRequest networkRequest = new NetworkRequest.Builder()
6749                 .addCapability(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_LATENCY)
6750                 .addCapability(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_BANDWIDTH)
6751                 .build();
6752         final TestNetworkCallback cb = new TestNetworkCallback();
6753         final Exception e = assertThrows(SecurityException.class,
6754                 () -> mCm.requestNetwork(networkRequest, cb));
6755         assertThat(e.getMessage(),
6756                 containsString(ConstantsShim.PROPERTY_SELF_CERTIFIED_NETWORK_CAPABILITIES));
6757     }
6758 
6759     @Test
6760     @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
6761     @EnableCompatChanges(ConnectivityCompatChanges.ENABLE_SELF_CERTIFIED_CAPABILITIES_DECLARATION)
6762     public void requestNetwork_withNetworkSliceDeclaration_shouldSucceed() throws Exception {
6763         mDeps.enableCompatChangeCheck();
6764         setupMockForNetworkCapabilitiesResources(
6765                 com.android.frameworks.tests.net.R.xml.self_certified_capabilities_both);
6766 
6767         final NetworkRequest networkRequest = new NetworkRequest.Builder()
6768                 .addCapability(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_LATENCY)
6769                 .addCapability(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_BANDWIDTH)
6770                 .build();
6771         final TestNetworkCallback cb = new TestNetworkCallback();
6772         mCm.requestNetwork(networkRequest, cb);
6773         mCm.unregisterNetworkCallback(cb);
6774     }
6775 
6776     @Test
6777     @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
6778     @EnableCompatChanges(ConnectivityCompatChanges.ENABLE_SELF_CERTIFIED_CAPABILITIES_DECLARATION)
6779     public void requestNetwork_withNetworkSliceDeclaration_shouldUseCache() throws Exception {
6780         mDeps.enableCompatChangeCheck();
6781         setupMockForNetworkCapabilitiesResources(
6782                 com.android.frameworks.tests.net.R.xml.self_certified_capabilities_both);
6783 
6784         final NetworkRequest networkRequest = new NetworkRequest.Builder()
6785                 .addCapability(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_LATENCY)
6786                 .addCapability(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_BANDWIDTH)
6787                 .build();
6788         final TestNetworkCallback cb = new TestNetworkCallback();
6789         mCm.requestNetwork(networkRequest, cb);
6790         mCm.unregisterNetworkCallback(cb);
6791 
6792         // Second call should use caches
6793         mCm.requestNetwork(networkRequest, cb);
6794         mCm.unregisterNetworkCallback(cb);
6795 
6796         // PackageManager's API only called once because the second call is using cache.
6797         verify(mPackageManager, times(1)).getProperty(
6798                 ConstantsShim.PROPERTY_SELF_CERTIFIED_NETWORK_CAPABILITIES,
6799                 mContext.getPackageName());
6800         verify(mPackageManager, times(1)).getResourcesForApplication(
6801                 mContext.getPackageName());
6802     }
6803 
6804     /**
6805      * Validate the service throws if request with CBS but without carrier privilege.
6806      */
6807     @Test
6808     public void testCBSRequestWithoutCarrierPrivilege() throws Exception {
6809         final NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
6810                 TRANSPORT_CELLULAR).addCapability(NET_CAPABILITY_CBS).build();
6811         final TestNetworkCallback networkCallback = new TestNetworkCallback();
6812 
6813         mServiceContext.setPermission(CONNECTIVITY_USE_RESTRICTED_NETWORKS, PERMISSION_DENIED);
6814         // Now file the test request and expect the service throws.
6815         assertThrows(SecurityException.class, () -> mCm.requestNetwork(nr, networkCallback));
6816     }
6817 
6818     private static class TestKeepaliveCallback extends PacketKeepaliveCallback {
6819 
6820         public enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR }
6821 
6822         private class CallbackValue {
6823             public CallbackType callbackType;
6824             public int error;
6825 
6826             public CallbackValue(CallbackType type) {
6827                 this.callbackType = type;
6828                 this.error = PacketKeepalive.SUCCESS;
6829                 assertTrue("onError callback must have error", type != CallbackType.ON_ERROR);
6830             }
6831 
6832             public CallbackValue(CallbackType type, int error) {
6833                 this.callbackType = type;
6834                 this.error = error;
6835                 assertEquals("error can only be set for onError", type, CallbackType.ON_ERROR);
6836             }
6837 
6838             @Override
6839             public boolean equals(Object o) {
6840                 return o instanceof CallbackValue &&
6841                         this.callbackType == ((CallbackValue) o).callbackType &&
6842                         this.error == ((CallbackValue) o).error;
6843             }
6844 
6845             @Override
6846             public String toString() {
6847                 return String.format("%s(%s, %d)", getClass().getSimpleName(), callbackType, error);
6848             }
6849         }
6850 
6851         private final LinkedBlockingQueue<CallbackValue> mCallbacks = new LinkedBlockingQueue<>();
6852 
6853         @Override
6854         public void onStarted() {
6855             mCallbacks.add(new CallbackValue(CallbackType.ON_STARTED));
6856         }
6857 
6858         @Override
6859         public void onStopped() {
6860             mCallbacks.add(new CallbackValue(CallbackType.ON_STOPPED));
6861         }
6862 
6863         @Override
6864         public void onError(int error) {
6865             mCallbacks.add(new CallbackValue(CallbackType.ON_ERROR, error));
6866         }
6867 
6868         private void expect(CallbackValue callbackValue) throws InterruptedException {
6869             assertEquals(callbackValue, mCallbacks.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
6870         }
6871 
6872         public void expectStarted() throws Exception {
6873             expect(new CallbackValue(CallbackType.ON_STARTED));
6874         }
6875 
6876         public void expectStopped() throws Exception {
6877             expect(new CallbackValue(CallbackType.ON_STOPPED));
6878         }
6879 
6880         public void expectError(int error) throws Exception {
6881             expect(new CallbackValue(CallbackType.ON_ERROR, error));
6882         }
6883     }
6884 
6885     private static class TestSocketKeepaliveCallback extends SocketKeepalive.Callback {
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             CallbackValue(CallbackType type) {
6894                 this.callbackType = type;
6895                 this.error = SocketKeepalive.SUCCESS;
6896                 assertTrue("onError callback must have error", type != CallbackType.ON_ERROR);
6897             }
6898 
6899             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,
6915                         error);
6916             }
6917         }
6918 
6919         private LinkedBlockingQueue<CallbackValue> mCallbacks = new LinkedBlockingQueue<>();
6920         private final Executor mExecutor;
6921 
6922         TestSocketKeepaliveCallback(@NonNull Executor executor) {
6923             mExecutor = executor;
6924         }
6925 
6926         @Override
6927         public void onStarted() {
6928             mCallbacks.add(new CallbackValue(CallbackType.ON_STARTED));
6929         }
6930 
6931         @Override
6932         public void onStopped() {
6933             mCallbacks.add(new CallbackValue(CallbackType.ON_STOPPED));
6934         }
6935 
6936         @Override
6937         public void onError(int error) {
6938             mCallbacks.add(new CallbackValue(CallbackType.ON_ERROR, error));
6939         }
6940 
6941         private void expect(CallbackValue callbackValue) throws InterruptedException {
6942             assertEquals(callbackValue, mCallbacks.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
6943 
6944         }
6945 
6946         public void expectStarted() throws InterruptedException {
6947             expect(new CallbackValue(CallbackType.ON_STARTED));
6948         }
6949 
6950         public void expectStopped() throws InterruptedException {
6951             expect(new CallbackValue(CallbackType.ON_STOPPED));
6952         }
6953 
6954         public void expectError(int error) throws InterruptedException {
6955             expect(new CallbackValue(CallbackType.ON_ERROR, error));
6956         }
6957 
6958         public void assertNoCallback() {
6959             waitForIdleSerialExecutor(mExecutor, TIMEOUT_MS);
6960             CallbackValue cv = mCallbacks.peek();
6961             assertNull("Unexpected callback: " + cv, cv);
6962         }
6963     }
6964 
6965     private Network connectKeepaliveNetwork(LinkProperties lp) throws Exception {
6966         // Ensure the network is disconnected before anything else occurs
6967         if (mWiFiAgent != null) {
6968             assertNull(mCm.getNetworkCapabilities(mWiFiAgent.getNetwork()));
6969         }
6970 
6971         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
6972         ExpectedBroadcast b = expectConnectivityAction(TYPE_WIFI, DetailedState.CONNECTED);
6973         mWiFiAgent.connect(true);
6974         b.expectBroadcast();
6975         verifyActiveNetwork(TRANSPORT_WIFI);
6976         mWiFiAgent.sendLinkProperties(lp);
6977         waitForIdle();
6978         return mWiFiAgent.getNetwork();
6979     }
6980 
6981     @Test
6982     public void testPacketKeepalives() throws Exception {
6983         final LinkAddress v4Addr = new LinkAddress("192.0.2.129/24");
6984         final InetAddress myIPv4 = v4Addr.getAddress();
6985         InetAddress notMyIPv4 = InetAddress.getByName("192.0.2.35");
6986         InetAddress myIPv6 = InetAddress.getByName("2001:db8::1");
6987         InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8");
6988         InetAddress dstIPv6 = InetAddress.getByName("2001:4860:4860::8888");
6989         doReturn(getClatInterfaceConfigParcel(v4Addr)).when(mMockNetd)
6990                 .interfaceGetCfg(CLAT_MOBILE_IFNAME);
6991         final int validKaInterval = 15;
6992         final int invalidKaInterval = 9;
6993 
6994         LinkProperties lp = new LinkProperties();
6995         lp.setInterfaceName(MOBILE_IFNAME);
6996         lp.addLinkAddress(new LinkAddress(myIPv6, 64));
6997         lp.addLinkAddress(new LinkAddress(myIPv4, 25));
6998         lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
6999         lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
7000 
7001         Network notMyNet = new Network(61234);
7002         Network myNet = connectKeepaliveNetwork(lp);
7003 
7004         TestKeepaliveCallback callback = new TestKeepaliveCallback();
7005         PacketKeepalive ka;
7006 
7007         // Attempt to start keepalives with invalid parameters and check for errors.
7008         ka = mCm.startNattKeepalive(notMyNet, validKaInterval, callback, myIPv4, 1234, dstIPv4);
7009         callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK);
7010 
7011         ka = mCm.startNattKeepalive(myNet, invalidKaInterval, callback, myIPv4, 1234, dstIPv4);
7012         callback.expectError(PacketKeepalive.ERROR_INVALID_INTERVAL);
7013 
7014         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 1234, dstIPv6);
7015         callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
7016 
7017         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv6, 1234, dstIPv4);
7018         callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
7019 
7020         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 123456, dstIPv4);
7021         callback.expectError(PacketKeepalive.ERROR_INVALID_PORT);
7022 
7023         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 123456, dstIPv4);
7024         callback.expectError(PacketKeepalive.ERROR_INVALID_PORT);
7025 
7026         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
7027         callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
7028 
7029         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
7030         callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
7031 
7032         // Check that a started keepalive can be stopped.
7033         mWiFiAgent.setStartKeepaliveEvent(PacketKeepalive.SUCCESS);
7034         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
7035         callback.expectStarted();
7036         mWiFiAgent.setStopKeepaliveEvent(PacketKeepalive.SUCCESS);
7037         ka.stop();
7038         callback.expectStopped();
7039 
7040         // Check that deleting the IP address stops the keepalive.
7041         LinkProperties bogusLp = new LinkProperties(lp);
7042         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
7043         callback.expectStarted();
7044         bogusLp.removeLinkAddress(new LinkAddress(myIPv4, 25));
7045         bogusLp.addLinkAddress(new LinkAddress(notMyIPv4, 25));
7046         mWiFiAgent.sendLinkProperties(bogusLp);
7047         callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
7048         mWiFiAgent.sendLinkProperties(lp);
7049 
7050         // Check that a started keepalive is stopped correctly when the network disconnects.
7051         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
7052         callback.expectStarted();
7053         mWiFiAgent.disconnect();
7054         mWiFiAgent.expectDisconnected();
7055         callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK);
7056 
7057         // ... and that stopping it after that has no adverse effects.
7058         waitForIdle();
7059         final Network myNetAlias = myNet;
7060         assertNull(mCm.getNetworkCapabilities(myNetAlias));
7061         ka.stop();
7062 
7063         // Reconnect.
7064         myNet = connectKeepaliveNetwork(lp);
7065         mWiFiAgent.setStartKeepaliveEvent(PacketKeepalive.SUCCESS);
7066 
7067         // Check that keepalive slots start from 1 and increment. The first one gets slot 1.
7068         mWiFiAgent.setExpectedKeepaliveSlot(1);
7069         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
7070         callback.expectStarted();
7071 
7072         // The second one gets slot 2.
7073         mWiFiAgent.setExpectedKeepaliveSlot(2);
7074         TestKeepaliveCallback callback2 = new TestKeepaliveCallback();
7075         PacketKeepalive ka2 = mCm.startNattKeepalive(
7076                 myNet, validKaInterval, callback2, myIPv4, 6789, dstIPv4);
7077         callback2.expectStarted();
7078 
7079         // Now stop the first one and create a third. This also gets slot 1.
7080         ka.stop();
7081         callback.expectStopped();
7082 
7083         mWiFiAgent.setExpectedKeepaliveSlot(1);
7084         TestKeepaliveCallback callback3 = new TestKeepaliveCallback();
7085         PacketKeepalive ka3 = mCm.startNattKeepalive(
7086                 myNet, validKaInterval, callback3, myIPv4, 9876, dstIPv4);
7087         callback3.expectStarted();
7088 
7089         ka2.stop();
7090         callback2.expectStopped();
7091 
7092         ka3.stop();
7093         callback3.expectStopped();
7094     }
7095 
7096     // Helper method to prepare the executor and run test
7097     private void runTestWithSerialExecutors(ThrowingConsumer<Executor> functor)
7098             throws Exception {
7099         final ExecutorService executorSingleThread = Executors.newSingleThreadExecutor();
7100         final Executor executorInline = (Runnable r) -> r.run();
7101         functor.accept(executorSingleThread);
7102         executorSingleThread.shutdown();
7103         functor.accept(executorInline);
7104     }
7105 
7106     @Test
7107     public void testNattSocketKeepalives() throws Exception {
7108         runTestWithSerialExecutors(executor -> doTestNattSocketKeepalivesWithExecutor(executor));
7109         runTestWithSerialExecutors(executor -> doTestNattSocketKeepalivesFdWithExecutor(executor));
7110     }
7111 
7112     private void doTestNattSocketKeepalivesWithExecutor(Executor executor) throws Exception {
7113         // TODO: 1. Move this outside of ConnectivityServiceTest.
7114         //       2. Make test to verify that Nat-T keepalive socket is created by IpSecService.
7115         //       3. Mock ipsec service.
7116         final InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
7117         final InetAddress notMyIPv4 = InetAddress.getByName("192.0.2.35");
7118         final InetAddress myIPv6 = InetAddress.getByName("2001:db8::1");
7119         final InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8");
7120         final InetAddress dstIPv6 = InetAddress.getByName("2001:4860:4860::8888");
7121 
7122         final int validKaInterval = 15;
7123         final int invalidKaInterval = 9;
7124 
7125         final IpSecManager mIpSec = (IpSecManager) mContext.getSystemService(Context.IPSEC_SERVICE);
7126         final UdpEncapsulationSocket testSocket = mIpSec.openUdpEncapsulationSocket();
7127         final int srcPort = testSocket.getPort();
7128 
7129         LinkProperties lp = new LinkProperties();
7130         lp.setInterfaceName("wlan12");
7131         lp.addLinkAddress(new LinkAddress(myIPv6, 64));
7132         lp.addLinkAddress(new LinkAddress(myIPv4, 25));
7133         lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
7134         lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
7135 
7136         Network notMyNet = new Network(61234);
7137         Network myNet = connectKeepaliveNetwork(lp);
7138 
7139         TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback(executor);
7140 
7141         // Attempt to start keepalives with invalid parameters and check for errors.
7142         // Invalid network.
7143         try (SocketKeepalive ka = mCm.createSocketKeepalive(
7144                 notMyNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
7145             ka.start(validKaInterval);
7146             callback.expectError(SocketKeepalive.ERROR_INVALID_NETWORK);
7147         }
7148 
7149         // Invalid interval.
7150         try (SocketKeepalive ka = mCm.createSocketKeepalive(
7151                 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
7152             ka.start(invalidKaInterval);
7153             callback.expectError(SocketKeepalive.ERROR_INVALID_INTERVAL);
7154         }
7155 
7156         // Invalid destination.
7157         try (SocketKeepalive ka = mCm.createSocketKeepalive(
7158                 myNet, testSocket, myIPv4, dstIPv6, executor, callback)) {
7159             ka.start(validKaInterval);
7160             callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
7161         }
7162 
7163         // Invalid source;
7164         try (SocketKeepalive ka = mCm.createSocketKeepalive(
7165                 myNet, testSocket, myIPv6, dstIPv4, executor, callback)) {
7166             ka.start(validKaInterval);
7167             callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
7168         }
7169 
7170         // Basic check before testing started keepalive.
7171         try (SocketKeepalive ka = mCm.createSocketKeepalive(
7172                 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
7173             ka.start(validKaInterval);
7174             callback.expectError(SocketKeepalive.ERROR_UNSUPPORTED);
7175         }
7176 
7177         // Check that a started keepalive can be stopped.
7178         mWiFiAgent.setStartKeepaliveEvent(SocketKeepalive.SUCCESS);
7179         try (SocketKeepalive ka = mCm.createSocketKeepalive(
7180                 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
7181             ka.start(validKaInterval);
7182             callback.expectStarted();
7183             mWiFiAgent.setStopKeepaliveEvent(SocketKeepalive.SUCCESS);
7184             ka.stop();
7185             callback.expectStopped();
7186 
7187             // Check that keepalive could be restarted.
7188             ka.start(validKaInterval);
7189             callback.expectStarted();
7190             ka.stop();
7191             callback.expectStopped();
7192 
7193             // Check that keepalive can be restarted without waiting for callback.
7194             ka.start(validKaInterval);
7195             callback.expectStarted();
7196             ka.stop();
7197             ka.start(validKaInterval);
7198             callback.expectStopped();
7199             callback.expectStarted();
7200             ka.stop();
7201             callback.expectStopped();
7202         }
7203 
7204         // Check that deleting the IP address stops the keepalive.
7205         LinkProperties bogusLp = new LinkProperties(lp);
7206         try (SocketKeepalive ka = mCm.createSocketKeepalive(
7207                 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
7208             ka.start(validKaInterval);
7209             callback.expectStarted();
7210             bogusLp.removeLinkAddress(new LinkAddress(myIPv4, 25));
7211             bogusLp.addLinkAddress(new LinkAddress(notMyIPv4, 25));
7212             mWiFiAgent.sendLinkProperties(bogusLp);
7213             callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
7214             mWiFiAgent.sendLinkProperties(lp);
7215         }
7216 
7217         // Check that a started keepalive is stopped correctly when the network disconnects.
7218         try (SocketKeepalive ka = mCm.createSocketKeepalive(
7219                 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
7220             ka.start(validKaInterval);
7221             callback.expectStarted();
7222             mWiFiAgent.disconnect();
7223             mWiFiAgent.expectDisconnected();
7224             callback.expectError(SocketKeepalive.ERROR_INVALID_NETWORK);
7225 
7226             // ... and that stopping it after that has no adverse effects.
7227             waitForIdle();
7228             assertNull(mCm.getNetworkCapabilities(myNet));
7229             ka.stop();
7230             callback.assertNoCallback();
7231         }
7232 
7233         // Reconnect.
7234         myNet = connectKeepaliveNetwork(lp);
7235         mWiFiAgent.setStartKeepaliveEvent(SocketKeepalive.SUCCESS);
7236 
7237         // Check that a stop followed by network disconnects does not result in crash.
7238         try (SocketKeepalive ka = mCm.createSocketKeepalive(
7239                 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
7240             ka.start(validKaInterval);
7241             callback.expectStarted();
7242             // Delay the response of keepalive events in networkAgent long enough to make sure
7243             // the follow-up network disconnection will be processed first.
7244             mWiFiAgent.setKeepaliveResponseDelay(3 * TIMEOUT_MS);
7245             ka.stop();
7246             // Call stop() twice shouldn't result in crash, b/182586681.
7247             ka.stop();
7248 
7249             // Make sure the stop has been processed. Wait for executor idle is needed to prevent
7250             // flaky since the actual stop call to the service is delegated to executor thread.
7251             waitForIdleSerialExecutor(executor, TIMEOUT_MS);
7252             waitForIdle();
7253 
7254             mWiFiAgent.disconnect();
7255             mWiFiAgent.expectDisconnected();
7256             callback.expectStopped();
7257             callback.assertNoCallback();
7258         }
7259 
7260         // Reconnect.
7261         waitForIdle();
7262         myNet = connectKeepaliveNetwork(lp);
7263         mWiFiAgent.setStartKeepaliveEvent(SocketKeepalive.SUCCESS);
7264 
7265         // Check that keepalive slots start from 1 and increment. The first one gets slot 1.
7266         mWiFiAgent.setExpectedKeepaliveSlot(1);
7267         try (SocketKeepalive ka = mCm.createSocketKeepalive(
7268                 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
7269             ka.start(validKaInterval);
7270             callback.expectStarted();
7271 
7272             // The second one gets slot 2.
7273             mWiFiAgent.setExpectedKeepaliveSlot(2);
7274             final UdpEncapsulationSocket testSocket2 = mIpSec.openUdpEncapsulationSocket();
7275             TestSocketKeepaliveCallback callback2 = new TestSocketKeepaliveCallback(executor);
7276             try (SocketKeepalive ka2 = mCm.createSocketKeepalive(
7277                     myNet, testSocket2, myIPv4, dstIPv4, executor, callback2)) {
7278                 ka2.start(validKaInterval);
7279                 callback2.expectStarted();
7280 
7281                 ka.stop();
7282                 callback.expectStopped();
7283 
7284                 ka2.stop();
7285                 callback2.expectStopped();
7286 
7287                 testSocket.close();
7288                 testSocket2.close();
7289             }
7290         }
7291 
7292         // Check that there is no port leaked after all keepalives and sockets are closed.
7293         // TODO: enable this check after ensuring a valid free port. See b/129512753#comment7.
7294         // assertFalse(isUdpPortInUse(srcPort));
7295         // assertFalse(isUdpPortInUse(srcPort2));
7296 
7297         mWiFiAgent.disconnect();
7298         mWiFiAgent.expectDisconnected();
7299         mWiFiAgent = null;
7300     }
7301 
7302     @Test
7303     public void testTcpSocketKeepalives() throws Exception {
7304         runTestWithSerialExecutors(executor -> doTestTcpSocketKeepalivesWithExecutor(executor));
7305     }
7306 
7307     private void doTestTcpSocketKeepalivesWithExecutor(Executor executor) throws Exception {
7308         final int srcPortV4 = 12345;
7309         final int srcPortV6 = 23456;
7310         final InetAddress myIPv4 = InetAddress.getByName("127.0.0.1");
7311         final InetAddress myIPv6 = InetAddress.getByName("::1");
7312 
7313         final int validKaInterval = 15;
7314 
7315         final LinkProperties lp = new LinkProperties();
7316         lp.setInterfaceName("wlan12");
7317         lp.addLinkAddress(new LinkAddress(myIPv6, 64));
7318         lp.addLinkAddress(new LinkAddress(myIPv4, 25));
7319         lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
7320         lp.addRoute(new RouteInfo(InetAddress.getByName("127.0.0.254")));
7321 
7322         final Network notMyNet = new Network(61234);
7323         final Network myNet = connectKeepaliveNetwork(lp);
7324 
7325         final Socket testSocketV4 = new Socket();
7326         final Socket testSocketV6 = new Socket();
7327 
7328         TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback(executor);
7329 
7330         // Attempt to start Tcp keepalives with invalid parameters and check for errors.
7331         // Invalid network.
7332         try (SocketKeepalive ka = mCm.createSocketKeepalive(
7333             notMyNet, testSocketV4, executor, callback)) {
7334             ka.start(validKaInterval);
7335             callback.expectError(SocketKeepalive.ERROR_INVALID_NETWORK);
7336         }
7337 
7338         // Invalid Socket (socket is not bound with IPv4 address).
7339         try (SocketKeepalive ka = mCm.createSocketKeepalive(
7340             myNet, testSocketV4, executor, callback)) {
7341             ka.start(validKaInterval);
7342             callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
7343         }
7344 
7345         // Invalid Socket (socket is not bound with IPv6 address).
7346         try (SocketKeepalive ka = mCm.createSocketKeepalive(
7347             myNet, testSocketV6, executor, callback)) {
7348             ka.start(validKaInterval);
7349             callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
7350         }
7351 
7352         // Bind the socket address
7353         testSocketV4.bind(new InetSocketAddress(myIPv4, srcPortV4));
7354         testSocketV6.bind(new InetSocketAddress(myIPv6, srcPortV6));
7355 
7356         // Invalid Socket (socket is bound with IPv4 address).
7357         try (SocketKeepalive ka = mCm.createSocketKeepalive(
7358             myNet, testSocketV4, executor, callback)) {
7359             ka.start(validKaInterval);
7360             callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
7361         }
7362 
7363         // Invalid Socket (socket is bound with IPv6 address).
7364         try (SocketKeepalive ka = mCm.createSocketKeepalive(
7365             myNet, testSocketV6, executor, callback)) {
7366             ka.start(validKaInterval);
7367             callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
7368         }
7369 
7370         testSocketV4.close();
7371         testSocketV6.close();
7372 
7373         mWiFiAgent.disconnect();
7374         mWiFiAgent.expectDisconnected();
7375         mWiFiAgent = null;
7376     }
7377 
7378     private void doTestNattSocketKeepalivesFdWithExecutor(Executor executor) throws Exception {
7379         final InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
7380         final InetAddress anyIPv4 = InetAddress.getByName("0.0.0.0");
7381         final InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8");
7382         final int validKaInterval = 15;
7383 
7384         // Prepare the target network.
7385         LinkProperties lp = new LinkProperties();
7386         lp.setInterfaceName("wlan12");
7387         lp.addLinkAddress(new LinkAddress(myIPv4, 25));
7388         lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
7389         Network myNet = connectKeepaliveNetwork(lp);
7390         mWiFiAgent.setStartKeepaliveEvent(SocketKeepalive.SUCCESS);
7391         mWiFiAgent.setStopKeepaliveEvent(SocketKeepalive.SUCCESS);
7392 
7393         TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback(executor);
7394 
7395         // Prepare the target file descriptor, keep only one instance.
7396         final IpSecManager mIpSec = (IpSecManager) mContext.getSystemService(Context.IPSEC_SERVICE);
7397         final UdpEncapsulationSocket testSocket = mIpSec.openUdpEncapsulationSocket();
7398         final int srcPort = testSocket.getPort();
7399         final ParcelFileDescriptor testPfd =
7400                 ParcelFileDescriptor.dup(testSocket.getFileDescriptor());
7401         testSocket.close();
7402         assertTrue(isUdpPortInUse(srcPort));
7403 
7404         // Start keepalive and explicit make the variable goes out of scope with try-with-resources
7405         // block.
7406         try (SocketKeepalive ka = mCm.createNattKeepalive(
7407                 myNet, testPfd, myIPv4, dstIPv4, executor, callback)) {
7408             ka.start(validKaInterval);
7409             callback.expectStarted();
7410             ka.stop();
7411             callback.expectStopped();
7412         }
7413 
7414         // Check that the ParcelFileDescriptor is still valid after keepalive stopped,
7415         // ErrnoException with EBADF will be thrown if the socket is closed when checking local
7416         // address.
7417         assertTrue(isUdpPortInUse(srcPort));
7418         final InetSocketAddress sa =
7419                 (InetSocketAddress) Os.getsockname(testPfd.getFileDescriptor());
7420         assertEquals(anyIPv4, sa.getAddress());
7421 
7422         testPfd.close();
7423         // TODO: enable this check after ensuring a valid free port. See b/129512753#comment7.
7424         // assertFalse(isUdpPortInUse(srcPort));
7425 
7426         mWiFiAgent.disconnect();
7427         mWiFiAgent.expectDisconnected();
7428         mWiFiAgent = null;
7429     }
7430 
7431     private static boolean isUdpPortInUse(int port) {
7432         try (DatagramSocket ignored = new DatagramSocket(port)) {
7433             return false;
7434         } catch (IOException alreadyInUse) {
7435             return true;
7436         }
7437     }
7438 
7439     @Test
7440     public void testGetCaptivePortalServerUrl() throws Exception {
7441         String url = mCm.getCaptivePortalServerUrl();
7442         assertEquals("http://connectivitycheck.gstatic.com/generate_204", url);
7443     }
7444 
7445     private static class TestNetworkPinner extends NetworkPinner {
7446         public static boolean awaitPin(int timeoutMs) throws InterruptedException {
7447             synchronized(sLock) {
7448                 if (sNetwork == null) {
7449                     sLock.wait(timeoutMs);
7450                 }
7451                 return sNetwork != null;
7452             }
7453         }
7454 
7455         public static boolean awaitUnpin(int timeoutMs) throws InterruptedException {
7456             synchronized(sLock) {
7457                 if (sNetwork != null) {
7458                     sLock.wait(timeoutMs);
7459                 }
7460                 return sNetwork == null;
7461             }
7462         }
7463     }
7464 
7465     private void assertPinnedToWifiWithCellDefault() {
7466         assertEquals(mWiFiAgent.getNetwork(), mCm.getBoundNetworkForProcess());
7467         assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetwork());
7468     }
7469 
7470     private void assertPinnedToWifiWithWifiDefault() {
7471         assertEquals(mWiFiAgent.getNetwork(), mCm.getBoundNetworkForProcess());
7472         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetwork());
7473     }
7474 
7475     private void assertNotPinnedToWifi() {
7476         assertNull(mCm.getBoundNetworkForProcess());
7477         assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetwork());
7478     }
7479 
7480     @Test
7481     public void testNetworkPinner() throws Exception {
7482         NetworkRequest wifiRequest = new NetworkRequest.Builder()
7483                 .addTransportType(TRANSPORT_WIFI)
7484                 .build();
7485         assertNull(mCm.getBoundNetworkForProcess());
7486 
7487         TestNetworkPinner.pin(mServiceContext, wifiRequest);
7488         assertNull(mCm.getBoundNetworkForProcess());
7489 
7490         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
7491         mCellAgent.connect(true);
7492         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
7493         mWiFiAgent.connect(false);
7494 
7495         // When wi-fi connects, expect to be pinned.
7496         assertTrue(TestNetworkPinner.awaitPin(100));
7497         assertPinnedToWifiWithCellDefault();
7498 
7499         // Disconnect and expect the pin to drop.
7500         mWiFiAgent.disconnect();
7501         assertTrue(TestNetworkPinner.awaitUnpin(100));
7502         assertNotPinnedToWifi();
7503 
7504         // Reconnecting does not cause the pin to come back.
7505         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
7506         mWiFiAgent.connect(false);
7507         assertFalse(TestNetworkPinner.awaitPin(100));
7508         assertNotPinnedToWifi();
7509 
7510         // Pinning while connected causes the pin to take effect immediately.
7511         TestNetworkPinner.pin(mServiceContext, wifiRequest);
7512         assertTrue(TestNetworkPinner.awaitPin(100));
7513         assertPinnedToWifiWithCellDefault();
7514 
7515         // Explicitly unpin and expect to use the default network again.
7516         TestNetworkPinner.unpin();
7517         assertNotPinnedToWifi();
7518 
7519         // Disconnect cell and wifi.
7520         ExpectedBroadcast b = expectConnectivityAction(3);  // cell down, wifi up, wifi down.
7521         mCellAgent.disconnect();
7522         mWiFiAgent.disconnect();
7523         b.expectBroadcast();
7524 
7525         // Pinning takes effect even if the pinned network is the default when the pin is set...
7526         TestNetworkPinner.pin(mServiceContext, wifiRequest);
7527         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
7528         mWiFiAgent.connect(false);
7529         assertTrue(TestNetworkPinner.awaitPin(100));
7530         assertPinnedToWifiWithWifiDefault();
7531 
7532         // ... and is maintained even when that network is no longer the default.
7533         b = expectConnectivityAction(1);
7534         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
7535         mCellAgent.connect(true);
7536         b.expectBroadcast();
7537         assertPinnedToWifiWithCellDefault();
7538     }
7539 
7540     @Test
7541     public void testNetworkCallbackMaximum() throws Exception {
7542         final int MAX_REQUESTS = 100;
7543         final int CALLBACKS = 88;
7544         final int DIFF_INTENTS = 10;
7545         final int SAME_INTENTS = 10;
7546         final int SYSTEM_ONLY_MAX_REQUESTS = 250;
7547         // CALLBACKS + DIFF_INTENTS + 1 (same intent)
7548         // = MAX_REQUESTS - 1, since the capacity is MAX_REQUEST - 1.
7549         assertEquals(MAX_REQUESTS - 1, CALLBACKS + DIFF_INTENTS + 1);
7550 
7551         NetworkRequest networkRequest = new NetworkRequest.Builder().build();
7552         ArrayList<Object> registered = new ArrayList<>();
7553 
7554         for (int j = 0; j < CALLBACKS; j++) {
7555             final NetworkCallback cb = new NetworkCallback();
7556             if (j < CALLBACKS / 2) {
7557                 mCm.requestNetwork(networkRequest, cb);
7558             } else {
7559                 mCm.registerNetworkCallback(networkRequest, cb);
7560             }
7561             registered.add(cb);
7562         }
7563 
7564         // Since ConnectivityService will de-duplicate the request with the same intent,
7565         // register multiple times does not really increase multiple requests.
7566         final PendingIntent same_pi = PendingIntent.getBroadcast(mContext, 0 /* requestCode */,
7567                 new Intent("same"), FLAG_IMMUTABLE);
7568         for (int j = 0; j < SAME_INTENTS; j++) {
7569             mCm.registerNetworkCallback(networkRequest, same_pi);
7570             // Wait for the requests with the same intent to be de-duplicated. Because
7571             // ConnectivityService side incrementCountOrThrow in binder, decrementCount in handler
7572             // thread, waitForIdle is needed to ensure decrementCount being invoked for same intent
7573             // requests before doing further tests.
7574             waitForIdle();
7575         }
7576         for (int j = 0; j < SAME_INTENTS; j++) {
7577             mCm.requestNetwork(networkRequest, same_pi);
7578             // Wait for the requests with the same intent to be de-duplicated.
7579             // Refer to the reason above.
7580             waitForIdle();
7581         }
7582         registered.add(same_pi);
7583 
7584         for (int j = 0; j < DIFF_INTENTS; j++) {
7585             if (j < DIFF_INTENTS / 2) {
7586                 final PendingIntent pi = PendingIntent.getBroadcast(mContext, 0 /* requestCode */,
7587                         new Intent("a" + j), FLAG_IMMUTABLE);
7588                 mCm.requestNetwork(networkRequest, pi);
7589                 registered.add(pi);
7590             } else {
7591                 final PendingIntent pi = PendingIntent.getBroadcast(mContext, 0 /* requestCode */,
7592                         new Intent("b" + j), FLAG_IMMUTABLE);
7593                 mCm.registerNetworkCallback(networkRequest, pi);
7594                 registered.add(pi);
7595             }
7596         }
7597 
7598         // Test that the limit is enforced when MAX_REQUESTS simultaneous requests are added.
7599         assertThrows(TooManyRequestsException.class, () ->
7600                 mCm.requestNetwork(networkRequest, new NetworkCallback())
7601         );
7602         assertThrows(TooManyRequestsException.class, () ->
7603                 mCm.registerNetworkCallback(networkRequest, new NetworkCallback())
7604         );
7605         assertThrows(TooManyRequestsException.class, () ->
7606                 mCm.requestNetwork(networkRequest,
7607                         PendingIntent.getBroadcast(mContext, 0 /* requestCode */,
7608                                 new Intent("c"), FLAG_IMMUTABLE))
7609         );
7610         assertThrows(TooManyRequestsException.class, () ->
7611                 mCm.registerNetworkCallback(networkRequest,
7612                         PendingIntent.getBroadcast(mContext, 0 /* requestCode */,
7613                                 new Intent("d"), FLAG_IMMUTABLE))
7614         );
7615 
7616         // The system gets another SYSTEM_ONLY_MAX_REQUESTS slots.
7617         final Handler handler = new Handler(ConnectivityThread.getInstanceLooper());
7618         withPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, () -> {
7619             ArrayList<NetworkCallback> systemRegistered = new ArrayList<>();
7620             for (int i = 0; i < SYSTEM_ONLY_MAX_REQUESTS - 1; i++) {
7621                 NetworkCallback cb = new NetworkCallback();
7622                 if (i % 2 == 0) {
7623                     mCm.registerDefaultNetworkCallbackForUid(1000000 + i, cb, handler);
7624                 } else {
7625                     mCm.registerNetworkCallback(networkRequest, cb);
7626                 }
7627                 systemRegistered.add(cb);
7628             }
7629             waitForIdle();
7630 
7631             assertThrows(TooManyRequestsException.class, () ->
7632                     mCm.registerDefaultNetworkCallbackForUid(1001042, new NetworkCallback(),
7633                             handler));
7634             assertThrows(TooManyRequestsException.class, () ->
7635                     mCm.registerNetworkCallback(networkRequest, new NetworkCallback()));
7636 
7637             for (NetworkCallback callback : systemRegistered) {
7638                 mCm.unregisterNetworkCallback(callback);
7639             }
7640             waitForIdle();  // Wait for requests to be unregistered before giving up the permission.
7641         });
7642 
7643         for (Object o : registered) {
7644             if (o instanceof NetworkCallback) {
7645                 mCm.unregisterNetworkCallback((NetworkCallback) o);
7646             }
7647             if (o instanceof PendingIntent) {
7648                 mCm.unregisterNetworkCallback((PendingIntent) o);
7649             }
7650         }
7651         waitForIdle();
7652 
7653         // Test that the limit is not hit when MAX_REQUESTS requests are added and removed.
7654         for (int i = 0; i < MAX_REQUESTS; i++) {
7655             NetworkCallback networkCallback = new NetworkCallback();
7656             mCm.requestNetwork(networkRequest, networkCallback);
7657             mCm.unregisterNetworkCallback(networkCallback);
7658             // While requestNetwork increases the count synchronously, unregister decreases it
7659             // asynchronously on a handler, so unregistering doesn't immediately free up
7660             // a slot : calling unregister-register when max requests are registered throws.
7661             // Potential fix : ConnectivityService catches TooManyRequestsException once when
7662             // creating NetworkRequestInfo and waits for handler thread (see
7663             // https://r.android.com/2707373 for impl). However, this complexity is not equal to
7664             // the issue ; the purpose of having "max requests" is only to help apps detect leaks.
7665             // Apps relying on exact enforcement or rapid request registration should reconsider.
7666             //
7667             // In this test, test thread registering all before handler thread decrements can cause
7668             // flakes. A single waitForIdle at (e.g.) MAX_REQUESTS / 2 processes decrements up to
7669             // that point, fixing the flake.
7670             if (MAX_REQUESTS / 2 == i) waitForIdle();
7671         }
7672         waitForIdle();
7673 
7674         for (int i = 0; i < MAX_REQUESTS; i++) {
7675             NetworkCallback networkCallback = new NetworkCallback();
7676             mCm.registerNetworkCallback(networkRequest, networkCallback);
7677             mCm.unregisterNetworkCallback(networkCallback);
7678             // See comment above for the reasons for this wait.
7679             if (MAX_REQUESTS / 2 == i) waitForIdle();
7680         }
7681         waitForIdle();
7682 
7683         for (int i = 0; i < MAX_REQUESTS; i++) {
7684             NetworkCallback networkCallback = new NetworkCallback();
7685             mCm.registerDefaultNetworkCallback(networkCallback);
7686             mCm.unregisterNetworkCallback(networkCallback);
7687             // See comment above for the reasons for this wait.
7688             if (MAX_REQUESTS / 2 == i) waitForIdle();
7689         }
7690         waitForIdle();
7691 
7692         for (int i = 0; i < MAX_REQUESTS; i++) {
7693             NetworkCallback networkCallback = new NetworkCallback();
7694             mCm.registerDefaultNetworkCallback(networkCallback);
7695             mCm.unregisterNetworkCallback(networkCallback);
7696             // See comment above for the reasons for this wait.
7697             if (MAX_REQUESTS / 2 == i) waitForIdle();
7698         }
7699         waitForIdle();
7700 
7701         withPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, () -> {
7702             for (int i = 0; i < MAX_REQUESTS; i++) {
7703                 NetworkCallback networkCallback = new NetworkCallback();
7704                 mCm.registerDefaultNetworkCallbackForUid(1000000 + i, networkCallback,
7705                         new Handler(ConnectivityThread.getInstanceLooper()));
7706                 mCm.unregisterNetworkCallback(networkCallback);
7707                 // See comment above for the reasons for this wait.
7708                 if (MAX_REQUESTS / 2 == i) waitForIdle();
7709             }
7710         });
7711         waitForIdle();
7712 
7713         for (int i = 0; i < MAX_REQUESTS; i++) {
7714             final PendingIntent pendingIntent = PendingIntent.getBroadcast(
7715                     mContext, 0 /* requestCode */, new Intent("e" + i), FLAG_IMMUTABLE);
7716             mCm.requestNetwork(networkRequest, pendingIntent);
7717             mCm.unregisterNetworkCallback(pendingIntent);
7718             // See comment above for the reasons for this wait.
7719             if (MAX_REQUESTS / 2 == i) waitForIdle();
7720         }
7721         waitForIdle();
7722 
7723         for (int i = 0; i < MAX_REQUESTS; i++) {
7724             final PendingIntent pendingIntent = PendingIntent.getBroadcast(
7725                     mContext, 0 /* requestCode */, new Intent("f" + i), FLAG_IMMUTABLE);
7726             mCm.registerNetworkCallback(networkRequest, pendingIntent);
7727             mCm.unregisterNetworkCallback(pendingIntent);
7728             // See comment above for the reasons for this wait.
7729             if (MAX_REQUESTS / 2 == i) waitForIdle();
7730         }
7731     }
7732 
7733     @Test
7734     public void testNetworkInfoOfTypeNone() throws Exception {
7735         ExpectedBroadcast b = expectConnectivityAction(1);
7736 
7737         verifyNoNetwork();
7738         TestNetworkAgentWrapper wifiAware = new TestNetworkAgentWrapper(TRANSPORT_WIFI_AWARE);
7739         assertNull(mCm.getActiveNetworkInfo());
7740 
7741         Network[] allNetworks = mCm.getAllNetworks();
7742         assertLength(1, allNetworks);
7743         Network network = allNetworks[0];
7744         NetworkCapabilities capabilities = mCm.getNetworkCapabilities(network);
7745         assertTrue(capabilities.hasTransport(TRANSPORT_WIFI_AWARE));
7746 
7747         final NetworkRequest request =
7748                 new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI_AWARE).build();
7749         final TestNetworkCallback callback = new TestNetworkCallback();
7750         mCm.registerNetworkCallback(request, callback);
7751 
7752         // Bring up wifi aware network.
7753         wifiAware.connect(false, false, false /* privateDnsProbeSent */);
7754         callback.expectAvailableCallbacksUnvalidated(wifiAware);
7755 
7756         assertNull(mCm.getActiveNetworkInfo());
7757         assertNull(mCm.getActiveNetwork());
7758         // TODO: getAllNetworkInfo is dirty and returns a non-empty array right from the start
7759         // of this test. Fix it and uncomment the assert below.
7760         //assertEmpty(mCm.getAllNetworkInfo());
7761 
7762         // Disconnect wifi aware network.
7763         wifiAware.disconnect();
7764         callback.expect(LOST, TIMEOUT_MS);
7765         mCm.unregisterNetworkCallback(callback);
7766 
7767         verifyNoNetwork();
7768         b.expectNoBroadcast(10);
7769     }
7770 
7771     @Test
7772     public void testDeprecatedAndUnsupportedOperations() throws Exception {
7773         final int TYPE_NONE = ConnectivityManager.TYPE_NONE;
7774         assertNull(mCm.getNetworkInfo(TYPE_NONE));
7775         assertNull(mCm.getNetworkForType(TYPE_NONE));
7776         assertNull(mCm.getLinkProperties(TYPE_NONE));
7777         assertFalse(mCm.isNetworkSupported(TYPE_NONE));
7778 
7779         assertThrows(IllegalArgumentException.class,
7780                 () -> mCm.networkCapabilitiesForType(TYPE_NONE));
7781 
7782         Class<UnsupportedOperationException> unsupported = UnsupportedOperationException.class;
7783         assertThrows(unsupported, () -> mCm.startUsingNetworkFeature(TYPE_WIFI, ""));
7784         assertThrows(unsupported, () -> mCm.stopUsingNetworkFeature(TYPE_WIFI, ""));
7785         // TODO: let test context have configuration application target sdk version
7786         // and test that pre-M requesting for TYPE_NONE sends back APN_REQUEST_FAILED
7787         assertThrows(unsupported, () -> mCm.startUsingNetworkFeature(TYPE_NONE, ""));
7788         assertThrows(unsupported, () -> mCm.stopUsingNetworkFeature(TYPE_NONE, ""));
7789         assertThrows(unsupported, () -> mCm.requestRouteToHostAddress(TYPE_NONE, null));
7790     }
7791 
7792     @Test
7793     public void testLinkPropertiesEnsuresDirectlyConnectedRoutes() throws Exception {
7794         final NetworkRequest networkRequest = new NetworkRequest.Builder()
7795                 .addTransportType(TRANSPORT_WIFI).build();
7796         final TestNetworkCallback networkCallback = new TestNetworkCallback();
7797         mCm.registerNetworkCallback(networkRequest, networkCallback);
7798 
7799         LinkProperties lp = new LinkProperties();
7800         lp.setInterfaceName(WIFI_IFNAME);
7801         LinkAddress myIpv4Address = new LinkAddress("192.168.12.3/24");
7802         RouteInfo myIpv4DefaultRoute = new RouteInfo((IpPrefix) null,
7803                 InetAddresses.parseNumericAddress("192.168.12.1"), lp.getInterfaceName());
7804         lp.addLinkAddress(myIpv4Address);
7805         lp.addRoute(myIpv4DefaultRoute);
7806 
7807         // Verify direct routes are added when network agent is first registered in
7808         // ConnectivityService.
7809         TestNetworkAgentWrapper networkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, lp);
7810         networkAgent.connect(true);
7811         networkCallback.expect(AVAILABLE, networkAgent);
7812         networkCallback.expect(NETWORK_CAPS_UPDATED, networkAgent);
7813         CallbackEntry.LinkPropertiesChanged cbi =
7814                 networkCallback.expect(LINK_PROPERTIES_CHANGED, networkAgent);
7815         networkCallback.expect(BLOCKED_STATUS, networkAgent);
7816         networkCallback.expectCaps(networkAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
7817         networkCallback.assertNoCallback();
7818         checkDirectlyConnectedRoutes(cbi.getLp(), asList(myIpv4Address),
7819                 asList(myIpv4DefaultRoute));
7820         checkDirectlyConnectedRoutes(mCm.getLinkProperties(networkAgent.getNetwork()),
7821                 asList(myIpv4Address), asList(myIpv4DefaultRoute));
7822 
7823         // Verify direct routes are added during subsequent link properties updates.
7824         LinkProperties newLp = new LinkProperties(lp);
7825         LinkAddress myIpv6Address1 = new LinkAddress("fe80::cafe/64");
7826         LinkAddress myIpv6Address2 = new LinkAddress("2001:db8::2/64");
7827         newLp.addLinkAddress(myIpv6Address1);
7828         newLp.addLinkAddress(myIpv6Address2);
7829         networkAgent.sendLinkProperties(newLp);
7830         cbi = networkCallback.expect(LINK_PROPERTIES_CHANGED, networkAgent);
7831         networkCallback.assertNoCallback();
7832         checkDirectlyConnectedRoutes(cbi.getLp(),
7833                 asList(myIpv4Address, myIpv6Address1, myIpv6Address2),
7834                 asList(myIpv4DefaultRoute));
7835         mCm.unregisterNetworkCallback(networkCallback);
7836     }
7837 
7838     private void expectNotifyNetworkStatus(List<Network> allNetworks, List<Network> defaultNetworks,
7839             String defaultIface, Integer vpnUid, String vpnIfname, List<String> underlyingIfaces)
7840             throws Exception {
7841         ArgumentCaptor<List<Network>> defaultNetworksCaptor = ArgumentCaptor.forClass(List.class);
7842         ArgumentCaptor<List<UnderlyingNetworkInfo>> vpnInfosCaptor =
7843                 ArgumentCaptor.forClass(List.class);
7844         ArgumentCaptor<List<NetworkStateSnapshot>> snapshotsCaptor =
7845                 ArgumentCaptor.forClass(List.class);
7846 
7847         verify(mStatsManager, atLeastOnce()).notifyNetworkStatus(defaultNetworksCaptor.capture(),
7848                 snapshotsCaptor.capture(), eq(defaultIface), vpnInfosCaptor.capture());
7849 
7850         assertSameElements(defaultNetworks, defaultNetworksCaptor.getValue());
7851 
7852         List<Network> snapshotNetworks = new ArrayList<Network>();
7853         for (NetworkStateSnapshot ns : snapshotsCaptor.getValue()) {
7854             snapshotNetworks.add(ns.getNetwork());
7855         }
7856         assertSameElements(allNetworks, snapshotNetworks);
7857 
7858         if (defaultIface != null) {
7859             assertNotNull(
7860                     "Did not find interface " + defaultIface + " in call to notifyNetworkStatus",
7861                     CollectionUtils.findFirst(snapshotsCaptor.getValue(), (ns) -> {
7862                         final LinkProperties lp = ns.getLinkProperties();
7863                         if (lp != null && TextUtils.equals(defaultIface, lp.getInterfaceName())) {
7864                             return true;
7865                         }
7866                         return false;
7867                     }));
7868         }
7869 
7870         List<UnderlyingNetworkInfo> infos = vpnInfosCaptor.getValue();
7871         if (vpnUid != null) {
7872             assertEquals("Should have exactly one VPN:", 1, infos.size());
7873             UnderlyingNetworkInfo info = infos.get(0);
7874             assertEquals("Unexpected VPN owner:", (int) vpnUid, info.getOwnerUid());
7875             assertEquals("Unexpected VPN interface:", vpnIfname, info.getInterface());
7876             assertSameElements(underlyingIfaces, info.getUnderlyingInterfaces());
7877         } else {
7878             assertEquals(0, infos.size());
7879             return;
7880         }
7881     }
7882 
7883     private void expectNotifyNetworkStatus(
7884             List<Network> allNetworks, List<Network> defaultNetworks, String defaultIface)
7885             throws Exception {
7886         expectNotifyNetworkStatus(allNetworks, defaultNetworks, defaultIface, null, null,
7887                 List.of());
7888     }
7889 
7890     private List<Network> onlyCell() {
7891         return List.of(mCellAgent.getNetwork());
7892     }
7893 
7894     private List<Network> onlyWifi() {
7895         return List.of(mWiFiAgent.getNetwork());
7896     }
7897 
7898     private List<Network> cellAndWifi() {
7899         return List.of(mCellAgent.getNetwork(), mWiFiAgent.getNetwork());
7900     }
7901 
7902     @Test
7903     public void testStatsIfacesChanged() throws Exception {
7904         LinkProperties cellLp = new LinkProperties();
7905         cellLp.setInterfaceName(MOBILE_IFNAME);
7906         LinkProperties wifiLp = new LinkProperties();
7907         wifiLp.setInterfaceName(WIFI_IFNAME);
7908 
7909         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
7910         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
7911 
7912         // Simple connection with initial LP should have updated ifaces.
7913         mCellAgent.connect(false);
7914         waitForIdle();
7915         List<Network> allNetworks = mService.shouldCreateNetworksImmediately()
7916                 ? cellAndWifi() : onlyCell();
7917         expectNotifyNetworkStatus(allNetworks, onlyCell(), MOBILE_IFNAME);
7918         reset(mStatsManager);
7919 
7920         // Verify change fields other than interfaces does not trigger a notification to NSS.
7921         cellLp.addLinkAddress(new LinkAddress("192.0.2.4/24"));
7922         cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("192.0.2.4"),
7923                 MOBILE_IFNAME));
7924         cellLp.setDnsServers(List.of(InetAddress.getAllByName("8.8.8.8")));
7925         mCellAgent.sendLinkProperties(cellLp);
7926         verifyNoMoreInteractions(mStatsManager);
7927         reset(mStatsManager);
7928 
7929         // Default network switch should update ifaces.
7930         mWiFiAgent.connect(false);
7931         mWiFiAgent.sendLinkProperties(wifiLp);
7932         waitForIdle();
7933         assertEquals(wifiLp, mService.getActiveLinkProperties());
7934         expectNotifyNetworkStatus(cellAndWifi(), onlyWifi(), WIFI_IFNAME);
7935         reset(mStatsManager);
7936 
7937         // Disconnecting a network updates ifaces again. The soon-to-be disconnected interface is
7938         // still in the list to ensure that stats are counted on that interface.
7939         // TODO: this means that if anything else uses that interface for any other reason before
7940         // notifyNetworkStatus is called again, traffic on that interface will be accounted to the
7941         // disconnected network. This is likely a bug in ConnectivityService; it should probably
7942         // call notifyNetworkStatus again without the disconnected network.
7943         mCellAgent.disconnect();
7944         waitForIdle();
7945         expectNotifyNetworkStatus(cellAndWifi(), onlyWifi(), WIFI_IFNAME);
7946         verifyNoMoreInteractions(mStatsManager);
7947         reset(mStatsManager);
7948 
7949         // Connecting a network updates ifaces even if the network doesn't become default.
7950         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
7951         mCellAgent.connect(false);
7952         waitForIdle();
7953         expectNotifyNetworkStatus(cellAndWifi(), onlyWifi(), WIFI_IFNAME);
7954         reset(mStatsManager);
7955 
7956         // Disconnect should update ifaces.
7957         mWiFiAgent.disconnect();
7958         waitForIdle();
7959         expectNotifyNetworkStatus(onlyCell(), onlyCell(), MOBILE_IFNAME);
7960         reset(mStatsManager);
7961 
7962         // Metered change should update ifaces
7963         mCellAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
7964         waitForIdle();
7965         expectNotifyNetworkStatus(onlyCell(), onlyCell(), MOBILE_IFNAME);
7966         reset(mStatsManager);
7967 
7968         mCellAgent.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
7969         waitForIdle();
7970         expectNotifyNetworkStatus(onlyCell(), onlyCell(), MOBILE_IFNAME);
7971         reset(mStatsManager);
7972 
7973         // Temp metered change shouldn't update ifaces
7974         mCellAgent.addCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED);
7975         waitForIdle();
7976         verify(mStatsManager, never()).notifyNetworkStatus(eq(onlyCell()),
7977                 any(List.class), eq(MOBILE_IFNAME), any(List.class));
7978         reset(mStatsManager);
7979 
7980         // Congested change shouldn't update ifaces
7981         mCellAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED);
7982         waitForIdle();
7983         verify(mStatsManager, never()).notifyNetworkStatus(eq(onlyCell()),
7984                 any(List.class), eq(MOBILE_IFNAME), any(List.class));
7985         reset(mStatsManager);
7986 
7987         // Roaming change should update ifaces
7988         mCellAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING);
7989         waitForIdle();
7990         expectNotifyNetworkStatus(onlyCell(), onlyCell(), MOBILE_IFNAME);
7991         reset(mStatsManager);
7992 
7993         // Test VPNs.
7994         final LinkProperties lp = new LinkProperties();
7995         lp.setInterfaceName(VPN_IFNAME);
7996 
7997         mMockVpn.establishForMyUid(lp);
7998         assertUidRangesUpdatedForMyUid(true);
7999 
8000         final List<Network> cellAndVpn = List.of(mCellAgent.getNetwork(), mMockVpn.getNetwork());
8001 
8002         // A VPN with default (null) underlying networks sets the underlying network's interfaces...
8003         expectNotifyNetworkStatus(cellAndVpn, cellAndVpn, MOBILE_IFNAME, Process.myUid(),
8004                 VPN_IFNAME, List.of(MOBILE_IFNAME));
8005 
8006         // ...and updates them as the default network switches.
8007         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
8008         mWiFiAgent.connect(false);
8009         mWiFiAgent.sendLinkProperties(wifiLp);
8010         final Network[] onlyNull = new Network[]{null};
8011         final List<Network> wifiAndVpn = List.of(mWiFiAgent.getNetwork(), mMockVpn.getNetwork());
8012         final List<Network> cellWifiAndVpn = List.of(mCellAgent.getNetwork(),
8013                 mWiFiAgent.getNetwork(), mMockVpn.getNetwork());
8014         final Network[] cellNullAndWifi =
8015                 new Network[] { mCellAgent.getNetwork(), null, mWiFiAgent.getNetwork() };
8016 
8017         waitForIdle();
8018         assertEquals(wifiLp, mService.getActiveLinkProperties());
8019         expectNotifyNetworkStatus(cellWifiAndVpn, wifiAndVpn, WIFI_IFNAME, Process.myUid(),
8020                 VPN_IFNAME, List.of(WIFI_IFNAME));
8021         reset(mStatsManager);
8022 
8023         // A VPN that sets its underlying networks passes the underlying interfaces, and influences
8024         // the default interface sent to NetworkStatsService by virtue of applying to the system
8025         // server UID (or, in this test, to the test's UID). This is the reason for sending
8026         // MOBILE_IFNAME even though the default network is wifi.
8027         // TODO: fix this to pass in the actual default network interface. Whether or not the VPN
8028         // applies to the system server UID should not have any bearing on network stats.
8029         mMockVpn.setUnderlyingNetworks(onlyCell().toArray(new Network[0]));
8030         waitForIdle();
8031         expectNotifyNetworkStatus(cellWifiAndVpn, wifiAndVpn, MOBILE_IFNAME, Process.myUid(),
8032                 VPN_IFNAME, List.of(MOBILE_IFNAME));
8033         reset(mStatsManager);
8034 
8035         mMockVpn.setUnderlyingNetworks(cellAndWifi().toArray(new Network[0]));
8036         waitForIdle();
8037         expectNotifyNetworkStatus(cellWifiAndVpn, wifiAndVpn, MOBILE_IFNAME, Process.myUid(),
8038                 VPN_IFNAME,  List.of(MOBILE_IFNAME, WIFI_IFNAME));
8039         reset(mStatsManager);
8040 
8041         // Null underlying networks are ignored.
8042         mMockVpn.setUnderlyingNetworks(cellNullAndWifi);
8043         waitForIdle();
8044         expectNotifyNetworkStatus(cellWifiAndVpn, wifiAndVpn, MOBILE_IFNAME, Process.myUid(),
8045                 VPN_IFNAME,  List.of(MOBILE_IFNAME, WIFI_IFNAME));
8046         reset(mStatsManager);
8047 
8048         // If an underlying network disconnects, that interface should no longer be underlying.
8049         // This doesn't actually work because disconnectAndDestroyNetwork only notifies
8050         // NetworkStatsService before the underlying network is actually removed. So the underlying
8051         // network will only be removed if notifyIfacesChangedForNetworkStats is called again. This
8052         // could result in incorrect data usage measurements if the interface used by the
8053         // disconnected network is reused by a system component that does not register an agent for
8054         // it (e.g., tethering).
8055         mCellAgent.disconnect();
8056         waitForIdle();
8057         assertNull(mService.getLinkProperties(mCellAgent.getNetwork()));
8058         expectNotifyNetworkStatus(cellWifiAndVpn, wifiAndVpn, MOBILE_IFNAME, Process.myUid(),
8059                 VPN_IFNAME, List.of(MOBILE_IFNAME, WIFI_IFNAME));
8060 
8061         // Confirm that we never tell NetworkStatsService that cell is no longer the underlying
8062         // network for the VPN...
8063         verify(mStatsManager, never()).notifyNetworkStatus(any(List.class),
8064                 any(List.class), any() /* anyString() doesn't match null */,
8065                 argThat(infos -> infos.get(0).getUnderlyingInterfaces().size() == 1
8066                         && WIFI_IFNAME.equals(infos.get(0).getUnderlyingInterfaces().get(0))));
8067         verifyNoMoreInteractions(mStatsManager);
8068         reset(mStatsManager);
8069 
8070         // ... but if something else happens that causes notifyIfacesChangedForNetworkStats to be
8071         // called again, it does. For example, connect Ethernet, but with a low score, such that it
8072         // does not become the default network.
8073         mEthernetAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
8074         mEthernetAgent.setScore(
8075                 new NetworkScore.Builder().setLegacyInt(30).setExiting(true).build());
8076         mEthernetAgent.connect(false);
8077         waitForIdle();
8078         verify(mStatsManager).notifyNetworkStatus(any(List.class),
8079                 any(List.class), any() /* anyString() doesn't match null */,
8080                 argThat(vpnInfos -> vpnInfos.get(0).getUnderlyingInterfaces().size() == 1
8081                         && WIFI_IFNAME.equals(vpnInfos.get(0).getUnderlyingInterfaces().get(0))));
8082         mEthernetAgent.disconnect();
8083         waitForIdle();
8084         reset(mStatsManager);
8085 
8086         // When a VPN declares no underlying networks (i.e., no connectivity), getAllVpnInfo
8087         // does not return the VPN, so CS does not pass it to NetworkStatsService. This causes
8088         // NetworkStatsFactory#adjustForTunAnd464Xlat not to attempt any VPN data migration, which
8089         // is probably a performance improvement (though it's very unlikely that a VPN would declare
8090         // no underlying networks).
8091         // Also, for the same reason as above, the active interface passed in is null.
8092         mMockVpn.setUnderlyingNetworks(new Network[0]);
8093         waitForIdle();
8094         expectNotifyNetworkStatus(wifiAndVpn, wifiAndVpn, null);
8095         reset(mStatsManager);
8096 
8097         // Specifying only a null underlying network is the same as no networks.
8098         mMockVpn.setUnderlyingNetworks(onlyNull);
8099         waitForIdle();
8100         expectNotifyNetworkStatus(wifiAndVpn, wifiAndVpn, null);
8101         reset(mStatsManager);
8102 
8103         // Specifying networks that are all disconnected is the same as specifying no networks.
8104         mMockVpn.setUnderlyingNetworks(onlyCell().toArray(new Network[0]));
8105         waitForIdle();
8106         expectNotifyNetworkStatus(wifiAndVpn, wifiAndVpn, null);
8107         reset(mStatsManager);
8108 
8109         // Passing in null again means follow the default network again.
8110         mMockVpn.setUnderlyingNetworks(null);
8111         waitForIdle();
8112         expectNotifyNetworkStatus(wifiAndVpn, wifiAndVpn, WIFI_IFNAME, Process.myUid(), VPN_IFNAME,
8113                 List.of(WIFI_IFNAME));
8114         reset(mStatsManager);
8115     }
8116 
8117     @Test
8118     public void testAdminUidsRedacted() throws Exception {
8119         final int[] adminUids = new int[] {Process.myUid() + 1};
8120         final NetworkCapabilities ncTemplate = new NetworkCapabilities();
8121         ncTemplate.setAdministratorUids(adminUids);
8122         mCellAgent =
8123                 new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, new LinkProperties(), ncTemplate);
8124         mCellAgent.connect(false /* validated */);
8125 
8126         // Verify case where caller has permission
8127         mServiceContext.setPermission(
8128                 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, PERMISSION_GRANTED);
8129         TestNetworkCallback callback = new TestNetworkCallback();
8130         mCm.registerDefaultNetworkCallback(callback);
8131         callback.expect(AVAILABLE, mCellAgent);
8132         callback.expectCaps(mCellAgent, c -> Arrays.equals(adminUids, c.getAdministratorUids()));
8133         mCm.unregisterNetworkCallback(callback);
8134 
8135         // Verify case where caller does NOT have permission
8136         mServiceContext.setPermission(
8137                 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, PERMISSION_DENIED);
8138         mServiceContext.setPermission(NETWORK_STACK, PERMISSION_DENIED);
8139         callback = new TestNetworkCallback();
8140         mCm.registerDefaultNetworkCallback(callback);
8141         callback.expect(AVAILABLE, mCellAgent);
8142         callback.expectCaps(mCellAgent, c -> c.getAdministratorUids().length == 0);
8143     }
8144 
8145     @Test
8146     public void testNonVpnUnderlyingNetworks() throws Exception {
8147         // Ensure wifi and cellular are not torn down.
8148         for (int transport : new int[]{TRANSPORT_CELLULAR, TRANSPORT_WIFI}) {
8149             final NetworkRequest request = new NetworkRequest.Builder()
8150                     .addTransportType(transport)
8151                     .removeCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
8152                     .build();
8153             mCm.requestNetwork(request, new NetworkCallback());
8154         }
8155 
8156         // Connect a VCN-managed wifi network.
8157         final LinkProperties wifiLp = new LinkProperties();
8158         wifiLp.setInterfaceName(WIFI_IFNAME);
8159         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp);
8160         mWiFiAgent.removeCapability(NET_CAPABILITY_NOT_VCN_MANAGED);
8161         mWiFiAgent.addCapability(NET_CAPABILITY_NOT_METERED);
8162         mWiFiAgent.connect(true /* validated */);
8163 
8164         final List<Network> none = List.of();
8165         expectNotifyNetworkStatus(onlyWifi(), none, null);  // Wifi is not the default network
8166 
8167         // Create a virtual network based on the wifi network.
8168         final int ownerUid = 10042;
8169         NetworkCapabilities nc = new NetworkCapabilities.Builder()
8170                 .setOwnerUid(ownerUid)
8171                 .setAdministratorUids(new int[]{ownerUid})
8172                 .build();
8173         final String vcnIface = "ipsec42";
8174         final LinkProperties lp = new LinkProperties();
8175         lp.setInterfaceName(vcnIface);
8176         final TestNetworkAgentWrapper vcn = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, lp, nc);
8177         vcn.setUnderlyingNetworks(List.of(mWiFiAgent.getNetwork()));
8178         vcn.connect(false /* validated */);
8179 
8180         final TestNetworkCallback callback = new TestNetworkCallback();
8181         mCm.registerDefaultNetworkCallback(callback);
8182         callback.expectAvailableCallbacksUnvalidated(vcn);
8183 
8184         // The underlying wifi network's capabilities are not propagated to the virtual network,
8185         // but NetworkStatsService is informed of the underlying interface.
8186         nc = mCm.getNetworkCapabilities(vcn.getNetwork());
8187         assertFalse(nc.hasTransport(TRANSPORT_WIFI));
8188         assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED));
8189         final List<Network> onlyVcn = List.of(vcn.getNetwork());
8190         final List<Network> vcnAndWifi = List.of(vcn.getNetwork(), mWiFiAgent.getNetwork());
8191         expectNotifyNetworkStatus(vcnAndWifi, onlyVcn, vcnIface, ownerUid, vcnIface,
8192                 List.of(WIFI_IFNAME));
8193 
8194         // Add NOT_METERED to the underlying network, check that it is not propagated.
8195         mWiFiAgent.addCapability(NET_CAPABILITY_NOT_METERED);
8196         callback.assertNoCallback();
8197         nc = mCm.getNetworkCapabilities(vcn.getNetwork());
8198         assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED));
8199 
8200         // Switch underlying networks.
8201         final LinkProperties cellLp = new LinkProperties();
8202         cellLp.setInterfaceName(MOBILE_IFNAME);
8203         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
8204         mCellAgent.removeCapability(NET_CAPABILITY_NOT_VCN_MANAGED);
8205         mCellAgent.addCapability(NET_CAPABILITY_NOT_ROAMING);
8206         mCellAgent.connect(false /* validated */);
8207         vcn.setUnderlyingNetworks(List.of(mCellAgent.getNetwork()));
8208 
8209         // The underlying capability changes do not propagate to the virtual network, but
8210         // NetworkStatsService is informed of the new underlying interface.
8211         callback.assertNoCallback();
8212         nc = mCm.getNetworkCapabilities(vcn.getNetwork());
8213         assertFalse(nc.hasTransport(TRANSPORT_WIFI));
8214         assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_ROAMING));
8215         final List<Network> vcnWifiAndCell = List.of(vcn.getNetwork(),
8216                 mWiFiAgent.getNetwork(), mCellAgent.getNetwork());
8217         expectNotifyNetworkStatus(vcnWifiAndCell, onlyVcn, vcnIface, ownerUid, vcnIface,
8218                 List.of(MOBILE_IFNAME));
8219     }
8220 
8221     @Test
8222     public void testBasicDnsConfigurationPushed() throws Exception {
8223         setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
8224 
8225         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
8226         final int netId = mCellAgent.getNetwork().netId;
8227         waitForIdle();
8228         if (mService.shouldCreateNetworksImmediately()) {
8229             verify(mMockDnsResolver, times(1)).createNetworkCache(netId);
8230         } else {
8231             verify(mMockDnsResolver, never()).setResolverConfiguration(any());
8232         }
8233 
8234         final LinkProperties cellLp = new LinkProperties();
8235         cellLp.setInterfaceName(MOBILE_IFNAME);
8236         // Add IPv4 and IPv6 default routes, because DNS-over-TLS code does
8237         // "is-reachable" testing in order to not program netd with unreachable
8238         // nameservers that it might try repeated to validate.
8239         cellLp.addLinkAddress(new LinkAddress("192.0.2.4/24"));
8240         cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("192.0.2.4"),
8241                 MOBILE_IFNAME));
8242         cellLp.addLinkAddress(new LinkAddress("2001:db8:1::1/64"));
8243         cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("2001:db8:1::1"),
8244                 MOBILE_IFNAME));
8245         mCellAgent.sendLinkProperties(cellLp);
8246         mCellAgent.connect(false);
8247         waitForIdle();
8248         if (!mService.shouldCreateNetworksImmediately()) {
8249             // CS tells dnsresolver about the empty DNS config for this network.
8250             verify(mMockDnsResolver, times(1)).createNetworkCache(netId);
8251         }
8252         verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(any());
8253 
8254         verifyNoMoreInteractions(mMockDnsResolver);
8255         reset(mMockDnsResolver);
8256 
8257         cellLp.addDnsServer(InetAddress.getByName("2001:db8::1"));
8258         mCellAgent.sendLinkProperties(cellLp);
8259         waitForIdle();
8260         verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
8261                 mResolverParamsParcelCaptor.capture());
8262         ResolverParamsParcel resolvrParams = mResolverParamsParcelCaptor.getValue();
8263         assertEquals(1, resolvrParams.servers.length);
8264         assertTrue(CollectionUtils.contains(resolvrParams.servers, "2001:db8::1"));
8265         // Opportunistic mode.
8266         assertTrue(CollectionUtils.contains(resolvrParams.tlsServers, "2001:db8::1"));
8267         reset(mMockDnsResolver);
8268 
8269         cellLp.addDnsServer(InetAddress.getByName("192.0.2.1"));
8270         mCellAgent.sendLinkProperties(cellLp);
8271         waitForIdle();
8272         verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
8273                 mResolverParamsParcelCaptor.capture());
8274         resolvrParams = mResolverParamsParcelCaptor.getValue();
8275         assertEquals(2, resolvrParams.servers.length);
8276         assertTrue(new ArraySet<>(resolvrParams.servers).containsAll(
8277                 asList("2001:db8::1", "192.0.2.1")));
8278         // Opportunistic mode.
8279         assertEquals(2, resolvrParams.tlsServers.length);
8280         assertTrue(new ArraySet<>(resolvrParams.tlsServers).containsAll(
8281                 asList("2001:db8::1", "192.0.2.1")));
8282         reset(mMockDnsResolver);
8283 
8284         final String TLS_SPECIFIER = "tls.example.com";
8285         final String TLS_SERVER6 = "2001:db8:53::53";
8286         final InetAddress[] TLS_IPS = new InetAddress[]{ InetAddress.getByName(TLS_SERVER6) };
8287         final String[] TLS_SERVERS = new String[]{ TLS_SERVER6 };
8288         mCellAgent.mNmCallbacks.notifyPrivateDnsConfigResolved(
8289                 new PrivateDnsConfig(TLS_SPECIFIER, TLS_IPS).toParcel());
8290 
8291         waitForIdle();
8292         verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
8293                 mResolverParamsParcelCaptor.capture());
8294         resolvrParams = mResolverParamsParcelCaptor.getValue();
8295         assertEquals(2, resolvrParams.servers.length);
8296         assertTrue(new ArraySet<>(resolvrParams.servers).containsAll(
8297                 asList("2001:db8::1", "192.0.2.1")));
8298         reset(mMockDnsResolver);
8299     }
8300 
8301     @Test
8302     public void testDnsConfigurationTransTypesPushed() throws Exception {
8303         final NetworkRequest request = new NetworkRequest.Builder()
8304                 .clearCapabilities().addCapability(NET_CAPABILITY_INTERNET)
8305                 .build();
8306         final TestNetworkCallback callback = new TestNetworkCallback();
8307         mCm.registerNetworkCallback(request, callback);
8308 
8309         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
8310         mWiFiAgent.connect(false);
8311         callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
8312         verify(mMockDnsResolver, times(1)).createNetworkCache(eq(mWiFiAgent.getNetwork().netId));
8313         verify(mMockDnsResolver, times(2)).setResolverConfiguration(
8314                 mResolverParamsParcelCaptor.capture());
8315         final ResolverParamsParcel resolverParams = mResolverParamsParcelCaptor.getValue();
8316         assertContainsExactly(resolverParams.transportTypes, TRANSPORT_WIFI);
8317         reset(mMockDnsResolver);
8318     }
8319 
8320     @Test
8321     public void testPrivateDnsNotification() throws Exception {
8322         NetworkRequest request = new NetworkRequest.Builder()
8323                 .clearCapabilities().addCapability(NET_CAPABILITY_INTERNET)
8324                 .build();
8325         TestNetworkCallback callback = new TestNetworkCallback();
8326         mCm.registerNetworkCallback(request, callback);
8327         // Bring up wifi.
8328         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
8329         mWiFiAgent.connect(false);
8330         callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
8331         // Private DNS resolution failed, checking if the notification will be shown or not.
8332         mWiFiAgent.setNetworkInvalid(true /* invalidBecauseOfPrivateDns */);
8333         mWiFiAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
8334         waitForIdle();
8335         // If network validation failed, NetworkMonitor will re-evaluate the network.
8336         // ConnectivityService should filter the redundant notification. This part is trying to
8337         // simulate that situation and check if ConnectivityService could filter that case.
8338         mWiFiAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
8339         waitForIdle();
8340         verify(mNotificationManager, timeout(TIMEOUT_MS).times(1)).notify(anyString(),
8341                 eq(NotificationType.PRIVATE_DNS_BROKEN.eventId), any());
8342         // If private DNS resolution successful, the PRIVATE_DNS_BROKEN notification shouldn't be
8343         // shown.
8344         mWiFiAgent.setNetworkValid(true /* privateDnsProbeSent */);
8345         mWiFiAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
8346         waitForIdle();
8347         verify(mNotificationManager, timeout(TIMEOUT_MS).times(1)).cancel(anyString(),
8348                 eq(NotificationType.PRIVATE_DNS_BROKEN.eventId));
8349         // If private DNS resolution failed again, the PRIVATE_DNS_BROKEN notification should be
8350         // shown again.
8351         mWiFiAgent.setNetworkInvalid(true /* invalidBecauseOfPrivateDns */);
8352         mWiFiAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
8353         waitForIdle();
8354         verify(mNotificationManager, timeout(TIMEOUT_MS).times(2)).notify(anyString(),
8355                 eq(NotificationType.PRIVATE_DNS_BROKEN.eventId), any());
8356     }
8357 
8358     @Test
8359     public void testPrivateDnsSettingsChange() throws Exception {
8360         // The default on Android is opportunistic mode ("Automatic").
8361         setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
8362 
8363         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
8364         final NetworkRequest cellRequest = new NetworkRequest.Builder()
8365                 .addTransportType(TRANSPORT_CELLULAR).build();
8366         mCm.requestNetwork(cellRequest, cellNetworkCallback);
8367 
8368         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
8369         final int netId = mCellAgent.getNetwork().netId;
8370         waitForIdle();
8371         if (mService.shouldCreateNetworksImmediately()) {
8372             verify(mMockDnsResolver, times(1)).createNetworkCache(netId);
8373         } else {
8374             verify(mMockDnsResolver, never()).setResolverConfiguration(any());
8375         }
8376 
8377         final LinkProperties cellLp = new LinkProperties();
8378         cellLp.setInterfaceName(MOBILE_IFNAME);
8379         // Add IPv4 and IPv6 default routes, because DNS-over-TLS code does
8380         // "is-reachable" testing in order to not program netd with unreachable
8381         // nameservers that it might try repeated to validate.
8382         cellLp.addLinkAddress(new LinkAddress("192.0.2.4/24"));
8383         cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("192.0.2.4"),
8384                 MOBILE_IFNAME));
8385         cellLp.addLinkAddress(new LinkAddress("2001:db8:1::1/64"));
8386         cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("2001:db8:1::1"),
8387                 MOBILE_IFNAME));
8388         cellLp.addDnsServer(InetAddress.getByName("2001:db8::1"));
8389         cellLp.addDnsServer(InetAddress.getByName("192.0.2.1"));
8390 
8391         mCellAgent.sendLinkProperties(cellLp);
8392         mCellAgent.connect(false);
8393         waitForIdle();
8394         if (!mService.shouldCreateNetworksImmediately()) {
8395             verify(mMockDnsResolver, times(1)).createNetworkCache(netId);
8396         }
8397         verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
8398                 mResolverParamsParcelCaptor.capture());
8399         ResolverParamsParcel resolvrParams = mResolverParamsParcelCaptor.getValue();
8400         assertEquals(2, resolvrParams.tlsServers.length);
8401         assertTrue(new ArraySet<>(resolvrParams.tlsServers).containsAll(
8402                 asList("2001:db8::1", "192.0.2.1")));
8403         // Opportunistic mode.
8404         assertEquals(2, resolvrParams.tlsServers.length);
8405         assertTrue(new ArraySet<>(resolvrParams.tlsServers).containsAll(
8406                 asList("2001:db8::1", "192.0.2.1")));
8407         verifyNoMoreInteractions(mMockDnsResolver);
8408         reset(mMockDnsResolver);
8409         cellNetworkCallback.expect(AVAILABLE, mCellAgent);
8410         cellNetworkCallback.expect(NETWORK_CAPS_UPDATED, mCellAgent);
8411         CallbackEntry.LinkPropertiesChanged cbi = cellNetworkCallback.expect(
8412                 LINK_PROPERTIES_CHANGED, mCellAgent);
8413         cellNetworkCallback.expect(BLOCKED_STATUS, mCellAgent);
8414         cellNetworkCallback.assertNoCallback();
8415         assertFalse(cbi.getLp().isPrivateDnsActive());
8416         assertNull(cbi.getLp().getPrivateDnsServerName());
8417 
8418         setPrivateDnsSettings(PRIVATE_DNS_MODE_OFF, "ignored.example.com");
8419         verify(mMockDnsResolver, times(1)).setResolverConfiguration(
8420                 mResolverParamsParcelCaptor.capture());
8421         resolvrParams = mResolverParamsParcelCaptor.getValue();
8422         assertEquals(2, resolvrParams.servers.length);
8423         assertTrue(new ArraySet<>(resolvrParams.servers).containsAll(
8424                 asList("2001:db8::1", "192.0.2.1")));
8425         reset(mMockDnsResolver);
8426         cellNetworkCallback.assertNoCallback();
8427 
8428         setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
8429         verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
8430                 mResolverParamsParcelCaptor.capture());
8431         resolvrParams = mResolverParamsParcelCaptor.getValue();
8432         assertEquals(2, resolvrParams.servers.length);
8433         assertTrue(new ArraySet<>(resolvrParams.servers).containsAll(
8434                 asList("2001:db8::1", "192.0.2.1")));
8435         assertEquals(2, resolvrParams.tlsServers.length);
8436         assertTrue(new ArraySet<>(resolvrParams.tlsServers).containsAll(
8437                 asList("2001:db8::1", "192.0.2.1")));
8438         reset(mMockDnsResolver);
8439         cellNetworkCallback.assertNoCallback();
8440 
8441         setPrivateDnsSettings(PRIVATE_DNS_MODE_PROVIDER_HOSTNAME, "strict.example.com");
8442         // Can't test dns configuration for strict mode without properly mocking
8443         // out the DNS lookups, but can test that LinkProperties is updated.
8444         cbi = cellNetworkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent);
8445         cellNetworkCallback.assertNoCallback();
8446         assertTrue(cbi.getLp().isPrivateDnsActive());
8447         assertEquals("strict.example.com", cbi.getLp().getPrivateDnsServerName());
8448     }
8449 
8450     private PrivateDnsValidationEventParcel makePrivateDnsValidationEvent(
8451             final int netId, final String ipAddress, final String hostname, final int validation) {
8452         final PrivateDnsValidationEventParcel event = new PrivateDnsValidationEventParcel();
8453         event.netId = netId;
8454         event.ipAddress = ipAddress;
8455         event.hostname = hostname;
8456         event.validation = validation;
8457         return event;
8458     }
8459 
8460     @Test
8461     public void testLinkPropertiesWithPrivateDnsValidationEvents() throws Exception {
8462         // The default on Android is opportunistic mode ("Automatic").
8463         setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
8464 
8465         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
8466         final NetworkRequest cellRequest = new NetworkRequest.Builder()
8467                 .addTransportType(TRANSPORT_CELLULAR).build();
8468         mCm.requestNetwork(cellRequest, cellNetworkCallback);
8469 
8470         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
8471         waitForIdle();
8472         LinkProperties lp = new LinkProperties();
8473         mCellAgent.sendLinkProperties(lp);
8474         mCellAgent.connect(false);
8475         waitForIdle();
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         Set<InetAddress> dnsServers = new HashSet<>();
8485         checkDnsServers(cbi.getLp(), dnsServers);
8486 
8487         // Send a validation event for a server that is not part of the current
8488         // resolver config. The validation event should be ignored.
8489         mService.mResolverUnsolEventCallback.onPrivateDnsValidationEvent(
8490                 makePrivateDnsValidationEvent(mCellAgent.getNetwork().netId, "",
8491                         "145.100.185.18", VALIDATION_RESULT_SUCCESS));
8492         cellNetworkCallback.assertNoCallback();
8493 
8494         // Add a dns server to the LinkProperties.
8495         LinkProperties lp2 = new LinkProperties(lp);
8496         lp2.addDnsServer(InetAddress.getByName("145.100.185.16"));
8497         mCellAgent.sendLinkProperties(lp2);
8498         cbi = cellNetworkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent);
8499         cellNetworkCallback.assertNoCallback();
8500         assertFalse(cbi.getLp().isPrivateDnsActive());
8501         assertNull(cbi.getLp().getPrivateDnsServerName());
8502         dnsServers.add(InetAddress.getByName("145.100.185.16"));
8503         checkDnsServers(cbi.getLp(), dnsServers);
8504 
8505         // Send a validation event containing a hostname that is not part of
8506         // the current resolver config. The validation event should be ignored.
8507         mService.mResolverUnsolEventCallback.onPrivateDnsValidationEvent(
8508                 makePrivateDnsValidationEvent(mCellAgent.getNetwork().netId,
8509                         "145.100.185.16", "hostname", VALIDATION_RESULT_SUCCESS));
8510         cellNetworkCallback.assertNoCallback();
8511 
8512         // Send a validation event where validation failed.
8513         mService.mResolverUnsolEventCallback.onPrivateDnsValidationEvent(
8514                 makePrivateDnsValidationEvent(mCellAgent.getNetwork().netId,
8515                         "145.100.185.16", "", VALIDATION_RESULT_FAILURE));
8516         cellNetworkCallback.assertNoCallback();
8517 
8518         // Send a validation event where validation succeeded for a server in
8519         // the current resolver config. A LinkProperties callback with updated
8520         // private dns fields should be sent.
8521         mService.mResolverUnsolEventCallback.onPrivateDnsValidationEvent(
8522                 makePrivateDnsValidationEvent(mCellAgent.getNetwork().netId,
8523                         "145.100.185.16", "", VALIDATION_RESULT_SUCCESS));
8524         cbi = cellNetworkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent);
8525         cellNetworkCallback.assertNoCallback();
8526         assertTrue(cbi.getLp().isPrivateDnsActive());
8527         assertNull(cbi.getLp().getPrivateDnsServerName());
8528         checkDnsServers(cbi.getLp(), dnsServers);
8529 
8530         // The private dns fields in LinkProperties should be preserved when
8531         // the network agent sends unrelated changes.
8532         LinkProperties lp3 = new LinkProperties(lp2);
8533         lp3.setMtu(1300);
8534         mCellAgent.sendLinkProperties(lp3);
8535         cbi = cellNetworkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent);
8536         cellNetworkCallback.assertNoCallback();
8537         assertTrue(cbi.getLp().isPrivateDnsActive());
8538         assertNull(cbi.getLp().getPrivateDnsServerName());
8539         checkDnsServers(cbi.getLp(), dnsServers);
8540         assertEquals(1300, cbi.getLp().getMtu());
8541 
8542         // Removing the only validated server should affect the private dns
8543         // fields in LinkProperties.
8544         LinkProperties lp4 = new LinkProperties(lp3);
8545         lp4.removeDnsServer(InetAddress.getByName("145.100.185.16"));
8546         mCellAgent.sendLinkProperties(lp4);
8547         cbi = cellNetworkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent);
8548         cellNetworkCallback.assertNoCallback();
8549         assertFalse(cbi.getLp().isPrivateDnsActive());
8550         assertNull(cbi.getLp().getPrivateDnsServerName());
8551         dnsServers.remove(InetAddress.getByName("145.100.185.16"));
8552         checkDnsServers(cbi.getLp(), dnsServers);
8553         assertEquals(1300, cbi.getLp().getMtu());
8554     }
8555 
8556     private void checkDirectlyConnectedRoutes(Object callbackObj,
8557             Collection<LinkAddress> linkAddresses, Collection<RouteInfo> otherRoutes) {
8558         assertTrue(callbackObj instanceof LinkProperties);
8559         LinkProperties lp = (LinkProperties) callbackObj;
8560 
8561         Set<RouteInfo> expectedRoutes = new ArraySet<>();
8562         expectedRoutes.addAll(otherRoutes);
8563         for (LinkAddress address : linkAddresses) {
8564             RouteInfo localRoute = new RouteInfo(address, null, lp.getInterfaceName());
8565             // Duplicates in linkAddresses are considered failures
8566             assertTrue(expectedRoutes.add(localRoute));
8567         }
8568         List<RouteInfo> observedRoutes = lp.getRoutes();
8569         assertEquals(expectedRoutes.size(), observedRoutes.size());
8570         assertTrue(observedRoutes.containsAll(expectedRoutes));
8571     }
8572 
8573     private static void checkDnsServers(Object callbackObj, Set<InetAddress> dnsServers) {
8574         assertTrue(callbackObj instanceof LinkProperties);
8575         LinkProperties lp = (LinkProperties) callbackObj;
8576         assertEquals(dnsServers.size(), lp.getDnsServers().size());
8577         assertTrue(lp.getDnsServers().containsAll(dnsServers));
8578     }
8579 
8580     @Test
8581     public void testApplyUnderlyingCapabilities() throws Exception {
8582         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
8583         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
8584         mCellAgent.connect(false /* validated */);
8585         mWiFiAgent.connect(false /* validated */);
8586 
8587         final NetworkCapabilities cellNc = new NetworkCapabilities()
8588                 .addTransportType(TRANSPORT_CELLULAR)
8589                 .addCapability(NET_CAPABILITY_INTERNET)
8590                 .addCapability(NET_CAPABILITY_NOT_CONGESTED)
8591                 .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
8592                 .setLinkDownstreamBandwidthKbps(10);
8593         final NetworkCapabilities wifiNc = new NetworkCapabilities()
8594                 .addTransportType(TRANSPORT_WIFI)
8595                 .addCapability(NET_CAPABILITY_INTERNET)
8596                 .addCapability(NET_CAPABILITY_NOT_METERED)
8597                 .addCapability(NET_CAPABILITY_NOT_ROAMING)
8598                 .addCapability(NET_CAPABILITY_NOT_CONGESTED)
8599                 .addCapability(NET_CAPABILITY_NOT_SUSPENDED)
8600                 .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
8601                 .setLinkUpstreamBandwidthKbps(20);
8602         mCellAgent.setNetworkCapabilities(cellNc, true /* sendToConnectivityService */);
8603         mWiFiAgent.setNetworkCapabilities(wifiNc, true /* sendToConnectivityService */);
8604         waitForIdle();
8605 
8606         final Network mobile = mCellAgent.getNetwork();
8607         final Network wifi = mWiFiAgent.getNetwork();
8608 
8609         final NetworkCapabilities initialCaps = new NetworkCapabilities();
8610         initialCaps.addTransportType(TRANSPORT_VPN);
8611         initialCaps.addCapability(NET_CAPABILITY_INTERNET);
8612         initialCaps.removeCapability(NET_CAPABILITY_NOT_VPN);
8613         final ArrayList<Network> emptyUnderlyingNetworks = new ArrayList<Network>();
8614         final ArrayList<Network> underlyingNetworksContainMobile = new ArrayList<Network>();
8615         underlyingNetworksContainMobile.add(mobile);
8616         final ArrayList<Network> underlyingNetworksContainWifi = new ArrayList<Network>();
8617         underlyingNetworksContainWifi.add(wifi);
8618         final ArrayList<Network> underlyingNetworksContainMobileAndMobile =
8619                 new ArrayList<Network>();
8620         underlyingNetworksContainMobileAndMobile.add(mobile);
8621         underlyingNetworksContainMobileAndMobile.add(wifi);
8622 
8623         final NetworkCapabilities withNoUnderlying = new NetworkCapabilities();
8624         withNoUnderlying.addCapability(NET_CAPABILITY_INTERNET);
8625         withNoUnderlying.addCapability(NET_CAPABILITY_NOT_CONGESTED);
8626         withNoUnderlying.addCapability(NET_CAPABILITY_NOT_ROAMING);
8627         withNoUnderlying.addCapability(NET_CAPABILITY_NOT_SUSPENDED);
8628         withNoUnderlying.addTransportType(TRANSPORT_VPN);
8629         withNoUnderlying.removeCapability(NET_CAPABILITY_NOT_VPN);
8630         withNoUnderlying.setUnderlyingNetworks(emptyUnderlyingNetworks);
8631 
8632         final NetworkCapabilities withMobileUnderlying = new NetworkCapabilities(withNoUnderlying);
8633         withMobileUnderlying.addTransportType(TRANSPORT_CELLULAR);
8634         withMobileUnderlying.removeCapability(NET_CAPABILITY_NOT_ROAMING);
8635         withMobileUnderlying.removeCapability(NET_CAPABILITY_NOT_SUSPENDED);
8636         withMobileUnderlying.setLinkDownstreamBandwidthKbps(10);
8637         withMobileUnderlying.setUnderlyingNetworks(underlyingNetworksContainMobile);
8638 
8639         final NetworkCapabilities withWifiUnderlying = new NetworkCapabilities(withNoUnderlying);
8640         withWifiUnderlying.addTransportType(TRANSPORT_WIFI);
8641         withWifiUnderlying.addCapability(NET_CAPABILITY_NOT_METERED);
8642         withWifiUnderlying.setLinkUpstreamBandwidthKbps(20);
8643         withWifiUnderlying.setUnderlyingNetworks(underlyingNetworksContainWifi);
8644 
8645         final NetworkCapabilities withWifiAndMobileUnderlying =
8646                 new NetworkCapabilities(withNoUnderlying);
8647         withWifiAndMobileUnderlying.addTransportType(TRANSPORT_CELLULAR);
8648         withWifiAndMobileUnderlying.addTransportType(TRANSPORT_WIFI);
8649         withWifiAndMobileUnderlying.removeCapability(NET_CAPABILITY_NOT_METERED);
8650         withWifiAndMobileUnderlying.removeCapability(NET_CAPABILITY_NOT_ROAMING);
8651         withWifiAndMobileUnderlying.setLinkDownstreamBandwidthKbps(10);
8652         withWifiAndMobileUnderlying.setLinkUpstreamBandwidthKbps(20);
8653         withWifiAndMobileUnderlying.setUnderlyingNetworks(underlyingNetworksContainMobileAndMobile);
8654 
8655         final NetworkCapabilities initialCapsNotMetered = new NetworkCapabilities(initialCaps);
8656         initialCapsNotMetered.addCapability(NET_CAPABILITY_NOT_METERED);
8657 
8658         NetworkCapabilities caps = new NetworkCapabilities(initialCaps);
8659         mService.applyUnderlyingCapabilities(new Network[]{}, initialCapsNotMetered, caps);
8660         assertEquals(withNoUnderlying, caps);
8661         assertEquals(0, new ArrayList<>(caps.getUnderlyingNetworks()).size());
8662 
8663         caps = new NetworkCapabilities(initialCaps);
8664         mService.applyUnderlyingCapabilities(new Network[]{null}, initialCapsNotMetered, caps);
8665         assertEquals(withNoUnderlying, caps);
8666         assertEquals(0, new ArrayList<>(caps.getUnderlyingNetworks()).size());
8667 
8668         caps = new NetworkCapabilities(initialCaps);
8669         mService.applyUnderlyingCapabilities(new Network[]{mobile}, initialCapsNotMetered, caps);
8670         assertEquals(withMobileUnderlying, caps);
8671         assertEquals(1, new ArrayList<>(caps.getUnderlyingNetworks()).size());
8672         assertEquals(mobile, new ArrayList<>(caps.getUnderlyingNetworks()).get(0));
8673 
8674         caps = new NetworkCapabilities(initialCaps);
8675         mService.applyUnderlyingCapabilities(new Network[]{wifi}, initialCapsNotMetered, caps);
8676         assertEquals(withWifiUnderlying, caps);
8677         assertEquals(1, new ArrayList<>(caps.getUnderlyingNetworks()).size());
8678         assertEquals(wifi, new ArrayList<>(caps.getUnderlyingNetworks()).get(0));
8679 
8680         withWifiUnderlying.removeCapability(NET_CAPABILITY_NOT_METERED);
8681         caps = new NetworkCapabilities(initialCaps);
8682         mService.applyUnderlyingCapabilities(new Network[]{wifi}, initialCaps, caps);
8683         assertEquals(withWifiUnderlying, caps);
8684         assertEquals(1, new ArrayList<>(caps.getUnderlyingNetworks()).size());
8685         assertEquals(wifi, new ArrayList<>(caps.getUnderlyingNetworks()).get(0));
8686 
8687         caps = new NetworkCapabilities(initialCaps);
8688         mService.applyUnderlyingCapabilities(new Network[]{mobile, wifi}, initialCaps, caps);
8689         assertEquals(withWifiAndMobileUnderlying, caps);
8690         assertEquals(2, new ArrayList<>(caps.getUnderlyingNetworks()).size());
8691         assertEquals(mobile, new ArrayList<>(caps.getUnderlyingNetworks()).get(0));
8692         assertEquals(wifi, new ArrayList<>(caps.getUnderlyingNetworks()).get(1));
8693 
8694         withWifiUnderlying.addCapability(NET_CAPABILITY_NOT_METERED);
8695         caps = new NetworkCapabilities(initialCaps);
8696         mService.applyUnderlyingCapabilities(new Network[]{null, mobile, null, wifi},
8697                 initialCapsNotMetered, caps);
8698         assertEquals(withWifiAndMobileUnderlying, caps);
8699         assertEquals(2, new ArrayList<>(caps.getUnderlyingNetworks()).size());
8700         assertEquals(mobile, new ArrayList<>(caps.getUnderlyingNetworks()).get(0));
8701         assertEquals(wifi, new ArrayList<>(caps.getUnderlyingNetworks()).get(1));
8702 
8703         caps = new NetworkCapabilities(initialCaps);
8704         mService.applyUnderlyingCapabilities(new Network[]{null, mobile, null, wifi},
8705                 initialCapsNotMetered, caps);
8706         assertEquals(withWifiAndMobileUnderlying, caps);
8707         assertEquals(2, new ArrayList<>(caps.getUnderlyingNetworks()).size());
8708         assertEquals(mobile, new ArrayList<>(caps.getUnderlyingNetworks()).get(0));
8709         assertEquals(wifi, new ArrayList<>(caps.getUnderlyingNetworks()).get(1));
8710 
8711         caps = new NetworkCapabilities(initialCaps);
8712         mService.applyUnderlyingCapabilities(null, initialCapsNotMetered, caps);
8713         assertEquals(withWifiUnderlying, caps);
8714         assertEquals(1, new ArrayList<>(caps.getUnderlyingNetworks()).size());
8715         assertEquals(wifi, new ArrayList<>(caps.getUnderlyingNetworks()).get(0));
8716     }
8717 
8718     @Test
8719     public void testVpnConnectDisconnectUnderlyingNetwork() throws Exception {
8720         final TestNetworkCallback callback = new TestNetworkCallback();
8721         final NetworkRequest request = new NetworkRequest.Builder()
8722                 .removeCapability(NET_CAPABILITY_NOT_VPN).build();
8723 
8724         runAsShell(NETWORK_SETTINGS, () -> {
8725             mCm.registerNetworkCallback(request, callback);
8726 
8727             // Bring up a VPN that specifies an underlying network that does not exist yet.
8728             // Note: it's sort of meaningless for a VPN app to declare a network that doesn't exist
8729             // yet, (and doing so is difficult without using reflection) but it's good to test that
8730             // the code behaves approximately correctly.
8731             mMockVpn.establishForMyUid(false, true, false);
8732             callback.expectAvailableCallbacksUnvalidated(mMockVpn);
8733             assertUidRangesUpdatedForMyUid(true);
8734             final Network wifiNetwork = new Network(mNetIdManager.peekNextNetId());
8735             mMockVpn.setUnderlyingNetworks(new Network[]{wifiNetwork});
8736             // onCapabilitiesChanged() should be called because
8737             // NetworkCapabilities#mUnderlyingNetworks is updated.
8738             final NetworkCapabilities vpnNc1 = callback.expectCaps(mMockVpn);
8739             // Since the wifi network hasn't brought up,
8740             // ConnectivityService#applyUnderlyingCapabilities cannot find it. Update
8741             // NetworkCapabilities#mUnderlyingNetworks to an empty array, and it will be updated to
8742             // the correct underlying networks once the wifi network brings up. But this case
8743             // shouldn't happen in reality since no one could get the network which hasn't brought
8744             // up. For the empty array of underlying networks, it should be happened for 2 cases,
8745             // the first one is that the VPN app declares an empty array for its underlying
8746             // networks, the second one is that the underlying networks are torn down.
8747             //
8748             // It shouldn't be null since the null value means the underlying networks of this
8749             // network should follow the default network.
8750             final ArrayList<Network> underlyingNetwork = new ArrayList<>();
8751             assertEquals(underlyingNetwork, vpnNc1.getUnderlyingNetworks());
8752             // Since the wifi network isn't exist, applyUnderlyingCapabilities()
8753             assertTrue(mCm.getNetworkCapabilities(mMockVpn.getNetwork())
8754                     .hasTransport(TRANSPORT_VPN));
8755             assertFalse(mCm.getNetworkCapabilities(mMockVpn.getNetwork())
8756                     .hasTransport(TRANSPORT_WIFI));
8757 
8758             // Make that underlying network connect, and expect to see its capabilities immediately
8759             // reflected in the VPN's capabilities.
8760             mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
8761             assertEquals(wifiNetwork, mWiFiAgent.getNetwork());
8762             mWiFiAgent.connect(false);
8763             // TODO: the callback for the VPN happens before any callbacks are called for the wifi
8764             // network that has just connected. There appear to be two issues here:
8765             // 1. The VPN code will accept an underlying network as soon as getNetworkCapabilities()
8766             //    for it returns non-null (which happens very early, during
8767             //    handleRegisterNetworkAgent).
8768             //    This is not correct because that that point the network is not connected and
8769             //    cannot pass any traffic.
8770             // 2. When a network connects, updateNetworkInfo propagates underlying network
8771             //    capabilities before rematching networks.
8772             // Given that this scenario can't really happen, this is probably fine for now.
8773             final NetworkCapabilities vpnNc2 = callback.expectCaps(mMockVpn);
8774             // The wifi network is brought up, NetworkCapabilities#mUnderlyingNetworks is updated to
8775             // it.
8776             underlyingNetwork.add(wifiNetwork);
8777             assertEquals(underlyingNetwork, vpnNc2.getUnderlyingNetworks());
8778             callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
8779             assertTrue(mCm.getNetworkCapabilities(mMockVpn.getNetwork())
8780                     .hasTransport(TRANSPORT_VPN));
8781             assertTrue(mCm.getNetworkCapabilities(mMockVpn.getNetwork())
8782                     .hasTransport(TRANSPORT_WIFI));
8783 
8784             // Disconnect the network, and expect to see the VPN capabilities change accordingly.
8785             mWiFiAgent.disconnect();
8786             callback.expect(LOST, mWiFiAgent);
8787             callback.expectCaps(mMockVpn, c -> c.getTransportTypes().length == 1
8788                             && c.hasTransport(TRANSPORT_VPN));
8789 
8790             mMockVpn.disconnect();
8791             mCm.unregisterNetworkCallback(callback);
8792         });
8793     }
8794 
8795     private void assertGetNetworkInfoOfGetActiveNetworkIsConnected(boolean expectedConnectivity) {
8796         // What Chromium used to do before https://chromium-review.googlesource.com/2605304
8797         assertEquals("Unexpected result for getActiveNetworkInfo(getActiveNetwork())",
8798                 expectedConnectivity, mCm.getNetworkInfo(mCm.getActiveNetwork()).isConnected());
8799     }
8800 
8801     @Test
8802     public void testVpnUnderlyingNetworkSuspended() throws Exception {
8803         final TestNetworkCallback callback = new TestNetworkCallback();
8804         mCm.registerDefaultNetworkCallback(callback);
8805 
8806         // Connect a VPN.
8807         mMockVpn.establishForMyUid(false /* validated */, true /* hasInternet */,
8808                 false /* privateDnsProbeSent */);
8809         callback.expectAvailableCallbacksUnvalidated(mMockVpn);
8810 
8811         // Connect cellular data.
8812         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
8813         mCellAgent.connect(false /* validated */);
8814         callback.expectCaps(mMockVpn, c -> c.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)
8815                 && c.hasTransport(TRANSPORT_CELLULAR));
8816         callback.assertNoCallback();
8817 
8818         assertTrue(mCm.getNetworkCapabilities(mMockVpn.getNetwork())
8819                 .hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
8820         assertNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
8821         assertNetworkInfo(TYPE_WIFI, DetailedState.DISCONNECTED);
8822         assertNetworkInfo(TYPE_VPN, DetailedState.CONNECTED);
8823         assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
8824         assertGetNetworkInfoOfGetActiveNetworkIsConnected(true);
8825 
8826         // Suspend the cellular network and expect the VPN to be suspended.
8827         mCellAgent.suspend();
8828         callback.expectCaps(mMockVpn, c -> !c.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)
8829                 && c.hasTransport(TRANSPORT_CELLULAR));
8830         callback.expect(SUSPENDED, mMockVpn);
8831         callback.assertNoCallback();
8832 
8833         assertFalse(mCm.getNetworkCapabilities(mMockVpn.getNetwork())
8834                 .hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
8835         assertNetworkInfo(TYPE_MOBILE, DetailedState.SUSPENDED);
8836         assertNetworkInfo(TYPE_WIFI, DetailedState.DISCONNECTED);
8837         assertNetworkInfo(TYPE_VPN, DetailedState.SUSPENDED);
8838         assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.SUSPENDED);
8839         // VPN's main underlying network is suspended, so no connectivity.
8840         assertGetNetworkInfoOfGetActiveNetworkIsConnected(false);
8841 
8842         // Switch to another network. The VPN should no longer be suspended.
8843         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
8844         mWiFiAgent.connect(false /* validated */);
8845         callback.expectCaps(mMockVpn, c -> c.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)
8846                 && c.hasTransport(TRANSPORT_WIFI));
8847         callback.expect(RESUMED, mMockVpn);
8848         callback.assertNoCallback();
8849 
8850         assertTrue(mCm.getNetworkCapabilities(mMockVpn.getNetwork())
8851                 .hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
8852         assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED);
8853         assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
8854         assertNetworkInfo(TYPE_VPN, DetailedState.CONNECTED);
8855         assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
8856         assertGetNetworkInfoOfGetActiveNetworkIsConnected(true);
8857 
8858         // Unsuspend cellular and then switch back to it. The VPN remains not suspended.
8859         mCellAgent.resume();
8860         callback.assertNoCallback();
8861         mWiFiAgent.disconnect();
8862         callback.expectCaps(mMockVpn, c -> c.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)
8863                 && c.hasTransport(TRANSPORT_CELLULAR));
8864         // Spurious double callback?
8865         callback.expectCaps(mMockVpn, c -> c.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)
8866                 && c.hasTransport(TRANSPORT_CELLULAR));
8867         callback.assertNoCallback();
8868 
8869         assertTrue(mCm.getNetworkCapabilities(mMockVpn.getNetwork())
8870                 .hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
8871         assertNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
8872         assertNetworkInfo(TYPE_WIFI, DetailedState.DISCONNECTED);
8873         assertNetworkInfo(TYPE_VPN, DetailedState.CONNECTED);
8874         assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
8875         assertGetNetworkInfoOfGetActiveNetworkIsConnected(true);
8876 
8877         // Suspend cellular and expect no connectivity.
8878         mCellAgent.suspend();
8879         callback.expectCaps(mMockVpn, c -> !c.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)
8880                 && c.hasTransport(TRANSPORT_CELLULAR));
8881         callback.expect(SUSPENDED, mMockVpn);
8882         callback.assertNoCallback();
8883 
8884         assertFalse(mCm.getNetworkCapabilities(mMockVpn.getNetwork())
8885                 .hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
8886         assertNetworkInfo(TYPE_MOBILE, DetailedState.SUSPENDED);
8887         assertNetworkInfo(TYPE_WIFI, DetailedState.DISCONNECTED);
8888         assertNetworkInfo(TYPE_VPN, DetailedState.SUSPENDED);
8889         assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.SUSPENDED);
8890         assertGetNetworkInfoOfGetActiveNetworkIsConnected(false);
8891 
8892         // Resume cellular and expect that connectivity comes back.
8893         mCellAgent.resume();
8894         callback.expectCaps(mMockVpn, c -> c.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)
8895                 && c.hasTransport(TRANSPORT_CELLULAR));
8896         callback.expect(RESUMED, mMockVpn);
8897         callback.assertNoCallback();
8898 
8899         assertTrue(mCm.getNetworkCapabilities(mMockVpn.getNetwork())
8900                 .hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
8901         assertNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
8902         assertNetworkInfo(TYPE_WIFI, DetailedState.DISCONNECTED);
8903         assertNetworkInfo(TYPE_VPN, DetailedState.CONNECTED);
8904         assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
8905         assertGetNetworkInfoOfGetActiveNetworkIsConnected(true);
8906     }
8907 
8908     @Test
8909     public void testVpnNetworkActive() throws Exception {
8910         final int uid = Process.myUid();
8911 
8912         final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback();
8913         final TestNetworkCallback genericNotVpnNetworkCallback = new TestNetworkCallback();
8914         final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
8915         final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
8916         final TestNetworkCallback defaultCallback = new TestNetworkCallback();
8917         final TestNetworkCallback systemDefaultCallback = new TestNetworkCallback();
8918         final NetworkRequest genericNotVpnRequest = new NetworkRequest.Builder().build();
8919         final NetworkRequest genericRequest = new NetworkRequest.Builder()
8920                 .removeCapability(NET_CAPABILITY_NOT_VPN).build();
8921         final NetworkRequest wifiRequest = new NetworkRequest.Builder()
8922                 .addTransportType(TRANSPORT_WIFI).build();
8923         final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder()
8924                 .removeCapability(NET_CAPABILITY_NOT_VPN)
8925                 .addTransportType(TRANSPORT_VPN).build();
8926         mCm.registerNetworkCallback(genericRequest, genericNetworkCallback);
8927         mCm.registerNetworkCallback(genericNotVpnRequest, genericNotVpnNetworkCallback);
8928         mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
8929         mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
8930         mCm.registerDefaultNetworkCallback(defaultCallback);
8931         mCm.registerSystemDefaultNetworkCallback(systemDefaultCallback,
8932                 new Handler(ConnectivityThread.getInstanceLooper()));
8933         defaultCallback.assertNoCallback();
8934 
8935         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
8936         mWiFiAgent.connect(false);
8937 
8938         genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
8939         genericNotVpnNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
8940         wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
8941         defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
8942         systemDefaultCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
8943         vpnNetworkCallback.assertNoCallback();
8944         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
8945 
8946         final Set<UidRange> ranges = uidRangesForUids(uid);
8947         mMockVpn.registerAgent(ranges);
8948         mMockVpn.setUnderlyingNetworks(new Network[0]);
8949 
8950         // VPN networks do not satisfy the default request and are automatically validated
8951         // by NetworkMonitor
8952         assertFalse(NetworkMonitorUtils.isValidationRequired(
8953                 false /* isDunValidationRequired */,
8954                 NetworkAgentConfigShimImpl.newInstance(mMockVpn.getNetworkAgentConfig())
8955                         .isVpnValidationRequired(),
8956                 mMockVpn.getAgent().getNetworkCapabilities()));
8957         mMockVpn.getAgent().setNetworkValid(false /* privateDnsProbeSent */);
8958 
8959         mMockVpn.connect(false);
8960 
8961         genericNetworkCallback.expectAvailableThenValidatedCallbacks(mMockVpn);
8962         genericNotVpnNetworkCallback.assertNoCallback();
8963         wifiNetworkCallback.assertNoCallback();
8964         vpnNetworkCallback.expectAvailableThenValidatedCallbacks(mMockVpn);
8965         defaultCallback.expectAvailableThenValidatedCallbacks(mMockVpn);
8966         systemDefaultCallback.assertNoCallback();
8967         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
8968         assertEquals(mWiFiAgent.getNetwork(), systemDefaultCallback.getLastAvailableNetwork());
8969 
8970         ranges.clear();
8971         mMockVpn.setUids(ranges);
8972 
8973         genericNetworkCallback.expect(LOST, mMockVpn);
8974         genericNotVpnNetworkCallback.assertNoCallback();
8975         wifiNetworkCallback.assertNoCallback();
8976         vpnNetworkCallback.expect(LOST, mMockVpn);
8977 
8978         // TODO : The default network callback should actually get a LOST call here (also see the
8979         // comment below for AVAILABLE). This is because ConnectivityService does not look at UID
8980         // ranges at all when determining whether a network should be rematched. In practice, VPNs
8981         // can't currently update their UIDs without disconnecting, so this does not matter too
8982         // much, but that is the reason the test here has to check for an update to the
8983         // capabilities instead of the expected LOST then AVAILABLE.
8984         defaultCallback.expectCaps(mMockVpn);
8985         systemDefaultCallback.assertNoCallback();
8986 
8987         ranges.add(new UidRange(uid, uid));
8988         mMockVpn.setUids(ranges);
8989 
8990         genericNetworkCallback.expectAvailableCallbacksValidated(mMockVpn);
8991         genericNotVpnNetworkCallback.assertNoCallback();
8992         wifiNetworkCallback.assertNoCallback();
8993         vpnNetworkCallback.expectAvailableCallbacksValidated(mMockVpn);
8994         // TODO : Here like above, AVAILABLE would be correct, but because this can't actually
8995         // happen outside of the test, ConnectivityService does not rematch callbacks.
8996         defaultCallback.expectCaps(mMockVpn);
8997         systemDefaultCallback.assertNoCallback();
8998 
8999         mWiFiAgent.disconnect();
9000 
9001         genericNetworkCallback.expect(LOST, mWiFiAgent);
9002         genericNotVpnNetworkCallback.expect(LOST, mWiFiAgent);
9003         wifiNetworkCallback.expect(LOST, mWiFiAgent);
9004         vpnNetworkCallback.assertNoCallback();
9005         defaultCallback.assertNoCallback();
9006         systemDefaultCallback.expect(LOST, mWiFiAgent);
9007 
9008         mMockVpn.disconnect();
9009 
9010         genericNetworkCallback.expect(LOST, mMockVpn);
9011         genericNotVpnNetworkCallback.assertNoCallback();
9012         wifiNetworkCallback.assertNoCallback();
9013         vpnNetworkCallback.expect(LOST, mMockVpn);
9014         defaultCallback.expect(LOST, mMockVpn);
9015         systemDefaultCallback.assertNoCallback();
9016         assertEquals(null, mCm.getActiveNetwork());
9017 
9018         mCm.unregisterNetworkCallback(genericNetworkCallback);
9019         mCm.unregisterNetworkCallback(wifiNetworkCallback);
9020         mCm.unregisterNetworkCallback(vpnNetworkCallback);
9021         mCm.unregisterNetworkCallback(defaultCallback);
9022         mCm.unregisterNetworkCallback(systemDefaultCallback);
9023     }
9024 
9025     @Test
9026     public void testVpnWithoutInternet() throws Exception {
9027         final int uid = Process.myUid();
9028 
9029         final TestNetworkCallback defaultCallback = new TestNetworkCallback();
9030         mCm.registerDefaultNetworkCallback(defaultCallback);
9031 
9032         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
9033         mWiFiAgent.connect(true);
9034 
9035         defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiAgent);
9036         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
9037 
9038         mMockVpn.establishForMyUid(true /* validated */, false /* hasInternet */,
9039                 false /* privateDnsProbeSent */);
9040         assertUidRangesUpdatedForMyUid(true);
9041 
9042         defaultCallback.assertNoCallback();
9043         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
9044 
9045         mMockVpn.disconnect();
9046         defaultCallback.assertNoCallback();
9047 
9048         mCm.unregisterNetworkCallback(defaultCallback);
9049     }
9050 
9051     @Test
9052     public void testVpnWithInternet() throws Exception {
9053         final int uid = Process.myUid();
9054 
9055         final TestNetworkCallback defaultCallback = new TestNetworkCallback();
9056         mCm.registerDefaultNetworkCallback(defaultCallback);
9057 
9058         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
9059         mWiFiAgent.connect(true);
9060 
9061         defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiAgent);
9062         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
9063 
9064         mMockVpn.establishForMyUid(true /* validated */, true /* hasInternet */,
9065                 false /* privateDnsProbeSent */);
9066         assertUidRangesUpdatedForMyUid(true);
9067 
9068         defaultCallback.expectAvailableThenValidatedCallbacks(mMockVpn);
9069         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
9070 
9071         mMockVpn.disconnect();
9072         defaultCallback.expect(LOST, mMockVpn);
9073         defaultCallback.expectAvailableCallbacksValidated(mWiFiAgent);
9074 
9075         mCm.unregisterNetworkCallback(defaultCallback);
9076     }
9077 
9078     @Test
9079     public void testVpnUnvalidated() throws Exception {
9080         final TestNetworkCallback callback = new TestNetworkCallback();
9081         mCm.registerDefaultNetworkCallback(callback);
9082 
9083         // Bring up Ethernet.
9084         mEthernetAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
9085         mEthernetAgent.connect(true);
9086         callback.expectAvailableThenValidatedCallbacks(mEthernetAgent);
9087         callback.assertNoCallback();
9088 
9089         // Bring up a VPN that has the INTERNET capability, initially unvalidated.
9090         mMockVpn.establishForMyUid(false /* validated */, true /* hasInternet */,
9091                 false /* privateDnsProbeSent */);
9092         assertUidRangesUpdatedForMyUid(true);
9093 
9094         // Even though the VPN is unvalidated, it becomes the default network for our app.
9095         callback.expectAvailableCallbacksUnvalidated(mMockVpn);
9096         callback.assertNoCallback();
9097 
9098         assertEquals(mMockVpn.getNetwork(), mCm.getActiveNetwork());
9099 
9100         NetworkCapabilities nc = mCm.getNetworkCapabilities(mMockVpn.getNetwork());
9101         assertFalse(nc.hasCapability(NET_CAPABILITY_VALIDATED));
9102         assertTrue(nc.hasCapability(NET_CAPABILITY_INTERNET));
9103 
9104         assertFalse(NetworkMonitorUtils.isValidationRequired(
9105                 false /* isDunValidationRequired */,
9106                 NetworkAgentConfigShimImpl.newInstance(mMockVpn.getNetworkAgentConfig())
9107                         .isVpnValidationRequired(),
9108                 mMockVpn.getAgent().getNetworkCapabilities()));
9109         assertTrue(NetworkMonitorUtils.isPrivateDnsValidationRequired(
9110                 mMockVpn.getAgent().getNetworkCapabilities()));
9111 
9112         // Pretend that the VPN network validates.
9113         mMockVpn.getAgent().setNetworkValid(false /* privateDnsProbeSent */);
9114         mMockVpn.getAgent().mNetworkMonitor.forceReevaluation(Process.myUid());
9115         // Expect to see the validated capability, but no other changes, because the VPN is already
9116         // the default network for the app.
9117         callback.expectCaps(mMockVpn, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
9118         callback.assertNoCallback();
9119 
9120         mMockVpn.disconnect();
9121         callback.expect(LOST, mMockVpn);
9122         callback.expectAvailableCallbacksValidated(mEthernetAgent);
9123     }
9124 
9125     @Test
9126     public void testVpnStartsWithUnderlyingCaps() throws Exception {
9127         final int uid = Process.myUid();
9128 
9129         final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
9130         final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder()
9131                 .removeCapability(NET_CAPABILITY_NOT_VPN)
9132                 .addTransportType(TRANSPORT_VPN)
9133                 .build();
9134         mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
9135         vpnNetworkCallback.assertNoCallback();
9136 
9137         // Connect cell. It will become the default network, and in the absence of setting
9138         // underlying networks explicitly it will become the sole underlying network for the vpn.
9139         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
9140         mCellAgent.addCapability(NET_CAPABILITY_NOT_SUSPENDED);
9141         mCellAgent.connect(true);
9142 
9143         mMockVpn.establishForMyUid(true /* validated */, false /* hasInternet */,
9144                 false /* privateDnsProbeSent */);
9145         assertUidRangesUpdatedForMyUid(true);
9146 
9147         vpnNetworkCallback.expectAvailableCallbacks(mMockVpn.getNetwork(),
9148                 false /* suspended */, false /* validated */, false /* blocked */, TIMEOUT_MS);
9149         vpnNetworkCallback.expectCaps(mMockVpn.getNetwork(), TIMEOUT_MS,
9150                 c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
9151 
9152         final NetworkCapabilities nc = mCm.getNetworkCapabilities(mMockVpn.getNetwork());
9153         assertTrue(nc.hasTransport(TRANSPORT_VPN));
9154         assertTrue(nc.hasTransport(TRANSPORT_CELLULAR));
9155         assertFalse(nc.hasTransport(TRANSPORT_WIFI));
9156         assertTrue(nc.hasCapability(NET_CAPABILITY_VALIDATED));
9157         assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED));
9158         assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
9159 
9160         assertVpnTransportInfo(nc, VpnManager.TYPE_VPN_SERVICE);
9161     }
9162 
9163     private void assertDefaultNetworkCapabilities(int userId, NetworkAgentWrapper... networks) {
9164         final NetworkCapabilities[] defaultCaps = mService.getDefaultNetworkCapabilitiesForUser(
9165                 userId, "com.android.calling.package", "com.test");
9166         final String defaultCapsString = Arrays.toString(defaultCaps);
9167         assertEquals(defaultCapsString, defaultCaps.length, networks.length);
9168         final Set<NetworkCapabilities> defaultCapsSet = new ArraySet<>(defaultCaps);
9169         for (NetworkAgentWrapper network : networks) {
9170             final NetworkCapabilities nc = mCm.getNetworkCapabilities(network.getNetwork());
9171             final String msg = "Did not find " + nc + " in " + Arrays.toString(defaultCaps);
9172             assertTrue(msg, defaultCapsSet.contains(nc));
9173         }
9174     }
9175 
9176     @Test
9177     public void testVpnSetUnderlyingNetworks() throws Exception {
9178         final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
9179         final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder()
9180                 .removeCapability(NET_CAPABILITY_NOT_VPN)
9181                 .addTransportType(TRANSPORT_VPN)
9182                 .build();
9183         NetworkCapabilities nc;
9184         mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
9185         vpnNetworkCallback.assertNoCallback();
9186 
9187         // Lingering timer is short and cell might be disconnected if the device is particularly
9188         // slow running the test, unless it's requested. Make sure the networks the test needs
9189         // are all requested.
9190         final NetworkCallback cellCallback = new NetworkCallback() {};
9191         final NetworkCallback wifiCallback = new NetworkCallback() {};
9192         mCm.requestNetwork(
9193                 new NetworkRequest.Builder().addTransportType(TRANSPORT_CELLULAR).build(),
9194                 cellCallback);
9195         mCm.requestNetwork(
9196                 new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI).build(),
9197                 wifiCallback);
9198 
9199         mMockVpn.establishForMyUid(true /* validated */, false /* hasInternet */,
9200                 false /* privateDnsProbeSent */);
9201         assertUidRangesUpdatedForMyUid(true);
9202 
9203         vpnNetworkCallback.expectAvailableThenValidatedCallbacks(mMockVpn);
9204         nc = mCm.getNetworkCapabilities(mMockVpn.getNetwork());
9205         assertTrue(nc.hasTransport(TRANSPORT_VPN));
9206         assertFalse(nc.hasTransport(TRANSPORT_CELLULAR));
9207         assertFalse(nc.hasTransport(TRANSPORT_WIFI));
9208         // For safety reasons a VPN without underlying networks is considered metered.
9209         assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED));
9210         // A VPN without underlying networks is not suspended.
9211         assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
9212         assertVpnTransportInfo(nc, VpnManager.TYPE_VPN_SERVICE);
9213 
9214         final int userId = UserHandle.getUserId(Process.myUid());
9215         assertDefaultNetworkCapabilities(userId /* no networks */);
9216 
9217         // Connect cell and use it as an underlying network.
9218         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
9219         mCellAgent.addCapability(NET_CAPABILITY_NOT_SUSPENDED);
9220         mCellAgent.connect(true);
9221 
9222         mMockVpn.setUnderlyingNetworks(new Network[] { mCellAgent.getNetwork() });
9223 
9224         vpnNetworkCallback.expectCaps(mMockVpn,
9225                 c -> c.hasTransport(TRANSPORT_VPN)
9226                         && c.hasTransport(TRANSPORT_CELLULAR)
9227                         && !c.hasTransport(TRANSPORT_WIFI)
9228                         && !c.hasCapability(NET_CAPABILITY_NOT_METERED)
9229                         && c.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
9230         assertDefaultNetworkCapabilities(userId, mCellAgent);
9231 
9232         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
9233         mWiFiAgent.addCapability(NET_CAPABILITY_NOT_METERED);
9234         mWiFiAgent.addCapability(NET_CAPABILITY_NOT_SUSPENDED);
9235         mWiFiAgent.connect(true);
9236 
9237         mMockVpn.setUnderlyingNetworks(
9238                 new Network[] { mCellAgent.getNetwork(), mWiFiAgent.getNetwork() });
9239 
9240         vpnNetworkCallback.expectCaps(mMockVpn,
9241                 c -> c.hasTransport(TRANSPORT_VPN)
9242                         && c.hasTransport(TRANSPORT_CELLULAR)
9243                         && c.hasTransport(TRANSPORT_WIFI)
9244                         && !c.hasCapability(NET_CAPABILITY_NOT_METERED)
9245                         && c.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
9246         assertDefaultNetworkCapabilities(userId, mCellAgent, mWiFiAgent);
9247 
9248         // Don't disconnect, but note the VPN is not using wifi any more.
9249         mMockVpn.setUnderlyingNetworks(new Network[] { mCellAgent.getNetwork() });
9250 
9251         vpnNetworkCallback.expectCaps(mMockVpn,
9252                 c -> c.hasTransport(TRANSPORT_VPN)
9253                         && c.hasTransport(TRANSPORT_CELLULAR)
9254                         && !c.hasTransport(TRANSPORT_WIFI)
9255                         && !c.hasCapability(NET_CAPABILITY_NOT_METERED)
9256                         && c.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
9257         // The return value of getDefaultNetworkCapabilitiesForUser always includes the default
9258         // network (wifi) as well as the underlying networks (cell).
9259         assertDefaultNetworkCapabilities(userId, mCellAgent, mWiFiAgent);
9260 
9261         // Remove NOT_SUSPENDED from the only network and observe VPN is now suspended.
9262         mCellAgent.removeCapability(NET_CAPABILITY_NOT_SUSPENDED);
9263         vpnNetworkCallback.expectCaps(mMockVpn,
9264                 c -> c.hasTransport(TRANSPORT_VPN)
9265                         && c.hasTransport(TRANSPORT_CELLULAR)
9266                         && !c.hasTransport(TRANSPORT_WIFI)
9267                         && !c.hasCapability(NET_CAPABILITY_NOT_METERED)
9268                         && !c.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
9269         vpnNetworkCallback.expect(SUSPENDED, mMockVpn);
9270 
9271         // Add NOT_SUSPENDED again and observe VPN is no longer suspended.
9272         mCellAgent.addCapability(NET_CAPABILITY_NOT_SUSPENDED);
9273         vpnNetworkCallback.expectCaps(mMockVpn,
9274                 c -> c.hasTransport(TRANSPORT_VPN)
9275                         && c.hasTransport(TRANSPORT_CELLULAR)
9276                         && !c.hasTransport(TRANSPORT_WIFI)
9277                         && !c.hasCapability(NET_CAPABILITY_NOT_METERED)
9278                         && c.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
9279         vpnNetworkCallback.expect(RESUMED, mMockVpn);
9280 
9281         // Use Wifi but not cell. Note the VPN is now unmetered and not suspended.
9282         mMockVpn.setUnderlyingNetworks(new Network[] { mWiFiAgent.getNetwork() });
9283 
9284         vpnNetworkCallback.expectCaps(mMockVpn,
9285                 c -> c.hasTransport(TRANSPORT_VPN)
9286                         && !c.hasTransport(TRANSPORT_CELLULAR)
9287                         && c.hasTransport(TRANSPORT_WIFI)
9288                         && c.hasCapability(NET_CAPABILITY_NOT_METERED)
9289                         && c.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
9290         assertDefaultNetworkCapabilities(userId, mWiFiAgent);
9291 
9292         // Use both again.
9293         mMockVpn.setUnderlyingNetworks(
9294                 new Network[] { mCellAgent.getNetwork(), mWiFiAgent.getNetwork() });
9295 
9296         vpnNetworkCallback.expectCaps(mMockVpn,
9297                 c -> c.hasTransport(TRANSPORT_VPN)
9298                         && c.hasTransport(TRANSPORT_CELLULAR)
9299                         && c.hasTransport(TRANSPORT_WIFI)
9300                         && !c.hasCapability(NET_CAPABILITY_NOT_METERED)
9301                         && c.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
9302         assertDefaultNetworkCapabilities(userId, mCellAgent, mWiFiAgent);
9303 
9304         // Cell is suspended again. As WiFi is not, this should not cause a callback.
9305         mCellAgent.removeCapability(NET_CAPABILITY_NOT_SUSPENDED);
9306         vpnNetworkCallback.assertNoCallback();
9307 
9308         // Stop using WiFi. The VPN is suspended again.
9309         mMockVpn.setUnderlyingNetworks(new Network[] { mCellAgent.getNetwork() });
9310         vpnNetworkCallback.expectCaps(mMockVpn,
9311                 c -> c.hasTransport(TRANSPORT_VPN)
9312                         && c.hasTransport(TRANSPORT_CELLULAR)
9313                         && !c.hasCapability(NET_CAPABILITY_NOT_METERED)
9314                         && !c.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
9315         vpnNetworkCallback.expect(SUSPENDED, mMockVpn);
9316         assertDefaultNetworkCapabilities(userId, mCellAgent, mWiFiAgent);
9317 
9318         // Use both again.
9319         mMockVpn.setUnderlyingNetworks(
9320                 new Network[] { mCellAgent.getNetwork(), mWiFiAgent.getNetwork() });
9321 
9322         vpnNetworkCallback.expectCaps(mMockVpn,
9323                 c -> c.hasTransport(TRANSPORT_VPN)
9324                         && c.hasTransport(TRANSPORT_CELLULAR)
9325                         && c.hasTransport(TRANSPORT_WIFI)
9326                         && !c.hasCapability(NET_CAPABILITY_NOT_METERED)
9327                         && c.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
9328         vpnNetworkCallback.expect(RESUMED, mMockVpn);
9329         assertDefaultNetworkCapabilities(userId, mCellAgent, mWiFiAgent);
9330 
9331         // Disconnect cell. Receive update without even removing the dead network from the
9332         // underlying networks – it's dead anyway. Not metered any more.
9333         mCellAgent.disconnect();
9334         vpnNetworkCallback.expectCaps(mMockVpn,
9335                 c -> c.hasTransport(TRANSPORT_VPN)
9336                         && !c.hasTransport(TRANSPORT_CELLULAR)
9337                         && c.hasTransport(TRANSPORT_WIFI)
9338                         && c.hasCapability(NET_CAPABILITY_NOT_METERED));
9339         assertDefaultNetworkCapabilities(userId, mWiFiAgent);
9340 
9341         // Disconnect wifi too. No underlying networks means this is now metered.
9342         mWiFiAgent.disconnect();
9343         vpnNetworkCallback.expectCaps(mMockVpn,
9344                 c -> c.hasTransport(TRANSPORT_VPN)
9345                         && !c.hasTransport(TRANSPORT_CELLULAR)
9346                         && !c.hasTransport(TRANSPORT_WIFI)
9347                         && !c.hasCapability(NET_CAPABILITY_NOT_METERED));
9348         // When a network disconnects, the callbacks are fired before all state is updated, so for a
9349         // short time, synchronous calls will behave as if the network is still connected. Wait for
9350         // things to settle.
9351         waitForIdle();
9352         assertDefaultNetworkCapabilities(userId /* no networks */);
9353 
9354         mMockVpn.disconnect();
9355         mCm.unregisterNetworkCallback(cellCallback);
9356         mCm.unregisterNetworkCallback(wifiCallback);
9357     }
9358 
9359     @Test
9360     public void testNullUnderlyingNetworks() throws Exception {
9361         final int uid = Process.myUid();
9362 
9363         final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
9364         final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder()
9365                 .removeCapability(NET_CAPABILITY_NOT_VPN)
9366                 .addTransportType(TRANSPORT_VPN)
9367                 .build();
9368         NetworkCapabilities nc;
9369         mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
9370         vpnNetworkCallback.assertNoCallback();
9371 
9372         mMockVpn.establishForMyUid(true /* validated */, false /* hasInternet */,
9373                 false /* privateDnsProbeSent */);
9374         assertUidRangesUpdatedForMyUid(true);
9375 
9376         vpnNetworkCallback.expectAvailableThenValidatedCallbacks(mMockVpn);
9377         nc = mCm.getNetworkCapabilities(mMockVpn.getNetwork());
9378         assertTrue(nc.hasTransport(TRANSPORT_VPN));
9379         assertFalse(nc.hasTransport(TRANSPORT_CELLULAR));
9380         assertFalse(nc.hasTransport(TRANSPORT_WIFI));
9381         // By default, VPN is set to track default network (i.e. its underlying networks is null).
9382         // In case of no default network, VPN is considered metered.
9383         assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED));
9384         assertVpnTransportInfo(nc, VpnManager.TYPE_VPN_SERVICE);
9385 
9386         // Connect to Cell; Cell is the default network.
9387         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
9388         mCellAgent.connect(true);
9389 
9390         vpnNetworkCallback.expectCaps(mMockVpn,
9391                 c -> c.hasTransport(TRANSPORT_VPN)
9392                         && c.hasTransport(TRANSPORT_CELLULAR)
9393                         && !c.hasTransport(TRANSPORT_WIFI)
9394                         && !c.hasCapability(NET_CAPABILITY_NOT_METERED));
9395 
9396         // Connect to WiFi; WiFi is the new default.
9397         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
9398         mWiFiAgent.addCapability(NET_CAPABILITY_NOT_METERED);
9399         mWiFiAgent.connect(true);
9400 
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 
9407         // Disconnect Cell. The default network did not change, so there shouldn't be any changes in
9408         // the capabilities.
9409         mCellAgent.disconnect();
9410 
9411         // Disconnect wifi too. Now we have no default network.
9412         mWiFiAgent.disconnect();
9413 
9414         vpnNetworkCallback.expectCaps(mMockVpn,
9415                 c -> c.hasTransport(TRANSPORT_VPN)
9416                         && !c.hasTransport(TRANSPORT_CELLULAR)
9417                         && !c.hasTransport(TRANSPORT_WIFI)
9418                         && !c.hasCapability(NET_CAPABILITY_NOT_METERED));
9419 
9420         mMockVpn.disconnect();
9421     }
9422 
9423     @Test
9424     public void testRestrictedProfileAffectsVpnUidRanges() throws Exception {
9425         // NETWORK_SETTINGS is necessary to see the UID ranges in NetworkCapabilities.
9426         mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_GRANTED);
9427 
9428         final NetworkRequest request = new NetworkRequest.Builder()
9429                 .removeCapability(NET_CAPABILITY_NOT_VPN)
9430                 .build();
9431         final TestNetworkCallback callback = new TestNetworkCallback();
9432         mCm.registerNetworkCallback(request, callback);
9433 
9434         // File a VPN request to prevent VPN network being lingered.
9435         final NetworkRequest vpnRequest = new NetworkRequest.Builder()
9436                 .addTransportType(TRANSPORT_VPN)
9437                 .removeCapability(NET_CAPABILITY_NOT_VPN)
9438                 .build();
9439         final TestNetworkCallback vpnCallback = new TestNetworkCallback();
9440         mCm.requestNetwork(vpnRequest, vpnCallback);
9441 
9442         // Bring up a VPN
9443         mMockVpn.establishForMyUid();
9444         assertUidRangesUpdatedForMyUid(true);
9445         callback.expectAvailableThenValidatedCallbacks(mMockVpn);
9446         callback.assertNoCallback();
9447 
9448         final int uid = Process.myUid();
9449         NetworkCapabilities nc = mCm.getNetworkCapabilities(mMockVpn.getNetwork());
9450         assertNotNull("nc=" + nc, nc.getUids());
9451         assertEquals(nc.getUids(), UidRange.toIntRanges(uidRangesForUids(uid)));
9452         assertVpnTransportInfo(nc, VpnManager.TYPE_VPN_SERVICE);
9453 
9454         // Set an underlying network and expect to see the VPN transports change.
9455         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
9456         mWiFiAgent.connect(true);
9457         callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
9458         callback.expectCaps(mMockVpn, c -> c.hasTransport(TRANSPORT_VPN)
9459                         && c.hasTransport(TRANSPORT_WIFI));
9460         callback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
9461 
9462         // New user added, this updates the Vpn uids, coverage in VpnTest.
9463         // This is equivalent to `mMockVpn.onUserAdded(RESTRICTED_USER);`
9464         final Set<UidRange> ranges = uidRangesForUids(uid);
9465         ranges.add(RESTRICTED_USER_UIDRANGE);
9466         mMockVpn.setUids(ranges);
9467 
9468         // Expect that the VPN UID ranges contain both |uid| and the UID range for the newly-added
9469         // restricted user.
9470         final UidRange rRange = UidRange.createForUser(UserHandle.of(RESTRICTED_USER));
9471         final Range<Integer> restrictUidRange = new Range<>(rRange.start, rRange.stop);
9472         final Range<Integer> singleUidRange = new Range<>(uid, uid);
9473         callback.expectCaps(mMockVpn, c ->
9474                 c.getUids().size() == 2
9475                 && c.getUids().contains(singleUidRange)
9476                 && c.getUids().contains(restrictUidRange)
9477                 && c.hasTransport(TRANSPORT_VPN)
9478                 && c.hasTransport(TRANSPORT_WIFI));
9479 
9480         // Change the VPN's capabilities somehow (specifically, disconnect wifi).
9481         mWiFiAgent.disconnect();
9482         callback.expect(LOST, mWiFiAgent);
9483         callback.expectCaps(mMockVpn, c ->
9484                 c.getUids().size() == 2
9485                 && c.getUids().contains(singleUidRange)
9486                 && c.getUids().contains(restrictUidRange)
9487                 && c.hasTransport(TRANSPORT_VPN)
9488                 && !c.hasTransport(TRANSPORT_WIFI));
9489 
9490         // User removed and expect to lose the UID range for the restricted user.
9491         // This updates the Vpn uids, coverage in VpnTest.
9492         // This is equivalent to `mMockVpn.onUserRemoved(RESTRICTED_USER);`
9493         mMockVpn.setUids(uidRangesForUids(uid));
9494 
9495         // Expect that the VPN gains the UID range for the restricted user, and that the capability
9496         // change made just before that (i.e., loss of TRANSPORT_WIFI) is preserved.
9497         callback.expectCaps(mMockVpn, c ->
9498                 c.getUids().size() == 1
9499                 && c.getUids().contains(singleUidRange)
9500                 && c.hasTransport(TRANSPORT_VPN)
9501                 && !c.hasTransport(TRANSPORT_WIFI));
9502 
9503         mCm.unregisterNetworkCallback(callback);
9504         mCm.unregisterNetworkCallback(vpnCallback);
9505     }
9506 
9507     @Test
9508     public void testLockdownVpnWithRestrictedProfiles() throws Exception {
9509         // For ConnectivityService#setAlwaysOnVpnPackage.
9510         mServiceContext.setPermission(
9511                 Manifest.permission.CONTROL_ALWAYS_ON_VPN, PERMISSION_GRANTED);
9512         // For call Vpn#setAlwaysOnPackage.
9513         mServiceContext.setPermission(
9514                 Manifest.permission.CONTROL_VPN, PERMISSION_GRANTED);
9515         // Necessary to see the UID ranges in NetworkCapabilities.
9516         mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_GRANTED);
9517 
9518         final NetworkRequest request = new NetworkRequest.Builder()
9519                 .removeCapability(NET_CAPABILITY_NOT_VPN)
9520                 .build();
9521         final TestNetworkCallback callback = new TestNetworkCallback();
9522         mCm.registerNetworkCallback(request, callback);
9523 
9524         final int uid = Process.myUid();
9525 
9526         // Connect wifi and check that UIDs in the main and restricted profiles have network access.
9527         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
9528         mWiFiAgent.connect(true /* validated */);
9529         final int restrictedUid = UserHandle.getUid(RESTRICTED_USER, 42 /* appId */);
9530         assertNotNull(mCm.getActiveNetworkForUid(uid));
9531         assertNotNull(mCm.getActiveNetworkForUid(restrictedUid));
9532 
9533         // Enable always-on VPN lockdown. The main user loses network access because no VPN is up.
9534         // Coverage in VpnTest.
9535         final List<Integer> excludedUids = new ArrayList<>();
9536         excludedUids.add(VPN_UID);
9537         if (mDeps.isAtLeastT()) {
9538             // On T onwards, the corresponding SDK sandbox UID should also be excluded
9539             excludedUids.add(toSdkSandboxUid(VPN_UID));
9540         }
9541         final List<Range<Integer>> primaryRanges = intRangesPrimaryExcludingUids(excludedUids);
9542         mCm.setRequireVpnForUids(true, primaryRanges);
9543 
9544         waitForIdle();
9545         assertNull(mCm.getActiveNetworkForUid(uid));
9546         // This is arguably overspecified: a UID that is not running doesn't have an active network.
9547         // But it's useful to check that non-default users do not lose network access, and to prove
9548         // that the loss of connectivity below is indeed due to the restricted profile coming up.
9549         assertNotNull(mCm.getActiveNetworkForUid(restrictedUid));
9550 
9551         // Start the restricted profile, and check that the UID within it loses network access.
9552         // TODO: check that VPN app within restricted profile still has access, etc.
9553         // Add a restricted user.
9554         // This is equivalent to `mMockVpn.onUserAdded(RESTRICTED_USER);`, coverage in VpnTest.
9555         final List<Range<Integer>> restrictedRanges =
9556                 intRangesExcludingUids(RESTRICTED_USER, excludedUids);
9557         mCm.setRequireVpnForUids(true, restrictedRanges);
9558         waitForIdle();
9559 
9560         assertNull(mCm.getActiveNetworkForUid(uid));
9561         assertNull(mCm.getActiveNetworkForUid(restrictedUid));
9562 
9563         // Stop the restricted profile, and check that the UID within it has network access again.
9564         // Remove the restricted user.
9565         // This is equivalent to `mMockVpn.onUserRemoved(RESTRICTED_USER);`, coverage in VpnTest.
9566         mCm.setRequireVpnForUids(false, restrictedRanges);
9567         waitForIdle();
9568 
9569         assertNull(mCm.getActiveNetworkForUid(uid));
9570         assertNotNull(mCm.getActiveNetworkForUid(restrictedUid));
9571 
9572         mCm.setRequireVpnForUids(false, primaryRanges);
9573 
9574         waitForIdle();
9575     }
9576 
9577     @Test
9578     public void testIsActiveNetworkMeteredOverWifi() throws Exception {
9579         // Returns true by default when no network is available.
9580         assertTrue(mCm.isActiveNetworkMetered());
9581         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
9582         mWiFiAgent.addCapability(NET_CAPABILITY_NOT_METERED);
9583         mWiFiAgent.connect(true);
9584         waitForIdle();
9585 
9586         assertFalse(mCm.isActiveNetworkMetered());
9587     }
9588 
9589     @Test
9590     public void testIsActiveNetworkMeteredOverCell() throws Exception {
9591         // Returns true by default when no network is available.
9592         assertTrue(mCm.isActiveNetworkMetered());
9593         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
9594         mCellAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
9595         mCellAgent.connect(true);
9596         waitForIdle();
9597 
9598         assertTrue(mCm.isActiveNetworkMetered());
9599     }
9600 
9601     @Test
9602     public void testIsActiveNetworkMeteredOverVpnTrackingPlatformDefault() throws Exception {
9603         // Returns true by default when no network is available.
9604         assertTrue(mCm.isActiveNetworkMetered());
9605         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
9606         mCellAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
9607         mCellAgent.connect(true);
9608         waitForIdle();
9609         assertTrue(mCm.isActiveNetworkMetered());
9610 
9611         // Connect VPN network. By default it is using current default network (Cell).
9612         mMockVpn.establishForMyUid();
9613         assertUidRangesUpdatedForMyUid(true);
9614 
9615         // Ensure VPN is now the active network.
9616         assertEquals(mMockVpn.getNetwork(), mCm.getActiveNetwork());
9617 
9618         // Expect VPN to be metered.
9619         assertTrue(mCm.isActiveNetworkMetered());
9620 
9621         // Connect WiFi.
9622         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
9623         mWiFiAgent.addCapability(NET_CAPABILITY_NOT_METERED);
9624         mWiFiAgent.connect(true);
9625         waitForIdle();
9626         // VPN should still be the active network.
9627         assertEquals(mMockVpn.getNetwork(), mCm.getActiveNetwork());
9628 
9629         // Expect VPN to be unmetered as it should now be using WiFi (new default).
9630         assertFalse(mCm.isActiveNetworkMetered());
9631 
9632         // Disconnecting Cell should not affect VPN's meteredness.
9633         mCellAgent.disconnect();
9634         waitForIdle();
9635 
9636         assertFalse(mCm.isActiveNetworkMetered());
9637 
9638         // Disconnect WiFi; Now there is no platform default network.
9639         mWiFiAgent.disconnect();
9640         waitForIdle();
9641 
9642         // VPN without any underlying networks is treated as metered.
9643         assertTrue(mCm.isActiveNetworkMetered());
9644 
9645         mMockVpn.disconnect();
9646     }
9647 
9648     @Test
9649     public void testIsActiveNetworkMeteredOverVpnSpecifyingUnderlyingNetworks() throws Exception {
9650         // Returns true by default when no network is available.
9651         assertTrue(mCm.isActiveNetworkMetered());
9652         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
9653         mCellAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
9654         mCellAgent.connect(true);
9655         waitForIdle();
9656         assertTrue(mCm.isActiveNetworkMetered());
9657 
9658         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
9659         mWiFiAgent.addCapability(NET_CAPABILITY_NOT_METERED);
9660         mWiFiAgent.connect(true);
9661         waitForIdle();
9662         assertFalse(mCm.isActiveNetworkMetered());
9663 
9664         // Connect VPN network.
9665         mMockVpn.establishForMyUid();
9666         assertUidRangesUpdatedForMyUid(true);
9667 
9668         // Ensure VPN is now the active network.
9669         assertEquals(mMockVpn.getNetwork(), mCm.getActiveNetwork());
9670         // VPN is using Cell
9671         mMockVpn.setUnderlyingNetworks(new Network[] { mCellAgent.getNetwork() });
9672         waitForIdle();
9673 
9674         // Expect VPN to be metered.
9675         assertTrue(mCm.isActiveNetworkMetered());
9676 
9677         // VPN is now using WiFi
9678         mMockVpn.setUnderlyingNetworks(new Network[] { mWiFiAgent.getNetwork() });
9679         waitForIdle();
9680 
9681         // Expect VPN to be unmetered
9682         assertFalse(mCm.isActiveNetworkMetered());
9683 
9684         // VPN is using Cell | WiFi.
9685         mMockVpn.setUnderlyingNetworks(
9686                 new Network[] { mCellAgent.getNetwork(), mWiFiAgent.getNetwork() });
9687         waitForIdle();
9688 
9689         // Expect VPN to be metered.
9690         assertTrue(mCm.isActiveNetworkMetered());
9691 
9692         // VPN is using WiFi | Cell.
9693         mMockVpn.setUnderlyingNetworks(
9694                 new Network[] { mWiFiAgent.getNetwork(), mCellAgent.getNetwork() });
9695         waitForIdle();
9696 
9697         // Order should not matter and VPN should still be metered.
9698         assertTrue(mCm.isActiveNetworkMetered());
9699 
9700         // VPN is not using any underlying networks.
9701         mMockVpn.setUnderlyingNetworks(new Network[0]);
9702         waitForIdle();
9703 
9704         // VPN without underlying networks is treated as metered.
9705         assertTrue(mCm.isActiveNetworkMetered());
9706 
9707         mMockVpn.disconnect();
9708     }
9709 
9710     @Test
9711     public void testIsActiveNetworkMeteredOverAlwaysMeteredVpn() throws Exception {
9712         // Returns true by default when no network is available.
9713         assertTrue(mCm.isActiveNetworkMetered());
9714         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
9715         mWiFiAgent.addCapability(NET_CAPABILITY_NOT_METERED);
9716         mWiFiAgent.connect(true);
9717         waitForIdle();
9718         assertFalse(mCm.isActiveNetworkMetered());
9719 
9720         // Connect VPN network.
9721         mMockVpn.registerAgent(true /* isAlwaysMetered */, uidRangesForUids(Process.myUid()),
9722                 new LinkProperties());
9723         mMockVpn.connect(true);
9724         waitForIdle();
9725         assertEquals(mMockVpn.getNetwork(), mCm.getActiveNetwork());
9726 
9727         // VPN is tracking current platform default (WiFi).
9728         mMockVpn.setUnderlyingNetworks(null);
9729         waitForIdle();
9730 
9731         // Despite VPN using WiFi (which is unmetered), VPN itself is marked as always metered.
9732         assertTrue(mCm.isActiveNetworkMetered());
9733 
9734 
9735         // VPN explicitly declares WiFi as its underlying network.
9736         mMockVpn.setUnderlyingNetworks(new Network[] { mWiFiAgent.getNetwork() });
9737         waitForIdle();
9738 
9739         // Doesn't really matter whether VPN declares its underlying networks explicitly.
9740         assertTrue(mCm.isActiveNetworkMetered());
9741 
9742         // With WiFi lost, VPN is basically without any underlying networks. And in that case it is
9743         // anyways suppose to be metered.
9744         mWiFiAgent.disconnect();
9745         waitForIdle();
9746 
9747         assertTrue(mCm.isActiveNetworkMetered());
9748 
9749         mMockVpn.disconnect();
9750     }
9751 
9752     private class DetailedBlockedStatusCallback extends TestNetworkCallback {
9753         public void expectAvailableThenValidatedCallbacks(HasNetwork n, int blockedStatus) {
9754             super.expectAvailableThenValidatedCallbacks(n.getNetwork(), blockedStatus, TIMEOUT_MS);
9755         }
9756         public void onBlockedStatusChanged(Network network, int blockedReasons) {
9757             getHistory().add(new CallbackEntry.BlockedStatusInt(network, blockedReasons));
9758         }
9759     }
9760 
9761     @Test
9762     public void testNetworkBlockedStatus() throws Exception {
9763         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
9764         final NetworkRequest cellRequest = new NetworkRequest.Builder()
9765                 .addTransportType(TRANSPORT_CELLULAR)
9766                 .build();
9767         mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
9768         final DetailedBlockedStatusCallback detailedCallback = new DetailedBlockedStatusCallback();
9769         mCm.registerNetworkCallback(cellRequest, detailedCallback);
9770 
9771         mockUidNetworkingBlocked();
9772 
9773         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
9774         mCellAgent.connect(true);
9775         cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
9776         detailedCallback.expectAvailableThenValidatedCallbacks(mCellAgent, BLOCKED_REASON_NONE);
9777         assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetwork());
9778         assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
9779         assertNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
9780         assertExtraInfoFromCmPresent(mCellAgent);
9781 
9782         setBlockedReasonChanged(BLOCKED_REASON_BATTERY_SAVER);
9783         cellNetworkCallback.expect(BLOCKED_STATUS, mCellAgent, cb -> cb.getBlocked());
9784         detailedCallback.expect(BLOCKED_STATUS_INT, mCellAgent,
9785                 cb -> cb.getReason() == BLOCKED_REASON_BATTERY_SAVER);
9786         assertNull(mCm.getActiveNetwork());
9787         assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
9788         assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
9789         assertExtraInfoFromCmBlocked(mCellAgent);
9790 
9791         // If blocked state does not change but blocked reason does, the boolean callback is called.
9792         // TODO: investigate de-duplicating.
9793         setBlockedReasonChanged(BLOCKED_METERED_REASON_USER_RESTRICTED);
9794         cellNetworkCallback.expect(BLOCKED_STATUS, mCellAgent, cb -> cb.getBlocked());
9795         detailedCallback.expect(BLOCKED_STATUS_INT, mCellAgent,
9796                 cb -> cb.getReason() == BLOCKED_METERED_REASON_USER_RESTRICTED);
9797 
9798         setBlockedReasonChanged(BLOCKED_REASON_NONE);
9799         cellNetworkCallback.expect(BLOCKED_STATUS, mCellAgent, cb -> !cb.getBlocked());
9800         detailedCallback.expect(BLOCKED_STATUS_INT, mCellAgent,
9801                 cb -> cb.getReason() == BLOCKED_REASON_NONE);
9802         assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetwork());
9803         assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
9804         assertNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
9805         assertExtraInfoFromCmPresent(mCellAgent);
9806 
9807         setBlockedReasonChanged(BLOCKED_METERED_REASON_DATA_SAVER);
9808         cellNetworkCallback.expect(BLOCKED_STATUS, mCellAgent, cb -> cb.getBlocked());
9809         detailedCallback.expect(BLOCKED_STATUS_INT, mCellAgent,
9810                 cb -> cb.getReason() == BLOCKED_METERED_REASON_DATA_SAVER);
9811         assertNull(mCm.getActiveNetwork());
9812         assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
9813         assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
9814         assertExtraInfoFromCmBlocked(mCellAgent);
9815 
9816         // Restrict the network based on UID rule and NOT_METERED capability change.
9817         mCellAgent.addCapability(NET_CAPABILITY_NOT_METERED);
9818         cellNetworkCallback.expectCaps(mCellAgent,
9819                 c -> c.hasCapability(NET_CAPABILITY_NOT_METERED));
9820         cellNetworkCallback.expect(BLOCKED_STATUS, mCellAgent, cb -> !cb.getBlocked());
9821         detailedCallback.expectCaps(mCellAgent, c -> c.hasCapability(NET_CAPABILITY_NOT_METERED));
9822         detailedCallback.expect(BLOCKED_STATUS_INT, mCellAgent,
9823                 cb -> cb.getReason() == BLOCKED_REASON_NONE);
9824         assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetwork());
9825         assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
9826         assertNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
9827         assertExtraInfoFromCmPresent(mCellAgent);
9828 
9829         mCellAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
9830         cellNetworkCallback.expectCaps(mCellAgent,
9831                 c -> !c.hasCapability(NET_CAPABILITY_NOT_METERED));
9832         cellNetworkCallback.expect(BLOCKED_STATUS, mCellAgent, cb -> cb.getBlocked());
9833         detailedCallback.expectCaps(mCellAgent,
9834                 c -> !c.hasCapability(NET_CAPABILITY_NOT_METERED));
9835         detailedCallback.expect(BLOCKED_STATUS_INT, mCellAgent,
9836                 cb -> cb.getReason() == BLOCKED_METERED_REASON_DATA_SAVER);
9837         assertNull(mCm.getActiveNetwork());
9838         assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
9839         assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
9840         assertExtraInfoFromCmBlocked(mCellAgent);
9841 
9842         setBlockedReasonChanged(BLOCKED_REASON_NONE);
9843         cellNetworkCallback.expect(BLOCKED_STATUS, mCellAgent, cb -> !cb.getBlocked());
9844         detailedCallback.expect(BLOCKED_STATUS_INT, mCellAgent,
9845                 cb -> cb.getReason() == BLOCKED_REASON_NONE);
9846         assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetwork());
9847         assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
9848         assertNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
9849         assertExtraInfoFromCmPresent(mCellAgent);
9850 
9851         setBlockedReasonChanged(BLOCKED_REASON_NONE);
9852         cellNetworkCallback.assertNoCallback();
9853         detailedCallback.assertNoCallback();
9854 
9855         // Restrict background data. Networking is not blocked because the network is unmetered.
9856         setBlockedReasonChanged(BLOCKED_METERED_REASON_DATA_SAVER);
9857         cellNetworkCallback.expect(BLOCKED_STATUS, mCellAgent, cb -> cb.getBlocked());
9858         detailedCallback.expect(BLOCKED_STATUS_INT, mCellAgent,
9859                 cb -> cb.getReason() == BLOCKED_METERED_REASON_DATA_SAVER);
9860         assertNull(mCm.getActiveNetwork());
9861         assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
9862         assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
9863         assertExtraInfoFromCmBlocked(mCellAgent);
9864         setBlockedReasonChanged(BLOCKED_METERED_REASON_DATA_SAVER);
9865         cellNetworkCallback.assertNoCallback();
9866 
9867         setBlockedReasonChanged(BLOCKED_REASON_NONE);
9868         cellNetworkCallback.expect(BLOCKED_STATUS, mCellAgent, cb -> !cb.getBlocked());
9869         detailedCallback.expect(BLOCKED_STATUS_INT, mCellAgent,
9870                 cb -> cb.getReason() == BLOCKED_REASON_NONE);
9871         assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
9872         assertNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
9873         assertExtraInfoFromCmPresent(mCellAgent);
9874 
9875         setBlockedReasonChanged(BLOCKED_REASON_NONE);
9876         cellNetworkCallback.assertNoCallback();
9877         detailedCallback.assertNoCallback();
9878         assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetwork());
9879         assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
9880         assertNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
9881         assertExtraInfoFromCmPresent(mCellAgent);
9882 
9883         // Remove PERMISSION_INTERNET and disable NETWORK_BLOCKED_WITHOUT_INTERNET_PERMISSION
9884         doReturn(INetd.PERMISSION_NONE).when(mBpfNetMaps).getNetPermForUid(Process.myUid());
9885         mDeps.setChangeIdEnabled(false,
9886                 NETWORK_BLOCKED_WITHOUT_INTERNET_PERMISSION, Process.myUid());
9887 
9888         setBlockedReasonChanged(BLOCKED_REASON_DOZE);
9889         if (mDeps.isAtLeastV()) {
9890             // On V+, network access from app that does not have INTERNET permission is considered
9891             // not blocked if NETWORK_BLOCKED_WITHOUT_INTERNET_PERMISSION is disabled.
9892             // So blocked status does not change from BLOCKED_REASON_NONE
9893             cellNetworkCallback.assertNoCallback();
9894             detailedCallback.assertNoCallback();
9895         } else {
9896             // On U-, onBlockedStatusChanged callback is called with blocked reasons CS receives
9897             // from NPMS callback regardless of permission app has.
9898             // Note that this cannot actually happen because on U-, NPMS will never notify any
9899             // blocked reasons for apps that don't have the INTERNET permission.
9900             cellNetworkCallback.expect(BLOCKED_STATUS, mCellAgent, cb -> cb.getBlocked());
9901             detailedCallback.expect(BLOCKED_STATUS_INT, mCellAgent,
9902                     cb -> cb.getReason() == BLOCKED_REASON_DOZE);
9903         }
9904 
9905         mCm.unregisterNetworkCallback(cellNetworkCallback);
9906     }
9907 
9908     @Test
9909     public void testNetworkBlockedStatusBeforeAndAfterConnect() throws Exception {
9910         final TestNetworkCallback defaultCallback = new TestNetworkCallback();
9911         mCm.registerDefaultNetworkCallback(defaultCallback);
9912         mockUidNetworkingBlocked();
9913 
9914         // No Networkcallbacks invoked before any network is active.
9915         setBlockedReasonChanged(BLOCKED_REASON_BATTERY_SAVER);
9916         setBlockedReasonChanged(BLOCKED_REASON_NONE);
9917         setBlockedReasonChanged(BLOCKED_METERED_REASON_DATA_SAVER);
9918         defaultCallback.assertNoCallback();
9919 
9920         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
9921         mCellAgent.connect(true);
9922         defaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mCellAgent);
9923         defaultCallback.expectCaps(mCellAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
9924 
9925         // Allow to use the network after switching to NOT_METERED network.
9926         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
9927         mWiFiAgent.addCapability(NET_CAPABILITY_NOT_METERED);
9928         mWiFiAgent.connect(true);
9929         defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiAgent);
9930 
9931         // Switch to METERED network. Restrict the use of the network.
9932         mWiFiAgent.disconnect();
9933         defaultCallback.expect(LOST, mWiFiAgent);
9934         defaultCallback.expectAvailableCallbacksValidatedAndBlocked(mCellAgent);
9935 
9936         // Network becomes NOT_METERED.
9937         mCellAgent.addCapability(NET_CAPABILITY_NOT_METERED);
9938         defaultCallback.expectCaps(mCellAgent, c -> c.hasCapability(NET_CAPABILITY_NOT_METERED));
9939         defaultCallback.expect(BLOCKED_STATUS, mCellAgent, cb -> !cb.getBlocked());
9940 
9941         // Verify there's no Networkcallbacks invoked after data saver on/off.
9942         setBlockedReasonChanged(BLOCKED_METERED_REASON_DATA_SAVER);
9943         setBlockedReasonChanged(BLOCKED_REASON_NONE);
9944         defaultCallback.assertNoCallback();
9945 
9946         mCellAgent.disconnect();
9947         defaultCallback.expect(LOST, mCellAgent);
9948         defaultCallback.assertNoCallback();
9949 
9950         mCm.unregisterNetworkCallback(defaultCallback);
9951     }
9952 
9953     private void expectNetworkRejectNonSecureVpn(InOrder inOrder, boolean add,
9954             UidRangeParcel... expected) throws Exception {
9955         inOrder.verify(mMockNetd).networkRejectNonSecureVpn(eq(add), aryEq(expected));
9956     }
9957 
9958     private void checkNetworkInfo(NetworkInfo ni, int type, DetailedState state) {
9959         assertNotNull(ni);
9960         assertEquals(type, ni.getType());
9961         assertEquals(ConnectivityManager.getNetworkTypeName(type), state, ni.getDetailedState());
9962         if (state == DetailedState.CONNECTED || state == DetailedState.SUSPENDED) {
9963             assertNotNull(ni.getExtraInfo());
9964         } else {
9965             // Technically speaking, a network that's in CONNECTING state will generally have a
9966             // non-null extraInfo. This doesn't actually happen in this test because it never calls
9967             // a legacy API while a network is connecting. When a network is in CONNECTING state
9968             // because of legacy lockdown VPN, its extraInfo is always null.
9969             assertNull(ni.getExtraInfo());
9970         }
9971     }
9972 
9973     private void assertActiveNetworkInfo(int type, DetailedState state) {
9974         checkNetworkInfo(mCm.getActiveNetworkInfo(), type, state);
9975     }
9976     private void assertNetworkInfo(int type, DetailedState state) {
9977         checkNetworkInfo(mCm.getNetworkInfo(type), type, state);
9978     }
9979 
9980     private void assertExtraInfoFromCm(TestNetworkAgentWrapper network, boolean present) {
9981         final NetworkInfo niForNetwork = mCm.getNetworkInfo(network.getNetwork());
9982         final NetworkInfo niForType = mCm.getNetworkInfo(network.getLegacyType());
9983         if (present) {
9984             assertEquals(network.getExtraInfo(), niForNetwork.getExtraInfo());
9985             assertEquals(network.getExtraInfo(), niForType.getExtraInfo());
9986         } else {
9987             assertNull(niForNetwork.getExtraInfo());
9988             assertNull(niForType.getExtraInfo());
9989         }
9990     }
9991 
9992     private void assertExtraInfoFromCmBlocked(TestNetworkAgentWrapper network) {
9993         assertExtraInfoFromCm(network, false);
9994     }
9995 
9996     private void assertExtraInfoFromCmPresent(TestNetworkAgentWrapper network) {
9997         assertExtraInfoFromCm(network, true);
9998     }
9999 
10000     // Checks that each of the |agents| receive a blocked status change callback with the specified
10001     // |blocked| value, in any order. This is needed because when an event affects multiple
10002     // networks, ConnectivityService does not guarantee the order in which callbacks are fired.
10003     private void assertBlockedCallbackInAnyOrder(TestNetworkCallback callback, boolean blocked,
10004             TestNetworkAgentWrapper... agents) {
10005         final List<Network> expectedNetworks = asList(agents).stream()
10006                 .map((agent) -> agent.getNetwork())
10007                 .collect(Collectors.toList());
10008 
10009         // Expect exactly one blocked callback for each agent.
10010         for (int i = 0; i < agents.length; i++) {
10011             final CallbackEntry e = callback.expect(BLOCKED_STATUS, TIMEOUT_MS,
10012                     c -> c.getBlocked() == blocked);
10013             final Network network = e.getNetwork();
10014             assertTrue("Received unexpected blocked callback for network " + network,
10015                     expectedNetworks.remove(network));
10016         }
10017     }
10018 
10019     @Test
10020     public void testNetworkBlockedStatusAlwaysOnVpn() throws Exception {
10021         mServiceContext.setPermission(
10022                 Manifest.permission.CONTROL_ALWAYS_ON_VPN, PERMISSION_GRANTED);
10023         mServiceContext.setPermission(
10024                 Manifest.permission.CONTROL_VPN, PERMISSION_GRANTED);
10025         mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_GRANTED);
10026 
10027         final TestNetworkCallback callback = new TestNetworkCallback();
10028         final NetworkRequest request = new NetworkRequest.Builder()
10029                 .removeCapability(NET_CAPABILITY_NOT_VPN)
10030                 .build();
10031         mCm.registerNetworkCallback(request, callback);
10032 
10033         final TestNetworkCallback defaultCallback = new TestNetworkCallback();
10034         mCm.registerDefaultNetworkCallback(defaultCallback);
10035 
10036         final TestNetworkCallback vpnUidCallback = new TestNetworkCallback();
10037         final NetworkRequest vpnUidRequest = new NetworkRequest.Builder().build();
10038         registerNetworkCallbackAsUid(vpnUidRequest, vpnUidCallback, VPN_UID);
10039 
10040         final TestNetworkCallback vpnUidDefaultCallback = new TestNetworkCallback();
10041         registerDefaultNetworkCallbackAsUid(vpnUidDefaultCallback, VPN_UID);
10042 
10043         final TestNetworkCallback vpnDefaultCallbackAsUid = new TestNetworkCallback();
10044         mCm.registerDefaultNetworkCallbackForUid(VPN_UID, vpnDefaultCallbackAsUid,
10045                 new Handler(ConnectivityThread.getInstanceLooper()));
10046 
10047         final int uid = Process.myUid();
10048 
10049         // Enable always-on VPN lockdown, coverage in VpnTest.
10050         final List<Integer> excludedUids = new ArrayList<Integer>();
10051         excludedUids.add(VPN_UID);
10052         if (mDeps.isAtLeastT()) {
10053             // On T onwards, the corresponding SDK sandbox UID should also be excluded
10054             excludedUids.add(toSdkSandboxUid(VPN_UID));
10055         }
10056 
10057         final List<Range<Integer>> primaryRanges = intRangesPrimaryExcludingUids(excludedUids);
10058         mCm.setRequireVpnForUids(true, primaryRanges);
10059         waitForIdle();
10060 
10061         final UidRangeParcel[] uidRangeParcels = intToUidRangeStableParcels(primaryRanges);
10062         InOrder inOrder = inOrder(mMockNetd);
10063         expectNetworkRejectNonSecureVpn(inOrder, true, uidRangeParcels);
10064 
10065         // Connect a network when lockdown is active, expect to see it blocked.
10066         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
10067         mWiFiAgent.connect(false /* validated */);
10068         callback.expectAvailableCallbacksUnvalidatedAndBlocked(mWiFiAgent);
10069         defaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mWiFiAgent);
10070         vpnUidCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
10071         vpnUidDefaultCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
10072         vpnDefaultCallbackAsUid.expectAvailableCallbacksUnvalidated(mWiFiAgent);
10073         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
10074         assertNull(mCm.getActiveNetwork());
10075         assertActiveNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED);
10076         // Mobile is BLOCKED even though it's not actually connected.
10077         assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
10078         assertNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED);
10079 
10080         // Disable lockdown, expect to see the network unblocked.
10081         mCm.setRequireVpnForUids(false, primaryRanges);
10082         waitForIdle();
10083         callback.expect(BLOCKED_STATUS, mWiFiAgent, cb -> !cb.getBlocked());
10084         defaultCallback.expect(BLOCKED_STATUS, mWiFiAgent, cb -> !cb.getBlocked());
10085         vpnUidCallback.assertNoCallback();
10086         vpnUidDefaultCallback.assertNoCallback();
10087         vpnDefaultCallbackAsUid.assertNoCallback();
10088         expectNetworkRejectNonSecureVpn(inOrder, false, uidRangeParcels);
10089         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
10090         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetwork());
10091         assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
10092         assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED);
10093         assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
10094 
10095         // Add our UID to the allowlist, expect network is not blocked. Coverage in VpnTest.
10096         excludedUids.add(uid);
10097         if (mDeps.isAtLeastT()) {
10098             // On T onwards, the corresponding SDK sandbox UID should also be excluded
10099             excludedUids.add(toSdkSandboxUid(uid));
10100         }
10101         final List<Range<Integer>> primaryRangesExcludingUid =
10102                 intRangesPrimaryExcludingUids(excludedUids);
10103         mCm.setRequireVpnForUids(true, primaryRangesExcludingUid);
10104         waitForIdle();
10105 
10106         callback.assertNoCallback();
10107         defaultCallback.assertNoCallback();
10108         vpnUidCallback.assertNoCallback();
10109         vpnUidDefaultCallback.assertNoCallback();
10110         vpnDefaultCallbackAsUid.assertNoCallback();
10111 
10112         final UidRangeParcel[] uidRangeParcelsAlsoExcludingUs =
10113                 intToUidRangeStableParcels(primaryRangesExcludingUid);
10114         expectNetworkRejectNonSecureVpn(inOrder, true, uidRangeParcelsAlsoExcludingUs);
10115         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
10116         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetwork());
10117         assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
10118         assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED);
10119         assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
10120 
10121         // Connect a new network, expect it to be unblocked.
10122         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
10123         mCellAgent.connect(false /* validated */);
10124         callback.expectAvailableCallbacksUnvalidated(mCellAgent);
10125         defaultCallback.assertNoCallback();
10126         vpnUidCallback.expectAvailableCallbacksUnvalidated(mCellAgent);
10127         vpnUidDefaultCallback.assertNoCallback();
10128         vpnDefaultCallbackAsUid.assertNoCallback();
10129         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
10130         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetwork());
10131         assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
10132         // Cellular is DISCONNECTED because it's not the default and there are no requests for it.
10133         assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED);
10134         assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
10135 
10136         // Disable lockdown
10137         mCm.setRequireVpnForUids(false, primaryRangesExcludingUid);
10138         waitForIdle();
10139         expectNetworkRejectNonSecureVpn(inOrder, false, uidRangeParcelsAlsoExcludingUs);
10140         // Remove our UID from the allowlist, and re-enable lockdown.
10141         mCm.setRequireVpnForUids(true, primaryRanges);
10142         waitForIdle();
10143         expectNetworkRejectNonSecureVpn(inOrder, true, uidRangeParcels);
10144         // Everything should now be blocked.
10145         defaultCallback.expect(BLOCKED_STATUS, mWiFiAgent, cb -> cb.getBlocked());
10146         assertBlockedCallbackInAnyOrder(callback, true, mWiFiAgent, mCellAgent);
10147         vpnUidCallback.assertNoCallback();
10148         vpnUidDefaultCallback.assertNoCallback();
10149         vpnDefaultCallbackAsUid.assertNoCallback();
10150         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
10151         assertNull(mCm.getActiveNetwork());
10152         assertActiveNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED);
10153         assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
10154         assertNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED);
10155 
10156         // Disable lockdown. Everything is unblocked.
10157         mCm.setRequireVpnForUids(false, primaryRanges);
10158         defaultCallback.expect(BLOCKED_STATUS, mWiFiAgent, cb -> !cb.getBlocked());
10159         assertBlockedCallbackInAnyOrder(callback, false, mWiFiAgent, mCellAgent);
10160         vpnUidCallback.assertNoCallback();
10161         vpnUidDefaultCallback.assertNoCallback();
10162         vpnDefaultCallbackAsUid.assertNoCallback();
10163         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
10164         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetwork());
10165         assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
10166         assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED);
10167         assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
10168 
10169         // Enable lockdown and connect a VPN. The VPN is not blocked.
10170         mCm.setRequireVpnForUids(true, primaryRanges);
10171         defaultCallback.expect(BLOCKED_STATUS, mWiFiAgent, cb -> cb.getBlocked());
10172         assertBlockedCallbackInAnyOrder(callback, true, mWiFiAgent, mCellAgent);
10173         vpnUidCallback.assertNoCallback();
10174         vpnUidDefaultCallback.assertNoCallback();
10175         vpnDefaultCallbackAsUid.assertNoCallback();
10176         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
10177         assertNull(mCm.getActiveNetwork());
10178         assertActiveNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED);
10179         assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
10180         assertNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED);
10181 
10182         mMockVpn.establishForMyUid();
10183         assertUidRangesUpdatedForMyUid(true);
10184         defaultCallback.expectAvailableThenValidatedCallbacks(mMockVpn);
10185         vpnUidCallback.assertNoCallback();  // vpnUidCallback has NOT_VPN capability.
10186         vpnUidDefaultCallback.assertNoCallback();  // VPN does not apply to VPN_UID
10187         vpnDefaultCallbackAsUid.assertNoCallback();
10188         assertEquals(mMockVpn.getNetwork(), mCm.getActiveNetwork());
10189         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
10190         assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
10191         assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED);
10192         assertNetworkInfo(TYPE_VPN, DetailedState.CONNECTED);
10193         assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
10194 
10195         mMockVpn.disconnect();
10196         defaultCallback.expect(LOST, mMockVpn);
10197         defaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mWiFiAgent);
10198         vpnUidCallback.assertNoCallback();
10199         vpnUidDefaultCallback.assertNoCallback();
10200         vpnDefaultCallbackAsUid.assertNoCallback();
10201         assertNull(mCm.getActiveNetwork());
10202 
10203         mCm.unregisterNetworkCallback(callback);
10204         mCm.unregisterNetworkCallback(defaultCallback);
10205         mCm.unregisterNetworkCallback(vpnUidCallback);
10206         mCm.unregisterNetworkCallback(vpnUidDefaultCallback);
10207         mCm.unregisterNetworkCallback(vpnDefaultCallbackAsUid);
10208     }
10209 
10210     @Test
10211     public void testVpnExcludesOwnUid() throws Exception {
10212         // required for registerDefaultNetworkCallbackForUid.
10213         mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_GRANTED);
10214 
10215         // Connect Wi-Fi.
10216         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
10217         mWiFiAgent.connect(true /* validated */);
10218 
10219         // Connect a VPN that excludes its UID from its UID ranges.
10220         final LinkProperties lp = new LinkProperties();
10221         lp.setInterfaceName(VPN_IFNAME);
10222         final int myUid = Process.myUid();
10223         final Set<UidRange> ranges = new ArraySet<>();
10224         ranges.add(new UidRange(0, myUid - 1));
10225         ranges.add(new UidRange(myUid + 1, UserHandle.PER_USER_RANGE - 1));
10226         mMockVpn.setUnderlyingNetworks(new Network[] { mWiFiAgent.getNetwork() });
10227         mMockVpn.establish(lp, myUid, ranges);
10228 
10229         // Wait for validation before registering callbacks.
10230         waitForIdle();
10231 
10232         final int otherUid = myUid + 1;
10233         final Handler h = new Handler(ConnectivityThread.getInstanceLooper());
10234         final TestNetworkCallback otherUidCb = new TestNetworkCallback();
10235         final TestNetworkCallback defaultCb = new TestNetworkCallback();
10236         final TestNetworkCallback perUidCb = new TestNetworkCallback();
10237         registerDefaultNetworkCallbackAsUid(otherUidCb, otherUid);
10238         mCm.registerDefaultNetworkCallback(defaultCb, h);
10239         doAsUid(Process.SYSTEM_UID,
10240                 () -> mCm.registerDefaultNetworkCallbackForUid(myUid, perUidCb, h));
10241 
10242         otherUidCb.expectAvailableCallbacksValidated(mMockVpn);
10243         // BUG (b/195265065): the default network for the VPN app is actually Wi-Fi, not the VPN.
10244         defaultCb.expectAvailableCallbacksValidated(mMockVpn);
10245         perUidCb.expectAvailableCallbacksValidated(mMockVpn);
10246         // getActiveNetwork is not affected by this bug.
10247         assertEquals(mMockVpn.getNetwork(), mCm.getActiveNetworkForUid(myUid + 1));
10248         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetwork());
10249         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetworkForUid(myUid));
10250 
10251         doAsUid(otherUid, () -> mCm.unregisterNetworkCallback(otherUidCb));
10252         mCm.unregisterNetworkCallback(defaultCb);
10253         doAsUid(Process.SYSTEM_UID, () -> mCm.unregisterNetworkCallback(perUidCb));
10254     }
10255 
10256     private void establishLegacyLockdownVpn(Network underlying) throws Exception {
10257         // The legacy lockdown VPN only supports userId 0, and must have an underlying network.
10258         assertNotNull(underlying);
10259         mMockVpn.setVpnType(VpnManager.TYPE_VPN_LEGACY);
10260         // The legacy lockdown VPN only supports userId 0.
10261         final Set<UidRange> ranges = Collections.singleton(PRIMARY_UIDRANGE);
10262         mMockVpn.registerAgent(ranges);
10263         mMockVpn.setUnderlyingNetworks(new Network[]{underlying});
10264         mMockVpn.connect(true);
10265     }
10266 
10267     private void doTestLockdownVpn(boolean isIkev2Vpn)
10268             throws Exception {
10269         mServiceContext.setPermission(
10270                 Manifest.permission.CONTROL_VPN, PERMISSION_GRANTED);
10271 
10272         final NetworkRequest request = new NetworkRequest.Builder().clearCapabilities().build();
10273         final TestNetworkCallback callback = new TestNetworkCallback();
10274         mCm.registerNetworkCallback(request, callback);
10275 
10276         final TestNetworkCallback defaultCallback = new TestNetworkCallback();
10277         mCm.registerDefaultNetworkCallback(defaultCallback);
10278 
10279         final TestNetworkCallback systemDefaultCallback = new TestNetworkCallback();
10280         mCm.registerSystemDefaultNetworkCallback(systemDefaultCallback,
10281                 new Handler(ConnectivityThread.getInstanceLooper()));
10282 
10283         // Init lockdown state to simulate LockdownVpnTracker behavior.
10284         mCm.setLegacyLockdownVpnEnabled(true);
10285         final List<Range<Integer>> ranges =
10286                 intRangesPrimaryExcludingUids(Collections.EMPTY_LIST /* excludedeUids */);
10287         mCm.setRequireVpnForUids(true /* requireVpn */, ranges);
10288 
10289         // Bring up a network.
10290         final LinkProperties cellLp = new LinkProperties();
10291         cellLp.setInterfaceName("rmnet0");
10292         cellLp.addLinkAddress(new LinkAddress("192.0.2.2/25"));
10293         cellLp.addRoute(new RouteInfo(new IpPrefix("0.0.0.0/0"), null, "rmnet0"));
10294         // When lockdown VPN is active, the NetworkInfo state in CONNECTIVITY_ACTION is overwritten
10295         // with the state of the VPN network. So expect a CONNECTING broadcast.
10296         final ExpectedBroadcast b = expectConnectivityAction(TYPE_MOBILE, DetailedState.CONNECTING);
10297         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
10298         mCellAgent.connect(false /* validated */);
10299         callback.expectAvailableCallbacksUnvalidatedAndBlocked(mCellAgent);
10300         defaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mCellAgent);
10301         systemDefaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mCellAgent);
10302         b.expectBroadcast();
10303         // Simulate LockdownVpnTracker attempting to start the VPN since it received the
10304         // systemDefault callback.
10305         mMockVpn.startLegacyVpnPrivileged(isIkev2Vpn);
10306         if (isIkev2Vpn) {
10307             // setVpnDefaultForUids() releases the original network request and creates a VPN
10308             // request so LOST callback is received.
10309             defaultCallback.expect(LOST, mCellAgent);
10310             // Due to the VPN default request, getActiveNetworkInfo() gets the mNoServiceNetwork
10311             // as the network satisfier.
10312             assertNull(mCm.getActiveNetworkInfo());
10313         } else {
10314             assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
10315         }
10316         assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
10317         assertNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED);
10318         assertNetworkInfo(TYPE_VPN, DetailedState.BLOCKED);
10319         assertExtraInfoFromCmBlocked(mCellAgent);
10320 
10321         final ExpectedBroadcast b2 = expectConnectivityAction(TYPE_VPN, DetailedState.CONNECTED);
10322         final ExpectedBroadcast b3 = expectConnectivityAction(TYPE_MOBILE, DetailedState.CONNECTED);
10323         establishLegacyLockdownVpn(mCellAgent.getNetwork());
10324         callback.expectAvailableThenValidatedCallbacks(mMockVpn);
10325         defaultCallback.expectAvailableThenValidatedCallbacks(mMockVpn);
10326         systemDefaultCallback.assertNoCallback();
10327         final NetworkCapabilities vpnNc = mCm.getNetworkCapabilities(mMockVpn.getNetwork());
10328         b2.expectBroadcast();
10329         b3.expectBroadcast();
10330         if (isIkev2Vpn) {
10331             // Due to the VPN default request, getActiveNetworkInfo() gets the VPN network as the
10332             // network satisfier which has TYPE_VPN.
10333             assertActiveNetworkInfo(TYPE_VPN, DetailedState.CONNECTED);
10334         } else {
10335             // LegacyVpnRunner does not call setVpnDefaultsForUids(), which means
10336             // getActiveNetworkInfo() can only return the info for the system-wide default instead.
10337             // This should be fixed, but LegacyVpnRunner will be removed soon anyway.
10338             assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
10339         }
10340         assertNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
10341         assertNetworkInfo(TYPE_WIFI, DetailedState.DISCONNECTED);
10342         assertNetworkInfo(TYPE_VPN, DetailedState.CONNECTED);
10343         assertExtraInfoFromCmPresent(mCellAgent);
10344         assertTrue(vpnNc.hasTransport(TRANSPORT_VPN));
10345         assertTrue(vpnNc.hasTransport(TRANSPORT_CELLULAR));
10346         assertFalse(vpnNc.hasTransport(TRANSPORT_WIFI));
10347         assertFalse(vpnNc.hasCapability(NET_CAPABILITY_NOT_METERED));
10348         assertVpnTransportInfo(vpnNc, VpnManager.TYPE_VPN_LEGACY);
10349 
10350         // Switch default network from cell to wifi. Expect VPN to disconnect and reconnect.
10351         final LinkProperties wifiLp = new LinkProperties();
10352         wifiLp.setInterfaceName("wlan0");
10353         wifiLp.addLinkAddress(new LinkAddress("192.0.2.163/25"));
10354         wifiLp.addRoute(new RouteInfo(new IpPrefix("0.0.0.0/0"), null, "wlan0"));
10355         final NetworkCapabilities wifiNc = new NetworkCapabilities();
10356         wifiNc.addTransportType(TRANSPORT_WIFI);
10357         wifiNc.addCapability(NET_CAPABILITY_NOT_METERED);
10358         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp, wifiNc);
10359 
10360         final ExpectedBroadcast b4 =
10361                 expectConnectivityAction(TYPE_MOBILE, DetailedState.DISCONNECTED);
10362         // Wifi is CONNECTING because the VPN isn't up yet.
10363         final ExpectedBroadcast b5 = expectConnectivityAction(TYPE_WIFI, DetailedState.CONNECTING);
10364         mWiFiAgent.connect(false /* validated */);
10365         // Wifi is not blocked since VPN network is still connected.
10366         callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
10367         defaultCallback.assertNoCallback();
10368         systemDefaultCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
10369         b4.expectBroadcast();
10370         b5.expectBroadcast();
10371 
10372         // Simulate LockdownVpnTracker restarting the VPN since it received the systemDefault
10373         // callback with different network.
10374         final ExpectedBroadcast b6 = expectConnectivityAction(TYPE_VPN, DetailedState.DISCONNECTED);
10375         mMockVpn.stopVpnRunnerPrivileged();
10376 
10377         mMockVpn.startLegacyVpnPrivileged(isIkev2Vpn);
10378         // VPN network is disconnected (to restart)
10379         callback.expect(LOST, mMockVpn);
10380         defaultCallback.expect(LOST, mMockVpn);
10381         // The network preference is cleared when VPN is disconnected so it receives callbacks for
10382         // the system-wide default.
10383         defaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mWiFiAgent);
10384         if (isIkev2Vpn) {
10385             // setVpnDefaultForUids() releases the original network request and creates a VPN
10386             // request so LOST callback is received.
10387             defaultCallback.expect(LOST, mWiFiAgent);
10388         }
10389         systemDefaultCallback.assertNoCallback();
10390         b6.expectBroadcast();
10391 
10392         // While the VPN is reconnecting on the new network, everything is blocked.
10393         if (isIkev2Vpn) {
10394             // Due to the VPN default request, getActiveNetworkInfo() gets the mNoServiceNetwork
10395             // as the network satisfier.
10396             assertNull(mCm.getActiveNetworkInfo());
10397         } else {
10398             assertActiveNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED);
10399         }
10400         assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
10401         assertNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED);
10402         assertNetworkInfo(TYPE_VPN, DetailedState.BLOCKED);
10403         assertExtraInfoFromCmBlocked(mWiFiAgent);
10404 
10405         // The VPN comes up again on wifi.
10406         final ExpectedBroadcast b7 = expectConnectivityAction(TYPE_VPN, DetailedState.CONNECTED);
10407         final ExpectedBroadcast b8 = expectConnectivityAction(TYPE_WIFI, DetailedState.CONNECTED);
10408         establishLegacyLockdownVpn(mWiFiAgent.getNetwork());
10409         callback.expectAvailableThenValidatedCallbacks(mMockVpn);
10410         defaultCallback.expectAvailableThenValidatedCallbacks(mMockVpn);
10411         systemDefaultCallback.assertNoCallback();
10412         b7.expectBroadcast();
10413         b8.expectBroadcast();
10414         if (isIkev2Vpn) {
10415             // Due to the VPN default request, getActiveNetworkInfo() gets the VPN network as the
10416             // network satisfier which has TYPE_VPN.
10417             assertActiveNetworkInfo(TYPE_VPN, DetailedState.CONNECTED);
10418         } else {
10419             // LegacyVpnRunner does not call setVpnDefaultsForUids(), which means
10420             // getActiveNetworkInfo() can only return the info for the system-wide default instead.
10421             // This should be fixed, but LegacyVpnRunner will be removed soon anyway.
10422             assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
10423         }
10424         assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED);
10425         assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
10426         assertNetworkInfo(TYPE_VPN, DetailedState.CONNECTED);
10427         assertExtraInfoFromCmPresent(mWiFiAgent);
10428         final NetworkCapabilities vpnNc2 = mCm.getNetworkCapabilities(mMockVpn.getNetwork());
10429         assertTrue(vpnNc2.hasTransport(TRANSPORT_VPN));
10430         assertTrue(vpnNc2.hasTransport(TRANSPORT_WIFI));
10431         assertFalse(vpnNc2.hasTransport(TRANSPORT_CELLULAR));
10432         assertTrue(vpnNc2.hasCapability(NET_CAPABILITY_NOT_METERED));
10433 
10434         // Disconnect cell. Nothing much happens since it's not the default network.
10435         mCellAgent.disconnect();
10436         callback.expect(LOST, mCellAgent);
10437         defaultCallback.assertNoCallback();
10438         systemDefaultCallback.assertNoCallback();
10439 
10440         if (isIkev2Vpn) {
10441             // Due to the VPN default request, getActiveNetworkInfo() gets the VPN network as the
10442             // network satisfier which has TYPE_VPN.
10443             assertActiveNetworkInfo(TYPE_VPN, DetailedState.CONNECTED);
10444         } else {
10445             // LegacyVpnRunner does not call setVpnDefaultsForUids(), which means
10446             // getActiveNetworkInfo() can only return the info for the system-wide default instead.
10447             // This should be fixed, but LegacyVpnRunner will be removed soon anyway.
10448             assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
10449         }
10450         assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED);
10451         assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
10452         assertNetworkInfo(TYPE_VPN, DetailedState.CONNECTED);
10453         assertExtraInfoFromCmPresent(mWiFiAgent);
10454 
10455         final ExpectedBroadcast b9 =
10456                 expectConnectivityAction(TYPE_WIFI, DetailedState.DISCONNECTED);
10457         final ExpectedBroadcast b10 =
10458                 expectConnectivityAction(TYPE_VPN, DetailedState.DISCONNECTED);
10459         mWiFiAgent.disconnect();
10460         callback.expect(LOST, mWiFiAgent);
10461         callback.expectCaps(mMockVpn, c -> !c.hasTransport(TRANSPORT_WIFI));
10462         defaultCallback.expectCaps(mMockVpn, c -> !c.hasTransport(TRANSPORT_WIFI));
10463         systemDefaultCallback.expect(LOST, mWiFiAgent);
10464         // TODO: There should only be one LOST callback. Since the WIFI network is underlying a VPN
10465         // network, ConnectivityService#propagateUnderlyingNetworkCapabilities() causes a rematch to
10466         // occur. Notably, this happens before setting the satisfiers of its network requests to
10467         // null. Since the satisfiers are set to null in the rematch, an extra LOST callback is
10468         // called.
10469         systemDefaultCallback.expect(LOST, mWiFiAgent);
10470         b9.expectBroadcast();
10471         mMockVpn.stopVpnRunnerPrivileged();
10472         callback.expect(LOST, mMockVpn);
10473         defaultCallback.expect(LOST, mMockVpn);
10474         b10.expectBroadcast();
10475 
10476         assertNoCallbacks(callback, defaultCallback, systemDefaultCallback);
10477     }
10478 
10479     @Test
10480     public void testLockdownVpn_LegacyVpnRunner() throws Exception {
10481         doTestLockdownVpn(false /* isIkev2Vpn */);
10482     }
10483 
10484     @Test
10485     public void testLockdownVpn_Ikev2VpnRunner() throws Exception {
10486         doTestLockdownVpn(true /* isIkev2Vpn */);
10487     }
10488 
10489     @Test @IgnoreUpTo(Build.VERSION_CODES.S_V2)
10490     public void testLockdownSetFirewallUidRule() throws Exception {
10491         final List<Range<Integer>> lockdownRange =
10492                 intRangesPrimaryExcludingUids(Collections.EMPTY_LIST /* excludedeUids */);
10493         // Enable Lockdown
10494         mCm.setRequireVpnForUids(true /* requireVpn */, lockdownRange);
10495         waitForIdle();
10496 
10497         // Lockdown rule is set to apps uids
10498         verify(mBpfNetMaps, times(3)).updateUidLockdownRule(anyInt(), eq(true) /* add */);
10499         verify(mBpfNetMaps).updateUidLockdownRule(APP1_UID, true /* add */);
10500         verify(mBpfNetMaps).updateUidLockdownRule(APP2_UID, true /* add */);
10501         verify(mBpfNetMaps).updateUidLockdownRule(VPN_UID, true /* add */);
10502 
10503         reset(mBpfNetMaps);
10504 
10505         // Disable lockdown
10506         mCm.setRequireVpnForUids(false /* requireVPN */, lockdownRange);
10507         waitForIdle();
10508 
10509         // Lockdown rule is removed from apps uids
10510         verify(mBpfNetMaps, times(3)).updateUidLockdownRule(anyInt(), eq(false) /* add */);
10511         verify(mBpfNetMaps).updateUidLockdownRule(APP1_UID, false /* add */);
10512         verify(mBpfNetMaps).updateUidLockdownRule(APP2_UID, false /* add */);
10513         verify(mBpfNetMaps).updateUidLockdownRule(VPN_UID, false /* add */);
10514 
10515         // Interface rules are not changed by Lockdown mode enable/disable
10516         verify(mBpfNetMaps, never()).addUidInterfaceRules(any(), any());
10517         verify(mBpfNetMaps, never()).removeUidInterfaceRules(any());
10518     }
10519 
10520     private void doTestSetUidFirewallRule(final int chain, final int defaultRule) {
10521         final int uid = 1001;
10522         mCm.setUidFirewallRule(chain, uid, FIREWALL_RULE_ALLOW);
10523         verify(mBpfNetMaps).setUidRule(chain, uid, FIREWALL_RULE_ALLOW);
10524         reset(mBpfNetMaps);
10525 
10526         mCm.setUidFirewallRule(chain, uid, FIREWALL_RULE_DENY);
10527         verify(mBpfNetMaps).setUidRule(chain, uid, FIREWALL_RULE_DENY);
10528         reset(mBpfNetMaps);
10529 
10530         mCm.setUidFirewallRule(chain, uid, FIREWALL_RULE_DEFAULT);
10531         verify(mBpfNetMaps).setUidRule(chain, uid, defaultRule);
10532         reset(mBpfNetMaps);
10533     }
10534 
10535     @Test @IgnoreUpTo(SC_V2)
10536     public void testSetUidFirewallRule() throws Exception {
10537         doTestSetUidFirewallRule(FIREWALL_CHAIN_DOZABLE, FIREWALL_RULE_DENY);
10538         doTestSetUidFirewallRule(FIREWALL_CHAIN_STANDBY, FIREWALL_RULE_ALLOW);
10539         doTestSetUidFirewallRule(FIREWALL_CHAIN_POWERSAVE, FIREWALL_RULE_DENY);
10540         doTestSetUidFirewallRule(FIREWALL_CHAIN_RESTRICTED, FIREWALL_RULE_DENY);
10541         doTestSetUidFirewallRule(FIREWALL_CHAIN_LOW_POWER_STANDBY, FIREWALL_RULE_DENY);
10542         if (SdkLevel.isAtLeastV()) {
10543             // FIREWALL_CHAIN_BACKGROUND is only available on V+.
10544             doTestSetUidFirewallRule(FIREWALL_CHAIN_BACKGROUND, FIREWALL_RULE_DENY);
10545         }
10546         doTestSetUidFirewallRule(FIREWALL_CHAIN_OEM_DENY_1, FIREWALL_RULE_ALLOW);
10547         doTestSetUidFirewallRule(FIREWALL_CHAIN_OEM_DENY_2, FIREWALL_RULE_ALLOW);
10548         doTestSetUidFirewallRule(FIREWALL_CHAIN_OEM_DENY_3, FIREWALL_RULE_ALLOW);
10549         doTestSetUidFirewallRule(FIREWALL_CHAIN_METERED_ALLOW, FIREWALL_RULE_DENY);
10550         doTestSetUidFirewallRule(FIREWALL_CHAIN_METERED_DENY_USER, FIREWALL_RULE_ALLOW);
10551         doTestSetUidFirewallRule(FIREWALL_CHAIN_METERED_DENY_ADMIN, FIREWALL_RULE_ALLOW);
10552     }
10553 
10554     @Test @IgnoreUpTo(SC_V2)
10555     public void testSetFirewallChainEnabled() throws Exception {
10556         final List<Integer> firewallChains = new ArrayList<>(Arrays.asList(
10557                 FIREWALL_CHAIN_DOZABLE,
10558                 FIREWALL_CHAIN_STANDBY,
10559                 FIREWALL_CHAIN_POWERSAVE,
10560                 FIREWALL_CHAIN_RESTRICTED,
10561                 FIREWALL_CHAIN_LOW_POWER_STANDBY,
10562                 FIREWALL_CHAIN_OEM_DENY_1,
10563                 FIREWALL_CHAIN_OEM_DENY_2,
10564                 FIREWALL_CHAIN_OEM_DENY_3));
10565         if (SdkLevel.isAtLeastV()) {
10566             // FIREWALL_CHAIN_BACKGROUND is only available on V+.
10567             firewallChains.add(FIREWALL_CHAIN_BACKGROUND);
10568         }
10569         for (final int chain: firewallChains) {
10570             mCm.setFirewallChainEnabled(chain, true /* enabled */);
10571             verify(mBpfNetMaps).setChildChain(chain, true /* enable */);
10572             reset(mBpfNetMaps);
10573 
10574             mCm.setFirewallChainEnabled(chain, false /* enabled */);
10575             verify(mBpfNetMaps).setChildChain(chain, false /* enable */);
10576             reset(mBpfNetMaps);
10577         }
10578     }
10579 
10580     private void doTestSetFirewallChainEnabledCloseSocket(final int chain,
10581             final boolean isAllowList) throws Exception {
10582         reset(mDestroySocketsWrapper);
10583 
10584         mCm.setFirewallChainEnabled(chain, true /* enabled */);
10585         final Set<Integer> uids =
10586                 new ArraySet<>(List.of(TEST_PACKAGE_UID, TEST_PACKAGE_UID2));
10587         if (isAllowList) {
10588             final Set<Range<Integer>> range = new ArraySet<>(
10589                     List.of(new Range<>(Process.FIRST_APPLICATION_UID, Integer.MAX_VALUE)));
10590             verify(mDestroySocketsWrapper).destroyLiveTcpSockets(range, uids);
10591         } else {
10592             verify(mDestroySocketsWrapper).destroyLiveTcpSocketsByOwnerUids(uids);
10593         }
10594 
10595         mCm.setFirewallChainEnabled(chain, false /* enabled */);
10596         verifyNoMoreInteractions(mDestroySocketsWrapper);
10597     }
10598 
10599     @Test @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
10600     public void testSetFirewallChainEnabledCloseSocket() throws Exception {
10601         doReturn(new ArraySet<>(Arrays.asList(TEST_PACKAGE_UID, TEST_PACKAGE_UID2)))
10602                 .when(mBpfNetMaps)
10603                 .getUidsWithDenyRuleOnDenyListChain(anyInt());
10604         doReturn(new ArraySet<>(Arrays.asList(TEST_PACKAGE_UID, TEST_PACKAGE_UID2)))
10605                 .when(mBpfNetMaps)
10606                 .getUidsWithAllowRuleOnAllowListChain(anyInt());
10607 
10608         final boolean allowlist = true;
10609         final boolean denylist = false;
10610 
10611         doTestSetFirewallChainEnabledCloseSocket(FIREWALL_CHAIN_DOZABLE, allowlist);
10612         doTestSetFirewallChainEnabledCloseSocket(FIREWALL_CHAIN_POWERSAVE, allowlist);
10613         doTestSetFirewallChainEnabledCloseSocket(FIREWALL_CHAIN_RESTRICTED, allowlist);
10614         doTestSetFirewallChainEnabledCloseSocket(FIREWALL_CHAIN_LOW_POWER_STANDBY, allowlist);
10615         if (SdkLevel.isAtLeastV()) {
10616             // FIREWALL_CHAIN_BACKGROUND is only available on V+.
10617             doTestSetFirewallChainEnabledCloseSocket(FIREWALL_CHAIN_BACKGROUND, allowlist);
10618         }
10619 
10620         doTestSetFirewallChainEnabledCloseSocket(FIREWALL_CHAIN_STANDBY, denylist);
10621         doTestSetFirewallChainEnabledCloseSocket(FIREWALL_CHAIN_OEM_DENY_1, denylist);
10622         doTestSetFirewallChainEnabledCloseSocket(FIREWALL_CHAIN_OEM_DENY_2, denylist);
10623         doTestSetFirewallChainEnabledCloseSocket(FIREWALL_CHAIN_OEM_DENY_3, denylist);
10624     }
10625 
10626     private void doTestReplaceFirewallChain(final int chain) {
10627         final int[] uids = new int[] {1001, 1002};
10628         mCm.replaceFirewallChain(chain, uids);
10629         verify(mBpfNetMaps).replaceUidChain(chain, uids);
10630         reset(mBpfNetMaps);
10631     }
10632 
10633     @Test @IgnoreUpTo(SC_V2)
10634     public void testReplaceFirewallChain() {
10635         doTestReplaceFirewallChain(FIREWALL_CHAIN_DOZABLE);
10636         doTestReplaceFirewallChain(FIREWALL_CHAIN_STANDBY);
10637         doTestReplaceFirewallChain(FIREWALL_CHAIN_POWERSAVE);
10638         doTestReplaceFirewallChain(FIREWALL_CHAIN_RESTRICTED);
10639         doTestReplaceFirewallChain(FIREWALL_CHAIN_LOW_POWER_STANDBY);
10640         if (SdkLevel.isAtLeastV()) {
10641             // FIREWALL_CHAIN_BACKGROUND is only available on V+.
10642             doTestReplaceFirewallChain(FIREWALL_CHAIN_BACKGROUND);
10643         }
10644         doTestReplaceFirewallChain(FIREWALL_CHAIN_OEM_DENY_1);
10645         doTestReplaceFirewallChain(FIREWALL_CHAIN_OEM_DENY_2);
10646         doTestReplaceFirewallChain(FIREWALL_CHAIN_OEM_DENY_3);
10647     }
10648 
10649     @Test @IgnoreUpTo(SC_V2)
10650     public void testInvalidFirewallChain() throws Exception {
10651         final int uid = 1001;
10652         final Class<IllegalArgumentException> expected = IllegalArgumentException.class;
10653         assertThrows(expected,
10654                 () -> mCm.setUidFirewallRule(-1 /* chain */, uid, FIREWALL_RULE_ALLOW));
10655         assertThrows(expected,
10656                 () -> mCm.setUidFirewallRule(100 /* chain */, uid, FIREWALL_RULE_ALLOW));
10657     }
10658 
10659     @Test @IgnoreUpTo(SC_V2)
10660     public void testInvalidFirewallRule() throws Exception {
10661         final Class<IllegalArgumentException> expected = IllegalArgumentException.class;
10662         assertThrows(expected,
10663                 () -> mCm.setUidFirewallRule(FIREWALL_CHAIN_DOZABLE,
10664                         1001 /* uid */, -1 /* rule */));
10665         assertThrows(expected,
10666                 () -> mCm.setUidFirewallRule(FIREWALL_CHAIN_DOZABLE,
10667                         1001 /* uid */, 100 /* rule */));
10668     }
10669 
10670     /**
10671      * Test mutable and requestable network capabilities such as
10672      * {@link NetworkCapabilities#NET_CAPABILITY_TRUSTED} and
10673      * {@link NetworkCapabilities#NET_CAPABILITY_NOT_VCN_MANAGED}. Verify that the
10674      * {@code ConnectivityService} re-assign the networks accordingly.
10675      */
10676     @Test
10677     public final void testLoseMutableAndRequestableCaps() throws Exception {
10678         final int[] testCaps = new int [] {
10679                 NET_CAPABILITY_TRUSTED,
10680                 NET_CAPABILITY_NOT_VCN_MANAGED
10681         };
10682         for (final int testCap : testCaps) {
10683             // Create requests with and without the testing capability.
10684             final TestNetworkCallback callbackWithCap = new TestNetworkCallback();
10685             final TestNetworkCallback callbackWithoutCap = new TestNetworkCallback();
10686             mCm.requestNetwork(new NetworkRequest.Builder().addCapability(testCap).build(),
10687                     callbackWithCap);
10688             mCm.requestNetwork(new NetworkRequest.Builder().removeCapability(testCap).build(),
10689                     callbackWithoutCap);
10690 
10691             // Setup networks with testing capability and verify the default network changes.
10692             mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
10693             mCellAgent.addCapability(testCap);
10694             mCellAgent.connect(true);
10695             callbackWithCap.expectAvailableThenValidatedCallbacks(mCellAgent);
10696             callbackWithoutCap.expectAvailableThenValidatedCallbacks(mCellAgent);
10697             verify(mMockNetd).networkSetDefault(eq(mCellAgent.getNetwork().netId));
10698             reset(mMockNetd);
10699 
10700             mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
10701             mWiFiAgent.addCapability(testCap);
10702             mWiFiAgent.connect(true);
10703             callbackWithCap.expectAvailableDoubleValidatedCallbacks(mWiFiAgent);
10704             callbackWithoutCap.expectAvailableDoubleValidatedCallbacks(mWiFiAgent);
10705             verify(mMockNetd).networkSetDefault(eq(mWiFiAgent.getNetwork().netId));
10706             reset(mMockNetd);
10707 
10708             // Remove the testing capability on wifi, verify the callback and default network
10709             // changes back to cellular.
10710             mWiFiAgent.removeCapability(testCap);
10711             callbackWithCap.expectAvailableCallbacksValidated(mCellAgent);
10712             callbackWithoutCap.expectCaps(mWiFiAgent, c -> !c.hasCapability(testCap));
10713             verify(mMockNetd).networkSetDefault(eq(mCellAgent.getNetwork().netId));
10714             reset(mMockNetd);
10715 
10716             mCellAgent.removeCapability(testCap);
10717             callbackWithCap.expect(LOST, mCellAgent);
10718             callbackWithoutCap.assertNoCallback();
10719             verify(mMockNetd).networkClearDefault();
10720 
10721             mCm.unregisterNetworkCallback(callbackWithCap);
10722             mCm.unregisterNetworkCallback(callbackWithoutCap);
10723         }
10724     }
10725 
10726     @Test
10727     public final void testBatteryStatsNetworkType() throws Exception {
10728         final LinkProperties cellLp = new LinkProperties();
10729         cellLp.setInterfaceName("cell0");
10730         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
10731         mCellAgent.connect(true);
10732         waitForIdle();
10733         final ArrayTrackRecord<ReportedInterfaces>.ReadHead readHead =
10734                 mDeps.mReportedInterfaceHistory.newReadHead();
10735         assertNotNull(readHead.poll(TIMEOUT_MS, ri -> ri.contentEquals(mServiceContext,
10736                 cellLp.getInterfaceName(),
10737                 new int[] { TRANSPORT_CELLULAR })));
10738 
10739         final LinkProperties wifiLp = new LinkProperties();
10740         wifiLp.setInterfaceName("wifi0");
10741         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp);
10742         mWiFiAgent.connect(true);
10743         waitForIdle();
10744         assertNotNull(readHead.poll(TIMEOUT_MS, ri -> ri.contentEquals(mServiceContext,
10745                 wifiLp.getInterfaceName(),
10746                 new int[] { TRANSPORT_WIFI })));
10747 
10748         mCellAgent.disconnect();
10749         mWiFiAgent.disconnect();
10750 
10751         cellLp.setInterfaceName("wifi0");
10752         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
10753         mCellAgent.connect(true);
10754         waitForIdle();
10755         assertNotNull(readHead.poll(TIMEOUT_MS, ri -> ri.contentEquals(mServiceContext,
10756                 cellLp.getInterfaceName(),
10757                 new int[] { TRANSPORT_CELLULAR })));
10758         mCellAgent.disconnect();
10759     }
10760 
10761     /**
10762      * Make simulated InterfaceConfigParcel for Nat464Xlat to query clat lower layer info.
10763      */
10764     private InterfaceConfigurationParcel getClatInterfaceConfigParcel(LinkAddress la) {
10765         final InterfaceConfigurationParcel cfg = new InterfaceConfigurationParcel();
10766         cfg.hwAddr = "11:22:33:44:55:66";
10767         cfg.ipv4Addr = la.getAddress().getHostAddress();
10768         cfg.prefixLength = la.getPrefixLength();
10769         return cfg;
10770     }
10771 
10772     /**
10773      * Make expected stack link properties, copied from Nat464Xlat.
10774      */
10775     private LinkProperties makeClatLinkProperties(LinkAddress la) {
10776         LinkAddress clatAddress = la;
10777         LinkProperties stacked = new LinkProperties();
10778         stacked.setInterfaceName(CLAT_MOBILE_IFNAME);
10779         RouteInfo ipv4Default = new RouteInfo(
10780                 new LinkAddress(Inet4Address.ANY, 0),
10781                 clatAddress.getAddress(), CLAT_MOBILE_IFNAME);
10782         stacked.addRoute(ipv4Default);
10783         stacked.addLinkAddress(clatAddress);
10784         return stacked;
10785     }
10786 
10787     private Nat64PrefixEventParcel makeNat64PrefixEvent(final int netId, final int prefixOperation,
10788             final String prefixAddress, final int prefixLength) {
10789         final Nat64PrefixEventParcel event = new Nat64PrefixEventParcel();
10790         event.netId = netId;
10791         event.prefixOperation = prefixOperation;
10792         event.prefixAddress = prefixAddress;
10793         event.prefixLength = prefixLength;
10794         return event;
10795     }
10796 
10797     private void verifyWakeupModifyInterface(String iface, boolean add) throws RemoteException {
10798         if (add) {
10799             verify(mMockNetd).wakeupAddInterface(eq(iface), anyString(), anyInt(),
10800                     anyInt());
10801         } else {
10802             verify(mMockNetd).wakeupDelInterface(eq(iface), anyString(), anyInt(),
10803                     anyInt());
10804         }
10805     }
10806 
10807     private <T> T verifyWithOrder(@Nullable InOrder inOrder, @NonNull T t) {
10808         if (inOrder != null) {
10809             return inOrder.verify(t);
10810         } else {
10811             // times(1) for consistency with the above. InOrder#verify always implies times(1).
10812             return verify(t, times(1));
10813         }
10814     }
10815 
10816     private <T> T verifyNeverWithOrder(@Nullable InOrder inOrder, @NonNull T t) {
10817         if (inOrder != null) {
10818             return inOrder.verify(t, never());
10819         } else {
10820             return verify(t, never());
10821         }
10822     }
10823 
10824     private void verifyClatdStart(@Nullable InOrder inOrder, @NonNull String iface, int netId,
10825             @NonNull String nat64Prefix) throws Exception {
10826         if (mDeps.isAtLeastT()) {
10827             verifyWithOrder(inOrder, mClatCoordinator)
10828                 .clatStart(eq(iface), eq(netId), eq(new IpPrefix(nat64Prefix)));
10829         } else {
10830             verifyWithOrder(inOrder, mMockNetd).clatdStart(eq(iface), eq(nat64Prefix));
10831         }
10832     }
10833 
10834     private void verifyNeverClatdStart(@Nullable InOrder inOrder, @NonNull String iface)
10835             throws Exception {
10836         if (mDeps.isAtLeastT()) {
10837             verifyNeverWithOrder(inOrder, mClatCoordinator).clatStart(eq(iface), anyInt(), any());
10838         } else {
10839             verifyNeverWithOrder(inOrder, mMockNetd).clatdStart(eq(iface), anyString());
10840         }
10841     }
10842 
10843     private void verifyClatdStop(@Nullable InOrder inOrder, @NonNull String iface)
10844             throws Exception {
10845         if (mDeps.isAtLeastT()) {
10846             verifyWithOrder(inOrder, mClatCoordinator).clatStop();
10847         } else {
10848             verifyWithOrder(inOrder, mMockNetd).clatdStop(eq(iface));
10849         }
10850     }
10851 
10852     private void verifyNeverClatdStop(@Nullable InOrder inOrder, @NonNull String iface)
10853             throws Exception {
10854         if (mDeps.isAtLeastT()) {
10855             verifyNeverWithOrder(inOrder, mClatCoordinator).clatStop();
10856         } else {
10857             verifyNeverWithOrder(inOrder, mMockNetd).clatdStop(eq(iface));
10858         }
10859     }
10860 
10861     private void expectNativeNetworkCreated(int netId, int permission, String iface,
10862             InOrder inOrder) throws Exception {
10863         verifyWithOrder(inOrder, mMockNetd).networkCreate(nativeNetworkConfigPhysical(netId,
10864                 permission));
10865         verifyWithOrder(inOrder, mMockDnsResolver).createNetworkCache(eq(netId));
10866         if (iface != null) {
10867             verifyWithOrder(inOrder, mMockNetd).networkAddInterface(netId, iface);
10868         }
10869     }
10870 
10871     private void expectNativeNetworkCreated(int netId, int permission, String iface)
10872             throws Exception {
10873         expectNativeNetworkCreated(netId, permission, iface, null /* inOrder */);
10874     }
10875 
10876     private int getIdleTimerLabel(int netId, int transportType) {
10877         return ConnectivityService.LegacyNetworkActivityTracker.getIdleTimerLabel(
10878                 mDeps.isAtLeastV(), netId, transportType);
10879     }
10880 
10881     @Test
10882     public void testStackedLinkProperties() throws Exception {
10883         final LinkAddress myIpv4 = new LinkAddress("1.2.3.4/24");
10884         final LinkAddress myIpv6 = new LinkAddress("2001:db8:1::1/64");
10885         final String kNat64PrefixString = "2001:db8:64:64:64:64::";
10886         final IpPrefix kNat64Prefix = new IpPrefix(InetAddress.getByName(kNat64PrefixString), 96);
10887         final String kOtherNat64PrefixString = "64:ff9b::";
10888         final IpPrefix kOtherNat64Prefix = new IpPrefix(
10889                 InetAddress.getByName(kOtherNat64PrefixString), 96);
10890         final RouteInfo ipv6Default =
10891                 new RouteInfo((IpPrefix) null, myIpv6.getAddress(), MOBILE_IFNAME);
10892         final RouteInfo ipv6Subnet = new RouteInfo(myIpv6, null, MOBILE_IFNAME);
10893         final RouteInfo ipv4Subnet = new RouteInfo(myIpv4, null, MOBILE_IFNAME);
10894         final RouteInfo stackedDefault =
10895                 new RouteInfo((IpPrefix) null, myIpv4.getAddress(), CLAT_MOBILE_IFNAME);
10896         final BaseNetdUnsolicitedEventListener netdUnsolicitedListener =
10897                 getRegisteredNetdUnsolicitedEventListener();
10898 
10899         final NetworkRequest networkRequest = new NetworkRequest.Builder()
10900                 .addTransportType(TRANSPORT_CELLULAR)
10901                 .addCapability(NET_CAPABILITY_INTERNET)
10902                 .build();
10903         final TestNetworkCallback networkCallback = new TestNetworkCallback();
10904         mCm.registerNetworkCallback(networkRequest, networkCallback);
10905 
10906         // Prepare ipv6 only link properties.
10907         final LinkProperties cellLp = new LinkProperties();
10908         cellLp.setInterfaceName(MOBILE_IFNAME);
10909         cellLp.addLinkAddress(myIpv6);
10910         cellLp.addRoute(ipv6Default);
10911         cellLp.addRoute(ipv6Subnet);
10912         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
10913         reset(mClatCoordinator);
10914 
10915         // Connect with ipv6 link properties. Expect prefix discovery to be started.
10916         mCellAgent.connect(true);
10917         int cellNetId = mCellAgent.getNetwork().netId;
10918         waitForIdle();
10919 
10920         expectNativeNetworkCreated(cellNetId, INetd.PERMISSION_NONE, MOBILE_IFNAME);
10921         assertRoutesAdded(cellNetId, ipv6Subnet, ipv6Default);
10922         final ArrayTrackRecord<ReportedInterfaces>.ReadHead readHead =
10923                 mDeps.mReportedInterfaceHistory.newReadHead();
10924         assertNotNull(readHead.poll(TIMEOUT_MS, ri -> ri.contentEquals(mServiceContext,
10925                 cellLp.getInterfaceName(),
10926                 new int[] { TRANSPORT_CELLULAR })));
10927 
10928         networkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
10929         verify(mMockDnsResolver, times(1)).startPrefix64Discovery(cellNetId);
10930 
10931         // Switching default network updates TCP buffer sizes.
10932         verifyTcpBufferSizeChange(ConnectivityService.DEFAULT_TCP_BUFFER_SIZES);
10933         // Add an IPv4 address. Expect prefix discovery to be stopped. Netd doesn't tell us that
10934         // the NAT64 prefix was removed because one was never discovered.
10935         cellLp.addLinkAddress(myIpv4);
10936         mCellAgent.sendLinkProperties(cellLp);
10937         networkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent);
10938         assertRoutesAdded(cellNetId, ipv4Subnet);
10939         verify(mMockDnsResolver, times(1)).stopPrefix64Discovery(cellNetId);
10940         verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(any());
10941 
10942         // Make sure BatteryStats was not told about any v4- interfaces, as none should have
10943         // come online yet.
10944         waitForIdle();
10945         assertNull(readHead.poll(0 /* timeout */, ri -> mServiceContext.equals(ri.context)
10946                 && ri.iface != null && ri.iface.startsWith("v4-")));
10947 
10948         verifyNoMoreInteractions(mMockNetd);
10949         verifyNoMoreInteractions(mClatCoordinator);
10950         verifyNoMoreInteractions(mMockDnsResolver);
10951         reset(mMockNetd);
10952         reset(mClatCoordinator);
10953         reset(mMockDnsResolver);
10954         doReturn(getClatInterfaceConfigParcel(myIpv4)).when(mMockNetd)
10955                 .interfaceGetCfg(CLAT_MOBILE_IFNAME);
10956 
10957         // Remove IPv4 address. Expect prefix discovery to be started again.
10958         cellLp.removeLinkAddress(myIpv4);
10959         mCellAgent.sendLinkProperties(cellLp);
10960         networkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent);
10961         verify(mMockDnsResolver, times(1)).startPrefix64Discovery(cellNetId);
10962         assertRoutesRemoved(cellNetId, ipv4Subnet);
10963 
10964         // When NAT64 prefix discovery succeeds, LinkProperties are updated and clatd is started.
10965         assertNull(mCm.getLinkProperties(mCellAgent.getNetwork()).getNat64Prefix());
10966         mService.mResolverUnsolEventCallback.onNat64PrefixEvent(
10967                 makeNat64PrefixEvent(cellNetId, PREFIX_OPERATION_ADDED, kNat64PrefixString, 96));
10968         LinkProperties lpBeforeClat = networkCallback.expect(
10969                 LINK_PROPERTIES_CHANGED, mCellAgent).getLp();
10970         assertEquals(0, lpBeforeClat.getStackedLinks().size());
10971         assertEquals(kNat64Prefix, lpBeforeClat.getNat64Prefix());
10972         verifyClatdStart(null /* inOrder */, MOBILE_IFNAME, cellNetId, kNat64Prefix.toString());
10973 
10974         // Clat iface comes up. Expect stacked link to be added.
10975         netdUnsolicitedListener.onInterfaceLinkStateChanged(
10976                 CLAT_MOBILE_IFNAME, true);
10977         networkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent);
10978         List<LinkProperties> stackedLps = mCm.getLinkProperties(mCellAgent.getNetwork())
10979                 .getStackedLinks();
10980         assertEquals(makeClatLinkProperties(myIpv4), stackedLps.get(0));
10981         assertRoutesAdded(cellNetId, stackedDefault);
10982         verify(mMockNetd, times(1)).networkAddInterface(cellNetId, CLAT_MOBILE_IFNAME);
10983         // Change trivial linkproperties and see if stacked link is preserved.
10984         cellLp.addDnsServer(InetAddress.getByName("8.8.8.8"));
10985         mCellAgent.sendLinkProperties(cellLp);
10986         networkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent);
10987 
10988         List<LinkProperties> stackedLpsAfterChange =
10989                 mCm.getLinkProperties(mCellAgent.getNetwork()).getStackedLinks();
10990         assertNotEquals(stackedLpsAfterChange, Collections.EMPTY_LIST);
10991         assertEquals(makeClatLinkProperties(myIpv4), stackedLpsAfterChange.get(0));
10992 
10993         verify(mMockDnsResolver, times(1)).setResolverConfiguration(
10994                 mResolverParamsParcelCaptor.capture());
10995         ResolverParamsParcel resolvrParams = mResolverParamsParcelCaptor.getValue();
10996         assertEquals(1, resolvrParams.servers.length);
10997         assertTrue(CollectionUtils.contains(resolvrParams.servers, "8.8.8.8"));
10998 
10999         for (final LinkProperties stackedLp : stackedLpsAfterChange) {
11000             assertNotNull(readHead.poll(TIMEOUT_MS, ri -> ri.contentEquals(mServiceContext,
11001                     stackedLp.getInterfaceName(),
11002                     new int[] { TRANSPORT_CELLULAR })));
11003         }
11004         reset(mMockNetd);
11005         reset(mClatCoordinator);
11006         doReturn(getClatInterfaceConfigParcel(myIpv4)).when(mMockNetd)
11007                 .interfaceGetCfg(CLAT_MOBILE_IFNAME);
11008         // Change the NAT64 prefix without first removing it.
11009         // Expect clatd to be stopped and started with the new prefix.
11010         mService.mResolverUnsolEventCallback.onNat64PrefixEvent(makeNat64PrefixEvent(
11011                 cellNetId, PREFIX_OPERATION_ADDED, kOtherNat64PrefixString, 96));
11012         networkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent,
11013                 cb -> cb.getLp().getStackedLinks().size() == 0);
11014         verifyClatdStop(null /* inOrder */, MOBILE_IFNAME);
11015         assertRoutesRemoved(cellNetId, stackedDefault);
11016         verify(mMockNetd, times(1)).networkRemoveInterface(cellNetId, CLAT_MOBILE_IFNAME);
11017 
11018         verifyClatdStart(null /* inOrder */, MOBILE_IFNAME, cellNetId,
11019                 kOtherNat64Prefix.toString());
11020         networkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent,
11021                 cb -> cb.getLp().getNat64Prefix().equals(kOtherNat64Prefix));
11022         netdUnsolicitedListener.onInterfaceLinkStateChanged(CLAT_MOBILE_IFNAME, true);
11023         networkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent,
11024                 cb -> cb.getLp().getStackedLinks().size() == 1);
11025         assertRoutesAdded(cellNetId, stackedDefault);
11026         verify(mMockNetd, times(1)).networkAddInterface(cellNetId, CLAT_MOBILE_IFNAME);
11027         reset(mMockNetd);
11028         reset(mClatCoordinator);
11029 
11030         // Add ipv4 address, expect that clatd and prefix discovery are stopped and stacked
11031         // linkproperties are cleaned up.
11032         cellLp.addLinkAddress(myIpv4);
11033         cellLp.addRoute(ipv4Subnet);
11034         mCellAgent.sendLinkProperties(cellLp);
11035         networkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent);
11036         assertRoutesAdded(cellNetId, ipv4Subnet);
11037         verifyClatdStop(null /* inOrder */, MOBILE_IFNAME);
11038         verify(mMockDnsResolver, times(1)).stopPrefix64Discovery(cellNetId);
11039 
11040         // As soon as stop is called, the linkproperties lose the stacked interface.
11041         networkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent);
11042         LinkProperties actualLpAfterIpv4 = mCm.getLinkProperties(mCellAgent.getNetwork());
11043         LinkProperties expected = new LinkProperties(cellLp);
11044         expected.setNat64Prefix(kOtherNat64Prefix);
11045         assertEquals(expected, actualLpAfterIpv4);
11046         assertEquals(0, actualLpAfterIpv4.getStackedLinks().size());
11047         assertRoutesRemoved(cellNetId, stackedDefault);
11048 
11049         // The interface removed callback happens but has no effect after stop is called.
11050         netdUnsolicitedListener.onInterfaceRemoved(CLAT_MOBILE_IFNAME);
11051         networkCallback.assertNoCallback();
11052         verify(mMockNetd, times(1)).networkRemoveInterface(cellNetId, CLAT_MOBILE_IFNAME);
11053 
11054         if (mDeps.isAtLeastU()) {
11055             verifyWakeupModifyInterface(CLAT_MOBILE_IFNAME, false);
11056         }
11057 
11058         verifyNoMoreInteractions(mMockNetd);
11059         verifyNoMoreInteractions(mClatCoordinator);
11060         verifyNoMoreInteractions(mMockDnsResolver);
11061         reset(mMockNetd);
11062         reset(mClatCoordinator);
11063         reset(mMockDnsResolver);
11064         doReturn(getClatInterfaceConfigParcel(myIpv4)).when(mMockNetd)
11065                 .interfaceGetCfg(CLAT_MOBILE_IFNAME);
11066 
11067         // Stopping prefix discovery causes netd to tell us that the NAT64 prefix is gone.
11068         mService.mResolverUnsolEventCallback.onNat64PrefixEvent(makeNat64PrefixEvent(
11069                 cellNetId, PREFIX_OPERATION_REMOVED, kOtherNat64PrefixString, 96));
11070         networkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent,
11071                 cb -> cb.getLp().getNat64Prefix() == null);
11072 
11073         // Remove IPv4 address and expect prefix discovery and clatd to be started again.
11074         cellLp.removeLinkAddress(myIpv4);
11075         cellLp.removeRoute(new RouteInfo(myIpv4, null, MOBILE_IFNAME));
11076         cellLp.removeDnsServer(InetAddress.getByName("8.8.8.8"));
11077         mCellAgent.sendLinkProperties(cellLp);
11078         networkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent);
11079         assertRoutesRemoved(cellNetId, ipv4Subnet);  // Directly-connected routes auto-added.
11080         verify(mMockDnsResolver, times(1)).startPrefix64Discovery(cellNetId);
11081         mService.mResolverUnsolEventCallback.onNat64PrefixEvent(makeNat64PrefixEvent(
11082                 cellNetId, PREFIX_OPERATION_ADDED, kNat64PrefixString, 96));
11083         networkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent);
11084         verifyClatdStart(null /* inOrder */, MOBILE_IFNAME, cellNetId, kNat64Prefix.toString());
11085 
11086         // Clat iface comes up. Expect stacked link to be added.
11087         netdUnsolicitedListener.onInterfaceLinkStateChanged(CLAT_MOBILE_IFNAME, true);
11088         networkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent,
11089                 cb -> cb.getLp().getStackedLinks().size() == 1
11090                         && cb.getLp().getNat64Prefix() != null);
11091         assertRoutesAdded(cellNetId, stackedDefault);
11092         verify(mMockNetd, times(1)).networkAddInterface(cellNetId, CLAT_MOBILE_IFNAME);
11093 
11094         if (mDeps.isAtLeastU()) {
11095             verifyWakeupModifyInterface(CLAT_MOBILE_IFNAME, true);
11096         }
11097 
11098         // NAT64 prefix is removed. Expect that clat is stopped.
11099         mService.mResolverUnsolEventCallback.onNat64PrefixEvent(makeNat64PrefixEvent(
11100                 cellNetId, PREFIX_OPERATION_REMOVED, kNat64PrefixString, 96));
11101         networkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent,
11102                 cb -> cb.getLp().getStackedLinks().size() == 0
11103                         && cb.getLp().getNat64Prefix() == null);
11104         assertRoutesRemoved(cellNetId, ipv4Subnet, stackedDefault);
11105 
11106         // Stop has no effect because clat is already stopped.
11107         verifyClatdStop(null /* inOrder */, MOBILE_IFNAME);
11108         networkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent,
11109                 cb -> cb.getLp().getStackedLinks().size() == 0);
11110         verify(mMockNetd, times(1)).networkRemoveInterface(cellNetId, CLAT_MOBILE_IFNAME);
11111         verify(mMockNetd, times(1)).interfaceGetCfg(CLAT_MOBILE_IFNAME);
11112 
11113         if (mDeps.isAtLeastU()) {
11114             verifyWakeupModifyInterface(CLAT_MOBILE_IFNAME, false);
11115         }
11116 
11117         // Clean up.
11118         mCellAgent.disconnect();
11119         networkCallback.expect(LOST, mCellAgent);
11120         networkCallback.assertNoCallback();
11121         verify(mMockNetd, times(1)).idletimerRemoveInterface(eq(MOBILE_IFNAME), anyInt(),
11122                 eq(Integer.toString(getIdleTimerLabel(cellNetId, TRANSPORT_CELLULAR))));
11123         verify(mMockNetd).networkDestroy(cellNetId);
11124         if (mDeps.isAtLeastU()) {
11125             verify(mMockNetd).setNetworkAllowlist(any());
11126         } else {
11127             verify(mMockNetd, never()).setNetworkAllowlist(any());
11128         }
11129 
11130         if (mDeps.isAtLeastU()) {
11131             verifyWakeupModifyInterface(MOBILE_IFNAME, false);
11132         }
11133 
11134         verifyNoMoreInteractions(mMockNetd);
11135         verifyNoMoreInteractions(mClatCoordinator);
11136         reset(mMockNetd);
11137         reset(mClatCoordinator);
11138 
11139         // Test disconnecting a network that is running 464xlat.
11140 
11141         // Connect a network with a NAT64 prefix.
11142         doReturn(getClatInterfaceConfigParcel(myIpv4)).when(mMockNetd)
11143                 .interfaceGetCfg(CLAT_MOBILE_IFNAME);
11144         cellLp.setNat64Prefix(kNat64Prefix);
11145         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
11146         mCellAgent.connect(false /* validated */);
11147         networkCallback.expectAvailableCallbacksUnvalidated(mCellAgent);
11148         cellNetId = mCellAgent.getNetwork().netId;
11149         verify(mMockNetd, times(1)).networkCreate(nativeNetworkConfigPhysical(cellNetId,
11150                 INetd.PERMISSION_NONE));
11151         assertRoutesAdded(cellNetId, ipv6Subnet, ipv6Default);
11152 
11153         // Clatd is started and clat iface comes up. Expect stacked link to be added.
11154         verifyClatdStart(null /* inOrder */, MOBILE_IFNAME, cellNetId, kNat64Prefix.toString());
11155         netdUnsolicitedListener.onInterfaceLinkStateChanged(CLAT_MOBILE_IFNAME, true /* up */);
11156         networkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent,
11157                 cb -> cb.getLp().getStackedLinks().size() == 1
11158                         && cb.getLp().getNat64Prefix().equals(kNat64Prefix));
11159         verify(mMockNetd).networkAddInterface(cellNetId, CLAT_MOBILE_IFNAME);
11160         // assertRoutesAdded sees all calls since last mMockNetd reset, so expect IPv6 routes again.
11161         assertRoutesAdded(cellNetId, ipv6Subnet, ipv6Default, stackedDefault);
11162 
11163         if (mDeps.isAtLeastU()) {
11164             verifyWakeupModifyInterface(MOBILE_IFNAME, true);
11165         }
11166 
11167         reset(mMockNetd);
11168         reset(mClatCoordinator);
11169 
11170         // Disconnect the network. clat is stopped and the network is destroyed.
11171         mCellAgent.disconnect();
11172         networkCallback.expect(LOST, mCellAgent);
11173         networkCallback.assertNoCallback();
11174         verifyClatdStop(null /* inOrder */, MOBILE_IFNAME);
11175 
11176         if (mDeps.isAtLeastU()) {
11177             verifyWakeupModifyInterface(CLAT_MOBILE_IFNAME, false);
11178         }
11179 
11180         verify(mMockNetd).idletimerRemoveInterface(eq(MOBILE_IFNAME), anyInt(),
11181                 eq(Integer.toString(getIdleTimerLabel(cellNetId, TRANSPORT_CELLULAR))));
11182         verify(mMockNetd).networkDestroy(cellNetId);
11183         if (mDeps.isAtLeastU()) {
11184             verify(mMockNetd).setNetworkAllowlist(any());
11185         } else {
11186             verify(mMockNetd, never()).setNetworkAllowlist(any());
11187         }
11188 
11189         if (mDeps.isAtLeastU()) {
11190             verifyWakeupModifyInterface(MOBILE_IFNAME, false);
11191         }
11192 
11193         verifyNoMoreInteractions(mMockNetd);
11194         verifyNoMoreInteractions(mClatCoordinator);
11195 
11196         mCm.unregisterNetworkCallback(networkCallback);
11197     }
11198 
11199     private void expectNat64PrefixChange(TestNetworkCallback callback,
11200             TestNetworkAgentWrapper agent, IpPrefix prefix) {
11201         callback.expect(LINK_PROPERTIES_CHANGED, agent,
11202                 x -> Objects.equals(x.getLp().getNat64Prefix(), prefix));
11203     }
11204 
11205     @Test
11206     public void testNat64PrefixMultipleSources() throws Exception {
11207         final String iface = "wlan0";
11208         final String pref64FromRaStr = "64:ff9b::";
11209         final String pref64FromDnsStr = "2001:db8:64::";
11210         final IpPrefix pref64FromRa = new IpPrefix(InetAddress.getByName(pref64FromRaStr), 96);
11211         final IpPrefix pref64FromDns = new IpPrefix(InetAddress.getByName(pref64FromDnsStr), 96);
11212         final IpPrefix newPref64FromRa = new IpPrefix("2001:db8:64:64:64:64::/96");
11213 
11214         final NetworkRequest request = new NetworkRequest.Builder()
11215                 .addCapability(NET_CAPABILITY_INTERNET)
11216                 .build();
11217         final TestNetworkCallback callback = new TestNetworkCallback();
11218         mCm.registerNetworkCallback(request, callback);
11219 
11220         final LinkProperties baseLp = new LinkProperties();
11221         baseLp.setInterfaceName(iface);
11222         baseLp.addLinkAddress(new LinkAddress("2001:db8:1::1/64"));
11223         baseLp.addDnsServer(InetAddress.getByName("2001:4860:4860::6464"));
11224 
11225         reset(mMockNetd, mMockDnsResolver);
11226         InOrder inOrder = inOrder(mMockNetd, mMockDnsResolver, mClatCoordinator);
11227 
11228         // If a network already has a NAT64 prefix on connect, clatd is started immediately and
11229         // prefix discovery is never started.
11230         LinkProperties lp = new LinkProperties(baseLp);
11231         lp.setNat64Prefix(pref64FromRa);
11232         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, lp);
11233         mWiFiAgent.connect(false);
11234         final Network network = mWiFiAgent.getNetwork();
11235         int netId = network.getNetId();
11236         callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
11237         verifyClatdStart(inOrder, iface, netId, pref64FromRa.toString());
11238         inOrder.verify(mMockDnsResolver).setPrefix64(netId, pref64FromRa.toString());
11239         inOrder.verify(mMockDnsResolver, never()).startPrefix64Discovery(netId);
11240         callback.assertNoCallback();
11241         assertEquals(pref64FromRa, mCm.getLinkProperties(network).getNat64Prefix());
11242 
11243         // If the RA prefix is withdrawn, clatd is stopped and prefix discovery is started.
11244         lp.setNat64Prefix(null);
11245         mWiFiAgent.sendLinkProperties(lp);
11246         expectNat64PrefixChange(callback, mWiFiAgent, null);
11247         verifyClatdStop(inOrder, iface);
11248         inOrder.verify(mMockDnsResolver).setPrefix64(netId, "");
11249         inOrder.verify(mMockDnsResolver).startPrefix64Discovery(netId);
11250 
11251         // If the RA prefix appears while DNS discovery is in progress, discovery is stopped and
11252         // clatd is started with the prefix from the RA.
11253         lp.setNat64Prefix(pref64FromRa);
11254         mWiFiAgent.sendLinkProperties(lp);
11255         expectNat64PrefixChange(callback, mWiFiAgent, pref64FromRa);
11256         verifyClatdStart(inOrder, iface, netId, pref64FromRa.toString());
11257         inOrder.verify(mMockDnsResolver).stopPrefix64Discovery(netId);
11258         inOrder.verify(mMockDnsResolver).setPrefix64(netId, pref64FromRa.toString());
11259 
11260         // Withdraw the RA prefix so we can test the case where an RA prefix appears after DNS
11261         // discovery has succeeded.
11262         lp.setNat64Prefix(null);
11263         mWiFiAgent.sendLinkProperties(lp);
11264         expectNat64PrefixChange(callback, mWiFiAgent, null);
11265         verifyClatdStop(inOrder, iface);
11266         inOrder.verify(mMockDnsResolver).setPrefix64(netId, "");
11267         inOrder.verify(mMockDnsResolver).startPrefix64Discovery(netId);
11268 
11269         mService.mResolverUnsolEventCallback.onNat64PrefixEvent(
11270                 makeNat64PrefixEvent(netId, PREFIX_OPERATION_ADDED, pref64FromDnsStr, 96));
11271         expectNat64PrefixChange(callback, mWiFiAgent, pref64FromDns);
11272         verifyClatdStart(inOrder, iface, netId, pref64FromDns.toString());
11273 
11274         // If an RA advertises the same prefix that was discovered by DNS, nothing happens: prefix
11275         // discovery is not stopped, and there are no callbacks.
11276         lp.setNat64Prefix(pref64FromDns);
11277         mWiFiAgent.sendLinkProperties(lp);
11278         callback.assertNoCallback();
11279         verifyNeverClatdStop(inOrder, iface);
11280         verifyNeverClatdStart(inOrder, iface);
11281         inOrder.verify(mMockDnsResolver, never()).stopPrefix64Discovery(netId);
11282         inOrder.verify(mMockDnsResolver, never()).startPrefix64Discovery(netId);
11283         inOrder.verify(mMockDnsResolver, never()).setPrefix64(eq(netId), anyString());
11284 
11285         // If the RA is later withdrawn, nothing happens again.
11286         lp.setNat64Prefix(null);
11287         mWiFiAgent.sendLinkProperties(lp);
11288         callback.assertNoCallback();
11289         verifyNeverClatdStop(inOrder, iface);
11290         verifyNeverClatdStart(inOrder, iface);
11291         inOrder.verify(mMockDnsResolver, never()).stopPrefix64Discovery(netId);
11292         inOrder.verify(mMockDnsResolver, never()).startPrefix64Discovery(netId);
11293         inOrder.verify(mMockDnsResolver, never()).setPrefix64(eq(netId), anyString());
11294 
11295         // If the RA prefix changes, clatd is restarted and prefix discovery is stopped.
11296         lp.setNat64Prefix(pref64FromRa);
11297         mWiFiAgent.sendLinkProperties(lp);
11298         expectNat64PrefixChange(callback, mWiFiAgent, pref64FromRa);
11299         verifyClatdStop(inOrder, iface);
11300         inOrder.verify(mMockDnsResolver).stopPrefix64Discovery(netId);
11301 
11302         // Stopping prefix discovery results in a prefix removed notification.
11303         mService.mResolverUnsolEventCallback.onNat64PrefixEvent(
11304                 makeNat64PrefixEvent(netId, PREFIX_OPERATION_REMOVED, pref64FromDnsStr, 96));
11305 
11306         verifyClatdStart(inOrder, iface, netId, pref64FromRa.toString());
11307         inOrder.verify(mMockDnsResolver).setPrefix64(netId, pref64FromRa.toString());
11308         inOrder.verify(mMockDnsResolver, never()).startPrefix64Discovery(netId);
11309 
11310         // If the RA prefix changes, clatd is restarted and prefix discovery is not started.
11311         lp.setNat64Prefix(newPref64FromRa);
11312         mWiFiAgent.sendLinkProperties(lp);
11313         expectNat64PrefixChange(callback, mWiFiAgent, newPref64FromRa);
11314         verifyClatdStop(inOrder, iface);
11315         inOrder.verify(mMockDnsResolver).setPrefix64(netId, "");
11316         verifyClatdStart(inOrder, iface, netId, newPref64FromRa.toString());
11317         inOrder.verify(mMockDnsResolver).setPrefix64(netId, newPref64FromRa.toString());
11318         inOrder.verify(mMockDnsResolver, never()).stopPrefix64Discovery(netId);
11319         inOrder.verify(mMockDnsResolver, never()).startPrefix64Discovery(netId);
11320 
11321         // If the RA prefix changes to the same value, nothing happens.
11322         lp.setNat64Prefix(newPref64FromRa);
11323         mWiFiAgent.sendLinkProperties(lp);
11324         callback.assertNoCallback();
11325         assertEquals(newPref64FromRa, mCm.getLinkProperties(network).getNat64Prefix());
11326         verifyNeverClatdStop(inOrder, iface);
11327         verifyNeverClatdStart(inOrder, iface);
11328         inOrder.verify(mMockDnsResolver, never()).stopPrefix64Discovery(netId);
11329         inOrder.verify(mMockDnsResolver, never()).startPrefix64Discovery(netId);
11330         inOrder.verify(mMockDnsResolver, never()).setPrefix64(eq(netId), anyString());
11331 
11332         // The transition between no prefix and DNS prefix is tested in testStackedLinkProperties.
11333 
11334         // If the same prefix is learned first by DNS and then by RA, and clat is later stopped,
11335         // (e.g., because the network disconnects) setPrefix64(netid, "") is never called.
11336         lp.setNat64Prefix(null);
11337         mWiFiAgent.sendLinkProperties(lp);
11338         expectNat64PrefixChange(callback, mWiFiAgent, null);
11339         verifyClatdStop(inOrder, iface);
11340         inOrder.verify(mMockDnsResolver).setPrefix64(netId, "");
11341         inOrder.verify(mMockDnsResolver).startPrefix64Discovery(netId);
11342         mService.mResolverUnsolEventCallback.onNat64PrefixEvent(
11343                 makeNat64PrefixEvent(netId, PREFIX_OPERATION_ADDED, pref64FromDnsStr, 96));
11344         expectNat64PrefixChange(callback, mWiFiAgent, pref64FromDns);
11345         verifyClatdStart(inOrder, iface, netId, pref64FromDns.toString());
11346         inOrder.verify(mMockDnsResolver, never()).setPrefix64(eq(netId), any());
11347 
11348         lp.setNat64Prefix(pref64FromDns);
11349         mWiFiAgent.sendLinkProperties(lp);
11350         callback.assertNoCallback();
11351         verifyNeverClatdStop(inOrder, iface);
11352         verifyNeverClatdStart(inOrder, iface);
11353         inOrder.verify(mMockDnsResolver, never()).stopPrefix64Discovery(netId);
11354         inOrder.verify(mMockDnsResolver, never()).startPrefix64Discovery(netId);
11355         inOrder.verify(mMockDnsResolver, never()).setPrefix64(eq(netId), anyString());
11356 
11357         // When tearing down a network, clat state is only updated after CALLBACK_LOST is fired, but
11358         // before CONNECTIVITY_ACTION is sent. Wait for CONNECTIVITY_ACTION before verifying that
11359         // clat has been stopped, or the test will be flaky.
11360         ExpectedBroadcast b = expectConnectivityAction(TYPE_WIFI, DetailedState.DISCONNECTED);
11361         mWiFiAgent.disconnect();
11362         callback.expect(LOST, mWiFiAgent);
11363         b.expectBroadcast();
11364 
11365         verifyClatdStop(inOrder, iface);
11366         inOrder.verify(mMockDnsResolver).stopPrefix64Discovery(netId);
11367         inOrder.verify(mMockDnsResolver, never()).setPrefix64(eq(netId), anyString());
11368 
11369         mCm.unregisterNetworkCallback(callback);
11370     }
11371 
11372     @Test
11373     public void testWith464XlatDisable() throws Exception {
11374         mDeps.setCellular464XlatEnabled(false);
11375 
11376         final TestNetworkCallback callback = new TestNetworkCallback();
11377         final TestNetworkCallback defaultCallback = new TestNetworkCallback();
11378         final NetworkRequest networkRequest = new NetworkRequest.Builder()
11379                 .addCapability(NET_CAPABILITY_INTERNET)
11380                 .build();
11381         mCm.registerNetworkCallback(networkRequest, callback);
11382         mCm.registerDefaultNetworkCallback(defaultCallback);
11383 
11384         // Bring up validated cell.
11385         final LinkProperties cellLp = new LinkProperties();
11386         cellLp.setInterfaceName(MOBILE_IFNAME);
11387         cellLp.addLinkAddress(new LinkAddress("2001:db8:1::1/64"));
11388         cellLp.addRoute(new RouteInfo(new IpPrefix("::/0"), null, MOBILE_IFNAME));
11389         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
11390 
11391         mCellAgent.sendLinkProperties(cellLp);
11392         mCellAgent.connect(true);
11393         callback.expectAvailableThenValidatedCallbacks(mCellAgent);
11394         defaultCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
11395         final int cellNetId = mCellAgent.getNetwork().netId;
11396         waitForIdle();
11397 
11398         verify(mMockDnsResolver, never()).startPrefix64Discovery(cellNetId);
11399         Nat464Xlat clat = getNat464Xlat(mCellAgent);
11400         assertTrue("Nat464Xlat was not IDLE", !clat.isStarted());
11401 
11402         // This cannot happen because prefix discovery cannot succeed if it is never started.
11403         mService.mResolverUnsolEventCallback.onNat64PrefixEvent(
11404                 makeNat64PrefixEvent(cellNetId, PREFIX_OPERATION_ADDED, "64:ff9b::", 96));
11405 
11406         // ... but still, check that even if it did, clatd would not be started.
11407         verify(mMockNetd, never()).clatdStart(anyString(), anyString());
11408         assertTrue("Nat464Xlat was not IDLE", !clat.isStarted());
11409     }
11410 
11411     final String transportToTestIfaceName(int transport) {
11412         switch (transport) {
11413             case TRANSPORT_WIFI:
11414                 return WIFI_IFNAME;
11415             case TRANSPORT_CELLULAR:
11416                 return MOBILE_IFNAME;
11417             case TRANSPORT_ETHERNET:
11418                 return ETHERNET_IFNAME;
11419             default:
11420                 throw new AssertionError("Unsupported transport type");
11421         }
11422     }
11423 
11424     private void doTestInterfaceClassActivityChanged(final int transportType) throws Exception {
11425         final BaseNetdUnsolicitedEventListener netdUnsolicitedEventListener =
11426                 getRegisteredNetdUnsolicitedEventListener();
11427 
11428         final int legacyType = transportToLegacyType(transportType);
11429         final LinkProperties lp = new LinkProperties();
11430         lp.setInterfaceName(transportToTestIfaceName(transportType));
11431         final TestNetworkAgentWrapper agent = new TestNetworkAgentWrapper(transportType, lp);
11432 
11433         final ConditionVariable onNetworkActiveCv = new ConditionVariable();
11434         final ConnectivityManager.OnNetworkActiveListener listener = onNetworkActiveCv::open;
11435 
11436         TestNetworkCallback defaultCallback = new TestNetworkCallback();
11437 
11438         testAndCleanup(() -> {
11439             mCm.registerDefaultNetworkCallback(defaultCallback);
11440             agent.connect(true);
11441             defaultCallback.expectAvailableThenValidatedCallbacks(agent);
11442             if (transportType == TRANSPORT_CELLULAR) {
11443                 verify(mIBatteryStats).noteMobileRadioPowerState(eq(DC_POWER_STATE_HIGH),
11444                         anyLong() /* timestampNs */, eq(NETWORK_ACTIVITY_NO_UID));
11445             } else if (transportType == TRANSPORT_WIFI) {
11446                 verify(mIBatteryStats).noteWifiRadioPowerState(eq(DC_POWER_STATE_HIGH),
11447                         anyLong() /* timestampNs */, eq(NETWORK_ACTIVITY_NO_UID));
11448             }
11449             clearInvocations(mIBatteryStats);
11450             final int idleTimerLabel = getIdleTimerLabel(agent.getNetwork().netId, transportType);
11451 
11452             // Network is considered active when the network becomes the default network.
11453             assertTrue(mCm.isDefaultNetworkActive());
11454 
11455             mCm.addDefaultNetworkActiveListener(listener);
11456 
11457             // Interface goes to inactive state
11458             netdUnsolicitedEventListener.onInterfaceClassActivityChanged(false /* isActive */,
11459                     idleTimerLabel, TIMESTAMP, NETWORK_ACTIVITY_NO_UID);
11460             mServiceContext.expectDataActivityBroadcast(legacyType, false /* isActive */,
11461                     TIMESTAMP);
11462             assertFalse(onNetworkActiveCv.block(TEST_CALLBACK_TIMEOUT_MS));
11463             assertFalse(mCm.isDefaultNetworkActive());
11464             if (mDeps.isAtLeastV()) {
11465                 if (transportType == TRANSPORT_CELLULAR) {
11466                     verify(mIBatteryStats).noteMobileRadioPowerState(eq(DC_POWER_STATE_LOW),
11467                             anyLong() /* timestampNs */, eq(NETWORK_ACTIVITY_NO_UID));
11468                 } else if (transportType == TRANSPORT_WIFI) {
11469                     verify(mIBatteryStats).noteWifiRadioPowerState(eq(DC_POWER_STATE_LOW),
11470                             anyLong() /* timestampNs */, eq(NETWORK_ACTIVITY_NO_UID));
11471                 }
11472             } else {
11473                 // If TrackMultiNetworks is disabled, LegacyNetworkActivityTracker does not call
11474                 // BatteryStats API by the netd activity change callback since BatteryStatsService
11475                 // listen to netd callback via NetworkManagementService and update battery stats by
11476                 // itself.
11477                 verify(mIBatteryStats, never())
11478                         .noteMobileRadioPowerState(anyInt(), anyLong(), anyInt());
11479                 verify(mIBatteryStats, never())
11480                         .noteWifiRadioPowerState(anyInt(), anyLong(), anyInt());
11481             }
11482 
11483             // Interface goes to active state
11484             netdUnsolicitedEventListener.onInterfaceClassActivityChanged(true /* isActive */,
11485                     idleTimerLabel, TIMESTAMP, TEST_PACKAGE_UID);
11486             mServiceContext.expectDataActivityBroadcast(legacyType, true /* isActive */, TIMESTAMP);
11487             assertTrue(onNetworkActiveCv.block(TEST_CALLBACK_TIMEOUT_MS));
11488             assertTrue(mCm.isDefaultNetworkActive());
11489             if (mDeps.isAtLeastV()) {
11490                 if (transportType == TRANSPORT_CELLULAR) {
11491                     verify(mIBatteryStats).noteMobileRadioPowerState(eq(DC_POWER_STATE_HIGH),
11492                             anyLong() /* timestampNs */, eq(TEST_PACKAGE_UID));
11493                 } else if (transportType == TRANSPORT_WIFI) {
11494                     verify(mIBatteryStats).noteWifiRadioPowerState(eq(DC_POWER_STATE_HIGH),
11495                             anyLong() /* timestampNs */, eq(TEST_PACKAGE_UID));
11496                 }
11497             } else {
11498                 // If TrackMultiNetworks is disabled, LegacyNetworkActivityTracker does not call
11499                 // BatteryStats API by the netd activity change callback since BatteryStatsService
11500                 // listen to netd callback via NetworkManagementService and update battery stats by
11501                 // itself.
11502                 verify(mIBatteryStats, never())
11503                         .noteMobileRadioPowerState(anyInt(), anyLong(), anyInt());
11504                 verify(mIBatteryStats, never())
11505                         .noteWifiRadioPowerState(anyInt(), anyLong(), anyInt());
11506             }
11507         }, () -> { // Cleanup
11508                 mCm.unregisterNetworkCallback(defaultCallback);
11509             }, () -> { // Cleanup
11510                 mCm.removeDefaultNetworkActiveListener(listener);
11511             }, () -> { // Cleanup
11512                 agent.disconnect();
11513             });
11514     }
11515 
11516     @Test
11517     public void testInterfaceClassActivityChangedWifi() throws Exception {
11518         doTestInterfaceClassActivityChanged(TRANSPORT_WIFI);
11519     }
11520 
11521     @Test
11522     public void testInterfaceClassActivityChangedCellular() throws Exception {
11523         doTestInterfaceClassActivityChanged(TRANSPORT_CELLULAR);
11524     }
11525 
11526     private void doTestOnNetworkActive_NewNetworkConnects(int transportType, boolean expectCapChanged)
11527             throws Exception {
11528         final ConditionVariable onNetworkActiveCv = new ConditionVariable();
11529         final ConnectivityManager.OnNetworkActiveListener listener = onNetworkActiveCv::open;
11530 
11531         final LinkProperties lp = new LinkProperties();
11532         lp.setInterfaceName(transportToTestIfaceName(transportType));
11533         final TestNetworkAgentWrapper agent = new TestNetworkAgentWrapper(transportType, lp);
11534 
11535         testAndCleanup(() -> {
11536             mCm.addDefaultNetworkActiveListener(listener);
11537             agent.connect(true);
11538             if (expectCapChanged) {
11539                 assertTrue(onNetworkActiveCv.block(TEST_CALLBACK_TIMEOUT_MS));
11540             } else {
11541                 assertFalse(onNetworkActiveCv.block(TEST_CALLBACK_TIMEOUT_MS));
11542             }
11543             assertTrue(mCm.isDefaultNetworkActive());
11544         }, () -> { // Cleanup
11545                 mCm.removeDefaultNetworkActiveListener(listener);
11546             }, () -> { // Cleanup
11547                 agent.disconnect();
11548             });
11549     }
11550 
11551     @Test
11552     public void testOnNetworkActive_NewCellConnects_CallbackCalled() throws Exception {
11553         doTestOnNetworkActive_NewNetworkConnects(TRANSPORT_CELLULAR, true /* expectCapChanged */);
11554     }
11555 
11556     @Test
11557     public void testOnNetworkActive_NewEthernetConnects_Callback() throws Exception {
11558         // On pre-V devices, LegacyNetworkActivityTracker calls onNetworkActive callback only for
11559         // networks that tracker adds the idle timer to. And the tracker does not set the idle timer
11560         // for the ethernet network.
11561         // So onNetworkActive is not called when the ethernet becomes the default network
11562         final boolean expectCapChanged = mDeps.isAtLeastV();
11563         doTestOnNetworkActive_NewNetworkConnects(TRANSPORT_ETHERNET, expectCapChanged);
11564     }
11565 
11566     @Test
11567     public void testIsDefaultNetworkActiveNoDefaultNetwork() throws Exception {
11568         // isDefaultNetworkActive returns true if there is no default network, which is known issue.
11569         assertTrue(mCm.isDefaultNetworkActive());
11570 
11571         final LinkProperties cellLp = new LinkProperties();
11572         cellLp.setInterfaceName(MOBILE_IFNAME);
11573         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
11574         mCellAgent.connect(true);
11575         // Network is considered active when the network becomes the default network.
11576         assertTrue(mCm.isDefaultNetworkActive());
11577 
11578         mCellAgent.disconnect();
11579         waitForIdle();
11580 
11581         assertTrue(mCm.isDefaultNetworkActive());
11582     }
11583 
11584     @Test
11585     public void testDataActivityTracking() throws Exception {
11586         final TestNetworkCallback networkCallback = new TestNetworkCallback();
11587         final NetworkRequest networkRequest = new NetworkRequest.Builder()
11588                 .addCapability(NET_CAPABILITY_INTERNET)
11589                 .build();
11590         mCm.registerNetworkCallback(networkRequest, networkCallback);
11591 
11592         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
11593         final String cellIdleTimerLabel = Integer.toString(getIdleTimerLabel(
11594                 mCellAgent.getNetwork().netId, TRANSPORT_CELLULAR));
11595         final LinkProperties cellLp = new LinkProperties();
11596         cellLp.setInterfaceName(MOBILE_IFNAME);
11597         mCellAgent.sendLinkProperties(cellLp);
11598         mCellAgent.connect(true);
11599         networkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
11600         verify(mMockNetd, times(1)).idletimerAddInterface(eq(MOBILE_IFNAME), anyInt(),
11601                 eq(cellIdleTimerLabel));
11602 
11603         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
11604         String wifiIdleTimerLabel = Integer.toString(getIdleTimerLabel(
11605                 mWiFiAgent.getNetwork().netId, TRANSPORT_WIFI));
11606         final LinkProperties wifiLp = new LinkProperties();
11607         wifiLp.setInterfaceName(WIFI_IFNAME);
11608         mWiFiAgent.sendLinkProperties(wifiLp);
11609 
11610         // Network switch
11611         mWiFiAgent.connect(true);
11612         networkCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
11613         networkCallback.expectLosing(mCellAgent);
11614         networkCallback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
11615         verify(mMockNetd, times(1)).idletimerAddInterface(eq(WIFI_IFNAME), anyInt(),
11616                 eq(wifiIdleTimerLabel));
11617         if (mDeps.isAtLeastV()) {
11618             // V+ devices add idleTimer when the network is first connected and remove when the
11619             // network is disconnected.
11620             verify(mMockNetd, never()).idletimerRemoveInterface(eq(MOBILE_IFNAME), anyInt(),
11621                     eq(Integer.toString(mCellAgent.getNetwork().netId)));
11622         } else {
11623             // pre V devices add idleTimer when the network becomes the default network and remove
11624             // when the network becomes no longer the default network.
11625             verify(mMockNetd, times(1)).idletimerRemoveInterface(eq(MOBILE_IFNAME), anyInt(),
11626                     eq(Integer.toString(TRANSPORT_CELLULAR)));
11627         }
11628 
11629         // Disconnect wifi and switch back to cell
11630         reset(mMockNetd);
11631         mWiFiAgent.disconnect();
11632         networkCallback.expect(LOST, mWiFiAgent);
11633         assertNoCallbacks(networkCallback);
11634         verify(mMockNetd, times(1)).idletimerRemoveInterface(eq(WIFI_IFNAME), anyInt(),
11635                 eq(wifiIdleTimerLabel));
11636         if (mDeps.isAtLeastV()) {
11637             verify(mMockNetd, never()).idletimerAddInterface(eq(MOBILE_IFNAME), anyInt(),
11638                     eq(Integer.toString(mCellAgent.getNetwork().netId)));
11639         } else {
11640             verify(mMockNetd, times(1)).idletimerAddInterface(eq(MOBILE_IFNAME), anyInt(),
11641                     eq(Integer.toString(TRANSPORT_CELLULAR)));
11642         }
11643 
11644         // reconnect wifi
11645         reset(mMockNetd);
11646         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
11647         wifiIdleTimerLabel = Integer.toString(getIdleTimerLabel(
11648                 mWiFiAgent.getNetwork().netId, TRANSPORT_WIFI));
11649         wifiLp.setInterfaceName(WIFI_IFNAME);
11650         mWiFiAgent.sendLinkProperties(wifiLp);
11651         mWiFiAgent.connect(true);
11652         networkCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
11653         networkCallback.expectLosing(mCellAgent);
11654         networkCallback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
11655         verify(mMockNetd, times(1)).idletimerAddInterface(eq(WIFI_IFNAME), anyInt(),
11656                 eq(wifiIdleTimerLabel));
11657         if (mDeps.isAtLeastV()) {
11658             verify(mMockNetd, never()).idletimerRemoveInterface(eq(MOBILE_IFNAME), anyInt(),
11659                     eq(Integer.toString(mCellAgent.getNetwork().netId)));
11660         } else {
11661             verify(mMockNetd, times(1)).idletimerRemoveInterface(eq(MOBILE_IFNAME), anyInt(),
11662                     eq(Integer.toString(TRANSPORT_CELLULAR)));
11663         }
11664 
11665         // Disconnect cell
11666         reset(mMockNetd);
11667         mCellAgent.disconnect();
11668         networkCallback.expect(LOST, mCellAgent);
11669         waitForIdle();
11670         if (mDeps.isAtLeastV()) {
11671             verify(mMockNetd, times(1)).idletimerRemoveInterface(eq(MOBILE_IFNAME), anyInt(),
11672                     eq(Integer.toString(mCellAgent.getNetwork().netId)));
11673         }  else {
11674             // LOST callback is triggered earlier than removing idle timer. Broadcast should also be
11675             // sent as network being switched. Ensure rule removal for cell will not be triggered
11676             // unexpectedly before network being removed.
11677             verify(mMockNetd, times(0)).idletimerRemoveInterface(eq(MOBILE_IFNAME), anyInt(),
11678                     eq(Integer.toString(TRANSPORT_CELLULAR)));
11679         }
11680         verify(mMockNetd, times(1)).networkDestroy(eq(mCellAgent.getNetwork().netId));
11681         verify(mMockDnsResolver, times(1)).destroyNetworkCache(eq(mCellAgent.getNetwork().netId));
11682 
11683         // Disconnect wifi
11684         ExpectedBroadcast b = expectConnectivityAction(TYPE_WIFI, DetailedState.DISCONNECTED);
11685         mWiFiAgent.disconnect();
11686         b.expectBroadcast();
11687         verify(mMockNetd, times(1)).idletimerRemoveInterface(eq(WIFI_IFNAME), anyInt(),
11688                 eq(wifiIdleTimerLabel));
11689 
11690         // Clean up
11691         mCm.unregisterNetworkCallback(networkCallback);
11692     }
11693 
11694     @Test
11695     public void testDataActivityTracking_VpnNetwork() throws Exception {
11696         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
11697         mWiFiAgent.connect(true /* validated */);
11698         mMockVpn.setUnderlyingNetworks(new Network[] { mWiFiAgent.getNetwork() });
11699 
11700         final LinkProperties lp = new LinkProperties();
11701         lp.setInterfaceName(VPN_IFNAME);
11702         mMockVpn.establishForMyUid(lp);
11703 
11704         // NetworkActivityTracker should not track the VPN network since VPN can change the
11705         // underlying network without disconnect.
11706         verify(mMockNetd, never()).idletimerAddInterface(eq(VPN_IFNAME), anyInt(), any());
11707     }
11708 
11709     private void verifyTcpBufferSizeChange(String tcpBufferSizes) throws Exception {
11710         String[] values = tcpBufferSizes.split(",");
11711         String rmemValues = String.join(" ", values[0], values[1], values[2]);
11712         String wmemValues = String.join(" ", values[3], values[4], values[5]);
11713         verify(mMockNetd, atLeastOnce()).setTcpRWmemorySize(rmemValues, wmemValues);
11714         reset(mMockNetd);
11715     }
11716 
11717     @Test
11718     public void testTcpBufferReset() throws Exception {
11719         final String testTcpBufferSizes = "1,2,3,4,5,6";
11720         final NetworkRequest networkRequest = new NetworkRequest.Builder()
11721                 .addTransportType(TRANSPORT_CELLULAR)
11722                 .addCapability(NET_CAPABILITY_INTERNET)
11723                 .build();
11724         final TestNetworkCallback networkCallback = new TestNetworkCallback();
11725         mCm.registerNetworkCallback(networkRequest, networkCallback);
11726 
11727         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
11728         reset(mMockNetd);
11729         // Switching default network updates TCP buffer sizes.
11730         mCellAgent.connect(false);
11731         networkCallback.expectAvailableCallbacksUnvalidated(mCellAgent);
11732         verifyTcpBufferSizeChange(ConnectivityService.DEFAULT_TCP_BUFFER_SIZES);
11733         // Change link Properties should have updated tcp buffer size.
11734         LinkProperties lp = new LinkProperties();
11735         lp.setTcpBufferSizes(testTcpBufferSizes);
11736         mCellAgent.sendLinkProperties(lp);
11737         networkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent);
11738         verifyTcpBufferSizeChange(testTcpBufferSizes);
11739         // Clean up.
11740         mCellAgent.disconnect();
11741         networkCallback.expect(LOST, mCellAgent);
11742         networkCallback.assertNoCallback();
11743         mCm.unregisterNetworkCallback(networkCallback);
11744     }
11745 
11746     @Test
11747     public void testGetGlobalProxyForNetwork() throws Exception {
11748         final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
11749         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
11750         final Network wifiNetwork = mWiFiAgent.getNetwork();
11751         mProxyTracker.setGlobalProxy(testProxyInfo);
11752         assertEquals(testProxyInfo, mService.getProxyForNetwork(wifiNetwork));
11753     }
11754 
11755     @Test
11756     public void testGetProxyForActiveNetwork() throws Exception {
11757         final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
11758         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
11759         mWiFiAgent.connect(true);
11760         waitForIdle();
11761         assertNull(mService.getProxyForNetwork(null));
11762 
11763         final LinkProperties testLinkProperties = new LinkProperties();
11764         testLinkProperties.setHttpProxy(testProxyInfo);
11765 
11766         mWiFiAgent.sendLinkProperties(testLinkProperties);
11767         waitForIdle();
11768 
11769         assertEquals(testProxyInfo, mService.getProxyForNetwork(null));
11770     }
11771 
11772     /*
11773      * Note for maintainers about how PAC proxies are implemented in Android.
11774      *
11775      * Generally, a proxy is just a hostname and a port to which requests are sent, instead of
11776      * sending them directly. Most HTTP libraries know to use this protocol, and the Java
11777      * language has properties to help handling these :
11778      *   https://docs.oracle.com/javase/8/docs/technotes/guides/net/proxies.html
11779      * Unfortunately these properties are very old and do not take multi-networking into account.
11780      *
11781      * A PAC proxy consists of a javascript file stored on a server, and the client is expected to
11782      * download the file and interpret the javascript for each HTTP request to know where to direct
11783      * it. The device must therefore run code (namely, a javascript interpreter) to interpret the
11784      * PAC file correctly. Most HTTP libraries do not know how to do this, since they do not
11785      * embark a javascript interpreter (and it would be generally unreasonable for them to do
11786      * so). Some apps, notably browsers, do know how to do this, but they are the exception rather
11787      * than the rule.
11788      * So to support most apps, Android embarks the javascript interpreter. When a network is
11789      * configured to have a PAC proxy, Android will first set the ProxyInfo object to an object
11790      * that contains the PAC URL (to communicate that to apps that know how to use it), then
11791      * download the PAC file and start a native process which will open a server on localhost,
11792      * and uses the interpreter inside WebView to interpret the PAC file. This server takes
11793      * a little bit of time to start and will listen on a random port. When the port is known,
11794      * the framework receives a notification and it updates the ProxyInfo in LinkProperties
11795      * as well as send a broadcast to inform apps. This new ProxyInfo still contains the PAC URL,
11796      * but it also contains "localhost" as the host and the port that the server listens to as
11797      * the port. This will let HTTP libraries that don't have a javascript interpreter work,
11798      * because they'll send the requests to this server running on localhost on the correct port,
11799      * and this server will do what is appropriate with each request according to the PAC file.
11800      *
11801      * Note that at the time of this writing, Android does not support starting multiple local
11802      * PAC servers, though this would be possible in theory by just starting multiple instances
11803      * of this process running their server on different ports. As a stopgap measure, Android
11804      * keeps one local server which is always the one for the default network. If a non-default
11805      * network has a PAC proxy, it will have a LinkProperties with a port of -1, which means it
11806      * could still be used by apps that know how to use the PAC URL directly, but not by HTTP
11807      * libs that don't know how to do that. When a network with a PAC proxy becomes the default,
11808      * the local server is started. When a network without a PAC proxy becomes the default, the
11809      * local server is stopped if it is running (and the LP for the old default network should
11810      * be reset to have a port of -1).
11811      *
11812      * In principle, each network can be configured with a different proxy (typically in the
11813      * network settings for a Wi-Fi network). These end up exposed in the LinkProperties of the
11814      * relevant network.
11815      * Android also exposes ConnectivityManager#getDefaultProxy, which is simply the proxy for
11816      * the default network. This was retrofitted from a time where Android did not support multiple
11817      * concurrent networks, hence the difficult architecture.
11818      * Note that there is also a "global" proxy that can be set by the DPM. When this is set,
11819      * it overrides the proxy settings for every single network at the same time – that is, the
11820      * system behaves as if the global proxy is the configured proxy for each network.
11821      *
11822      * Generally there are four ways for apps to look up the proxy.
11823      * - Looking up the ProxyInfo in the LinkProperties for a network.
11824      * - Listening to the PROXY_CHANGED_ACTION broadcast
11825      * - Calling ConnectivityManager#getDefaultProxy, or ConnectivityManager#getProxyForNetwork
11826      *   which can be used to retrieve the proxy for any given network or the default network by
11827      *   passing null.
11828      * - Reading the standard JVM properties (http{s,}.proxy{Host,Port}). See the Java
11829      *   distribution documentation for details on how these are supposed to work :
11830      *    https://docs.oracle.com/javase/8/docs/technotes/guides/net/proxies.html
11831      *   In Android, these are set by ActivityThread in each process in response to the broadcast.
11832      *   Many apps actually use these, and it's important they work because it's part of the
11833      *   Java standard, meaning they need to be set for existing Java libs to work on Android.
11834      */
11835     @Test
11836     public void testPacProxy() throws Exception {
11837         final Uri pacUrl = Uri.parse("https://pac-url");
11838 
11839         final TestNetworkCallback cellCallback = new TestNetworkCallback();
11840         final NetworkRequest cellRequest = new NetworkRequest.Builder()
11841                 .addTransportType(TRANSPORT_CELLULAR).build();
11842         // Request cell to make sure it doesn't disconnect at an arbitrary point in the test,
11843         // which would make testing the callbacks on it difficult.
11844         mCm.requestNetwork(cellRequest, cellCallback);
11845         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
11846         mCellAgent.connect(true);
11847         cellCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
11848 
11849         final TestNetworkCallback wifiCallback = new TestNetworkCallback();
11850         final NetworkRequest wifiRequest = new NetworkRequest.Builder()
11851                 .addTransportType(TRANSPORT_WIFI).build();
11852         mCm.registerNetworkCallback(wifiRequest, wifiCallback);
11853 
11854         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
11855         mWiFiAgent.connect(true);
11856         wifiCallback.expectAvailableThenValidatedCallbacks(mWiFiAgent);
11857         cellCallback.assertNoCallback();
11858 
11859         final ProxyInfo initialProxyInfo = ProxyInfo.buildPacProxy(pacUrl);
11860         final LinkProperties testLinkProperties = new LinkProperties();
11861         testLinkProperties.setHttpProxy(initialProxyInfo);
11862         mWiFiAgent.sendLinkProperties(testLinkProperties);
11863         wifiCallback.expect(CallbackEntry.LINK_PROPERTIES_CHANGED, mWiFiAgent);
11864         cellCallback.assertNoCallback();
11865 
11866         // At first the local PAC proxy server is unstarted (see the description of what the local
11867         // server is in the comment at the top of this method). It will contain the PAC URL and a
11868         // port of -1 because it is unstarted. Check that all ways of getting that proxy info
11869         // returns the same object that was initially created.
11870         final ProxyInfo unstartedDefaultProxyInfo = mService.getProxyForNetwork(null);
11871         final ProxyInfo unstartedWifiProxyInfo = mService.getProxyForNetwork(
11872                 mWiFiAgent.getNetwork());
11873         final LinkProperties unstartedLp =
11874                 mService.getLinkProperties(mWiFiAgent.getNetwork());
11875 
11876         assertEquals(initialProxyInfo, unstartedDefaultProxyInfo);
11877         assertEquals(initialProxyInfo, unstartedWifiProxyInfo);
11878         assertEquals(initialProxyInfo, unstartedLp.getHttpProxy());
11879 
11880         // Make sure the cell network is unaffected. The LP are per-network and each network has
11881         // its own configuration. The default proxy and broadcast are system-wide, and the JVM
11882         // properties are per-process, and therefore can have only one value at any given time,
11883         // so the code sets them to the proxy of the default network (TODO : really, since the
11884         // default process is per-network, the JVM properties (http.proxyHost family – see
11885         // the comment at the top of the method for details about these) also should be per-network
11886         // and even the broadcast contents should be but none of this is implemented). The LP are
11887         // still per-network, and a process that wants to use a non-default network is supposed to
11888         // look up the proxy in its LP and it has to be correct.
11889         assertNull(mService.getLinkProperties(mCellAgent.getNetwork()).getHttpProxy());
11890         assertNull(mService.getProxyForNetwork(mCellAgent.getNetwork()));
11891 
11892         // Simulate PacManager sending the notification that the local server has started
11893         final ProxyInfo servingProxyInfo = new ProxyInfo(pacUrl, 2097);
11894         final ExpectedBroadcast servingProxyBroadcast = expectProxyChangeAction(servingProxyInfo);
11895         mService.simulateUpdateProxyInfo(mWiFiAgent.getNetwork(), servingProxyInfo);
11896         wifiCallback.expect(CallbackEntry.LINK_PROPERTIES_CHANGED, mWiFiAgent);
11897         cellCallback.assertNoCallback();
11898         servingProxyBroadcast.expectBroadcast();
11899 
11900         final ProxyInfo startedDefaultProxyInfo = mService.getProxyForNetwork(null);
11901         final ProxyInfo startedWifiProxyInfo = mService.getProxyForNetwork(
11902                 mWiFiAgent.getNetwork());
11903         final LinkProperties startedLp = mService.getLinkProperties(mWiFiAgent.getNetwork());
11904         assertEquals(servingProxyInfo, startedDefaultProxyInfo);
11905         assertEquals(servingProxyInfo, startedWifiProxyInfo);
11906         assertEquals(servingProxyInfo, startedLp.getHttpProxy());
11907         // Make sure the cell network is still unaffected
11908         assertNull(mService.getLinkProperties(mCellAgent.getNetwork()).getHttpProxy());
11909         assertNull(mService.getProxyForNetwork(mCellAgent.getNetwork()));
11910 
11911         // Start an ethernet network which will become the default, in order to test what happens
11912         // to the proxy of wifi while manipulating the proxy of ethernet.
11913         final Uri ethPacUrl = Uri.parse("https://ethernet-pac-url");
11914         final TestableNetworkCallback ethernetCallback = new TestableNetworkCallback();
11915         final NetworkRequest ethernetRequest = new NetworkRequest.Builder()
11916                 .addTransportType(TRANSPORT_ETHERNET).build();
11917         mEthernetAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
11918         mCm.registerNetworkCallback(ethernetRequest, ethernetCallback);
11919         mEthernetAgent.connect(true);
11920         ethernetCallback.expectAvailableThenValidatedCallbacks(mEthernetAgent);
11921 
11922         // Wifi is no longer the default, so it should get a callback to LP changed with a PAC
11923         // proxy but a port of -1 (since the local proxy doesn't serve wifi now)
11924         wifiCallback.expect(LINK_PROPERTIES_CHANGED, mWiFiAgent,
11925                 lp -> lp.getLp().getHttpProxy().getPort() == -1
11926                         && lp.getLp().getHttpProxy().isPacProxy());
11927         // Wifi is lingered as it was the default but is no longer serving any request.
11928         wifiCallback.expect(CallbackEntry.LOSING, mWiFiAgent);
11929 
11930         // Now arrange for Ethernet to have a PAC proxy.
11931         final ProxyInfo ethProxy = ProxyInfo.buildPacProxy(ethPacUrl);
11932         final LinkProperties ethLinkProperties = new LinkProperties();
11933         ethLinkProperties.setHttpProxy(ethProxy);
11934         mEthernetAgent.sendLinkProperties(ethLinkProperties);
11935         ethernetCallback.expect(CallbackEntry.LINK_PROPERTIES_CHANGED, mEthernetAgent);
11936         // Default network is Ethernet
11937         assertEquals(ethProxy, mService.getProxyForNetwork(null));
11938         assertEquals(ethProxy, mService.getProxyForNetwork(mEthernetAgent.getNetwork()));
11939         // Proxy info for WiFi ideally should be the old one with the old server still running,
11940         // but as the PAC code only handles one server at any given time, this can't work. Wifi
11941         // having null as a proxy also won't work (apps using WiFi will try to access the network
11942         // without proxy) but is not as bad as having the new proxy (that would send requests
11943         // over the default network).
11944         assertEquals(initialProxyInfo, mService.getProxyForNetwork(mWiFiAgent.getNetwork()));
11945         assertNull(mService.getProxyForNetwork(mCellAgent.getNetwork()));
11946 
11947         // Expect the local PAC proxy server starts to serve the proxy on Ethernet. Use
11948         // simulateUpdateProxyInfo to simulate this, and check that the callback is called to
11949         // inform apps of the port and that the various networks have the expected proxies in
11950         // their link properties.
11951         final ProxyInfo servingEthProxy = new ProxyInfo(ethPacUrl, 2099);
11952         final ExpectedBroadcast servingEthProxyBroadcast = expectProxyChangeAction(servingEthProxy);
11953         final ExpectedBroadcast servingProxyBroadcast2 = expectProxyChangeAction(servingProxyInfo);
11954         mService.simulateUpdateProxyInfo(mEthernetAgent.getNetwork(), servingEthProxy);
11955         ethernetCallback.expect(CallbackEntry.LINK_PROPERTIES_CHANGED, mEthernetAgent);
11956         assertEquals(servingEthProxy, mService.getProxyForNetwork(null));
11957         assertEquals(servingEthProxy, mService.getProxyForNetwork(mEthernetAgent.getNetwork()));
11958         assertEquals(initialProxyInfo, mService.getProxyForNetwork(mWiFiAgent.getNetwork()));
11959         assertNull(mService.getProxyForNetwork(mCellAgent.getNetwork()));
11960         servingEthProxyBroadcast.expectBroadcast();
11961 
11962         // Ethernet disconnects, back to WiFi
11963         mEthernetAgent.disconnect();
11964         ethernetCallback.expect(CallbackEntry.LOST, mEthernetAgent);
11965 
11966         // WiFi is now the default network again. However, the local proxy server does not serve
11967         // WiFi at this time, so at this time a proxy with port -1 is still the correct value.
11968         // In time, the local proxy server for ethernet will be downed and the local proxy server
11969         // for WiFi will be restarted, and WiFi will see an update to its LP with the new port,
11970         // but in this test this won't happen until the test simulates the local proxy starting
11971         // up for WiFi (which is done just a few lines below). This is therefore the perfect place
11972         // to check that WiFi is unaffected until the new local proxy starts up.
11973         wifiCallback.assertNoCallback();
11974         assertEquals(initialProxyInfo, mService.getProxyForNetwork(null));
11975         assertEquals(initialProxyInfo, mService.getProxyForNetwork(mWiFiAgent.getNetwork()));
11976         assertNull(mService.getProxyForNetwork(mCellAgent.getNetwork()));
11977         // Note : strictly speaking, for correctness here apps should expect a broadcast with a
11978         // port of -1, since that's the current default proxy. The code does not send this
11979         // broadcast. In practice though, not sending it is more useful since the new proxy will
11980         // start momentarily, so broadcasting and getting all apps to update and retry once now
11981         // and again in 250ms is kind of counter-productive, so don't fix this bug.
11982 
11983         // After a while the PAC file for wifi is resolved again and the local proxy server
11984         // starts up. This should cause a LP event to inform clients of the port to access the
11985         // proxy server for wifi.
11986         mService.simulateUpdateProxyInfo(mWiFiAgent.getNetwork(), servingProxyInfo);
11987         wifiCallback.expect(CallbackEntry.LINK_PROPERTIES_CHANGED, mWiFiAgent);
11988         assertEquals(servingProxyInfo, mService.getProxyForNetwork(null));
11989         assertEquals(servingProxyInfo, mService.getProxyForNetwork(mWiFiAgent.getNetwork()));
11990         assertNull(mService.getProxyForNetwork(mCellAgent.getNetwork()));
11991         servingProxyBroadcast2.expectBroadcast();
11992 
11993         // Expect a broadcast for an empty proxy after wifi disconnected, because cell is now
11994         // the default network and it doesn't have a proxy. Whether "no proxy" is a null pointer
11995         // or a ProxyInfo with an empty host doesn't matter because both are correct, so this test
11996         // accepts both.
11997         final ExpectedBroadcast emptyProxyBroadcast = expectProxyChangeAction(
11998                 proxy -> proxy == null || TextUtils.isEmpty(proxy.getHost()));
11999         mWiFiAgent.disconnect();
12000         emptyProxyBroadcast.expectBroadcast();
12001         wifiCallback.expect(CallbackEntry.LOST, mWiFiAgent);
12002         assertNull(mService.getProxyForNetwork(null));
12003         assertNull(mService.getLinkProperties(mCellAgent.getNetwork()).getHttpProxy());
12004         assertNull(mService.getGlobalProxy());
12005 
12006         mCm.unregisterNetworkCallback(cellCallback);
12007     }
12008 
12009     @Test
12010     public void testPacProxy_NetworkDisconnects_BroadcastSent() throws Exception {
12011         // Make a WiFi network with a PAC URI.
12012         final Uri pacUrl = Uri.parse("https://pac-url");
12013         final ProxyInfo initialProxyInfo = ProxyInfo.buildPacProxy(pacUrl);
12014         final LinkProperties testLinkProperties = new LinkProperties();
12015         testLinkProperties.setHttpProxy(initialProxyInfo);
12016 
12017         final TestNetworkCallback wifiCallback = new TestNetworkCallback();
12018         final NetworkRequest wifiRequest = new NetworkRequest.Builder()
12019                 .addTransportType(TRANSPORT_WIFI).build();
12020         mCm.registerNetworkCallback(wifiRequest, wifiCallback);
12021 
12022         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, testLinkProperties);
12023         mWiFiAgent.connect(true);
12024         // Wifi is up, but the local proxy server hasn't started yet.
12025         wifiCallback.expectAvailableThenValidatedCallbacks(mWiFiAgent);
12026 
12027         // Simulate PacManager sending the notification that the local server has started
12028         final ProxyInfo servingProxyInfo = new ProxyInfo(pacUrl, 2097);
12029         final ExpectedBroadcast servingProxyBroadcast = expectProxyChangeAction(servingProxyInfo);
12030         mService.simulateUpdateProxyInfo(mWiFiAgent.getNetwork(), servingProxyInfo);
12031         wifiCallback.expect(CallbackEntry.LINK_PROPERTIES_CHANGED, mWiFiAgent);
12032         servingProxyBroadcast.expectBroadcast();
12033 
12034         // Now disconnect Wi-Fi and make sure there is a broadcast for some empty proxy. Whether
12035         // the "empty" proxy is a null pointer or a ProxyInfo with an empty host doesn't matter
12036         // because both are correct, so this test accepts both.
12037         final ExpectedBroadcast emptyProxyBroadcast = expectProxyChangeAction(
12038                 proxy -> proxy == null || TextUtils.isEmpty(proxy.getHost()));
12039         mWiFiAgent.disconnect();
12040         wifiCallback.expect(CallbackEntry.LOST, mWiFiAgent);
12041         emptyProxyBroadcast.expectBroadcast();
12042     }
12043 
12044     @Test
12045     public void testGetProxyForVPN() throws Exception {
12046         final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
12047 
12048         // Set up a WiFi network with no proxy
12049         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
12050         mWiFiAgent.connect(true);
12051         waitForIdle();
12052         assertNull(mService.getProxyForNetwork(null));
12053 
12054         // Connect a VPN network with a proxy.
12055         LinkProperties testLinkProperties = new LinkProperties();
12056         testLinkProperties.setHttpProxy(testProxyInfo);
12057         mMockVpn.establishForMyUid(testLinkProperties);
12058         assertUidRangesUpdatedForMyUid(true);
12059 
12060         // Test that the VPN network returns a proxy, and the WiFi does not.
12061         assertEquals(testProxyInfo, mService.getProxyForNetwork(mMockVpn.getNetwork()));
12062         assertEquals(testProxyInfo, mService.getProxyForNetwork(null));
12063         assertNull(mService.getProxyForNetwork(mWiFiAgent.getNetwork()));
12064 
12065         // Test that the VPN network returns no proxy when it is set to null.
12066         testLinkProperties.setHttpProxy(null);
12067         mMockVpn.sendLinkProperties(testLinkProperties);
12068         waitForIdle();
12069         assertNull(mService.getProxyForNetwork(mMockVpn.getNetwork()));
12070         assertNull(mService.getProxyForNetwork(null));
12071 
12072         // Set WiFi proxy and check that the vpn proxy is still null.
12073         testLinkProperties.setHttpProxy(testProxyInfo);
12074         mWiFiAgent.sendLinkProperties(testLinkProperties);
12075         waitForIdle();
12076         assertNull(mService.getProxyForNetwork(null));
12077 
12078         // Disconnect from VPN and check that the active network, which is now the WiFi, has the
12079         // correct proxy setting.
12080         mMockVpn.disconnect();
12081         waitForIdle();
12082         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetwork());
12083         assertEquals(testProxyInfo, mService.getProxyForNetwork(mWiFiAgent.getNetwork()));
12084         assertEquals(testProxyInfo, mService.getProxyForNetwork(null));
12085     }
12086 
12087     @Test
12088     public void testFullyRoutedVpnResultsInInterfaceFilteringRules() throws Exception {
12089         LinkProperties lp = new LinkProperties();
12090         lp.setInterfaceName("tun0");
12091         lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
12092         lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), RTN_UNREACHABLE));
12093         // The uid range needs to cover the test app so the network is visible to it.
12094         final Set<UidRange> vpnRange = Collections.singleton(PRIMARY_UIDRANGE);
12095         mMockVpn.establish(lp, VPN_UID, vpnRange);
12096         assertVpnUidRangesUpdated(true, vpnRange, VPN_UID);
12097 
12098         // A connected VPN should have interface rules set up. There are two expected invocations,
12099         // one during the VPN initial connection, one during the VPN LinkProperties update.
12100         ArgumentCaptor<int[]> uidCaptor = ArgumentCaptor.forClass(int[].class);
12101         verify(mBpfNetMaps, times(2)).addUidInterfaceRules(eq("tun0"), uidCaptor.capture());
12102         assertContainsExactly(uidCaptor.getAllValues().get(0), APP1_UID, APP2_UID);
12103         assertContainsExactly(uidCaptor.getAllValues().get(1), APP1_UID, APP2_UID);
12104 
12105         mMockVpn.disconnect();
12106         waitForIdle();
12107 
12108         // Disconnected VPN should have interface rules removed
12109         verify(mBpfNetMaps).removeUidInterfaceRules(uidCaptor.capture());
12110         assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
12111     }
12112 
12113     private void checkInterfaceFilteringRuleWithNullInterface(final LinkProperties lp,
12114             final int uid) throws Exception {
12115         // The uid range needs to cover the test app so the network is visible to it.
12116         final Set<UidRange> vpnRange = Collections.singleton(PRIMARY_UIDRANGE);
12117         mMockVpn.establish(lp, uid, vpnRange);
12118         assertVpnUidRangesUpdated(true, vpnRange, uid);
12119 
12120         if (mDeps.isAtLeastT()) {
12121             // On T and above, VPN should have rules for null interface. Null Interface is a
12122             // wildcard and this accepts traffic from all the interfaces.
12123             // There are two expected invocations, one during the VPN initial
12124             // connection, one during the VPN LinkProperties update.
12125             ArgumentCaptor<int[]> uidCaptor = ArgumentCaptor.forClass(int[].class);
12126             verify(mBpfNetMaps, times(2)).addUidInterfaceRules(
12127                     eq(null) /* iface */, uidCaptor.capture());
12128             if (uid == VPN_UID) {
12129                 assertContainsExactly(uidCaptor.getAllValues().get(0), APP1_UID, APP2_UID);
12130                 assertContainsExactly(uidCaptor.getAllValues().get(1), APP1_UID, APP2_UID);
12131             } else {
12132                 assertContainsExactly(uidCaptor.getAllValues().get(0), APP1_UID, APP2_UID, VPN_UID);
12133                 assertContainsExactly(uidCaptor.getAllValues().get(1), APP1_UID, APP2_UID, VPN_UID);
12134             }
12135 
12136             mMockVpn.disconnect();
12137             waitForIdle();
12138 
12139             // Disconnected VPN should have interface rules removed
12140             verify(mBpfNetMaps).removeUidInterfaceRules(uidCaptor.capture());
12141             if (uid == VPN_UID) {
12142                 assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
12143             } else {
12144                 assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID, VPN_UID);
12145             }
12146         } else {
12147             // Before T, rules are not configured for null interface.
12148             verify(mBpfNetMaps, never()).addUidInterfaceRules(any(), any());
12149         }
12150     }
12151 
12152     @Test
12153     public void testLegacyVpnInterfaceFilteringRule() throws Exception {
12154         LinkProperties lp = new LinkProperties();
12155         lp.setInterfaceName("tun0");
12156         lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
12157         lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
12158         // Legacy VPN should have interface filtering with null interface.
12159         checkInterfaceFilteringRuleWithNullInterface(lp, Process.SYSTEM_UID);
12160     }
12161 
12162     @Test
12163     public void testLocalIpv4OnlyVpnInterfaceFilteringRule() throws Exception {
12164         LinkProperties lp = new LinkProperties();
12165         lp.setInterfaceName("tun0");
12166         lp.addRoute(new RouteInfo(new IpPrefix("192.0.2.0/24"), null, "tun0"));
12167         lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), RTN_UNREACHABLE));
12168         // VPN that does not provide a default route should have interface filtering with null
12169         // interface.
12170         checkInterfaceFilteringRuleWithNullInterface(lp, VPN_UID);
12171     }
12172 
12173     @Test
12174     public void testVpnHandoverChangesInterfaceFilteringRule() throws Exception {
12175         LinkProperties lp = new LinkProperties();
12176         lp.setInterfaceName("tun0");
12177         lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
12178         lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
12179         // The uid range needs to cover the test app so the network is visible to it.
12180         final Set<UidRange> vpnRange = Collections.singleton(PRIMARY_UIDRANGE);
12181         mMockVpn.establish(lp, VPN_UID, vpnRange);
12182         assertVpnUidRangesUpdated(true, vpnRange, VPN_UID);
12183 
12184         // Connected VPN should have interface rules set up. There are two expected invocations,
12185         // one during VPN uid update, one during VPN LinkProperties update
12186         ArgumentCaptor<int[]> uidCaptor = ArgumentCaptor.forClass(int[].class);
12187         verify(mBpfNetMaps, times(2)).addUidInterfaceRules(eq("tun0"), uidCaptor.capture());
12188         assertContainsExactly(uidCaptor.getAllValues().get(0), APP1_UID, APP2_UID);
12189         assertContainsExactly(uidCaptor.getAllValues().get(1), APP1_UID, APP2_UID);
12190 
12191         reset(mBpfNetMaps);
12192         InOrder inOrder = inOrder(mBpfNetMaps);
12193         lp.setInterfaceName("tun1");
12194         mMockVpn.sendLinkProperties(lp);
12195         waitForIdle();
12196         // VPN handover (switch to a new interface) should result in rules being updated (old rules
12197         // removed first, then new rules added)
12198         inOrder.verify(mBpfNetMaps).removeUidInterfaceRules(uidCaptor.capture());
12199         assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
12200         inOrder.verify(mBpfNetMaps).addUidInterfaceRules(eq("tun1"), uidCaptor.capture());
12201         assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
12202 
12203         reset(mBpfNetMaps);
12204         lp = new LinkProperties();
12205         lp.setInterfaceName("tun1");
12206         lp.addRoute(new RouteInfo(new IpPrefix("192.0.2.0/24"), null, "tun1"));
12207         mMockVpn.sendLinkProperties(lp);
12208         waitForIdle();
12209         // VPN not routing everything should no longer have interface filtering rules
12210         verify(mBpfNetMaps).removeUidInterfaceRules(uidCaptor.capture());
12211         assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
12212 
12213         reset(mBpfNetMaps);
12214         lp = new LinkProperties();
12215         lp.setInterfaceName("tun1");
12216         lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), RTN_UNREACHABLE));
12217         lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
12218         mMockVpn.sendLinkProperties(lp);
12219         waitForIdle();
12220         // Back to routing all IPv6 traffic should have filtering rules
12221         verify(mBpfNetMaps).addUidInterfaceRules(eq("tun1"), uidCaptor.capture());
12222         assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
12223     }
12224 
12225     @Test
12226     public void testUidUpdateChangesInterfaceFilteringRule() throws Exception {
12227         LinkProperties lp = new LinkProperties();
12228         lp.setInterfaceName("tun0");
12229         lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), RTN_UNREACHABLE));
12230         lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
12231         // The uid range needs to cover the test app so the network is visible to it.
12232         final UidRange vpnRange = PRIMARY_UIDRANGE;
12233         final Set<UidRange> vpnRanges = Collections.singleton(vpnRange);
12234         mMockVpn.establish(lp, VPN_UID, vpnRanges);
12235         assertVpnUidRangesUpdated(true, vpnRanges, VPN_UID);
12236 
12237         reset(mBpfNetMaps);
12238         InOrder inOrder = inOrder(mBpfNetMaps);
12239 
12240         // Update to new range which is old range minus APP1, i.e. only APP2
12241         final Set<UidRange> newRanges = new HashSet<>(asList(
12242                 new UidRange(vpnRange.start, APP1_UID - 1),
12243                 new UidRange(APP1_UID + 1, vpnRange.stop)));
12244         mMockVpn.setUids(newRanges);
12245         waitForIdle();
12246 
12247         ArgumentCaptor<int[]> uidCaptor = ArgumentCaptor.forClass(int[].class);
12248         // Verify old rules are removed before new rules are added
12249         inOrder.verify(mBpfNetMaps).removeUidInterfaceRules(uidCaptor.capture());
12250         assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
12251         inOrder.verify(mBpfNetMaps).addUidInterfaceRules(eq("tun0"), uidCaptor.capture());
12252         assertContainsExactly(uidCaptor.getValue(), APP2_UID);
12253     }
12254 
12255     @Test
12256     public void testLinkPropertiesWithWakeOnLanForActiveNetwork() throws Exception {
12257         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
12258 
12259         LinkProperties wifiLp = new LinkProperties();
12260         wifiLp.setInterfaceName(WIFI_WOL_IFNAME);
12261         wifiLp.setWakeOnLanSupported(false);
12262 
12263         // Default network switch should update ifaces.
12264         mWiFiAgent.connect(false);
12265         mWiFiAgent.sendLinkProperties(wifiLp);
12266         waitForIdle();
12267 
12268         // ConnectivityService should have changed the WakeOnLanSupported to true
12269         wifiLp.setWakeOnLanSupported(true);
12270         assertEquals(wifiLp, mService.getActiveLinkProperties());
12271     }
12272 
12273     @Test
12274     public void testLegacyExtraInfoSentToNetworkMonitor() throws Exception {
12275         class TestNetworkAgent extends NetworkAgent {
12276             TestNetworkAgent(Context context, Looper looper, NetworkAgentConfig config) {
12277                 super(context, looper, "MockAgent", new NetworkCapabilities(),
12278                         new LinkProperties(), 40 , config, null /* provider */);
12279             }
12280         }
12281         final NetworkAgent naNoExtraInfo = new TestNetworkAgent(
12282                 mServiceContext, mCsHandlerThread.getLooper(), new NetworkAgentConfig());
12283         naNoExtraInfo.register();
12284         verify(mNetworkStack).makeNetworkMonitor(any(), isNull(String.class), any());
12285         naNoExtraInfo.unregister();
12286 
12287         reset(mNetworkStack);
12288         final NetworkAgentConfig config =
12289                 new NetworkAgentConfig.Builder().setLegacyExtraInfo("legacyinfo").build();
12290         final NetworkAgent naExtraInfo = new TestNetworkAgent(
12291                 mServiceContext, mCsHandlerThread.getLooper(), config);
12292         naExtraInfo.register();
12293         verify(mNetworkStack).makeNetworkMonitor(any(), eq("legacyinfo"), any());
12294         naExtraInfo.unregister();
12295     }
12296 
12297     // To avoid granting location permission bypass.
12298     private void denyAllLocationPrivilegedPermissions() {
12299         mServiceContext.setPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
12300                 PERMISSION_DENIED);
12301         mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_DENIED);
12302         mServiceContext.setPermission(NETWORK_STACK, PERMISSION_DENIED);
12303         mServiceContext.setPermission(Manifest.permission.NETWORK_SETUP_WIZARD,
12304                 PERMISSION_DENIED);
12305     }
12306 
12307     private void setupLocationPermissions(
12308             int targetSdk, boolean locationToggle, String op, String perm) throws Exception {
12309         denyAllLocationPrivilegedPermissions();
12310 
12311         final ApplicationInfo applicationInfo = new ApplicationInfo();
12312         applicationInfo.targetSdkVersion = targetSdk;
12313         doReturn(applicationInfo).when(mPackageManager)
12314                 .getApplicationInfoAsUser(anyString(), anyInt(), any());
12315         doReturn(targetSdk).when(mPackageManager).getTargetSdkVersion(any());
12316 
12317         doReturn(locationToggle).when(mLocationManager).isLocationEnabledForUser(any());
12318 
12319         if (op != null) {
12320             doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOpsManager).noteOp(
12321                     eq(op), eq(Process.myUid()), eq(mContext.getPackageName()),
12322                     eq(getAttributionTag()), anyString());
12323         }
12324 
12325         if (perm != null) {
12326             mServiceContext.setPermission(perm, PERMISSION_GRANTED);
12327         }
12328     }
12329 
12330     private int getOwnerUidNetCapsPermission(int ownerUid, int callerUid,
12331             boolean includeLocationSensitiveInfo) {
12332         final NetworkCapabilities netCap = new NetworkCapabilities().setOwnerUid(ownerUid);
12333 
12334         return mService.createWithLocationInfoSanitizedIfNecessaryWhenParceled(
12335                 netCap, includeLocationSensitiveInfo, Process.myUid(), callerUid,
12336                 mContext.getPackageName(), getAttributionTag())
12337                 .getOwnerUid();
12338     }
12339 
12340     private void verifyTransportInfoCopyNetCapsPermission(
12341             int callerUid, boolean includeLocationSensitiveInfo,
12342             boolean shouldMakeCopyWithLocationSensitiveFieldsParcelable) {
12343         final TransportInfo transportInfo = mock(TransportInfo.class);
12344         doReturn(REDACT_FOR_ACCESS_FINE_LOCATION).when(transportInfo).getApplicableRedactions();
12345         final NetworkCapabilities netCap =
12346                 new NetworkCapabilities().setTransportInfo(transportInfo);
12347 
12348         mService.createWithLocationInfoSanitizedIfNecessaryWhenParceled(
12349                 netCap, includeLocationSensitiveInfo, Process.myPid(), callerUid,
12350                 mContext.getPackageName(), getAttributionTag());
12351         if (shouldMakeCopyWithLocationSensitiveFieldsParcelable) {
12352             verify(transportInfo).makeCopy(REDACT_NONE);
12353         } else {
12354             verify(transportInfo).makeCopy(REDACT_FOR_ACCESS_FINE_LOCATION);
12355         }
12356     }
12357 
12358     private void verifyOwnerUidAndTransportInfoNetCapsPermission(
12359             boolean shouldInclLocationSensitiveOwnerUidWithoutIncludeFlag,
12360             boolean shouldInclLocationSensitiveOwnerUidWithIncludeFlag,
12361             boolean shouldInclLocationSensitiveTransportInfoWithoutIncludeFlag,
12362             boolean shouldInclLocationSensitiveTransportInfoWithIncludeFlag) {
12363         final int myUid = Process.myUid();
12364 
12365         final int expectedOwnerUidWithoutIncludeFlag =
12366                 shouldInclLocationSensitiveOwnerUidWithoutIncludeFlag
12367                         ? myUid : INVALID_UID;
12368         assertEquals(expectedOwnerUidWithoutIncludeFlag, getOwnerUidNetCapsPermission(
12369                 myUid, myUid, false /* includeLocationSensitiveInfo */));
12370 
12371         final int expectedOwnerUidWithIncludeFlag =
12372                 shouldInclLocationSensitiveOwnerUidWithIncludeFlag ? myUid : INVALID_UID;
12373         assertEquals(expectedOwnerUidWithIncludeFlag, getOwnerUidNetCapsPermission(
12374                 myUid, myUid, true /* includeLocationSensitiveInfo */));
12375 
12376         verifyTransportInfoCopyNetCapsPermission(myUid,
12377                 false, /* includeLocationSensitiveInfo */
12378                 shouldInclLocationSensitiveTransportInfoWithoutIncludeFlag);
12379 
12380         verifyTransportInfoCopyNetCapsPermission(myUid,
12381                 true, /* includeLocationSensitiveInfo */
12382                 shouldInclLocationSensitiveTransportInfoWithIncludeFlag);
12383 
12384     }
12385 
12386     private void verifyOwnerUidAndTransportInfoNetCapsPermissionPreS() {
12387         verifyOwnerUidAndTransportInfoNetCapsPermission(
12388                 // Ensure that owner uid is included even if the request asks to remove it (which is
12389                 // the default) since the app has necessary permissions and targetSdk < S.
12390                 true, /* shouldInclLocationSensitiveOwnerUidWithoutIncludeFlag */
12391                 true, /* shouldInclLocationSensitiveOwnerUidWithIncludeFlag */
12392                 // Ensure that location info is removed if the request asks to remove it even if the
12393                 // app has necessary permissions.
12394                 false, /* shouldInclLocationSensitiveTransportInfoWithoutIncludeFlag */
12395                 true /* shouldInclLocationSensitiveTransportInfoWithIncludeFlag */
12396         );
12397     }
12398 
12399     @Test
12400     public void testCreateWithLocationInfoSanitizedWithFineLocationAfterQPreS()
12401             throws Exception {
12402         setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
12403                 Manifest.permission.ACCESS_FINE_LOCATION);
12404 
12405         verifyOwnerUidAndTransportInfoNetCapsPermissionPreS();
12406     }
12407 
12408     @Test
12409     public void testCreateWithLocationInfoSanitizedWithFineLocationPreSWithAndWithoutCallbackFlag()
12410             throws Exception {
12411         setupLocationPermissions(Build.VERSION_CODES.R, true, AppOpsManager.OPSTR_FINE_LOCATION,
12412                 Manifest.permission.ACCESS_FINE_LOCATION);
12413 
12414         verifyOwnerUidAndTransportInfoNetCapsPermissionPreS();
12415     }
12416 
12417     @Test
12418     public void
12419             testCreateWithLocationInfoSanitizedWithFineLocationAfterSWithAndWithoutCallbackFlag()
12420             throws Exception {
12421         setupLocationPermissions(Build.VERSION_CODES.S, true, AppOpsManager.OPSTR_FINE_LOCATION,
12422                 Manifest.permission.ACCESS_FINE_LOCATION);
12423 
12424         verifyOwnerUidAndTransportInfoNetCapsPermission(
12425                 // Ensure that the owner UID is removed if the request asks us to remove it even
12426                 // if the app has necessary permissions since targetSdk >= S.
12427                 false, /* shouldInclLocationSensitiveOwnerUidWithoutIncludeFlag */
12428                 true, /* shouldInclLocationSensitiveOwnerUidWithIncludeFlag */
12429                 // Ensure that location info is removed if the request asks to remove it even if the
12430                 // app has necessary permissions.
12431                 false, /* shouldInclLocationSensitiveTransportInfoWithoutIncludeFlag */
12432                 true /* shouldInclLocationSensitiveTransportInfoWithIncludeFlag */
12433         );
12434     }
12435 
12436     @Test
12437     public void testCreateWithLocationInfoSanitizedWithCoarseLocationPreQ()
12438             throws Exception {
12439         setupLocationPermissions(Build.VERSION_CODES.P, true, AppOpsManager.OPSTR_COARSE_LOCATION,
12440                 Manifest.permission.ACCESS_COARSE_LOCATION);
12441 
12442         verifyOwnerUidAndTransportInfoNetCapsPermissionPreS();
12443     }
12444 
12445     private void verifyOwnerUidAndTransportInfoNetCapsNotIncluded() {
12446         verifyOwnerUidAndTransportInfoNetCapsPermission(
12447                 false, /* shouldInclLocationSensitiveOwnerUidWithoutIncludeFlag */
12448                 false, /* shouldInclLocationSensitiveOwnerUidWithIncludeFlag */
12449                 false, /* shouldInclLocationSensitiveTransportInfoWithoutIncludeFlag */
12450                 false /* shouldInclLocationSensitiveTransportInfoWithIncludeFlag */
12451         );
12452     }
12453 
12454     @Test
12455     public void testCreateWithLocationInfoSanitizedLocationOff() throws Exception {
12456         // Test that even with fine location permission, and UIDs matching, the UID is sanitized.
12457         setupLocationPermissions(Build.VERSION_CODES.Q, false, AppOpsManager.OPSTR_FINE_LOCATION,
12458                 Manifest.permission.ACCESS_FINE_LOCATION);
12459 
12460         verifyOwnerUidAndTransportInfoNetCapsNotIncluded();
12461     }
12462 
12463     @Test
12464     public void testCreateWithLocationInfoSanitizedWrongUid() throws Exception {
12465         // Test that even with fine location permission, not being the owner leads to sanitization.
12466         setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
12467                 Manifest.permission.ACCESS_FINE_LOCATION);
12468 
12469         final int myUid = Process.myUid();
12470         assertEquals(Process.INVALID_UID,
12471                 getOwnerUidNetCapsPermission(myUid + 1, myUid,
12472                         true /* includeLocationSensitiveInfo */));
12473     }
12474 
12475     @Test
12476     public void testCreateWithLocationInfoSanitizedWithCoarseLocationAfterQ()
12477             throws Exception {
12478         // Test that not having fine location permission leads to sanitization.
12479         setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_COARSE_LOCATION,
12480                 Manifest.permission.ACCESS_COARSE_LOCATION);
12481 
12482         verifyOwnerUidAndTransportInfoNetCapsNotIncluded();
12483     }
12484 
12485     @Test
12486     public void testCreateWithLocationInfoSanitizedWithCoarseLocationAfterS()
12487             throws Exception {
12488         // Test that not having fine location permission leads to sanitization.
12489         setupLocationPermissions(Build.VERSION_CODES.S, true, AppOpsManager.OPSTR_COARSE_LOCATION,
12490                 Manifest.permission.ACCESS_COARSE_LOCATION);
12491 
12492         verifyOwnerUidAndTransportInfoNetCapsNotIncluded();
12493     }
12494 
12495     @Test
12496     public void testCreateForCallerWithLocalMacAddressSanitizedWithLocalMacAddressPermission()
12497             throws Exception {
12498         mServiceContext.setPermission(Manifest.permission.LOCAL_MAC_ADDRESS, PERMISSION_GRANTED);
12499 
12500         final TransportInfo transportInfo = mock(TransportInfo.class);
12501         doReturn(REDACT_FOR_ACCESS_FINE_LOCATION | REDACT_FOR_LOCAL_MAC_ADDRESS)
12502                 .when(transportInfo).getApplicableRedactions();
12503         final NetworkCapabilities netCap =
12504                 new NetworkCapabilities().setTransportInfo(transportInfo);
12505 
12506         mService.createWithLocationInfoSanitizedIfNecessaryWhenParceled(
12507                 netCap, false /* includeLocationSensitiveInfoInTransportInfo */,
12508                 Process.myPid(), Process.myUid(),
12509                 mContext.getPackageName(), getAttributionTag());
12510         // don't redact MAC_ADDRESS fields, only location sensitive fields.
12511         verify(transportInfo).makeCopy(REDACT_FOR_ACCESS_FINE_LOCATION);
12512     }
12513 
12514     @Test
12515     public void testCreateForCallerWithLocalMacAddressSanitizedWithoutLocalMacAddressPermission()
12516             throws Exception {
12517         mServiceContext.setPermission(Manifest.permission.LOCAL_MAC_ADDRESS, PERMISSION_DENIED);
12518 
12519         final TransportInfo transportInfo = mock(TransportInfo.class);
12520         doReturn(REDACT_FOR_ACCESS_FINE_LOCATION | REDACT_FOR_LOCAL_MAC_ADDRESS)
12521                 .when(transportInfo).getApplicableRedactions();
12522         final NetworkCapabilities netCap =
12523                 new NetworkCapabilities().setTransportInfo(transportInfo);
12524 
12525         mService.createWithLocationInfoSanitizedIfNecessaryWhenParceled(
12526                 netCap, false /* includeLocationSensitiveInfoInTransportInfo */,
12527                 Process.myPid(), Process.myUid(),
12528                 mContext.getPackageName(), getAttributionTag());
12529         // redact both MAC_ADDRESS & location sensitive fields.
12530         verify(transportInfo).makeCopy(REDACT_FOR_ACCESS_FINE_LOCATION
12531                 | REDACT_FOR_LOCAL_MAC_ADDRESS);
12532     }
12533 
12534     @Test
12535     public void testCreateForCallerWithLocalMacAddressSanitizedWithSettingsPermission()
12536             throws Exception {
12537         mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_GRANTED);
12538 
12539         final TransportInfo transportInfo = mock(TransportInfo.class);
12540         doReturn(REDACT_FOR_ACCESS_FINE_LOCATION | REDACT_FOR_NETWORK_SETTINGS)
12541                 .when(transportInfo).getApplicableRedactions();
12542         final NetworkCapabilities netCap =
12543                 new NetworkCapabilities().setTransportInfo(transportInfo);
12544 
12545         mService.createWithLocationInfoSanitizedIfNecessaryWhenParceled(
12546                 netCap, false /* includeLocationSensitiveInfoInTransportInfo */,
12547                 Process.myPid(), Process.myUid(),
12548                 mContext.getPackageName(), getAttributionTag());
12549         // don't redact NETWORK_SETTINGS fields, only location sensitive fields.
12550         verify(transportInfo).makeCopy(REDACT_FOR_ACCESS_FINE_LOCATION);
12551     }
12552 
12553     @Test
12554     public void testCreateForCallerWithLocalMacAddressSanitizedWithoutSettingsPermission()
12555             throws Exception {
12556         mServiceContext.setPermission(Manifest.permission.LOCAL_MAC_ADDRESS, PERMISSION_DENIED);
12557 
12558         final TransportInfo transportInfo = mock(TransportInfo.class);
12559         doReturn(REDACT_FOR_ACCESS_FINE_LOCATION | REDACT_FOR_NETWORK_SETTINGS)
12560                 .when(transportInfo).getApplicableRedactions();
12561         final NetworkCapabilities netCap =
12562                 new NetworkCapabilities().setTransportInfo(transportInfo);
12563 
12564         mService.createWithLocationInfoSanitizedIfNecessaryWhenParceled(
12565                 netCap, false /* includeLocationSensitiveInfoInTransportInfo */,
12566                 Process.myPid(), Process.myUid(),
12567                 mContext.getPackageName(), getAttributionTag());
12568         // redact both NETWORK_SETTINGS & location sensitive fields.
12569         verify(transportInfo).makeCopy(
12570                 REDACT_FOR_ACCESS_FINE_LOCATION | REDACT_FOR_NETWORK_SETTINGS);
12571     }
12572 
12573     /**
12574      * Test TransportInfo to verify redaction mechanism.
12575      */
12576     private static class TestTransportInfo implements TransportInfo {
12577         public final boolean locationRedacted;
12578         public final boolean localMacAddressRedacted;
12579         public final boolean settingsRedacted;
12580 
12581         TestTransportInfo() {
12582             locationRedacted = false;
12583             localMacAddressRedacted = false;
12584             settingsRedacted = false;
12585         }
12586 
12587         TestTransportInfo(boolean locationRedacted, boolean localMacAddressRedacted,
12588                 boolean settingsRedacted) {
12589             this.locationRedacted = locationRedacted;
12590             this.localMacAddressRedacted =
12591                     localMacAddressRedacted;
12592             this.settingsRedacted = settingsRedacted;
12593         }
12594 
12595         @Override
12596         public TransportInfo makeCopy(@NetworkCapabilities.RedactionType long redactions) {
12597             return new TestTransportInfo(
12598                     locationRedacted | (redactions & REDACT_FOR_ACCESS_FINE_LOCATION) != 0,
12599                     localMacAddressRedacted | (redactions & REDACT_FOR_LOCAL_MAC_ADDRESS) != 0,
12600                     settingsRedacted | (redactions & REDACT_FOR_NETWORK_SETTINGS) != 0
12601             );
12602         }
12603 
12604         @Override
12605         public @NetworkCapabilities.RedactionType long getApplicableRedactions() {
12606             return REDACT_FOR_ACCESS_FINE_LOCATION | REDACT_FOR_LOCAL_MAC_ADDRESS
12607                     | REDACT_FOR_NETWORK_SETTINGS;
12608         }
12609 
12610         @Override
12611         public boolean equals(Object other) {
12612             if (!(other instanceof TestTransportInfo)) return false;
12613             TestTransportInfo that = (TestTransportInfo) other;
12614             return that.locationRedacted == this.locationRedacted
12615                     && that.localMacAddressRedacted == this.localMacAddressRedacted
12616                     && that.settingsRedacted == this.settingsRedacted;
12617         }
12618 
12619         @Override
12620         public int hashCode() {
12621             return Objects.hash(locationRedacted, localMacAddressRedacted, settingsRedacted);
12622         }
12623 
12624         @Override
12625         public String toString() {
12626             return String.format(
12627                     "TestTransportInfo{locationRedacted=%s macRedacted=%s settingsRedacted=%s}",
12628                     locationRedacted, localMacAddressRedacted, settingsRedacted);
12629         }
12630     }
12631 
12632     private TestTransportInfo getTestTransportInfo(NetworkCapabilities nc) {
12633         return (TestTransportInfo) nc.getTransportInfo();
12634     }
12635 
12636     private TestTransportInfo getTestTransportInfo(TestNetworkAgentWrapper n) {
12637         final NetworkCapabilities nc = mCm.getNetworkCapabilities(n.getNetwork());
12638         assertNotNull(nc);
12639         return getTestTransportInfo(nc);
12640     }
12641 
12642 
12643     private void verifyNetworkCallbackLocationDataInclusionUsingTransportInfoAndOwnerUidInNetCaps(
12644             @NonNull TestNetworkCallback wifiNetworkCallback, int actualOwnerUid,
12645             @NonNull TransportInfo actualTransportInfo, int expectedOwnerUid,
12646             @NonNull TransportInfo expectedTransportInfo) throws Exception {
12647         doReturn(Build.VERSION_CODES.S).when(mPackageManager).getTargetSdkVersion(anyString());
12648         final NetworkCapabilities ncTemplate =
12649                 new NetworkCapabilities()
12650                         .addTransportType(TRANSPORT_WIFI)
12651                         .setOwnerUid(actualOwnerUid);
12652 
12653         final NetworkRequest wifiRequest = new NetworkRequest.Builder()
12654                 .addTransportType(TRANSPORT_WIFI).build();
12655         mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
12656 
12657         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, new LinkProperties(),
12658                 ncTemplate);
12659         mWiFiAgent.connect(false);
12660 
12661         wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
12662 
12663         // Send network capabilities update with TransportInfo to trigger capabilities changed
12664         // callback.
12665         mWiFiAgent.setNetworkCapabilities(ncTemplate.setTransportInfo(actualTransportInfo), true);
12666 
12667         wifiNetworkCallback.expectCaps(mWiFiAgent,
12668                 c -> Objects.equals(expectedOwnerUid, c.getOwnerUid())
12669                         && Objects.equals(expectedTransportInfo, c.getTransportInfo()));
12670     }
12671 
12672     @Test
12673     public void testVerifyLocationDataIsNotIncludedWhenInclFlagNotSet() throws Exception {
12674         final TestNetworkCallback wifiNetworkCallack = new TestNetworkCallback();
12675         final int ownerUid = Process.myUid();
12676         final TransportInfo transportInfo = new TestTransportInfo();
12677         // Even though the test uid holds privileged permissions, mask location fields since
12678         // the callback did not explicitly opt-in to get location data.
12679         final TransportInfo sanitizedTransportInfo = new TestTransportInfo(
12680                 true, /* locationRedacted */
12681                 true, /* localMacAddressRedacted */
12682                 true /* settingsRedacted */
12683         );
12684         // Should not expect location data since the callback does not set the flag for including
12685         // location data.
12686         verifyNetworkCallbackLocationDataInclusionUsingTransportInfoAndOwnerUidInNetCaps(
12687                 wifiNetworkCallack, ownerUid, transportInfo, INVALID_UID, sanitizedTransportInfo);
12688     }
12689 
12690     @Test
12691     public void testTransportInfoRedactionInSynchronousCalls() throws Exception {
12692         final NetworkCapabilities ncTemplate = new NetworkCapabilities()
12693                 .addTransportType(TRANSPORT_WIFI)
12694                 .setTransportInfo(new TestTransportInfo());
12695 
12696         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, new LinkProperties(), ncTemplate);
12697         mWiFiAgent.connect(true /* validated; waits for callback */);
12698 
12699         // NETWORK_SETTINGS redaction is controlled by the NETWORK_SETTINGS permission
12700         assertTrue(getTestTransportInfo(mWiFiAgent).settingsRedacted);
12701         withPermission(NETWORK_SETTINGS, () -> {
12702             assertFalse(getTestTransportInfo(mWiFiAgent).settingsRedacted);
12703         });
12704         assertTrue(getTestTransportInfo(mWiFiAgent).settingsRedacted);
12705 
12706         // LOCAL_MAC_ADDRESS redaction is controlled by the LOCAL_MAC_ADDRESS permission
12707         assertTrue(getTestTransportInfo(mWiFiAgent).localMacAddressRedacted);
12708         withPermission(LOCAL_MAC_ADDRESS, () -> {
12709             assertFalse(getTestTransportInfo(mWiFiAgent).localMacAddressRedacted);
12710         });
12711         assertTrue(getTestTransportInfo(mWiFiAgent).localMacAddressRedacted);
12712 
12713         // Synchronous getNetworkCapabilities calls never return unredacted location-sensitive
12714         // information.
12715         assertTrue(getTestTransportInfo(mWiFiAgent).locationRedacted);
12716         setupLocationPermissions(Build.VERSION_CODES.S, true, AppOpsManager.OPSTR_FINE_LOCATION,
12717                 Manifest.permission.ACCESS_FINE_LOCATION);
12718         assertTrue(getTestTransportInfo(mWiFiAgent).locationRedacted);
12719         denyAllLocationPrivilegedPermissions();
12720         assertTrue(getTestTransportInfo(mWiFiAgent).locationRedacted);
12721     }
12722 
12723     private void setupConnectionOwnerUid(int vpnOwnerUid, @VpnManager.VpnType int vpnType)
12724             throws Exception {
12725         final Set<UidRange> vpnRange = Collections.singleton(PRIMARY_UIDRANGE);
12726         mMockVpn.setVpnType(vpnType);
12727         mMockVpn.establish(new LinkProperties(), vpnOwnerUid, vpnRange);
12728         assertVpnUidRangesUpdated(true, vpnRange, vpnOwnerUid);
12729 
12730         mDeps.setConnectionOwnerUid(42);
12731     }
12732 
12733     private void setupConnectionOwnerUidAsVpnApp(int vpnOwnerUid, @VpnManager.VpnType int vpnType)
12734             throws Exception {
12735         setupConnectionOwnerUid(vpnOwnerUid, vpnType);
12736 
12737         // Test as VPN app
12738         mServiceContext.setPermission(NETWORK_STACK, PERMISSION_DENIED);
12739         mServiceContext.setPermission(
12740                 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, PERMISSION_DENIED);
12741     }
12742 
12743     private ConnectionInfo getTestConnectionInfo() throws Exception {
12744         return new ConnectionInfo(
12745                 IPPROTO_TCP,
12746                 new InetSocketAddress(InetAddresses.parseNumericAddress("1.2.3.4"), 1234),
12747                 new InetSocketAddress(InetAddresses.parseNumericAddress("2.3.4.5"), 2345));
12748     }
12749 
12750     @Test
12751     public void testGetConnectionOwnerUidPlatformVpn() throws Exception {
12752         final int myUid = Process.myUid();
12753         setupConnectionOwnerUidAsVpnApp(myUid, VpnManager.TYPE_VPN_PLATFORM);
12754 
12755         assertEquals(INVALID_UID, mService.getConnectionOwnerUid(getTestConnectionInfo()));
12756     }
12757 
12758     @Test
12759     public void testGetConnectionOwnerUidVpnServiceWrongUser() throws Exception {
12760         final int myUid = Process.myUid();
12761         setupConnectionOwnerUidAsVpnApp(myUid + 1, VpnManager.TYPE_VPN_SERVICE);
12762 
12763         assertEquals(INVALID_UID, mService.getConnectionOwnerUid(getTestConnectionInfo()));
12764     }
12765 
12766     @Test
12767     public void testGetConnectionOwnerUidVpnServiceDoesNotThrow() throws Exception {
12768         final int myUid = Process.myUid();
12769         setupConnectionOwnerUidAsVpnApp(myUid, VpnManager.TYPE_VPN_SERVICE);
12770 
12771         assertEquals(42, mService.getConnectionOwnerUid(getTestConnectionInfo()));
12772     }
12773 
12774     @Test
12775     public void testGetConnectionOwnerUidVpnServiceNetworkStackDoesNotThrow() throws Exception {
12776         final int myUid = Process.myUid();
12777         setupConnectionOwnerUid(myUid, VpnManager.TYPE_VPN_SERVICE);
12778         mServiceContext.setPermission(NETWORK_STACK, PERMISSION_GRANTED);
12779 
12780         assertEquals(42, mService.getConnectionOwnerUid(getTestConnectionInfo()));
12781     }
12782 
12783     @Test
12784     public void testGetConnectionOwnerUidVpnServiceMainlineNetworkStackDoesNotThrow()
12785             throws Exception {
12786         final int myUid = Process.myUid();
12787         setupConnectionOwnerUid(myUid, VpnManager.TYPE_VPN_SERVICE);
12788         mServiceContext.setPermission(
12789                 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, PERMISSION_GRANTED);
12790 
12791         assertEquals(42, mService.getConnectionOwnerUid(getTestConnectionInfo()));
12792     }
12793 
12794     private static PackageInfo buildPackageInfo(boolean hasSystemPermission, int uid) {
12795         final PackageInfo packageInfo = new PackageInfo();
12796         if (hasSystemPermission) {
12797             packageInfo.requestedPermissions = new String[] {
12798                     CHANGE_NETWORK_STATE, CONNECTIVITY_USE_RESTRICTED_NETWORKS };
12799             packageInfo.requestedPermissionsFlags = new int[] {
12800                     REQUESTED_PERMISSION_GRANTED, REQUESTED_PERMISSION_GRANTED };
12801         } else {
12802             packageInfo.requestedPermissions = new String[0];
12803         }
12804         packageInfo.applicationInfo = new ApplicationInfo();
12805         packageInfo.applicationInfo.privateFlags = 0;
12806         packageInfo.applicationInfo.uid = UserHandle.getUid(UserHandle.USER_SYSTEM,
12807                 UserHandle.getAppId(uid));
12808         return packageInfo;
12809     }
12810 
12811     @Test
12812     public void testRegisterConnectivityDiagnosticsCallbackInvalidRequest() throws Exception {
12813         final NetworkRequest request =
12814                 new NetworkRequest(
12815                         new NetworkCapabilities(), TYPE_ETHERNET, 0, NetworkRequest.Type.NONE);
12816         try {
12817             mService.registerConnectivityDiagnosticsCallback(
12818                     mConnectivityDiagnosticsCallback, request, mContext.getPackageName());
12819             fail("registerConnectivityDiagnosticsCallback should throw on invalid NetworkRequest");
12820         } catch (IllegalArgumentException expected) {
12821         }
12822     }
12823 
12824     private void assertRouteInfoParcelMatches(RouteInfo route, RouteInfoParcel parcel) {
12825         assertEquals(route.getDestination().toString(), parcel.destination);
12826         assertEquals(route.getInterface(), parcel.ifName);
12827         assertEquals(route.getMtu(), parcel.mtu);
12828 
12829         switch (route.getType()) {
12830             case RouteInfo.RTN_UNICAST:
12831                 if (route.hasGateway()) {
12832                     assertEquals(route.getGateway().getHostAddress(), parcel.nextHop);
12833                 } else {
12834                     assertEquals(INetd.NEXTHOP_NONE, parcel.nextHop);
12835                 }
12836                 break;
12837             case RouteInfo.RTN_UNREACHABLE:
12838                 assertEquals(INetd.NEXTHOP_UNREACHABLE, parcel.nextHop);
12839                 break;
12840             case RouteInfo.RTN_THROW:
12841                 assertEquals(INetd.NEXTHOP_THROW, parcel.nextHop);
12842                 break;
12843             default:
12844                 assertEquals(INetd.NEXTHOP_NONE, parcel.nextHop);
12845                 break;
12846         }
12847     }
12848 
12849     private void assertRoutesAdded(int netId, RouteInfo... routes) throws Exception {
12850         // TODO: add @JavaDerive(equals=true) to RouteInfoParcel, use eq() directly, and delete
12851         // assertRouteInfoParcelMatches above.
12852         ArgumentCaptor<RouteInfoParcel> captor = ArgumentCaptor.forClass(RouteInfoParcel.class);
12853         verify(mMockNetd, times(routes.length)).networkAddRouteParcel(eq(netId), captor.capture());
12854         for (int i = 0; i < routes.length; i++) {
12855             assertRouteInfoParcelMatches(routes[i], captor.getAllValues().get(i));
12856         }
12857     }
12858 
12859     private void assertRoutesRemoved(int netId, RouteInfo... routes) throws Exception {
12860         ArgumentCaptor<RouteInfoParcel> captor = ArgumentCaptor.forClass(RouteInfoParcel.class);
12861         verify(mMockNetd, times(routes.length)).networkRemoveRouteParcel(eq(netId),
12862                 captor.capture());
12863         for (int i = 0; i < routes.length; i++) {
12864             assertRouteInfoParcelMatches(routes[i], captor.getAllValues().get(i));
12865         }
12866     }
12867 
12868     @Test
12869     public void testRegisterUnregisterConnectivityDiagnosticsCallback() throws Exception {
12870         final NetworkRequest wifiRequest =
12871                 new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI).build();
12872         doReturn(mIBinder).when(mConnectivityDiagnosticsCallback).asBinder();
12873 
12874         mService.registerConnectivityDiagnosticsCallback(
12875                 mConnectivityDiagnosticsCallback, wifiRequest, mContext.getPackageName());
12876 
12877         // Block until all other events are done processing.
12878         HandlerUtils.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
12879 
12880         verify(mIBinder).linkToDeath(any(ConnectivityDiagnosticsCallbackInfo.class), anyInt());
12881         verify(mConnectivityDiagnosticsCallback).asBinder();
12882         assertTrue(mService.mConnectivityDiagnosticsCallbacks.containsKey(mIBinder));
12883 
12884         mService.unregisterConnectivityDiagnosticsCallback(mConnectivityDiagnosticsCallback);
12885         verify(mIBinder, timeout(TIMEOUT_MS))
12886                 .unlinkToDeath(any(ConnectivityDiagnosticsCallbackInfo.class), anyInt());
12887         assertFalse(mService.mConnectivityDiagnosticsCallbacks.containsKey(mIBinder));
12888         verify(mConnectivityDiagnosticsCallback, atLeastOnce()).asBinder();
12889     }
12890 
12891     @Test
12892     public void testRegisterDuplicateConnectivityDiagnosticsCallback() throws Exception {
12893         final NetworkRequest wifiRequest =
12894                 new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI).build();
12895         doReturn(mIBinder).when(mConnectivityDiagnosticsCallback).asBinder();
12896 
12897         mService.registerConnectivityDiagnosticsCallback(
12898                 mConnectivityDiagnosticsCallback, wifiRequest, mContext.getPackageName());
12899 
12900         // Block until all other events are done processing.
12901         HandlerUtils.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
12902 
12903         verify(mIBinder).linkToDeath(any(ConnectivityDiagnosticsCallbackInfo.class), anyInt());
12904         verify(mConnectivityDiagnosticsCallback).asBinder();
12905         assertTrue(mService.mConnectivityDiagnosticsCallbacks.containsKey(mIBinder));
12906 
12907         // Register the same callback again
12908         mService.registerConnectivityDiagnosticsCallback(
12909                 mConnectivityDiagnosticsCallback, wifiRequest, mContext.getPackageName());
12910 
12911         // Block until all other events are done processing.
12912         HandlerUtils.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
12913 
12914         assertTrue(mService.mConnectivityDiagnosticsCallbacks.containsKey(mIBinder));
12915     }
12916 
12917     @Test(expected = NullPointerException.class)
12918     public void testRegisterConnectivityDiagnosticsCallbackNullCallback() {
12919         mService.registerConnectivityDiagnosticsCallback(
12920                 null /* callback */,
12921                 new NetworkRequest.Builder().build(),
12922                 mContext.getPackageName());
12923     }
12924 
12925     @Test(expected = NullPointerException.class)
12926     public void testRegisterConnectivityDiagnosticsCallbackNullNetworkRequest() {
12927         mService.registerConnectivityDiagnosticsCallback(
12928                 mConnectivityDiagnosticsCallback,
12929                 null /* request */,
12930                 mContext.getPackageName());
12931     }
12932 
12933     @Test(expected = NullPointerException.class)
12934     public void testRegisterConnectivityDiagnosticsCallbackNullPackageName() {
12935         mService.registerConnectivityDiagnosticsCallback(
12936                 mConnectivityDiagnosticsCallback,
12937                 new NetworkRequest.Builder().build(),
12938                 null /* callingPackageName */);
12939     }
12940 
12941     @Test(expected = NullPointerException.class)
12942     public void testUnregisterConnectivityDiagnosticsCallbackNullPackageName() {
12943         mService.unregisterConnectivityDiagnosticsCallback(null /* callback */);
12944     }
12945 
12946     public NetworkAgentInfo fakeMobileNai(NetworkCapabilities nc) {
12947         final NetworkCapabilities cellNc = new NetworkCapabilities.Builder(nc)
12948                 .addTransportType(TRANSPORT_CELLULAR).build();
12949         final NetworkInfo info = new NetworkInfo(TYPE_MOBILE, TelephonyManager.NETWORK_TYPE_LTE,
12950                 ConnectivityManager.getNetworkTypeName(TYPE_MOBILE),
12951                 TelephonyManager.getNetworkTypeName(TelephonyManager.NETWORK_TYPE_LTE));
12952         return fakeNai(cellNc, info);
12953     }
12954 
12955     private NetworkAgentInfo fakeWifiNai(NetworkCapabilities nc) {
12956         final NetworkCapabilities wifiNc = new NetworkCapabilities.Builder(nc)
12957                 .addTransportType(TRANSPORT_WIFI).build();
12958         final NetworkInfo info = new NetworkInfo(TYPE_WIFI, 0 /* subtype */,
12959                 ConnectivityManager.getNetworkTypeName(TYPE_WIFI), "" /* subtypeName */);
12960         return fakeNai(wifiNc, info);
12961     }
12962 
12963     private NetworkAgentInfo fakeVpnNai(NetworkCapabilities nc) {
12964         final NetworkCapabilities vpnNc = new NetworkCapabilities.Builder(nc)
12965                 .addTransportType(TRANSPORT_VPN).build();
12966         final NetworkInfo info = new NetworkInfo(TYPE_VPN, 0 /* subtype */,
12967                 ConnectivityManager.getNetworkTypeName(TYPE_VPN), "" /* subtypeName */);
12968         return fakeNai(vpnNc, info);
12969     }
12970 
12971     private NetworkAgentInfo fakeNai(NetworkCapabilities nc, NetworkInfo networkInfo) {
12972         return new NetworkAgentInfo(null, new Network(NET_ID), networkInfo, new LinkProperties(),
12973                 nc, null /* localNetworkConfig */,
12974                 new NetworkScore.Builder().setLegacyInt(0).build(),
12975                 mServiceContext, null, new NetworkAgentConfig(), mService, null, null, 0,
12976                 INVALID_UID, TEST_LINGER_DELAY_MS, mQosCallbackTracker,
12977                 new ConnectivityService.Dependencies());
12978     }
12979 
12980     @Test
12981     public void testCheckConnectivityDiagnosticsPermissionsNetworkStack() throws Exception {
12982         final NetworkAgentInfo naiWithoutUid = fakeMobileNai(new NetworkCapabilities());
12983 
12984         mServiceContext.setPermission(NETWORK_STACK, PERMISSION_GRANTED);
12985         assertTrue(
12986                 "NetworkStack permission not applied",
12987                 mService.hasConnectivityDiagnosticsPermissions(
12988                         Process.myPid(), Process.myUid(), naiWithoutUid,
12989                         mContext.getOpPackageName()));
12990     }
12991 
12992     @Test
12993     public void testCheckConnectivityDiagnosticsPermissionsSysUi() throws Exception {
12994         final NetworkAgentInfo naiWithoutUid = fakeMobileNai(new NetworkCapabilities());
12995 
12996         mServiceContext.setPermission(STATUS_BAR_SERVICE, PERMISSION_GRANTED);
12997         assertTrue(
12998                 "SysUi permission (STATUS_BAR_SERVICE) not applied",
12999                 mService.hasConnectivityDiagnosticsPermissions(
13000                         Process.myPid(), Process.myUid(), naiWithoutUid,
13001                         mContext.getOpPackageName()));
13002     }
13003 
13004     @Test
13005     public void testCheckConnectivityDiagnosticsPermissionsWrongUidPackageName() throws Exception {
13006         final int wrongUid = Process.myUid() + 1;
13007 
13008         final NetworkCapabilities nc = new NetworkCapabilities();
13009         nc.setAdministratorUids(new int[] {wrongUid});
13010         final NetworkAgentInfo naiWithUid = fakeWifiNai(nc);
13011 
13012         mServiceContext.setPermission(NETWORK_STACK, PERMISSION_DENIED);
13013 
13014         assertFalse(
13015                 "Mismatched uid/package name should not pass the location permission check",
13016                 mService.hasConnectivityDiagnosticsPermissions(
13017                         Process.myPid() + 1, wrongUid, naiWithUid, mContext.getOpPackageName()));
13018     }
13019 
13020     private void verifyConnectivityDiagnosticsPermissionsWithNetworkAgentInfo(
13021             NetworkAgentInfo info, boolean expectPermission) {
13022         mServiceContext.setPermission(NETWORK_STACK, PERMISSION_DENIED);
13023 
13024         assertEquals(
13025                 "Unexpected ConnDiags permission",
13026                 expectPermission,
13027                 mService.hasConnectivityDiagnosticsPermissions(
13028                         Process.myPid(), Process.myUid(), info, mContext.getOpPackageName()));
13029     }
13030 
13031     @Test
13032     public void testCheckConnectivityDiagnosticsPermissionsCellularNoLocationPermission()
13033             throws Exception {
13034         final NetworkCapabilities nc = new NetworkCapabilities();
13035         nc.setAdministratorUids(new int[] {Process.myUid()});
13036         final NetworkAgentInfo naiWithUid = fakeMobileNai(nc);
13037 
13038         verifyConnectivityDiagnosticsPermissionsWithNetworkAgentInfo(naiWithUid,
13039                 true /* expectPermission */);
13040     }
13041 
13042     @Test
13043     public void testCheckConnectivityDiagnosticsPermissionsWifiNoLocationPermission()
13044             throws Exception {
13045         final NetworkCapabilities nc = new NetworkCapabilities();
13046         nc.setAdministratorUids(new int[] {Process.myUid()});
13047         final NetworkAgentInfo naiWithUid = fakeWifiNai(nc);
13048 
13049         verifyConnectivityDiagnosticsPermissionsWithNetworkAgentInfo(naiWithUid,
13050                 false /* expectPermission */);
13051     }
13052 
13053     @Test
13054     public void testCheckConnectivityDiagnosticsPermissionsActiveVpn() throws Exception {
13055         final NetworkAgentInfo naiWithoutUid = fakeMobileNai(new NetworkCapabilities());
13056 
13057         mMockVpn.establishForMyUid();
13058         assertUidRangesUpdatedForMyUid(true);
13059 
13060         // Wait for networks to connect and broadcasts to be sent before removing permissions.
13061         waitForIdle();
13062         setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
13063                 Manifest.permission.ACCESS_FINE_LOCATION);
13064 
13065         assertTrue(mMockVpn.setUnderlyingNetworks(new Network[] {naiWithoutUid.network}));
13066         waitForIdle();
13067         assertTrue(
13068                 "Active VPN permission not applied",
13069                 mService.hasConnectivityDiagnosticsPermissions(
13070                         Process.myPid(), Process.myUid(), naiWithoutUid,
13071                         mContext.getOpPackageName()));
13072 
13073         assertTrue(mMockVpn.setUnderlyingNetworks(null));
13074         waitForIdle();
13075         assertFalse(
13076                 "VPN shouldn't receive callback on non-underlying network",
13077                 mService.hasConnectivityDiagnosticsPermissions(
13078                         Process.myPid(), Process.myUid(), naiWithoutUid,
13079                         mContext.getOpPackageName()));
13080     }
13081 
13082     @Test
13083     public void testCheckConnectivityDiagnosticsPermissionsNetworkAdministrator() throws Exception {
13084         final NetworkCapabilities nc = new NetworkCapabilities();
13085         nc.setAdministratorUids(new int[] {Process.myUid()});
13086         final NetworkAgentInfo naiWithUid = fakeMobileNai(nc);
13087 
13088         setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
13089                 Manifest.permission.ACCESS_FINE_LOCATION);
13090         mServiceContext.setPermission(NETWORK_STACK, PERMISSION_DENIED);
13091 
13092         assertTrue(
13093                 "NetworkCapabilities administrator uid permission not applied",
13094                 mService.hasConnectivityDiagnosticsPermissions(
13095                         Process.myPid(), Process.myUid(), naiWithUid, mContext.getOpPackageName()));
13096     }
13097 
13098     @Test
13099     public void testCheckConnectivityDiagnosticsPermissionsFails() throws Exception {
13100         final NetworkCapabilities nc = new NetworkCapabilities();
13101         nc.setOwnerUid(Process.myUid());
13102         nc.setAdministratorUids(new int[] {Process.myUid()});
13103         final NetworkAgentInfo naiWithUid = fakeMobileNai(nc);
13104 
13105         setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
13106                 Manifest.permission.ACCESS_FINE_LOCATION);
13107         mServiceContext.setPermission(NETWORK_STACK, PERMISSION_DENIED);
13108 
13109         // Use wrong pid and uid
13110         assertFalse(
13111                 "Permissions allowed when they shouldn't be granted",
13112                 mService.hasConnectivityDiagnosticsPermissions(
13113                         Process.myPid() + 1, Process.myUid() + 1, naiWithUid,
13114                         mContext.getOpPackageName()));
13115     }
13116 
13117     @Test
13118     public void testUnderlyingNetworksWillBeSetInNetworkAgentInfoConstructor() throws Exception {
13119         assumeTrue(mDeps.isAtLeastT());
13120         final Network network1 = new Network(100);
13121         final Network network2 = new Network(101);
13122         final List<Network> underlyingNetworks = new ArrayList<>();
13123         final NetworkCapabilities ncWithEmptyUnderlyingNetworks = new NetworkCapabilities.Builder()
13124                 .setUnderlyingNetworks(underlyingNetworks)
13125                 .build();
13126         final NetworkAgentInfo vpnNaiWithEmptyUnderlyingNetworks =
13127                 fakeVpnNai(ncWithEmptyUnderlyingNetworks);
13128         assertEquals(underlyingNetworks,
13129                 Arrays.asList(vpnNaiWithEmptyUnderlyingNetworks.declaredUnderlyingNetworks));
13130 
13131         underlyingNetworks.add(network1);
13132         underlyingNetworks.add(network2);
13133         final NetworkCapabilities ncWithUnderlyingNetworks = new NetworkCapabilities.Builder()
13134                 .setUnderlyingNetworks(underlyingNetworks)
13135                 .build();
13136         final NetworkAgentInfo vpnNaiWithUnderlyingNetwokrs = fakeVpnNai(ncWithUnderlyingNetworks);
13137         assertEquals(underlyingNetworks,
13138                 Arrays.asList(vpnNaiWithUnderlyingNetwokrs.declaredUnderlyingNetworks));
13139 
13140         final NetworkCapabilities ncWithoutUnderlyingNetworks = new NetworkCapabilities.Builder()
13141                 .build();
13142         final NetworkAgentInfo vpnNaiWithoutUnderlyingNetwokrs =
13143                 fakeVpnNai(ncWithoutUnderlyingNetworks);
13144         assertNull(vpnNaiWithoutUnderlyingNetwokrs.declaredUnderlyingNetworks);
13145     }
13146 
13147     @Test
13148     public void testRegisterConnectivityDiagnosticsCallbackCallsOnConnectivityReport()
13149             throws Exception {
13150         // Set up the Network, which leads to a ConnectivityReport being cached for the network.
13151         final TestNetworkCallback callback = new TestNetworkCallback();
13152         mCm.registerDefaultNetworkCallback(callback);
13153         final LinkProperties linkProperties = new LinkProperties();
13154         linkProperties.setInterfaceName(INTERFACE_NAME);
13155         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, linkProperties);
13156         mCellAgent.connect(true);
13157         callback.expectAvailableThenValidatedCallbacks(mCellAgent);
13158         callback.assertNoCallback();
13159 
13160         final NetworkRequest request = new NetworkRequest.Builder().build();
13161         doReturn(mIBinder).when(mConnectivityDiagnosticsCallback).asBinder();
13162 
13163         mServiceContext.setPermission(NETWORK_STACK, PERMISSION_GRANTED);
13164 
13165         mService.registerConnectivityDiagnosticsCallback(
13166                 mConnectivityDiagnosticsCallback, request, mContext.getPackageName());
13167 
13168         verify(mConnectivityDiagnosticsCallback, timeout(TIMEOUT_MS))
13169                 .onConnectivityReportAvailable(argThat(report -> {
13170                     return INTERFACE_NAME.equals(report.getLinkProperties().getInterfaceName())
13171                             && report.getNetworkCapabilities().hasTransport(TRANSPORT_CELLULAR);
13172                 }));
13173     }
13174 
13175     private void setUpConnectivityDiagnosticsCallback() throws Exception {
13176         final NetworkRequest request = new NetworkRequest.Builder().build();
13177         doReturn(mIBinder).when(mConnectivityDiagnosticsCallback).asBinder();
13178 
13179         mServiceContext.setPermission(NETWORK_STACK, PERMISSION_GRANTED);
13180 
13181         mService.registerConnectivityDiagnosticsCallback(
13182                 mConnectivityDiagnosticsCallback, request, mContext.getPackageName());
13183 
13184         // Block until all other events are done processing.
13185         HandlerUtils.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
13186 
13187         // Connect the cell agent verify that it notifies TestNetworkCallback that it is available
13188         final TestNetworkCallback callback = new TestNetworkCallback();
13189         mCm.registerDefaultNetworkCallback(callback);
13190 
13191         final NetworkCapabilities ncTemplate = new NetworkCapabilities()
13192                 .addTransportType(TRANSPORT_CELLULAR)
13193                 .setTransportInfo(new TestTransportInfo());
13194         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, new LinkProperties(),
13195                 ncTemplate);
13196         mCellAgent.connect(true);
13197         callback.expectAvailableThenValidatedCallbacks(mCellAgent);
13198         callback.assertNoCallback();
13199 
13200         // Make sure a report is sent and that the caps are suitably redacted.
13201         verify(mConnectivityDiagnosticsCallback, timeout(TIMEOUT_MS))
13202                 .onConnectivityReportAvailable(argThat(report ->
13203                         areConnDiagCapsRedacted(report.getNetworkCapabilities())));
13204         reset(mConnectivityDiagnosticsCallback);
13205     }
13206 
13207     private boolean areConnDiagCapsRedacted(NetworkCapabilities nc) {
13208         TestTransportInfo ti = getTestTransportInfo(nc);
13209         return nc.getUids() == null
13210                 && nc.getAdministratorUids().length == 0
13211                 && nc.getOwnerUid() == Process.INVALID_UID
13212                 && ti.locationRedacted
13213                 && ti.localMacAddressRedacted
13214                 && ti.settingsRedacted;
13215     }
13216 
13217     @Test
13218     public void testConnectivityDiagnosticsCallbackOnDataStallSuspected() throws Exception {
13219         setUpConnectivityDiagnosticsCallback();
13220 
13221         // Trigger notifyDataStallSuspected() on the INetworkMonitorCallbacks instance in the
13222         // cellular network agent
13223         mCellAgent.notifyDataStallSuspected();
13224 
13225         // Verify onDataStallSuspected fired
13226         verify(mConnectivityDiagnosticsCallback, timeout(TIMEOUT_MS)).onDataStallSuspected(
13227                 argThat(report -> areConnDiagCapsRedacted(report.getNetworkCapabilities())));
13228     }
13229 
13230     @Test
13231     public void testConnectivityDiagnosticsCallbackOnConnectivityReported() throws Exception {
13232         setUpConnectivityDiagnosticsCallback();
13233 
13234         final Network n = mCellAgent.getNetwork();
13235         final boolean hasConnectivity = true;
13236         mService.reportNetworkConnectivity(n, hasConnectivity);
13237 
13238         // Verify onNetworkConnectivityReported fired
13239         verify(mConnectivityDiagnosticsCallback, timeout(TIMEOUT_MS))
13240                 .onNetworkConnectivityReported(eq(n), eq(hasConnectivity));
13241         verify(mConnectivityDiagnosticsCallback, timeout(TIMEOUT_MS))
13242                 .onConnectivityReportAvailable(
13243                         argThat(report ->
13244                                 areConnDiagCapsRedacted(report.getNetworkCapabilities())));
13245 
13246         final boolean noConnectivity = false;
13247         mService.reportNetworkConnectivity(n, noConnectivity);
13248 
13249         // Wait for onNetworkConnectivityReported to fire
13250         verify(mConnectivityDiagnosticsCallback, timeout(TIMEOUT_MS))
13251                 .onNetworkConnectivityReported(eq(n), eq(noConnectivity));
13252 
13253         // Also expect a ConnectivityReport after NetworkMonitor asynchronously re-validates
13254         verify(mConnectivityDiagnosticsCallback, timeout(TIMEOUT_MS).times(2))
13255                 .onConnectivityReportAvailable(
13256                         argThat(report ->
13257                                 areConnDiagCapsRedacted(report.getNetworkCapabilities())));
13258     }
13259 
13260     @Test
13261     public void testConnectivityDiagnosticsCallbackOnConnectivityReportedSeparateUid()
13262             throws Exception {
13263         setUpConnectivityDiagnosticsCallback();
13264 
13265         // report known Connectivity from a different uid. Verify that network is not re-validated
13266         // and this callback is not notified.
13267         final Network n = mCellAgent.getNetwork();
13268         final boolean hasConnectivity = true;
13269         doAsUid(Process.myUid() + 1, () -> mService.reportNetworkConnectivity(n, hasConnectivity));
13270 
13271         // Block until all other events are done processing.
13272         HandlerUtils.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
13273 
13274         // Verify onNetworkConnectivityReported did not fire
13275         verify(mConnectivityDiagnosticsCallback, never())
13276                 .onNetworkConnectivityReported(any(), anyBoolean());
13277         verify(mConnectivityDiagnosticsCallback, never())
13278                 .onConnectivityReportAvailable(any());
13279 
13280         // report different Connectivity from a different uid. Verify that network is re-validated
13281         // and that this callback is notified.
13282         final boolean noConnectivity = false;
13283         doAsUid(Process.myUid() + 1, () -> mService.reportNetworkConnectivity(n, noConnectivity));
13284 
13285         // Wait for onNetworkConnectivityReported to fire
13286         verify(mConnectivityDiagnosticsCallback, timeout(TIMEOUT_MS))
13287                 .onNetworkConnectivityReported(eq(n), eq(noConnectivity));
13288 
13289         // Also expect a ConnectivityReport after NetworkMonitor asynchronously re-validates
13290         verify(mConnectivityDiagnosticsCallback, timeout(TIMEOUT_MS))
13291                 .onConnectivityReportAvailable(
13292                         argThat(report ->
13293                                 areConnDiagCapsRedacted(report.getNetworkCapabilities())));
13294     }
13295 
13296     @Test(expected = NullPointerException.class)
13297     public void testSimulateDataStallNullNetwork() {
13298         mService.simulateDataStall(
13299                 DataStallReport.DETECTION_METHOD_DNS_EVENTS,
13300                 0L /* timestampMillis */,
13301                 null /* network */,
13302                 new PersistableBundle());
13303     }
13304 
13305     @Test(expected = NullPointerException.class)
13306     public void testSimulateDataStallNullPersistableBundle() {
13307         mService.simulateDataStall(
13308                 DataStallReport.DETECTION_METHOD_DNS_EVENTS,
13309                 0L /* timestampMillis */,
13310                 mock(Network.class),
13311                 null /* extras */);
13312     }
13313 
13314     @Test
13315     public void testRouteAddDeleteUpdate() throws Exception {
13316         final NetworkRequest request = new NetworkRequest.Builder().build();
13317         final TestNetworkCallback networkCallback = new TestNetworkCallback();
13318         mCm.registerNetworkCallback(request, networkCallback);
13319         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
13320         reset(mMockNetd);
13321         mCellAgent.connect(false);
13322         networkCallback.expectAvailableCallbacksUnvalidated(mCellAgent);
13323         final int netId = mCellAgent.getNetwork().netId;
13324 
13325         final String iface = "rmnet_data0";
13326         final InetAddress gateway = InetAddress.getByName("fe80::5678");
13327         RouteInfo direct = RouteInfo.makeHostRoute(gateway, iface);
13328         RouteInfo rio1 = new RouteInfo(new IpPrefix("2001:db8:1::/48"), gateway, iface);
13329         RouteInfo rio2 = new RouteInfo(new IpPrefix("2001:db8:2::/48"), gateway, iface);
13330         RouteInfo defaultRoute = new RouteInfo((IpPrefix) null, gateway, iface);
13331         RouteInfo defaultWithMtu = new RouteInfo(null, gateway, iface, RouteInfo.RTN_UNICAST,
13332                                                  1280 /* mtu */);
13333 
13334         // Send LinkProperties and check that we ask netd to add routes.
13335         LinkProperties lp = new LinkProperties();
13336         lp.setInterfaceName(iface);
13337         lp.addRoute(direct);
13338         lp.addRoute(rio1);
13339         lp.addRoute(defaultRoute);
13340         mCellAgent.sendLinkProperties(lp);
13341         networkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent,
13342                 x -> x.getLp().getRoutes().size() == 3);
13343 
13344         assertRoutesAdded(netId, direct, rio1, defaultRoute);
13345         reset(mMockNetd);
13346 
13347         // Send updated LinkProperties and check that we ask netd to add, remove, update routes.
13348         assertTrue(lp.getRoutes().contains(defaultRoute));
13349         lp.removeRoute(rio1);
13350         lp.addRoute(rio2);
13351         lp.addRoute(defaultWithMtu);
13352         // Ensure adding the same route with a different MTU replaces the previous route.
13353         assertFalse(lp.getRoutes().contains(defaultRoute));
13354         assertTrue(lp.getRoutes().contains(defaultWithMtu));
13355 
13356         mCellAgent.sendLinkProperties(lp);
13357         networkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent,
13358                 x -> x.getLp().getRoutes().contains(rio2));
13359 
13360         assertRoutesRemoved(netId, rio1);
13361         assertRoutesAdded(netId, rio2);
13362 
13363         ArgumentCaptor<RouteInfoParcel> captor = ArgumentCaptor.forClass(RouteInfoParcel.class);
13364         verify(mMockNetd).networkUpdateRouteParcel(eq(netId), captor.capture());
13365         assertRouteInfoParcelMatches(defaultWithMtu, captor.getValue());
13366 
13367 
13368         mCm.unregisterNetworkCallback(networkCallback);
13369     }
13370 
13371     private void verifyDump(String[] args) {
13372         final StringWriter stringWriter = new StringWriter();
13373         mService.dump(new FileDescriptor(), new PrintWriter(stringWriter), args);
13374         assertFalse(stringWriter.toString().isEmpty());
13375     }
13376 
13377     @Test
13378     public void testDumpDoesNotCrash() throws Exception {
13379         mServiceContext.setPermission(DUMP, PERMISSION_GRANTED);
13380         // Filing a couple requests prior to testing the dump.
13381         final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback();
13382         final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
13383         final NetworkRequest genericRequest = new NetworkRequest.Builder()
13384                 .clearCapabilities().build();
13385         final NetworkRequest wifiRequest = new NetworkRequest.Builder()
13386                 .addTransportType(TRANSPORT_WIFI).build();
13387         mCm.registerNetworkCallback(genericRequest, genericNetworkCallback);
13388         mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
13389 
13390         // NetworkProvider
13391         final NetworkProvider wifiProvider = new NetworkProvider(mServiceContext,
13392                 mCsHandlerThread.getLooper(), "Wifi provider");
13393         mCm.registerNetworkProvider(wifiProvider);
13394 
13395         // NetworkAgent
13396         final LinkProperties wifiLp = new LinkProperties();
13397         wifiLp.setInterfaceName(WIFI_IFNAME);
13398         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp);
13399         mWiFiAgent.connect(true);
13400 
13401         // NetworkOffer
13402         final NetworkScore wifiScore = new NetworkScore.Builder().build();
13403         final NetworkCapabilities wifiCaps = new NetworkCapabilities.Builder()
13404                 .addTransportType(TRANSPORT_WIFI)
13405                 .addCapability(NET_CAPABILITY_INTERNET)
13406                 .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
13407                 .build();
13408         final TestableNetworkOfferCallback wifiCallback = new TestableNetworkOfferCallback(
13409                 TIMEOUT_MS /* timeout */, TEST_CALLBACK_TIMEOUT_MS /* noCallbackTimeout */);
13410         wifiProvider.registerNetworkOffer(wifiScore, wifiCaps, r -> r.run(), wifiCallback);
13411 
13412         // Profile preferences
13413         final UserHandle testHandle = setupEnterpriseNetwork();
13414         final TestNetworkAgentWrapper workAgent = makeEnterpriseNetworkAgent();
13415         workAgent.connect(true);
13416         mCm.setProfileNetworkPreference(testHandle, PROFILE_NETWORK_PREFERENCE_ENTERPRISE,
13417                 null /* executor */, null /* listener */);
13418 
13419         // OEM preferences
13420         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
13421                 OEM_NETWORK_PREFERENCE_OEM_PAID;
13422         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true);
13423         setOemNetworkPreference(networkPref, TEST_PACKAGE_NAME);
13424 
13425         // Mobile data preferred UIDs
13426         setAndUpdateMobileDataPreferredUids(Set.of(TEST_PACKAGE_UID));
13427 
13428         verifyDump(new String[0]);
13429 
13430         // Verify dump with arguments.
13431         final String dumpPrio = "--dump-priority";
13432         final String[] dumpArgs = {dumpPrio};
13433         verifyDump(dumpArgs);
13434 
13435         final String[] highDumpArgs = {dumpPrio, "HIGH"};
13436         verifyDump(highDumpArgs);
13437 
13438         final String[] normalDumpArgs = {dumpPrio, "NORMAL"};
13439         verifyDump(normalDumpArgs);
13440 
13441         // Invalid args should do dumpNormal w/o exception
13442         final String[] unknownDumpArgs = {dumpPrio, "UNKNOWN"};
13443         verifyDump(unknownDumpArgs);
13444 
13445         final String[] invalidDumpArgs = {"UNKNOWN"};
13446         verifyDump(invalidDumpArgs);
13447     }
13448 
13449     @Test
13450     public void testRequestsSortedByIdSortsCorrectly() {
13451         final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback();
13452         final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
13453         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
13454         final NetworkRequest genericRequest = new NetworkRequest.Builder()
13455                 .clearCapabilities().build();
13456         final NetworkRequest wifiRequest = new NetworkRequest.Builder()
13457                 .addTransportType(TRANSPORT_WIFI).build();
13458         final NetworkRequest cellRequest = new NetworkRequest.Builder()
13459                 .addTransportType(TRANSPORT_CELLULAR).build();
13460         mCm.registerNetworkCallback(genericRequest, genericNetworkCallback);
13461         mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
13462         mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
13463         waitForIdle();
13464 
13465         final NetworkRequestInfo[] nriOutput = mService.requestsSortedById();
13466 
13467         assertTrue(nriOutput.length > 1);
13468         for (int i = 0; i < nriOutput.length - 1; i++) {
13469             final boolean isRequestIdInOrder =
13470                     nriOutput[i].mRequests.get(0).requestId
13471                             < nriOutput[i + 1].mRequests.get(0).requestId;
13472             assertTrue(isRequestIdInOrder);
13473         }
13474     }
13475 
13476     private void assertUidRangesUpdatedForMyUid(boolean add) throws Exception {
13477         final int uid = Process.myUid();
13478         assertVpnUidRangesUpdated(add, uidRangesForUids(uid), uid);
13479     }
13480 
13481     private void assertVpnUidRangesUpdated(boolean add, Set<UidRange> vpnRanges, int exemptUid)
13482             throws Exception {
13483         InOrder inOrder = inOrder(mMockNetd, mDestroySocketsWrapper);
13484         final Set<Integer> exemptUidSet = new ArraySet<>(List.of(exemptUid, Process.VPN_UID));
13485         ArgumentCaptor<int[]> exemptUidCaptor = ArgumentCaptor.forClass(int[].class);
13486 
13487         if (mDeps.isAtLeastU()) {
13488             inOrder.verify(mDestroySocketsWrapper).destroyLiveTcpSockets(
13489                     UidRange.toIntRanges(vpnRanges), exemptUidSet);
13490         } else {
13491             inOrder.verify(mMockNetd).socketDestroy(eq(toUidRangeStableParcels(vpnRanges)),
13492                     exemptUidCaptor.capture());
13493             assertContainsExactly(exemptUidCaptor.getValue(), Process.VPN_UID, exemptUid);
13494         }
13495 
13496         if (add) {
13497             inOrder.verify(mMockNetd, times(1)).networkAddUidRangesParcel(
13498                     new NativeUidRangeConfig(mMockVpn.getNetwork().getNetId(),
13499                             toUidRangeStableParcels(vpnRanges), PREFERENCE_ORDER_VPN));
13500         } else {
13501             inOrder.verify(mMockNetd, times(1)).networkRemoveUidRangesParcel(
13502                     new NativeUidRangeConfig(mMockVpn.getNetwork().getNetId(),
13503                             toUidRangeStableParcels(vpnRanges), PREFERENCE_ORDER_VPN));
13504         }
13505 
13506         if (mDeps.isAtLeastU()) {
13507             inOrder.verify(mDestroySocketsWrapper).destroyLiveTcpSockets(
13508                     UidRange.toIntRanges(vpnRanges), exemptUidSet);
13509         } else {
13510             inOrder.verify(mMockNetd).socketDestroy(eq(toUidRangeStableParcels(vpnRanges)),
13511                     exemptUidCaptor.capture());
13512             assertContainsExactly(exemptUidCaptor.getValue(), Process.VPN_UID, exemptUid);
13513         }
13514     }
13515 
13516     @Test
13517     public void testVpnUidRangesUpdate() throws Exception {
13518         // Set up a WiFi network without proxy.
13519         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
13520         mWiFiAgent.connect(true);
13521         assertNull(mService.getProxyForNetwork(null));
13522         assertNull(mCm.getDefaultProxy());
13523 
13524         final ExpectedBroadcast b1 = expectProxyChangeAction();
13525         final LinkProperties lp = new LinkProperties();
13526         lp.setInterfaceName("tun0");
13527         lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
13528         lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
13529         final UidRange vpnRange = PRIMARY_UIDRANGE;
13530         final Set<UidRange> vpnRanges = Collections.singleton(vpnRange);
13531         mMockVpn.establish(lp, VPN_UID, vpnRanges);
13532         assertVpnUidRangesUpdated(true, vpnRanges, VPN_UID);
13533         // VPN is connected but proxy is not set, so there is no need to send proxy broadcast.
13534         b1.expectNoBroadcast(500);
13535 
13536         // Update to new range which is old range minus APP1, i.e. only APP2
13537         final ExpectedBroadcast b2 = expectProxyChangeAction();
13538         final Set<UidRange> newRanges = new HashSet<>(asList(
13539                 new UidRange(vpnRange.start, APP1_UID - 1),
13540                 new UidRange(APP1_UID + 1, vpnRange.stop)));
13541         mMockVpn.setUids(newRanges);
13542         waitForIdle();
13543 
13544         assertVpnUidRangesUpdated(true, newRanges, VPN_UID);
13545         assertVpnUidRangesUpdated(false, vpnRanges, VPN_UID);
13546 
13547         // Uid has changed but proxy is not set, so there is no need to send proxy broadcast.
13548         b2.expectNoBroadcast(500);
13549 
13550         final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
13551         final ExpectedBroadcast b3 = expectProxyChangeAction();
13552         lp.setHttpProxy(testProxyInfo);
13553         mMockVpn.sendLinkProperties(lp);
13554         waitForIdle();
13555         // Proxy is set, so send a proxy broadcast.
13556         b3.expectBroadcast();
13557 
13558         final ExpectedBroadcast b4 = expectProxyChangeAction();
13559         mMockVpn.setUids(vpnRanges);
13560         waitForIdle();
13561         // Uid has changed and proxy is already set, so send a proxy broadcast.
13562         b4.expectBroadcast();
13563 
13564         final ExpectedBroadcast b5 = expectProxyChangeAction();
13565         // Proxy is removed, send a proxy broadcast.
13566         lp.setHttpProxy(null);
13567         mMockVpn.sendLinkProperties(lp);
13568         waitForIdle();
13569         b5.expectBroadcast();
13570 
13571         // Proxy is added in WiFi(default network), setDefaultProxy will be called.
13572         final LinkProperties wifiLp = mCm.getLinkProperties(mWiFiAgent.getNetwork());
13573         assertNotNull(wifiLp);
13574         final ExpectedBroadcast b6 = expectProxyChangeAction(testProxyInfo);
13575         wifiLp.setHttpProxy(testProxyInfo);
13576         mWiFiAgent.sendLinkProperties(wifiLp);
13577         waitForIdle();
13578         b6.expectBroadcast();
13579     }
13580 
13581     @Test
13582     public void testProxyBroadcastWillBeSentWhenVpnHasProxyAndConnects() throws Exception {
13583         // Set up a WiFi network without proxy.
13584         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
13585         mWiFiAgent.connect(true);
13586         assertNull(mService.getProxyForNetwork(null));
13587         assertNull(mCm.getDefaultProxy());
13588 
13589         final LinkProperties lp = new LinkProperties();
13590         lp.setInterfaceName("tun0");
13591         lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
13592         lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
13593         final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
13594         lp.setHttpProxy(testProxyInfo);
13595         final UidRange vpnRange = PRIMARY_UIDRANGE;
13596         final Set<UidRange> vpnRanges = Collections.singleton(vpnRange);
13597         final ExpectedBroadcast b1 = expectProxyChangeAction();
13598         mMockVpn.setOwnerAndAdminUid(VPN_UID);
13599         mMockVpn.registerAgent(false, vpnRanges, lp);
13600         // In any case, the proxy broadcast won't be sent before VPN goes into CONNECTED state.
13601         // Otherwise, the app that calls ConnectivityManager#getDefaultProxy() when it receives the
13602         // proxy broadcast will get null.
13603         b1.expectNoBroadcast(500);
13604 
13605         final ExpectedBroadcast b2 = expectProxyChangeAction();
13606         mMockVpn.connect(true /* validated */, true /* hasInternet */,
13607                 false /* privateDnsProbeSent */);
13608         waitForIdle();
13609         assertVpnUidRangesUpdated(true, vpnRanges, VPN_UID);
13610         // Vpn is connected with proxy, so the proxy broadcast will be sent to inform the apps to
13611         // update their proxy data.
13612         b2.expectBroadcast();
13613     }
13614 
13615     @Test
13616     public void testProxyBroadcastWillBeSentWhenTheProxyOfNonDefaultNetworkHasChanged()
13617             throws Exception {
13618         // Set up a CELLULAR network without proxy.
13619         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
13620         mCellAgent.connect(true);
13621         assertNull(mService.getProxyForNetwork(null));
13622         assertNull(mCm.getDefaultProxy());
13623         // CELLULAR network should be the default network.
13624         assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetwork());
13625 
13626         // Set up a WiFi network without proxy.
13627         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
13628         mWiFiAgent.connect(true);
13629         assertNull(mService.getProxyForNetwork(null));
13630         assertNull(mCm.getDefaultProxy());
13631         // WiFi network should be the default network.
13632         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetwork());
13633         // CELLULAR network is not the default network.
13634         assertNotEquals(mCellAgent.getNetwork(), mCm.getActiveNetwork());
13635 
13636         // CELLULAR network is not the system default network, but it might be a per-app default
13637         // network. The proxy broadcast should be sent once its proxy has changed.
13638         final LinkProperties cellularLp = new LinkProperties();
13639         cellularLp.setInterfaceName(MOBILE_IFNAME);
13640         final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
13641         final ExpectedBroadcast b = expectProxyChangeAction();
13642         cellularLp.setHttpProxy(testProxyInfo);
13643         mCellAgent.sendLinkProperties(cellularLp);
13644         b.expectBroadcast();
13645     }
13646 
13647     @Test
13648     public void testInvalidRequestTypes() {
13649         final int[] invalidReqTypeInts = new int[]{-1, NetworkRequest.Type.NONE.ordinal(),
13650                 NetworkRequest.Type.LISTEN.ordinal(), NetworkRequest.Type.values().length};
13651         final NetworkCapabilities nc = new NetworkCapabilities().addTransportType(TRANSPORT_WIFI);
13652 
13653         for (int reqTypeInt : invalidReqTypeInts) {
13654             assertThrows("Expect throws for invalid request type " + reqTypeInt,
13655                     IllegalArgumentException.class,
13656                     () -> mService.requestNetwork(Process.INVALID_UID, nc, reqTypeInt, null, 0,
13657                             null, ConnectivityManager.TYPE_NONE, NetworkCallback.FLAG_NONE,
13658                             mContext.getPackageName(), getAttributionTag())
13659             );
13660         }
13661     }
13662 
13663     @Test
13664     public void testKeepConnected() throws Exception {
13665         setAlwaysOnNetworks(false);
13666         registerDefaultNetworkCallbacks();
13667         final TestNetworkCallback allNetworksCb = new TestNetworkCallback();
13668         final NetworkRequest allNetworksRequest = new NetworkRequest.Builder().clearCapabilities()
13669                 .build();
13670         mCm.registerNetworkCallback(allNetworksRequest, allNetworksCb);
13671 
13672         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
13673         mCellAgent.connect(true /* validated */);
13674 
13675         mDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
13676         allNetworksCb.expectAvailableThenValidatedCallbacks(mCellAgent);
13677 
13678         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
13679         mWiFiAgent.connect(true /* validated */);
13680 
13681         mDefaultNetworkCallback.expectAvailableDoubleValidatedCallbacks(mWiFiAgent);
13682         // While the default callback doesn't see the network before it's validated, the listen
13683         // sees the network come up and validate later
13684         allNetworksCb.expectAvailableCallbacksUnvalidated(mWiFiAgent);
13685         allNetworksCb.expectLosing(mCellAgent);
13686         allNetworksCb.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
13687         allNetworksCb.expect(LOST, mCellAgent, TEST_LINGER_DELAY_MS * 2);
13688 
13689         // The cell network has disconnected (see LOST above) because it was outscored and
13690         // had no requests (see setAlwaysOnNetworks(false) above)
13691         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
13692         final NetworkScore score = new NetworkScore.Builder().setLegacyInt(30).build();
13693         mCellAgent.setScore(score);
13694         mCellAgent.connect(false /* validated */);
13695 
13696         // The cell network gets torn down right away.
13697         allNetworksCb.expectAvailableCallbacksUnvalidated(mCellAgent);
13698         allNetworksCb.expect(LOST, mCellAgent, TEST_NASCENT_DELAY_MS * 2);
13699         allNetworksCb.assertNoCallback();
13700 
13701         // Now create a cell network with KEEP_CONNECTED_FOR_HANDOVER and make sure it's
13702         // not disconnected immediately when outscored.
13703         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
13704         final NetworkScore scoreKeepup = new NetworkScore.Builder().setLegacyInt(30)
13705                 .setKeepConnectedReason(KEEP_CONNECTED_FOR_HANDOVER).build();
13706         mCellAgent.setScore(scoreKeepup);
13707         mCellAgent.connect(true /* validated */);
13708 
13709         allNetworksCb.expectAvailableThenValidatedCallbacks(mCellAgent);
13710         mDefaultNetworkCallback.assertNoCallback();
13711 
13712         mWiFiAgent.disconnect();
13713 
13714         allNetworksCb.expect(LOST, mWiFiAgent);
13715         mDefaultNetworkCallback.expect(LOST, mWiFiAgent);
13716         mDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellAgent);
13717 
13718         // Reconnect a WiFi network and make sure the cell network is still not torn down.
13719         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
13720         mWiFiAgent.connect(true /* validated */);
13721 
13722         allNetworksCb.expectAvailableThenValidatedCallbacks(mWiFiAgent);
13723         mDefaultNetworkCallback.expectAvailableDoubleValidatedCallbacks(mWiFiAgent);
13724 
13725         // Now remove the reason to keep connected and make sure the network lingers and is
13726         // torn down.
13727         mCellAgent.setScore(new NetworkScore.Builder().setLegacyInt(30).build());
13728         allNetworksCb.expectLosing(mCellAgent, TEST_NASCENT_DELAY_MS * 2);
13729         allNetworksCb.expect(LOST, mCellAgent, TEST_LINGER_DELAY_MS * 2);
13730         mDefaultNetworkCallback.assertNoCallback();
13731 
13732         mCm.unregisterNetworkCallback(allNetworksCb);
13733         // mDefaultNetworkCallback will be unregistered by tearDown()
13734     }
13735 
13736     private class QosCallbackMockHelper {
13737         @NonNull public final QosFilter mFilter;
13738         @NonNull public final IQosCallback mCallback;
13739         @NonNull public final TestNetworkAgentWrapper mAgentWrapper;
13740         @NonNull private final List<IQosCallback> mCallbacks = new ArrayList();
13741 
13742         QosCallbackMockHelper() throws Exception {
13743             Log.d(TAG, "QosCallbackMockHelper: ");
13744             mFilter = mock(QosFilter.class);
13745 
13746             // Ensure the network is disconnected before anything else occurs
13747             assertNull(mCellAgent);
13748 
13749             mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
13750             mCellAgent.connect(true);
13751 
13752             verifyActiveNetwork(TRANSPORT_CELLULAR);
13753             waitForIdle();
13754             final Network network = mCellAgent.getNetwork();
13755 
13756             final Pair<IQosCallback, IBinder> pair = createQosCallback();
13757             mCallback = pair.first;
13758 
13759             doReturn(network).when(mFilter).getNetwork();
13760             doReturn(QosCallbackException.EX_TYPE_FILTER_NONE).when(mFilter).validate();
13761             mAgentWrapper = mCellAgent;
13762         }
13763 
13764         void registerQosCallback(@NonNull final QosFilter filter,
13765                 @NonNull final IQosCallback callback) {
13766             mCallbacks.add(callback);
13767             final NetworkAgentInfo nai =
13768                     mService.getNetworkAgentInfoForNetwork(filter.getNetwork());
13769             mService.registerQosCallbackInternal(filter, callback, nai);
13770         }
13771 
13772         void tearDown() {
13773             for (int i = 0; i < mCallbacks.size(); i++) {
13774                 mService.unregisterQosCallback(mCallbacks.get(i));
13775             }
13776         }
13777     }
13778 
13779     private Pair<IQosCallback, IBinder> createQosCallback() {
13780         final IQosCallback callback = mock(IQosCallback.class);
13781         final IBinder binder = mock(Binder.class);
13782         doReturn(binder).when(callback).asBinder();
13783         doReturn(true).when(binder).isBinderAlive();
13784         return new Pair<>(callback, binder);
13785     }
13786 
13787 
13788     @Test
13789     public void testQosCallbackRegistration() throws Exception {
13790         mQosCallbackMockHelper = new QosCallbackMockHelper();
13791         final NetworkAgentWrapper wrapper = mQosCallbackMockHelper.mAgentWrapper;
13792 
13793         doReturn(QosCallbackException.EX_TYPE_FILTER_NONE)
13794                 .when(mQosCallbackMockHelper.mFilter).validate();
13795         mQosCallbackMockHelper.registerQosCallback(
13796                 mQosCallbackMockHelper.mFilter, mQosCallbackMockHelper.mCallback);
13797 
13798         final OnQosCallbackRegister cbRegister1 =
13799                 (OnQosCallbackRegister) wrapper.getCallbackHistory().poll(1000, x -> true);
13800         assertNotNull(cbRegister1);
13801 
13802         final int registerCallbackId = cbRegister1.mQosCallbackId;
13803         mService.unregisterQosCallback(mQosCallbackMockHelper.mCallback);
13804         final OnQosCallbackUnregister cbUnregister =
13805                 (OnQosCallbackUnregister) wrapper.getCallbackHistory().poll(1000, x -> true);
13806         assertNotNull(cbUnregister);
13807         assertEquals(registerCallbackId, cbUnregister.mQosCallbackId);
13808         assertNull(wrapper.getCallbackHistory().poll(200, x -> true));
13809     }
13810 
13811     @Test
13812     public void testQosCallbackNoRegistrationOnValidationError() throws Exception {
13813         mQosCallbackMockHelper = new QosCallbackMockHelper();
13814 
13815         doReturn(QosCallbackException.EX_TYPE_FILTER_NETWORK_RELEASED)
13816                 .when(mQosCallbackMockHelper.mFilter).validate();
13817         mQosCallbackMockHelper.registerQosCallback(
13818                 mQosCallbackMockHelper.mFilter, mQosCallbackMockHelper.mCallback);
13819         waitForIdle();
13820         verify(mQosCallbackMockHelper.mCallback)
13821                 .onError(eq(QosCallbackException.EX_TYPE_FILTER_NETWORK_RELEASED));
13822     }
13823 
13824     @Test
13825     public void testQosCallbackAvailableAndLost() throws Exception {
13826         mQosCallbackMockHelper = new QosCallbackMockHelper();
13827         final int sessionId = 10;
13828         final int qosCallbackId = 1;
13829 
13830         doReturn(QosCallbackException.EX_TYPE_FILTER_NONE)
13831                 .when(mQosCallbackMockHelper.mFilter).validate();
13832         mQosCallbackMockHelper.registerQosCallback(
13833                 mQosCallbackMockHelper.mFilter, mQosCallbackMockHelper.mCallback);
13834         waitForIdle();
13835 
13836         final EpsBearerQosSessionAttributes attributes = new EpsBearerQosSessionAttributes(
13837                 1, 2, 3, 4, 5, new ArrayList<>());
13838         mQosCallbackMockHelper.mAgentWrapper.getNetworkAgent()
13839                 .sendQosSessionAvailable(qosCallbackId, sessionId, attributes);
13840         waitForIdle();
13841 
13842         verify(mQosCallbackMockHelper.mCallback).onQosEpsBearerSessionAvailable(argThat(session ->
13843                 session.getSessionId() == sessionId
13844                         && session.getSessionType() == QosSession.TYPE_EPS_BEARER), eq(attributes));
13845 
13846         mQosCallbackMockHelper.mAgentWrapper.getNetworkAgent()
13847                 .sendQosSessionLost(qosCallbackId, sessionId, QosSession.TYPE_EPS_BEARER);
13848         waitForIdle();
13849         verify(mQosCallbackMockHelper.mCallback).onQosSessionLost(argThat(session ->
13850                 session.getSessionId() == sessionId
13851                         && session.getSessionType() == QosSession.TYPE_EPS_BEARER));
13852     }
13853 
13854     @Test
13855     public void testNrQosCallbackAvailableAndLost() throws Exception {
13856         mQosCallbackMockHelper = new QosCallbackMockHelper();
13857         final int sessionId = 10;
13858         final int qosCallbackId = 1;
13859 
13860         doReturn(QosCallbackException.EX_TYPE_FILTER_NONE)
13861                 .when(mQosCallbackMockHelper.mFilter).validate();
13862         mQosCallbackMockHelper.registerQosCallback(
13863                 mQosCallbackMockHelper.mFilter, mQosCallbackMockHelper.mCallback);
13864         waitForIdle();
13865 
13866         final NrQosSessionAttributes attributes = new NrQosSessionAttributes(
13867                 1, 2, 3, 4, 5, 6, 7, new ArrayList<>());
13868         mQosCallbackMockHelper.mAgentWrapper.getNetworkAgent()
13869                 .sendQosSessionAvailable(qosCallbackId, sessionId, attributes);
13870         waitForIdle();
13871 
13872         verify(mQosCallbackMockHelper.mCallback).onNrQosSessionAvailable(argThat(session ->
13873                 session.getSessionId() == sessionId
13874                         && session.getSessionType() == QosSession.TYPE_NR_BEARER), eq(attributes));
13875 
13876         mQosCallbackMockHelper.mAgentWrapper.getNetworkAgent()
13877                 .sendQosSessionLost(qosCallbackId, sessionId, QosSession.TYPE_NR_BEARER);
13878         waitForIdle();
13879         verify(mQosCallbackMockHelper.mCallback).onQosSessionLost(argThat(session ->
13880                 session.getSessionId() == sessionId
13881                         && session.getSessionType() == QosSession.TYPE_NR_BEARER));
13882     }
13883 
13884     @Test @IgnoreUpTo(SC_V2)
13885     public void testQosCallbackAvailableOnValidationError() throws Exception {
13886         mQosCallbackMockHelper = new QosCallbackMockHelper();
13887         final NetworkAgentWrapper wrapper = mQosCallbackMockHelper.mAgentWrapper;
13888         final int sessionId = 10;
13889         final int qosCallbackId = 1;
13890 
13891         doReturn(QosCallbackException.EX_TYPE_FILTER_NONE)
13892                 .when(mQosCallbackMockHelper.mFilter).validate();
13893         mQosCallbackMockHelper.registerQosCallback(
13894                 mQosCallbackMockHelper.mFilter, mQosCallbackMockHelper.mCallback);
13895         OnQosCallbackRegister cbRegister1 =
13896                 (OnQosCallbackRegister) wrapper.getCallbackHistory().poll(1000, x -> true);
13897         assertNotNull(cbRegister1);
13898         final int registerCallbackId = cbRegister1.mQosCallbackId;
13899 
13900         waitForIdle();
13901 
13902         doReturn(QosCallbackException.EX_TYPE_FILTER_SOCKET_REMOTE_ADDRESS_CHANGED)
13903                 .when(mQosCallbackMockHelper.mFilter).validate();
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         final NetworkAgentWrapper.CallbackType.OnQosCallbackUnregister cbUnregister;
13911         cbUnregister = (NetworkAgentWrapper.CallbackType.OnQosCallbackUnregister)
13912                 wrapper.getCallbackHistory().poll(1000, x -> true);
13913         assertNotNull(cbUnregister);
13914         assertEquals(registerCallbackId, cbUnregister.mQosCallbackId);
13915         waitForIdle();
13916         verify(mQosCallbackMockHelper.mCallback)
13917                 .onError(eq(QosCallbackException.EX_TYPE_FILTER_SOCKET_REMOTE_ADDRESS_CHANGED));
13918     }
13919 
13920     @Test @IgnoreUpTo(SC_V2)
13921     public void testQosCallbackLostOnValidationError() throws Exception {
13922         mQosCallbackMockHelper = new QosCallbackMockHelper();
13923         final int sessionId = 10;
13924         final int qosCallbackId = 1;
13925 
13926         doReturn(QosCallbackException.EX_TYPE_FILTER_NONE)
13927                 .when(mQosCallbackMockHelper.mFilter).validate();
13928         mQosCallbackMockHelper.registerQosCallback(
13929                 mQosCallbackMockHelper.mFilter, mQosCallbackMockHelper.mCallback);
13930         waitForIdle();
13931         EpsBearerQosSessionAttributes attributes =
13932                 sendQosSessionEvent(qosCallbackId, sessionId, true);
13933         waitForIdle();
13934 
13935         verify(mQosCallbackMockHelper.mCallback).onQosEpsBearerSessionAvailable(argThat(session ->
13936                 session.getSessionId() == sessionId
13937                         && session.getSessionType() == QosSession.TYPE_EPS_BEARER), eq(attributes));
13938 
13939         doReturn(QosCallbackException.EX_TYPE_FILTER_SOCKET_REMOTE_ADDRESS_CHANGED)
13940                 .when(mQosCallbackMockHelper.mFilter).validate();
13941 
13942         sendQosSessionEvent(qosCallbackId, sessionId, false);
13943         waitForIdle();
13944         verify(mQosCallbackMockHelper.mCallback)
13945                 .onError(eq(QosCallbackException.EX_TYPE_FILTER_SOCKET_REMOTE_ADDRESS_CHANGED));
13946     }
13947 
13948     private EpsBearerQosSessionAttributes sendQosSessionEvent(
13949             int qosCallbackId, int sessionId, boolean available) {
13950         if (available) {
13951             final EpsBearerQosSessionAttributes attributes = new EpsBearerQosSessionAttributes(
13952                     1, 2, 3, 4, 5, new ArrayList<>());
13953             mQosCallbackMockHelper.mAgentWrapper.getNetworkAgent()
13954                     .sendQosSessionAvailable(qosCallbackId, sessionId, attributes);
13955             return attributes;
13956         } else {
13957             mQosCallbackMockHelper.mAgentWrapper.getNetworkAgent()
13958                     .sendQosSessionLost(qosCallbackId, sessionId, QosSession.TYPE_EPS_BEARER);
13959             return null;
13960         }
13961 
13962     }
13963 
13964     @Test
13965     public void testQosCallbackTooManyRequests() throws Exception {
13966         mQosCallbackMockHelper = new QosCallbackMockHelper();
13967 
13968         doReturn(QosCallbackException.EX_TYPE_FILTER_NONE)
13969                 .when(mQosCallbackMockHelper.mFilter).validate();
13970         for (int i = 0; i < 100; i++) {
13971             final Pair<IQosCallback, IBinder> pair = createQosCallback();
13972 
13973             try {
13974                 mQosCallbackMockHelper.registerQosCallback(
13975                         mQosCallbackMockHelper.mFilter, pair.first);
13976             } catch (ServiceSpecificException e) {
13977                 assertEquals(e.errorCode, ConnectivityManager.Errors.TOO_MANY_REQUESTS);
13978                 if (i < 50) {
13979                     fail("TOO_MANY_REQUESTS thrown too early, the count is " + i);
13980                 }
13981 
13982                 // As long as there is at least 50 requests, it is safe to assume it works.
13983                 // Note: The count isn't being tested precisely against 100 because the counter
13984                 // is shared with request network.
13985                 return;
13986             }
13987         }
13988         fail("TOO_MANY_REQUESTS never thrown");
13989     }
13990 
13991     private void mockGetApplicationInfo(@NonNull final String packageName, final int uid) {
13992         mockGetApplicationInfo(packageName, uid, PRIMARY_USER_HANDLE);
13993     }
13994 
13995     private void mockGetApplicationInfo(@NonNull final String packageName, final int uid,
13996             @NonNull final UserHandle user) {
13997         final ApplicationInfo applicationInfo = new ApplicationInfo();
13998         applicationInfo.uid = uid;
13999         try {
14000             doReturn(applicationInfo).when(mPackageManager).getApplicationInfoAsUser(
14001                     eq(packageName), anyInt(), eq(user));
14002         } catch (Exception e) {
14003             fail(e.getMessage());
14004         }
14005     }
14006 
14007     private void mockGetApplicationInfoThrowsNameNotFound(@NonNull final String packageName,
14008             @NonNull final UserHandle user)
14009             throws Exception {
14010         doThrow(new PackageManager.NameNotFoundException(packageName)).when(
14011                 mPackageManager).getApplicationInfoAsUser(eq(packageName), anyInt(), eq(user));
14012     }
14013 
14014     private void mockHasSystemFeature(@NonNull final String featureName, final boolean hasFeature) {
14015         doReturn(hasFeature).when(mPackageManager).hasSystemFeature(eq(featureName));
14016     }
14017 
14018     private Range<Integer> getNriFirstUidRange(@NonNull final NetworkRequestInfo nri) {
14019         return nri.mRequests.get(0).networkCapabilities.getUids().iterator().next();
14020     }
14021 
14022     private OemNetworkPreferences createDefaultOemNetworkPreferences(
14023             @OemNetworkPreferences.OemNetworkPreference final int preference) {
14024         // Arrange PackageManager mocks
14025         mockGetApplicationInfo(TEST_PACKAGE_NAME, TEST_PACKAGE_UID);
14026 
14027         // Build OemNetworkPreferences object
14028         return new OemNetworkPreferences.Builder()
14029                 .addNetworkPreference(TEST_PACKAGE_NAME, preference)
14030                 .build();
14031     }
14032 
14033     @Test
14034     public void testOemNetworkRequestFactoryPreferenceUninitializedThrowsError() {
14035         @OemNetworkPreferences.OemNetworkPreference final int prefToTest =
14036                 OEM_NETWORK_PREFERENCE_UNINITIALIZED;
14037 
14038         // Act on OemNetworkRequestFactory.createNrisFromOemNetworkPreferences()
14039         assertThrows(IllegalArgumentException.class,
14040                 () -> mService.new OemNetworkRequestFactory()
14041                         .createNrisFromOemNetworkPreferences(
14042                                 createDefaultOemNetworkPreferences(prefToTest)));
14043     }
14044 
14045     @Test
14046     public void testOemNetworkRequestFactoryPreferenceOemPaid()
14047             throws Exception {
14048         // Expectations
14049         final int expectedNumOfNris = 1;
14050         final int expectedNumOfRequests = 3;
14051 
14052         @OemNetworkPreferences.OemNetworkPreference final int prefToTest =
14053                 OEM_NETWORK_PREFERENCE_OEM_PAID;
14054 
14055         // Act on OemNetworkRequestFactory.createNrisFromOemNetworkPreferences()
14056         final ArraySet<NetworkRequestInfo> nris =
14057                 mService.new OemNetworkRequestFactory()
14058                         .createNrisFromOemNetworkPreferences(
14059                                 createDefaultOemNetworkPreferences(prefToTest));
14060         final NetworkRequestInfo nri = nris.iterator().next();
14061         assertEquals(PREFERENCE_ORDER_OEM, nri.mPreferenceOrder);
14062         final List<NetworkRequest> mRequests = nri.mRequests;
14063         assertEquals(expectedNumOfNris, nris.size());
14064         assertEquals(expectedNumOfRequests, mRequests.size());
14065         assertTrue(mRequests.get(0).isListen());
14066         assertTrue(mRequests.get(0).hasCapability(NET_CAPABILITY_NOT_METERED));
14067         assertTrue(mRequests.get(0).hasCapability(NET_CAPABILITY_VALIDATED));
14068         assertTrue(mRequests.get(1).isRequest());
14069         assertTrue(mRequests.get(1).hasCapability(NET_CAPABILITY_OEM_PAID));
14070         assertEquals(NetworkRequest.Type.TRACK_DEFAULT, mRequests.get(2).type);
14071         assertTrue(mService.getDefaultRequest().networkCapabilities.equalsNetCapabilities(
14072                 mRequests.get(2).networkCapabilities));
14073     }
14074 
14075     @Test
14076     public void testOemNetworkRequestFactoryPreferenceOemPaidNoFallback()
14077             throws Exception {
14078         // Expectations
14079         final int expectedNumOfNris = 1;
14080         final int expectedNumOfRequests = 2;
14081 
14082         @OemNetworkPreferences.OemNetworkPreference final int prefToTest =
14083                 OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK;
14084 
14085         // Act on OemNetworkRequestFactory.createNrisFromOemNetworkPreferences()
14086         final ArraySet<NetworkRequestInfo> nris =
14087                 mService.new OemNetworkRequestFactory()
14088                         .createNrisFromOemNetworkPreferences(
14089                                 createDefaultOemNetworkPreferences(prefToTest));
14090         final NetworkRequestInfo nri = nris.iterator().next();
14091         assertEquals(PREFERENCE_ORDER_OEM, nri.mPreferenceOrder);
14092         final List<NetworkRequest> mRequests = nri.mRequests;
14093         assertEquals(expectedNumOfNris, nris.size());
14094         assertEquals(expectedNumOfRequests, mRequests.size());
14095         assertTrue(mRequests.get(0).isListen());
14096         assertTrue(mRequests.get(0).hasCapability(NET_CAPABILITY_NOT_METERED));
14097         assertTrue(mRequests.get(0).hasCapability(NET_CAPABILITY_VALIDATED));
14098         assertTrue(mRequests.get(1).isRequest());
14099         assertTrue(mRequests.get(1).hasCapability(NET_CAPABILITY_OEM_PAID));
14100     }
14101 
14102     @Test
14103     public void testOemNetworkRequestFactoryPreferenceOemPaidOnly()
14104             throws Exception {
14105         // Expectations
14106         final int expectedNumOfNris = 1;
14107         final int expectedNumOfRequests = 1;
14108 
14109         @OemNetworkPreferences.OemNetworkPreference final int prefToTest =
14110                 OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY;
14111 
14112         // Act on OemNetworkRequestFactory.createNrisFromOemNetworkPreferences()
14113         final ArraySet<NetworkRequestInfo> nris =
14114                 mService.new OemNetworkRequestFactory()
14115                         .createNrisFromOemNetworkPreferences(
14116                                 createDefaultOemNetworkPreferences(prefToTest));
14117         final NetworkRequestInfo nri = nris.iterator().next();
14118         assertEquals(PREFERENCE_ORDER_OEM, nri.mPreferenceOrder);
14119         final List<NetworkRequest> mRequests = nri.mRequests;
14120         assertEquals(expectedNumOfNris, nris.size());
14121         assertEquals(expectedNumOfRequests, mRequests.size());
14122         assertTrue(mRequests.get(0).isRequest());
14123         assertTrue(mRequests.get(0).hasCapability(NET_CAPABILITY_OEM_PAID));
14124     }
14125 
14126     @Test
14127     public void testOemNetworkRequestFactoryPreferenceOemPrivateOnly()
14128             throws Exception {
14129         // Expectations
14130         final int expectedNumOfNris = 1;
14131         final int expectedNumOfRequests = 1;
14132 
14133         @OemNetworkPreferences.OemNetworkPreference final int prefToTest =
14134                 OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY;
14135 
14136         // Act on OemNetworkRequestFactory.createNrisFromOemNetworkPreferences()
14137         final ArraySet<NetworkRequestInfo> nris =
14138                 mService.new OemNetworkRequestFactory()
14139                         .createNrisFromOemNetworkPreferences(
14140                                 createDefaultOemNetworkPreferences(prefToTest));
14141         final NetworkRequestInfo nri = nris.iterator().next();
14142         assertEquals(PREFERENCE_ORDER_OEM, nri.mPreferenceOrder);
14143         final List<NetworkRequest> mRequests = nri.mRequests;
14144         assertEquals(expectedNumOfNris, nris.size());
14145         assertEquals(expectedNumOfRequests, mRequests.size());
14146         assertTrue(mRequests.get(0).isRequest());
14147         assertTrue(mRequests.get(0).hasCapability(NET_CAPABILITY_OEM_PRIVATE));
14148         assertFalse(mRequests.get(0).hasCapability(NET_CAPABILITY_OEM_PAID));
14149     }
14150 
14151     @Test
14152     public void testOemNetworkRequestFactoryCreatesCorrectNumOfNris()
14153             throws Exception {
14154         // Expectations
14155         final int expectedNumOfNris = 2;
14156 
14157         // Arrange PackageManager mocks
14158         final String testPackageName2 = "com.google.apps.dialer";
14159         mockGetApplicationInfo(TEST_PACKAGE_NAME, TEST_PACKAGE_UID);
14160         mockGetApplicationInfo(testPackageName2, TEST_PACKAGE_UID);
14161 
14162         // Build OemNetworkPreferences object
14163         final int testOemPref = OEM_NETWORK_PREFERENCE_OEM_PAID;
14164         final int testOemPref2 = OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK;
14165         final OemNetworkPreferences pref = new OemNetworkPreferences.Builder()
14166                 .addNetworkPreference(TEST_PACKAGE_NAME, testOemPref)
14167                 .addNetworkPreference(testPackageName2, testOemPref2)
14168                 .build();
14169 
14170         // Act on OemNetworkRequestFactory.createNrisFromOemNetworkPreferences()
14171         final ArraySet<NetworkRequestInfo> nris =
14172                 mService.new OemNetworkRequestFactory().createNrisFromOemNetworkPreferences(pref);
14173 
14174         assertNotNull(nris);
14175         assertEquals(expectedNumOfNris, nris.size());
14176     }
14177 
14178     @Test
14179     public void testOemNetworkRequestFactoryMultiplePrefsCorrectlySetsUids()
14180             throws Exception {
14181         // Arrange PackageManager mocks
14182         final String testPackageName2 = "com.google.apps.dialer";
14183         final int testPackageNameUid2 = 456;
14184         mockGetApplicationInfo(TEST_PACKAGE_NAME, TEST_PACKAGE_UID);
14185         mockGetApplicationInfo(testPackageName2, testPackageNameUid2);
14186 
14187         // Build OemNetworkPreferences object
14188         final int testOemPref = OEM_NETWORK_PREFERENCE_OEM_PAID;
14189         final int testOemPref2 = OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK;
14190         final OemNetworkPreferences pref = new OemNetworkPreferences.Builder()
14191                 .addNetworkPreference(TEST_PACKAGE_NAME, testOemPref)
14192                 .addNetworkPreference(testPackageName2, testOemPref2)
14193                 .build();
14194 
14195         // Act on OemNetworkRequestFactory.createNrisFromOemNetworkPreferences()
14196         final List<NetworkRequestInfo> nris =
14197                 new ArrayList<>(
14198                         mService.new OemNetworkRequestFactory().createNrisFromOemNetworkPreferences(
14199                                 pref));
14200 
14201         // Sort by uid to access nris by index
14202         nris.sort(Comparator.comparingInt(nri -> getNriFirstUidRange(nri).getLower()));
14203         assertEquals(TEST_PACKAGE_UID, (int) getNriFirstUidRange(nris.get(0)).getLower());
14204         assertEquals(TEST_PACKAGE_UID, (int) getNriFirstUidRange(nris.get(0)).getUpper());
14205         assertEquals(testPackageNameUid2, (int) getNriFirstUidRange(nris.get(1)).getLower());
14206         assertEquals(testPackageNameUid2, (int) getNriFirstUidRange(nris.get(1)).getUpper());
14207     }
14208 
14209     @Test
14210     public void testOemNetworkRequestFactoryMultipleUsersSetsUids()
14211             throws Exception {
14212         // Arrange users
14213         final int secondUserTestPackageUid = UserHandle.getUid(SECONDARY_USER, TEST_PACKAGE_UID);
14214         final int thirdUserTestPackageUid = UserHandle.getUid(TERTIARY_USER, TEST_PACKAGE_UID);
14215         doReturn(asList(PRIMARY_USER_HANDLE, SECONDARY_USER_HANDLE, TERTIARY_USER_HANDLE))
14216                 .when(mUserManager).getUserHandles(anyBoolean());
14217 
14218         // Arrange PackageManager mocks testing for users who have and don't have a package.
14219         mockGetApplicationInfoThrowsNameNotFound(TEST_PACKAGE_NAME, PRIMARY_USER_HANDLE);
14220         mockGetApplicationInfo(TEST_PACKAGE_NAME, secondUserTestPackageUid, SECONDARY_USER_HANDLE);
14221         mockGetApplicationInfo(TEST_PACKAGE_NAME, thirdUserTestPackageUid, TERTIARY_USER_HANDLE);
14222 
14223         // Build OemNetworkPreferences object
14224         final int testOemPref = OEM_NETWORK_PREFERENCE_OEM_PAID;
14225         final OemNetworkPreferences pref = new OemNetworkPreferences.Builder()
14226                 .addNetworkPreference(TEST_PACKAGE_NAME, testOemPref)
14227                 .build();
14228 
14229         // Act on OemNetworkRequestFactory.createNrisFromOemNetworkPreferences()
14230         final List<NetworkRequestInfo> nris =
14231                 new ArrayList<>(
14232                         mService.new OemNetworkRequestFactory().createNrisFromOemNetworkPreferences(
14233                                 pref));
14234 
14235         // UIDs for users with installed packages should be present.
14236         // Three users exist, but only two have the test package installed.
14237         final int expectedUidSize = 2;
14238         final List<Range<Integer>> uids =
14239                 new ArrayList<>(nris.get(0).mRequests.get(0).networkCapabilities.getUids());
14240         assertEquals(expectedUidSize, uids.size());
14241 
14242         // Sort by uid to access nris by index
14243         uids.sort(Comparator.comparingInt(uid -> uid.getLower()));
14244         assertEquals(secondUserTestPackageUid, (int) uids.get(0).getLower());
14245         assertEquals(secondUserTestPackageUid, (int) uids.get(0).getUpper());
14246         assertEquals(thirdUserTestPackageUid, (int) uids.get(1).getLower());
14247         assertEquals(thirdUserTestPackageUid, (int) uids.get(1).getUpper());
14248     }
14249 
14250     @Test
14251     public void testOemNetworkRequestFactoryAddsPackagesToCorrectPreference()
14252             throws Exception {
14253         // Expectations
14254         final int expectedNumOfNris = 1;
14255         final int expectedNumOfAppUids = 2;
14256 
14257         // Arrange PackageManager mocks
14258         final String testPackageName2 = "com.google.apps.dialer";
14259         final int testPackageNameUid2 = 456;
14260         mockGetApplicationInfo(TEST_PACKAGE_NAME, TEST_PACKAGE_UID);
14261         mockGetApplicationInfo(testPackageName2, testPackageNameUid2);
14262 
14263         // Build OemNetworkPreferences object
14264         final int testOemPref = OEM_NETWORK_PREFERENCE_OEM_PAID;
14265         final OemNetworkPreferences pref = new OemNetworkPreferences.Builder()
14266                 .addNetworkPreference(TEST_PACKAGE_NAME, testOemPref)
14267                 .addNetworkPreference(testPackageName2, testOemPref)
14268                 .build();
14269 
14270         // Act on OemNetworkRequestFactory.createNrisFromOemNetworkPreferences()
14271         final ArraySet<NetworkRequestInfo> nris =
14272                 mService.new OemNetworkRequestFactory().createNrisFromOemNetworkPreferences(pref);
14273 
14274         assertEquals(expectedNumOfNris, nris.size());
14275         assertEquals(expectedNumOfAppUids,
14276                 nris.iterator().next().mRequests.get(0).networkCapabilities.getUids().size());
14277     }
14278 
14279     @Test
14280     public void testSetOemNetworkPreferenceNullListenerAndPrefParamThrowsNpe() {
14281         mockHasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, true);
14282 
14283         // Act on ConnectivityService.setOemNetworkPreference()
14284         assertThrows(NullPointerException.class,
14285                 () -> mService.setOemNetworkPreference(
14286                         null,
14287                         null));
14288     }
14289 
14290     @Test
14291     public void testSetOemNetworkPreferenceFailsForNonAutomotive()
14292             throws Exception {
14293         mockHasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, false);
14294         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
14295                 OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY;
14296 
14297         // Act on ConnectivityService.setOemNetworkPreference()
14298         assertThrows(UnsupportedOperationException.class,
14299                 () -> mService.setOemNetworkPreference(
14300                         createDefaultOemNetworkPreferences(networkPref),
14301                         null));
14302     }
14303 
14304     @Test
14305     public void testSetOemNetworkPreferenceFailsForTestRequestWithoutPermission() {
14306         // Calling setOemNetworkPreference() with a test pref requires the permission
14307         // MANAGE_TEST_NETWORKS.
14308         mockHasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, false);
14309         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
14310                 OEM_NETWORK_PREFERENCE_TEST;
14311 
14312         // Act on ConnectivityService.setOemNetworkPreference()
14313         assertThrows(SecurityException.class,
14314                 () -> mService.setOemNetworkPreference(
14315                         createDefaultOemNetworkPreferences(networkPref),
14316                         null));
14317     }
14318 
14319     @Test
14320     public void testSetOemNetworkPreferenceFailsForInvalidTestRequest() {
14321         assertSetOemNetworkPreferenceFailsForInvalidTestRequest(OEM_NETWORK_PREFERENCE_TEST);
14322     }
14323 
14324     @Test
14325     public void testSetOemNetworkPreferenceFailsForInvalidTestOnlyRequest() {
14326         assertSetOemNetworkPreferenceFailsForInvalidTestRequest(OEM_NETWORK_PREFERENCE_TEST_ONLY);
14327     }
14328 
14329     private void assertSetOemNetworkPreferenceFailsForInvalidTestRequest(
14330             @OemNetworkPreferences.OemNetworkPreference final int oemNetworkPreferenceForTest) {
14331         mockHasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, true);
14332         final String secondPackage = "does.not.matter";
14333 
14334         // A valid test request would only have a single mapping.
14335         final OemNetworkPreferences pref = new OemNetworkPreferences.Builder()
14336                 .addNetworkPreference(TEST_PACKAGE_NAME, oemNetworkPreferenceForTest)
14337                 .addNetworkPreference(secondPackage, oemNetworkPreferenceForTest)
14338                 .build();
14339 
14340         // Act on ConnectivityService.setOemNetworkPreference()
14341         assertThrows(IllegalArgumentException.class,
14342                 () -> mService.setOemNetworkPreference(pref, null));
14343     }
14344 
14345     private void setOemNetworkPreferenceAgentConnected(final int transportType,
14346             final boolean connectAgent) throws Exception {
14347         switch(transportType) {
14348             // Corresponds to a metered cellular network. Will be used for the default network.
14349             case TRANSPORT_CELLULAR:
14350                 if (!connectAgent) {
14351                     mCellAgent.disconnect();
14352                     break;
14353                 }
14354                 mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
14355                 mCellAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
14356                 mCellAgent.connect(true);
14357                 break;
14358             // Corresponds to a restricted ethernet network with OEM_PAID/OEM_PRIVATE.
14359             case TRANSPORT_ETHERNET:
14360                 if (!connectAgent) {
14361                     stopOemManagedNetwork();
14362                     break;
14363                 }
14364                 startOemManagedNetwork(true);
14365                 break;
14366             // Corresponds to unmetered Wi-Fi.
14367             case TRANSPORT_WIFI:
14368                 if (!connectAgent) {
14369                     mWiFiAgent.disconnect();
14370                     break;
14371                 }
14372                 mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
14373                 mWiFiAgent.addCapability(NET_CAPABILITY_NOT_METERED);
14374                 mWiFiAgent.connect(true);
14375                 break;
14376             default:
14377                 throw new AssertionError("Unsupported transport type passed in.");
14378 
14379         }
14380         waitForIdle();
14381     }
14382 
14383     private void startOemManagedNetwork(final boolean isOemPaid) throws Exception {
14384         mEthernetAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
14385         mEthernetAgent.addCapability(
14386                 isOemPaid ? NET_CAPABILITY_OEM_PAID : NET_CAPABILITY_OEM_PRIVATE);
14387         mEthernetAgent.removeCapability(NET_CAPABILITY_NOT_RESTRICTED);
14388         mEthernetAgent.connect(true);
14389     }
14390 
14391     private void stopOemManagedNetwork() {
14392         mEthernetAgent.disconnect();
14393         waitForIdle();
14394     }
14395 
14396     private void verifyMultipleDefaultNetworksTracksCorrectly(
14397             final int expectedOemRequestsSize,
14398             @NonNull final Network expectedDefaultNetwork,
14399             @NonNull final Network expectedPerAppNetwork) {
14400         // The current test setup assumes two tracked default network requests; one for the default
14401         // network and the other for the OEM network preference being tested. This will be validated
14402         // each time to confirm it doesn't change under test.
14403         final int expectedDefaultNetworkRequestsSize = 2;
14404         assertEquals(expectedDefaultNetworkRequestsSize, mService.mDefaultNetworkRequests.size());
14405         for (final NetworkRequestInfo defaultRequest : mService.mDefaultNetworkRequests) {
14406             final Network defaultNetwork = defaultRequest.getSatisfier() == null
14407                     ? null : defaultRequest.getSatisfier().network();
14408             // If this is the default request.
14409             if (defaultRequest == mService.mDefaultRequest) {
14410                 assertEquals(
14411                         expectedDefaultNetwork,
14412                         defaultNetwork);
14413                 // Make sure this value doesn't change.
14414                 assertEquals(1, defaultRequest.mRequests.size());
14415                 continue;
14416             }
14417             assertEquals(expectedPerAppNetwork, defaultNetwork);
14418             assertEquals(expectedOemRequestsSize, defaultRequest.mRequests.size());
14419         }
14420         verifyMultipleDefaultCallbacks(expectedDefaultNetwork, expectedPerAppNetwork);
14421     }
14422 
14423     /**
14424      * Verify default callbacks for 'available' fire as expected. This will only run if
14425      * registerDefaultNetworkCallbacks() was executed prior and will only be different if the
14426      * setOemNetworkPreference() per-app API was used for the current process.
14427      * @param expectedSystemDefault the expected network for the system default.
14428      * @param expectedPerAppDefault the expected network for the current process's default.
14429      */
14430     private void verifyMultipleDefaultCallbacks(
14431             @NonNull final Network expectedSystemDefault,
14432             @NonNull final Network expectedPerAppDefault) {
14433         if (null != mSystemDefaultNetworkCallback && null != expectedSystemDefault
14434                 && mService.mNoServiceNetwork.network() != expectedSystemDefault) {
14435             // getLastAvailableNetwork() is used as this method can be called successively with
14436             // the same network to validate therefore expectAvailableThenValidatedCallbacks
14437             // can't be used.
14438             assertEquals(mSystemDefaultNetworkCallback.getLastAvailableNetwork(),
14439                     expectedSystemDefault);
14440         }
14441         if (null != mDefaultNetworkCallback && null != expectedPerAppDefault
14442                 && mService.mNoServiceNetwork.network() != expectedPerAppDefault) {
14443             assertEquals(mDefaultNetworkCallback.getLastAvailableNetwork(),
14444                     expectedPerAppDefault);
14445         }
14446     }
14447 
14448     private void registerDefaultNetworkCallbacks() {
14449         if (mSystemDefaultNetworkCallback != null || mDefaultNetworkCallback != null
14450                 || mProfileDefaultNetworkCallback != null
14451                 || mProfileDefaultNetworkCallbackAsAppUid2 != null
14452                 || mTestPackageDefaultNetworkCallback2 != null
14453                 || mTestPackageDefaultNetworkCallback != null) {
14454             throw new IllegalStateException("Default network callbacks already registered");
14455         }
14456 
14457         mSystemDefaultNetworkCallback = new TestNetworkCallback();
14458         mDefaultNetworkCallback = new TestNetworkCallback();
14459         mProfileDefaultNetworkCallback = new TestNetworkCallback();
14460         mTestPackageDefaultNetworkCallback = new TestNetworkCallback();
14461         mProfileDefaultNetworkCallbackAsAppUid2 = new TestNetworkCallback();
14462         mTestPackageDefaultNetworkCallback2 = new TestNetworkCallback();
14463         mCm.registerSystemDefaultNetworkCallback(mSystemDefaultNetworkCallback,
14464                 new Handler(ConnectivityThread.getInstanceLooper()));
14465         mCm.registerDefaultNetworkCallback(mDefaultNetworkCallback);
14466         registerDefaultNetworkCallbackAsUid(mProfileDefaultNetworkCallback,
14467                 TEST_WORK_PROFILE_APP_UID);
14468         registerDefaultNetworkCallbackAsUid(mTestPackageDefaultNetworkCallback, TEST_PACKAGE_UID);
14469         registerDefaultNetworkCallbackAsUid(mProfileDefaultNetworkCallbackAsAppUid2,
14470                 TEST_WORK_PROFILE_APP_UID_2);
14471         registerDefaultNetworkCallbackAsUid(mTestPackageDefaultNetworkCallback2,
14472                 TEST_PACKAGE_UID2);
14473         // TODO: test using ConnectivityManager#registerDefaultNetworkCallbackAsUid as well.
14474         mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_DENIED);
14475     }
14476 
14477     private void unregisterDefaultNetworkCallbacks() {
14478         if (null != mDefaultNetworkCallback) {
14479             mCm.unregisterNetworkCallback(mDefaultNetworkCallback);
14480         }
14481         if (null != mSystemDefaultNetworkCallback) {
14482             mCm.unregisterNetworkCallback(mSystemDefaultNetworkCallback);
14483         }
14484         if (null != mProfileDefaultNetworkCallback) {
14485             mCm.unregisterNetworkCallback(mProfileDefaultNetworkCallback);
14486         }
14487         if (null != mTestPackageDefaultNetworkCallback) {
14488             mCm.unregisterNetworkCallback(mTestPackageDefaultNetworkCallback);
14489         }
14490         if (null != mProfileDefaultNetworkCallbackAsAppUid2) {
14491             mCm.unregisterNetworkCallback(mProfileDefaultNetworkCallbackAsAppUid2);
14492         }
14493         if (null != mTestPackageDefaultNetworkCallback2) {
14494             mCm.unregisterNetworkCallback(mTestPackageDefaultNetworkCallback2);
14495         }
14496         mSystemDefaultNetworkCallback = null;
14497         mDefaultNetworkCallback = null;
14498         mProfileDefaultNetworkCallback = null;
14499         mTestPackageDefaultNetworkCallback = null;
14500         mProfileDefaultNetworkCallbackAsAppUid2 = null;
14501         mTestPackageDefaultNetworkCallback2 = null;
14502     }
14503 
14504     private void setupMultipleDefaultNetworksForOemNetworkPreferenceNotCurrentUidTest(
14505             @OemNetworkPreferences.OemNetworkPreference final int networkPrefToSetup)
14506             throws Exception {
14507         final int testPackageNameUid = TEST_PACKAGE_UID;
14508         final String testPackageName = "per.app.defaults.package";
14509         setupMultipleDefaultNetworksForOemNetworkPreferenceTest(
14510                 networkPrefToSetup, testPackageNameUid, testPackageName);
14511     }
14512 
14513     private void setupMultipleDefaultNetworksForOemNetworkPreferenceCurrentUidTest(
14514             @OemNetworkPreferences.OemNetworkPreference final int networkPrefToSetup)
14515             throws Exception {
14516         final int testPackageNameUid = Process.myUid();
14517         final String testPackageName = "per.app.defaults.package";
14518         setupMultipleDefaultNetworksForOemNetworkPreferenceTest(
14519                 networkPrefToSetup, testPackageNameUid, testPackageName);
14520     }
14521 
14522     private void setupMultipleDefaultNetworksForOemNetworkPreferenceTest(
14523             @OemNetworkPreferences.OemNetworkPreference final int networkPrefToSetup,
14524             final int testPackageUid, @NonNull final String testPackageName) throws Exception {
14525         // Only the default request should be included at start.
14526         assertEquals(1, mService.mDefaultNetworkRequests.size());
14527 
14528         final UidRangeParcel[] uidRanges =
14529                 toUidRangeStableParcels(uidRangesForUids(testPackageUid));
14530         setupSetOemNetworkPreferenceForPreferenceTest(
14531                 networkPrefToSetup, uidRanges, testPackageName);
14532     }
14533 
14534     private void setupSetOemNetworkPreferenceForPreferenceTest(
14535             @OemNetworkPreferences.OemNetworkPreference final int networkPrefToSetup,
14536             @NonNull final UidRangeParcel[] uidRanges,
14537             @NonNull final String testPackageName) throws Exception {
14538         setupSetOemNetworkPreferenceForPreferenceTest(networkPrefToSetup, uidRanges,
14539                 testPackageName, PRIMARY_USER_HANDLE, true /* hasAutomotiveFeature */);
14540     }
14541 
14542     private void setupSetOemNetworkPreferenceForPreferenceTest(
14543             @OemNetworkPreferences.OemNetworkPreference final int networkPrefToSetup,
14544             @NonNull final UidRangeParcel[] uidRanges,
14545             @NonNull final String testPackageName,
14546             @NonNull final UserHandle user) throws Exception {
14547         setupSetOemNetworkPreferenceForPreferenceTest(networkPrefToSetup, uidRanges,
14548                 testPackageName, user, true /* hasAutomotiveFeature */);
14549     }
14550 
14551     private void setupSetOemNetworkPreferenceForPreferenceTest(
14552             @OemNetworkPreferences.OemNetworkPreference final int networkPrefToSetup,
14553             @NonNull final UidRangeParcel[] uidRanges,
14554             @NonNull final String testPackageName,
14555             @NonNull final UserHandle user,
14556             final boolean hasAutomotiveFeature) throws Exception {
14557         mockHasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, hasAutomotiveFeature);
14558 
14559         // These tests work off a single UID therefore using 'start' is valid.
14560         mockGetApplicationInfo(testPackageName, uidRanges[0].start, user);
14561 
14562         setOemNetworkPreference(networkPrefToSetup, testPackageName);
14563     }
14564 
14565     private void setOemNetworkPreference(final int networkPrefToSetup,
14566             @NonNull final String... testPackageNames)
14567             throws Exception {
14568         mockHasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, true);
14569 
14570         // Build OemNetworkPreferences object
14571         final OemNetworkPreferences.Builder builder = new OemNetworkPreferences.Builder();
14572         for (final String packageName : testPackageNames) {
14573             builder.addNetworkPreference(packageName, networkPrefToSetup);
14574         }
14575         final OemNetworkPreferences pref = builder.build();
14576 
14577         // Act on ConnectivityService.setOemNetworkPreference()
14578         final TestOemListenerCallback oemPrefListener = new TestOemListenerCallback();
14579         mService.setOemNetworkPreference(pref, oemPrefListener);
14580 
14581         // Verify call returned successfully
14582         oemPrefListener.expectOnComplete();
14583     }
14584 
14585     private static class TestOemListenerCallback implements IOnCompleteListener {
14586         final CompletableFuture<Object> mDone = new CompletableFuture<>();
14587 
14588         @Override
14589         public void onComplete() {
14590             mDone.complete(new Object());
14591         }
14592 
14593         void expectOnComplete() {
14594             try {
14595                 mDone.get(TIMEOUT_MS, TimeUnit.MILLISECONDS);
14596             } catch (TimeoutException e) {
14597                 fail("Expected onComplete() not received after " + TIMEOUT_MS + " ms");
14598             } catch (Exception e) {
14599                 fail(e.getMessage());
14600             }
14601         }
14602 
14603         @Override
14604         public IBinder asBinder() {
14605             return null;
14606         }
14607     }
14608 
14609     @Test
14610     public void testMultiDefaultGetActiveNetworkIsCorrect() throws Exception {
14611         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
14612                 OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY;
14613         final int expectedOemPrefRequestSize = 1;
14614         registerDefaultNetworkCallbacks();
14615 
14616         // Setup the test process to use networkPref for their default network.
14617         setupMultipleDefaultNetworksForOemNetworkPreferenceCurrentUidTest(networkPref);
14618 
14619         // Bring up ethernet with OEM_PAID. This will satisfy NET_CAPABILITY_OEM_PAID.
14620         // The active network for the default should be null at this point as this is a retricted
14621         // network.
14622         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, true);
14623         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
14624                 null,
14625                 mEthernetAgent.getNetwork());
14626 
14627         // Verify that the active network is correct
14628         verifyActiveNetwork(TRANSPORT_ETHERNET);
14629         // default NCs will be unregistered in tearDown
14630     }
14631 
14632     @Test
14633     public void testMultiDefaultIsActiveNetworkMeteredIsCorrect() throws Exception {
14634         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
14635                 OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY;
14636         final int expectedOemPrefRequestSize = 1;
14637         registerDefaultNetworkCallbacks();
14638 
14639         // Setup the test process to use networkPref for their default network.
14640         setupMultipleDefaultNetworksForOemNetworkPreferenceCurrentUidTest(networkPref);
14641 
14642         // Returns true by default when no network is available.
14643         assertTrue(mCm.isActiveNetworkMetered());
14644 
14645         // Connect to an unmetered restricted network that will only be available to the OEM pref.
14646         mEthernetAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
14647         mEthernetAgent.addCapability(NET_CAPABILITY_OEM_PAID);
14648         mEthernetAgent.addCapability(NET_CAPABILITY_NOT_METERED);
14649         mEthernetAgent.removeCapability(NET_CAPABILITY_NOT_RESTRICTED);
14650         mEthernetAgent.connect(true);
14651         waitForIdle();
14652 
14653         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
14654                 null,
14655                 mEthernetAgent.getNetwork());
14656 
14657         assertFalse(mCm.isActiveNetworkMetered());
14658         // default NCs will be unregistered in tearDown
14659     }
14660 
14661     @Test
14662     public void testPerAppDefaultRegisterDefaultNetworkCallback() throws Exception {
14663         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
14664                 OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY;
14665         final int expectedOemPrefRequestSize = 1;
14666         final TestNetworkCallback defaultNetworkCallback = new TestNetworkCallback();
14667 
14668         // Register the default network callback before the pref is already set. This means that
14669         // the policy will be applied to the callback on setOemNetworkPreference().
14670         mCm.registerDefaultNetworkCallback(defaultNetworkCallback);
14671         defaultNetworkCallback.assertNoCallback();
14672 
14673         final TestNetworkCallback otherUidDefaultCallback = new TestNetworkCallback();
14674         withPermission(NETWORK_SETTINGS, () ->
14675                 mCm.registerDefaultNetworkCallbackForUid(TEST_PACKAGE_UID, otherUidDefaultCallback,
14676                         new Handler(ConnectivityThread.getInstanceLooper())));
14677 
14678         // Setup the test process to use networkPref for their default network.
14679         setupMultipleDefaultNetworksForOemNetworkPreferenceCurrentUidTest(networkPref);
14680 
14681         // Bring up ethernet with OEM_PAID. This will satisfy NET_CAPABILITY_OEM_PAID.
14682         // The active nai for the default is null at this point as this is a restricted network.
14683         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, true);
14684         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
14685                 null,
14686                 mEthernetAgent.getNetwork());
14687 
14688         // At this point with a restricted network used, the available callback should trigger.
14689         defaultNetworkCallback.expectAvailableThenValidatedCallbacks(mEthernetAgent);
14690         assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mEthernetAgent.getNetwork());
14691         otherUidDefaultCallback.assertNoCallback();
14692 
14693         // Now bring down the default network which should trigger a LOST callback.
14694         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, false);
14695 
14696         // At this point, with no network is available, the lost callback should trigger
14697         defaultNetworkCallback.expect(LOST, mEthernetAgent);
14698         otherUidDefaultCallback.assertNoCallback();
14699 
14700         // Confirm we can unregister without issues.
14701         mCm.unregisterNetworkCallback(defaultNetworkCallback);
14702         mCm.unregisterNetworkCallback(otherUidDefaultCallback);
14703     }
14704 
14705     @Test
14706     public void testPerAppDefaultRegisterDefaultNetworkCallbackAfterPrefSet() throws Exception {
14707         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
14708                 OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY;
14709         final int expectedOemPrefRequestSize = 1;
14710         final TestNetworkCallback defaultNetworkCallback = new TestNetworkCallback();
14711 
14712         // Setup the test process to use networkPref for their default network.
14713         setupMultipleDefaultNetworksForOemNetworkPreferenceCurrentUidTest(networkPref);
14714 
14715         // Register the default network callback after the pref is already set. This means that
14716         // the policy will be applied to the callback on requestNetwork().
14717         mCm.registerDefaultNetworkCallback(defaultNetworkCallback);
14718         defaultNetworkCallback.assertNoCallback();
14719 
14720         final TestNetworkCallback otherUidDefaultCallback = new TestNetworkCallback();
14721         withPermission(NETWORK_SETTINGS, () ->
14722                 mCm.registerDefaultNetworkCallbackForUid(TEST_PACKAGE_UID, otherUidDefaultCallback,
14723                         new Handler(ConnectivityThread.getInstanceLooper())));
14724 
14725         // Bring up ethernet with OEM_PAID. This will satisfy NET_CAPABILITY_OEM_PAID.
14726         // The active nai for the default is null at this point as this is a restricted network.
14727         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, true);
14728         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
14729                 null,
14730                 mEthernetAgent.getNetwork());
14731 
14732         // At this point with a restricted network used, the available callback should trigger
14733         defaultNetworkCallback.expectAvailableThenValidatedCallbacks(mEthernetAgent);
14734         assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mEthernetAgent.getNetwork());
14735         otherUidDefaultCallback.assertNoCallback();
14736 
14737         // Now bring down the default network which should trigger a LOST callback.
14738         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, false);
14739         otherUidDefaultCallback.assertNoCallback();
14740 
14741         // At this point, with no network is available, the lost callback should trigger
14742         defaultNetworkCallback.expect(LOST, mEthernetAgent);
14743         otherUidDefaultCallback.assertNoCallback();
14744 
14745         // Confirm we can unregister without issues.
14746         mCm.unregisterNetworkCallback(defaultNetworkCallback);
14747         mCm.unregisterNetworkCallback(otherUidDefaultCallback);
14748     }
14749 
14750     @Test
14751     public void testPerAppDefaultRegisterDefaultNetworkCallbackDoesNotFire() throws Exception {
14752         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
14753                 OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY;
14754         final int expectedOemPrefRequestSize = 1;
14755         final TestNetworkCallback defaultNetworkCallback = new TestNetworkCallback();
14756         final int userId = UserHandle.getUserId(Process.myUid());
14757 
14758         mCm.registerDefaultNetworkCallback(defaultNetworkCallback);
14759         defaultNetworkCallback.assertNoCallback();
14760 
14761         final TestNetworkCallback otherUidDefaultCallback = new TestNetworkCallback();
14762         withPermission(NETWORK_SETTINGS, () ->
14763                 mCm.registerDefaultNetworkCallbackForUid(TEST_PACKAGE_UID, otherUidDefaultCallback,
14764                         new Handler(ConnectivityThread.getInstanceLooper())));
14765 
14766         // Setup a process different than the test process to use the default network. This means
14767         // that the defaultNetworkCallback won't be tracked by the per-app policy.
14768         setupMultipleDefaultNetworksForOemNetworkPreferenceNotCurrentUidTest(networkPref);
14769 
14770         // Bring up ethernet with OEM_PAID. This will satisfy NET_CAPABILITY_OEM_PAID.
14771         // The active nai for the default is null at this point as this is a restricted network.
14772         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, true);
14773         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
14774                 null,
14775                 mEthernetAgent.getNetwork());
14776 
14777         // As this callback does not have access to the OEM_PAID network, it will not fire.
14778         defaultNetworkCallback.assertNoCallback();
14779         assertDefaultNetworkCapabilities(userId /* no networks */);
14780 
14781         // The other UID does have access, and gets a callback.
14782         otherUidDefaultCallback.expectAvailableThenValidatedCallbacks(mEthernetAgent);
14783 
14784         // Bring up unrestricted cellular. This should now satisfy the default network.
14785         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true);
14786         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
14787                 mCellAgent.getNetwork(),
14788                 mEthernetAgent.getNetwork());
14789 
14790         // At this point with an unrestricted network used, the available callback should trigger
14791         // The other UID is unaffected and remains on the paid network.
14792         defaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
14793         assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCellAgent.getNetwork());
14794         assertDefaultNetworkCapabilities(userId, mCellAgent);
14795         otherUidDefaultCallback.assertNoCallback();
14796 
14797         // Now bring down the per-app network.
14798         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, false);
14799 
14800         // Since the callback didn't use the per-app network, only the other UID gets a callback.
14801         // Because the preference specifies no fallback, it does not switch to cellular.
14802         defaultNetworkCallback.assertNoCallback();
14803         otherUidDefaultCallback.expect(LOST, mEthernetAgent);
14804 
14805         // Now bring down the default network.
14806         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, false);
14807 
14808         // As this callback was tracking the default, this should now trigger.
14809         defaultNetworkCallback.expect(LOST, mCellAgent);
14810         otherUidDefaultCallback.assertNoCallback();
14811 
14812         // Confirm we can unregister without issues.
14813         mCm.unregisterNetworkCallback(defaultNetworkCallback);
14814         mCm.unregisterNetworkCallback(otherUidDefaultCallback);
14815     }
14816 
14817     /**
14818      * This method assumes that the same uidRanges input will be used to verify that dependencies
14819      * are called as expected.
14820      */
14821     private void verifySetOemNetworkPreferenceForPreference(
14822             @NonNull final UidRangeParcel[] uidRanges,
14823             final int addUidRangesNetId,
14824             final int addUidRangesTimes,
14825             final int removeUidRangesNetId,
14826             final int removeUidRangesTimes,
14827             final boolean shouldDestroyNetwork) throws RemoteException {
14828         verifySetOemNetworkPreferenceForPreference(uidRanges, uidRanges,
14829                 addUidRangesNetId, addUidRangesTimes, removeUidRangesNetId, removeUidRangesTimes,
14830                 shouldDestroyNetwork);
14831     }
14832 
14833     private void verifySetOemNetworkPreferenceForPreference(
14834             @NonNull final UidRangeParcel[] addedUidRanges,
14835             @NonNull final UidRangeParcel[] removedUidRanges,
14836             final int addUidRangesNetId,
14837             final int addUidRangesTimes,
14838             final int removeUidRangesNetId,
14839             final int removeUidRangesTimes,
14840             final boolean shouldDestroyNetwork) throws RemoteException {
14841         final boolean useAnyIdForAdd = OEM_PREF_ANY_NET_ID == addUidRangesNetId;
14842         final boolean useAnyIdForRemove = OEM_PREF_ANY_NET_ID == removeUidRangesNetId;
14843 
14844         // Validate that add/remove uid range (with oem priority) to/from netd.
14845         verify(mMockNetd, times(addUidRangesTimes)).networkAddUidRangesParcel(argThat(config ->
14846                 (useAnyIdForAdd ? true : addUidRangesNetId == config.netId)
14847                         && Arrays.equals(addedUidRanges, config.uidRanges)
14848                         && PREFERENCE_ORDER_OEM == config.subPriority));
14849         verify(mMockNetd, times(removeUidRangesTimes)).networkRemoveUidRangesParcel(
14850                 argThat(config -> (useAnyIdForRemove ? true : removeUidRangesNetId == config.netId)
14851                         && Arrays.equals(removedUidRanges, config.uidRanges)
14852                         && PREFERENCE_ORDER_OEM == config.subPriority));
14853         if (shouldDestroyNetwork) {
14854             verify(mMockNetd, times(1))
14855                     .networkDestroy((useAnyIdForRemove ? anyInt() : eq(removeUidRangesNetId)));
14856         }
14857         reset(mMockNetd);
14858     }
14859 
14860     /**
14861      * Test the tracked default requests allows test requests without standard setup.
14862      */
14863     @Test
14864     public void testSetOemNetworkPreferenceAllowsValidTestRequestWithoutChecks() throws Exception {
14865         @OemNetworkPreferences.OemNetworkPreference int networkPref =
14866                 OEM_NETWORK_PREFERENCE_TEST;
14867         validateSetOemNetworkPreferenceAllowsValidTestPrefRequest(networkPref);
14868     }
14869 
14870     /**
14871      * Test the tracked default requests allows test only requests without standard setup.
14872      */
14873     @Test
14874     public void testSetOemNetworkPreferenceAllowsValidTestOnlyRequestWithoutChecks()
14875             throws Exception {
14876         @OemNetworkPreferences.OemNetworkPreference int networkPref =
14877                 OEM_NETWORK_PREFERENCE_TEST_ONLY;
14878         validateSetOemNetworkPreferenceAllowsValidTestPrefRequest(networkPref);
14879     }
14880 
14881     private void validateSetOemNetworkPreferenceAllowsValidTestPrefRequest(int networkPref)
14882             throws Exception {
14883         // The caller must have the MANAGE_TEST_NETWORKS permission.
14884         final int testPackageUid = 123;
14885         final String validTestPackageName = "does.not.matter";
14886         final UidRangeParcel[] uidRanges =
14887                 toUidRangeStableParcels(uidRangesForUids(testPackageUid));
14888         mServiceContext.setPermission(
14889                 Manifest.permission.MANAGE_TEST_NETWORKS, PERMISSION_GRANTED);
14890 
14891         // Put the system into a state in which setOemNetworkPreference() would normally fail. This
14892         // will confirm that a valid test request can bypass these checks.
14893         mockHasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, false);
14894         mServiceContext.setPermission(
14895                 Manifest.permission.CONTROL_OEM_PAID_NETWORK_PREFERENCE, PERMISSION_DENIED);
14896 
14897         // Validate the starting requests only includes the system default request.
14898         assertEquals(1, mService.mDefaultNetworkRequests.size());
14899 
14900         // Add an OEM default network request to track.
14901         setupSetOemNetworkPreferenceForPreferenceTest(
14902                 networkPref, uidRanges, validTestPackageName, PRIMARY_USER_HANDLE,
14903                 false /* hasAutomotiveFeature */);
14904 
14905         // Two requests should now exist; the system default and the test request.
14906         assertEquals(2, mService.mDefaultNetworkRequests.size());
14907     }
14908 
14909     /**
14910      * Test the tracked default requests clear previous OEM requests on setOemNetworkPreference().
14911      */
14912     @Test
14913     public void testSetOemNetworkPreferenceClearPreviousOemValues() throws Exception {
14914         @OemNetworkPreferences.OemNetworkPreference int networkPref =
14915                 OEM_NETWORK_PREFERENCE_OEM_PAID;
14916         final int testPackageUid = 123;
14917         final String testPackageName = "com.google.apps.contacts";
14918         final UidRangeParcel[] uidRanges =
14919                 toUidRangeStableParcels(uidRangesForUids(testPackageUid));
14920 
14921         // Validate the starting requests only includes the system default request.
14922         assertEquals(1, mService.mDefaultNetworkRequests.size());
14923 
14924         // Add an OEM default network request to track.
14925         setupSetOemNetworkPreferenceForPreferenceTest(networkPref, uidRanges, testPackageName);
14926 
14927         // Two requests should exist, one for the fallback and one for the pref.
14928         assertEquals(2, mService.mDefaultNetworkRequests.size());
14929 
14930         networkPref = OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY;
14931         setupSetOemNetworkPreferenceForPreferenceTest(networkPref, uidRanges, testPackageName);
14932 
14933         // Two requests should still exist validating the previous per-app request was replaced.
14934         assertEquals(2, mService.mDefaultNetworkRequests.size());
14935     }
14936 
14937     /**
14938      * Test network priority for preference OEM_NETWORK_PREFERENCE_OEM_PAID in the following order:
14939      * NET_CAPABILITY_NOT_METERED -> NET_CAPABILITY_OEM_PAID -> fallback
14940      */
14941     @Test
14942     public void testMultilayerForPreferenceOemPaidEvaluatesCorrectly()
14943             throws Exception {
14944         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
14945                 OEM_NETWORK_PREFERENCE_OEM_PAID;
14946 
14947         // Arrange PackageManager mocks
14948         final UidRangeParcel[] uidRanges =
14949                 toUidRangeStableParcels(uidRangesForUids(TEST_PACKAGE_UID));
14950         setupSetOemNetworkPreferenceForPreferenceTest(networkPref, uidRanges, TEST_PACKAGE_NAME);
14951 
14952         // Verify the starting state. No networks should be connected.
14953         verifySetOemNetworkPreferenceForPreference(uidRanges,
14954                 OEM_PREF_ANY_NET_ID, 0 /* times */,
14955                 OEM_PREF_ANY_NET_ID, 0 /* times */,
14956                 false /* shouldDestroyNetwork */);
14957 
14958         // Test lowest to highest priority requests.
14959         // Bring up metered cellular. This will satisfy the fallback network.
14960         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true);
14961         verifySetOemNetworkPreferenceForPreference(uidRanges,
14962                 mCellAgent.getNetwork().netId, 1 /* times */,
14963                 OEM_PREF_ANY_NET_ID, 0 /* times */,
14964                 false /* shouldDestroyNetwork */);
14965 
14966         // Bring up ethernet with OEM_PAID. This will satisfy NET_CAPABILITY_OEM_PAID.
14967         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, true);
14968         verifySetOemNetworkPreferenceForPreference(uidRanges,
14969                 mEthernetAgent.getNetwork().netId, 1 /* times */,
14970                 mCellAgent.getNetwork().netId, 1 /* times */,
14971                 false /* shouldDestroyNetwork */);
14972 
14973         // Bring up unmetered Wi-Fi. This will satisfy NET_CAPABILITY_NOT_METERED.
14974         setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, true);
14975         verifySetOemNetworkPreferenceForPreference(uidRanges,
14976                 mWiFiAgent.getNetwork().netId, 1 /* times */,
14977                 mEthernetAgent.getNetwork().netId, 1 /* times */,
14978                 false /* shouldDestroyNetwork */);
14979 
14980         // Disconnecting OEM_PAID should have no effect as it is lower in priority then unmetered.
14981         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, false);
14982         // netd should not be called as default networks haven't changed.
14983         verifySetOemNetworkPreferenceForPreference(uidRanges,
14984                 OEM_PREF_ANY_NET_ID, 0 /* times */,
14985                 OEM_PREF_ANY_NET_ID, 0 /* times */,
14986                 false /* shouldDestroyNetwork */);
14987 
14988         // Disconnecting unmetered should put PANS on lowest priority fallback request.
14989         setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, false);
14990         verifySetOemNetworkPreferenceForPreference(uidRanges,
14991                 mCellAgent.getNetwork().netId, 1 /* times */,
14992                 mWiFiAgent.getNetwork().netId, 0 /* times */,
14993                 true /* shouldDestroyNetwork */);
14994 
14995         // Disconnecting the fallback network should result in no connectivity.
14996         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, false);
14997         verifySetOemNetworkPreferenceForPreference(uidRanges,
14998                 OEM_PREF_ANY_NET_ID, 0 /* times */,
14999                 mCellAgent.getNetwork().netId, 0 /* times */,
15000                 true /* shouldDestroyNetwork */);
15001     }
15002 
15003     /**
15004      * Test network priority for OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK in the following order:
15005      * NET_CAPABILITY_NOT_METERED -> NET_CAPABILITY_OEM_PAID
15006      */
15007     @Test
15008     public void testMultilayerForPreferenceOemPaidNoFallbackEvaluatesCorrectly()
15009             throws Exception {
15010         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
15011                 OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK;
15012 
15013         // Arrange PackageManager mocks
15014         final UidRangeParcel[] uidRanges =
15015                 toUidRangeStableParcels(uidRangesForUids(TEST_PACKAGE_UID));
15016         setupSetOemNetworkPreferenceForPreferenceTest(networkPref, uidRanges, TEST_PACKAGE_NAME);
15017 
15018         // Verify the starting state. This preference doesn't support using the fallback network
15019         // therefore should be on the disconnected network as it has no networks to connect to.
15020         verifySetOemNetworkPreferenceForPreference(uidRanges,
15021                 mService.mNoServiceNetwork.network.getNetId(), 1 /* times */,
15022                 OEM_PREF_ANY_NET_ID, 0 /* times */,
15023                 false /* shouldDestroyNetwork */);
15024 
15025         // Test lowest to highest priority requests.
15026         // Bring up metered cellular. This will satisfy the fallback network.
15027         // This preference should not use this network as it doesn't support fallback usage.
15028         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true);
15029         verifySetOemNetworkPreferenceForPreference(uidRanges,
15030                 OEM_PREF_ANY_NET_ID, 0 /* 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                 mService.mNoServiceNetwork.network.getNetId(), 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 unmetered should put PANS on OEM_PAID.
15049         setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, false);
15050         verifySetOemNetworkPreferenceForPreference(uidRanges,
15051                 mEthernetAgent.getNetwork().netId, 1 /* times */,
15052                 mWiFiAgent.getNetwork().netId, 0 /* times */,
15053                 true /* shouldDestroyNetwork */);
15054 
15055         // Disconnecting OEM_PAID should result in no connectivity.
15056         // OEM_PAID_NO_FALLBACK not supporting a fallback now uses the disconnected network.
15057         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, false);
15058         verifySetOemNetworkPreferenceForPreference(uidRanges,
15059                 mService.mNoServiceNetwork.network.getNetId(), 1 /* times */,
15060                 mEthernetAgent.getNetwork().netId, 0 /* times */,
15061                 true /* shouldDestroyNetwork */);
15062     }
15063 
15064     /**
15065      * Test network priority for OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY in the following order:
15066      * NET_CAPABILITY_OEM_PAID
15067      * This preference should only apply to OEM_PAID networks.
15068      */
15069     @Test
15070     public void testMultilayerForPreferenceOemPaidOnlyEvaluatesCorrectly()
15071             throws Exception {
15072         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
15073                 OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY;
15074 
15075         // Arrange PackageManager mocks
15076         final UidRangeParcel[] uidRanges =
15077                 toUidRangeStableParcels(uidRangesForUids(TEST_PACKAGE_UID));
15078         setupSetOemNetworkPreferenceForPreferenceTest(networkPref, uidRanges, TEST_PACKAGE_NAME);
15079 
15080         // Verify the starting state. This preference doesn't support using the fallback network
15081         // therefore should be on the disconnected network as it has no networks to connect to.
15082         verifySetOemNetworkPreferenceForPreference(uidRanges,
15083                 mService.mNoServiceNetwork.network.getNetId(), 1 /* times */,
15084                 OEM_PREF_ANY_NET_ID, 0 /* times */,
15085                 false /* shouldDestroyNetwork */);
15086 
15087         // Bring up metered cellular. This should not apply to this preference.
15088         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true);
15089         verifySetOemNetworkPreferenceForPreference(uidRanges,
15090                 OEM_PREF_ANY_NET_ID, 0 /* times */,
15091                 OEM_PREF_ANY_NET_ID, 0 /* times */,
15092                 false /* shouldDestroyNetwork */);
15093 
15094         // Bring up unmetered Wi-Fi. This should not apply to this preference.
15095         setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, true);
15096         verifySetOemNetworkPreferenceForPreference(uidRanges,
15097                 OEM_PREF_ANY_NET_ID, 0 /* times */,
15098                 OEM_PREF_ANY_NET_ID, 0 /* times */,
15099                 false /* shouldDestroyNetwork */);
15100 
15101         // Bring up ethernet with OEM_PAID. This will satisfy NET_CAPABILITY_OEM_PAID.
15102         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, true);
15103         verifySetOemNetworkPreferenceForPreference(uidRanges,
15104                 mEthernetAgent.getNetwork().netId, 1 /* times */,
15105                 mService.mNoServiceNetwork.network.getNetId(), 1 /* times */,
15106                 false /* shouldDestroyNetwork */);
15107 
15108         // Disconnecting OEM_PAID should result in no connectivity.
15109         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, false);
15110         verifySetOemNetworkPreferenceForPreference(uidRanges,
15111                 mService.mNoServiceNetwork.network.getNetId(), 1 /* times */,
15112                 mEthernetAgent.getNetwork().netId, 0 /* times */,
15113                 true /* shouldDestroyNetwork */);
15114     }
15115 
15116     /**
15117      * Test network priority for OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY in the following order:
15118      * NET_CAPABILITY_OEM_PRIVATE
15119      * This preference should only apply to OEM_PRIVATE networks.
15120      */
15121     @Test
15122     public void testMultilayerForPreferenceOemPrivateOnlyEvaluatesCorrectly()
15123             throws Exception {
15124         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
15125                 OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY;
15126 
15127         // Arrange PackageManager mocks
15128         final UidRangeParcel[] uidRanges =
15129                 toUidRangeStableParcels(uidRangesForUids(TEST_PACKAGE_UID));
15130         setupSetOemNetworkPreferenceForPreferenceTest(networkPref, uidRanges, TEST_PACKAGE_NAME);
15131 
15132         // Verify the starting state. This preference doesn't support using the fallback network
15133         // therefore should be on the disconnected network as it has no networks to connect to.
15134         verifySetOemNetworkPreferenceForPreference(uidRanges,
15135                 mService.mNoServiceNetwork.network.getNetId(), 1 /* times */,
15136                 OEM_PREF_ANY_NET_ID, 0 /* times */,
15137                 false /* shouldDestroyNetwork */);
15138 
15139         // Bring up metered cellular. This should not apply to this preference.
15140         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true);
15141         verifySetOemNetworkPreferenceForPreference(uidRanges,
15142                 OEM_PREF_ANY_NET_ID, 0 /* times */,
15143                 OEM_PREF_ANY_NET_ID, 0 /* times */,
15144                 false /* shouldDestroyNetwork */);
15145 
15146         // Bring up unmetered Wi-Fi. This should not apply to this preference.
15147         setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, true);
15148         verifySetOemNetworkPreferenceForPreference(uidRanges,
15149                 OEM_PREF_ANY_NET_ID, 0 /* times */,
15150                 OEM_PREF_ANY_NET_ID, 0 /* times */,
15151                 false /* shouldDestroyNetwork */);
15152 
15153         // Bring up ethernet with OEM_PRIVATE. This will satisfy NET_CAPABILITY_OEM_PRIVATE.
15154         startOemManagedNetwork(false);
15155         verifySetOemNetworkPreferenceForPreference(uidRanges,
15156                 mEthernetAgent.getNetwork().netId, 1 /* times */,
15157                 mService.mNoServiceNetwork.network.getNetId(), 1 /* times */,
15158                 false /* shouldDestroyNetwork */);
15159 
15160         // Disconnecting OEM_PRIVATE should result in no connectivity.
15161         stopOemManagedNetwork();
15162         verifySetOemNetworkPreferenceForPreference(uidRanges,
15163                 mService.mNoServiceNetwork.network.getNetId(), 1 /* times */,
15164                 mEthernetAgent.getNetwork().netId, 0 /* times */,
15165                 true /* shouldDestroyNetwork */);
15166     }
15167 
15168     @Test
15169     public void testMultilayerForMultipleUsersEvaluatesCorrectly()
15170             throws Exception {
15171         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
15172                 OEM_NETWORK_PREFERENCE_OEM_PAID;
15173 
15174         // Arrange users
15175         final int secondUser = 10;
15176         final UserHandle secondUserHandle = new UserHandle(secondUser);
15177         doReturn(asList(PRIMARY_USER_HANDLE, secondUserHandle)).when(mUserManager)
15178                 .getUserHandles(anyBoolean());
15179 
15180         // Arrange PackageManager mocks
15181         final int secondUserTestPackageUid = UserHandle.getUid(secondUser, TEST_PACKAGE_UID);
15182         final UidRangeParcel[] uidRanges =
15183                 toUidRangeStableParcels(
15184                         uidRangesForUids(TEST_PACKAGE_UID, secondUserTestPackageUid));
15185         mockGetApplicationInfo(TEST_PACKAGE_NAME, secondUserTestPackageUid, secondUserHandle);
15186         setupSetOemNetworkPreferenceForPreferenceTest(networkPref, uidRanges, TEST_PACKAGE_NAME);
15187 
15188         // Verify the starting state. No networks should be connected.
15189         verifySetOemNetworkPreferenceForPreference(uidRanges,
15190                 OEM_PREF_ANY_NET_ID, 0 /* times */,
15191                 OEM_PREF_ANY_NET_ID, 0 /* times */,
15192                 false /* shouldDestroyNetwork */);
15193 
15194         // Test that we correctly add the expected values for multiple users.
15195         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true);
15196         verifySetOemNetworkPreferenceForPreference(uidRanges,
15197                 mCellAgent.getNetwork().netId, 1 /* times */,
15198                 OEM_PREF_ANY_NET_ID, 0 /* times */,
15199                 false /* shouldDestroyNetwork */);
15200 
15201         // Test that we correctly remove the expected values for multiple users.
15202         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, false);
15203         verifySetOemNetworkPreferenceForPreference(uidRanges,
15204                 OEM_PREF_ANY_NET_ID, 0 /* times */,
15205                 mCellAgent.getNetwork().netId, 0 /* times */,
15206                 true /* shouldDestroyNetwork */);
15207     }
15208 
15209     @Test
15210     public void testMultilayerForBroadcastedUsersEvaluatesCorrectly()
15211             throws Exception {
15212         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
15213                 OEM_NETWORK_PREFERENCE_OEM_PAID;
15214 
15215         // Arrange users
15216         final int secondUser = 10;
15217         final UserHandle secondUserHandle = new UserHandle(secondUser);
15218         doReturn(asList(PRIMARY_USER_HANDLE)).when(mUserManager).getUserHandles(anyBoolean());
15219 
15220         // Arrange PackageManager mocks
15221         final int secondUserTestPackageUid = UserHandle.getUid(secondUser, TEST_PACKAGE_UID);
15222         final UidRangeParcel[] uidRangesSingleUser =
15223                 toUidRangeStableParcels(uidRangesForUids(TEST_PACKAGE_UID));
15224         final UidRangeParcel[] uidRangesBothUsers =
15225                 toUidRangeStableParcels(
15226                         uidRangesForUids(TEST_PACKAGE_UID, secondUserTestPackageUid));
15227         mockGetApplicationInfo(TEST_PACKAGE_NAME, secondUserTestPackageUid, secondUserHandle);
15228         setupSetOemNetworkPreferenceForPreferenceTest(
15229                 networkPref, uidRangesSingleUser, TEST_PACKAGE_NAME);
15230 
15231         // Verify the starting state. No networks should be connected.
15232         verifySetOemNetworkPreferenceForPreference(uidRangesSingleUser,
15233                 OEM_PREF_ANY_NET_ID, 0 /* times */,
15234                 OEM_PREF_ANY_NET_ID, 0 /* times */,
15235                 false /* shouldDestroyNetwork */);
15236 
15237         // Test that we correctly add the expected values for multiple users.
15238         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true);
15239         verifySetOemNetworkPreferenceForPreference(uidRangesSingleUser,
15240                 mCellAgent.getNetwork().netId, 1 /* times */,
15241                 OEM_PREF_ANY_NET_ID, 0 /* times */,
15242                 false /* shouldDestroyNetwork */);
15243 
15244         // Send a broadcast indicating a user was added.
15245         doReturn(asList(PRIMARY_USER_HANDLE, secondUserHandle)).when(mUserManager)
15246                 .getUserHandles(anyBoolean());
15247         final Intent addedIntent = new Intent(ACTION_USER_ADDED);
15248         addedIntent.putExtra(Intent.EXTRA_USER, UserHandle.of(secondUser));
15249         processBroadcast(addedIntent);
15250 
15251         // Test that we correctly add values for all users and remove for the single user.
15252         verifySetOemNetworkPreferenceForPreference(uidRangesBothUsers, uidRangesSingleUser,
15253                 mCellAgent.getNetwork().netId, 1 /* times */,
15254                 mCellAgent.getNetwork().netId, 1 /* times */,
15255                 false /* shouldDestroyNetwork */);
15256 
15257         // Send a broadcast indicating a user was removed.
15258         doReturn(asList(PRIMARY_USER_HANDLE)).when(mUserManager).getUserHandles(anyBoolean());
15259         final Intent removedIntent = new Intent(ACTION_USER_REMOVED);
15260         removedIntent.putExtra(Intent.EXTRA_USER, UserHandle.of(secondUser));
15261         processBroadcast(removedIntent);
15262 
15263         // Test that we correctly add values for the single user and remove for the all users.
15264         verifySetOemNetworkPreferenceForPreference(uidRangesSingleUser, uidRangesBothUsers,
15265                 mCellAgent.getNetwork().netId, 1 /* times */,
15266                 mCellAgent.getNetwork().netId, 1 /* times */,
15267                 false /* shouldDestroyNetwork */);
15268     }
15269 
15270     @Test
15271     public void testMultilayerForPackageChangesEvaluatesCorrectly()
15272             throws Exception {
15273         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
15274                 OEM_NETWORK_PREFERENCE_OEM_PAID;
15275         final String packageScheme = "package:";
15276 
15277         // Arrange PackageManager mocks
15278         final String packageToInstall = "package.to.install";
15279         final int packageToInstallUid = 81387;
15280         final UidRangeParcel[] uidRangesSinglePackage =
15281                 toUidRangeStableParcels(uidRangesForUids(TEST_PACKAGE_UID));
15282         mockGetApplicationInfo(TEST_PACKAGE_NAME, TEST_PACKAGE_UID);
15283         mockGetApplicationInfoThrowsNameNotFound(packageToInstall, PRIMARY_USER_HANDLE);
15284         setOemNetworkPreference(networkPref, TEST_PACKAGE_NAME, packageToInstall);
15285         grantUsingBackgroundNetworksPermissionForUid(Binder.getCallingUid(), packageToInstall);
15286 
15287         // Verify the starting state. No networks should be connected.
15288         verifySetOemNetworkPreferenceForPreference(uidRangesSinglePackage,
15289                 OEM_PREF_ANY_NET_ID, 0 /* times */,
15290                 OEM_PREF_ANY_NET_ID, 0 /* times */,
15291                 false /* shouldDestroyNetwork */);
15292 
15293         // Test that we correctly add the expected values for installed packages.
15294         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true);
15295         verifySetOemNetworkPreferenceForPreference(uidRangesSinglePackage,
15296                 mCellAgent.getNetwork().netId, 1 /* times */,
15297                 OEM_PREF_ANY_NET_ID, 0 /* times */,
15298                 false /* shouldDestroyNetwork */);
15299 
15300         // Set the system to recognize the package to be installed
15301         mockGetApplicationInfo(packageToInstall, packageToInstallUid);
15302         final UidRangeParcel[] uidRangesAllPackages =
15303                 toUidRangeStableParcels(uidRangesForUids(TEST_PACKAGE_UID, packageToInstallUid));
15304 
15305         // Send a broadcast indicating a package was installed.
15306         final Intent addedIntent = new Intent(ACTION_PACKAGE_ADDED);
15307         addedIntent.setData(Uri.parse(packageScheme + packageToInstall));
15308         processBroadcast(addedIntent);
15309 
15310         // Test the single package is removed and the combined packages are added.
15311         verifySetOemNetworkPreferenceForPreference(uidRangesAllPackages, uidRangesSinglePackage,
15312                 mCellAgent.getNetwork().netId, 1 /* times */,
15313                 mCellAgent.getNetwork().netId, 1 /* times */,
15314                 false /* shouldDestroyNetwork */);
15315 
15316         // Set the system to no longer recognize the package to be installed
15317         mockGetApplicationInfoThrowsNameNotFound(packageToInstall, PRIMARY_USER_HANDLE);
15318 
15319         // Send a broadcast indicating a package was removed.
15320         final Intent removedIntent = new Intent(ACTION_PACKAGE_REMOVED);
15321         removedIntent.setData(Uri.parse(packageScheme + packageToInstall));
15322         processBroadcast(removedIntent);
15323 
15324         // Test the combined packages are removed and the single package is added.
15325         verifySetOemNetworkPreferenceForPreference(uidRangesSinglePackage, uidRangesAllPackages,
15326                 mCellAgent.getNetwork().netId, 1 /* times */,
15327                 mCellAgent.getNetwork().netId, 1 /* times */,
15328                 false /* shouldDestroyNetwork */);
15329 
15330         // Set the system to change the installed package's uid
15331         final int replacedTestPackageUid = TEST_PACKAGE_UID + 1;
15332         mockGetApplicationInfo(TEST_PACKAGE_NAME, replacedTestPackageUid);
15333         final UidRangeParcel[] uidRangesReplacedPackage =
15334                 toUidRangeStableParcels(uidRangesForUids(replacedTestPackageUid));
15335 
15336         // Send a broadcast indicating a package was replaced.
15337         final Intent replacedIntent = new Intent(ACTION_PACKAGE_REPLACED);
15338         replacedIntent.setData(Uri.parse(packageScheme + TEST_PACKAGE_NAME));
15339         processBroadcast(replacedIntent);
15340 
15341         // Test the original uid is removed and is replaced with the new uid.
15342         verifySetOemNetworkPreferenceForPreference(uidRangesReplacedPackage, uidRangesSinglePackage,
15343                 mCellAgent.getNetwork().netId, 1 /* times */,
15344                 mCellAgent.getNetwork().netId, 1 /* times */,
15345                 false /* shouldDestroyNetwork */);
15346     }
15347 
15348     /**
15349      * Test network priority for preference OEM_NETWORK_PREFERENCE_OEM_PAID in the following order:
15350      * NET_CAPABILITY_NOT_METERED -> NET_CAPABILITY_OEM_PAID -> fallback
15351      */
15352     @Test
15353     public void testMultipleDefaultNetworksTracksOemNetworkPreferenceOemPaidCorrectly()
15354             throws Exception {
15355         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
15356                 OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PAID;
15357         setupMultipleDefaultNetworksForOemNetworkPreferenceCurrentUidTest(networkPref);
15358         final int expectedDefaultRequestSize = 2;
15359         final int expectedOemPrefRequestSize = 3;
15360         registerDefaultNetworkCallbacks();
15361 
15362         // The fallback as well as the OEM preference should now be tracked.
15363         assertEquals(expectedDefaultRequestSize, mService.mDefaultNetworkRequests.size());
15364 
15365         // Test lowest to highest priority requests.
15366         // Bring up metered cellular. This will satisfy the fallback network.
15367         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true);
15368         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
15369                 mCellAgent.getNetwork(),
15370                 mCellAgent.getNetwork());
15371 
15372         // Bring up ethernet with OEM_PAID. This will satisfy NET_CAPABILITY_OEM_PAID.
15373         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, true);
15374         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
15375                 mCellAgent.getNetwork(),
15376                 mEthernetAgent.getNetwork());
15377 
15378         // Bring up unmetered Wi-Fi. This will satisfy NET_CAPABILITY_NOT_METERED.
15379         setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, true);
15380         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
15381                 mWiFiAgent.getNetwork(),
15382                 mWiFiAgent.getNetwork());
15383 
15384         // Disconnecting unmetered Wi-Fi will put the pref on OEM_PAID and fallback on cellular.
15385         setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, false);
15386         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
15387                 mCellAgent.getNetwork(),
15388                 mEthernetAgent.getNetwork());
15389 
15390         // Disconnecting cellular should keep OEM network on OEM_PAID and fallback will be null.
15391         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, false);
15392         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
15393                 null,
15394                 mEthernetAgent.getNetwork());
15395 
15396         // Disconnecting OEM_PAID will put both on null as it is the last network.
15397         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, false);
15398         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
15399                 null,
15400                 null);
15401 
15402         // default callbacks will be unregistered in tearDown
15403     }
15404 
15405     @Test
15406     public void testNetworkFactoryRequestsWithMultilayerRequest()
15407             throws Exception {
15408         // First use OEM_PAID preference to create a multi-layer request : 1. listen for
15409         // unmetered, 2. request network with cap OEM_PAID, 3, request the default network for
15410         // fallback.
15411         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
15412                 OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PAID;
15413         setupMultipleDefaultNetworksForOemNetworkPreferenceCurrentUidTest(networkPref);
15414 
15415         final HandlerThread handlerThread = new HandlerThread("MockFactory");
15416         handlerThread.start();
15417         NetworkCapabilities internetFilter = new NetworkCapabilities()
15418                 .addCapability(NET_CAPABILITY_INTERNET)
15419                 .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED);
15420         final MockNetworkFactory internetFactory = new MockNetworkFactory(handlerThread.getLooper(),
15421                 mServiceContext, "internetFactory", internetFilter, mCsHandlerThread);
15422         internetFactory.setScoreFilter(40);
15423         internetFactory.register();
15424         // Default internet request only. The unmetered request is never sent to factories (it's a
15425         // LISTEN, not requestable). The 3rd (fallback) request in OEM_PAID NRI is TRACK_DEFAULT
15426         // which is also not sent to factories. Finally, the OEM_PAID request doesn't match the
15427         // internetFactory filter.
15428         internetFactory.expectRequestAdds(1);
15429         internetFactory.assertRequestCountEquals(1);
15430 
15431         NetworkCapabilities oemPaidFilter = new NetworkCapabilities()
15432                 .addCapability(NET_CAPABILITY_INTERNET)
15433                 .addCapability(NET_CAPABILITY_OEM_PAID)
15434                 .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
15435                 .removeCapability(NET_CAPABILITY_NOT_RESTRICTED);
15436         final MockNetworkFactory oemPaidFactory = new MockNetworkFactory(handlerThread.getLooper(),
15437                 mServiceContext, "oemPaidFactory", oemPaidFilter, mCsHandlerThread);
15438         oemPaidFactory.setScoreFilter(40);
15439         oemPaidFactory.register();
15440         oemPaidFactory.expectRequestAdd(); // Because nobody satisfies the request
15441 
15442         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
15443         mCellAgent.connect(true);
15444 
15445         // A network connected that satisfies the default internet request. For the OEM_PAID
15446         // preference, this is not as good as an OEM_PAID network, so even if the score of
15447         // the network is better than the factory announced, it still should try to bring up
15448         // the network.
15449         expectNoRequestChanged(oemPaidFactory);
15450         oemPaidFactory.assertRequestCountEquals(1);
15451         // The internet factory however is outscored, and should lose its requests.
15452         internetFactory.expectRequestRemove();
15453         internetFactory.assertRequestCountEquals(0);
15454 
15455         final NetworkCapabilities oemPaidNc = new NetworkCapabilities();
15456         oemPaidNc.addCapability(NET_CAPABILITY_OEM_PAID);
15457         oemPaidNc.removeCapability(NET_CAPABILITY_NOT_RESTRICTED);
15458         final TestNetworkAgentWrapper oemPaidAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR,
15459                 new LinkProperties(), oemPaidNc);
15460         oemPaidAgent.connect(true);
15461 
15462         // The oemPaidAgent has score 50/cell transport, so it beats what the oemPaidFactory can
15463         // provide, therefore it loses the request.
15464         oemPaidFactory.expectRequestRemove();
15465         oemPaidFactory.assertRequestCountEquals(0);
15466         expectNoRequestChanged(internetFactory);
15467         internetFactory.assertRequestCountEquals(0);
15468 
15469         oemPaidAgent.setScore(new NetworkScore.Builder().setLegacyInt(20).setExiting(true).build());
15470         // Now the that the agent is weak, the oemPaidFactory can beat the existing network for the
15471         // OEM_PAID request. The internet factory however can't beat a network that has OEM_PAID
15472         // for the preference request, so it doesn't see the request.
15473         oemPaidFactory.expectRequestAdd();
15474         oemPaidFactory.assertRequestCountEquals(1);
15475         expectNoRequestChanged(internetFactory);
15476         internetFactory.assertRequestCountEquals(0);
15477 
15478         mCellAgent.disconnect();
15479         // The network satisfying the default internet request has disconnected, so the
15480         // internetFactory sees the default request again. However there is a network with OEM_PAID
15481         // connected, so the 2nd OEM_PAID req is already satisfied, so the oemPaidFactory doesn't
15482         // care about networks that don't have OEM_PAID.
15483         expectNoRequestChanged(oemPaidFactory);
15484         oemPaidFactory.assertRequestCountEquals(1);
15485         internetFactory.expectRequestAdd();
15486         internetFactory.assertRequestCountEquals(1);
15487 
15488         // Cell connects again, still with score 50. Back to the previous state.
15489         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
15490         mCellAgent.connect(true);
15491         expectNoRequestChanged(oemPaidFactory);
15492         oemPaidFactory.assertRequestCountEquals(1);
15493         internetFactory.expectRequestRemove();
15494         internetFactory.assertRequestCountEquals(0);
15495 
15496         // Create a request that holds the upcoming wifi network.
15497         final TestNetworkCallback wifiCallback = new TestNetworkCallback();
15498         mCm.requestNetwork(new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI).build(),
15499                 wifiCallback);
15500 
15501         // Now WiFi connects and it's unmetered, but it's weaker than cell.
15502         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
15503         mWiFiAgent.addCapability(NET_CAPABILITY_NOT_METERED);
15504         mWiFiAgent.setScore(new NetworkScore.Builder().setLegacyInt(30).setExiting(true)
15505                 .build()); // Not the best Internet network, but unmetered
15506         mWiFiAgent.connect(true);
15507 
15508         // The OEM_PAID preference prefers an unmetered network to an OEM_PAID network, so
15509         // the oemPaidFactory can't beat wifi no matter how high its score.
15510         oemPaidFactory.expectRequestRemove();
15511         expectNoRequestChanged(internetFactory);
15512 
15513         mCellAgent.disconnect();
15514         // Now that the best internet network (cell, with its 50 score compared to 30 for WiFi
15515         // at this point), the default internet request is satisfied by a network worse than
15516         // the internetFactory announced, so it gets the request. However, there is still an
15517         // unmetered network, so the oemPaidNetworkFactory still can't beat this.
15518         expectNoRequestChanged(oemPaidFactory);
15519         internetFactory.expectRequestAdd();
15520         mCm.unregisterNetworkCallback(wifiCallback);
15521         handlerThread.quitSafely();
15522         handlerThread.join();
15523     }
15524 
15525     /**
15526      * Test network priority for OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK in the following order:
15527      * NET_CAPABILITY_NOT_METERED -> NET_CAPABILITY_OEM_PAID
15528      */
15529     @Test
15530     public void testMultipleDefaultNetworksTracksOemNetworkPreferenceOemPaidNoFallbackCorrectly()
15531             throws Exception {
15532         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
15533                 OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK;
15534         setupMultipleDefaultNetworksForOemNetworkPreferenceCurrentUidTest(networkPref);
15535         final int expectedDefaultRequestSize = 2;
15536         final int expectedOemPrefRequestSize = 2;
15537         registerDefaultNetworkCallbacks();
15538 
15539         // The fallback as well as the OEM preference should now be tracked.
15540         assertEquals(expectedDefaultRequestSize, mService.mDefaultNetworkRequests.size());
15541 
15542         // Test lowest to highest priority requests.
15543         // Bring up metered cellular. This will satisfy the fallback network but not the pref.
15544         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true);
15545         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
15546                 mCellAgent.getNetwork(),
15547                 mService.mNoServiceNetwork.network());
15548 
15549         // Bring up ethernet with OEM_PAID. This will satisfy NET_CAPABILITY_OEM_PAID.
15550         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, true);
15551         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
15552                 mCellAgent.getNetwork(),
15553                 mEthernetAgent.getNetwork());
15554 
15555         // Bring up unmetered Wi-Fi. This will satisfy NET_CAPABILITY_NOT_METERED.
15556         setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, true);
15557         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
15558                 mWiFiAgent.getNetwork(),
15559                 mWiFiAgent.getNetwork());
15560 
15561         // Disconnecting unmetered Wi-Fi will put the OEM pref on OEM_PAID and fallback on cellular.
15562         setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, false);
15563         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
15564                 mCellAgent.getNetwork(),
15565                 mEthernetAgent.getNetwork());
15566 
15567         // Disconnecting cellular should keep OEM network on OEM_PAID and fallback will be null.
15568         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, false);
15569         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
15570                 null,
15571                 mEthernetAgent.getNetwork());
15572 
15573         // Disconnecting OEM_PAID puts the fallback on null and the pref on the disconnected net.
15574         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, false);
15575         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
15576                 null,
15577                 mService.mNoServiceNetwork.network());
15578 
15579         // default callbacks will be unregistered in tearDown
15580     }
15581 
15582     /**
15583      * Test network priority for OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY in the following order:
15584      * NET_CAPABILITY_OEM_PAID
15585      * This preference should only apply to OEM_PAID networks.
15586      */
15587     @Test
15588     public void testMultipleDefaultNetworksTracksOemNetworkPreferenceOemPaidOnlyCorrectly()
15589             throws Exception {
15590         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
15591                 OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY;
15592         setupMultipleDefaultNetworksForOemNetworkPreferenceCurrentUidTest(networkPref);
15593         final int expectedDefaultRequestSize = 2;
15594         final int expectedOemPrefRequestSize = 1;
15595         registerDefaultNetworkCallbacks();
15596 
15597         // The fallback as well as the OEM preference should now be tracked.
15598         assertEquals(expectedDefaultRequestSize, mService.mDefaultNetworkRequests.size());
15599 
15600         // Test lowest to highest priority requests.
15601         // Bring up metered cellular. This will satisfy the fallback network.
15602         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true);
15603         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
15604                 mCellAgent.getNetwork(),
15605                 mService.mNoServiceNetwork.network());
15606 
15607         // Bring up ethernet with OEM_PAID. This will satisfy NET_CAPABILITY_OEM_PAID.
15608         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, true);
15609         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
15610                 mCellAgent.getNetwork(),
15611                 mEthernetAgent.getNetwork());
15612 
15613         // Bring up unmetered Wi-Fi. The OEM network shouldn't change, the fallback will take Wi-Fi.
15614         setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, true);
15615         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
15616                 mWiFiAgent.getNetwork(),
15617                 mEthernetAgent.getNetwork());
15618 
15619         // Disconnecting unmetered Wi-Fi shouldn't change the OEM network with fallback on cellular.
15620         setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, false);
15621         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
15622                 mCellAgent.getNetwork(),
15623                 mEthernetAgent.getNetwork());
15624 
15625         // Disconnecting OEM_PAID will keep the fallback on cellular and nothing for OEM_PAID.
15626         // OEM_PAID_ONLY not supporting a fallback now uses the disconnected network.
15627         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, false);
15628         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
15629                 mCellAgent.getNetwork(),
15630                 mService.mNoServiceNetwork.network());
15631 
15632         // Disconnecting cellular will put the fallback on null and the pref on disconnected.
15633         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, false);
15634         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
15635                 null,
15636                 mService.mNoServiceNetwork.network());
15637 
15638         // default callbacks will be unregistered in tearDown
15639     }
15640 
15641     /**
15642      * Test network priority for OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY in the following order:
15643      * NET_CAPABILITY_OEM_PRIVATE
15644      * This preference should only apply to OEM_PRIVATE networks.
15645      */
15646     @Test
15647     public void testMultipleDefaultNetworksTracksOemNetworkPreferenceOemPrivateOnlyCorrectly()
15648             throws Exception {
15649         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
15650                 OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY;
15651         setupMultipleDefaultNetworksForOemNetworkPreferenceCurrentUidTest(networkPref);
15652         final int expectedDefaultRequestSize = 2;
15653         final int expectedOemPrefRequestSize = 1;
15654         registerDefaultNetworkCallbacks();
15655 
15656         // The fallback as well as the OEM preference should now be tracked.
15657         assertEquals(expectedDefaultRequestSize, mService.mDefaultNetworkRequests.size());
15658 
15659         // Test lowest to highest priority requests.
15660         // Bring up metered cellular. This will satisfy the fallback network.
15661         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true);
15662         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
15663                 mCellAgent.getNetwork(),
15664                 mService.mNoServiceNetwork.network());
15665 
15666         // Bring up ethernet with OEM_PRIVATE. This will satisfy NET_CAPABILITY_OEM_PRIVATE.
15667         startOemManagedNetwork(false);
15668         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
15669                 mCellAgent.getNetwork(),
15670                 mEthernetAgent.getNetwork());
15671 
15672         // Bring up unmetered Wi-Fi. The OEM network shouldn't change, the fallback will take Wi-Fi.
15673         setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, true);
15674         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
15675                 mWiFiAgent.getNetwork(),
15676                 mEthernetAgent.getNetwork());
15677 
15678         // Disconnecting unmetered Wi-Fi shouldn't change the OEM network with fallback on cellular.
15679         setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, false);
15680         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
15681                 mCellAgent.getNetwork(),
15682                 mEthernetAgent.getNetwork());
15683 
15684         // Disconnecting OEM_PRIVATE will keep the fallback on cellular.
15685         // OEM_PRIVATE_ONLY not supporting a fallback now uses to the disconnected network.
15686         stopOemManagedNetwork();
15687         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
15688                 mCellAgent.getNetwork(),
15689                 mService.mNoServiceNetwork.network());
15690 
15691         // Disconnecting cellular will put the fallback on null and pref on disconnected.
15692         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, false);
15693         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
15694                 null,
15695                 mService.mNoServiceNetwork.network());
15696 
15697         // default callbacks will be unregistered in tearDown
15698     }
15699 
15700     @Test
15701     public void testCapabilityWithOemNetworkPreference() throws Exception {
15702         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
15703                 OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY;
15704         setupMultipleDefaultNetworksForOemNetworkPreferenceNotCurrentUidTest(networkPref);
15705         registerDefaultNetworkCallbacks();
15706 
15707         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true);
15708 
15709         mSystemDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
15710         mDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
15711 
15712         mCellAgent.addCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED);
15713         mSystemDefaultNetworkCallback.expectCaps(mCellAgent,
15714                 c -> c.hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED));
15715         mDefaultNetworkCallback.expectCaps(mCellAgent,
15716                 c -> c.hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED));
15717 
15718         // default callbacks will be unregistered in tearDown
15719     }
15720 
15721     @Test
15722     public void testSetOemNetworkPreferenceLogsRequest() throws Exception {
15723         mServiceContext.setPermission(DUMP, PERMISSION_GRANTED);
15724         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
15725                 OEM_NETWORK_PREFERENCE_OEM_PAID;
15726         final StringWriter stringWriter = new StringWriter();
15727         final String logIdentifier = "UPDATE INITIATED: OemNetworkPreferences";
15728         final Pattern pattern = Pattern.compile(logIdentifier);
15729 
15730         final int expectedNumLogs = 2;
15731         final UidRangeParcel[] uidRanges =
15732                 toUidRangeStableParcels(uidRangesForUids(TEST_PACKAGE_UID));
15733 
15734         // Call twice to generate two logs.
15735         setupSetOemNetworkPreferenceForPreferenceTest(networkPref, uidRanges, TEST_PACKAGE_NAME);
15736         setupSetOemNetworkPreferenceForPreferenceTest(networkPref, uidRanges, TEST_PACKAGE_NAME);
15737         mService.dump(new FileDescriptor(), new PrintWriter(stringWriter), new String[0]);
15738 
15739         final String dumpOutput = stringWriter.toString();
15740         final Matcher matcher = pattern.matcher(dumpOutput);
15741         int count = 0;
15742         while (matcher.find()) {
15743             count++;
15744         }
15745         assertEquals(expectedNumLogs, count);
15746     }
15747 
15748     @Test
15749     public void testGetAllNetworkStateSnapshots() throws Exception {
15750         verifyNoNetwork();
15751 
15752         // Setup test cellular network with specified LinkProperties and NetworkCapabilities,
15753         // verify the content of the snapshot matches.
15754         final LinkProperties cellLp = new LinkProperties();
15755         final LinkAddress myIpv4Addr = new LinkAddress(InetAddress.getByName("192.0.2.129"), 25);
15756         final LinkAddress myIpv6Addr = new LinkAddress(InetAddress.getByName("2001:db8::1"), 64);
15757         cellLp.setInterfaceName("test01");
15758         cellLp.addLinkAddress(myIpv4Addr);
15759         cellLp.addLinkAddress(myIpv6Addr);
15760         cellLp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
15761         cellLp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
15762         cellLp.addRoute(new RouteInfo(myIpv4Addr, null));
15763         cellLp.addRoute(new RouteInfo(myIpv6Addr, null));
15764         final NetworkCapabilities cellNcTemplate = new NetworkCapabilities.Builder()
15765                 .addTransportType(TRANSPORT_CELLULAR).addCapability(NET_CAPABILITY_MMS).build();
15766 
15767         final TestNetworkCallback cellCb = new TestNetworkCallback();
15768         mCm.requestNetwork(new NetworkRequest.Builder().addCapability(NET_CAPABILITY_MMS).build(),
15769                 cellCb);
15770         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp, cellNcTemplate);
15771         mCellAgent.connect(true);
15772         cellCb.expectAvailableCallbacksUnvalidated(mCellAgent);
15773         List<NetworkStateSnapshot> snapshots = mCm.getAllNetworkStateSnapshots();
15774         assertLength(1, snapshots);
15775 
15776         // Compose the expected cellular snapshot for verification.
15777         final NetworkCapabilities cellNc =
15778                 mCm.getNetworkCapabilities(mCellAgent.getNetwork());
15779         final NetworkStateSnapshot cellSnapshot = new NetworkStateSnapshot(
15780                 mCellAgent.getNetwork(), cellNc, cellLp,
15781                 null, ConnectivityManager.TYPE_MOBILE);
15782         assertEquals(cellSnapshot, snapshots.get(0));
15783 
15784         // Connect wifi and verify the snapshots.
15785         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
15786         mWiFiAgent.connect(true);
15787         waitForIdle();
15788         // Compose the expected wifi snapshot for verification.
15789         final NetworkCapabilities wifiNc =
15790                 mCm.getNetworkCapabilities(mWiFiAgent.getNetwork());
15791         final NetworkStateSnapshot wifiSnapshot = new NetworkStateSnapshot(
15792                 mWiFiAgent.getNetwork(), wifiNc, new LinkProperties(), null,
15793                 ConnectivityManager.TYPE_WIFI);
15794 
15795         snapshots = mCm.getAllNetworkStateSnapshots();
15796         assertLength(2, snapshots);
15797         assertContainsAll(snapshots, cellSnapshot, wifiSnapshot);
15798 
15799         // Set cellular as suspended, verify the snapshots will contain suspended networks.
15800         mCellAgent.suspend();
15801         waitForIdle();
15802         final NetworkCapabilities cellSuspendedNc =
15803                 mCm.getNetworkCapabilities(mCellAgent.getNetwork());
15804         assertFalse(cellSuspendedNc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
15805         final NetworkStateSnapshot cellSuspendedSnapshot = new NetworkStateSnapshot(
15806                 mCellAgent.getNetwork(), cellSuspendedNc, cellLp,
15807                 null, ConnectivityManager.TYPE_MOBILE);
15808         snapshots = mCm.getAllNetworkStateSnapshots();
15809         assertLength(2, snapshots);
15810         assertContainsAll(snapshots, cellSuspendedSnapshot, wifiSnapshot);
15811 
15812         // Disconnect wifi, verify the snapshots contain only cellular.
15813         mWiFiAgent.disconnect();
15814         waitForIdle();
15815         snapshots = mCm.getAllNetworkStateSnapshots();
15816         assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetwork());
15817         assertLength(1, snapshots);
15818         assertEquals(cellSuspendedSnapshot, snapshots.get(0));
15819 
15820         mCellAgent.resume();
15821         waitForIdle();
15822         snapshots = mCm.getAllNetworkStateSnapshots();
15823         assertLength(1, snapshots);
15824         assertEquals(cellSnapshot, snapshots.get(0));
15825 
15826         mCellAgent.disconnect();
15827         waitForIdle();
15828         verifyNoNetwork();
15829         mCm.unregisterNetworkCallback(cellCb);
15830     }
15831 
15832     // Cannot be part of MockNetworkFactory since it requires method of the test.
15833     private void expectNoRequestChanged(@NonNull MockNetworkFactory factory) {
15834         waitForIdle();
15835         factory.assertNoRequestChanged();
15836     }
15837 
15838     @Test
15839     public void testRegisterBestMatchingNetworkCallback_noIssueToFactory() throws Exception {
15840         // Prepare mock mms factory.
15841         final HandlerThread handlerThread = new HandlerThread("MockCellularFactory");
15842         handlerThread.start();
15843         NetworkCapabilities filter = new NetworkCapabilities()
15844                 .addTransportType(TRANSPORT_CELLULAR)
15845                 .addCapability(NET_CAPABILITY_MMS);
15846         final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
15847                 mServiceContext, "testFactory", filter, mCsHandlerThread);
15848         testFactory.setScoreFilter(40);
15849 
15850         try {
15851             // Register the factory. It doesn't see the default request because its filter does
15852             // not include INTERNET.
15853             testFactory.register();
15854             expectNoRequestChanged(testFactory);
15855             testFactory.assertRequestCountEquals(0);
15856             // The factory won't try to start the network since the default request doesn't
15857             // match the filter (no INTERNET capability).
15858             assertFalse(testFactory.getMyStartRequested());
15859 
15860             // Register callback for listening best matching network. Verify that the request won't
15861             // be sent to factory.
15862             final TestNetworkCallback bestMatchingCb = new TestNetworkCallback();
15863             mCm.registerBestMatchingNetworkCallback(
15864                     new NetworkRequest.Builder().addCapability(NET_CAPABILITY_MMS).build(),
15865                     bestMatchingCb, mCsHandlerThread.getThreadHandler());
15866             bestMatchingCb.assertNoCallback();
15867             expectNoRequestChanged(testFactory);
15868             testFactory.assertRequestCountEquals(0);
15869             assertFalse(testFactory.getMyStartRequested());
15870 
15871             // Fire a normal mms request, verify the factory will only see the request.
15872             final TestNetworkCallback mmsNetworkCallback = new TestNetworkCallback();
15873             final NetworkRequest mmsRequest = new NetworkRequest.Builder()
15874                     .addCapability(NET_CAPABILITY_MMS).build();
15875             mCm.requestNetwork(mmsRequest, mmsNetworkCallback);
15876             testFactory.expectRequestAdd();
15877             testFactory.assertRequestCountEquals(1);
15878             assertTrue(testFactory.getMyStartRequested());
15879 
15880             // Unregister best matching callback, verify factory see no change.
15881             mCm.unregisterNetworkCallback(bestMatchingCb);
15882             expectNoRequestChanged(testFactory);
15883             testFactory.assertRequestCountEquals(1);
15884             assertTrue(testFactory.getMyStartRequested());
15885         } finally {
15886             testFactory.terminate();
15887             handlerThread.quitSafely();
15888             handlerThread.join();
15889         }
15890     }
15891 
15892     @Test
15893     public void testRegisterBestMatchingNetworkCallback_trackBestNetwork() throws Exception {
15894         final TestNetworkCallback bestMatchingCb = new TestNetworkCallback();
15895         mCm.registerBestMatchingNetworkCallback(
15896                 new NetworkRequest.Builder().addCapability(NET_CAPABILITY_TRUSTED).build(),
15897                 bestMatchingCb, mCsHandlerThread.getThreadHandler());
15898 
15899         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
15900         mCellAgent.connect(true);
15901         bestMatchingCb.expectAvailableThenValidatedCallbacks(mCellAgent);
15902 
15903         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
15904         mWiFiAgent.connect(true);
15905         bestMatchingCb.expectAvailableDoubleValidatedCallbacks(mWiFiAgent);
15906 
15907         // Change something on cellular to trigger capabilities changed, since the callback
15908         // only cares about the best network, verify it received nothing from cellular.
15909         mCellAgent.addCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED);
15910         bestMatchingCb.assertNoCallback();
15911 
15912         // Make cellular the best network again, verify the callback now tracks cellular.
15913         mWiFiAgent.adjustScore(-50);
15914         bestMatchingCb.expectAvailableCallbacksValidated(mCellAgent);
15915 
15916         // Make cellular temporary non-trusted, which will not satisfying the request.
15917         // Verify the callback switch from/to the other network accordingly.
15918         mCellAgent.removeCapability(NET_CAPABILITY_TRUSTED);
15919         bestMatchingCb.expectAvailableCallbacksValidated(mWiFiAgent);
15920         mCellAgent.addCapability(NET_CAPABILITY_TRUSTED);
15921         bestMatchingCb.expectAvailableDoubleValidatedCallbacks(mCellAgent);
15922 
15923         // Verify the callback doesn't care about wifi disconnect.
15924         mWiFiAgent.disconnect();
15925         bestMatchingCb.assertNoCallback();
15926         mCellAgent.disconnect();
15927         bestMatchingCb.expect(LOST, mCellAgent);
15928     }
15929 
15930     private UidRangeParcel[] uidRangeFor(final UserHandle handle) {
15931         final UidRange range = UidRange.createForUser(handle);
15932         return new UidRangeParcel[] { new UidRangeParcel(range.start, range.stop) };
15933     }
15934 
15935     private UidRangeParcel[] uidRangeFor(final UserHandle handle,
15936             ProfileNetworkPreference profileNetworkPreference) {
15937         final Set<UidRange> uidRangeSet;
15938         UidRange range = UidRange.createForUser(handle);
15939         if (profileNetworkPreference.getIncludedUids().length != 0) {
15940             uidRangeSet = UidRangeUtils.convertArrayToUidRange(
15941                     profileNetworkPreference.getIncludedUids());
15942 
15943         } else if (profileNetworkPreference.getExcludedUids().length != 0)  {
15944             uidRangeSet = UidRangeUtils.removeRangeSetFromUidRange(
15945                     range, UidRangeUtils.convertArrayToUidRange(
15946                             profileNetworkPreference.getExcludedUids()));
15947         } else {
15948             uidRangeSet = new ArraySet<>();
15949             uidRangeSet.add(range);
15950         }
15951         UidRangeParcel[] uidRangeParcels = new UidRangeParcel[uidRangeSet.size()];
15952         int i = 0;
15953         for (UidRange range1 : uidRangeSet) {
15954             uidRangeParcels[i] = new UidRangeParcel(range1.start, range1.stop);
15955             i++;
15956         }
15957         return uidRangeParcels;
15958     }
15959 
15960     private static class TestOnCompleteListener implements Runnable {
15961         final class OnComplete {}
15962         final ArrayTrackRecord<OnComplete>.ReadHead mHistory =
15963                 new ArrayTrackRecord<OnComplete>().newReadHead();
15964 
15965         @Override
15966         public void run() {
15967             mHistory.add(new OnComplete());
15968         }
15969 
15970         public void expectOnComplete() {
15971             assertNotNull(mHistory.poll(TIMEOUT_MS, it -> true));
15972         }
15973     }
15974 
15975     private TestNetworkAgentWrapper makeEnterpriseNetworkAgent() throws Exception {
15976         final NetworkCapabilities workNc = new NetworkCapabilities();
15977         workNc.addCapability(NET_CAPABILITY_ENTERPRISE);
15978         workNc.removeCapability(NET_CAPABILITY_NOT_RESTRICTED);
15979         return new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, new LinkProperties(), workNc);
15980     }
15981 
15982     private TestNetworkAgentWrapper makeEnterpriseNetworkAgent(int enterpriseId) throws Exception {
15983         final NetworkCapabilities workNc = new NetworkCapabilities();
15984         workNc.addCapability(NET_CAPABILITY_ENTERPRISE);
15985         workNc.removeCapability(NET_CAPABILITY_NOT_RESTRICTED);
15986         workNc.addEnterpriseId(enterpriseId);
15987         return new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, new LinkProperties(), workNc);
15988     }
15989 
15990     private TestNetworkCallback mEnterpriseCallback;
15991     private UserHandle setupEnterpriseNetwork() {
15992         final UserHandle userHandle = UserHandle.of(TEST_WORK_PROFILE_USER_ID);
15993         mServiceContext.setWorkProfile(userHandle, true);
15994 
15995         // File a request to avoid the enterprise network being disconnected as soon as the default
15996         // request goes away – it would make impossible to test that networkRemoveUidRanges
15997         // is called, as the network would disconnect first for lack of a request.
15998         mEnterpriseCallback = new TestNetworkCallback();
15999         final NetworkRequest keepUpRequest = new NetworkRequest.Builder()
16000                 .addCapability(NET_CAPABILITY_ENTERPRISE)
16001                 .build();
16002         mCm.requestNetwork(keepUpRequest, mEnterpriseCallback);
16003         return userHandle;
16004     }
16005 
16006     private void maybeTearDownEnterpriseNetwork() {
16007         if (null != mEnterpriseCallback) {
16008             mCm.unregisterNetworkCallback(mEnterpriseCallback);
16009         }
16010     }
16011 
16012     /**
16013      * Make sure per profile network preferences behave as expected for a given
16014      * profile network preference.
16015      */
16016     private void doTestPreferenceForUserNetworkUpDownForGivenPreference(
16017             ProfileNetworkPreference profileNetworkPreference,
16018             boolean connectWorkProfileAgentAhead,
16019             UserHandle testHandle,
16020             TestNetworkCallback profileDefaultNetworkCallback,
16021             TestNetworkCallback disAllowProfileDefaultNetworkCallback) throws Exception {
16022         final InOrder inOrder = inOrder(mMockNetd, mMockDnsResolver);
16023 
16024         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
16025         mCellAgent.connect(true);
16026 
16027         mSystemDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
16028         mDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
16029         profileDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
16030         if (disAllowProfileDefaultNetworkCallback != null) {
16031             disAllowProfileDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
16032         }
16033         inOrder.verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
16034                 mCellAgent.getNetwork().netId, INetd.PERMISSION_NONE));
16035 
16036         final TestNetworkAgentWrapper workAgent =
16037                 makeEnterpriseNetworkAgent(profileNetworkPreference.getPreferenceEnterpriseId());
16038         if (mService.shouldCreateNetworksImmediately()) {
16039             expectNativeNetworkCreated(workAgent.getNetwork().netId, INetd.PERMISSION_SYSTEM,
16040                     null /* iface */, inOrder);
16041         }
16042         if (connectWorkProfileAgentAhead) {
16043             workAgent.connect(false);
16044             if (!mService.shouldCreateNetworksImmediately()) {
16045                 expectNativeNetworkCreated(workAgent.getNetwork().netId, INetd.PERMISSION_SYSTEM,
16046                         null /* iface */, inOrder);
16047             }
16048         }
16049 
16050         final TestOnCompleteListener listener = new TestOnCompleteListener();
16051         mCm.setProfileNetworkPreferences(testHandle, List.of(profileNetworkPreference),
16052                 r -> r.run(), listener);
16053         listener.expectOnComplete();
16054         boolean allowFallback = true;
16055         if (profileNetworkPreference.getPreference()
16056                 == PROFILE_NETWORK_PREFERENCE_ENTERPRISE_NO_FALLBACK) {
16057             allowFallback = false;
16058         }
16059         if (allowFallback && !connectWorkProfileAgentAhead) {
16060             // Setting a network preference for this user will create a new set of routing rules for
16061             // the UID range that corresponds to this user, inorder to define the default network
16062             // for these apps separately. This is true because the multi-layer request relevant to
16063             // this UID range contains a TRACK_DEFAULT, so the range will be moved through
16064             // UID-specific rules to the correct network – in this case the system default network.
16065             // The case where the default network for the profile happens to be the same as the
16066             // system default is not handled specially, the rules are always active as long as
16067             // a preference is set.
16068             inOrder.verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
16069                     mCellAgent.getNetwork().netId,
16070                     uidRangeFor(testHandle, profileNetworkPreference),
16071                     PREFERENCE_ORDER_PROFILE));
16072         }
16073 
16074         // The enterprise network is not ready yet.
16075         assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback);
16076         if (allowFallback && !connectWorkProfileAgentAhead) {
16077             assertNoCallbacks(profileDefaultNetworkCallback);
16078         } else if (!connectWorkProfileAgentAhead) {
16079             profileDefaultNetworkCallback.expect(LOST, mCellAgent);
16080             if (disAllowProfileDefaultNetworkCallback != null) {
16081                 assertNoCallbacks(disAllowProfileDefaultNetworkCallback);
16082             }
16083         }
16084 
16085         if (!connectWorkProfileAgentAhead) {
16086             workAgent.connect(false);
16087             if (!mService.shouldCreateNetworksImmediately()) {
16088                 inOrder.verify(mMockNetd).networkCreate(
16089                         nativeNetworkConfigPhysical(workAgent.getNetwork().netId,
16090                                 INetd.PERMISSION_SYSTEM));
16091             }
16092         }
16093 
16094         profileDefaultNetworkCallback.expectAvailableCallbacksUnvalidated(workAgent);
16095         if (disAllowProfileDefaultNetworkCallback != null) {
16096             disAllowProfileDefaultNetworkCallback.assertNoCallback();
16097         }
16098         mSystemDefaultNetworkCallback.assertNoCallback();
16099         mDefaultNetworkCallback.assertNoCallback();
16100         inOrder.verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
16101                 workAgent.getNetwork().netId,
16102                 uidRangeFor(testHandle, profileNetworkPreference),
16103                 PREFERENCE_ORDER_PROFILE));
16104 
16105         if (allowFallback && !connectWorkProfileAgentAhead) {
16106             inOrder.verify(mMockNetd).networkRemoveUidRangesParcel(new NativeUidRangeConfig(
16107                     mCellAgent.getNetwork().netId,
16108                     uidRangeFor(testHandle, profileNetworkPreference),
16109                     PREFERENCE_ORDER_PROFILE));
16110         }
16111 
16112         // Make sure changes to the work agent send callbacks to the app in the work profile, but
16113         // not to the other apps.
16114         workAgent.setNetworkValid(true /* privateDnsProbeSent */);
16115         workAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
16116         profileDefaultNetworkCallback.expectCaps(workAgent,
16117                 c -> c.hasCapability(NET_CAPABILITY_VALIDATED)
16118                         && c.hasCapability(NET_CAPABILITY_ENTERPRISE)
16119                         && c.hasEnterpriseId(profileNetworkPreference.getPreferenceEnterpriseId())
16120                         && c.getEnterpriseIds().length == 1);
16121         if (disAllowProfileDefaultNetworkCallback != null) {
16122             assertNoCallbacks(disAllowProfileDefaultNetworkCallback);
16123         }
16124         assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback);
16125 
16126         workAgent.addCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED);
16127         profileDefaultNetworkCallback.expectCaps(workAgent,
16128                 c -> c.hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED));
16129         if (disAllowProfileDefaultNetworkCallback != null) {
16130             assertNoCallbacks(disAllowProfileDefaultNetworkCallback);
16131         }
16132         assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback);
16133 
16134         // Conversely, change a capability on the system-wide default network and make sure
16135         // that only the apps outside of the work profile receive the callbacks.
16136         mCellAgent.addCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED);
16137         mSystemDefaultNetworkCallback.expectCaps(mCellAgent,
16138                 c -> c.hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED));
16139         mDefaultNetworkCallback.expectCaps(mCellAgent,
16140                 c -> c.hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED));
16141         if (disAllowProfileDefaultNetworkCallback != null) {
16142             disAllowProfileDefaultNetworkCallback.expectCaps(mCellAgent,
16143                     c -> c.hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED));
16144         }
16145         profileDefaultNetworkCallback.assertNoCallback();
16146 
16147         // Disconnect and reconnect the system-wide default network and make sure that the
16148         // apps on this network see the appropriate callbacks, and the app on the work profile
16149         // doesn't because it continues to use the enterprise network.
16150         mCellAgent.disconnect();
16151         mSystemDefaultNetworkCallback.expect(LOST, mCellAgent);
16152         mDefaultNetworkCallback.expect(LOST, mCellAgent);
16153         if (disAllowProfileDefaultNetworkCallback != null) {
16154             disAllowProfileDefaultNetworkCallback.expect(LOST, mCellAgent);
16155         }
16156         profileDefaultNetworkCallback.assertNoCallback();
16157         inOrder.verify(mMockNetd).networkDestroy(mCellAgent.getNetwork().netId);
16158 
16159         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
16160         mCellAgent.connect(true);
16161         mSystemDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
16162         mDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
16163         if (disAllowProfileDefaultNetworkCallback != null) {
16164             disAllowProfileDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
16165 
16166         }
16167         profileDefaultNetworkCallback.assertNoCallback();
16168         inOrder.verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
16169                 mCellAgent.getNetwork().netId, INetd.PERMISSION_NONE));
16170 
16171         // When the agent disconnects, test that the app on the work profile falls back to the
16172         // default network.
16173         workAgent.disconnect();
16174         profileDefaultNetworkCallback.expect(LOST, workAgent);
16175         if (allowFallback) {
16176             profileDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellAgent);
16177             if (disAllowProfileDefaultNetworkCallback != null) {
16178                 assertNoCallbacks(disAllowProfileDefaultNetworkCallback);
16179             }
16180         }
16181         assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback);
16182         if (allowFallback) {
16183             inOrder.verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
16184                     mCellAgent.getNetwork().netId,
16185                     uidRangeFor(testHandle, profileNetworkPreference),
16186                     PREFERENCE_ORDER_PROFILE));
16187         }
16188         inOrder.verify(mMockNetd).networkDestroy(workAgent.getNetwork().netId);
16189 
16190         mCellAgent.disconnect();
16191         mSystemDefaultNetworkCallback.expect(LOST, mCellAgent);
16192         mDefaultNetworkCallback.expect(LOST, mCellAgent);
16193         if (disAllowProfileDefaultNetworkCallback != null) {
16194             disAllowProfileDefaultNetworkCallback.expect(LOST, mCellAgent);
16195         }
16196         if (allowFallback) {
16197             profileDefaultNetworkCallback.expect(LOST, mCellAgent);
16198         }
16199 
16200         // Waiting for the handler to be idle before checking for networkDestroy is necessary
16201         // here because ConnectivityService calls onLost before the network is fully torn down.
16202         waitForIdle();
16203         inOrder.verify(mMockNetd).networkDestroy(mCellAgent.getNetwork().netId);
16204 
16205         // If the control comes here, callbacks seem to behave correctly in the presence of
16206         // a default network when the enterprise network goes up and down. Now, make sure they
16207         // also behave correctly in the absence of a system-wide default network.
16208         final TestNetworkAgentWrapper workAgent2 =
16209                 makeEnterpriseNetworkAgent(profileNetworkPreference.getPreferenceEnterpriseId());
16210         workAgent2.connect(false);
16211 
16212         profileDefaultNetworkCallback.expectAvailableCallbacksUnvalidated(workAgent2);
16213         if (disAllowProfileDefaultNetworkCallback != null) {
16214             assertNoCallbacks(disAllowProfileDefaultNetworkCallback);
16215         }
16216         assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback);
16217         inOrder.verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
16218                 workAgent2.getNetwork().netId, INetd.PERMISSION_SYSTEM));
16219         inOrder.verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
16220                 workAgent2.getNetwork().netId,
16221                 uidRangeFor(testHandle, profileNetworkPreference), PREFERENCE_ORDER_PROFILE));
16222 
16223         workAgent2.setNetworkValid(true /* privateDnsProbeSent */);
16224         workAgent2.mNetworkMonitor.forceReevaluation(Process.myUid());
16225         profileDefaultNetworkCallback.expectCaps(workAgent2,
16226                 c -> c.hasCapability(NET_CAPABILITY_ENTERPRISE)
16227                         && !c.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)
16228                         && c.hasEnterpriseId(profileNetworkPreference.getPreferenceEnterpriseId())
16229                         && c.getEnterpriseIds().length == 1);
16230         if (disAllowProfileDefaultNetworkCallback != null) {
16231             assertNoCallbacks(disAllowProfileDefaultNetworkCallback);
16232         }
16233         assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback);
16234         inOrder.verify(mMockNetd, never()).networkAddUidRangesParcel(any());
16235 
16236         // When the agent disconnects, test that the app on the work profile fall back to the
16237         // default network.
16238         workAgent2.disconnect();
16239         profileDefaultNetworkCallback.expect(LOST, workAgent2);
16240         if (disAllowProfileDefaultNetworkCallback != null) {
16241             assertNoCallbacks(disAllowProfileDefaultNetworkCallback);
16242         }
16243         assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback);
16244         inOrder.verify(mMockNetd).networkDestroy(workAgent2.getNetwork().netId);
16245 
16246         assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback,
16247                 profileDefaultNetworkCallback);
16248 
16249         // Callbacks will be unregistered by tearDown()
16250     }
16251 
16252     /**
16253      * Make sure per-profile networking preference behaves as expected when the enterprise network
16254      * goes up and down while the preference is active. Make sure they behave as expected whether
16255      * there is a general default network or not.
16256      */
16257     @Test
16258     public void testPreferenceForUserNetworkUpDown() throws Exception {
16259         final UserHandle testHandle = setupEnterpriseNetwork();
16260         registerDefaultNetworkCallbacks();
16261         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder =
16262                 new ProfileNetworkPreference.Builder();
16263         profileNetworkPreferenceBuilder.setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE);
16264         profileNetworkPreferenceBuilder.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1);
16265         doTestPreferenceForUserNetworkUpDownForGivenPreference(
16266                 profileNetworkPreferenceBuilder.build(), false,
16267                 testHandle, mProfileDefaultNetworkCallback, null);
16268     }
16269 
16270     /**
16271      * Make sure per-profile networking preference behaves as expected when the enterprise network
16272      * goes up and down while the preference is active. Make sure they behave as expected whether
16273      * there is a general default network or not when configured to not fallback to default network.
16274      */
16275     @Test
16276     public void testPreferenceForUserNetworkUpDownWithNoFallback() throws Exception {
16277         final UserHandle testHandle = setupEnterpriseNetwork();
16278         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder =
16279                 new ProfileNetworkPreference.Builder();
16280         profileNetworkPreferenceBuilder.setPreference(
16281                 PROFILE_NETWORK_PREFERENCE_ENTERPRISE_NO_FALLBACK);
16282         profileNetworkPreferenceBuilder.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1);
16283         registerDefaultNetworkCallbacks();
16284         doTestPreferenceForUserNetworkUpDownForGivenPreference(
16285                 profileNetworkPreferenceBuilder.build(), false,
16286                 testHandle, mProfileDefaultNetworkCallback, null);
16287     }
16288 
16289     /**
16290      * Make sure per-profile networking preference behaves as expected when the enterprise network
16291      * goes up and down while the preference is active. Make sure they behave as expected whether
16292      * there is a general default network or not when configured to not fallback to default network
16293      * along with already connected enterprise work agent
16294      */
16295     @Test
16296     public void testPreferenceForUserNetworkUpDownWithNoFallbackWithAlreadyConnectedWorkAgent()
16297             throws Exception {
16298         final UserHandle testHandle = setupEnterpriseNetwork();
16299         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder =
16300                 new ProfileNetworkPreference.Builder();
16301         profileNetworkPreferenceBuilder.setPreference(
16302                 PROFILE_NETWORK_PREFERENCE_ENTERPRISE_NO_FALLBACK);
16303         profileNetworkPreferenceBuilder.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1);
16304         registerDefaultNetworkCallbacks();
16305         doTestPreferenceForUserNetworkUpDownForGivenPreference(
16306                 profileNetworkPreferenceBuilder.build(), true, testHandle,
16307                 mProfileDefaultNetworkCallback, null);
16308     }
16309 
16310     /**
16311      * Make sure per-profile networking preference for specific uid of test handle
16312      * behaves as expected
16313      */
16314     @Test
16315     public void testPreferenceForDefaultUidOfTestHandle() throws Exception {
16316         final UserHandle testHandle = setupEnterpriseNetwork();
16317         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder =
16318                 new ProfileNetworkPreference.Builder();
16319         profileNetworkPreferenceBuilder.setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE);
16320         profileNetworkPreferenceBuilder.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1);
16321         profileNetworkPreferenceBuilder.setIncludedUids(
16322                 new int[]{testHandle.getUid(TEST_WORK_PROFILE_APP_UID)});
16323         registerDefaultNetworkCallbacks();
16324         doTestPreferenceForUserNetworkUpDownForGivenPreference(
16325                 profileNetworkPreferenceBuilder.build(), false, testHandle,
16326                 mProfileDefaultNetworkCallback, null);
16327     }
16328 
16329     /**
16330      * Make sure per-profile networking preference for specific uid of test handle
16331      * behaves as expected
16332      */
16333     @Test
16334     public void testPreferenceForSpecificUidOfOnlyOneApp() throws Exception {
16335         final UserHandle testHandle = setupEnterpriseNetwork();
16336         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder =
16337                 new ProfileNetworkPreference.Builder();
16338         profileNetworkPreferenceBuilder.setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE);
16339         profileNetworkPreferenceBuilder.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1);
16340         profileNetworkPreferenceBuilder.setIncludedUids(
16341                 new int[]{testHandle.getUid(TEST_WORK_PROFILE_APP_UID_2)});
16342         registerDefaultNetworkCallbacks();
16343         doTestPreferenceForUserNetworkUpDownForGivenPreference(
16344                 profileNetworkPreferenceBuilder.build(), false,
16345                 testHandle, mProfileDefaultNetworkCallbackAsAppUid2, null);
16346     }
16347 
16348     /**
16349      * Make sure per-profile networking preference for specific uid of test handle
16350      * behaves as expected
16351      */
16352     @Test
16353     public void testPreferenceForDisallowSpecificUidOfApp() throws Exception {
16354         final UserHandle testHandle = setupEnterpriseNetwork();
16355         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder =
16356                 new ProfileNetworkPreference.Builder();
16357         profileNetworkPreferenceBuilder.setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE);
16358         profileNetworkPreferenceBuilder.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1);
16359         profileNetworkPreferenceBuilder.setExcludedUids(
16360                 new int[]{testHandle.getUid(TEST_WORK_PROFILE_APP_UID_2)});
16361         registerDefaultNetworkCallbacks();
16362         doTestPreferenceForUserNetworkUpDownForGivenPreference(
16363                 profileNetworkPreferenceBuilder.build(), false,
16364                 testHandle, mProfileDefaultNetworkCallback,
16365                 mProfileDefaultNetworkCallbackAsAppUid2);
16366     }
16367 
16368     /**
16369      * Make sure per-profile networking preference for specific uid of test handle
16370      * invalid uid inputs
16371      */
16372     @Test
16373     public void testPreferenceForInvalidUids() throws Exception {
16374         final UserHandle testHandle = setupEnterpriseNetwork();
16375         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder =
16376                 new ProfileNetworkPreference.Builder();
16377         profileNetworkPreferenceBuilder.setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE);
16378         profileNetworkPreferenceBuilder.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1);
16379         profileNetworkPreferenceBuilder.setExcludedUids(
16380                 new int[]{testHandle.getUid(0) - 1});
16381         final TestOnCompleteListener listener = new TestOnCompleteListener();
16382         Assert.assertThrows(IllegalArgumentException.class, () -> mCm.setProfileNetworkPreferences(
16383                 testHandle, List.of(profileNetworkPreferenceBuilder.build()),
16384                 r -> r.run(), listener));
16385 
16386         profileNetworkPreferenceBuilder.setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE);
16387         profileNetworkPreferenceBuilder.setIncludedUids(
16388                 new int[]{testHandle.getUid(0) - 1});
16389         Assert.assertThrows(IllegalArgumentException.class,
16390                 () -> mCm.setProfileNetworkPreferences(
16391                         testHandle, List.of(profileNetworkPreferenceBuilder.build()),
16392                         r -> r.run(), listener));
16393 
16394 
16395         profileNetworkPreferenceBuilder.setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE);
16396         profileNetworkPreferenceBuilder.setIncludedUids(
16397                 new int[]{testHandle.getUid(0) - 1});
16398         profileNetworkPreferenceBuilder.setExcludedUids(
16399                 new int[]{testHandle.getUid(TEST_WORK_PROFILE_APP_UID_2)});
16400         Assert.assertThrows(IllegalArgumentException.class,
16401                 () -> mCm.setProfileNetworkPreferences(
16402                         testHandle, List.of(profileNetworkPreferenceBuilder.build()),
16403                         r -> r.run(), listener));
16404 
16405         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder2 =
16406                 new ProfileNetworkPreference.Builder();
16407         profileNetworkPreferenceBuilder2.setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE);
16408         profileNetworkPreferenceBuilder2.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1);
16409         profileNetworkPreferenceBuilder2.setIncludedUids(
16410                 new int[]{testHandle.getUid(TEST_WORK_PROFILE_APP_UID_2)});
16411         profileNetworkPreferenceBuilder.setIncludedUids(
16412                 new int[]{testHandle.getUid(TEST_WORK_PROFILE_APP_UID_2)});
16413         Assert.assertThrows(IllegalArgumentException.class,
16414                 () -> mCm.setProfileNetworkPreferences(
16415                         testHandle, List.of(profileNetworkPreferenceBuilder.build(),
16416                                 profileNetworkPreferenceBuilder2.build()),
16417                         r -> r.run(), listener));
16418 
16419         profileNetworkPreferenceBuilder2.setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE);
16420         profileNetworkPreferenceBuilder2.setExcludedUids(
16421                 new int[]{testHandle.getUid(TEST_WORK_PROFILE_APP_UID_2)});
16422         profileNetworkPreferenceBuilder.setExcludedUids(
16423                 new int[]{testHandle.getUid(TEST_WORK_PROFILE_APP_UID_2)});
16424         Assert.assertThrows(IllegalArgumentException.class,
16425                 () -> mCm.setProfileNetworkPreferences(
16426                         testHandle, List.of(profileNetworkPreferenceBuilder.build(),
16427                                 profileNetworkPreferenceBuilder2.build()),
16428                         r -> r.run(), listener));
16429 
16430         profileNetworkPreferenceBuilder2.setPreference(
16431                 PROFILE_NETWORK_PREFERENCE_ENTERPRISE_NO_FALLBACK);
16432         profileNetworkPreferenceBuilder2.setExcludedUids(
16433                 new int[]{testHandle.getUid(TEST_WORK_PROFILE_APP_UID_2)});
16434         profileNetworkPreferenceBuilder.setExcludedUids(
16435                 new int[]{testHandle.getUid(TEST_WORK_PROFILE_APP_UID_2)});
16436         Assert.assertThrows(IllegalArgumentException.class,
16437                 () -> mCm.setProfileNetworkPreferences(
16438                         testHandle, List.of(profileNetworkPreferenceBuilder.build(),
16439                                 profileNetworkPreferenceBuilder2.build()),
16440                         r -> r.run(), listener));
16441     }
16442 
16443     /**
16444      * Make sure per-profile networking preference behaves as expected when the enterprise network
16445      * goes up and down while the preference is active. Make sure they behave as expected whether
16446      * there is a general default network or not when configured to fallback to default network
16447      * along with already connected enterprise work agent
16448      */
16449     @Test
16450     public void testPreferenceForUserNetworkUpDownWithFallbackWithAlreadyConnectedWorkAgent()
16451             throws Exception {
16452         final UserHandle testHandle = setupEnterpriseNetwork();
16453         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder =
16454                 new ProfileNetworkPreference.Builder();
16455         profileNetworkPreferenceBuilder.setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE);
16456         profileNetworkPreferenceBuilder.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1);
16457         registerDefaultNetworkCallbacks();
16458         doTestPreferenceForUserNetworkUpDownForGivenPreference(
16459                 profileNetworkPreferenceBuilder.build(), true,
16460                 testHandle, mProfileDefaultNetworkCallback,
16461                 null);
16462     }
16463 
16464     /**
16465      * Make sure per-profile networking preference behaves as expected when the enterprise network
16466      * goes up and down while the preference is active for a given enterprise identifier
16467      */
16468     @Test
16469     public void testPreferenceForUserNetworkUpDownWithDefaultEnterpriseId()
16470             throws Exception {
16471         final UserHandle testHandle = setupEnterpriseNetwork();
16472         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder =
16473                 new ProfileNetworkPreference.Builder();
16474         profileNetworkPreferenceBuilder.setPreference(
16475                 PROFILE_NETWORK_PREFERENCE_ENTERPRISE_NO_FALLBACK);
16476         profileNetworkPreferenceBuilder.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1);
16477         registerDefaultNetworkCallbacks();
16478         doTestPreferenceForUserNetworkUpDownForGivenPreference(
16479                 profileNetworkPreferenceBuilder.build(), true,
16480                 testHandle, mProfileDefaultNetworkCallback,
16481                 null);
16482     }
16483 
16484     /**
16485      * Make sure per-profile networking preference behaves as expected when the enterprise network
16486      * goes up and down while the preference is active for a given enterprise identifier
16487      */
16488     @Test
16489     public void testPreferenceForUserNetworkUpDownWithId2()
16490             throws Exception {
16491         final UserHandle testHandle = setupEnterpriseNetwork();
16492         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder =
16493                 new ProfileNetworkPreference.Builder();
16494         profileNetworkPreferenceBuilder.setPreference(
16495                 PROFILE_NETWORK_PREFERENCE_ENTERPRISE_NO_FALLBACK);
16496         profileNetworkPreferenceBuilder.setPreferenceEnterpriseId(
16497                 NET_ENTERPRISE_ID_2);
16498         registerDefaultNetworkCallbacks();
16499         doTestPreferenceForUserNetworkUpDownForGivenPreference(
16500                 profileNetworkPreferenceBuilder.build(), true,
16501                 testHandle, mProfileDefaultNetworkCallback, null);
16502     }
16503 
16504     /**
16505      * Make sure per-profile networking preference behaves as expected when the enterprise network
16506      * goes up and down while the preference is active for a given enterprise identifier
16507      */
16508     @Test
16509     public void testPreferenceForUserNetworkUpDownWithInvalidId()
16510             throws Exception {
16511         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder =
16512                 new ProfileNetworkPreference.Builder();
16513         profileNetworkPreferenceBuilder.setPreference(
16514                 PROFILE_NETWORK_PREFERENCE_ENTERPRISE_NO_FALLBACK);
16515         profileNetworkPreferenceBuilder.setPreferenceEnterpriseId(0);
16516         registerDefaultNetworkCallbacks();
16517         assertThrows("Should not be able to set invalid enterprise id",
16518                 IllegalStateException.class, () -> profileNetworkPreferenceBuilder.build());
16519     }
16520 
16521     /**
16522      * Make sure per-profile networking preference throws exception when default preference
16523      * is set along with enterprise preference.
16524      */
16525     @Test
16526     public void testPreferenceWithInvalidPreferenceDefaultAndEnterpriseTogether()
16527             throws Exception {
16528         final UserHandle testHandle = setupEnterpriseNetwork();
16529         mServiceContext.setWorkProfile(testHandle, true);
16530 
16531         final int testWorkProfileAppUid1 =
16532                 UserHandle.getUid(testHandle.getIdentifier(), TEST_APP_ID);
16533         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder1 =
16534                 new ProfileNetworkPreference.Builder();
16535         profileNetworkPreferenceBuilder1.setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE);
16536         profileNetworkPreferenceBuilder1.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1);
16537         profileNetworkPreferenceBuilder1.setIncludedUids(new int[]{testWorkProfileAppUid1});
16538 
16539         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder2 =
16540                 new ProfileNetworkPreference.Builder();
16541         profileNetworkPreferenceBuilder2.setPreference(PROFILE_NETWORK_PREFERENCE_DEFAULT);
16542         final TestOnCompleteListener listener = new TestOnCompleteListener();
16543         Assert.assertThrows(IllegalArgumentException.class,
16544                 () -> mCm.setProfileNetworkPreferences(
16545                         testHandle, List.of(profileNetworkPreferenceBuilder1.build(),
16546                                 profileNetworkPreferenceBuilder2.build()),
16547                         r -> r.run(), listener));
16548         Assert.assertThrows(IllegalArgumentException.class,
16549                 () -> mCm.setProfileNetworkPreferences(
16550                         testHandle, List.of(profileNetworkPreferenceBuilder2.build(),
16551                                 profileNetworkPreferenceBuilder1.build()),
16552                         r -> r.run(), listener));
16553     }
16554 
16555     /**
16556      * Make sure per profile network preferences behave as expected when two slices with
16557      * two different apps within same user profile is configured
16558      * Make sure per profile network preferences overrides with latest preference when
16559      * same user preference is set twice
16560      */
16561     @Test
16562     public void testSetPreferenceWithOverridingPreference()
16563             throws Exception {
16564         final InOrder inOrder = inOrder(mMockNetd);
16565         final UserHandle testHandle = setupEnterpriseNetwork();
16566         mServiceContext.setWorkProfile(testHandle, true);
16567         registerDefaultNetworkCallbacks();
16568 
16569         final TestNetworkCallback appCb1 = new TestNetworkCallback();
16570         final TestNetworkCallback appCb2 = new TestNetworkCallback();
16571         final TestNetworkCallback appCb3 = new TestNetworkCallback();
16572 
16573         final int testWorkProfileAppUid1 =
16574                 UserHandle.getUid(testHandle.getIdentifier(), TEST_APP_ID);
16575         final int testWorkProfileAppUid2 =
16576                 UserHandle.getUid(testHandle.getIdentifier(), TEST_APP_ID_2);
16577         final int testWorkProfileAppUid3 =
16578                 UserHandle.getUid(testHandle.getIdentifier(), TEST_APP_ID_3);
16579 
16580         registerDefaultNetworkCallbackAsUid(appCb1, testWorkProfileAppUid1);
16581         registerDefaultNetworkCallbackAsUid(appCb2, testWorkProfileAppUid2);
16582         registerDefaultNetworkCallbackAsUid(appCb3, testWorkProfileAppUid3);
16583 
16584         // Connect both a regular cell agent and an enterprise network first.
16585         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
16586         mCellAgent.connect(true);
16587 
16588         final TestNetworkAgentWrapper workAgent1 = makeEnterpriseNetworkAgent(NET_ENTERPRISE_ID_1);
16589         final TestNetworkAgentWrapper workAgent2 = makeEnterpriseNetworkAgent(NET_ENTERPRISE_ID_2);
16590         workAgent1.connect(true);
16591         workAgent2.connect(true);
16592 
16593         mSystemDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
16594         mDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
16595 
16596         appCb1.expectAvailableThenValidatedCallbacks(mCellAgent);
16597         appCb2.expectAvailableThenValidatedCallbacks(mCellAgent);
16598         appCb3.expectAvailableThenValidatedCallbacks(mCellAgent);
16599 
16600         verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
16601                 mCellAgent.getNetwork().netId, INetd.PERMISSION_NONE));
16602         verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
16603                 workAgent1.getNetwork().netId, INetd.PERMISSION_SYSTEM));
16604         verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
16605                 workAgent2.getNetwork().netId, INetd.PERMISSION_SYSTEM));
16606 
16607         final TestOnCompleteListener listener = new TestOnCompleteListener();
16608 
16609         // Set preferences for testHandle to map testWorkProfileAppUid1 to
16610         // NET_ENTERPRISE_ID_1 and testWorkProfileAppUid2 to NET_ENTERPRISE_ID_2.
16611         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder1 =
16612                 new ProfileNetworkPreference.Builder();
16613         profileNetworkPreferenceBuilder1.setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE);
16614         profileNetworkPreferenceBuilder1.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1);
16615         profileNetworkPreferenceBuilder1.setIncludedUids(new int[]{testWorkProfileAppUid1});
16616 
16617         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder2 =
16618                 new ProfileNetworkPreference.Builder();
16619         profileNetworkPreferenceBuilder2.setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE);
16620         profileNetworkPreferenceBuilder2.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_2);
16621         profileNetworkPreferenceBuilder2.setIncludedUids(new int[]{testWorkProfileAppUid2});
16622 
16623         mCm.setProfileNetworkPreferences(testHandle,
16624                 List.of(profileNetworkPreferenceBuilder1.build(),
16625                         profileNetworkPreferenceBuilder2.build()),
16626                 r -> r.run(), listener);
16627         listener.expectOnComplete();
16628         verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
16629                 workAgent2.getNetwork().netId,
16630                 uidRangeFor(testHandle, profileNetworkPreferenceBuilder2.build()),
16631                 PREFERENCE_ORDER_PROFILE));
16632         verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
16633                 workAgent1.getNetwork().netId,
16634                 uidRangeFor(testHandle, profileNetworkPreferenceBuilder1.build()),
16635                 PREFERENCE_ORDER_PROFILE));
16636 
16637         assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback);
16638         appCb1.expectAvailableCallbacksValidated(workAgent1);
16639         appCb2.expectAvailableCallbacksValidated(workAgent2);
16640 
16641         // Set preferences for testHandle to map testWorkProfileAppUid3 to
16642         // to NET_ENTERPRISE_ID_1.
16643         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder3 =
16644                 new ProfileNetworkPreference.Builder();
16645         profileNetworkPreferenceBuilder3.setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE);
16646         profileNetworkPreferenceBuilder3.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1);
16647         profileNetworkPreferenceBuilder3.setIncludedUids(new int[]{testWorkProfileAppUid3});
16648 
16649         mCm.setProfileNetworkPreferences(testHandle,
16650                 List.of(profileNetworkPreferenceBuilder3.build()),
16651                 r -> r.run(), listener);
16652         listener.expectOnComplete();
16653         verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
16654                 workAgent1.getNetwork().netId,
16655                 uidRangeFor(testHandle, profileNetworkPreferenceBuilder3.build()),
16656                 PREFERENCE_ORDER_PROFILE));
16657         verify(mMockNetd).networkRemoveUidRangesParcel(new NativeUidRangeConfig(
16658                 workAgent2.getNetwork().netId,
16659                 uidRangeFor(testHandle, profileNetworkPreferenceBuilder2.build()),
16660                 PREFERENCE_ORDER_PROFILE));
16661         verify(mMockNetd).networkRemoveUidRangesParcel(new NativeUidRangeConfig(
16662                 workAgent1.getNetwork().netId,
16663                 uidRangeFor(testHandle, profileNetworkPreferenceBuilder1.build()),
16664                 PREFERENCE_ORDER_PROFILE));
16665 
16666         assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback);
16667         appCb3.expectAvailableCallbacksValidated(workAgent1);
16668         appCb2.expectAvailableCallbacksValidated(mCellAgent);
16669         appCb1.expectAvailableCallbacksValidated(mCellAgent);
16670 
16671         // Set the preferences for testHandle to default.
16672         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder =
16673                 new ProfileNetworkPreference.Builder();
16674         profileNetworkPreferenceBuilder.setPreference(PROFILE_NETWORK_PREFERENCE_DEFAULT);
16675 
16676         mCm.setProfileNetworkPreferences(testHandle,
16677                 List.of(profileNetworkPreferenceBuilder.build()),
16678                 r -> r.run(), listener);
16679         listener.expectOnComplete();
16680         verify(mMockNetd).networkRemoveUidRangesParcel(new NativeUidRangeConfig(
16681                 workAgent1.getNetwork().netId,
16682                 uidRangeFor(testHandle, profileNetworkPreferenceBuilder3.build()),
16683                 PREFERENCE_ORDER_PROFILE));
16684 
16685         assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback, appCb1, appCb2);
16686         appCb3.expectAvailableCallbacksValidated(mCellAgent);
16687         workAgent2.disconnect();
16688         mCellAgent.disconnect();
16689 
16690         mCm.unregisterNetworkCallback(appCb1);
16691         mCm.unregisterNetworkCallback(appCb2);
16692         mCm.unregisterNetworkCallback(appCb3);
16693         // Other callbacks will be unregistered by tearDown()
16694     }
16695 
16696     private NetworkCallback requestForEnterpriseId(@NetworkCapabilities.EnterpriseId final int id) {
16697         final NetworkCapabilities nc = new NetworkCapabilities.Builder()
16698                 .addCapability(NET_CAPABILITY_ENTERPRISE).addEnterpriseId(id).build();
16699         final NetworkRequest req = new NetworkRequest.Builder().setCapabilities(nc).build();
16700         final NetworkCallback cb = new TestableNetworkCallback();
16701         mCm.requestNetwork(req, cb);
16702         return cb;
16703     }
16704 
16705     /**
16706      * Make sure per profile network preferences behave as expected when multiple slices with
16707      * multiple different apps within same user profile is configured.
16708      */
16709     @Test
16710     public void testSetPreferenceWithMultiplePreferences()
16711             throws Exception {
16712         final UserHandle testHandle = setupEnterpriseNetwork();
16713         mServiceContext.setWorkProfile(testHandle, true);
16714         registerDefaultNetworkCallbacks();
16715 
16716         final TestNetworkCallback appCb1 = new TestNetworkCallback();
16717         final TestNetworkCallback appCb2 = new TestNetworkCallback();
16718         final TestNetworkCallback appCb3 = new TestNetworkCallback();
16719         final TestNetworkCallback appCb4 = new TestNetworkCallback();
16720         final TestNetworkCallback appCb5 = new TestNetworkCallback();
16721 
16722         final int testWorkProfileAppUid1 =
16723                 UserHandle.getUid(testHandle.getIdentifier(), TEST_APP_ID);
16724         final int testWorkProfileAppUid2 =
16725                 UserHandle.getUid(testHandle.getIdentifier(), TEST_APP_ID_2);
16726         final int testWorkProfileAppUid3 =
16727                 UserHandle.getUid(testHandle.getIdentifier(), TEST_APP_ID_3);
16728         final int testWorkProfileAppUid4 =
16729                 UserHandle.getUid(testHandle.getIdentifier(), TEST_APP_ID_4);
16730         final int testWorkProfileAppUid5 =
16731                 UserHandle.getUid(testHandle.getIdentifier(), TEST_APP_ID_5);
16732 
16733         registerDefaultNetworkCallbackAsUid(appCb1, testWorkProfileAppUid1);
16734         registerDefaultNetworkCallbackAsUid(appCb2, testWorkProfileAppUid2);
16735         registerDefaultNetworkCallbackAsUid(appCb3, testWorkProfileAppUid3);
16736         registerDefaultNetworkCallbackAsUid(appCb4, testWorkProfileAppUid4);
16737         registerDefaultNetworkCallbackAsUid(appCb5, testWorkProfileAppUid5);
16738 
16739         // Connect both a regular cell agent and an enterprise network first.
16740         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
16741         mCellAgent.connect(true);
16742 
16743         final TestNetworkAgentWrapper workAgent1 = makeEnterpriseNetworkAgent(NET_ENTERPRISE_ID_1);
16744         final TestNetworkAgentWrapper workAgent2 = makeEnterpriseNetworkAgent(NET_ENTERPRISE_ID_2);
16745         final TestNetworkAgentWrapper workAgent3 = makeEnterpriseNetworkAgent(NET_ENTERPRISE_ID_3);
16746         final TestNetworkAgentWrapper workAgent4 = makeEnterpriseNetworkAgent(NET_ENTERPRISE_ID_4);
16747         final TestNetworkAgentWrapper workAgent5 = makeEnterpriseNetworkAgent(NET_ENTERPRISE_ID_5);
16748 
16749         final NetworkCallback keepupCb1 = requestForEnterpriseId(NET_ENTERPRISE_ID_1);
16750         final NetworkCallback keepupCb2 = requestForEnterpriseId(NET_ENTERPRISE_ID_2);
16751         final NetworkCallback keepupCb3 = requestForEnterpriseId(NET_ENTERPRISE_ID_3);
16752         final NetworkCallback keepupCb4 = requestForEnterpriseId(NET_ENTERPRISE_ID_4);
16753         final NetworkCallback keepupCb5 = requestForEnterpriseId(NET_ENTERPRISE_ID_5);
16754 
16755         workAgent1.connect(true);
16756         workAgent2.connect(true);
16757         workAgent3.connect(true);
16758         workAgent4.connect(true);
16759         workAgent5.connect(true);
16760 
16761         mSystemDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
16762         mDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
16763         appCb1.expectAvailableThenValidatedCallbacks(mCellAgent);
16764         appCb2.expectAvailableThenValidatedCallbacks(mCellAgent);
16765         appCb3.expectAvailableThenValidatedCallbacks(mCellAgent);
16766         appCb4.expectAvailableThenValidatedCallbacks(mCellAgent);
16767         appCb5.expectAvailableThenValidatedCallbacks(mCellAgent);
16768 
16769         verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
16770                 mCellAgent.getNetwork().netId, INetd.PERMISSION_NONE));
16771         verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
16772                 workAgent1.getNetwork().netId, INetd.PERMISSION_SYSTEM));
16773         verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
16774                 workAgent2.getNetwork().netId, INetd.PERMISSION_SYSTEM));
16775         verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
16776                 workAgent3.getNetwork().netId, INetd.PERMISSION_SYSTEM));
16777         verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
16778                 workAgent4.getNetwork().netId, INetd.PERMISSION_SYSTEM));
16779         verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
16780                 workAgent5.getNetwork().netId, INetd.PERMISSION_SYSTEM));
16781 
16782         final TestOnCompleteListener listener = new TestOnCompleteListener();
16783 
16784         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder1 =
16785                 new ProfileNetworkPreference.Builder();
16786         profileNetworkPreferenceBuilder1.setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE);
16787         profileNetworkPreferenceBuilder1.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1);
16788         profileNetworkPreferenceBuilder1.setIncludedUids(new int[]{testWorkProfileAppUid1});
16789 
16790         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder2 =
16791                 new ProfileNetworkPreference.Builder();
16792         profileNetworkPreferenceBuilder2.setPreference(
16793                 PROFILE_NETWORK_PREFERENCE_ENTERPRISE_NO_FALLBACK);
16794         profileNetworkPreferenceBuilder2.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_2);
16795         profileNetworkPreferenceBuilder2.setIncludedUids(new int[]{testWorkProfileAppUid2});
16796 
16797         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder3 =
16798                 new ProfileNetworkPreference.Builder();
16799         profileNetworkPreferenceBuilder3.setPreference(
16800                 PROFILE_NETWORK_PREFERENCE_ENTERPRISE);
16801         profileNetworkPreferenceBuilder3.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_3);
16802         profileNetworkPreferenceBuilder3.setIncludedUids(new int[]{testWorkProfileAppUid3});
16803 
16804         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder4 =
16805                 new ProfileNetworkPreference.Builder();
16806         profileNetworkPreferenceBuilder4.setPreference(
16807                 PROFILE_NETWORK_PREFERENCE_ENTERPRISE_NO_FALLBACK);
16808         profileNetworkPreferenceBuilder4.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_4);
16809         profileNetworkPreferenceBuilder4.setIncludedUids(new int[]{testWorkProfileAppUid4});
16810 
16811         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder5 =
16812                 new ProfileNetworkPreference.Builder();
16813         profileNetworkPreferenceBuilder5.setPreference(
16814                 PROFILE_NETWORK_PREFERENCE_ENTERPRISE);
16815         profileNetworkPreferenceBuilder5.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_5);
16816         profileNetworkPreferenceBuilder5.setIncludedUids(new int[]{testWorkProfileAppUid5});
16817 
16818         mCm.setProfileNetworkPreferences(testHandle,
16819                 List.of(profileNetworkPreferenceBuilder1.build(),
16820                         profileNetworkPreferenceBuilder2.build(),
16821                         profileNetworkPreferenceBuilder3.build(),
16822                         profileNetworkPreferenceBuilder4.build(),
16823                         profileNetworkPreferenceBuilder5.build()),
16824                 r -> r.run(), listener);
16825 
16826         listener.expectOnComplete();
16827 
16828         verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
16829                 workAgent1.getNetwork().netId,
16830                 uidRangeFor(testHandle, profileNetworkPreferenceBuilder1.build()),
16831                 PREFERENCE_ORDER_PROFILE));
16832         verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
16833                 workAgent2.getNetwork().netId,
16834                 uidRangeFor(testHandle, profileNetworkPreferenceBuilder2.build()),
16835                 PREFERENCE_ORDER_PROFILE));
16836         verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
16837                 workAgent3.getNetwork().netId,
16838                 uidRangeFor(testHandle, profileNetworkPreferenceBuilder3.build()),
16839                 PREFERENCE_ORDER_PROFILE));
16840         verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
16841                 workAgent4.getNetwork().netId,
16842                 uidRangeFor(testHandle, profileNetworkPreferenceBuilder4.build()),
16843                 PREFERENCE_ORDER_PROFILE));
16844         verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
16845                 workAgent5.getNetwork().netId,
16846                 uidRangeFor(testHandle, profileNetworkPreferenceBuilder5.build()),
16847                 PREFERENCE_ORDER_PROFILE));
16848 
16849         assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback);
16850         appCb1.expectAvailableCallbacksValidated(workAgent1);
16851         appCb2.expectAvailableCallbacksValidated(workAgent2);
16852         appCb3.expectAvailableCallbacksValidated(workAgent3);
16853         appCb4.expectAvailableCallbacksValidated(workAgent4);
16854         appCb5.expectAvailableCallbacksValidated(workAgent5);
16855 
16856         workAgent1.disconnect();
16857         workAgent2.disconnect();
16858         workAgent3.disconnect();
16859         workAgent4.disconnect();
16860         workAgent5.disconnect();
16861 
16862         appCb1.expect(LOST, workAgent1);
16863         appCb2.expect(LOST, workAgent2);
16864         appCb3.expect(LOST, workAgent3);
16865         appCb4.expect(LOST, workAgent4);
16866         appCb5.expect(LOST, workAgent5);
16867 
16868         appCb1.expectAvailableCallbacksValidated(mCellAgent);
16869         appCb2.assertNoCallback();
16870         appCb3.expectAvailableCallbacksValidated(mCellAgent);
16871         appCb4.assertNoCallback();
16872         appCb5.expectAvailableCallbacksValidated(mCellAgent);
16873 
16874         verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
16875                 mCellAgent.getNetwork().netId,
16876                 uidRangeFor(testHandle, profileNetworkPreferenceBuilder1.build()),
16877                 PREFERENCE_ORDER_PROFILE));
16878         verify(mMockNetd, never()).networkAddUidRangesParcel(new NativeUidRangeConfig(
16879                 mCellAgent.getNetwork().netId,
16880                 uidRangeFor(testHandle, profileNetworkPreferenceBuilder2.build()),
16881                 PREFERENCE_ORDER_PROFILE));
16882         verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
16883                 mCellAgent.getNetwork().netId,
16884                 uidRangeFor(testHandle, profileNetworkPreferenceBuilder3.build()),
16885                 PREFERENCE_ORDER_PROFILE));
16886         verify(mMockNetd, never()).networkAddUidRangesParcel(new NativeUidRangeConfig(
16887                 mCellAgent.getNetwork().netId,
16888                 uidRangeFor(testHandle, profileNetworkPreferenceBuilder4.build()),
16889                 PREFERENCE_ORDER_PROFILE));
16890         verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
16891                 mCellAgent.getNetwork().netId,
16892                 uidRangeFor(testHandle, profileNetworkPreferenceBuilder5.build()),
16893                 PREFERENCE_ORDER_PROFILE));
16894 
16895         mSystemDefaultNetworkCallback.assertNoCallback();
16896         mDefaultNetworkCallback.assertNoCallback();
16897 
16898         // Set the preferences for testHandle to default.
16899         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder =
16900                 new ProfileNetworkPreference.Builder();
16901         profileNetworkPreferenceBuilder.setPreference(PROFILE_NETWORK_PREFERENCE_DEFAULT);
16902 
16903         mCm.setProfileNetworkPreferences(testHandle,
16904                 List.of(profileNetworkPreferenceBuilder.build()),
16905                 r -> r.run(), listener);
16906         listener.expectOnComplete();
16907         assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback, appCb1, appCb3,
16908                 appCb5);
16909         appCb2.expectAvailableCallbacksValidated(mCellAgent);
16910         appCb4.expectAvailableCallbacksValidated(mCellAgent);
16911         mCellAgent.disconnect();
16912 
16913         mCm.unregisterNetworkCallback(keepupCb1);
16914         mCm.unregisterNetworkCallback(keepupCb2);
16915         mCm.unregisterNetworkCallback(keepupCb3);
16916         mCm.unregisterNetworkCallback(keepupCb4);
16917         mCm.unregisterNetworkCallback(keepupCb5);
16918 
16919         mCm.unregisterNetworkCallback(appCb1);
16920         mCm.unregisterNetworkCallback(appCb2);
16921         mCm.unregisterNetworkCallback(appCb3);
16922         mCm.unregisterNetworkCallback(appCb4);
16923         mCm.unregisterNetworkCallback(appCb5);
16924         // Other callbacks will be unregistered by tearDown()
16925     }
16926 
16927     /**
16928      * Test that, in a given networking context, calling setPreferenceForUser to set per-profile
16929      * defaults on then off works as expected.
16930      */
16931     @Test
16932     public void testSetPreferenceForUserOnOff() throws Exception {
16933         final InOrder inOrder = inOrder(mMockNetd);
16934         final UserHandle testHandle = setupEnterpriseNetwork();
16935 
16936         // Connect both a regular cell agent and an enterprise network first.
16937         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
16938         mCellAgent.connect(true);
16939 
16940         final TestNetworkAgentWrapper workAgent = makeEnterpriseNetworkAgent();
16941         workAgent.connect(true);
16942 
16943         final TestOnCompleteListener listener = new TestOnCompleteListener();
16944         mCm.setProfileNetworkPreference(testHandle, PROFILE_NETWORK_PREFERENCE_ENTERPRISE,
16945                 r -> r.run(), listener);
16946         listener.expectOnComplete();
16947         inOrder.verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
16948                 mCellAgent.getNetwork().netId, INetd.PERMISSION_NONE));
16949         inOrder.verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
16950                 workAgent.getNetwork().netId, uidRangeFor(testHandle), PREFERENCE_ORDER_PROFILE));
16951 
16952         registerDefaultNetworkCallbacks();
16953 
16954         mSystemDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellAgent);
16955         mDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellAgent);
16956         mProfileDefaultNetworkCallback.expectAvailableCallbacksValidated(workAgent);
16957 
16958         mCm.setProfileNetworkPreference(testHandle, PROFILE_NETWORK_PREFERENCE_DEFAULT,
16959                 r -> r.run(), listener);
16960         listener.expectOnComplete();
16961 
16962         mProfileDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellAgent);
16963         assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback);
16964         inOrder.verify(mMockNetd).networkRemoveUidRangesParcel(new NativeUidRangeConfig(
16965                 workAgent.getNetwork().netId, uidRangeFor(testHandle), PREFERENCE_ORDER_PROFILE));
16966 
16967         workAgent.disconnect();
16968         mCellAgent.disconnect();
16969 
16970         // Callbacks will be unregistered by tearDown()
16971     }
16972 
16973     /**
16974      * Test per-profile default networks for two different profiles concurrently.
16975      */
16976     @Test
16977     public void testSetPreferenceForTwoProfiles() throws Exception {
16978         final InOrder inOrder = inOrder(mMockNetd);
16979         final UserHandle testHandle2 = setupEnterpriseNetwork();
16980         final UserHandle testHandle4 = UserHandle.of(TEST_WORK_PROFILE_USER_ID + 2);
16981         mServiceContext.setWorkProfile(testHandle4, true);
16982         registerDefaultNetworkCallbacks();
16983 
16984         final TestNetworkCallback app4Cb = new TestNetworkCallback();
16985         final int testWorkProfileAppUid4 =
16986                 UserHandle.getUid(testHandle4.getIdentifier(), TEST_APP_ID);
16987         registerDefaultNetworkCallbackAsUid(app4Cb, testWorkProfileAppUid4);
16988 
16989         // Connect both a regular cell agent and an enterprise network first.
16990         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
16991         mCellAgent.connect(true);
16992 
16993         final TestNetworkAgentWrapper workAgent = makeEnterpriseNetworkAgent();
16994         workAgent.connect(true);
16995 
16996         mSystemDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
16997         mDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
16998         mProfileDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
16999         app4Cb.expectAvailableThenValidatedCallbacks(mCellAgent);
17000         inOrder.verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
17001                 mCellAgent.getNetwork().netId, INetd.PERMISSION_NONE));
17002         inOrder.verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
17003                 workAgent.getNetwork().netId, INetd.PERMISSION_SYSTEM));
17004 
17005         final TestOnCompleteListener listener = new TestOnCompleteListener();
17006         mCm.setProfileNetworkPreference(testHandle2, PROFILE_NETWORK_PREFERENCE_ENTERPRISE,
17007                 r -> r.run(), listener);
17008         listener.expectOnComplete();
17009         inOrder.verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
17010                 workAgent.getNetwork().netId, uidRangeFor(testHandle2), PREFERENCE_ORDER_PROFILE));
17011 
17012         mProfileDefaultNetworkCallback.expectAvailableCallbacksValidated(workAgent);
17013         assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback,
17014                 app4Cb);
17015 
17016         mCm.setProfileNetworkPreference(testHandle4, PROFILE_NETWORK_PREFERENCE_ENTERPRISE,
17017                 r -> r.run(), listener);
17018         listener.expectOnComplete();
17019         inOrder.verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
17020                 workAgent.getNetwork().netId, uidRangeFor(testHandle4), PREFERENCE_ORDER_PROFILE));
17021 
17022         app4Cb.expectAvailableCallbacksValidated(workAgent);
17023         assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback,
17024                 mProfileDefaultNetworkCallback);
17025 
17026         mCm.setProfileNetworkPreference(testHandle2, PROFILE_NETWORK_PREFERENCE_DEFAULT,
17027                 r -> r.run(), listener);
17028         listener.expectOnComplete();
17029         inOrder.verify(mMockNetd).networkRemoveUidRangesParcel(new NativeUidRangeConfig(
17030                 workAgent.getNetwork().netId, uidRangeFor(testHandle2), PREFERENCE_ORDER_PROFILE));
17031 
17032         mProfileDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellAgent);
17033         assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback,
17034                 app4Cb);
17035 
17036         workAgent.disconnect();
17037         mCellAgent.disconnect();
17038 
17039         mCm.unregisterNetworkCallback(app4Cb);
17040         // Other callbacks will be unregistered by tearDown()
17041     }
17042 
17043     @Test
17044     public void testProfilePreferenceRemovedUponUserRemoved() throws Exception {
17045         final InOrder inOrder = inOrder(mMockNetd);
17046         final UserHandle testHandle = setupEnterpriseNetwork();
17047 
17048         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
17049         mCellAgent.connect(true);
17050 
17051         final TestOnCompleteListener listener = new TestOnCompleteListener();
17052         mCm.setProfileNetworkPreference(testHandle, PROFILE_NETWORK_PREFERENCE_ENTERPRISE,
17053                 r -> r.run(), listener);
17054         listener.expectOnComplete();
17055         inOrder.verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
17056                 mCellAgent.getNetwork().netId, INetd.PERMISSION_NONE));
17057         inOrder.verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
17058                 mCellAgent.getNetwork().netId, uidRangeFor(testHandle),
17059                 PREFERENCE_ORDER_PROFILE));
17060 
17061         final Intent removedIntent = new Intent(ACTION_USER_REMOVED);
17062         removedIntent.putExtra(Intent.EXTRA_USER, testHandle);
17063         processBroadcast(removedIntent);
17064 
17065         inOrder.verify(mMockNetd).networkRemoveUidRangesParcel(new NativeUidRangeConfig(
17066                 mCellAgent.getNetwork().netId, uidRangeFor(testHandle),
17067                 PREFERENCE_ORDER_PROFILE));
17068     }
17069 
17070     @Test
17071     public void testProfileNetworkPreferenceBlocking_addUser() throws Exception {
17072         final InOrder inOrder = inOrder(mMockNetd);
17073         doReturn(asList(PRIMARY_USER_HANDLE)).when(mUserManager).getUserHandles(anyBoolean());
17074 
17075         // Only one network
17076         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
17077         mCellAgent.connect(true);
17078 
17079         // Verify uid ranges 0~99999 are allowed
17080         final ArraySet<UidRange> allowedRanges = new ArraySet<>();
17081         allowedRanges.add(PRIMARY_UIDRANGE);
17082         final NativeUidRangeConfig config1User = new NativeUidRangeConfig(
17083                 mCellAgent.getNetwork().netId,
17084                 toUidRangeStableParcels(allowedRanges),
17085                 0 /* subPriority */);
17086         if (mDeps.isAtLeastU()) {
17087             inOrder.verify(mMockNetd).setNetworkAllowlist(new NativeUidRangeConfig[]{config1User});
17088         } else {
17089             inOrder.verify(mMockNetd, never()).setNetworkAllowlist(any());
17090         }
17091 
17092         doReturn(asList(PRIMARY_USER_HANDLE, SECONDARY_USER_HANDLE))
17093                 .when(mUserManager).getUserHandles(anyBoolean());
17094         final Intent addedIntent = new Intent(ACTION_USER_ADDED);
17095         addedIntent.putExtra(Intent.EXTRA_USER, UserHandle.of(SECONDARY_USER));
17096         processBroadcast(addedIntent);
17097 
17098         // Make sure the allow list has been updated.
17099         allowedRanges.add(UidRange.createForUser(SECONDARY_USER_HANDLE));
17100         final NativeUidRangeConfig config2Users = new NativeUidRangeConfig(
17101                 mCellAgent.getNetwork().netId,
17102                 toUidRangeStableParcels(allowedRanges),
17103                 0 /* subPriority */);
17104         if (mDeps.isAtLeastU()) {
17105             inOrder.verify(mMockNetd).setNetworkAllowlist(new NativeUidRangeConfig[]{config2Users});
17106         } else {
17107             inOrder.verify(mMockNetd, never()).setNetworkAllowlist(any());
17108         }
17109     }
17110 
17111     @Test
17112     public void testProfileNetworkPreferenceBlocking_changePreference() throws Exception {
17113         final InOrder inOrder = inOrder(mMockNetd);
17114         final UserHandle testHandle = setupEnterpriseNetwork();
17115         doReturn(asList(PRIMARY_USER_HANDLE, testHandle))
17116                 .when(mUserManager).getUserHandles(anyBoolean());
17117 
17118         // Start with 1 default network and 1 enterprise network, both networks should
17119         // not be restricted since the blocking preference is not set yet.
17120         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
17121         mCellAgent.connect(true);
17122 
17123         // Verify uid ranges 0~99999, 200000~299999 are all allowed for cellular.
17124         final UidRange profileUidRange =
17125                 UidRange.createForUser(UserHandle.of(TEST_WORK_PROFILE_USER_ID));
17126         ArraySet<UidRange> allowedAllUidRanges = new ArraySet<>();
17127         allowedAllUidRanges.add(PRIMARY_UIDRANGE);
17128         allowedAllUidRanges.add(profileUidRange);
17129         final UidRangeParcel[] allowAllUidRangesParcel = toUidRangeStableParcels(
17130                 allowedAllUidRanges);
17131         final NativeUidRangeConfig cellAllAllowedConfig = new NativeUidRangeConfig(
17132                 mCellAgent.getNetwork().netId,
17133                 allowAllUidRangesParcel,
17134                 0 /* subPriority */);
17135         if (mDeps.isAtLeastU()) {
17136             inOrder.verify(mMockNetd).setNetworkAllowlist(
17137                     new NativeUidRangeConfig[]{cellAllAllowedConfig});
17138         } else {
17139             inOrder.verify(mMockNetd, never()).setNetworkAllowlist(any());
17140         }
17141 
17142         // Verify the same uid ranges are also applied for enterprise network.
17143         final TestNetworkAgentWrapper enterpriseAgent = makeEnterpriseNetworkAgent(
17144                 NET_ENTERPRISE_ID_1);
17145         enterpriseAgent.connect(true);
17146         final NativeUidRangeConfig enterpriseAllAllowedConfig = new NativeUidRangeConfig(
17147                 enterpriseAgent.getNetwork().netId,
17148                 allowAllUidRangesParcel,
17149                 0 /* subPriority */);
17150         // Network agents are stored in an ArraySet which does not guarantee the order and
17151         // making the order of the list undeterministic. Thus, verify this in order insensitive way.
17152         final ArgumentCaptor<NativeUidRangeConfig[]> configsCaptor = ArgumentCaptor.forClass(
17153                 NativeUidRangeConfig[].class);
17154         if (mDeps.isAtLeastU()) {
17155             inOrder.verify(mMockNetd).setNetworkAllowlist(configsCaptor.capture());
17156             assertContainsAll(List.of(configsCaptor.getValue()),
17157                     List.of(cellAllAllowedConfig, enterpriseAllAllowedConfig));
17158         } else {
17159             inOrder.verify(mMockNetd, never()).setNetworkAllowlist(any());
17160         }
17161 
17162         // Setup profile preference which only applies to test app uid on the managed profile.
17163         ProfileNetworkPreference.Builder prefBuilder = new ProfileNetworkPreference.Builder();
17164         prefBuilder.setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE_BLOCKING)
17165                 .setIncludedUids(new int[]{testHandle.getUid(TEST_WORK_PROFILE_APP_UID)})
17166                 .setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1);
17167         final TestOnCompleteListener listener = new TestOnCompleteListener();
17168         mCm.setProfileNetworkPreferences(testHandle,
17169                 List.of(prefBuilder.build()),
17170                 r -> r.run(), listener);
17171         listener.expectOnComplete();
17172 
17173         // Verify Netd is called for the preferences changed.
17174         // Cell: 0~99999, 200000~TEST_APP_UID-1, TEST_APP_UID+1~299999
17175         // Enterprise: 0~99999, 200000~299999
17176         final ArraySet<UidRange> excludeAppRanges = new ArraySet<>();
17177         excludeAppRanges.add(PRIMARY_UIDRANGE);
17178         excludeAppRanges.addAll(UidRangeUtils.removeRangeSetFromUidRange(
17179                 profileUidRange,
17180                 new ArraySet(new UidRange[]{
17181                         (new UidRange(TEST_WORK_PROFILE_APP_UID, TEST_WORK_PROFILE_APP_UID))})
17182         ));
17183         final UidRangeParcel[] excludeAppRangesParcel = toUidRangeStableParcels(excludeAppRanges);
17184         final NativeUidRangeConfig cellExcludeAppConfig = new NativeUidRangeConfig(
17185                 mCellAgent.getNetwork().netId,
17186                 excludeAppRangesParcel,
17187                 0 /* subPriority */);
17188         if (mDeps.isAtLeastU()) {
17189             inOrder.verify(mMockNetd).setNetworkAllowlist(configsCaptor.capture());
17190             assertContainsAll(List.of(configsCaptor.getValue()),
17191                     List.of(cellExcludeAppConfig, enterpriseAllAllowedConfig));
17192         } else {
17193             inOrder.verify(mMockNetd, never()).setNetworkAllowlist(any());
17194         }
17195 
17196         // Verify unset by giving all allowed set for all users when the preference got removed.
17197         mCm.setProfileNetworkPreference(testHandle, PROFILE_NETWORK_PREFERENCE_ENTERPRISE,
17198                 r -> r.run(), listener);
17199         listener.expectOnComplete();
17200         if (mDeps.isAtLeastU()) {
17201             inOrder.verify(mMockNetd).setNetworkAllowlist(configsCaptor.capture());
17202             assertContainsAll(List.of(configsCaptor.getValue()),
17203                     List.of(cellAllAllowedConfig, enterpriseAllAllowedConfig));
17204         } else {
17205             inOrder.verify(mMockNetd, never()).setNetworkAllowlist(any());
17206         }
17207 
17208         // Verify issuing with cellular set only when a network with enterprise capability
17209         // disconnects.
17210         enterpriseAgent.disconnect();
17211         waitForIdle();
17212         if (mDeps.isAtLeastU()) {
17213             inOrder.verify(mMockNetd).setNetworkAllowlist(
17214                     new NativeUidRangeConfig[]{cellAllAllowedConfig});
17215         } else {
17216             inOrder.verify(mMockNetd, never()).setNetworkAllowlist(any());
17217         }
17218     }
17219 
17220     @Test
17221     public void testProfileNetworkPreferenceBlocking_networkChanges() throws Exception {
17222         final InOrder inOrder = inOrder(mMockNetd);
17223         final UserHandle testHandle = setupEnterpriseNetwork();
17224         doReturn(asList(PRIMARY_USER_HANDLE, testHandle))
17225                 .when(mUserManager).getUserHandles(anyBoolean());
17226 
17227         // Setup profile preference which only applies to test app uid on the managed profile.
17228         ProfileNetworkPreference.Builder prefBuilder = new ProfileNetworkPreference.Builder();
17229         prefBuilder.setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE_BLOCKING)
17230                 .setIncludedUids(new int[]{testHandle.getUid(TEST_WORK_PROFILE_APP_UID)})
17231                 .setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1);
17232         final TestOnCompleteListener listener = new TestOnCompleteListener();
17233         mCm.setProfileNetworkPreferences(testHandle,
17234                 List.of(prefBuilder.build()),
17235                 r -> r.run(), listener);
17236         listener.expectOnComplete();
17237         if (mDeps.isAtLeastU()) {
17238             inOrder.verify(mMockNetd).setNetworkAllowlist(new NativeUidRangeConfig[]{});
17239         } else {
17240             inOrder.verify(mMockNetd, never()).setNetworkAllowlist(any());
17241         }
17242 
17243         // Start with 1 default network, which should be restricted since the blocking
17244         // preference is already set.
17245         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
17246         mCellAgent.connect(true);
17247 
17248         // Verify cellular network applies to the allow list.
17249         // Cell: 0~99999, 200000~TEST_APP_UID-1, TEST_APP_UID+1~299999
17250         // Enterprise: 0~99999, 200000~299999
17251         final ArraySet<UidRange> excludeAppRanges = new ArraySet<>();
17252         final UidRange profileUidRange =
17253                 UidRange.createForUser(UserHandle.of(TEST_WORK_PROFILE_USER_ID));
17254         excludeAppRanges.add(PRIMARY_UIDRANGE);
17255         excludeAppRanges.addAll(UidRangeUtils.removeRangeSetFromUidRange(
17256                 profileUidRange,
17257                 new ArraySet(new UidRange[]{
17258                         (new UidRange(TEST_WORK_PROFILE_APP_UID, TEST_WORK_PROFILE_APP_UID))})
17259         ));
17260         final UidRangeParcel[] excludeAppRangesParcel = toUidRangeStableParcels(excludeAppRanges);
17261         final NativeUidRangeConfig cellExcludeAppConfig = new NativeUidRangeConfig(
17262                 mCellAgent.getNetwork().netId,
17263                 excludeAppRangesParcel,
17264                 0 /* subPriority */);
17265         if (mDeps.isAtLeastU()) {
17266             inOrder.verify(mMockNetd).setNetworkAllowlist(
17267                     new NativeUidRangeConfig[]{cellExcludeAppConfig});
17268         } else {
17269             inOrder.verify(mMockNetd, never()).setNetworkAllowlist(any());
17270         }
17271 
17272         // Verify enterprise network is not blocked for test app.
17273         final TestNetworkAgentWrapper enterpriseAgent = makeEnterpriseNetworkAgent(
17274                 NET_ENTERPRISE_ID_1);
17275         enterpriseAgent.connect(true);
17276         ArraySet<UidRange> allowedAllUidRanges = new ArraySet<>();
17277         allowedAllUidRanges.add(PRIMARY_UIDRANGE);
17278         allowedAllUidRanges.add(profileUidRange);
17279         final UidRangeParcel[] allowAllUidRangesParcel = toUidRangeStableParcels(
17280                 allowedAllUidRanges);
17281         final NativeUidRangeConfig enterpriseAllAllowedConfig = new NativeUidRangeConfig(
17282                 enterpriseAgent.getNetwork().netId,
17283                 allowAllUidRangesParcel,
17284                 0 /* subPriority */);
17285         // Network agents are stored in an ArraySet which does not guarantee the order and
17286         // making the order of the list undeterministic. Thus, verify this in order insensitive way.
17287         final ArgumentCaptor<NativeUidRangeConfig[]> configsCaptor = ArgumentCaptor.forClass(
17288                 NativeUidRangeConfig[].class);
17289         if (mDeps.isAtLeastU()) {
17290             inOrder.verify(mMockNetd).setNetworkAllowlist(configsCaptor.capture());
17291             assertContainsAll(List.of(configsCaptor.getValue()),
17292                     List.of(enterpriseAllAllowedConfig, cellExcludeAppConfig));
17293         } else {
17294             inOrder.verify(mMockNetd, never()).setNetworkAllowlist(any());
17295         }
17296 
17297         // Verify issuing with cellular set only when enterprise network disconnects.
17298         enterpriseAgent.disconnect();
17299         waitForIdle();
17300         if (mDeps.isAtLeastU()) {
17301             inOrder.verify(mMockNetd).setNetworkAllowlist(
17302                     new NativeUidRangeConfig[]{cellExcludeAppConfig});
17303         } else {
17304             inOrder.verify(mMockNetd, never()).setNetworkAllowlist(any());
17305         }
17306 
17307         mCellAgent.disconnect();
17308         waitForIdle();
17309         if (mDeps.isAtLeastU()) {
17310             inOrder.verify(mMockNetd).setNetworkAllowlist(new NativeUidRangeConfig[]{});
17311         } else {
17312             inOrder.verify(mMockNetd, never()).setNetworkAllowlist(any());
17313         }
17314     }
17315 
17316     /**
17317      * Make sure wrong preferences for per-profile default networking are rejected.
17318      */
17319     @Test
17320     public void testProfileNetworkPrefWrongPreference() throws Exception {
17321         final UserHandle testHandle = UserHandle.of(TEST_WORK_PROFILE_USER_ID);
17322         mServiceContext.setWorkProfile(testHandle, true);
17323         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder =
17324                 new ProfileNetworkPreference.Builder();
17325         profileNetworkPreferenceBuilder.setPreference(
17326                 PROFILE_NETWORK_PREFERENCE_ENTERPRISE_BLOCKING + 1);
17327         profileNetworkPreferenceBuilder.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1);
17328         assertThrows("Should not be able to set an illegal preference",
17329                 IllegalArgumentException.class,
17330                 () -> mCm.setProfileNetworkPreferences(testHandle,
17331                         List.of(profileNetworkPreferenceBuilder.build()),
17332                         null, null));
17333     }
17334 
17335     /**
17336      * Make sure requests for per-profile default networking for a non-work profile are
17337      * rejected
17338      */
17339     @Test
17340     public void testProfileNetworkPrefWrongProfile() throws Exception {
17341         final UserHandle testHandle = UserHandle.of(TEST_WORK_PROFILE_USER_ID);
17342         mServiceContext.setWorkProfile(testHandle, false);
17343         mServiceContext.setDeviceOwner(testHandle, null);
17344         assertThrows("Should not be able to set a user pref for a non-work profile "
17345                 + "and non device owner",
17346                 IllegalArgumentException.class , () ->
17347                         mCm.setProfileNetworkPreference(testHandle,
17348                                 PROFILE_NETWORK_PREFERENCE_ENTERPRISE, null, null));
17349     }
17350 
17351     /**
17352      * Make sure requests for per-profile default networking for a device owner is
17353      * accepted on T and not accepted on S
17354      */
17355     @Test
17356     public void testProfileNetworkDeviceOwner() throws Exception {
17357         final UserHandle testHandle = UserHandle.of(TEST_WORK_PROFILE_USER_ID);
17358         mServiceContext.setWorkProfile(testHandle, false);
17359         mServiceContext.setDeviceOwner(testHandle, "deviceOwnerPackage");
17360         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder =
17361                 new ProfileNetworkPreference.Builder();
17362         profileNetworkPreferenceBuilder.setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE);
17363         profileNetworkPreferenceBuilder.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1);
17364         final TestOnCompleteListener listener = new TestOnCompleteListener();
17365         if (mDeps.isAtLeastT()) {
17366             mCm.setProfileNetworkPreferences(testHandle,
17367                     List.of(profileNetworkPreferenceBuilder.build()),
17368                     r -> r.run(), listener);
17369         } else {
17370             // S should not allow setting preference on device owner
17371             assertThrows("Should not be able to set a user pref for a non-work profile on S",
17372                     IllegalArgumentException.class , () ->
17373                             mCm.setProfileNetworkPreferences(testHandle,
17374                                     List.of(profileNetworkPreferenceBuilder.build()),
17375                                     r -> r.run(), listener));
17376         }
17377     }
17378 
17379     @Test
17380     public void testSubIdsExist() throws Exception {
17381         final Set<Integer> subIds = Collections.singleton(Process.myUid());
17382         final NetworkCapabilities nc = new NetworkCapabilities();
17383         nc.setSubscriptionIds(subIds);
17384 
17385         final NetworkCapabilities result =
17386                 mService.networkCapabilitiesRestrictedForCallerPermissions(
17387                         nc, Process.myPid(), Process.myUid());
17388         assertEquals(subIds, result.getSubscriptionIds());
17389     }
17390 
17391     private NetworkRequest getRequestWithSubIds() {
17392         return new NetworkRequest.Builder()
17393                 .setSubscriptionIds(Collections.singleton(Process.myUid()))
17394                 .build();
17395     }
17396 
17397     private NetworkRequest getRestrictedRequestForWifiWithSubIds() {
17398         return new NetworkRequest.Builder()
17399             .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
17400             .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
17401             .setSubscriptionIds(Collections.singleton(TEST_SUBSCRIPTION_ID))
17402             .build();
17403     }
17404 
17405     @Test
17406     public void testNetworkRequestWithSubIds() throws Exception {
17407         final PendingIntent pendingIntent = PendingIntent.getBroadcast(
17408                 mContext, 0 /* requestCode */, new Intent("a"), FLAG_IMMUTABLE);
17409         final NetworkCallback networkCallback1 = new NetworkCallback();
17410         final NetworkCallback networkCallback2 = new NetworkCallback();
17411 
17412         mCm.requestNetwork(getRequestWithSubIds(), networkCallback1);
17413         mCm.requestNetwork(getRequestWithSubIds(), pendingIntent);
17414         mCm.registerNetworkCallback(getRequestWithSubIds(), networkCallback2);
17415 
17416         mCm.unregisterNetworkCallback(networkCallback1);
17417         mCm.releaseNetworkRequest(pendingIntent);
17418         mCm.unregisterNetworkCallback(networkCallback2);
17419     }
17420 
17421     @Test
17422     @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
17423     public void testCarrierConfigAppSendNetworkRequestForRestrictedWifi() throws Exception {
17424         mServiceContext.setPermission(CONNECTIVITY_USE_RESTRICTED_NETWORKS, PERMISSION_DENIED);
17425         doReturn(true).when(mCarrierPrivilegeAuthenticator)
17426                 .isCarrierServiceUidForNetworkCapabilities(anyInt(), any());
17427         final PendingIntent pendingIntent = PendingIntent.getBroadcast(
17428                 mContext, 0 /* requestCode */, new Intent("a"), FLAG_IMMUTABLE);
17429         final NetworkCallback networkCallback1 = new NetworkCallback();
17430         final NetworkCallback networkCallback2 = new NetworkCallback();
17431 
17432         mCm.requestNetwork(
17433                 getRestrictedRequestForWifiWithSubIds(), networkCallback1);
17434         mCm.requestNetwork(
17435                 getRestrictedRequestForWifiWithSubIds(), pendingIntent);
17436         mCm.registerNetworkCallback(
17437                 getRestrictedRequestForWifiWithSubIds(), networkCallback2);
17438 
17439         mCm.unregisterNetworkCallback(networkCallback1);
17440         mCm.releaseNetworkRequest(pendingIntent);
17441         mCm.unregisterNetworkCallback(networkCallback2);
17442     }
17443 
17444     private void doTestNetworkRequestWithCarrierPrivilegesLost(
17445             boolean shouldGrantRestrictedNetworkPermission,
17446             int lostPrivilegeUid,
17447             int lostPrivilegeSubId,
17448             boolean expectUnavailable,
17449             boolean expectCapChanged) throws Exception {
17450         if (shouldGrantRestrictedNetworkPermission) {
17451             mServiceContext.setPermission(CONNECTIVITY_USE_RESTRICTED_NETWORKS, PERMISSION_GRANTED);
17452         } else {
17453             mServiceContext.setPermission(CONNECTIVITY_USE_RESTRICTED_NETWORKS, PERMISSION_DENIED);
17454         }
17455 
17456         NetworkCapabilities filter =
17457                 getRestrictedRequestForWifiWithSubIds().networkCapabilities;
17458         final HandlerThread handlerThread = new HandlerThread("testRestrictedFactoryRequests");
17459         handlerThread.start();
17460 
17461         final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
17462                 mServiceContext, "testFactory", filter, mCsHandlerThread);
17463         testFactory.register();
17464         testFactory.assertRequestCountEquals(0);
17465 
17466         doReturn(true).when(mCarrierPrivilegeAuthenticator)
17467                 .isCarrierServiceUidForNetworkCapabilities(eq(Process.myUid()), any());
17468         final TestNetworkCallback networkCallback = new TestNetworkCallback();
17469         final NetworkRequest networkrequest =
17470                 getRestrictedRequestForWifiWithSubIds();
17471         mCm.requestNetwork(networkrequest, networkCallback);
17472         testFactory.expectRequestAdd();
17473         testFactory.assertRequestCountEquals(1);
17474 
17475         NetworkCapabilities nc = new NetworkCapabilities.Builder(filter)
17476                 .setAllowedUids(Set.of(Process.myUid()))
17477                 .build();
17478         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, new LinkProperties(), nc);
17479         mWiFiAgent.connect(false);
17480         networkCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
17481         final NetworkAgentInfo nai = mService.getNetworkAgentInfoForNetwork(
17482                 mWiFiAgent.getNetwork());
17483 
17484         doReturn(false).when(mCarrierPrivilegeAuthenticator)
17485                 .isCarrierServiceUidForNetworkCapabilities(eq(Process.myUid()), any());
17486         doReturn(TEST_SUBSCRIPTION_ID).when(mCarrierPrivilegeAuthenticator)
17487                 .getSubIdFromNetworkCapabilities(any());
17488 
17489         visibleOnHandlerThread(mCsHandlerThread.getThreadHandler(), () -> {
17490             mDeps.mCarrierPrivilegesLostListener.accept(lostPrivilegeUid, lostPrivilegeSubId);
17491         });
17492         waitForIdle();
17493 
17494         if (expectCapChanged) {
17495             networkCallback.expect(NETWORK_CAPS_UPDATED);
17496         }
17497         if (expectUnavailable) {
17498             networkCallback.expect(UNAVAILABLE);
17499         }
17500         if (!expectCapChanged && !expectUnavailable) {
17501             networkCallback.assertNoCallback();
17502         }
17503 
17504         mWiFiAgent.disconnect();
17505 
17506         if (expectUnavailable) {
17507             testFactory.expectRequestRemove();
17508             testFactory.assertRequestCountEquals(0);
17509         } else {
17510             testFactory.expectRequestAdd();
17511             testFactory.assertRequestCountEquals(1);
17512         }
17513 
17514         handlerThread.quitSafely();
17515         handlerThread.join();
17516     }
17517 
17518     @Test
17519     @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
17520     public void testRestrictedRequestRemovedDueToCarrierPrivilegesLost() throws Exception {
17521         doTestNetworkRequestWithCarrierPrivilegesLost(
17522                 false /* shouldGrantRestrictedNetworkPermission */,
17523                 Process.myUid(),
17524                 TEST_SUBSCRIPTION_ID,
17525                 true /* expectUnavailable */,
17526                 true /* expectCapChanged */);
17527     }
17528 
17529     @Test
17530     @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
17531     public void testRequestNotRemoved_MismatchSubId() throws Exception {
17532         doTestNetworkRequestWithCarrierPrivilegesLost(
17533                 false /* shouldGrantRestrictedNetworkPermission */,
17534                 Process.myUid(),
17535                 TEST_SUBSCRIPTION_ID + 1,
17536                 false /* expectUnavailable */,
17537                 false /* expectCapChanged */);
17538     }
17539     @Test
17540     @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
17541     public void testRequestNotRemoved_MismatchUid() throws Exception {
17542         doTestNetworkRequestWithCarrierPrivilegesLost(
17543                 false /* shouldGrantRestrictedNetworkPermission */,
17544                 Process.myUid() + 1,
17545                 TEST_SUBSCRIPTION_ID,
17546                 false /* expectUnavailable */,
17547                 false /* expectCapChanged */);
17548     }
17549 
17550     @Test
17551     @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
17552     public void testRequestNotRemoved_HasRestrictedNetworkPermission() throws Exception {
17553         doTestNetworkRequestWithCarrierPrivilegesLost(
17554                 true /* shouldGrantRestrictedNetworkPermission */,
17555                 Process.myUid(),
17556                 TEST_SUBSCRIPTION_ID,
17557                 false /* expectUnavailable */,
17558                 true /* expectCapChanged */);
17559     }
17560 
17561     @Test
17562     public void testAllowedUidsExistWithoutNetworkFactoryPermission() throws Exception {
17563         // Make sure NETWORK_FACTORY permission is not granted.
17564         mServiceContext.setPermission(NETWORK_FACTORY, PERMISSION_DENIED);
17565         mServiceContext.setPermission(MANAGE_TEST_NETWORKS, PERMISSION_GRANTED);
17566         final TestNetworkCallback cb = new TestNetworkCallback();
17567         mCm.requestNetwork(new NetworkRequest.Builder()
17568                         .clearCapabilities()
17569                         .addTransportType(TRANSPORT_TEST)
17570                         .addTransportType(TRANSPORT_CELLULAR)
17571                         .build(),
17572                 cb);
17573 
17574         final ArraySet<Integer> uids = new ArraySet<>();
17575         uids.add(200);
17576         final NetworkCapabilities nc = new NetworkCapabilities.Builder()
17577                 .addTransportType(TRANSPORT_TEST)
17578                 .removeCapability(NET_CAPABILITY_NOT_RESTRICTED)
17579                 .setAllowedUids(uids)
17580                 .setOwnerUid(Process.myUid())
17581                 .setAdministratorUids(new int[] {Process.myUid()})
17582                 .build();
17583         final TestNetworkAgentWrapper agent = new TestNetworkAgentWrapper(TRANSPORT_TEST,
17584                 new LinkProperties(), nc);
17585         agent.connect(true);
17586         cb.expectAvailableThenValidatedCallbacks(agent);
17587 
17588         uids.add(300);
17589         uids.add(400);
17590         nc.setAllowedUids(uids);
17591         agent.setNetworkCapabilities(nc, true /* sendToConnectivityService */);
17592         if (mDeps.isAtLeastT()) {
17593             // AllowedUids is not cleared even without the NETWORK_FACTORY permission
17594             // because the caller is the owner of the network.
17595             cb.expectCaps(agent, c -> c.getAllowedUids().equals(uids));
17596         } else {
17597             cb.assertNoCallback();
17598         }
17599     }
17600 
17601     @Test
17602     public void testAllowedUids() throws Exception {
17603         final int preferenceOrder =
17604                 ConnectivityService.PREFERENCE_ORDER_IRRELEVANT_BECAUSE_NOT_DEFAULT;
17605         mServiceContext.setPermission(NETWORK_FACTORY, PERMISSION_GRANTED);
17606         mServiceContext.setPermission(MANAGE_TEST_NETWORKS, PERMISSION_GRANTED);
17607         final TestNetworkCallback cb = new TestNetworkCallback();
17608         mCm.requestNetwork(new NetworkRequest.Builder()
17609                         .clearCapabilities()
17610                         .addTransportType(TRANSPORT_TEST)
17611                         .addTransportType(TRANSPORT_CELLULAR)
17612                         .build(),
17613                 cb);
17614 
17615         final ArraySet<Integer> uids = new ArraySet<>();
17616         uids.add(200);
17617         final NetworkCapabilities nc = new NetworkCapabilities.Builder()
17618                 .addTransportType(TRANSPORT_TEST)
17619                 .removeCapability(NET_CAPABILITY_NOT_RESTRICTED)
17620                 .setAllowedUids(uids)
17621                 .build();
17622         final TestNetworkAgentWrapper agent = new TestNetworkAgentWrapper(TRANSPORT_TEST,
17623                 new LinkProperties(), nc);
17624         agent.connect(true);
17625         cb.expectAvailableThenValidatedCallbacks(agent);
17626 
17627         final InOrder inOrder = inOrder(mMockNetd);
17628         final NativeUidRangeConfig uids200Parcel = new NativeUidRangeConfig(
17629                 agent.getNetwork().getNetId(),
17630                 intToUidRangeStableParcels(uids),
17631                 preferenceOrder);
17632         if (mDeps.isAtLeastT()) {
17633             inOrder.verify(mMockNetd, times(1)).networkAddUidRangesParcel(uids200Parcel);
17634         }
17635 
17636         uids.add(300);
17637         uids.add(400);
17638         nc.setAllowedUids(uids);
17639         agent.setNetworkCapabilities(nc, true /* sendToConnectivityService */);
17640         if (mDeps.isAtLeastT()) {
17641             cb.expectCaps(agent, c -> c.getAllowedUids().equals(uids));
17642         } else {
17643             cb.assertNoCallback();
17644         }
17645 
17646         uids.remove(200);
17647         final NativeUidRangeConfig uids300400Parcel = new NativeUidRangeConfig(
17648                 agent.getNetwork().getNetId(),
17649                 intToUidRangeStableParcels(uids),
17650                 preferenceOrder);
17651         if (mDeps.isAtLeastT()) {
17652             inOrder.verify(mMockNetd, times(1)).networkAddUidRangesParcel(uids300400Parcel);
17653         }
17654 
17655         nc.setAllowedUids(uids);
17656         agent.setNetworkCapabilities(nc, true /* sendToConnectivityService */);
17657         if (mDeps.isAtLeastT()) {
17658             cb.expectCaps(agent, c -> c.getAllowedUids().equals(uids));
17659             inOrder.verify(mMockNetd, times(1)).networkRemoveUidRangesParcel(uids200Parcel);
17660         } else {
17661             cb.assertNoCallback();
17662         }
17663 
17664         uids.clear();
17665         uids.add(600);
17666         nc.setAllowedUids(uids);
17667         agent.setNetworkCapabilities(nc, true /* sendToConnectivityService */);
17668         if (mDeps.isAtLeastT()) {
17669             cb.expectCaps(agent, c -> c.getAllowedUids().equals(uids));
17670         } else {
17671             cb.assertNoCallback();
17672         }
17673         final NativeUidRangeConfig uids600Parcel = new NativeUidRangeConfig(
17674                 agent.getNetwork().getNetId(),
17675                 intToUidRangeStableParcels(uids),
17676                 preferenceOrder);
17677         if (mDeps.isAtLeastT()) {
17678             inOrder.verify(mMockNetd, times(1)).networkAddUidRangesParcel(uids600Parcel);
17679             inOrder.verify(mMockNetd, times(1)).networkRemoveUidRangesParcel(uids300400Parcel);
17680         }
17681 
17682         uids.clear();
17683         nc.setAllowedUids(uids);
17684         agent.setNetworkCapabilities(nc, true /* sendToConnectivityService */);
17685         if (mDeps.isAtLeastT()) {
17686             cb.expectCaps(agent, c -> c.getAllowedUids().isEmpty());
17687             inOrder.verify(mMockNetd, times(1)).networkRemoveUidRangesParcel(uids600Parcel);
17688         } else {
17689             cb.assertNoCallback();
17690             verify(mMockNetd, never()).networkAddUidRangesParcel(any());
17691             verify(mMockNetd, never()).networkRemoveUidRangesParcel(any());
17692         }
17693 
17694     }
17695 
17696     @Test
17697     public void testAutomotiveEthernetAllowedUids() throws Exception {
17698         mServiceContext.setPermission(NETWORK_FACTORY, PERMISSION_GRANTED);
17699         mServiceContext.setPermission(MANAGE_TEST_NETWORKS, PERMISSION_GRANTED);
17700 
17701         // Has automotive feature.
17702         validateAutomotiveEthernetAllowedUids(true);
17703 
17704         // No automotive feature.
17705         validateAutomotiveEthernetAllowedUids(false);
17706     }
17707 
17708     private void validateAutomotiveEthernetAllowedUids(final boolean hasAutomotiveFeature)
17709             throws Exception {
17710         mockHasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, hasAutomotiveFeature);
17711 
17712         // Simulate a restricted ethernet network.
17713         final NetworkCapabilities.Builder ncb = new NetworkCapabilities.Builder()
17714                 .addTransportType(TRANSPORT_ETHERNET)
17715                 .addCapability(NET_CAPABILITY_INTERNET)
17716                 .addCapability(NET_CAPABILITY_NOT_SUSPENDED)
17717                 .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
17718                 .removeCapability(NET_CAPABILITY_NOT_RESTRICTED);
17719 
17720         mEthernetAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET,
17721                 new LinkProperties(), ncb.build());
17722 
17723         final ArraySet<Integer> serviceUidSet = new ArraySet<>();
17724         serviceUidSet.add(TEST_PACKAGE_UID);
17725 
17726         final TestNetworkCallback cb = new TestNetworkCallback();
17727 
17728         mCm.requestNetwork(new NetworkRequest.Builder()
17729                 .addTransportType(TRANSPORT_ETHERNET)
17730                 .removeCapability(NET_CAPABILITY_NOT_RESTRICTED)
17731                 .build(), cb);
17732         mEthernetAgent.connect(true);
17733         cb.expectAvailableThenValidatedCallbacks(mEthernetAgent);
17734 
17735         // Cell gets to set the service UID as access UID
17736         ncb.setAllowedUids(serviceUidSet);
17737         mEthernetAgent.setNetworkCapabilities(ncb.build(), true /* sendToCS */);
17738         if (mDeps.isAtLeastT() && hasAutomotiveFeature) {
17739             cb.expectCaps(mEthernetAgent, c -> c.getAllowedUids().equals(serviceUidSet));
17740         } else {
17741             // S and no automotive feature must ignore access UIDs.
17742             cb.assertNoCallback(TEST_CALLBACK_TIMEOUT_MS);
17743         }
17744 
17745         mEthernetAgent.disconnect();
17746         cb.expect(LOST, mEthernetAgent);
17747         mCm.unregisterNetworkCallback(cb);
17748     }
17749 
17750     @Test
17751     public void testCbsAllowedUids() throws Exception {
17752         mServiceContext.setPermission(NETWORK_FACTORY, PERMISSION_GRANTED);
17753         mServiceContext.setPermission(MANAGE_TEST_NETWORKS, PERMISSION_GRANTED);
17754 
17755         // In this test TEST_PACKAGE_UID will be the UID of the carrier service UID.
17756         doReturn(true).when(mCarrierPrivilegeAuthenticator)
17757                 .isCarrierServiceUidForNetworkCapabilities(eq(TEST_PACKAGE_UID), any());
17758 
17759         // Simulate a restricted telephony network. The telephony factory is entitled to set
17760         // the access UID to the service package on any of its restricted networks.
17761         final NetworkCapabilities.Builder ncb = new NetworkCapabilities.Builder()
17762                 .addTransportType(TRANSPORT_CELLULAR)
17763                 .addCapability(NET_CAPABILITY_INTERNET)
17764                 .addCapability(NET_CAPABILITY_NOT_SUSPENDED)
17765                 .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
17766                 .removeCapability(NET_CAPABILITY_NOT_RESTRICTED)
17767                 .setNetworkSpecifier(new TelephonyNetworkSpecifier(1 /* subid */));
17768 
17769         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR,
17770                 new LinkProperties(), ncb.build());
17771 
17772         final ArraySet<Integer> serviceUidSet = new ArraySet<>();
17773         serviceUidSet.add(TEST_PACKAGE_UID);
17774         final ArraySet<Integer> nonServiceUidSet = new ArraySet<>();
17775         nonServiceUidSet.add(TEST_PACKAGE_UID2);
17776         final ArraySet<Integer> serviceUidSetPlus = new ArraySet<>();
17777         serviceUidSetPlus.add(TEST_PACKAGE_UID);
17778         serviceUidSetPlus.add(TEST_PACKAGE_UID2);
17779 
17780         final TestNetworkCallback cb = new TestNetworkCallback();
17781 
17782         // Cell gets to set the service UID as access UID
17783         mCm.requestNetwork(new NetworkRequest.Builder()
17784                 .addTransportType(TRANSPORT_CELLULAR)
17785                 .removeCapability(NET_CAPABILITY_NOT_RESTRICTED)
17786                 .build(), cb);
17787         mCellAgent.connect(true);
17788         cb.expectAvailableThenValidatedCallbacks(mCellAgent);
17789         ncb.setAllowedUids(serviceUidSet);
17790         mCellAgent.setNetworkCapabilities(ncb.build(), true /* sendToCS */);
17791         if (mDeps.isAtLeastT()) {
17792             cb.expectCaps(mCellAgent, c -> c.getAllowedUids().equals(serviceUidSet));
17793         } else {
17794             // S must ignore access UIDs.
17795             cb.assertNoCallback(TEST_CALLBACK_TIMEOUT_MS);
17796         }
17797 
17798         // ...but not to some other UID. Rejection sets UIDs to the empty set
17799         ncb.setAllowedUids(nonServiceUidSet);
17800         mCellAgent.setNetworkCapabilities(ncb.build(), true /* sendToCS */);
17801         if (mDeps.isAtLeastT()) {
17802             cb.expectCaps(mCellAgent, c -> c.getAllowedUids().isEmpty());
17803         } else {
17804             // S must ignore access UIDs.
17805             cb.assertNoCallback(TEST_CALLBACK_TIMEOUT_MS);
17806         }
17807 
17808         // ...and also not to multiple UIDs even including the service UID
17809         ncb.setAllowedUids(serviceUidSetPlus);
17810         mCellAgent.setNetworkCapabilities(ncb.build(), true /* sendToCS */);
17811         cb.assertNoCallback(TEST_CALLBACK_TIMEOUT_MS);
17812 
17813         mCellAgent.disconnect();
17814         cb.expect(LOST, mCellAgent);
17815         mCm.unregisterNetworkCallback(cb);
17816 
17817         // Must be unset before touching the transports, because remove and add transport types
17818         // check the specifier on the builder immediately, contradicting normal builder semantics
17819         // TODO : fix the builder
17820         ncb.setNetworkSpecifier(null);
17821         ncb.removeTransportType(TRANSPORT_CELLULAR);
17822         ncb.addTransportType(TRANSPORT_BLUETOOTH);
17823         // Wifi does not get to set access UID, even to the correct UID
17824         mCm.requestNetwork(new NetworkRequest.Builder()
17825                 .addTransportType(TRANSPORT_BLUETOOTH)
17826                 .removeCapability(NET_CAPABILITY_NOT_RESTRICTED)
17827                 .build(), cb);
17828         final TestNetworkAgentWrapper bluetoothAgent = new TestNetworkAgentWrapper(
17829                 TRANSPORT_BLUETOOTH, new LinkProperties(), ncb.build());
17830         bluetoothAgent.connect(true);
17831         cb.expectAvailableThenValidatedCallbacks(bluetoothAgent);
17832         ncb.setAllowedUids(serviceUidSet);
17833         bluetoothAgent.setNetworkCapabilities(ncb.build(), true /* sendToCS */);
17834         cb.assertNoCallback(TEST_CALLBACK_TIMEOUT_MS);
17835         mCm.unregisterNetworkCallback(cb);
17836     }
17837 
17838     @Test
17839     public void testSanitizedCapabilitiesFromAgentDoesNotMutateArgument()
17840             throws Exception {
17841         // This NetworkCapabilities builds an usual object to maximize the chance that this requires
17842         // sanitization, so we have a high chance to detect any changes to the original.
17843         final NetworkCapabilities unsanitized = new NetworkCapabilities.Builder()
17844                 .withoutDefaultCapabilities()
17845                 .addTransportType(TRANSPORT_WIFI)
17846                 .addCapability(NET_CAPABILITY_INTERNET)
17847                 .setOwnerUid(12345)
17848                 .setAdministratorUids(new int[] {12345, 23456, 34567})
17849                 .setLinkUpstreamBandwidthKbps(20)
17850                 .setLinkDownstreamBandwidthKbps(10)
17851                 .setNetworkSpecifier(new EthernetNetworkSpecifier("foobar"))
17852                 .setTransportInfo(new WifiInfo.Builder().setBssid("AA:AA:AA:AA:AA:AA").build())
17853                 .setSignalStrength(-75)
17854                 .setSsid("SSID1")
17855                 .setRequestorUid(98765)
17856                 .setRequestorPackageName("TestPackage")
17857                 .setSubscriptionIds(Collections.singleton(Process.myUid()))
17858                 .setUids(UidRange.toIntRanges(uidRangesForUids(
17859                         UserHandle.getUid(PRIMARY_USER, 10100),
17860                         UserHandle.getUid(SECONDARY_USER, 10101),
17861                         UserHandle.getUid(TERTIARY_USER, 10043))))
17862                 .setAllowedUids(Set.of(45678, 56789, 65432))
17863                 .setUnderlyingNetworks(List.of(new Network(99999)))
17864                 .build();
17865         final NetworkCapabilities copyOfUnsanitized = new NetworkCapabilities(unsanitized);
17866         final NetworkInfo info = new NetworkInfo(TYPE_MOBILE, TelephonyManager.NETWORK_TYPE_LTE,
17867                 ConnectivityManager.getNetworkTypeName(TYPE_MOBILE),
17868                 TelephonyManager.getNetworkTypeName(TelephonyManager.NETWORK_TYPE_LTE));
17869         final NetworkAgentInfo agent = fakeNai(unsanitized, info);
17870         agent.setDeclaredCapabilities(unsanitized);
17871         final NetworkCapabilities sanitized = agent.getDeclaredCapabilitiesSanitized(
17872                 null /* carrierPrivilegeAuthenticator */);
17873         assertEquals(copyOfUnsanitized, unsanitized);
17874         assertNotEquals(sanitized, unsanitized);
17875     }
17876 
17877     /**
17878      * Validate request counts are counted accurately on setProfileNetworkPreference on set/replace.
17879      */
17880     @Test
17881     public void testProfileNetworkPrefCountsRequestsCorrectlyOnSet() throws Exception {
17882         final UserHandle testHandle = setupEnterpriseNetwork();
17883         final TestOnCompleteListener listener = new TestOnCompleteListener();
17884         // Leave one request available so the profile preference can be set.
17885         withRequestCountersAcquired(1 /* countToLeaveAvailable */, () -> {
17886             withPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
17887                     Process.myPid(), Process.myUid(), () -> {
17888                         // Set initially to test the limit prior to having existing requests.
17889                         mCm.setProfileNetworkPreference(testHandle,
17890                                 PROFILE_NETWORK_PREFERENCE_ENTERPRISE,
17891                                 Runnable::run, listener);
17892                     });
17893             listener.expectOnComplete();
17894 
17895             // Simulate filing requests as some app on the work profile
17896             final int otherAppUid = UserHandle.getUid(TEST_WORK_PROFILE_USER_ID,
17897                     UserHandle.getAppId(Process.myUid() + 1));
17898             final int remainingCount = ConnectivityService.MAX_NETWORK_REQUESTS_PER_UID
17899                     - mService.mNetworkRequestCounter.get(otherAppUid)
17900                     - 1;
17901             final NetworkCallback[] callbacks = new NetworkCallback[remainingCount];
17902             doAsUid(otherAppUid, () -> {
17903                 for (int i = 0; i < remainingCount; ++i) {
17904                     callbacks[i] = new TestNetworkCallback();
17905                     mCm.registerDefaultNetworkCallback(callbacks[i]);
17906                 }
17907             });
17908 
17909             withPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
17910                     Process.myPid(), Process.myUid(), () -> {
17911                         // re-set so as to test the limit as part of replacing existing requests.
17912                         mCm.setProfileNetworkPreference(testHandle,
17913                                 PROFILE_NETWORK_PREFERENCE_ENTERPRISE, Runnable::run, listener);
17914                     });
17915             listener.expectOnComplete();
17916 
17917             doAsUid(otherAppUid, () -> {
17918                 for (final NetworkCallback callback : callbacks) {
17919                     mCm.unregisterNetworkCallback(callback);
17920                 }
17921             });
17922         });
17923     }
17924 
17925     /**
17926      * Validate request counts are counted accurately on setOemNetworkPreference on set/replace.
17927      */
17928     @Test
17929     public void testSetOemNetworkPreferenceCountsRequestsCorrectlyOnSet() throws Exception {
17930         mockHasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, true);
17931         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
17932                 OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY;
17933         // Leave one request available so the OEM preference can be set.
17934         withRequestCountersAcquired(1 /* countToLeaveAvailable */, () ->
17935                 withPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, () -> {
17936                     // Set initially to test the limit prior to having existing requests.
17937                     final TestOemListenerCallback listener = new TestOemListenerCallback();
17938                     mService.setOemNetworkPreference(
17939                             createDefaultOemNetworkPreferences(networkPref), listener);
17940                     listener.expectOnComplete();
17941 
17942                     // re-set so as to test the limit as part of replacing existing requests.
17943                     mService.setOemNetworkPreference(
17944                             createDefaultOemNetworkPreferences(networkPref), listener);
17945                     listener.expectOnComplete();
17946                 }));
17947     }
17948 
17949     private void withRequestCountersAcquired(final int countToLeaveAvailable,
17950             @NonNull final ThrowingRunnable r) throws Exception {
17951         final ArraySet<TestNetworkCallback> callbacks = new ArraySet<>();
17952         try {
17953             final int requestCount = mService.mSystemNetworkRequestCounter.get(Process.myUid());
17954             // The limit is hit when total requests = limit - 1, and exceeded with a crash when
17955             // total requests >= limit.
17956             final int countToFile =
17957                     MAX_NETWORK_REQUESTS_PER_SYSTEM_UID - requestCount - countToLeaveAvailable;
17958             // Need permission so registerDefaultNetworkCallback uses mSystemNetworkRequestCounter
17959             withPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, () -> {
17960                 for (int i = 1; i < countToFile; i++) {
17961                     final TestNetworkCallback cb = new TestNetworkCallback();
17962                     mCm.registerDefaultNetworkCallback(cb);
17963                     callbacks.add(cb);
17964                 }
17965                 assertEquals(MAX_NETWORK_REQUESTS_PER_SYSTEM_UID - 1 - countToLeaveAvailable,
17966                         mService.mSystemNetworkRequestCounter.get(Process.myUid()));
17967             });
17968             // Code to run to check if it triggers a max request count limit error.
17969             r.run();
17970         } finally {
17971             for (final TestNetworkCallback cb : callbacks) {
17972                 mCm.unregisterNetworkCallback(cb);
17973             }
17974         }
17975     }
17976 
17977     private void assertCreateNrisFromMobileDataPreferredUids(Set<Integer> uids) {
17978         final Set<NetworkRequestInfo> nris =
17979                 mService.createNrisFromMobileDataPreferredUids(uids);
17980         final NetworkRequestInfo nri = nris.iterator().next();
17981         // Verify that one NRI is created with multilayer requests. Because one NRI can contain
17982         // multiple uid ranges, so it only need create one NRI here.
17983         assertEquals(1, nris.size());
17984         assertTrue(nri.isMultilayerRequest());
17985         assertEquals(nri.getUids(), uidRangesForUids(uids));
17986         assertEquals(PREFERENCE_ORDER_MOBILE_DATA_PREFERERRED, nri.mPreferenceOrder);
17987     }
17988 
17989     /**
17990      * Test createNrisFromMobileDataPreferredUids returns correct NetworkRequestInfo.
17991      */
17992     @Test
17993     public void testCreateNrisFromMobileDataPreferredUids() {
17994         // Verify that empty uid set should not create any NRI for it.
17995         final Set<NetworkRequestInfo> nrisNoUid =
17996                 mService.createNrisFromMobileDataPreferredUids(new ArraySet<>());
17997         assertEquals(0, nrisNoUid.size());
17998 
17999         final int uid1 = PRIMARY_USER_HANDLE.getUid(TEST_PACKAGE_UID);
18000         final int uid2 = PRIMARY_USER_HANDLE.getUid(TEST_PACKAGE_UID2);
18001         final int uid3 = SECONDARY_USER_HANDLE.getUid(TEST_PACKAGE_UID);
18002         assertCreateNrisFromMobileDataPreferredUids(Set.of(uid1));
18003         assertCreateNrisFromMobileDataPreferredUids(Set.of(uid1, uid3));
18004         assertCreateNrisFromMobileDataPreferredUids(Set.of(uid1, uid2));
18005     }
18006 
18007     private void setAndUpdateMobileDataPreferredUids(Set<Integer> uids) {
18008         ConnectivitySettingsManager.setMobileDataPreferredUids(mServiceContext, uids);
18009         mService.updateMobileDataPreferredUids();
18010         waitForIdle();
18011     }
18012 
18013     /**
18014      * Test that MOBILE_DATA_PREFERRED_UIDS changes will send correct net id and uid ranges to netd.
18015      */
18016     @Test
18017     public void testMobileDataPreferredUidsChanged() throws Exception {
18018         final InOrder inorder = inOrder(mMockNetd);
18019         registerDefaultNetworkCallbacks();
18020         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
18021         mCellAgent.connect(true);
18022         mDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
18023         mTestPackageDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
18024 
18025         final int cellNetId = mCellAgent.getNetwork().netId;
18026         inorder.verify(mMockNetd, times(1)).networkCreate(nativeNetworkConfigPhysical(
18027                 cellNetId, INetd.PERMISSION_NONE));
18028 
18029         // Initial mobile data preferred uids status.
18030         setAndUpdateMobileDataPreferredUids(Set.of());
18031         inorder.verify(mMockNetd, never()).networkAddUidRangesParcel(any());
18032         inorder.verify(mMockNetd, never()).networkRemoveUidRangesParcel(any());
18033 
18034         // Set MOBILE_DATA_PREFERRED_UIDS setting and verify that net id and uid ranges send to netd
18035         final Set<Integer> uids1 = Set.of(PRIMARY_USER_HANDLE.getUid(TEST_PACKAGE_UID));
18036         final UidRangeParcel[] uidRanges1 = toUidRangeStableParcels(uidRangesForUids(uids1));
18037         final NativeUidRangeConfig config1 = new NativeUidRangeConfig(cellNetId, uidRanges1,
18038                 PREFERENCE_ORDER_MOBILE_DATA_PREFERERRED);
18039         setAndUpdateMobileDataPreferredUids(uids1);
18040         inorder.verify(mMockNetd, times(1)).networkAddUidRangesParcel(config1);
18041         inorder.verify(mMockNetd, never()).networkRemoveUidRangesParcel(any());
18042 
18043         // Set MOBILE_DATA_PREFERRED_UIDS setting again and verify that old rules are removed and
18044         // new rules are added.
18045         final Set<Integer> uids2 = Set.of(PRIMARY_USER_HANDLE.getUid(TEST_PACKAGE_UID),
18046                 PRIMARY_USER_HANDLE.getUid(TEST_PACKAGE_UID2),
18047                 SECONDARY_USER_HANDLE.getUid(TEST_PACKAGE_UID));
18048         final UidRangeParcel[] uidRanges2 = toUidRangeStableParcels(uidRangesForUids(uids2));
18049         final NativeUidRangeConfig config2 = new NativeUidRangeConfig(cellNetId, uidRanges2,
18050                 PREFERENCE_ORDER_MOBILE_DATA_PREFERERRED);
18051         setAndUpdateMobileDataPreferredUids(uids2);
18052         inorder.verify(mMockNetd, times(1)).networkRemoveUidRangesParcel(config1);
18053         inorder.verify(mMockNetd, times(1)).networkAddUidRangesParcel(config2);
18054 
18055         // Clear MOBILE_DATA_PREFERRED_UIDS setting again and verify that old rules are removed and
18056         // new rules are not added.
18057         setAndUpdateMobileDataPreferredUids(Set.of());
18058         inorder.verify(mMockNetd, times(1)).networkRemoveUidRangesParcel(config2);
18059         inorder.verify(mMockNetd, never()).networkAddUidRangesParcel(any());
18060     }
18061 
18062     /**
18063      * Make sure mobile data preferred uids feature behaves as expected when the mobile network
18064      * goes up and down while the uids is set. Make sure they behave as expected whether
18065      * there is a general default network or not.
18066      */
18067     @Test
18068     public void testMobileDataPreferenceForMobileNetworkUpDown() throws Exception {
18069         final InOrder inorder = inOrder(mMockNetd);
18070         // File a request for cell to ensure it doesn't go down.
18071         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
18072         final NetworkRequest cellRequest = new NetworkRequest.Builder()
18073                 .addTransportType(TRANSPORT_CELLULAR).build();
18074         mCm.requestNetwork(cellRequest, cellNetworkCallback);
18075         cellNetworkCallback.assertNoCallback();
18076 
18077         registerDefaultNetworkCallbacks();
18078         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
18079         mWiFiAgent.connect(true);
18080         mDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mWiFiAgent);
18081         mTestPackageDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mWiFiAgent);
18082         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_PACKAGE_UID));
18083 
18084         final int wifiNetId = mWiFiAgent.getNetwork().netId;
18085         inorder.verify(mMockNetd, times(1)).networkCreate(nativeNetworkConfigPhysical(
18086                 wifiNetId, INetd.PERMISSION_NONE));
18087 
18088         // Initial mobile data preferred uids status.
18089         setAndUpdateMobileDataPreferredUids(Set.of());
18090         inorder.verify(mMockNetd, never()).networkAddUidRangesParcel(any());
18091         inorder.verify(mMockNetd, never()).networkRemoveUidRangesParcel(any());
18092 
18093         // Set MOBILE_DATA_PREFERRED_UIDS setting and verify that wifi net id and uid ranges send to
18094         // netd.
18095         final Set<Integer> uids = Set.of(PRIMARY_USER_HANDLE.getUid(TEST_PACKAGE_UID));
18096         final UidRangeParcel[] uidRanges = toUidRangeStableParcels(uidRangesForUids(uids));
18097         final NativeUidRangeConfig wifiConfig = new NativeUidRangeConfig(wifiNetId, uidRanges,
18098                 PREFERENCE_ORDER_MOBILE_DATA_PREFERERRED);
18099         setAndUpdateMobileDataPreferredUids(uids);
18100         inorder.verify(mMockNetd, times(1)).networkAddUidRangesParcel(wifiConfig);
18101         inorder.verify(mMockNetd, never()).networkRemoveUidRangesParcel(any());
18102 
18103         // Cellular network connected. mTestPackageDefaultNetworkCallback should receive
18104         // callback with cellular network and net id and uid ranges should be updated to netd.
18105         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
18106         mCellAgent.connect(true);
18107         cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
18108         mDefaultNetworkCallback.assertNoCallback();
18109         mTestPackageDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
18110         assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_PACKAGE_UID));
18111 
18112         final int cellNetId = mCellAgent.getNetwork().netId;
18113         final NativeUidRangeConfig cellConfig = new NativeUidRangeConfig(cellNetId, uidRanges,
18114                 PREFERENCE_ORDER_MOBILE_DATA_PREFERERRED);
18115         inorder.verify(mMockNetd, times(1)).networkCreate(nativeNetworkConfigPhysical(
18116                 cellNetId, INetd.PERMISSION_NONE));
18117         inorder.verify(mMockNetd, times(1)).networkAddUidRangesParcel(cellConfig);
18118         inorder.verify(mMockNetd, times(1)).networkRemoveUidRangesParcel(wifiConfig);
18119 
18120         // Cellular network disconnected. mTestPackageDefaultNetworkCallback should receive
18121         // callback with wifi network from fallback request.
18122         mCellAgent.disconnect();
18123         mDefaultNetworkCallback.assertNoCallback();
18124         cellNetworkCallback.expect(LOST, mCellAgent);
18125         mTestPackageDefaultNetworkCallback.expect(LOST, mCellAgent);
18126         mTestPackageDefaultNetworkCallback.expectAvailableCallbacksValidated(mWiFiAgent);
18127         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_PACKAGE_UID));
18128         inorder.verify(mMockNetd, times(1)).networkAddUidRangesParcel(wifiConfig);
18129         inorder.verify(mMockNetd, never()).networkRemoveUidRangesParcel(any());
18130         inorder.verify(mMockNetd).networkDestroy(cellNetId);
18131 
18132         // Cellular network comes back. mTestPackageDefaultNetworkCallback should receive
18133         // callback with cellular network.
18134         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
18135         mCellAgent.connect(true);
18136         cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
18137         mDefaultNetworkCallback.assertNoCallback();
18138         mTestPackageDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
18139         assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_PACKAGE_UID));
18140 
18141         final int cellNetId2 = mCellAgent.getNetwork().netId;
18142         final NativeUidRangeConfig cellConfig2 = new NativeUidRangeConfig(cellNetId2, uidRanges,
18143                 PREFERENCE_ORDER_MOBILE_DATA_PREFERERRED);
18144         inorder.verify(mMockNetd, times(1)).networkCreate(nativeNetworkConfigPhysical(
18145                 cellNetId2, INetd.PERMISSION_NONE));
18146         inorder.verify(mMockNetd, times(1)).networkAddUidRangesParcel(cellConfig2);
18147         inorder.verify(mMockNetd, times(1)).networkRemoveUidRangesParcel(wifiConfig);
18148 
18149         // Wifi network disconnected. mTestPackageDefaultNetworkCallback should not receive
18150         // any callback.
18151         mWiFiAgent.disconnect();
18152         mDefaultNetworkCallback.expect(LOST, mWiFiAgent);
18153         mDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellAgent);
18154         mTestPackageDefaultNetworkCallback.assertNoCallback();
18155         assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_PACKAGE_UID));
18156         waitForIdle();
18157         inorder.verify(mMockNetd, never()).networkAddUidRangesParcel(any());
18158         inorder.verify(mMockNetd, never()).networkRemoveUidRangesParcel(any());
18159         inorder.verify(mMockNetd).networkDestroy(wifiNetId);
18160 
18161         mCm.unregisterNetworkCallback(cellNetworkCallback);
18162     }
18163 
18164     @Test
18165     public void testMultilayerRequestsOfSetMobileDataPreferredUids() throws Exception {
18166         // First set mobile data preferred uid to create a multi-layer requests: 1. request for
18167         // cellular, 2. track the default network for fallback.
18168         setAndUpdateMobileDataPreferredUids(
18169                 Set.of(PRIMARY_USER_HANDLE.getUid(TEST_PACKAGE_UID)));
18170 
18171         final HandlerThread handlerThread = new HandlerThread("MockFactory");
18172         handlerThread.start();
18173         final NetworkCapabilities cellFilter = new NetworkCapabilities()
18174                 .addTransportType(TRANSPORT_CELLULAR)
18175                 .addCapability(NET_CAPABILITY_INTERNET)
18176                 .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED);
18177         final MockNetworkFactory cellFactory = new MockNetworkFactory(handlerThread.getLooper(),
18178                 mServiceContext, "cellFactory", cellFilter, mCsHandlerThread);
18179         cellFactory.setScoreFilter(40);
18180 
18181         try {
18182             cellFactory.register();
18183             // Default internet request and the mobile data preferred request.
18184             cellFactory.expectRequestAdds(2);
18185             cellFactory.assertRequestCountEquals(2);
18186 
18187             mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
18188             mWiFiAgent.connect(true);
18189 
18190             // The cellFactory however is outscored, and should lose default internet request.
18191             // But it should still see mobile data preferred request.
18192             cellFactory.expectRequestRemove();
18193             cellFactory.assertRequestCountEquals(1);
18194 
18195             mWiFiAgent.disconnect();
18196             // The network satisfying the default internet request has disconnected, so the
18197             // cellFactory sees the default internet requests again.
18198             cellFactory.expectRequestAdd();
18199             cellFactory.assertRequestCountEquals(2);
18200         } finally {
18201             cellFactory.terminate();
18202             handlerThread.quitSafely();
18203             handlerThread.join();
18204         }
18205     }
18206 
18207     /**
18208      * Validate request counts are counted accurately on MOBILE_DATA_PREFERRED_UIDS change
18209      * on set/replace.
18210      */
18211     @Test
18212     public void testMobileDataPreferredUidsChangedCountsRequestsCorrectlyOnSet() throws Exception {
18213         ConnectivitySettingsManager.setMobileDataPreferredUids(mServiceContext,
18214                 Set.of(PRIMARY_USER_HANDLE.getUid(TEST_PACKAGE_UID)));
18215         // Leave one request available so MDO preference set up above can be set.
18216         withRequestCountersAcquired(1 /* countToLeaveAvailable */, () ->
18217                 withPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
18218                         Process.myPid(), Process.myUid(), () -> {
18219                             // Set initially to test the limit prior to having existing requests.
18220                             mService.updateMobileDataPreferredUids();
18221                             waitForIdle();
18222 
18223                             // re-set so as to test the limit as part of replacing existing requests
18224                             mService.updateMobileDataPreferredUids();
18225                             waitForIdle();
18226                         }));
18227     }
18228 
18229     @Test
18230     public void testAllNetworkPreferencesCanCoexist()
18231             throws Exception {
18232         final InOrder inorder = inOrder(mMockNetd);
18233         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
18234                 OEM_NETWORK_PREFERENCE_OEM_PAID;
18235         final UserHandle testHandle = setupEnterpriseNetwork();
18236 
18237         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true);
18238         final int cellNetId = mCellAgent.getNetwork().netId;
18239         inorder.verify(mMockNetd, times(1)).networkCreate(nativeNetworkConfigPhysical(
18240                 cellNetId, INetd.PERMISSION_NONE));
18241 
18242         // Set oem network preference
18243         final int[] uids1 = new int[] { PRIMARY_USER_HANDLE.getUid(TEST_PACKAGE_UID) };
18244         final UidRangeParcel[] uidRanges1 = toUidRangeStableParcels(uidRangesForUids(uids1));
18245         final NativeUidRangeConfig config1 = new NativeUidRangeConfig(cellNetId, uidRanges1,
18246                 PREFERENCE_ORDER_OEM);
18247         setupSetOemNetworkPreferenceForPreferenceTest(networkPref, uidRanges1, TEST_PACKAGE_NAME);
18248         inorder.verify(mMockNetd, times(1)).networkAddUidRangesParcel(config1);
18249         inorder.verify(mMockNetd, never()).networkRemoveUidRangesParcel(any());
18250 
18251         // Set user profile network preference
18252         final TestNetworkAgentWrapper workAgent = makeEnterpriseNetworkAgent();
18253         workAgent.connect(true);
18254 
18255         final TestOnCompleteListener listener = new TestOnCompleteListener();
18256         mCm.setProfileNetworkPreference(testHandle, PROFILE_NETWORK_PREFERENCE_ENTERPRISE,
18257                 r -> r.run(), listener);
18258         listener.expectOnComplete();
18259         final NativeUidRangeConfig config2 = new NativeUidRangeConfig(workAgent.getNetwork().netId,
18260                 uidRangeFor(testHandle), PREFERENCE_ORDER_PROFILE);
18261         inorder.verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
18262                 workAgent.getNetwork().netId, INetd.PERMISSION_SYSTEM));
18263         inorder.verify(mMockNetd, never()).networkRemoveUidRangesParcel(any());
18264         inorder.verify(mMockNetd).networkAddUidRangesParcel(config2);
18265 
18266         // Set MOBILE_DATA_PREFERRED_UIDS setting
18267         final Set<Integer> uids2 = Set.of(PRIMARY_USER_HANDLE.getUid(TEST_PACKAGE_UID2));
18268         final UidRangeParcel[] uidRanges2 = toUidRangeStableParcels(uidRangesForUids(uids2));
18269         final NativeUidRangeConfig config3 = new NativeUidRangeConfig(cellNetId, uidRanges2,
18270                 PREFERENCE_ORDER_MOBILE_DATA_PREFERERRED);
18271         setAndUpdateMobileDataPreferredUids(uids2);
18272         inorder.verify(mMockNetd, never()).networkRemoveUidRangesParcel(any());
18273         inorder.verify(mMockNetd, times(1)).networkAddUidRangesParcel(config3);
18274 
18275         // Set oem network preference again with different uid.
18276         final Set<Integer> uids3 = Set.of(PRIMARY_USER_HANDLE.getUid(TEST_PACKAGE_UID3));
18277         final UidRangeParcel[] uidRanges3 = toUidRangeStableParcels(uidRangesForUids(uids3));
18278         final NativeUidRangeConfig config4 = new NativeUidRangeConfig(cellNetId, uidRanges3,
18279                 PREFERENCE_ORDER_OEM);
18280         setupSetOemNetworkPreferenceForPreferenceTest(networkPref, uidRanges3, "com.android.test");
18281         inorder.verify(mMockNetd, times(1)).networkRemoveUidRangesParcel(config1);
18282         inorder.verify(mMockNetd, times(1)).networkAddUidRangesParcel(config4);
18283 
18284         // Remove user profile network preference
18285         mCm.setProfileNetworkPreference(testHandle, PROFILE_NETWORK_PREFERENCE_DEFAULT,
18286                 r -> r.run(), listener);
18287         listener.expectOnComplete();
18288         inorder.verify(mMockNetd, times(1)).networkRemoveUidRangesParcel(config2);
18289         inorder.verify(mMockNetd, never()).networkAddUidRangesParcel(any());
18290 
18291         // Set MOBILE_DATA_PREFERRED_UIDS setting again with same uid as oem network preference.
18292         final NativeUidRangeConfig config6 = new NativeUidRangeConfig(cellNetId, uidRanges3,
18293                 PREFERENCE_ORDER_MOBILE_DATA_PREFERERRED);
18294         setAndUpdateMobileDataPreferredUids(uids3);
18295         inorder.verify(mMockNetd, times(1)).networkRemoveUidRangesParcel(config3);
18296         inorder.verify(mMockNetd, times(1)).networkAddUidRangesParcel(config6);
18297     }
18298 
18299     @Test
18300     public void testNetworkCallbackAndActiveNetworkForUid_AllNetworkPreferencesEnabled()
18301             throws Exception {
18302         // File a request for cell to ensure it doesn't go down.
18303         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
18304         final NetworkRequest cellRequest = new NetworkRequest.Builder()
18305                 .addTransportType(TRANSPORT_CELLULAR).build();
18306         mCm.requestNetwork(cellRequest, cellNetworkCallback);
18307         cellNetworkCallback.assertNoCallback();
18308 
18309         // Register callbacks and have wifi network as default network.
18310         registerDefaultNetworkCallbacks();
18311         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
18312         mWiFiAgent.connect(true);
18313         mDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mWiFiAgent);
18314         mProfileDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mWiFiAgent);
18315         mTestPackageDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mWiFiAgent);
18316         assertEquals(mWiFiAgent.getNetwork(),
18317                 mCm.getActiveNetworkForUid(TEST_WORK_PROFILE_APP_UID));
18318         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_PACKAGE_UID));
18319 
18320         // Set MOBILE_DATA_PREFERRED_UIDS setting with TEST_WORK_PROFILE_APP_UID and
18321         // TEST_PACKAGE_UID. Both mProfileDefaultNetworkCallback and
18322         // mTestPackageDefaultNetworkCallback should receive callback with cell network.
18323         setAndUpdateMobileDataPreferredUids(Set.of(TEST_WORK_PROFILE_APP_UID, TEST_PACKAGE_UID));
18324         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
18325         mCellAgent.connect(true);
18326         cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
18327         mDefaultNetworkCallback.assertNoCallback();
18328         mProfileDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
18329         mTestPackageDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
18330         assertEquals(mCellAgent.getNetwork(),
18331                 mCm.getActiveNetworkForUid(TEST_WORK_PROFILE_APP_UID));
18332         assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_PACKAGE_UID));
18333 
18334         // Set user profile network preference with test profile. mProfileDefaultNetworkCallback
18335         // should receive callback with higher priority network preference (enterprise network).
18336         // The others should have no callbacks.
18337         final UserHandle testHandle = setupEnterpriseNetwork();
18338         final TestNetworkAgentWrapper workAgent = makeEnterpriseNetworkAgent();
18339         workAgent.connect(true);
18340         final TestOnCompleteListener listener = new TestOnCompleteListener();
18341         mCm.setProfileNetworkPreference(testHandle, PROFILE_NETWORK_PREFERENCE_ENTERPRISE,
18342                 r -> r.run(), listener);
18343         listener.expectOnComplete();
18344         assertNoCallbacks(mDefaultNetworkCallback, mTestPackageDefaultNetworkCallback);
18345         mProfileDefaultNetworkCallback.expectAvailableCallbacksValidated(workAgent);
18346         assertEquals(workAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_WORK_PROFILE_APP_UID));
18347         assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_PACKAGE_UID));
18348 
18349         // Set oem network preference with TEST_PACKAGE_UID. mTestPackageDefaultNetworkCallback
18350         // should receive callback with higher priority network preference (current default network)
18351         // and the others should have no callbacks.
18352         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
18353                 OEM_NETWORK_PREFERENCE_OEM_PAID;
18354         final int[] uids1 = new int[] { TEST_PACKAGE_UID };
18355         final UidRangeParcel[] uidRanges1 = toUidRangeStableParcels(uidRangesForUids(uids1));
18356         setupSetOemNetworkPreferenceForPreferenceTest(networkPref, uidRanges1, TEST_PACKAGE_NAME);
18357         assertNoCallbacks(mDefaultNetworkCallback, mProfileDefaultNetworkCallback);
18358         mTestPackageDefaultNetworkCallback.expectAvailableCallbacksValidated(mWiFiAgent);
18359         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_PACKAGE_UID));
18360         assertEquals(workAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_WORK_PROFILE_APP_UID));
18361 
18362         // Set oem network preference with TEST_WORK_PROFILE_APP_UID. Both
18363         // mProfileDefaultNetworkCallback and mTestPackageDefaultNetworkCallback should receive
18364         // callback.
18365         final int[] uids2 = new int[] { TEST_WORK_PROFILE_APP_UID };
18366         final UidRangeParcel[] uidRanges2 = toUidRangeStableParcels(uidRangesForUids(uids2));
18367         doReturn(Arrays.asList(testHandle)).when(mUserManager).getUserHandles(anyBoolean());
18368         setupSetOemNetworkPreferenceForPreferenceTest(
18369                 networkPref, uidRanges2, "com.android.test", testHandle);
18370         mDefaultNetworkCallback.assertNoCallback();
18371         mProfileDefaultNetworkCallback.expectAvailableCallbacksValidated(mWiFiAgent);
18372         mTestPackageDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellAgent);
18373         assertEquals(mWiFiAgent.getNetwork(),
18374                 mCm.getActiveNetworkForUid(TEST_WORK_PROFILE_APP_UID));
18375         assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_PACKAGE_UID));
18376 
18377         // Remove oem network preference, mProfileDefaultNetworkCallback should receive callback
18378         // with current highest priority network preference (enterprise network) and the others
18379         // should have no callbacks.
18380         final TestOemListenerCallback oemPrefListener = new TestOemListenerCallback();
18381         mService.setOemNetworkPreference(
18382                 new OemNetworkPreferences.Builder().build(), oemPrefListener);
18383         oemPrefListener.expectOnComplete();
18384         assertNoCallbacks(mDefaultNetworkCallback, mTestPackageDefaultNetworkCallback);
18385         mProfileDefaultNetworkCallback.expectAvailableCallbacksValidated(workAgent);
18386         assertEquals(workAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_WORK_PROFILE_APP_UID));
18387         assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_PACKAGE_UID));
18388 
18389         // Remove user profile network preference.
18390         mCm.setProfileNetworkPreference(testHandle, PROFILE_NETWORK_PREFERENCE_DEFAULT,
18391                 r -> r.run(), listener);
18392         listener.expectOnComplete();
18393         assertNoCallbacks(mDefaultNetworkCallback, mTestPackageDefaultNetworkCallback);
18394         mProfileDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellAgent);
18395         assertEquals(mCellAgent.getNetwork(),
18396                 mCm.getActiveNetworkForUid(TEST_WORK_PROFILE_APP_UID));
18397         assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_PACKAGE_UID));
18398 
18399         // Disconnect wifi
18400         mWiFiAgent.disconnect();
18401         assertNoCallbacks(mProfileDefaultNetworkCallback, mTestPackageDefaultNetworkCallback);
18402         mDefaultNetworkCallback.expect(LOST, mWiFiAgent);
18403         mDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellAgent);
18404     }
18405 
18406     @Test
18407     public void testRequestRouteToHostAddress_PackageDoesNotBelongToCaller() {
18408         assertThrows(SecurityException.class, () -> mService.requestRouteToHostAddress(
18409                 ConnectivityManager.TYPE_NONE, null /* hostAddress */, "com.not.package.owner",
18410                 null /* callingAttributionTag */));
18411     }
18412 
18413     @Test @IgnoreUpTo(SC_V2)
18414     public void testUpdateRateLimit_EnableDisable() throws Exception {
18415         final LinkProperties wifiLp = new LinkProperties();
18416         wifiLp.setInterfaceName(WIFI_IFNAME);
18417         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp);
18418         mWiFiAgent.connect(true);
18419 
18420         final LinkProperties cellLp = new LinkProperties();
18421         cellLp.setInterfaceName(MOBILE_IFNAME);
18422         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
18423         mCellAgent.connect(false);
18424 
18425         waitForIdle();
18426 
18427         final ArrayTrackRecord<Pair<String, Long>>.ReadHead readHeadWifi =
18428                 mDeps.mRateLimitHistory.newReadHead();
18429         final ArrayTrackRecord<Pair<String, Long>>.ReadHead readHeadCell =
18430                 mDeps.mRateLimitHistory.newReadHead();
18431 
18432         // set rate limit to 8MBit/s => 1MB/s
18433         final int rateLimitInBytesPerSec = 1 * 1000 * 1000;
18434         setIngressRateLimit(rateLimitInBytesPerSec);
18435 
18436         assertNotNull(readHeadWifi.poll(TIMEOUT_MS,
18437                 it -> it.first == wifiLp.getInterfaceName()
18438                         && it.second == rateLimitInBytesPerSec));
18439         assertNotNull(readHeadCell.poll(TIMEOUT_MS,
18440                 it -> it.first == cellLp.getInterfaceName()
18441                         && it.second == rateLimitInBytesPerSec));
18442 
18443         // disable rate limiting
18444         setIngressRateLimit(-1);
18445 
18446         assertNotNull(readHeadWifi.poll(TIMEOUT_MS,
18447                 it -> it.first == wifiLp.getInterfaceName() && it.second == -1));
18448         assertNotNull(readHeadCell.poll(TIMEOUT_MS,
18449                 it -> it.first == cellLp.getInterfaceName() && it.second == -1));
18450     }
18451 
18452     @Test @IgnoreUpTo(SC_V2)
18453     public void testUpdateRateLimit_WhenNewNetworkIsAdded() throws Exception {
18454         final LinkProperties wifiLp = new LinkProperties();
18455         wifiLp.setInterfaceName(WIFI_IFNAME);
18456         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp);
18457         mWiFiAgent.connect(true);
18458 
18459         waitForIdle();
18460 
18461         final ArrayTrackRecord<Pair<String, Long>>.ReadHead readHead =
18462                 mDeps.mRateLimitHistory.newReadHead();
18463 
18464         // set rate limit to 8MBit/s => 1MB/s
18465         final int rateLimitInBytesPerSec = 1 * 1000 * 1000;
18466         setIngressRateLimit(rateLimitInBytesPerSec);
18467         assertNotNull(readHead.poll(TIMEOUT_MS, it -> it.first == wifiLp.getInterfaceName()
18468                 && it.second == rateLimitInBytesPerSec));
18469 
18470         final LinkProperties cellLp = new LinkProperties();
18471         cellLp.setInterfaceName(MOBILE_IFNAME);
18472         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
18473         mCellAgent.connect(false);
18474         assertNotNull(readHead.poll(TIMEOUT_MS, it -> it.first == cellLp.getInterfaceName()
18475                 && it.second == rateLimitInBytesPerSec));
18476     }
18477 
18478     @Test @IgnoreUpTo(SC_V2)
18479     public void testUpdateRateLimit_OnlyAffectsInternetCapableNetworks() throws Exception {
18480         final LinkProperties wifiLp = new LinkProperties();
18481         wifiLp.setInterfaceName(WIFI_IFNAME);
18482 
18483         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp);
18484         mWiFiAgent.connectWithoutInternet();
18485 
18486         waitForIdle();
18487 
18488         setIngressRateLimit(1000);
18489         setIngressRateLimit(-1);
18490 
18491         final ArrayTrackRecord<Pair<String, Long>>.ReadHead readHeadWifi =
18492                 mDeps.mRateLimitHistory.newReadHead();
18493         assertNull(readHeadWifi.poll(TIMEOUT_MS, it -> it.first == wifiLp.getInterfaceName()));
18494     }
18495 
18496     @Test @IgnoreUpTo(SC_V2)
18497     public void testUpdateRateLimit_DisconnectingResetsRateLimit()
18498             throws Exception {
18499         // Steps:
18500         // - connect network
18501         // - set rate limit
18502         // - disconnect network (interface still exists)
18503         // - disable rate limit
18504         // - connect network
18505         // - ensure network interface is not rate limited
18506         final LinkProperties wifiLp = new LinkProperties();
18507         wifiLp.setInterfaceName(WIFI_IFNAME);
18508         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp);
18509         mWiFiAgent.connect(true);
18510         waitForIdle();
18511 
18512         final ArrayTrackRecord<Pair<String, Long>>.ReadHead readHeadWifi =
18513                 mDeps.mRateLimitHistory.newReadHead();
18514 
18515         int rateLimitInBytesPerSec = 1000;
18516         setIngressRateLimit(rateLimitInBytesPerSec);
18517         assertNotNull(readHeadWifi.poll(TIMEOUT_MS,
18518                 it -> it.first == wifiLp.getInterfaceName()
18519                         && it.second == rateLimitInBytesPerSec));
18520 
18521         mWiFiAgent.disconnect();
18522         assertNotNull(readHeadWifi.poll(TIMEOUT_MS,
18523                 it -> it.first == wifiLp.getInterfaceName() && it.second == -1));
18524 
18525         setIngressRateLimit(-1);
18526 
18527         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp);
18528         mWiFiAgent.connect(true);
18529         assertNull(readHeadWifi.poll(TIMEOUT_MS, it -> it.first == wifiLp.getInterfaceName()));
18530     }
18531 
18532     @Test @IgnoreUpTo(SC_V2)
18533     public void testUpdateRateLimit_UpdateExistingRateLimit() throws Exception {
18534         final LinkProperties wifiLp = new LinkProperties();
18535         wifiLp.setInterfaceName(WIFI_IFNAME);
18536         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp);
18537         mWiFiAgent.connect(true);
18538         waitForIdle();
18539 
18540         final ArrayTrackRecord<Pair<String, Long>>.ReadHead readHeadWifi =
18541                 mDeps.mRateLimitHistory.newReadHead();
18542 
18543         // update an active ingress rate limit
18544         setIngressRateLimit(1000);
18545         setIngressRateLimit(2000);
18546 
18547         // verify the following order of execution:
18548         // 1. ingress rate limit set to 1000.
18549         // 2. ingress rate limit disabled (triggered by updating active rate limit).
18550         // 3. ingress rate limit set to 2000.
18551         assertNotNull(readHeadWifi.poll(TIMEOUT_MS,
18552                 it -> it.first == wifiLp.getInterfaceName()
18553                         && it.second == 1000));
18554         assertNotNull(readHeadWifi.poll(TIMEOUT_MS,
18555                 it -> it.first == wifiLp.getInterfaceName()
18556                         && it.second == -1));
18557         assertNotNull(readHeadWifi.poll(TIMEOUT_MS,
18558                 it -> it.first == wifiLp.getInterfaceName()
18559                         && it.second == 2000));
18560     }
18561 
18562     @Test @IgnoreAfter(SC_V2)
18563     public void testUpdateRateLimit_DoesNothingBeforeT() throws Exception {
18564         final LinkProperties wifiLp = new LinkProperties();
18565         wifiLp.setInterfaceName(WIFI_IFNAME);
18566         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp);
18567         mWiFiAgent.connect(true);
18568         waitForIdle();
18569 
18570         final ArrayTrackRecord<Pair<String, Long>>.ReadHead readHead =
18571                 mDeps.mRateLimitHistory.newReadHead();
18572 
18573         setIngressRateLimit(1000);
18574         waitForIdle();
18575 
18576         assertNull(readHead.poll(TEST_CALLBACK_TIMEOUT_MS, it -> true));
18577     }
18578 
18579     @Test
18580     public void testOfferNetwork_ChecksArgumentsOutsideOfHandler() throws Exception {
18581         final TestableNetworkOfferCallback callback = new TestableNetworkOfferCallback(
18582                 TIMEOUT_MS /* timeout */, TEST_CALLBACK_TIMEOUT_MS /* noCallbackTimeout */);
18583         final NetworkProvider testProvider = new NetworkProvider(mServiceContext,
18584                 mCsHandlerThread.getLooper(), "Test provider");
18585         final NetworkCapabilities caps = new NetworkCapabilities.Builder()
18586                 .addCapability(NET_CAPABILITY_INTERNET)
18587                 .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
18588                 .build();
18589 
18590         final NetworkScore score = new NetworkScore.Builder().build();
18591         testProvider.registerNetworkOffer(score, caps, r -> r.run(), callback);
18592         testProvider.unregisterNetworkOffer(callback);
18593 
18594         assertThrows(NullPointerException.class,
18595                 () -> mService.offerNetwork(100, score, caps, null));
18596         assertThrows(NullPointerException.class, () -> mService.unofferNetwork(null));
18597     }
18598 
18599     public void doTestIgnoreValidationAfterRoam(int resValue, final boolean enabled)
18600             throws Exception {
18601         doReturn(resValue).when(mResources)
18602                 .getInteger(R.integer.config_validationFailureAfterRoamIgnoreTimeMillis);
18603 
18604         final String bssid1 = "AA:AA:AA:AA:AA:AA";
18605         final String bssid2 = "BB:BB:BB:BB:BB:BB";
18606         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
18607         mCellAgent.connect(true);
18608         NetworkCapabilities wifiNc1 = new NetworkCapabilities()
18609                 .addCapability(NET_CAPABILITY_INTERNET)
18610                 .addCapability(NET_CAPABILITY_NOT_VPN)
18611                 .addCapability(NET_CAPABILITY_NOT_RESTRICTED)
18612                 .addCapability(NET_CAPABILITY_TRUSTED)
18613                 .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
18614                 .addTransportType(TRANSPORT_WIFI)
18615                 .setTransportInfo(new WifiInfo.Builder().setBssid(bssid1).build());
18616         NetworkCapabilities wifiNc2 = new NetworkCapabilities(wifiNc1)
18617                 .setTransportInfo(new WifiInfo.Builder().setBssid(bssid2).build());
18618         final LinkProperties wifiLp = new LinkProperties();
18619         wifiLp.setInterfaceName(WIFI_IFNAME);
18620         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp, wifiNc1);
18621         mWiFiAgent.connect(true);
18622 
18623         // The default network will be switching to Wi-Fi Network.
18624         final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
18625         final NetworkRequest wifiRequest = new NetworkRequest.Builder()
18626                 .addTransportType(TRANSPORT_WIFI).build();
18627         mCm.requestNetwork(wifiRequest, wifiNetworkCallback);
18628         wifiNetworkCallback.expectAvailableCallbacksValidated(mWiFiAgent);
18629         registerDefaultNetworkCallbacks();
18630         mDefaultNetworkCallback.expectAvailableCallbacksValidated(mWiFiAgent);
18631 
18632         // There is a bug in the current code where ignoring validation after roam will not
18633         // correctly change the default network if the result if the validation is partial or
18634         // captive portal. TODO : fix the bug and reinstate this code.
18635         if (false) {
18636             // Wi-Fi roaming from wifiNc1 to wifiNc2 but the network is now behind a captive portal.
18637             mWiFiAgent.setNetworkCapabilities(wifiNc2, true /* sendToConnectivityService */);
18638             // The only thing changed in this CAPS is the BSSID, which can't be tested for in this
18639             // test because it's redacted.
18640             wifiNetworkCallback.expectCaps(mWiFiAgent);
18641             mDefaultNetworkCallback.expectCaps(mWiFiAgent);
18642             mWiFiAgent.setNetworkPortal(TEST_REDIRECT_URL, false /* privateDnsProbeSent */);
18643             mCm.reportNetworkConnectivity(mWiFiAgent.getNetwork(), false);
18644             // Wi-Fi is now detected to have a portal : cell should become the default network.
18645             mDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellAgent);
18646             wifiNetworkCallback.expectCaps(mWiFiAgent,
18647                     c -> !c.hasCapability(NET_CAPABILITY_VALIDATED));
18648             wifiNetworkCallback.expectCaps(mWiFiAgent,
18649                     c -> c.hasCapability(NET_CAPABILITY_CAPTIVE_PORTAL));
18650 
18651             // Wi-Fi becomes valid again. The default network goes back to Wi-Fi.
18652             mWiFiAgent.setNetworkValid(false /* privateDnsProbeSent */);
18653             mCm.reportNetworkConnectivity(mWiFiAgent.getNetwork(), true);
18654             mDefaultNetworkCallback.expectAvailableCallbacksValidated(mWiFiAgent);
18655             wifiNetworkCallback.expectCaps(mWiFiAgent,
18656                     c -> !c.hasCapability(NET_CAPABILITY_CAPTIVE_PORTAL));
18657 
18658             // Wi-Fi roaming from wifiNc2 to wifiNc1, and the network now has partial connectivity.
18659             mWiFiAgent.setNetworkCapabilities(wifiNc1, true);
18660             wifiNetworkCallback.expectCaps(mWiFiAgent);
18661             mDefaultNetworkCallback.expectCaps(mWiFiAgent);
18662             mWiFiAgent.setNetworkPartial();
18663             mCm.reportNetworkConnectivity(mWiFiAgent.getNetwork(), false);
18664             // Wi-Fi now only offers partial connectivity, so in the absence of accepting partial
18665             // connectivity explicitly for this network, it loses default status to cell.
18666             mDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellAgent);
18667             wifiNetworkCallback.expectCaps(mWiFiAgent,
18668                     c -> c.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY));
18669 
18670             // Wi-Fi becomes valid again. The default network goes back to Wi-Fi.
18671             mWiFiAgent.setNetworkValid(false /* privateDnsProbeSent */);
18672             mCm.reportNetworkConnectivity(mWiFiAgent.getNetwork(), true);
18673             mDefaultNetworkCallback.expectAvailableCallbacksValidated(mWiFiAgent);
18674             wifiNetworkCallback.expectCaps(mWiFiAgent,
18675                     c -> !c.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY));
18676         }
18677         mCm.unregisterNetworkCallback(wifiNetworkCallback);
18678 
18679         // Wi-Fi roams from wifiNc1 to wifiNc2, and now becomes really invalid. If validation
18680         // failures after roam are not ignored, this will cause cell to become the default network.
18681         // If they are ignored, this will not cause a switch until later.
18682         mWiFiAgent.setNetworkCapabilities(wifiNc2, true);
18683         mDefaultNetworkCallback.expectCaps(mWiFiAgent);
18684         mWiFiAgent.setNetworkInvalid(false /* invalidBecauseOfPrivateDns */);
18685         mCm.reportNetworkConnectivity(mWiFiAgent.getNetwork(), false);
18686 
18687         if (enabled) {
18688             // Network validation failed, but the result will be ignored.
18689             assertTrue(mCm.getNetworkCapabilities(mWiFiAgent.getNetwork()).hasCapability(
18690                     NET_CAPABILITY_VALIDATED));
18691             mWiFiAgent.setNetworkValid(false);
18692 
18693             // Behavior of after config_validationFailureAfterRoamIgnoreTimeMillis
18694             ConditionVariable waitForValidationBlock = new ConditionVariable();
18695             doReturn(50).when(mResources)
18696                     .getInteger(R.integer.config_validationFailureAfterRoamIgnoreTimeMillis);
18697             // Wi-Fi roaming from wifiNc2 to wifiNc1.
18698             mWiFiAgent.setNetworkCapabilities(wifiNc1, true);
18699             mWiFiAgent.setNetworkInvalid(false);
18700             waitForValidationBlock.block(150);
18701             mCm.reportNetworkConnectivity(mWiFiAgent.getNetwork(), false);
18702             mDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellAgent);
18703         } else {
18704             mDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellAgent);
18705         }
18706 
18707         // Wi-Fi is still connected and would become the default network if cell were to
18708         // disconnect. This assertion ensures that the switch to cellular was not caused by
18709         // Wi-Fi disconnecting (e.g., because the capability change to wifiNc2 caused it
18710         // to stop satisfying the default request).
18711         mCellAgent.disconnect();
18712         mDefaultNetworkCallback.expect(LOST, mCellAgent);
18713         mDefaultNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
18714 
18715     }
18716 
18717     @Test
18718     public void testIgnoreValidationAfterRoamDisabled() throws Exception {
18719         doTestIgnoreValidationAfterRoam(-1, false /* enabled */);
18720     }
18721 
18722     @Test
18723     public void testIgnoreValidationAfterRoamEnabled() throws Exception {
18724         final boolean enabled = !mDeps.isAtLeastT();
18725         doTestIgnoreValidationAfterRoam(5_000, enabled);
18726     }
18727 
18728     @Test
18729     public void testShouldIgnoreValidationFailureAfterRoam() {
18730         // Always disabled on T+.
18731         assumeFalse(mDeps.isAtLeastT());
18732 
18733         NetworkAgentInfo nai = fakeWifiNai(new NetworkCapabilities());
18734 
18735         // Enabled, but never roamed.
18736         doReturn(5_000).when(mResources)
18737                 .getInteger(R.integer.config_validationFailureAfterRoamIgnoreTimeMillis);
18738         assertEquals(0, nai.lastRoamTime);
18739         assertFalse(mService.shouldIgnoreValidationFailureAfterRoam(nai));
18740 
18741         // Roamed recently.
18742         nai.lastRoamTime = SystemClock.elapsedRealtime() - 500 /* ms */;
18743         assertTrue(mService.shouldIgnoreValidationFailureAfterRoam(nai));
18744 
18745         // Disabled due to invalid setting (maximum is 10 seconds).
18746         doReturn(15_000).when(mResources)
18747                 .getInteger(R.integer.config_validationFailureAfterRoamIgnoreTimeMillis);
18748         assertFalse(mService.shouldIgnoreValidationFailureAfterRoam(nai));
18749 
18750         // Disabled.
18751         doReturn(-1).when(mResources)
18752                 .getInteger(R.integer.config_validationFailureAfterRoamIgnoreTimeMillis);
18753         assertFalse(mService.shouldIgnoreValidationFailureAfterRoam(nai));
18754     }
18755 
18756 
18757     @Test
18758     public void testLegacyTetheringApiGuardWithProperPermission() throws Exception {
18759         final String testIface = "test0";
18760         mServiceContext.setPermission(ACCESS_NETWORK_STATE, PERMISSION_DENIED);
18761         assertThrows(SecurityException.class, () -> mService.getLastTetherError(testIface));
18762         assertThrows(SecurityException.class, () -> mService.getTetherableIfaces());
18763         assertThrows(SecurityException.class, () -> mService.getTetheredIfaces());
18764         assertThrows(SecurityException.class, () -> mService.getTetheringErroredIfaces());
18765         assertThrows(SecurityException.class, () -> mService.getTetherableUsbRegexs());
18766         assertThrows(SecurityException.class, () -> mService.getTetherableWifiRegexs());
18767 
18768         withPermission(ACCESS_NETWORK_STATE, () -> {
18769             mService.getLastTetherError(testIface);
18770             verify(mTetheringManager).getLastTetherError(testIface);
18771 
18772             mService.getTetherableIfaces();
18773             verify(mTetheringManager).getTetherableIfaces();
18774 
18775             mService.getTetheredIfaces();
18776             verify(mTetheringManager).getTetheredIfaces();
18777 
18778             mService.getTetheringErroredIfaces();
18779             verify(mTetheringManager).getTetheringErroredIfaces();
18780 
18781             mService.getTetherableUsbRegexs();
18782             verify(mTetheringManager).getTetherableUsbRegexs();
18783 
18784             mService.getTetherableWifiRegexs();
18785             verify(mTetheringManager).getTetherableWifiRegexs();
18786         });
18787     }
18788 
18789     private void verifyMtuSetOnWifiInterface(int mtu) throws Exception {
18790         verify(mMockNetd, times(1)).interfaceSetMtu(WIFI_IFNAME, mtu);
18791     }
18792 
18793     private void verifyMtuNeverSetOnWifiInterface() throws Exception {
18794         verify(mMockNetd, never()).interfaceSetMtu(eq(WIFI_IFNAME), anyInt());
18795     }
18796 
18797     private void verifyMtuSetOnWifiInterfaceOnlyUpToT(int mtu) throws Exception {
18798         if (!mService.shouldCreateNetworksImmediately()) {
18799             verify(mMockNetd, times(1)).interfaceSetMtu(WIFI_IFNAME, mtu);
18800         } else {
18801             verify(mMockNetd, never()).interfaceSetMtu(eq(WIFI_IFNAME), anyInt());
18802         }
18803     }
18804 
18805     private void verifyMtuSetOnWifiInterfaceOnlyStartingFromU(int mtu) throws Exception {
18806         if (mService.shouldCreateNetworksImmediately()) {
18807             verify(mMockNetd, times(1)).interfaceSetMtu(WIFI_IFNAME, mtu);
18808         } else {
18809             verify(mMockNetd, never()).interfaceSetMtu(eq(WIFI_IFNAME), anyInt());
18810         }
18811     }
18812 
18813     @Test
18814     public void testSendLinkPropertiesSetInterfaceMtuBeforeConnect() throws Exception {
18815         final int mtu = 1281;
18816         LinkProperties lp = new LinkProperties();
18817         lp.setInterfaceName(WIFI_IFNAME);
18818         lp.setMtu(mtu);
18819 
18820         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
18821         mWiFiAgent.sendLinkProperties(lp);
18822         waitForIdle();
18823         verifyMtuSetOnWifiInterface(mtu);
18824         reset(mMockNetd);
18825 
18826         mWiFiAgent.connect(false /* validated */);
18827         // Before U, the MTU is always (re-)applied when the network connects.
18828         verifyMtuSetOnWifiInterfaceOnlyUpToT(mtu);
18829     }
18830 
18831     @Test
18832     public void testSendLinkPropertiesUpdateInterfaceMtuBeforeConnect() throws Exception {
18833         final int mtu = 1327;
18834         LinkProperties lp = new LinkProperties();
18835         lp.setInterfaceName(WIFI_IFNAME);
18836         lp.setMtu(mtu);
18837 
18838         // Registering an agent with an MTU only sets the MTU on U+.
18839         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, lp);
18840         waitForIdle();
18841         verifyMtuSetOnWifiInterfaceOnlyStartingFromU(mtu);
18842         reset(mMockNetd);
18843 
18844         // Future updates with the same MTU don't set the MTU even on T when it's not set initially.
18845         mWiFiAgent.sendLinkProperties(lp);
18846         waitForIdle();
18847         verifyMtuNeverSetOnWifiInterface();
18848 
18849         // Updating with a different MTU does work.
18850         lp.setMtu(mtu + 1);
18851         mWiFiAgent.sendLinkProperties(lp);
18852         waitForIdle();
18853         verifyMtuSetOnWifiInterface(mtu + 1);
18854         reset(mMockNetd);
18855 
18856         mWiFiAgent.connect(false /* validated */);
18857         // Before U, the MTU is always (re-)applied when the network connects.
18858         verifyMtuSetOnWifiInterfaceOnlyUpToT(mtu + 1);
18859     }
18860 
18861     @Test
18862     public void testSendLinkPropertiesUpdateInterfaceMtuAfterConnect() throws Exception {
18863         final int mtu = 1327;
18864         LinkProperties lp = new LinkProperties();
18865         lp.setInterfaceName(WIFI_IFNAME);
18866         lp.setMtu(mtu);
18867 
18868         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
18869         mWiFiAgent.connect(false /* validated */);
18870         verifyMtuNeverSetOnWifiInterface();
18871 
18872         mWiFiAgent.sendLinkProperties(lp);
18873         waitForIdle();
18874         // The MTU is always (re-)applied when the network connects.
18875         verifyMtuSetOnWifiInterface(mtu);
18876     }
18877 
18878     @Test
18879     public void testSendLinkPropertiesSetInterfaceMtu_DifferentMtu() throws Exception {
18880         final int mtu = 1328, mtu2 = 1500;
18881         LinkProperties lp = new LinkProperties();
18882         lp.setInterfaceName(WIFI_IFNAME);
18883         lp.setMtu(mtu);
18884 
18885         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, lp);
18886         mWiFiAgent.connect(false /* validated */);
18887         verifyMtuSetOnWifiInterface(mtu);
18888         reset(mMockNetd);
18889 
18890         LinkProperties lp2 = new LinkProperties(lp);
18891         lp2.setMtu(mtu2);
18892         mWiFiAgent.sendLinkProperties(lp2);
18893         waitForIdle();
18894         verifyMtuSetOnWifiInterface(mtu2);
18895     }
18896 
18897     @Test
18898     public void testSendLinkPropertiesSetInterfaceMtu_IdenticalMtuAndIface() throws Exception {
18899         final int mtu = 1329;
18900         LinkProperties lp = new LinkProperties();
18901         lp.setInterfaceName(WIFI_IFNAME);
18902         lp.setMtu(mtu);
18903 
18904         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, lp);
18905         mWiFiAgent.connect(false /* validated */);
18906         verifyMtuSetOnWifiInterface(mtu);
18907         reset(mMockNetd);
18908 
18909         mWiFiAgent.sendLinkProperties(new LinkProperties(lp));
18910         waitForIdle();
18911         verifyMtuNeverSetOnWifiInterface();
18912     }
18913 
18914     @Test
18915     public void testSendLinkPropertiesSetInterfaceMtu_IdenticalMtuAndNullIface() throws Exception {
18916         final int mtu = 1330;
18917         LinkProperties lp = new LinkProperties();
18918         lp.setInterfaceName(WIFI_IFNAME);
18919         lp.setMtu(mtu);
18920 
18921         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, lp);
18922         mWiFiAgent.connect(false /* validated */);
18923         verifyMtuSetOnWifiInterface(mtu);
18924         reset(mMockNetd);
18925 
18926         LinkProperties lp2 = new LinkProperties(lp);
18927         lp2.setInterfaceName(null);
18928         mWiFiAgent.sendLinkProperties(new LinkProperties(lp2));
18929         waitForIdle();
18930         verifyMtuNeverSetOnWifiInterface();
18931     }
18932 
18933     @Test
18934     public void testSendLinkPropertiesSetInterfaceMtu_IdenticalMtuDiffIface() throws Exception {
18935         final int mtu = 1331;
18936         LinkProperties lp = new LinkProperties();
18937         lp.setInterfaceName(WIFI_IFNAME);
18938         lp.setMtu(mtu);
18939 
18940         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, lp);
18941         mWiFiAgent.connect(false /* validated */);
18942         verifyMtuSetOnWifiInterface(mtu);
18943         reset(mMockNetd);
18944 
18945         final String ifaceName2 = WIFI_IFNAME + "_2";
18946         LinkProperties lp2 = new LinkProperties(lp);
18947         lp2.setInterfaceName(ifaceName2);
18948 
18949         mWiFiAgent.sendLinkProperties(new LinkProperties(lp2));
18950         waitForIdle();
18951         verify(mMockNetd, times(1)).interfaceSetMtu(eq(ifaceName2), eq(mtu));
18952         verifyMtuNeverSetOnWifiInterface();
18953     }
18954 
18955     @Test
18956     public void testCreateDeliveryGroupKeyForConnectivityAction() throws Exception {
18957         final NetworkInfo info = new NetworkInfo(0 /* type */, 2 /* subtype */,
18958                 "MOBILE" /* typeName */, "LTE" /* subtypeName */);
18959         assertEquals("0;2;null", createDeliveryGroupKeyForConnectivityAction(info));
18960 
18961         info.setExtraInfo("test_info");
18962         assertEquals("0;2;test_info", createDeliveryGroupKeyForConnectivityAction(info));
18963     }
18964 
18965     @Test
18966     public void testNetdWakeupAddInterfaceForWifiTransport() throws Exception {
18967         final LinkProperties wifiLp = new LinkProperties();
18968         wifiLp.setInterfaceName(WIFI_IFNAME);
18969         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp);
18970         mWiFiAgent.connect(false /* validated */);
18971 
18972         final String expectedPrefix = makeNflogPrefix(WIFI_IFNAME,
18973                 mWiFiAgent.getNetwork().getNetworkHandle());
18974         verify(mMockNetd).wakeupAddInterface(WIFI_IFNAME, expectedPrefix, PACKET_WAKEUP_MARK_MASK,
18975                 PACKET_WAKEUP_MARK_MASK);
18976     }
18977 
18978     @Test
18979     public void testNetdWakeupAddInterfaceForCellularTransport() throws Exception {
18980         final LinkProperties cellLp = new LinkProperties();
18981         cellLp.setInterfaceName(MOBILE_IFNAME);
18982         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
18983         mCellAgent.connect(false /* validated */);
18984 
18985         if (mDeps.isAtLeastU()) {
18986             final String expectedPrefix = makeNflogPrefix(MOBILE_IFNAME,
18987                     mCellAgent.getNetwork().getNetworkHandle());
18988             verify(mMockNetd).wakeupAddInterface(MOBILE_IFNAME, expectedPrefix,
18989                     PACKET_WAKEUP_MARK_MASK, PACKET_WAKEUP_MARK_MASK);
18990         } else {
18991             verify(mMockNetd, never()).wakeupAddInterface(eq(MOBILE_IFNAME), anyString(), anyInt(),
18992                     anyInt());
18993         }
18994     }
18995 
18996     @Test
18997     public void testNetdWakeupAddInterfaceForEthernetTransport() throws Exception {
18998         final String ethernetIface = "eth42";
18999 
19000         final LinkProperties ethLp = new LinkProperties();
19001         ethLp.setInterfaceName(ethernetIface);
19002         mEthernetAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET, ethLp);
19003         mEthernetAgent.connect(false /* validated */);
19004 
19005         verify(mMockNetd, never()).wakeupAddInterface(eq(ethernetIface), anyString(), anyInt(),
19006                 anyInt());
19007     }
19008 
19009     // UidFrozenStateChangedCallback is added in U API.
19010     // Returning UidFrozenStateChangedCallback directly makes the test fail on T- devices since
19011     // AndroidJUnit4ClassRunner iterates all declared methods and tries to resolve the return type.
19012     // Solve this by wrapping it in an AtomicReference. Because of erasure, this removes the
19013     // resolving problem as the type isn't seen dynamically.
19014     private AtomicReference<UidFrozenStateChangedCallback> getUidFrozenStateChangedCallback() {
19015         ArgumentCaptor<UidFrozenStateChangedCallback> activityManagerCallbackCaptor =
19016                 ArgumentCaptor.forClass(UidFrozenStateChangedCallback.class);
19017         verify(mActivityManager).registerUidFrozenStateChangedCallback(any(),
19018                 activityManagerCallbackCaptor.capture());
19019         return new AtomicReference<>(activityManagerCallbackCaptor.getValue());
19020     }
19021 
19022     private BaseNetdUnsolicitedEventListener getRegisteredNetdUnsolicitedEventListener()
19023             throws RemoteException {
19024         ArgumentCaptor<BaseNetdUnsolicitedEventListener> netdCallbackCaptor =
19025                 ArgumentCaptor.forClass(BaseNetdUnsolicitedEventListener.class);
19026         verify(mMockNetd).registerUnsolicitedEventListener(netdCallbackCaptor.capture());
19027         return netdCallbackCaptor.getValue();
19028     }
19029 
19030     private static final int TEST_FROZEN_UID = 1000;
19031     private static final int TEST_UNFROZEN_UID = 2000;
19032 
19033     /**
19034      * Send a UidFrozenStateChanged message to ConnectivityService. Verify that only the frozen UID
19035      * gets passed to socketDestroy().
19036      */
19037     @Test
19038     @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
19039     public void testFrozenUidSocketDestroy() throws Exception {
19040         final UidFrozenStateChangedCallback callback =
19041                 getUidFrozenStateChangedCallback().get();
19042 
19043         final int[] uids = {TEST_FROZEN_UID, TEST_UNFROZEN_UID};
19044         final int[] frozenStates = {UID_FROZEN_STATE_FROZEN, UID_FROZEN_STATE_UNFROZEN};
19045 
19046         callback.onUidFrozenStateChanged(uids, frozenStates);
19047 
19048         waitForIdle();
19049 
19050         verify(mDestroySocketsWrapper).destroyLiveTcpSocketsByOwnerUids(Set.of(TEST_FROZEN_UID));
19051     }
19052 
19053     private void doTestDelayFrozenUidSocketDestroy(int transportType,
19054             boolean freezeWithNetworkInactive, boolean expectDelay) throws Exception {
19055         final TestNetworkCallback defaultCallback = new TestNetworkCallback();
19056         final LinkProperties lp = new LinkProperties();
19057         lp.setInterfaceName(transportToTestIfaceName(transportType));
19058         final TestNetworkAgentWrapper agent = new TestNetworkAgentWrapper(transportType, lp);
19059         final int idleTimerLabel = getIdleTimerLabel(agent.getNetwork().netId, transportType);
19060         testAndCleanup(() -> {
19061             final UidFrozenStateChangedCallback uidFrozenStateChangedCallback =
19062                     getUidFrozenStateChangedCallback().get();
19063             final BaseNetdUnsolicitedEventListener netdUnsolicitedEventListener =
19064                     getRegisteredNetdUnsolicitedEventListener();
19065 
19066             mCm.registerDefaultNetworkCallback(defaultCallback);
19067             agent.connect(true);
19068             defaultCallback.expectAvailableThenValidatedCallbacks(agent);
19069             if (freezeWithNetworkInactive) {
19070                 // Make network inactive
19071                 netdUnsolicitedEventListener.onInterfaceClassActivityChanged(false /* isActive */,
19072                         idleTimerLabel, TIMESTAMP, NETWORK_ACTIVITY_NO_UID);
19073             }
19074 
19075             // Freeze TEST_FROZEN_UID and TEST_UNFROZEN_UID
19076             final int[] uids1 = {TEST_FROZEN_UID, TEST_UNFROZEN_UID};
19077             final int[] frozenStates1 = {UID_FROZEN_STATE_FROZEN, UID_FROZEN_STATE_FROZEN};
19078             uidFrozenStateChangedCallback.onUidFrozenStateChanged(uids1, frozenStates1);
19079             waitForIdle();
19080 
19081             if (expectDelay) {
19082                 verify(mDestroySocketsWrapper, never()).destroyLiveTcpSocketsByOwnerUids(any());
19083             } else {
19084                 verify(mDestroySocketsWrapper).destroyLiveTcpSocketsByOwnerUids(
19085                         Set.of(TEST_FROZEN_UID, TEST_UNFROZEN_UID));
19086                 clearInvocations(mDestroySocketsWrapper);
19087             }
19088 
19089             // Unfreeze TEST_UNFROZEN_UID
19090             final int[] uids2 = {TEST_UNFROZEN_UID};
19091             final int[] frozenStates2 = {UID_FROZEN_STATE_UNFROZEN};
19092             uidFrozenStateChangedCallback.onUidFrozenStateChanged(uids2, frozenStates2);
19093 
19094             // Make network active
19095             netdUnsolicitedEventListener.onInterfaceClassActivityChanged(true /* isActive */,
19096                     idleTimerLabel, TIMESTAMP, TEST_PACKAGE_UID);
19097             waitForIdle();
19098 
19099             if (expectDelay) {
19100                 verify(mDestroySocketsWrapper).destroyLiveTcpSocketsByOwnerUids(
19101                         Set.of(TEST_FROZEN_UID));
19102             } else {
19103                 verify(mDestroySocketsWrapper, never()).destroyLiveTcpSocketsByOwnerUids(any());
19104             }
19105         }, () -> { // Cleanup
19106                 agent.disconnect();
19107             }, () -> {
19108                 mCm.unregisterNetworkCallback(defaultCallback);
19109             });
19110     }
19111 
19112     @Test
19113     @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
19114     public void testDelayFrozenUidSocketDestroy_ActiveCellular() throws Exception {
19115         doTestDelayFrozenUidSocketDestroy(TRANSPORT_CELLULAR, false /* freezeWithNetworkInactive */,
19116                 false /* expectDelay */);
19117     }
19118 
19119     @Test
19120     @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
19121     public void testDelayFrozenUidSocketDestroy_InactiveCellular() throws Exception {
19122         // When the default network is cellular and cellular network is inactive, closing socket
19123         // is delayed.
19124         doTestDelayFrozenUidSocketDestroy(TRANSPORT_CELLULAR, true /* freezeWithNetworkInactive */,
19125                 true /* expectDelay */);
19126     }
19127 
19128     @Test
19129     @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
19130     public void testDelayFrozenUidSocketDestroy_ActiveWifi() throws Exception {
19131         doTestDelayFrozenUidSocketDestroy(TRANSPORT_WIFI, false /* freezeWithNetworkInactive */,
19132                 false /* expectDelay */);
19133     }
19134 
19135     @Test
19136     @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
19137     public void testDelayFrozenUidSocketDestroy_InactiveWifi() throws Exception {
19138         doTestDelayFrozenUidSocketDestroy(TRANSPORT_WIFI, true /* freezeWithNetworkInactive */,
19139                 false /* expectDelay */);
19140     }
19141 
19142     /**
19143      * @param switchToWifi if true, simulate a migration of the default network to wifi
19144      *                     if false, simulate a cell disconnection
19145      */
19146     private void doTestLoseCellDefaultNetwork_ClosePendingFrozenSockets(final boolean switchToWifi)
19147             throws Exception {
19148         final UidFrozenStateChangedCallback uidFrozenStateChangedCallback =
19149                 getUidFrozenStateChangedCallback().get();
19150         final BaseNetdUnsolicitedEventListener netdUnsolicitedEventListener =
19151                 getRegisteredNetdUnsolicitedEventListener();
19152 
19153         final LinkProperties wifiLp = new LinkProperties();
19154         wifiLp.setInterfaceName(WIFI_IFNAME);
19155         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp);
19156 
19157         final LinkProperties cellLp = new LinkProperties();
19158         cellLp.setInterfaceName(MOBILE_IFNAME);
19159         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
19160         final int idleTimerLabel =
19161                 getIdleTimerLabel(mCellAgent.getNetwork().netId, TRANSPORT_CELLULAR);
19162 
19163         final TestNetworkCallback defaultCallback = new TestNetworkCallback();
19164         mCm.registerDefaultNetworkCallback(defaultCallback);
19165         try {
19166             mCellAgent.connect(true);
19167             defaultCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
19168 
19169             // Make cell network inactive
19170             netdUnsolicitedEventListener.onInterfaceClassActivityChanged(false /* isActive */,
19171                     idleTimerLabel, TIMESTAMP, NETWORK_ACTIVITY_NO_UID);
19172 
19173             // Freeze TEST_FROZEN_UID
19174             final int[] uids = {TEST_FROZEN_UID};
19175             final int[] frozenStates = {UID_FROZEN_STATE_FROZEN};
19176             uidFrozenStateChangedCallback.onUidFrozenStateChanged(uids, frozenStates);
19177             waitForIdle();
19178 
19179             // Closing frozen sockets should be delayed since the default network is cellular
19180             // and cellular network is inactive.
19181             verify(mDestroySocketsWrapper, never()).destroyLiveTcpSocketsByOwnerUids(any());
19182 
19183             if (switchToWifi) {
19184                 mWiFiAgent.connect(true);
19185                 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiAgent);
19186             } else {
19187                 mCellAgent.disconnect();
19188                 waitForIdle();
19189             }
19190 
19191             // Pending frozen sockets should be closed since the cellular network is no longer the
19192             // default network.
19193             verify(mDestroySocketsWrapper)
19194                     .destroyLiveTcpSocketsByOwnerUids(Set.of(TEST_FROZEN_UID));
19195         } finally {
19196             mCm.unregisterNetworkCallback(defaultCallback);
19197         }
19198     }
19199 
19200     @Test
19201     @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
19202     public void testLoseCellDefaultNetwork_SwitchToWifi_ClosePendingFrozenSockets()
19203             throws Exception {
19204         doTestLoseCellDefaultNetwork_ClosePendingFrozenSockets(true /* switchToWifi */);
19205     }
19206 
19207     @Test
19208     @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
19209     public void testLoseCellDefaultNetwork_NoDefaultNetwork_ClosePendingFrozenSockets()
19210             throws Exception {
19211         doTestLoseCellDefaultNetwork_ClosePendingFrozenSockets(false /* switchToWifi */);
19212     }
19213 
19214     @Test
19215     public void testDisconnectSuspendedNetworkStopClatd() throws Exception {
19216         final TestNetworkCallback networkCallback = new TestNetworkCallback();
19217         final NetworkRequest networkRequest = new NetworkRequest.Builder()
19218                 .addCapability(NET_CAPABILITY_DUN)
19219                 .build();
19220         mCm.requestNetwork(networkRequest, networkCallback);
19221 
19222         final IpPrefix nat64Prefix = new IpPrefix(InetAddress.getByName("64:ff9b::"), 96);
19223         NetworkCapabilities nc = new NetworkCapabilities().addCapability(NET_CAPABILITY_DUN);
19224         final LinkProperties lp = new LinkProperties();
19225         lp.setInterfaceName(MOBILE_IFNAME);
19226         lp.addLinkAddress(new LinkAddress("2001:db8:1::1/64"));
19227         lp.setNat64Prefix(nat64Prefix);
19228         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, lp, nc);
19229         mCellAgent.connect(true /* validated */, false /* hasInternet */,
19230                 false /* privateDnsProbeSent */);
19231 
19232         verifyClatdStart(null /* inOrder */, MOBILE_IFNAME, mCellAgent.getNetwork().netId,
19233                 nat64Prefix.toString());
19234 
19235         mCellAgent.suspend();
19236         mCm.unregisterNetworkCallback(networkCallback);
19237         mCellAgent.expectDisconnected();
19238         waitForIdle();
19239 
19240         verifyClatdStop(null /* inOrder */, MOBILE_IFNAME);
19241     }
19242 
19243     private static final int EXPECTED_TEST_METHOD_COUNT = 332;
19244 
19245     @Test
19246     public void testTestMethodCount() {
19247         final Class<?> testClass = this.getClass();
19248 
19249         int actualTestMethodCount = 0;
19250         for (final Method method : testClass.getDeclaredMethods()) {
19251             if (method.isAnnotationPresent(Test.class)) {
19252                 actualTestMethodCount++;
19253             }
19254         }
19255 
19256         assertEquals("Adding tests in ConnectivityServiceTest is deprecated, "
19257                 + "as it is too big for maintenance. Please consider adding new tests "
19258                 + "in subclasses of CSTest instead.",
19259                 EXPECTED_TEST_METHOD_COUNT, actualTestMethodCount);
19260     }
19261 
19262     // Note : adding tests in ConnectivityServiceTest is deprecated, as it is too big for
19263     // maintenance. Please consider adding new tests in subclasses of CSTest instead.
19264 }
19265