• 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.app.ActivityManager.UidFrozenStateChangedCallback.UID_FROZEN_STATE_FROZEN;
34 import static android.app.ActivityManager.UidFrozenStateChangedCallback.UID_FROZEN_STATE_UNFROZEN;
35 import static android.app.PendingIntent.FLAG_IMMUTABLE;
36 import static android.content.Intent.ACTION_PACKAGE_ADDED;
37 import static android.content.Intent.ACTION_PACKAGE_REMOVED;
38 import static android.content.Intent.ACTION_PACKAGE_REPLACED;
39 import static android.content.Intent.ACTION_USER_ADDED;
40 import static android.content.Intent.ACTION_USER_REMOVED;
41 import static android.content.pm.PackageInfo.REQUESTED_PERMISSION_GRANTED;
42 import static android.content.pm.PackageManager.FEATURE_ETHERNET;
43 import static android.content.pm.PackageManager.FEATURE_WIFI;
44 import static android.content.pm.PackageManager.FEATURE_WIFI_DIRECT;
45 import static android.content.pm.PackageManager.GET_PERMISSIONS;
46 import static android.content.pm.PackageManager.PERMISSION_DENIED;
47 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
48 import static android.net.ConnectivityManager.ACTION_CAPTIVE_PORTAL_SIGN_IN;
49 import static android.net.ConnectivityManager.BLOCKED_METERED_REASON_DATA_SAVER;
50 import static android.net.ConnectivityManager.BLOCKED_METERED_REASON_MASK;
51 import static android.net.ConnectivityManager.BLOCKED_METERED_REASON_USER_RESTRICTED;
52 import static android.net.ConnectivityManager.BLOCKED_REASON_BATTERY_SAVER;
53 import static android.net.ConnectivityManager.BLOCKED_REASON_NONE;
54 import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
55 import static android.net.ConnectivityManager.EXTRA_NETWORK_INFO;
56 import static android.net.ConnectivityManager.EXTRA_NETWORK_TYPE;
57 import static android.net.ConnectivityManager.FIREWALL_CHAIN_DOZABLE;
58 import static android.net.ConnectivityManager.FIREWALL_CHAIN_LOW_POWER_STANDBY;
59 import static android.net.ConnectivityManager.FIREWALL_CHAIN_OEM_DENY_1;
60 import static android.net.ConnectivityManager.FIREWALL_CHAIN_OEM_DENY_2;
61 import static android.net.ConnectivityManager.FIREWALL_CHAIN_OEM_DENY_3;
62 import static android.net.ConnectivityManager.FIREWALL_CHAIN_POWERSAVE;
63 import static android.net.ConnectivityManager.FIREWALL_CHAIN_RESTRICTED;
64 import static android.net.ConnectivityManager.FIREWALL_CHAIN_STANDBY;
65 import static android.net.ConnectivityManager.FIREWALL_RULE_ALLOW;
66 import static android.net.ConnectivityManager.FIREWALL_RULE_DEFAULT;
67 import static android.net.ConnectivityManager.FIREWALL_RULE_DENY;
68 import static android.net.ConnectivityManager.PROFILE_NETWORK_PREFERENCE_DEFAULT;
69 import static android.net.ConnectivityManager.PROFILE_NETWORK_PREFERENCE_ENTERPRISE;
70 import static android.net.ConnectivityManager.PROFILE_NETWORK_PREFERENCE_ENTERPRISE_BLOCKING;
71 import static android.net.ConnectivityManager.PROFILE_NETWORK_PREFERENCE_ENTERPRISE_NO_FALLBACK;
72 import static android.net.ConnectivityManager.TYPE_ETHERNET;
73 import static android.net.ConnectivityManager.TYPE_MOBILE;
74 import static android.net.ConnectivityManager.TYPE_MOBILE_FOTA;
75 import static android.net.ConnectivityManager.TYPE_MOBILE_MMS;
76 import static android.net.ConnectivityManager.TYPE_MOBILE_SUPL;
77 import static android.net.ConnectivityManager.TYPE_PROXY;
78 import static android.net.ConnectivityManager.TYPE_VPN;
79 import static android.net.ConnectivityManager.TYPE_WIFI;
80 import static android.net.ConnectivitySettingsManager.PRIVATE_DNS_MODE_OFF;
81 import static android.net.ConnectivitySettingsManager.PRIVATE_DNS_MODE_OPPORTUNISTIC;
82 import static android.net.ConnectivitySettingsManager.PRIVATE_DNS_MODE_PROVIDER_HOSTNAME;
83 import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_DNS;
84 import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_FALLBACK;
85 import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_HTTP;
86 import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_HTTPS;
87 import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_PRIVDNS;
88 import static android.net.INetworkMonitor.NETWORK_VALIDATION_RESULT_PARTIAL;
89 import static android.net.INetworkMonitor.NETWORK_VALIDATION_RESULT_VALID;
90 import static android.net.NetworkCapabilities.NET_CAPABILITY_BIP;
91 import static android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL;
92 import static android.net.NetworkCapabilities.NET_CAPABILITY_CBS;
93 import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN;
94 import static android.net.NetworkCapabilities.NET_CAPABILITY_EIMS;
95 import static android.net.NetworkCapabilities.NET_CAPABILITY_ENTERPRISE;
96 import static android.net.NetworkCapabilities.NET_CAPABILITY_FOREGROUND;
97 import static android.net.NetworkCapabilities.NET_CAPABILITY_FOTA;
98 import static android.net.NetworkCapabilities.NET_CAPABILITY_IA;
99 import static android.net.NetworkCapabilities.NET_CAPABILITY_IMS;
100 import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
101 import static android.net.NetworkCapabilities.NET_CAPABILITY_MMS;
102 import static android.net.NetworkCapabilities.NET_CAPABILITY_MMTEL;
103 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED;
104 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
105 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
106 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING;
107 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED;
108 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED;
109 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN;
110 import static android.net.NetworkCapabilities.NET_CAPABILITY_OEM_PAID;
111 import static android.net.NetworkCapabilities.NET_CAPABILITY_OEM_PRIVATE;
112 import static android.net.NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVITY;
113 import static android.net.NetworkCapabilities.NET_CAPABILITY_RCS;
114 import static android.net.NetworkCapabilities.NET_CAPABILITY_SUPL;
115 import static android.net.NetworkCapabilities.NET_CAPABILITY_TEMPORARILY_NOT_METERED;
116 import static android.net.NetworkCapabilities.NET_CAPABILITY_TRUSTED;
117 import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
118 import static android.net.NetworkCapabilities.NET_CAPABILITY_VSIM;
119 import static android.net.NetworkCapabilities.NET_CAPABILITY_WIFI_P2P;
120 import static android.net.NetworkCapabilities.NET_CAPABILITY_XCAP;
121 import static android.net.NetworkCapabilities.NET_ENTERPRISE_ID_1;
122 import static android.net.NetworkCapabilities.NET_ENTERPRISE_ID_2;
123 import static android.net.NetworkCapabilities.NET_ENTERPRISE_ID_3;
124 import static android.net.NetworkCapabilities.NET_ENTERPRISE_ID_4;
125 import static android.net.NetworkCapabilities.NET_ENTERPRISE_ID_5;
126 import static android.net.NetworkCapabilities.REDACT_FOR_ACCESS_FINE_LOCATION;
127 import static android.net.NetworkCapabilities.REDACT_FOR_LOCAL_MAC_ADDRESS;
128 import static android.net.NetworkCapabilities.REDACT_FOR_NETWORK_SETTINGS;
129 import static android.net.NetworkCapabilities.REDACT_NONE;
130 import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
131 import static android.net.NetworkCapabilities.TRANSPORT_ETHERNET;
132 import static android.net.NetworkCapabilities.TRANSPORT_TEST;
133 import static android.net.NetworkCapabilities.TRANSPORT_VPN;
134 import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
135 import static android.net.NetworkCapabilities.TRANSPORT_WIFI_AWARE;
136 import static android.net.NetworkScore.KEEP_CONNECTED_FOR_HANDOVER;
137 import static android.net.OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PAID;
138 import static android.net.OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK;
139 import static android.net.OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY;
140 import static android.net.OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY;
141 import static android.net.OemNetworkPreferences.OEM_NETWORK_PREFERENCE_TEST;
142 import static android.net.OemNetworkPreferences.OEM_NETWORK_PREFERENCE_TEST_ONLY;
143 import static android.net.OemNetworkPreferences.OEM_NETWORK_PREFERENCE_UNINITIALIZED;
144 import static android.net.Proxy.PROXY_CHANGE_ACTION;
145 import static android.net.RouteInfo.RTN_UNREACHABLE;
146 import static android.net.resolv.aidl.IDnsResolverUnsolicitedEventListener.PREFIX_OPERATION_ADDED;
147 import static android.net.resolv.aidl.IDnsResolverUnsolicitedEventListener.PREFIX_OPERATION_REMOVED;
148 import static android.net.resolv.aidl.IDnsResolverUnsolicitedEventListener.VALIDATION_RESULT_FAILURE;
149 import static android.net.resolv.aidl.IDnsResolverUnsolicitedEventListener.VALIDATION_RESULT_SUCCESS;
150 import static android.os.Process.INVALID_UID;
151 import static android.system.OsConstants.IPPROTO_TCP;
152 
153 import static com.android.server.ConnectivityService.KEY_DESTROY_FROZEN_SOCKETS_VERSION;
154 import static com.android.server.ConnectivityService.MAX_NETWORK_REQUESTS_PER_SYSTEM_UID;
155 import static com.android.server.ConnectivityService.PREFERENCE_ORDER_MOBILE_DATA_PREFERERRED;
156 import static com.android.server.ConnectivityService.PREFERENCE_ORDER_OEM;
157 import static com.android.server.ConnectivityService.PREFERENCE_ORDER_PROFILE;
158 import static com.android.server.ConnectivityService.PREFERENCE_ORDER_VPN;
159 import static com.android.server.ConnectivityService.createDeliveryGroupKeyForConnectivityAction;
160 import static com.android.server.ConnectivityService.makeNflogPrefix;
161 import static com.android.server.ConnectivityServiceTestUtils.transportToLegacyType;
162 import static com.android.server.NetworkAgentWrapper.CallbackType.OnQosCallbackRegister;
163 import static com.android.server.NetworkAgentWrapper.CallbackType.OnQosCallbackUnregister;
164 import static com.android.testutils.ConcurrentUtils.await;
165 import static com.android.testutils.ConcurrentUtils.durationOf;
166 import static com.android.testutils.DevSdkIgnoreRule.IgnoreAfter;
167 import static com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
168 import static com.android.testutils.DevSdkIgnoreRuleKt.SC_V2;
169 import static com.android.testutils.FunctionalUtils.ignoreExceptions;
170 import static com.android.testutils.HandlerUtils.visibleOnHandlerThread;
171 import static com.android.testutils.HandlerUtils.waitForIdleSerialExecutor;
172 import static com.android.testutils.MiscAsserts.assertContainsAll;
173 import static com.android.testutils.MiscAsserts.assertContainsExactly;
174 import static com.android.testutils.MiscAsserts.assertEmpty;
175 import static com.android.testutils.MiscAsserts.assertLength;
176 import static com.android.testutils.MiscAsserts.assertRunsInAtMost;
177 import static com.android.testutils.MiscAsserts.assertSameElements;
178 import static com.android.testutils.MiscAsserts.assertThrows;
179 import static com.android.testutils.RecorderCallback.CallbackEntry.AVAILABLE;
180 import static com.android.testutils.RecorderCallback.CallbackEntry.BLOCKED_STATUS;
181 import static com.android.testutils.RecorderCallback.CallbackEntry.BLOCKED_STATUS_INT;
182 import static com.android.testutils.RecorderCallback.CallbackEntry.LINK_PROPERTIES_CHANGED;
183 import static com.android.testutils.RecorderCallback.CallbackEntry.LOSING;
184 import static com.android.testutils.RecorderCallback.CallbackEntry.LOST;
185 import static com.android.testutils.RecorderCallback.CallbackEntry.NETWORK_CAPS_UPDATED;
186 import static com.android.testutils.RecorderCallback.CallbackEntry.RESUMED;
187 import static com.android.testutils.RecorderCallback.CallbackEntry.SUSPENDED;
188 import static com.android.testutils.RecorderCallback.CallbackEntry.UNAVAILABLE;
189 import static com.android.testutils.TestPermissionUtil.runAsShell;
190 
191 import static org.hamcrest.MatcherAssert.assertThat;
192 import static org.hamcrest.Matchers.containsString;
193 import static org.junit.Assert.assertEquals;
194 import static org.junit.Assert.assertFalse;
195 import static org.junit.Assert.assertNotEquals;
196 import static org.junit.Assert.assertNotNull;
197 import static org.junit.Assert.assertNull;
198 import static org.junit.Assert.assertTrue;
199 import static org.junit.Assert.fail;
200 import static org.junit.Assume.assumeFalse;
201 import static org.junit.Assume.assumeTrue;
202 import static org.mockito.AdditionalMatchers.aryEq;
203 import static org.mockito.ArgumentMatchers.anyBoolean;
204 import static org.mockito.ArgumentMatchers.anyLong;
205 import static org.mockito.ArgumentMatchers.anyString;
206 import static org.mockito.ArgumentMatchers.argThat;
207 import static org.mockito.ArgumentMatchers.eq;
208 import static org.mockito.ArgumentMatchers.isNull;
209 import static org.mockito.Matchers.anyInt;
210 import static org.mockito.Mockito.any;
211 import static org.mockito.Mockito.atLeastOnce;
212 import static org.mockito.Mockito.doAnswer;
213 import static org.mockito.Mockito.doNothing;
214 import static org.mockito.Mockito.doReturn;
215 import static org.mockito.Mockito.doThrow;
216 import static org.mockito.Mockito.inOrder;
217 import static org.mockito.Mockito.mock;
218 import static org.mockito.Mockito.never;
219 import static org.mockito.Mockito.reset;
220 import static org.mockito.Mockito.spy;
221 import static org.mockito.Mockito.timeout;
222 import static org.mockito.Mockito.times;
223 import static org.mockito.Mockito.verify;
224 import static org.mockito.Mockito.verifyNoMoreInteractions;
225 
226 import static java.util.Arrays.asList;
227 
228 import android.Manifest;
229 import android.annotation.NonNull;
230 import android.annotation.Nullable;
231 import android.app.ActivityManager;
232 import android.app.ActivityManager.UidFrozenStateChangedCallback;
233 import android.app.AlarmManager;
234 import android.app.AppOpsManager;
235 import android.app.BroadcastOptions;
236 import android.app.NotificationManager;
237 import android.app.PendingIntent;
238 import android.app.admin.DevicePolicyManager;
239 import android.app.usage.NetworkStatsManager;
240 import android.compat.testing.PlatformCompatChangeRule;
241 import android.content.BroadcastReceiver;
242 import android.content.ComponentName;
243 import android.content.ContentProvider;
244 import android.content.ContentResolver;
245 import android.content.Context;
246 import android.content.Intent;
247 import android.content.IntentFilter;
248 import android.content.pm.ApplicationInfo;
249 import android.content.pm.PackageInfo;
250 import android.content.pm.PackageManager;
251 import android.content.pm.ResolveInfo;
252 import android.content.pm.ServiceInfo;
253 import android.content.pm.UserInfo;
254 import android.content.res.Resources;
255 import android.location.LocationManager;
256 import android.net.CaptivePortal;
257 import android.net.CaptivePortalData;
258 import android.net.ConnectionInfo;
259 import android.net.ConnectivityDiagnosticsManager.DataStallReport;
260 import android.net.ConnectivityManager;
261 import android.net.ConnectivityManager.NetworkCallback;
262 import android.net.ConnectivityManager.PacketKeepalive;
263 import android.net.ConnectivityManager.PacketKeepaliveCallback;
264 import android.net.ConnectivityManager.TooManyRequestsException;
265 import android.net.ConnectivitySettingsManager;
266 import android.net.ConnectivityThread;
267 import android.net.DataStallReportParcelable;
268 import android.net.EthernetManager;
269 import android.net.EthernetNetworkSpecifier;
270 import android.net.IConnectivityDiagnosticsCallback;
271 import android.net.IDnsResolver;
272 import android.net.INetd;
273 import android.net.INetworkMonitor;
274 import android.net.INetworkMonitorCallbacks;
275 import android.net.IOnCompleteListener;
276 import android.net.IQosCallback;
277 import android.net.InetAddresses;
278 import android.net.InterfaceConfigurationParcel;
279 import android.net.IpPrefix;
280 import android.net.IpSecManager;
281 import android.net.IpSecManager.UdpEncapsulationSocket;
282 import android.net.LinkAddress;
283 import android.net.LinkProperties;
284 import android.net.MatchAllNetworkSpecifier;
285 import android.net.NativeNetworkConfig;
286 import android.net.NativeNetworkType;
287 import android.net.Network;
288 import android.net.NetworkAgent;
289 import android.net.NetworkAgentConfig;
290 import android.net.NetworkCapabilities;
291 import android.net.NetworkFactory;
292 import android.net.NetworkInfo;
293 import android.net.NetworkInfo.DetailedState;
294 import android.net.NetworkPolicyManager;
295 import android.net.NetworkPolicyManager.NetworkPolicyCallback;
296 import android.net.NetworkProvider;
297 import android.net.NetworkRequest;
298 import android.net.NetworkScore;
299 import android.net.NetworkSpecifier;
300 import android.net.NetworkStack;
301 import android.net.NetworkStateSnapshot;
302 import android.net.NetworkTestResultParcelable;
303 import android.net.OemNetworkPreferences;
304 import android.net.PacProxyManager;
305 import android.net.ProfileNetworkPreference;
306 import android.net.Proxy;
307 import android.net.ProxyInfo;
308 import android.net.QosCallbackException;
309 import android.net.QosFilter;
310 import android.net.QosSession;
311 import android.net.ResolverParamsParcel;
312 import android.net.RouteInfo;
313 import android.net.RouteInfoParcel;
314 import android.net.SocketKeepalive;
315 import android.net.TelephonyNetworkSpecifier;
316 import android.net.TetheringManager;
317 import android.net.TransportInfo;
318 import android.net.UidRange;
319 import android.net.UidRangeParcel;
320 import android.net.UnderlyingNetworkInfo;
321 import android.net.Uri;
322 import android.net.VpnManager;
323 import android.net.VpnTransportInfo;
324 import android.net.connectivity.ConnectivityCompatChanges;
325 import android.net.metrics.IpConnectivityLog;
326 import android.net.netd.aidl.NativeUidRangeConfig;
327 import android.net.networkstack.NetworkStackClientBase;
328 import android.net.resolv.aidl.Nat64PrefixEventParcel;
329 import android.net.resolv.aidl.PrivateDnsValidationEventParcel;
330 import android.net.shared.PrivateDnsConfig;
331 import android.net.wifi.WifiInfo;
332 import android.os.BadParcelableException;
333 import android.os.BatteryStatsManager;
334 import android.os.Binder;
335 import android.os.Build;
336 import android.os.Bundle;
337 import android.os.ConditionVariable;
338 import android.os.Handler;
339 import android.os.HandlerThread;
340 import android.os.IBinder;
341 import android.os.INetworkManagementService;
342 import android.os.Looper;
343 import android.os.Messenger;
344 import android.os.Parcel;
345 import android.os.ParcelFileDescriptor;
346 import android.os.Parcelable;
347 import android.os.PersistableBundle;
348 import android.os.Process;
349 import android.os.RemoteException;
350 import android.os.ServiceSpecificException;
351 import android.os.SystemClock;
352 import android.os.SystemConfigManager;
353 import android.os.UserHandle;
354 import android.os.UserManager;
355 import android.provider.Settings;
356 import android.security.Credentials;
357 import android.system.Os;
358 import android.telephony.SubscriptionManager;
359 import android.telephony.TelephonyManager;
360 import android.telephony.data.EpsBearerQosSessionAttributes;
361 import android.telephony.data.NrQosSessionAttributes;
362 import android.test.mock.MockContentResolver;
363 import android.text.TextUtils;
364 import android.util.ArraySet;
365 import android.util.Log;
366 import android.util.Pair;
367 import android.util.Range;
368 import android.util.SparseArray;
369 
370 import androidx.test.InstrumentationRegistry;
371 import androidx.test.filters.SmallTest;
372 
373 import com.android.connectivity.resources.R;
374 import com.android.internal.annotations.GuardedBy;
375 import com.android.internal.app.IBatteryStats;
376 import com.android.internal.net.VpnConfig;
377 import com.android.internal.net.VpnProfile;
378 import com.android.internal.util.WakeupMessage;
379 import com.android.internal.util.test.BroadcastInterceptingContext;
380 import com.android.internal.util.test.FakeSettingsProvider;
381 import com.android.net.module.util.ArrayTrackRecord;
382 import com.android.net.module.util.CollectionUtils;
383 import com.android.net.module.util.LocationPermissionChecker;
384 import com.android.net.module.util.NetworkMonitorUtils;
385 import com.android.networkstack.apishim.ConstantsShim;
386 import com.android.networkstack.apishim.NetworkAgentConfigShimImpl;
387 import com.android.networkstack.apishim.common.BroadcastOptionsShim;
388 import com.android.networkstack.apishim.common.UnsupportedApiLevelException;
389 import com.android.server.ConnectivityService.ConnectivityDiagnosticsCallbackInfo;
390 import com.android.server.ConnectivityService.NetworkRequestInfo;
391 import com.android.server.ConnectivityServiceTest.ConnectivityServiceDependencies.DestroySocketsWrapper;
392 import com.android.server.ConnectivityServiceTest.ConnectivityServiceDependencies.ReportedInterfaces;
393 import com.android.server.connectivity.ApplicationSelfCertifiedNetworkCapabilities;
394 import com.android.server.connectivity.AutomaticOnOffKeepaliveTracker;
395 import com.android.server.connectivity.CarrierPrivilegeAuthenticator;
396 import com.android.server.connectivity.ClatCoordinator;
397 import com.android.server.connectivity.ConnectivityFlags;
398 import com.android.server.connectivity.ConnectivityResources;
399 import com.android.server.connectivity.MultinetworkPolicyTracker;
400 import com.android.server.connectivity.MultinetworkPolicyTrackerTestDependencies;
401 import com.android.server.connectivity.Nat464Xlat;
402 import com.android.server.connectivity.NetworkAgentInfo;
403 import com.android.server.connectivity.NetworkNotificationManager;
404 import com.android.server.connectivity.NetworkNotificationManager.NotificationType;
405 import com.android.server.connectivity.ProxyTracker;
406 import com.android.server.connectivity.QosCallbackTracker;
407 import com.android.server.connectivity.UidRangeUtils;
408 import com.android.server.connectivity.Vpn;
409 import com.android.server.connectivity.VpnProfileStore;
410 import com.android.server.net.LockdownVpnTracker;
411 import com.android.server.net.NetworkPinner;
412 import com.android.testutils.DevSdkIgnoreRule;
413 import com.android.testutils.DevSdkIgnoreRunner;
414 import com.android.testutils.FunctionalUtils.Function3;
415 import com.android.testutils.FunctionalUtils.ThrowingConsumer;
416 import com.android.testutils.FunctionalUtils.ThrowingRunnable;
417 import com.android.testutils.HandlerUtils;
418 import com.android.testutils.RecorderCallback.CallbackEntry;
419 import com.android.testutils.TestableNetworkCallback;
420 import com.android.testutils.TestableNetworkOfferCallback;
421 
422 import libcore.junit.util.compat.CoreCompatChangeRule.DisableCompatChanges;
423 import libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges;
424 
425 import org.junit.After;
426 import org.junit.Assert;
427 import org.junit.Before;
428 import org.junit.Ignore;
429 import org.junit.Rule;
430 import org.junit.Test;
431 import org.junit.runner.RunWith;
432 import org.mockito.AdditionalAnswers;
433 import org.mockito.ArgumentCaptor;
434 import org.mockito.InOrder;
435 import org.mockito.Mock;
436 import org.mockito.MockitoAnnotations;
437 import org.mockito.Spy;
438 import org.mockito.stubbing.Answer;
439 
440 import java.io.FileDescriptor;
441 import java.io.IOException;
442 import java.io.PrintWriter;
443 import java.io.StringWriter;
444 import java.net.DatagramSocket;
445 import java.net.Inet4Address;
446 import java.net.Inet6Address;
447 import java.net.InetAddress;
448 import java.net.InetSocketAddress;
449 import java.net.Socket;
450 import java.nio.charset.StandardCharsets;
451 import java.util.ArrayList;
452 import java.util.Arrays;
453 import java.util.Collection;
454 import java.util.Collections;
455 import java.util.Comparator;
456 import java.util.HashMap;
457 import java.util.HashSet;
458 import java.util.List;
459 import java.util.Map;
460 import java.util.Objects;
461 import java.util.Set;
462 import java.util.concurrent.CompletableFuture;
463 import java.util.concurrent.CountDownLatch;
464 import java.util.concurrent.Executor;
465 import java.util.concurrent.ExecutorService;
466 import java.util.concurrent.Executors;
467 import java.util.concurrent.LinkedBlockingQueue;
468 import java.util.concurrent.TimeUnit;
469 import java.util.concurrent.TimeoutException;
470 import java.util.concurrent.atomic.AtomicBoolean;
471 import java.util.concurrent.atomic.AtomicReference;
472 import java.util.function.Consumer;
473 import java.util.function.Predicate;
474 import java.util.function.Supplier;
475 import java.util.regex.Matcher;
476 import java.util.regex.Pattern;
477 import java.util.stream.Collectors;
478 
479 /**
480  * Tests for {@link ConnectivityService}.
481  *
482  * Build, install and run with:
483  *  runtest frameworks-net -c com.android.server.ConnectivityServiceTest
484  */
485 @RunWith(DevSdkIgnoreRunner.class)
486 @SmallTest
487 @DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
488 public class ConnectivityServiceTest {
489     private static final String TAG = "ConnectivityServiceTest";
490 
491     @Rule
492     public final DevSdkIgnoreRule ignoreRule = new DevSdkIgnoreRule();
493 
494     @Rule
495     public final PlatformCompatChangeRule compatChangeRule = new PlatformCompatChangeRule();
496 
497     private static final int TIMEOUT_MS = 2_000;
498     // Broadcasts can take a long time to be delivered. The test will not wait for that long unless
499     // there is a failure, so use a long timeout.
500     private static final int BROADCAST_TIMEOUT_MS = 30_000;
501     private static final int TEST_LINGER_DELAY_MS = 400;
502     private static final int TEST_NASCENT_DELAY_MS = 300;
503     // Chosen to be less than the linger and nascent timeout. This ensures that we can distinguish
504     // between a LOST callback that arrives immediately and a LOST callback that arrives after
505     // the linger/nascent timeout. For this, our assertions should run fast enough to leave
506     // less than (mService.mLingerDelayMs - TEST_CALLBACK_TIMEOUT_MS) between the time callbacks are
507     // supposedly fired, and the time we call expectCallback.
508     private static final int TEST_CALLBACK_TIMEOUT_MS = 250;
509     // Chosen to be less than TEST_CALLBACK_TIMEOUT_MS. This ensures that requests have time to
510     // complete before callbacks are verified.
511     private static final int TEST_REQUEST_TIMEOUT_MS = 150;
512 
513     private static final int UNREASONABLY_LONG_ALARM_WAIT_MS = 2_000;
514 
515     private static final long TIMESTAMP = 1234L;
516 
517     private static final int NET_ID = 110;
518     private static final int OEM_PREF_ANY_NET_ID = -1;
519     // Set a non-zero value to verify the flow to set tcp init rwnd value.
520     private static final int TEST_TCP_INIT_RWND = 60;
521 
522     // Used for testing the per-work-profile default network.
523     private static final int TEST_APP_ID = 103;
524     private static final int TEST_WORK_PROFILE_USER_ID = 2;
525     private static final int TEST_WORK_PROFILE_APP_UID =
526             UserHandle.getUid(TEST_WORK_PROFILE_USER_ID, TEST_APP_ID);
527     private static final int TEST_APP_ID_2 = 104;
528     private static final int TEST_WORK_PROFILE_APP_UID_2 =
529             UserHandle.getUid(TEST_WORK_PROFILE_USER_ID, TEST_APP_ID_2);
530     private static final int TEST_APP_ID_3 = 105;
531     private static final int TEST_APP_ID_4 = 106;
532     private static final int TEST_APP_ID_5 = 107;
533 
534     private static final String CLAT_PREFIX = "v4-";
535     private static final String MOBILE_IFNAME = "test_rmnet_data0";
536     private static final String CLAT_MOBILE_IFNAME = CLAT_PREFIX + MOBILE_IFNAME;
537     private static final String WIFI_IFNAME = "test_wlan0";
538     private static final String WIFI_WOL_IFNAME = "test_wlan_wol";
539     private static final String VPN_IFNAME = "tun10042";
540     private static final String TEST_PACKAGE_NAME = "com.android.test.package";
541     private static final int TEST_PACKAGE_UID = 123;
542     private static final int TEST_PACKAGE_UID2 = 321;
543     private static final int TEST_PACKAGE_UID3 = 456;
544 
545     private static final int PACKET_WAKEUP_MARK_MASK = 0x80000000;
546 
547     private static final String ALWAYS_ON_PACKAGE = "com.android.test.alwaysonvpn";
548 
549     private static final String INTERFACE_NAME = "interface";
550 
551     private static final String TEST_VENUE_URL_NA_PASSPOINT = "https://android.com/";
552     private static final String TEST_VENUE_URL_NA_OTHER = "https://example.com/";
553     private static final String TEST_TERMS_AND_CONDITIONS_URL_NA_PASSPOINT =
554             "https://android.com/terms/";
555     private static final String TEST_TERMS_AND_CONDITIONS_URL_NA_OTHER =
556             "https://example.com/terms/";
557     private static final String TEST_VENUE_URL_CAPPORT = "https://android.com/capport/";
558     private static final String TEST_USER_PORTAL_API_URL_CAPPORT =
559             "https://android.com/user/api/capport/";
560     private static final String TEST_FRIENDLY_NAME = "Network friendly name";
561     private static final String TEST_REDIRECT_URL = "http://example.com/firstPath";
562 
563     private MockContext mServiceContext;
564     private HandlerThread mCsHandlerThread;
565     private ConnectivityServiceDependencies mDeps;
566     private AutomaticOnOffKeepaliveTrackerDependencies mAutoOnOffKeepaliveDependencies;
567     private ConnectivityService mService;
568     private WrappedConnectivityManager mCm;
569     private TestNetworkAgentWrapper mWiFiAgent;
570     private TestNetworkAgentWrapper mCellAgent;
571     private TestNetworkAgentWrapper mEthernetAgent;
572     private MockVpn mMockVpn;
573     private Context mContext;
574     private NetworkPolicyCallback mPolicyCallback;
575     private WrappedMultinetworkPolicyTracker mPolicyTracker;
576     private ProxyTracker mProxyTracker;
577     private HandlerThread mAlarmManagerThread;
578     private TestNetIdManager mNetIdManager;
579     private QosCallbackMockHelper mQosCallbackMockHelper;
580     private QosCallbackTracker mQosCallbackTracker;
581     private TestNetworkCallback mDefaultNetworkCallback;
582     private TestNetworkCallback mSystemDefaultNetworkCallback;
583     private TestNetworkCallback mProfileDefaultNetworkCallback;
584     private TestNetworkCallback mTestPackageDefaultNetworkCallback;
585     private TestNetworkCallback mProfileDefaultNetworkCallbackAsAppUid2;
586     private TestNetworkCallback mTestPackageDefaultNetworkCallback2;
587 
588     // State variables required to emulate NetworkPolicyManagerService behaviour.
589     private int mBlockedReasons = BLOCKED_REASON_NONE;
590 
591     @Mock DeviceIdleInternal mDeviceIdleInternal;
592     @Mock INetworkManagementService mNetworkManagementService;
593     @Mock NetworkStatsManager mStatsManager;
594     @Mock IDnsResolver mMockDnsResolver;
595     @Mock INetd mMockNetd;
596     @Mock NetworkStackClientBase mNetworkStack;
597     @Mock PackageManager mPackageManager;
598     @Mock UserManager mUserManager;
599     @Mock NotificationManager mNotificationManager;
600     @Mock AlarmManager mAlarmManager;
601     @Mock IConnectivityDiagnosticsCallback mConnectivityDiagnosticsCallback;
602     @Mock IBinder mIBinder;
603     @Mock LocationManager mLocationManager;
604     @Mock AppOpsManager mAppOpsManager;
605     @Mock TelephonyManager mTelephonyManager;
606     @Mock EthernetManager mEthernetManager;
607     @Mock NetworkPolicyManager mNetworkPolicyManager;
608     @Mock VpnProfileStore mVpnProfileStore;
609     @Mock SystemConfigManager mSystemConfigManager;
610     @Mock DevicePolicyManager mDevicePolicyManager;
611     @Mock Resources mResources;
612     @Mock ClatCoordinator mClatCoordinator;
613     @Mock PacProxyManager mPacProxyManager;
614     @Mock BpfNetMaps mBpfNetMaps;
615     @Mock CarrierPrivilegeAuthenticator mCarrierPrivilegeAuthenticator;
616     @Mock TetheringManager mTetheringManager;
617     @Mock BroadcastOptionsShim mBroadcastOptionsShim;
618     @Mock ActivityManager mActivityManager;
619     @Mock DestroySocketsWrapper mDestroySocketsWrapper;
620     @Mock SubscriptionManager mSubscriptionManager;
621 
622     // BatteryStatsManager is final and cannot be mocked with regular mockito, so just mock the
623     // underlying binder calls.
624     final BatteryStatsManager mBatteryStatsManager =
625             new BatteryStatsManager(mock(IBatteryStats.class));
626 
627     private ArgumentCaptor<ResolverParamsParcel> mResolverParamsParcelCaptor =
628             ArgumentCaptor.forClass(ResolverParamsParcel.class);
629 
630     // This class exists to test bindProcessToNetwork and getBoundNetworkForProcess. These methods
631     // do not go through ConnectivityService but talk to netd directly, so they don't automatically
632     // reflect the state of our test ConnectivityService.
633     private class WrappedConnectivityManager extends ConnectivityManager {
634         private Network mFakeBoundNetwork;
635 
bindProcessToNetwork(Network network)636         public synchronized boolean bindProcessToNetwork(Network network) {
637             mFakeBoundNetwork = network;
638             return true;
639         }
640 
getBoundNetworkForProcess()641         public synchronized Network getBoundNetworkForProcess() {
642             return mFakeBoundNetwork;
643         }
644 
WrappedConnectivityManager(Context context, ConnectivityService service)645         public WrappedConnectivityManager(Context context, ConnectivityService service) {
646             super(context, service);
647         }
648     }
649 
650     private class MockContext extends BroadcastInterceptingContext {
651         private final MockContentResolver mContentResolver;
652 
653         @Spy private Resources mInternalResources;
654         private final LinkedBlockingQueue<Intent> mStartedActivities = new LinkedBlockingQueue<>();
655 
656         // Map of permission name -> PermissionManager.Permission_{GRANTED|DENIED} constant
657         // For permissions granted across the board, the key is only the permission name.
658         // For permissions only granted to a combination of uid/pid, the key
659         // is "<permission name>,<pid>,<uid>". PID+UID permissons have priority over generic ones.
660         private final HashMap<String, Integer> mMockedPermissions = new HashMap<>();
661 
mockStringResource(int resId)662         private void mockStringResource(int resId) {
663             doAnswer((inv) -> {
664                 return "Mock string resource ID=" + inv.getArgument(0);
665             }).when(mInternalResources).getString(resId);
666         }
667 
MockContext(Context base, ContentProvider settingsProvider)668         MockContext(Context base, ContentProvider settingsProvider) {
669             super(base);
670 
671             mInternalResources = spy(base.getResources());
672             doReturn(new String[] {
673                     "wifi,1,1,1,-1,true",
674                     "mobile,0,0,0,-1,true",
675                     "mobile_mms,2,0,2,60000,true",
676                     "mobile_supl,3,0,2,60000,true",
677             }).when(mInternalResources)
678                     .getStringArray(com.android.internal.R.array.networkAttributes);
679 
680             final int[] stringResourcesToMock = new int[] {
681                 com.android.internal.R.string.config_customVpnAlwaysOnDisconnectedDialogComponent,
682                 com.android.internal.R.string.vpn_lockdown_config,
683                 com.android.internal.R.string.vpn_lockdown_connected,
684                 com.android.internal.R.string.vpn_lockdown_connecting,
685                 com.android.internal.R.string.vpn_lockdown_disconnected,
686                 com.android.internal.R.string.vpn_lockdown_error,
687             };
688             for (int resId : stringResourcesToMock) {
689                 mockStringResource(resId);
690             }
691 
692             mContentResolver = new MockContentResolver();
693             mContentResolver.addProvider(Settings.AUTHORITY, settingsProvider);
694         }
695 
696         @Override
startActivityAsUser(Intent intent, UserHandle handle)697         public void startActivityAsUser(Intent intent, UserHandle handle) {
698             mStartedActivities.offer(intent);
699         }
700 
expectStartActivityIntent(int timeoutMs)701         public Intent expectStartActivityIntent(int timeoutMs) {
702             Intent intent = null;
703             try {
704                 intent = mStartedActivities.poll(timeoutMs, TimeUnit.MILLISECONDS);
705             } catch (InterruptedException e) {}
706             assertNotNull("Did not receive sign-in intent after " + timeoutMs + "ms", intent);
707             return intent;
708         }
709 
expectNoStartActivityIntent(int timeoutMs)710         public void expectNoStartActivityIntent(int timeoutMs) {
711             try {
712                 assertNull("Received unexpected Intent to start activity",
713                         mStartedActivities.poll(timeoutMs, TimeUnit.MILLISECONDS));
714             } catch (InterruptedException e) {}
715         }
716 
717         @Override
startService(Intent service)718         public ComponentName startService(Intent service) {
719             final String action = service.getAction();
720             if (!VpnConfig.SERVICE_INTERFACE.equals(action)
721                     && !ConstantsShim.ACTION_VPN_MANAGER_EVENT.equals(action)) {
722                 fail("Attempt to start unknown service, action=" + action);
723             }
724             return new ComponentName(service.getPackage(), "com.android.test.Service");
725         }
726 
727         @Override
getSystemService(String name)728         public Object getSystemService(String name) {
729             if (Context.CONNECTIVITY_SERVICE.equals(name)) return mCm;
730             if (Context.NOTIFICATION_SERVICE.equals(name)) return mNotificationManager;
731             if (Context.USER_SERVICE.equals(name)) return mUserManager;
732             if (Context.ALARM_SERVICE.equals(name)) return mAlarmManager;
733             if (Context.LOCATION_SERVICE.equals(name)) return mLocationManager;
734             if (Context.APP_OPS_SERVICE.equals(name)) return mAppOpsManager;
735             if (Context.TELEPHONY_SERVICE.equals(name)) return mTelephonyManager;
736             if (Context.ETHERNET_SERVICE.equals(name)) return mEthernetManager;
737             if (Context.NETWORK_POLICY_SERVICE.equals(name)) return mNetworkPolicyManager;
738             if (Context.DEVICE_POLICY_SERVICE.equals(name)) return mDevicePolicyManager;
739             if (Context.SYSTEM_CONFIG_SERVICE.equals(name)) return mSystemConfigManager;
740             if (Context.NETWORK_STATS_SERVICE.equals(name)) return mStatsManager;
741             if (Context.BATTERY_STATS_SERVICE.equals(name)) return mBatteryStatsManager;
742             if (Context.PAC_PROXY_SERVICE.equals(name)) return mPacProxyManager;
743             if (Context.TETHERING_SERVICE.equals(name)) return mTetheringManager;
744             if (Context.ACTIVITY_SERVICE.equals(name)) return mActivityManager;
745             if (Context.TELEPHONY_SUBSCRIPTION_SERVICE.equals(name)) return mSubscriptionManager;
746             return super.getSystemService(name);
747         }
748 
749         final HashMap<UserHandle, UserManager> mUserManagers = new HashMap<>();
750         @Override
createContextAsUser(UserHandle user, int flags)751         public Context createContextAsUser(UserHandle user, int flags) {
752             final Context asUser = mock(Context.class, AdditionalAnswers.delegatesTo(this));
753             doReturn(user).when(asUser).getUser();
754             doAnswer((inv) -> {
755                 final UserManager um = mUserManagers.computeIfAbsent(user,
756                         u -> mock(UserManager.class, AdditionalAnswers.delegatesTo(mUserManager)));
757                 return um;
758             }).when(asUser).getSystemService(Context.USER_SERVICE);
759             return asUser;
760         }
761 
setWorkProfile(@onNull final UserHandle userHandle, boolean value)762         public void setWorkProfile(@NonNull final UserHandle userHandle, boolean value) {
763             // This relies on all contexts for a given user returning the same UM mock
764             final UserManager umMock = createContextAsUser(userHandle, 0 /* flags */)
765                     .getSystemService(UserManager.class);
766             doReturn(value).when(umMock).isManagedProfile();
767             doReturn(value).when(mUserManager).isManagedProfile(eq(userHandle.getIdentifier()));
768         }
769 
setDeviceOwner(@onNull final UserHandle userHandle, String value)770         public void setDeviceOwner(@NonNull final UserHandle userHandle, String value) {
771             // This relies on all contexts for a given user returning the same UM mock
772             final DevicePolicyManager dpmMock = createContextAsUser(userHandle, 0 /* flags */)
773                     .getSystemService(DevicePolicyManager.class);
774             doReturn(value).when(dpmMock).getDeviceOwner();
775             doReturn(value).when(mDevicePolicyManager).getDeviceOwner();
776         }
777 
778         @Override
getContentResolver()779         public ContentResolver getContentResolver() {
780             return mContentResolver;
781         }
782 
783         @Override
getResources()784         public Resources getResources() {
785             return mInternalResources;
786         }
787 
788         @Override
getPackageManager()789         public PackageManager getPackageManager() {
790             return mPackageManager;
791         }
792 
checkMockedPermission(String permission, int pid, int uid, Function3<String, Integer, Integer, Integer> ifAbsent )793         private int checkMockedPermission(String permission, int pid, int uid,
794                 Function3<String, Integer, Integer, Integer> ifAbsent /* perm, uid, pid -> int */) {
795             final Integer granted = mMockedPermissions.get(permission + "," + pid + "," + uid);
796             if (null != granted) {
797                 return granted;
798             }
799             final Integer allGranted = mMockedPermissions.get(permission);
800             if (null != allGranted) {
801                 return allGranted;
802             }
803             return ifAbsent.apply(permission, pid, uid);
804         }
805 
806         @Override
checkPermission(String permission, int pid, int uid)807         public int checkPermission(String permission, int pid, int uid) {
808             return checkMockedPermission(permission, pid, uid,
809                     (perm, p, u) -> super.checkPermission(perm, p, u));
810         }
811 
812         @Override
checkCallingOrSelfPermission(String permission)813         public int checkCallingOrSelfPermission(String permission) {
814             return checkMockedPermission(permission, Process.myPid(), Process.myUid(),
815                     (perm, p, u) -> super.checkCallingOrSelfPermission(perm));
816         }
817 
818         @Override
enforceCallingOrSelfPermission(String permission, String message)819         public void enforceCallingOrSelfPermission(String permission, String message) {
820             final Integer granted = checkMockedPermission(permission,
821                     Process.myPid(), Process.myUid(),
822                     (perm, p, u) -> {
823                         super.enforceCallingOrSelfPermission(perm, message);
824                         // enforce will crash if the permission is not granted
825                         return PERMISSION_GRANTED;
826                     });
827 
828             if (!granted.equals(PERMISSION_GRANTED)) {
829                 throw new SecurityException("[Test] permission denied: " + permission);
830             }
831         }
832 
833         /**
834          * Mock checks for the specified permission, and have them behave as per {@code granted}.
835          *
836          * This will apply to all calls no matter what the checked UID and PID are.
837          *
838          * <p>Passing null reverts to default behavior, which does a real permission check on the
839          * test package.
840          * @param granted One of {@link PackageManager#PERMISSION_GRANTED} or
841          *                {@link PackageManager#PERMISSION_DENIED}.
842          */
setPermission(String permission, Integer granted)843         public void setPermission(String permission, Integer granted) {
844             mMockedPermissions.put(permission, granted);
845         }
846 
847         /**
848          * Mock checks for the specified permission, and have them behave as per {@code granted}.
849          *
850          * This will only apply to the passed UID and PID.
851          *
852          * <p>Passing null reverts to default behavior, which does a real permission check on the
853          * test package.
854          * @param granted One of {@link PackageManager#PERMISSION_GRANTED} or
855          *                {@link PackageManager#PERMISSION_DENIED}.
856          */
setPermission(String permission, int pid, int uid, Integer granted)857         public void setPermission(String permission, int pid, int uid, Integer granted) {
858             final String key = permission + "," + pid + "," + uid;
859             mMockedPermissions.put(key, granted);
860         }
861 
862         @Override
registerReceiverForAllUsers(@ullable BroadcastReceiver receiver, @NonNull IntentFilter filter, @Nullable String broadcastPermission, @Nullable Handler scheduler)863         public Intent registerReceiverForAllUsers(@Nullable BroadcastReceiver receiver,
864                 @NonNull IntentFilter filter, @Nullable String broadcastPermission,
865                 @Nullable Handler scheduler) {
866             // TODO: ensure MultinetworkPolicyTracker's BroadcastReceiver is tested; just returning
867             // null should not pass the test
868             return null;
869         }
870 
871         @Override
sendStickyBroadcast(Intent intent, Bundle options)872         public void sendStickyBroadcast(Intent intent, Bundle options) {
873             // Verify that delivery group policy APIs were used on U.
874             if (mDeps.isAtLeastU() && CONNECTIVITY_ACTION.equals(intent.getAction())) {
875                 final NetworkInfo ni = intent.getParcelableExtra(EXTRA_NETWORK_INFO,
876                         NetworkInfo.class);
877                 try {
878                     verify(mBroadcastOptionsShim).setDeliveryGroupPolicy(
879                             eq(ConstantsShim.DELIVERY_GROUP_POLICY_MOST_RECENT));
880                     verify(mBroadcastOptionsShim).setDeliveryGroupMatchingKey(
881                             eq(CONNECTIVITY_ACTION),
882                             eq(createDeliveryGroupKeyForConnectivityAction(ni)));
883                     verify(mBroadcastOptionsShim).setDeferralPolicy(
884                             eq(ConstantsShim.DEFERRAL_POLICY_UNTIL_ACTIVE));
885                 } catch (UnsupportedApiLevelException e) {
886                     throw new RuntimeException(e);
887                 }
888             }
889             super.sendStickyBroadcast(intent, options);
890         }
891     }
892 
893     // This was only added in the T SDK, but this test needs to build against the R+S SDKs, too.
toSdkSandboxUid(int appUid)894     private static int toSdkSandboxUid(int appUid) {
895         final int firstSdkSandboxUid = 20000;
896         return appUid + (firstSdkSandboxUid - Process.FIRST_APPLICATION_UID);
897     }
898 
899     // This function assumes the UID range for user 0 ([1, 99999])
uidRangeParcelsExcludingUids(Integer... excludedUids)900     private static UidRangeParcel[] uidRangeParcelsExcludingUids(Integer... excludedUids) {
901         int start = 1;
902         Arrays.sort(excludedUids);
903         List<UidRangeParcel> parcels = new ArrayList<UidRangeParcel>();
904         for (int excludedUid : excludedUids) {
905             if (excludedUid == start) {
906                 start++;
907             } else {
908                 parcels.add(new UidRangeParcel(start, excludedUid - 1));
909                 start = excludedUid + 1;
910             }
911         }
912         if (start <= 99999) {
913             parcels.add(new UidRangeParcel(start, 99999));
914         }
915 
916         return parcels.toArray(new UidRangeParcel[0]);
917     }
918 
waitForIdle()919     private void waitForIdle() {
920         HandlerUtils.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
921         waitForIdle(mCellAgent, TIMEOUT_MS);
922         waitForIdle(mWiFiAgent, TIMEOUT_MS);
923         waitForIdle(mEthernetAgent, TIMEOUT_MS);
924         HandlerUtils.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
925         HandlerUtils.waitForIdle(ConnectivityThread.get(), TIMEOUT_MS);
926     }
927 
waitForIdle(TestNetworkAgentWrapper agent, long timeoutMs)928     private void waitForIdle(TestNetworkAgentWrapper agent, long timeoutMs) {
929         if (agent == null) {
930             return;
931         }
932         agent.waitForIdle(timeoutMs);
933     }
934 
935     @Test
testWaitForIdle()936     public void testWaitForIdle() throws Exception {
937         final int attempts = 50;  // Causes the test to take about 200ms on bullhead-eng.
938 
939         // Tests that waitForIdle returns immediately if the service is already idle.
940         for (int i = 0; i < attempts; i++) {
941             waitForIdle();
942         }
943 
944         // Bring up a network that we can use to send messages to ConnectivityService.
945         ExpectedBroadcast b = expectConnectivityAction(TYPE_WIFI, DetailedState.CONNECTED);
946         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
947         mWiFiAgent.connect(false);
948         b.expectBroadcast();
949         Network n = mWiFiAgent.getNetwork();
950         assertNotNull(n);
951 
952         // Tests that calling waitForIdle waits for messages to be processed.
953         for (int i = 0; i < attempts; i++) {
954             mWiFiAgent.setSignalStrength(i);
955             waitForIdle();
956             assertEquals(i, mCm.getNetworkCapabilities(n).getSignalStrength());
957         }
958     }
959 
960     // This test has an inherent race condition in it, and cannot be enabled for continuous testing
961     // or presubmit tests. It is kept for manual runs and documentation purposes.
962     @Ignore
verifyThatNotWaitingForIdleCausesRaceConditions()963     public void verifyThatNotWaitingForIdleCausesRaceConditions() throws Exception {
964         // Bring up a network that we can use to send messages to ConnectivityService.
965         ExpectedBroadcast b = expectConnectivityAction(TYPE_WIFI, DetailedState.CONNECTED);
966         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
967         mWiFiAgent.connect(false);
968         b.expectBroadcast();
969         Network n = mWiFiAgent.getNetwork();
970         assertNotNull(n);
971 
972         // Ensure that not calling waitForIdle causes a race condition.
973         final int attempts = 50;  // Causes the test to take about 200ms on bullhead-eng.
974         for (int i = 0; i < attempts; i++) {
975             mWiFiAgent.setSignalStrength(i);
976             if (i != mCm.getNetworkCapabilities(n).getSignalStrength()) {
977                 // We hit a race condition, as expected. Pass the test.
978                 return;
979             }
980         }
981 
982         // No race? There is a bug in this test.
983         fail("expected race condition at least once in " + attempts + " attempts");
984     }
985 
986     private class TestNetworkAgentWrapper extends NetworkAgentWrapper {
987         private static final int VALIDATION_RESULT_INVALID = 0;
988 
989         private static final long DATA_STALL_TIMESTAMP = 10L;
990         private static final int DATA_STALL_DETECTION_METHOD = 1;
991 
992         private INetworkMonitor mNetworkMonitor;
993         private INetworkMonitorCallbacks mNmCallbacks;
994         private int mNmValidationResult = VALIDATION_RESULT_INVALID;
995         private int mProbesCompleted;
996         private int mProbesSucceeded;
997         private String mNmValidationRedirectUrl = null;
998         private boolean mNmProvNotificationRequested = false;
999 
1000         private final ConditionVariable mNetworkStatusReceived = new ConditionVariable();
1001         // Contains the redirectUrl from networkStatus(). Before reading, wait for
1002         // mNetworkStatusReceived.
1003         private String mRedirectUrl;
1004 
TestNetworkAgentWrapper(int transport)1005         TestNetworkAgentWrapper(int transport) throws Exception {
1006             this(transport, new LinkProperties(), null /* ncTemplate */, null /* provider */, null);
1007         }
1008 
TestNetworkAgentWrapper(int transport, LinkProperties linkProperties)1009         TestNetworkAgentWrapper(int transport, LinkProperties linkProperties)
1010                 throws Exception {
1011             this(transport, linkProperties, null /* ncTemplate */, null /* provider */, null);
1012         }
1013 
TestNetworkAgentWrapper(int transport, LinkProperties linkProperties, NetworkCapabilities ncTemplate)1014         private TestNetworkAgentWrapper(int transport, LinkProperties linkProperties,
1015                 NetworkCapabilities ncTemplate) throws Exception {
1016             this(transport, linkProperties, ncTemplate, null /* provider */, null);
1017         }
1018 
TestNetworkAgentWrapper(int transport, LinkProperties linkProperties, NetworkCapabilities ncTemplate, NetworkProvider provider)1019         private TestNetworkAgentWrapper(int transport, LinkProperties linkProperties,
1020                 NetworkCapabilities ncTemplate, NetworkProvider provider) throws Exception {
1021             this(transport, linkProperties, ncTemplate, provider /* provider */, null);
1022         }
1023 
TestNetworkAgentWrapper(int transport, NetworkAgentWrapper.Callbacks callbacks)1024         private TestNetworkAgentWrapper(int transport, NetworkAgentWrapper.Callbacks callbacks)
1025                 throws Exception {
1026             this(transport, new LinkProperties(), null /* ncTemplate */, null /* provider */,
1027                     callbacks);
1028         }
1029 
TestNetworkAgentWrapper(int transport, LinkProperties linkProperties, NetworkCapabilities ncTemplate, NetworkProvider provider, NetworkAgentWrapper.Callbacks callbacks)1030         private TestNetworkAgentWrapper(int transport, LinkProperties linkProperties,
1031                 NetworkCapabilities ncTemplate, NetworkProvider provider,
1032                 NetworkAgentWrapper.Callbacks callbacks) throws Exception {
1033             super(transport, linkProperties, ncTemplate, provider, callbacks, mServiceContext);
1034 
1035             // Waits for the NetworkAgent to be registered, which includes the creation of the
1036             // NetworkMonitor.
1037             waitForIdle(TIMEOUT_MS);
1038             HandlerUtils.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
1039             HandlerUtils.waitForIdle(ConnectivityThread.get(), TIMEOUT_MS);
1040         }
1041 
1042         class TestInstrumentedNetworkAgent extends InstrumentedNetworkAgent {
TestInstrumentedNetworkAgent(NetworkAgentWrapper wrapper, LinkProperties lp, NetworkAgentConfig nac, NetworkProvider provider)1043             TestInstrumentedNetworkAgent(NetworkAgentWrapper wrapper, LinkProperties lp,
1044                     NetworkAgentConfig nac, NetworkProvider provider) {
1045                 super(wrapper, lp, nac, provider);
1046             }
1047 
1048             @Override
networkStatus(int status, String redirectUrl)1049             public void networkStatus(int status, String redirectUrl) {
1050                 mRedirectUrl = redirectUrl;
1051                 mNetworkStatusReceived.open();
1052             }
1053 
1054         }
1055 
1056         @Override
makeNetworkAgent(LinkProperties linkProperties, NetworkAgentConfig nac, NetworkProvider provider)1057         protected InstrumentedNetworkAgent makeNetworkAgent(LinkProperties linkProperties,
1058                 NetworkAgentConfig nac, NetworkProvider provider) throws Exception {
1059             mNetworkMonitor = mock(INetworkMonitor.class);
1060 
1061             final Answer validateAnswer = inv -> {
1062                 new Thread(ignoreExceptions(this::onValidationRequested)).start();
1063                 return null;
1064             };
1065 
1066             doAnswer(validateAnswer).when(mNetworkMonitor).notifyNetworkConnected(any(), any());
1067             doAnswer(validateAnswer).when(mNetworkMonitor).notifyNetworkConnectedParcel(any());
1068             doAnswer(validateAnswer).when(mNetworkMonitor).forceReevaluation(anyInt());
1069 
1070             final ArgumentCaptor<Network> nmNetworkCaptor = ArgumentCaptor.forClass(Network.class);
1071             final ArgumentCaptor<INetworkMonitorCallbacks> nmCbCaptor =
1072                     ArgumentCaptor.forClass(INetworkMonitorCallbacks.class);
1073             doNothing().when(mNetworkStack).makeNetworkMonitor(
1074                     nmNetworkCaptor.capture(),
1075                     any() /* name */,
1076                     nmCbCaptor.capture());
1077 
1078             final InstrumentedNetworkAgent na =
1079                     new TestInstrumentedNetworkAgent(this, linkProperties, nac, provider);
1080 
1081             assertEquals(na.getNetwork().netId, nmNetworkCaptor.getValue().netId);
1082             mNmCallbacks = nmCbCaptor.getValue();
1083 
1084             mNmCallbacks.onNetworkMonitorCreated(mNetworkMonitor);
1085 
1086             return na;
1087         }
1088 
onValidationRequested()1089         private void onValidationRequested() throws Exception {
1090             if (mDeps.isAtLeastT()) {
1091                 verify(mNetworkMonitor).notifyNetworkConnectedParcel(any());
1092             } else {
1093                 verify(mNetworkMonitor).notifyNetworkConnected(any(), any());
1094             }
1095             if (mNmProvNotificationRequested
1096                     && ((mNmValidationResult & NETWORK_VALIDATION_RESULT_VALID) != 0)) {
1097                 mNmCallbacks.hideProvisioningNotification();
1098                 mNmProvNotificationRequested = false;
1099             }
1100 
1101             mNmCallbacks.notifyProbeStatusChanged(mProbesCompleted, mProbesSucceeded);
1102             final NetworkTestResultParcelable p = new NetworkTestResultParcelable();
1103             p.result = mNmValidationResult;
1104             p.probesAttempted = mProbesCompleted;
1105             p.probesSucceeded = mProbesSucceeded;
1106             p.redirectUrl = mNmValidationRedirectUrl;
1107             p.timestampMillis = TIMESTAMP;
1108             mNmCallbacks.notifyNetworkTestedWithExtras(p);
1109 
1110             if (mNmValidationRedirectUrl != null) {
1111                 mNmCallbacks.showProvisioningNotification(
1112                         "test_provisioning_notif_action", TEST_PACKAGE_NAME);
1113                 mNmProvNotificationRequested = true;
1114             }
1115         }
1116 
1117         /**
1118          * Connect without adding any internet capability.
1119          */
connectWithoutInternet()1120         public void connectWithoutInternet() {
1121             super.connect();
1122         }
1123 
1124         /**
1125          * Transition this NetworkAgent to CONNECTED state with NET_CAPABILITY_INTERNET.
1126          * @param validated Indicate if network should pretend to be validated.
1127          */
connect(boolean validated)1128         public void connect(boolean validated) {
1129             connect(validated, true, false /* privateDnsProbeSent */);
1130         }
1131 
1132         /**
1133          * Transition this NetworkAgent to CONNECTED state.
1134          *
1135          * @param validated Indicate if network should pretend to be validated.
1136          *                  Note that if this is true, this method will mock the NetworkMonitor
1137          *                  probes to pretend the network is invalid after it validated once,
1138          *                  so that subsequent attempts (with mNetworkMonitor.forceReevaluation)
1139          *                  will fail unless setNetworkValid is called again manually.
1140          * @param hasInternet Indicate if network should pretend to have NET_CAPABILITY_INTERNET.
1141          * @param privateDnsProbeSent whether the private DNS probe should be considered to have
1142          *                            been sent, assuming |validated| is true.
1143          *                            If |validated| is false, |privateDnsProbeSent| is not used.
1144          *                            If |validated| is true and |privateDnsProbeSent| is false,
1145          *                            the probe has not been sent.
1146          *                            If |validated| is true and |privateDnsProbeSent| is true,
1147          *                            the probe has been sent and has succeeded. When the NM probes
1148          *                            are mocked to be invalid, private DNS is the reason this
1149          *                            network is invalid ; see @param |validated|.
1150          */
connect(boolean validated, boolean hasInternet, boolean privateDnsProbeSent)1151         public void connect(boolean validated, boolean hasInternet,
1152                 boolean privateDnsProbeSent) {
1153             final ConditionVariable validatedCv = new ConditionVariable();
1154             final ConditionVariable capsChangedCv = new ConditionVariable();
1155             final NetworkRequest request = new NetworkRequest.Builder()
1156                     .addTransportType(getNetworkCapabilities().getTransportTypes()[0])
1157                     .clearCapabilities()
1158                     .build();
1159             if (validated) {
1160                 setNetworkValid(privateDnsProbeSent);
1161             }
1162             final NetworkCallback callback = new NetworkCallback() {
1163                 public void onCapabilitiesChanged(Network network,
1164                         NetworkCapabilities networkCapabilities) {
1165                     if (network.equals(getNetwork())) {
1166                         capsChangedCv.open();
1167                         if (networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED)) {
1168                             validatedCv.open();
1169                         }
1170                     }
1171                 }
1172             };
1173             mCm.registerNetworkCallback(request, callback);
1174 
1175             if (hasInternet) {
1176                 addCapability(NET_CAPABILITY_INTERNET);
1177             }
1178 
1179             connectWithoutInternet();
1180             waitFor(capsChangedCv);
1181 
1182             if (validated) {
1183                 // Wait for network to validate.
1184                 waitFor(validatedCv);
1185                 setNetworkInvalid(privateDnsProbeSent);
1186             }
1187             mCm.unregisterNetworkCallback(callback);
1188         }
1189 
connectWithCaptivePortal(String redirectUrl, boolean privateDnsProbeSent)1190         public void connectWithCaptivePortal(String redirectUrl,
1191                 boolean privateDnsProbeSent) {
1192             setNetworkPortal(redirectUrl, privateDnsProbeSent);
1193             connect(false, true /* hasInternet */, privateDnsProbeSent);
1194         }
1195 
connectWithPartialConnectivity()1196         public void connectWithPartialConnectivity() {
1197             setNetworkPartial();
1198             connect(false);
1199         }
1200 
connectWithPartialValidConnectivity(boolean privateDnsProbeSent)1201         public void connectWithPartialValidConnectivity(boolean privateDnsProbeSent) {
1202             setNetworkPartialValid(privateDnsProbeSent);
1203             connect(false, true /* hasInternet */, privateDnsProbeSent);
1204         }
1205 
setNetworkValid(boolean privateDnsProbeSent)1206         void setNetworkValid(boolean privateDnsProbeSent) {
1207             mNmValidationResult = NETWORK_VALIDATION_RESULT_VALID;
1208             mNmValidationRedirectUrl = null;
1209             int probesSucceeded = NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_HTTPS;
1210             if (privateDnsProbeSent) {
1211                 probesSucceeded |= NETWORK_VALIDATION_PROBE_PRIVDNS;
1212             }
1213             // The probesCompleted equals to probesSucceeded for the case of valid network, so put
1214             // the same value into two different parameter of the method.
1215             setProbesStatus(probesSucceeded, probesSucceeded);
1216         }
1217 
setNetworkInvalid(boolean invalidBecauseOfPrivateDns)1218         void setNetworkInvalid(boolean invalidBecauseOfPrivateDns) {
1219             mNmValidationResult = VALIDATION_RESULT_INVALID;
1220             mNmValidationRedirectUrl = null;
1221             int probesCompleted = NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_HTTPS
1222                     | NETWORK_VALIDATION_PROBE_HTTP;
1223             int probesSucceeded = 0;
1224             // If |invalidBecauseOfPrivateDns| is true, it means the network is invalid because
1225             // NetworkMonitor tried to validate the private DNS but failed. Therefore it
1226             // didn't get a chance to try the HTTP probe.
1227             if (invalidBecauseOfPrivateDns) {
1228                 probesCompleted &= ~NETWORK_VALIDATION_PROBE_HTTP;
1229                 probesSucceeded = probesCompleted;
1230                 probesCompleted |= NETWORK_VALIDATION_PROBE_PRIVDNS;
1231             }
1232             setProbesStatus(probesCompleted, probesSucceeded);
1233         }
1234 
setNetworkPortal(String redirectUrl, boolean privateDnsProbeSent)1235         void setNetworkPortal(String redirectUrl, boolean privateDnsProbeSent) {
1236             setNetworkInvalid(privateDnsProbeSent);
1237             mNmValidationRedirectUrl = redirectUrl;
1238             // Suppose the portal is found when NetworkMonitor probes NETWORK_VALIDATION_PROBE_HTTP
1239             // in the beginning, so the NETWORK_VALIDATION_PROBE_HTTPS hasn't probed yet.
1240             int probesCompleted = NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_HTTP;
1241             int probesSucceeded = VALIDATION_RESULT_INVALID;
1242             if (privateDnsProbeSent) {
1243                 probesCompleted |= NETWORK_VALIDATION_PROBE_PRIVDNS;
1244             }
1245             setProbesStatus(probesCompleted, probesSucceeded);
1246         }
1247 
setNetworkPartial()1248         void setNetworkPartial() {
1249             mNmValidationResult = NETWORK_VALIDATION_RESULT_PARTIAL;
1250             mNmValidationRedirectUrl = null;
1251             int probesCompleted = NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_HTTPS
1252                     | NETWORK_VALIDATION_PROBE_FALLBACK;
1253             int probesSucceeded = NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_FALLBACK;
1254             setProbesStatus(probesCompleted, probesSucceeded);
1255         }
1256 
setNetworkPartialValid(boolean privateDnsProbeSent)1257         void setNetworkPartialValid(boolean privateDnsProbeSent) {
1258             setNetworkPartial();
1259             mNmValidationResult |= NETWORK_VALIDATION_RESULT_VALID;
1260             mNmValidationRedirectUrl = null;
1261             int probesCompleted = NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_HTTPS
1262                     | NETWORK_VALIDATION_PROBE_HTTP;
1263             int probesSucceeded = NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_HTTP;
1264             // Assume the partial network cannot pass the private DNS validation as well, so only
1265             // add NETWORK_VALIDATION_PROBE_DNS in probesCompleted but not probesSucceeded.
1266             if (privateDnsProbeSent) {
1267                 probesCompleted |= NETWORK_VALIDATION_PROBE_PRIVDNS;
1268             }
1269             setProbesStatus(probesCompleted, probesSucceeded);
1270         }
1271 
setProbesStatus(int probesCompleted, int probesSucceeded)1272         void setProbesStatus(int probesCompleted, int probesSucceeded) {
1273             mProbesCompleted = probesCompleted;
1274             mProbesSucceeded = probesSucceeded;
1275         }
1276 
notifyCapportApiDataChanged(CaptivePortalData data)1277         void notifyCapportApiDataChanged(CaptivePortalData data) {
1278             try {
1279                 mNmCallbacks.notifyCaptivePortalDataChanged(data);
1280             } catch (RemoteException e) {
1281                 throw new AssertionError("This cannot happen", e);
1282             }
1283         }
1284 
waitForRedirectUrl()1285         public String waitForRedirectUrl() {
1286             assertTrue(mNetworkStatusReceived.block(TIMEOUT_MS));
1287             return mRedirectUrl;
1288         }
1289 
expectDisconnected()1290         public void expectDisconnected() {
1291             expectDisconnected(TIMEOUT_MS);
1292         }
1293 
expectPreventReconnectReceived()1294         public void expectPreventReconnectReceived() {
1295             expectPreventReconnectReceived(TIMEOUT_MS);
1296         }
1297 
notifyDataStallSuspected()1298         void notifyDataStallSuspected() throws Exception {
1299             final DataStallReportParcelable p = new DataStallReportParcelable();
1300             p.detectionMethod = DATA_STALL_DETECTION_METHOD;
1301             p.timestampMillis = DATA_STALL_TIMESTAMP;
1302             mNmCallbacks.notifyDataStallSuspected(p);
1303         }
1304     }
1305 
1306     /**
1307      * A NetworkFactory that allows to wait until any in-flight NetworkRequest add or remove
1308      * operations have been processed and test for them.
1309      */
1310     private static class MockNetworkFactory extends NetworkFactory {
1311         private final AtomicBoolean mNetworkStarted = new AtomicBoolean(false);
1312 
1313         static class RequestEntry {
1314             @NonNull
1315             public final NetworkRequest request;
1316 
RequestEntry(@onNull final NetworkRequest request)1317             RequestEntry(@NonNull final NetworkRequest request) {
1318                 this.request = request;
1319             }
1320 
1321             static final class Add extends RequestEntry {
Add(@onNull final NetworkRequest request)1322                 Add(@NonNull final NetworkRequest request) {
1323                     super(request);
1324                 }
1325             }
1326 
1327             static final class Remove extends RequestEntry {
Remove(@onNull final NetworkRequest request)1328                 Remove(@NonNull final NetworkRequest request) {
1329                     super(request);
1330                 }
1331             }
1332 
1333             @Override
toString()1334             public String toString() {
1335                 return "RequestEntry [ " + getClass().getName() + " : " + request + " ]";
1336             }
1337         }
1338 
1339         // History of received requests adds and removes.
1340         private final ArrayTrackRecord<RequestEntry>.ReadHead mRequestHistory =
1341                 new ArrayTrackRecord<RequestEntry>().newReadHead();
1342 
failIfNull(@ullable final T obj, @Nullable final String message)1343         private static <T> T failIfNull(@Nullable final T obj, @Nullable final String message) {
1344             if (null == obj) fail(null != message ? message : "Must not be null");
1345             return obj;
1346         }
1347 
expectRequestAdd()1348         public RequestEntry.Add expectRequestAdd() {
1349             return failIfNull((RequestEntry.Add) mRequestHistory.poll(TIMEOUT_MS,
1350                     it -> it instanceof RequestEntry.Add), "Expected request add");
1351         }
1352 
expectRequestAdds(final int count)1353         public void expectRequestAdds(final int count) {
1354             for (int i = count; i > 0; --i) {
1355                 expectRequestAdd();
1356             }
1357         }
1358 
expectRequestRemove()1359         public RequestEntry.Remove expectRequestRemove() {
1360             return failIfNull((RequestEntry.Remove) mRequestHistory.poll(TIMEOUT_MS,
1361                     it -> it instanceof RequestEntry.Remove), "Expected request remove");
1362         }
1363 
expectRequestRemoves(final int count)1364         public void expectRequestRemoves(final int count) {
1365             for (int i = count; i > 0; --i) {
1366                 expectRequestRemove();
1367             }
1368         }
1369 
1370         // Used to collect the networks requests managed by this factory. This is a duplicate of
1371         // the internal information stored in the NetworkFactory (which is private).
1372         private SparseArray<NetworkRequest> mNetworkRequests = new SparseArray<>();
1373         private final HandlerThread mHandlerSendingRequests;
1374 
MockNetworkFactory(Looper looper, Context context, String logTag, NetworkCapabilities filter, HandlerThread threadSendingRequests)1375         public MockNetworkFactory(Looper looper, Context context, String logTag,
1376                 NetworkCapabilities filter, HandlerThread threadSendingRequests) {
1377             super(looper, context, logTag, filter);
1378             mHandlerSendingRequests = threadSendingRequests;
1379         }
1380 
getMyRequestCount()1381         public int getMyRequestCount() {
1382             return getRequestCount();
1383         }
1384 
startNetwork()1385         protected void startNetwork() {
1386             mNetworkStarted.set(true);
1387         }
1388 
stopNetwork()1389         protected void stopNetwork() {
1390             mNetworkStarted.set(false);
1391         }
1392 
getMyStartRequested()1393         public boolean getMyStartRequested() {
1394             return mNetworkStarted.get();
1395         }
1396 
1397 
1398         @Override
needNetworkFor(NetworkRequest request)1399         protected void needNetworkFor(NetworkRequest request) {
1400             mNetworkRequests.put(request.requestId, request);
1401             super.needNetworkFor(request);
1402             mRequestHistory.add(new RequestEntry.Add(request));
1403         }
1404 
1405         @Override
releaseNetworkFor(NetworkRequest request)1406         protected void releaseNetworkFor(NetworkRequest request) {
1407             mNetworkRequests.remove(request.requestId);
1408             super.releaseNetworkFor(request);
1409             mRequestHistory.add(new RequestEntry.Remove(request));
1410         }
1411 
assertRequestCountEquals(final int count)1412         public void assertRequestCountEquals(final int count) {
1413             assertEquals(count, getMyRequestCount());
1414         }
1415 
1416         // Trigger releasing the request as unfulfillable
triggerUnfulfillable(NetworkRequest r)1417         public void triggerUnfulfillable(NetworkRequest r) {
1418             super.releaseRequestAsUnfulfillableByAnyFactory(r);
1419         }
1420 
assertNoRequestChanged()1421         public void assertNoRequestChanged() {
1422             // Make sure there are no remaining requests unaccounted for.
1423             HandlerUtils.waitForIdle(mHandlerSendingRequests, TIMEOUT_MS);
1424             assertNull(mRequestHistory.poll(0, r -> true));
1425         }
1426     }
1427 
uidRangesForUids(int... uids)1428     private Set<UidRange> uidRangesForUids(int... uids) {
1429         final ArraySet<UidRange> ranges = new ArraySet<>();
1430         for (final int uid : uids) {
1431             ranges.add(new UidRange(uid, uid));
1432         }
1433         return ranges;
1434     }
1435 
uidRangesForUids(Collection<Integer> uids)1436     private Set<UidRange> uidRangesForUids(Collection<Integer> uids) {
1437         return uidRangesForUids(CollectionUtils.toIntArray(uids));
1438     }
1439 
startHandlerThreadAndReturnLooper()1440     private static Looper startHandlerThreadAndReturnLooper() {
1441         final HandlerThread handlerThread = new HandlerThread("MockVpnThread");
1442         handlerThread.start();
1443         return handlerThread.getLooper();
1444     }
1445 
1446     private class MockVpn extends Vpn implements TestableNetworkCallback.HasNetwork {
1447         // Careful ! This is different from mNetworkAgent, because MockNetworkAgent does
1448         // not inherit from NetworkAgent.
1449         private TestNetworkAgentWrapper mMockNetworkAgent;
1450         private boolean mAgentRegistered = false;
1451 
1452         private int mVpnType = VpnManager.TYPE_VPN_SERVICE;
1453         private UnderlyingNetworkInfo mUnderlyingNetworkInfo;
1454 
1455         // These ConditionVariables allow tests to wait for LegacyVpnRunner to be stopped/started.
1456         // TODO: this scheme is ad-hoc and error-prone because it does not fail if, for example, the
1457         // test expects two starts in a row, or even if the production code calls start twice in a
1458         // row. find a better solution. Simply putting a method to create a LegacyVpnRunner into
1459         // Vpn.Dependencies doesn't work because LegacyVpnRunner is not a static class and has
1460         // extensive access into the internals of Vpn.
1461         private ConditionVariable mStartLegacyVpnCv = new ConditionVariable();
1462         private ConditionVariable mStopVpnRunnerCv = new ConditionVariable();
1463 
MockVpn(int userId)1464         public MockVpn(int userId) {
1465             super(startHandlerThreadAndReturnLooper(), mServiceContext,
1466                     new Dependencies() {
1467                         @Override
1468                         public boolean isCallerSystem() {
1469                             return true;
1470                         }
1471 
1472                         @Override
1473                         public DeviceIdleInternal getDeviceIdleInternal() {
1474                             return mDeviceIdleInternal;
1475                         }
1476                     },
1477                     mNetworkManagementService, mMockNetd, userId, mVpnProfileStore,
1478                     new SystemServices(mServiceContext) {
1479                         @Override
1480                         public String settingsSecureGetStringForUser(String key, int userId) {
1481                             switch (key) {
1482                                 // Settings keys not marked as @Readable are not readable from
1483                                 // non-privileged apps, unless marked as testOnly=true
1484                                 // (atest refuses to install testOnly=true apps), even if mocked
1485                                 // in the content provider, because
1486                                 // Settings.Secure.NameValueCache#getStringForUser checks the key
1487                                 // before querying the mock settings provider.
1488                                 case Settings.Secure.ALWAYS_ON_VPN_APP:
1489                                     return null;
1490                                 default:
1491                                     return super.settingsSecureGetStringForUser(key, userId);
1492                             }
1493                         }
1494                     }, new Ikev2SessionCreator());
1495         }
1496 
setUids(Set<UidRange> uids)1497         public void setUids(Set<UidRange> uids) {
1498             mNetworkCapabilities.setUids(UidRange.toIntRanges(uids));
1499             if (mAgentRegistered) {
1500                 mMockNetworkAgent.setNetworkCapabilities(mNetworkCapabilities, true);
1501             }
1502         }
1503 
setVpnType(int vpnType)1504         public void setVpnType(int vpnType) {
1505             mVpnType = vpnType;
1506         }
1507 
1508         @Override
getNetwork()1509         public Network getNetwork() {
1510             return (mMockNetworkAgent == null) ? null : mMockNetworkAgent.getNetwork();
1511         }
1512 
getNetworkAgentConfig()1513         public NetworkAgentConfig getNetworkAgentConfig() {
1514             return null == mMockNetworkAgent ? null : mMockNetworkAgent.getNetworkAgentConfig();
1515         }
1516 
1517         @Override
getActiveVpnType()1518         public int getActiveVpnType() {
1519             return mVpnType;
1520         }
1521 
makeLinkProperties()1522         private LinkProperties makeLinkProperties() {
1523             final LinkProperties lp = new LinkProperties();
1524             lp.setInterfaceName(VPN_IFNAME);
1525             return lp;
1526         }
1527 
registerAgent(boolean isAlwaysMetered, Set<UidRange> uids, LinkProperties lp)1528         private void registerAgent(boolean isAlwaysMetered, Set<UidRange> uids, LinkProperties lp)
1529                 throws Exception {
1530             if (mAgentRegistered) throw new IllegalStateException("already registered");
1531             updateState(NetworkInfo.DetailedState.CONNECTING, "registerAgent");
1532             mConfig = new VpnConfig();
1533             mConfig.session = "MySession12345";
1534             setUids(uids);
1535             if (!isAlwaysMetered) mNetworkCapabilities.addCapability(NET_CAPABILITY_NOT_METERED);
1536             mInterface = VPN_IFNAME;
1537             mNetworkCapabilities.setTransportInfo(new VpnTransportInfo(getActiveVpnType(),
1538                     mConfig.session));
1539             mMockNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN, lp,
1540                     mNetworkCapabilities);
1541             mMockNetworkAgent.waitForIdle(TIMEOUT_MS);
1542 
1543             verify(mMockNetd, times(1)).networkAddUidRangesParcel(
1544                     new NativeUidRangeConfig(mMockVpn.getNetwork().getNetId(),
1545                             toUidRangeStableParcels(uids), PREFERENCE_ORDER_VPN));
1546             verify(mMockNetd, never()).networkRemoveUidRangesParcel(argThat(config ->
1547                     mMockVpn.getNetwork().getNetId() == config.netId
1548                             && PREFERENCE_ORDER_VPN == config.subPriority));
1549             mAgentRegistered = true;
1550             verify(mMockNetd).networkCreate(nativeNetworkConfigVpn(getNetwork().netId,
1551                     !mMockNetworkAgent.isBypassableVpn(), mVpnType));
1552             updateState(NetworkInfo.DetailedState.CONNECTED, "registerAgent");
1553             mNetworkCapabilities.set(mMockNetworkAgent.getNetworkCapabilities());
1554             mNetworkAgent = mMockNetworkAgent.getNetworkAgent();
1555         }
1556 
registerAgent(Set<UidRange> uids)1557         private void registerAgent(Set<UidRange> uids) throws Exception {
1558             registerAgent(false /* isAlwaysMetered */, uids, makeLinkProperties());
1559         }
1560 
connect(boolean validated, boolean hasInternet, boolean privateDnsProbeSent)1561         private void connect(boolean validated, boolean hasInternet,
1562                 boolean privateDnsProbeSent) {
1563             mMockNetworkAgent.connect(validated, hasInternet, privateDnsProbeSent);
1564         }
1565 
connect(boolean validated)1566         private void connect(boolean validated) {
1567             mMockNetworkAgent.connect(validated);
1568         }
1569 
getAgent()1570         private TestNetworkAgentWrapper getAgent() {
1571             return mMockNetworkAgent;
1572         }
1573 
setOwnerAndAdminUid(int uid)1574         private void setOwnerAndAdminUid(int uid) throws Exception {
1575             mNetworkCapabilities.setOwnerUid(uid);
1576             mNetworkCapabilities.setAdministratorUids(new int[]{uid});
1577         }
1578 
establish(LinkProperties lp, int uid, Set<UidRange> ranges, boolean validated, boolean hasInternet, boolean privateDnsProbeSent)1579         public void establish(LinkProperties lp, int uid, Set<UidRange> ranges, boolean validated,
1580                 boolean hasInternet, boolean privateDnsProbeSent) throws Exception {
1581             setOwnerAndAdminUid(uid);
1582             registerAgent(false, ranges, lp);
1583             connect(validated, hasInternet, privateDnsProbeSent);
1584             waitForIdle();
1585         }
1586 
establish(LinkProperties lp, int uid, Set<UidRange> ranges)1587         public void establish(LinkProperties lp, int uid, Set<UidRange> ranges) throws Exception {
1588             establish(lp, uid, ranges, true, true, false);
1589         }
1590 
establishForMyUid(LinkProperties lp)1591         public void establishForMyUid(LinkProperties lp) throws Exception {
1592             final int uid = Process.myUid();
1593             establish(lp, uid, uidRangesForUids(uid), true, true, false);
1594         }
1595 
establishForMyUid(boolean validated, boolean hasInternet, boolean privateDnsProbeSent)1596         public void establishForMyUid(boolean validated, boolean hasInternet,
1597                 boolean privateDnsProbeSent) throws Exception {
1598             final int uid = Process.myUid();
1599             establish(makeLinkProperties(), uid, uidRangesForUids(uid), validated, hasInternet,
1600                     privateDnsProbeSent);
1601         }
1602 
establishForMyUid()1603         public void establishForMyUid() throws Exception {
1604             establishForMyUid(makeLinkProperties());
1605         }
1606 
sendLinkProperties(LinkProperties lp)1607         public void sendLinkProperties(LinkProperties lp) {
1608             mMockNetworkAgent.sendLinkProperties(lp);
1609         }
1610 
disconnect()1611         public void disconnect() {
1612             if (mMockNetworkAgent != null) {
1613                 mMockNetworkAgent.disconnect();
1614                 updateState(NetworkInfo.DetailedState.DISCONNECTED, "disconnect");
1615             }
1616             mAgentRegistered = false;
1617             setUids(null);
1618             // Remove NET_CAPABILITY_INTERNET or MockNetworkAgent will refuse to connect later on.
1619             mNetworkCapabilities.removeCapability(NET_CAPABILITY_INTERNET);
1620             mInterface = null;
1621         }
1622 
1623         @Override
startLegacyVpnRunner()1624         public void startLegacyVpnRunner() {
1625             mStartLegacyVpnCv.open();
1626         }
1627 
expectStartLegacyVpnRunner()1628         public void expectStartLegacyVpnRunner() {
1629             assertTrue("startLegacyVpnRunner not called after " + TIMEOUT_MS + " ms",
1630                     mStartLegacyVpnCv.block(TIMEOUT_MS));
1631 
1632             // startLegacyVpn calls stopVpnRunnerPrivileged, which will open mStopVpnRunnerCv, just
1633             // before calling startLegacyVpnRunner. Restore mStopVpnRunnerCv, so the test can expect
1634             // that the VpnRunner is stopped and immediately restarted by calling
1635             // expectStartLegacyVpnRunner() and expectStopVpnRunnerPrivileged() back-to-back.
1636             mStopVpnRunnerCv = new ConditionVariable();
1637         }
1638 
1639         @Override
stopVpnRunnerPrivileged()1640         public void stopVpnRunnerPrivileged() {
1641             if (mVpnRunner != null) {
1642                 super.stopVpnRunnerPrivileged();
1643                 disconnect();
1644                 mStartLegacyVpnCv = new ConditionVariable();
1645             }
1646             mVpnRunner = null;
1647             mStopVpnRunnerCv.open();
1648         }
1649 
expectStopVpnRunnerPrivileged()1650         public void expectStopVpnRunnerPrivileged() {
1651             assertTrue("stopVpnRunnerPrivileged not called after " + TIMEOUT_MS + " ms",
1652                     mStopVpnRunnerCv.block(TIMEOUT_MS));
1653         }
1654 
1655         @Override
getUnderlyingNetworkInfo()1656         public synchronized UnderlyingNetworkInfo getUnderlyingNetworkInfo() {
1657             if (mUnderlyingNetworkInfo != null) return mUnderlyingNetworkInfo;
1658 
1659             return super.getUnderlyingNetworkInfo();
1660         }
1661 
setUnderlyingNetworkInfo( UnderlyingNetworkInfo underlyingNetworkInfo)1662         private synchronized void setUnderlyingNetworkInfo(
1663                 UnderlyingNetworkInfo underlyingNetworkInfo) {
1664             mUnderlyingNetworkInfo = underlyingNetworkInfo;
1665         }
1666     }
1667 
toUidRangeStableParcels(final @NonNull Set<UidRange> ranges)1668     private UidRangeParcel[] toUidRangeStableParcels(final @NonNull Set<UidRange> ranges) {
1669         return ranges.stream().map(
1670                 r -> new UidRangeParcel(r.start, r.stop)).toArray(UidRangeParcel[]::new);
1671     }
1672 
intToUidRangeStableParcels(final @NonNull Set<Integer> ranges)1673     private UidRangeParcel[] intToUidRangeStableParcels(final @NonNull Set<Integer> ranges) {
1674         return ranges.stream().map(r -> new UidRangeParcel(r, r)).toArray(UidRangeParcel[]::new);
1675     }
1676 
assertVpnTransportInfo(NetworkCapabilities nc, int type)1677     private void assertVpnTransportInfo(NetworkCapabilities nc, int type) {
1678         assertNotNull(nc);
1679         final TransportInfo ti = nc.getTransportInfo();
1680         assertTrue("VPN TransportInfo is not a VpnTransportInfo: " + ti,
1681                 ti instanceof VpnTransportInfo);
1682         assertEquals(type, ((VpnTransportInfo) ti).getType());
1683 
1684     }
1685 
processBroadcast(Intent intent)1686     private void processBroadcast(Intent intent) {
1687         mServiceContext.sendBroadcast(intent);
1688         waitForIdle();
1689     }
1690 
mockVpn(int uid)1691     private void mockVpn(int uid) {
1692         int userId = UserHandle.getUserId(uid);
1693         mMockVpn = new MockVpn(userId);
1694     }
1695 
mockUidNetworkingBlocked()1696     private void mockUidNetworkingBlocked() {
1697         doAnswer(i -> isUidBlocked(mBlockedReasons, i.getArgument(1))
1698         ).when(mNetworkPolicyManager).isUidNetworkingBlocked(anyInt(), anyBoolean());
1699     }
1700 
isUidBlocked(int blockedReasons, boolean meteredNetwork)1701     private boolean isUidBlocked(int blockedReasons, boolean meteredNetwork) {
1702         final int blockedOnAllNetworksReason = (blockedReasons & ~BLOCKED_METERED_REASON_MASK);
1703         if (blockedOnAllNetworksReason != BLOCKED_REASON_NONE) {
1704             return true;
1705         }
1706         if (meteredNetwork) {
1707             return blockedReasons != BLOCKED_REASON_NONE;
1708         }
1709         return false;
1710     }
1711 
setBlockedReasonChanged(int blockedReasons)1712     private void setBlockedReasonChanged(int blockedReasons) {
1713         mBlockedReasons = blockedReasons;
1714         mPolicyCallback.onUidBlockedReasonChanged(Process.myUid(), blockedReasons);
1715     }
1716 
getNat464Xlat(NetworkAgentWrapper mna)1717     private Nat464Xlat getNat464Xlat(NetworkAgentWrapper mna) {
1718         return mService.getNetworkAgentInfoForNetwork(mna.getNetwork()).clatd;
1719     }
1720 
1721     private class WrappedMultinetworkPolicyTracker extends MultinetworkPolicyTracker {
1722         volatile int mConfigMeteredMultipathPreference;
1723 
WrappedMultinetworkPolicyTracker(Context c, Handler h, Runnable r)1724         WrappedMultinetworkPolicyTracker(Context c, Handler h, Runnable r) {
1725             super(c, h, r, new MultinetworkPolicyTrackerTestDependencies(mResources));
1726         }
1727 
1728         @Override
configMeteredMultipathPreference()1729         public int configMeteredMultipathPreference() {
1730             return mConfigMeteredMultipathPreference;
1731         }
1732     }
1733 
1734     /**
1735      * Wait up to TIMEOUT_MS for {@code conditionVariable} to open.
1736      * Fails if TIMEOUT_MS goes by before {@code conditionVariable} opens.
1737      */
waitFor(ConditionVariable conditionVariable)1738     static private void waitFor(ConditionVariable conditionVariable) {
1739         if (conditionVariable.block(TIMEOUT_MS)) {
1740             return;
1741         }
1742         fail("ConditionVariable was blocked for more than " + TIMEOUT_MS + "ms");
1743     }
1744 
doAsUid(final int uid, @NonNull final Supplier<T> what)1745     private <T> T doAsUid(final int uid, @NonNull final Supplier<T> what) {
1746         mDeps.setCallingUid(uid);
1747         try {
1748             return what.get();
1749         } finally {
1750             mDeps.setCallingUid(null);
1751         }
1752     }
1753 
doAsUid(final int uid, @NonNull final Runnable what)1754     private void doAsUid(final int uid, @NonNull final Runnable what) {
1755         doAsUid(uid, () -> {
1756             what.run(); return Void.TYPE;
1757         });
1758     }
1759 
registerNetworkCallbackAsUid(NetworkRequest request, NetworkCallback callback, int uid)1760     private void registerNetworkCallbackAsUid(NetworkRequest request, NetworkCallback callback,
1761             int uid) {
1762         doAsUid(uid, () -> {
1763             mCm.registerNetworkCallback(request, callback);
1764         });
1765     }
1766 
registerDefaultNetworkCallbackAsUid(@onNull final NetworkCallback callback, final int uid)1767     private void registerDefaultNetworkCallbackAsUid(@NonNull final NetworkCallback callback,
1768             final int uid) {
1769         doAsUid(uid, () -> {
1770             mCm.registerDefaultNetworkCallback(callback);
1771             waitForIdle();
1772         });
1773     }
1774 
withPermission(String permission, ThrowingRunnable r)1775     private void withPermission(String permission, ThrowingRunnable r) throws Exception {
1776         try {
1777             mServiceContext.setPermission(permission, PERMISSION_GRANTED);
1778             r.run();
1779         } finally {
1780             mServiceContext.setPermission(permission, null);
1781         }
1782     }
1783 
withPermission(String permission, int pid, int uid, ThrowingRunnable r)1784     private void withPermission(String permission, int pid, int uid, ThrowingRunnable r)
1785             throws Exception {
1786         try {
1787             mServiceContext.setPermission(permission, pid, uid, PERMISSION_GRANTED);
1788             r.run();
1789         } finally {
1790             mServiceContext.setPermission(permission, pid, uid, null);
1791         }
1792     }
1793 
1794     private static final int PRIMARY_USER = 0;
1795     private static final int SECONDARY_USER = 10;
1796     private static final int TERTIARY_USER = 11;
1797     private static final UidRange PRIMARY_UIDRANGE =
1798             UidRange.createForUser(UserHandle.of(PRIMARY_USER));
1799     private static final int APP1_UID = UserHandle.getUid(PRIMARY_USER, 10100);
1800     private static final int APP2_UID = UserHandle.getUid(PRIMARY_USER, 10101);
1801     private static final int VPN_UID = UserHandle.getUid(PRIMARY_USER, 10043);
1802     private static final UserInfo PRIMARY_USER_INFO = new UserInfo(PRIMARY_USER, "",
1803             UserInfo.FLAG_PRIMARY);
1804     private static final UserHandle PRIMARY_USER_HANDLE = new UserHandle(PRIMARY_USER);
1805     private static final UserHandle SECONDARY_USER_HANDLE = new UserHandle(SECONDARY_USER);
1806     private static final UserHandle TERTIARY_USER_HANDLE = new UserHandle(TERTIARY_USER);
1807 
1808     private static final int RESTRICTED_USER = 1;
1809     private static final UserInfo RESTRICTED_USER_INFO = new UserInfo(RESTRICTED_USER, "",
1810             UserInfo.FLAG_RESTRICTED);
1811     static {
1812         RESTRICTED_USER_INFO.restrictedProfileParentId = PRIMARY_USER;
1813     }
1814 
1815     @Before
setUp()1816     public void setUp() throws Exception {
1817         mNetIdManager = new TestNetIdManager();
1818 
1819         mContext = InstrumentationRegistry.getContext();
1820 
1821         MockitoAnnotations.initMocks(this);
1822 
1823         doReturn(asList(PRIMARY_USER_INFO)).when(mUserManager).getAliveUsers();
1824         doReturn(asList(PRIMARY_USER_HANDLE)).when(mUserManager).getUserHandles(anyBoolean());
1825         doReturn(PRIMARY_USER_INFO).when(mUserManager).getUserInfo(PRIMARY_USER);
1826         // canHaveRestrictedProfile does not take a userId. It applies to the userId of the context
1827         // it was started from, i.e., PRIMARY_USER.
1828         doReturn(true).when(mUserManager).canHaveRestrictedProfile();
1829         doReturn(RESTRICTED_USER_INFO).when(mUserManager).getUserInfo(RESTRICTED_USER);
1830 
1831         final ApplicationInfo applicationInfo = new ApplicationInfo();
1832         applicationInfo.targetSdkVersion = Build.VERSION_CODES.Q;
1833         doReturn(applicationInfo).when(mPackageManager)
1834                 .getApplicationInfoAsUser(anyString(), anyInt(), any());
1835         doReturn(applicationInfo.targetSdkVersion).when(mPackageManager)
1836                 .getTargetSdkVersion(anyString());
1837         doReturn(new int[0]).when(mSystemConfigManager).getSystemPermissionUids(anyString());
1838 
1839         // InstrumentationTestRunner prepares a looper, but AndroidJUnitRunner does not.
1840         // http://b/25897652 .
1841         if (Looper.myLooper() == null) {
1842             Looper.prepare();
1843         }
1844         mockDefaultPackages();
1845         mockHasSystemFeature(FEATURE_WIFI, true);
1846         mockHasSystemFeature(FEATURE_WIFI_DIRECT, true);
1847         mockHasSystemFeature(FEATURE_ETHERNET, true);
1848         doReturn(true).when(mTelephonyManager).isDataCapable();
1849 
1850         FakeSettingsProvider.clearSettingsProvider();
1851         mServiceContext = new MockContext(InstrumentationRegistry.getContext(),
1852                 new FakeSettingsProvider());
1853         mServiceContext.setUseRegisteredHandlers(true);
1854         mServiceContext.setPermission(NETWORK_FACTORY, PERMISSION_GRANTED);
1855         mServiceContext.setPermission(NETWORK_STACK, PERMISSION_GRANTED);
1856         mServiceContext.setPermission(CONTROL_OEM_PAID_NETWORK_PREFERENCE, PERMISSION_GRANTED);
1857         mServiceContext.setPermission(PACKET_KEEPALIVE_OFFLOAD, PERMISSION_GRANTED);
1858         mServiceContext.setPermission(CONNECTIVITY_USE_RESTRICTED_NETWORKS, PERMISSION_GRANTED);
1859 
1860         mAlarmManagerThread = new HandlerThread("TestAlarmManager");
1861         mAlarmManagerThread.start();
1862         initAlarmManager(mAlarmManager, mAlarmManagerThread.getThreadHandler());
1863 
1864         mCsHandlerThread = new HandlerThread("TestConnectivityService");
1865         mProxyTracker = new ProxyTracker(mServiceContext, mock(Handler.class),
1866                 16 /* EVENT_PROXY_HAS_CHANGED */);
1867 
1868         initMockedResources();
1869         final Context mockResContext = mock(Context.class);
1870         doReturn(mResources).when(mockResContext).getResources();
1871         ConnectivityResources.setResourcesContextForTest(mockResContext);
1872         mDeps = new ConnectivityServiceDependencies(mockResContext);
1873         mAutoOnOffKeepaliveDependencies =
1874                 new AutomaticOnOffKeepaliveTrackerDependencies(mServiceContext);
1875         mService = new ConnectivityService(mServiceContext,
1876                 mMockDnsResolver,
1877                 mock(IpConnectivityLog.class),
1878                 mMockNetd,
1879                 mDeps);
1880         mService.mLingerDelayMs = TEST_LINGER_DELAY_MS;
1881         mService.mNascentDelayMs = TEST_NASCENT_DELAY_MS;
1882 
1883         final ArgumentCaptor<NetworkPolicyCallback> policyCallbackCaptor =
1884                 ArgumentCaptor.forClass(NetworkPolicyCallback.class);
1885         verify(mNetworkPolicyManager).registerNetworkPolicyCallback(any(),
1886                 policyCallbackCaptor.capture());
1887         mPolicyCallback = policyCallbackCaptor.getValue();
1888 
1889         // Create local CM before sending system ready so that we can answer
1890         // getSystemService() correctly.
1891         mCm = new WrappedConnectivityManager(InstrumentationRegistry.getContext(), mService);
1892         mService.systemReadyInternal();
1893         verify(mMockDnsResolver).registerUnsolicitedEventListener(any());
1894 
1895         mockVpn(Process.myUid());
1896         mCm.bindProcessToNetwork(null);
1897         mQosCallbackTracker = mock(QosCallbackTracker.class);
1898 
1899         // Ensure that the default setting for Captive Portals is used for most tests
1900         setCaptivePortalMode(ConnectivitySettingsManager.CAPTIVE_PORTAL_MODE_PROMPT);
1901         setAlwaysOnNetworks(false);
1902         setPrivateDnsSettings(PRIVATE_DNS_MODE_OFF, "ignored.example.com");
1903     }
1904 
initMockedResources()1905     private void initMockedResources() {
1906         doReturn(60000).when(mResources).getInteger(R.integer.config_networkTransitionTimeout);
1907         doReturn("").when(mResources).getString(R.string.config_networkCaptivePortalServerUrl);
1908         doReturn(new String[]{ WIFI_WOL_IFNAME }).when(mResources).getStringArray(
1909                 R.array.config_wakeonlan_supported_interfaces);
1910         doReturn(new String[] { "0,1", "1,3" }).when(mResources).getStringArray(
1911                 R.array.config_networkSupportedKeepaliveCount);
1912         doReturn(new String[0]).when(mResources).getStringArray(
1913                 R.array.config_networkNotifySwitches);
1914         doReturn(new int[]{10, 11, 12, 14, 15}).when(mResources).getIntArray(
1915                 R.array.config_protectedNetworks);
1916         // We don't test the actual notification value strings, so just return an empty array.
1917         // It doesn't matter what the values are as long as it's not null.
1918         doReturn(new String[0]).when(mResources)
1919                 .getStringArray(R.array.network_switch_type_name);
1920 
1921         doReturn(R.array.config_networkSupportedKeepaliveCount).when(mResources)
1922                 .getIdentifier(eq("config_networkSupportedKeepaliveCount"), eq("array"), any());
1923         doReturn(R.array.network_switch_type_name).when(mResources)
1924                 .getIdentifier(eq("network_switch_type_name"), eq("array"), any());
1925         doReturn(1).when(mResources).getInteger(R.integer.config_networkAvoidBadWifi);
1926         doReturn(0).when(mResources).getInteger(R.integer.config_activelyPreferBadWifi);
1927         doReturn(true).when(mResources)
1928                 .getBoolean(R.bool.config_cellular_radio_timesharing_capable);
1929         doReturn(PACKET_WAKEUP_MARK_MASK).when(mResources).getInteger(
1930                 R.integer.config_networkWakeupPacketMask);
1931         doReturn(PACKET_WAKEUP_MARK_MASK).when(mResources).getInteger(
1932                 R.integer.config_networkWakeupPacketMark);
1933     }
1934 
1935     class ConnectivityServiceDependencies extends ConnectivityService.Dependencies {
1936         final ConnectivityResources mConnRes;
1937         final ArraySet<Pair<Long, Integer>> mEnabledChangeIds = new ArraySet<>();
1938 
ConnectivityServiceDependencies(final Context mockResContext)1939         ConnectivityServiceDependencies(final Context mockResContext) {
1940             mConnRes = new ConnectivityResources(mockResContext);
1941         }
1942 
1943         @Override
makeHandlerThread()1944         public HandlerThread makeHandlerThread() {
1945             return mCsHandlerThread;
1946         }
1947 
1948         @Override
getNetworkStack()1949         public NetworkStackClientBase getNetworkStack() {
1950             return mNetworkStack;
1951         }
1952 
1953         @Override
makeProxyTracker(final Context context, final Handler handler)1954         public ProxyTracker makeProxyTracker(final Context context, final Handler handler) {
1955             return mProxyTracker;
1956         }
1957 
1958         @Override
makeNetIdManager()1959         public NetIdManager makeNetIdManager() {
1960             return mNetIdManager;
1961         }
1962 
1963         @Override
queryUserAccess(final int uid, final Network network, final ConnectivityService cs)1964         public boolean queryUserAccess(final int uid, final Network network,
1965                 final ConnectivityService cs) {
1966             return true;
1967         }
1968 
1969         @Override
makeMultinetworkPolicyTracker(final Context c, final Handler h, final Runnable r)1970         public MultinetworkPolicyTracker makeMultinetworkPolicyTracker(final Context c,
1971                 final Handler h, final Runnable r) {
1972             if (null != mPolicyTracker) {
1973                 throw new IllegalStateException("Multinetwork policy tracker already initialized");
1974             }
1975             mPolicyTracker = new WrappedMultinetworkPolicyTracker(mServiceContext, h, r);
1976             return mPolicyTracker;
1977         }
1978 
1979         @Override
makeAutomaticOnOffKeepaliveTracker(final Context c, final Handler h)1980         public AutomaticOnOffKeepaliveTracker makeAutomaticOnOffKeepaliveTracker(final Context c,
1981                 final Handler h) {
1982             return new AutomaticOnOffKeepaliveTracker(c, h, mAutoOnOffKeepaliveDependencies);
1983         }
1984 
1985         @Override
getResources(final Context ctx)1986         public ConnectivityResources getResources(final Context ctx) {
1987             return mConnRes;
1988         }
1989 
1990         @Override
makeLocationPermissionChecker(final Context context)1991         public LocationPermissionChecker makeLocationPermissionChecker(final Context context) {
1992             return new LocationPermissionChecker(context) {
1993                 @Override
1994                 protected int getCurrentUser() {
1995                     return runAsShell(CREATE_USERS, () -> super.getCurrentUser());
1996                 }
1997             };
1998         }
1999 
2000         @Override
makeCarrierPrivilegeAuthenticator( @onNull final Context context, @NonNull final TelephonyManager tm)2001         public CarrierPrivilegeAuthenticator makeCarrierPrivilegeAuthenticator(
2002                 @NonNull final Context context, @NonNull final TelephonyManager tm) {
2003             return mDeps.isAtLeastT() ? mCarrierPrivilegeAuthenticator : null;
2004         }
2005 
2006         @Override
intentFilterEquals(final PendingIntent a, final PendingIntent b)2007         public boolean intentFilterEquals(final PendingIntent a, final PendingIntent b) {
2008             return runAsShell(GET_INTENT_SENDER_INTENT, () -> a.intentFilterEquals(b));
2009         }
2010 
2011         @GuardedBy("this")
2012         private Integer mCallingUid = null;
2013 
2014         @Override
getCallingUid()2015         public int getCallingUid() {
2016             synchronized (this) {
2017                 if (null != mCallingUid) return mCallingUid;
2018                 return super.getCallingUid();
2019             }
2020         }
2021 
2022         // Pass null for the real calling UID
setCallingUid(final Integer uid)2023         public void setCallingUid(final Integer uid) {
2024             synchronized (this) {
2025                 mCallingUid = uid;
2026             }
2027         }
2028 
2029         @GuardedBy("this")
2030         private boolean mCellular464XlatEnabled = true;
2031 
2032         @Override
getCellular464XlatEnabled()2033         public boolean getCellular464XlatEnabled() {
2034             synchronized (this) {
2035                 return mCellular464XlatEnabled;
2036             }
2037         }
2038 
setCellular464XlatEnabled(final boolean enabled)2039         public void setCellular464XlatEnabled(final boolean enabled) {
2040             synchronized (this) {
2041                 mCellular464XlatEnabled = enabled;
2042             }
2043         }
2044 
2045         @GuardedBy("this")
2046         private Integer mConnectionOwnerUid = null;
2047 
2048         @Override
getConnectionOwnerUid(final int protocol, final InetSocketAddress local, final InetSocketAddress remote)2049         public int getConnectionOwnerUid(final int protocol, final InetSocketAddress local,
2050                 final InetSocketAddress remote) {
2051             synchronized (this) {
2052                 if (null != mConnectionOwnerUid) return mConnectionOwnerUid;
2053                 return super.getConnectionOwnerUid(protocol, local, remote);
2054             }
2055         }
2056 
2057         // Pass null to get the production implementation of getConnectionOwnerUid
setConnectionOwnerUid(final Integer uid)2058         public void setConnectionOwnerUid(final Integer uid) {
2059             synchronized (this) {
2060                 mConnectionOwnerUid = uid;
2061             }
2062         }
2063 
2064         final class ReportedInterfaces {
2065             public final Context context;
2066             public final String iface;
2067             public final int[] transportTypes;
ReportedInterfaces(final Context c, final String i, final int[] t)2068             ReportedInterfaces(final Context c, final String i, final int[] t) {
2069                 context = c;
2070                 iface = i;
2071                 transportTypes = t;
2072             }
2073 
contentEquals(final Context c, final String i, final int[] t)2074             public boolean contentEquals(final Context c, final String i, final int[] t) {
2075                 return Objects.equals(context, c) && Objects.equals(iface, i)
2076                         && Arrays.equals(transportTypes, t);
2077             }
2078         }
2079 
2080         final ArrayTrackRecord<ReportedInterfaces> mReportedInterfaceHistory =
2081                 new ArrayTrackRecord<>();
2082 
2083         @Override
reportNetworkInterfaceForTransports(final Context context, final String iface, final int[] transportTypes)2084         public void reportNetworkInterfaceForTransports(final Context context, final String iface,
2085                 final int[] transportTypes) {
2086             mReportedInterfaceHistory.add(new ReportedInterfaces(context, iface, transportTypes));
2087             super.reportNetworkInterfaceForTransports(context, iface, transportTypes);
2088         }
2089 
2090         @Override
isFeatureEnabled(Context context, String name)2091         public boolean isFeatureEnabled(Context context, String name) {
2092             switch (name) {
2093                 case ConnectivityFlags.NO_REMATCH_ALL_REQUESTS_ON_REGISTER:
2094                     return true;
2095                 case KEY_DESTROY_FROZEN_SOCKETS_VERSION:
2096                     return true;
2097                 default:
2098                     return super.isFeatureEnabled(context, name);
2099             }
2100         }
2101 
setChangeIdEnabled(final boolean enabled, final long changeId, final int uid)2102         public void setChangeIdEnabled(final boolean enabled, final long changeId, final int uid) {
2103             final Pair<Long, Integer> data = new Pair<>(changeId, uid);
2104             // mEnabledChangeIds is read on the handler thread and maybe the test thread, so
2105             // make sure both threads see it before continuing.
2106             visibleOnHandlerThread(mCsHandlerThread.getThreadHandler(), () -> {
2107                 if (enabled) {
2108                     mEnabledChangeIds.add(data);
2109                 } else {
2110                     mEnabledChangeIds.remove(data);
2111                 }
2112             });
2113         }
2114 
2115         @Override
isChangeEnabled(final long changeId, final int uid)2116         public boolean isChangeEnabled(final long changeId, final int uid) {
2117             return mEnabledChangeIds.contains(new Pair<>(changeId, uid));
2118         }
2119 
2120         // In AOSP, build version codes are all over the place (e.g. at the time of this writing
2121         // U == V). Define custom ones.
2122         private static final int VERSION_UNMOCKED = -1;
2123         private static final int VERSION_R = 1;
2124         private static final int VERSION_S = 2;
2125         private static final int VERSION_T = 3;
2126         private static final int VERSION_U = 4;
2127         private static final int VERSION_V = 5;
2128         private static final int VERSION_MAX = VERSION_V;
2129         private int mSdkLevel = VERSION_UNMOCKED;
2130 
setBuildSdk(final int sdkLevel)2131         private void setBuildSdk(final int sdkLevel) {
2132             if (sdkLevel > VERSION_MAX) {
2133                 throw new IllegalArgumentException("setBuildSdk must not be called with"
2134                         + " Build.VERSION constants but Dependencies.VERSION_* constants");
2135             }
2136             visibleOnHandlerThread(mCsHandlerThread.getThreadHandler(), () -> mSdkLevel = sdkLevel);
2137         }
2138 
2139         @Override
isAtLeastS()2140         public boolean isAtLeastS() {
2141             return mSdkLevel == VERSION_UNMOCKED ? super.isAtLeastS()
2142                     : mSdkLevel >= VERSION_S;
2143         }
2144 
2145         @Override
isAtLeastT()2146         public boolean isAtLeastT() {
2147             return mSdkLevel == VERSION_UNMOCKED ? super.isAtLeastT()
2148                     : mSdkLevel >= VERSION_T;
2149         }
2150 
2151         @Override
isAtLeastU()2152         public boolean isAtLeastU() {
2153             return mSdkLevel == VERSION_UNMOCKED ? super.isAtLeastU()
2154                     : mSdkLevel >= VERSION_U;
2155         }
2156 
2157         @Override
getBpfNetMaps(Context context, INetd netd)2158         public BpfNetMaps getBpfNetMaps(Context context, INetd netd) {
2159             return mBpfNetMaps;
2160         }
2161 
2162         @Override
getClatCoordinator(INetd netd)2163         public ClatCoordinator getClatCoordinator(INetd netd) {
2164             return mClatCoordinator;
2165         }
2166 
2167         final ArrayTrackRecord<Pair<String, Long>> mRateLimitHistory = new ArrayTrackRecord<>();
2168         final Map<String, Long> mActiveRateLimit = new HashMap<>();
2169 
2170         @Override
enableIngressRateLimit(final String iface, final long rateInBytesPerSecond)2171         public void enableIngressRateLimit(final String iface, final long rateInBytesPerSecond) {
2172             mRateLimitHistory.add(new Pair<>(iface, rateInBytesPerSecond));
2173             // Due to a TC limitation, the rate limit needs to be removed before it can be
2174             // updated. Check that this happened.
2175             assertEquals(-1L, (long) mActiveRateLimit.getOrDefault(iface, -1L));
2176             mActiveRateLimit.put(iface, rateInBytesPerSecond);
2177             // verify that clsact qdisc has already been created, otherwise attaching a tc police
2178             // filter will fail.
2179             try {
2180                 verify(mMockNetd).networkAddInterface(anyInt(), eq(iface));
2181             } catch (RemoteException e) {
2182                 fail(e.getMessage());
2183             }
2184         }
2185 
2186         @Override
disableIngressRateLimit(final String iface)2187         public void disableIngressRateLimit(final String iface) {
2188             mRateLimitHistory.add(new Pair<>(iface, -1L));
2189             assertNotEquals(-1L, (long) mActiveRateLimit.getOrDefault(iface, -1L));
2190             mActiveRateLimit.put(iface, -1L);
2191         }
2192 
2193         @Override
makeBroadcastOptionsShim(BroadcastOptions options)2194         public BroadcastOptionsShim makeBroadcastOptionsShim(BroadcastOptions options) {
2195             reset(mBroadcastOptionsShim);
2196             return mBroadcastOptionsShim;
2197         }
2198 
2199         @GuardedBy("this")
2200         private boolean mForceDisableCompatChangeCheck = true;
2201 
2202         /**
2203          * By default, the {@link #isChangeEnabled(long, String, UserHandle)} will always return
2204          * true as the mForceDisableCompatChangeCheck is true and compat change check logic is
2205          * never executed. The compat change check logic can be turned on by calling this method.
2206          * If this method is called, the
2207          * {@link libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges} or
2208          * {@link libcore.junit.util.compat.CoreCompatChangeRule.DisableCompatChanges} must be
2209          * used to turn on/off the compat change flag.
2210          */
enableCompatChangeCheck()2211         private void enableCompatChangeCheck() {
2212             synchronized (this) {
2213                 mForceDisableCompatChangeCheck = false;
2214             }
2215         }
2216 
2217         @Override
isChangeEnabled(long changeId, @NonNull final String packageName, @NonNull final UserHandle user)2218         public boolean isChangeEnabled(long changeId,
2219                 @NonNull final String packageName,
2220                 @NonNull final UserHandle user) {
2221             synchronized (this) {
2222                 if (mForceDisableCompatChangeCheck) {
2223                     return false;
2224                 } else {
2225                     return super.isChangeEnabled(changeId, packageName, user);
2226                 }
2227             }
2228         }
2229 
2230         // Class to be mocked and used to verify destroy sockets methods call
2231         public class DestroySocketsWrapper {
destroyLiveTcpSockets(final Set<Range<Integer>> ranges, final Set<Integer> exemptUids)2232             public void destroyLiveTcpSockets(final Set<Range<Integer>> ranges,
2233                     final Set<Integer> exemptUids){}
destroyLiveTcpSocketsByOwnerUids(final Set<Integer> ownerUids)2234             public void destroyLiveTcpSocketsByOwnerUids(final Set<Integer> ownerUids){}
2235         }
2236 
2237         @Override @SuppressWarnings("DirectInvocationOnMock")
destroyLiveTcpSockets(final Set<Range<Integer>> ranges, final Set<Integer> exemptUids)2238         public void destroyLiveTcpSockets(final Set<Range<Integer>> ranges,
2239                 final Set<Integer> exemptUids) {
2240             // Call mocked destroyLiveTcpSockets so that test can verify this method call
2241             mDestroySocketsWrapper.destroyLiveTcpSockets(ranges, exemptUids);
2242         }
2243 
2244         @Override @SuppressWarnings("DirectInvocationOnMock")
destroyLiveTcpSocketsByOwnerUids(final Set<Integer> ownerUids)2245         public void destroyLiveTcpSocketsByOwnerUids(final Set<Integer> ownerUids) {
2246             // Call mocked destroyLiveTcpSocketsByOwnerUids so that test can verify this method call
2247             mDestroySocketsWrapper.destroyLiveTcpSocketsByOwnerUids(ownerUids);
2248         }
2249 
2250         final ArrayTrackRecord<Pair<Integer, Long>>.ReadHead mScheduledEvaluationTimeouts =
2251                 new ArrayTrackRecord<Pair<Integer, Long>>().newReadHead();
2252         @Override
scheduleEvaluationTimeout(@onNull Handler handler, @NonNull final Network network, final long delayMs)2253         public void scheduleEvaluationTimeout(@NonNull Handler handler,
2254                 @NonNull final Network network, final long delayMs) {
2255             mScheduledEvaluationTimeouts.add(new Pair<>(network.netId, delayMs));
2256             super.scheduleEvaluationTimeout(handler, network, delayMs);
2257         }
2258     }
2259 
2260     private class AutomaticOnOffKeepaliveTrackerDependencies
2261             extends AutomaticOnOffKeepaliveTracker.Dependencies {
2262         AutomaticOnOffKeepaliveTrackerDependencies(Context context) {
2263             super(context);
2264         }
2265 
2266         @Override
2267         public boolean isFeatureEnabled(@NonNull final String name, final boolean defaultEnabled) {
2268             // Tests for enabling the feature are verified in AutomaticOnOffKeepaliveTrackerTest.
2269             // Assuming enabled here to focus on ConnectivityService tests.
2270             return true;
2271         }
2272     }
2273 
2274     private static void initAlarmManager(final AlarmManager am, final Handler alarmHandler) {
2275         doAnswer(inv -> {
2276             final long when = inv.getArgument(1);
2277             final WakeupMessage wakeupMsg = inv.getArgument(3);
2278             final Handler handler = inv.getArgument(4);
2279 
2280             long delayMs = when - SystemClock.elapsedRealtime();
2281             if (delayMs < 0) delayMs = 0;
2282             if (delayMs > UNREASONABLY_LONG_ALARM_WAIT_MS) {
2283                 fail("Attempting to send msg more than " + UNREASONABLY_LONG_ALARM_WAIT_MS
2284                         + "ms into the future: " + delayMs);
2285             }
2286             alarmHandler.postDelayed(() -> handler.post(wakeupMsg::onAlarm), wakeupMsg /* token */,
2287                     delayMs);
2288 
2289             return null;
2290         }).when(am).setExact(eq(AlarmManager.ELAPSED_REALTIME_WAKEUP), anyLong(), anyString(),
2291                 any(WakeupMessage.class), any());
2292 
2293         doAnswer(inv -> {
2294             final WakeupMessage wakeupMsg = inv.getArgument(0);
2295             alarmHandler.removeCallbacksAndMessages(wakeupMsg /* token */);
2296             return null;
2297         }).when(am).cancel(any(WakeupMessage.class));
2298     }
2299 
2300     @After
2301     public void tearDown() throws Exception {
2302         unregisterDefaultNetworkCallbacks();
2303         maybeTearDownEnterpriseNetwork();
2304         setAlwaysOnNetworks(false);
2305         if (mCellAgent != null) {
2306             mCellAgent.disconnect();
2307             mCellAgent = null;
2308         }
2309         if (mWiFiAgent != null) {
2310             mWiFiAgent.disconnect();
2311             mWiFiAgent = null;
2312         }
2313         if (mEthernetAgent != null) {
2314             mEthernetAgent.disconnect();
2315             mEthernetAgent = null;
2316         }
2317 
2318         if (mQosCallbackMockHelper != null) {
2319             mQosCallbackMockHelper.tearDown();
2320             mQosCallbackMockHelper = null;
2321         }
2322         mMockVpn.disconnect();
2323         waitForIdle();
2324 
2325         FakeSettingsProvider.clearSettingsProvider();
2326         ConnectivityResources.setResourcesContextForTest(null);
2327 
2328         mCsHandlerThread.quitSafely();
2329         mCsHandlerThread.join();
2330         mAlarmManagerThread.quitSafely();
2331         mAlarmManagerThread.join();
2332     }
2333 
2334     private void mockDefaultPackages() throws Exception {
2335         final String myPackageName = mContext.getPackageName();
2336         final PackageInfo myPackageInfo = mContext.getPackageManager().getPackageInfo(
2337                 myPackageName, PackageManager.GET_PERMISSIONS);
2338         doReturn(new String[] {myPackageName}).when(mPackageManager)
2339                 .getPackagesForUid(Binder.getCallingUid());
2340         doReturn(myPackageInfo).when(mPackageManager).getPackageInfoAsUser(
2341                 eq(myPackageName), anyInt(), eq(UserHandle.getCallingUserId()));
2342 
2343         doReturn(asList(new PackageInfo[] {
2344                 buildPackageInfo(/* SYSTEM */ false, APP1_UID),
2345                 buildPackageInfo(/* SYSTEM */ false, APP2_UID),
2346                 buildPackageInfo(/* SYSTEM */ false, VPN_UID)
2347         })).when(mPackageManager).getInstalledPackagesAsUser(eq(GET_PERMISSIONS), anyInt());
2348 
2349         // Create a fake always-on VPN package.
2350         final int userId = UserHandle.getCallingUserId();
2351         final ApplicationInfo applicationInfo = new ApplicationInfo();
2352         applicationInfo.targetSdkVersion = Build.VERSION_CODES.R;  // Always-on supported in N+.
2353         doReturn(applicationInfo).when(mPackageManager).getApplicationInfoAsUser(
2354                 eq(ALWAYS_ON_PACKAGE), anyInt(), eq(userId));
2355 
2356         // Minimal mocking to keep Vpn#isAlwaysOnPackageSupported happy.
2357         ResolveInfo rInfo = new ResolveInfo();
2358         rInfo.serviceInfo = new ServiceInfo();
2359         rInfo.serviceInfo.metaData = new Bundle();
2360         final List<ResolveInfo> services = asList(new ResolveInfo[]{rInfo});
2361         doReturn(services).when(mPackageManager).queryIntentServicesAsUser(
2362                 any(), eq(PackageManager.GET_META_DATA), eq(userId));
2363         doReturn(Process.myUid()).when(mPackageManager).getPackageUidAsUser(
2364                 TEST_PACKAGE_NAME, userId);
2365         doReturn(VPN_UID).when(mPackageManager).getPackageUidAsUser(ALWAYS_ON_PACKAGE, userId);
2366     }
2367 
2368     private void verifyActiveNetwork(int transport) {
2369         // Test getActiveNetworkInfo()
2370         assertNotNull(mCm.getActiveNetworkInfo());
2371         assertEquals(transportToLegacyType(transport), mCm.getActiveNetworkInfo().getType());
2372         // Test getActiveNetwork()
2373         assertNotNull(mCm.getActiveNetwork());
2374         assertEquals(mCm.getActiveNetwork(), mCm.getActiveNetworkForUid(Process.myUid()));
2375         if (!NetworkCapabilities.isValidTransport(transport)) {
2376             throw new IllegalStateException("Unknown transport " + transport);
2377         }
2378         switch (transport) {
2379             case TRANSPORT_WIFI:
2380                 assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetwork());
2381                 break;
2382             case TRANSPORT_CELLULAR:
2383                 assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetwork());
2384                 break;
2385             case TRANSPORT_ETHERNET:
2386                 assertEquals(mEthernetAgent.getNetwork(), mCm.getActiveNetwork());
2387                 break;
2388             default:
2389                 break;
2390         }
2391         // Test getNetworkInfo(Network)
2392         assertNotNull(mCm.getNetworkInfo(mCm.getActiveNetwork()));
2393         assertEquals(transportToLegacyType(transport),
2394                 mCm.getNetworkInfo(mCm.getActiveNetwork()).getType());
2395         assertNotNull(mCm.getActiveNetworkInfoForUid(Process.myUid()));
2396         // Test getNetworkCapabilities(Network)
2397         assertNotNull(mCm.getNetworkCapabilities(mCm.getActiveNetwork()));
2398         assertTrue(mCm.getNetworkCapabilities(mCm.getActiveNetwork()).hasTransport(transport));
2399     }
2400 
2401     private void verifyNoNetwork() {
2402         waitForIdle();
2403         // Test getActiveNetworkInfo()
2404         assertNull(mCm.getActiveNetworkInfo());
2405         // Test getActiveNetwork()
2406         assertNull(mCm.getActiveNetwork());
2407         assertNull(mCm.getActiveNetworkForUid(Process.myUid()));
2408         // Test getAllNetworks()
2409         assertEmpty(mCm.getAllNetworks());
2410         assertEmpty(mCm.getAllNetworkStateSnapshots());
2411     }
2412 
2413     /**
2414      * Class to simplify expecting broadcasts using BroadcastInterceptingContext.
2415      * Ensures that the receiver is unregistered after the expected broadcast is received. This
2416      * cannot be done in the BroadcastReceiver itself because BroadcastInterceptingContext runs
2417      * the receivers' receive method while iterating over the list of receivers, and unregistering
2418      * the receiver during iteration throws ConcurrentModificationException.
2419      */
2420     private class ExpectedBroadcast extends CompletableFuture<Intent>  {
2421         private final BroadcastReceiver mReceiver;
2422 
2423         ExpectedBroadcast(BroadcastReceiver receiver) {
2424             mReceiver = receiver;
2425         }
2426 
2427         public Intent expectBroadcast(int timeoutMs) throws Exception {
2428             try {
2429                 return get(timeoutMs, TimeUnit.MILLISECONDS);
2430             } catch (TimeoutException e) {
2431                 fail("Expected broadcast not received after " + timeoutMs + " ms");
2432                 return null;
2433             } finally {
2434                 mServiceContext.unregisterReceiver(mReceiver);
2435             }
2436         }
2437 
2438         public Intent expectBroadcast() throws Exception {
2439             return expectBroadcast(BROADCAST_TIMEOUT_MS);
2440         }
2441 
2442         public void expectNoBroadcast(int timeoutMs) throws Exception {
2443             waitForIdle();
2444             try {
2445                 final Intent intent = get(timeoutMs, TimeUnit.MILLISECONDS);
2446                 fail("Unexpected broadcast: " + intent.getAction() + " " + intent.getExtras());
2447             } catch (TimeoutException expected) {
2448             } finally {
2449                 mServiceContext.unregisterReceiver(mReceiver);
2450             }
2451         }
2452     }
2453 
2454     private ExpectedBroadcast registerBroadcastReceiverThat(final String action, final int count,
2455             @NonNull final Predicate<Intent> filter) {
2456         final IntentFilter intentFilter = new IntentFilter(action);
2457         // AtomicReference allows receiver to access expected even though it is constructed later.
2458         final AtomicReference<ExpectedBroadcast> expectedRef = new AtomicReference<>();
2459         final BroadcastReceiver receiver = new BroadcastReceiver() {
2460             private int mRemaining = count;
2461             public void onReceive(Context context, Intent intent) {
2462                 logIntent(intent);
2463                 if (!filter.test(intent)) return;
2464                 if (--mRemaining == 0) {
2465                     expectedRef.get().complete(intent);
2466                 }
2467             }
2468         };
2469         final ExpectedBroadcast expected = new ExpectedBroadcast(receiver);
2470         expectedRef.set(expected);
2471         mServiceContext.registerReceiver(receiver, intentFilter);
2472         return expected;
2473     }
2474 
2475     private void logIntent(Intent intent) {
2476         final String action = intent.getAction();
2477         if (CONNECTIVITY_ACTION.equals(action)) {
2478             final int type = intent.getIntExtra(EXTRA_NETWORK_TYPE, -1);
2479             final NetworkInfo ni = intent.getParcelableExtra(EXTRA_NETWORK_INFO);
2480             Log.d(TAG, "Received " + action + ", type=" + type + " ni=" + ni);
2481         } else if (PROXY_CHANGE_ACTION.equals(action)) {
2482             final ProxyInfo proxy = (ProxyInfo) intent.getExtra(
2483                     Proxy.EXTRA_PROXY_INFO, ProxyInfo.buildPacProxy(Uri.EMPTY));
2484             Log.d(TAG, "Received " + action + ", proxy = " + proxy);
2485         } else {
2486             throw new IllegalArgumentException("Unsupported logging " + action);
2487         }
2488     }
2489 
2490     /** Expects that {@code count} CONNECTIVITY_ACTION broadcasts are received. */
2491     private ExpectedBroadcast expectConnectivityAction(final int count) {
2492         return registerBroadcastReceiverThat(CONNECTIVITY_ACTION, count, intent -> true);
2493     }
2494 
2495     private ExpectedBroadcast expectConnectivityAction(int type, NetworkInfo.DetailedState state) {
2496         return registerBroadcastReceiverThat(CONNECTIVITY_ACTION, 1, intent -> {
2497             final int actualType = intent.getIntExtra(EXTRA_NETWORK_TYPE, -1);
2498             final NetworkInfo ni = intent.getParcelableExtra(EXTRA_NETWORK_INFO);
2499             return type == actualType
2500                     && state == ni.getDetailedState()
2501                     && extraInfoInBroadcastHasExpectedNullness(ni);
2502         });
2503     }
2504 
2505     /** Expects that PROXY_CHANGE_ACTION broadcast is received. */
2506     private ExpectedBroadcast expectProxyChangeAction() {
2507         return registerBroadcastReceiverThat(PROXY_CHANGE_ACTION, 1, intent -> true);
2508     }
2509 
2510     private ExpectedBroadcast expectProxyChangeAction(ProxyInfo proxy) {
2511         return expectProxyChangeAction(actualProxy -> proxy.equals(actualProxy));
2512     }
2513 
2514     private ExpectedBroadcast expectProxyChangeAction(Predicate<ProxyInfo> tester) {
2515         return registerBroadcastReceiverThat(PROXY_CHANGE_ACTION, 1, intent -> {
2516             final ProxyInfo actualProxy = (ProxyInfo) intent.getExtra(Proxy.EXTRA_PROXY_INFO,
2517                     ProxyInfo.buildPacProxy(Uri.EMPTY));
2518             return tester.test(actualProxy);
2519         });
2520     }
2521 
2522     private boolean extraInfoInBroadcastHasExpectedNullness(NetworkInfo ni) {
2523         final DetailedState state = ni.getDetailedState();
2524         if (state == DetailedState.CONNECTED && ni.getExtraInfo() == null) return false;
2525         // Expect a null extraInfo if the network is CONNECTING, because a CONNECTIVITY_ACTION
2526         // broadcast with a state of CONNECTING only happens due to legacy VPN lockdown, which also
2527         // nulls out extraInfo.
2528         if (state == DetailedState.CONNECTING && ni.getExtraInfo() != null) return false;
2529         // Can't make any assertions about DISCONNECTED broadcasts. When a network actually
2530         // disconnects, disconnectAndDestroyNetwork sets its state to DISCONNECTED and its extraInfo
2531         // to null. But if the DISCONNECTED broadcast is just simulated by LegacyTypeTracker due to
2532         // a network switch, extraInfo will likely be populated.
2533         // This is likely a bug in CS, but likely not one we can fix without impacting apps.
2534         return true;
2535     }
2536 
2537     @Test
2538     public void testNetworkTypes() {
2539         // Ensure that our mocks for the networkAttributes config variable work as expected. If they
2540         // don't, then tests that depend on CONNECTIVITY_ACTION broadcasts for these network types
2541         // will fail. Failing here is much easier to debug.
2542         assertTrue(mCm.isNetworkSupported(TYPE_WIFI));
2543         assertTrue(mCm.isNetworkSupported(TYPE_MOBILE));
2544         assertTrue(mCm.isNetworkSupported(TYPE_MOBILE_MMS));
2545         assertTrue(mCm.isNetworkSupported(TYPE_MOBILE_FOTA));
2546         assertFalse(mCm.isNetworkSupported(TYPE_PROXY));
2547 
2548         // Check that TYPE_ETHERNET is supported. Unlike the asserts above, which only validate our
2549         // mocks, this assert exercises the ConnectivityService code path that ensures that
2550         // TYPE_ETHERNET is supported if the ethernet service is running.
2551         assertTrue(mCm.isNetworkSupported(TYPE_ETHERNET));
2552     }
2553 
2554     @Test
2555     public void testNetworkFeature() throws Exception {
2556         // Connect the cell agent and wait for the connected broadcast.
2557         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
2558         mCellAgent.addCapability(NET_CAPABILITY_SUPL);
2559         ExpectedBroadcast b = expectConnectivityAction(TYPE_MOBILE, DetailedState.CONNECTED);
2560         mCellAgent.connect(true);
2561         b.expectBroadcast();
2562 
2563         // Build legacy request for SUPL.
2564         final NetworkCapabilities legacyCaps = new NetworkCapabilities();
2565         legacyCaps.addTransportType(TRANSPORT_CELLULAR);
2566         legacyCaps.addCapability(NET_CAPABILITY_SUPL);
2567         final NetworkRequest legacyRequest = new NetworkRequest(legacyCaps, TYPE_MOBILE_SUPL,
2568                 ConnectivityManager.REQUEST_ID_UNSET, NetworkRequest.Type.REQUEST);
2569 
2570         // File request, withdraw it and make sure no broadcast is sent
2571         b = expectConnectivityAction(1);
2572         final TestNetworkCallback callback = new TestNetworkCallback();
2573         mCm.requestNetwork(legacyRequest, callback);
2574         callback.expect(AVAILABLE, mCellAgent);
2575         mCm.unregisterNetworkCallback(callback);
2576         b.expectNoBroadcast(800);  // 800ms long enough to at least flake if this is sent
2577 
2578         // Disconnect the network and expect mobile disconnected broadcast.
2579         b = expectConnectivityAction(TYPE_MOBILE, DetailedState.DISCONNECTED);
2580         mCellAgent.disconnect();
2581         b.expectBroadcast();
2582     }
2583 
2584     @Test
2585     public void testLingering() throws Exception {
2586         verifyNoNetwork();
2587         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
2588         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
2589         assertNull(mCm.getActiveNetworkInfo());
2590         assertNull(mCm.getActiveNetwork());
2591         // Test bringing up validated cellular.
2592         ExpectedBroadcast b = expectConnectivityAction(TYPE_MOBILE, DetailedState.CONNECTED);
2593         mCellAgent.connect(true);
2594         b.expectBroadcast();
2595         verifyActiveNetwork(TRANSPORT_CELLULAR);
2596         assertLength(2, mCm.getAllNetworks());
2597         assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork())
2598                 || mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork()));
2599         assertTrue(mCm.getAllNetworks()[0].equals(mWiFiAgent.getNetwork())
2600                 || mCm.getAllNetworks()[1].equals(mWiFiAgent.getNetwork()));
2601         // Test bringing up validated WiFi.
2602         b = expectConnectivityAction(2);
2603         mWiFiAgent.connect(true);
2604         b.expectBroadcast();
2605         verifyActiveNetwork(TRANSPORT_WIFI);
2606         assertLength(2, mCm.getAllNetworks());
2607         assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork())
2608                 || mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork()));
2609         assertTrue(mCm.getAllNetworks()[0].equals(mCellAgent.getNetwork())
2610                 || mCm.getAllNetworks()[1].equals(mCellAgent.getNetwork()));
2611         // Test cellular linger timeout.
2612         mCellAgent.expectDisconnected();
2613         waitForIdle();
2614         assertLength(1, mCm.getAllNetworks());
2615         verifyActiveNetwork(TRANSPORT_WIFI);
2616         assertLength(1, mCm.getAllNetworks());
2617         assertEquals(mCm.getAllNetworks()[0], mCm.getActiveNetwork());
2618         // Test WiFi disconnect.
2619         b = expectConnectivityAction(1);
2620         mWiFiAgent.disconnect();
2621         b.expectBroadcast();
2622         verifyNoNetwork();
2623     }
2624 
2625     /**
2626      * Verify a newly created network will be inactive instead of torn down even if no one is
2627      * requesting.
2628      */
2629     @Test
2630     public void testNewNetworkInactive() throws Exception {
2631         // Create a callback that monitoring the testing network.
2632         final TestNetworkCallback listenCallback = new TestNetworkCallback();
2633         mCm.registerNetworkCallback(new NetworkRequest.Builder().build(), listenCallback);
2634 
2635         // 1. Create a network that is not requested by anyone, and does not satisfy any of the
2636         // default requests. Verify that the network will be inactive instead of torn down.
2637         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
2638         mWiFiAgent.connectWithoutInternet();
2639         listenCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
2640         listenCallback.assertNoCallback();
2641 
2642         // Verify that the network will be torn down after nascent expiry. A small period of time
2643         // is added in case of flakiness.
2644         final int nascentTimeoutMs =
2645                 mService.mNascentDelayMs + mService.mNascentDelayMs / 4;
2646         listenCallback.expect(LOST, mWiFiAgent, nascentTimeoutMs);
2647 
2648         // 2. Create a network that is satisfied by a request comes later.
2649         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
2650         mWiFiAgent.connectWithoutInternet();
2651         listenCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
2652         final NetworkRequest wifiRequest = new NetworkRequest.Builder()
2653                 .addTransportType(TRANSPORT_WIFI).build();
2654         final TestNetworkCallback wifiCallback = new TestNetworkCallback();
2655         mCm.requestNetwork(wifiRequest, wifiCallback);
2656         wifiCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
2657 
2658         // Verify that the network will be kept since the request is still satisfied. And is able
2659         // to get disconnected as usual if the request is released after the nascent timer expires.
2660         listenCallback.assertNoCallback(nascentTimeoutMs);
2661         mCm.unregisterNetworkCallback(wifiCallback);
2662         listenCallback.expect(LOST, mWiFiAgent);
2663 
2664         // 3. Create a network that is satisfied by a request comes later.
2665         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
2666         mWiFiAgent.connectWithoutInternet();
2667         listenCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
2668         mCm.requestNetwork(wifiRequest, wifiCallback);
2669         wifiCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
2670 
2671         // Verify that the network will still be torn down after the request gets removed.
2672         mCm.unregisterNetworkCallback(wifiCallback);
2673         listenCallback.expect(LOST, mWiFiAgent);
2674 
2675         // There is no need to ensure that LOSING is never sent in the common case that the
2676         // network immediately satisfies a request that was already present, because it is already
2677         // verified anywhere whenever {@code TestNetworkCallback#expectAvailable*} is called.
2678 
2679         mCm.unregisterNetworkCallback(listenCallback);
2680     }
2681 
2682     /**
2683      * Verify a newly created network will be inactive and switch to background if only background
2684      * request is satisfied.
2685      */
2686     @Test
2687     public void testNewNetworkInactive_bgNetwork() throws Exception {
2688         // Create a callback that monitoring the wifi network.
2689         final TestNetworkCallback wifiListenCallback = new TestNetworkCallback();
2690         mCm.registerNetworkCallback(new NetworkRequest.Builder()
2691                 .addTransportType(TRANSPORT_WIFI).build(), wifiListenCallback);
2692 
2693         // Create callbacks that can monitor background and foreground mobile networks.
2694         // This is done by granting using background networks permission before registration. Thus,
2695         // the service will not add {@code NET_CAPABILITY_FOREGROUND} by default.
2696         grantUsingBackgroundNetworksPermissionForUid(Binder.getCallingUid());
2697         final TestNetworkCallback bgMobileListenCallback = new TestNetworkCallback();
2698         final TestNetworkCallback fgMobileListenCallback = new TestNetworkCallback();
2699         mCm.registerNetworkCallback(new NetworkRequest.Builder()
2700                 .addTransportType(TRANSPORT_CELLULAR).build(), bgMobileListenCallback);
2701         mCm.registerNetworkCallback(new NetworkRequest.Builder()
2702                 .addTransportType(TRANSPORT_CELLULAR)
2703                 .addCapability(NET_CAPABILITY_FOREGROUND).build(), fgMobileListenCallback);
2704 
2705         // Connect wifi, which satisfies default request.
2706         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
2707         mWiFiAgent.connect(true);
2708         wifiListenCallback.expectAvailableThenValidatedCallbacks(mWiFiAgent);
2709 
2710         // Connect a cellular network, verify that satisfies only the background callback.
2711         setAlwaysOnNetworks(true);
2712         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
2713         mCellAgent.connect(true);
2714         bgMobileListenCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
2715         fgMobileListenCallback.assertNoCallback();
2716         assertFalse(isForegroundNetwork(mCellAgent));
2717 
2718         mCellAgent.disconnect();
2719         bgMobileListenCallback.expect(LOST, mCellAgent);
2720         fgMobileListenCallback.assertNoCallback();
2721 
2722         mCm.unregisterNetworkCallback(wifiListenCallback);
2723         mCm.unregisterNetworkCallback(bgMobileListenCallback);
2724         mCm.unregisterNetworkCallback(fgMobileListenCallback);
2725     }
2726 
2727     @Test
2728     public void testBinderDeathAfterUnregister() throws Exception {
2729         final NetworkCapabilities caps = new NetworkCapabilities.Builder()
2730                 .addTransportType(TRANSPORT_WIFI)
2731                 .build();
2732         final Handler handler = new Handler(ConnectivityThread.getInstanceLooper());
2733         final Messenger messenger = new Messenger(handler);
2734         final CompletableFuture<Binder.DeathRecipient> deathRecipient = new CompletableFuture<>();
2735         final Binder binder = new Binder() {
2736             private DeathRecipient mDeathRecipient;
2737             @Override
2738             public void linkToDeath(@NonNull final DeathRecipient recipient, final int flags) {
2739                 synchronized (this) {
2740                     mDeathRecipient = recipient;
2741                 }
2742                 super.linkToDeath(recipient, flags);
2743                 deathRecipient.complete(recipient);
2744             }
2745 
2746             @Override
2747             public boolean unlinkToDeath(@NonNull final DeathRecipient recipient, final int flags) {
2748                 synchronized (this) {
2749                     if (null == mDeathRecipient) {
2750                         throw new IllegalStateException();
2751                     }
2752                     mDeathRecipient = null;
2753                 }
2754                 return super.unlinkToDeath(recipient, flags);
2755             }
2756         };
2757         final NetworkRequest request = mService.listenForNetwork(caps, messenger, binder,
2758                 NetworkCallback.FLAG_NONE, mContext.getOpPackageName(),
2759                 mContext.getAttributionTag());
2760         mService.releaseNetworkRequest(request);
2761         deathRecipient.get().binderDied();
2762         // Wait for the release message to be processed.
2763         waitForIdle();
2764         // After waitForIdle(), the message was processed and the service didn't crash.
2765     }
2766 
2767     // TODO : migrate to @Parameterized
2768     @Test
2769     public void testValidatedCellularOutscoresUnvalidatedWiFi_CanTimeShare() throws Exception {
2770         // The behavior of this test should be the same whether the radio can time share or not.
2771         doTestValidatedCellularOutscoresUnvalidatedWiFi(true);
2772     }
2773 
2774     // TODO : migrate to @Parameterized
2775     @Test
2776     public void testValidatedCellularOutscoresUnvalidatedWiFi_CannotTimeShare() throws Exception {
2777         doTestValidatedCellularOutscoresUnvalidatedWiFi(false);
2778     }
2779 
2780     private void doTestValidatedCellularOutscoresUnvalidatedWiFi(
2781             final boolean cellRadioTimesharingCapable) throws Exception {
2782         mService.mCellularRadioTimesharingCapable = cellRadioTimesharingCapable;
2783         // Test bringing up unvalidated WiFi
2784         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
2785         ExpectedBroadcast b = expectConnectivityAction(1);
2786         mWiFiAgent.connect(false);
2787         b.expectBroadcast();
2788         verifyActiveNetwork(TRANSPORT_WIFI);
2789         // Test bringing up unvalidated cellular
2790         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
2791         mCellAgent.connect(false);
2792         waitForIdle();
2793         verifyActiveNetwork(TRANSPORT_WIFI);
2794         // Test cellular disconnect.
2795         mCellAgent.disconnect();
2796         waitForIdle();
2797         verifyActiveNetwork(TRANSPORT_WIFI);
2798         // Test bringing up validated cellular
2799         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
2800         b = expectConnectivityAction(2);
2801         mCellAgent.connect(true);
2802         b.expectBroadcast();
2803         verifyActiveNetwork(TRANSPORT_CELLULAR);
2804         // Test cellular disconnect.
2805         b = expectConnectivityAction(2);
2806         mCellAgent.disconnect();
2807         b.expectBroadcast();
2808         verifyActiveNetwork(TRANSPORT_WIFI);
2809         // Test WiFi disconnect.
2810         b = expectConnectivityAction(1);
2811         mWiFiAgent.disconnect();
2812         b.expectBroadcast();
2813         verifyNoNetwork();
2814     }
2815 
2816     // TODO : migrate to @Parameterized
2817     @Test
2818     public void testUnvalidatedWifiOutscoresUnvalidatedCellular_CanTimeShare() throws Exception {
2819         doTestUnvalidatedWifiOutscoresUnvalidatedCellular(true);
2820     }
2821 
2822     // TODO : migrate to @Parameterized
2823     @Test
2824     public void testUnvalidatedWifiOutscoresUnvalidatedCellular_CannotTimeShare() throws Exception {
2825         doTestUnvalidatedWifiOutscoresUnvalidatedCellular(false);
2826     }
2827 
2828     private void doTestUnvalidatedWifiOutscoresUnvalidatedCellular(
2829             final boolean cellRadioTimesharingCapable) throws Exception {
2830         mService.mCellularRadioTimesharingCapable = cellRadioTimesharingCapable;
2831         // Test bringing up unvalidated cellular.
2832         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
2833         ExpectedBroadcast b = expectConnectivityAction(1);
2834         mCellAgent.connect(false);
2835         b.expectBroadcast();
2836         verifyActiveNetwork(TRANSPORT_CELLULAR);
2837         // Test bringing up unvalidated WiFi.
2838         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
2839         b = expectConnectivityAction(2);
2840         mWiFiAgent.connect(false);
2841         b.expectBroadcast();
2842         verifyActiveNetwork(TRANSPORT_WIFI);
2843         // Test WiFi disconnect.
2844         b = expectConnectivityAction(2);
2845         mWiFiAgent.disconnect();
2846         b.expectBroadcast();
2847         verifyActiveNetwork(TRANSPORT_CELLULAR);
2848         // Test cellular disconnect.
2849         b = expectConnectivityAction(1);
2850         mCellAgent.disconnect();
2851         b.expectBroadcast();
2852         verifyNoNetwork();
2853     }
2854 
2855     // TODO : migrate to @Parameterized
2856     @Test
2857     public void testUnlingeringDoesNotValidate_CanTimeShare() throws Exception {
2858         doTestUnlingeringDoesNotValidate(true);
2859     }
2860 
2861     // TODO : migrate to @Parameterized
2862     @Test
2863     public void testUnlingeringDoesNotValidate_CannotTimeShare() throws Exception {
2864         doTestUnlingeringDoesNotValidate(false);
2865     }
2866 
2867     private void doTestUnlingeringDoesNotValidate(
2868             final boolean cellRadioTimesharingCapable) throws Exception {
2869         mService.mCellularRadioTimesharingCapable = cellRadioTimesharingCapable;
2870         // Test bringing up unvalidated WiFi.
2871         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
2872         ExpectedBroadcast b = expectConnectivityAction(1);
2873         mWiFiAgent.connect(false);
2874         b.expectBroadcast();
2875         verifyActiveNetwork(TRANSPORT_WIFI);
2876         assertFalse(mCm.getNetworkCapabilities(mWiFiAgent.getNetwork()).hasCapability(
2877                 NET_CAPABILITY_VALIDATED));
2878         // Test bringing up validated cellular.
2879         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
2880         b = expectConnectivityAction(2);
2881         mCellAgent.connect(true);
2882         b.expectBroadcast();
2883         verifyActiveNetwork(TRANSPORT_CELLULAR);
2884         assertFalse(mCm.getNetworkCapabilities(mWiFiAgent.getNetwork()).hasCapability(
2885                 NET_CAPABILITY_VALIDATED));
2886         // Test cellular disconnect.
2887         b = expectConnectivityAction(2);
2888         mCellAgent.disconnect();
2889         b.expectBroadcast();
2890         verifyActiveNetwork(TRANSPORT_WIFI);
2891         // Unlingering a network should not cause it to be marked as validated.
2892         assertFalse(mCm.getNetworkCapabilities(mWiFiAgent.getNetwork()).hasCapability(
2893                 NET_CAPABILITY_VALIDATED));
2894     }
2895 
2896     // TODO : migrate to @Parameterized
2897     @Test
2898     public void testRequestMigrationToSameTransport_CanTimeShare() throws Exception {
2899         // Simulate a device where the cell radio is capable of time sharing
2900         mService.mCellularRadioTimesharingCapable = true;
2901         doTestRequestMigrationToSameTransport(TRANSPORT_CELLULAR, true);
2902         doTestRequestMigrationToSameTransport(TRANSPORT_WIFI, true);
2903         doTestRequestMigrationToSameTransport(TRANSPORT_ETHERNET, true);
2904     }
2905 
2906     // TODO : migrate to @Parameterized
2907     @Test
2908     public void testRequestMigrationToSameTransport_CannotTimeShare() throws Exception {
2909         // Simulate a device where the cell radio is not capable of time sharing
2910         mService.mCellularRadioTimesharingCapable = false;
2911         doTestRequestMigrationToSameTransport(TRANSPORT_CELLULAR, false);
2912         doTestRequestMigrationToSameTransport(TRANSPORT_WIFI, true);
2913         doTestRequestMigrationToSameTransport(TRANSPORT_ETHERNET, true);
2914     }
2915 
2916     private void doTestRequestMigrationToSameTransport(final int transport,
2917             final boolean expectLingering) throws Exception {
2918         // To speed up tests the linger delay is very short by default in tests but this
2919         // test needs to make sure the delay is not incurred so a longer value is safer (it
2920         // reduces the risk that a bug exists but goes undetected). The alarm manager in the test
2921         // throws and crashes CS if this is set to anything more than the below constant though.
2922         mService.mLingerDelayMs = UNREASONABLY_LONG_ALARM_WAIT_MS;
2923 
2924         final TestNetworkCallback generalCb = new TestNetworkCallback();
2925         final TestNetworkCallback defaultCb = new TestNetworkCallback();
2926         mCm.registerNetworkCallback(
2927                 new NetworkRequest.Builder().addTransportType(transport).build(),
2928                 generalCb);
2929         mCm.registerDefaultNetworkCallback(defaultCb);
2930 
2931         // Bring up net agent 1
2932         final TestNetworkAgentWrapper net1 = new TestNetworkAgentWrapper(transport);
2933         net1.connect(true);
2934         // Make sure the default request is on net 1
2935         generalCb.expectAvailableThenValidatedCallbacks(net1);
2936         defaultCb.expectAvailableThenValidatedCallbacks(net1);
2937 
2938         // Bring up net 2 with primary and mms
2939         final TestNetworkAgentWrapper net2 = new TestNetworkAgentWrapper(transport);
2940         net2.addCapability(NET_CAPABILITY_MMS);
2941         net2.setScore(new NetworkScore.Builder().setTransportPrimary(true).build());
2942         net2.connect(true);
2943 
2944         // Make sure the default request goes to net 2
2945         generalCb.expectAvailableCallbacksUnvalidated(net2);
2946         if (expectLingering) {
2947             generalCb.expectLosing(net1);
2948         }
2949         generalCb.expectCaps(net2, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
2950         defaultCb.expectAvailableDoubleValidatedCallbacks(net2);
2951 
2952         // Make sure cell 1 is unwanted immediately if the radio can't time share, but only
2953         // after some delay if it can.
2954         if (expectLingering) {
2955             net1.assertNotDisconnected(TEST_CALLBACK_TIMEOUT_MS); // always incurs the timeout
2956             generalCb.assertNoCallback();
2957             // assertNotDisconnected waited for TEST_CALLBACK_TIMEOUT_MS, so waiting for the
2958             // linger period gives TEST_CALLBACK_TIMEOUT_MS time for the event to process.
2959             net1.expectDisconnected(UNREASONABLY_LONG_ALARM_WAIT_MS);
2960         } else {
2961             net1.expectDisconnected(TEST_CALLBACK_TIMEOUT_MS);
2962         }
2963         net1.disconnect();
2964         generalCb.expect(LOST, net1);
2965 
2966         // Remove primary from net 2
2967         net2.setScore(new NetworkScore.Builder().build());
2968         // Request MMS
2969         final TestNetworkCallback mmsCallback = new TestNetworkCallback();
2970         mCm.requestNetwork(new NetworkRequest.Builder().addCapability(NET_CAPABILITY_MMS).build(),
2971                 mmsCallback);
2972         mmsCallback.expectAvailableCallbacksValidated(net2);
2973 
2974         // Bring up net 3 with primary but without MMS
2975         final TestNetworkAgentWrapper net3 = new TestNetworkAgentWrapper(transport);
2976         net3.setScore(new NetworkScore.Builder().setTransportPrimary(true).build());
2977         net3.connect(true);
2978 
2979         // Make sure default goes to net 3, but the MMS request doesn't
2980         generalCb.expectAvailableThenValidatedCallbacks(net3);
2981         defaultCb.expectAvailableDoubleValidatedCallbacks(net3);
2982         mmsCallback.assertNoCallback();
2983         net2.assertNotDisconnected(TEST_CALLBACK_TIMEOUT_MS); // Always incurs the timeout
2984 
2985         // Revoke MMS request and make sure net 2 is torn down with the appropriate delay
2986         mCm.unregisterNetworkCallback(mmsCallback);
2987         if (expectLingering) {
2988             // If the radio can time share, the linger delay hasn't elapsed yet, so apps will
2989             // get LOSING. If the radio can't time share, this is a hard loss, since the last
2990             // request keeping up this network has been removed and the network isn't lingering
2991             // for any other request.
2992             generalCb.expectLosing(net2);
2993             net2.assertNotDisconnected(TEST_CALLBACK_TIMEOUT_MS);
2994             // Timeout 0 because after a while LOST will actually arrive
2995             generalCb.assertNoCallback(0 /* timeoutMs */);
2996             net2.expectDisconnected(UNREASONABLY_LONG_ALARM_WAIT_MS);
2997         } else {
2998             net2.expectDisconnected(TEST_CALLBACK_TIMEOUT_MS);
2999         }
3000         net2.disconnect();
3001         generalCb.expect(LOST, net2);
3002         defaultCb.assertNoCallback();
3003 
3004         net3.disconnect();
3005         mCm.unregisterNetworkCallback(defaultCb);
3006         mCm.unregisterNetworkCallback(generalCb);
3007     }
3008 
3009     // TODO : migrate to @Parameterized
3010     @Test
3011     public void testCellularOutscoresWeakWifi_CanTimeShare() throws Exception {
3012         // The behavior of this test should be the same whether the radio can time share or not.
3013         doTestCellularOutscoresWeakWifi(true);
3014     }
3015 
3016     // TODO : migrate to @Parameterized
3017     @Test
3018     public void testCellularOutscoresWeakWifi_CannotTimeShare() throws Exception {
3019         doTestCellularOutscoresWeakWifi(false);
3020     }
3021 
3022     private void doTestCellularOutscoresWeakWifi(
3023             final boolean cellRadioTimesharingCapable) throws Exception {
3024         mService.mCellularRadioTimesharingCapable = cellRadioTimesharingCapable;
3025         // Test bringing up validated cellular.
3026         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
3027         ExpectedBroadcast b = expectConnectivityAction(1);
3028         mCellAgent.connect(true);
3029         b.expectBroadcast();
3030         verifyActiveNetwork(TRANSPORT_CELLULAR);
3031         // Test bringing up validated WiFi.
3032         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3033         b = expectConnectivityAction(2);
3034         mWiFiAgent.connect(true);
3035         b.expectBroadcast();
3036         verifyActiveNetwork(TRANSPORT_WIFI);
3037         // Test WiFi getting really weak.
3038         b = expectConnectivityAction(2);
3039         mWiFiAgent.adjustScore(-11);
3040         b.expectBroadcast();
3041         verifyActiveNetwork(TRANSPORT_CELLULAR);
3042         // Test WiFi restoring signal strength.
3043         b = expectConnectivityAction(2);
3044         mWiFiAgent.adjustScore(11);
3045         b.expectBroadcast();
3046         verifyActiveNetwork(TRANSPORT_WIFI);
3047     }
3048 
3049     // TODO : migrate to @Parameterized
3050     @Test
3051     public void testReapingNetwork_CanTimeShare() throws Exception {
3052         doTestReapingNetwork(true);
3053     }
3054 
3055     // TODO : migrate to @Parameterized
3056     @Test
3057     public void testReapingNetwork_CannotTimeShare() throws Exception {
3058         doTestReapingNetwork(false);
3059     }
3060 
3061     private void doTestReapingNetwork(
3062             final boolean cellRadioTimesharingCapable) throws Exception {
3063         mService.mCellularRadioTimesharingCapable = cellRadioTimesharingCapable;
3064         // Test bringing up WiFi without NET_CAPABILITY_INTERNET.
3065         // Expect it to be torn down immediately because it satisfies no requests.
3066         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3067         mWiFiAgent.connectWithoutInternet();
3068         mWiFiAgent.expectDisconnected();
3069         // Test bringing up cellular without NET_CAPABILITY_INTERNET.
3070         // Expect it to be torn down immediately because it satisfies no requests.
3071         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3072         mCellAgent.connectWithoutInternet();
3073         mCellAgent.expectDisconnected();
3074         // Test bringing up validated WiFi.
3075         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3076         final ExpectedBroadcast b = expectConnectivityAction(TYPE_WIFI, DetailedState.CONNECTED);
3077         mWiFiAgent.connect(true);
3078         b.expectBroadcast();
3079         verifyActiveNetwork(TRANSPORT_WIFI);
3080         // Test bringing up unvalidated cellular.
3081         // Expect it to be torn down because it could never be the highest scoring network
3082         // satisfying the default request even if it validated.
3083         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
3084         mCellAgent.connect(false);
3085         mCellAgent.expectDisconnected();
3086         verifyActiveNetwork(TRANSPORT_WIFI);
3087         mWiFiAgent.disconnect();
3088         mWiFiAgent.expectDisconnected();
3089     }
3090 
3091     // TODO : migrate to @Parameterized
3092     @Test
3093     public void testCellularFallback_CanTimeShare() throws Exception {
3094         doTestCellularFallback(true);
3095     }
3096 
3097     // TODO : migrate to @Parameterized
3098     @Test
3099     public void testCellularFallback_CannotTimeShare() throws Exception {
3100         doTestCellularFallback(false);
3101     }
3102 
3103     private void doTestCellularFallback(
3104             final boolean cellRadioTimesharingCapable) throws Exception {
3105         mService.mCellularRadioTimesharingCapable = cellRadioTimesharingCapable;
3106         // Test bringing up validated cellular.
3107         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
3108         ExpectedBroadcast b = expectConnectivityAction(1);
3109         mCellAgent.connect(true);
3110         b.expectBroadcast();
3111         verifyActiveNetwork(TRANSPORT_CELLULAR);
3112         // Test bringing up validated WiFi.
3113         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3114         b = expectConnectivityAction(2);
3115         mWiFiAgent.connect(true);
3116         b.expectBroadcast();
3117         verifyActiveNetwork(TRANSPORT_WIFI);
3118         // Reevaluate WiFi (it'll instantly fail DNS).
3119         b = expectConnectivityAction(2);
3120         assertTrue(mCm.getNetworkCapabilities(mWiFiAgent.getNetwork()).hasCapability(
3121                 NET_CAPABILITY_VALIDATED));
3122         mCm.reportBadNetwork(mWiFiAgent.getNetwork());
3123         // Should quickly fall back to Cellular.
3124         b.expectBroadcast();
3125         assertFalse(mCm.getNetworkCapabilities(mWiFiAgent.getNetwork()).hasCapability(
3126                 NET_CAPABILITY_VALIDATED));
3127         verifyActiveNetwork(TRANSPORT_CELLULAR);
3128         // Reevaluate cellular (it'll instantly fail DNS).
3129         b = expectConnectivityAction(2);
3130         assertTrue(mCm.getNetworkCapabilities(mCellAgent.getNetwork()).hasCapability(
3131                 NET_CAPABILITY_VALIDATED));
3132         mCm.reportBadNetwork(mCellAgent.getNetwork());
3133         // Should quickly fall back to WiFi.
3134         b.expectBroadcast();
3135         assertFalse(mCm.getNetworkCapabilities(mCellAgent.getNetwork()).hasCapability(
3136                 NET_CAPABILITY_VALIDATED));
3137         assertFalse(mCm.getNetworkCapabilities(mWiFiAgent.getNetwork()).hasCapability(
3138                 NET_CAPABILITY_VALIDATED));
3139         verifyActiveNetwork(TRANSPORT_WIFI);
3140     }
3141 
3142     // TODO : migrate to @Parameterized
3143     @Test
3144     public void testWiFiFallback_CanTimeShare() throws Exception {
3145         doTestWiFiFallback(true);
3146     }
3147 
3148     // TODO : migrate to @Parameterized
3149     @Test
3150     public void testWiFiFallback_CannotTimeShare() throws Exception {
3151         doTestWiFiFallback(false);
3152     }
3153 
3154     private void doTestWiFiFallback(
3155             final boolean cellRadioTimesharingCapable) throws Exception {
3156         mService.mCellularRadioTimesharingCapable = cellRadioTimesharingCapable;
3157         // Test bringing up unvalidated WiFi.
3158         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3159         ExpectedBroadcast b = expectConnectivityAction(1);
3160         mWiFiAgent.connect(false);
3161         b.expectBroadcast();
3162         verifyActiveNetwork(TRANSPORT_WIFI);
3163         // Test bringing up validated cellular.
3164         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
3165         b = expectConnectivityAction(2);
3166         mCellAgent.connect(true);
3167         b.expectBroadcast();
3168         verifyActiveNetwork(TRANSPORT_CELLULAR);
3169         // Reevaluate cellular (it'll instantly fail DNS).
3170         b = expectConnectivityAction(2);
3171         assertTrue(mCm.getNetworkCapabilities(mCellAgent.getNetwork()).hasCapability(
3172                 NET_CAPABILITY_VALIDATED));
3173         mCm.reportBadNetwork(mCellAgent.getNetwork());
3174         // Should quickly fall back to WiFi.
3175         b.expectBroadcast();
3176         assertFalse(mCm.getNetworkCapabilities(mCellAgent.getNetwork()).hasCapability(
3177                 NET_CAPABILITY_VALIDATED));
3178         verifyActiveNetwork(TRANSPORT_WIFI);
3179     }
3180 
3181     @Test
3182     public void testRequiresValidation() {
3183         assertTrue(NetworkMonitorUtils.isValidationRequired(false /* isDunValidationRequired */,
3184                 false /* isVpnValidationRequired */,
3185                 mCm.getDefaultRequest().networkCapabilities));
3186     }
3187 
3188     /**
3189      * Utility NetworkCallback for testing. The caller must explicitly test for all the callbacks
3190      * this class receives, by calling expect() exactly once each time a callback is
3191      * received. assertNoCallback may be called at any time.
3192      */
3193     private class TestNetworkCallback extends TestableNetworkCallback {
3194         TestNetworkCallback() {
3195             // In the context of this test, the testable network callbacks should use waitForIdle
3196             // before calling assertNoCallback in an effort to detect issues where a callback is
3197             // not yet sent but a message currently in the queue of a handler will cause it to
3198             // be sent soon.
3199             super(TEST_CALLBACK_TIMEOUT_MS, TEST_CALLBACK_TIMEOUT_MS,
3200                     ConnectivityServiceTest.this::waitForIdle);
3201         }
3202 
3203         public CallbackEntry.Losing expectLosing(final HasNetwork n, final long timeoutMs) {
3204             final CallbackEntry.Losing losing = expect(LOSING, n, timeoutMs);
3205             final int maxMsToLive = losing.getMaxMsToLive();
3206             if (maxMsToLive < 0 || maxMsToLive > mService.mLingerDelayMs) {
3207                 // maxMsToLive is the value that was received in the onLosing callback. That must
3208                 // not be negative, so check that.
3209                 // Also, maxMsToLive is the remaining time until the network expires.
3210                 // mService.mLingerDelayMs is how long the network takes from when it's first
3211                 // detected to be unneeded to when it expires, so maxMsToLive should never
3212                 // be greater than that.
3213                 fail(String.format("Invalid linger time value %d, must be between %d and %d",
3214                         maxMsToLive, 0, mService.mLingerDelayMs));
3215             }
3216             return losing;
3217         }
3218 
3219         public CallbackEntry.Losing expectLosing(final HasNetwork n) {
3220             return expectLosing(n, getDefaultTimeoutMs());
3221         }
3222     }
3223 
3224     // Can't be part of TestNetworkCallback because "cannot be declared static; static methods can
3225     // only be declared in a static or top level type".
3226     static void assertNoCallbacks(final long timeoutMs, TestNetworkCallback ... callbacks) {
3227         for (TestNetworkCallback c : callbacks) {
3228             c.assertNoCallback(timeoutMs);
3229         }
3230     }
3231 
3232     static void assertNoCallbacks(TestNetworkCallback ... callbacks) {
3233         for (TestNetworkCallback c : callbacks) {
3234             c.assertNoCallback(); // each callback uses its own timeout
3235         }
3236     }
3237 
3238     static void expectOnLost(TestNetworkAgentWrapper network, TestNetworkCallback ... callbacks) {
3239         for (TestNetworkCallback c : callbacks) {
3240             c.expect(LOST, network);
3241         }
3242     }
3243 
3244     static void expectAvailableCallbacksUnvalidatedWithSpecifier(TestNetworkAgentWrapper network,
3245             NetworkSpecifier specifier, TestNetworkCallback ... callbacks) {
3246         for (TestNetworkCallback c : callbacks) {
3247             c.expect(AVAILABLE, network);
3248             c.expectCaps(network, cb -> !cb.hasCapability(NET_CAPABILITY_VALIDATED)
3249                     && Objects.equals(specifier, cb.getNetworkSpecifier()));
3250             c.expect(LINK_PROPERTIES_CHANGED, network);
3251             c.expect(BLOCKED_STATUS, network);
3252         }
3253     }
3254 
3255     @Test
3256     public void testNetworkDoesntMatchRequestsUntilConnected() throws Exception {
3257         final TestNetworkCallback cb = new TestNetworkCallback();
3258         final NetworkRequest wifiRequest = new NetworkRequest.Builder()
3259                 .addTransportType(TRANSPORT_WIFI).build();
3260         mCm.requestNetwork(wifiRequest, cb);
3261         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3262         // Updating the score triggers a rematch.
3263         mWiFiAgent.setScore(new NetworkScore.Builder().build());
3264         cb.assertNoCallback();
3265         mWiFiAgent.connect(false);
3266         cb.expectAvailableCallbacksUnvalidated(mWiFiAgent);
3267         cb.assertNoCallback();
3268         mCm.unregisterNetworkCallback(cb);
3269     }
3270 
3271     @Test
3272     public void testNetworkNotVisibleUntilConnected() throws Exception {
3273         final TestNetworkCallback cb = new TestNetworkCallback();
3274         final NetworkRequest wifiRequest = new NetworkRequest.Builder()
3275                 .addTransportType(TRANSPORT_WIFI).build();
3276         mCm.registerNetworkCallback(wifiRequest, cb);
3277         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3278         final NetworkCapabilities nc = mWiFiAgent.getNetworkCapabilities();
3279         nc.addCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED);
3280         mWiFiAgent.setNetworkCapabilities(nc, true /* sendToConnectivityService */);
3281         cb.assertNoCallback();
3282         mWiFiAgent.connect(false);
3283         cb.expectAvailableCallbacksUnvalidated(mWiFiAgent);
3284         final CallbackEntry found = CollectionUtils.findLast(cb.getHistory(),
3285                 it -> it instanceof CallbackEntry.CapabilitiesChanged);
3286         assertTrue(((CallbackEntry.CapabilitiesChanged) found).getCaps()
3287                 .hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED));
3288         cb.assertNoCallback();
3289         mCm.unregisterNetworkCallback(cb);
3290     }
3291 
3292     @Test
3293     public void testStateChangeNetworkCallbacks() throws Exception {
3294         final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback();
3295         final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
3296         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
3297         final NetworkRequest genericRequest = new NetworkRequest.Builder()
3298                 .clearCapabilities().build();
3299         final NetworkRequest wifiRequest = new NetworkRequest.Builder()
3300                 .addTransportType(TRANSPORT_WIFI).build();
3301         final NetworkRequest cellRequest = new NetworkRequest.Builder()
3302                 .addTransportType(TRANSPORT_CELLULAR).build();
3303         mCm.registerNetworkCallback(genericRequest, genericNetworkCallback);
3304         mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
3305         mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
3306 
3307         // Test unvalidated networks
3308         ExpectedBroadcast b = expectConnectivityAction(1);
3309         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
3310         mCellAgent.connect(false);
3311         genericNetworkCallback.expectAvailableCallbacksUnvalidated(mCellAgent);
3312         cellNetworkCallback.expectAvailableCallbacksUnvalidated(mCellAgent);
3313         assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetwork());
3314         b.expectBroadcast();
3315         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
3316 
3317         // This should not trigger spurious onAvailable() callbacks, b/21762680.
3318         mCellAgent.adjustScore(-1);
3319         waitForIdle();
3320         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
3321         assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetwork());
3322 
3323         b = expectConnectivityAction(2);
3324         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3325         mWiFiAgent.connect(false);
3326         genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
3327         wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
3328         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetwork());
3329         b.expectBroadcast();
3330         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
3331 
3332         b = expectConnectivityAction(2);
3333         mWiFiAgent.disconnect();
3334         genericNetworkCallback.expect(CallbackEntry.LOST, mWiFiAgent);
3335         wifiNetworkCallback.expect(CallbackEntry.LOST, mWiFiAgent);
3336         cellNetworkCallback.assertNoCallback();
3337         b.expectBroadcast();
3338         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
3339 
3340         b = expectConnectivityAction(1);
3341         mCellAgent.disconnect();
3342         genericNetworkCallback.expect(CallbackEntry.LOST, mCellAgent);
3343         cellNetworkCallback.expect(CallbackEntry.LOST, mCellAgent);
3344         b.expectBroadcast();
3345         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
3346 
3347         // Test validated networks
3348         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
3349         mCellAgent.connect(true);
3350         genericNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
3351         cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
3352         assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetwork());
3353         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
3354 
3355         // This should not trigger spurious onAvailable() callbacks, b/21762680.
3356         mCellAgent.adjustScore(-1);
3357         waitForIdle();
3358         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
3359         assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetwork());
3360 
3361         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3362         mWiFiAgent.connect(true);
3363         genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
3364         genericNetworkCallback.expectLosing(mCellAgent);
3365         genericNetworkCallback.expectCaps(mWiFiAgent,
3366                 c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
3367         wifiNetworkCallback.expectAvailableThenValidatedCallbacks(mWiFiAgent);
3368         cellNetworkCallback.expectLosing(mCellAgent);
3369         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetwork());
3370         // Cell will disconnect after the lingering period. Before that elapses check that
3371         // there have been no callbacks.
3372         assertNoCallbacks(0 /* timeoutMs */,
3373                 genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
3374 
3375         mWiFiAgent.disconnect();
3376         genericNetworkCallback.expect(LOST, mWiFiAgent);
3377         wifiNetworkCallback.expect(LOST, mWiFiAgent);
3378         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
3379 
3380         mCellAgent.disconnect();
3381         genericNetworkCallback.expect(LOST, mCellAgent);
3382         cellNetworkCallback.expect(LOST, mCellAgent);
3383         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
3384     }
3385 
3386     private void doNetworkCallbacksSanitizationTest(boolean sanitized) throws Exception {
3387         final TestNetworkCallback callback = new TestNetworkCallback();
3388         final TestNetworkCallback defaultCallback = new TestNetworkCallback();
3389         final NetworkRequest wifiRequest = new NetworkRequest.Builder()
3390                 .addTransportType(TRANSPORT_WIFI).build();
3391         mCm.registerNetworkCallback(wifiRequest, callback);
3392         mCm.registerDefaultNetworkCallback(defaultCallback);
3393 
3394         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3395         mWiFiAgent.connect(false);
3396         callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
3397         defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
3398 
3399         final LinkProperties newLp = new LinkProperties();
3400         final Uri capportUrl = Uri.parse("https://capport.example.com/api");
3401         final CaptivePortalData capportData = new CaptivePortalData.Builder()
3402                 .setCaptive(true).build();
3403 
3404         final Uri expectedCapportUrl = sanitized ? null : capportUrl;
3405         newLp.setCaptivePortalApiUrl(capportUrl);
3406         mWiFiAgent.sendLinkProperties(newLp);
3407         callback.expect(LINK_PROPERTIES_CHANGED, mWiFiAgent, cb ->
3408                 Objects.equals(expectedCapportUrl, cb.getLp().getCaptivePortalApiUrl()));
3409         defaultCallback.expect(LINK_PROPERTIES_CHANGED, mWiFiAgent, cb ->
3410                 Objects.equals(expectedCapportUrl, cb.getLp().getCaptivePortalApiUrl()));
3411 
3412         final CaptivePortalData expectedCapportData = sanitized ? null : capportData;
3413         mWiFiAgent.notifyCapportApiDataChanged(capportData);
3414         callback.expect(LINK_PROPERTIES_CHANGED, mWiFiAgent, cb ->
3415                 Objects.equals(expectedCapportData, cb.getLp().getCaptivePortalData()));
3416         defaultCallback.expect(LINK_PROPERTIES_CHANGED, mWiFiAgent, cb ->
3417                 Objects.equals(expectedCapportData, cb.getLp().getCaptivePortalData()));
3418 
3419         final LinkProperties lp = mCm.getLinkProperties(mWiFiAgent.getNetwork());
3420         assertEquals(expectedCapportUrl, lp.getCaptivePortalApiUrl());
3421         assertEquals(expectedCapportData, lp.getCaptivePortalData());
3422     }
3423 
3424     @Test
3425     public void networkCallbacksSanitizationTest_Sanitize() throws Exception {
3426         mServiceContext.setPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
3427                 PERMISSION_DENIED);
3428         mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_DENIED);
3429         doNetworkCallbacksSanitizationTest(true /* sanitized */);
3430     }
3431 
3432     @Test
3433     public void networkCallbacksSanitizationTest_NoSanitize_NetworkStack() throws Exception {
3434         mServiceContext.setPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
3435                 PERMISSION_GRANTED);
3436         mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_DENIED);
3437         doNetworkCallbacksSanitizationTest(false /* sanitized */);
3438     }
3439 
3440     @Test
3441     public void networkCallbacksSanitizationTest_NoSanitize_Settings() throws Exception {
3442         mServiceContext.setPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
3443                 PERMISSION_DENIED);
3444         mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_GRANTED);
3445         doNetworkCallbacksSanitizationTest(false /* sanitized */);
3446     }
3447 
3448     @Test
3449     public void testOwnerUidCannotChange() throws Exception {
3450         final NetworkCapabilities ncTemplate = new NetworkCapabilities();
3451         final int originalOwnerUid = Process.myUid();
3452         ncTemplate.setOwnerUid(originalOwnerUid);
3453 
3454         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, new LinkProperties(), ncTemplate);
3455         mWiFiAgent.connect(false);
3456         waitForIdle();
3457 
3458         // Send ConnectivityService an update to the mWiFiAgent's capabilities that changes
3459         // the owner UID and an unrelated capability.
3460         NetworkCapabilities agentCapabilities = mWiFiAgent.getNetworkCapabilities();
3461         assertEquals(originalOwnerUid, agentCapabilities.getOwnerUid());
3462         agentCapabilities.setOwnerUid(42);
3463         assertFalse(agentCapabilities.hasCapability(NET_CAPABILITY_NOT_CONGESTED));
3464         agentCapabilities.addCapability(NET_CAPABILITY_NOT_CONGESTED);
3465         mWiFiAgent.setNetworkCapabilities(agentCapabilities, true);
3466         waitForIdle();
3467 
3468         // Owner UIDs are not visible without location permission.
3469         setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
3470                 Manifest.permission.ACCESS_FINE_LOCATION);
3471 
3472         // Check that the capability change has been applied but the owner UID is not modified.
3473         NetworkCapabilities nc = mCm.getNetworkCapabilities(mWiFiAgent.getNetwork());
3474         assertEquals(originalOwnerUid, nc.getOwnerUid());
3475         assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_CONGESTED));
3476     }
3477 
3478     @Test
3479     public void testMultipleLingering() throws Exception {
3480         // This test would be flaky with the default 120ms timer: that is short enough that
3481         // lingered networks are torn down before assertions can be run. We don't want to mock the
3482         // lingering timer to keep the WakeupMessage logic realistic: this has already proven useful
3483         // in detecting races. Furthermore, sometimes the test is running while Phenotype is running
3484         // so hot that the test doesn't get the CPU for multiple hundreds of milliseconds, so this
3485         // needs to be suitably long.
3486         mService.mLingerDelayMs = 2_000;
3487 
3488         NetworkRequest request = new NetworkRequest.Builder()
3489                 .clearCapabilities().addCapability(NET_CAPABILITY_NOT_METERED)
3490                 .build();
3491         TestNetworkCallback callback = new TestNetworkCallback();
3492         mCm.registerNetworkCallback(request, callback);
3493 
3494         TestNetworkCallback defaultCallback = new TestNetworkCallback();
3495         mCm.registerDefaultNetworkCallback(defaultCallback);
3496 
3497         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
3498         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3499         mEthernetAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
3500 
3501         mCellAgent.addCapability(NET_CAPABILITY_NOT_METERED);
3502         mWiFiAgent.addCapability(NET_CAPABILITY_NOT_METERED);
3503         mEthernetAgent.addCapability(NET_CAPABILITY_NOT_METERED);
3504 
3505         mCellAgent.connect(true);
3506         callback.expectAvailableThenValidatedCallbacks(mCellAgent);
3507         defaultCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
3508         assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetwork());
3509         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
3510 
3511         mWiFiAgent.connect(true);
3512         // We get AVAILABLE on wifi when wifi connects and satisfies our unmetered request.
3513         // We then get LOSING when wifi validates and cell is outscored.
3514         callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
3515         // TODO: Investigate sending validated before losing.
3516         callback.expectLosing(mCellAgent);
3517         callback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
3518         defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiAgent);
3519         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetwork());
3520         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
3521 
3522         mEthernetAgent.connect(true);
3523         callback.expectAvailableCallbacksUnvalidated(mEthernetAgent);
3524         // TODO: Investigate sending validated before losing.
3525         callback.expectLosing(mWiFiAgent);
3526         callback.expectCaps(mEthernetAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
3527         defaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetAgent);
3528         assertEquals(mEthernetAgent.getNetwork(), mCm.getActiveNetwork());
3529         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
3530 
3531         mEthernetAgent.disconnect();
3532         callback.expect(LOST, mEthernetAgent);
3533         defaultCallback.expect(LOST, mEthernetAgent);
3534         defaultCallback.expectAvailableCallbacksValidated(mWiFiAgent);
3535         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
3536 
3537         for (int i = 0; i < 4; i++) {
3538             TestNetworkAgentWrapper oldNetwork, newNetwork;
3539             if (i % 2 == 0) {
3540                 mWiFiAgent.adjustScore(-15);
3541                 oldNetwork = mWiFiAgent;
3542                 newNetwork = mCellAgent;
3543             } else {
3544                 mWiFiAgent.adjustScore(15);
3545                 oldNetwork = mCellAgent;
3546                 newNetwork = mWiFiAgent;
3547 
3548             }
3549             callback.expectLosing(oldNetwork);
3550             // TODO: should we send an AVAILABLE callback to newNetwork, to indicate that it is no
3551             // longer lingering?
3552             defaultCallback.expectAvailableCallbacksValidated(newNetwork);
3553             assertEquals(newNetwork.getNetwork(), mCm.getActiveNetwork());
3554         }
3555         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetwork());
3556 
3557         // Verify that if a network no longer satisfies a request, we send LOST and not LOSING, even
3558         // if the network is still up.
3559         mWiFiAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
3560         // We expect a notification about the capabilities change, and nothing else.
3561         defaultCallback.expectCaps(mWiFiAgent, c -> !c.hasCapability(NET_CAPABILITY_NOT_METERED));
3562         defaultCallback.assertNoCallback();
3563         callback.expect(LOST, mWiFiAgent);
3564         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
3565 
3566         // Wifi no longer satisfies our listen, which is for an unmetered network.
3567         // But because its score is 55, it's still up (and the default network).
3568         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetwork());
3569 
3570         // Disconnect our test networks.
3571         mWiFiAgent.disconnect();
3572         defaultCallback.expect(LOST, mWiFiAgent);
3573         defaultCallback.expectAvailableCallbacksValidated(mCellAgent);
3574         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
3575         mCellAgent.disconnect();
3576         defaultCallback.expect(LOST, mCellAgent);
3577         waitForIdle();
3578         assertEquals(null, mCm.getActiveNetwork());
3579 
3580         mCm.unregisterNetworkCallback(callback);
3581         waitForIdle();
3582 
3583         // Check that a network is only lingered or torn down if it would not satisfy a request even
3584         // if it validated.
3585         request = new NetworkRequest.Builder().clearCapabilities().build();
3586         callback = new TestNetworkCallback();
3587 
3588         mCm.registerNetworkCallback(request, callback);
3589 
3590         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
3591         mCellAgent.connect(false);   // Score: 10
3592         callback.expectAvailableCallbacksUnvalidated(mCellAgent);
3593         defaultCallback.expectAvailableCallbacksUnvalidated(mCellAgent);
3594         assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetwork());
3595         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
3596 
3597         // Bring up wifi with a score of 20.
3598         // Cell stays up because it would satisfy the default request if it validated.
3599         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3600         mWiFiAgent.connect(false);   // Score: 20
3601         callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
3602         defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
3603         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetwork());
3604         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
3605 
3606         mWiFiAgent.disconnect();
3607         callback.expect(LOST, mWiFiAgent);
3608         defaultCallback.expect(LOST, mWiFiAgent);
3609         defaultCallback.expectAvailableCallbacksUnvalidated(mCellAgent);
3610         assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetwork());
3611         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
3612 
3613         // Bring up wifi, then validate it. Previous versions would immediately tear down cell, but
3614         // it's arguably correct to linger it, since it was the default network before it validated.
3615         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3616         mWiFiAgent.connect(true);
3617         callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
3618         // TODO: Investigate sending validated before losing.
3619         callback.expectLosing(mCellAgent);
3620         callback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
3621         defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiAgent);
3622         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetwork());
3623         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
3624 
3625         mWiFiAgent.disconnect();
3626         callback.expect(LOST, mWiFiAgent);
3627         defaultCallback.expect(LOST, mWiFiAgent);
3628         defaultCallback.expectAvailableCallbacksUnvalidated(mCellAgent);
3629         mCellAgent.disconnect();
3630         callback.expect(LOST, mCellAgent);
3631         defaultCallback.expect(LOST, mCellAgent);
3632         waitForIdle();
3633         assertEquals(null, mCm.getActiveNetwork());
3634 
3635         // If a network is lingering, and we add and remove a request from it, resume lingering.
3636         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
3637         mCellAgent.connect(true);
3638         callback.expectAvailableThenValidatedCallbacks(mCellAgent);
3639         defaultCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
3640         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
3641         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3642         mWiFiAgent.connect(true);
3643         defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiAgent);
3644         callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
3645         // TODO: Investigate sending validated before losing.
3646         callback.expectLosing(mCellAgent);
3647         callback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
3648         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
3649 
3650         NetworkRequest cellRequest = new NetworkRequest.Builder()
3651                 .addTransportType(TRANSPORT_CELLULAR).build();
3652         NetworkCallback noopCallback = new NetworkCallback();
3653         mCm.requestNetwork(cellRequest, noopCallback);
3654         // TODO: should this cause an AVAILABLE callback, to indicate that the network is no longer
3655         // lingering?
3656         mCm.unregisterNetworkCallback(noopCallback);
3657         callback.expectLosing(mCellAgent);
3658 
3659         // Similar to the above: lingering can start even after the lingered request is removed.
3660         // Disconnect wifi and switch to cell.
3661         mWiFiAgent.disconnect();
3662         callback.expect(LOST, mWiFiAgent);
3663         defaultCallback.expect(LOST, mWiFiAgent);
3664         defaultCallback.expectAvailableCallbacksValidated(mCellAgent);
3665         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
3666 
3667         // Cell is now the default network. Pin it with a cell-specific request.
3668         noopCallback = new NetworkCallback();  // Can't reuse NetworkCallbacks. http://b/20701525
3669         mCm.requestNetwork(cellRequest, noopCallback);
3670 
3671         // Now connect wifi, and expect it to become the default network.
3672         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3673         mWiFiAgent.connect(true);
3674         callback.expectAvailableThenValidatedCallbacks(mWiFiAgent);
3675         defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiAgent);
3676         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
3677         // The default request is lingering on cell, but nothing happens to cell, and we send no
3678         // callbacks for it, because it's kept up by cellRequest.
3679         callback.assertNoCallback();
3680         // Now unregister cellRequest and expect cell to start lingering.
3681         mCm.unregisterNetworkCallback(noopCallback);
3682         callback.expectLosing(mCellAgent);
3683 
3684         // Let linger run its course.
3685         callback.assertNoCallback(0 /* timeoutMs */);
3686         final int lingerTimeoutMs = mService.mLingerDelayMs + mService.mLingerDelayMs / 4;
3687         callback.expect(LOST, mCellAgent, lingerTimeoutMs);
3688 
3689         // Register a TRACK_DEFAULT request and check that it does not affect lingering.
3690         TestNetworkCallback trackDefaultCallback = new TestNetworkCallback();
3691         mCm.registerDefaultNetworkCallback(trackDefaultCallback);
3692         trackDefaultCallback.expectAvailableCallbacksValidated(mWiFiAgent);
3693         mEthernetAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
3694         mEthernetAgent.connect(true);
3695         callback.expectAvailableCallbacksUnvalidated(mEthernetAgent);
3696         callback.expectLosing(mWiFiAgent);
3697         callback.expectCaps(mEthernetAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
3698         trackDefaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetAgent);
3699         defaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetAgent);
3700         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
3701 
3702         // Let linger run its course.
3703         callback.expect(LOST, mWiFiAgent, lingerTimeoutMs);
3704 
3705         // Clean up.
3706         mEthernetAgent.disconnect();
3707         callback.expect(LOST, mEthernetAgent);
3708         defaultCallback.expect(LOST, mEthernetAgent);
3709         trackDefaultCallback.expect(LOST, mEthernetAgent);
3710 
3711         mCm.unregisterNetworkCallback(callback);
3712         mCm.unregisterNetworkCallback(defaultCallback);
3713         mCm.unregisterNetworkCallback(trackDefaultCallback);
3714     }
3715 
3716     private void grantUsingBackgroundNetworksPermissionForUid(final int uid) throws Exception {
3717         grantUsingBackgroundNetworksPermissionForUid(uid, mContext.getPackageName());
3718     }
3719 
3720     private void grantUsingBackgroundNetworksPermissionForUid(
3721             final int uid, final String packageName) throws Exception {
3722         doReturn(buildPackageInfo(true /* hasSystemPermission */, uid)).when(mPackageManager)
3723                 .getPackageInfo(eq(packageName), eq(GET_PERMISSIONS));
3724 
3725         // Send a broadcast indicating a package was installed.
3726         final Intent addedIntent = new Intent(ACTION_PACKAGE_ADDED);
3727         addedIntent.putExtra(Intent.EXTRA_UID, uid);
3728         addedIntent.setData(Uri.parse("package:" + packageName));
3729         processBroadcast(addedIntent);
3730     }
3731 
3732     @Test
3733     public void testNetworkGoesIntoBackgroundAfterLinger() throws Exception {
3734         setAlwaysOnNetworks(true);
3735         grantUsingBackgroundNetworksPermissionForUid(Binder.getCallingUid());
3736         NetworkRequest request = new NetworkRequest.Builder()
3737                 .clearCapabilities()
3738                 .build();
3739         TestNetworkCallback callback = new TestNetworkCallback();
3740         mCm.registerNetworkCallback(request, callback);
3741 
3742         TestNetworkCallback defaultCallback = new TestNetworkCallback();
3743         mCm.registerDefaultNetworkCallback(defaultCallback);
3744 
3745         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
3746         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3747 
3748         mCellAgent.connect(true);
3749         callback.expectAvailableThenValidatedCallbacks(mCellAgent);
3750         defaultCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
3751 
3752         // Wifi comes up and cell lingers.
3753         mWiFiAgent.connect(true);
3754         defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiAgent);
3755         callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
3756         callback.expectLosing(mCellAgent);
3757         callback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
3758 
3759         // File a request for cellular, then release it.
3760         NetworkRequest cellRequest = new NetworkRequest.Builder()
3761                 .addTransportType(TRANSPORT_CELLULAR).build();
3762         NetworkCallback noopCallback = new NetworkCallback();
3763         mCm.requestNetwork(cellRequest, noopCallback);
3764         mCm.unregisterNetworkCallback(noopCallback);
3765         callback.expectLosing(mCellAgent);
3766 
3767         // Let linger run its course.
3768         callback.assertNoCallback();
3769         final int lingerTimeoutMs = TEST_LINGER_DELAY_MS + TEST_LINGER_DELAY_MS / 4;
3770         callback.expectCaps(mCellAgent, lingerTimeoutMs,
3771                 c -> !c.hasCapability(NET_CAPABILITY_FOREGROUND));
3772 
3773         // Clean up.
3774         mCm.unregisterNetworkCallback(defaultCallback);
3775         mCm.unregisterNetworkCallback(callback);
3776     }
3777 
3778     /** Expects the specified notification and returns the notification ID. */
3779     private int expectNotification(TestNetworkAgentWrapper agent, NotificationType type) {
3780         verify(mNotificationManager, timeout(TIMEOUT_MS)).notify(
3781                 eq(NetworkNotificationManager.tagFor(agent.getNetwork().netId)),
3782                 eq(type.eventId), any());
3783         return type.eventId;
3784     }
3785 
3786     private void expectNoNotification(@NonNull final TestNetworkAgentWrapper agent) {
3787         verify(mNotificationManager, never()).notifyAsUser(anyString(), anyInt(), any(), any());
3788     }
3789 
3790     /**
3791      * Expects the specified notification happens when the unvalidated prompt message arrives
3792      *
3793      * @return the notification ID.
3794      **/
3795     private int expectUnvalidationCheckWillNotify(TestNetworkAgentWrapper agent,
3796             NotificationType type) {
3797         mService.scheduleEvaluationTimeout(agent.getNetwork(), 0 /* delayMs */);
3798         waitForIdle();
3799         return expectNotification(agent, type);
3800     }
3801 
3802     /**
3803      * Expects that the notification for the specified network is cleared.
3804      *
3805      * This generally happens when the network disconnects or when the newtwork validates. During
3806      * normal usage the notification is also cleared by the system when the notification is tapped.
3807      */
3808     private void expectClearNotification(TestNetworkAgentWrapper agent, NotificationType type) {
3809         verify(mNotificationManager, timeout(TIMEOUT_MS)).cancel(
3810                 eq(NetworkNotificationManager.tagFor(agent.getNetwork().netId)), eq(type.eventId));
3811     }
3812 
3813     /**
3814      * Expects that no notification happens when the unvalidated prompt message arrives
3815      *
3816      * @return the notification ID.
3817      **/
3818     private void expectUnvalidationCheckWillNotNotify(TestNetworkAgentWrapper agent) {
3819         mService.scheduleEvaluationTimeout(agent.getNetwork(), 0 /*delayMs */);
3820         waitForIdle();
3821         expectNoNotification(agent);
3822     }
3823 
3824     private void expectDisconnectAndClearNotifications(TestNetworkCallback callback,
3825             TestNetworkAgentWrapper agent, NotificationType type) {
3826         callback.expect(LOST, agent);
3827         expectClearNotification(agent, type);
3828     }
3829 
3830     private NativeNetworkConfig nativeNetworkConfigPhysical(int netId, int permission) {
3831         return new NativeNetworkConfig(netId, NativeNetworkType.PHYSICAL, permission,
3832                 /*secure=*/ false, VpnManager.TYPE_VPN_NONE, /*excludeLocalRoutes=*/ false);
3833     }
3834 
3835     private NativeNetworkConfig nativeNetworkConfigVpn(int netId, boolean secure, int vpnType) {
3836         return new NativeNetworkConfig(netId, NativeNetworkType.VIRTUAL, INetd.PERMISSION_NONE,
3837                 secure, vpnType, /*excludeLocalRoutes=*/ false);
3838     }
3839 
3840     @Test
3841     public void testNetworkAgentCallbacks() throws Exception {
3842         // Keeps track of the order of events that happen in this test.
3843         final LinkedBlockingQueue<String> eventOrder = new LinkedBlockingQueue<>();
3844 
3845         final NetworkRequest request = new NetworkRequest.Builder()
3846                 .addTransportType(TRANSPORT_WIFI).build();
3847         final TestNetworkCallback callback = new TestNetworkCallback();
3848 
3849         // Expectations for state when various callbacks fire. These expectations run on the handler
3850         // thread and not on the test thread because they need to prevent the handler thread from
3851         // advancing while they examine state.
3852 
3853         // 1. When onCreated fires, netd has been told to create the network.
3854         final Consumer<NetworkAgent> onNetworkCreated = (agent) -> {
3855             eventOrder.offer("onNetworkCreated");
3856             try {
3857                 verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
3858                         agent.getNetwork().getNetId(), INetd.PERMISSION_NONE));
3859             } catch (RemoteException impossible) {
3860                 fail();
3861             }
3862         };
3863 
3864         // 2. onNetworkUnwanted isn't precisely ordered with respect to any particular events. Just
3865         //    check that it is fired at some point after disconnect.
3866         final Consumer<NetworkAgent> onNetworkUnwanted = (agent) -> {
3867             eventOrder.offer("onNetworkUnwanted");
3868         };
3869 
3870         // 3. While the teardown timer is running, connectivity APIs report the network is gone, but
3871         //    netd has not yet been told to destroy it.
3872         final Consumer<Network> duringTeardown = (network) -> {
3873             eventOrder.offer("timePasses");
3874             assertNull(mCm.getLinkProperties(network));
3875             try {
3876                 verify(mMockNetd, never()).networkDestroy(network.getNetId());
3877             } catch (RemoteException impossible) {
3878                 fail();
3879             }
3880         };
3881 
3882         // 4. After onNetworkDisconnected is called, connectivity APIs report the network is gone,
3883         // and netd has been told to destroy it.
3884         final Consumer<NetworkAgent> onNetworkDisconnected = (agent) -> {
3885             eventOrder.offer("onNetworkDisconnected");
3886             assertNull(mCm.getLinkProperties(agent.getNetwork()));
3887             try {
3888                 verify(mMockNetd).networkDestroy(agent.getNetwork().getNetId());
3889             } catch (RemoteException impossible) {
3890                 fail();
3891             }
3892         };
3893 
3894         final NetworkAgentWrapper.Callbacks callbacks = new NetworkAgentWrapper.Callbacks(
3895                 onNetworkCreated, onNetworkUnwanted, onNetworkDisconnected);
3896 
3897         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, callbacks);
3898 
3899         if (mService.shouldCreateNetworksImmediately()) {
3900             assertEquals("onNetworkCreated", eventOrder.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
3901         } else {
3902             assertNull(eventOrder.poll());
3903         }
3904 
3905         // Connect a network, and file a request for it after it has come up, to ensure the nascent
3906         // timer is cleared and the test does not have to wait for it. Filing the request after the
3907         // network has come up is necessary because ConnectivityService does not appear to clear the
3908         // nascent timer if the first request satisfied by the network was filed before the network
3909         // connected.
3910         // TODO: fix this bug, file the request before connecting, and remove the waitForIdle.
3911         mWiFiAgent.connectWithoutInternet();
3912         if (!mService.shouldCreateNetworksImmediately()) {
3913             assertEquals("onNetworkCreated", eventOrder.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
3914         } else {
3915             waitForIdle();
3916             assertNull(eventOrder.poll());
3917         }
3918         mCm.requestNetwork(request, callback);
3919         callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
3920 
3921         // Set teardown delay and make sure CS has processed it.
3922         mWiFiAgent.getNetworkAgent().setTeardownDelayMillis(300);
3923         waitForIdle();
3924 
3925         // Post the duringTeardown lambda to the handler so it fires while teardown is in progress.
3926         // The delay must be long enough it will run after the unregisterNetworkCallback has torn
3927         // down the network and started the teardown timer, and short enough that the lambda is
3928         // scheduled to run before the teardown timer.
3929         final Handler h = new Handler(mCsHandlerThread.getLooper());
3930         h.postDelayed(() -> duringTeardown.accept(mWiFiAgent.getNetwork()), 150);
3931 
3932         // Disconnect the network and check that events happened in the right order.
3933         mCm.unregisterNetworkCallback(callback);
3934         assertEquals("onNetworkUnwanted", eventOrder.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
3935         assertEquals("timePasses", eventOrder.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
3936         assertEquals("onNetworkDisconnected", eventOrder.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
3937 
3938         mCm.unregisterNetworkCallback(callback);
3939     }
3940 
3941     @Test
3942     public void testExplicitlySelected() throws Exception {
3943         final NetworkRequest request = new NetworkRequest.Builder()
3944                 .clearCapabilities().addCapability(NET_CAPABILITY_INTERNET)
3945                 .build();
3946         final TestNetworkCallback callback = new TestNetworkCallback();
3947         mCm.registerNetworkCallback(request, callback);
3948 
3949         // Bring up validated cell
3950         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
3951         mCellAgent.connect(true);
3952         callback.expectAvailableThenValidatedCallbacks(mCellAgent);
3953 
3954         // Bring up unvalidated wifi with explicitlySelected=true.
3955         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3956         mWiFiAgent.explicitlySelected(true, false);
3957         mWiFiAgent.connect(false);
3958         callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
3959 
3960         // Cell remains the default.
3961         assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetwork());
3962 
3963         // Expect a high-priority NO_INTERNET notification.
3964         expectUnvalidationCheckWillNotify(mWiFiAgent, NotificationType.NO_INTERNET);
3965 
3966         // Lower WiFi's score to lower than cell, and check that it doesn't disconnect because
3967         // it's explicitly selected.
3968         mWiFiAgent.adjustScore(-40);
3969         mWiFiAgent.adjustScore(40);
3970         callback.assertNoCallback();
3971 
3972         // If the user chooses yes on the "No Internet access, stay connected?" dialog, we switch to
3973         // wifi even though it's unvalidated.
3974         mCm.setAcceptUnvalidated(mWiFiAgent.getNetwork(), true, false);
3975         callback.expectLosing(mCellAgent);
3976         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetwork());
3977 
3978         // Disconnect wifi, and then reconnect, again with explicitlySelected=true.
3979         mWiFiAgent.disconnect();
3980         expectDisconnectAndClearNotifications(callback, mWiFiAgent, NotificationType.NO_INTERNET);
3981 
3982         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3983         mWiFiAgent.explicitlySelected(true, false);
3984         mWiFiAgent.connect(false);
3985         callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
3986 
3987         // Expect a high-priority NO_INTERNET notification.
3988         expectUnvalidationCheckWillNotify(mWiFiAgent, NotificationType.NO_INTERNET);
3989 
3990         // If the user chooses no on the "No Internet access, stay connected?" dialog, we ask the
3991         // network to disconnect.
3992         mCm.setAcceptUnvalidated(mWiFiAgent.getNetwork(), false, false);
3993         expectDisconnectAndClearNotifications(callback, mWiFiAgent, NotificationType.NO_INTERNET);
3994         reset(mNotificationManager);
3995 
3996         // Reconnect, again with explicitlySelected=true, but this time validate.
3997         // Expect no notifications.
3998         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3999         mWiFiAgent.explicitlySelected(true, false);
4000         mWiFiAgent.connect(true);
4001         callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
4002         callback.expectLosing(mCellAgent);
4003         callback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
4004         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetwork());
4005         expectUnvalidationCheckWillNotNotify(mWiFiAgent);
4006 
4007         // Now request cell so it doesn't disconnect during the test
4008         final NetworkRequest cellRequest = new NetworkRequest.Builder()
4009                 .clearCapabilities().addTransportType(TRANSPORT_CELLULAR).build();
4010         final TestNetworkCallback cellCallback = new TestNetworkCallback();
4011         mCm.requestNetwork(cellRequest, cellCallback);
4012 
4013         mEthernetAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
4014         mEthernetAgent.connect(true);
4015         callback.expectAvailableCallbacksUnvalidated(mEthernetAgent);
4016         callback.expectLosing(mWiFiAgent);
4017         callback.expectCaps(mEthernetAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
4018         assertEquals(mEthernetAgent.getNetwork(), mCm.getActiveNetwork());
4019         callback.assertNoCallback();
4020 
4021         // Disconnect wifi, and then reconnect as if the user had selected "yes, don't ask again"
4022         // (i.e., with explicitlySelected=true and acceptUnvalidated=true). Expect to switch to
4023         // wifi immediately.
4024         mWiFiAgent.disconnect();
4025         callback.expect(LOST, mWiFiAgent);
4026         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4027         mWiFiAgent.explicitlySelected(true, true);
4028         mWiFiAgent.connect(false);
4029         callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
4030         callback.expectLosing(mEthernetAgent);
4031         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetwork());
4032         mEthernetAgent.disconnect();
4033         callback.expect(LOST, mEthernetAgent);
4034         expectUnvalidationCheckWillNotNotify(mWiFiAgent);
4035 
4036         // Disconnect and reconnect with explicitlySelected=false and acceptUnvalidated=true.
4037         // Check that the network is not scored specially and that the device prefers cell data.
4038         mWiFiAgent.disconnect();
4039         callback.expect(LOST, mWiFiAgent);
4040 
4041         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4042         mWiFiAgent.explicitlySelected(false, true);
4043         mWiFiAgent.connect(false);
4044         callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
4045         assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetwork());
4046         expectUnvalidationCheckWillNotNotify(mWiFiAgent);
4047 
4048         // Clean up.
4049         mWiFiAgent.disconnect();
4050         mCellAgent.disconnect();
4051 
4052         callback.expect(LOST, mWiFiAgent);
4053         callback.expect(LOST, mCellAgent);
4054         mCm.unregisterNetworkCallback(cellCallback);
4055     }
4056 
4057     private void doTestFirstEvaluation(
4058             @NonNull final Consumer<TestNetworkAgentWrapper> doConnect,
4059             final boolean waitForSecondCaps,
4060             final boolean evaluatedByValidation)
4061             throws Exception {
4062         final NetworkRequest request = new NetworkRequest.Builder()
4063                 .addTransportType(TRANSPORT_WIFI)
4064                 .build();
4065         TestNetworkCallback callback = new TestNetworkCallback();
4066         mCm.registerNetworkCallback(request, callback);
4067 
4068         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4069         doConnect.accept(mWiFiAgent);
4070         // Expect the available callbacks, but don't require specific values for their arguments
4071         // since this method doesn't know how the network was connected.
4072         callback.expect(AVAILABLE, mWiFiAgent);
4073         callback.expect(NETWORK_CAPS_UPDATED, mWiFiAgent);
4074         callback.expect(LINK_PROPERTIES_CHANGED, mWiFiAgent);
4075         callback.expect(BLOCKED_STATUS, mWiFiAgent);
4076         if (waitForSecondCaps) {
4077             // This is necessary because of b/245893397, the same bug that happens where we use
4078             // expectAvailableDoubleValidatedCallbacks.
4079             callback.expect(NETWORK_CAPS_UPDATED, mWiFiAgent);
4080         }
4081         final NetworkAgentInfo nai =
4082                 mService.getNetworkAgentInfoForNetwork(mWiFiAgent.getNetwork());
4083         final long firstEvaluation = nai.getFirstEvaluationConcludedTime();
4084         if (evaluatedByValidation) {
4085             assertNotEquals(0L, firstEvaluation);
4086         } else {
4087             assertEquals(0L, firstEvaluation);
4088         }
4089         mService.scheduleEvaluationTimeout(mWiFiAgent.getNetwork(), 0L /* timeout */);
4090         waitForIdle();
4091         if (evaluatedByValidation) {
4092             assertEquals(firstEvaluation, nai.getFirstEvaluationConcludedTime());
4093         } else {
4094             assertNotEquals(0L, nai.getFirstEvaluationConcludedTime());
4095         }
4096         mWiFiAgent.disconnect();
4097         callback.expect(LOST, mWiFiAgent);
4098 
4099         mCm.unregisterNetworkCallback(callback);
4100     }
4101 
4102     @Test
4103     public void testEverEvaluated() throws Exception {
4104         doTestFirstEvaluation(naw -> naw.connect(true /* validated */),
4105                 true /* waitForSecondCaps */, true /* immediatelyEvaluated */);
4106         doTestFirstEvaluation(naw -> naw.connectWithPartialConnectivity(),
4107                 true /* waitForSecondCaps */, true /* immediatelyEvaluated */);
4108         doTestFirstEvaluation(naw -> naw.connectWithCaptivePortal(TEST_REDIRECT_URL, false),
4109                 true /* waitForSecondCaps */, true /* immediatelyEvaluated */);
4110         doTestFirstEvaluation(naw -> naw.connect(false /* validated */),
4111                 false /* waitForSecondCaps */, false /* immediatelyEvaluated */);
4112     }
4113 
4114     private void tryNetworkFactoryRequests(int capability) throws Exception {
4115         // Verify NOT_RESTRICTED is set appropriately
4116         final NetworkCapabilities nc = new NetworkRequest.Builder().addCapability(capability)
4117                 .build().networkCapabilities;
4118         if (capability == NET_CAPABILITY_CBS || capability == NET_CAPABILITY_DUN
4119                 || capability == NET_CAPABILITY_EIMS || capability == NET_CAPABILITY_FOTA
4120                 || capability == NET_CAPABILITY_IA || capability == NET_CAPABILITY_IMS
4121                 || capability == NET_CAPABILITY_RCS || capability == NET_CAPABILITY_XCAP
4122                 || capability == NET_CAPABILITY_VSIM || capability == NET_CAPABILITY_BIP
4123                 || capability == NET_CAPABILITY_ENTERPRISE || capability == NET_CAPABILITY_MMTEL) {
4124             assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
4125         } else {
4126             assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
4127         }
4128 
4129         NetworkCapabilities filter = new NetworkCapabilities();
4130         filter.addTransportType(TRANSPORT_CELLULAR);
4131         filter.addCapability(capability);
4132         // Add NOT_VCN_MANAGED capability into filter unconditionally since some requests will add
4133         // NOT_VCN_MANAGED automatically but not for NetworkCapabilities,
4134         // see {@code NetworkCapabilities#deduceNotVcnManagedCapability} for more details.
4135         filter.addCapability(NET_CAPABILITY_NOT_VCN_MANAGED);
4136         final HandlerThread handlerThread = new HandlerThread("testNetworkFactoryRequests");
4137         handlerThread.start();
4138         final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
4139                 mServiceContext, "testFactory", filter, mCsHandlerThread);
4140         testFactory.setScoreFilter(45);
4141         testFactory.register();
4142 
4143         final NetworkCallback networkCallback;
4144         if (capability != NET_CAPABILITY_INTERNET) {
4145             // If the capability passed in argument is part of the default request, then the
4146             // factory will see the default request. Otherwise the filter will prevent the
4147             // factory from seeing it. In that case, add a request so it can be tested.
4148             assertFalse(testFactory.getMyStartRequested());
4149             NetworkRequest request = new NetworkRequest.Builder().addCapability(capability).build();
4150             networkCallback = new NetworkCallback();
4151             mCm.requestNetwork(request, networkCallback);
4152         } else {
4153             networkCallback = null;
4154         }
4155         testFactory.expectRequestAdd();
4156         testFactory.assertRequestCountEquals(1);
4157         assertTrue(testFactory.getMyStartRequested());
4158 
4159         // Now bring in a higher scored network.
4160         TestNetworkAgentWrapper testAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
4161         // When testAgent connects, because of its score (50 legacy int / cell transport)
4162         // it will beat or equal the testFactory's offer, so the request will be removed.
4163         // Note the agent as validated only if the capability is INTERNET, as it's the only case
4164         // where it makes sense.
4165         testAgent.connect(NET_CAPABILITY_INTERNET == capability /* validated */);
4166         testAgent.addCapability(capability);
4167         testFactory.expectRequestRemove();
4168         testFactory.assertRequestCountEquals(0);
4169         assertFalse(testFactory.getMyStartRequested());
4170 
4171         // Add a request and make sure it's not sent to the factory, because the agent
4172         // is satisfying it better.
4173         final NetworkCallback cb = new ConnectivityManager.NetworkCallback();
4174         mCm.requestNetwork(new NetworkRequest.Builder().addCapability(capability).build(), cb);
4175         expectNoRequestChanged(testFactory);
4176         testFactory.assertRequestCountEquals(0);
4177         assertFalse(testFactory.getMyStartRequested());
4178 
4179         // If using legacy scores, make the test agent weak enough to have the exact same score as
4180         // the factory (50 for cell - 5 adjustment). Make sure the factory doesn't see the request.
4181         // If not using legacy score, this is a no-op and the "same score removes request" behavior
4182         // has already been tested above.
4183         testAgent.adjustScore(-5);
4184         expectNoRequestChanged(testFactory);
4185         assertFalse(testFactory.getMyStartRequested());
4186 
4187         // Make the test agent weak enough that the factory will see the two requests (the one that
4188         // was just sent, and either the default one or the one sent at the top of this test if
4189         // the default won't be seen).
4190         testAgent.setScore(new NetworkScore.Builder().setLegacyInt(2).setExiting(true).build());
4191         testFactory.expectRequestAdds(2);
4192         testFactory.assertRequestCountEquals(2);
4193         assertTrue(testFactory.getMyStartRequested());
4194 
4195         // Now unregister and make sure the request is removed.
4196         mCm.unregisterNetworkCallback(cb);
4197         testFactory.expectRequestRemove();
4198 
4199         // Bring in a bunch of requests.
4200         assertEquals(1, testFactory.getMyRequestCount());
4201         ConnectivityManager.NetworkCallback[] networkCallbacks =
4202                 new ConnectivityManager.NetworkCallback[10];
4203         for (int i = 0; i< networkCallbacks.length; i++) {
4204             networkCallbacks[i] = new ConnectivityManager.NetworkCallback();
4205             NetworkRequest.Builder builder = new NetworkRequest.Builder();
4206             builder.addCapability(capability);
4207             mCm.requestNetwork(builder.build(), networkCallbacks[i]);
4208         }
4209         testFactory.expectRequestAdds(10);
4210         testFactory.assertRequestCountEquals(11); // +1 for the default/test specific request
4211         assertTrue(testFactory.getMyStartRequested());
4212 
4213         // Remove the requests.
4214         for (int i = 0; i < networkCallbacks.length; i++) {
4215             mCm.unregisterNetworkCallback(networkCallbacks[i]);
4216         }
4217         testFactory.expectRequestRemoves(10);
4218         testFactory.assertRequestCountEquals(1);
4219         assertTrue(testFactory.getMyStartRequested());
4220 
4221         // Adjust the agent score up again. Expect the request to be withdrawn.
4222         testAgent.setScore(new NetworkScore.Builder().setLegacyInt(50).build());
4223         testFactory.expectRequestRemove();
4224         testFactory.assertRequestCountEquals(0);
4225         assertFalse(testFactory.getMyStartRequested());
4226 
4227         // Drop the higher scored network.
4228         testAgent.disconnect();
4229         testFactory.expectRequestAdd();
4230         testFactory.assertRequestCountEquals(1);
4231         assertEquals(1, testFactory.getMyRequestCount());
4232         assertTrue(testFactory.getMyStartRequested());
4233 
4234         testFactory.terminate();
4235         testFactory.assertNoRequestChanged();
4236         if (networkCallback != null) mCm.unregisterNetworkCallback(networkCallback);
4237         handlerThread.quit();
4238     }
4239 
4240     @Test
4241     public void testNetworkFactoryRequests() throws Exception {
4242         tryNetworkFactoryRequests(NET_CAPABILITY_MMS);
4243         tryNetworkFactoryRequests(NET_CAPABILITY_SUPL);
4244         tryNetworkFactoryRequests(NET_CAPABILITY_DUN);
4245         tryNetworkFactoryRequests(NET_CAPABILITY_FOTA);
4246         tryNetworkFactoryRequests(NET_CAPABILITY_IMS);
4247         tryNetworkFactoryRequests(NET_CAPABILITY_CBS);
4248         tryNetworkFactoryRequests(NET_CAPABILITY_WIFI_P2P);
4249         tryNetworkFactoryRequests(NET_CAPABILITY_IA);
4250         tryNetworkFactoryRequests(NET_CAPABILITY_RCS);
4251         tryNetworkFactoryRequests(NET_CAPABILITY_MMTEL);
4252         tryNetworkFactoryRequests(NET_CAPABILITY_XCAP);
4253         tryNetworkFactoryRequests(NET_CAPABILITY_ENTERPRISE);
4254         tryNetworkFactoryRequests(NET_CAPABILITY_EIMS);
4255         tryNetworkFactoryRequests(NET_CAPABILITY_NOT_METERED);
4256         tryNetworkFactoryRequests(NET_CAPABILITY_INTERNET);
4257         tryNetworkFactoryRequests(NET_CAPABILITY_TRUSTED);
4258         tryNetworkFactoryRequests(NET_CAPABILITY_NOT_VPN);
4259         tryNetworkFactoryRequests(NET_CAPABILITY_VSIM);
4260         tryNetworkFactoryRequests(NET_CAPABILITY_BIP);
4261         // Skipping VALIDATED and CAPTIVE_PORTAL as they're disallowed.
4262     }
4263 
4264     @Test
4265     public void testRegisterIgnoringScore() throws Exception {
4266         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4267         mWiFiAgent.setScore(new NetworkScore.Builder().setLegacyInt(90).build());
4268         mWiFiAgent.connect(true /* validated */);
4269 
4270         // Make sure the factory sees the default network
4271         final NetworkCapabilities filter = new NetworkCapabilities();
4272         filter.addTransportType(TRANSPORT_CELLULAR);
4273         filter.addCapability(NET_CAPABILITY_INTERNET);
4274         filter.addCapability(NET_CAPABILITY_NOT_VCN_MANAGED);
4275         final HandlerThread handlerThread = new HandlerThread("testNetworkFactoryRequests");
4276         handlerThread.start();
4277         final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
4278                 mServiceContext, "testFactory", filter, mCsHandlerThread);
4279         testFactory.register();
4280 
4281         final MockNetworkFactory testFactoryAll = new MockNetworkFactory(handlerThread.getLooper(),
4282                 mServiceContext, "testFactoryAll", filter, mCsHandlerThread);
4283         testFactoryAll.registerIgnoringScore();
4284 
4285         // The regular test factory should not see the request, because WiFi is stronger than cell.
4286         expectNoRequestChanged(testFactory);
4287         // With ignoringScore though the request is seen.
4288         testFactoryAll.expectRequestAdd();
4289 
4290         // The legacy int will be ignored anyway, set the only other knob to true
4291         mWiFiAgent.setScore(new NetworkScore.Builder().setLegacyInt(110)
4292                 .setTransportPrimary(true).build());
4293 
4294         expectNoRequestChanged(testFactory); // still not seeing the request
4295         expectNoRequestChanged(testFactoryAll); // still seeing the request
4296 
4297         mWiFiAgent.disconnect();
4298     }
4299 
4300     @Test
4301     public void testNetworkFactoryUnregister() throws Exception {
4302         // Make sure the factory sees the default network
4303         final NetworkCapabilities filter = new NetworkCapabilities();
4304         filter.addCapability(NET_CAPABILITY_INTERNET);
4305         filter.addCapability(NET_CAPABILITY_NOT_VCN_MANAGED);
4306 
4307         final HandlerThread handlerThread = new HandlerThread("testNetworkFactoryRequests");
4308         handlerThread.start();
4309 
4310         // Checks that calling setScoreFilter on a NetworkFactory immediately before closing it
4311         // does not crash.
4312         for (int i = 0; i < 100; i++) {
4313             final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
4314                     mServiceContext, "testFactory", filter, mCsHandlerThread);
4315             // Register the factory and don't be surprised when the default request arrives.
4316             testFactory.register();
4317             testFactory.expectRequestAdd();
4318 
4319             testFactory.setScoreFilter(42);
4320             testFactory.terminate();
4321             testFactory.assertNoRequestChanged();
4322 
4323             if (i % 2 == 0) {
4324                 try {
4325                     testFactory.register();
4326                     fail("Re-registering terminated NetworkFactory should throw");
4327                 } catch (IllegalStateException expected) {
4328                 }
4329             }
4330         }
4331         handlerThread.quit();
4332     }
4333 
4334     @Test
4335     public void testNoMutableNetworkRequests() throws Exception {
4336         final PendingIntent pendingIntent = PendingIntent.getBroadcast(
4337                 mContext, 0 /* requestCode */, new Intent("a"), FLAG_IMMUTABLE);
4338         final NetworkRequest request1 = new NetworkRequest.Builder()
4339                 .addCapability(NET_CAPABILITY_VALIDATED)
4340                 .build();
4341         final NetworkRequest request2 = new NetworkRequest.Builder()
4342                 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL)
4343                 .build();
4344 
4345         final Class<IllegalArgumentException> expected = IllegalArgumentException.class;
4346         assertThrows(expected, () -> mCm.requestNetwork(request1, new NetworkCallback()));
4347         assertThrows(expected, () -> mCm.requestNetwork(request1, pendingIntent));
4348         assertThrows(expected, () -> mCm.requestNetwork(request2, new NetworkCallback()));
4349         assertThrows(expected, () -> mCm.requestNetwork(request2, pendingIntent));
4350     }
4351 
4352     @Test
4353     public void testNoAllowedUidsInNetworkRequests() throws Exception {
4354         final PendingIntent pendingIntent = PendingIntent.getBroadcast(
4355                 mContext, 0 /* requestCode */, new Intent("a"), FLAG_IMMUTABLE);
4356         final NetworkRequest r = new NetworkRequest.Builder().build();
4357         final ArraySet<Integer> allowedUids = new ArraySet<>();
4358         allowedUids.add(6);
4359         allowedUids.add(9);
4360         r.networkCapabilities.setAllowedUids(allowedUids);
4361 
4362         final Handler handler = new Handler(ConnectivityThread.getInstanceLooper());
4363         final NetworkCallback cb = new NetworkCallback();
4364 
4365         final Class<IllegalArgumentException> expected = IllegalArgumentException.class;
4366         assertThrows(expected, () -> mCm.requestNetwork(r, cb));
4367         assertThrows(expected, () -> mCm.requestNetwork(r, pendingIntent));
4368         assertThrows(expected, () -> mCm.registerNetworkCallback(r, cb));
4369         assertThrows(expected, () -> mCm.registerNetworkCallback(r, cb, handler));
4370         assertThrows(expected, () -> mCm.registerNetworkCallback(r, pendingIntent));
4371         assertThrows(expected, () -> mCm.registerBestMatchingNetworkCallback(r, cb, handler));
4372 
4373         // Make sure that resetting the access UIDs to the empty set will allow calling
4374         // requestNetwork and registerNetworkCallback.
4375         r.networkCapabilities.setAllowedUids(Collections.emptySet());
4376         mCm.requestNetwork(r, cb);
4377         mCm.unregisterNetworkCallback(cb);
4378         mCm.registerNetworkCallback(r, cb);
4379         mCm.unregisterNetworkCallback(cb);
4380     }
4381 
4382     @Test
4383     public void testMMSonWiFi() throws Exception {
4384         // Test bringing up cellular without MMS NetworkRequest gets reaped
4385         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
4386         mCellAgent.addCapability(NET_CAPABILITY_MMS);
4387         mCellAgent.connectWithoutInternet();
4388         mCellAgent.expectDisconnected();
4389         waitForIdle();
4390         assertEmpty(mCm.getAllNetworks());
4391         verifyNoNetwork();
4392 
4393         // Test bringing up validated WiFi.
4394         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4395         final ExpectedBroadcast b = expectConnectivityAction(TYPE_WIFI, DetailedState.CONNECTED);
4396         mWiFiAgent.connect(true);
4397         b.expectBroadcast();
4398         verifyActiveNetwork(TRANSPORT_WIFI);
4399 
4400         // Register MMS NetworkRequest
4401         NetworkRequest.Builder builder = new NetworkRequest.Builder();
4402         builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
4403         final TestNetworkCallback networkCallback = new TestNetworkCallback();
4404         mCm.requestNetwork(builder.build(), networkCallback);
4405 
4406         // Test bringing up unvalidated cellular with MMS
4407         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
4408         mCellAgent.addCapability(NET_CAPABILITY_MMS);
4409         mCellAgent.connectWithoutInternet();
4410         networkCallback.expectAvailableCallbacksUnvalidated(mCellAgent);
4411         verifyActiveNetwork(TRANSPORT_WIFI);
4412 
4413         // Test releasing NetworkRequest disconnects cellular with MMS
4414         mCm.unregisterNetworkCallback(networkCallback);
4415         mCellAgent.expectDisconnected();
4416         verifyActiveNetwork(TRANSPORT_WIFI);
4417     }
4418 
4419     @Test
4420     public void testMMSonCell() throws Exception {
4421         // Test bringing up cellular without MMS
4422         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
4423         ExpectedBroadcast b = expectConnectivityAction(TYPE_MOBILE, DetailedState.CONNECTED);
4424         mCellAgent.connect(false);
4425         b.expectBroadcast();
4426         verifyActiveNetwork(TRANSPORT_CELLULAR);
4427 
4428         // Register MMS NetworkRequest
4429         NetworkRequest.Builder builder = new NetworkRequest.Builder();
4430         builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
4431         final TestNetworkCallback networkCallback = new TestNetworkCallback();
4432         mCm.requestNetwork(builder.build(), networkCallback);
4433 
4434         // Test bringing up MMS cellular network
4435         TestNetworkAgentWrapper
4436                 mmsNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
4437         mmsNetworkAgent.addCapability(NET_CAPABILITY_MMS);
4438         mmsNetworkAgent.connectWithoutInternet();
4439         networkCallback.expectAvailableCallbacksUnvalidated(mmsNetworkAgent);
4440         verifyActiveNetwork(TRANSPORT_CELLULAR);
4441 
4442         // Test releasing MMS NetworkRequest does not disconnect main cellular NetworkAgent
4443         mCm.unregisterNetworkCallback(networkCallback);
4444         mmsNetworkAgent.expectDisconnected();
4445         verifyActiveNetwork(TRANSPORT_CELLULAR);
4446     }
4447 
4448     @Test
4449     public void testPartialConnectivity() throws Exception {
4450         // Register network callback.
4451         NetworkRequest request = new NetworkRequest.Builder()
4452                 .clearCapabilities().addCapability(NET_CAPABILITY_INTERNET)
4453                 .build();
4454         TestNetworkCallback callback = new TestNetworkCallback();
4455         mCm.registerNetworkCallback(request, callback);
4456 
4457         // Bring up validated mobile data.
4458         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
4459         mCellAgent.connect(true);
4460         callback.expectAvailableThenValidatedCallbacks(mCellAgent);
4461 
4462         // Bring up wifi with partial connectivity.
4463         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4464         mWiFiAgent.connectWithPartialConnectivity();
4465         callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
4466         callback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY));
4467 
4468         // Mobile data should be the default network.
4469         assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetwork());
4470         callback.assertNoCallback();
4471 
4472         // Expect a PARTIAL_CONNECTIVITY notification. The notification appears as soon as partial
4473         // connectivity is detected, and is low priority because the network was not explicitly
4474         // selected by the user. This happens if we reconnect to a network where the user previously
4475         // accepted partial connectivity without checking "always".
4476         expectNotification(mWiFiAgent, NotificationType.PARTIAL_CONNECTIVITY);
4477 
4478         // With HTTPS probe disabled, NetworkMonitor should pass the network validation with http
4479         // probe.
4480         mWiFiAgent.setNetworkPartialValid(false /* privateDnsProbeSent */);
4481         // If the user chooses yes to use this partial connectivity wifi, switch the default
4482         // network to wifi and check if wifi becomes valid or not.
4483         mCm.setAcceptPartialConnectivity(mWiFiAgent.getNetwork(), true /* accept */,
4484                 false /* always */);
4485         // If user accepts partial connectivity network,
4486         // NetworkMonitor#setAcceptPartialConnectivity() should be called too.
4487         waitForIdle();
4488         verify(mWiFiAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
4489 
4490         // Need a trigger point to let NetworkMonitor tell ConnectivityService that the network is
4491         // validated.
4492         mCm.reportNetworkConnectivity(mWiFiAgent.getNetwork(), true);
4493         callback.expectLosing(mCellAgent);
4494         NetworkCapabilities nc =
4495                 callback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
4496         assertTrue(nc.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY));
4497         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetwork());
4498 
4499         // Once the network validates, the notification disappears.
4500         expectClearNotification(mWiFiAgent, NotificationType.PARTIAL_CONNECTIVITY);
4501 
4502         // Disconnect and reconnect wifi with partial connectivity again.
4503         mWiFiAgent.disconnect();
4504         callback.expect(LOST, mWiFiAgent);
4505 
4506         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4507         mWiFiAgent.connectWithPartialConnectivity();
4508         callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
4509         callback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY));
4510 
4511         // Mobile data should be the default network.
4512         assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetwork());
4513         waitForIdle();
4514 
4515         // Expect a low-priority PARTIAL_CONNECTIVITY notification as soon as partial connectivity
4516         // is detected.
4517         expectNotification(mWiFiAgent, NotificationType.PARTIAL_CONNECTIVITY);
4518 
4519         // If the user chooses no, disconnect wifi immediately.
4520         mCm.setAcceptPartialConnectivity(mWiFiAgent.getNetwork(), false /* accept */,
4521                 false /* always */);
4522         callback.expect(LOST, mWiFiAgent);
4523         expectClearNotification(mWiFiAgent, NotificationType.PARTIAL_CONNECTIVITY);
4524         reset(mNotificationManager);
4525 
4526         // If the user accepted partial connectivity before, and the device connects to that network
4527         // again, but now the network has full connectivity, then the network shouldn't contain
4528         // NET_CAPABILITY_PARTIAL_CONNECTIVITY.
4529         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4530         // acceptUnvalidated is also used as setting for accepting partial networks.
4531         mWiFiAgent.explicitlySelected(true /* explicitlySelected */, true /* acceptUnvalidated */);
4532         mWiFiAgent.connect(true);
4533         expectUnvalidationCheckWillNotNotify(mWiFiAgent);
4534 
4535         // If user accepted partial connectivity network before,
4536         // NetworkMonitor#setAcceptPartialConnectivity() will be called in
4537         // ConnectivityService#updateNetworkInfo().
4538         callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
4539         verify(mWiFiAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
4540         callback.expectLosing(mCellAgent);
4541         nc = callback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
4542         assertFalse(nc.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY));
4543 
4544         // Wifi should be the default network.
4545         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetwork());
4546         mWiFiAgent.disconnect();
4547         callback.expect(LOST, mWiFiAgent);
4548 
4549         // The user accepted partial connectivity and selected "don't ask again". Now the user
4550         // reconnects to the partial connectivity network. Switch to wifi as soon as partial
4551         // connectivity is detected.
4552         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4553         mWiFiAgent.explicitlySelected(true /* explicitlySelected */, true /* acceptUnvalidated */);
4554         mWiFiAgent.connectWithPartialConnectivity();
4555         // If user accepted partial connectivity network before,
4556         // NetworkMonitor#setAcceptPartialConnectivity() will be called in
4557         // ConnectivityService#updateNetworkInfo().
4558         callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
4559         verify(mWiFiAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
4560         callback.expectLosing(mCellAgent);
4561         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetwork());
4562         callback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY));
4563         expectUnvalidationCheckWillNotNotify(mWiFiAgent);
4564 
4565         mWiFiAgent.setNetworkValid(false /* privateDnsProbeSent */);
4566 
4567         // Need a trigger point to let NetworkMonitor tell ConnectivityService that the network is
4568         // validated.
4569         mCm.reportNetworkConnectivity(mWiFiAgent.getNetwork(), true);
4570         callback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
4571         mWiFiAgent.disconnect();
4572         callback.expect(LOST, mWiFiAgent);
4573 
4574         // If the user accepted partial connectivity, and the device auto-reconnects to the partial
4575         // connectivity network, it should contain both PARTIAL_CONNECTIVITY and VALIDATED.
4576         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4577         mWiFiAgent.explicitlySelected(false /* explicitlySelected */, true /* acceptUnvalidated */);
4578 
4579         // NetworkMonitor will immediately (once the HTTPS probe fails...) report the network as
4580         // valid, because ConnectivityService calls setAcceptPartialConnectivity before it calls
4581         // notifyNetworkConnected.
4582         mWiFiAgent.connectWithPartialValidConnectivity(false /* privateDnsProbeSent */);
4583         callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
4584         verify(mWiFiAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
4585         callback.expectLosing(mCellAgent);
4586         callback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY)
4587                 && c.hasCapability(NET_CAPABILITY_VALIDATED));
4588         expectUnvalidationCheckWillNotNotify(mWiFiAgent);
4589         mWiFiAgent.disconnect();
4590         callback.expect(LOST, mWiFiAgent);
4591         verifyNoMoreInteractions(mNotificationManager);
4592     }
4593 
4594     @Test
4595     public void testCaptivePortalOnPartialConnectivity() throws Exception {
4596         final TestNetworkCallback wifiCallback = new TestNetworkCallback();
4597         final NetworkRequest wifiRequest = new NetworkRequest.Builder()
4598                 .addTransportType(TRANSPORT_WIFI)
4599                 .build();
4600         mCm.registerNetworkCallback(wifiRequest, wifiCallback);
4601 
4602         final TestNetworkCallback validatedCallback = new TestNetworkCallback();
4603         final NetworkRequest validatedRequest = new NetworkRequest.Builder()
4604                 .addCapability(NET_CAPABILITY_VALIDATED).build();
4605         mCm.registerNetworkCallback(validatedRequest, validatedCallback);
4606 
4607         // Bring up a network with a captive portal.
4608         // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
4609         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4610         String redirectUrl = "http://android.com/path";
4611         mWiFiAgent.connectWithCaptivePortal(redirectUrl, false /* privateDnsProbeSent */);
4612         wifiCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
4613         assertEquals(mWiFiAgent.waitForRedirectUrl(), redirectUrl);
4614 
4615         // This is necessary because of b/245893397, the same bug that happens where we use
4616         // expectAvailableDoubleValidatedCallbacks.
4617         // TODO : fix b/245893397 and remove this.
4618         wifiCallback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_CAPTIVE_PORTAL));
4619 
4620         // Check that startCaptivePortalApp sends the expected command to NetworkMonitor.
4621         mCm.startCaptivePortalApp(mWiFiAgent.getNetwork());
4622         verify(mWiFiAgent.mNetworkMonitor, timeout(TIMEOUT_MS).times(1)).launchCaptivePortalApp();
4623 
4624         // Report that the captive portal is dismissed with partial connectivity, and check that
4625         // callbacks are fired with PARTIAL and without CAPTIVE_PORTAL.
4626         mWiFiAgent.setNetworkPartial();
4627         mCm.reportNetworkConnectivity(mWiFiAgent.getNetwork(), true);
4628         waitForIdle();
4629         wifiCallback.expectCaps(mWiFiAgent,
4630                 c -> c.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY)
4631                         && !c.hasCapability(NET_CAPABILITY_CAPTIVE_PORTAL));
4632 
4633         // Report partial connectivity is accepted.
4634         mWiFiAgent.setNetworkPartialValid(false /* privateDnsProbeSent */);
4635         mCm.setAcceptPartialConnectivity(mWiFiAgent.getNetwork(), true /* accept */,
4636                 false /* always */);
4637         waitForIdle();
4638         mCm.reportNetworkConnectivity(mWiFiAgent.getNetwork(), true);
4639         wifiCallback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
4640         validatedCallback.expectAvailableCallbacksValidated(mWiFiAgent);
4641         validatedCallback.expectCaps(mWiFiAgent,
4642                 c -> c.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY));
4643 
4644         mCm.unregisterNetworkCallback(wifiCallback);
4645         mCm.unregisterNetworkCallback(validatedCallback);
4646     }
4647 
4648     @Test
4649     public void testCaptivePortal() throws Exception {
4650         final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
4651         final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
4652                 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
4653         mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
4654 
4655         final TestNetworkCallback validatedCallback = new TestNetworkCallback();
4656         final NetworkRequest validatedRequest = new NetworkRequest.Builder()
4657                 .addCapability(NET_CAPABILITY_VALIDATED).build();
4658         mCm.registerNetworkCallback(validatedRequest, validatedCallback);
4659 
4660         // Bring up a network with a captive portal.
4661         // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
4662         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4663         String firstRedirectUrl = "http://example.com/firstPath";
4664         mWiFiAgent.connectWithCaptivePortal(firstRedirectUrl, false /* privateDnsProbeSent */);
4665         captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
4666         assertEquals(mWiFiAgent.waitForRedirectUrl(), firstRedirectUrl);
4667 
4668         // Take down network.
4669         // Expect onLost callback.
4670         mWiFiAgent.disconnect();
4671         captivePortalCallback.expect(LOST, mWiFiAgent);
4672 
4673         // Bring up a network with a captive portal.
4674         // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
4675         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4676         String secondRedirectUrl = "http://example.com/secondPath";
4677         mWiFiAgent.connectWithCaptivePortal(secondRedirectUrl, false /* privateDnsProbeSent */);
4678         captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
4679         assertEquals(mWiFiAgent.waitForRedirectUrl(), secondRedirectUrl);
4680 
4681         // Make captive portal disappear then revalidate.
4682         // Expect onLost callback because network no longer provides NET_CAPABILITY_CAPTIVE_PORTAL.
4683         mWiFiAgent.setNetworkValid(false /* privateDnsProbeSent */);
4684         mCm.reportNetworkConnectivity(mWiFiAgent.getNetwork(), true);
4685         captivePortalCallback.expect(LOST, mWiFiAgent);
4686 
4687         // Expect NET_CAPABILITY_VALIDATED onAvailable callback.
4688         validatedCallback.expectAvailableDoubleValidatedCallbacks(mWiFiAgent);
4689 
4690         // Break network connectivity.
4691         // Expect NET_CAPABILITY_VALIDATED onLost callback.
4692         mWiFiAgent.setNetworkInvalid(false /* invalidBecauseOfPrivateDns */);
4693         mCm.reportNetworkConnectivity(mWiFiAgent.getNetwork(), false);
4694         validatedCallback.expect(LOST, mWiFiAgent);
4695     }
4696 
4697     private Intent startCaptivePortalApp(TestNetworkAgentWrapper networkAgent) throws Exception {
4698         Network network = networkAgent.getNetwork();
4699         // Check that startCaptivePortalApp sends the expected command to NetworkMonitor.
4700         mCm.startCaptivePortalApp(network);
4701         waitForIdle();
4702         verify(networkAgent.mNetworkMonitor).launchCaptivePortalApp();
4703 
4704         // NetworkMonitor uses startCaptivePortal(Network, Bundle) (startCaptivePortalAppInternal)
4705         final Bundle testBundle = new Bundle();
4706         final String testKey = "testkey";
4707         final String testValue = "testvalue";
4708         testBundle.putString(testKey, testValue);
4709         mServiceContext.setPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
4710                 PERMISSION_GRANTED);
4711         mCm.startCaptivePortalApp(network, testBundle);
4712         final Intent signInIntent = mServiceContext.expectStartActivityIntent(TIMEOUT_MS);
4713         assertEquals(ACTION_CAPTIVE_PORTAL_SIGN_IN, signInIntent.getAction());
4714         assertEquals(testValue, signInIntent.getStringExtra(testKey));
4715         return signInIntent;
4716     }
4717 
4718     @Test
4719     public void testCaptivePortalApp() throws Exception {
4720         final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
4721         final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
4722                 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
4723         mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
4724 
4725         final TestNetworkCallback validatedCallback = new TestNetworkCallback();
4726         final NetworkRequest validatedRequest = new NetworkRequest.Builder()
4727                 .addCapability(NET_CAPABILITY_VALIDATED).build();
4728         mCm.registerNetworkCallback(validatedRequest, validatedCallback);
4729 
4730         // Bring up wifi.
4731         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4732         mWiFiAgent.connect(true);
4733         validatedCallback.expectAvailableDoubleValidatedCallbacks(mWiFiAgent);
4734         Network wifiNetwork = mWiFiAgent.getNetwork();
4735 
4736         // Check that calling startCaptivePortalApp does nothing.
4737         final int fastTimeoutMs = 100;
4738         mCm.startCaptivePortalApp(wifiNetwork);
4739         waitForIdle();
4740         verify(mWiFiAgent.mNetworkMonitor, never()).launchCaptivePortalApp();
4741         mServiceContext.expectNoStartActivityIntent(fastTimeoutMs);
4742 
4743         // Turn into a captive portal.
4744         mWiFiAgent.setNetworkPortal("http://example.com", false /* privateDnsProbeSent */);
4745         mCm.reportNetworkConnectivity(wifiNetwork, false);
4746         captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
4747         validatedCallback.expect(LOST, mWiFiAgent);
4748         // This is necessary because of b/245893397, the same bug that happens where we use
4749         // expectAvailableDoubleValidatedCallbacks.
4750         // TODO : fix b/245893397 and remove this.
4751         captivePortalCallback.expectCaps(mWiFiAgent);
4752 
4753         startCaptivePortalApp(mWiFiAgent);
4754 
4755         // Report that the captive portal is dismissed, and check that callbacks are fired
4756         mWiFiAgent.setNetworkValid(false /* privateDnsProbeSent */);
4757         mWiFiAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
4758         validatedCallback.expectAvailableCallbacksValidated(mWiFiAgent);
4759         captivePortalCallback.expect(LOST, mWiFiAgent);
4760 
4761         mCm.unregisterNetworkCallback(validatedCallback);
4762         mCm.unregisterNetworkCallback(captivePortalCallback);
4763     }
4764 
4765     @Test
4766     public void testCaptivePortalApp_IgnoreNetwork() throws Exception {
4767         final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
4768         final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
4769                 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
4770         mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
4771 
4772         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4773         mWiFiAgent.connectWithCaptivePortal(TEST_REDIRECT_URL, false);
4774         captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
4775 
4776         final Intent signInIntent = startCaptivePortalApp(mWiFiAgent);
4777         final CaptivePortal captivePortal = signInIntent
4778                 .getParcelableExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL);
4779 
4780         captivePortal.ignoreNetwork();
4781         waitForIdle();
4782 
4783         // Since network will disconnect, ensure no notification of response to NetworkMonitor
4784         verify(mWiFiAgent.mNetworkMonitor, never())
4785                 .notifyCaptivePortalAppFinished(CaptivePortal.APP_RETURN_UNWANTED);
4786 
4787         // Report that the network is disconnected
4788         mWiFiAgent.expectDisconnected();
4789         mWiFiAgent.expectPreventReconnectReceived();
4790         verify(mWiFiAgent.mNetworkMonitor).notifyNetworkDisconnected();
4791         captivePortalCallback.expect(LOST, mWiFiAgent);
4792 
4793         mCm.unregisterNetworkCallback(captivePortalCallback);
4794     }
4795 
4796     @Test
4797     public void testAvoidOrIgnoreCaptivePortals() throws Exception {
4798         final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
4799         final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
4800                 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
4801         mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
4802 
4803         final TestNetworkCallback validatedCallback = new TestNetworkCallback();
4804         final NetworkRequest validatedRequest = new NetworkRequest.Builder()
4805                 .addCapability(NET_CAPABILITY_VALIDATED).build();
4806         mCm.registerNetworkCallback(validatedRequest, validatedCallback);
4807 
4808         setCaptivePortalMode(ConnectivitySettingsManager.CAPTIVE_PORTAL_MODE_AVOID);
4809         // Bring up a network with a captive portal.
4810         // Expect it to fail to connect and not result in any callbacks.
4811         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4812         final String firstRedirectUrl = "http://example.com/firstPath";
4813 
4814         mWiFiAgent.connectWithCaptivePortal(firstRedirectUrl, false /* privateDnsProbeSent */);
4815         mWiFiAgent.expectDisconnected();
4816         mWiFiAgent.expectPreventReconnectReceived();
4817 
4818         assertNoCallbacks(captivePortalCallback, validatedCallback);
4819     }
4820 
4821     @Test
4822     public void testCaptivePortalApi() throws Exception {
4823         mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_GRANTED);
4824 
4825         final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
4826         final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
4827                 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
4828         mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
4829 
4830         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4831         final String redirectUrl = "http://example.com/firstPath";
4832 
4833         mWiFiAgent.connectWithCaptivePortal(redirectUrl,
4834                 false /* privateDnsProbeSent */);
4835         captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
4836 
4837         final CaptivePortalData testData = new CaptivePortalData.Builder()
4838                 .setUserPortalUrl(Uri.parse(redirectUrl))
4839                 .setBytesRemaining(12345L)
4840                 .build();
4841 
4842         mWiFiAgent.notifyCapportApiDataChanged(testData);
4843 
4844         captivePortalCallback.expect(LINK_PROPERTIES_CHANGED, mWiFiAgent,
4845                 cb -> testData.equals(cb.getLp().getCaptivePortalData()));
4846 
4847         final LinkProperties newLps = new LinkProperties();
4848         newLps.setMtu(1234);
4849         mWiFiAgent.sendLinkProperties(newLps);
4850         // CaptivePortalData is not lost and unchanged when LPs are received from the NetworkAgent
4851         captivePortalCallback.expect(LINK_PROPERTIES_CHANGED, mWiFiAgent,
4852                 cb -> testData.equals(cb.getLp().getCaptivePortalData())
4853                         && cb.getLp().getMtu() == 1234);
4854     }
4855 
4856     private TestNetworkCallback setupNetworkCallbackAndConnectToWifi() throws Exception {
4857         // Grant NETWORK_SETTINGS permission to be able to receive LinkProperties change callbacks
4858         // with sensitive (captive portal) data
4859         mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_GRANTED);
4860 
4861         final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
4862         final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
4863                 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
4864         mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
4865 
4866         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4867 
4868         mWiFiAgent.connectWithCaptivePortal(TEST_REDIRECT_URL,
4869                 false /* privateDnsProbeSent */);
4870         captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
4871         return captivePortalCallback;
4872     }
4873 
4874     private class CaptivePortalTestData {
4875         CaptivePortalTestData(CaptivePortalData naPasspointData, CaptivePortalData capportData,
4876                 CaptivePortalData naOtherData, CaptivePortalData expectedMergedPasspointData,
4877                 CaptivePortalData expectedMergedOtherData) {
4878             mNaPasspointData = naPasspointData;
4879             mCapportData = capportData;
4880             mNaOtherData = naOtherData;
4881             mExpectedMergedPasspointData = expectedMergedPasspointData;
4882             mExpectedMergedOtherData = expectedMergedOtherData;
4883         }
4884 
4885         public final CaptivePortalData mNaPasspointData;
4886         public final CaptivePortalData mCapportData;
4887         public final CaptivePortalData mNaOtherData;
4888         public final CaptivePortalData mExpectedMergedPasspointData;
4889         public final CaptivePortalData mExpectedMergedOtherData;
4890 
4891     }
4892 
4893     private CaptivePortalTestData setupCaptivePortalData() {
4894         final CaptivePortalData capportData = new CaptivePortalData.Builder()
4895                 .setUserPortalUrl(Uri.parse(TEST_REDIRECT_URL))
4896                 .setVenueInfoUrl(Uri.parse(TEST_VENUE_URL_CAPPORT))
4897                 .setUserPortalUrl(Uri.parse(TEST_USER_PORTAL_API_URL_CAPPORT))
4898                 .setExpiryTime(1000000L)
4899                 .setBytesRemaining(12345L)
4900                 .build();
4901 
4902         final CaptivePortalData naPasspointData = new CaptivePortalData.Builder()
4903                 .setBytesRemaining(80802L)
4904                 .setVenueInfoUrl(Uri.parse(TEST_VENUE_URL_NA_PASSPOINT),
4905                         CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_PASSPOINT)
4906                 .setUserPortalUrl(Uri.parse(TEST_TERMS_AND_CONDITIONS_URL_NA_PASSPOINT),
4907                         CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_PASSPOINT)
4908                 .setVenueFriendlyName(TEST_FRIENDLY_NAME).build();
4909 
4910         final CaptivePortalData naOtherData = new CaptivePortalData.Builder()
4911                 .setBytesRemaining(80802L)
4912                 .setVenueInfoUrl(Uri.parse(TEST_VENUE_URL_NA_OTHER),
4913                         CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_OTHER)
4914                 .setUserPortalUrl(Uri.parse(TEST_TERMS_AND_CONDITIONS_URL_NA_OTHER),
4915                         CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_OTHER)
4916                 .setVenueFriendlyName(TEST_FRIENDLY_NAME).build();
4917 
4918         final CaptivePortalData expectedMergedPasspointData = new CaptivePortalData.Builder()
4919                 .setUserPortalUrl(Uri.parse(TEST_REDIRECT_URL))
4920                 .setBytesRemaining(12345L)
4921                 .setExpiryTime(1000000L)
4922                 .setVenueInfoUrl(Uri.parse(TEST_VENUE_URL_NA_PASSPOINT),
4923                         CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_PASSPOINT)
4924                 .setUserPortalUrl(Uri.parse(TEST_TERMS_AND_CONDITIONS_URL_NA_PASSPOINT),
4925                         CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_PASSPOINT)
4926                 .setVenueFriendlyName(TEST_FRIENDLY_NAME).build();
4927 
4928         final CaptivePortalData expectedMergedOtherData = new CaptivePortalData.Builder()
4929                 .setUserPortalUrl(Uri.parse(TEST_REDIRECT_URL))
4930                 .setBytesRemaining(12345L)
4931                 .setExpiryTime(1000000L)
4932                 .setVenueInfoUrl(Uri.parse(TEST_VENUE_URL_CAPPORT))
4933                 .setUserPortalUrl(Uri.parse(TEST_USER_PORTAL_API_URL_CAPPORT))
4934                 .setVenueFriendlyName(TEST_FRIENDLY_NAME).build();
4935         return new CaptivePortalTestData(naPasspointData, capportData, naOtherData,
4936                 expectedMergedPasspointData, expectedMergedOtherData);
4937     }
4938 
4939     @Test
4940     public void testMergeCaptivePortalApiWithFriendlyNameAndVenueUrl() throws Exception {
4941         final TestNetworkCallback captivePortalCallback = setupNetworkCallbackAndConnectToWifi();
4942         final CaptivePortalTestData captivePortalTestData = setupCaptivePortalData();
4943 
4944         // Baseline capport data
4945         mWiFiAgent.notifyCapportApiDataChanged(captivePortalTestData.mCapportData);
4946 
4947         captivePortalCallback.expect(LINK_PROPERTIES_CHANGED, mWiFiAgent,
4948                 cb -> captivePortalTestData.mCapportData.equals(cb.getLp().getCaptivePortalData()));
4949 
4950         // Venue URL, T&C URL and friendly name from Network agent with Passpoint source, confirm
4951         // that API data gets precedence on the bytes remaining.
4952         final LinkProperties linkProperties = new LinkProperties();
4953         linkProperties.setCaptivePortalData(captivePortalTestData.mNaPasspointData);
4954         mWiFiAgent.sendLinkProperties(linkProperties);
4955 
4956         // Make sure that the capport data is merged
4957         captivePortalCallback.expect(LINK_PROPERTIES_CHANGED, mWiFiAgent,
4958                 cb -> captivePortalTestData.mExpectedMergedPasspointData.equals(
4959                         cb.getLp().getCaptivePortalData()));
4960 
4961         // Now send this information from non-Passpoint source, confirm that Capport data takes
4962         // precedence
4963         linkProperties.setCaptivePortalData(captivePortalTestData.mNaOtherData);
4964         mWiFiAgent.sendLinkProperties(linkProperties);
4965 
4966         // Make sure that the capport data is merged
4967         captivePortalCallback.expect(LINK_PROPERTIES_CHANGED, mWiFiAgent,
4968                 cb -> captivePortalTestData.mExpectedMergedOtherData.equals(
4969                         cb.getLp().getCaptivePortalData()));
4970 
4971         // Create a new LP with no Network agent capport data
4972         final LinkProperties newLps = new LinkProperties();
4973         newLps.setMtu(1234);
4974         mWiFiAgent.sendLinkProperties(newLps);
4975         // CaptivePortalData is not lost and has the original values when LPs are received from the
4976         // NetworkAgent
4977         captivePortalCallback.expect(LINK_PROPERTIES_CHANGED, mWiFiAgent,
4978                 cb -> captivePortalTestData.mCapportData.equals(cb.getLp().getCaptivePortalData())
4979                         && cb.getLp().getMtu() == 1234);
4980 
4981         // Now send capport data only from the Network agent
4982         mWiFiAgent.notifyCapportApiDataChanged(null);
4983         captivePortalCallback.expect(LINK_PROPERTIES_CHANGED, mWiFiAgent,
4984                 cb -> cb.getLp().getCaptivePortalData() == null);
4985 
4986         newLps.setCaptivePortalData(captivePortalTestData.mNaPasspointData);
4987         mWiFiAgent.sendLinkProperties(newLps);
4988 
4989         // Make sure that only the network agent capport data is available
4990         captivePortalCallback.expect(LINK_PROPERTIES_CHANGED, mWiFiAgent,
4991                 cb -> captivePortalTestData.mNaPasspointData.equals(
4992                         cb.getLp().getCaptivePortalData()));
4993     }
4994 
4995     @Test
4996     public void testMergeCaptivePortalDataFromNetworkAgentFirstThenCapport() throws Exception {
4997         final TestNetworkCallback captivePortalCallback = setupNetworkCallbackAndConnectToWifi();
4998         final CaptivePortalTestData captivePortalTestData = setupCaptivePortalData();
4999 
5000         // Venue URL and friendly name from Network agent, confirm that API data gets precedence
5001         // on the bytes remaining.
5002         final LinkProperties linkProperties = new LinkProperties();
5003         linkProperties.setCaptivePortalData(captivePortalTestData.mNaPasspointData);
5004         mWiFiAgent.sendLinkProperties(linkProperties);
5005 
5006         // Make sure that the data is saved correctly
5007         captivePortalCallback.expect(LINK_PROPERTIES_CHANGED, mWiFiAgent,
5008                 cb -> captivePortalTestData.mNaPasspointData.equals(
5009                         cb.getLp().getCaptivePortalData()));
5010 
5011         // Expected merged data: Network agent data is preferred, and values that are not used by
5012         // it are merged from capport data
5013         mWiFiAgent.notifyCapportApiDataChanged(captivePortalTestData.mCapportData);
5014 
5015         // Make sure that the Capport data is merged correctly
5016         captivePortalCallback.expect(LINK_PROPERTIES_CHANGED, mWiFiAgent,
5017                 cb -> captivePortalTestData.mExpectedMergedPasspointData.equals(
5018                         cb.getLp().getCaptivePortalData()));
5019 
5020         // Now set the naData to null
5021         linkProperties.setCaptivePortalData(null);
5022         mWiFiAgent.sendLinkProperties(linkProperties);
5023 
5024         // Make sure that the Capport data is retained correctly
5025         captivePortalCallback.expect(LINK_PROPERTIES_CHANGED, mWiFiAgent,
5026                 cb -> captivePortalTestData.mCapportData.equals(cb.getLp().getCaptivePortalData()));
5027     }
5028 
5029     @Test
5030     public void testMergeCaptivePortalDataFromNetworkAgentOtherSourceFirstThenCapport()
5031             throws Exception {
5032         final TestNetworkCallback captivePortalCallback = setupNetworkCallbackAndConnectToWifi();
5033         final CaptivePortalTestData captivePortalTestData = setupCaptivePortalData();
5034 
5035         // Venue URL and friendly name from Network agent, confirm that API data gets precedence
5036         // on the bytes remaining.
5037         final LinkProperties linkProperties = new LinkProperties();
5038         linkProperties.setCaptivePortalData(captivePortalTestData.mNaOtherData);
5039         mWiFiAgent.sendLinkProperties(linkProperties);
5040 
5041         // Make sure that the data is saved correctly
5042         captivePortalCallback.expect(LINK_PROPERTIES_CHANGED, mWiFiAgent,
5043                 cb -> captivePortalTestData.mNaOtherData.equals(cb.getLp().getCaptivePortalData()));
5044 
5045         // Expected merged data: Network agent data is preferred, and values that are not used by
5046         // it are merged from capport data
5047         mWiFiAgent.notifyCapportApiDataChanged(captivePortalTestData.mCapportData);
5048 
5049         // Make sure that the Capport data is merged correctly
5050         captivePortalCallback.expect(LINK_PROPERTIES_CHANGED, mWiFiAgent,
5051                 cb -> captivePortalTestData.mExpectedMergedOtherData.equals(
5052                         cb.getLp().getCaptivePortalData()));
5053     }
5054 
5055     private NetworkRequest.Builder newWifiRequestBuilder() {
5056         return new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI);
5057     }
5058 
5059     // A NetworkSpecifier subclass that matches all networks but must not be visible to apps.
5060     static class ConfidentialMatchAllNetworkSpecifier extends NetworkSpecifier implements
5061             Parcelable {
5062         public static final Parcelable.Creator<ConfidentialMatchAllNetworkSpecifier> CREATOR =
5063                 new Parcelable.Creator<ConfidentialMatchAllNetworkSpecifier>() {
5064                     public ConfidentialMatchAllNetworkSpecifier createFromParcel(Parcel in) {
5065                         return new ConfidentialMatchAllNetworkSpecifier();
5066                     }
5067 
5068                     public ConfidentialMatchAllNetworkSpecifier[] newArray(int size) {
5069                         return new ConfidentialMatchAllNetworkSpecifier[size];
5070                     }
5071                 };
5072         @Override
5073         public boolean canBeSatisfiedBy(NetworkSpecifier other) {
5074             return true;
5075         }
5076 
5077         @Override
5078         public int describeContents() {
5079             return 0;
5080         }
5081 
5082         @Override
5083         public void writeToParcel(Parcel dest, int flags) {}
5084 
5085         @Override
5086         public NetworkSpecifier redact() {
5087             return null;
5088         }
5089     }
5090 
5091     // A network specifier that matches either another LocalNetworkSpecifier with the same
5092     // string or a ConfidentialMatchAllNetworkSpecifier, and can be passed to apps as is.
5093     static class LocalStringNetworkSpecifier extends NetworkSpecifier implements Parcelable {
5094         public static final Parcelable.Creator<LocalStringNetworkSpecifier> CREATOR =
5095                 new Parcelable.Creator<LocalStringNetworkSpecifier>() {
5096                     public LocalStringNetworkSpecifier createFromParcel(Parcel in) {
5097                         return new LocalStringNetworkSpecifier(in);
5098                     }
5099 
5100                     public LocalStringNetworkSpecifier[] newArray(int size) {
5101                         return new LocalStringNetworkSpecifier[size];
5102                     }
5103                 };
5104         private String mString;
5105 
5106         LocalStringNetworkSpecifier(String string) {
5107             mString = string;
5108         }
5109 
5110         LocalStringNetworkSpecifier(Parcel in) {
5111             mString = in.readString();
5112         }
5113 
5114         @Override
5115         public boolean canBeSatisfiedBy(NetworkSpecifier other) {
5116             if (other instanceof LocalStringNetworkSpecifier) {
5117                 return TextUtils.equals(mString,
5118                         ((LocalStringNetworkSpecifier) other).mString);
5119             }
5120             if (other instanceof ConfidentialMatchAllNetworkSpecifier) return true;
5121             return false;
5122         }
5123 
5124         @Override
5125         public int describeContents() {
5126             return 0;
5127         }
5128         @Override
5129         public void writeToParcel(Parcel dest, int flags) {
5130             dest.writeString(mString);
5131         }
5132     }
5133 
5134     /**
5135      * Verify request matching behavior with network specifiers.
5136      *
5137      * This test does not check updating the specifier on a live network because the specifier is
5138      * immutable and this triggers a WTF in
5139      * {@link ConnectivityService#mixInCapabilities(NetworkAgentInfo, NetworkCapabilities)}.
5140      */
5141     @Test
5142     public void testNetworkSpecifier() throws Exception {
5143         NetworkRequest rEmpty1 = newWifiRequestBuilder().build();
5144         NetworkRequest rEmpty2 = newWifiRequestBuilder().setNetworkSpecifier((String) null).build();
5145         NetworkRequest rEmpty3 = newWifiRequestBuilder().setNetworkSpecifier("").build();
5146         NetworkRequest rEmpty4 = newWifiRequestBuilder().setNetworkSpecifier(
5147             (NetworkSpecifier) null).build();
5148         NetworkRequest rFoo = newWifiRequestBuilder().setNetworkSpecifier(
5149                 new LocalStringNetworkSpecifier("foo")).build();
5150         NetworkRequest rBar = newWifiRequestBuilder().setNetworkSpecifier(
5151                 new LocalStringNetworkSpecifier("bar")).build();
5152 
5153         TestNetworkCallback cEmpty1 = new TestNetworkCallback();
5154         TestNetworkCallback cEmpty2 = new TestNetworkCallback();
5155         TestNetworkCallback cEmpty3 = new TestNetworkCallback();
5156         TestNetworkCallback cEmpty4 = new TestNetworkCallback();
5157         TestNetworkCallback cFoo = new TestNetworkCallback();
5158         TestNetworkCallback cBar = new TestNetworkCallback();
5159         TestNetworkCallback[] emptyCallbacks = new TestNetworkCallback[] {
5160                 cEmpty1, cEmpty2, cEmpty3, cEmpty4 };
5161 
5162         mCm.registerNetworkCallback(rEmpty1, cEmpty1);
5163         mCm.registerNetworkCallback(rEmpty2, cEmpty2);
5164         mCm.registerNetworkCallback(rEmpty3, cEmpty3);
5165         mCm.registerNetworkCallback(rEmpty4, cEmpty4);
5166         mCm.registerNetworkCallback(rFoo, cFoo);
5167         mCm.registerNetworkCallback(rBar, cBar);
5168 
5169         LocalStringNetworkSpecifier nsFoo = new LocalStringNetworkSpecifier("foo");
5170         LocalStringNetworkSpecifier nsBar = new LocalStringNetworkSpecifier("bar");
5171 
5172         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
5173         mWiFiAgent.connect(false);
5174         expectAvailableCallbacksUnvalidatedWithSpecifier(mWiFiAgent, null /* specifier */,
5175                 cEmpty1, cEmpty2, cEmpty3, cEmpty4);
5176         assertNoCallbacks(cFoo, cBar);
5177 
5178         mWiFiAgent.disconnect();
5179         expectOnLost(mWiFiAgent, cEmpty1, cEmpty2, cEmpty3, cEmpty4);
5180 
5181         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
5182         mWiFiAgent.setNetworkSpecifier(nsFoo);
5183         mWiFiAgent.connect(false);
5184         expectAvailableCallbacksUnvalidatedWithSpecifier(mWiFiAgent, nsFoo,
5185                 cEmpty1, cEmpty2, cEmpty3, cEmpty4, cFoo);
5186         cBar.assertNoCallback();
5187         assertEquals(nsFoo,
5188                 mCm.getNetworkCapabilities(mWiFiAgent.getNetwork()).getNetworkSpecifier());
5189         assertNoCallbacks(cEmpty1, cEmpty2, cEmpty3, cEmpty4, cFoo);
5190 
5191         mWiFiAgent.disconnect();
5192         expectOnLost(mWiFiAgent, cEmpty1, cEmpty2, cEmpty3, cEmpty4, cFoo);
5193 
5194         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
5195         mWiFiAgent.setNetworkSpecifier(nsBar);
5196         mWiFiAgent.connect(false);
5197         expectAvailableCallbacksUnvalidatedWithSpecifier(mWiFiAgent, nsBar,
5198                 cEmpty1, cEmpty2, cEmpty3, cEmpty4, cBar);
5199         cFoo.assertNoCallback();
5200         assertEquals(nsBar,
5201                 mCm.getNetworkCapabilities(mWiFiAgent.getNetwork()).getNetworkSpecifier());
5202 
5203         mWiFiAgent.disconnect();
5204         expectOnLost(mWiFiAgent, cEmpty1, cEmpty2, cEmpty3, cEmpty4, cBar);
5205         cFoo.assertNoCallback();
5206 
5207         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
5208         mWiFiAgent.setNetworkSpecifier(new ConfidentialMatchAllNetworkSpecifier());
5209         mWiFiAgent.connect(false);
5210         expectAvailableCallbacksUnvalidatedWithSpecifier(mWiFiAgent, null /* specifier */,
5211                 cEmpty1, cEmpty2, cEmpty3, cEmpty4, cFoo, cBar);
5212         assertNull(mCm.getNetworkCapabilities(mWiFiAgent.getNetwork()).getNetworkSpecifier());
5213 
5214         mWiFiAgent.disconnect();
5215         expectOnLost(mWiFiAgent, cEmpty1, cEmpty2, cEmpty3, cEmpty4, cFoo, cBar);
5216     }
5217 
5218     /**
5219      * @return the context's attribution tag
5220      */
5221     private String getAttributionTag() {
5222         return mContext.getAttributionTag();
5223     }
5224 
5225     static class NonParcelableSpecifier extends NetworkSpecifier {
5226         @Override
5227         public boolean canBeSatisfiedBy(NetworkSpecifier other) {
5228             return false;
5229         }
5230     }
5231     static class ParcelableSpecifier extends NonParcelableSpecifier implements Parcelable {
5232         public static final Parcelable.Creator<NonParcelableSpecifier> CREATOR =
5233                 new Parcelable.Creator<NonParcelableSpecifier>() {
5234                     public NonParcelableSpecifier createFromParcel(Parcel in) {
5235                         return new NonParcelableSpecifier();
5236                     }
5237 
5238                     public NonParcelableSpecifier[] newArray(int size) {
5239                         return new NonParcelableSpecifier[size];
5240                     }
5241                 };
5242         @Override public int describeContents() {
5243             return 0;
5244         }
5245         @Override public void writeToParcel(Parcel p, int flags) {}
5246     }
5247 
5248     @Test
5249     public void testInvalidNetworkSpecifier() {
5250         assertThrows(IllegalArgumentException.class, () -> {
5251             NetworkRequest.Builder builder = new NetworkRequest.Builder();
5252             builder.setNetworkSpecifier(new MatchAllNetworkSpecifier());
5253         });
5254 
5255         assertThrows(IllegalArgumentException.class, () -> {
5256             NetworkCapabilities networkCapabilities = new NetworkCapabilities();
5257             networkCapabilities.addTransportType(TRANSPORT_WIFI)
5258                     .setNetworkSpecifier(new MatchAllNetworkSpecifier());
5259             mService.requestNetwork(Process.INVALID_UID, networkCapabilities,
5260                     NetworkRequest.Type.REQUEST.ordinal(), null, 0, null,
5261                     ConnectivityManager.TYPE_WIFI, NetworkCallback.FLAG_NONE,
5262                     mContext.getPackageName(), getAttributionTag());
5263         });
5264 
5265         final NetworkRequest.Builder builder =
5266                 new NetworkRequest.Builder().addTransportType(TRANSPORT_ETHERNET);
5267         assertThrows(ClassCastException.class, () -> {
5268             builder.setNetworkSpecifier(new NonParcelableSpecifier());
5269             Parcel parcelW = Parcel.obtain();
5270             builder.build().writeToParcel(parcelW, 0);
5271         });
5272 
5273         final NetworkRequest nr =
5274                 new NetworkRequest.Builder().addTransportType(TRANSPORT_ETHERNET)
5275                 .setNetworkSpecifier(new ParcelableSpecifier())
5276                 .build();
5277         assertNotNull(nr);
5278 
5279         assertThrows(BadParcelableException.class, () -> {
5280             Parcel parcelW = Parcel.obtain();
5281             nr.writeToParcel(parcelW, 0);
5282             byte[] bytes = parcelW.marshall();
5283             parcelW.recycle();
5284 
5285             Parcel parcelR = Parcel.obtain();
5286             parcelR.unmarshall(bytes, 0, bytes.length);
5287             parcelR.setDataPosition(0);
5288             NetworkRequest rereadNr = NetworkRequest.CREATOR.createFromParcel(parcelR);
5289         });
5290     }
5291 
5292     @Test
5293     public void testNetworkRequestUidSpoofSecurityException() throws Exception {
5294         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
5295         mWiFiAgent.connect(false);
5296         NetworkRequest networkRequest = newWifiRequestBuilder().build();
5297         TestNetworkCallback networkCallback = new TestNetworkCallback();
5298         doThrow(new SecurityException()).when(mAppOpsManager).checkPackage(anyInt(), anyString());
5299         assertThrows(SecurityException.class, () -> {
5300             mCm.requestNetwork(networkRequest, networkCallback);
5301         });
5302     }
5303 
5304     @Test
5305     public void testInvalidSignalStrength() {
5306         NetworkRequest r = new NetworkRequest.Builder()
5307                 .addCapability(NET_CAPABILITY_INTERNET)
5308                 .addTransportType(TRANSPORT_WIFI)
5309                 .setSignalStrength(-75)
5310                 .build();
5311         // Registering a NetworkCallback with signal strength but w/o NETWORK_SIGNAL_STRENGTH_WAKEUP
5312         // permission should get SecurityException.
5313         assertThrows(SecurityException.class, () ->
5314                 mCm.registerNetworkCallback(r, new NetworkCallback()));
5315 
5316         assertThrows(SecurityException.class, () ->
5317                 mCm.registerNetworkCallback(r, PendingIntent.getService(
5318                         mServiceContext, 0 /* requestCode */, new Intent(), FLAG_IMMUTABLE)));
5319 
5320         // Requesting a Network with signal strength should get IllegalArgumentException.
5321         assertThrows(IllegalArgumentException.class, () ->
5322                 mCm.requestNetwork(r, new NetworkCallback()));
5323 
5324         assertThrows(IllegalArgumentException.class, () ->
5325                 mCm.requestNetwork(r, PendingIntent.getService(
5326                         mServiceContext, 0 /* requestCode */, new Intent(), FLAG_IMMUTABLE)));
5327     }
5328 
5329     @Test
5330     public void testRegisterDefaultNetworkCallback() throws Exception {
5331         final TestNetworkCallback defaultNetworkCallback = new TestNetworkCallback();
5332         mCm.registerDefaultNetworkCallback(defaultNetworkCallback);
5333         defaultNetworkCallback.assertNoCallback();
5334 
5335         final Handler handler = new Handler(ConnectivityThread.getInstanceLooper());
5336         final TestNetworkCallback systemDefaultCallback = new TestNetworkCallback();
5337         mCm.registerSystemDefaultNetworkCallback(systemDefaultCallback, handler);
5338         systemDefaultCallback.assertNoCallback();
5339 
5340         // Create a TRANSPORT_CELLULAR request to keep the mobile interface up
5341         // whenever Wi-Fi is up. Without this, the mobile network agent is
5342         // reaped before any other activity can take place.
5343         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
5344         final NetworkRequest cellRequest = new NetworkRequest.Builder()
5345                 .addTransportType(TRANSPORT_CELLULAR).build();
5346         mCm.requestNetwork(cellRequest, cellNetworkCallback);
5347         cellNetworkCallback.assertNoCallback();
5348 
5349         // Bring up cell and expect CALLBACK_AVAILABLE.
5350         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
5351         mCellAgent.connect(true);
5352         cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
5353         defaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
5354         systemDefaultCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
5355         assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
5356         assertEquals(systemDefaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
5357 
5358         // Bring up wifi and expect CALLBACK_AVAILABLE.
5359         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
5360         mWiFiAgent.connect(true);
5361         cellNetworkCallback.assertNoCallback();
5362         defaultNetworkCallback.expectAvailableDoubleValidatedCallbacks(mWiFiAgent);
5363         systemDefaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiAgent);
5364         assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
5365         assertEquals(systemDefaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
5366 
5367         // Bring down cell. Expect no default network callback, since it wasn't the default.
5368         mCellAgent.disconnect();
5369         cellNetworkCallback.expect(LOST, mCellAgent);
5370         defaultNetworkCallback.assertNoCallback();
5371         systemDefaultCallback.assertNoCallback();
5372         assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
5373         assertEquals(systemDefaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
5374 
5375         // Bring up cell. Expect no default network callback, since it won't be the default.
5376         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
5377         mCellAgent.connect(true);
5378         cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
5379         defaultNetworkCallback.assertNoCallback();
5380         systemDefaultCallback.assertNoCallback();
5381         assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
5382         assertEquals(systemDefaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
5383 
5384         // Bring down wifi. Expect the default network callback to notified of LOST wifi
5385         // followed by AVAILABLE cell.
5386         mWiFiAgent.disconnect();
5387         cellNetworkCallback.assertNoCallback();
5388         defaultNetworkCallback.expect(LOST, mWiFiAgent);
5389         defaultNetworkCallback.expectAvailableCallbacksValidated(mCellAgent);
5390         systemDefaultCallback.expect(LOST, mWiFiAgent);
5391         systemDefaultCallback.expectAvailableCallbacksValidated(mCellAgent);
5392         mCellAgent.disconnect();
5393         cellNetworkCallback.expect(LOST, mCellAgent);
5394         defaultNetworkCallback.expect(LOST, mCellAgent);
5395         systemDefaultCallback.expect(LOST, mCellAgent);
5396         waitForIdle();
5397         assertEquals(null, mCm.getActiveNetwork());
5398 
5399         mMockVpn.establishForMyUid();
5400         assertUidRangesUpdatedForMyUid(true);
5401         defaultNetworkCallback.expectAvailableThenValidatedCallbacks(mMockVpn);
5402         systemDefaultCallback.assertNoCallback();
5403         assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
5404         assertEquals(null, systemDefaultCallback.getLastAvailableNetwork());
5405 
5406         mMockVpn.disconnect();
5407         defaultNetworkCallback.expect(LOST, mMockVpn);
5408         systemDefaultCallback.assertNoCallback();
5409         waitForIdle();
5410         assertEquals(null, mCm.getActiveNetwork());
5411     }
5412 
5413     @Test
5414     public void testAdditionalStateCallbacks() throws Exception {
5415         // File a network request for mobile.
5416         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
5417         final NetworkRequest cellRequest = new NetworkRequest.Builder()
5418                 .addTransportType(TRANSPORT_CELLULAR).build();
5419         mCm.requestNetwork(cellRequest, cellNetworkCallback);
5420 
5421         // Bring up the mobile network.
5422         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
5423         mCellAgent.connect(true);
5424 
5425         // We should get onAvailable(), onCapabilitiesChanged(), and
5426         // onLinkPropertiesChanged() in rapid succession. Additionally, we
5427         // should get onCapabilitiesChanged() when the mobile network validates.
5428         cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
5429         cellNetworkCallback.assertNoCallback();
5430 
5431         // Update LinkProperties.
5432         final LinkProperties lp = new LinkProperties();
5433         lp.setInterfaceName("foonet_data0");
5434         mCellAgent.sendLinkProperties(lp);
5435         // We should get onLinkPropertiesChanged().
5436         cellNetworkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent);
5437         cellNetworkCallback.assertNoCallback();
5438 
5439         // Suspend the network.
5440         mCellAgent.suspend();
5441         cellNetworkCallback.expectCaps(mCellAgent,
5442                 c -> !c.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
5443         cellNetworkCallback.expect(SUSPENDED, mCellAgent);
5444         cellNetworkCallback.assertNoCallback();
5445         assertEquals(NetworkInfo.State.SUSPENDED, mCm.getActiveNetworkInfo().getState());
5446 
5447         // Register a garden variety default network request.
5448         TestNetworkCallback dfltNetworkCallback = new TestNetworkCallback();
5449         mCm.registerDefaultNetworkCallback(dfltNetworkCallback);
5450         // We should get onAvailable(), onCapabilitiesChanged(), onLinkPropertiesChanged(),
5451         // as well as onNetworkSuspended() in rapid succession.
5452         dfltNetworkCallback.expectAvailableAndSuspendedCallbacks(mCellAgent, true);
5453         dfltNetworkCallback.assertNoCallback();
5454         mCm.unregisterNetworkCallback(dfltNetworkCallback);
5455 
5456         mCellAgent.resume();
5457         cellNetworkCallback.expectCaps(mCellAgent,
5458                 c -> c.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
5459         cellNetworkCallback.expect(RESUMED, mCellAgent);
5460         cellNetworkCallback.assertNoCallback();
5461         assertEquals(NetworkInfo.State.CONNECTED, mCm.getActiveNetworkInfo().getState());
5462 
5463         dfltNetworkCallback = new TestNetworkCallback();
5464         mCm.registerDefaultNetworkCallback(dfltNetworkCallback);
5465         // This time onNetworkSuspended should not be called.
5466         dfltNetworkCallback.expectAvailableCallbacksValidated(mCellAgent);
5467         dfltNetworkCallback.assertNoCallback();
5468 
5469         mCm.unregisterNetworkCallback(dfltNetworkCallback);
5470         mCm.unregisterNetworkCallback(cellNetworkCallback);
5471     }
5472 
5473     @Test
5474     public void testRegisterPrivilegedDefaultCallbacksRequirePermissions() throws Exception {
5475         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
5476         mCellAgent.connect(false /* validated */);
5477         mServiceContext.setPermission(CONNECTIVITY_USE_RESTRICTED_NETWORKS, PERMISSION_DENIED);
5478 
5479         final Handler handler = new Handler(ConnectivityThread.getInstanceLooper());
5480         final TestNetworkCallback callback = new TestNetworkCallback();
5481         assertThrows(SecurityException.class,
5482                 () -> mCm.registerSystemDefaultNetworkCallback(callback, handler));
5483         callback.assertNoCallback();
5484         assertThrows(SecurityException.class,
5485                 () -> mCm.registerDefaultNetworkCallbackForUid(APP1_UID, callback, handler));
5486         callback.assertNoCallback();
5487 
5488         mServiceContext.setPermission(CONNECTIVITY_USE_RESTRICTED_NETWORKS, PERMISSION_GRANTED);
5489         mCm.registerSystemDefaultNetworkCallback(callback, handler);
5490         mServiceContext.setPermission(CONNECTIVITY_USE_RESTRICTED_NETWORKS, PERMISSION_DENIED);
5491         callback.expectAvailableCallbacksUnvalidated(mCellAgent);
5492         mCm.unregisterNetworkCallback(callback);
5493 
5494         mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_GRANTED);
5495         mCm.registerSystemDefaultNetworkCallback(callback, handler);
5496         callback.expectAvailableCallbacksUnvalidated(mCellAgent);
5497         mCm.unregisterNetworkCallback(callback);
5498 
5499         mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_DENIED);
5500         mServiceContext.setPermission(NETWORK_SETUP_WIZARD, PERMISSION_GRANTED);
5501         mCm.registerSystemDefaultNetworkCallback(callback, handler);
5502         callback.expectAvailableCallbacksUnvalidated(mCellAgent);
5503         mCm.unregisterNetworkCallback(callback);
5504 
5505         mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_GRANTED);
5506         mCm.registerDefaultNetworkCallbackForUid(APP1_UID, callback, handler);
5507         callback.expectAvailableCallbacksUnvalidated(mCellAgent);
5508         mCm.unregisterNetworkCallback(callback);
5509     }
5510 
5511     @Test
5512     public void testNetworkCallbackWithNullUids() throws Exception {
5513         final NetworkRequest request = new NetworkRequest.Builder()
5514                 .removeCapability(NET_CAPABILITY_NOT_VPN)
5515                 .build();
5516         final TestNetworkCallback callback = new TestNetworkCallback();
5517         mCm.registerNetworkCallback(request, callback);
5518 
5519         // Attempt to file a callback for networks applying to another UID. This does not actually
5520         // work, because this code does not currently have permission to do so. The callback behaves
5521         // exactly the same as the one registered just above.
5522         final int otherUid = UserHandle.getUid(RESTRICTED_USER, VPN_UID);
5523         final NetworkRequest otherUidRequest = new NetworkRequest.Builder()
5524                 .removeCapability(NET_CAPABILITY_NOT_VPN)
5525                 .setUids(UidRange.toIntRanges(uidRangesForUids(otherUid)))
5526                 .build();
5527         final TestNetworkCallback otherUidCallback = new TestNetworkCallback();
5528         mCm.registerNetworkCallback(otherUidRequest, otherUidCallback);
5529 
5530         final NetworkRequest includeOtherUidsRequest = new NetworkRequest.Builder()
5531                 .removeCapability(NET_CAPABILITY_NOT_VPN)
5532                 .setIncludeOtherUidNetworks(true)
5533                 .build();
5534         final TestNetworkCallback includeOtherUidsCallback = new TestNetworkCallback();
5535         mCm.registerNetworkCallback(includeOtherUidsRequest, includeOtherUidsCallback);
5536 
5537         // Both callbacks see a network with no specifier that applies to their UID.
5538         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
5539         mWiFiAgent.connect(false /* validated */);
5540         callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
5541         otherUidCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
5542         includeOtherUidsCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
5543         mWiFiAgent.disconnect();
5544         callback.expect(LOST, mWiFiAgent);
5545         otherUidCallback.expect(LOST, mWiFiAgent);
5546         includeOtherUidsCallback.expect(LOST, mWiFiAgent);
5547 
5548         // Only the includeOtherUidsCallback sees a VPN that does not apply to its UID.
5549         final UidRange range = UidRange.createForUser(UserHandle.of(RESTRICTED_USER));
5550         final Set<UidRange> vpnRanges = Collections.singleton(range);
5551         mMockVpn.establish(new LinkProperties(), VPN_UID, vpnRanges);
5552         includeOtherUidsCallback.expectAvailableThenValidatedCallbacks(mMockVpn);
5553         callback.assertNoCallback();
5554         otherUidCallback.assertNoCallback();
5555 
5556         mMockVpn.disconnect();
5557         includeOtherUidsCallback.expect(LOST, mMockVpn);
5558         callback.assertNoCallback();
5559         otherUidCallback.assertNoCallback();
5560     }
5561 
5562     private static class RedactableNetworkSpecifier extends NetworkSpecifier {
5563         public static final int ID_INVALID = -1;
5564 
5565         public final int networkId;
5566 
5567         RedactableNetworkSpecifier(int networkId) {
5568             this.networkId = networkId;
5569         }
5570 
5571         @Override
5572         public boolean canBeSatisfiedBy(NetworkSpecifier other) {
5573             return other instanceof RedactableNetworkSpecifier
5574                     && this.networkId == ((RedactableNetworkSpecifier) other).networkId;
5575         }
5576 
5577         @Override
5578         public NetworkSpecifier redact() {
5579             return new RedactableNetworkSpecifier(ID_INVALID);
5580         }
5581     }
5582 
5583     @Test
5584     public void testNetworkCallbackWithNullUidsRedactsSpecifier() throws Exception {
5585         final RedactableNetworkSpecifier specifier = new RedactableNetworkSpecifier(42);
5586         final NetworkRequest request = new NetworkRequest.Builder()
5587                 .addCapability(NET_CAPABILITY_INTERNET)
5588                 .addTransportType(TRANSPORT_WIFI)
5589                 .setNetworkSpecifier(specifier)
5590                 .build();
5591         final TestNetworkCallback callback = new TestNetworkCallback();
5592         mCm.registerNetworkCallback(request, callback);
5593 
5594         // Attempt to file a callback for networks applying to another UID. This does not actually
5595         // work, because this code does not currently have permission to do so. The callback behaves
5596         // exactly the same as the one registered just above.
5597         final int otherUid = UserHandle.getUid(RESTRICTED_USER, VPN_UID);
5598         final NetworkRequest otherUidRequest = new NetworkRequest.Builder()
5599                 .addCapability(NET_CAPABILITY_INTERNET)
5600                 .addTransportType(TRANSPORT_WIFI)
5601                 .setNetworkSpecifier(specifier)
5602                 .setUids(UidRange.toIntRanges(uidRangesForUids(otherUid)))
5603                 .build();
5604         final TestNetworkCallback otherUidCallback = new TestNetworkCallback();
5605         mCm.registerNetworkCallback(otherUidRequest, otherUidCallback);
5606 
5607         final NetworkRequest includeOtherUidsRequest = new NetworkRequest.Builder()
5608                 .addCapability(NET_CAPABILITY_INTERNET)
5609                 .addTransportType(TRANSPORT_WIFI)
5610                 .setNetworkSpecifier(specifier)
5611                 .setIncludeOtherUidNetworks(true)
5612                 .build();
5613         final TestNetworkCallback includeOtherUidsCallback = new TestNetworkCallback();
5614         mCm.registerNetworkCallback(includeOtherUidsRequest, callback);
5615 
5616         // Only the regular callback sees the network, because callbacks filed with no UID have
5617         // their specifiers redacted.
5618         final LinkProperties emptyLp = new LinkProperties();
5619         final NetworkCapabilities ncTemplate = new NetworkCapabilities()
5620                 .addTransportType(TRANSPORT_WIFI)
5621                 .setNetworkSpecifier(specifier);
5622         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, emptyLp, ncTemplate);
5623         mWiFiAgent.connect(false /* validated */);
5624         callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
5625         otherUidCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
5626         includeOtherUidsCallback.assertNoCallback();
5627     }
5628 
5629     private void setCaptivePortalMode(int mode) {
5630         ContentResolver cr = mServiceContext.getContentResolver();
5631         Settings.Global.putInt(cr, ConnectivitySettingsManager.CAPTIVE_PORTAL_MODE, mode);
5632     }
5633 
5634     private void setAlwaysOnNetworks(boolean enable) {
5635         ContentResolver cr = mServiceContext.getContentResolver();
5636         Settings.Global.putInt(cr, ConnectivitySettingsManager.MOBILE_DATA_ALWAYS_ON,
5637                 enable ? 1 : 0);
5638         mService.updateAlwaysOnNetworks();
5639         waitForIdle();
5640     }
5641 
5642     private void setPrivateDnsSettings(int mode, String specifier) {
5643         ConnectivitySettingsManager.setPrivateDnsMode(mServiceContext, mode);
5644         ConnectivitySettingsManager.setPrivateDnsHostname(mServiceContext, specifier);
5645         mService.updatePrivateDnsSettings();
5646         waitForIdle();
5647     }
5648 
5649     private void setIngressRateLimit(int rateLimitInBytesPerSec) {
5650         ConnectivitySettingsManager.setIngressRateLimitInBytesPerSecond(mServiceContext,
5651                 rateLimitInBytesPerSec);
5652         mService.updateIngressRateLimit();
5653         waitForIdle();
5654     }
5655 
5656     private boolean isForegroundNetwork(TestNetworkAgentWrapper network) {
5657         NetworkCapabilities nc = mCm.getNetworkCapabilities(network.getNetwork());
5658         assertNotNull(nc);
5659         return nc.hasCapability(NET_CAPABILITY_FOREGROUND);
5660     }
5661 
5662     @Test
5663     public void testBackgroundNetworks() throws Exception {
5664         // Create a cellular background request.
5665         grantUsingBackgroundNetworksPermissionForUid(Binder.getCallingUid());
5666         final TestNetworkCallback cellBgCallback = new TestNetworkCallback();
5667         mCm.requestBackgroundNetwork(new NetworkRequest.Builder()
5668                 .addTransportType(TRANSPORT_CELLULAR).build(),
5669                 cellBgCallback, mCsHandlerThread.getThreadHandler());
5670 
5671         // Make callbacks for monitoring.
5672         final NetworkRequest request = new NetworkRequest.Builder().build();
5673         final NetworkRequest fgRequest = new NetworkRequest.Builder()
5674                 .addCapability(NET_CAPABILITY_FOREGROUND).build();
5675         final TestNetworkCallback callback = new TestNetworkCallback();
5676         final TestNetworkCallback fgCallback = new TestNetworkCallback();
5677         mCm.registerNetworkCallback(request, callback);
5678         mCm.registerNetworkCallback(fgRequest, fgCallback);
5679 
5680         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
5681         mCellAgent.connect(true);
5682         callback.expectAvailableThenValidatedCallbacks(mCellAgent);
5683         fgCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
5684         assertTrue(isForegroundNetwork(mCellAgent));
5685 
5686         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
5687         mWiFiAgent.connect(true);
5688 
5689         // When wifi connects, cell lingers.
5690         callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
5691         callback.expectLosing(mCellAgent);
5692         callback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
5693         fgCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
5694         fgCallback.expectLosing(mCellAgent);
5695         fgCallback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
5696         assertTrue(isForegroundNetwork(mCellAgent));
5697         assertTrue(isForegroundNetwork(mWiFiAgent));
5698 
5699         // When lingering is complete, cell is still there but is now in the background.
5700         waitForIdle();
5701         int timeoutMs = TEST_LINGER_DELAY_MS + TEST_LINGER_DELAY_MS / 4;
5702         fgCallback.expect(LOST, mCellAgent, timeoutMs);
5703         // Expect a network capabilities update sans FOREGROUND.
5704         callback.expectCaps(mCellAgent, c -> !c.hasCapability(NET_CAPABILITY_FOREGROUND));
5705         assertFalse(isForegroundNetwork(mCellAgent));
5706         assertTrue(isForegroundNetwork(mWiFiAgent));
5707 
5708         // File a cell request and check that cell comes into the foreground.
5709         final NetworkRequest cellRequest = new NetworkRequest.Builder()
5710                 .addTransportType(TRANSPORT_CELLULAR).build();
5711         final TestNetworkCallback cellCallback = new TestNetworkCallback();
5712         mCm.requestNetwork(cellRequest, cellCallback);
5713         cellCallback.expectAvailableCallbacksValidated(mCellAgent);
5714         fgCallback.expectAvailableCallbacksValidated(mCellAgent);
5715         // Expect a network capabilities update with FOREGROUND, because the most recent
5716         // request causes its state to change.
5717         cellCallback.expectCaps(mCellAgent, c -> c.hasCapability(NET_CAPABILITY_FOREGROUND));
5718         callback.expectCaps(mCellAgent, c -> c.hasCapability(NET_CAPABILITY_FOREGROUND));
5719         assertTrue(isForegroundNetwork(mCellAgent));
5720         assertTrue(isForegroundNetwork(mWiFiAgent));
5721 
5722         // Release the request. The network immediately goes into the background, since it was not
5723         // lingering.
5724         mCm.unregisterNetworkCallback(cellCallback);
5725         fgCallback.expect(LOST, mCellAgent);
5726         // Expect a network capabilities update sans FOREGROUND.
5727         callback.expectCaps(mCellAgent, c -> !c.hasCapability(NET_CAPABILITY_FOREGROUND));
5728         assertFalse(isForegroundNetwork(mCellAgent));
5729         assertTrue(isForegroundNetwork(mWiFiAgent));
5730 
5731         // Disconnect wifi and check that cell is foreground again.
5732         mWiFiAgent.disconnect();
5733         callback.expect(LOST, mWiFiAgent);
5734         fgCallback.expect(LOST, mWiFiAgent);
5735         fgCallback.expectAvailableCallbacksValidated(mCellAgent);
5736         assertTrue(isForegroundNetwork(mCellAgent));
5737 
5738         mCm.unregisterNetworkCallback(callback);
5739         mCm.unregisterNetworkCallback(fgCallback);
5740         mCm.unregisterNetworkCallback(cellBgCallback);
5741     }
5742 
5743     @Ignore // This test has instrinsic chances of spurious failures: ignore for continuous testing.
5744     public void benchmarkRequestRegistrationAndCallbackDispatch() throws Exception {
5745         // TODO: turn this unit test into a real benchmarking test.
5746         // Benchmarks connecting and switching performance in the presence of a large number of
5747         // NetworkRequests.
5748         // 1. File NUM_REQUESTS requests.
5749         // 2. Have a network connect. Wait for NUM_REQUESTS onAvailable callbacks to fire.
5750         // 3. Have a new network connect and outscore the previous. Wait for NUM_REQUESTS onLosing
5751         //    and NUM_REQUESTS onAvailable callbacks to fire.
5752         // See how long it took.
5753         final int NUM_REQUESTS = 90;
5754         final int REGISTER_TIME_LIMIT_MS = 200;
5755         final int CONNECT_TIME_LIMIT_MS = 60;
5756         final int SWITCH_TIME_LIMIT_MS = 60;
5757         final int UNREGISTER_TIME_LIMIT_MS = 20;
5758 
5759         final NetworkRequest request = new NetworkRequest.Builder().clearCapabilities().build();
5760         final NetworkCallback[] callbacks = new NetworkCallback[NUM_REQUESTS];
5761         final CountDownLatch availableLatch = new CountDownLatch(NUM_REQUESTS);
5762         final CountDownLatch losingLatch = new CountDownLatch(NUM_REQUESTS);
5763 
5764         for (int i = 0; i < NUM_REQUESTS; i++) {
5765             callbacks[i] = new NetworkCallback() {
5766                 @Override public void onAvailable(Network n) { availableLatch.countDown(); }
5767                 @Override public void onLosing(Network n, int t) { losingLatch.countDown(); }
5768             };
5769         }
5770 
5771         assertRunsInAtMost("Registering callbacks", REGISTER_TIME_LIMIT_MS, () -> {
5772             for (NetworkCallback cb : callbacks) {
5773                 mCm.registerNetworkCallback(request, cb);
5774             }
5775         });
5776 
5777         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
5778         // Don't request that the network validate, because otherwise connect() will block until
5779         // the network gets NET_CAPABILITY_VALIDATED, after all the callbacks below have fired,
5780         // and we won't actually measure anything.
5781         mCellAgent.connect(false);
5782 
5783         long onAvailableDispatchingDuration = durationOf(() -> {
5784             await(availableLatch, 10 * CONNECT_TIME_LIMIT_MS);
5785         });
5786         Log.d(TAG, String.format("Dispatched %d of %d onAvailable callbacks in %dms",
5787                 NUM_REQUESTS - availableLatch.getCount(), NUM_REQUESTS,
5788                 onAvailableDispatchingDuration));
5789         assertTrue(String.format("Dispatching %d onAvailable callbacks in %dms, expected %dms",
5790                 NUM_REQUESTS, onAvailableDispatchingDuration, CONNECT_TIME_LIMIT_MS),
5791                 onAvailableDispatchingDuration <= CONNECT_TIME_LIMIT_MS);
5792 
5793         // Give wifi a high enough score that we'll linger cell when wifi comes up.
5794         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
5795         mWiFiAgent.adjustScore(40);
5796         mWiFiAgent.connect(false);
5797 
5798         long onLostDispatchingDuration = durationOf(() -> {
5799             await(losingLatch, 10 * SWITCH_TIME_LIMIT_MS);
5800         });
5801         Log.d(TAG, String.format("Dispatched %d of %d onLosing callbacks in %dms",
5802                 NUM_REQUESTS - losingLatch.getCount(), NUM_REQUESTS, onLostDispatchingDuration));
5803         assertTrue(String.format("Dispatching %d onLosing callbacks in %dms, expected %dms",
5804                 NUM_REQUESTS, onLostDispatchingDuration, SWITCH_TIME_LIMIT_MS),
5805                 onLostDispatchingDuration <= SWITCH_TIME_LIMIT_MS);
5806 
5807         assertRunsInAtMost("Unregistering callbacks", UNREGISTER_TIME_LIMIT_MS, () -> {
5808             for (NetworkCallback cb : callbacks) {
5809                 mCm.unregisterNetworkCallback(cb);
5810             }
5811         });
5812     }
5813 
5814     @Test
5815     public void testMobileDataAlwaysOn() throws Exception {
5816         grantUsingBackgroundNetworksPermissionForUid(Binder.getCallingUid());
5817         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
5818         final NetworkRequest cellRequest = new NetworkRequest.Builder()
5819                 .addTransportType(TRANSPORT_CELLULAR).build();
5820         mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
5821 
5822         final HandlerThread handlerThread = new HandlerThread("MobileDataAlwaysOnFactory");
5823         handlerThread.start();
5824         NetworkCapabilities filter = new NetworkCapabilities()
5825                 .addTransportType(TRANSPORT_CELLULAR)
5826                 .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
5827                 .addCapability(NET_CAPABILITY_INTERNET);
5828         final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
5829                 mServiceContext, "testFactory", filter, mCsHandlerThread);
5830         testFactory.setScoreFilter(40);
5831 
5832         // Register the factory and expect it to start looking for a network.
5833         testFactory.register();
5834 
5835         try {
5836             // Expect the factory to receive the default network request.
5837             testFactory.expectRequestAdd();
5838             testFactory.assertRequestCountEquals(1);
5839             assertTrue(testFactory.getMyStartRequested());
5840 
5841             // Bring up wifi. The factory stops looking for a network.
5842             mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
5843             // Score 60 - 40 penalty for not validated yet, then 60 when it validates
5844             mWiFiAgent.connect(true);
5845             // The network connects with a low score, so the offer can still beat it and
5846             // nothing happens. Then the network validates, and the offer with its filter score
5847             // of 40 can no longer beat it and the request is removed.
5848             testFactory.expectRequestRemove();
5849             testFactory.assertRequestCountEquals(0);
5850 
5851             assertFalse(testFactory.getMyStartRequested());
5852 
5853             // Turn on mobile data always on. This request will not match the wifi request, so
5854             // it will be sent to the test factory whose filters allow to see it.
5855             setAlwaysOnNetworks(true);
5856             testFactory.expectRequestAdd();
5857             testFactory.assertRequestCountEquals(1);
5858 
5859             assertTrue(testFactory.getMyStartRequested());
5860 
5861             // Bring up cell data and check that the factory stops looking.
5862             assertLength(1, mCm.getAllNetworks());
5863             mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
5864             mCellAgent.connect(false);
5865             cellNetworkCallback.expectAvailableCallbacks(mCellAgent, false, false, false,
5866                     TEST_CALLBACK_TIMEOUT_MS);
5867             // When cell connects, it will satisfy the "mobile always on request" right away
5868             // by virtue of being the only network that can satisfy the request. However, its
5869             // score is low (50 - 40 = 10) so the test factory can still hope to beat it.
5870             expectNoRequestChanged(testFactory);
5871 
5872             // Next, cell validates. This gives it a score of 50 and the test factory can't
5873             // hope to beat that according to its filters. It will see the message that its
5874             // offer is now unnecessary.
5875             mCellAgent.setNetworkValid(true);
5876             // Need a trigger point to let NetworkMonitor tell ConnectivityService that network is
5877             // validated – see testPartialConnectivity.
5878             mCm.reportNetworkConnectivity(mCellAgent.getNetwork(), true);
5879             cellNetworkCallback.expectCaps(mCellAgent,
5880                     c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
5881             testFactory.expectRequestRemove();
5882             testFactory.assertRequestCountEquals(0);
5883             // Accordingly, the factory shouldn't be started.
5884             assertFalse(testFactory.getMyStartRequested());
5885 
5886             // Check that cell data stays up.
5887             waitForIdle();
5888             verifyActiveNetwork(TRANSPORT_WIFI);
5889             assertLength(2, mCm.getAllNetworks());
5890 
5891             // Cell disconnects. There is still the "mobile data always on" request outstanding,
5892             // and the test factory should see it now that it isn't hopelessly outscored.
5893             mCellAgent.disconnect();
5894             cellNetworkCallback.expect(LOST, mCellAgent);
5895             // Wait for the network to be removed from internal structures before
5896             // calling synchronous getter
5897             waitForIdle();
5898             assertLength(1, mCm.getAllNetworks());
5899             testFactory.expectRequestAdd();
5900             testFactory.assertRequestCountEquals(1);
5901 
5902             // Reconnect cell validated, see the request disappear again. Then withdraw the
5903             // mobile always on request. This will tear down cell, and there shouldn't be a
5904             // blip where the test factory briefly sees the request or anything.
5905             mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
5906             mCellAgent.connect(true);
5907             cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
5908             waitForIdle();
5909             assertLength(2, mCm.getAllNetworks());
5910             testFactory.expectRequestRemove();
5911             testFactory.assertRequestCountEquals(0);
5912             setAlwaysOnNetworks(false);
5913             expectNoRequestChanged(testFactory);
5914             testFactory.assertRequestCountEquals(0);
5915             assertFalse(testFactory.getMyStartRequested());
5916             // ...  and cell data to be torn down immediately since it is no longer nascent.
5917             cellNetworkCallback.expect(LOST, mCellAgent);
5918             waitForIdle();
5919             assertLength(1, mCm.getAllNetworks());
5920             testFactory.terminate();
5921             testFactory.assertNoRequestChanged();
5922         } finally {
5923             mCm.unregisterNetworkCallback(cellNetworkCallback);
5924             handlerThread.quit();
5925         }
5926     }
5927 
5928     @Test
5929     public void testSetAllowBadWifiUntil() throws Exception {
5930         runAsShell(NETWORK_SETTINGS,
5931                 () -> mService.setTestAllowBadWifiUntil(System.currentTimeMillis() + 5_000L));
5932         waitForIdle();
5933         testAvoidBadWifiConfig_controlledBySettings();
5934 
5935         runAsShell(NETWORK_SETTINGS,
5936                 () -> mService.setTestAllowBadWifiUntil(System.currentTimeMillis() - 5_000L));
5937         waitForIdle();
5938         testAvoidBadWifiConfig_ignoreSettings();
5939     }
5940 
5941     private void testAvoidBadWifiConfig_controlledBySettings() {
5942         final ContentResolver cr = mServiceContext.getContentResolver();
5943         final String settingName = ConnectivitySettingsManager.NETWORK_AVOID_BAD_WIFI;
5944 
5945         Settings.Global.putString(cr, settingName, "0");
5946         mPolicyTracker.reevaluate();
5947         waitForIdle();
5948         assertFalse(mService.avoidBadWifi());
5949         assertFalse(mPolicyTracker.shouldNotifyWifiUnvalidated());
5950 
5951         Settings.Global.putString(cr, settingName, "1");
5952         mPolicyTracker.reevaluate();
5953         waitForIdle();
5954         assertTrue(mService.avoidBadWifi());
5955         assertFalse(mPolicyTracker.shouldNotifyWifiUnvalidated());
5956 
5957         Settings.Global.putString(cr, settingName, null);
5958         mPolicyTracker.reevaluate();
5959         waitForIdle();
5960         assertFalse(mService.avoidBadWifi());
5961         assertTrue(mPolicyTracker.shouldNotifyWifiUnvalidated());
5962     }
5963 
5964     private void testAvoidBadWifiConfig_ignoreSettings() {
5965         final ContentResolver cr = mServiceContext.getContentResolver();
5966         final String settingName = ConnectivitySettingsManager.NETWORK_AVOID_BAD_WIFI;
5967 
5968         String[] values = new String[] {null, "0", "1"};
5969         for (int i = 0; i < values.length; i++) {
5970             Settings.Global.putString(cr, settingName, values[i]);
5971             mPolicyTracker.reevaluate();
5972             waitForIdle();
5973             String msg = String.format("config=false, setting=%s", values[i]);
5974             assertTrue(mService.avoidBadWifi());
5975             assertFalse(msg, mPolicyTracker.shouldNotifyWifiUnvalidated());
5976         }
5977     }
5978 
5979     @Test
5980     public void testAvoidBadWifiSetting() throws Exception {
5981         doReturn(1).when(mResources).getInteger(R.integer.config_networkAvoidBadWifi);
5982         testAvoidBadWifiConfig_ignoreSettings();
5983 
5984         doReturn(0).when(mResources).getInteger(R.integer.config_networkAvoidBadWifi);
5985         testAvoidBadWifiConfig_controlledBySettings();
5986     }
5987 
5988     @Test
5989     public void testActivelyPreferBadWifiSetting() throws Exception {
5990         doReturn(1).when(mResources).getInteger(R.integer.config_activelyPreferBadWifi);
5991         mPolicyTracker.reevaluate();
5992         waitForIdle();
5993         assertTrue(mService.mNetworkRanker.getConfiguration().activelyPreferBadWifi());
5994 
5995         doReturn(0).when(mResources).getInteger(R.integer.config_activelyPreferBadWifi);
5996         mPolicyTracker.reevaluate();
5997         waitForIdle();
5998         if (mDeps.isAtLeastU()) {
5999             // U+ ignore the setting and always actively prefers bad wifi
6000             assertTrue(mService.mNetworkRanker.getConfiguration().activelyPreferBadWifi());
6001         } else {
6002             assertFalse(mService.mNetworkRanker.getConfiguration().activelyPreferBadWifi());
6003         }
6004     }
6005 
6006     @Test
6007     public void testOffersAvoidsBadWifi() throws Exception {
6008         // Normal mode : the carrier doesn't restrict moving away from bad wifi.
6009         // This has getAvoidBadWifi return true.
6010         doReturn(1).when(mResources).getInteger(R.integer.config_networkAvoidBadWifi);
6011         // Don't request cell separately for the purposes of this test.
6012         setAlwaysOnNetworks(false);
6013 
6014         final NetworkProvider cellProvider = new NetworkProvider(mServiceContext,
6015                 mCsHandlerThread.getLooper(), "Cell provider");
6016         final NetworkProvider wifiProvider = new NetworkProvider(mServiceContext,
6017                 mCsHandlerThread.getLooper(), "Wifi provider");
6018 
6019         mCm.registerNetworkProvider(cellProvider);
6020         mCm.registerNetworkProvider(wifiProvider);
6021 
6022         final NetworkScore cellScore = new NetworkScore.Builder().build();
6023         final NetworkScore wifiScore = new NetworkScore.Builder().build();
6024         final NetworkCapabilities defaultCaps = new NetworkCapabilities.Builder()
6025                 .addCapability(NET_CAPABILITY_INTERNET)
6026                 .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
6027                 .build();
6028         final NetworkCapabilities cellCaps = new NetworkCapabilities.Builder()
6029                 .addTransportType(TRANSPORT_CELLULAR)
6030                 .addCapability(NET_CAPABILITY_INTERNET)
6031                 .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
6032                 .build();
6033         final NetworkCapabilities wifiCaps = new NetworkCapabilities.Builder()
6034                 .addTransportType(TRANSPORT_WIFI)
6035                 .addCapability(NET_CAPABILITY_INTERNET)
6036                 .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
6037                 .build();
6038         final TestableNetworkOfferCallback cellCallback = new TestableNetworkOfferCallback(
6039                 TIMEOUT_MS /* timeout */, TEST_CALLBACK_TIMEOUT_MS /* noCallbackTimeout */);
6040         final TestableNetworkOfferCallback wifiCallback = new TestableNetworkOfferCallback(
6041                 TIMEOUT_MS /* timeout */, TEST_CALLBACK_TIMEOUT_MS /* noCallbackTimeout */);
6042 
6043         // Offer callbacks will run on the CS handler thread in this test.
6044         cellProvider.registerNetworkOffer(cellScore, cellCaps, r -> r.run(), cellCallback);
6045         wifiProvider.registerNetworkOffer(wifiScore, wifiCaps, r -> r.run(), wifiCallback);
6046 
6047         // Both providers see the default request.
6048         cellCallback.expectOnNetworkNeeded(defaultCaps);
6049         wifiCallback.expectOnNetworkNeeded(defaultCaps);
6050 
6051         // Listen to cell and wifi to know when agents are finished processing
6052         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
6053         final NetworkRequest cellRequest = new NetworkRequest.Builder()
6054                 .addTransportType(TRANSPORT_CELLULAR).build();
6055         mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
6056         final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
6057         final NetworkRequest wifiRequest = new NetworkRequest.Builder()
6058                 .addTransportType(TRANSPORT_WIFI).build();
6059         mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
6060 
6061         // Cell connects and validates.
6062         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR,
6063                 new LinkProperties(), null /* ncTemplate */, cellProvider);
6064         mCellAgent.connect(true);
6065         cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
6066         cellCallback.assertNoCallback();
6067         wifiCallback.assertNoCallback();
6068 
6069         // Bring up wifi. At first it's invalidated, so cell is still needed.
6070         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI,
6071                 new LinkProperties(), null /* ncTemplate */, wifiProvider);
6072         mWiFiAgent.connect(false);
6073         wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
6074         cellCallback.assertNoCallback();
6075         wifiCallback.assertNoCallback();
6076 
6077         // Wifi validates. Cell is no longer needed, because it's outscored.
6078         mWiFiAgent.setNetworkValid(true /* privateDnsProbeSent */);
6079         // Have CS reconsider the network (see testPartialConnectivity)
6080         mCm.reportNetworkConnectivity(mWiFiAgent.getNetwork(), true);
6081         wifiNetworkCallback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
6082         cellCallback.expectOnNetworkUnneeded(defaultCaps);
6083         wifiCallback.assertNoCallback();
6084 
6085         // Wifi is no longer validated. Cell is needed again.
6086         mWiFiAgent.setNetworkInvalid(true /* invalidBecauseOfPrivateDns */);
6087         mCm.reportNetworkConnectivity(mWiFiAgent.getNetwork(), false);
6088         wifiNetworkCallback.expectCaps(mWiFiAgent,
6089                 c -> !c.hasCapability(NET_CAPABILITY_VALIDATED));
6090         cellCallback.expectOnNetworkNeeded(defaultCaps);
6091         wifiCallback.assertNoCallback();
6092 
6093         // Disconnect wifi and pretend the carrier restricts moving away from bad wifi.
6094         mWiFiAgent.disconnect();
6095         wifiNetworkCallback.expect(LOST, mWiFiAgent);
6096         // This has getAvoidBadWifi return false. This test doesn't change the value of the
6097         // associated setting.
6098         doReturn(0).when(mResources).getInteger(R.integer.config_networkAvoidBadWifi);
6099         mPolicyTracker.reevaluate();
6100         waitForIdle();
6101 
6102         // Connect wifi again, cell is needed until wifi validates.
6103         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI,
6104                 new LinkProperties(), null /* ncTemplate */, wifiProvider);
6105         mWiFiAgent.connect(false);
6106         wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
6107         cellCallback.assertNoCallback();
6108         wifiCallback.assertNoCallback();
6109         mWiFiAgent.setNetworkValid(true /* privateDnsProbeSent */);
6110         mCm.reportNetworkConnectivity(mWiFiAgent.getNetwork(), true);
6111         wifiNetworkCallback.expectCaps(mWiFiAgent,
6112                 c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
6113         cellCallback.expectOnNetworkUnneeded(defaultCaps);
6114         wifiCallback.assertNoCallback();
6115 
6116         // Wifi loses validation. Because the device doesn't avoid bad wifis, cell is
6117         // not needed.
6118         mWiFiAgent.setNetworkInvalid(true /* invalidBecauseOfPrivateDns */);
6119         mCm.reportNetworkConnectivity(mWiFiAgent.getNetwork(), false);
6120         wifiNetworkCallback.expectCaps(mWiFiAgent,
6121                 c -> !c.hasCapability(NET_CAPABILITY_VALIDATED));
6122         cellCallback.assertNoCallback();
6123         wifiCallback.assertNoCallback();
6124     }
6125 
6126     public void doTestPreferBadWifi(final boolean avoidBadWifi,
6127             final boolean preferBadWifi, final boolean explicitlySelected,
6128             @NonNull Predicate<Long> checkUnvalidationTimeout) throws Exception {
6129         // Pretend we're on a carrier that restricts switching away from bad wifi, and
6130         // depending on the parameter one that may indeed prefer bad wifi.
6131         doReturn(avoidBadWifi ? 1 : 0).when(mResources)
6132                 .getInteger(R.integer.config_networkAvoidBadWifi);
6133         doReturn(preferBadWifi ? 1 : 0).when(mResources)
6134                 .getInteger(R.integer.config_activelyPreferBadWifi);
6135         mPolicyTracker.reevaluate();
6136 
6137         registerDefaultNetworkCallbacks();
6138         final NetworkRequest wifiRequest = new NetworkRequest.Builder()
6139                 .clearCapabilities()
6140                 .addTransportType(TRANSPORT_WIFI)
6141                 .build();
6142         final TestNetworkCallback wifiCallback = new TestNetworkCallback();
6143         mCm.registerNetworkCallback(wifiRequest, wifiCallback);
6144 
6145         // Bring up validated cell and unvalidated wifi.
6146         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
6147         mCellAgent.connect(true);
6148         mDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
6149 
6150         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
6151         mWiFiAgent.explicitlySelected(explicitlySelected, false /* acceptUnvalidated */);
6152         mWiFiAgent.connect(false);
6153         wifiCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
6154 
6155         assertNotNull(mDeps.mScheduledEvaluationTimeouts.poll(TIMEOUT_MS,
6156                 t -> t.first == mWiFiAgent.getNetwork().netId
6157                         && checkUnvalidationTimeout.test(t.second)));
6158 
6159         if (!avoidBadWifi && preferBadWifi) {
6160             expectUnvalidationCheckWillNotify(mWiFiAgent, NotificationType.LOST_INTERNET);
6161             mDefaultNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
6162         } else {
6163             expectUnvalidationCheckWillNotNotify(mWiFiAgent);
6164             mDefaultNetworkCallback.assertNoCallback();
6165         }
6166     }
6167 
6168     @Test
6169     public void testPreferBadWifi_doNotAvoid_doNotPrefer() throws Exception {
6170         // Starting with U this mode is no longer supported and can't actually be tested
6171         assumeFalse(mDeps.isAtLeastU());
6172         doTestPreferBadWifi(false /* avoidBadWifi */, false /* preferBadWifi */,
6173                 false /* explicitlySelected */, timeout -> timeout < 14_000);
6174     }
6175 
6176     @Test
6177     public void testPreferBadWifi_doNotAvoid_doPrefer_notExplicit() throws Exception {
6178         doTestPreferBadWifi(false /* avoidBadWifi */, true /* preferBadWifi */,
6179                 false /* explicitlySelected */, timeout -> timeout > 14_000);
6180     }
6181 
6182     @Test
6183     public void testPreferBadWifi_doNotAvoid_doPrefer_explicitlySelected() throws Exception {
6184         doTestPreferBadWifi(false /* avoidBadWifi */, true /* preferBadWifi */,
6185                 true /* explicitlySelected */, timeout -> timeout < 14_000);
6186     }
6187 
6188     @Test
6189     public void testPreferBadWifi_doAvoid_doNotPrefer() throws Exception {
6190         // If avoidBadWifi=true, then preferBadWifi should be irrelevant. Test anyway.
6191         doTestPreferBadWifi(true /* avoidBadWifi */, false /* preferBadWifi */,
6192                 false /* explicitlySelected */, timeout -> timeout < 14_000);
6193     }
6194 
6195     @Test
6196     public void testPreferBadWifi_doAvoid_doPrefer() throws Exception {
6197         // If avoidBadWifi=true, then preferBadWifi should be irrelevant. Test anyway.
6198         doTestPreferBadWifi(true /* avoidBadWifi */, true /* preferBadWifi */,
6199                 false /* explicitlySelected */, timeout -> timeout < 14_000);
6200     }
6201 
6202     @Test
6203     public void testAvoidBadWifi() throws Exception {
6204         final ContentResolver cr = mServiceContext.getContentResolver();
6205 
6206         // Pretend we're on a carrier that restricts switching away from bad wifi.
6207         doReturn(0).when(mResources).getInteger(R.integer.config_networkAvoidBadWifi);
6208 
6209         // File a request for cell to ensure it doesn't go down.
6210         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
6211         final NetworkRequest cellRequest = new NetworkRequest.Builder()
6212                 .addTransportType(TRANSPORT_CELLULAR).build();
6213         mCm.requestNetwork(cellRequest, cellNetworkCallback);
6214 
6215         TestNetworkCallback defaultCallback = new TestNetworkCallback();
6216         mCm.registerDefaultNetworkCallback(defaultCallback);
6217 
6218         NetworkRequest validatedWifiRequest = new NetworkRequest.Builder()
6219                 .addTransportType(TRANSPORT_WIFI)
6220                 .addCapability(NET_CAPABILITY_VALIDATED)
6221                 .build();
6222         TestNetworkCallback validatedWifiCallback = new TestNetworkCallback();
6223         mCm.registerNetworkCallback(validatedWifiRequest, validatedWifiCallback);
6224 
6225         // Prompt mode, so notifications can be tested
6226         Settings.Global.putString(cr, ConnectivitySettingsManager.NETWORK_AVOID_BAD_WIFI, null);
6227         mPolicyTracker.reevaluate();
6228 
6229         // Bring up validated cell.
6230         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
6231         mCellAgent.connect(true);
6232         cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
6233         defaultCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
6234         Network cellNetwork = mCellAgent.getNetwork();
6235 
6236         // Bring up validated wifi.
6237         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
6238         mWiFiAgent.connect(true);
6239         defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiAgent);
6240         validatedWifiCallback.expectAvailableDoubleValidatedCallbacks(mWiFiAgent);
6241         Network wifiNetwork = mWiFiAgent.getNetwork();
6242 
6243         // Fail validation on wifi.
6244         mWiFiAgent.setNetworkInvalid(false /* invalidBecauseOfPrivateDns */);
6245         mCm.reportNetworkConnectivity(wifiNetwork, false);
6246         defaultCallback.expectCaps(mWiFiAgent, c -> !c.hasCapability(NET_CAPABILITY_VALIDATED));
6247         validatedWifiCallback.expect(LOST, mWiFiAgent);
6248         expectNotification(mWiFiAgent, NotificationType.LOST_INTERNET);
6249 
6250         // Because avoid bad wifi is off, we don't switch to cellular.
6251         defaultCallback.assertNoCallback();
6252         assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
6253                 NET_CAPABILITY_VALIDATED));
6254         assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
6255                 NET_CAPABILITY_VALIDATED));
6256         assertEquals(mCm.getActiveNetwork(), wifiNetwork);
6257 
6258         // Simulate switching to a carrier that does not restrict avoiding bad wifi, and expect
6259         // that we switch back to cell.
6260         doReturn(1).when(mResources).getInteger(R.integer.config_networkAvoidBadWifi);
6261         mPolicyTracker.reevaluate();
6262         defaultCallback.expectAvailableCallbacksValidated(mCellAgent);
6263         assertEquals(mCm.getActiveNetwork(), cellNetwork);
6264         expectClearNotification(mWiFiAgent, NotificationType.LOST_INTERNET);
6265 
6266         // Switch back to a restrictive carrier.
6267         doReturn(0).when(mResources).getInteger(R.integer.config_networkAvoidBadWifi);
6268         mPolicyTracker.reevaluate();
6269         defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
6270         assertEquals(mCm.getActiveNetwork(), wifiNetwork);
6271         // A notification was already shown for this very network.
6272         expectNoNotification(mWiFiAgent);
6273 
6274         // Simulate the user selecting "switch" on the dialog, and check that we switch to cell.
6275         // In principle this is a little bit unrealistic because the switch to a less restrictive
6276         // carrier above should have remove the notification but this doesn't matter for the
6277         // purposes of this test.
6278         mCm.setAvoidUnvalidated(wifiNetwork);
6279         defaultCallback.expectAvailableCallbacksValidated(mCellAgent);
6280         assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
6281                 NET_CAPABILITY_VALIDATED));
6282         assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
6283                 NET_CAPABILITY_VALIDATED));
6284         assertEquals(mCm.getActiveNetwork(), cellNetwork);
6285 
6286         // Disconnect and reconnect wifi to clear the one-time switch above.
6287         mWiFiAgent.disconnect();
6288         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
6289         mWiFiAgent.connect(true);
6290         defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiAgent);
6291         validatedWifiCallback.expectAvailableDoubleValidatedCallbacks(mWiFiAgent);
6292         wifiNetwork = mWiFiAgent.getNetwork();
6293 
6294         // Fail validation on wifi and expect the dialog to appear.
6295         mWiFiAgent.setNetworkInvalid(false /* invalidBecauseOfPrivateDns */);
6296         mCm.reportNetworkConnectivity(wifiNetwork, false);
6297         defaultCallback.expectCaps(mWiFiAgent, c -> !c.hasCapability(NET_CAPABILITY_VALIDATED));
6298         validatedWifiCallback.expect(LOST, mWiFiAgent);
6299         expectNotification(mWiFiAgent, NotificationType.LOST_INTERNET);
6300 
6301         // Simulate the user selecting "switch" and checking the don't ask again checkbox.
6302         Settings.Global.putInt(cr, ConnectivitySettingsManager.NETWORK_AVOID_BAD_WIFI, 1);
6303         mPolicyTracker.reevaluate();
6304 
6305         // We now switch to cell.
6306         defaultCallback.expectAvailableCallbacksValidated(mCellAgent);
6307         assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
6308                 NET_CAPABILITY_VALIDATED));
6309         assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
6310                 NET_CAPABILITY_VALIDATED));
6311         assertEquals(mCm.getActiveNetwork(), cellNetwork);
6312         expectClearNotification(mWiFiAgent, NotificationType.LOST_INTERNET);
6313 
6314         // Simulate the user turning the cellular fallback setting off and then on.
6315         // We switch to wifi and then to cell.
6316         Settings.Global.putString(cr, ConnectivitySettingsManager.NETWORK_AVOID_BAD_WIFI, null);
6317         mPolicyTracker.reevaluate();
6318         defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
6319         assertEquals(mCm.getActiveNetwork(), wifiNetwork);
6320         // Notification is cleared again because CS doesn't particularly remember that it has
6321         // cleared it before, and if it hasn't cleared it before then it should do so now.
6322         expectClearNotification(mWiFiAgent, NotificationType.LOST_INTERNET);
6323         Settings.Global.putInt(cr, ConnectivitySettingsManager.NETWORK_AVOID_BAD_WIFI, 1);
6324         mPolicyTracker.reevaluate();
6325         defaultCallback.expectAvailableCallbacksValidated(mCellAgent);
6326         assertEquals(mCm.getActiveNetwork(), cellNetwork);
6327 
6328         // If cell goes down, we switch to wifi.
6329         mCellAgent.disconnect();
6330         defaultCallback.expect(LOST, mCellAgent);
6331         defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
6332         validatedWifiCallback.assertNoCallback();
6333         // Notification is cleared yet again because the device switched to wifi.
6334         expectClearNotification(mWiFiAgent, NotificationType.LOST_INTERNET);
6335 
6336         mCm.unregisterNetworkCallback(cellNetworkCallback);
6337         mCm.unregisterNetworkCallback(validatedWifiCallback);
6338         mCm.unregisterNetworkCallback(defaultCallback);
6339     }
6340 
6341     @Test
6342     public void testMeteredMultipathPreferenceSetting() throws Exception {
6343         final ContentResolver cr = mServiceContext.getContentResolver();
6344         final String settingName = ConnectivitySettingsManager.NETWORK_METERED_MULTIPATH_PREFERENCE;
6345 
6346         for (int config : asList(0, 3, 2)) {
6347             for (String setting: asList(null, "0", "2", "1")) {
6348                 mPolicyTracker.mConfigMeteredMultipathPreference = config;
6349                 Settings.Global.putString(cr, settingName, setting);
6350                 mPolicyTracker.reevaluate();
6351                 waitForIdle();
6352 
6353                 final int expected = (setting != null) ? Integer.parseInt(setting) : config;
6354                 String msg = String.format("config=%d, setting=%s", config, setting);
6355                 assertEquals(msg, expected, mCm.getMultipathPreference(null));
6356             }
6357         }
6358     }
6359 
6360     /**
6361      * Validate that a satisfied network request does not trigger onUnavailable() once the
6362      * time-out period expires.
6363      */
6364     @Test
6365     public void testSatisfiedNetworkRequestDoesNotTriggerOnUnavailable() throws Exception {
6366         NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
6367                 NetworkCapabilities.TRANSPORT_WIFI).build();
6368         final TestNetworkCallback networkCallback = new TestNetworkCallback();
6369         mCm.requestNetwork(nr, networkCallback, TEST_REQUEST_TIMEOUT_MS);
6370 
6371         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
6372         mWiFiAgent.connect(false);
6373         networkCallback.expectAvailableCallbacks(mWiFiAgent, false, false, false,
6374                 TEST_CALLBACK_TIMEOUT_MS);
6375 
6376         // pass timeout and validate that UNAVAILABLE is not called
6377         networkCallback.assertNoCallback();
6378     }
6379 
6380     /**
6381      * Validate that a satisfied network request followed by a disconnected (lost) network does
6382      * not trigger onUnavailable() once the time-out period expires.
6383      */
6384     @Test
6385     public void testSatisfiedThenLostNetworkRequestDoesNotTriggerOnUnavailable() throws Exception {
6386         NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
6387                 NetworkCapabilities.TRANSPORT_WIFI).build();
6388         final TestNetworkCallback networkCallback = new TestNetworkCallback();
6389         mCm.requestNetwork(nr, networkCallback, TEST_REQUEST_TIMEOUT_MS);
6390 
6391         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
6392         mWiFiAgent.connect(false);
6393         networkCallback.expectAvailableCallbacks(mWiFiAgent, false, false, false,
6394                 TEST_CALLBACK_TIMEOUT_MS);
6395         mWiFiAgent.disconnect();
6396         networkCallback.expect(LOST, mWiFiAgent);
6397 
6398         // Validate that UNAVAILABLE is not called
6399         networkCallback.assertNoCallback();
6400     }
6401 
6402     /**
6403      * Validate that when a time-out is specified for a network request the onUnavailable()
6404      * callback is called when time-out expires. Then validate that if network request is
6405      * (somehow) satisfied - the callback isn't called later.
6406      */
6407     @Test
6408     public void testTimedoutNetworkRequest() throws Exception {
6409         NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
6410                 NetworkCapabilities.TRANSPORT_WIFI).build();
6411         final TestNetworkCallback networkCallback = new TestNetworkCallback();
6412         final int timeoutMs = 10;
6413         mCm.requestNetwork(nr, networkCallback, timeoutMs);
6414 
6415         // pass timeout and validate that UNAVAILABLE is called
6416         networkCallback.expect(UNAVAILABLE);
6417 
6418         // create a network satisfying request - validate that request not triggered
6419         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
6420         mWiFiAgent.connect(false);
6421         networkCallback.assertNoCallback();
6422     }
6423 
6424     /**
6425      * Validate that when a network request is unregistered (cancelled), no posterior event can
6426      * trigger the callback.
6427      */
6428     @Test
6429     public void testNoCallbackAfterUnregisteredNetworkRequest() throws Exception {
6430         NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
6431                 NetworkCapabilities.TRANSPORT_WIFI).build();
6432         final TestNetworkCallback networkCallback = new TestNetworkCallback();
6433         final int timeoutMs = 10;
6434 
6435         mCm.requestNetwork(nr, networkCallback, timeoutMs);
6436         mCm.unregisterNetworkCallback(networkCallback);
6437         // Regardless of the timeout, unregistering the callback in ConnectivityManager ensures
6438         // that this callback will not be called.
6439         networkCallback.assertNoCallback();
6440 
6441         // create a network satisfying request - validate that request not triggered
6442         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
6443         mWiFiAgent.connect(false);
6444         networkCallback.assertNoCallback();
6445     }
6446 
6447     @Test
6448     public void testUnfulfillableNetworkRequest() throws Exception {
6449         runUnfulfillableNetworkRequest(false);
6450     }
6451 
6452     @Test
6453     public void testUnfulfillableNetworkRequestAfterUnregister() throws Exception {
6454         runUnfulfillableNetworkRequest(true);
6455     }
6456 
6457     /**
6458      * Validate the callback flow for a factory releasing a request as unfulfillable.
6459      */
6460     private void runUnfulfillableNetworkRequest(boolean preUnregister) throws Exception {
6461         NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
6462                 NetworkCapabilities.TRANSPORT_WIFI).build();
6463         final TestNetworkCallback networkCallback = new TestNetworkCallback();
6464 
6465         final HandlerThread handlerThread = new HandlerThread("testUnfulfillableNetworkRequest");
6466         handlerThread.start();
6467         NetworkCapabilities filter = new NetworkCapabilities()
6468                 .addTransportType(TRANSPORT_WIFI)
6469                 .addCapability(NET_CAPABILITY_INTERNET)
6470                 .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED);
6471         final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
6472                 mServiceContext, "testFactory", filter, mCsHandlerThread);
6473         testFactory.setScoreFilter(40);
6474 
6475         // Register the factory and expect it to receive the default request.
6476         testFactory.register();
6477         testFactory.expectRequestAdd();
6478 
6479         try {
6480             // Now file the test request and expect it.
6481             mCm.requestNetwork(nr, networkCallback);
6482             final NetworkRequest newRequest = testFactory.expectRequestAdd().request;
6483 
6484             if (preUnregister) {
6485                 mCm.unregisterNetworkCallback(networkCallback);
6486 
6487                 // The request has been released : the factory should see it removed
6488                 // immediately.
6489                 testFactory.expectRequestRemove();
6490 
6491                 // Simulate the factory releasing the request as unfulfillable: no-op since
6492                 // the callback has already been unregistered (but a test that no exceptions are
6493                 // thrown).
6494                 testFactory.triggerUnfulfillable(newRequest);
6495             } else {
6496                 // Simulate the factory releasing the request as unfulfillable and expect
6497                 // onUnavailable!
6498                 testFactory.triggerUnfulfillable(newRequest);
6499 
6500                 networkCallback.expect(UNAVAILABLE);
6501 
6502                 // Declaring a request unfulfillable releases it automatically.
6503                 testFactory.expectRequestRemove();
6504 
6505                 // unregister network callback - a no-op (since already freed by the
6506                 // on-unavailable), but should not fail or throw exceptions.
6507                 mCm.unregisterNetworkCallback(networkCallback);
6508 
6509                 // The factory should not see any further removal, as this request has
6510                 // already been removed.
6511             }
6512         } finally {
6513             testFactory.terminate();
6514             handlerThread.quit();
6515         }
6516     }
6517 
6518     @Test
6519     @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
6520     @DisableCompatChanges(ConnectivityCompatChanges.ENABLE_SELF_CERTIFIED_CAPABILITIES_DECLARATION)
6521     public void testSelfCertifiedCapabilitiesDisabled()
6522             throws Exception {
6523         mDeps.enableCompatChangeCheck();
6524         final NetworkRequest networkRequest = new NetworkRequest.Builder()
6525                 .addCapability(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_LATENCY)
6526                 .addCapability(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_BANDWIDTH)
6527                 .build();
6528         final TestNetworkCallback cb = new TestNetworkCallback();
6529         mCm.requestNetwork(networkRequest, cb);
6530         mCm.unregisterNetworkCallback(cb);
6531     }
6532 
6533     /** Set the networkSliceResourceId to 0 will result in NameNotFoundException be thrown. */
6534     private void setupMockForNetworkCapabilitiesResources(int networkSliceResourceId)
6535             throws PackageManager.NameNotFoundException {
6536         if (networkSliceResourceId == 0) {
6537             doThrow(new PackageManager.NameNotFoundException()).when(mPackageManager).getProperty(
6538                     ConstantsShim.PROPERTY_SELF_CERTIFIED_NETWORK_CAPABILITIES,
6539                     mContext.getPackageName());
6540         } else {
6541             final PackageManager.Property property = new PackageManager.Property(
6542                     ConstantsShim.PROPERTY_SELF_CERTIFIED_NETWORK_CAPABILITIES,
6543                     networkSliceResourceId,
6544                     true /* isResource */,
6545                     mContext.getPackageName(),
6546                     "dummyClass"
6547             );
6548             doReturn(property).when(mPackageManager).getProperty(
6549                     ConstantsShim.PROPERTY_SELF_CERTIFIED_NETWORK_CAPABILITIES,
6550                     mContext.getPackageName());
6551             doReturn(mContext.getResources()).when(mPackageManager).getResourcesForApplication(
6552                     mContext.getPackageName());
6553         }
6554     }
6555 
6556     @Test
6557     @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
6558     @EnableCompatChanges(ConnectivityCompatChanges.ENABLE_SELF_CERTIFIED_CAPABILITIES_DECLARATION)
6559     public void requestNetwork_withoutPrioritizeBandwidthDeclaration_shouldThrowException()
6560             throws Exception {
6561         mDeps.enableCompatChangeCheck();
6562         setupMockForNetworkCapabilitiesResources(
6563                 com.android.frameworks.tests.net.R.xml.self_certified_capabilities_latency);
6564         final NetworkRequest networkRequest = new NetworkRequest.Builder()
6565                 .addCapability(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_BANDWIDTH)
6566                 .build();
6567         final TestNetworkCallback cb = new TestNetworkCallback();
6568         final Exception e = assertThrows(SecurityException.class,
6569                 () -> mCm.requestNetwork(networkRequest, cb));
6570         assertThat(e.getMessage(),
6571                 containsString(ApplicationSelfCertifiedNetworkCapabilities.PRIORITIZE_BANDWIDTH));
6572     }
6573 
6574     @Test
6575     @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
6576     @EnableCompatChanges(ConnectivityCompatChanges.ENABLE_SELF_CERTIFIED_CAPABILITIES_DECLARATION)
6577     public void requestNetwork_withoutPrioritizeLatencyDeclaration_shouldThrowException()
6578             throws Exception {
6579         mDeps.enableCompatChangeCheck();
6580         setupMockForNetworkCapabilitiesResources(
6581                 com.android.frameworks.tests.net.R.xml.self_certified_capabilities_bandwidth);
6582         final NetworkRequest networkRequest = new NetworkRequest.Builder()
6583                 .addCapability(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_LATENCY)
6584                 .build();
6585         final TestNetworkCallback cb = new TestNetworkCallback();
6586         final Exception e = assertThrows(SecurityException.class,
6587                 () -> mCm.requestNetwork(networkRequest, cb));
6588         assertThat(e.getMessage(),
6589                 containsString(ApplicationSelfCertifiedNetworkCapabilities.PRIORITIZE_LATENCY));
6590     }
6591 
6592     @Test
6593     @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
6594     @EnableCompatChanges(ConnectivityCompatChanges.ENABLE_SELF_CERTIFIED_CAPABILITIES_DECLARATION)
6595     public void requestNetwork_withoutNetworkSliceProperty_shouldThrowException() throws Exception {
6596         mDeps.enableCompatChangeCheck();
6597         setupMockForNetworkCapabilitiesResources(0 /* networkSliceResourceId */);
6598         final NetworkRequest networkRequest = new NetworkRequest.Builder()
6599                 .addCapability(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_LATENCY)
6600                 .addCapability(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_BANDWIDTH)
6601                 .build();
6602         final TestNetworkCallback cb = new TestNetworkCallback();
6603         final Exception e = assertThrows(SecurityException.class,
6604                 () -> mCm.requestNetwork(networkRequest, cb));
6605         assertThat(e.getMessage(),
6606                 containsString(ConstantsShim.PROPERTY_SELF_CERTIFIED_NETWORK_CAPABILITIES));
6607     }
6608 
6609     @Test
6610     @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
6611     @EnableCompatChanges(ConnectivityCompatChanges.ENABLE_SELF_CERTIFIED_CAPABILITIES_DECLARATION)
6612     public void requestNetwork_withNetworkSliceDeclaration_shouldSucceed() throws Exception {
6613         mDeps.enableCompatChangeCheck();
6614         setupMockForNetworkCapabilitiesResources(
6615                 com.android.frameworks.tests.net.R.xml.self_certified_capabilities_both);
6616 
6617         final NetworkRequest networkRequest = new NetworkRequest.Builder()
6618                 .addCapability(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_LATENCY)
6619                 .addCapability(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_BANDWIDTH)
6620                 .build();
6621         final TestNetworkCallback cb = new TestNetworkCallback();
6622         mCm.requestNetwork(networkRequest, cb);
6623         mCm.unregisterNetworkCallback(cb);
6624     }
6625 
6626     @Test
6627     @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
6628     @EnableCompatChanges(ConnectivityCompatChanges.ENABLE_SELF_CERTIFIED_CAPABILITIES_DECLARATION)
6629     public void requestNetwork_withNetworkSliceDeclaration_shouldUseCache() throws Exception {
6630         mDeps.enableCompatChangeCheck();
6631         setupMockForNetworkCapabilitiesResources(
6632                 com.android.frameworks.tests.net.R.xml.self_certified_capabilities_both);
6633 
6634         final NetworkRequest networkRequest = new NetworkRequest.Builder()
6635                 .addCapability(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_LATENCY)
6636                 .addCapability(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_BANDWIDTH)
6637                 .build();
6638         final TestNetworkCallback cb = new TestNetworkCallback();
6639         mCm.requestNetwork(networkRequest, cb);
6640         mCm.unregisterNetworkCallback(cb);
6641 
6642         // Second call should use caches
6643         mCm.requestNetwork(networkRequest, cb);
6644         mCm.unregisterNetworkCallback(cb);
6645 
6646         // PackageManager's API only called once because the second call is using cache.
6647         verify(mPackageManager, times(1)).getProperty(
6648                 ConstantsShim.PROPERTY_SELF_CERTIFIED_NETWORK_CAPABILITIES,
6649                 mContext.getPackageName());
6650         verify(mPackageManager, times(1)).getResourcesForApplication(
6651                 mContext.getPackageName());
6652     }
6653 
6654     /**
6655      * Validate the service throws if request with CBS but without carrier privilege.
6656      */
6657     @Test
6658     public void testCBSRequestWithoutCarrierPrivilege() throws Exception {
6659         final NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
6660                 TRANSPORT_CELLULAR).addCapability(NET_CAPABILITY_CBS).build();
6661         final TestNetworkCallback networkCallback = new TestNetworkCallback();
6662 
6663         mServiceContext.setPermission(CONNECTIVITY_USE_RESTRICTED_NETWORKS, PERMISSION_DENIED);
6664         // Now file the test request and expect the service throws.
6665         assertThrows(SecurityException.class, () -> mCm.requestNetwork(nr, networkCallback));
6666     }
6667 
6668     private static class TestKeepaliveCallback extends PacketKeepaliveCallback {
6669 
6670         public enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR }
6671 
6672         private class CallbackValue {
6673             public CallbackType callbackType;
6674             public int error;
6675 
6676             public CallbackValue(CallbackType type) {
6677                 this.callbackType = type;
6678                 this.error = PacketKeepalive.SUCCESS;
6679                 assertTrue("onError callback must have error", type != CallbackType.ON_ERROR);
6680             }
6681 
6682             public CallbackValue(CallbackType type, int error) {
6683                 this.callbackType = type;
6684                 this.error = error;
6685                 assertEquals("error can only be set for onError", type, CallbackType.ON_ERROR);
6686             }
6687 
6688             @Override
6689             public boolean equals(Object o) {
6690                 return o instanceof CallbackValue &&
6691                         this.callbackType == ((CallbackValue) o).callbackType &&
6692                         this.error == ((CallbackValue) o).error;
6693             }
6694 
6695             @Override
6696             public String toString() {
6697                 return String.format("%s(%s, %d)", getClass().getSimpleName(), callbackType, error);
6698             }
6699         }
6700 
6701         private final LinkedBlockingQueue<CallbackValue> mCallbacks = new LinkedBlockingQueue<>();
6702 
6703         @Override
6704         public void onStarted() {
6705             mCallbacks.add(new CallbackValue(CallbackType.ON_STARTED));
6706         }
6707 
6708         @Override
6709         public void onStopped() {
6710             mCallbacks.add(new CallbackValue(CallbackType.ON_STOPPED));
6711         }
6712 
6713         @Override
6714         public void onError(int error) {
6715             mCallbacks.add(new CallbackValue(CallbackType.ON_ERROR, error));
6716         }
6717 
6718         private void expect(CallbackValue callbackValue) throws InterruptedException {
6719             assertEquals(callbackValue, mCallbacks.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
6720         }
6721 
6722         public void expectStarted() throws Exception {
6723             expect(new CallbackValue(CallbackType.ON_STARTED));
6724         }
6725 
6726         public void expectStopped() throws Exception {
6727             expect(new CallbackValue(CallbackType.ON_STOPPED));
6728         }
6729 
6730         public void expectError(int error) throws Exception {
6731             expect(new CallbackValue(CallbackType.ON_ERROR, error));
6732         }
6733     }
6734 
6735     private static class TestSocketKeepaliveCallback extends SocketKeepalive.Callback {
6736 
6737         public enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR };
6738 
6739         private class CallbackValue {
6740             public CallbackType callbackType;
6741             public int error;
6742 
6743             CallbackValue(CallbackType type) {
6744                 this.callbackType = type;
6745                 this.error = SocketKeepalive.SUCCESS;
6746                 assertTrue("onError callback must have error", type != CallbackType.ON_ERROR);
6747             }
6748 
6749             CallbackValue(CallbackType type, int error) {
6750                 this.callbackType = type;
6751                 this.error = error;
6752                 assertEquals("error can only be set for onError", type, CallbackType.ON_ERROR);
6753             }
6754 
6755             @Override
6756             public boolean equals(Object o) {
6757                 return o instanceof CallbackValue
6758                         && this.callbackType == ((CallbackValue) o).callbackType
6759                         && this.error == ((CallbackValue) o).error;
6760             }
6761 
6762             @Override
6763             public String toString() {
6764                 return String.format("%s(%s, %d)", getClass().getSimpleName(), callbackType,
6765                         error);
6766             }
6767         }
6768 
6769         private LinkedBlockingQueue<CallbackValue> mCallbacks = new LinkedBlockingQueue<>();
6770         private final Executor mExecutor;
6771 
6772         TestSocketKeepaliveCallback(@NonNull Executor executor) {
6773             mExecutor = executor;
6774         }
6775 
6776         @Override
6777         public void onStarted() {
6778             mCallbacks.add(new CallbackValue(CallbackType.ON_STARTED));
6779         }
6780 
6781         @Override
6782         public void onStopped() {
6783             mCallbacks.add(new CallbackValue(CallbackType.ON_STOPPED));
6784         }
6785 
6786         @Override
6787         public void onError(int error) {
6788             mCallbacks.add(new CallbackValue(CallbackType.ON_ERROR, error));
6789         }
6790 
6791         private void expect(CallbackValue callbackValue) throws InterruptedException {
6792             assertEquals(callbackValue, mCallbacks.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
6793 
6794         }
6795 
6796         public void expectStarted() throws InterruptedException {
6797             expect(new CallbackValue(CallbackType.ON_STARTED));
6798         }
6799 
6800         public void expectStopped() throws InterruptedException {
6801             expect(new CallbackValue(CallbackType.ON_STOPPED));
6802         }
6803 
6804         public void expectError(int error) throws InterruptedException {
6805             expect(new CallbackValue(CallbackType.ON_ERROR, error));
6806         }
6807 
6808         public void assertNoCallback() {
6809             waitForIdleSerialExecutor(mExecutor, TIMEOUT_MS);
6810             CallbackValue cv = mCallbacks.peek();
6811             assertNull("Unexpected callback: " + cv, cv);
6812         }
6813     }
6814 
6815     private Network connectKeepaliveNetwork(LinkProperties lp) throws Exception {
6816         // Ensure the network is disconnected before anything else occurs
6817         if (mWiFiAgent != null) {
6818             assertNull(mCm.getNetworkCapabilities(mWiFiAgent.getNetwork()));
6819         }
6820 
6821         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
6822         ExpectedBroadcast b = expectConnectivityAction(TYPE_WIFI, DetailedState.CONNECTED);
6823         mWiFiAgent.connect(true);
6824         b.expectBroadcast();
6825         verifyActiveNetwork(TRANSPORT_WIFI);
6826         mWiFiAgent.sendLinkProperties(lp);
6827         waitForIdle();
6828         return mWiFiAgent.getNetwork();
6829     }
6830 
6831     @Test
6832     public void testPacketKeepalives() throws Exception {
6833         InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
6834         InetAddress notMyIPv4 = InetAddress.getByName("192.0.2.35");
6835         InetAddress myIPv6 = InetAddress.getByName("2001:db8::1");
6836         InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8");
6837         InetAddress dstIPv6 = InetAddress.getByName("2001:4860:4860::8888");
6838 
6839         final int validKaInterval = 15;
6840         final int invalidKaInterval = 9;
6841 
6842         LinkProperties lp = new LinkProperties();
6843         lp.setInterfaceName("wlan12");
6844         lp.addLinkAddress(new LinkAddress(myIPv6, 64));
6845         lp.addLinkAddress(new LinkAddress(myIPv4, 25));
6846         lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
6847         lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
6848 
6849         Network notMyNet = new Network(61234);
6850         Network myNet = connectKeepaliveNetwork(lp);
6851 
6852         TestKeepaliveCallback callback = new TestKeepaliveCallback();
6853         PacketKeepalive ka;
6854 
6855         // Attempt to start keepalives with invalid parameters and check for errors.
6856         ka = mCm.startNattKeepalive(notMyNet, validKaInterval, callback, myIPv4, 1234, dstIPv4);
6857         callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK);
6858 
6859         ka = mCm.startNattKeepalive(myNet, invalidKaInterval, callback, myIPv4, 1234, dstIPv4);
6860         callback.expectError(PacketKeepalive.ERROR_INVALID_INTERVAL);
6861 
6862         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 1234, dstIPv6);
6863         callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
6864 
6865         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv6, 1234, dstIPv4);
6866         callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
6867 
6868         // NAT-T is only supported for IPv4.
6869         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv6, 1234, dstIPv6);
6870         callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
6871 
6872         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 123456, dstIPv4);
6873         callback.expectError(PacketKeepalive.ERROR_INVALID_PORT);
6874 
6875         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 123456, dstIPv4);
6876         callback.expectError(PacketKeepalive.ERROR_INVALID_PORT);
6877 
6878         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
6879         callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
6880 
6881         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
6882         callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
6883 
6884         // Check that a started keepalive can be stopped.
6885         mWiFiAgent.setStartKeepaliveEvent(PacketKeepalive.SUCCESS);
6886         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
6887         callback.expectStarted();
6888         mWiFiAgent.setStopKeepaliveEvent(PacketKeepalive.SUCCESS);
6889         ka.stop();
6890         callback.expectStopped();
6891 
6892         // Check that deleting the IP address stops the keepalive.
6893         LinkProperties bogusLp = new LinkProperties(lp);
6894         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
6895         callback.expectStarted();
6896         bogusLp.removeLinkAddress(new LinkAddress(myIPv4, 25));
6897         bogusLp.addLinkAddress(new LinkAddress(notMyIPv4, 25));
6898         mWiFiAgent.sendLinkProperties(bogusLp);
6899         callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
6900         mWiFiAgent.sendLinkProperties(lp);
6901 
6902         // Check that a started keepalive is stopped correctly when the network disconnects.
6903         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
6904         callback.expectStarted();
6905         mWiFiAgent.disconnect();
6906         mWiFiAgent.expectDisconnected();
6907         callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK);
6908 
6909         // ... and that stopping it after that has no adverse effects.
6910         waitForIdle();
6911         final Network myNetAlias = myNet;
6912         assertNull(mCm.getNetworkCapabilities(myNetAlias));
6913         ka.stop();
6914 
6915         // Reconnect.
6916         myNet = connectKeepaliveNetwork(lp);
6917         mWiFiAgent.setStartKeepaliveEvent(PacketKeepalive.SUCCESS);
6918 
6919         // Check that keepalive slots start from 1 and increment. The first one gets slot 1.
6920         mWiFiAgent.setExpectedKeepaliveSlot(1);
6921         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
6922         callback.expectStarted();
6923 
6924         // The second one gets slot 2.
6925         mWiFiAgent.setExpectedKeepaliveSlot(2);
6926         TestKeepaliveCallback callback2 = new TestKeepaliveCallback();
6927         PacketKeepalive ka2 = mCm.startNattKeepalive(
6928                 myNet, validKaInterval, callback2, myIPv4, 6789, dstIPv4);
6929         callback2.expectStarted();
6930 
6931         // Now stop the first one and create a third. This also gets slot 1.
6932         ka.stop();
6933         callback.expectStopped();
6934 
6935         mWiFiAgent.setExpectedKeepaliveSlot(1);
6936         TestKeepaliveCallback callback3 = new TestKeepaliveCallback();
6937         PacketKeepalive ka3 = mCm.startNattKeepalive(
6938                 myNet, validKaInterval, callback3, myIPv4, 9876, dstIPv4);
6939         callback3.expectStarted();
6940 
6941         ka2.stop();
6942         callback2.expectStopped();
6943 
6944         ka3.stop();
6945         callback3.expectStopped();
6946     }
6947 
6948     // Helper method to prepare the executor and run test
6949     private void runTestWithSerialExecutors(ThrowingConsumer<Executor> functor)
6950             throws Exception {
6951         final ExecutorService executorSingleThread = Executors.newSingleThreadExecutor();
6952         final Executor executorInline = (Runnable r) -> r.run();
6953         functor.accept(executorSingleThread);
6954         executorSingleThread.shutdown();
6955         functor.accept(executorInline);
6956     }
6957 
6958     @Test
6959     public void testNattSocketKeepalives() throws Exception {
6960         runTestWithSerialExecutors(executor -> doTestNattSocketKeepalivesWithExecutor(executor));
6961         runTestWithSerialExecutors(executor -> doTestNattSocketKeepalivesFdWithExecutor(executor));
6962     }
6963 
6964     private void doTestNattSocketKeepalivesWithExecutor(Executor executor) throws Exception {
6965         // TODO: 1. Move this outside of ConnectivityServiceTest.
6966         //       2. Make test to verify that Nat-T keepalive socket is created by IpSecService.
6967         //       3. Mock ipsec service.
6968         final InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
6969         final InetAddress notMyIPv4 = InetAddress.getByName("192.0.2.35");
6970         final InetAddress myIPv6 = InetAddress.getByName("2001:db8::1");
6971         final InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8");
6972         final InetAddress dstIPv6 = InetAddress.getByName("2001:4860:4860::8888");
6973 
6974         final int validKaInterval = 15;
6975         final int invalidKaInterval = 9;
6976 
6977         final IpSecManager mIpSec = (IpSecManager) mContext.getSystemService(Context.IPSEC_SERVICE);
6978         final UdpEncapsulationSocket testSocket = mIpSec.openUdpEncapsulationSocket();
6979         final int srcPort = testSocket.getPort();
6980 
6981         LinkProperties lp = new LinkProperties();
6982         lp.setInterfaceName("wlan12");
6983         lp.addLinkAddress(new LinkAddress(myIPv6, 64));
6984         lp.addLinkAddress(new LinkAddress(myIPv4, 25));
6985         lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
6986         lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
6987 
6988         Network notMyNet = new Network(61234);
6989         Network myNet = connectKeepaliveNetwork(lp);
6990 
6991         TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback(executor);
6992 
6993         // Attempt to start keepalives with invalid parameters and check for errors.
6994         // Invalid network.
6995         try (SocketKeepalive ka = mCm.createSocketKeepalive(
6996                 notMyNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
6997             ka.start(validKaInterval);
6998             callback.expectError(SocketKeepalive.ERROR_INVALID_NETWORK);
6999         }
7000 
7001         // Invalid interval.
7002         try (SocketKeepalive ka = mCm.createSocketKeepalive(
7003                 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
7004             ka.start(invalidKaInterval);
7005             callback.expectError(SocketKeepalive.ERROR_INVALID_INTERVAL);
7006         }
7007 
7008         // Invalid destination.
7009         try (SocketKeepalive ka = mCm.createSocketKeepalive(
7010                 myNet, testSocket, myIPv4, dstIPv6, executor, callback)) {
7011             ka.start(validKaInterval);
7012             callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
7013         }
7014 
7015         // Invalid source;
7016         try (SocketKeepalive ka = mCm.createSocketKeepalive(
7017                 myNet, testSocket, myIPv6, dstIPv4, executor, callback)) {
7018             ka.start(validKaInterval);
7019             callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
7020         }
7021 
7022         // NAT-T is only supported for IPv4.
7023         try (SocketKeepalive ka = mCm.createSocketKeepalive(
7024                 myNet, testSocket, myIPv6, dstIPv6, executor, callback)) {
7025             ka.start(validKaInterval);
7026             callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
7027         }
7028 
7029         // Basic check before testing started keepalive.
7030         try (SocketKeepalive ka = mCm.createSocketKeepalive(
7031                 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
7032             ka.start(validKaInterval);
7033             callback.expectError(SocketKeepalive.ERROR_UNSUPPORTED);
7034         }
7035 
7036         // Check that a started keepalive can be stopped.
7037         mWiFiAgent.setStartKeepaliveEvent(SocketKeepalive.SUCCESS);
7038         try (SocketKeepalive ka = mCm.createSocketKeepalive(
7039                 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
7040             ka.start(validKaInterval);
7041             callback.expectStarted();
7042             mWiFiAgent.setStopKeepaliveEvent(SocketKeepalive.SUCCESS);
7043             ka.stop();
7044             callback.expectStopped();
7045 
7046             // Check that keepalive could be restarted.
7047             ka.start(validKaInterval);
7048             callback.expectStarted();
7049             ka.stop();
7050             callback.expectStopped();
7051 
7052             // Check that keepalive can be restarted without waiting for callback.
7053             ka.start(validKaInterval);
7054             callback.expectStarted();
7055             ka.stop();
7056             ka.start(validKaInterval);
7057             callback.expectStopped();
7058             callback.expectStarted();
7059             ka.stop();
7060             callback.expectStopped();
7061         }
7062 
7063         // Check that deleting the IP address stops the keepalive.
7064         LinkProperties bogusLp = new LinkProperties(lp);
7065         try (SocketKeepalive ka = mCm.createSocketKeepalive(
7066                 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
7067             ka.start(validKaInterval);
7068             callback.expectStarted();
7069             bogusLp.removeLinkAddress(new LinkAddress(myIPv4, 25));
7070             bogusLp.addLinkAddress(new LinkAddress(notMyIPv4, 25));
7071             mWiFiAgent.sendLinkProperties(bogusLp);
7072             callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
7073             mWiFiAgent.sendLinkProperties(lp);
7074         }
7075 
7076         // Check that a started keepalive is stopped correctly when the network disconnects.
7077         try (SocketKeepalive ka = mCm.createSocketKeepalive(
7078                 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
7079             ka.start(validKaInterval);
7080             callback.expectStarted();
7081             mWiFiAgent.disconnect();
7082             mWiFiAgent.expectDisconnected();
7083             callback.expectError(SocketKeepalive.ERROR_INVALID_NETWORK);
7084 
7085             // ... and that stopping it after that has no adverse effects.
7086             waitForIdle();
7087             assertNull(mCm.getNetworkCapabilities(myNet));
7088             ka.stop();
7089             callback.assertNoCallback();
7090         }
7091 
7092         // Reconnect.
7093         myNet = connectKeepaliveNetwork(lp);
7094         mWiFiAgent.setStartKeepaliveEvent(SocketKeepalive.SUCCESS);
7095 
7096         // Check that a stop followed by network disconnects does not result in crash.
7097         try (SocketKeepalive ka = mCm.createSocketKeepalive(
7098                 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
7099             ka.start(validKaInterval);
7100             callback.expectStarted();
7101             // Delay the response of keepalive events in networkAgent long enough to make sure
7102             // the follow-up network disconnection will be processed first.
7103             mWiFiAgent.setKeepaliveResponseDelay(3 * TIMEOUT_MS);
7104             ka.stop();
7105             // Call stop() twice shouldn't result in crash, b/182586681.
7106             ka.stop();
7107 
7108             // Make sure the stop has been processed. Wait for executor idle is needed to prevent
7109             // flaky since the actual stop call to the service is delegated to executor thread.
7110             waitForIdleSerialExecutor(executor, TIMEOUT_MS);
7111             waitForIdle();
7112 
7113             mWiFiAgent.disconnect();
7114             mWiFiAgent.expectDisconnected();
7115             callback.expectStopped();
7116             callback.assertNoCallback();
7117         }
7118 
7119         // Reconnect.
7120         waitForIdle();
7121         myNet = connectKeepaliveNetwork(lp);
7122         mWiFiAgent.setStartKeepaliveEvent(SocketKeepalive.SUCCESS);
7123 
7124         // Check that keepalive slots start from 1 and increment. The first one gets slot 1.
7125         mWiFiAgent.setExpectedKeepaliveSlot(1);
7126         try (SocketKeepalive ka = mCm.createSocketKeepalive(
7127                 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
7128             ka.start(validKaInterval);
7129             callback.expectStarted();
7130 
7131             // The second one gets slot 2.
7132             mWiFiAgent.setExpectedKeepaliveSlot(2);
7133             final UdpEncapsulationSocket testSocket2 = mIpSec.openUdpEncapsulationSocket();
7134             TestSocketKeepaliveCallback callback2 = new TestSocketKeepaliveCallback(executor);
7135             try (SocketKeepalive ka2 = mCm.createSocketKeepalive(
7136                     myNet, testSocket2, myIPv4, dstIPv4, executor, callback2)) {
7137                 ka2.start(validKaInterval);
7138                 callback2.expectStarted();
7139 
7140                 ka.stop();
7141                 callback.expectStopped();
7142 
7143                 ka2.stop();
7144                 callback2.expectStopped();
7145 
7146                 testSocket.close();
7147                 testSocket2.close();
7148             }
7149         }
7150 
7151         // Check that there is no port leaked after all keepalives and sockets are closed.
7152         // TODO: enable this check after ensuring a valid free port. See b/129512753#comment7.
7153         // assertFalse(isUdpPortInUse(srcPort));
7154         // assertFalse(isUdpPortInUse(srcPort2));
7155 
7156         mWiFiAgent.disconnect();
7157         mWiFiAgent.expectDisconnected();
7158         mWiFiAgent = null;
7159     }
7160 
7161     @Test
7162     public void testTcpSocketKeepalives() throws Exception {
7163         runTestWithSerialExecutors(executor -> doTestTcpSocketKeepalivesWithExecutor(executor));
7164     }
7165 
7166     private void doTestTcpSocketKeepalivesWithExecutor(Executor executor) throws Exception {
7167         final int srcPortV4 = 12345;
7168         final int srcPortV6 = 23456;
7169         final InetAddress myIPv4 = InetAddress.getByName("127.0.0.1");
7170         final InetAddress myIPv6 = InetAddress.getByName("::1");
7171 
7172         final int validKaInterval = 15;
7173 
7174         final LinkProperties lp = new LinkProperties();
7175         lp.setInterfaceName("wlan12");
7176         lp.addLinkAddress(new LinkAddress(myIPv6, 64));
7177         lp.addLinkAddress(new LinkAddress(myIPv4, 25));
7178         lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
7179         lp.addRoute(new RouteInfo(InetAddress.getByName("127.0.0.254")));
7180 
7181         final Network notMyNet = new Network(61234);
7182         final Network myNet = connectKeepaliveNetwork(lp);
7183 
7184         final Socket testSocketV4 = new Socket();
7185         final Socket testSocketV6 = new Socket();
7186 
7187         TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback(executor);
7188 
7189         // Attempt to start Tcp keepalives with invalid parameters and check for errors.
7190         // Invalid network.
7191         try (SocketKeepalive ka = mCm.createSocketKeepalive(
7192             notMyNet, testSocketV4, executor, callback)) {
7193             ka.start(validKaInterval);
7194             callback.expectError(SocketKeepalive.ERROR_INVALID_NETWORK);
7195         }
7196 
7197         // Invalid Socket (socket is not bound with IPv4 address).
7198         try (SocketKeepalive ka = mCm.createSocketKeepalive(
7199             myNet, testSocketV4, executor, callback)) {
7200             ka.start(validKaInterval);
7201             callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
7202         }
7203 
7204         // Invalid Socket (socket is not bound with IPv6 address).
7205         try (SocketKeepalive ka = mCm.createSocketKeepalive(
7206             myNet, testSocketV6, executor, callback)) {
7207             ka.start(validKaInterval);
7208             callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
7209         }
7210 
7211         // Bind the socket address
7212         testSocketV4.bind(new InetSocketAddress(myIPv4, srcPortV4));
7213         testSocketV6.bind(new InetSocketAddress(myIPv6, srcPortV6));
7214 
7215         // Invalid Socket (socket is bound with IPv4 address).
7216         try (SocketKeepalive ka = mCm.createSocketKeepalive(
7217             myNet, testSocketV4, executor, callback)) {
7218             ka.start(validKaInterval);
7219             callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
7220         }
7221 
7222         // Invalid Socket (socket is bound with IPv6 address).
7223         try (SocketKeepalive ka = mCm.createSocketKeepalive(
7224             myNet, testSocketV6, executor, callback)) {
7225             ka.start(validKaInterval);
7226             callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
7227         }
7228 
7229         testSocketV4.close();
7230         testSocketV6.close();
7231 
7232         mWiFiAgent.disconnect();
7233         mWiFiAgent.expectDisconnected();
7234         mWiFiAgent = null;
7235     }
7236 
7237     private void doTestNattSocketKeepalivesFdWithExecutor(Executor executor) throws Exception {
7238         final InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
7239         final InetAddress anyIPv4 = InetAddress.getByName("0.0.0.0");
7240         final InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8");
7241         final int validKaInterval = 15;
7242 
7243         // Prepare the target network.
7244         LinkProperties lp = new LinkProperties();
7245         lp.setInterfaceName("wlan12");
7246         lp.addLinkAddress(new LinkAddress(myIPv4, 25));
7247         lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
7248         Network myNet = connectKeepaliveNetwork(lp);
7249         mWiFiAgent.setStartKeepaliveEvent(SocketKeepalive.SUCCESS);
7250         mWiFiAgent.setStopKeepaliveEvent(SocketKeepalive.SUCCESS);
7251 
7252         TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback(executor);
7253 
7254         // Prepare the target file descriptor, keep only one instance.
7255         final IpSecManager mIpSec = (IpSecManager) mContext.getSystemService(Context.IPSEC_SERVICE);
7256         final UdpEncapsulationSocket testSocket = mIpSec.openUdpEncapsulationSocket();
7257         final int srcPort = testSocket.getPort();
7258         final ParcelFileDescriptor testPfd =
7259                 ParcelFileDescriptor.dup(testSocket.getFileDescriptor());
7260         testSocket.close();
7261         assertTrue(isUdpPortInUse(srcPort));
7262 
7263         // Start keepalive and explicit make the variable goes out of scope with try-with-resources
7264         // block.
7265         try (SocketKeepalive ka = mCm.createNattKeepalive(
7266                 myNet, testPfd, myIPv4, dstIPv4, executor, callback)) {
7267             ka.start(validKaInterval);
7268             callback.expectStarted();
7269             ka.stop();
7270             callback.expectStopped();
7271         }
7272 
7273         // Check that the ParcelFileDescriptor is still valid after keepalive stopped,
7274         // ErrnoException with EBADF will be thrown if the socket is closed when checking local
7275         // address.
7276         assertTrue(isUdpPortInUse(srcPort));
7277         final InetSocketAddress sa =
7278                 (InetSocketAddress) Os.getsockname(testPfd.getFileDescriptor());
7279         assertEquals(anyIPv4, sa.getAddress());
7280 
7281         testPfd.close();
7282         // TODO: enable this check after ensuring a valid free port. See b/129512753#comment7.
7283         // assertFalse(isUdpPortInUse(srcPort));
7284 
7285         mWiFiAgent.disconnect();
7286         mWiFiAgent.expectDisconnected();
7287         mWiFiAgent = null;
7288     }
7289 
7290     private static boolean isUdpPortInUse(int port) {
7291         try (DatagramSocket ignored = new DatagramSocket(port)) {
7292             return false;
7293         } catch (IOException alreadyInUse) {
7294             return true;
7295         }
7296     }
7297 
7298     @Test
7299     public void testGetCaptivePortalServerUrl() throws Exception {
7300         String url = mCm.getCaptivePortalServerUrl();
7301         assertEquals("http://connectivitycheck.gstatic.com/generate_204", url);
7302     }
7303 
7304     private static class TestNetworkPinner extends NetworkPinner {
7305         public static boolean awaitPin(int timeoutMs) throws InterruptedException {
7306             synchronized(sLock) {
7307                 if (sNetwork == null) {
7308                     sLock.wait(timeoutMs);
7309                 }
7310                 return sNetwork != null;
7311             }
7312         }
7313 
7314         public static boolean awaitUnpin(int timeoutMs) throws InterruptedException {
7315             synchronized(sLock) {
7316                 if (sNetwork != null) {
7317                     sLock.wait(timeoutMs);
7318                 }
7319                 return sNetwork == null;
7320             }
7321         }
7322     }
7323 
7324     private void assertPinnedToWifiWithCellDefault() {
7325         assertEquals(mWiFiAgent.getNetwork(), mCm.getBoundNetworkForProcess());
7326         assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetwork());
7327     }
7328 
7329     private void assertPinnedToWifiWithWifiDefault() {
7330         assertEquals(mWiFiAgent.getNetwork(), mCm.getBoundNetworkForProcess());
7331         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetwork());
7332     }
7333 
7334     private void assertNotPinnedToWifi() {
7335         assertNull(mCm.getBoundNetworkForProcess());
7336         assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetwork());
7337     }
7338 
7339     @Test
7340     public void testNetworkPinner() throws Exception {
7341         NetworkRequest wifiRequest = new NetworkRequest.Builder()
7342                 .addTransportType(TRANSPORT_WIFI)
7343                 .build();
7344         assertNull(mCm.getBoundNetworkForProcess());
7345 
7346         TestNetworkPinner.pin(mServiceContext, wifiRequest);
7347         assertNull(mCm.getBoundNetworkForProcess());
7348 
7349         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
7350         mCellAgent.connect(true);
7351         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
7352         mWiFiAgent.connect(false);
7353 
7354         // When wi-fi connects, expect to be pinned.
7355         assertTrue(TestNetworkPinner.awaitPin(100));
7356         assertPinnedToWifiWithCellDefault();
7357 
7358         // Disconnect and expect the pin to drop.
7359         mWiFiAgent.disconnect();
7360         assertTrue(TestNetworkPinner.awaitUnpin(100));
7361         assertNotPinnedToWifi();
7362 
7363         // Reconnecting does not cause the pin to come back.
7364         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
7365         mWiFiAgent.connect(false);
7366         assertFalse(TestNetworkPinner.awaitPin(100));
7367         assertNotPinnedToWifi();
7368 
7369         // Pinning while connected causes the pin to take effect immediately.
7370         TestNetworkPinner.pin(mServiceContext, wifiRequest);
7371         assertTrue(TestNetworkPinner.awaitPin(100));
7372         assertPinnedToWifiWithCellDefault();
7373 
7374         // Explicitly unpin and expect to use the default network again.
7375         TestNetworkPinner.unpin();
7376         assertNotPinnedToWifi();
7377 
7378         // Disconnect cell and wifi.
7379         ExpectedBroadcast b = expectConnectivityAction(3);  // cell down, wifi up, wifi down.
7380         mCellAgent.disconnect();
7381         mWiFiAgent.disconnect();
7382         b.expectBroadcast();
7383 
7384         // Pinning takes effect even if the pinned network is the default when the pin is set...
7385         TestNetworkPinner.pin(mServiceContext, wifiRequest);
7386         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
7387         mWiFiAgent.connect(false);
7388         assertTrue(TestNetworkPinner.awaitPin(100));
7389         assertPinnedToWifiWithWifiDefault();
7390 
7391         // ... and is maintained even when that network is no longer the default.
7392         b = expectConnectivityAction(1);
7393         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
7394         mCellAgent.connect(true);
7395         b.expectBroadcast();
7396         assertPinnedToWifiWithCellDefault();
7397     }
7398 
7399     @Test
7400     public void testNetworkCallbackMaximum() throws Exception {
7401         final int MAX_REQUESTS = 100;
7402         final int CALLBACKS = 87;
7403         final int DIFF_INTENTS = 10;
7404         final int SAME_INTENTS = 10;
7405         final int SYSTEM_ONLY_MAX_REQUESTS = 250;
7406         // Assert 1 (Default request filed before testing) + CALLBACKS + DIFF_INTENTS +
7407         // 1 (same intent) = MAX_REQUESTS - 1, since the capacity is MAX_REQUEST - 1.
7408         assertEquals(MAX_REQUESTS - 1, 1 + CALLBACKS + DIFF_INTENTS + 1);
7409 
7410         NetworkRequest networkRequest = new NetworkRequest.Builder().build();
7411         ArrayList<Object> registered = new ArrayList<>();
7412 
7413         for (int j = 0; j < CALLBACKS; j++) {
7414             final NetworkCallback cb = new NetworkCallback();
7415             if (j < CALLBACKS / 2) {
7416                 mCm.requestNetwork(networkRequest, cb);
7417             } else {
7418                 mCm.registerNetworkCallback(networkRequest, cb);
7419             }
7420             registered.add(cb);
7421         }
7422 
7423         // Since ConnectivityService will de-duplicate the request with the same intent,
7424         // register multiple times does not really increase multiple requests.
7425         final PendingIntent same_pi = PendingIntent.getBroadcast(mContext, 0 /* requestCode */,
7426                 new Intent("same"), FLAG_IMMUTABLE);
7427         for (int j = 0; j < SAME_INTENTS; j++) {
7428             mCm.registerNetworkCallback(networkRequest, same_pi);
7429             // Wait for the requests with the same intent to be de-duplicated. Because
7430             // ConnectivityService side incrementCountOrThrow in binder, decrementCount in handler
7431             // thread, waitForIdle is needed to ensure decrementCount being invoked for same intent
7432             // requests before doing further tests.
7433             waitForIdle();
7434         }
7435         for (int j = 0; j < SAME_INTENTS; j++) {
7436             mCm.requestNetwork(networkRequest, same_pi);
7437             // Wait for the requests with the same intent to be de-duplicated.
7438             // Refer to the reason above.
7439             waitForIdle();
7440         }
7441         registered.add(same_pi);
7442 
7443         for (int j = 0; j < DIFF_INTENTS; j++) {
7444             if (j < DIFF_INTENTS / 2) {
7445                 final PendingIntent pi = PendingIntent.getBroadcast(mContext, 0 /* requestCode */,
7446                         new Intent("a" + j), FLAG_IMMUTABLE);
7447                 mCm.requestNetwork(networkRequest, pi);
7448                 registered.add(pi);
7449             } else {
7450                 final PendingIntent pi = PendingIntent.getBroadcast(mContext, 0 /* requestCode */,
7451                         new Intent("b" + j), FLAG_IMMUTABLE);
7452                 mCm.registerNetworkCallback(networkRequest, pi);
7453                 registered.add(pi);
7454             }
7455         }
7456 
7457         // Test that the limit is enforced when MAX_REQUESTS simultaneous requests are added.
7458         assertThrows(TooManyRequestsException.class, () ->
7459                 mCm.requestNetwork(networkRequest, new NetworkCallback())
7460         );
7461         assertThrows(TooManyRequestsException.class, () ->
7462                 mCm.registerNetworkCallback(networkRequest, new NetworkCallback())
7463         );
7464         assertThrows(TooManyRequestsException.class, () ->
7465                 mCm.requestNetwork(networkRequest,
7466                         PendingIntent.getBroadcast(mContext, 0 /* requestCode */,
7467                                 new Intent("c"), FLAG_IMMUTABLE))
7468         );
7469         assertThrows(TooManyRequestsException.class, () ->
7470                 mCm.registerNetworkCallback(networkRequest,
7471                         PendingIntent.getBroadcast(mContext, 0 /* requestCode */,
7472                                 new Intent("d"), FLAG_IMMUTABLE))
7473         );
7474 
7475         // The system gets another SYSTEM_ONLY_MAX_REQUESTS slots.
7476         final Handler handler = new Handler(ConnectivityThread.getInstanceLooper());
7477         withPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, () -> {
7478             ArrayList<NetworkCallback> systemRegistered = new ArrayList<>();
7479             for (int i = 0; i < SYSTEM_ONLY_MAX_REQUESTS - 1; i++) {
7480                 NetworkCallback cb = new NetworkCallback();
7481                 if (i % 2 == 0) {
7482                     mCm.registerDefaultNetworkCallbackForUid(1000000 + i, cb, handler);
7483                 } else {
7484                     mCm.registerNetworkCallback(networkRequest, cb);
7485                 }
7486                 systemRegistered.add(cb);
7487             }
7488             waitForIdle();
7489 
7490             assertThrows(TooManyRequestsException.class, () ->
7491                     mCm.registerDefaultNetworkCallbackForUid(1001042, new NetworkCallback(),
7492                             handler));
7493             assertThrows(TooManyRequestsException.class, () ->
7494                     mCm.registerNetworkCallback(networkRequest, new NetworkCallback()));
7495 
7496             for (NetworkCallback callback : systemRegistered) {
7497                 mCm.unregisterNetworkCallback(callback);
7498             }
7499             waitForIdle();  // Wait for requests to be unregistered before giving up the permission.
7500         });
7501 
7502         for (Object o : registered) {
7503             if (o instanceof NetworkCallback) {
7504                 mCm.unregisterNetworkCallback((NetworkCallback) o);
7505             }
7506             if (o instanceof PendingIntent) {
7507                 mCm.unregisterNetworkCallback((PendingIntent) o);
7508             }
7509         }
7510         waitForIdle();
7511 
7512         // Test that the limit is not hit when MAX_REQUESTS requests are added and removed.
7513         for (int i = 0; i < MAX_REQUESTS; i++) {
7514             NetworkCallback networkCallback = new NetworkCallback();
7515             mCm.requestNetwork(networkRequest, networkCallback);
7516             mCm.unregisterNetworkCallback(networkCallback);
7517         }
7518         waitForIdle();
7519 
7520         for (int i = 0; i < MAX_REQUESTS; i++) {
7521             NetworkCallback networkCallback = new NetworkCallback();
7522             mCm.registerNetworkCallback(networkRequest, networkCallback);
7523             mCm.unregisterNetworkCallback(networkCallback);
7524         }
7525         waitForIdle();
7526 
7527         for (int i = 0; i < MAX_REQUESTS; i++) {
7528             NetworkCallback networkCallback = new NetworkCallback();
7529             mCm.registerDefaultNetworkCallback(networkCallback);
7530             mCm.unregisterNetworkCallback(networkCallback);
7531         }
7532         waitForIdle();
7533 
7534         for (int i = 0; i < MAX_REQUESTS; i++) {
7535             NetworkCallback networkCallback = new NetworkCallback();
7536             mCm.registerDefaultNetworkCallback(networkCallback);
7537             mCm.unregisterNetworkCallback(networkCallback);
7538         }
7539         waitForIdle();
7540 
7541         withPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, () -> {
7542             for (int i = 0; i < MAX_REQUESTS; i++) {
7543                 NetworkCallback networkCallback = new NetworkCallback();
7544                 mCm.registerDefaultNetworkCallbackForUid(1000000 + i, networkCallback,
7545                         new Handler(ConnectivityThread.getInstanceLooper()));
7546                 mCm.unregisterNetworkCallback(networkCallback);
7547             }
7548         });
7549         waitForIdle();
7550 
7551         for (int i = 0; i < MAX_REQUESTS; i++) {
7552             final PendingIntent pendingIntent = PendingIntent.getBroadcast(
7553                     mContext, 0 /* requestCode */, new Intent("e" + i), FLAG_IMMUTABLE);
7554             mCm.requestNetwork(networkRequest, pendingIntent);
7555             mCm.unregisterNetworkCallback(pendingIntent);
7556         }
7557         waitForIdle();
7558 
7559         for (int i = 0; i < MAX_REQUESTS; i++) {
7560             final PendingIntent pendingIntent = PendingIntent.getBroadcast(
7561                     mContext, 0 /* requestCode */, new Intent("f" + i), FLAG_IMMUTABLE);
7562             mCm.registerNetworkCallback(networkRequest, pendingIntent);
7563             mCm.unregisterNetworkCallback(pendingIntent);
7564         }
7565     }
7566 
7567     @Test
7568     public void testNetworkInfoOfTypeNone() throws Exception {
7569         ExpectedBroadcast b = expectConnectivityAction(1);
7570 
7571         verifyNoNetwork();
7572         TestNetworkAgentWrapper wifiAware = new TestNetworkAgentWrapper(TRANSPORT_WIFI_AWARE);
7573         assertNull(mCm.getActiveNetworkInfo());
7574 
7575         Network[] allNetworks = mCm.getAllNetworks();
7576         assertLength(1, allNetworks);
7577         Network network = allNetworks[0];
7578         NetworkCapabilities capabilities = mCm.getNetworkCapabilities(network);
7579         assertTrue(capabilities.hasTransport(TRANSPORT_WIFI_AWARE));
7580 
7581         final NetworkRequest request =
7582                 new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI_AWARE).build();
7583         final TestNetworkCallback callback = new TestNetworkCallback();
7584         mCm.registerNetworkCallback(request, callback);
7585 
7586         // Bring up wifi aware network.
7587         wifiAware.connect(false, false, false /* privateDnsProbeSent */);
7588         callback.expectAvailableCallbacksUnvalidated(wifiAware);
7589 
7590         assertNull(mCm.getActiveNetworkInfo());
7591         assertNull(mCm.getActiveNetwork());
7592         // TODO: getAllNetworkInfo is dirty and returns a non-empty array right from the start
7593         // of this test. Fix it and uncomment the assert below.
7594         //assertEmpty(mCm.getAllNetworkInfo());
7595 
7596         // Disconnect wifi aware network.
7597         wifiAware.disconnect();
7598         callback.expect(LOST, TIMEOUT_MS);
7599         mCm.unregisterNetworkCallback(callback);
7600 
7601         verifyNoNetwork();
7602         b.expectNoBroadcast(10);
7603     }
7604 
7605     @Test
7606     public void testDeprecatedAndUnsupportedOperations() throws Exception {
7607         final int TYPE_NONE = ConnectivityManager.TYPE_NONE;
7608         assertNull(mCm.getNetworkInfo(TYPE_NONE));
7609         assertNull(mCm.getNetworkForType(TYPE_NONE));
7610         assertNull(mCm.getLinkProperties(TYPE_NONE));
7611         assertFalse(mCm.isNetworkSupported(TYPE_NONE));
7612 
7613         assertThrows(IllegalArgumentException.class,
7614                 () -> mCm.networkCapabilitiesForType(TYPE_NONE));
7615 
7616         Class<UnsupportedOperationException> unsupported = UnsupportedOperationException.class;
7617         assertThrows(unsupported, () -> mCm.startUsingNetworkFeature(TYPE_WIFI, ""));
7618         assertThrows(unsupported, () -> mCm.stopUsingNetworkFeature(TYPE_WIFI, ""));
7619         // TODO: let test context have configuration application target sdk version
7620         // and test that pre-M requesting for TYPE_NONE sends back APN_REQUEST_FAILED
7621         assertThrows(unsupported, () -> mCm.startUsingNetworkFeature(TYPE_NONE, ""));
7622         assertThrows(unsupported, () -> mCm.stopUsingNetworkFeature(TYPE_NONE, ""));
7623         assertThrows(unsupported, () -> mCm.requestRouteToHostAddress(TYPE_NONE, null));
7624     }
7625 
7626     @Test
7627     public void testLinkPropertiesEnsuresDirectlyConnectedRoutes() throws Exception {
7628         final NetworkRequest networkRequest = new NetworkRequest.Builder()
7629                 .addTransportType(TRANSPORT_WIFI).build();
7630         final TestNetworkCallback networkCallback = new TestNetworkCallback();
7631         mCm.registerNetworkCallback(networkRequest, networkCallback);
7632 
7633         LinkProperties lp = new LinkProperties();
7634         lp.setInterfaceName(WIFI_IFNAME);
7635         LinkAddress myIpv4Address = new LinkAddress("192.168.12.3/24");
7636         RouteInfo myIpv4DefaultRoute = new RouteInfo((IpPrefix) null,
7637                 InetAddresses.parseNumericAddress("192.168.12.1"), lp.getInterfaceName());
7638         lp.addLinkAddress(myIpv4Address);
7639         lp.addRoute(myIpv4DefaultRoute);
7640 
7641         // Verify direct routes are added when network agent is first registered in
7642         // ConnectivityService.
7643         TestNetworkAgentWrapper networkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, lp);
7644         networkAgent.connect(true);
7645         networkCallback.expect(AVAILABLE, networkAgent);
7646         networkCallback.expect(NETWORK_CAPS_UPDATED, networkAgent);
7647         CallbackEntry.LinkPropertiesChanged cbi =
7648                 networkCallback.expect(LINK_PROPERTIES_CHANGED, networkAgent);
7649         networkCallback.expect(BLOCKED_STATUS, networkAgent);
7650         networkCallback.expectCaps(networkAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
7651         networkCallback.assertNoCallback();
7652         checkDirectlyConnectedRoutes(cbi.getLp(), asList(myIpv4Address),
7653                 asList(myIpv4DefaultRoute));
7654         checkDirectlyConnectedRoutes(mCm.getLinkProperties(networkAgent.getNetwork()),
7655                 asList(myIpv4Address), asList(myIpv4DefaultRoute));
7656 
7657         // Verify direct routes are added during subsequent link properties updates.
7658         LinkProperties newLp = new LinkProperties(lp);
7659         LinkAddress myIpv6Address1 = new LinkAddress("fe80::cafe/64");
7660         LinkAddress myIpv6Address2 = new LinkAddress("2001:db8::2/64");
7661         newLp.addLinkAddress(myIpv6Address1);
7662         newLp.addLinkAddress(myIpv6Address2);
7663         networkAgent.sendLinkProperties(newLp);
7664         cbi = networkCallback.expect(LINK_PROPERTIES_CHANGED, networkAgent);
7665         networkCallback.assertNoCallback();
7666         checkDirectlyConnectedRoutes(cbi.getLp(),
7667                 asList(myIpv4Address, myIpv6Address1, myIpv6Address2),
7668                 asList(myIpv4DefaultRoute));
7669         mCm.unregisterNetworkCallback(networkCallback);
7670     }
7671 
7672     private void expectNotifyNetworkStatus(List<Network> allNetworks, List<Network> defaultNetworks,
7673             String defaultIface, Integer vpnUid, String vpnIfname, List<String> underlyingIfaces)
7674             throws Exception {
7675         ArgumentCaptor<List<Network>> defaultNetworksCaptor = ArgumentCaptor.forClass(List.class);
7676         ArgumentCaptor<List<UnderlyingNetworkInfo>> vpnInfosCaptor =
7677                 ArgumentCaptor.forClass(List.class);
7678         ArgumentCaptor<List<NetworkStateSnapshot>> snapshotsCaptor =
7679                 ArgumentCaptor.forClass(List.class);
7680 
7681         verify(mStatsManager, atLeastOnce()).notifyNetworkStatus(defaultNetworksCaptor.capture(),
7682                 snapshotsCaptor.capture(), eq(defaultIface), vpnInfosCaptor.capture());
7683 
7684         assertSameElements(defaultNetworks, defaultNetworksCaptor.getValue());
7685 
7686         List<Network> snapshotNetworks = new ArrayList<Network>();
7687         for (NetworkStateSnapshot ns : snapshotsCaptor.getValue()) {
7688             snapshotNetworks.add(ns.getNetwork());
7689         }
7690         assertSameElements(allNetworks, snapshotNetworks);
7691 
7692         if (defaultIface != null) {
7693             assertNotNull(
7694                     "Did not find interface " + defaultIface + " in call to notifyNetworkStatus",
7695                     CollectionUtils.findFirst(snapshotsCaptor.getValue(), (ns) -> {
7696                         final LinkProperties lp = ns.getLinkProperties();
7697                         if (lp != null && TextUtils.equals(defaultIface, lp.getInterfaceName())) {
7698                             return true;
7699                         }
7700                         return false;
7701                     }));
7702         }
7703 
7704         List<UnderlyingNetworkInfo> infos = vpnInfosCaptor.getValue();
7705         if (vpnUid != null) {
7706             assertEquals("Should have exactly one VPN:", 1, infos.size());
7707             UnderlyingNetworkInfo info = infos.get(0);
7708             assertEquals("Unexpected VPN owner:", (int) vpnUid, info.getOwnerUid());
7709             assertEquals("Unexpected VPN interface:", vpnIfname, info.getInterface());
7710             assertSameElements(underlyingIfaces, info.getUnderlyingInterfaces());
7711         } else {
7712             assertEquals(0, infos.size());
7713             return;
7714         }
7715     }
7716 
7717     private void expectNotifyNetworkStatus(
7718             List<Network> allNetworks, List<Network> defaultNetworks, String defaultIface)
7719             throws Exception {
7720         expectNotifyNetworkStatus(allNetworks, defaultNetworks, defaultIface, null, null,
7721                 List.of());
7722     }
7723 
7724     private List<Network> onlyCell() {
7725         return List.of(mCellAgent.getNetwork());
7726     }
7727 
7728     private List<Network> onlyWifi() {
7729         return List.of(mWiFiAgent.getNetwork());
7730     }
7731 
7732     private List<Network> cellAndWifi() {
7733         return List.of(mCellAgent.getNetwork(), mWiFiAgent.getNetwork());
7734     }
7735 
7736     @Test
7737     public void testStatsIfacesChanged() throws Exception {
7738         LinkProperties cellLp = new LinkProperties();
7739         cellLp.setInterfaceName(MOBILE_IFNAME);
7740         LinkProperties wifiLp = new LinkProperties();
7741         wifiLp.setInterfaceName(WIFI_IFNAME);
7742 
7743         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
7744         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
7745 
7746         // Simple connection with initial LP should have updated ifaces.
7747         mCellAgent.connect(false);
7748         waitForIdle();
7749         List<Network> allNetworks = mService.shouldCreateNetworksImmediately()
7750                 ? cellAndWifi() : onlyCell();
7751         expectNotifyNetworkStatus(allNetworks, onlyCell(), MOBILE_IFNAME);
7752         reset(mStatsManager);
7753 
7754         // Verify change fields other than interfaces does not trigger a notification to NSS.
7755         cellLp.addLinkAddress(new LinkAddress("192.0.2.4/24"));
7756         cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("192.0.2.4"),
7757                 MOBILE_IFNAME));
7758         cellLp.setDnsServers(List.of(InetAddress.getAllByName("8.8.8.8")));
7759         mCellAgent.sendLinkProperties(cellLp);
7760         verifyNoMoreInteractions(mStatsManager);
7761         reset(mStatsManager);
7762 
7763         // Default network switch should update ifaces.
7764         mWiFiAgent.connect(false);
7765         mWiFiAgent.sendLinkProperties(wifiLp);
7766         waitForIdle();
7767         assertEquals(wifiLp, mService.getActiveLinkProperties());
7768         expectNotifyNetworkStatus(cellAndWifi(), onlyWifi(), WIFI_IFNAME);
7769         reset(mStatsManager);
7770 
7771         // Disconnecting a network updates ifaces again. The soon-to-be disconnected interface is
7772         // still in the list to ensure that stats are counted on that interface.
7773         // TODO: this means that if anything else uses that interface for any other reason before
7774         // notifyNetworkStatus is called again, traffic on that interface will be accounted to the
7775         // disconnected network. This is likely a bug in ConnectivityService; it should probably
7776         // call notifyNetworkStatus again without the disconnected network.
7777         mCellAgent.disconnect();
7778         waitForIdle();
7779         expectNotifyNetworkStatus(cellAndWifi(), onlyWifi(), WIFI_IFNAME);
7780         verifyNoMoreInteractions(mStatsManager);
7781         reset(mStatsManager);
7782 
7783         // Connecting a network updates ifaces even if the network doesn't become default.
7784         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
7785         mCellAgent.connect(false);
7786         waitForIdle();
7787         expectNotifyNetworkStatus(cellAndWifi(), onlyWifi(), WIFI_IFNAME);
7788         reset(mStatsManager);
7789 
7790         // Disconnect should update ifaces.
7791         mWiFiAgent.disconnect();
7792         waitForIdle();
7793         expectNotifyNetworkStatus(onlyCell(), onlyCell(), MOBILE_IFNAME);
7794         reset(mStatsManager);
7795 
7796         // Metered change should update ifaces
7797         mCellAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
7798         waitForIdle();
7799         expectNotifyNetworkStatus(onlyCell(), onlyCell(), MOBILE_IFNAME);
7800         reset(mStatsManager);
7801 
7802         mCellAgent.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
7803         waitForIdle();
7804         expectNotifyNetworkStatus(onlyCell(), onlyCell(), MOBILE_IFNAME);
7805         reset(mStatsManager);
7806 
7807         // Temp metered change shouldn't update ifaces
7808         mCellAgent.addCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED);
7809         waitForIdle();
7810         verify(mStatsManager, never()).notifyNetworkStatus(eq(onlyCell()),
7811                 any(List.class), eq(MOBILE_IFNAME), any(List.class));
7812         reset(mStatsManager);
7813 
7814         // Congested change shouldn't update ifaces
7815         mCellAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED);
7816         waitForIdle();
7817         verify(mStatsManager, never()).notifyNetworkStatus(eq(onlyCell()),
7818                 any(List.class), eq(MOBILE_IFNAME), any(List.class));
7819         reset(mStatsManager);
7820 
7821         // Roaming change should update ifaces
7822         mCellAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING);
7823         waitForIdle();
7824         expectNotifyNetworkStatus(onlyCell(), onlyCell(), MOBILE_IFNAME);
7825         reset(mStatsManager);
7826 
7827         // Test VPNs.
7828         final LinkProperties lp = new LinkProperties();
7829         lp.setInterfaceName(VPN_IFNAME);
7830 
7831         mMockVpn.establishForMyUid(lp);
7832         assertUidRangesUpdatedForMyUid(true);
7833 
7834         final List<Network> cellAndVpn = List.of(mCellAgent.getNetwork(), mMockVpn.getNetwork());
7835 
7836         // A VPN with default (null) underlying networks sets the underlying network's interfaces...
7837         expectNotifyNetworkStatus(cellAndVpn, cellAndVpn, MOBILE_IFNAME, Process.myUid(),
7838                 VPN_IFNAME, List.of(MOBILE_IFNAME));
7839 
7840         // ...and updates them as the default network switches.
7841         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
7842         mWiFiAgent.connect(false);
7843         mWiFiAgent.sendLinkProperties(wifiLp);
7844         final Network[] onlyNull = new Network[]{null};
7845         final List<Network> wifiAndVpn = List.of(mWiFiAgent.getNetwork(), mMockVpn.getNetwork());
7846         final List<Network> cellWifiAndVpn = List.of(mCellAgent.getNetwork(),
7847                 mWiFiAgent.getNetwork(), mMockVpn.getNetwork());
7848         final Network[] cellNullAndWifi =
7849                 new Network[] { mCellAgent.getNetwork(), null, mWiFiAgent.getNetwork() };
7850 
7851         waitForIdle();
7852         assertEquals(wifiLp, mService.getActiveLinkProperties());
7853         expectNotifyNetworkStatus(cellWifiAndVpn, wifiAndVpn, WIFI_IFNAME, Process.myUid(),
7854                 VPN_IFNAME, List.of(WIFI_IFNAME));
7855         reset(mStatsManager);
7856 
7857         // A VPN that sets its underlying networks passes the underlying interfaces, and influences
7858         // the default interface sent to NetworkStatsService by virtue of applying to the system
7859         // server UID (or, in this test, to the test's UID). This is the reason for sending
7860         // MOBILE_IFNAME even though the default network is wifi.
7861         // TODO: fix this to pass in the actual default network interface. Whether or not the VPN
7862         // applies to the system server UID should not have any bearing on network stats.
7863         mMockVpn.setUnderlyingNetworks(onlyCell().toArray(new Network[0]));
7864         waitForIdle();
7865         expectNotifyNetworkStatus(cellWifiAndVpn, wifiAndVpn, MOBILE_IFNAME, Process.myUid(),
7866                 VPN_IFNAME, List.of(MOBILE_IFNAME));
7867         reset(mStatsManager);
7868 
7869         mMockVpn.setUnderlyingNetworks(cellAndWifi().toArray(new Network[0]));
7870         waitForIdle();
7871         expectNotifyNetworkStatus(cellWifiAndVpn, wifiAndVpn, MOBILE_IFNAME, Process.myUid(),
7872                 VPN_IFNAME,  List.of(MOBILE_IFNAME, WIFI_IFNAME));
7873         reset(mStatsManager);
7874 
7875         // Null underlying networks are ignored.
7876         mMockVpn.setUnderlyingNetworks(cellNullAndWifi);
7877         waitForIdle();
7878         expectNotifyNetworkStatus(cellWifiAndVpn, wifiAndVpn, MOBILE_IFNAME, Process.myUid(),
7879                 VPN_IFNAME,  List.of(MOBILE_IFNAME, WIFI_IFNAME));
7880         reset(mStatsManager);
7881 
7882         // If an underlying network disconnects, that interface should no longer be underlying.
7883         // This doesn't actually work because disconnectAndDestroyNetwork only notifies
7884         // NetworkStatsService before the underlying network is actually removed. So the underlying
7885         // network will only be removed if notifyIfacesChangedForNetworkStats is called again. This
7886         // could result in incorrect data usage measurements if the interface used by the
7887         // disconnected network is reused by a system component that does not register an agent for
7888         // it (e.g., tethering).
7889         mCellAgent.disconnect();
7890         waitForIdle();
7891         assertNull(mService.getLinkProperties(mCellAgent.getNetwork()));
7892         expectNotifyNetworkStatus(cellWifiAndVpn, wifiAndVpn, MOBILE_IFNAME, Process.myUid(),
7893                 VPN_IFNAME, List.of(MOBILE_IFNAME, WIFI_IFNAME));
7894 
7895         // Confirm that we never tell NetworkStatsService that cell is no longer the underlying
7896         // network for the VPN...
7897         verify(mStatsManager, never()).notifyNetworkStatus(any(List.class),
7898                 any(List.class), any() /* anyString() doesn't match null */,
7899                 argThat(infos -> infos.get(0).getUnderlyingInterfaces().size() == 1
7900                         && WIFI_IFNAME.equals(infos.get(0).getUnderlyingInterfaces().get(0))));
7901         verifyNoMoreInteractions(mStatsManager);
7902         reset(mStatsManager);
7903 
7904         // ... but if something else happens that causes notifyIfacesChangedForNetworkStats to be
7905         // called again, it does. For example, connect Ethernet, but with a low score, such that it
7906         // does not become the default network.
7907         mEthernetAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
7908         mEthernetAgent.setScore(
7909                 new NetworkScore.Builder().setLegacyInt(30).setExiting(true).build());
7910         mEthernetAgent.connect(false);
7911         waitForIdle();
7912         verify(mStatsManager).notifyNetworkStatus(any(List.class),
7913                 any(List.class), any() /* anyString() doesn't match null */,
7914                 argThat(vpnInfos -> vpnInfos.get(0).getUnderlyingInterfaces().size() == 1
7915                         && WIFI_IFNAME.equals(vpnInfos.get(0).getUnderlyingInterfaces().get(0))));
7916         mEthernetAgent.disconnect();
7917         waitForIdle();
7918         reset(mStatsManager);
7919 
7920         // When a VPN declares no underlying networks (i.e., no connectivity), getAllVpnInfo
7921         // does not return the VPN, so CS does not pass it to NetworkStatsService. This causes
7922         // NetworkStatsFactory#adjustForTunAnd464Xlat not to attempt any VPN data migration, which
7923         // is probably a performance improvement (though it's very unlikely that a VPN would declare
7924         // no underlying networks).
7925         // Also, for the same reason as above, the active interface passed in is null.
7926         mMockVpn.setUnderlyingNetworks(new Network[0]);
7927         waitForIdle();
7928         expectNotifyNetworkStatus(wifiAndVpn, wifiAndVpn, null);
7929         reset(mStatsManager);
7930 
7931         // Specifying only a null underlying network is the same as no networks.
7932         mMockVpn.setUnderlyingNetworks(onlyNull);
7933         waitForIdle();
7934         expectNotifyNetworkStatus(wifiAndVpn, wifiAndVpn, null);
7935         reset(mStatsManager);
7936 
7937         // Specifying networks that are all disconnected is the same as specifying no networks.
7938         mMockVpn.setUnderlyingNetworks(onlyCell().toArray(new Network[0]));
7939         waitForIdle();
7940         expectNotifyNetworkStatus(wifiAndVpn, wifiAndVpn, null);
7941         reset(mStatsManager);
7942 
7943         // Passing in null again means follow the default network again.
7944         mMockVpn.setUnderlyingNetworks(null);
7945         waitForIdle();
7946         expectNotifyNetworkStatus(wifiAndVpn, wifiAndVpn, WIFI_IFNAME, Process.myUid(), VPN_IFNAME,
7947                 List.of(WIFI_IFNAME));
7948         reset(mStatsManager);
7949     }
7950 
7951     @Test
7952     public void testAdminUidsRedacted() throws Exception {
7953         final int[] adminUids = new int[] {Process.myUid() + 1};
7954         final NetworkCapabilities ncTemplate = new NetworkCapabilities();
7955         ncTemplate.setAdministratorUids(adminUids);
7956         mCellAgent =
7957                 new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, new LinkProperties(), ncTemplate);
7958         mCellAgent.connect(false /* validated */);
7959 
7960         // Verify case where caller has permission
7961         mServiceContext.setPermission(
7962                 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, PERMISSION_GRANTED);
7963         TestNetworkCallback callback = new TestNetworkCallback();
7964         mCm.registerDefaultNetworkCallback(callback);
7965         callback.expect(AVAILABLE, mCellAgent);
7966         callback.expectCaps(mCellAgent, c -> Arrays.equals(adminUids, c.getAdministratorUids()));
7967         mCm.unregisterNetworkCallback(callback);
7968 
7969         // Verify case where caller does NOT have permission
7970         mServiceContext.setPermission(
7971                 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, PERMISSION_DENIED);
7972         mServiceContext.setPermission(NETWORK_STACK, PERMISSION_DENIED);
7973         callback = new TestNetworkCallback();
7974         mCm.registerDefaultNetworkCallback(callback);
7975         callback.expect(AVAILABLE, mCellAgent);
7976         callback.expectCaps(mCellAgent, c -> c.getAdministratorUids().length == 0);
7977     }
7978 
7979     @Test
7980     public void testNonVpnUnderlyingNetworks() throws Exception {
7981         // Ensure wifi and cellular are not torn down.
7982         for (int transport : new int[]{TRANSPORT_CELLULAR, TRANSPORT_WIFI}) {
7983             final NetworkRequest request = new NetworkRequest.Builder()
7984                     .addTransportType(transport)
7985                     .removeCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
7986                     .build();
7987             mCm.requestNetwork(request, new NetworkCallback());
7988         }
7989 
7990         // Connect a VCN-managed wifi network.
7991         final LinkProperties wifiLp = new LinkProperties();
7992         wifiLp.setInterfaceName(WIFI_IFNAME);
7993         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp);
7994         mWiFiAgent.removeCapability(NET_CAPABILITY_NOT_VCN_MANAGED);
7995         mWiFiAgent.addCapability(NET_CAPABILITY_NOT_METERED);
7996         mWiFiAgent.connect(true /* validated */);
7997 
7998         final List<Network> none = List.of();
7999         expectNotifyNetworkStatus(onlyWifi(), none, null);  // Wifi is not the default network
8000 
8001         // Create a virtual network based on the wifi network.
8002         final int ownerUid = 10042;
8003         NetworkCapabilities nc = new NetworkCapabilities.Builder()
8004                 .setOwnerUid(ownerUid)
8005                 .setAdministratorUids(new int[]{ownerUid})
8006                 .build();
8007         final String vcnIface = "ipsec42";
8008         final LinkProperties lp = new LinkProperties();
8009         lp.setInterfaceName(vcnIface);
8010         final TestNetworkAgentWrapper vcn = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, lp, nc);
8011         vcn.setUnderlyingNetworks(List.of(mWiFiAgent.getNetwork()));
8012         vcn.connect(false /* validated */);
8013 
8014         final TestNetworkCallback callback = new TestNetworkCallback();
8015         mCm.registerDefaultNetworkCallback(callback);
8016         callback.expectAvailableCallbacksUnvalidated(vcn);
8017 
8018         // The underlying wifi network's capabilities are not propagated to the virtual network,
8019         // but NetworkStatsService is informed of the underlying interface.
8020         nc = mCm.getNetworkCapabilities(vcn.getNetwork());
8021         assertFalse(nc.hasTransport(TRANSPORT_WIFI));
8022         assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED));
8023         final List<Network> onlyVcn = List.of(vcn.getNetwork());
8024         final List<Network> vcnAndWifi = List.of(vcn.getNetwork(), mWiFiAgent.getNetwork());
8025         expectNotifyNetworkStatus(vcnAndWifi, onlyVcn, vcnIface, ownerUid, vcnIface,
8026                 List.of(WIFI_IFNAME));
8027 
8028         // Add NOT_METERED to the underlying network, check that it is not propagated.
8029         mWiFiAgent.addCapability(NET_CAPABILITY_NOT_METERED);
8030         callback.assertNoCallback();
8031         nc = mCm.getNetworkCapabilities(vcn.getNetwork());
8032         assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED));
8033 
8034         // Switch underlying networks.
8035         final LinkProperties cellLp = new LinkProperties();
8036         cellLp.setInterfaceName(MOBILE_IFNAME);
8037         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
8038         mCellAgent.removeCapability(NET_CAPABILITY_NOT_VCN_MANAGED);
8039         mCellAgent.addCapability(NET_CAPABILITY_NOT_ROAMING);
8040         mCellAgent.connect(false /* validated */);
8041         vcn.setUnderlyingNetworks(List.of(mCellAgent.getNetwork()));
8042 
8043         // The underlying capability changes do not propagate to the virtual network, but
8044         // NetworkStatsService is informed of the new underlying interface.
8045         callback.assertNoCallback();
8046         nc = mCm.getNetworkCapabilities(vcn.getNetwork());
8047         assertFalse(nc.hasTransport(TRANSPORT_WIFI));
8048         assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_ROAMING));
8049         final List<Network> vcnWifiAndCell = List.of(vcn.getNetwork(),
8050                 mWiFiAgent.getNetwork(), mCellAgent.getNetwork());
8051         expectNotifyNetworkStatus(vcnWifiAndCell, onlyVcn, vcnIface, ownerUid, vcnIface,
8052                 List.of(MOBILE_IFNAME));
8053     }
8054 
8055     @Test
8056     public void testBasicDnsConfigurationPushed() throws Exception {
8057         setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
8058 
8059         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
8060         final int netId = mCellAgent.getNetwork().netId;
8061         waitForIdle();
8062         if (mService.shouldCreateNetworksImmediately()) {
8063             verify(mMockDnsResolver, times(1)).createNetworkCache(netId);
8064         } else {
8065             verify(mMockDnsResolver, never()).setResolverConfiguration(any());
8066         }
8067 
8068         final LinkProperties cellLp = new LinkProperties();
8069         cellLp.setInterfaceName(MOBILE_IFNAME);
8070         // Add IPv4 and IPv6 default routes, because DNS-over-TLS code does
8071         // "is-reachable" testing in order to not program netd with unreachable
8072         // nameservers that it might try repeated to validate.
8073         cellLp.addLinkAddress(new LinkAddress("192.0.2.4/24"));
8074         cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("192.0.2.4"),
8075                 MOBILE_IFNAME));
8076         cellLp.addLinkAddress(new LinkAddress("2001:db8:1::1/64"));
8077         cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("2001:db8:1::1"),
8078                 MOBILE_IFNAME));
8079         mCellAgent.sendLinkProperties(cellLp);
8080         mCellAgent.connect(false);
8081         waitForIdle();
8082         if (!mService.shouldCreateNetworksImmediately()) {
8083             // CS tells dnsresolver about the empty DNS config for this network.
8084             verify(mMockDnsResolver, times(1)).createNetworkCache(netId);
8085         }
8086         verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(any());
8087 
8088         verifyNoMoreInteractions(mMockDnsResolver);
8089         reset(mMockDnsResolver);
8090 
8091         cellLp.addDnsServer(InetAddress.getByName("2001:db8::1"));
8092         mCellAgent.sendLinkProperties(cellLp);
8093         waitForIdle();
8094         verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
8095                 mResolverParamsParcelCaptor.capture());
8096         ResolverParamsParcel resolvrParams = mResolverParamsParcelCaptor.getValue();
8097         assertEquals(1, resolvrParams.servers.length);
8098         assertTrue(CollectionUtils.contains(resolvrParams.servers, "2001:db8::1"));
8099         // Opportunistic mode.
8100         assertTrue(CollectionUtils.contains(resolvrParams.tlsServers, "2001:db8::1"));
8101         reset(mMockDnsResolver);
8102 
8103         cellLp.addDnsServer(InetAddress.getByName("192.0.2.1"));
8104         mCellAgent.sendLinkProperties(cellLp);
8105         waitForIdle();
8106         verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
8107                 mResolverParamsParcelCaptor.capture());
8108         resolvrParams = mResolverParamsParcelCaptor.getValue();
8109         assertEquals(2, resolvrParams.servers.length);
8110         assertTrue(new ArraySet<>(resolvrParams.servers).containsAll(
8111                 asList("2001:db8::1", "192.0.2.1")));
8112         // Opportunistic mode.
8113         assertEquals(2, resolvrParams.tlsServers.length);
8114         assertTrue(new ArraySet<>(resolvrParams.tlsServers).containsAll(
8115                 asList("2001:db8::1", "192.0.2.1")));
8116         reset(mMockDnsResolver);
8117 
8118         final String TLS_SPECIFIER = "tls.example.com";
8119         final String TLS_SERVER6 = "2001:db8:53::53";
8120         final InetAddress[] TLS_IPS = new InetAddress[]{ InetAddress.getByName(TLS_SERVER6) };
8121         final String[] TLS_SERVERS = new String[]{ TLS_SERVER6 };
8122         mCellAgent.mNmCallbacks.notifyPrivateDnsConfigResolved(
8123                 new PrivateDnsConfig(TLS_SPECIFIER, TLS_IPS).toParcel());
8124 
8125         waitForIdle();
8126         verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
8127                 mResolverParamsParcelCaptor.capture());
8128         resolvrParams = mResolverParamsParcelCaptor.getValue();
8129         assertEquals(2, resolvrParams.servers.length);
8130         assertTrue(new ArraySet<>(resolvrParams.servers).containsAll(
8131                 asList("2001:db8::1", "192.0.2.1")));
8132         reset(mMockDnsResolver);
8133     }
8134 
8135     @Test
8136     public void testDnsConfigurationTransTypesPushed() throws Exception {
8137         final NetworkRequest request = new NetworkRequest.Builder()
8138                 .clearCapabilities().addCapability(NET_CAPABILITY_INTERNET)
8139                 .build();
8140         final TestNetworkCallback callback = new TestNetworkCallback();
8141         mCm.registerNetworkCallback(request, callback);
8142 
8143         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
8144         mWiFiAgent.connect(false);
8145         callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
8146         verify(mMockDnsResolver, times(1)).createNetworkCache(eq(mWiFiAgent.getNetwork().netId));
8147         verify(mMockDnsResolver, times(2)).setResolverConfiguration(
8148                 mResolverParamsParcelCaptor.capture());
8149         final ResolverParamsParcel resolverParams = mResolverParamsParcelCaptor.getValue();
8150         assertContainsExactly(resolverParams.transportTypes, TRANSPORT_WIFI);
8151         reset(mMockDnsResolver);
8152     }
8153 
8154     @Test
8155     public void testPrivateDnsNotification() throws Exception {
8156         NetworkRequest request = new NetworkRequest.Builder()
8157                 .clearCapabilities().addCapability(NET_CAPABILITY_INTERNET)
8158                 .build();
8159         TestNetworkCallback callback = new TestNetworkCallback();
8160         mCm.registerNetworkCallback(request, callback);
8161         // Bring up wifi.
8162         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
8163         mWiFiAgent.connect(false);
8164         callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
8165         // Private DNS resolution failed, checking if the notification will be shown or not.
8166         mWiFiAgent.setNetworkInvalid(true /* invalidBecauseOfPrivateDns */);
8167         mWiFiAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
8168         waitForIdle();
8169         // If network validation failed, NetworkMonitor will re-evaluate the network.
8170         // ConnectivityService should filter the redundant notification. This part is trying to
8171         // simulate that situation and check if ConnectivityService could filter that case.
8172         mWiFiAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
8173         waitForIdle();
8174         verify(mNotificationManager, timeout(TIMEOUT_MS).times(1)).notify(anyString(),
8175                 eq(NotificationType.PRIVATE_DNS_BROKEN.eventId), any());
8176         // If private DNS resolution successful, the PRIVATE_DNS_BROKEN notification shouldn't be
8177         // shown.
8178         mWiFiAgent.setNetworkValid(true /* privateDnsProbeSent */);
8179         mWiFiAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
8180         waitForIdle();
8181         verify(mNotificationManager, timeout(TIMEOUT_MS).times(1)).cancel(anyString(),
8182                 eq(NotificationType.PRIVATE_DNS_BROKEN.eventId));
8183         // If private DNS resolution failed again, the PRIVATE_DNS_BROKEN notification should be
8184         // shown again.
8185         mWiFiAgent.setNetworkInvalid(true /* invalidBecauseOfPrivateDns */);
8186         mWiFiAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
8187         waitForIdle();
8188         verify(mNotificationManager, timeout(TIMEOUT_MS).times(2)).notify(anyString(),
8189                 eq(NotificationType.PRIVATE_DNS_BROKEN.eventId), any());
8190     }
8191 
8192     @Test
8193     public void testPrivateDnsSettingsChange() throws Exception {
8194         // The default on Android is opportunistic mode ("Automatic").
8195         setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
8196 
8197         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
8198         final NetworkRequest cellRequest = new NetworkRequest.Builder()
8199                 .addTransportType(TRANSPORT_CELLULAR).build();
8200         mCm.requestNetwork(cellRequest, cellNetworkCallback);
8201 
8202         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
8203         final int netId = mCellAgent.getNetwork().netId;
8204         waitForIdle();
8205         if (mService.shouldCreateNetworksImmediately()) {
8206             verify(mMockDnsResolver, times(1)).createNetworkCache(netId);
8207         } else {
8208             verify(mMockDnsResolver, never()).setResolverConfiguration(any());
8209         }
8210 
8211         final LinkProperties cellLp = new LinkProperties();
8212         cellLp.setInterfaceName(MOBILE_IFNAME);
8213         // Add IPv4 and IPv6 default routes, because DNS-over-TLS code does
8214         // "is-reachable" testing in order to not program netd with unreachable
8215         // nameservers that it might try repeated to validate.
8216         cellLp.addLinkAddress(new LinkAddress("192.0.2.4/24"));
8217         cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("192.0.2.4"),
8218                 MOBILE_IFNAME));
8219         cellLp.addLinkAddress(new LinkAddress("2001:db8:1::1/64"));
8220         cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("2001:db8:1::1"),
8221                 MOBILE_IFNAME));
8222         cellLp.addDnsServer(InetAddress.getByName("2001:db8::1"));
8223         cellLp.addDnsServer(InetAddress.getByName("192.0.2.1"));
8224 
8225         mCellAgent.sendLinkProperties(cellLp);
8226         mCellAgent.connect(false);
8227         waitForIdle();
8228         if (!mService.shouldCreateNetworksImmediately()) {
8229             verify(mMockDnsResolver, times(1)).createNetworkCache(netId);
8230         }
8231         verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
8232                 mResolverParamsParcelCaptor.capture());
8233         ResolverParamsParcel resolvrParams = mResolverParamsParcelCaptor.getValue();
8234         assertEquals(2, resolvrParams.tlsServers.length);
8235         assertTrue(new ArraySet<>(resolvrParams.tlsServers).containsAll(
8236                 asList("2001:db8::1", "192.0.2.1")));
8237         // Opportunistic mode.
8238         assertEquals(2, resolvrParams.tlsServers.length);
8239         assertTrue(new ArraySet<>(resolvrParams.tlsServers).containsAll(
8240                 asList("2001:db8::1", "192.0.2.1")));
8241         verifyNoMoreInteractions(mMockDnsResolver);
8242         reset(mMockDnsResolver);
8243         cellNetworkCallback.expect(AVAILABLE, mCellAgent);
8244         cellNetworkCallback.expect(NETWORK_CAPS_UPDATED, mCellAgent);
8245         CallbackEntry.LinkPropertiesChanged cbi = cellNetworkCallback.expect(
8246                 LINK_PROPERTIES_CHANGED, mCellAgent);
8247         cellNetworkCallback.expect(BLOCKED_STATUS, mCellAgent);
8248         cellNetworkCallback.assertNoCallback();
8249         assertFalse(cbi.getLp().isPrivateDnsActive());
8250         assertNull(cbi.getLp().getPrivateDnsServerName());
8251 
8252         setPrivateDnsSettings(PRIVATE_DNS_MODE_OFF, "ignored.example.com");
8253         verify(mMockDnsResolver, times(1)).setResolverConfiguration(
8254                 mResolverParamsParcelCaptor.capture());
8255         resolvrParams = mResolverParamsParcelCaptor.getValue();
8256         assertEquals(2, resolvrParams.servers.length);
8257         assertTrue(new ArraySet<>(resolvrParams.servers).containsAll(
8258                 asList("2001:db8::1", "192.0.2.1")));
8259         reset(mMockDnsResolver);
8260         cellNetworkCallback.assertNoCallback();
8261 
8262         setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
8263         verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
8264                 mResolverParamsParcelCaptor.capture());
8265         resolvrParams = mResolverParamsParcelCaptor.getValue();
8266         assertEquals(2, resolvrParams.servers.length);
8267         assertTrue(new ArraySet<>(resolvrParams.servers).containsAll(
8268                 asList("2001:db8::1", "192.0.2.1")));
8269         assertEquals(2, resolvrParams.tlsServers.length);
8270         assertTrue(new ArraySet<>(resolvrParams.tlsServers).containsAll(
8271                 asList("2001:db8::1", "192.0.2.1")));
8272         reset(mMockDnsResolver);
8273         cellNetworkCallback.assertNoCallback();
8274 
8275         setPrivateDnsSettings(PRIVATE_DNS_MODE_PROVIDER_HOSTNAME, "strict.example.com");
8276         // Can't test dns configuration for strict mode without properly mocking
8277         // out the DNS lookups, but can test that LinkProperties is updated.
8278         cbi = cellNetworkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent);
8279         cellNetworkCallback.assertNoCallback();
8280         assertTrue(cbi.getLp().isPrivateDnsActive());
8281         assertEquals("strict.example.com", cbi.getLp().getPrivateDnsServerName());
8282     }
8283 
8284     private PrivateDnsValidationEventParcel makePrivateDnsValidationEvent(
8285             final int netId, final String ipAddress, final String hostname, final int validation) {
8286         final PrivateDnsValidationEventParcel event = new PrivateDnsValidationEventParcel();
8287         event.netId = netId;
8288         event.ipAddress = ipAddress;
8289         event.hostname = hostname;
8290         event.validation = validation;
8291         return event;
8292     }
8293 
8294     @Test
8295     public void testLinkPropertiesWithPrivateDnsValidationEvents() throws Exception {
8296         // The default on Android is opportunistic mode ("Automatic").
8297         setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
8298 
8299         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
8300         final NetworkRequest cellRequest = new NetworkRequest.Builder()
8301                 .addTransportType(TRANSPORT_CELLULAR).build();
8302         mCm.requestNetwork(cellRequest, cellNetworkCallback);
8303 
8304         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
8305         waitForIdle();
8306         LinkProperties lp = new LinkProperties();
8307         mCellAgent.sendLinkProperties(lp);
8308         mCellAgent.connect(false);
8309         waitForIdle();
8310         cellNetworkCallback.expect(AVAILABLE, mCellAgent);
8311         cellNetworkCallback.expect(NETWORK_CAPS_UPDATED, mCellAgent);
8312         CallbackEntry.LinkPropertiesChanged cbi = cellNetworkCallback.expect(
8313                 LINK_PROPERTIES_CHANGED, mCellAgent);
8314         cellNetworkCallback.expect(BLOCKED_STATUS, mCellAgent);
8315         cellNetworkCallback.assertNoCallback();
8316         assertFalse(cbi.getLp().isPrivateDnsActive());
8317         assertNull(cbi.getLp().getPrivateDnsServerName());
8318         Set<InetAddress> dnsServers = new HashSet<>();
8319         checkDnsServers(cbi.getLp(), dnsServers);
8320 
8321         // Send a validation event for a server that is not part of the current
8322         // resolver config. The validation event should be ignored.
8323         mService.mResolverUnsolEventCallback.onPrivateDnsValidationEvent(
8324                 makePrivateDnsValidationEvent(mCellAgent.getNetwork().netId, "",
8325                         "145.100.185.18", VALIDATION_RESULT_SUCCESS));
8326         cellNetworkCallback.assertNoCallback();
8327 
8328         // Add a dns server to the LinkProperties.
8329         LinkProperties lp2 = new LinkProperties(lp);
8330         lp2.addDnsServer(InetAddress.getByName("145.100.185.16"));
8331         mCellAgent.sendLinkProperties(lp2);
8332         cbi = cellNetworkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent);
8333         cellNetworkCallback.assertNoCallback();
8334         assertFalse(cbi.getLp().isPrivateDnsActive());
8335         assertNull(cbi.getLp().getPrivateDnsServerName());
8336         dnsServers.add(InetAddress.getByName("145.100.185.16"));
8337         checkDnsServers(cbi.getLp(), dnsServers);
8338 
8339         // Send a validation event containing a hostname that is not part of
8340         // the current resolver config. The validation event should be ignored.
8341         mService.mResolverUnsolEventCallback.onPrivateDnsValidationEvent(
8342                 makePrivateDnsValidationEvent(mCellAgent.getNetwork().netId,
8343                         "145.100.185.16", "hostname", VALIDATION_RESULT_SUCCESS));
8344         cellNetworkCallback.assertNoCallback();
8345 
8346         // Send a validation event where validation failed.
8347         mService.mResolverUnsolEventCallback.onPrivateDnsValidationEvent(
8348                 makePrivateDnsValidationEvent(mCellAgent.getNetwork().netId,
8349                         "145.100.185.16", "", VALIDATION_RESULT_FAILURE));
8350         cellNetworkCallback.assertNoCallback();
8351 
8352         // Send a validation event where validation succeeded for a server in
8353         // the current resolver config. A LinkProperties callback with updated
8354         // private dns fields should be sent.
8355         mService.mResolverUnsolEventCallback.onPrivateDnsValidationEvent(
8356                 makePrivateDnsValidationEvent(mCellAgent.getNetwork().netId,
8357                         "145.100.185.16", "", VALIDATION_RESULT_SUCCESS));
8358         cbi = cellNetworkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent);
8359         cellNetworkCallback.assertNoCallback();
8360         assertTrue(cbi.getLp().isPrivateDnsActive());
8361         assertNull(cbi.getLp().getPrivateDnsServerName());
8362         checkDnsServers(cbi.getLp(), dnsServers);
8363 
8364         // The private dns fields in LinkProperties should be preserved when
8365         // the network agent sends unrelated changes.
8366         LinkProperties lp3 = new LinkProperties(lp2);
8367         lp3.setMtu(1300);
8368         mCellAgent.sendLinkProperties(lp3);
8369         cbi = cellNetworkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent);
8370         cellNetworkCallback.assertNoCallback();
8371         assertTrue(cbi.getLp().isPrivateDnsActive());
8372         assertNull(cbi.getLp().getPrivateDnsServerName());
8373         checkDnsServers(cbi.getLp(), dnsServers);
8374         assertEquals(1300, cbi.getLp().getMtu());
8375 
8376         // Removing the only validated server should affect the private dns
8377         // fields in LinkProperties.
8378         LinkProperties lp4 = new LinkProperties(lp3);
8379         lp4.removeDnsServer(InetAddress.getByName("145.100.185.16"));
8380         mCellAgent.sendLinkProperties(lp4);
8381         cbi = cellNetworkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent);
8382         cellNetworkCallback.assertNoCallback();
8383         assertFalse(cbi.getLp().isPrivateDnsActive());
8384         assertNull(cbi.getLp().getPrivateDnsServerName());
8385         dnsServers.remove(InetAddress.getByName("145.100.185.16"));
8386         checkDnsServers(cbi.getLp(), dnsServers);
8387         assertEquals(1300, cbi.getLp().getMtu());
8388     }
8389 
8390     private void checkDirectlyConnectedRoutes(Object callbackObj,
8391             Collection<LinkAddress> linkAddresses, Collection<RouteInfo> otherRoutes) {
8392         assertTrue(callbackObj instanceof LinkProperties);
8393         LinkProperties lp = (LinkProperties) callbackObj;
8394 
8395         Set<RouteInfo> expectedRoutes = new ArraySet<>();
8396         expectedRoutes.addAll(otherRoutes);
8397         for (LinkAddress address : linkAddresses) {
8398             RouteInfo localRoute = new RouteInfo(address, null, lp.getInterfaceName());
8399             // Duplicates in linkAddresses are considered failures
8400             assertTrue(expectedRoutes.add(localRoute));
8401         }
8402         List<RouteInfo> observedRoutes = lp.getRoutes();
8403         assertEquals(expectedRoutes.size(), observedRoutes.size());
8404         assertTrue(observedRoutes.containsAll(expectedRoutes));
8405     }
8406 
8407     private static void checkDnsServers(Object callbackObj, Set<InetAddress> dnsServers) {
8408         assertTrue(callbackObj instanceof LinkProperties);
8409         LinkProperties lp = (LinkProperties) callbackObj;
8410         assertEquals(dnsServers.size(), lp.getDnsServers().size());
8411         assertTrue(lp.getDnsServers().containsAll(dnsServers));
8412     }
8413 
8414     @Test
8415     public void testApplyUnderlyingCapabilities() throws Exception {
8416         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
8417         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
8418         mCellAgent.connect(false /* validated */);
8419         mWiFiAgent.connect(false /* validated */);
8420 
8421         final NetworkCapabilities cellNc = new NetworkCapabilities()
8422                 .addTransportType(TRANSPORT_CELLULAR)
8423                 .addCapability(NET_CAPABILITY_INTERNET)
8424                 .addCapability(NET_CAPABILITY_NOT_CONGESTED)
8425                 .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
8426                 .setLinkDownstreamBandwidthKbps(10);
8427         final NetworkCapabilities wifiNc = new NetworkCapabilities()
8428                 .addTransportType(TRANSPORT_WIFI)
8429                 .addCapability(NET_CAPABILITY_INTERNET)
8430                 .addCapability(NET_CAPABILITY_NOT_METERED)
8431                 .addCapability(NET_CAPABILITY_NOT_ROAMING)
8432                 .addCapability(NET_CAPABILITY_NOT_CONGESTED)
8433                 .addCapability(NET_CAPABILITY_NOT_SUSPENDED)
8434                 .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
8435                 .setLinkUpstreamBandwidthKbps(20);
8436         mCellAgent.setNetworkCapabilities(cellNc, true /* sendToConnectivityService */);
8437         mWiFiAgent.setNetworkCapabilities(wifiNc, true /* sendToConnectivityService */);
8438         waitForIdle();
8439 
8440         final Network mobile = mCellAgent.getNetwork();
8441         final Network wifi = mWiFiAgent.getNetwork();
8442 
8443         final NetworkCapabilities initialCaps = new NetworkCapabilities();
8444         initialCaps.addTransportType(TRANSPORT_VPN);
8445         initialCaps.addCapability(NET_CAPABILITY_INTERNET);
8446         initialCaps.removeCapability(NET_CAPABILITY_NOT_VPN);
8447         final ArrayList<Network> emptyUnderlyingNetworks = new ArrayList<Network>();
8448         final ArrayList<Network> underlyingNetworksContainMobile = new ArrayList<Network>();
8449         underlyingNetworksContainMobile.add(mobile);
8450         final ArrayList<Network> underlyingNetworksContainWifi = new ArrayList<Network>();
8451         underlyingNetworksContainWifi.add(wifi);
8452         final ArrayList<Network> underlyingNetworksContainMobileAndMobile =
8453                 new ArrayList<Network>();
8454         underlyingNetworksContainMobileAndMobile.add(mobile);
8455         underlyingNetworksContainMobileAndMobile.add(wifi);
8456 
8457         final NetworkCapabilities withNoUnderlying = new NetworkCapabilities();
8458         withNoUnderlying.addCapability(NET_CAPABILITY_INTERNET);
8459         withNoUnderlying.addCapability(NET_CAPABILITY_NOT_CONGESTED);
8460         withNoUnderlying.addCapability(NET_CAPABILITY_NOT_ROAMING);
8461         withNoUnderlying.addCapability(NET_CAPABILITY_NOT_SUSPENDED);
8462         withNoUnderlying.addTransportType(TRANSPORT_VPN);
8463         withNoUnderlying.removeCapability(NET_CAPABILITY_NOT_VPN);
8464         withNoUnderlying.setUnderlyingNetworks(emptyUnderlyingNetworks);
8465 
8466         final NetworkCapabilities withMobileUnderlying = new NetworkCapabilities(withNoUnderlying);
8467         withMobileUnderlying.addTransportType(TRANSPORT_CELLULAR);
8468         withMobileUnderlying.removeCapability(NET_CAPABILITY_NOT_ROAMING);
8469         withMobileUnderlying.removeCapability(NET_CAPABILITY_NOT_SUSPENDED);
8470         withMobileUnderlying.setLinkDownstreamBandwidthKbps(10);
8471         withMobileUnderlying.setUnderlyingNetworks(underlyingNetworksContainMobile);
8472 
8473         final NetworkCapabilities withWifiUnderlying = new NetworkCapabilities(withNoUnderlying);
8474         withWifiUnderlying.addTransportType(TRANSPORT_WIFI);
8475         withWifiUnderlying.addCapability(NET_CAPABILITY_NOT_METERED);
8476         withWifiUnderlying.setLinkUpstreamBandwidthKbps(20);
8477         withWifiUnderlying.setUnderlyingNetworks(underlyingNetworksContainWifi);
8478 
8479         final NetworkCapabilities withWifiAndMobileUnderlying =
8480                 new NetworkCapabilities(withNoUnderlying);
8481         withWifiAndMobileUnderlying.addTransportType(TRANSPORT_CELLULAR);
8482         withWifiAndMobileUnderlying.addTransportType(TRANSPORT_WIFI);
8483         withWifiAndMobileUnderlying.removeCapability(NET_CAPABILITY_NOT_METERED);
8484         withWifiAndMobileUnderlying.removeCapability(NET_CAPABILITY_NOT_ROAMING);
8485         withWifiAndMobileUnderlying.setLinkDownstreamBandwidthKbps(10);
8486         withWifiAndMobileUnderlying.setLinkUpstreamBandwidthKbps(20);
8487         withWifiAndMobileUnderlying.setUnderlyingNetworks(underlyingNetworksContainMobileAndMobile);
8488 
8489         final NetworkCapabilities initialCapsNotMetered = new NetworkCapabilities(initialCaps);
8490         initialCapsNotMetered.addCapability(NET_CAPABILITY_NOT_METERED);
8491 
8492         NetworkCapabilities caps = new NetworkCapabilities(initialCaps);
8493         mService.applyUnderlyingCapabilities(new Network[]{}, initialCapsNotMetered, caps);
8494         assertEquals(withNoUnderlying, caps);
8495         assertEquals(0, new ArrayList<>(caps.getUnderlyingNetworks()).size());
8496 
8497         caps = new NetworkCapabilities(initialCaps);
8498         mService.applyUnderlyingCapabilities(new Network[]{null}, initialCapsNotMetered, caps);
8499         assertEquals(withNoUnderlying, caps);
8500         assertEquals(0, new ArrayList<>(caps.getUnderlyingNetworks()).size());
8501 
8502         caps = new NetworkCapabilities(initialCaps);
8503         mService.applyUnderlyingCapabilities(new Network[]{mobile}, initialCapsNotMetered, caps);
8504         assertEquals(withMobileUnderlying, caps);
8505         assertEquals(1, new ArrayList<>(caps.getUnderlyingNetworks()).size());
8506         assertEquals(mobile, new ArrayList<>(caps.getUnderlyingNetworks()).get(0));
8507 
8508         caps = new NetworkCapabilities(initialCaps);
8509         mService.applyUnderlyingCapabilities(new Network[]{wifi}, initialCapsNotMetered, caps);
8510         assertEquals(withWifiUnderlying, caps);
8511         assertEquals(1, new ArrayList<>(caps.getUnderlyingNetworks()).size());
8512         assertEquals(wifi, new ArrayList<>(caps.getUnderlyingNetworks()).get(0));
8513 
8514         withWifiUnderlying.removeCapability(NET_CAPABILITY_NOT_METERED);
8515         caps = new NetworkCapabilities(initialCaps);
8516         mService.applyUnderlyingCapabilities(new Network[]{wifi}, initialCaps, caps);
8517         assertEquals(withWifiUnderlying, caps);
8518         assertEquals(1, new ArrayList<>(caps.getUnderlyingNetworks()).size());
8519         assertEquals(wifi, new ArrayList<>(caps.getUnderlyingNetworks()).get(0));
8520 
8521         caps = new NetworkCapabilities(initialCaps);
8522         mService.applyUnderlyingCapabilities(new Network[]{mobile, wifi}, initialCaps, caps);
8523         assertEquals(withWifiAndMobileUnderlying, caps);
8524         assertEquals(2, new ArrayList<>(caps.getUnderlyingNetworks()).size());
8525         assertEquals(mobile, new ArrayList<>(caps.getUnderlyingNetworks()).get(0));
8526         assertEquals(wifi, new ArrayList<>(caps.getUnderlyingNetworks()).get(1));
8527 
8528         withWifiUnderlying.addCapability(NET_CAPABILITY_NOT_METERED);
8529         caps = new NetworkCapabilities(initialCaps);
8530         mService.applyUnderlyingCapabilities(new Network[]{null, mobile, null, wifi},
8531                 initialCapsNotMetered, caps);
8532         assertEquals(withWifiAndMobileUnderlying, caps);
8533         assertEquals(2, new ArrayList<>(caps.getUnderlyingNetworks()).size());
8534         assertEquals(mobile, new ArrayList<>(caps.getUnderlyingNetworks()).get(0));
8535         assertEquals(wifi, new ArrayList<>(caps.getUnderlyingNetworks()).get(1));
8536 
8537         caps = new NetworkCapabilities(initialCaps);
8538         mService.applyUnderlyingCapabilities(new Network[]{null, mobile, null, wifi},
8539                 initialCapsNotMetered, caps);
8540         assertEquals(withWifiAndMobileUnderlying, caps);
8541         assertEquals(2, new ArrayList<>(caps.getUnderlyingNetworks()).size());
8542         assertEquals(mobile, new ArrayList<>(caps.getUnderlyingNetworks()).get(0));
8543         assertEquals(wifi, new ArrayList<>(caps.getUnderlyingNetworks()).get(1));
8544 
8545         caps = new NetworkCapabilities(initialCaps);
8546         mService.applyUnderlyingCapabilities(null, initialCapsNotMetered, caps);
8547         assertEquals(withWifiUnderlying, caps);
8548         assertEquals(1, new ArrayList<>(caps.getUnderlyingNetworks()).size());
8549         assertEquals(wifi, new ArrayList<>(caps.getUnderlyingNetworks()).get(0));
8550     }
8551 
8552     @Test
8553     public void testVpnConnectDisconnectUnderlyingNetwork() throws Exception {
8554         final TestNetworkCallback callback = new TestNetworkCallback();
8555         final NetworkRequest request = new NetworkRequest.Builder()
8556                 .removeCapability(NET_CAPABILITY_NOT_VPN).build();
8557 
8558         runAsShell(NETWORK_SETTINGS, () -> {
8559             mCm.registerNetworkCallback(request, callback);
8560 
8561             // Bring up a VPN that specifies an underlying network that does not exist yet.
8562             // Note: it's sort of meaningless for a VPN app to declare a network that doesn't exist
8563             // yet, (and doing so is difficult without using reflection) but it's good to test that
8564             // the code behaves approximately correctly.
8565             mMockVpn.establishForMyUid(false, true, false);
8566             callback.expectAvailableCallbacksUnvalidated(mMockVpn);
8567             assertUidRangesUpdatedForMyUid(true);
8568             final Network wifiNetwork = new Network(mNetIdManager.peekNextNetId());
8569             mMockVpn.setUnderlyingNetworks(new Network[]{wifiNetwork});
8570             // onCapabilitiesChanged() should be called because
8571             // NetworkCapabilities#mUnderlyingNetworks is updated.
8572             final NetworkCapabilities vpnNc1 = callback.expectCaps(mMockVpn);
8573             // Since the wifi network hasn't brought up,
8574             // ConnectivityService#applyUnderlyingCapabilities cannot find it. Update
8575             // NetworkCapabilities#mUnderlyingNetworks to an empty array, and it will be updated to
8576             // the correct underlying networks once the wifi network brings up. But this case
8577             // shouldn't happen in reality since no one could get the network which hasn't brought
8578             // up. For the empty array of underlying networks, it should be happened for 2 cases,
8579             // the first one is that the VPN app declares an empty array for its underlying
8580             // networks, the second one is that the underlying networks are torn down.
8581             //
8582             // It shouldn't be null since the null value means the underlying networks of this
8583             // network should follow the default network.
8584             final ArrayList<Network> underlyingNetwork = new ArrayList<>();
8585             assertEquals(underlyingNetwork, vpnNc1.getUnderlyingNetworks());
8586             // Since the wifi network isn't exist, applyUnderlyingCapabilities()
8587             assertTrue(mCm.getNetworkCapabilities(mMockVpn.getNetwork())
8588                     .hasTransport(TRANSPORT_VPN));
8589             assertFalse(mCm.getNetworkCapabilities(mMockVpn.getNetwork())
8590                     .hasTransport(TRANSPORT_WIFI));
8591 
8592             // Make that underlying network connect, and expect to see its capabilities immediately
8593             // reflected in the VPN's capabilities.
8594             mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
8595             assertEquals(wifiNetwork, mWiFiAgent.getNetwork());
8596             mWiFiAgent.connect(false);
8597             // TODO: the callback for the VPN happens before any callbacks are called for the wifi
8598             // network that has just connected. There appear to be two issues here:
8599             // 1. The VPN code will accept an underlying network as soon as getNetworkCapabilities()
8600             //    for it returns non-null (which happens very early, during
8601             //    handleRegisterNetworkAgent).
8602             //    This is not correct because that that point the network is not connected and
8603             //    cannot pass any traffic.
8604             // 2. When a network connects, updateNetworkInfo propagates underlying network
8605             //    capabilities before rematching networks.
8606             // Given that this scenario can't really happen, this is probably fine for now.
8607             final NetworkCapabilities vpnNc2 = callback.expectCaps(mMockVpn);
8608             // The wifi network is brought up, NetworkCapabilities#mUnderlyingNetworks is updated to
8609             // it.
8610             underlyingNetwork.add(wifiNetwork);
8611             assertEquals(underlyingNetwork, vpnNc2.getUnderlyingNetworks());
8612             callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
8613             assertTrue(mCm.getNetworkCapabilities(mMockVpn.getNetwork())
8614                     .hasTransport(TRANSPORT_VPN));
8615             assertTrue(mCm.getNetworkCapabilities(mMockVpn.getNetwork())
8616                     .hasTransport(TRANSPORT_WIFI));
8617 
8618             // Disconnect the network, and expect to see the VPN capabilities change accordingly.
8619             mWiFiAgent.disconnect();
8620             callback.expect(LOST, mWiFiAgent);
8621             callback.expectCaps(mMockVpn, c -> c.getTransportTypes().length == 1
8622                             && c.hasTransport(TRANSPORT_VPN));
8623 
8624             mMockVpn.disconnect();
8625             mCm.unregisterNetworkCallback(callback);
8626         });
8627     }
8628 
8629     private void assertGetNetworkInfoOfGetActiveNetworkIsConnected(boolean expectedConnectivity) {
8630         // What Chromium used to do before https://chromium-review.googlesource.com/2605304
8631         assertEquals("Unexpected result for getActiveNetworkInfo(getActiveNetwork())",
8632                 expectedConnectivity, mCm.getNetworkInfo(mCm.getActiveNetwork()).isConnected());
8633     }
8634 
8635     @Test
8636     public void testVpnUnderlyingNetworkSuspended() throws Exception {
8637         final TestNetworkCallback callback = new TestNetworkCallback();
8638         mCm.registerDefaultNetworkCallback(callback);
8639 
8640         // Connect a VPN.
8641         mMockVpn.establishForMyUid(false /* validated */, true /* hasInternet */,
8642                 false /* privateDnsProbeSent */);
8643         callback.expectAvailableCallbacksUnvalidated(mMockVpn);
8644 
8645         // Connect cellular data.
8646         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
8647         mCellAgent.connect(false /* validated */);
8648         callback.expectCaps(mMockVpn, c -> c.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)
8649                 && c.hasTransport(TRANSPORT_CELLULAR));
8650         callback.assertNoCallback();
8651 
8652         assertTrue(mCm.getNetworkCapabilities(mMockVpn.getNetwork())
8653                 .hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
8654         assertNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
8655         assertNetworkInfo(TYPE_WIFI, DetailedState.DISCONNECTED);
8656         assertNetworkInfo(TYPE_VPN, DetailedState.CONNECTED);
8657         assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
8658         assertGetNetworkInfoOfGetActiveNetworkIsConnected(true);
8659 
8660         // Suspend the cellular network and expect the VPN to be suspended.
8661         mCellAgent.suspend();
8662         callback.expectCaps(mMockVpn, c -> !c.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)
8663                 && c.hasTransport(TRANSPORT_CELLULAR));
8664         callback.expect(SUSPENDED, mMockVpn);
8665         callback.assertNoCallback();
8666 
8667         assertFalse(mCm.getNetworkCapabilities(mMockVpn.getNetwork())
8668                 .hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
8669         assertNetworkInfo(TYPE_MOBILE, DetailedState.SUSPENDED);
8670         assertNetworkInfo(TYPE_WIFI, DetailedState.DISCONNECTED);
8671         assertNetworkInfo(TYPE_VPN, DetailedState.SUSPENDED);
8672         assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.SUSPENDED);
8673         // VPN's main underlying network is suspended, so no connectivity.
8674         assertGetNetworkInfoOfGetActiveNetworkIsConnected(false);
8675 
8676         // Switch to another network. The VPN should no longer be suspended.
8677         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
8678         mWiFiAgent.connect(false /* validated */);
8679         callback.expectCaps(mMockVpn, c -> c.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)
8680                 && c.hasTransport(TRANSPORT_WIFI));
8681         callback.expect(RESUMED, mMockVpn);
8682         callback.assertNoCallback();
8683 
8684         assertTrue(mCm.getNetworkCapabilities(mMockVpn.getNetwork())
8685                 .hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
8686         assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED);
8687         assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
8688         assertNetworkInfo(TYPE_VPN, DetailedState.CONNECTED);
8689         assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
8690         assertGetNetworkInfoOfGetActiveNetworkIsConnected(true);
8691 
8692         // Unsuspend cellular and then switch back to it. The VPN remains not suspended.
8693         mCellAgent.resume();
8694         callback.assertNoCallback();
8695         mWiFiAgent.disconnect();
8696         callback.expectCaps(mMockVpn, c -> c.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)
8697                 && c.hasTransport(TRANSPORT_CELLULAR));
8698         // Spurious double callback?
8699         callback.expectCaps(mMockVpn, c -> c.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)
8700                 && c.hasTransport(TRANSPORT_CELLULAR));
8701         callback.assertNoCallback();
8702 
8703         assertTrue(mCm.getNetworkCapabilities(mMockVpn.getNetwork())
8704                 .hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
8705         assertNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
8706         assertNetworkInfo(TYPE_WIFI, DetailedState.DISCONNECTED);
8707         assertNetworkInfo(TYPE_VPN, DetailedState.CONNECTED);
8708         assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
8709         assertGetNetworkInfoOfGetActiveNetworkIsConnected(true);
8710 
8711         // Suspend cellular and expect no connectivity.
8712         mCellAgent.suspend();
8713         callback.expectCaps(mMockVpn, c -> !c.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)
8714                 && c.hasTransport(TRANSPORT_CELLULAR));
8715         callback.expect(SUSPENDED, mMockVpn);
8716         callback.assertNoCallback();
8717 
8718         assertFalse(mCm.getNetworkCapabilities(mMockVpn.getNetwork())
8719                 .hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
8720         assertNetworkInfo(TYPE_MOBILE, DetailedState.SUSPENDED);
8721         assertNetworkInfo(TYPE_WIFI, DetailedState.DISCONNECTED);
8722         assertNetworkInfo(TYPE_VPN, DetailedState.SUSPENDED);
8723         assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.SUSPENDED);
8724         assertGetNetworkInfoOfGetActiveNetworkIsConnected(false);
8725 
8726         // Resume cellular and expect that connectivity comes back.
8727         mCellAgent.resume();
8728         callback.expectCaps(mMockVpn, c -> c.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)
8729                 && c.hasTransport(TRANSPORT_CELLULAR));
8730         callback.expect(RESUMED, mMockVpn);
8731         callback.assertNoCallback();
8732 
8733         assertTrue(mCm.getNetworkCapabilities(mMockVpn.getNetwork())
8734                 .hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
8735         assertNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
8736         assertNetworkInfo(TYPE_WIFI, DetailedState.DISCONNECTED);
8737         assertNetworkInfo(TYPE_VPN, DetailedState.CONNECTED);
8738         assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
8739         assertGetNetworkInfoOfGetActiveNetworkIsConnected(true);
8740     }
8741 
8742     @Test
8743     public void testVpnNetworkActive() throws Exception {
8744         final int uid = Process.myUid();
8745 
8746         final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback();
8747         final TestNetworkCallback genericNotVpnNetworkCallback = new TestNetworkCallback();
8748         final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
8749         final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
8750         final TestNetworkCallback defaultCallback = new TestNetworkCallback();
8751         final TestNetworkCallback systemDefaultCallback = new TestNetworkCallback();
8752         final NetworkRequest genericNotVpnRequest = new NetworkRequest.Builder().build();
8753         final NetworkRequest genericRequest = new NetworkRequest.Builder()
8754                 .removeCapability(NET_CAPABILITY_NOT_VPN).build();
8755         final NetworkRequest wifiRequest = new NetworkRequest.Builder()
8756                 .addTransportType(TRANSPORT_WIFI).build();
8757         final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder()
8758                 .removeCapability(NET_CAPABILITY_NOT_VPN)
8759                 .addTransportType(TRANSPORT_VPN).build();
8760         mCm.registerNetworkCallback(genericRequest, genericNetworkCallback);
8761         mCm.registerNetworkCallback(genericNotVpnRequest, genericNotVpnNetworkCallback);
8762         mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
8763         mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
8764         mCm.registerDefaultNetworkCallback(defaultCallback);
8765         mCm.registerSystemDefaultNetworkCallback(systemDefaultCallback,
8766                 new Handler(ConnectivityThread.getInstanceLooper()));
8767         defaultCallback.assertNoCallback();
8768 
8769         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
8770         mWiFiAgent.connect(false);
8771 
8772         genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
8773         genericNotVpnNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
8774         wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
8775         defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
8776         systemDefaultCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
8777         vpnNetworkCallback.assertNoCallback();
8778         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
8779 
8780         final Set<UidRange> ranges = uidRangesForUids(uid);
8781         mMockVpn.registerAgent(ranges);
8782         mMockVpn.setUnderlyingNetworks(new Network[0]);
8783 
8784         // VPN networks do not satisfy the default request and are automatically validated
8785         // by NetworkMonitor
8786         assertFalse(NetworkMonitorUtils.isValidationRequired(
8787                 false /* isDunValidationRequired */,
8788                 NetworkAgentConfigShimImpl.newInstance(mMockVpn.getNetworkAgentConfig())
8789                         .isVpnValidationRequired(),
8790                 mMockVpn.getAgent().getNetworkCapabilities()));
8791         mMockVpn.getAgent().setNetworkValid(false /* privateDnsProbeSent */);
8792 
8793         mMockVpn.connect(false);
8794 
8795         genericNetworkCallback.expectAvailableThenValidatedCallbacks(mMockVpn);
8796         genericNotVpnNetworkCallback.assertNoCallback();
8797         wifiNetworkCallback.assertNoCallback();
8798         vpnNetworkCallback.expectAvailableThenValidatedCallbacks(mMockVpn);
8799         defaultCallback.expectAvailableThenValidatedCallbacks(mMockVpn);
8800         systemDefaultCallback.assertNoCallback();
8801         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
8802         assertEquals(mWiFiAgent.getNetwork(), systemDefaultCallback.getLastAvailableNetwork());
8803 
8804         ranges.clear();
8805         mMockVpn.setUids(ranges);
8806 
8807         genericNetworkCallback.expect(LOST, mMockVpn);
8808         genericNotVpnNetworkCallback.assertNoCallback();
8809         wifiNetworkCallback.assertNoCallback();
8810         vpnNetworkCallback.expect(LOST, mMockVpn);
8811 
8812         // TODO : The default network callback should actually get a LOST call here (also see the
8813         // comment below for AVAILABLE). This is because ConnectivityService does not look at UID
8814         // ranges at all when determining whether a network should be rematched. In practice, VPNs
8815         // can't currently update their UIDs without disconnecting, so this does not matter too
8816         // much, but that is the reason the test here has to check for an update to the
8817         // capabilities instead of the expected LOST then AVAILABLE.
8818         defaultCallback.expectCaps(mMockVpn);
8819         systemDefaultCallback.assertNoCallback();
8820 
8821         ranges.add(new UidRange(uid, uid));
8822         mMockVpn.setUids(ranges);
8823 
8824         genericNetworkCallback.expectAvailableCallbacksValidated(mMockVpn);
8825         genericNotVpnNetworkCallback.assertNoCallback();
8826         wifiNetworkCallback.assertNoCallback();
8827         vpnNetworkCallback.expectAvailableCallbacksValidated(mMockVpn);
8828         // TODO : Here like above, AVAILABLE would be correct, but because this can't actually
8829         // happen outside of the test, ConnectivityService does not rematch callbacks.
8830         defaultCallback.expectCaps(mMockVpn);
8831         systemDefaultCallback.assertNoCallback();
8832 
8833         mWiFiAgent.disconnect();
8834 
8835         genericNetworkCallback.expect(LOST, mWiFiAgent);
8836         genericNotVpnNetworkCallback.expect(LOST, mWiFiAgent);
8837         wifiNetworkCallback.expect(LOST, mWiFiAgent);
8838         vpnNetworkCallback.assertNoCallback();
8839         defaultCallback.assertNoCallback();
8840         systemDefaultCallback.expect(LOST, mWiFiAgent);
8841 
8842         mMockVpn.disconnect();
8843 
8844         genericNetworkCallback.expect(LOST, mMockVpn);
8845         genericNotVpnNetworkCallback.assertNoCallback();
8846         wifiNetworkCallback.assertNoCallback();
8847         vpnNetworkCallback.expect(LOST, mMockVpn);
8848         defaultCallback.expect(LOST, mMockVpn);
8849         systemDefaultCallback.assertNoCallback();
8850         assertEquals(null, mCm.getActiveNetwork());
8851 
8852         mCm.unregisterNetworkCallback(genericNetworkCallback);
8853         mCm.unregisterNetworkCallback(wifiNetworkCallback);
8854         mCm.unregisterNetworkCallback(vpnNetworkCallback);
8855         mCm.unregisterNetworkCallback(defaultCallback);
8856         mCm.unregisterNetworkCallback(systemDefaultCallback);
8857     }
8858 
8859     @Test
8860     public void testVpnWithoutInternet() throws Exception {
8861         final int uid = Process.myUid();
8862 
8863         final TestNetworkCallback defaultCallback = new TestNetworkCallback();
8864         mCm.registerDefaultNetworkCallback(defaultCallback);
8865 
8866         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
8867         mWiFiAgent.connect(true);
8868 
8869         defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiAgent);
8870         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
8871 
8872         mMockVpn.establishForMyUid(true /* validated */, false /* hasInternet */,
8873                 false /* privateDnsProbeSent */);
8874         assertUidRangesUpdatedForMyUid(true);
8875 
8876         defaultCallback.assertNoCallback();
8877         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
8878 
8879         mMockVpn.disconnect();
8880         defaultCallback.assertNoCallback();
8881 
8882         mCm.unregisterNetworkCallback(defaultCallback);
8883     }
8884 
8885     @Test
8886     public void testVpnWithInternet() throws Exception {
8887         final int uid = Process.myUid();
8888 
8889         final TestNetworkCallback defaultCallback = new TestNetworkCallback();
8890         mCm.registerDefaultNetworkCallback(defaultCallback);
8891 
8892         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
8893         mWiFiAgent.connect(true);
8894 
8895         defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiAgent);
8896         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
8897 
8898         mMockVpn.establishForMyUid(true /* validated */, true /* hasInternet */,
8899                 false /* privateDnsProbeSent */);
8900         assertUidRangesUpdatedForMyUid(true);
8901 
8902         defaultCallback.expectAvailableThenValidatedCallbacks(mMockVpn);
8903         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
8904 
8905         mMockVpn.disconnect();
8906         defaultCallback.expect(LOST, mMockVpn);
8907         defaultCallback.expectAvailableCallbacksValidated(mWiFiAgent);
8908 
8909         mCm.unregisterNetworkCallback(defaultCallback);
8910     }
8911 
8912     @Test
8913     public void testVpnUnvalidated() throws Exception {
8914         final TestNetworkCallback callback = new TestNetworkCallback();
8915         mCm.registerDefaultNetworkCallback(callback);
8916 
8917         // Bring up Ethernet.
8918         mEthernetAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
8919         mEthernetAgent.connect(true);
8920         callback.expectAvailableThenValidatedCallbacks(mEthernetAgent);
8921         callback.assertNoCallback();
8922 
8923         // Bring up a VPN that has the INTERNET capability, initially unvalidated.
8924         mMockVpn.establishForMyUid(false /* validated */, true /* hasInternet */,
8925                 false /* privateDnsProbeSent */);
8926         assertUidRangesUpdatedForMyUid(true);
8927 
8928         // Even though the VPN is unvalidated, it becomes the default network for our app.
8929         callback.expectAvailableCallbacksUnvalidated(mMockVpn);
8930         callback.assertNoCallback();
8931 
8932         assertEquals(mMockVpn.getNetwork(), mCm.getActiveNetwork());
8933 
8934         NetworkCapabilities nc = mCm.getNetworkCapabilities(mMockVpn.getNetwork());
8935         assertFalse(nc.hasCapability(NET_CAPABILITY_VALIDATED));
8936         assertTrue(nc.hasCapability(NET_CAPABILITY_INTERNET));
8937 
8938         assertFalse(NetworkMonitorUtils.isValidationRequired(
8939                 false /* isDunValidationRequired */,
8940                 NetworkAgentConfigShimImpl.newInstance(mMockVpn.getNetworkAgentConfig())
8941                         .isVpnValidationRequired(),
8942                 mMockVpn.getAgent().getNetworkCapabilities()));
8943         assertTrue(NetworkMonitorUtils.isPrivateDnsValidationRequired(
8944                 mMockVpn.getAgent().getNetworkCapabilities()));
8945 
8946         // Pretend that the VPN network validates.
8947         mMockVpn.getAgent().setNetworkValid(false /* privateDnsProbeSent */);
8948         mMockVpn.getAgent().mNetworkMonitor.forceReevaluation(Process.myUid());
8949         // Expect to see the validated capability, but no other changes, because the VPN is already
8950         // the default network for the app.
8951         callback.expectCaps(mMockVpn, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
8952         callback.assertNoCallback();
8953 
8954         mMockVpn.disconnect();
8955         callback.expect(LOST, mMockVpn);
8956         callback.expectAvailableCallbacksValidated(mEthernetAgent);
8957     }
8958 
8959     @Test
8960     public void testVpnStartsWithUnderlyingCaps() throws Exception {
8961         final int uid = Process.myUid();
8962 
8963         final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
8964         final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder()
8965                 .removeCapability(NET_CAPABILITY_NOT_VPN)
8966                 .addTransportType(TRANSPORT_VPN)
8967                 .build();
8968         mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
8969         vpnNetworkCallback.assertNoCallback();
8970 
8971         // Connect cell. It will become the default network, and in the absence of setting
8972         // underlying networks explicitly it will become the sole underlying network for the vpn.
8973         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
8974         mCellAgent.addCapability(NET_CAPABILITY_NOT_SUSPENDED);
8975         mCellAgent.connect(true);
8976 
8977         mMockVpn.establishForMyUid(true /* validated */, false /* hasInternet */,
8978                 false /* privateDnsProbeSent */);
8979         assertUidRangesUpdatedForMyUid(true);
8980 
8981         vpnNetworkCallback.expectAvailableCallbacks(mMockVpn.getNetwork(),
8982                 false /* suspended */, false /* validated */, false /* blocked */, TIMEOUT_MS);
8983         vpnNetworkCallback.expectCaps(mMockVpn.getNetwork(), TIMEOUT_MS,
8984                 c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
8985 
8986         final NetworkCapabilities nc = mCm.getNetworkCapabilities(mMockVpn.getNetwork());
8987         assertTrue(nc.hasTransport(TRANSPORT_VPN));
8988         assertTrue(nc.hasTransport(TRANSPORT_CELLULAR));
8989         assertFalse(nc.hasTransport(TRANSPORT_WIFI));
8990         assertTrue(nc.hasCapability(NET_CAPABILITY_VALIDATED));
8991         assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED));
8992         assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
8993 
8994         assertVpnTransportInfo(nc, VpnManager.TYPE_VPN_SERVICE);
8995     }
8996 
8997     private void assertDefaultNetworkCapabilities(int userId, NetworkAgentWrapper... networks) {
8998         final NetworkCapabilities[] defaultCaps = mService.getDefaultNetworkCapabilitiesForUser(
8999                 userId, "com.android.calling.package", "com.test");
9000         final String defaultCapsString = Arrays.toString(defaultCaps);
9001         assertEquals(defaultCapsString, defaultCaps.length, networks.length);
9002         final Set<NetworkCapabilities> defaultCapsSet = new ArraySet<>(defaultCaps);
9003         for (NetworkAgentWrapper network : networks) {
9004             final NetworkCapabilities nc = mCm.getNetworkCapabilities(network.getNetwork());
9005             final String msg = "Did not find " + nc + " in " + Arrays.toString(defaultCaps);
9006             assertTrue(msg, defaultCapsSet.contains(nc));
9007         }
9008     }
9009 
9010     @Test
9011     public void testVpnSetUnderlyingNetworks() throws Exception {
9012         final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
9013         final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder()
9014                 .removeCapability(NET_CAPABILITY_NOT_VPN)
9015                 .addTransportType(TRANSPORT_VPN)
9016                 .build();
9017         NetworkCapabilities nc;
9018         mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
9019         vpnNetworkCallback.assertNoCallback();
9020 
9021         mMockVpn.establishForMyUid(true /* validated */, false /* hasInternet */,
9022                 false /* privateDnsProbeSent */);
9023         assertUidRangesUpdatedForMyUid(true);
9024 
9025         vpnNetworkCallback.expectAvailableThenValidatedCallbacks(mMockVpn);
9026         nc = mCm.getNetworkCapabilities(mMockVpn.getNetwork());
9027         assertTrue(nc.hasTransport(TRANSPORT_VPN));
9028         assertFalse(nc.hasTransport(TRANSPORT_CELLULAR));
9029         assertFalse(nc.hasTransport(TRANSPORT_WIFI));
9030         // For safety reasons a VPN without underlying networks is considered metered.
9031         assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED));
9032         // A VPN without underlying networks is not suspended.
9033         assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
9034         assertVpnTransportInfo(nc, VpnManager.TYPE_VPN_SERVICE);
9035 
9036         final int userId = UserHandle.getUserId(Process.myUid());
9037         assertDefaultNetworkCapabilities(userId /* no networks */);
9038 
9039         // Connect cell and use it as an underlying network.
9040         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
9041         mCellAgent.addCapability(NET_CAPABILITY_NOT_SUSPENDED);
9042         mCellAgent.connect(true);
9043 
9044         mMockVpn.setUnderlyingNetworks(new Network[] { mCellAgent.getNetwork() });
9045 
9046         vpnNetworkCallback.expectCaps(mMockVpn,
9047                 c -> c.hasTransport(TRANSPORT_VPN)
9048                         && c.hasTransport(TRANSPORT_CELLULAR)
9049                         && !c.hasTransport(TRANSPORT_WIFI)
9050                         && !c.hasCapability(NET_CAPABILITY_NOT_METERED)
9051                         && c.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
9052         assertDefaultNetworkCapabilities(userId, mCellAgent);
9053 
9054         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
9055         mWiFiAgent.addCapability(NET_CAPABILITY_NOT_METERED);
9056         mWiFiAgent.addCapability(NET_CAPABILITY_NOT_SUSPENDED);
9057         mWiFiAgent.connect(true);
9058 
9059         mMockVpn.setUnderlyingNetworks(
9060                 new Network[] { mCellAgent.getNetwork(), mWiFiAgent.getNetwork() });
9061 
9062         vpnNetworkCallback.expectCaps(mMockVpn,
9063                 c -> c.hasTransport(TRANSPORT_VPN)
9064                         && c.hasTransport(TRANSPORT_CELLULAR)
9065                         && c.hasTransport(TRANSPORT_WIFI)
9066                         && !c.hasCapability(NET_CAPABILITY_NOT_METERED)
9067                         && c.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
9068         assertDefaultNetworkCapabilities(userId, mCellAgent, mWiFiAgent);
9069 
9070         // Don't disconnect, but note the VPN is not using wifi any more.
9071         mMockVpn.setUnderlyingNetworks(new Network[] { mCellAgent.getNetwork() });
9072 
9073         vpnNetworkCallback.expectCaps(mMockVpn,
9074                 c -> c.hasTransport(TRANSPORT_VPN)
9075                         && c.hasTransport(TRANSPORT_CELLULAR)
9076                         && !c.hasTransport(TRANSPORT_WIFI)
9077                         && !c.hasCapability(NET_CAPABILITY_NOT_METERED)
9078                         && c.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
9079         // The return value of getDefaultNetworkCapabilitiesForUser always includes the default
9080         // network (wifi) as well as the underlying networks (cell).
9081         assertDefaultNetworkCapabilities(userId, mCellAgent, mWiFiAgent);
9082 
9083         // Remove NOT_SUSPENDED from the only network and observe VPN is now suspended.
9084         mCellAgent.removeCapability(NET_CAPABILITY_NOT_SUSPENDED);
9085         vpnNetworkCallback.expectCaps(mMockVpn,
9086                 c -> c.hasTransport(TRANSPORT_VPN)
9087                         && c.hasTransport(TRANSPORT_CELLULAR)
9088                         && !c.hasTransport(TRANSPORT_WIFI)
9089                         && !c.hasCapability(NET_CAPABILITY_NOT_METERED)
9090                         && !c.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
9091         vpnNetworkCallback.expect(SUSPENDED, mMockVpn);
9092 
9093         // Add NOT_SUSPENDED again and observe VPN is no longer suspended.
9094         mCellAgent.addCapability(NET_CAPABILITY_NOT_SUSPENDED);
9095         vpnNetworkCallback.expectCaps(mMockVpn,
9096                 c -> c.hasTransport(TRANSPORT_VPN)
9097                         && c.hasTransport(TRANSPORT_CELLULAR)
9098                         && !c.hasTransport(TRANSPORT_WIFI)
9099                         && !c.hasCapability(NET_CAPABILITY_NOT_METERED)
9100                         && c.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
9101         vpnNetworkCallback.expect(RESUMED, mMockVpn);
9102 
9103         // Use Wifi but not cell. Note the VPN is now unmetered and not suspended.
9104         mMockVpn.setUnderlyingNetworks(new Network[] { mWiFiAgent.getNetwork() });
9105 
9106         vpnNetworkCallback.expectCaps(mMockVpn,
9107                 c -> c.hasTransport(TRANSPORT_VPN)
9108                         && !c.hasTransport(TRANSPORT_CELLULAR)
9109                         && c.hasTransport(TRANSPORT_WIFI)
9110                         && c.hasCapability(NET_CAPABILITY_NOT_METERED)
9111                         && c.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
9112         assertDefaultNetworkCapabilities(userId, mWiFiAgent);
9113 
9114         // Use both again.
9115         mMockVpn.setUnderlyingNetworks(
9116                 new Network[] { mCellAgent.getNetwork(), mWiFiAgent.getNetwork() });
9117 
9118         vpnNetworkCallback.expectCaps(mMockVpn,
9119                 c -> c.hasTransport(TRANSPORT_VPN)
9120                         && c.hasTransport(TRANSPORT_CELLULAR)
9121                         && c.hasTransport(TRANSPORT_WIFI)
9122                         && !c.hasCapability(NET_CAPABILITY_NOT_METERED)
9123                         && c.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
9124         assertDefaultNetworkCapabilities(userId, mCellAgent, mWiFiAgent);
9125 
9126         // Cell is suspended again. As WiFi is not, this should not cause a callback.
9127         mCellAgent.removeCapability(NET_CAPABILITY_NOT_SUSPENDED);
9128         vpnNetworkCallback.assertNoCallback();
9129 
9130         // Stop using WiFi. The VPN is suspended again.
9131         mMockVpn.setUnderlyingNetworks(new Network[] { mCellAgent.getNetwork() });
9132         vpnNetworkCallback.expectCaps(mMockVpn,
9133                 c -> c.hasTransport(TRANSPORT_VPN)
9134                         && c.hasTransport(TRANSPORT_CELLULAR)
9135                         && !c.hasCapability(NET_CAPABILITY_NOT_METERED)
9136                         && !c.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
9137         vpnNetworkCallback.expect(SUSPENDED, mMockVpn);
9138         assertDefaultNetworkCapabilities(userId, mCellAgent, mWiFiAgent);
9139 
9140         // Use both again.
9141         mMockVpn.setUnderlyingNetworks(
9142                 new Network[] { mCellAgent.getNetwork(), mWiFiAgent.getNetwork() });
9143 
9144         vpnNetworkCallback.expectCaps(mMockVpn,
9145                 c -> c.hasTransport(TRANSPORT_VPN)
9146                         && c.hasTransport(TRANSPORT_CELLULAR)
9147                         && c.hasTransport(TRANSPORT_WIFI)
9148                         && !c.hasCapability(NET_CAPABILITY_NOT_METERED)
9149                         && c.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
9150         vpnNetworkCallback.expect(RESUMED, mMockVpn);
9151         assertDefaultNetworkCapabilities(userId, mCellAgent, mWiFiAgent);
9152 
9153         // Disconnect cell. Receive update without even removing the dead network from the
9154         // underlying networks – it's dead anyway. Not metered any more.
9155         mCellAgent.disconnect();
9156         vpnNetworkCallback.expectCaps(mMockVpn,
9157                 c -> c.hasTransport(TRANSPORT_VPN)
9158                         && !c.hasTransport(TRANSPORT_CELLULAR)
9159                         && c.hasTransport(TRANSPORT_WIFI)
9160                         && c.hasCapability(NET_CAPABILITY_NOT_METERED));
9161         assertDefaultNetworkCapabilities(userId, mWiFiAgent);
9162 
9163         // Disconnect wifi too. No underlying networks means this is now metered.
9164         mWiFiAgent.disconnect();
9165         vpnNetworkCallback.expectCaps(mMockVpn,
9166                 c -> c.hasTransport(TRANSPORT_VPN)
9167                         && !c.hasTransport(TRANSPORT_CELLULAR)
9168                         && !c.hasTransport(TRANSPORT_WIFI)
9169                         && !c.hasCapability(NET_CAPABILITY_NOT_METERED));
9170         // When a network disconnects, the callbacks are fired before all state is updated, so for a
9171         // short time, synchronous calls will behave as if the network is still connected. Wait for
9172         // things to settle.
9173         waitForIdle();
9174         assertDefaultNetworkCapabilities(userId /* no networks */);
9175 
9176         mMockVpn.disconnect();
9177     }
9178 
9179     @Test
9180     public void testNullUnderlyingNetworks() throws Exception {
9181         final int uid = Process.myUid();
9182 
9183         final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
9184         final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder()
9185                 .removeCapability(NET_CAPABILITY_NOT_VPN)
9186                 .addTransportType(TRANSPORT_VPN)
9187                 .build();
9188         NetworkCapabilities nc;
9189         mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
9190         vpnNetworkCallback.assertNoCallback();
9191 
9192         mMockVpn.establishForMyUid(true /* validated */, false /* hasInternet */,
9193                 false /* privateDnsProbeSent */);
9194         assertUidRangesUpdatedForMyUid(true);
9195 
9196         vpnNetworkCallback.expectAvailableThenValidatedCallbacks(mMockVpn);
9197         nc = mCm.getNetworkCapabilities(mMockVpn.getNetwork());
9198         assertTrue(nc.hasTransport(TRANSPORT_VPN));
9199         assertFalse(nc.hasTransport(TRANSPORT_CELLULAR));
9200         assertFalse(nc.hasTransport(TRANSPORT_WIFI));
9201         // By default, VPN is set to track default network (i.e. its underlying networks is null).
9202         // In case of no default network, VPN is considered metered.
9203         assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED));
9204         assertVpnTransportInfo(nc, VpnManager.TYPE_VPN_SERVICE);
9205 
9206         // Connect to Cell; Cell is the default network.
9207         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
9208         mCellAgent.connect(true);
9209 
9210         vpnNetworkCallback.expectCaps(mMockVpn,
9211                 c -> c.hasTransport(TRANSPORT_VPN)
9212                         && c.hasTransport(TRANSPORT_CELLULAR)
9213                         && !c.hasTransport(TRANSPORT_WIFI)
9214                         && !c.hasCapability(NET_CAPABILITY_NOT_METERED));
9215 
9216         // Connect to WiFi; WiFi is the new default.
9217         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
9218         mWiFiAgent.addCapability(NET_CAPABILITY_NOT_METERED);
9219         mWiFiAgent.connect(true);
9220 
9221         vpnNetworkCallback.expectCaps(mMockVpn,
9222                 c -> c.hasTransport(TRANSPORT_VPN)
9223                         && !c.hasTransport(TRANSPORT_CELLULAR)
9224                         && c.hasTransport(TRANSPORT_WIFI)
9225                         && c.hasCapability(NET_CAPABILITY_NOT_METERED));
9226 
9227         // Disconnect Cell. The default network did not change, so there shouldn't be any changes in
9228         // the capabilities.
9229         mCellAgent.disconnect();
9230 
9231         // Disconnect wifi too. Now we have no default network.
9232         mWiFiAgent.disconnect();
9233 
9234         vpnNetworkCallback.expectCaps(mMockVpn,
9235                 c -> c.hasTransport(TRANSPORT_VPN)
9236                         && !c.hasTransport(TRANSPORT_CELLULAR)
9237                         && !c.hasTransport(TRANSPORT_WIFI)
9238                         && !c.hasCapability(NET_CAPABILITY_NOT_METERED));
9239 
9240         mMockVpn.disconnect();
9241     }
9242 
9243     @Test
9244     public void testRestrictedProfileAffectsVpnUidRanges() throws Exception {
9245         // NETWORK_SETTINGS is necessary to see the UID ranges in NetworkCapabilities.
9246         mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_GRANTED);
9247 
9248         final NetworkRequest request = new NetworkRequest.Builder()
9249                 .removeCapability(NET_CAPABILITY_NOT_VPN)
9250                 .build();
9251         final TestNetworkCallback callback = new TestNetworkCallback();
9252         mCm.registerNetworkCallback(request, callback);
9253 
9254         // File a VPN request to prevent VPN network being lingered.
9255         final NetworkRequest vpnRequest = new NetworkRequest.Builder()
9256                 .addTransportType(TRANSPORT_VPN)
9257                 .removeCapability(NET_CAPABILITY_NOT_VPN)
9258                 .build();
9259         final TestNetworkCallback vpnCallback = new TestNetworkCallback();
9260         mCm.requestNetwork(vpnRequest, vpnCallback);
9261 
9262         // Bring up a VPN
9263         mMockVpn.establishForMyUid();
9264         assertUidRangesUpdatedForMyUid(true);
9265         callback.expectAvailableThenValidatedCallbacks(mMockVpn);
9266         callback.assertNoCallback();
9267 
9268         final int uid = Process.myUid();
9269         NetworkCapabilities nc = mCm.getNetworkCapabilities(mMockVpn.getNetwork());
9270         assertNotNull("nc=" + nc, nc.getUids());
9271         assertEquals(nc.getUids(), UidRange.toIntRanges(uidRangesForUids(uid)));
9272         assertVpnTransportInfo(nc, VpnManager.TYPE_VPN_SERVICE);
9273 
9274         // Set an underlying network and expect to see the VPN transports change.
9275         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
9276         mWiFiAgent.connect(true);
9277         callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
9278         callback.expectCaps(mMockVpn, c -> c.hasTransport(TRANSPORT_VPN)
9279                         && c.hasTransport(TRANSPORT_WIFI));
9280         callback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
9281 
9282         doReturn(UserHandle.getUid(RESTRICTED_USER, VPN_UID)).when(mPackageManager)
9283                 .getPackageUidAsUser(ALWAYS_ON_PACKAGE, RESTRICTED_USER);
9284 
9285         // New user added
9286         mMockVpn.onUserAdded(RESTRICTED_USER);
9287 
9288         // Expect that the VPN UID ranges contain both |uid| and the UID range for the newly-added
9289         // restricted user.
9290         final UidRange rRange = UidRange.createForUser(UserHandle.of(RESTRICTED_USER));
9291         final Range<Integer> restrictUidRange = new Range<>(rRange.start, rRange.stop);
9292         final Range<Integer> singleUidRange = new Range<>(uid, uid);
9293         callback.expectCaps(mMockVpn, c ->
9294                 c.getUids().size() == 2
9295                 && c.getUids().contains(singleUidRange)
9296                 && c.getUids().contains(restrictUidRange)
9297                 && c.hasTransport(TRANSPORT_VPN)
9298                 && c.hasTransport(TRANSPORT_WIFI));
9299 
9300         // Change the VPN's capabilities somehow (specifically, disconnect wifi).
9301         mWiFiAgent.disconnect();
9302         callback.expect(LOST, mWiFiAgent);
9303         callback.expectCaps(mMockVpn, c ->
9304                 c.getUids().size() == 2
9305                 && c.getUids().contains(singleUidRange)
9306                 && c.getUids().contains(restrictUidRange)
9307                 && c.hasTransport(TRANSPORT_VPN)
9308                 && !c.hasTransport(TRANSPORT_WIFI));
9309 
9310         // User removed and expect to lose the UID range for the restricted user.
9311         mMockVpn.onUserRemoved(RESTRICTED_USER);
9312 
9313         // Expect that the VPN gains the UID range for the restricted user, and that the capability
9314         // change made just before that (i.e., loss of TRANSPORT_WIFI) is preserved.
9315         callback.expectCaps(mMockVpn, c ->
9316                 c.getUids().size() == 1
9317                 && c.getUids().contains(singleUidRange)
9318                 && c.hasTransport(TRANSPORT_VPN)
9319                 && !c.hasTransport(TRANSPORT_WIFI));
9320 
9321         mCm.unregisterNetworkCallback(callback);
9322         mCm.unregisterNetworkCallback(vpnCallback);
9323     }
9324 
9325     @Test
9326     public void testLockdownVpnWithRestrictedProfiles() throws Exception {
9327         // For ConnectivityService#setAlwaysOnVpnPackage.
9328         mServiceContext.setPermission(
9329                 Manifest.permission.CONTROL_ALWAYS_ON_VPN, PERMISSION_GRANTED);
9330         // For call Vpn#setAlwaysOnPackage.
9331         mServiceContext.setPermission(
9332                 Manifest.permission.CONTROL_VPN, PERMISSION_GRANTED);
9333         // Necessary to see the UID ranges in NetworkCapabilities.
9334         mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_GRANTED);
9335 
9336         final NetworkRequest request = new NetworkRequest.Builder()
9337                 .removeCapability(NET_CAPABILITY_NOT_VPN)
9338                 .build();
9339         final TestNetworkCallback callback = new TestNetworkCallback();
9340         mCm.registerNetworkCallback(request, callback);
9341 
9342         final int uid = Process.myUid();
9343 
9344         // Connect wifi and check that UIDs in the main and restricted profiles have network access.
9345         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
9346         mWiFiAgent.connect(true /* validated */);
9347         final int restrictedUid = UserHandle.getUid(RESTRICTED_USER, 42 /* appId */);
9348         assertNotNull(mCm.getActiveNetworkForUid(uid));
9349         assertNotNull(mCm.getActiveNetworkForUid(restrictedUid));
9350 
9351         // Enable always-on VPN lockdown. The main user loses network access because no VPN is up.
9352         final ArrayList<String> allowList = new ArrayList<>();
9353         mMockVpn.setAlwaysOnPackage(ALWAYS_ON_PACKAGE, true /* lockdown */, allowList);
9354         waitForIdle();
9355         assertNull(mCm.getActiveNetworkForUid(uid));
9356         // This is arguably overspecified: a UID that is not running doesn't have an active network.
9357         // But it's useful to check that non-default users do not lose network access, and to prove
9358         // that the loss of connectivity below is indeed due to the restricted profile coming up.
9359         assertNotNull(mCm.getActiveNetworkForUid(restrictedUid));
9360 
9361         // Start the restricted profile, and check that the UID within it loses network access.
9362         doReturn(UserHandle.getUid(RESTRICTED_USER, VPN_UID)).when(mPackageManager)
9363                 .getPackageUidAsUser(ALWAYS_ON_PACKAGE, RESTRICTED_USER);
9364         doReturn(asList(PRIMARY_USER_INFO, RESTRICTED_USER_INFO)).when(mUserManager)
9365                 .getAliveUsers();
9366         // TODO: check that VPN app within restricted profile still has access, etc.
9367         mMockVpn.onUserAdded(RESTRICTED_USER);
9368         final Intent addedIntent = new Intent(ACTION_USER_ADDED);
9369         addedIntent.putExtra(Intent.EXTRA_USER, UserHandle.of(RESTRICTED_USER));
9370         addedIntent.putExtra(Intent.EXTRA_USER_HANDLE, RESTRICTED_USER);
9371         processBroadcast(addedIntent);
9372         assertNull(mCm.getActiveNetworkForUid(uid));
9373         assertNull(mCm.getActiveNetworkForUid(restrictedUid));
9374 
9375         // Stop the restricted profile, and check that the UID within it has network access again.
9376         doReturn(asList(PRIMARY_USER_INFO)).when(mUserManager).getAliveUsers();
9377 
9378         // Send a USER_REMOVED broadcast and expect to lose the UID range for the restricted user.
9379         mMockVpn.onUserRemoved(RESTRICTED_USER);
9380         final Intent removedIntent = new Intent(ACTION_USER_REMOVED);
9381         removedIntent.putExtra(Intent.EXTRA_USER, UserHandle.of(RESTRICTED_USER));
9382         removedIntent.putExtra(Intent.EXTRA_USER_HANDLE, RESTRICTED_USER);
9383         processBroadcast(removedIntent);
9384         assertNull(mCm.getActiveNetworkForUid(uid));
9385         assertNotNull(mCm.getActiveNetworkForUid(restrictedUid));
9386 
9387         mMockVpn.setAlwaysOnPackage(null, false /* lockdown */, allowList);
9388         waitForIdle();
9389     }
9390 
9391     @Test
9392     public void testIsActiveNetworkMeteredOverWifi() throws Exception {
9393         // Returns true by default when no network is available.
9394         assertTrue(mCm.isActiveNetworkMetered());
9395         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
9396         mWiFiAgent.addCapability(NET_CAPABILITY_NOT_METERED);
9397         mWiFiAgent.connect(true);
9398         waitForIdle();
9399 
9400         assertFalse(mCm.isActiveNetworkMetered());
9401     }
9402 
9403     @Test
9404     public void testIsActiveNetworkMeteredOverCell() throws Exception {
9405         // Returns true by default when no network is available.
9406         assertTrue(mCm.isActiveNetworkMetered());
9407         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
9408         mCellAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
9409         mCellAgent.connect(true);
9410         waitForIdle();
9411 
9412         assertTrue(mCm.isActiveNetworkMetered());
9413     }
9414 
9415     @Test
9416     public void testIsActiveNetworkMeteredOverVpnTrackingPlatformDefault() throws Exception {
9417         // Returns true by default when no network is available.
9418         assertTrue(mCm.isActiveNetworkMetered());
9419         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
9420         mCellAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
9421         mCellAgent.connect(true);
9422         waitForIdle();
9423         assertTrue(mCm.isActiveNetworkMetered());
9424 
9425         // Connect VPN network. By default it is using current default network (Cell).
9426         mMockVpn.establishForMyUid();
9427         assertUidRangesUpdatedForMyUid(true);
9428 
9429         // Ensure VPN is now the active network.
9430         assertEquals(mMockVpn.getNetwork(), mCm.getActiveNetwork());
9431 
9432         // Expect VPN to be metered.
9433         assertTrue(mCm.isActiveNetworkMetered());
9434 
9435         // Connect WiFi.
9436         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
9437         mWiFiAgent.addCapability(NET_CAPABILITY_NOT_METERED);
9438         mWiFiAgent.connect(true);
9439         waitForIdle();
9440         // VPN should still be the active network.
9441         assertEquals(mMockVpn.getNetwork(), mCm.getActiveNetwork());
9442 
9443         // Expect VPN to be unmetered as it should now be using WiFi (new default).
9444         assertFalse(mCm.isActiveNetworkMetered());
9445 
9446         // Disconnecting Cell should not affect VPN's meteredness.
9447         mCellAgent.disconnect();
9448         waitForIdle();
9449 
9450         assertFalse(mCm.isActiveNetworkMetered());
9451 
9452         // Disconnect WiFi; Now there is no platform default network.
9453         mWiFiAgent.disconnect();
9454         waitForIdle();
9455 
9456         // VPN without any underlying networks is treated as metered.
9457         assertTrue(mCm.isActiveNetworkMetered());
9458 
9459         mMockVpn.disconnect();
9460     }
9461 
9462     @Test
9463     public void testIsActiveNetworkMeteredOverVpnSpecifyingUnderlyingNetworks() throws Exception {
9464         // Returns true by default when no network is available.
9465         assertTrue(mCm.isActiveNetworkMetered());
9466         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
9467         mCellAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
9468         mCellAgent.connect(true);
9469         waitForIdle();
9470         assertTrue(mCm.isActiveNetworkMetered());
9471 
9472         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
9473         mWiFiAgent.addCapability(NET_CAPABILITY_NOT_METERED);
9474         mWiFiAgent.connect(true);
9475         waitForIdle();
9476         assertFalse(mCm.isActiveNetworkMetered());
9477 
9478         // Connect VPN network.
9479         mMockVpn.establishForMyUid();
9480         assertUidRangesUpdatedForMyUid(true);
9481 
9482         // Ensure VPN is now the active network.
9483         assertEquals(mMockVpn.getNetwork(), mCm.getActiveNetwork());
9484         // VPN is using Cell
9485         mMockVpn.setUnderlyingNetworks(new Network[] { mCellAgent.getNetwork() });
9486         waitForIdle();
9487 
9488         // Expect VPN to be metered.
9489         assertTrue(mCm.isActiveNetworkMetered());
9490 
9491         // VPN is now using WiFi
9492         mMockVpn.setUnderlyingNetworks(new Network[] { mWiFiAgent.getNetwork() });
9493         waitForIdle();
9494 
9495         // Expect VPN to be unmetered
9496         assertFalse(mCm.isActiveNetworkMetered());
9497 
9498         // VPN is using Cell | WiFi.
9499         mMockVpn.setUnderlyingNetworks(
9500                 new Network[] { mCellAgent.getNetwork(), mWiFiAgent.getNetwork() });
9501         waitForIdle();
9502 
9503         // Expect VPN to be metered.
9504         assertTrue(mCm.isActiveNetworkMetered());
9505 
9506         // VPN is using WiFi | Cell.
9507         mMockVpn.setUnderlyingNetworks(
9508                 new Network[] { mWiFiAgent.getNetwork(), mCellAgent.getNetwork() });
9509         waitForIdle();
9510 
9511         // Order should not matter and VPN should still be metered.
9512         assertTrue(mCm.isActiveNetworkMetered());
9513 
9514         // VPN is not using any underlying networks.
9515         mMockVpn.setUnderlyingNetworks(new Network[0]);
9516         waitForIdle();
9517 
9518         // VPN without underlying networks is treated as metered.
9519         assertTrue(mCm.isActiveNetworkMetered());
9520 
9521         mMockVpn.disconnect();
9522     }
9523 
9524     @Test
9525     public void testIsActiveNetworkMeteredOverAlwaysMeteredVpn() throws Exception {
9526         // Returns true by default when no network is available.
9527         assertTrue(mCm.isActiveNetworkMetered());
9528         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
9529         mWiFiAgent.addCapability(NET_CAPABILITY_NOT_METERED);
9530         mWiFiAgent.connect(true);
9531         waitForIdle();
9532         assertFalse(mCm.isActiveNetworkMetered());
9533 
9534         // Connect VPN network.
9535         mMockVpn.registerAgent(true /* isAlwaysMetered */, uidRangesForUids(Process.myUid()),
9536                 new LinkProperties());
9537         mMockVpn.connect(true);
9538         waitForIdle();
9539         assertEquals(mMockVpn.getNetwork(), mCm.getActiveNetwork());
9540 
9541         // VPN is tracking current platform default (WiFi).
9542         mMockVpn.setUnderlyingNetworks(null);
9543         waitForIdle();
9544 
9545         // Despite VPN using WiFi (which is unmetered), VPN itself is marked as always metered.
9546         assertTrue(mCm.isActiveNetworkMetered());
9547 
9548 
9549         // VPN explicitly declares WiFi as its underlying network.
9550         mMockVpn.setUnderlyingNetworks(new Network[] { mWiFiAgent.getNetwork() });
9551         waitForIdle();
9552 
9553         // Doesn't really matter whether VPN declares its underlying networks explicitly.
9554         assertTrue(mCm.isActiveNetworkMetered());
9555 
9556         // With WiFi lost, VPN is basically without any underlying networks. And in that case it is
9557         // anyways suppose to be metered.
9558         mWiFiAgent.disconnect();
9559         waitForIdle();
9560 
9561         assertTrue(mCm.isActiveNetworkMetered());
9562 
9563         mMockVpn.disconnect();
9564     }
9565 
9566     private class DetailedBlockedStatusCallback extends TestNetworkCallback {
9567         public void expectAvailableThenValidatedCallbacks(HasNetwork n, int blockedStatus) {
9568             super.expectAvailableThenValidatedCallbacks(n.getNetwork(), blockedStatus, TIMEOUT_MS);
9569         }
9570         public void onBlockedStatusChanged(Network network, int blockedReasons) {
9571             getHistory().add(new CallbackEntry.BlockedStatusInt(network, blockedReasons));
9572         }
9573     }
9574 
9575     @Test
9576     public void testNetworkBlockedStatus() throws Exception {
9577         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
9578         final NetworkRequest cellRequest = new NetworkRequest.Builder()
9579                 .addTransportType(TRANSPORT_CELLULAR)
9580                 .build();
9581         mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
9582         final DetailedBlockedStatusCallback detailedCallback = new DetailedBlockedStatusCallback();
9583         mCm.registerNetworkCallback(cellRequest, detailedCallback);
9584 
9585         mockUidNetworkingBlocked();
9586 
9587         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
9588         mCellAgent.connect(true);
9589         cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
9590         detailedCallback.expectAvailableThenValidatedCallbacks(mCellAgent, BLOCKED_REASON_NONE);
9591         assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetwork());
9592         assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
9593         assertNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
9594         assertExtraInfoFromCmPresent(mCellAgent);
9595 
9596         setBlockedReasonChanged(BLOCKED_REASON_BATTERY_SAVER);
9597         cellNetworkCallback.expect(BLOCKED_STATUS, mCellAgent, cb -> cb.getBlocked());
9598         detailedCallback.expect(BLOCKED_STATUS_INT, mCellAgent,
9599                 cb -> cb.getReason() == BLOCKED_REASON_BATTERY_SAVER);
9600         assertNull(mCm.getActiveNetwork());
9601         assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
9602         assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
9603         assertExtraInfoFromCmBlocked(mCellAgent);
9604 
9605         // If blocked state does not change but blocked reason does, the boolean callback is called.
9606         // TODO: investigate de-duplicating.
9607         setBlockedReasonChanged(BLOCKED_METERED_REASON_USER_RESTRICTED);
9608         cellNetworkCallback.expect(BLOCKED_STATUS, mCellAgent, cb -> cb.getBlocked());
9609         detailedCallback.expect(BLOCKED_STATUS_INT, mCellAgent,
9610                 cb -> cb.getReason() == BLOCKED_METERED_REASON_USER_RESTRICTED);
9611 
9612         setBlockedReasonChanged(BLOCKED_REASON_NONE);
9613         cellNetworkCallback.expect(BLOCKED_STATUS, mCellAgent, cb -> !cb.getBlocked());
9614         detailedCallback.expect(BLOCKED_STATUS_INT, mCellAgent,
9615                 cb -> cb.getReason() == BLOCKED_REASON_NONE);
9616         assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetwork());
9617         assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
9618         assertNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
9619         assertExtraInfoFromCmPresent(mCellAgent);
9620 
9621         setBlockedReasonChanged(BLOCKED_METERED_REASON_DATA_SAVER);
9622         cellNetworkCallback.expect(BLOCKED_STATUS, mCellAgent, cb -> cb.getBlocked());
9623         detailedCallback.expect(BLOCKED_STATUS_INT, mCellAgent,
9624                 cb -> cb.getReason() == BLOCKED_METERED_REASON_DATA_SAVER);
9625         assertNull(mCm.getActiveNetwork());
9626         assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
9627         assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
9628         assertExtraInfoFromCmBlocked(mCellAgent);
9629 
9630         // Restrict the network based on UID rule and NOT_METERED capability change.
9631         mCellAgent.addCapability(NET_CAPABILITY_NOT_METERED);
9632         cellNetworkCallback.expectCaps(mCellAgent,
9633                 c -> c.hasCapability(NET_CAPABILITY_NOT_METERED));
9634         cellNetworkCallback.expect(BLOCKED_STATUS, mCellAgent, cb -> !cb.getBlocked());
9635         detailedCallback.expectCaps(mCellAgent, c -> c.hasCapability(NET_CAPABILITY_NOT_METERED));
9636         detailedCallback.expect(BLOCKED_STATUS_INT, mCellAgent,
9637                 cb -> cb.getReason() == BLOCKED_REASON_NONE);
9638         assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetwork());
9639         assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
9640         assertNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
9641         assertExtraInfoFromCmPresent(mCellAgent);
9642 
9643         mCellAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
9644         cellNetworkCallback.expectCaps(mCellAgent,
9645                 c -> !c.hasCapability(NET_CAPABILITY_NOT_METERED));
9646         cellNetworkCallback.expect(BLOCKED_STATUS, mCellAgent, cb -> cb.getBlocked());
9647         detailedCallback.expectCaps(mCellAgent,
9648                 c -> !c.hasCapability(NET_CAPABILITY_NOT_METERED));
9649         detailedCallback.expect(BLOCKED_STATUS_INT, mCellAgent,
9650                 cb -> cb.getReason() == BLOCKED_METERED_REASON_DATA_SAVER);
9651         assertNull(mCm.getActiveNetwork());
9652         assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
9653         assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
9654         assertExtraInfoFromCmBlocked(mCellAgent);
9655 
9656         setBlockedReasonChanged(BLOCKED_REASON_NONE);
9657         cellNetworkCallback.expect(BLOCKED_STATUS, mCellAgent, cb -> !cb.getBlocked());
9658         detailedCallback.expect(BLOCKED_STATUS_INT, mCellAgent,
9659                 cb -> cb.getReason() == BLOCKED_REASON_NONE);
9660         assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetwork());
9661         assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
9662         assertNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
9663         assertExtraInfoFromCmPresent(mCellAgent);
9664 
9665         setBlockedReasonChanged(BLOCKED_REASON_NONE);
9666         cellNetworkCallback.assertNoCallback();
9667         detailedCallback.assertNoCallback();
9668 
9669         // Restrict background data. Networking is not blocked because the network is unmetered.
9670         setBlockedReasonChanged(BLOCKED_METERED_REASON_DATA_SAVER);
9671         cellNetworkCallback.expect(BLOCKED_STATUS, mCellAgent, cb -> cb.getBlocked());
9672         detailedCallback.expect(BLOCKED_STATUS_INT, mCellAgent,
9673                 cb -> cb.getReason() == BLOCKED_METERED_REASON_DATA_SAVER);
9674         assertNull(mCm.getActiveNetwork());
9675         assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
9676         assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
9677         assertExtraInfoFromCmBlocked(mCellAgent);
9678         setBlockedReasonChanged(BLOCKED_METERED_REASON_DATA_SAVER);
9679         cellNetworkCallback.assertNoCallback();
9680 
9681         setBlockedReasonChanged(BLOCKED_REASON_NONE);
9682         cellNetworkCallback.expect(BLOCKED_STATUS, mCellAgent, cb -> !cb.getBlocked());
9683         detailedCallback.expect(BLOCKED_STATUS_INT, mCellAgent,
9684                 cb -> cb.getReason() == BLOCKED_REASON_NONE);
9685         assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
9686         assertNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
9687         assertExtraInfoFromCmPresent(mCellAgent);
9688 
9689         setBlockedReasonChanged(BLOCKED_REASON_NONE);
9690         cellNetworkCallback.assertNoCallback();
9691         detailedCallback.assertNoCallback();
9692         assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetwork());
9693         assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
9694         assertNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
9695         assertExtraInfoFromCmPresent(mCellAgent);
9696 
9697         mCm.unregisterNetworkCallback(cellNetworkCallback);
9698     }
9699 
9700     @Test
9701     public void testNetworkBlockedStatusBeforeAndAfterConnect() throws Exception {
9702         final TestNetworkCallback defaultCallback = new TestNetworkCallback();
9703         mCm.registerDefaultNetworkCallback(defaultCallback);
9704         mockUidNetworkingBlocked();
9705 
9706         // No Networkcallbacks invoked before any network is active.
9707         setBlockedReasonChanged(BLOCKED_REASON_BATTERY_SAVER);
9708         setBlockedReasonChanged(BLOCKED_REASON_NONE);
9709         setBlockedReasonChanged(BLOCKED_METERED_REASON_DATA_SAVER);
9710         defaultCallback.assertNoCallback();
9711 
9712         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
9713         mCellAgent.connect(true);
9714         defaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mCellAgent);
9715         defaultCallback.expectCaps(mCellAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
9716 
9717         // Allow to use the network after switching to NOT_METERED network.
9718         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
9719         mWiFiAgent.addCapability(NET_CAPABILITY_NOT_METERED);
9720         mWiFiAgent.connect(true);
9721         defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiAgent);
9722 
9723         // Switch to METERED network. Restrict the use of the network.
9724         mWiFiAgent.disconnect();
9725         defaultCallback.expect(LOST, mWiFiAgent);
9726         defaultCallback.expectAvailableCallbacksValidatedAndBlocked(mCellAgent);
9727 
9728         // Network becomes NOT_METERED.
9729         mCellAgent.addCapability(NET_CAPABILITY_NOT_METERED);
9730         defaultCallback.expectCaps(mCellAgent, c -> c.hasCapability(NET_CAPABILITY_NOT_METERED));
9731         defaultCallback.expect(BLOCKED_STATUS, mCellAgent, cb -> !cb.getBlocked());
9732 
9733         // Verify there's no Networkcallbacks invoked after data saver on/off.
9734         setBlockedReasonChanged(BLOCKED_METERED_REASON_DATA_SAVER);
9735         setBlockedReasonChanged(BLOCKED_REASON_NONE);
9736         defaultCallback.assertNoCallback();
9737 
9738         mCellAgent.disconnect();
9739         defaultCallback.expect(LOST, mCellAgent);
9740         defaultCallback.assertNoCallback();
9741 
9742         mCm.unregisterNetworkCallback(defaultCallback);
9743     }
9744 
9745     private void expectNetworkRejectNonSecureVpn(InOrder inOrder, boolean add,
9746             UidRangeParcel... expected) throws Exception {
9747         inOrder.verify(mMockNetd).networkRejectNonSecureVpn(eq(add), aryEq(expected));
9748     }
9749 
9750     private void checkNetworkInfo(NetworkInfo ni, int type, DetailedState state) {
9751         assertNotNull(ni);
9752         assertEquals(type, ni.getType());
9753         assertEquals(ConnectivityManager.getNetworkTypeName(type), state, ni.getDetailedState());
9754         if (state == DetailedState.CONNECTED || state == DetailedState.SUSPENDED) {
9755             assertNotNull(ni.getExtraInfo());
9756         } else {
9757             // Technically speaking, a network that's in CONNECTING state will generally have a
9758             // non-null extraInfo. This doesn't actually happen in this test because it never calls
9759             // a legacy API while a network is connecting. When a network is in CONNECTING state
9760             // because of legacy lockdown VPN, its extraInfo is always null.
9761             assertNull(ni.getExtraInfo());
9762         }
9763     }
9764 
9765     private void assertActiveNetworkInfo(int type, DetailedState state) {
9766         checkNetworkInfo(mCm.getActiveNetworkInfo(), type, state);
9767     }
9768     private void assertNetworkInfo(int type, DetailedState state) {
9769         checkNetworkInfo(mCm.getNetworkInfo(type), type, state);
9770     }
9771 
9772     private void assertExtraInfoFromCm(TestNetworkAgentWrapper network, boolean present) {
9773         final NetworkInfo niForNetwork = mCm.getNetworkInfo(network.getNetwork());
9774         final NetworkInfo niForType = mCm.getNetworkInfo(network.getLegacyType());
9775         if (present) {
9776             assertEquals(network.getExtraInfo(), niForNetwork.getExtraInfo());
9777             assertEquals(network.getExtraInfo(), niForType.getExtraInfo());
9778         } else {
9779             assertNull(niForNetwork.getExtraInfo());
9780             assertNull(niForType.getExtraInfo());
9781         }
9782     }
9783 
9784     private void assertExtraInfoFromCmBlocked(TestNetworkAgentWrapper network) {
9785         assertExtraInfoFromCm(network, false);
9786     }
9787 
9788     private void assertExtraInfoFromCmPresent(TestNetworkAgentWrapper network) {
9789         assertExtraInfoFromCm(network, true);
9790     }
9791 
9792     // Checks that each of the |agents| receive a blocked status change callback with the specified
9793     // |blocked| value, in any order. This is needed because when an event affects multiple
9794     // networks, ConnectivityService does not guarantee the order in which callbacks are fired.
9795     private void assertBlockedCallbackInAnyOrder(TestNetworkCallback callback, boolean blocked,
9796             TestNetworkAgentWrapper... agents) {
9797         final List<Network> expectedNetworks = asList(agents).stream()
9798                 .map((agent) -> agent.getNetwork())
9799                 .collect(Collectors.toList());
9800 
9801         // Expect exactly one blocked callback for each agent.
9802         for (int i = 0; i < agents.length; i++) {
9803             final CallbackEntry e = callback.expect(BLOCKED_STATUS, TIMEOUT_MS,
9804                     c -> c.getBlocked() == blocked);
9805             final Network network = e.getNetwork();
9806             assertTrue("Received unexpected blocked callback for network " + network,
9807                     expectedNetworks.remove(network));
9808         }
9809     }
9810 
9811     @Test
9812     public void testNetworkBlockedStatusAlwaysOnVpn() throws Exception {
9813         mServiceContext.setPermission(
9814                 Manifest.permission.CONTROL_ALWAYS_ON_VPN, PERMISSION_GRANTED);
9815         mServiceContext.setPermission(
9816                 Manifest.permission.CONTROL_VPN, PERMISSION_GRANTED);
9817         mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_GRANTED);
9818 
9819         final TestNetworkCallback callback = new TestNetworkCallback();
9820         final NetworkRequest request = new NetworkRequest.Builder()
9821                 .removeCapability(NET_CAPABILITY_NOT_VPN)
9822                 .build();
9823         mCm.registerNetworkCallback(request, callback);
9824 
9825         final TestNetworkCallback defaultCallback = new TestNetworkCallback();
9826         mCm.registerDefaultNetworkCallback(defaultCallback);
9827 
9828         final TestNetworkCallback vpnUidCallback = new TestNetworkCallback();
9829         final NetworkRequest vpnUidRequest = new NetworkRequest.Builder().build();
9830         registerNetworkCallbackAsUid(vpnUidRequest, vpnUidCallback, VPN_UID);
9831 
9832         final TestNetworkCallback vpnUidDefaultCallback = new TestNetworkCallback();
9833         registerDefaultNetworkCallbackAsUid(vpnUidDefaultCallback, VPN_UID);
9834 
9835         final TestNetworkCallback vpnDefaultCallbackAsUid = new TestNetworkCallback();
9836         mCm.registerDefaultNetworkCallbackForUid(VPN_UID, vpnDefaultCallbackAsUid,
9837                 new Handler(ConnectivityThread.getInstanceLooper()));
9838 
9839         final int uid = Process.myUid();
9840         final ArrayList<String> allowList = new ArrayList<>();
9841         mMockVpn.setAlwaysOnPackage(ALWAYS_ON_PACKAGE, true /* lockdown */, allowList);
9842         waitForIdle();
9843 
9844         final Set<Integer> excludedUids = new ArraySet<Integer>();
9845         excludedUids.add(VPN_UID);
9846         if (mDeps.isAtLeastT()) {
9847             // On T onwards, the corresponding SDK sandbox UID should also be excluded
9848             excludedUids.add(toSdkSandboxUid(VPN_UID));
9849         }
9850         final UidRangeParcel[] uidRangeParcels = uidRangeParcelsExcludingUids(
9851                 excludedUids.toArray(new Integer[0]));
9852         InOrder inOrder = inOrder(mMockNetd);
9853         expectNetworkRejectNonSecureVpn(inOrder, true, uidRangeParcels);
9854 
9855         // Connect a network when lockdown is active, expect to see it blocked.
9856         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
9857         mWiFiAgent.connect(false /* validated */);
9858         callback.expectAvailableCallbacksUnvalidatedAndBlocked(mWiFiAgent);
9859         defaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mWiFiAgent);
9860         vpnUidCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
9861         vpnUidDefaultCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
9862         vpnDefaultCallbackAsUid.expectAvailableCallbacksUnvalidated(mWiFiAgent);
9863         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
9864         assertNull(mCm.getActiveNetwork());
9865         assertActiveNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED);
9866         // Mobile is BLOCKED even though it's not actually connected.
9867         assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
9868         assertNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED);
9869 
9870         // Disable lockdown, expect to see the network unblocked.
9871         mMockVpn.setAlwaysOnPackage(null, false /* lockdown */, allowList);
9872         callback.expect(BLOCKED_STATUS, mWiFiAgent, cb -> !cb.getBlocked());
9873         defaultCallback.expect(BLOCKED_STATUS, mWiFiAgent, cb -> !cb.getBlocked());
9874         vpnUidCallback.assertNoCallback();
9875         vpnUidDefaultCallback.assertNoCallback();
9876         vpnDefaultCallbackAsUid.assertNoCallback();
9877         expectNetworkRejectNonSecureVpn(inOrder, false, uidRangeParcels);
9878         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
9879         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetwork());
9880         assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
9881         assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED);
9882         assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
9883 
9884         // Add our UID to the allowlist and re-enable lockdown, expect network is not blocked.
9885         allowList.add(TEST_PACKAGE_NAME);
9886         mMockVpn.setAlwaysOnPackage(ALWAYS_ON_PACKAGE, true /* lockdown */, allowList);
9887         callback.assertNoCallback();
9888         defaultCallback.assertNoCallback();
9889         vpnUidCallback.assertNoCallback();
9890         vpnUidDefaultCallback.assertNoCallback();
9891         vpnDefaultCallbackAsUid.assertNoCallback();
9892 
9893         excludedUids.add(uid);
9894         if (mDeps.isAtLeastT()) {
9895             // On T onwards, the corresponding SDK sandbox UID should also be excluded
9896             excludedUids.add(toSdkSandboxUid(uid));
9897         }
9898         final UidRangeParcel[] uidRangeParcelsAlsoExcludingUs = uidRangeParcelsExcludingUids(
9899                 excludedUids.toArray(new Integer[0]));
9900         expectNetworkRejectNonSecureVpn(inOrder, true, uidRangeParcelsAlsoExcludingUs);
9901         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
9902         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetwork());
9903         assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
9904         assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED);
9905         assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
9906 
9907         // Connect a new network, expect it to be unblocked.
9908         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
9909         mCellAgent.connect(false /* validated */);
9910         callback.expectAvailableCallbacksUnvalidated(mCellAgent);
9911         defaultCallback.assertNoCallback();
9912         vpnUidCallback.expectAvailableCallbacksUnvalidated(mCellAgent);
9913         vpnUidDefaultCallback.assertNoCallback();
9914         vpnDefaultCallbackAsUid.assertNoCallback();
9915         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
9916         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetwork());
9917         assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
9918         // Cellular is DISCONNECTED because it's not the default and there are no requests for it.
9919         assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED);
9920         assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
9921 
9922         // Disable lockdown, remove our UID from the allowlist, and re-enable lockdown.
9923         // Everything should now be blocked.
9924         mMockVpn.setAlwaysOnPackage(null, false /* lockdown */, allowList);
9925         waitForIdle();
9926         expectNetworkRejectNonSecureVpn(inOrder, false, uidRangeParcelsAlsoExcludingUs);
9927         allowList.clear();
9928         mMockVpn.setAlwaysOnPackage(ALWAYS_ON_PACKAGE, true /* lockdown */, allowList);
9929         waitForIdle();
9930         expectNetworkRejectNonSecureVpn(inOrder, true, uidRangeParcels);
9931         defaultCallback.expect(BLOCKED_STATUS, mWiFiAgent, cb -> cb.getBlocked());
9932         assertBlockedCallbackInAnyOrder(callback, true, mWiFiAgent, mCellAgent);
9933         vpnUidCallback.assertNoCallback();
9934         vpnUidDefaultCallback.assertNoCallback();
9935         vpnDefaultCallbackAsUid.assertNoCallback();
9936         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
9937         assertNull(mCm.getActiveNetwork());
9938         assertActiveNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED);
9939         assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
9940         assertNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED);
9941 
9942         // Disable lockdown. Everything is unblocked.
9943         mMockVpn.setAlwaysOnPackage(null, false /* lockdown */, allowList);
9944         defaultCallback.expect(BLOCKED_STATUS, mWiFiAgent, cb -> !cb.getBlocked());
9945         assertBlockedCallbackInAnyOrder(callback, false, mWiFiAgent, mCellAgent);
9946         vpnUidCallback.assertNoCallback();
9947         vpnUidDefaultCallback.assertNoCallback();
9948         vpnDefaultCallbackAsUid.assertNoCallback();
9949         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
9950         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetwork());
9951         assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
9952         assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED);
9953         assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
9954 
9955         // Enable and disable an always-on VPN package without lockdown. Expect no changes.
9956         reset(mMockNetd);
9957         mMockVpn.setAlwaysOnPackage(ALWAYS_ON_PACKAGE, false /* lockdown */, allowList);
9958         inOrder.verify(mMockNetd, never()).networkRejectNonSecureVpn(anyBoolean(), any());
9959         callback.assertNoCallback();
9960         defaultCallback.assertNoCallback();
9961         vpnUidCallback.assertNoCallback();
9962         vpnUidDefaultCallback.assertNoCallback();
9963         vpnDefaultCallbackAsUid.assertNoCallback();
9964         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
9965         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetwork());
9966         assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
9967         assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED);
9968         assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
9969 
9970         mMockVpn.setAlwaysOnPackage(null, false /* lockdown */, allowList);
9971         inOrder.verify(mMockNetd, never()).networkRejectNonSecureVpn(anyBoolean(), any());
9972         callback.assertNoCallback();
9973         defaultCallback.assertNoCallback();
9974         vpnUidCallback.assertNoCallback();
9975         vpnUidDefaultCallback.assertNoCallback();
9976         vpnDefaultCallbackAsUid.assertNoCallback();
9977         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
9978         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetwork());
9979         assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
9980         assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED);
9981         assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
9982 
9983         // Enable lockdown and connect a VPN. The VPN is not blocked.
9984         mMockVpn.setAlwaysOnPackage(ALWAYS_ON_PACKAGE, true /* lockdown */, allowList);
9985         defaultCallback.expect(BLOCKED_STATUS, mWiFiAgent, cb -> cb.getBlocked());
9986         assertBlockedCallbackInAnyOrder(callback, true, mWiFiAgent, mCellAgent);
9987         vpnUidCallback.assertNoCallback();
9988         vpnUidDefaultCallback.assertNoCallback();
9989         vpnDefaultCallbackAsUid.assertNoCallback();
9990         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
9991         assertNull(mCm.getActiveNetwork());
9992         assertActiveNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED);
9993         assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
9994         assertNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED);
9995 
9996         mMockVpn.establishForMyUid();
9997         assertUidRangesUpdatedForMyUid(true);
9998         defaultCallback.expectAvailableThenValidatedCallbacks(mMockVpn);
9999         vpnUidCallback.assertNoCallback();  // vpnUidCallback has NOT_VPN capability.
10000         vpnUidDefaultCallback.assertNoCallback();  // VPN does not apply to VPN_UID
10001         vpnDefaultCallbackAsUid.assertNoCallback();
10002         assertEquals(mMockVpn.getNetwork(), mCm.getActiveNetwork());
10003         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
10004         assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
10005         assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED);
10006         assertNetworkInfo(TYPE_VPN, DetailedState.CONNECTED);
10007         assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
10008 
10009         mMockVpn.disconnect();
10010         defaultCallback.expect(LOST, mMockVpn);
10011         defaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mWiFiAgent);
10012         vpnUidCallback.assertNoCallback();
10013         vpnUidDefaultCallback.assertNoCallback();
10014         vpnDefaultCallbackAsUid.assertNoCallback();
10015         assertNull(mCm.getActiveNetwork());
10016 
10017         mCm.unregisterNetworkCallback(callback);
10018         mCm.unregisterNetworkCallback(defaultCallback);
10019         mCm.unregisterNetworkCallback(vpnUidCallback);
10020         mCm.unregisterNetworkCallback(vpnUidDefaultCallback);
10021         mCm.unregisterNetworkCallback(vpnDefaultCallbackAsUid);
10022     }
10023 
10024     @Test
10025     public void testVpnExcludesOwnUid() throws Exception {
10026         // required for registerDefaultNetworkCallbackForUid.
10027         mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_GRANTED);
10028 
10029         // Connect Wi-Fi.
10030         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
10031         mWiFiAgent.connect(true /* validated */);
10032 
10033         // Connect a VPN that excludes its UID from its UID ranges.
10034         final LinkProperties lp = new LinkProperties();
10035         lp.setInterfaceName(VPN_IFNAME);
10036         final int myUid = Process.myUid();
10037         final Set<UidRange> ranges = new ArraySet<>();
10038         ranges.add(new UidRange(0, myUid - 1));
10039         ranges.add(new UidRange(myUid + 1, UserHandle.PER_USER_RANGE - 1));
10040         mMockVpn.setUnderlyingNetworks(new Network[] { mWiFiAgent.getNetwork() });
10041         mMockVpn.establish(lp, myUid, ranges);
10042 
10043         // Wait for validation before registering callbacks.
10044         waitForIdle();
10045 
10046         final int otherUid = myUid + 1;
10047         final Handler h = new Handler(ConnectivityThread.getInstanceLooper());
10048         final TestNetworkCallback otherUidCb = new TestNetworkCallback();
10049         final TestNetworkCallback defaultCb = new TestNetworkCallback();
10050         final TestNetworkCallback perUidCb = new TestNetworkCallback();
10051         registerDefaultNetworkCallbackAsUid(otherUidCb, otherUid);
10052         mCm.registerDefaultNetworkCallback(defaultCb, h);
10053         doAsUid(Process.SYSTEM_UID,
10054                 () -> mCm.registerDefaultNetworkCallbackForUid(myUid, perUidCb, h));
10055 
10056         otherUidCb.expectAvailableCallbacksValidated(mMockVpn);
10057         // BUG (b/195265065): the default network for the VPN app is actually Wi-Fi, not the VPN.
10058         defaultCb.expectAvailableCallbacksValidated(mMockVpn);
10059         perUidCb.expectAvailableCallbacksValidated(mMockVpn);
10060         // getActiveNetwork is not affected by this bug.
10061         assertEquals(mMockVpn.getNetwork(), mCm.getActiveNetworkForUid(myUid + 1));
10062         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetwork());
10063         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetworkForUid(myUid));
10064 
10065         doAsUid(otherUid, () -> mCm.unregisterNetworkCallback(otherUidCb));
10066         mCm.unregisterNetworkCallback(defaultCb);
10067         doAsUid(Process.SYSTEM_UID, () -> mCm.unregisterNetworkCallback(perUidCb));
10068     }
10069 
10070     private VpnProfile setupLegacyLockdownVpn() {
10071         final String profileName = "testVpnProfile";
10072         final byte[] profileTag = profileName.getBytes(StandardCharsets.UTF_8);
10073         doReturn(profileTag).when(mVpnProfileStore).get(Credentials.LOCKDOWN_VPN);
10074 
10075         final VpnProfile profile = new VpnProfile(profileName);
10076         profile.name = "My VPN";
10077         profile.server = "192.0.2.1";
10078         profile.dnsServers = "8.8.8.8";
10079         profile.type = VpnProfile.TYPE_IPSEC_XAUTH_PSK;
10080         final byte[] encodedProfile = profile.encode();
10081         doReturn(encodedProfile).when(mVpnProfileStore).get(Credentials.VPN + profileName);
10082 
10083         return profile;
10084     }
10085 
10086     private void establishLegacyLockdownVpn(Network underlying) throws Exception {
10087         // The legacy lockdown VPN only supports userId 0, and must have an underlying network.
10088         assertNotNull(underlying);
10089         mMockVpn.setVpnType(VpnManager.TYPE_VPN_LEGACY);
10090         // The legacy lockdown VPN only supports userId 0.
10091         final Set<UidRange> ranges = Collections.singleton(PRIMARY_UIDRANGE);
10092         mMockVpn.registerAgent(ranges);
10093         mMockVpn.setUnderlyingNetworks(new Network[]{underlying});
10094         mMockVpn.connect(true);
10095     }
10096 
10097     @Test
10098     public void testLegacyLockdownVpn() throws Exception {
10099         mServiceContext.setPermission(
10100                 Manifest.permission.CONTROL_VPN, PERMISSION_GRANTED);
10101 
10102         final NetworkRequest request = new NetworkRequest.Builder().clearCapabilities().build();
10103         final TestNetworkCallback callback = new TestNetworkCallback();
10104         mCm.registerNetworkCallback(request, callback);
10105 
10106         final TestNetworkCallback defaultCallback = new TestNetworkCallback();
10107         mCm.registerDefaultNetworkCallback(defaultCallback);
10108 
10109         final TestNetworkCallback systemDefaultCallback = new TestNetworkCallback();
10110         mCm.registerSystemDefaultNetworkCallback(systemDefaultCallback,
10111                 new Handler(ConnectivityThread.getInstanceLooper()));
10112 
10113         // Pretend lockdown VPN was configured.
10114         final VpnProfile profile = setupLegacyLockdownVpn();
10115 
10116         // LockdownVpnTracker disables the Vpn teardown code and enables lockdown.
10117         // Check the VPN's state before it does so.
10118         assertTrue(mMockVpn.getEnableTeardown());
10119         assertFalse(mMockVpn.getLockdown());
10120 
10121         // VMSHandlerThread was used inside VpnManagerService and taken into LockDownVpnTracker.
10122         // VpnManagerService was decoupled from this test but this handlerThread is still required
10123         // in LockDownVpnTracker. Keep it until LockDownVpnTracker related verification is moved to
10124         // its own test.
10125         final HandlerThread VMSHandlerThread = new HandlerThread("TestVpnManagerService");
10126         VMSHandlerThread.start();
10127 
10128         // LockdownVpnTracker is created from VpnManagerService but VpnManagerService is decoupled
10129         // from ConnectivityServiceTest. Create it directly to simulate LockdownVpnTracker is
10130         // created.
10131         // TODO: move LockdownVpnTracker related tests to its own test.
10132         // Lockdown VPN disables teardown and enables lockdown.
10133         final LockdownVpnTracker lockdownVpnTracker = new LockdownVpnTracker(mServiceContext,
10134                 VMSHandlerThread.getThreadHandler(), mMockVpn, profile);
10135         lockdownVpnTracker.init();
10136         assertFalse(mMockVpn.getEnableTeardown());
10137         assertTrue(mMockVpn.getLockdown());
10138 
10139         // Bring up a network.
10140         // Expect nothing to happen because the network does not have an IPv4 default route: legacy
10141         // VPN only supports IPv4.
10142         final LinkProperties cellLp = new LinkProperties();
10143         cellLp.setInterfaceName("rmnet0");
10144         cellLp.addLinkAddress(new LinkAddress("2001:db8::1/64"));
10145         cellLp.addRoute(new RouteInfo(new IpPrefix("::/0"), null, "rmnet0"));
10146         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
10147         mCellAgent.connect(false /* validated */);
10148         callback.expectAvailableCallbacksUnvalidatedAndBlocked(mCellAgent);
10149         defaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mCellAgent);
10150         systemDefaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mCellAgent);
10151         waitForIdle();
10152         assertNull(mMockVpn.getAgent());
10153 
10154         // Add an IPv4 address. Ideally the VPN should start, but it doesn't because nothing calls
10155         // LockdownVpnTracker#handleStateChangedLocked. This is a bug.
10156         // TODO: consider fixing this.
10157         cellLp.addLinkAddress(new LinkAddress("192.0.2.2/25"));
10158         cellLp.addRoute(new RouteInfo(new IpPrefix("0.0.0.0/0"), null, "rmnet0"));
10159         mCellAgent.sendLinkProperties(cellLp);
10160         callback.expect(LINK_PROPERTIES_CHANGED, mCellAgent);
10161         defaultCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent);
10162         systemDefaultCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent);
10163         waitForIdle();
10164         assertNull(mMockVpn.getAgent());
10165 
10166         // Disconnect, then try again with a network that supports IPv4 at connection time.
10167         // Expect lockdown VPN to come up.
10168         ExpectedBroadcast b1 = expectConnectivityAction(TYPE_MOBILE, DetailedState.DISCONNECTED);
10169         mCellAgent.disconnect();
10170         callback.expect(LOST, mCellAgent);
10171         defaultCallback.expect(LOST, mCellAgent);
10172         systemDefaultCallback.expect(LOST, mCellAgent);
10173         b1.expectBroadcast();
10174 
10175         // When lockdown VPN is active, the NetworkInfo state in CONNECTIVITY_ACTION is overwritten
10176         // with the state of the VPN network. So expect a CONNECTING broadcast.
10177         b1 = expectConnectivityAction(TYPE_MOBILE, DetailedState.CONNECTING);
10178         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
10179         mCellAgent.connect(false /* validated */);
10180         callback.expectAvailableCallbacksUnvalidatedAndBlocked(mCellAgent);
10181         defaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mCellAgent);
10182         systemDefaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mCellAgent);
10183         b1.expectBroadcast();
10184         assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
10185         assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
10186         assertNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED);
10187         assertNetworkInfo(TYPE_VPN, DetailedState.BLOCKED);
10188         assertExtraInfoFromCmBlocked(mCellAgent);
10189 
10190         // TODO: it would be nice if we could simply rely on the production code here, and have
10191         // LockdownVpnTracker start the VPN, have the VPN code register its NetworkAgent with
10192         // ConnectivityService, etc. That would require duplicating a fair bit of code from the
10193         // Vpn tests around how to mock out LegacyVpnRunner. But even if we did that, this does not
10194         // work for at least two reasons:
10195         // 1. In this test, calling registerNetworkAgent does not actually result in an agent being
10196         //    registered. This is because nothing calls onNetworkMonitorCreated, which is what
10197         //    actually ends up causing handleRegisterNetworkAgent to be called. Code in this test
10198         //    that wants to register an agent must use TestNetworkAgentWrapper.
10199         // 2. Even if we exposed Vpn#agentConnect to the test, and made MockVpn#agentConnect call
10200         //    the TestNetworkAgentWrapper code, this would deadlock because the
10201         //    TestNetworkAgentWrapper code cannot be called on the handler thread since it calls
10202         //    waitForIdle().
10203         mMockVpn.expectStartLegacyVpnRunner();
10204         b1 = expectConnectivityAction(TYPE_VPN, DetailedState.CONNECTED);
10205         ExpectedBroadcast b2 = expectConnectivityAction(TYPE_MOBILE, DetailedState.CONNECTED);
10206         establishLegacyLockdownVpn(mCellAgent.getNetwork());
10207         callback.expectAvailableThenValidatedCallbacks(mMockVpn);
10208         defaultCallback.expectAvailableThenValidatedCallbacks(mMockVpn);
10209         systemDefaultCallback.assertNoCallback();
10210         NetworkCapabilities vpnNc = mCm.getNetworkCapabilities(mMockVpn.getNetwork());
10211         b1.expectBroadcast();
10212         b2.expectBroadcast();
10213         assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
10214         assertNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
10215         assertNetworkInfo(TYPE_WIFI, DetailedState.DISCONNECTED);
10216         assertNetworkInfo(TYPE_VPN, DetailedState.CONNECTED);
10217         assertExtraInfoFromCmPresent(mCellAgent);
10218         assertTrue(vpnNc.hasTransport(TRANSPORT_VPN));
10219         assertTrue(vpnNc.hasTransport(TRANSPORT_CELLULAR));
10220         assertFalse(vpnNc.hasTransport(TRANSPORT_WIFI));
10221         assertFalse(vpnNc.hasCapability(NET_CAPABILITY_NOT_METERED));
10222         assertVpnTransportInfo(vpnNc, VpnManager.TYPE_VPN_LEGACY);
10223 
10224         // Switch default network from cell to wifi. Expect VPN to disconnect and reconnect.
10225         final LinkProperties wifiLp = new LinkProperties();
10226         wifiLp.setInterfaceName("wlan0");
10227         wifiLp.addLinkAddress(new LinkAddress("192.0.2.163/25"));
10228         wifiLp.addRoute(new RouteInfo(new IpPrefix("0.0.0.0/0"), null, "wlan0"));
10229         final NetworkCapabilities wifiNc = new NetworkCapabilities();
10230         wifiNc.addTransportType(TRANSPORT_WIFI);
10231         wifiNc.addCapability(NET_CAPABILITY_NOT_METERED);
10232         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp, wifiNc);
10233 
10234         b1 = expectConnectivityAction(TYPE_MOBILE, DetailedState.DISCONNECTED);
10235         // Wifi is CONNECTING because the VPN isn't up yet.
10236         b2 = expectConnectivityAction(TYPE_WIFI, DetailedState.CONNECTING);
10237         ExpectedBroadcast b3 = expectConnectivityAction(TYPE_VPN, DetailedState.DISCONNECTED);
10238         mWiFiAgent.connect(false /* validated */);
10239         b1.expectBroadcast();
10240         b2.expectBroadcast();
10241         b3.expectBroadcast();
10242         mMockVpn.expectStopVpnRunnerPrivileged();
10243         mMockVpn.expectStartLegacyVpnRunner();
10244 
10245         // TODO: why is wifi not blocked? Is it because when this callback is sent, the VPN is still
10246         // connected, so the network is not considered blocked by the lockdown UID ranges? But the
10247         // fact that a VPN is connected should only result in the VPN itself being unblocked, not
10248         // any other network. Bug in isUidBlockedByVpn?
10249         callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
10250         callback.expect(LOST, mMockVpn);
10251         defaultCallback.expect(LOST, mMockVpn);
10252         defaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mWiFiAgent);
10253         systemDefaultCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
10254 
10255         // While the VPN is reconnecting on the new network, everything is blocked.
10256         assertActiveNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED);
10257         assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
10258         assertNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED);
10259         assertNetworkInfo(TYPE_VPN, DetailedState.BLOCKED);
10260         assertExtraInfoFromCmBlocked(mWiFiAgent);
10261 
10262         // The VPN comes up again on wifi.
10263         b1 = expectConnectivityAction(TYPE_VPN, DetailedState.CONNECTED);
10264         b2 = expectConnectivityAction(TYPE_WIFI, DetailedState.CONNECTED);
10265         establishLegacyLockdownVpn(mWiFiAgent.getNetwork());
10266         callback.expectAvailableThenValidatedCallbacks(mMockVpn);
10267         defaultCallback.expectAvailableThenValidatedCallbacks(mMockVpn);
10268         systemDefaultCallback.assertNoCallback();
10269         b1.expectBroadcast();
10270         b2.expectBroadcast();
10271         assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
10272         assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED);
10273         assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
10274         assertNetworkInfo(TYPE_VPN, DetailedState.CONNECTED);
10275         assertExtraInfoFromCmPresent(mWiFiAgent);
10276         vpnNc = mCm.getNetworkCapabilities(mMockVpn.getNetwork());
10277         assertTrue(vpnNc.hasTransport(TRANSPORT_VPN));
10278         assertTrue(vpnNc.hasTransport(TRANSPORT_WIFI));
10279         assertFalse(vpnNc.hasTransport(TRANSPORT_CELLULAR));
10280         assertTrue(vpnNc.hasCapability(NET_CAPABILITY_NOT_METERED));
10281 
10282         // Disconnect cell. Nothing much happens since it's not the default network.
10283         mCellAgent.disconnect();
10284         callback.expect(LOST, mCellAgent);
10285         defaultCallback.assertNoCallback();
10286         systemDefaultCallback.assertNoCallback();
10287 
10288         assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
10289         assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED);
10290         assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
10291         assertNetworkInfo(TYPE_VPN, DetailedState.CONNECTED);
10292         assertExtraInfoFromCmPresent(mWiFiAgent);
10293 
10294         b1 = expectConnectivityAction(TYPE_WIFI, DetailedState.DISCONNECTED);
10295         b2 = expectConnectivityAction(TYPE_VPN, DetailedState.DISCONNECTED);
10296         mWiFiAgent.disconnect();
10297         callback.expect(LOST, mWiFiAgent);
10298         systemDefaultCallback.expect(LOST, mWiFiAgent);
10299         b1.expectBroadcast();
10300         callback.expectCaps(mMockVpn, c -> !c.hasTransport(TRANSPORT_WIFI));
10301         mMockVpn.expectStopVpnRunnerPrivileged();
10302         callback.expect(LOST, mMockVpn);
10303         b2.expectBroadcast();
10304 
10305         VMSHandlerThread.quitSafely();
10306         VMSHandlerThread.join();
10307     }
10308 
10309     @Test @IgnoreUpTo(Build.VERSION_CODES.S_V2)
10310     public void testLockdownSetFirewallUidRule() throws Exception {
10311         final Set<Range<Integer>> lockdownRange = UidRange.toIntRanges(Set.of(PRIMARY_UIDRANGE));
10312         // Enable Lockdown
10313         mCm.setRequireVpnForUids(true /* requireVpn */, lockdownRange);
10314         waitForIdle();
10315 
10316         // Lockdown rule is set to apps uids
10317         verify(mBpfNetMaps, times(3)).updateUidLockdownRule(anyInt(), eq(true) /* add */);
10318         verify(mBpfNetMaps).updateUidLockdownRule(APP1_UID, true /* add */);
10319         verify(mBpfNetMaps).updateUidLockdownRule(APP2_UID, true /* add */);
10320         verify(mBpfNetMaps).updateUidLockdownRule(VPN_UID, true /* add */);
10321 
10322         reset(mBpfNetMaps);
10323 
10324         // Disable lockdown
10325         mCm.setRequireVpnForUids(false /* requireVPN */, lockdownRange);
10326         waitForIdle();
10327 
10328         // Lockdown rule is removed from apps uids
10329         verify(mBpfNetMaps, times(3)).updateUidLockdownRule(anyInt(), eq(false) /* add */);
10330         verify(mBpfNetMaps).updateUidLockdownRule(APP1_UID, false /* add */);
10331         verify(mBpfNetMaps).updateUidLockdownRule(APP2_UID, false /* add */);
10332         verify(mBpfNetMaps).updateUidLockdownRule(VPN_UID, false /* add */);
10333 
10334         // Interface rules are not changed by Lockdown mode enable/disable
10335         verify(mBpfNetMaps, never()).addUidInterfaceRules(any(), any());
10336         verify(mBpfNetMaps, never()).removeUidInterfaceRules(any());
10337     }
10338 
10339     private void doTestSetUidFirewallRule(final int chain, final int defaultRule) {
10340         final int uid = 1001;
10341         mCm.setUidFirewallRule(chain, uid, FIREWALL_RULE_ALLOW);
10342         verify(mBpfNetMaps).setUidRule(chain, uid, FIREWALL_RULE_ALLOW);
10343         reset(mBpfNetMaps);
10344 
10345         mCm.setUidFirewallRule(chain, uid, FIREWALL_RULE_DENY);
10346         verify(mBpfNetMaps).setUidRule(chain, uid, FIREWALL_RULE_DENY);
10347         reset(mBpfNetMaps);
10348 
10349         mCm.setUidFirewallRule(chain, uid, FIREWALL_RULE_DEFAULT);
10350         verify(mBpfNetMaps).setUidRule(chain, uid, defaultRule);
10351         reset(mBpfNetMaps);
10352     }
10353 
10354     @Test @IgnoreUpTo(SC_V2)
10355     public void testSetUidFirewallRule() throws Exception {
10356         doTestSetUidFirewallRule(FIREWALL_CHAIN_DOZABLE, FIREWALL_RULE_DENY);
10357         doTestSetUidFirewallRule(FIREWALL_CHAIN_STANDBY, FIREWALL_RULE_ALLOW);
10358         doTestSetUidFirewallRule(FIREWALL_CHAIN_POWERSAVE, FIREWALL_RULE_DENY);
10359         doTestSetUidFirewallRule(FIREWALL_CHAIN_RESTRICTED, FIREWALL_RULE_DENY);
10360         doTestSetUidFirewallRule(FIREWALL_CHAIN_LOW_POWER_STANDBY, FIREWALL_RULE_DENY);
10361         doTestSetUidFirewallRule(FIREWALL_CHAIN_OEM_DENY_1, FIREWALL_RULE_ALLOW);
10362         doTestSetUidFirewallRule(FIREWALL_CHAIN_OEM_DENY_2, FIREWALL_RULE_ALLOW);
10363         doTestSetUidFirewallRule(FIREWALL_CHAIN_OEM_DENY_3, FIREWALL_RULE_ALLOW);
10364     }
10365 
10366     @Test @IgnoreUpTo(SC_V2)
10367     public void testSetFirewallChainEnabled() throws Exception {
10368         final List<Integer> firewallChains = Arrays.asList(
10369                 FIREWALL_CHAIN_DOZABLE,
10370                 FIREWALL_CHAIN_STANDBY,
10371                 FIREWALL_CHAIN_POWERSAVE,
10372                 FIREWALL_CHAIN_RESTRICTED,
10373                 FIREWALL_CHAIN_LOW_POWER_STANDBY,
10374                 FIREWALL_CHAIN_OEM_DENY_1,
10375                 FIREWALL_CHAIN_OEM_DENY_2,
10376                 FIREWALL_CHAIN_OEM_DENY_3);
10377         for (final int chain: firewallChains) {
10378             mCm.setFirewallChainEnabled(chain, true /* enabled */);
10379             verify(mBpfNetMaps).setChildChain(chain, true /* enable */);
10380             reset(mBpfNetMaps);
10381 
10382             mCm.setFirewallChainEnabled(chain, false /* enabled */);
10383             verify(mBpfNetMaps).setChildChain(chain, false /* enable */);
10384             reset(mBpfNetMaps);
10385         }
10386     }
10387 
10388     private void doTestSetFirewallChainEnabledCloseSocket(final int chain,
10389             final boolean isAllowList) throws Exception {
10390         reset(mDestroySocketsWrapper);
10391 
10392         mCm.setFirewallChainEnabled(chain, true /* enabled */);
10393         final Set<Integer> uids =
10394                 new ArraySet<>(List.of(TEST_PACKAGE_UID, TEST_PACKAGE_UID2));
10395         if (isAllowList) {
10396             final Set<Range<Integer>> range = new ArraySet<>(
10397                     List.of(new Range<>(Process.FIRST_APPLICATION_UID, Integer.MAX_VALUE)));
10398             verify(mDestroySocketsWrapper).destroyLiveTcpSockets(range, uids);
10399         } else {
10400             verify(mDestroySocketsWrapper).destroyLiveTcpSocketsByOwnerUids(uids);
10401         }
10402 
10403         mCm.setFirewallChainEnabled(chain, false /* enabled */);
10404         verifyNoMoreInteractions(mDestroySocketsWrapper);
10405     }
10406 
10407     @Test @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
10408     public void testSetFirewallChainEnabledCloseSocket() throws Exception {
10409         doReturn(new ArraySet<>(Arrays.asList(TEST_PACKAGE_UID, TEST_PACKAGE_UID2)))
10410                 .when(mBpfNetMaps)
10411                 .getUidsWithDenyRuleOnDenyListChain(anyInt());
10412         doReturn(new ArraySet<>(Arrays.asList(TEST_PACKAGE_UID, TEST_PACKAGE_UID2)))
10413                 .when(mBpfNetMaps)
10414                 .getUidsWithAllowRuleOnAllowListChain(anyInt());
10415 
10416         final boolean allowlist = true;
10417         final boolean denylist = false;
10418 
10419         doReturn(true).when(mBpfNetMaps).isFirewallAllowList(anyInt());
10420         doTestSetFirewallChainEnabledCloseSocket(FIREWALL_CHAIN_DOZABLE, allowlist);
10421         doTestSetFirewallChainEnabledCloseSocket(FIREWALL_CHAIN_POWERSAVE, allowlist);
10422         doTestSetFirewallChainEnabledCloseSocket(FIREWALL_CHAIN_RESTRICTED, allowlist);
10423         doTestSetFirewallChainEnabledCloseSocket(FIREWALL_CHAIN_LOW_POWER_STANDBY, allowlist);
10424 
10425         doReturn(false).when(mBpfNetMaps).isFirewallAllowList(anyInt());
10426         doTestSetFirewallChainEnabledCloseSocket(FIREWALL_CHAIN_STANDBY, denylist);
10427         doTestSetFirewallChainEnabledCloseSocket(FIREWALL_CHAIN_OEM_DENY_1, denylist);
10428         doTestSetFirewallChainEnabledCloseSocket(FIREWALL_CHAIN_OEM_DENY_2, denylist);
10429         doTestSetFirewallChainEnabledCloseSocket(FIREWALL_CHAIN_OEM_DENY_3, denylist);
10430     }
10431 
10432     private void doTestReplaceFirewallChain(final int chain) {
10433         final int[] uids = new int[] {1001, 1002};
10434         mCm.replaceFirewallChain(chain, uids);
10435         verify(mBpfNetMaps).replaceUidChain(chain, uids);
10436         reset(mBpfNetMaps);
10437     }
10438 
10439     @Test @IgnoreUpTo(SC_V2)
10440     public void testReplaceFirewallChain() {
10441         doTestReplaceFirewallChain(FIREWALL_CHAIN_DOZABLE);
10442         doTestReplaceFirewallChain(FIREWALL_CHAIN_STANDBY);
10443         doTestReplaceFirewallChain(FIREWALL_CHAIN_POWERSAVE);
10444         doTestReplaceFirewallChain(FIREWALL_CHAIN_RESTRICTED);
10445         doTestReplaceFirewallChain(FIREWALL_CHAIN_LOW_POWER_STANDBY);
10446         doTestReplaceFirewallChain(FIREWALL_CHAIN_OEM_DENY_1);
10447         doTestReplaceFirewallChain(FIREWALL_CHAIN_OEM_DENY_2);
10448         doTestReplaceFirewallChain(FIREWALL_CHAIN_OEM_DENY_3);
10449     }
10450 
10451     @Test @IgnoreUpTo(SC_V2)
10452     public void testInvalidFirewallChain() throws Exception {
10453         final int uid = 1001;
10454         final Class<IllegalArgumentException> expected = IllegalArgumentException.class;
10455         assertThrows(expected,
10456                 () -> mCm.setUidFirewallRule(-1 /* chain */, uid, FIREWALL_RULE_ALLOW));
10457         assertThrows(expected,
10458                 () -> mCm.setUidFirewallRule(100 /* chain */, uid, FIREWALL_RULE_ALLOW));
10459     }
10460 
10461     @Test @IgnoreUpTo(SC_V2)
10462     public void testInvalidFirewallRule() throws Exception {
10463         final Class<IllegalArgumentException> expected = IllegalArgumentException.class;
10464         assertThrows(expected,
10465                 () -> mCm.setUidFirewallRule(FIREWALL_CHAIN_DOZABLE,
10466                         1001 /* uid */, -1 /* rule */));
10467         assertThrows(expected,
10468                 () -> mCm.setUidFirewallRule(FIREWALL_CHAIN_DOZABLE,
10469                         1001 /* uid */, 100 /* rule */));
10470     }
10471 
10472     /**
10473      * Test mutable and requestable network capabilities such as
10474      * {@link NetworkCapabilities#NET_CAPABILITY_TRUSTED} and
10475      * {@link NetworkCapabilities#NET_CAPABILITY_NOT_VCN_MANAGED}. Verify that the
10476      * {@code ConnectivityService} re-assign the networks accordingly.
10477      */
10478     @Test
10479     public final void testLoseMutableAndRequestableCaps() throws Exception {
10480         final int[] testCaps = new int [] {
10481                 NET_CAPABILITY_TRUSTED,
10482                 NET_CAPABILITY_NOT_VCN_MANAGED
10483         };
10484         for (final int testCap : testCaps) {
10485             // Create requests with and without the testing capability.
10486             final TestNetworkCallback callbackWithCap = new TestNetworkCallback();
10487             final TestNetworkCallback callbackWithoutCap = new TestNetworkCallback();
10488             mCm.requestNetwork(new NetworkRequest.Builder().addCapability(testCap).build(),
10489                     callbackWithCap);
10490             mCm.requestNetwork(new NetworkRequest.Builder().removeCapability(testCap).build(),
10491                     callbackWithoutCap);
10492 
10493             // Setup networks with testing capability and verify the default network changes.
10494             mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
10495             mCellAgent.addCapability(testCap);
10496             mCellAgent.connect(true);
10497             callbackWithCap.expectAvailableThenValidatedCallbacks(mCellAgent);
10498             callbackWithoutCap.expectAvailableThenValidatedCallbacks(mCellAgent);
10499             verify(mMockNetd).networkSetDefault(eq(mCellAgent.getNetwork().netId));
10500             reset(mMockNetd);
10501 
10502             mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
10503             mWiFiAgent.addCapability(testCap);
10504             mWiFiAgent.connect(true);
10505             callbackWithCap.expectAvailableDoubleValidatedCallbacks(mWiFiAgent);
10506             callbackWithoutCap.expectAvailableDoubleValidatedCallbacks(mWiFiAgent);
10507             verify(mMockNetd).networkSetDefault(eq(mWiFiAgent.getNetwork().netId));
10508             reset(mMockNetd);
10509 
10510             // Remove the testing capability on wifi, verify the callback and default network
10511             // changes back to cellular.
10512             mWiFiAgent.removeCapability(testCap);
10513             callbackWithCap.expectAvailableCallbacksValidated(mCellAgent);
10514             callbackWithoutCap.expectCaps(mWiFiAgent, c -> !c.hasCapability(testCap));
10515             verify(mMockNetd).networkSetDefault(eq(mCellAgent.getNetwork().netId));
10516             reset(mMockNetd);
10517 
10518             mCellAgent.removeCapability(testCap);
10519             callbackWithCap.expect(LOST, mCellAgent);
10520             callbackWithoutCap.assertNoCallback();
10521             verify(mMockNetd).networkClearDefault();
10522 
10523             mCm.unregisterNetworkCallback(callbackWithCap);
10524             mCm.unregisterNetworkCallback(callbackWithoutCap);
10525         }
10526     }
10527 
10528     @Test
10529     public final void testBatteryStatsNetworkType() throws Exception {
10530         final LinkProperties cellLp = new LinkProperties();
10531         cellLp.setInterfaceName("cell0");
10532         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
10533         mCellAgent.connect(true);
10534         waitForIdle();
10535         final ArrayTrackRecord<ReportedInterfaces>.ReadHead readHead =
10536                 mDeps.mReportedInterfaceHistory.newReadHead();
10537         assertNotNull(readHead.poll(TIMEOUT_MS, ri -> ri.contentEquals(mServiceContext,
10538                 cellLp.getInterfaceName(),
10539                 new int[] { TRANSPORT_CELLULAR })));
10540 
10541         final LinkProperties wifiLp = new LinkProperties();
10542         wifiLp.setInterfaceName("wifi0");
10543         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp);
10544         mWiFiAgent.connect(true);
10545         waitForIdle();
10546         assertNotNull(readHead.poll(TIMEOUT_MS, ri -> ri.contentEquals(mServiceContext,
10547                 wifiLp.getInterfaceName(),
10548                 new int[] { TRANSPORT_WIFI })));
10549 
10550         mCellAgent.disconnect();
10551         mWiFiAgent.disconnect();
10552 
10553         cellLp.setInterfaceName("wifi0");
10554         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
10555         mCellAgent.connect(true);
10556         waitForIdle();
10557         assertNotNull(readHead.poll(TIMEOUT_MS, ri -> ri.contentEquals(mServiceContext,
10558                 cellLp.getInterfaceName(),
10559                 new int[] { TRANSPORT_CELLULAR })));
10560         mCellAgent.disconnect();
10561     }
10562 
10563     /**
10564      * Make simulated InterfaceConfigParcel for Nat464Xlat to query clat lower layer info.
10565      */
10566     private InterfaceConfigurationParcel getClatInterfaceConfigParcel(LinkAddress la) {
10567         final InterfaceConfigurationParcel cfg = new InterfaceConfigurationParcel();
10568         cfg.hwAddr = "11:22:33:44:55:66";
10569         cfg.ipv4Addr = la.getAddress().getHostAddress();
10570         cfg.prefixLength = la.getPrefixLength();
10571         return cfg;
10572     }
10573 
10574     /**
10575      * Make expected stack link properties, copied from Nat464Xlat.
10576      */
10577     private LinkProperties makeClatLinkProperties(LinkAddress la) {
10578         LinkAddress clatAddress = la;
10579         LinkProperties stacked = new LinkProperties();
10580         stacked.setInterfaceName(CLAT_MOBILE_IFNAME);
10581         RouteInfo ipv4Default = new RouteInfo(
10582                 new LinkAddress(Inet4Address.ANY, 0),
10583                 clatAddress.getAddress(), CLAT_MOBILE_IFNAME);
10584         stacked.addRoute(ipv4Default);
10585         stacked.addLinkAddress(clatAddress);
10586         return stacked;
10587     }
10588 
10589     private Nat64PrefixEventParcel makeNat64PrefixEvent(final int netId, final int prefixOperation,
10590             final String prefixAddress, final int prefixLength) {
10591         final Nat64PrefixEventParcel event = new Nat64PrefixEventParcel();
10592         event.netId = netId;
10593         event.prefixOperation = prefixOperation;
10594         event.prefixAddress = prefixAddress;
10595         event.prefixLength = prefixLength;
10596         return event;
10597     }
10598 
10599     private void verifyWakeupModifyInterface(String iface, boolean add) throws RemoteException {
10600         if (add) {
10601             verify(mMockNetd).wakeupAddInterface(eq(iface), anyString(), anyInt(),
10602                     anyInt());
10603         } else {
10604             verify(mMockNetd).wakeupDelInterface(eq(iface), anyString(), anyInt(),
10605                     anyInt());
10606         }
10607     }
10608 
10609     private <T> T verifyWithOrder(@Nullable InOrder inOrder, @NonNull T t) {
10610         if (inOrder != null) {
10611             return inOrder.verify(t);
10612         } else {
10613             // times(1) for consistency with the above. InOrder#verify always implies times(1).
10614             return verify(t, times(1));
10615         }
10616     }
10617 
10618     private <T> T verifyNeverWithOrder(@Nullable InOrder inOrder, @NonNull T t) {
10619         if (inOrder != null) {
10620             return inOrder.verify(t, never());
10621         } else {
10622             return verify(t, never());
10623         }
10624     }
10625 
10626     private void verifyClatdStart(@Nullable InOrder inOrder, @NonNull String iface, int netId,
10627             @NonNull String nat64Prefix) throws Exception {
10628         if (mDeps.isAtLeastT()) {
10629             verifyWithOrder(inOrder, mClatCoordinator)
10630                 .clatStart(eq(iface), eq(netId), eq(new IpPrefix(nat64Prefix)));
10631         } else {
10632             verifyWithOrder(inOrder, mMockNetd).clatdStart(eq(iface), eq(nat64Prefix));
10633         }
10634     }
10635 
10636     private void verifyNeverClatdStart(@Nullable InOrder inOrder, @NonNull String iface)
10637             throws Exception {
10638         if (mDeps.isAtLeastT()) {
10639             verifyNeverWithOrder(inOrder, mClatCoordinator).clatStart(eq(iface), anyInt(), any());
10640         } else {
10641             verifyNeverWithOrder(inOrder, mMockNetd).clatdStart(eq(iface), anyString());
10642         }
10643     }
10644 
10645     private void verifyClatdStop(@Nullable InOrder inOrder, @NonNull String iface)
10646             throws Exception {
10647         if (mDeps.isAtLeastT()) {
10648             verifyWithOrder(inOrder, mClatCoordinator).clatStop();
10649         } else {
10650             verifyWithOrder(inOrder, mMockNetd).clatdStop(eq(iface));
10651         }
10652     }
10653 
10654     private void verifyNeverClatdStop(@Nullable InOrder inOrder, @NonNull String iface)
10655             throws Exception {
10656         if (mDeps.isAtLeastT()) {
10657             verifyNeverWithOrder(inOrder, mClatCoordinator).clatStop();
10658         } else {
10659             verifyNeverWithOrder(inOrder, mMockNetd).clatdStop(eq(iface));
10660         }
10661     }
10662 
10663     private void expectNativeNetworkCreated(int netId, int permission, String iface,
10664             InOrder inOrder) throws Exception {
10665         verifyWithOrder(inOrder, mMockNetd).networkCreate(nativeNetworkConfigPhysical(netId,
10666                 permission));
10667         verifyWithOrder(inOrder, mMockDnsResolver).createNetworkCache(eq(netId));
10668         if (iface != null) {
10669             verifyWithOrder(inOrder, mMockNetd).networkAddInterface(netId, iface);
10670         }
10671     }
10672 
10673     private void expectNativeNetworkCreated(int netId, int permission, String iface)
10674             throws Exception {
10675         expectNativeNetworkCreated(netId, permission, iface, null /* inOrder */);
10676     }
10677 
10678     @Test
10679     public void testStackedLinkProperties() throws Exception {
10680         final LinkAddress myIpv4 = new LinkAddress("1.2.3.4/24");
10681         final LinkAddress myIpv6 = new LinkAddress("2001:db8:1::1/64");
10682         final String kNat64PrefixString = "2001:db8:64:64:64:64::";
10683         final IpPrefix kNat64Prefix = new IpPrefix(InetAddress.getByName(kNat64PrefixString), 96);
10684         final String kOtherNat64PrefixString = "64:ff9b::";
10685         final IpPrefix kOtherNat64Prefix = new IpPrefix(
10686                 InetAddress.getByName(kOtherNat64PrefixString), 96);
10687         final RouteInfo ipv6Default =
10688                 new RouteInfo((IpPrefix) null, myIpv6.getAddress(), MOBILE_IFNAME);
10689         final RouteInfo ipv6Subnet = new RouteInfo(myIpv6, null, MOBILE_IFNAME);
10690         final RouteInfo ipv4Subnet = new RouteInfo(myIpv4, null, MOBILE_IFNAME);
10691         final RouteInfo stackedDefault =
10692                 new RouteInfo((IpPrefix) null, myIpv4.getAddress(), CLAT_MOBILE_IFNAME);
10693 
10694         final NetworkRequest networkRequest = new NetworkRequest.Builder()
10695                 .addTransportType(TRANSPORT_CELLULAR)
10696                 .addCapability(NET_CAPABILITY_INTERNET)
10697                 .build();
10698         final TestNetworkCallback networkCallback = new TestNetworkCallback();
10699         mCm.registerNetworkCallback(networkRequest, networkCallback);
10700 
10701         // Prepare ipv6 only link properties.
10702         final LinkProperties cellLp = new LinkProperties();
10703         cellLp.setInterfaceName(MOBILE_IFNAME);
10704         cellLp.addLinkAddress(myIpv6);
10705         cellLp.addRoute(ipv6Default);
10706         cellLp.addRoute(ipv6Subnet);
10707         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
10708         reset(mClatCoordinator);
10709 
10710         // Connect with ipv6 link properties. Expect prefix discovery to be started.
10711         mCellAgent.connect(true);
10712         int cellNetId = mCellAgent.getNetwork().netId;
10713         waitForIdle();
10714 
10715         expectNativeNetworkCreated(cellNetId, INetd.PERMISSION_NONE, MOBILE_IFNAME);
10716         assertRoutesAdded(cellNetId, ipv6Subnet, ipv6Default);
10717         final ArrayTrackRecord<ReportedInterfaces>.ReadHead readHead =
10718                 mDeps.mReportedInterfaceHistory.newReadHead();
10719         assertNotNull(readHead.poll(TIMEOUT_MS, ri -> ri.contentEquals(mServiceContext,
10720                 cellLp.getInterfaceName(),
10721                 new int[] { TRANSPORT_CELLULAR })));
10722 
10723         networkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
10724         verify(mMockDnsResolver, times(1)).startPrefix64Discovery(cellNetId);
10725 
10726         // Switching default network updates TCP buffer sizes.
10727         verifyTcpBufferSizeChange(ConnectivityService.DEFAULT_TCP_BUFFER_SIZES);
10728         // Add an IPv4 address. Expect prefix discovery to be stopped. Netd doesn't tell us that
10729         // the NAT64 prefix was removed because one was never discovered.
10730         cellLp.addLinkAddress(myIpv4);
10731         mCellAgent.sendLinkProperties(cellLp);
10732         networkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent);
10733         assertRoutesAdded(cellNetId, ipv4Subnet);
10734         verify(mMockDnsResolver, times(1)).stopPrefix64Discovery(cellNetId);
10735         verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(any());
10736 
10737         // Make sure BatteryStats was not told about any v4- interfaces, as none should have
10738         // come online yet.
10739         waitForIdle();
10740         assertNull(readHead.poll(0 /* timeout */, ri -> mServiceContext.equals(ri.context)
10741                 && ri.iface != null && ri.iface.startsWith("v4-")));
10742 
10743         verifyNoMoreInteractions(mMockNetd);
10744         verifyNoMoreInteractions(mClatCoordinator);
10745         verifyNoMoreInteractions(mMockDnsResolver);
10746         reset(mMockNetd);
10747         reset(mClatCoordinator);
10748         reset(mMockDnsResolver);
10749         doReturn(getClatInterfaceConfigParcel(myIpv4)).when(mMockNetd)
10750                 .interfaceGetCfg(CLAT_MOBILE_IFNAME);
10751 
10752         // Remove IPv4 address. Expect prefix discovery to be started again.
10753         cellLp.removeLinkAddress(myIpv4);
10754         mCellAgent.sendLinkProperties(cellLp);
10755         networkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent);
10756         verify(mMockDnsResolver, times(1)).startPrefix64Discovery(cellNetId);
10757         assertRoutesRemoved(cellNetId, ipv4Subnet);
10758 
10759         // When NAT64 prefix discovery succeeds, LinkProperties are updated and clatd is started.
10760         Nat464Xlat clat = getNat464Xlat(mCellAgent);
10761         assertNull(mCm.getLinkProperties(mCellAgent.getNetwork()).getNat64Prefix());
10762         mService.mResolverUnsolEventCallback.onNat64PrefixEvent(
10763                 makeNat64PrefixEvent(cellNetId, PREFIX_OPERATION_ADDED, kNat64PrefixString, 96));
10764         LinkProperties lpBeforeClat = networkCallback.expect(
10765                 LINK_PROPERTIES_CHANGED, mCellAgent).getLp();
10766         assertEquals(0, lpBeforeClat.getStackedLinks().size());
10767         assertEquals(kNat64Prefix, lpBeforeClat.getNat64Prefix());
10768         verifyClatdStart(null /* inOrder */, MOBILE_IFNAME, cellNetId, kNat64Prefix.toString());
10769 
10770         // Clat iface comes up. Expect stacked link to be added.
10771         clat.interfaceLinkStateChanged(CLAT_MOBILE_IFNAME, true);
10772         networkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent);
10773         List<LinkProperties> stackedLps = mCm.getLinkProperties(mCellAgent.getNetwork())
10774                 .getStackedLinks();
10775         assertEquals(makeClatLinkProperties(myIpv4), stackedLps.get(0));
10776         assertRoutesAdded(cellNetId, stackedDefault);
10777         verify(mMockNetd, times(1)).networkAddInterface(cellNetId, CLAT_MOBILE_IFNAME);
10778         // Change trivial linkproperties and see if stacked link is preserved.
10779         cellLp.addDnsServer(InetAddress.getByName("8.8.8.8"));
10780         mCellAgent.sendLinkProperties(cellLp);
10781         networkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent);
10782 
10783         List<LinkProperties> stackedLpsAfterChange =
10784                 mCm.getLinkProperties(mCellAgent.getNetwork()).getStackedLinks();
10785         assertNotEquals(stackedLpsAfterChange, Collections.EMPTY_LIST);
10786         assertEquals(makeClatLinkProperties(myIpv4), stackedLpsAfterChange.get(0));
10787 
10788         verify(mMockDnsResolver, times(1)).setResolverConfiguration(
10789                 mResolverParamsParcelCaptor.capture());
10790         ResolverParamsParcel resolvrParams = mResolverParamsParcelCaptor.getValue();
10791         assertEquals(1, resolvrParams.servers.length);
10792         assertTrue(CollectionUtils.contains(resolvrParams.servers, "8.8.8.8"));
10793 
10794         for (final LinkProperties stackedLp : stackedLpsAfterChange) {
10795             assertNotNull(readHead.poll(TIMEOUT_MS, ri -> ri.contentEquals(mServiceContext,
10796                     stackedLp.getInterfaceName(),
10797                     new int[] { TRANSPORT_CELLULAR })));
10798         }
10799         reset(mMockNetd);
10800         reset(mClatCoordinator);
10801         doReturn(getClatInterfaceConfigParcel(myIpv4)).when(mMockNetd)
10802                 .interfaceGetCfg(CLAT_MOBILE_IFNAME);
10803         // Change the NAT64 prefix without first removing it.
10804         // Expect clatd to be stopped and started with the new prefix.
10805         mService.mResolverUnsolEventCallback.onNat64PrefixEvent(makeNat64PrefixEvent(
10806                 cellNetId, PREFIX_OPERATION_ADDED, kOtherNat64PrefixString, 96));
10807         networkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent,
10808                 cb -> cb.getLp().getStackedLinks().size() == 0);
10809         verifyClatdStop(null /* inOrder */, MOBILE_IFNAME);
10810         assertRoutesRemoved(cellNetId, stackedDefault);
10811         verify(mMockNetd, times(1)).networkRemoveInterface(cellNetId, CLAT_MOBILE_IFNAME);
10812 
10813         verifyClatdStart(null /* inOrder */, MOBILE_IFNAME, cellNetId,
10814                 kOtherNat64Prefix.toString());
10815         networkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent,
10816                 cb -> cb.getLp().getNat64Prefix().equals(kOtherNat64Prefix));
10817         clat.interfaceLinkStateChanged(CLAT_MOBILE_IFNAME, true);
10818         networkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent,
10819                 cb -> cb.getLp().getStackedLinks().size() == 1);
10820         assertRoutesAdded(cellNetId, stackedDefault);
10821         verify(mMockNetd, times(1)).networkAddInterface(cellNetId, CLAT_MOBILE_IFNAME);
10822         reset(mMockNetd);
10823         reset(mClatCoordinator);
10824 
10825         // Add ipv4 address, expect that clatd and prefix discovery are stopped and stacked
10826         // linkproperties are cleaned up.
10827         cellLp.addLinkAddress(myIpv4);
10828         cellLp.addRoute(ipv4Subnet);
10829         mCellAgent.sendLinkProperties(cellLp);
10830         networkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent);
10831         assertRoutesAdded(cellNetId, ipv4Subnet);
10832         verifyClatdStop(null /* inOrder */, MOBILE_IFNAME);
10833         verify(mMockDnsResolver, times(1)).stopPrefix64Discovery(cellNetId);
10834 
10835         // As soon as stop is called, the linkproperties lose the stacked interface.
10836         networkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent);
10837         LinkProperties actualLpAfterIpv4 = mCm.getLinkProperties(mCellAgent.getNetwork());
10838         LinkProperties expected = new LinkProperties(cellLp);
10839         expected.setNat64Prefix(kOtherNat64Prefix);
10840         assertEquals(expected, actualLpAfterIpv4);
10841         assertEquals(0, actualLpAfterIpv4.getStackedLinks().size());
10842         assertRoutesRemoved(cellNetId, stackedDefault);
10843 
10844         // The interface removed callback happens but has no effect after stop is called.
10845         clat.interfaceRemoved(CLAT_MOBILE_IFNAME);
10846         networkCallback.assertNoCallback();
10847         verify(mMockNetd, times(1)).networkRemoveInterface(cellNetId, CLAT_MOBILE_IFNAME);
10848 
10849         if (mDeps.isAtLeastU()) {
10850             verifyWakeupModifyInterface(CLAT_MOBILE_IFNAME, false);
10851         }
10852 
10853         verifyNoMoreInteractions(mMockNetd);
10854         verifyNoMoreInteractions(mClatCoordinator);
10855         verifyNoMoreInteractions(mMockDnsResolver);
10856         reset(mMockNetd);
10857         reset(mClatCoordinator);
10858         reset(mMockDnsResolver);
10859         doReturn(getClatInterfaceConfigParcel(myIpv4)).when(mMockNetd)
10860                 .interfaceGetCfg(CLAT_MOBILE_IFNAME);
10861 
10862         // Stopping prefix discovery causes netd to tell us that the NAT64 prefix is gone.
10863         mService.mResolverUnsolEventCallback.onNat64PrefixEvent(makeNat64PrefixEvent(
10864                 cellNetId, PREFIX_OPERATION_REMOVED, kOtherNat64PrefixString, 96));
10865         networkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent,
10866                 cb -> cb.getLp().getNat64Prefix() == null);
10867 
10868         // Remove IPv4 address and expect prefix discovery and clatd to be started again.
10869         cellLp.removeLinkAddress(myIpv4);
10870         cellLp.removeRoute(new RouteInfo(myIpv4, null, MOBILE_IFNAME));
10871         cellLp.removeDnsServer(InetAddress.getByName("8.8.8.8"));
10872         mCellAgent.sendLinkProperties(cellLp);
10873         networkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent);
10874         assertRoutesRemoved(cellNetId, ipv4Subnet);  // Directly-connected routes auto-added.
10875         verify(mMockDnsResolver, times(1)).startPrefix64Discovery(cellNetId);
10876         mService.mResolverUnsolEventCallback.onNat64PrefixEvent(makeNat64PrefixEvent(
10877                 cellNetId, PREFIX_OPERATION_ADDED, kNat64PrefixString, 96));
10878         networkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent);
10879         verifyClatdStart(null /* inOrder */, MOBILE_IFNAME, cellNetId, kNat64Prefix.toString());
10880 
10881         // Clat iface comes up. Expect stacked link to be added.
10882         clat.interfaceLinkStateChanged(CLAT_MOBILE_IFNAME, true);
10883         networkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent,
10884                 cb -> cb.getLp().getStackedLinks().size() == 1
10885                         && cb.getLp().getNat64Prefix() != null);
10886         assertRoutesAdded(cellNetId, stackedDefault);
10887         verify(mMockNetd, times(1)).networkAddInterface(cellNetId, CLAT_MOBILE_IFNAME);
10888 
10889         if (mDeps.isAtLeastU()) {
10890             verifyWakeupModifyInterface(CLAT_MOBILE_IFNAME, true);
10891         }
10892 
10893         // NAT64 prefix is removed. Expect that clat is stopped.
10894         mService.mResolverUnsolEventCallback.onNat64PrefixEvent(makeNat64PrefixEvent(
10895                 cellNetId, PREFIX_OPERATION_REMOVED, kNat64PrefixString, 96));
10896         networkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent,
10897                 cb -> cb.getLp().getStackedLinks().size() == 0
10898                         && cb.getLp().getNat64Prefix() == null);
10899         assertRoutesRemoved(cellNetId, ipv4Subnet, stackedDefault);
10900 
10901         // Stop has no effect because clat is already stopped.
10902         verifyClatdStop(null /* inOrder */, MOBILE_IFNAME);
10903         networkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent,
10904                 cb -> cb.getLp().getStackedLinks().size() == 0);
10905         verify(mMockNetd, times(1)).networkRemoveInterface(cellNetId, CLAT_MOBILE_IFNAME);
10906         verify(mMockNetd, times(1)).interfaceGetCfg(CLAT_MOBILE_IFNAME);
10907 
10908         if (mDeps.isAtLeastU()) {
10909             verifyWakeupModifyInterface(CLAT_MOBILE_IFNAME, false);
10910         }
10911 
10912         // Clean up.
10913         mCellAgent.disconnect();
10914         networkCallback.expect(LOST, mCellAgent);
10915         networkCallback.assertNoCallback();
10916         verify(mMockNetd, times(1)).idletimerRemoveInterface(eq(MOBILE_IFNAME), anyInt(),
10917                 eq(Integer.toString(TRANSPORT_CELLULAR)));
10918         verify(mMockNetd).networkDestroy(cellNetId);
10919         if (mDeps.isAtLeastU()) {
10920             verify(mMockNetd).setNetworkAllowlist(any());
10921         } else {
10922             verify(mMockNetd, never()).setNetworkAllowlist(any());
10923         }
10924 
10925         if (mDeps.isAtLeastU()) {
10926             verifyWakeupModifyInterface(MOBILE_IFNAME, false);
10927         }
10928 
10929         verifyNoMoreInteractions(mMockNetd);
10930         verifyNoMoreInteractions(mClatCoordinator);
10931         reset(mMockNetd);
10932         reset(mClatCoordinator);
10933 
10934         // Test disconnecting a network that is running 464xlat.
10935 
10936         // Connect a network with a NAT64 prefix.
10937         doReturn(getClatInterfaceConfigParcel(myIpv4)).when(mMockNetd)
10938                 .interfaceGetCfg(CLAT_MOBILE_IFNAME);
10939         cellLp.setNat64Prefix(kNat64Prefix);
10940         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
10941         mCellAgent.connect(false /* validated */);
10942         networkCallback.expectAvailableCallbacksUnvalidated(mCellAgent);
10943         cellNetId = mCellAgent.getNetwork().netId;
10944         verify(mMockNetd, times(1)).networkCreate(nativeNetworkConfigPhysical(cellNetId,
10945                 INetd.PERMISSION_NONE));
10946         assertRoutesAdded(cellNetId, ipv6Subnet, ipv6Default);
10947 
10948         // Clatd is started and clat iface comes up. Expect stacked link to be added.
10949         verifyClatdStart(null /* inOrder */, MOBILE_IFNAME, cellNetId, kNat64Prefix.toString());
10950         clat = getNat464Xlat(mCellAgent);
10951         clat.interfaceLinkStateChanged(CLAT_MOBILE_IFNAME, true /* up */);
10952         networkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent,
10953                 cb -> cb.getLp().getStackedLinks().size() == 1
10954                         && cb.getLp().getNat64Prefix().equals(kNat64Prefix));
10955         verify(mMockNetd).networkAddInterface(cellNetId, CLAT_MOBILE_IFNAME);
10956         // assertRoutesAdded sees all calls since last mMockNetd reset, so expect IPv6 routes again.
10957         assertRoutesAdded(cellNetId, ipv6Subnet, ipv6Default, stackedDefault);
10958 
10959         if (mDeps.isAtLeastU()) {
10960             verifyWakeupModifyInterface(MOBILE_IFNAME, true);
10961         }
10962 
10963         reset(mMockNetd);
10964         reset(mClatCoordinator);
10965 
10966         // Disconnect the network. clat is stopped and the network is destroyed.
10967         mCellAgent.disconnect();
10968         networkCallback.expect(LOST, mCellAgent);
10969         networkCallback.assertNoCallback();
10970         verifyClatdStop(null /* inOrder */, MOBILE_IFNAME);
10971 
10972         if (mDeps.isAtLeastU()) {
10973             verifyWakeupModifyInterface(CLAT_MOBILE_IFNAME, false);
10974         }
10975 
10976         verify(mMockNetd).idletimerRemoveInterface(eq(MOBILE_IFNAME), anyInt(),
10977                 eq(Integer.toString(TRANSPORT_CELLULAR)));
10978         verify(mMockNetd).networkDestroy(cellNetId);
10979         if (mDeps.isAtLeastU()) {
10980             verify(mMockNetd).setNetworkAllowlist(any());
10981         } else {
10982             verify(mMockNetd, never()).setNetworkAllowlist(any());
10983         }
10984 
10985         if (mDeps.isAtLeastU()) {
10986             verifyWakeupModifyInterface(MOBILE_IFNAME, false);
10987         }
10988 
10989         verifyNoMoreInteractions(mMockNetd);
10990         verifyNoMoreInteractions(mClatCoordinator);
10991 
10992         mCm.unregisterNetworkCallback(networkCallback);
10993     }
10994 
10995     private void expectNat64PrefixChange(TestNetworkCallback callback,
10996             TestNetworkAgentWrapper agent, IpPrefix prefix) {
10997         callback.expect(LINK_PROPERTIES_CHANGED, agent,
10998                 x -> Objects.equals(x.getLp().getNat64Prefix(), prefix));
10999     }
11000 
11001     @Test
11002     public void testNat64PrefixMultipleSources() throws Exception {
11003         final String iface = "wlan0";
11004         final String pref64FromRaStr = "64:ff9b::";
11005         final String pref64FromDnsStr = "2001:db8:64::";
11006         final IpPrefix pref64FromRa = new IpPrefix(InetAddress.getByName(pref64FromRaStr), 96);
11007         final IpPrefix pref64FromDns = new IpPrefix(InetAddress.getByName(pref64FromDnsStr), 96);
11008         final IpPrefix newPref64FromRa = new IpPrefix("2001:db8:64:64:64:64::/96");
11009 
11010         final NetworkRequest request = new NetworkRequest.Builder()
11011                 .addCapability(NET_CAPABILITY_INTERNET)
11012                 .build();
11013         final TestNetworkCallback callback = new TestNetworkCallback();
11014         mCm.registerNetworkCallback(request, callback);
11015 
11016         final LinkProperties baseLp = new LinkProperties();
11017         baseLp.setInterfaceName(iface);
11018         baseLp.addLinkAddress(new LinkAddress("2001:db8:1::1/64"));
11019         baseLp.addDnsServer(InetAddress.getByName("2001:4860:4860::6464"));
11020 
11021         reset(mMockNetd, mMockDnsResolver);
11022         InOrder inOrder = inOrder(mMockNetd, mMockDnsResolver, mClatCoordinator);
11023 
11024         // If a network already has a NAT64 prefix on connect, clatd is started immediately and
11025         // prefix discovery is never started.
11026         LinkProperties lp = new LinkProperties(baseLp);
11027         lp.setNat64Prefix(pref64FromRa);
11028         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, lp);
11029         mWiFiAgent.connect(false);
11030         final Network network = mWiFiAgent.getNetwork();
11031         int netId = network.getNetId();
11032         callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
11033         verifyClatdStart(inOrder, iface, netId, pref64FromRa.toString());
11034         inOrder.verify(mMockDnsResolver).setPrefix64(netId, pref64FromRa.toString());
11035         inOrder.verify(mMockDnsResolver, never()).startPrefix64Discovery(netId);
11036         callback.assertNoCallback();
11037         assertEquals(pref64FromRa, mCm.getLinkProperties(network).getNat64Prefix());
11038 
11039         // If the RA prefix is withdrawn, clatd is stopped and prefix discovery is started.
11040         lp.setNat64Prefix(null);
11041         mWiFiAgent.sendLinkProperties(lp);
11042         expectNat64PrefixChange(callback, mWiFiAgent, null);
11043         verifyClatdStop(inOrder, iface);
11044         inOrder.verify(mMockDnsResolver).setPrefix64(netId, "");
11045         inOrder.verify(mMockDnsResolver).startPrefix64Discovery(netId);
11046 
11047         // If the RA prefix appears while DNS discovery is in progress, discovery is stopped and
11048         // clatd is started with the prefix from the RA.
11049         lp.setNat64Prefix(pref64FromRa);
11050         mWiFiAgent.sendLinkProperties(lp);
11051         expectNat64PrefixChange(callback, mWiFiAgent, pref64FromRa);
11052         verifyClatdStart(inOrder, iface, netId, pref64FromRa.toString());
11053         inOrder.verify(mMockDnsResolver).stopPrefix64Discovery(netId);
11054         inOrder.verify(mMockDnsResolver).setPrefix64(netId, pref64FromRa.toString());
11055 
11056         // Withdraw the RA prefix so we can test the case where an RA prefix appears after DNS
11057         // discovery has succeeded.
11058         lp.setNat64Prefix(null);
11059         mWiFiAgent.sendLinkProperties(lp);
11060         expectNat64PrefixChange(callback, mWiFiAgent, null);
11061         verifyClatdStop(inOrder, iface);
11062         inOrder.verify(mMockDnsResolver).setPrefix64(netId, "");
11063         inOrder.verify(mMockDnsResolver).startPrefix64Discovery(netId);
11064 
11065         mService.mResolverUnsolEventCallback.onNat64PrefixEvent(
11066                 makeNat64PrefixEvent(netId, PREFIX_OPERATION_ADDED, pref64FromDnsStr, 96));
11067         expectNat64PrefixChange(callback, mWiFiAgent, pref64FromDns);
11068         verifyClatdStart(inOrder, iface, netId, pref64FromDns.toString());
11069 
11070         // If an RA advertises the same prefix that was discovered by DNS, nothing happens: prefix
11071         // discovery is not stopped, and there are no callbacks.
11072         lp.setNat64Prefix(pref64FromDns);
11073         mWiFiAgent.sendLinkProperties(lp);
11074         callback.assertNoCallback();
11075         verifyNeverClatdStop(inOrder, iface);
11076         verifyNeverClatdStart(inOrder, iface);
11077         inOrder.verify(mMockDnsResolver, never()).stopPrefix64Discovery(netId);
11078         inOrder.verify(mMockDnsResolver, never()).startPrefix64Discovery(netId);
11079         inOrder.verify(mMockDnsResolver, never()).setPrefix64(eq(netId), anyString());
11080 
11081         // If the RA is later withdrawn, nothing happens again.
11082         lp.setNat64Prefix(null);
11083         mWiFiAgent.sendLinkProperties(lp);
11084         callback.assertNoCallback();
11085         verifyNeverClatdStop(inOrder, iface);
11086         verifyNeverClatdStart(inOrder, iface);
11087         inOrder.verify(mMockDnsResolver, never()).stopPrefix64Discovery(netId);
11088         inOrder.verify(mMockDnsResolver, never()).startPrefix64Discovery(netId);
11089         inOrder.verify(mMockDnsResolver, never()).setPrefix64(eq(netId), anyString());
11090 
11091         // If the RA prefix changes, clatd is restarted and prefix discovery is stopped.
11092         lp.setNat64Prefix(pref64FromRa);
11093         mWiFiAgent.sendLinkProperties(lp);
11094         expectNat64PrefixChange(callback, mWiFiAgent, pref64FromRa);
11095         verifyClatdStop(inOrder, iface);
11096         inOrder.verify(mMockDnsResolver).stopPrefix64Discovery(netId);
11097 
11098         // Stopping prefix discovery results in a prefix removed notification.
11099         mService.mResolverUnsolEventCallback.onNat64PrefixEvent(
11100                 makeNat64PrefixEvent(netId, PREFIX_OPERATION_REMOVED, pref64FromDnsStr, 96));
11101 
11102         verifyClatdStart(inOrder, iface, netId, pref64FromRa.toString());
11103         inOrder.verify(mMockDnsResolver).setPrefix64(netId, pref64FromRa.toString());
11104         inOrder.verify(mMockDnsResolver, never()).startPrefix64Discovery(netId);
11105 
11106         // If the RA prefix changes, clatd is restarted and prefix discovery is not started.
11107         lp.setNat64Prefix(newPref64FromRa);
11108         mWiFiAgent.sendLinkProperties(lp);
11109         expectNat64PrefixChange(callback, mWiFiAgent, newPref64FromRa);
11110         verifyClatdStop(inOrder, iface);
11111         inOrder.verify(mMockDnsResolver).setPrefix64(netId, "");
11112         verifyClatdStart(inOrder, iface, netId, newPref64FromRa.toString());
11113         inOrder.verify(mMockDnsResolver).setPrefix64(netId, newPref64FromRa.toString());
11114         inOrder.verify(mMockDnsResolver, never()).stopPrefix64Discovery(netId);
11115         inOrder.verify(mMockDnsResolver, never()).startPrefix64Discovery(netId);
11116 
11117         // If the RA prefix changes to the same value, nothing happens.
11118         lp.setNat64Prefix(newPref64FromRa);
11119         mWiFiAgent.sendLinkProperties(lp);
11120         callback.assertNoCallback();
11121         assertEquals(newPref64FromRa, mCm.getLinkProperties(network).getNat64Prefix());
11122         verifyNeverClatdStop(inOrder, iface);
11123         verifyNeverClatdStart(inOrder, iface);
11124         inOrder.verify(mMockDnsResolver, never()).stopPrefix64Discovery(netId);
11125         inOrder.verify(mMockDnsResolver, never()).startPrefix64Discovery(netId);
11126         inOrder.verify(mMockDnsResolver, never()).setPrefix64(eq(netId), anyString());
11127 
11128         // The transition between no prefix and DNS prefix is tested in testStackedLinkProperties.
11129 
11130         // If the same prefix is learned first by DNS and then by RA, and clat is later stopped,
11131         // (e.g., because the network disconnects) setPrefix64(netid, "") is never called.
11132         lp.setNat64Prefix(null);
11133         mWiFiAgent.sendLinkProperties(lp);
11134         expectNat64PrefixChange(callback, mWiFiAgent, null);
11135         verifyClatdStop(inOrder, iface);
11136         inOrder.verify(mMockDnsResolver).setPrefix64(netId, "");
11137         inOrder.verify(mMockDnsResolver).startPrefix64Discovery(netId);
11138         mService.mResolverUnsolEventCallback.onNat64PrefixEvent(
11139                 makeNat64PrefixEvent(netId, PREFIX_OPERATION_ADDED, pref64FromDnsStr, 96));
11140         expectNat64PrefixChange(callback, mWiFiAgent, pref64FromDns);
11141         verifyClatdStart(inOrder, iface, netId, pref64FromDns.toString());
11142         inOrder.verify(mMockDnsResolver, never()).setPrefix64(eq(netId), any());
11143 
11144         lp.setNat64Prefix(pref64FromDns);
11145         mWiFiAgent.sendLinkProperties(lp);
11146         callback.assertNoCallback();
11147         verifyNeverClatdStop(inOrder, iface);
11148         verifyNeverClatdStart(inOrder, iface);
11149         inOrder.verify(mMockDnsResolver, never()).stopPrefix64Discovery(netId);
11150         inOrder.verify(mMockDnsResolver, never()).startPrefix64Discovery(netId);
11151         inOrder.verify(mMockDnsResolver, never()).setPrefix64(eq(netId), anyString());
11152 
11153         // When tearing down a network, clat state is only updated after CALLBACK_LOST is fired, but
11154         // before CONNECTIVITY_ACTION is sent. Wait for CONNECTIVITY_ACTION before verifying that
11155         // clat has been stopped, or the test will be flaky.
11156         ExpectedBroadcast b = expectConnectivityAction(TYPE_WIFI, DetailedState.DISCONNECTED);
11157         mWiFiAgent.disconnect();
11158         callback.expect(LOST, mWiFiAgent);
11159         b.expectBroadcast();
11160 
11161         verifyClatdStop(inOrder, iface);
11162         inOrder.verify(mMockDnsResolver).stopPrefix64Discovery(netId);
11163         inOrder.verify(mMockDnsResolver, never()).setPrefix64(eq(netId), anyString());
11164 
11165         mCm.unregisterNetworkCallback(callback);
11166     }
11167 
11168     @Test
11169     public void testWith464XlatDisable() throws Exception {
11170         mDeps.setCellular464XlatEnabled(false);
11171 
11172         final TestNetworkCallback callback = new TestNetworkCallback();
11173         final TestNetworkCallback defaultCallback = new TestNetworkCallback();
11174         final NetworkRequest networkRequest = new NetworkRequest.Builder()
11175                 .addCapability(NET_CAPABILITY_INTERNET)
11176                 .build();
11177         mCm.registerNetworkCallback(networkRequest, callback);
11178         mCm.registerDefaultNetworkCallback(defaultCallback);
11179 
11180         // Bring up validated cell.
11181         final LinkProperties cellLp = new LinkProperties();
11182         cellLp.setInterfaceName(MOBILE_IFNAME);
11183         cellLp.addLinkAddress(new LinkAddress("2001:db8:1::1/64"));
11184         cellLp.addRoute(new RouteInfo(new IpPrefix("::/0"), null, MOBILE_IFNAME));
11185         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
11186 
11187         mCellAgent.sendLinkProperties(cellLp);
11188         mCellAgent.connect(true);
11189         callback.expectAvailableThenValidatedCallbacks(mCellAgent);
11190         defaultCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
11191         final int cellNetId = mCellAgent.getNetwork().netId;
11192         waitForIdle();
11193 
11194         verify(mMockDnsResolver, never()).startPrefix64Discovery(cellNetId);
11195         Nat464Xlat clat = getNat464Xlat(mCellAgent);
11196         assertTrue("Nat464Xlat was not IDLE", !clat.isStarted());
11197 
11198         // This cannot happen because prefix discovery cannot succeed if it is never started.
11199         mService.mResolverUnsolEventCallback.onNat64PrefixEvent(
11200                 makeNat64PrefixEvent(cellNetId, PREFIX_OPERATION_ADDED, "64:ff9b::", 96));
11201 
11202         // ... but still, check that even if it did, clatd would not be started.
11203         verify(mMockNetd, never()).clatdStart(anyString(), anyString());
11204         assertTrue("Nat464Xlat was not IDLE", !clat.isStarted());
11205     }
11206 
11207     @Test
11208     public void testDataActivityTracking() throws Exception {
11209         final TestNetworkCallback networkCallback = new TestNetworkCallback();
11210         final NetworkRequest networkRequest = new NetworkRequest.Builder()
11211                 .addCapability(NET_CAPABILITY_INTERNET)
11212                 .build();
11213         mCm.registerNetworkCallback(networkRequest, networkCallback);
11214 
11215         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
11216         final LinkProperties cellLp = new LinkProperties();
11217         cellLp.setInterfaceName(MOBILE_IFNAME);
11218         mCellAgent.sendLinkProperties(cellLp);
11219         mCellAgent.connect(true);
11220         networkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
11221         verify(mMockNetd, times(1)).idletimerAddInterface(eq(MOBILE_IFNAME), anyInt(),
11222                 eq(Integer.toString(TRANSPORT_CELLULAR)));
11223 
11224         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
11225         final LinkProperties wifiLp = new LinkProperties();
11226         wifiLp.setInterfaceName(WIFI_IFNAME);
11227         mWiFiAgent.sendLinkProperties(wifiLp);
11228 
11229         // Network switch
11230         mWiFiAgent.connect(true);
11231         networkCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
11232         networkCallback.expectLosing(mCellAgent);
11233         networkCallback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
11234         verify(mMockNetd, times(1)).idletimerAddInterface(eq(WIFI_IFNAME), anyInt(),
11235                 eq(Integer.toString(TRANSPORT_WIFI)));
11236         verify(mMockNetd, times(1)).idletimerRemoveInterface(eq(MOBILE_IFNAME), anyInt(),
11237                 eq(Integer.toString(TRANSPORT_CELLULAR)));
11238 
11239         // Disconnect wifi and switch back to cell
11240         reset(mMockNetd);
11241         mWiFiAgent.disconnect();
11242         networkCallback.expect(LOST, mWiFiAgent);
11243         assertNoCallbacks(networkCallback);
11244         verify(mMockNetd, times(1)).idletimerRemoveInterface(eq(WIFI_IFNAME), anyInt(),
11245                 eq(Integer.toString(TRANSPORT_WIFI)));
11246         verify(mMockNetd, times(1)).idletimerAddInterface(eq(MOBILE_IFNAME), anyInt(),
11247                 eq(Integer.toString(TRANSPORT_CELLULAR)));
11248 
11249         // reconnect wifi
11250         reset(mMockNetd);
11251         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
11252         wifiLp.setInterfaceName(WIFI_IFNAME);
11253         mWiFiAgent.sendLinkProperties(wifiLp);
11254         mWiFiAgent.connect(true);
11255         networkCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
11256         networkCallback.expectLosing(mCellAgent);
11257         networkCallback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
11258         verify(mMockNetd, times(1)).idletimerAddInterface(eq(WIFI_IFNAME), anyInt(),
11259                 eq(Integer.toString(TRANSPORT_WIFI)));
11260         verify(mMockNetd, times(1)).idletimerRemoveInterface(eq(MOBILE_IFNAME), anyInt(),
11261                 eq(Integer.toString(TRANSPORT_CELLULAR)));
11262 
11263         // Disconnect cell
11264         reset(mMockNetd);
11265         mCellAgent.disconnect();
11266         networkCallback.expect(LOST, mCellAgent);
11267         // LOST callback is triggered earlier than removing idle timer. Broadcast should also be
11268         // sent as network being switched. Ensure rule removal for cell will not be triggered
11269         // unexpectedly before network being removed.
11270         waitForIdle();
11271         verify(mMockNetd, times(0)).idletimerRemoveInterface(eq(MOBILE_IFNAME), anyInt(),
11272                 eq(Integer.toString(TRANSPORT_CELLULAR)));
11273         verify(mMockNetd, times(1)).networkDestroy(eq(mCellAgent.getNetwork().netId));
11274         verify(mMockDnsResolver, times(1)).destroyNetworkCache(eq(mCellAgent.getNetwork().netId));
11275 
11276         // Disconnect wifi
11277         ExpectedBroadcast b = expectConnectivityAction(TYPE_WIFI, DetailedState.DISCONNECTED);
11278         mWiFiAgent.disconnect();
11279         b.expectBroadcast();
11280         verify(mMockNetd, times(1)).idletimerRemoveInterface(eq(WIFI_IFNAME), anyInt(),
11281                 eq(Integer.toString(TRANSPORT_WIFI)));
11282 
11283         // Clean up
11284         mCm.unregisterNetworkCallback(networkCallback);
11285     }
11286 
11287     private void verifyTcpBufferSizeChange(String tcpBufferSizes) throws Exception {
11288         String[] values = tcpBufferSizes.split(",");
11289         String rmemValues = String.join(" ", values[0], values[1], values[2]);
11290         String wmemValues = String.join(" ", values[3], values[4], values[5]);
11291         verify(mMockNetd, atLeastOnce()).setTcpRWmemorySize(rmemValues, wmemValues);
11292         reset(mMockNetd);
11293     }
11294 
11295     @Test
11296     public void testTcpBufferReset() throws Exception {
11297         final String testTcpBufferSizes = "1,2,3,4,5,6";
11298         final NetworkRequest networkRequest = new NetworkRequest.Builder()
11299                 .addTransportType(TRANSPORT_CELLULAR)
11300                 .addCapability(NET_CAPABILITY_INTERNET)
11301                 .build();
11302         final TestNetworkCallback networkCallback = new TestNetworkCallback();
11303         mCm.registerNetworkCallback(networkRequest, networkCallback);
11304 
11305         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
11306         reset(mMockNetd);
11307         // Switching default network updates TCP buffer sizes.
11308         mCellAgent.connect(false);
11309         networkCallback.expectAvailableCallbacksUnvalidated(mCellAgent);
11310         verifyTcpBufferSizeChange(ConnectivityService.DEFAULT_TCP_BUFFER_SIZES);
11311         // Change link Properties should have updated tcp buffer size.
11312         LinkProperties lp = new LinkProperties();
11313         lp.setTcpBufferSizes(testTcpBufferSizes);
11314         mCellAgent.sendLinkProperties(lp);
11315         networkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent);
11316         verifyTcpBufferSizeChange(testTcpBufferSizes);
11317         // Clean up.
11318         mCellAgent.disconnect();
11319         networkCallback.expect(LOST, mCellAgent);
11320         networkCallback.assertNoCallback();
11321         mCm.unregisterNetworkCallback(networkCallback);
11322     }
11323 
11324     @Test
11325     public void testGetGlobalProxyForNetwork() throws Exception {
11326         final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
11327         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
11328         final Network wifiNetwork = mWiFiAgent.getNetwork();
11329         mProxyTracker.setGlobalProxy(testProxyInfo);
11330         assertEquals(testProxyInfo, mService.getProxyForNetwork(wifiNetwork));
11331     }
11332 
11333     @Test
11334     public void testGetProxyForActiveNetwork() throws Exception {
11335         final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
11336         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
11337         mWiFiAgent.connect(true);
11338         waitForIdle();
11339         assertNull(mService.getProxyForNetwork(null));
11340 
11341         final LinkProperties testLinkProperties = new LinkProperties();
11342         testLinkProperties.setHttpProxy(testProxyInfo);
11343 
11344         mWiFiAgent.sendLinkProperties(testLinkProperties);
11345         waitForIdle();
11346 
11347         assertEquals(testProxyInfo, mService.getProxyForNetwork(null));
11348     }
11349 
11350     /*
11351      * Note for maintainers about how PAC proxies are implemented in Android.
11352      *
11353      * Generally, a proxy is just a hostname and a port to which requests are sent, instead of
11354      * sending them directly. Most HTTP libraries know to use this protocol, and the Java
11355      * language has properties to help handling these :
11356      *   https://docs.oracle.com/javase/8/docs/technotes/guides/net/proxies.html
11357      * Unfortunately these properties are very old and do not take multi-networking into account.
11358      *
11359      * A PAC proxy consists of a javascript file stored on a server, and the client is expected to
11360      * download the file and interpret the javascript for each HTTP request to know where to direct
11361      * it. The device must therefore run code (namely, a javascript interpreter) to interpret the
11362      * PAC file correctly. Most HTTP libraries do not know how to do this, since they do not
11363      * embark a javascript interpreter (and it would be generally unreasonable for them to do
11364      * so). Some apps, notably browsers, do know how to do this, but they are the exception rather
11365      * than the rule.
11366      * So to support most apps, Android embarks the javascript interpreter. When a network is
11367      * configured to have a PAC proxy, Android will first set the ProxyInfo object to an object
11368      * that contains the PAC URL (to communicate that to apps that know how to use it), then
11369      * download the PAC file and start a native process which will open a server on localhost,
11370      * and uses the interpreter inside WebView to interpret the PAC file. This server takes
11371      * a little bit of time to start and will listen on a random port. When the port is known,
11372      * the framework receives a notification and it updates the ProxyInfo in LinkProperties
11373      * as well as send a broadcast to inform apps. This new ProxyInfo still contains the PAC URL,
11374      * but it also contains "localhost" as the host and the port that the server listens to as
11375      * the port. This will let HTTP libraries that don't have a javascript interpreter work,
11376      * because they'll send the requests to this server running on localhost on the correct port,
11377      * and this server will do what is appropriate with each request according to the PAC file.
11378      *
11379      * Note that at the time of this writing, Android does not support starting multiple local
11380      * PAC servers, though this would be possible in theory by just starting multiple instances
11381      * of this process running their server on different ports. As a stopgap measure, Android
11382      * keeps one local server which is always the one for the default network. If a non-default
11383      * network has a PAC proxy, it will have a LinkProperties with a port of -1, which means it
11384      * could still be used by apps that know how to use the PAC URL directly, but not by HTTP
11385      * libs that don't know how to do that. When a network with a PAC proxy becomes the default,
11386      * the local server is started. When a network without a PAC proxy becomes the default, the
11387      * local server is stopped if it is running (and the LP for the old default network should
11388      * be reset to have a port of -1).
11389      *
11390      * In principle, each network can be configured with a different proxy (typically in the
11391      * network settings for a Wi-Fi network). These end up exposed in the LinkProperties of the
11392      * relevant network.
11393      * Android also exposes ConnectivityManager#getDefaultProxy, which is simply the proxy for
11394      * the default network. This was retrofitted from a time where Android did not support multiple
11395      * concurrent networks, hence the difficult architecture.
11396      * Note that there is also a "global" proxy that can be set by the DPM. When this is set,
11397      * it overrides the proxy settings for every single network at the same time – that is, the
11398      * system behaves as if the global proxy is the configured proxy for each network.
11399      *
11400      * Generally there are four ways for apps to look up the proxy.
11401      * - Looking up the ProxyInfo in the LinkProperties for a network.
11402      * - Listening to the PROXY_CHANGED_ACTION broadcast
11403      * - Calling ConnectivityManager#getDefaultProxy, or ConnectivityManager#getProxyForNetwork
11404      *   which can be used to retrieve the proxy for any given network or the default network by
11405      *   passing null.
11406      * - Reading the standard JVM properties (http{s,}.proxy{Host,Port}). See the Java
11407      *   distribution documentation for details on how these are supposed to work :
11408      *    https://docs.oracle.com/javase/8/docs/technotes/guides/net/proxies.html
11409      *   In Android, these are set by ActivityThread in each process in response to the broadcast.
11410      *   Many apps actually use these, and it's important they work because it's part of the
11411      *   Java standard, meaning they need to be set for existing Java libs to work on Android.
11412      */
11413     @Test
11414     public void testPacProxy() throws Exception {
11415         final Uri pacUrl = Uri.parse("https://pac-url");
11416 
11417         final TestNetworkCallback cellCallback = new TestNetworkCallback();
11418         final NetworkRequest cellRequest = new NetworkRequest.Builder()
11419                 .addTransportType(TRANSPORT_CELLULAR).build();
11420         // Request cell to make sure it doesn't disconnect at an arbitrary point in the test,
11421         // which would make testing the callbacks on it difficult.
11422         mCm.requestNetwork(cellRequest, cellCallback);
11423         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
11424         mCellAgent.connect(true);
11425         cellCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
11426 
11427         final TestNetworkCallback wifiCallback = new TestNetworkCallback();
11428         final NetworkRequest wifiRequest = new NetworkRequest.Builder()
11429                 .addTransportType(TRANSPORT_WIFI).build();
11430         mCm.registerNetworkCallback(wifiRequest, wifiCallback);
11431 
11432         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
11433         mWiFiAgent.connect(true);
11434         wifiCallback.expectAvailableThenValidatedCallbacks(mWiFiAgent);
11435         cellCallback.assertNoCallback();
11436 
11437         final ProxyInfo initialProxyInfo = ProxyInfo.buildPacProxy(pacUrl);
11438         final LinkProperties testLinkProperties = new LinkProperties();
11439         testLinkProperties.setHttpProxy(initialProxyInfo);
11440         mWiFiAgent.sendLinkProperties(testLinkProperties);
11441         wifiCallback.expect(CallbackEntry.LINK_PROPERTIES_CHANGED, mWiFiAgent);
11442         cellCallback.assertNoCallback();
11443 
11444         // At first the local PAC proxy server is unstarted (see the description of what the local
11445         // server is in the comment at the top of this method). It will contain the PAC URL and a
11446         // port of -1 because it is unstarted. Check that all ways of getting that proxy info
11447         // returns the same object that was initially created.
11448         final ProxyInfo unstartedDefaultProxyInfo = mService.getProxyForNetwork(null);
11449         final ProxyInfo unstartedWifiProxyInfo = mService.getProxyForNetwork(
11450                 mWiFiAgent.getNetwork());
11451         final LinkProperties unstartedLp =
11452                 mService.getLinkProperties(mWiFiAgent.getNetwork());
11453 
11454         assertEquals(initialProxyInfo, unstartedDefaultProxyInfo);
11455         assertEquals(initialProxyInfo, unstartedWifiProxyInfo);
11456         assertEquals(initialProxyInfo, unstartedLp.getHttpProxy());
11457 
11458         // Make sure the cell network is unaffected. The LP are per-network and each network has
11459         // its own configuration. The default proxy and broadcast are system-wide, and the JVM
11460         // properties are per-process, and therefore can have only one value at any given time,
11461         // so the code sets them to the proxy of the default network (TODO : really, since the
11462         // default process is per-network, the JVM properties (http.proxyHost family – see
11463         // the comment at the top of the method for details about these) also should be per-network
11464         // and even the broadcast contents should be but none of this is implemented). The LP are
11465         // still per-network, and a process that wants to use a non-default network is supposed to
11466         // look up the proxy in its LP and it has to be correct.
11467         assertNull(mService.getLinkProperties(mCellAgent.getNetwork()).getHttpProxy());
11468         assertNull(mService.getProxyForNetwork(mCellAgent.getNetwork()));
11469 
11470         // Simulate PacManager sending the notification that the local server has started
11471         final ProxyInfo servingProxyInfo = new ProxyInfo(pacUrl, 2097);
11472         final ExpectedBroadcast servingProxyBroadcast = expectProxyChangeAction(servingProxyInfo);
11473         mService.simulateUpdateProxyInfo(mWiFiAgent.getNetwork(), servingProxyInfo);
11474         wifiCallback.expect(CallbackEntry.LINK_PROPERTIES_CHANGED, mWiFiAgent);
11475         cellCallback.assertNoCallback();
11476         servingProxyBroadcast.expectBroadcast();
11477 
11478         final ProxyInfo startedDefaultProxyInfo = mService.getProxyForNetwork(null);
11479         final ProxyInfo startedWifiProxyInfo = mService.getProxyForNetwork(
11480                 mWiFiAgent.getNetwork());
11481         final LinkProperties startedLp = mService.getLinkProperties(mWiFiAgent.getNetwork());
11482         assertEquals(servingProxyInfo, startedDefaultProxyInfo);
11483         assertEquals(servingProxyInfo, startedWifiProxyInfo);
11484         assertEquals(servingProxyInfo, startedLp.getHttpProxy());
11485         // Make sure the cell network is still unaffected
11486         assertNull(mService.getLinkProperties(mCellAgent.getNetwork()).getHttpProxy());
11487         assertNull(mService.getProxyForNetwork(mCellAgent.getNetwork()));
11488 
11489         // Start an ethernet network which will become the default, in order to test what happens
11490         // to the proxy of wifi while manipulating the proxy of ethernet.
11491         final Uri ethPacUrl = Uri.parse("https://ethernet-pac-url");
11492         final TestableNetworkCallback ethernetCallback = new TestableNetworkCallback();
11493         final NetworkRequest ethernetRequest = new NetworkRequest.Builder()
11494                 .addTransportType(TRANSPORT_ETHERNET).build();
11495         mEthernetAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
11496         mCm.registerNetworkCallback(ethernetRequest, ethernetCallback);
11497         mEthernetAgent.connect(true);
11498         ethernetCallback.expectAvailableThenValidatedCallbacks(mEthernetAgent);
11499 
11500         // Wifi is no longer the default, so it should get a callback to LP changed with a PAC
11501         // proxy but a port of -1 (since the local proxy doesn't serve wifi now)
11502         wifiCallback.expect(LINK_PROPERTIES_CHANGED, mWiFiAgent,
11503                 lp -> lp.getLp().getHttpProxy().getPort() == -1
11504                         && lp.getLp().getHttpProxy().isPacProxy());
11505         // Wifi is lingered as it was the default but is no longer serving any request.
11506         wifiCallback.expect(CallbackEntry.LOSING, mWiFiAgent);
11507 
11508         // Now arrange for Ethernet to have a PAC proxy.
11509         final ProxyInfo ethProxy = ProxyInfo.buildPacProxy(ethPacUrl);
11510         final LinkProperties ethLinkProperties = new LinkProperties();
11511         ethLinkProperties.setHttpProxy(ethProxy);
11512         mEthernetAgent.sendLinkProperties(ethLinkProperties);
11513         ethernetCallback.expect(CallbackEntry.LINK_PROPERTIES_CHANGED, mEthernetAgent);
11514         // Default network is Ethernet
11515         assertEquals(ethProxy, mService.getProxyForNetwork(null));
11516         assertEquals(ethProxy, mService.getProxyForNetwork(mEthernetAgent.getNetwork()));
11517         // Proxy info for WiFi ideally should be the old one with the old server still running,
11518         // but as the PAC code only handles one server at any given time, this can't work. Wifi
11519         // having null as a proxy also won't work (apps using WiFi will try to access the network
11520         // without proxy) but is not as bad as having the new proxy (that would send requests
11521         // over the default network).
11522         assertEquals(initialProxyInfo, mService.getProxyForNetwork(mWiFiAgent.getNetwork()));
11523         assertNull(mService.getProxyForNetwork(mCellAgent.getNetwork()));
11524 
11525         // Expect the local PAC proxy server starts to serve the proxy on Ethernet. Use
11526         // simulateUpdateProxyInfo to simulate this, and check that the callback is called to
11527         // inform apps of the port and that the various networks have the expected proxies in
11528         // their link properties.
11529         final ProxyInfo servingEthProxy = new ProxyInfo(ethPacUrl, 2099);
11530         final ExpectedBroadcast servingEthProxyBroadcast = expectProxyChangeAction(servingEthProxy);
11531         final ExpectedBroadcast servingProxyBroadcast2 = expectProxyChangeAction(servingProxyInfo);
11532         mService.simulateUpdateProxyInfo(mEthernetAgent.getNetwork(), servingEthProxy);
11533         ethernetCallback.expect(CallbackEntry.LINK_PROPERTIES_CHANGED, mEthernetAgent);
11534         assertEquals(servingEthProxy, mService.getProxyForNetwork(null));
11535         assertEquals(servingEthProxy, mService.getProxyForNetwork(mEthernetAgent.getNetwork()));
11536         assertEquals(initialProxyInfo, mService.getProxyForNetwork(mWiFiAgent.getNetwork()));
11537         assertNull(mService.getProxyForNetwork(mCellAgent.getNetwork()));
11538         servingEthProxyBroadcast.expectBroadcast();
11539 
11540         // Ethernet disconnects, back to WiFi
11541         mEthernetAgent.disconnect();
11542         ethernetCallback.expect(CallbackEntry.LOST, mEthernetAgent);
11543 
11544         // WiFi is now the default network again. However, the local proxy server does not serve
11545         // WiFi at this time, so at this time a proxy with port -1 is still the correct value.
11546         // In time, the local proxy server for ethernet will be downed and the local proxy server
11547         // for WiFi will be restarted, and WiFi will see an update to its LP with the new port,
11548         // but in this test this won't happen until the test simulates the local proxy starting
11549         // up for WiFi (which is done just a few lines below). This is therefore the perfect place
11550         // to check that WiFi is unaffected until the new local proxy starts up.
11551         wifiCallback.assertNoCallback();
11552         assertEquals(initialProxyInfo, mService.getProxyForNetwork(null));
11553         assertEquals(initialProxyInfo, mService.getProxyForNetwork(mWiFiAgent.getNetwork()));
11554         assertNull(mService.getProxyForNetwork(mCellAgent.getNetwork()));
11555         // Note : strictly speaking, for correctness here apps should expect a broadcast with a
11556         // port of -1, since that's the current default proxy. The code does not send this
11557         // broadcast. In practice though, not sending it is more useful since the new proxy will
11558         // start momentarily, so broadcasting and getting all apps to update and retry once now
11559         // and again in 250ms is kind of counter-productive, so don't fix this bug.
11560 
11561         // After a while the PAC file for wifi is resolved again and the local proxy server
11562         // starts up. This should cause a LP event to inform clients of the port to access the
11563         // proxy server for wifi.
11564         mService.simulateUpdateProxyInfo(mWiFiAgent.getNetwork(), servingProxyInfo);
11565         wifiCallback.expect(CallbackEntry.LINK_PROPERTIES_CHANGED, mWiFiAgent);
11566         assertEquals(servingProxyInfo, mService.getProxyForNetwork(null));
11567         assertEquals(servingProxyInfo, mService.getProxyForNetwork(mWiFiAgent.getNetwork()));
11568         assertNull(mService.getProxyForNetwork(mCellAgent.getNetwork()));
11569         servingProxyBroadcast2.expectBroadcast();
11570 
11571         // Expect a broadcast for an empty proxy after wifi disconnected, because cell is now
11572         // the default network and it doesn't have a proxy. Whether "no proxy" is a null pointer
11573         // or a ProxyInfo with an empty host doesn't matter because both are correct, so this test
11574         // accepts both.
11575         final ExpectedBroadcast emptyProxyBroadcast = expectProxyChangeAction(
11576                 proxy -> proxy == null || TextUtils.isEmpty(proxy.getHost()));
11577         mWiFiAgent.disconnect();
11578         emptyProxyBroadcast.expectBroadcast();
11579         wifiCallback.expect(CallbackEntry.LOST, mWiFiAgent);
11580         assertNull(mService.getProxyForNetwork(null));
11581         assertNull(mService.getLinkProperties(mCellAgent.getNetwork()).getHttpProxy());
11582         assertNull(mService.getGlobalProxy());
11583 
11584         mCm.unregisterNetworkCallback(cellCallback);
11585     }
11586 
11587     @Test
11588     public void testPacProxy_NetworkDisconnects_BroadcastSent() throws Exception {
11589         // Make a WiFi network with a PAC URI.
11590         final Uri pacUrl = Uri.parse("https://pac-url");
11591         final ProxyInfo initialProxyInfo = ProxyInfo.buildPacProxy(pacUrl);
11592         final LinkProperties testLinkProperties = new LinkProperties();
11593         testLinkProperties.setHttpProxy(initialProxyInfo);
11594 
11595         final TestNetworkCallback wifiCallback = new TestNetworkCallback();
11596         final NetworkRequest wifiRequest = new NetworkRequest.Builder()
11597                 .addTransportType(TRANSPORT_WIFI).build();
11598         mCm.registerNetworkCallback(wifiRequest, wifiCallback);
11599 
11600         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, testLinkProperties);
11601         mWiFiAgent.connect(true);
11602         // Wifi is up, but the local proxy server hasn't started yet.
11603         wifiCallback.expectAvailableThenValidatedCallbacks(mWiFiAgent);
11604 
11605         // Simulate PacManager sending the notification that the local server has started
11606         final ProxyInfo servingProxyInfo = new ProxyInfo(pacUrl, 2097);
11607         final ExpectedBroadcast servingProxyBroadcast = expectProxyChangeAction(servingProxyInfo);
11608         mService.simulateUpdateProxyInfo(mWiFiAgent.getNetwork(), servingProxyInfo);
11609         wifiCallback.expect(CallbackEntry.LINK_PROPERTIES_CHANGED, mWiFiAgent);
11610         servingProxyBroadcast.expectBroadcast();
11611 
11612         // Now disconnect Wi-Fi and make sure there is a broadcast for some empty proxy. Whether
11613         // the "empty" proxy is a null pointer or a ProxyInfo with an empty host doesn't matter
11614         // because both are correct, so this test accepts both.
11615         final ExpectedBroadcast emptyProxyBroadcast = expectProxyChangeAction(
11616                 proxy -> proxy == null || TextUtils.isEmpty(proxy.getHost()));
11617         mWiFiAgent.disconnect();
11618         wifiCallback.expect(CallbackEntry.LOST, mWiFiAgent);
11619         emptyProxyBroadcast.expectBroadcast();
11620     }
11621 
11622     @Test
11623     public void testGetProxyForVPN() throws Exception {
11624         final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
11625 
11626         // Set up a WiFi network with no proxy
11627         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
11628         mWiFiAgent.connect(true);
11629         waitForIdle();
11630         assertNull(mService.getProxyForNetwork(null));
11631 
11632         // Connect a VPN network with a proxy.
11633         LinkProperties testLinkProperties = new LinkProperties();
11634         testLinkProperties.setHttpProxy(testProxyInfo);
11635         mMockVpn.establishForMyUid(testLinkProperties);
11636         assertUidRangesUpdatedForMyUid(true);
11637 
11638         // Test that the VPN network returns a proxy, and the WiFi does not.
11639         assertEquals(testProxyInfo, mService.getProxyForNetwork(mMockVpn.getNetwork()));
11640         assertEquals(testProxyInfo, mService.getProxyForNetwork(null));
11641         assertNull(mService.getProxyForNetwork(mWiFiAgent.getNetwork()));
11642 
11643         // Test that the VPN network returns no proxy when it is set to null.
11644         testLinkProperties.setHttpProxy(null);
11645         mMockVpn.sendLinkProperties(testLinkProperties);
11646         waitForIdle();
11647         assertNull(mService.getProxyForNetwork(mMockVpn.getNetwork()));
11648         assertNull(mService.getProxyForNetwork(null));
11649 
11650         // Set WiFi proxy and check that the vpn proxy is still null.
11651         testLinkProperties.setHttpProxy(testProxyInfo);
11652         mWiFiAgent.sendLinkProperties(testLinkProperties);
11653         waitForIdle();
11654         assertNull(mService.getProxyForNetwork(null));
11655 
11656         // Disconnect from VPN and check that the active network, which is now the WiFi, has the
11657         // correct proxy setting.
11658         mMockVpn.disconnect();
11659         waitForIdle();
11660         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetwork());
11661         assertEquals(testProxyInfo, mService.getProxyForNetwork(mWiFiAgent.getNetwork()));
11662         assertEquals(testProxyInfo, mService.getProxyForNetwork(null));
11663     }
11664 
11665     @Test
11666     public void testFullyRoutedVpnResultsInInterfaceFilteringRules() throws Exception {
11667         LinkProperties lp = new LinkProperties();
11668         lp.setInterfaceName("tun0");
11669         lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
11670         lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), RTN_UNREACHABLE));
11671         // The uid range needs to cover the test app so the network is visible to it.
11672         final Set<UidRange> vpnRange = Collections.singleton(PRIMARY_UIDRANGE);
11673         mMockVpn.establish(lp, VPN_UID, vpnRange);
11674         assertVpnUidRangesUpdated(true, vpnRange, VPN_UID);
11675 
11676         // A connected VPN should have interface rules set up. There are two expected invocations,
11677         // one during the VPN initial connection, one during the VPN LinkProperties update.
11678         ArgumentCaptor<int[]> uidCaptor = ArgumentCaptor.forClass(int[].class);
11679         verify(mBpfNetMaps, times(2)).addUidInterfaceRules(eq("tun0"), uidCaptor.capture());
11680         assertContainsExactly(uidCaptor.getAllValues().get(0), APP1_UID, APP2_UID);
11681         assertContainsExactly(uidCaptor.getAllValues().get(1), APP1_UID, APP2_UID);
11682 
11683         mMockVpn.disconnect();
11684         waitForIdle();
11685 
11686         // Disconnected VPN should have interface rules removed
11687         verify(mBpfNetMaps).removeUidInterfaceRules(uidCaptor.capture());
11688         assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
11689     }
11690 
11691     private void checkInterfaceFilteringRuleWithNullInterface(final LinkProperties lp,
11692             final int uid) throws Exception {
11693         // The uid range needs to cover the test app so the network is visible to it.
11694         final Set<UidRange> vpnRange = Collections.singleton(PRIMARY_UIDRANGE);
11695         mMockVpn.establish(lp, uid, vpnRange);
11696         assertVpnUidRangesUpdated(true, vpnRange, uid);
11697 
11698         if (mDeps.isAtLeastT()) {
11699             // On T and above, VPN should have rules for null interface. Null Interface is a
11700             // wildcard and this accepts traffic from all the interfaces.
11701             // There are two expected invocations, one during the VPN initial
11702             // connection, one during the VPN LinkProperties update.
11703             ArgumentCaptor<int[]> uidCaptor = ArgumentCaptor.forClass(int[].class);
11704             verify(mBpfNetMaps, times(2)).addUidInterfaceRules(
11705                     eq(null) /* iface */, uidCaptor.capture());
11706             if (uid == VPN_UID) {
11707                 assertContainsExactly(uidCaptor.getAllValues().get(0), APP1_UID, APP2_UID);
11708                 assertContainsExactly(uidCaptor.getAllValues().get(1), APP1_UID, APP2_UID);
11709             } else {
11710                 assertContainsExactly(uidCaptor.getAllValues().get(0), APP1_UID, APP2_UID, VPN_UID);
11711                 assertContainsExactly(uidCaptor.getAllValues().get(1), APP1_UID, APP2_UID, VPN_UID);
11712             }
11713 
11714             mMockVpn.disconnect();
11715             waitForIdle();
11716 
11717             // Disconnected VPN should have interface rules removed
11718             verify(mBpfNetMaps).removeUidInterfaceRules(uidCaptor.capture());
11719             if (uid == VPN_UID) {
11720                 assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
11721             } else {
11722                 assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID, VPN_UID);
11723             }
11724         } else {
11725             // Before T, rules are not configured for null interface.
11726             verify(mBpfNetMaps, never()).addUidInterfaceRules(any(), any());
11727         }
11728     }
11729 
11730     @Test
11731     public void testLegacyVpnInterfaceFilteringRule() throws Exception {
11732         LinkProperties lp = new LinkProperties();
11733         lp.setInterfaceName("tun0");
11734         lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
11735         lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
11736         // Legacy VPN should have interface filtering with null interface.
11737         checkInterfaceFilteringRuleWithNullInterface(lp, Process.SYSTEM_UID);
11738     }
11739 
11740     @Test
11741     public void testLocalIpv4OnlyVpnInterfaceFilteringRule() throws Exception {
11742         LinkProperties lp = new LinkProperties();
11743         lp.setInterfaceName("tun0");
11744         lp.addRoute(new RouteInfo(new IpPrefix("192.0.2.0/24"), null, "tun0"));
11745         lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), RTN_UNREACHABLE));
11746         // VPN that does not provide a default route should have interface filtering with null
11747         // interface.
11748         checkInterfaceFilteringRuleWithNullInterface(lp, VPN_UID);
11749     }
11750 
11751     @Test
11752     public void testVpnHandoverChangesInterfaceFilteringRule() throws Exception {
11753         LinkProperties lp = new LinkProperties();
11754         lp.setInterfaceName("tun0");
11755         lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
11756         lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
11757         // The uid range needs to cover the test app so the network is visible to it.
11758         final Set<UidRange> vpnRange = Collections.singleton(PRIMARY_UIDRANGE);
11759         mMockVpn.establish(lp, VPN_UID, vpnRange);
11760         assertVpnUidRangesUpdated(true, vpnRange, VPN_UID);
11761 
11762         // Connected VPN should have interface rules set up. There are two expected invocations,
11763         // one during VPN uid update, one during VPN LinkProperties update
11764         ArgumentCaptor<int[]> uidCaptor = ArgumentCaptor.forClass(int[].class);
11765         verify(mBpfNetMaps, times(2)).addUidInterfaceRules(eq("tun0"), uidCaptor.capture());
11766         assertContainsExactly(uidCaptor.getAllValues().get(0), APP1_UID, APP2_UID);
11767         assertContainsExactly(uidCaptor.getAllValues().get(1), APP1_UID, APP2_UID);
11768 
11769         reset(mBpfNetMaps);
11770         InOrder inOrder = inOrder(mBpfNetMaps);
11771         lp.setInterfaceName("tun1");
11772         mMockVpn.sendLinkProperties(lp);
11773         waitForIdle();
11774         // VPN handover (switch to a new interface) should result in rules being updated (old rules
11775         // removed first, then new rules added)
11776         inOrder.verify(mBpfNetMaps).removeUidInterfaceRules(uidCaptor.capture());
11777         assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
11778         inOrder.verify(mBpfNetMaps).addUidInterfaceRules(eq("tun1"), uidCaptor.capture());
11779         assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
11780 
11781         reset(mBpfNetMaps);
11782         lp = new LinkProperties();
11783         lp.setInterfaceName("tun1");
11784         lp.addRoute(new RouteInfo(new IpPrefix("192.0.2.0/24"), null, "tun1"));
11785         mMockVpn.sendLinkProperties(lp);
11786         waitForIdle();
11787         // VPN not routing everything should no longer have interface filtering rules
11788         verify(mBpfNetMaps).removeUidInterfaceRules(uidCaptor.capture());
11789         assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
11790 
11791         reset(mBpfNetMaps);
11792         lp = new LinkProperties();
11793         lp.setInterfaceName("tun1");
11794         lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), RTN_UNREACHABLE));
11795         lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
11796         mMockVpn.sendLinkProperties(lp);
11797         waitForIdle();
11798         // Back to routing all IPv6 traffic should have filtering rules
11799         verify(mBpfNetMaps).addUidInterfaceRules(eq("tun1"), uidCaptor.capture());
11800         assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
11801     }
11802 
11803     @Test
11804     public void testUidUpdateChangesInterfaceFilteringRule() throws Exception {
11805         LinkProperties lp = new LinkProperties();
11806         lp.setInterfaceName("tun0");
11807         lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), RTN_UNREACHABLE));
11808         lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
11809         // The uid range needs to cover the test app so the network is visible to it.
11810         final UidRange vpnRange = PRIMARY_UIDRANGE;
11811         final Set<UidRange> vpnRanges = Collections.singleton(vpnRange);
11812         mMockVpn.establish(lp, VPN_UID, vpnRanges);
11813         assertVpnUidRangesUpdated(true, vpnRanges, VPN_UID);
11814 
11815         reset(mBpfNetMaps);
11816         InOrder inOrder = inOrder(mBpfNetMaps);
11817 
11818         // Update to new range which is old range minus APP1, i.e. only APP2
11819         final Set<UidRange> newRanges = new HashSet<>(asList(
11820                 new UidRange(vpnRange.start, APP1_UID - 1),
11821                 new UidRange(APP1_UID + 1, vpnRange.stop)));
11822         mMockVpn.setUids(newRanges);
11823         waitForIdle();
11824 
11825         ArgumentCaptor<int[]> uidCaptor = ArgumentCaptor.forClass(int[].class);
11826         // Verify old rules are removed before new rules are added
11827         inOrder.verify(mBpfNetMaps).removeUidInterfaceRules(uidCaptor.capture());
11828         assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
11829         inOrder.verify(mBpfNetMaps).addUidInterfaceRules(eq("tun0"), uidCaptor.capture());
11830         assertContainsExactly(uidCaptor.getValue(), APP2_UID);
11831     }
11832 
11833     @Test
11834     public void testLinkPropertiesWithWakeOnLanForActiveNetwork() throws Exception {
11835         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
11836 
11837         LinkProperties wifiLp = new LinkProperties();
11838         wifiLp.setInterfaceName(WIFI_WOL_IFNAME);
11839         wifiLp.setWakeOnLanSupported(false);
11840 
11841         // Default network switch should update ifaces.
11842         mWiFiAgent.connect(false);
11843         mWiFiAgent.sendLinkProperties(wifiLp);
11844         waitForIdle();
11845 
11846         // ConnectivityService should have changed the WakeOnLanSupported to true
11847         wifiLp.setWakeOnLanSupported(true);
11848         assertEquals(wifiLp, mService.getActiveLinkProperties());
11849     }
11850 
11851     @Test
11852     public void testLegacyExtraInfoSentToNetworkMonitor() throws Exception {
11853         class TestNetworkAgent extends NetworkAgent {
11854             TestNetworkAgent(Context context, Looper looper, NetworkAgentConfig config) {
11855                 super(context, looper, "MockAgent", new NetworkCapabilities(),
11856                         new LinkProperties(), 40 , config, null /* provider */);
11857             }
11858         }
11859         final NetworkAgent naNoExtraInfo = new TestNetworkAgent(
11860                 mServiceContext, mCsHandlerThread.getLooper(), new NetworkAgentConfig());
11861         naNoExtraInfo.register();
11862         verify(mNetworkStack).makeNetworkMonitor(any(), isNull(String.class), any());
11863         naNoExtraInfo.unregister();
11864 
11865         reset(mNetworkStack);
11866         final NetworkAgentConfig config =
11867                 new NetworkAgentConfig.Builder().setLegacyExtraInfo("legacyinfo").build();
11868         final NetworkAgent naExtraInfo = new TestNetworkAgent(
11869                 mServiceContext, mCsHandlerThread.getLooper(), config);
11870         naExtraInfo.register();
11871         verify(mNetworkStack).makeNetworkMonitor(any(), eq("legacyinfo"), any());
11872         naExtraInfo.unregister();
11873     }
11874 
11875     // To avoid granting location permission bypass.
11876     private void denyAllLocationPrivilegedPermissions() {
11877         mServiceContext.setPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
11878                 PERMISSION_DENIED);
11879         mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_DENIED);
11880         mServiceContext.setPermission(NETWORK_STACK, PERMISSION_DENIED);
11881         mServiceContext.setPermission(Manifest.permission.NETWORK_SETUP_WIZARD,
11882                 PERMISSION_DENIED);
11883     }
11884 
11885     private void setupLocationPermissions(
11886             int targetSdk, boolean locationToggle, String op, String perm) throws Exception {
11887         denyAllLocationPrivilegedPermissions();
11888 
11889         final ApplicationInfo applicationInfo = new ApplicationInfo();
11890         applicationInfo.targetSdkVersion = targetSdk;
11891         doReturn(applicationInfo).when(mPackageManager)
11892                 .getApplicationInfoAsUser(anyString(), anyInt(), any());
11893         doReturn(targetSdk).when(mPackageManager).getTargetSdkVersion(any());
11894 
11895         doReturn(locationToggle).when(mLocationManager).isLocationEnabledForUser(any());
11896 
11897         if (op != null) {
11898             doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOpsManager).noteOp(
11899                     eq(op), eq(Process.myUid()), eq(mContext.getPackageName()),
11900                     eq(getAttributionTag()), anyString());
11901         }
11902 
11903         if (perm != null) {
11904             mServiceContext.setPermission(perm, PERMISSION_GRANTED);
11905         }
11906     }
11907 
11908     private int getOwnerUidNetCapsPermission(int ownerUid, int callerUid,
11909             boolean includeLocationSensitiveInfo) {
11910         final NetworkCapabilities netCap = new NetworkCapabilities().setOwnerUid(ownerUid);
11911 
11912         return mService.createWithLocationInfoSanitizedIfNecessaryWhenParceled(
11913                 netCap, includeLocationSensitiveInfo, Process.myUid(), callerUid,
11914                 mContext.getPackageName(), getAttributionTag())
11915                 .getOwnerUid();
11916     }
11917 
11918     private void verifyTransportInfoCopyNetCapsPermission(
11919             int callerUid, boolean includeLocationSensitiveInfo,
11920             boolean shouldMakeCopyWithLocationSensitiveFieldsParcelable) {
11921         final TransportInfo transportInfo = mock(TransportInfo.class);
11922         doReturn(REDACT_FOR_ACCESS_FINE_LOCATION).when(transportInfo).getApplicableRedactions();
11923         final NetworkCapabilities netCap =
11924                 new NetworkCapabilities().setTransportInfo(transportInfo);
11925 
11926         mService.createWithLocationInfoSanitizedIfNecessaryWhenParceled(
11927                 netCap, includeLocationSensitiveInfo, Process.myPid(), callerUid,
11928                 mContext.getPackageName(), getAttributionTag());
11929         if (shouldMakeCopyWithLocationSensitiveFieldsParcelable) {
11930             verify(transportInfo).makeCopy(REDACT_NONE);
11931         } else {
11932             verify(transportInfo).makeCopy(REDACT_FOR_ACCESS_FINE_LOCATION);
11933         }
11934     }
11935 
11936     private void verifyOwnerUidAndTransportInfoNetCapsPermission(
11937             boolean shouldInclLocationSensitiveOwnerUidWithoutIncludeFlag,
11938             boolean shouldInclLocationSensitiveOwnerUidWithIncludeFlag,
11939             boolean shouldInclLocationSensitiveTransportInfoWithoutIncludeFlag,
11940             boolean shouldInclLocationSensitiveTransportInfoWithIncludeFlag) {
11941         final int myUid = Process.myUid();
11942 
11943         final int expectedOwnerUidWithoutIncludeFlag =
11944                 shouldInclLocationSensitiveOwnerUidWithoutIncludeFlag
11945                         ? myUid : INVALID_UID;
11946         assertEquals(expectedOwnerUidWithoutIncludeFlag, getOwnerUidNetCapsPermission(
11947                 myUid, myUid, false /* includeLocationSensitiveInfo */));
11948 
11949         final int expectedOwnerUidWithIncludeFlag =
11950                 shouldInclLocationSensitiveOwnerUidWithIncludeFlag ? myUid : INVALID_UID;
11951         assertEquals(expectedOwnerUidWithIncludeFlag, getOwnerUidNetCapsPermission(
11952                 myUid, myUid, true /* includeLocationSensitiveInfo */));
11953 
11954         verifyTransportInfoCopyNetCapsPermission(myUid,
11955                 false, /* includeLocationSensitiveInfo */
11956                 shouldInclLocationSensitiveTransportInfoWithoutIncludeFlag);
11957 
11958         verifyTransportInfoCopyNetCapsPermission(myUid,
11959                 true, /* includeLocationSensitiveInfo */
11960                 shouldInclLocationSensitiveTransportInfoWithIncludeFlag);
11961 
11962     }
11963 
11964     private void verifyOwnerUidAndTransportInfoNetCapsPermissionPreS() {
11965         verifyOwnerUidAndTransportInfoNetCapsPermission(
11966                 // Ensure that owner uid is included even if the request asks to remove it (which is
11967                 // the default) since the app has necessary permissions and targetSdk < S.
11968                 true, /* shouldInclLocationSensitiveOwnerUidWithoutIncludeFlag */
11969                 true, /* shouldInclLocationSensitiveOwnerUidWithIncludeFlag */
11970                 // Ensure that location info is removed if the request asks to remove it even if the
11971                 // app has necessary permissions.
11972                 false, /* shouldInclLocationSensitiveTransportInfoWithoutIncludeFlag */
11973                 true /* shouldInclLocationSensitiveTransportInfoWithIncludeFlag */
11974         );
11975     }
11976 
11977     @Test
11978     public void testCreateWithLocationInfoSanitizedWithFineLocationAfterQPreS()
11979             throws Exception {
11980         setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
11981                 Manifest.permission.ACCESS_FINE_LOCATION);
11982 
11983         verifyOwnerUidAndTransportInfoNetCapsPermissionPreS();
11984     }
11985 
11986     @Test
11987     public void testCreateWithLocationInfoSanitizedWithFineLocationPreSWithAndWithoutCallbackFlag()
11988             throws Exception {
11989         setupLocationPermissions(Build.VERSION_CODES.R, true, AppOpsManager.OPSTR_FINE_LOCATION,
11990                 Manifest.permission.ACCESS_FINE_LOCATION);
11991 
11992         verifyOwnerUidAndTransportInfoNetCapsPermissionPreS();
11993     }
11994 
11995     @Test
11996     public void
11997             testCreateWithLocationInfoSanitizedWithFineLocationAfterSWithAndWithoutCallbackFlag()
11998             throws Exception {
11999         setupLocationPermissions(Build.VERSION_CODES.S, true, AppOpsManager.OPSTR_FINE_LOCATION,
12000                 Manifest.permission.ACCESS_FINE_LOCATION);
12001 
12002         verifyOwnerUidAndTransportInfoNetCapsPermission(
12003                 // Ensure that the owner UID is removed if the request asks us to remove it even
12004                 // if the app has necessary permissions since targetSdk >= S.
12005                 false, /* shouldInclLocationSensitiveOwnerUidWithoutIncludeFlag */
12006                 true, /* shouldInclLocationSensitiveOwnerUidWithIncludeFlag */
12007                 // Ensure that location info is removed if the request asks to remove it even if the
12008                 // app has necessary permissions.
12009                 false, /* shouldInclLocationSensitiveTransportInfoWithoutIncludeFlag */
12010                 true /* shouldInclLocationSensitiveTransportInfoWithIncludeFlag */
12011         );
12012     }
12013 
12014     @Test
12015     public void testCreateWithLocationInfoSanitizedWithCoarseLocationPreQ()
12016             throws Exception {
12017         setupLocationPermissions(Build.VERSION_CODES.P, true, AppOpsManager.OPSTR_COARSE_LOCATION,
12018                 Manifest.permission.ACCESS_COARSE_LOCATION);
12019 
12020         verifyOwnerUidAndTransportInfoNetCapsPermissionPreS();
12021     }
12022 
12023     private void verifyOwnerUidAndTransportInfoNetCapsNotIncluded() {
12024         verifyOwnerUidAndTransportInfoNetCapsPermission(
12025                 false, /* shouldInclLocationSensitiveOwnerUidWithoutIncludeFlag */
12026                 false, /* shouldInclLocationSensitiveOwnerUidWithIncludeFlag */
12027                 false, /* shouldInclLocationSensitiveTransportInfoWithoutIncludeFlag */
12028                 false /* shouldInclLocationSensitiveTransportInfoWithIncludeFlag */
12029         );
12030     }
12031 
12032     @Test
12033     public void testCreateWithLocationInfoSanitizedLocationOff() throws Exception {
12034         // Test that even with fine location permission, and UIDs matching, the UID is sanitized.
12035         setupLocationPermissions(Build.VERSION_CODES.Q, false, AppOpsManager.OPSTR_FINE_LOCATION,
12036                 Manifest.permission.ACCESS_FINE_LOCATION);
12037 
12038         verifyOwnerUidAndTransportInfoNetCapsNotIncluded();
12039     }
12040 
12041     @Test
12042     public void testCreateWithLocationInfoSanitizedWrongUid() throws Exception {
12043         // Test that even with fine location permission, not being the owner leads to sanitization.
12044         setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
12045                 Manifest.permission.ACCESS_FINE_LOCATION);
12046 
12047         final int myUid = Process.myUid();
12048         assertEquals(Process.INVALID_UID,
12049                 getOwnerUidNetCapsPermission(myUid + 1, myUid,
12050                         true /* includeLocationSensitiveInfo */));
12051     }
12052 
12053     @Test
12054     public void testCreateWithLocationInfoSanitizedWithCoarseLocationAfterQ()
12055             throws Exception {
12056         // Test that not having fine location permission leads to sanitization.
12057         setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_COARSE_LOCATION,
12058                 Manifest.permission.ACCESS_COARSE_LOCATION);
12059 
12060         verifyOwnerUidAndTransportInfoNetCapsNotIncluded();
12061     }
12062 
12063     @Test
12064     public void testCreateWithLocationInfoSanitizedWithCoarseLocationAfterS()
12065             throws Exception {
12066         // Test that not having fine location permission leads to sanitization.
12067         setupLocationPermissions(Build.VERSION_CODES.S, true, AppOpsManager.OPSTR_COARSE_LOCATION,
12068                 Manifest.permission.ACCESS_COARSE_LOCATION);
12069 
12070         verifyOwnerUidAndTransportInfoNetCapsNotIncluded();
12071     }
12072 
12073     @Test
12074     public void testCreateForCallerWithLocalMacAddressSanitizedWithLocalMacAddressPermission()
12075             throws Exception {
12076         mServiceContext.setPermission(Manifest.permission.LOCAL_MAC_ADDRESS, PERMISSION_GRANTED);
12077 
12078         final TransportInfo transportInfo = mock(TransportInfo.class);
12079         doReturn(REDACT_FOR_ACCESS_FINE_LOCATION | REDACT_FOR_LOCAL_MAC_ADDRESS)
12080                 .when(transportInfo).getApplicableRedactions();
12081         final NetworkCapabilities netCap =
12082                 new NetworkCapabilities().setTransportInfo(transportInfo);
12083 
12084         mService.createWithLocationInfoSanitizedIfNecessaryWhenParceled(
12085                 netCap, false /* includeLocationSensitiveInfoInTransportInfo */,
12086                 Process.myPid(), Process.myUid(),
12087                 mContext.getPackageName(), getAttributionTag());
12088         // don't redact MAC_ADDRESS fields, only location sensitive fields.
12089         verify(transportInfo).makeCopy(REDACT_FOR_ACCESS_FINE_LOCATION);
12090     }
12091 
12092     @Test
12093     public void testCreateForCallerWithLocalMacAddressSanitizedWithoutLocalMacAddressPermission()
12094             throws Exception {
12095         mServiceContext.setPermission(Manifest.permission.LOCAL_MAC_ADDRESS, PERMISSION_DENIED);
12096 
12097         final TransportInfo transportInfo = mock(TransportInfo.class);
12098         doReturn(REDACT_FOR_ACCESS_FINE_LOCATION | REDACT_FOR_LOCAL_MAC_ADDRESS)
12099                 .when(transportInfo).getApplicableRedactions();
12100         final NetworkCapabilities netCap =
12101                 new NetworkCapabilities().setTransportInfo(transportInfo);
12102 
12103         mService.createWithLocationInfoSanitizedIfNecessaryWhenParceled(
12104                 netCap, false /* includeLocationSensitiveInfoInTransportInfo */,
12105                 Process.myPid(), Process.myUid(),
12106                 mContext.getPackageName(), getAttributionTag());
12107         // redact both MAC_ADDRESS & location sensitive fields.
12108         verify(transportInfo).makeCopy(REDACT_FOR_ACCESS_FINE_LOCATION
12109                 | REDACT_FOR_LOCAL_MAC_ADDRESS);
12110     }
12111 
12112     @Test
12113     public void testCreateForCallerWithLocalMacAddressSanitizedWithSettingsPermission()
12114             throws Exception {
12115         mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_GRANTED);
12116 
12117         final TransportInfo transportInfo = mock(TransportInfo.class);
12118         doReturn(REDACT_FOR_ACCESS_FINE_LOCATION | REDACT_FOR_NETWORK_SETTINGS)
12119                 .when(transportInfo).getApplicableRedactions();
12120         final NetworkCapabilities netCap =
12121                 new NetworkCapabilities().setTransportInfo(transportInfo);
12122 
12123         mService.createWithLocationInfoSanitizedIfNecessaryWhenParceled(
12124                 netCap, false /* includeLocationSensitiveInfoInTransportInfo */,
12125                 Process.myPid(), Process.myUid(),
12126                 mContext.getPackageName(), getAttributionTag());
12127         // don't redact NETWORK_SETTINGS fields, only location sensitive fields.
12128         verify(transportInfo).makeCopy(REDACT_FOR_ACCESS_FINE_LOCATION);
12129     }
12130 
12131     @Test
12132     public void testCreateForCallerWithLocalMacAddressSanitizedWithoutSettingsPermission()
12133             throws Exception {
12134         mServiceContext.setPermission(Manifest.permission.LOCAL_MAC_ADDRESS, PERMISSION_DENIED);
12135 
12136         final TransportInfo transportInfo = mock(TransportInfo.class);
12137         doReturn(REDACT_FOR_ACCESS_FINE_LOCATION | REDACT_FOR_NETWORK_SETTINGS)
12138                 .when(transportInfo).getApplicableRedactions();
12139         final NetworkCapabilities netCap =
12140                 new NetworkCapabilities().setTransportInfo(transportInfo);
12141 
12142         mService.createWithLocationInfoSanitizedIfNecessaryWhenParceled(
12143                 netCap, false /* includeLocationSensitiveInfoInTransportInfo */,
12144                 Process.myPid(), Process.myUid(),
12145                 mContext.getPackageName(), getAttributionTag());
12146         // redact both NETWORK_SETTINGS & location sensitive fields.
12147         verify(transportInfo).makeCopy(
12148                 REDACT_FOR_ACCESS_FINE_LOCATION | REDACT_FOR_NETWORK_SETTINGS);
12149     }
12150 
12151     /**
12152      * Test TransportInfo to verify redaction mechanism.
12153      */
12154     private static class TestTransportInfo implements TransportInfo {
12155         public final boolean locationRedacted;
12156         public final boolean localMacAddressRedacted;
12157         public final boolean settingsRedacted;
12158 
12159         TestTransportInfo() {
12160             locationRedacted = false;
12161             localMacAddressRedacted = false;
12162             settingsRedacted = false;
12163         }
12164 
12165         TestTransportInfo(boolean locationRedacted, boolean localMacAddressRedacted,
12166                 boolean settingsRedacted) {
12167             this.locationRedacted = locationRedacted;
12168             this.localMacAddressRedacted =
12169                     localMacAddressRedacted;
12170             this.settingsRedacted = settingsRedacted;
12171         }
12172 
12173         @Override
12174         public TransportInfo makeCopy(@NetworkCapabilities.RedactionType long redactions) {
12175             return new TestTransportInfo(
12176                     locationRedacted | (redactions & REDACT_FOR_ACCESS_FINE_LOCATION) != 0,
12177                     localMacAddressRedacted | (redactions & REDACT_FOR_LOCAL_MAC_ADDRESS) != 0,
12178                     settingsRedacted | (redactions & REDACT_FOR_NETWORK_SETTINGS) != 0
12179             );
12180         }
12181 
12182         @Override
12183         public @NetworkCapabilities.RedactionType long getApplicableRedactions() {
12184             return REDACT_FOR_ACCESS_FINE_LOCATION | REDACT_FOR_LOCAL_MAC_ADDRESS
12185                     | REDACT_FOR_NETWORK_SETTINGS;
12186         }
12187 
12188         @Override
12189         public boolean equals(Object other) {
12190             if (!(other instanceof TestTransportInfo)) return false;
12191             TestTransportInfo that = (TestTransportInfo) other;
12192             return that.locationRedacted == this.locationRedacted
12193                     && that.localMacAddressRedacted == this.localMacAddressRedacted
12194                     && that.settingsRedacted == this.settingsRedacted;
12195         }
12196 
12197         @Override
12198         public int hashCode() {
12199             return Objects.hash(locationRedacted, localMacAddressRedacted, settingsRedacted);
12200         }
12201 
12202         @Override
12203         public String toString() {
12204             return String.format(
12205                     "TestTransportInfo{locationRedacted=%s macRedacted=%s settingsRedacted=%s}",
12206                     locationRedacted, localMacAddressRedacted, settingsRedacted);
12207         }
12208     }
12209 
12210     private TestTransportInfo getTestTransportInfo(NetworkCapabilities nc) {
12211         return (TestTransportInfo) nc.getTransportInfo();
12212     }
12213 
12214     private TestTransportInfo getTestTransportInfo(TestNetworkAgentWrapper n) {
12215         final NetworkCapabilities nc = mCm.getNetworkCapabilities(n.getNetwork());
12216         assertNotNull(nc);
12217         return getTestTransportInfo(nc);
12218     }
12219 
12220 
12221     private void verifyNetworkCallbackLocationDataInclusionUsingTransportInfoAndOwnerUidInNetCaps(
12222             @NonNull TestNetworkCallback wifiNetworkCallback, int actualOwnerUid,
12223             @NonNull TransportInfo actualTransportInfo, int expectedOwnerUid,
12224             @NonNull TransportInfo expectedTransportInfo) throws Exception {
12225         doReturn(Build.VERSION_CODES.S).when(mPackageManager).getTargetSdkVersion(anyString());
12226         final NetworkCapabilities ncTemplate =
12227                 new NetworkCapabilities()
12228                         .addTransportType(TRANSPORT_WIFI)
12229                         .setOwnerUid(actualOwnerUid);
12230 
12231         final NetworkRequest wifiRequest = new NetworkRequest.Builder()
12232                 .addTransportType(TRANSPORT_WIFI).build();
12233         mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
12234 
12235         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, new LinkProperties(),
12236                 ncTemplate);
12237         mWiFiAgent.connect(false);
12238 
12239         wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
12240 
12241         // Send network capabilities update with TransportInfo to trigger capabilities changed
12242         // callback.
12243         mWiFiAgent.setNetworkCapabilities(ncTemplate.setTransportInfo(actualTransportInfo), true);
12244 
12245         wifiNetworkCallback.expectCaps(mWiFiAgent,
12246                 c -> Objects.equals(expectedOwnerUid, c.getOwnerUid())
12247                         && Objects.equals(expectedTransportInfo, c.getTransportInfo()));
12248     }
12249 
12250     @Test
12251     public void testVerifyLocationDataIsNotIncludedWhenInclFlagNotSet() throws Exception {
12252         final TestNetworkCallback wifiNetworkCallack = new TestNetworkCallback();
12253         final int ownerUid = Process.myUid();
12254         final TransportInfo transportInfo = new TestTransportInfo();
12255         // Even though the test uid holds privileged permissions, mask location fields since
12256         // the callback did not explicitly opt-in to get location data.
12257         final TransportInfo sanitizedTransportInfo = new TestTransportInfo(
12258                 true, /* locationRedacted */
12259                 true, /* localMacAddressRedacted */
12260                 true /* settingsRedacted */
12261         );
12262         // Should not expect location data since the callback does not set the flag for including
12263         // location data.
12264         verifyNetworkCallbackLocationDataInclusionUsingTransportInfoAndOwnerUidInNetCaps(
12265                 wifiNetworkCallack, ownerUid, transportInfo, INVALID_UID, sanitizedTransportInfo);
12266     }
12267 
12268     @Test
12269     public void testTransportInfoRedactionInSynchronousCalls() throws Exception {
12270         final NetworkCapabilities ncTemplate = new NetworkCapabilities()
12271                 .addTransportType(TRANSPORT_WIFI)
12272                 .setTransportInfo(new TestTransportInfo());
12273 
12274         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, new LinkProperties(), ncTemplate);
12275         mWiFiAgent.connect(true /* validated; waits for callback */);
12276 
12277         // NETWORK_SETTINGS redaction is controlled by the NETWORK_SETTINGS permission
12278         assertTrue(getTestTransportInfo(mWiFiAgent).settingsRedacted);
12279         withPermission(NETWORK_SETTINGS, () -> {
12280             assertFalse(getTestTransportInfo(mWiFiAgent).settingsRedacted);
12281         });
12282         assertTrue(getTestTransportInfo(mWiFiAgent).settingsRedacted);
12283 
12284         // LOCAL_MAC_ADDRESS redaction is controlled by the LOCAL_MAC_ADDRESS permission
12285         assertTrue(getTestTransportInfo(mWiFiAgent).localMacAddressRedacted);
12286         withPermission(LOCAL_MAC_ADDRESS, () -> {
12287             assertFalse(getTestTransportInfo(mWiFiAgent).localMacAddressRedacted);
12288         });
12289         assertTrue(getTestTransportInfo(mWiFiAgent).localMacAddressRedacted);
12290 
12291         // Synchronous getNetworkCapabilities calls never return unredacted location-sensitive
12292         // information.
12293         assertTrue(getTestTransportInfo(mWiFiAgent).locationRedacted);
12294         setupLocationPermissions(Build.VERSION_CODES.S, true, AppOpsManager.OPSTR_FINE_LOCATION,
12295                 Manifest.permission.ACCESS_FINE_LOCATION);
12296         assertTrue(getTestTransportInfo(mWiFiAgent).locationRedacted);
12297         denyAllLocationPrivilegedPermissions();
12298         assertTrue(getTestTransportInfo(mWiFiAgent).locationRedacted);
12299     }
12300 
12301     private void setupConnectionOwnerUid(int vpnOwnerUid, @VpnManager.VpnType int vpnType)
12302             throws Exception {
12303         final Set<UidRange> vpnRange = Collections.singleton(PRIMARY_UIDRANGE);
12304         mMockVpn.setVpnType(vpnType);
12305         mMockVpn.establish(new LinkProperties(), vpnOwnerUid, vpnRange);
12306         assertVpnUidRangesUpdated(true, vpnRange, vpnOwnerUid);
12307 
12308         final UnderlyingNetworkInfo underlyingNetworkInfo =
12309                 new UnderlyingNetworkInfo(vpnOwnerUid, VPN_IFNAME, new ArrayList<>());
12310         mMockVpn.setUnderlyingNetworkInfo(underlyingNetworkInfo);
12311         mDeps.setConnectionOwnerUid(42);
12312     }
12313 
12314     private void setupConnectionOwnerUidAsVpnApp(int vpnOwnerUid, @VpnManager.VpnType int vpnType)
12315             throws Exception {
12316         setupConnectionOwnerUid(vpnOwnerUid, vpnType);
12317 
12318         // Test as VPN app
12319         mServiceContext.setPermission(NETWORK_STACK, PERMISSION_DENIED);
12320         mServiceContext.setPermission(
12321                 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, PERMISSION_DENIED);
12322     }
12323 
12324     private ConnectionInfo getTestConnectionInfo() throws Exception {
12325         return new ConnectionInfo(
12326                 IPPROTO_TCP,
12327                 new InetSocketAddress(InetAddresses.parseNumericAddress("1.2.3.4"), 1234),
12328                 new InetSocketAddress(InetAddresses.parseNumericAddress("2.3.4.5"), 2345));
12329     }
12330 
12331     @Test
12332     public void testGetConnectionOwnerUidPlatformVpn() throws Exception {
12333         final int myUid = Process.myUid();
12334         setupConnectionOwnerUidAsVpnApp(myUid, VpnManager.TYPE_VPN_PLATFORM);
12335 
12336         assertEquals(INVALID_UID, mService.getConnectionOwnerUid(getTestConnectionInfo()));
12337     }
12338 
12339     @Test
12340     public void testGetConnectionOwnerUidVpnServiceWrongUser() throws Exception {
12341         final int myUid = Process.myUid();
12342         setupConnectionOwnerUidAsVpnApp(myUid + 1, VpnManager.TYPE_VPN_SERVICE);
12343 
12344         assertEquals(INVALID_UID, mService.getConnectionOwnerUid(getTestConnectionInfo()));
12345     }
12346 
12347     @Test
12348     public void testGetConnectionOwnerUidVpnServiceDoesNotThrow() throws Exception {
12349         final int myUid = Process.myUid();
12350         setupConnectionOwnerUidAsVpnApp(myUid, VpnManager.TYPE_VPN_SERVICE);
12351 
12352         assertEquals(42, mService.getConnectionOwnerUid(getTestConnectionInfo()));
12353     }
12354 
12355     @Test
12356     public void testGetConnectionOwnerUidVpnServiceNetworkStackDoesNotThrow() throws Exception {
12357         final int myUid = Process.myUid();
12358         setupConnectionOwnerUid(myUid, VpnManager.TYPE_VPN_SERVICE);
12359         mServiceContext.setPermission(NETWORK_STACK, PERMISSION_GRANTED);
12360 
12361         assertEquals(42, mService.getConnectionOwnerUid(getTestConnectionInfo()));
12362     }
12363 
12364     @Test
12365     public void testGetConnectionOwnerUidVpnServiceMainlineNetworkStackDoesNotThrow()
12366             throws Exception {
12367         final int myUid = Process.myUid();
12368         setupConnectionOwnerUid(myUid, VpnManager.TYPE_VPN_SERVICE);
12369         mServiceContext.setPermission(
12370                 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, PERMISSION_GRANTED);
12371 
12372         assertEquals(42, mService.getConnectionOwnerUid(getTestConnectionInfo()));
12373     }
12374 
12375     private static PackageInfo buildPackageInfo(boolean hasSystemPermission, int uid) {
12376         final PackageInfo packageInfo = new PackageInfo();
12377         if (hasSystemPermission) {
12378             packageInfo.requestedPermissions = new String[] {
12379                     CHANGE_NETWORK_STATE, CONNECTIVITY_USE_RESTRICTED_NETWORKS };
12380             packageInfo.requestedPermissionsFlags = new int[] {
12381                     REQUESTED_PERMISSION_GRANTED, REQUESTED_PERMISSION_GRANTED };
12382         } else {
12383             packageInfo.requestedPermissions = new String[0];
12384         }
12385         packageInfo.applicationInfo = new ApplicationInfo();
12386         packageInfo.applicationInfo.privateFlags = 0;
12387         packageInfo.applicationInfo.uid = UserHandle.getUid(UserHandle.USER_SYSTEM,
12388                 UserHandle.getAppId(uid));
12389         return packageInfo;
12390     }
12391 
12392     @Test
12393     public void testRegisterConnectivityDiagnosticsCallbackInvalidRequest() throws Exception {
12394         final NetworkRequest request =
12395                 new NetworkRequest(
12396                         new NetworkCapabilities(), TYPE_ETHERNET, 0, NetworkRequest.Type.NONE);
12397         try {
12398             mService.registerConnectivityDiagnosticsCallback(
12399                     mConnectivityDiagnosticsCallback, request, mContext.getPackageName());
12400             fail("registerConnectivityDiagnosticsCallback should throw on invalid NetworkRequest");
12401         } catch (IllegalArgumentException expected) {
12402         }
12403     }
12404 
12405     private void assertRouteInfoParcelMatches(RouteInfo route, RouteInfoParcel parcel) {
12406         assertEquals(route.getDestination().toString(), parcel.destination);
12407         assertEquals(route.getInterface(), parcel.ifName);
12408         assertEquals(route.getMtu(), parcel.mtu);
12409 
12410         switch (route.getType()) {
12411             case RouteInfo.RTN_UNICAST:
12412                 if (route.hasGateway()) {
12413                     assertEquals(route.getGateway().getHostAddress(), parcel.nextHop);
12414                 } else {
12415                     assertEquals(INetd.NEXTHOP_NONE, parcel.nextHop);
12416                 }
12417                 break;
12418             case RouteInfo.RTN_UNREACHABLE:
12419                 assertEquals(INetd.NEXTHOP_UNREACHABLE, parcel.nextHop);
12420                 break;
12421             case RouteInfo.RTN_THROW:
12422                 assertEquals(INetd.NEXTHOP_THROW, parcel.nextHop);
12423                 break;
12424             default:
12425                 assertEquals(INetd.NEXTHOP_NONE, parcel.nextHop);
12426                 break;
12427         }
12428     }
12429 
12430     private void assertRoutesAdded(int netId, RouteInfo... routes) throws Exception {
12431         // TODO: add @JavaDerive(equals=true) to RouteInfoParcel, use eq() directly, and delete
12432         // assertRouteInfoParcelMatches above.
12433         ArgumentCaptor<RouteInfoParcel> captor = ArgumentCaptor.forClass(RouteInfoParcel.class);
12434         verify(mMockNetd, times(routes.length)).networkAddRouteParcel(eq(netId), captor.capture());
12435         for (int i = 0; i < routes.length; i++) {
12436             assertRouteInfoParcelMatches(routes[i], captor.getAllValues().get(i));
12437         }
12438     }
12439 
12440     private void assertRoutesRemoved(int netId, RouteInfo... routes) throws Exception {
12441         ArgumentCaptor<RouteInfoParcel> captor = ArgumentCaptor.forClass(RouteInfoParcel.class);
12442         verify(mMockNetd, times(routes.length)).networkRemoveRouteParcel(eq(netId),
12443                 captor.capture());
12444         for (int i = 0; i < routes.length; i++) {
12445             assertRouteInfoParcelMatches(routes[i], captor.getAllValues().get(i));
12446         }
12447     }
12448 
12449     @Test
12450     public void testRegisterUnregisterConnectivityDiagnosticsCallback() throws Exception {
12451         final NetworkRequest wifiRequest =
12452                 new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI).build();
12453         doReturn(mIBinder).when(mConnectivityDiagnosticsCallback).asBinder();
12454 
12455         mService.registerConnectivityDiagnosticsCallback(
12456                 mConnectivityDiagnosticsCallback, wifiRequest, mContext.getPackageName());
12457 
12458         // Block until all other events are done processing.
12459         HandlerUtils.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
12460 
12461         verify(mIBinder).linkToDeath(any(ConnectivityDiagnosticsCallbackInfo.class), anyInt());
12462         verify(mConnectivityDiagnosticsCallback).asBinder();
12463         assertTrue(mService.mConnectivityDiagnosticsCallbacks.containsKey(mIBinder));
12464 
12465         mService.unregisterConnectivityDiagnosticsCallback(mConnectivityDiagnosticsCallback);
12466         verify(mIBinder, timeout(TIMEOUT_MS))
12467                 .unlinkToDeath(any(ConnectivityDiagnosticsCallbackInfo.class), anyInt());
12468         assertFalse(mService.mConnectivityDiagnosticsCallbacks.containsKey(mIBinder));
12469         verify(mConnectivityDiagnosticsCallback, atLeastOnce()).asBinder();
12470     }
12471 
12472     @Test
12473     public void testRegisterDuplicateConnectivityDiagnosticsCallback() throws Exception {
12474         final NetworkRequest wifiRequest =
12475                 new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI).build();
12476         doReturn(mIBinder).when(mConnectivityDiagnosticsCallback).asBinder();
12477 
12478         mService.registerConnectivityDiagnosticsCallback(
12479                 mConnectivityDiagnosticsCallback, wifiRequest, mContext.getPackageName());
12480 
12481         // Block until all other events are done processing.
12482         HandlerUtils.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
12483 
12484         verify(mIBinder).linkToDeath(any(ConnectivityDiagnosticsCallbackInfo.class), anyInt());
12485         verify(mConnectivityDiagnosticsCallback).asBinder();
12486         assertTrue(mService.mConnectivityDiagnosticsCallbacks.containsKey(mIBinder));
12487 
12488         // Register the same callback again
12489         mService.registerConnectivityDiagnosticsCallback(
12490                 mConnectivityDiagnosticsCallback, wifiRequest, mContext.getPackageName());
12491 
12492         // Block until all other events are done processing.
12493         HandlerUtils.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
12494 
12495         assertTrue(mService.mConnectivityDiagnosticsCallbacks.containsKey(mIBinder));
12496     }
12497 
12498     @Test(expected = NullPointerException.class)
12499     public void testRegisterConnectivityDiagnosticsCallbackNullCallback() {
12500         mService.registerConnectivityDiagnosticsCallback(
12501                 null /* callback */,
12502                 new NetworkRequest.Builder().build(),
12503                 mContext.getPackageName());
12504     }
12505 
12506     @Test(expected = NullPointerException.class)
12507     public void testRegisterConnectivityDiagnosticsCallbackNullNetworkRequest() {
12508         mService.registerConnectivityDiagnosticsCallback(
12509                 mConnectivityDiagnosticsCallback,
12510                 null /* request */,
12511                 mContext.getPackageName());
12512     }
12513 
12514     @Test(expected = NullPointerException.class)
12515     public void testRegisterConnectivityDiagnosticsCallbackNullPackageName() {
12516         mService.registerConnectivityDiagnosticsCallback(
12517                 mConnectivityDiagnosticsCallback,
12518                 new NetworkRequest.Builder().build(),
12519                 null /* callingPackageName */);
12520     }
12521 
12522     @Test(expected = NullPointerException.class)
12523     public void testUnregisterConnectivityDiagnosticsCallbackNullPackageName() {
12524         mService.unregisterConnectivityDiagnosticsCallback(null /* callback */);
12525     }
12526 
12527     public NetworkAgentInfo fakeMobileNai(NetworkCapabilities nc) {
12528         final NetworkCapabilities cellNc = new NetworkCapabilities.Builder(nc)
12529                 .addTransportType(TRANSPORT_CELLULAR).build();
12530         final NetworkInfo info = new NetworkInfo(TYPE_MOBILE, TelephonyManager.NETWORK_TYPE_LTE,
12531                 ConnectivityManager.getNetworkTypeName(TYPE_MOBILE),
12532                 TelephonyManager.getNetworkTypeName(TelephonyManager.NETWORK_TYPE_LTE));
12533         return fakeNai(cellNc, info);
12534     }
12535 
12536     private NetworkAgentInfo fakeWifiNai(NetworkCapabilities nc) {
12537         final NetworkCapabilities wifiNc = new NetworkCapabilities.Builder(nc)
12538                 .addTransportType(TRANSPORT_WIFI).build();
12539         final NetworkInfo info = new NetworkInfo(TYPE_WIFI, 0 /* subtype */,
12540                 ConnectivityManager.getNetworkTypeName(TYPE_WIFI), "" /* subtypeName */);
12541         return fakeNai(wifiNc, info);
12542     }
12543 
12544     private NetworkAgentInfo fakeVpnNai(NetworkCapabilities nc) {
12545         final NetworkCapabilities vpnNc = new NetworkCapabilities.Builder(nc)
12546                 .addTransportType(TRANSPORT_VPN).build();
12547         final NetworkInfo info = new NetworkInfo(TYPE_VPN, 0 /* subtype */,
12548                 ConnectivityManager.getNetworkTypeName(TYPE_VPN), "" /* subtypeName */);
12549         return fakeNai(vpnNc, info);
12550     }
12551 
12552     private NetworkAgentInfo fakeNai(NetworkCapabilities nc, NetworkInfo networkInfo) {
12553         return new NetworkAgentInfo(null, new Network(NET_ID), networkInfo, new LinkProperties(),
12554                 nc, new NetworkScore.Builder().setLegacyInt(0).build(),
12555                 mServiceContext, null, new NetworkAgentConfig(), mService, null, null, 0,
12556                 INVALID_UID, TEST_LINGER_DELAY_MS, mQosCallbackTracker,
12557                 new ConnectivityService.Dependencies());
12558     }
12559 
12560     @Test
12561     public void testCheckConnectivityDiagnosticsPermissionsNetworkStack() throws Exception {
12562         final NetworkAgentInfo naiWithoutUid = fakeMobileNai(new NetworkCapabilities());
12563 
12564         mServiceContext.setPermission(NETWORK_STACK, PERMISSION_GRANTED);
12565         assertTrue(
12566                 "NetworkStack permission not applied",
12567                 mService.checkConnectivityDiagnosticsPermissions(
12568                         Process.myPid(), Process.myUid(), naiWithoutUid,
12569                         mContext.getOpPackageName()));
12570     }
12571 
12572     @Test
12573     public void testCheckConnectivityDiagnosticsPermissionsWrongUidPackageName() throws Exception {
12574         final int wrongUid = Process.myUid() + 1;
12575 
12576         final NetworkCapabilities nc = new NetworkCapabilities();
12577         nc.setAdministratorUids(new int[] {wrongUid});
12578         final NetworkAgentInfo naiWithUid = fakeWifiNai(nc);
12579 
12580         mServiceContext.setPermission(NETWORK_STACK, PERMISSION_DENIED);
12581 
12582         assertFalse(
12583                 "Mismatched uid/package name should not pass the location permission check",
12584                 mService.checkConnectivityDiagnosticsPermissions(
12585                         Process.myPid() + 1, wrongUid, naiWithUid, mContext.getOpPackageName()));
12586     }
12587 
12588     private void verifyConnectivityDiagnosticsPermissionsWithNetworkAgentInfo(
12589             NetworkAgentInfo info, boolean expectPermission) {
12590         mServiceContext.setPermission(NETWORK_STACK, PERMISSION_DENIED);
12591 
12592         assertEquals(
12593                 "Unexpected ConnDiags permission",
12594                 expectPermission,
12595                 mService.checkConnectivityDiagnosticsPermissions(
12596                         Process.myPid(), Process.myUid(), info, mContext.getOpPackageName()));
12597     }
12598 
12599     @Test
12600     public void testCheckConnectivityDiagnosticsPermissionsCellularNoLocationPermission()
12601             throws Exception {
12602         final NetworkCapabilities nc = new NetworkCapabilities();
12603         nc.setAdministratorUids(new int[] {Process.myUid()});
12604         final NetworkAgentInfo naiWithUid = fakeMobileNai(nc);
12605 
12606         verifyConnectivityDiagnosticsPermissionsWithNetworkAgentInfo(naiWithUid,
12607                 true /* expectPermission */);
12608     }
12609 
12610     @Test
12611     public void testCheckConnectivityDiagnosticsPermissionsWifiNoLocationPermission()
12612             throws Exception {
12613         final NetworkCapabilities nc = new NetworkCapabilities();
12614         nc.setAdministratorUids(new int[] {Process.myUid()});
12615         final NetworkAgentInfo naiWithUid = fakeWifiNai(nc);
12616 
12617         verifyConnectivityDiagnosticsPermissionsWithNetworkAgentInfo(naiWithUid,
12618                 false /* expectPermission */);
12619     }
12620 
12621     @Test
12622     public void testCheckConnectivityDiagnosticsPermissionsActiveVpn() throws Exception {
12623         final NetworkAgentInfo naiWithoutUid = fakeMobileNai(new NetworkCapabilities());
12624 
12625         mMockVpn.establishForMyUid();
12626         assertUidRangesUpdatedForMyUid(true);
12627 
12628         // Wait for networks to connect and broadcasts to be sent before removing permissions.
12629         waitForIdle();
12630         setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
12631                 Manifest.permission.ACCESS_FINE_LOCATION);
12632 
12633         assertTrue(mMockVpn.setUnderlyingNetworks(new Network[] {naiWithoutUid.network}));
12634         waitForIdle();
12635         assertTrue(
12636                 "Active VPN permission not applied",
12637                 mService.checkConnectivityDiagnosticsPermissions(
12638                         Process.myPid(), Process.myUid(), naiWithoutUid,
12639                         mContext.getOpPackageName()));
12640 
12641         assertTrue(mMockVpn.setUnderlyingNetworks(null));
12642         waitForIdle();
12643         assertFalse(
12644                 "VPN shouldn't receive callback on non-underlying network",
12645                 mService.checkConnectivityDiagnosticsPermissions(
12646                         Process.myPid(), Process.myUid(), naiWithoutUid,
12647                         mContext.getOpPackageName()));
12648     }
12649 
12650     @Test
12651     public void testCheckConnectivityDiagnosticsPermissionsNetworkAdministrator() throws Exception {
12652         final NetworkCapabilities nc = new NetworkCapabilities();
12653         nc.setAdministratorUids(new int[] {Process.myUid()});
12654         final NetworkAgentInfo naiWithUid = fakeMobileNai(nc);
12655 
12656         setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
12657                 Manifest.permission.ACCESS_FINE_LOCATION);
12658         mServiceContext.setPermission(NETWORK_STACK, PERMISSION_DENIED);
12659 
12660         assertTrue(
12661                 "NetworkCapabilities administrator uid permission not applied",
12662                 mService.checkConnectivityDiagnosticsPermissions(
12663                         Process.myPid(), Process.myUid(), naiWithUid, mContext.getOpPackageName()));
12664     }
12665 
12666     @Test
12667     public void testCheckConnectivityDiagnosticsPermissionsFails() throws Exception {
12668         final NetworkCapabilities nc = new NetworkCapabilities();
12669         nc.setOwnerUid(Process.myUid());
12670         nc.setAdministratorUids(new int[] {Process.myUid()});
12671         final NetworkAgentInfo naiWithUid = fakeMobileNai(nc);
12672 
12673         setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
12674                 Manifest.permission.ACCESS_FINE_LOCATION);
12675         mServiceContext.setPermission(NETWORK_STACK, PERMISSION_DENIED);
12676 
12677         // Use wrong pid and uid
12678         assertFalse(
12679                 "Permissions allowed when they shouldn't be granted",
12680                 mService.checkConnectivityDiagnosticsPermissions(
12681                         Process.myPid() + 1, Process.myUid() + 1, naiWithUid,
12682                         mContext.getOpPackageName()));
12683     }
12684 
12685     @Test
12686     public void testUnderlyingNetworksWillBeSetInNetworkAgentInfoConstructor() throws Exception {
12687         assumeTrue(mDeps.isAtLeastT());
12688         final Network network1 = new Network(100);
12689         final Network network2 = new Network(101);
12690         final List<Network> underlyingNetworks = new ArrayList<>();
12691         final NetworkCapabilities ncWithEmptyUnderlyingNetworks = new NetworkCapabilities.Builder()
12692                 .setUnderlyingNetworks(underlyingNetworks)
12693                 .build();
12694         final NetworkAgentInfo vpnNaiWithEmptyUnderlyingNetworks =
12695                 fakeVpnNai(ncWithEmptyUnderlyingNetworks);
12696         assertEquals(underlyingNetworks,
12697                 Arrays.asList(vpnNaiWithEmptyUnderlyingNetworks.declaredUnderlyingNetworks));
12698 
12699         underlyingNetworks.add(network1);
12700         underlyingNetworks.add(network2);
12701         final NetworkCapabilities ncWithUnderlyingNetworks = new NetworkCapabilities.Builder()
12702                 .setUnderlyingNetworks(underlyingNetworks)
12703                 .build();
12704         final NetworkAgentInfo vpnNaiWithUnderlyingNetwokrs = fakeVpnNai(ncWithUnderlyingNetworks);
12705         assertEquals(underlyingNetworks,
12706                 Arrays.asList(vpnNaiWithUnderlyingNetwokrs.declaredUnderlyingNetworks));
12707 
12708         final NetworkCapabilities ncWithoutUnderlyingNetworks = new NetworkCapabilities.Builder()
12709                 .build();
12710         final NetworkAgentInfo vpnNaiWithoutUnderlyingNetwokrs =
12711                 fakeVpnNai(ncWithoutUnderlyingNetworks);
12712         assertNull(vpnNaiWithoutUnderlyingNetwokrs.declaredUnderlyingNetworks);
12713     }
12714 
12715     @Test
12716     public void testRegisterConnectivityDiagnosticsCallbackCallsOnConnectivityReport()
12717             throws Exception {
12718         // Set up the Network, which leads to a ConnectivityReport being cached for the network.
12719         final TestNetworkCallback callback = new TestNetworkCallback();
12720         mCm.registerDefaultNetworkCallback(callback);
12721         final LinkProperties linkProperties = new LinkProperties();
12722         linkProperties.setInterfaceName(INTERFACE_NAME);
12723         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, linkProperties);
12724         mCellAgent.connect(true);
12725         callback.expectAvailableThenValidatedCallbacks(mCellAgent);
12726         callback.assertNoCallback();
12727 
12728         final NetworkRequest request = new NetworkRequest.Builder().build();
12729         doReturn(mIBinder).when(mConnectivityDiagnosticsCallback).asBinder();
12730 
12731         mServiceContext.setPermission(NETWORK_STACK, PERMISSION_GRANTED);
12732 
12733         mService.registerConnectivityDiagnosticsCallback(
12734                 mConnectivityDiagnosticsCallback, request, mContext.getPackageName());
12735 
12736         verify(mConnectivityDiagnosticsCallback, timeout(TIMEOUT_MS))
12737                 .onConnectivityReportAvailable(argThat(report -> {
12738                     return INTERFACE_NAME.equals(report.getLinkProperties().getInterfaceName())
12739                             && report.getNetworkCapabilities().hasTransport(TRANSPORT_CELLULAR);
12740                 }));
12741     }
12742 
12743     private void setUpConnectivityDiagnosticsCallback() throws Exception {
12744         final NetworkRequest request = new NetworkRequest.Builder().build();
12745         doReturn(mIBinder).when(mConnectivityDiagnosticsCallback).asBinder();
12746 
12747         mServiceContext.setPermission(NETWORK_STACK, PERMISSION_GRANTED);
12748 
12749         mService.registerConnectivityDiagnosticsCallback(
12750                 mConnectivityDiagnosticsCallback, request, mContext.getPackageName());
12751 
12752         // Block until all other events are done processing.
12753         HandlerUtils.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
12754 
12755         // Connect the cell agent verify that it notifies TestNetworkCallback that it is available
12756         final TestNetworkCallback callback = new TestNetworkCallback();
12757         mCm.registerDefaultNetworkCallback(callback);
12758 
12759         final NetworkCapabilities ncTemplate = new NetworkCapabilities()
12760                 .addTransportType(TRANSPORT_CELLULAR)
12761                 .setTransportInfo(new TestTransportInfo());
12762         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, new LinkProperties(),
12763                 ncTemplate);
12764         mCellAgent.connect(true);
12765         callback.expectAvailableThenValidatedCallbacks(mCellAgent);
12766         callback.assertNoCallback();
12767 
12768         // Make sure a report is sent and that the caps are suitably redacted.
12769         verify(mConnectivityDiagnosticsCallback, timeout(TIMEOUT_MS))
12770                 .onConnectivityReportAvailable(argThat(report ->
12771                         areConnDiagCapsRedacted(report.getNetworkCapabilities())));
12772         reset(mConnectivityDiagnosticsCallback);
12773     }
12774 
12775     private boolean areConnDiagCapsRedacted(NetworkCapabilities nc) {
12776         TestTransportInfo ti = getTestTransportInfo(nc);
12777         return nc.getUids() == null
12778                 && nc.getAdministratorUids().length == 0
12779                 && nc.getOwnerUid() == Process.INVALID_UID
12780                 && ti.locationRedacted
12781                 && ti.localMacAddressRedacted
12782                 && ti.settingsRedacted;
12783     }
12784 
12785     @Test
12786     public void testConnectivityDiagnosticsCallbackOnDataStallSuspected() throws Exception {
12787         setUpConnectivityDiagnosticsCallback();
12788 
12789         // Trigger notifyDataStallSuspected() on the INetworkMonitorCallbacks instance in the
12790         // cellular network agent
12791         mCellAgent.notifyDataStallSuspected();
12792 
12793         // Verify onDataStallSuspected fired
12794         verify(mConnectivityDiagnosticsCallback, timeout(TIMEOUT_MS)).onDataStallSuspected(
12795                 argThat(report -> areConnDiagCapsRedacted(report.getNetworkCapabilities())));
12796     }
12797 
12798     @Test
12799     public void testConnectivityDiagnosticsCallbackOnConnectivityReported() throws Exception {
12800         setUpConnectivityDiagnosticsCallback();
12801 
12802         final Network n = mCellAgent.getNetwork();
12803         final boolean hasConnectivity = true;
12804         mService.reportNetworkConnectivity(n, hasConnectivity);
12805 
12806         // Verify onNetworkConnectivityReported fired
12807         verify(mConnectivityDiagnosticsCallback, timeout(TIMEOUT_MS))
12808                 .onNetworkConnectivityReported(eq(n), eq(hasConnectivity));
12809         verify(mConnectivityDiagnosticsCallback, timeout(TIMEOUT_MS))
12810                 .onConnectivityReportAvailable(
12811                         argThat(report ->
12812                                 areConnDiagCapsRedacted(report.getNetworkCapabilities())));
12813 
12814         final boolean noConnectivity = false;
12815         mService.reportNetworkConnectivity(n, noConnectivity);
12816 
12817         // Wait for onNetworkConnectivityReported to fire
12818         verify(mConnectivityDiagnosticsCallback, timeout(TIMEOUT_MS))
12819                 .onNetworkConnectivityReported(eq(n), eq(noConnectivity));
12820 
12821         // Also expect a ConnectivityReport after NetworkMonitor asynchronously re-validates
12822         verify(mConnectivityDiagnosticsCallback, timeout(TIMEOUT_MS).times(2))
12823                 .onConnectivityReportAvailable(
12824                         argThat(report ->
12825                                 areConnDiagCapsRedacted(report.getNetworkCapabilities())));
12826     }
12827 
12828     @Test
12829     public void testConnectivityDiagnosticsCallbackOnConnectivityReportedSeparateUid()
12830             throws Exception {
12831         setUpConnectivityDiagnosticsCallback();
12832 
12833         // report known Connectivity from a different uid. Verify that network is not re-validated
12834         // and this callback is not notified.
12835         final Network n = mCellAgent.getNetwork();
12836         final boolean hasConnectivity = true;
12837         doAsUid(Process.myUid() + 1, () -> mService.reportNetworkConnectivity(n, hasConnectivity));
12838 
12839         // Block until all other events are done processing.
12840         HandlerUtils.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
12841 
12842         // Verify onNetworkConnectivityReported did not fire
12843         verify(mConnectivityDiagnosticsCallback, never())
12844                 .onNetworkConnectivityReported(any(), anyBoolean());
12845         verify(mConnectivityDiagnosticsCallback, never())
12846                 .onConnectivityReportAvailable(any());
12847 
12848         // report different Connectivity from a different uid. Verify that network is re-validated
12849         // and that this callback is notified.
12850         final boolean noConnectivity = false;
12851         doAsUid(Process.myUid() + 1, () -> mService.reportNetworkConnectivity(n, noConnectivity));
12852 
12853         // Wait for onNetworkConnectivityReported to fire
12854         verify(mConnectivityDiagnosticsCallback, timeout(TIMEOUT_MS))
12855                 .onNetworkConnectivityReported(eq(n), eq(noConnectivity));
12856 
12857         // Also expect a ConnectivityReport after NetworkMonitor asynchronously re-validates
12858         verify(mConnectivityDiagnosticsCallback, timeout(TIMEOUT_MS))
12859                 .onConnectivityReportAvailable(
12860                         argThat(report ->
12861                                 areConnDiagCapsRedacted(report.getNetworkCapabilities())));
12862     }
12863 
12864     @Test(expected = NullPointerException.class)
12865     public void testSimulateDataStallNullNetwork() {
12866         mService.simulateDataStall(
12867                 DataStallReport.DETECTION_METHOD_DNS_EVENTS,
12868                 0L /* timestampMillis */,
12869                 null /* network */,
12870                 new PersistableBundle());
12871     }
12872 
12873     @Test(expected = NullPointerException.class)
12874     public void testSimulateDataStallNullPersistableBundle() {
12875         mService.simulateDataStall(
12876                 DataStallReport.DETECTION_METHOD_DNS_EVENTS,
12877                 0L /* timestampMillis */,
12878                 mock(Network.class),
12879                 null /* extras */);
12880     }
12881 
12882     @Test
12883     public void testRouteAddDeleteUpdate() throws Exception {
12884         final NetworkRequest request = new NetworkRequest.Builder().build();
12885         final TestNetworkCallback networkCallback = new TestNetworkCallback();
12886         mCm.registerNetworkCallback(request, networkCallback);
12887         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
12888         reset(mMockNetd);
12889         mCellAgent.connect(false);
12890         networkCallback.expectAvailableCallbacksUnvalidated(mCellAgent);
12891         final int netId = mCellAgent.getNetwork().netId;
12892 
12893         final String iface = "rmnet_data0";
12894         final InetAddress gateway = InetAddress.getByName("fe80::5678");
12895         RouteInfo direct = RouteInfo.makeHostRoute(gateway, iface);
12896         RouteInfo rio1 = new RouteInfo(new IpPrefix("2001:db8:1::/48"), gateway, iface);
12897         RouteInfo rio2 = new RouteInfo(new IpPrefix("2001:db8:2::/48"), gateway, iface);
12898         RouteInfo defaultRoute = new RouteInfo((IpPrefix) null, gateway, iface);
12899         RouteInfo defaultWithMtu = new RouteInfo(null, gateway, iface, RouteInfo.RTN_UNICAST,
12900                                                  1280 /* mtu */);
12901 
12902         // Send LinkProperties and check that we ask netd to add routes.
12903         LinkProperties lp = new LinkProperties();
12904         lp.setInterfaceName(iface);
12905         lp.addRoute(direct);
12906         lp.addRoute(rio1);
12907         lp.addRoute(defaultRoute);
12908         mCellAgent.sendLinkProperties(lp);
12909         networkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent,
12910                 x -> x.getLp().getRoutes().size() == 3);
12911 
12912         assertRoutesAdded(netId, direct, rio1, defaultRoute);
12913         reset(mMockNetd);
12914 
12915         // Send updated LinkProperties and check that we ask netd to add, remove, update routes.
12916         assertTrue(lp.getRoutes().contains(defaultRoute));
12917         lp.removeRoute(rio1);
12918         lp.addRoute(rio2);
12919         lp.addRoute(defaultWithMtu);
12920         // Ensure adding the same route with a different MTU replaces the previous route.
12921         assertFalse(lp.getRoutes().contains(defaultRoute));
12922         assertTrue(lp.getRoutes().contains(defaultWithMtu));
12923 
12924         mCellAgent.sendLinkProperties(lp);
12925         networkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent,
12926                 x -> x.getLp().getRoutes().contains(rio2));
12927 
12928         assertRoutesRemoved(netId, rio1);
12929         assertRoutesAdded(netId, rio2);
12930 
12931         ArgumentCaptor<RouteInfoParcel> captor = ArgumentCaptor.forClass(RouteInfoParcel.class);
12932         verify(mMockNetd).networkUpdateRouteParcel(eq(netId), captor.capture());
12933         assertRouteInfoParcelMatches(defaultWithMtu, captor.getValue());
12934 
12935 
12936         mCm.unregisterNetworkCallback(networkCallback);
12937     }
12938 
12939     private void verifyDump(String[] args) {
12940         final StringWriter stringWriter = new StringWriter();
12941         mService.dump(new FileDescriptor(), new PrintWriter(stringWriter), args);
12942         assertFalse(stringWriter.toString().isEmpty());
12943     }
12944 
12945     @Test
12946     public void testDumpDoesNotCrash() {
12947         mServiceContext.setPermission(DUMP, PERMISSION_GRANTED);
12948         // Filing a couple requests prior to testing the dump.
12949         final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback();
12950         final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
12951         final NetworkRequest genericRequest = new NetworkRequest.Builder()
12952                 .clearCapabilities().build();
12953         final NetworkRequest wifiRequest = new NetworkRequest.Builder()
12954                 .addTransportType(TRANSPORT_WIFI).build();
12955         mCm.registerNetworkCallback(genericRequest, genericNetworkCallback);
12956         mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
12957 
12958         verifyDump(new String[0]);
12959 
12960         // Verify dump with arguments.
12961         final String dumpPrio = "--dump-priority";
12962         final String[] dumpArgs = {dumpPrio};
12963         verifyDump(dumpArgs);
12964 
12965         final String[] highDumpArgs = {dumpPrio, "HIGH"};
12966         verifyDump(highDumpArgs);
12967 
12968         final String[] normalDumpArgs = {dumpPrio, "NORMAL"};
12969         verifyDump(normalDumpArgs);
12970 
12971         // Invalid args should do dumpNormal w/o exception
12972         final String[] unknownDumpArgs = {dumpPrio, "UNKNOWN"};
12973         verifyDump(unknownDumpArgs);
12974 
12975         final String[] invalidDumpArgs = {"UNKNOWN"};
12976         verifyDump(invalidDumpArgs);
12977     }
12978 
12979     @Test
12980     public void testRequestsSortedByIdSortsCorrectly() {
12981         final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback();
12982         final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
12983         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
12984         final NetworkRequest genericRequest = new NetworkRequest.Builder()
12985                 .clearCapabilities().build();
12986         final NetworkRequest wifiRequest = new NetworkRequest.Builder()
12987                 .addTransportType(TRANSPORT_WIFI).build();
12988         final NetworkRequest cellRequest = new NetworkRequest.Builder()
12989                 .addTransportType(TRANSPORT_CELLULAR).build();
12990         mCm.registerNetworkCallback(genericRequest, genericNetworkCallback);
12991         mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
12992         mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
12993         waitForIdle();
12994 
12995         final NetworkRequestInfo[] nriOutput = mService.requestsSortedById();
12996 
12997         assertTrue(nriOutput.length > 1);
12998         for (int i = 0; i < nriOutput.length - 1; i++) {
12999             final boolean isRequestIdInOrder =
13000                     nriOutput[i].mRequests.get(0).requestId
13001                             < nriOutput[i + 1].mRequests.get(0).requestId;
13002             assertTrue(isRequestIdInOrder);
13003         }
13004     }
13005 
13006     private void assertUidRangesUpdatedForMyUid(boolean add) throws Exception {
13007         final int uid = Process.myUid();
13008         assertVpnUidRangesUpdated(add, uidRangesForUids(uid), uid);
13009     }
13010 
13011     private void assertVpnUidRangesUpdated(boolean add, Set<UidRange> vpnRanges, int exemptUid)
13012             throws Exception {
13013         InOrder inOrder = inOrder(mMockNetd, mDestroySocketsWrapper);
13014         final Set<Integer> exemptUidSet = new ArraySet<>(List.of(exemptUid, Process.VPN_UID));
13015         ArgumentCaptor<int[]> exemptUidCaptor = ArgumentCaptor.forClass(int[].class);
13016 
13017         if (mDeps.isAtLeastU()) {
13018             inOrder.verify(mDestroySocketsWrapper).destroyLiveTcpSockets(
13019                     UidRange.toIntRanges(vpnRanges), exemptUidSet);
13020         } else {
13021             inOrder.verify(mMockNetd).socketDestroy(eq(toUidRangeStableParcels(vpnRanges)),
13022                     exemptUidCaptor.capture());
13023             assertContainsExactly(exemptUidCaptor.getValue(), Process.VPN_UID, exemptUid);
13024         }
13025 
13026         if (add) {
13027             inOrder.verify(mMockNetd, times(1)).networkAddUidRangesParcel(
13028                     new NativeUidRangeConfig(mMockVpn.getNetwork().getNetId(),
13029                             toUidRangeStableParcels(vpnRanges), PREFERENCE_ORDER_VPN));
13030         } else {
13031             inOrder.verify(mMockNetd, times(1)).networkRemoveUidRangesParcel(
13032                     new NativeUidRangeConfig(mMockVpn.getNetwork().getNetId(),
13033                             toUidRangeStableParcels(vpnRanges), PREFERENCE_ORDER_VPN));
13034         }
13035 
13036         if (mDeps.isAtLeastU()) {
13037             inOrder.verify(mDestroySocketsWrapper).destroyLiveTcpSockets(
13038                     UidRange.toIntRanges(vpnRanges), exemptUidSet);
13039         } else {
13040             inOrder.verify(mMockNetd).socketDestroy(eq(toUidRangeStableParcels(vpnRanges)),
13041                     exemptUidCaptor.capture());
13042             assertContainsExactly(exemptUidCaptor.getValue(), Process.VPN_UID, exemptUid);
13043         }
13044     }
13045 
13046     @Test
13047     public void testVpnUidRangesUpdate() throws Exception {
13048         // Set up a WiFi network without proxy.
13049         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
13050         mWiFiAgent.connect(true);
13051         assertNull(mService.getProxyForNetwork(null));
13052         assertNull(mCm.getDefaultProxy());
13053 
13054         final ExpectedBroadcast b1 = expectProxyChangeAction();
13055         final LinkProperties lp = new LinkProperties();
13056         lp.setInterfaceName("tun0");
13057         lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
13058         lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
13059         final UidRange vpnRange = PRIMARY_UIDRANGE;
13060         final Set<UidRange> vpnRanges = Collections.singleton(vpnRange);
13061         mMockVpn.establish(lp, VPN_UID, vpnRanges);
13062         assertVpnUidRangesUpdated(true, vpnRanges, VPN_UID);
13063         // VPN is connected but proxy is not set, so there is no need to send proxy broadcast.
13064         b1.expectNoBroadcast(500);
13065 
13066         // Update to new range which is old range minus APP1, i.e. only APP2
13067         final ExpectedBroadcast b2 = expectProxyChangeAction();
13068         final Set<UidRange> newRanges = new HashSet<>(asList(
13069                 new UidRange(vpnRange.start, APP1_UID - 1),
13070                 new UidRange(APP1_UID + 1, vpnRange.stop)));
13071         mMockVpn.setUids(newRanges);
13072         waitForIdle();
13073 
13074         assertVpnUidRangesUpdated(true, newRanges, VPN_UID);
13075         assertVpnUidRangesUpdated(false, vpnRanges, VPN_UID);
13076 
13077         // Uid has changed but proxy is not set, so there is no need to send proxy broadcast.
13078         b2.expectNoBroadcast(500);
13079 
13080         final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
13081         final ExpectedBroadcast b3 = expectProxyChangeAction();
13082         lp.setHttpProxy(testProxyInfo);
13083         mMockVpn.sendLinkProperties(lp);
13084         waitForIdle();
13085         // Proxy is set, so send a proxy broadcast.
13086         b3.expectBroadcast();
13087 
13088         final ExpectedBroadcast b4 = expectProxyChangeAction();
13089         mMockVpn.setUids(vpnRanges);
13090         waitForIdle();
13091         // Uid has changed and proxy is already set, so send a proxy broadcast.
13092         b4.expectBroadcast();
13093 
13094         final ExpectedBroadcast b5 = expectProxyChangeAction();
13095         // Proxy is removed, send a proxy broadcast.
13096         lp.setHttpProxy(null);
13097         mMockVpn.sendLinkProperties(lp);
13098         waitForIdle();
13099         b5.expectBroadcast();
13100 
13101         // Proxy is added in WiFi(default network), setDefaultProxy will be called.
13102         final LinkProperties wifiLp = mCm.getLinkProperties(mWiFiAgent.getNetwork());
13103         assertNotNull(wifiLp);
13104         final ExpectedBroadcast b6 = expectProxyChangeAction(testProxyInfo);
13105         wifiLp.setHttpProxy(testProxyInfo);
13106         mWiFiAgent.sendLinkProperties(wifiLp);
13107         waitForIdle();
13108         b6.expectBroadcast();
13109     }
13110 
13111     @Test
13112     public void testProxyBroadcastWillBeSentWhenVpnHasProxyAndConnects() throws Exception {
13113         // Set up a WiFi network without proxy.
13114         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
13115         mWiFiAgent.connect(true);
13116         assertNull(mService.getProxyForNetwork(null));
13117         assertNull(mCm.getDefaultProxy());
13118 
13119         final LinkProperties lp = new LinkProperties();
13120         lp.setInterfaceName("tun0");
13121         lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
13122         lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
13123         final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
13124         lp.setHttpProxy(testProxyInfo);
13125         final UidRange vpnRange = PRIMARY_UIDRANGE;
13126         final Set<UidRange> vpnRanges = Collections.singleton(vpnRange);
13127         final ExpectedBroadcast b1 = expectProxyChangeAction();
13128         mMockVpn.setOwnerAndAdminUid(VPN_UID);
13129         mMockVpn.registerAgent(false, vpnRanges, lp);
13130         // In any case, the proxy broadcast won't be sent before VPN goes into CONNECTED state.
13131         // Otherwise, the app that calls ConnectivityManager#getDefaultProxy() when it receives the
13132         // proxy broadcast will get null.
13133         b1.expectNoBroadcast(500);
13134 
13135         final ExpectedBroadcast b2 = expectProxyChangeAction();
13136         mMockVpn.connect(true /* validated */, true /* hasInternet */,
13137                 false /* privateDnsProbeSent */);
13138         waitForIdle();
13139         assertVpnUidRangesUpdated(true, vpnRanges, VPN_UID);
13140         // Vpn is connected with proxy, so the proxy broadcast will be sent to inform the apps to
13141         // update their proxy data.
13142         b2.expectBroadcast();
13143     }
13144 
13145     @Test
13146     public void testProxyBroadcastWillBeSentWhenTheProxyOfNonDefaultNetworkHasChanged()
13147             throws Exception {
13148         // Set up a CELLULAR network without proxy.
13149         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
13150         mCellAgent.connect(true);
13151         assertNull(mService.getProxyForNetwork(null));
13152         assertNull(mCm.getDefaultProxy());
13153         // CELLULAR network should be the default network.
13154         assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetwork());
13155 
13156         // Set up a WiFi network without proxy.
13157         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
13158         mWiFiAgent.connect(true);
13159         assertNull(mService.getProxyForNetwork(null));
13160         assertNull(mCm.getDefaultProxy());
13161         // WiFi network should be the default network.
13162         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetwork());
13163         // CELLULAR network is not the default network.
13164         assertNotEquals(mCellAgent.getNetwork(), mCm.getActiveNetwork());
13165 
13166         // CELLULAR network is not the system default network, but it might be a per-app default
13167         // network. The proxy broadcast should be sent once its proxy has changed.
13168         final LinkProperties cellularLp = new LinkProperties();
13169         cellularLp.setInterfaceName(MOBILE_IFNAME);
13170         final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
13171         final ExpectedBroadcast b = expectProxyChangeAction();
13172         cellularLp.setHttpProxy(testProxyInfo);
13173         mCellAgent.sendLinkProperties(cellularLp);
13174         b.expectBroadcast();
13175     }
13176 
13177     @Test
13178     public void testInvalidRequestTypes() {
13179         final int[] invalidReqTypeInts = new int[]{-1, NetworkRequest.Type.NONE.ordinal(),
13180                 NetworkRequest.Type.LISTEN.ordinal(), NetworkRequest.Type.values().length};
13181         final NetworkCapabilities nc = new NetworkCapabilities().addTransportType(TRANSPORT_WIFI);
13182 
13183         for (int reqTypeInt : invalidReqTypeInts) {
13184             assertThrows("Expect throws for invalid request type " + reqTypeInt,
13185                     IllegalArgumentException.class,
13186                     () -> mService.requestNetwork(Process.INVALID_UID, nc, reqTypeInt, null, 0,
13187                             null, ConnectivityManager.TYPE_NONE, NetworkCallback.FLAG_NONE,
13188                             mContext.getPackageName(), getAttributionTag())
13189             );
13190         }
13191     }
13192 
13193     @Test
13194     public void testKeepConnected() throws Exception {
13195         setAlwaysOnNetworks(false);
13196         registerDefaultNetworkCallbacks();
13197         final TestNetworkCallback allNetworksCb = new TestNetworkCallback();
13198         final NetworkRequest allNetworksRequest = new NetworkRequest.Builder().clearCapabilities()
13199                 .build();
13200         mCm.registerNetworkCallback(allNetworksRequest, allNetworksCb);
13201 
13202         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
13203         mCellAgent.connect(true /* validated */);
13204 
13205         mDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
13206         allNetworksCb.expectAvailableThenValidatedCallbacks(mCellAgent);
13207 
13208         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
13209         mWiFiAgent.connect(true /* validated */);
13210 
13211         mDefaultNetworkCallback.expectAvailableDoubleValidatedCallbacks(mWiFiAgent);
13212         // While the default callback doesn't see the network before it's validated, the listen
13213         // sees the network come up and validate later
13214         allNetworksCb.expectAvailableCallbacksUnvalidated(mWiFiAgent);
13215         allNetworksCb.expectLosing(mCellAgent);
13216         allNetworksCb.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
13217         allNetworksCb.expect(LOST, mCellAgent, TEST_LINGER_DELAY_MS * 2);
13218 
13219         // The cell network has disconnected (see LOST above) because it was outscored and
13220         // had no requests (see setAlwaysOnNetworks(false) above)
13221         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
13222         final NetworkScore score = new NetworkScore.Builder().setLegacyInt(30).build();
13223         mCellAgent.setScore(score);
13224         mCellAgent.connect(false /* validated */);
13225 
13226         // The cell network gets torn down right away.
13227         allNetworksCb.expectAvailableCallbacksUnvalidated(mCellAgent);
13228         allNetworksCb.expect(LOST, mCellAgent, TEST_NASCENT_DELAY_MS * 2);
13229         allNetworksCb.assertNoCallback();
13230 
13231         // Now create a cell network with KEEP_CONNECTED_FOR_HANDOVER and make sure it's
13232         // not disconnected immediately when outscored.
13233         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
13234         final NetworkScore scoreKeepup = new NetworkScore.Builder().setLegacyInt(30)
13235                 .setKeepConnectedReason(KEEP_CONNECTED_FOR_HANDOVER).build();
13236         mCellAgent.setScore(scoreKeepup);
13237         mCellAgent.connect(true /* validated */);
13238 
13239         allNetworksCb.expectAvailableThenValidatedCallbacks(mCellAgent);
13240         mDefaultNetworkCallback.assertNoCallback();
13241 
13242         mWiFiAgent.disconnect();
13243 
13244         allNetworksCb.expect(LOST, mWiFiAgent);
13245         mDefaultNetworkCallback.expect(LOST, mWiFiAgent);
13246         mDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellAgent);
13247 
13248         // Reconnect a WiFi network and make sure the cell network is still not torn down.
13249         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
13250         mWiFiAgent.connect(true /* validated */);
13251 
13252         allNetworksCb.expectAvailableThenValidatedCallbacks(mWiFiAgent);
13253         mDefaultNetworkCallback.expectAvailableDoubleValidatedCallbacks(mWiFiAgent);
13254 
13255         // Now remove the reason to keep connected and make sure the network lingers and is
13256         // torn down.
13257         mCellAgent.setScore(new NetworkScore.Builder().setLegacyInt(30).build());
13258         allNetworksCb.expectLosing(mCellAgent, TEST_NASCENT_DELAY_MS * 2);
13259         allNetworksCb.expect(LOST, mCellAgent, TEST_LINGER_DELAY_MS * 2);
13260         mDefaultNetworkCallback.assertNoCallback();
13261 
13262         mCm.unregisterNetworkCallback(allNetworksCb);
13263         // mDefaultNetworkCallback will be unregistered by tearDown()
13264     }
13265 
13266     private class QosCallbackMockHelper {
13267         @NonNull public final QosFilter mFilter;
13268         @NonNull public final IQosCallback mCallback;
13269         @NonNull public final TestNetworkAgentWrapper mAgentWrapper;
13270         @NonNull private final List<IQosCallback> mCallbacks = new ArrayList();
13271 
13272         QosCallbackMockHelper() throws Exception {
13273             Log.d(TAG, "QosCallbackMockHelper: ");
13274             mFilter = mock(QosFilter.class);
13275 
13276             // Ensure the network is disconnected before anything else occurs
13277             assertNull(mCellAgent);
13278 
13279             mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
13280             mCellAgent.connect(true);
13281 
13282             verifyActiveNetwork(TRANSPORT_CELLULAR);
13283             waitForIdle();
13284             final Network network = mCellAgent.getNetwork();
13285 
13286             final Pair<IQosCallback, IBinder> pair = createQosCallback();
13287             mCallback = pair.first;
13288 
13289             doReturn(network).when(mFilter).getNetwork();
13290             doReturn(QosCallbackException.EX_TYPE_FILTER_NONE).when(mFilter).validate();
13291             mAgentWrapper = mCellAgent;
13292         }
13293 
13294         void registerQosCallback(@NonNull final QosFilter filter,
13295                 @NonNull final IQosCallback callback) {
13296             mCallbacks.add(callback);
13297             final NetworkAgentInfo nai =
13298                     mService.getNetworkAgentInfoForNetwork(filter.getNetwork());
13299             mService.registerQosCallbackInternal(filter, callback, nai);
13300         }
13301 
13302         void tearDown() {
13303             for (int i = 0; i < mCallbacks.size(); i++) {
13304                 mService.unregisterQosCallback(mCallbacks.get(i));
13305             }
13306         }
13307     }
13308 
13309     private Pair<IQosCallback, IBinder> createQosCallback() {
13310         final IQosCallback callback = mock(IQosCallback.class);
13311         final IBinder binder = mock(Binder.class);
13312         doReturn(binder).when(callback).asBinder();
13313         doReturn(true).when(binder).isBinderAlive();
13314         return new Pair<>(callback, binder);
13315     }
13316 
13317 
13318     @Test
13319     public void testQosCallbackRegistration() throws Exception {
13320         mQosCallbackMockHelper = new QosCallbackMockHelper();
13321         final NetworkAgentWrapper wrapper = mQosCallbackMockHelper.mAgentWrapper;
13322 
13323         doReturn(QosCallbackException.EX_TYPE_FILTER_NONE)
13324                 .when(mQosCallbackMockHelper.mFilter).validate();
13325         mQosCallbackMockHelper.registerQosCallback(
13326                 mQosCallbackMockHelper.mFilter, mQosCallbackMockHelper.mCallback);
13327 
13328         final OnQosCallbackRegister cbRegister1 =
13329                 (OnQosCallbackRegister) wrapper.getCallbackHistory().poll(1000, x -> true);
13330         assertNotNull(cbRegister1);
13331 
13332         final int registerCallbackId = cbRegister1.mQosCallbackId;
13333         mService.unregisterQosCallback(mQosCallbackMockHelper.mCallback);
13334         final OnQosCallbackUnregister cbUnregister =
13335                 (OnQosCallbackUnregister) wrapper.getCallbackHistory().poll(1000, x -> true);
13336         assertNotNull(cbUnregister);
13337         assertEquals(registerCallbackId, cbUnregister.mQosCallbackId);
13338         assertNull(wrapper.getCallbackHistory().poll(200, x -> true));
13339     }
13340 
13341     @Test
13342     public void testQosCallbackNoRegistrationOnValidationError() throws Exception {
13343         mQosCallbackMockHelper = new QosCallbackMockHelper();
13344 
13345         doReturn(QosCallbackException.EX_TYPE_FILTER_NETWORK_RELEASED)
13346                 .when(mQosCallbackMockHelper.mFilter).validate();
13347         mQosCallbackMockHelper.registerQosCallback(
13348                 mQosCallbackMockHelper.mFilter, mQosCallbackMockHelper.mCallback);
13349         waitForIdle();
13350         verify(mQosCallbackMockHelper.mCallback)
13351                 .onError(eq(QosCallbackException.EX_TYPE_FILTER_NETWORK_RELEASED));
13352     }
13353 
13354     @Test
13355     public void testQosCallbackAvailableAndLost() throws Exception {
13356         mQosCallbackMockHelper = new QosCallbackMockHelper();
13357         final int sessionId = 10;
13358         final int qosCallbackId = 1;
13359 
13360         doReturn(QosCallbackException.EX_TYPE_FILTER_NONE)
13361                 .when(mQosCallbackMockHelper.mFilter).validate();
13362         mQosCallbackMockHelper.registerQosCallback(
13363                 mQosCallbackMockHelper.mFilter, mQosCallbackMockHelper.mCallback);
13364         waitForIdle();
13365 
13366         final EpsBearerQosSessionAttributes attributes = new EpsBearerQosSessionAttributes(
13367                 1, 2, 3, 4, 5, new ArrayList<>());
13368         mQosCallbackMockHelper.mAgentWrapper.getNetworkAgent()
13369                 .sendQosSessionAvailable(qosCallbackId, sessionId, attributes);
13370         waitForIdle();
13371 
13372         verify(mQosCallbackMockHelper.mCallback).onQosEpsBearerSessionAvailable(argThat(session ->
13373                 session.getSessionId() == sessionId
13374                         && session.getSessionType() == QosSession.TYPE_EPS_BEARER), eq(attributes));
13375 
13376         mQosCallbackMockHelper.mAgentWrapper.getNetworkAgent()
13377                 .sendQosSessionLost(qosCallbackId, sessionId, QosSession.TYPE_EPS_BEARER);
13378         waitForIdle();
13379         verify(mQosCallbackMockHelper.mCallback).onQosSessionLost(argThat(session ->
13380                 session.getSessionId() == sessionId
13381                         && session.getSessionType() == QosSession.TYPE_EPS_BEARER));
13382     }
13383 
13384     @Test
13385     public void testNrQosCallbackAvailableAndLost() throws Exception {
13386         mQosCallbackMockHelper = new QosCallbackMockHelper();
13387         final int sessionId = 10;
13388         final int qosCallbackId = 1;
13389 
13390         doReturn(QosCallbackException.EX_TYPE_FILTER_NONE)
13391                 .when(mQosCallbackMockHelper.mFilter).validate();
13392         mQosCallbackMockHelper.registerQosCallback(
13393                 mQosCallbackMockHelper.mFilter, mQosCallbackMockHelper.mCallback);
13394         waitForIdle();
13395 
13396         final NrQosSessionAttributes attributes = new NrQosSessionAttributes(
13397                 1, 2, 3, 4, 5, 6, 7, new ArrayList<>());
13398         mQosCallbackMockHelper.mAgentWrapper.getNetworkAgent()
13399                 .sendQosSessionAvailable(qosCallbackId, sessionId, attributes);
13400         waitForIdle();
13401 
13402         verify(mQosCallbackMockHelper.mCallback).onNrQosSessionAvailable(argThat(session ->
13403                 session.getSessionId() == sessionId
13404                         && session.getSessionType() == QosSession.TYPE_NR_BEARER), eq(attributes));
13405 
13406         mQosCallbackMockHelper.mAgentWrapper.getNetworkAgent()
13407                 .sendQosSessionLost(qosCallbackId, sessionId, QosSession.TYPE_NR_BEARER);
13408         waitForIdle();
13409         verify(mQosCallbackMockHelper.mCallback).onQosSessionLost(argThat(session ->
13410                 session.getSessionId() == sessionId
13411                         && session.getSessionType() == QosSession.TYPE_NR_BEARER));
13412     }
13413 
13414     @Test @IgnoreUpTo(SC_V2)
13415     public void testQosCallbackAvailableOnValidationError() throws Exception {
13416         mQosCallbackMockHelper = new QosCallbackMockHelper();
13417         final NetworkAgentWrapper wrapper = mQosCallbackMockHelper.mAgentWrapper;
13418         final int sessionId = 10;
13419         final int qosCallbackId = 1;
13420 
13421         doReturn(QosCallbackException.EX_TYPE_FILTER_NONE)
13422                 .when(mQosCallbackMockHelper.mFilter).validate();
13423         mQosCallbackMockHelper.registerQosCallback(
13424                 mQosCallbackMockHelper.mFilter, mQosCallbackMockHelper.mCallback);
13425         OnQosCallbackRegister cbRegister1 =
13426                 (OnQosCallbackRegister) wrapper.getCallbackHistory().poll(1000, x -> true);
13427         assertNotNull(cbRegister1);
13428         final int registerCallbackId = cbRegister1.mQosCallbackId;
13429 
13430         waitForIdle();
13431 
13432         doReturn(QosCallbackException.EX_TYPE_FILTER_SOCKET_REMOTE_ADDRESS_CHANGED)
13433                 .when(mQosCallbackMockHelper.mFilter).validate();
13434         final EpsBearerQosSessionAttributes attributes = new EpsBearerQosSessionAttributes(
13435                 1, 2, 3, 4, 5, new ArrayList<>());
13436         mQosCallbackMockHelper.mAgentWrapper.getNetworkAgent()
13437                 .sendQosSessionAvailable(qosCallbackId, sessionId, attributes);
13438         waitForIdle();
13439 
13440         final NetworkAgentWrapper.CallbackType.OnQosCallbackUnregister cbUnregister;
13441         cbUnregister = (NetworkAgentWrapper.CallbackType.OnQosCallbackUnregister)
13442                 wrapper.getCallbackHistory().poll(1000, x -> true);
13443         assertNotNull(cbUnregister);
13444         assertEquals(registerCallbackId, cbUnregister.mQosCallbackId);
13445         waitForIdle();
13446         verify(mQosCallbackMockHelper.mCallback)
13447                 .onError(eq(QosCallbackException.EX_TYPE_FILTER_SOCKET_REMOTE_ADDRESS_CHANGED));
13448     }
13449 
13450     @Test @IgnoreUpTo(SC_V2)
13451     public void testQosCallbackLostOnValidationError() throws Exception {
13452         mQosCallbackMockHelper = new QosCallbackMockHelper();
13453         final int sessionId = 10;
13454         final int qosCallbackId = 1;
13455 
13456         doReturn(QosCallbackException.EX_TYPE_FILTER_NONE)
13457                 .when(mQosCallbackMockHelper.mFilter).validate();
13458         mQosCallbackMockHelper.registerQosCallback(
13459                 mQosCallbackMockHelper.mFilter, mQosCallbackMockHelper.mCallback);
13460         waitForIdle();
13461         EpsBearerQosSessionAttributes attributes =
13462                 sendQosSessionEvent(qosCallbackId, sessionId, true);
13463         waitForIdle();
13464 
13465         verify(mQosCallbackMockHelper.mCallback).onQosEpsBearerSessionAvailable(argThat(session ->
13466                 session.getSessionId() == sessionId
13467                         && session.getSessionType() == QosSession.TYPE_EPS_BEARER), eq(attributes));
13468 
13469         doReturn(QosCallbackException.EX_TYPE_FILTER_SOCKET_REMOTE_ADDRESS_CHANGED)
13470                 .when(mQosCallbackMockHelper.mFilter).validate();
13471 
13472         sendQosSessionEvent(qosCallbackId, sessionId, false);
13473         waitForIdle();
13474         verify(mQosCallbackMockHelper.mCallback)
13475                 .onError(eq(QosCallbackException.EX_TYPE_FILTER_SOCKET_REMOTE_ADDRESS_CHANGED));
13476     }
13477 
13478     private EpsBearerQosSessionAttributes sendQosSessionEvent(
13479             int qosCallbackId, int sessionId, boolean available) {
13480         if (available) {
13481             final EpsBearerQosSessionAttributes attributes = new EpsBearerQosSessionAttributes(
13482                     1, 2, 3, 4, 5, new ArrayList<>());
13483             mQosCallbackMockHelper.mAgentWrapper.getNetworkAgent()
13484                     .sendQosSessionAvailable(qosCallbackId, sessionId, attributes);
13485             return attributes;
13486         } else {
13487             mQosCallbackMockHelper.mAgentWrapper.getNetworkAgent()
13488                     .sendQosSessionLost(qosCallbackId, sessionId, QosSession.TYPE_EPS_BEARER);
13489             return null;
13490         }
13491 
13492     }
13493 
13494     @Test
13495     public void testQosCallbackTooManyRequests() throws Exception {
13496         mQosCallbackMockHelper = new QosCallbackMockHelper();
13497 
13498         doReturn(QosCallbackException.EX_TYPE_FILTER_NONE)
13499                 .when(mQosCallbackMockHelper.mFilter).validate();
13500         for (int i = 0; i < 100; i++) {
13501             final Pair<IQosCallback, IBinder> pair = createQosCallback();
13502 
13503             try {
13504                 mQosCallbackMockHelper.registerQosCallback(
13505                         mQosCallbackMockHelper.mFilter, pair.first);
13506             } catch (ServiceSpecificException e) {
13507                 assertEquals(e.errorCode, ConnectivityManager.Errors.TOO_MANY_REQUESTS);
13508                 if (i < 50) {
13509                     fail("TOO_MANY_REQUESTS thrown too early, the count is " + i);
13510                 }
13511 
13512                 // As long as there is at least 50 requests, it is safe to assume it works.
13513                 // Note: The count isn't being tested precisely against 100 because the counter
13514                 // is shared with request network.
13515                 return;
13516             }
13517         }
13518         fail("TOO_MANY_REQUESTS never thrown");
13519     }
13520 
13521     private void mockGetApplicationInfo(@NonNull final String packageName, final int uid) {
13522         mockGetApplicationInfo(packageName, uid, PRIMARY_USER_HANDLE);
13523     }
13524 
13525     private void mockGetApplicationInfo(@NonNull final String packageName, final int uid,
13526             @NonNull final UserHandle user) {
13527         final ApplicationInfo applicationInfo = new ApplicationInfo();
13528         applicationInfo.uid = uid;
13529         try {
13530             doReturn(applicationInfo).when(mPackageManager).getApplicationInfoAsUser(
13531                     eq(packageName), anyInt(), eq(user));
13532         } catch (Exception e) {
13533             fail(e.getMessage());
13534         }
13535     }
13536 
13537     private void mockGetApplicationInfoThrowsNameNotFound(@NonNull final String packageName,
13538             @NonNull final UserHandle user)
13539             throws Exception {
13540         doThrow(new PackageManager.NameNotFoundException(packageName)).when(
13541                 mPackageManager).getApplicationInfoAsUser(eq(packageName), anyInt(), eq(user));
13542     }
13543 
13544     private void mockHasSystemFeature(@NonNull final String featureName, final boolean hasFeature) {
13545         doReturn(hasFeature).when(mPackageManager).hasSystemFeature(eq(featureName));
13546     }
13547 
13548     private Range<Integer> getNriFirstUidRange(@NonNull final NetworkRequestInfo nri) {
13549         return nri.mRequests.get(0).networkCapabilities.getUids().iterator().next();
13550     }
13551 
13552     private OemNetworkPreferences createDefaultOemNetworkPreferences(
13553             @OemNetworkPreferences.OemNetworkPreference final int preference) {
13554         // Arrange PackageManager mocks
13555         mockGetApplicationInfo(TEST_PACKAGE_NAME, TEST_PACKAGE_UID);
13556 
13557         // Build OemNetworkPreferences object
13558         return new OemNetworkPreferences.Builder()
13559                 .addNetworkPreference(TEST_PACKAGE_NAME, preference)
13560                 .build();
13561     }
13562 
13563     @Test
13564     public void testOemNetworkRequestFactoryPreferenceUninitializedThrowsError() {
13565         @OemNetworkPreferences.OemNetworkPreference final int prefToTest =
13566                 OEM_NETWORK_PREFERENCE_UNINITIALIZED;
13567 
13568         // Act on OemNetworkRequestFactory.createNrisFromOemNetworkPreferences()
13569         assertThrows(IllegalArgumentException.class,
13570                 () -> mService.new OemNetworkRequestFactory()
13571                         .createNrisFromOemNetworkPreferences(
13572                                 createDefaultOemNetworkPreferences(prefToTest)));
13573     }
13574 
13575     @Test
13576     public void testOemNetworkRequestFactoryPreferenceOemPaid()
13577             throws Exception {
13578         // Expectations
13579         final int expectedNumOfNris = 1;
13580         final int expectedNumOfRequests = 3;
13581 
13582         @OemNetworkPreferences.OemNetworkPreference final int prefToTest =
13583                 OEM_NETWORK_PREFERENCE_OEM_PAID;
13584 
13585         // Act on OemNetworkRequestFactory.createNrisFromOemNetworkPreferences()
13586         final ArraySet<NetworkRequestInfo> nris =
13587                 mService.new OemNetworkRequestFactory()
13588                         .createNrisFromOemNetworkPreferences(
13589                                 createDefaultOemNetworkPreferences(prefToTest));
13590         final NetworkRequestInfo nri = nris.iterator().next();
13591         assertEquals(PREFERENCE_ORDER_OEM, nri.mPreferenceOrder);
13592         final List<NetworkRequest> mRequests = nri.mRequests;
13593         assertEquals(expectedNumOfNris, nris.size());
13594         assertEquals(expectedNumOfRequests, mRequests.size());
13595         assertTrue(mRequests.get(0).isListen());
13596         assertTrue(mRequests.get(0).hasCapability(NET_CAPABILITY_NOT_METERED));
13597         assertTrue(mRequests.get(0).hasCapability(NET_CAPABILITY_VALIDATED));
13598         assertTrue(mRequests.get(1).isRequest());
13599         assertTrue(mRequests.get(1).hasCapability(NET_CAPABILITY_OEM_PAID));
13600         assertEquals(NetworkRequest.Type.TRACK_DEFAULT, mRequests.get(2).type);
13601         assertTrue(mService.getDefaultRequest().networkCapabilities.equalsNetCapabilities(
13602                 mRequests.get(2).networkCapabilities));
13603     }
13604 
13605     @Test
13606     public void testOemNetworkRequestFactoryPreferenceOemPaidNoFallback()
13607             throws Exception {
13608         // Expectations
13609         final int expectedNumOfNris = 1;
13610         final int expectedNumOfRequests = 2;
13611 
13612         @OemNetworkPreferences.OemNetworkPreference final int prefToTest =
13613                 OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK;
13614 
13615         // Act on OemNetworkRequestFactory.createNrisFromOemNetworkPreferences()
13616         final ArraySet<NetworkRequestInfo> nris =
13617                 mService.new OemNetworkRequestFactory()
13618                         .createNrisFromOemNetworkPreferences(
13619                                 createDefaultOemNetworkPreferences(prefToTest));
13620         final NetworkRequestInfo nri = nris.iterator().next();
13621         assertEquals(PREFERENCE_ORDER_OEM, nri.mPreferenceOrder);
13622         final List<NetworkRequest> mRequests = nri.mRequests;
13623         assertEquals(expectedNumOfNris, nris.size());
13624         assertEquals(expectedNumOfRequests, mRequests.size());
13625         assertTrue(mRequests.get(0).isListen());
13626         assertTrue(mRequests.get(0).hasCapability(NET_CAPABILITY_NOT_METERED));
13627         assertTrue(mRequests.get(0).hasCapability(NET_CAPABILITY_VALIDATED));
13628         assertTrue(mRequests.get(1).isRequest());
13629         assertTrue(mRequests.get(1).hasCapability(NET_CAPABILITY_OEM_PAID));
13630     }
13631 
13632     @Test
13633     public void testOemNetworkRequestFactoryPreferenceOemPaidOnly()
13634             throws Exception {
13635         // Expectations
13636         final int expectedNumOfNris = 1;
13637         final int expectedNumOfRequests = 1;
13638 
13639         @OemNetworkPreferences.OemNetworkPreference final int prefToTest =
13640                 OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY;
13641 
13642         // Act on OemNetworkRequestFactory.createNrisFromOemNetworkPreferences()
13643         final ArraySet<NetworkRequestInfo> nris =
13644                 mService.new OemNetworkRequestFactory()
13645                         .createNrisFromOemNetworkPreferences(
13646                                 createDefaultOemNetworkPreferences(prefToTest));
13647         final NetworkRequestInfo nri = nris.iterator().next();
13648         assertEquals(PREFERENCE_ORDER_OEM, nri.mPreferenceOrder);
13649         final List<NetworkRequest> mRequests = nri.mRequests;
13650         assertEquals(expectedNumOfNris, nris.size());
13651         assertEquals(expectedNumOfRequests, mRequests.size());
13652         assertTrue(mRequests.get(0).isRequest());
13653         assertTrue(mRequests.get(0).hasCapability(NET_CAPABILITY_OEM_PAID));
13654     }
13655 
13656     @Test
13657     public void testOemNetworkRequestFactoryPreferenceOemPrivateOnly()
13658             throws Exception {
13659         // Expectations
13660         final int expectedNumOfNris = 1;
13661         final int expectedNumOfRequests = 1;
13662 
13663         @OemNetworkPreferences.OemNetworkPreference final int prefToTest =
13664                 OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY;
13665 
13666         // Act on OemNetworkRequestFactory.createNrisFromOemNetworkPreferences()
13667         final ArraySet<NetworkRequestInfo> nris =
13668                 mService.new OemNetworkRequestFactory()
13669                         .createNrisFromOemNetworkPreferences(
13670                                 createDefaultOemNetworkPreferences(prefToTest));
13671         final NetworkRequestInfo nri = nris.iterator().next();
13672         assertEquals(PREFERENCE_ORDER_OEM, nri.mPreferenceOrder);
13673         final List<NetworkRequest> mRequests = nri.mRequests;
13674         assertEquals(expectedNumOfNris, nris.size());
13675         assertEquals(expectedNumOfRequests, mRequests.size());
13676         assertTrue(mRequests.get(0).isRequest());
13677         assertTrue(mRequests.get(0).hasCapability(NET_CAPABILITY_OEM_PRIVATE));
13678         assertFalse(mRequests.get(0).hasCapability(NET_CAPABILITY_OEM_PAID));
13679     }
13680 
13681     @Test
13682     public void testOemNetworkRequestFactoryCreatesCorrectNumOfNris()
13683             throws Exception {
13684         // Expectations
13685         final int expectedNumOfNris = 2;
13686 
13687         // Arrange PackageManager mocks
13688         final String testPackageName2 = "com.google.apps.dialer";
13689         mockGetApplicationInfo(TEST_PACKAGE_NAME, TEST_PACKAGE_UID);
13690         mockGetApplicationInfo(testPackageName2, TEST_PACKAGE_UID);
13691 
13692         // Build OemNetworkPreferences object
13693         final int testOemPref = OEM_NETWORK_PREFERENCE_OEM_PAID;
13694         final int testOemPref2 = OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK;
13695         final OemNetworkPreferences pref = new OemNetworkPreferences.Builder()
13696                 .addNetworkPreference(TEST_PACKAGE_NAME, testOemPref)
13697                 .addNetworkPreference(testPackageName2, testOemPref2)
13698                 .build();
13699 
13700         // Act on OemNetworkRequestFactory.createNrisFromOemNetworkPreferences()
13701         final ArraySet<NetworkRequestInfo> nris =
13702                 mService.new OemNetworkRequestFactory().createNrisFromOemNetworkPreferences(pref);
13703 
13704         assertNotNull(nris);
13705         assertEquals(expectedNumOfNris, nris.size());
13706     }
13707 
13708     @Test
13709     public void testOemNetworkRequestFactoryMultiplePrefsCorrectlySetsUids()
13710             throws Exception {
13711         // Arrange PackageManager mocks
13712         final String testPackageName2 = "com.google.apps.dialer";
13713         final int testPackageNameUid2 = 456;
13714         mockGetApplicationInfo(TEST_PACKAGE_NAME, TEST_PACKAGE_UID);
13715         mockGetApplicationInfo(testPackageName2, testPackageNameUid2);
13716 
13717         // Build OemNetworkPreferences object
13718         final int testOemPref = OEM_NETWORK_PREFERENCE_OEM_PAID;
13719         final int testOemPref2 = OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK;
13720         final OemNetworkPreferences pref = new OemNetworkPreferences.Builder()
13721                 .addNetworkPreference(TEST_PACKAGE_NAME, testOemPref)
13722                 .addNetworkPreference(testPackageName2, testOemPref2)
13723                 .build();
13724 
13725         // Act on OemNetworkRequestFactory.createNrisFromOemNetworkPreferences()
13726         final List<NetworkRequestInfo> nris =
13727                 new ArrayList<>(
13728                         mService.new OemNetworkRequestFactory().createNrisFromOemNetworkPreferences(
13729                                 pref));
13730 
13731         // Sort by uid to access nris by index
13732         nris.sort(Comparator.comparingInt(nri -> getNriFirstUidRange(nri).getLower()));
13733         assertEquals(TEST_PACKAGE_UID, (int) getNriFirstUidRange(nris.get(0)).getLower());
13734         assertEquals(TEST_PACKAGE_UID, (int) getNriFirstUidRange(nris.get(0)).getUpper());
13735         assertEquals(testPackageNameUid2, (int) getNriFirstUidRange(nris.get(1)).getLower());
13736         assertEquals(testPackageNameUid2, (int) getNriFirstUidRange(nris.get(1)).getUpper());
13737     }
13738 
13739     @Test
13740     public void testOemNetworkRequestFactoryMultipleUsersSetsUids()
13741             throws Exception {
13742         // Arrange users
13743         final int secondUserTestPackageUid = UserHandle.getUid(SECONDARY_USER, TEST_PACKAGE_UID);
13744         final int thirdUserTestPackageUid = UserHandle.getUid(TERTIARY_USER, TEST_PACKAGE_UID);
13745         doReturn(asList(PRIMARY_USER_HANDLE, SECONDARY_USER_HANDLE, TERTIARY_USER_HANDLE))
13746                 .when(mUserManager).getUserHandles(anyBoolean());
13747 
13748         // Arrange PackageManager mocks testing for users who have and don't have a package.
13749         mockGetApplicationInfoThrowsNameNotFound(TEST_PACKAGE_NAME, PRIMARY_USER_HANDLE);
13750         mockGetApplicationInfo(TEST_PACKAGE_NAME, secondUserTestPackageUid, SECONDARY_USER_HANDLE);
13751         mockGetApplicationInfo(TEST_PACKAGE_NAME, thirdUserTestPackageUid, TERTIARY_USER_HANDLE);
13752 
13753         // Build OemNetworkPreferences object
13754         final int testOemPref = OEM_NETWORK_PREFERENCE_OEM_PAID;
13755         final OemNetworkPreferences pref = new OemNetworkPreferences.Builder()
13756                 .addNetworkPreference(TEST_PACKAGE_NAME, testOemPref)
13757                 .build();
13758 
13759         // Act on OemNetworkRequestFactory.createNrisFromOemNetworkPreferences()
13760         final List<NetworkRequestInfo> nris =
13761                 new ArrayList<>(
13762                         mService.new OemNetworkRequestFactory().createNrisFromOemNetworkPreferences(
13763                                 pref));
13764 
13765         // UIDs for users with installed packages should be present.
13766         // Three users exist, but only two have the test package installed.
13767         final int expectedUidSize = 2;
13768         final List<Range<Integer>> uids =
13769                 new ArrayList<>(nris.get(0).mRequests.get(0).networkCapabilities.getUids());
13770         assertEquals(expectedUidSize, uids.size());
13771 
13772         // Sort by uid to access nris by index
13773         uids.sort(Comparator.comparingInt(uid -> uid.getLower()));
13774         assertEquals(secondUserTestPackageUid, (int) uids.get(0).getLower());
13775         assertEquals(secondUserTestPackageUid, (int) uids.get(0).getUpper());
13776         assertEquals(thirdUserTestPackageUid, (int) uids.get(1).getLower());
13777         assertEquals(thirdUserTestPackageUid, (int) uids.get(1).getUpper());
13778     }
13779 
13780     @Test
13781     public void testOemNetworkRequestFactoryAddsPackagesToCorrectPreference()
13782             throws Exception {
13783         // Expectations
13784         final int expectedNumOfNris = 1;
13785         final int expectedNumOfAppUids = 2;
13786 
13787         // Arrange PackageManager mocks
13788         final String testPackageName2 = "com.google.apps.dialer";
13789         final int testPackageNameUid2 = 456;
13790         mockGetApplicationInfo(TEST_PACKAGE_NAME, TEST_PACKAGE_UID);
13791         mockGetApplicationInfo(testPackageName2, testPackageNameUid2);
13792 
13793         // Build OemNetworkPreferences object
13794         final int testOemPref = OEM_NETWORK_PREFERENCE_OEM_PAID;
13795         final OemNetworkPreferences pref = new OemNetworkPreferences.Builder()
13796                 .addNetworkPreference(TEST_PACKAGE_NAME, testOemPref)
13797                 .addNetworkPreference(testPackageName2, testOemPref)
13798                 .build();
13799 
13800         // Act on OemNetworkRequestFactory.createNrisFromOemNetworkPreferences()
13801         final ArraySet<NetworkRequestInfo> nris =
13802                 mService.new OemNetworkRequestFactory().createNrisFromOemNetworkPreferences(pref);
13803 
13804         assertEquals(expectedNumOfNris, nris.size());
13805         assertEquals(expectedNumOfAppUids,
13806                 nris.iterator().next().mRequests.get(0).networkCapabilities.getUids().size());
13807     }
13808 
13809     @Test
13810     public void testSetOemNetworkPreferenceNullListenerAndPrefParamThrowsNpe() {
13811         mockHasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, true);
13812 
13813         // Act on ConnectivityService.setOemNetworkPreference()
13814         assertThrows(NullPointerException.class,
13815                 () -> mService.setOemNetworkPreference(
13816                         null,
13817                         null));
13818     }
13819 
13820     @Test
13821     public void testSetOemNetworkPreferenceFailsForNonAutomotive()
13822             throws Exception {
13823         mockHasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, false);
13824         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
13825                 OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY;
13826 
13827         // Act on ConnectivityService.setOemNetworkPreference()
13828         assertThrows(UnsupportedOperationException.class,
13829                 () -> mService.setOemNetworkPreference(
13830                         createDefaultOemNetworkPreferences(networkPref),
13831                         null));
13832     }
13833 
13834     @Test
13835     public void testSetOemNetworkPreferenceFailsForTestRequestWithoutPermission() {
13836         // Calling setOemNetworkPreference() with a test pref requires the permission
13837         // MANAGE_TEST_NETWORKS.
13838         mockHasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, false);
13839         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
13840                 OEM_NETWORK_PREFERENCE_TEST;
13841 
13842         // Act on ConnectivityService.setOemNetworkPreference()
13843         assertThrows(SecurityException.class,
13844                 () -> mService.setOemNetworkPreference(
13845                         createDefaultOemNetworkPreferences(networkPref),
13846                         null));
13847     }
13848 
13849     @Test
13850     public void testSetOemNetworkPreferenceFailsForInvalidTestRequest() {
13851         assertSetOemNetworkPreferenceFailsForInvalidTestRequest(OEM_NETWORK_PREFERENCE_TEST);
13852     }
13853 
13854     @Test
13855     public void testSetOemNetworkPreferenceFailsForInvalidTestOnlyRequest() {
13856         assertSetOemNetworkPreferenceFailsForInvalidTestRequest(OEM_NETWORK_PREFERENCE_TEST_ONLY);
13857     }
13858 
13859     private void assertSetOemNetworkPreferenceFailsForInvalidTestRequest(
13860             @OemNetworkPreferences.OemNetworkPreference final int oemNetworkPreferenceForTest) {
13861         mockHasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, true);
13862         final String secondPackage = "does.not.matter";
13863 
13864         // A valid test request would only have a single mapping.
13865         final OemNetworkPreferences pref = new OemNetworkPreferences.Builder()
13866                 .addNetworkPreference(TEST_PACKAGE_NAME, oemNetworkPreferenceForTest)
13867                 .addNetworkPreference(secondPackage, oemNetworkPreferenceForTest)
13868                 .build();
13869 
13870         // Act on ConnectivityService.setOemNetworkPreference()
13871         assertThrows(IllegalArgumentException.class,
13872                 () -> mService.setOemNetworkPreference(pref, null));
13873     }
13874 
13875     private void setOemNetworkPreferenceAgentConnected(final int transportType,
13876             final boolean connectAgent) throws Exception {
13877         switch(transportType) {
13878             // Corresponds to a metered cellular network. Will be used for the default network.
13879             case TRANSPORT_CELLULAR:
13880                 if (!connectAgent) {
13881                     mCellAgent.disconnect();
13882                     break;
13883                 }
13884                 mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
13885                 mCellAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
13886                 mCellAgent.connect(true);
13887                 break;
13888             // Corresponds to a restricted ethernet network with OEM_PAID/OEM_PRIVATE.
13889             case TRANSPORT_ETHERNET:
13890                 if (!connectAgent) {
13891                     stopOemManagedNetwork();
13892                     break;
13893                 }
13894                 startOemManagedNetwork(true);
13895                 break;
13896             // Corresponds to unmetered Wi-Fi.
13897             case TRANSPORT_WIFI:
13898                 if (!connectAgent) {
13899                     mWiFiAgent.disconnect();
13900                     break;
13901                 }
13902                 mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
13903                 mWiFiAgent.addCapability(NET_CAPABILITY_NOT_METERED);
13904                 mWiFiAgent.connect(true);
13905                 break;
13906             default:
13907                 throw new AssertionError("Unsupported transport type passed in.");
13908 
13909         }
13910         waitForIdle();
13911     }
13912 
13913     private void startOemManagedNetwork(final boolean isOemPaid) throws Exception {
13914         mEthernetAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
13915         mEthernetAgent.addCapability(
13916                 isOemPaid ? NET_CAPABILITY_OEM_PAID : NET_CAPABILITY_OEM_PRIVATE);
13917         mEthernetAgent.removeCapability(NET_CAPABILITY_NOT_RESTRICTED);
13918         mEthernetAgent.connect(true);
13919     }
13920 
13921     private void stopOemManagedNetwork() {
13922         mEthernetAgent.disconnect();
13923         waitForIdle();
13924     }
13925 
13926     private void verifyMultipleDefaultNetworksTracksCorrectly(
13927             final int expectedOemRequestsSize,
13928             @NonNull final Network expectedDefaultNetwork,
13929             @NonNull final Network expectedPerAppNetwork) {
13930         // The current test setup assumes two tracked default network requests; one for the default
13931         // network and the other for the OEM network preference being tested. This will be validated
13932         // each time to confirm it doesn't change under test.
13933         final int expectedDefaultNetworkRequestsSize = 2;
13934         assertEquals(expectedDefaultNetworkRequestsSize, mService.mDefaultNetworkRequests.size());
13935         for (final NetworkRequestInfo defaultRequest : mService.mDefaultNetworkRequests) {
13936             final Network defaultNetwork = defaultRequest.getSatisfier() == null
13937                     ? null : defaultRequest.getSatisfier().network();
13938             // If this is the default request.
13939             if (defaultRequest == mService.mDefaultRequest) {
13940                 assertEquals(
13941                         expectedDefaultNetwork,
13942                         defaultNetwork);
13943                 // Make sure this value doesn't change.
13944                 assertEquals(1, defaultRequest.mRequests.size());
13945                 continue;
13946             }
13947             assertEquals(expectedPerAppNetwork, defaultNetwork);
13948             assertEquals(expectedOemRequestsSize, defaultRequest.mRequests.size());
13949         }
13950         verifyMultipleDefaultCallbacks(expectedDefaultNetwork, expectedPerAppNetwork);
13951     }
13952 
13953     /**
13954      * Verify default callbacks for 'available' fire as expected. This will only run if
13955      * registerDefaultNetworkCallbacks() was executed prior and will only be different if the
13956      * setOemNetworkPreference() per-app API was used for the current process.
13957      * @param expectedSystemDefault the expected network for the system default.
13958      * @param expectedPerAppDefault the expected network for the current process's default.
13959      */
13960     private void verifyMultipleDefaultCallbacks(
13961             @NonNull final Network expectedSystemDefault,
13962             @NonNull final Network expectedPerAppDefault) {
13963         if (null != mSystemDefaultNetworkCallback && null != expectedSystemDefault
13964                 && mService.mNoServiceNetwork.network() != expectedSystemDefault) {
13965             // getLastAvailableNetwork() is used as this method can be called successively with
13966             // the same network to validate therefore expectAvailableThenValidatedCallbacks
13967             // can't be used.
13968             assertEquals(mSystemDefaultNetworkCallback.getLastAvailableNetwork(),
13969                     expectedSystemDefault);
13970         }
13971         if (null != mDefaultNetworkCallback && null != expectedPerAppDefault
13972                 && mService.mNoServiceNetwork.network() != expectedPerAppDefault) {
13973             assertEquals(mDefaultNetworkCallback.getLastAvailableNetwork(),
13974                     expectedPerAppDefault);
13975         }
13976     }
13977 
13978     private void registerDefaultNetworkCallbacks() {
13979         if (mSystemDefaultNetworkCallback != null || mDefaultNetworkCallback != null
13980                 || mProfileDefaultNetworkCallback != null
13981                 || mProfileDefaultNetworkCallbackAsAppUid2 != null
13982                 || mTestPackageDefaultNetworkCallback2 != null
13983                 || mTestPackageDefaultNetworkCallback != null) {
13984             throw new IllegalStateException("Default network callbacks already registered");
13985         }
13986 
13987         mSystemDefaultNetworkCallback = new TestNetworkCallback();
13988         mDefaultNetworkCallback = new TestNetworkCallback();
13989         mProfileDefaultNetworkCallback = new TestNetworkCallback();
13990         mTestPackageDefaultNetworkCallback = new TestNetworkCallback();
13991         mProfileDefaultNetworkCallbackAsAppUid2 = new TestNetworkCallback();
13992         mTestPackageDefaultNetworkCallback2 = new TestNetworkCallback();
13993         mCm.registerSystemDefaultNetworkCallback(mSystemDefaultNetworkCallback,
13994                 new Handler(ConnectivityThread.getInstanceLooper()));
13995         mCm.registerDefaultNetworkCallback(mDefaultNetworkCallback);
13996         registerDefaultNetworkCallbackAsUid(mProfileDefaultNetworkCallback,
13997                 TEST_WORK_PROFILE_APP_UID);
13998         registerDefaultNetworkCallbackAsUid(mTestPackageDefaultNetworkCallback, TEST_PACKAGE_UID);
13999         registerDefaultNetworkCallbackAsUid(mProfileDefaultNetworkCallbackAsAppUid2,
14000                 TEST_WORK_PROFILE_APP_UID_2);
14001         registerDefaultNetworkCallbackAsUid(mTestPackageDefaultNetworkCallback2,
14002                 TEST_PACKAGE_UID2);
14003         // TODO: test using ConnectivityManager#registerDefaultNetworkCallbackAsUid as well.
14004         mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_DENIED);
14005     }
14006 
14007     private void unregisterDefaultNetworkCallbacks() {
14008         if (null != mDefaultNetworkCallback) {
14009             mCm.unregisterNetworkCallback(mDefaultNetworkCallback);
14010         }
14011         if (null != mSystemDefaultNetworkCallback) {
14012             mCm.unregisterNetworkCallback(mSystemDefaultNetworkCallback);
14013         }
14014         if (null != mProfileDefaultNetworkCallback) {
14015             mCm.unregisterNetworkCallback(mProfileDefaultNetworkCallback);
14016         }
14017         if (null != mTestPackageDefaultNetworkCallback) {
14018             mCm.unregisterNetworkCallback(mTestPackageDefaultNetworkCallback);
14019         }
14020         if (null != mProfileDefaultNetworkCallbackAsAppUid2) {
14021             mCm.unregisterNetworkCallback(mProfileDefaultNetworkCallbackAsAppUid2);
14022         }
14023         if (null != mTestPackageDefaultNetworkCallback2) {
14024             mCm.unregisterNetworkCallback(mTestPackageDefaultNetworkCallback2);
14025         }
14026         mSystemDefaultNetworkCallback = null;
14027         mDefaultNetworkCallback = null;
14028         mProfileDefaultNetworkCallback = null;
14029         mTestPackageDefaultNetworkCallback = null;
14030         mProfileDefaultNetworkCallbackAsAppUid2 = null;
14031         mTestPackageDefaultNetworkCallback2 = null;
14032     }
14033 
14034     private void setupMultipleDefaultNetworksForOemNetworkPreferenceNotCurrentUidTest(
14035             @OemNetworkPreferences.OemNetworkPreference final int networkPrefToSetup)
14036             throws Exception {
14037         final int testPackageNameUid = TEST_PACKAGE_UID;
14038         final String testPackageName = "per.app.defaults.package";
14039         setupMultipleDefaultNetworksForOemNetworkPreferenceTest(
14040                 networkPrefToSetup, testPackageNameUid, testPackageName);
14041     }
14042 
14043     private void setupMultipleDefaultNetworksForOemNetworkPreferenceCurrentUidTest(
14044             @OemNetworkPreferences.OemNetworkPreference final int networkPrefToSetup)
14045             throws Exception {
14046         final int testPackageNameUid = Process.myUid();
14047         final String testPackageName = "per.app.defaults.package";
14048         setupMultipleDefaultNetworksForOemNetworkPreferenceTest(
14049                 networkPrefToSetup, testPackageNameUid, testPackageName);
14050     }
14051 
14052     private void setupMultipleDefaultNetworksForOemNetworkPreferenceTest(
14053             @OemNetworkPreferences.OemNetworkPreference final int networkPrefToSetup,
14054             final int testPackageUid, @NonNull final String testPackageName) throws Exception {
14055         // Only the default request should be included at start.
14056         assertEquals(1, mService.mDefaultNetworkRequests.size());
14057 
14058         final UidRangeParcel[] uidRanges =
14059                 toUidRangeStableParcels(uidRangesForUids(testPackageUid));
14060         setupSetOemNetworkPreferenceForPreferenceTest(
14061                 networkPrefToSetup, uidRanges, testPackageName);
14062     }
14063 
14064     private void setupSetOemNetworkPreferenceForPreferenceTest(
14065             @OemNetworkPreferences.OemNetworkPreference final int networkPrefToSetup,
14066             @NonNull final UidRangeParcel[] uidRanges,
14067             @NonNull final String testPackageName) throws Exception {
14068         setupSetOemNetworkPreferenceForPreferenceTest(networkPrefToSetup, uidRanges,
14069                 testPackageName, PRIMARY_USER_HANDLE, true /* hasAutomotiveFeature */);
14070     }
14071 
14072     private void setupSetOemNetworkPreferenceForPreferenceTest(
14073             @OemNetworkPreferences.OemNetworkPreference final int networkPrefToSetup,
14074             @NonNull final UidRangeParcel[] uidRanges,
14075             @NonNull final String testPackageName,
14076             @NonNull final UserHandle user) throws Exception {
14077         setupSetOemNetworkPreferenceForPreferenceTest(networkPrefToSetup, uidRanges,
14078                 testPackageName, user, true /* hasAutomotiveFeature */);
14079     }
14080 
14081     private void setupSetOemNetworkPreferenceForPreferenceTest(
14082             @OemNetworkPreferences.OemNetworkPreference final int networkPrefToSetup,
14083             @NonNull final UidRangeParcel[] uidRanges,
14084             @NonNull final String testPackageName,
14085             @NonNull final UserHandle user,
14086             final boolean hasAutomotiveFeature) throws Exception {
14087         mockHasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, hasAutomotiveFeature);
14088 
14089         // These tests work off a single UID therefore using 'start' is valid.
14090         mockGetApplicationInfo(testPackageName, uidRanges[0].start, user);
14091 
14092         setOemNetworkPreference(networkPrefToSetup, testPackageName);
14093     }
14094 
14095     private void setOemNetworkPreference(final int networkPrefToSetup,
14096             @NonNull final String... testPackageNames)
14097             throws Exception {
14098         mockHasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, true);
14099 
14100         // Build OemNetworkPreferences object
14101         final OemNetworkPreferences.Builder builder = new OemNetworkPreferences.Builder();
14102         for (final String packageName : testPackageNames) {
14103             builder.addNetworkPreference(packageName, networkPrefToSetup);
14104         }
14105         final OemNetworkPreferences pref = builder.build();
14106 
14107         // Act on ConnectivityService.setOemNetworkPreference()
14108         final TestOemListenerCallback oemPrefListener = new TestOemListenerCallback();
14109         mService.setOemNetworkPreference(pref, oemPrefListener);
14110 
14111         // Verify call returned successfully
14112         oemPrefListener.expectOnComplete();
14113     }
14114 
14115     private static class TestOemListenerCallback implements IOnCompleteListener {
14116         final CompletableFuture<Object> mDone = new CompletableFuture<>();
14117 
14118         @Override
14119         public void onComplete() {
14120             mDone.complete(new Object());
14121         }
14122 
14123         void expectOnComplete() {
14124             try {
14125                 mDone.get(TIMEOUT_MS, TimeUnit.MILLISECONDS);
14126             } catch (TimeoutException e) {
14127                 fail("Expected onComplete() not received after " + TIMEOUT_MS + " ms");
14128             } catch (Exception e) {
14129                 fail(e.getMessage());
14130             }
14131         }
14132 
14133         @Override
14134         public IBinder asBinder() {
14135             return null;
14136         }
14137     }
14138 
14139     @Test
14140     public void testMultiDefaultGetActiveNetworkIsCorrect() throws Exception {
14141         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
14142                 OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY;
14143         final int expectedOemPrefRequestSize = 1;
14144         registerDefaultNetworkCallbacks();
14145 
14146         // Setup the test process to use networkPref for their default network.
14147         setupMultipleDefaultNetworksForOemNetworkPreferenceCurrentUidTest(networkPref);
14148 
14149         // Bring up ethernet with OEM_PAID. This will satisfy NET_CAPABILITY_OEM_PAID.
14150         // The active network for the default should be null at this point as this is a retricted
14151         // network.
14152         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, true);
14153         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
14154                 null,
14155                 mEthernetAgent.getNetwork());
14156 
14157         // Verify that the active network is correct
14158         verifyActiveNetwork(TRANSPORT_ETHERNET);
14159         // default NCs will be unregistered in tearDown
14160     }
14161 
14162     @Test
14163     public void testMultiDefaultIsActiveNetworkMeteredIsCorrect() throws Exception {
14164         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
14165                 OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY;
14166         final int expectedOemPrefRequestSize = 1;
14167         registerDefaultNetworkCallbacks();
14168 
14169         // Setup the test process to use networkPref for their default network.
14170         setupMultipleDefaultNetworksForOemNetworkPreferenceCurrentUidTest(networkPref);
14171 
14172         // Returns true by default when no network is available.
14173         assertTrue(mCm.isActiveNetworkMetered());
14174 
14175         // Connect to an unmetered restricted network that will only be available to the OEM pref.
14176         mEthernetAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
14177         mEthernetAgent.addCapability(NET_CAPABILITY_OEM_PAID);
14178         mEthernetAgent.addCapability(NET_CAPABILITY_NOT_METERED);
14179         mEthernetAgent.removeCapability(NET_CAPABILITY_NOT_RESTRICTED);
14180         mEthernetAgent.connect(true);
14181         waitForIdle();
14182 
14183         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
14184                 null,
14185                 mEthernetAgent.getNetwork());
14186 
14187         assertFalse(mCm.isActiveNetworkMetered());
14188         // default NCs will be unregistered in tearDown
14189     }
14190 
14191     @Test
14192     public void testPerAppDefaultRegisterDefaultNetworkCallback() throws Exception {
14193         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
14194                 OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY;
14195         final int expectedOemPrefRequestSize = 1;
14196         final TestNetworkCallback defaultNetworkCallback = new TestNetworkCallback();
14197 
14198         // Register the default network callback before the pref is already set. This means that
14199         // the policy will be applied to the callback on setOemNetworkPreference().
14200         mCm.registerDefaultNetworkCallback(defaultNetworkCallback);
14201         defaultNetworkCallback.assertNoCallback();
14202 
14203         final TestNetworkCallback otherUidDefaultCallback = new TestNetworkCallback();
14204         withPermission(NETWORK_SETTINGS, () ->
14205                 mCm.registerDefaultNetworkCallbackForUid(TEST_PACKAGE_UID, otherUidDefaultCallback,
14206                         new Handler(ConnectivityThread.getInstanceLooper())));
14207 
14208         // Setup the test process to use networkPref for their default network.
14209         setupMultipleDefaultNetworksForOemNetworkPreferenceCurrentUidTest(networkPref);
14210 
14211         // Bring up ethernet with OEM_PAID. This will satisfy NET_CAPABILITY_OEM_PAID.
14212         // The active nai for the default is null at this point as this is a restricted network.
14213         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, true);
14214         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
14215                 null,
14216                 mEthernetAgent.getNetwork());
14217 
14218         // At this point with a restricted network used, the available callback should trigger.
14219         defaultNetworkCallback.expectAvailableThenValidatedCallbacks(mEthernetAgent);
14220         assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mEthernetAgent.getNetwork());
14221         otherUidDefaultCallback.assertNoCallback();
14222 
14223         // Now bring down the default network which should trigger a LOST callback.
14224         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, false);
14225 
14226         // At this point, with no network is available, the lost callback should trigger
14227         defaultNetworkCallback.expect(LOST, mEthernetAgent);
14228         otherUidDefaultCallback.assertNoCallback();
14229 
14230         // Confirm we can unregister without issues.
14231         mCm.unregisterNetworkCallback(defaultNetworkCallback);
14232         mCm.unregisterNetworkCallback(otherUidDefaultCallback);
14233     }
14234 
14235     @Test
14236     public void testPerAppDefaultRegisterDefaultNetworkCallbackAfterPrefSet() throws Exception {
14237         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
14238                 OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY;
14239         final int expectedOemPrefRequestSize = 1;
14240         final TestNetworkCallback defaultNetworkCallback = new TestNetworkCallback();
14241 
14242         // Setup the test process to use networkPref for their default network.
14243         setupMultipleDefaultNetworksForOemNetworkPreferenceCurrentUidTest(networkPref);
14244 
14245         // Register the default network callback after the pref is already set. This means that
14246         // the policy will be applied to the callback on requestNetwork().
14247         mCm.registerDefaultNetworkCallback(defaultNetworkCallback);
14248         defaultNetworkCallback.assertNoCallback();
14249 
14250         final TestNetworkCallback otherUidDefaultCallback = new TestNetworkCallback();
14251         withPermission(NETWORK_SETTINGS, () ->
14252                 mCm.registerDefaultNetworkCallbackForUid(TEST_PACKAGE_UID, otherUidDefaultCallback,
14253                         new Handler(ConnectivityThread.getInstanceLooper())));
14254 
14255         // Bring up ethernet with OEM_PAID. This will satisfy NET_CAPABILITY_OEM_PAID.
14256         // The active nai for the default is null at this point as this is a restricted network.
14257         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, true);
14258         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
14259                 null,
14260                 mEthernetAgent.getNetwork());
14261 
14262         // At this point with a restricted network used, the available callback should trigger
14263         defaultNetworkCallback.expectAvailableThenValidatedCallbacks(mEthernetAgent);
14264         assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mEthernetAgent.getNetwork());
14265         otherUidDefaultCallback.assertNoCallback();
14266 
14267         // Now bring down the default network which should trigger a LOST callback.
14268         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, false);
14269         otherUidDefaultCallback.assertNoCallback();
14270 
14271         // At this point, with no network is available, the lost callback should trigger
14272         defaultNetworkCallback.expect(LOST, mEthernetAgent);
14273         otherUidDefaultCallback.assertNoCallback();
14274 
14275         // Confirm we can unregister without issues.
14276         mCm.unregisterNetworkCallback(defaultNetworkCallback);
14277         mCm.unregisterNetworkCallback(otherUidDefaultCallback);
14278     }
14279 
14280     @Test
14281     public void testPerAppDefaultRegisterDefaultNetworkCallbackDoesNotFire() throws Exception {
14282         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
14283                 OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY;
14284         final int expectedOemPrefRequestSize = 1;
14285         final TestNetworkCallback defaultNetworkCallback = new TestNetworkCallback();
14286         final int userId = UserHandle.getUserId(Process.myUid());
14287 
14288         mCm.registerDefaultNetworkCallback(defaultNetworkCallback);
14289         defaultNetworkCallback.assertNoCallback();
14290 
14291         final TestNetworkCallback otherUidDefaultCallback = new TestNetworkCallback();
14292         withPermission(NETWORK_SETTINGS, () ->
14293                 mCm.registerDefaultNetworkCallbackForUid(TEST_PACKAGE_UID, otherUidDefaultCallback,
14294                         new Handler(ConnectivityThread.getInstanceLooper())));
14295 
14296         // Setup a process different than the test process to use the default network. This means
14297         // that the defaultNetworkCallback won't be tracked by the per-app policy.
14298         setupMultipleDefaultNetworksForOemNetworkPreferenceNotCurrentUidTest(networkPref);
14299 
14300         // Bring up ethernet with OEM_PAID. This will satisfy NET_CAPABILITY_OEM_PAID.
14301         // The active nai for the default is null at this point as this is a restricted network.
14302         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, true);
14303         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
14304                 null,
14305                 mEthernetAgent.getNetwork());
14306 
14307         // As this callback does not have access to the OEM_PAID network, it will not fire.
14308         defaultNetworkCallback.assertNoCallback();
14309         assertDefaultNetworkCapabilities(userId /* no networks */);
14310 
14311         // The other UID does have access, and gets a callback.
14312         otherUidDefaultCallback.expectAvailableThenValidatedCallbacks(mEthernetAgent);
14313 
14314         // Bring up unrestricted cellular. This should now satisfy the default network.
14315         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true);
14316         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
14317                 mCellAgent.getNetwork(),
14318                 mEthernetAgent.getNetwork());
14319 
14320         // At this point with an unrestricted network used, the available callback should trigger
14321         // The other UID is unaffected and remains on the paid network.
14322         defaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
14323         assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCellAgent.getNetwork());
14324         assertDefaultNetworkCapabilities(userId, mCellAgent);
14325         otherUidDefaultCallback.assertNoCallback();
14326 
14327         // Now bring down the per-app network.
14328         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, false);
14329 
14330         // Since the callback didn't use the per-app network, only the other UID gets a callback.
14331         // Because the preference specifies no fallback, it does not switch to cellular.
14332         defaultNetworkCallback.assertNoCallback();
14333         otherUidDefaultCallback.expect(LOST, mEthernetAgent);
14334 
14335         // Now bring down the default network.
14336         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, false);
14337 
14338         // As this callback was tracking the default, this should now trigger.
14339         defaultNetworkCallback.expect(LOST, mCellAgent);
14340         otherUidDefaultCallback.assertNoCallback();
14341 
14342         // Confirm we can unregister without issues.
14343         mCm.unregisterNetworkCallback(defaultNetworkCallback);
14344         mCm.unregisterNetworkCallback(otherUidDefaultCallback);
14345     }
14346 
14347     /**
14348      * This method assumes that the same uidRanges input will be used to verify that dependencies
14349      * are called as expected.
14350      */
14351     private void verifySetOemNetworkPreferenceForPreference(
14352             @NonNull final UidRangeParcel[] uidRanges,
14353             final int addUidRangesNetId,
14354             final int addUidRangesTimes,
14355             final int removeUidRangesNetId,
14356             final int removeUidRangesTimes,
14357             final boolean shouldDestroyNetwork) throws RemoteException {
14358         verifySetOemNetworkPreferenceForPreference(uidRanges, uidRanges,
14359                 addUidRangesNetId, addUidRangesTimes, removeUidRangesNetId, removeUidRangesTimes,
14360                 shouldDestroyNetwork);
14361     }
14362 
14363     private void verifySetOemNetworkPreferenceForPreference(
14364             @NonNull final UidRangeParcel[] addedUidRanges,
14365             @NonNull final UidRangeParcel[] removedUidRanges,
14366             final int addUidRangesNetId,
14367             final int addUidRangesTimes,
14368             final int removeUidRangesNetId,
14369             final int removeUidRangesTimes,
14370             final boolean shouldDestroyNetwork) throws RemoteException {
14371         final boolean useAnyIdForAdd = OEM_PREF_ANY_NET_ID == addUidRangesNetId;
14372         final boolean useAnyIdForRemove = OEM_PREF_ANY_NET_ID == removeUidRangesNetId;
14373 
14374         // Validate that add/remove uid range (with oem priority) to/from netd.
14375         verify(mMockNetd, times(addUidRangesTimes)).networkAddUidRangesParcel(argThat(config ->
14376                 (useAnyIdForAdd ? true : addUidRangesNetId == config.netId)
14377                         && Arrays.equals(addedUidRanges, config.uidRanges)
14378                         && PREFERENCE_ORDER_OEM == config.subPriority));
14379         verify(mMockNetd, times(removeUidRangesTimes)).networkRemoveUidRangesParcel(
14380                 argThat(config -> (useAnyIdForRemove ? true : removeUidRangesNetId == config.netId)
14381                         && Arrays.equals(removedUidRanges, config.uidRanges)
14382                         && PREFERENCE_ORDER_OEM == config.subPriority));
14383         if (shouldDestroyNetwork) {
14384             verify(mMockNetd, times(1))
14385                     .networkDestroy((useAnyIdForRemove ? anyInt() : eq(removeUidRangesNetId)));
14386         }
14387         reset(mMockNetd);
14388     }
14389 
14390     /**
14391      * Test the tracked default requests allows test requests without standard setup.
14392      */
14393     @Test
14394     public void testSetOemNetworkPreferenceAllowsValidTestRequestWithoutChecks() throws Exception {
14395         @OemNetworkPreferences.OemNetworkPreference int networkPref =
14396                 OEM_NETWORK_PREFERENCE_TEST;
14397         validateSetOemNetworkPreferenceAllowsValidTestPrefRequest(networkPref);
14398     }
14399 
14400     /**
14401      * Test the tracked default requests allows test only requests without standard setup.
14402      */
14403     @Test
14404     public void testSetOemNetworkPreferenceAllowsValidTestOnlyRequestWithoutChecks()
14405             throws Exception {
14406         @OemNetworkPreferences.OemNetworkPreference int networkPref =
14407                 OEM_NETWORK_PREFERENCE_TEST_ONLY;
14408         validateSetOemNetworkPreferenceAllowsValidTestPrefRequest(networkPref);
14409     }
14410 
14411     private void validateSetOemNetworkPreferenceAllowsValidTestPrefRequest(int networkPref)
14412             throws Exception {
14413         // The caller must have the MANAGE_TEST_NETWORKS permission.
14414         final int testPackageUid = 123;
14415         final String validTestPackageName = "does.not.matter";
14416         final UidRangeParcel[] uidRanges =
14417                 toUidRangeStableParcels(uidRangesForUids(testPackageUid));
14418         mServiceContext.setPermission(
14419                 Manifest.permission.MANAGE_TEST_NETWORKS, PERMISSION_GRANTED);
14420 
14421         // Put the system into a state in which setOemNetworkPreference() would normally fail. This
14422         // will confirm that a valid test request can bypass these checks.
14423         mockHasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, false);
14424         mServiceContext.setPermission(
14425                 Manifest.permission.CONTROL_OEM_PAID_NETWORK_PREFERENCE, PERMISSION_DENIED);
14426 
14427         // Validate the starting requests only includes the system default request.
14428         assertEquals(1, mService.mDefaultNetworkRequests.size());
14429 
14430         // Add an OEM default network request to track.
14431         setupSetOemNetworkPreferenceForPreferenceTest(
14432                 networkPref, uidRanges, validTestPackageName, PRIMARY_USER_HANDLE,
14433                 false /* hasAutomotiveFeature */);
14434 
14435         // Two requests should now exist; the system default and the test request.
14436         assertEquals(2, mService.mDefaultNetworkRequests.size());
14437     }
14438 
14439     /**
14440      * Test the tracked default requests clear previous OEM requests on setOemNetworkPreference().
14441      */
14442     @Test
14443     public void testSetOemNetworkPreferenceClearPreviousOemValues() throws Exception {
14444         @OemNetworkPreferences.OemNetworkPreference int networkPref =
14445                 OEM_NETWORK_PREFERENCE_OEM_PAID;
14446         final int testPackageUid = 123;
14447         final String testPackageName = "com.google.apps.contacts";
14448         final UidRangeParcel[] uidRanges =
14449                 toUidRangeStableParcels(uidRangesForUids(testPackageUid));
14450 
14451         // Validate the starting requests only includes the system default request.
14452         assertEquals(1, mService.mDefaultNetworkRequests.size());
14453 
14454         // Add an OEM default network request to track.
14455         setupSetOemNetworkPreferenceForPreferenceTest(networkPref, uidRanges, testPackageName);
14456 
14457         // Two requests should exist, one for the fallback and one for the pref.
14458         assertEquals(2, mService.mDefaultNetworkRequests.size());
14459 
14460         networkPref = OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY;
14461         setupSetOemNetworkPreferenceForPreferenceTest(networkPref, uidRanges, testPackageName);
14462 
14463         // Two requests should still exist validating the previous per-app request was replaced.
14464         assertEquals(2, mService.mDefaultNetworkRequests.size());
14465     }
14466 
14467     /**
14468      * Test network priority for preference OEM_NETWORK_PREFERENCE_OEM_PAID in the following order:
14469      * NET_CAPABILITY_NOT_METERED -> NET_CAPABILITY_OEM_PAID -> fallback
14470      */
14471     @Test
14472     public void testMultilayerForPreferenceOemPaidEvaluatesCorrectly()
14473             throws Exception {
14474         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
14475                 OEM_NETWORK_PREFERENCE_OEM_PAID;
14476 
14477         // Arrange PackageManager mocks
14478         final UidRangeParcel[] uidRanges =
14479                 toUidRangeStableParcels(uidRangesForUids(TEST_PACKAGE_UID));
14480         setupSetOemNetworkPreferenceForPreferenceTest(networkPref, uidRanges, TEST_PACKAGE_NAME);
14481 
14482         // Verify the starting state. No networks should be connected.
14483         verifySetOemNetworkPreferenceForPreference(uidRanges,
14484                 OEM_PREF_ANY_NET_ID, 0 /* times */,
14485                 OEM_PREF_ANY_NET_ID, 0 /* times */,
14486                 false /* shouldDestroyNetwork */);
14487 
14488         // Test lowest to highest priority requests.
14489         // Bring up metered cellular. This will satisfy the fallback network.
14490         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true);
14491         verifySetOemNetworkPreferenceForPreference(uidRanges,
14492                 mCellAgent.getNetwork().netId, 1 /* times */,
14493                 OEM_PREF_ANY_NET_ID, 0 /* times */,
14494                 false /* shouldDestroyNetwork */);
14495 
14496         // Bring up ethernet with OEM_PAID. This will satisfy NET_CAPABILITY_OEM_PAID.
14497         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, true);
14498         verifySetOemNetworkPreferenceForPreference(uidRanges,
14499                 mEthernetAgent.getNetwork().netId, 1 /* times */,
14500                 mCellAgent.getNetwork().netId, 1 /* times */,
14501                 false /* shouldDestroyNetwork */);
14502 
14503         // Bring up unmetered Wi-Fi. This will satisfy NET_CAPABILITY_NOT_METERED.
14504         setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, true);
14505         verifySetOemNetworkPreferenceForPreference(uidRanges,
14506                 mWiFiAgent.getNetwork().netId, 1 /* times */,
14507                 mEthernetAgent.getNetwork().netId, 1 /* times */,
14508                 false /* shouldDestroyNetwork */);
14509 
14510         // Disconnecting OEM_PAID should have no effect as it is lower in priority then unmetered.
14511         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, false);
14512         // netd should not be called as default networks haven't changed.
14513         verifySetOemNetworkPreferenceForPreference(uidRanges,
14514                 OEM_PREF_ANY_NET_ID, 0 /* times */,
14515                 OEM_PREF_ANY_NET_ID, 0 /* times */,
14516                 false /* shouldDestroyNetwork */);
14517 
14518         // Disconnecting unmetered should put PANS on lowest priority fallback request.
14519         setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, false);
14520         verifySetOemNetworkPreferenceForPreference(uidRanges,
14521                 mCellAgent.getNetwork().netId, 1 /* times */,
14522                 mWiFiAgent.getNetwork().netId, 0 /* times */,
14523                 true /* shouldDestroyNetwork */);
14524 
14525         // Disconnecting the fallback network should result in no connectivity.
14526         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, false);
14527         verifySetOemNetworkPreferenceForPreference(uidRanges,
14528                 OEM_PREF_ANY_NET_ID, 0 /* times */,
14529                 mCellAgent.getNetwork().netId, 0 /* times */,
14530                 true /* shouldDestroyNetwork */);
14531     }
14532 
14533     /**
14534      * Test network priority for OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK in the following order:
14535      * NET_CAPABILITY_NOT_METERED -> NET_CAPABILITY_OEM_PAID
14536      */
14537     @Test
14538     public void testMultilayerForPreferenceOemPaidNoFallbackEvaluatesCorrectly()
14539             throws Exception {
14540         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
14541                 OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK;
14542 
14543         // Arrange PackageManager mocks
14544         final UidRangeParcel[] uidRanges =
14545                 toUidRangeStableParcels(uidRangesForUids(TEST_PACKAGE_UID));
14546         setupSetOemNetworkPreferenceForPreferenceTest(networkPref, uidRanges, TEST_PACKAGE_NAME);
14547 
14548         // Verify the starting state. This preference doesn't support using the fallback network
14549         // therefore should be on the disconnected network as it has no networks to connect to.
14550         verifySetOemNetworkPreferenceForPreference(uidRanges,
14551                 mService.mNoServiceNetwork.network.getNetId(), 1 /* times */,
14552                 OEM_PREF_ANY_NET_ID, 0 /* times */,
14553                 false /* shouldDestroyNetwork */);
14554 
14555         // Test lowest to highest priority requests.
14556         // Bring up metered cellular. This will satisfy the fallback network.
14557         // This preference should not use this network as it doesn't support fallback usage.
14558         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true);
14559         verifySetOemNetworkPreferenceForPreference(uidRanges,
14560                 OEM_PREF_ANY_NET_ID, 0 /* times */,
14561                 OEM_PREF_ANY_NET_ID, 0 /* times */,
14562                 false /* shouldDestroyNetwork */);
14563 
14564         // Bring up ethernet with OEM_PAID. This will satisfy NET_CAPABILITY_OEM_PAID.
14565         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, true);
14566         verifySetOemNetworkPreferenceForPreference(uidRanges,
14567                 mEthernetAgent.getNetwork().netId, 1 /* times */,
14568                 mService.mNoServiceNetwork.network.getNetId(), 1 /* times */,
14569                 false /* shouldDestroyNetwork */);
14570 
14571         // Bring up unmetered Wi-Fi. This will satisfy NET_CAPABILITY_NOT_METERED.
14572         setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, true);
14573         verifySetOemNetworkPreferenceForPreference(uidRanges,
14574                 mWiFiAgent.getNetwork().netId, 1 /* times */,
14575                 mEthernetAgent.getNetwork().netId, 1 /* times */,
14576                 false /* shouldDestroyNetwork */);
14577 
14578         // Disconnecting unmetered should put PANS on OEM_PAID.
14579         setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, false);
14580         verifySetOemNetworkPreferenceForPreference(uidRanges,
14581                 mEthernetAgent.getNetwork().netId, 1 /* times */,
14582                 mWiFiAgent.getNetwork().netId, 0 /* times */,
14583                 true /* shouldDestroyNetwork */);
14584 
14585         // Disconnecting OEM_PAID should result in no connectivity.
14586         // OEM_PAID_NO_FALLBACK not supporting a fallback now uses the disconnected network.
14587         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, false);
14588         verifySetOemNetworkPreferenceForPreference(uidRanges,
14589                 mService.mNoServiceNetwork.network.getNetId(), 1 /* times */,
14590                 mEthernetAgent.getNetwork().netId, 0 /* times */,
14591                 true /* shouldDestroyNetwork */);
14592     }
14593 
14594     /**
14595      * Test network priority for OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY in the following order:
14596      * NET_CAPABILITY_OEM_PAID
14597      * This preference should only apply to OEM_PAID networks.
14598      */
14599     @Test
14600     public void testMultilayerForPreferenceOemPaidOnlyEvaluatesCorrectly()
14601             throws Exception {
14602         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
14603                 OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY;
14604 
14605         // Arrange PackageManager mocks
14606         final UidRangeParcel[] uidRanges =
14607                 toUidRangeStableParcels(uidRangesForUids(TEST_PACKAGE_UID));
14608         setupSetOemNetworkPreferenceForPreferenceTest(networkPref, uidRanges, TEST_PACKAGE_NAME);
14609 
14610         // Verify the starting state. This preference doesn't support using the fallback network
14611         // therefore should be on the disconnected network as it has no networks to connect to.
14612         verifySetOemNetworkPreferenceForPreference(uidRanges,
14613                 mService.mNoServiceNetwork.network.getNetId(), 1 /* times */,
14614                 OEM_PREF_ANY_NET_ID, 0 /* times */,
14615                 false /* shouldDestroyNetwork */);
14616 
14617         // Bring up metered cellular. This should not apply to this preference.
14618         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true);
14619         verifySetOemNetworkPreferenceForPreference(uidRanges,
14620                 OEM_PREF_ANY_NET_ID, 0 /* times */,
14621                 OEM_PREF_ANY_NET_ID, 0 /* times */,
14622                 false /* shouldDestroyNetwork */);
14623 
14624         // Bring up unmetered Wi-Fi. This should not apply to this preference.
14625         setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, true);
14626         verifySetOemNetworkPreferenceForPreference(uidRanges,
14627                 OEM_PREF_ANY_NET_ID, 0 /* times */,
14628                 OEM_PREF_ANY_NET_ID, 0 /* times */,
14629                 false /* shouldDestroyNetwork */);
14630 
14631         // Bring up ethernet with OEM_PAID. This will satisfy NET_CAPABILITY_OEM_PAID.
14632         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, true);
14633         verifySetOemNetworkPreferenceForPreference(uidRanges,
14634                 mEthernetAgent.getNetwork().netId, 1 /* times */,
14635                 mService.mNoServiceNetwork.network.getNetId(), 1 /* times */,
14636                 false /* shouldDestroyNetwork */);
14637 
14638         // Disconnecting OEM_PAID should result in no connectivity.
14639         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, false);
14640         verifySetOemNetworkPreferenceForPreference(uidRanges,
14641                 mService.mNoServiceNetwork.network.getNetId(), 1 /* times */,
14642                 mEthernetAgent.getNetwork().netId, 0 /* times */,
14643                 true /* shouldDestroyNetwork */);
14644     }
14645 
14646     /**
14647      * Test network priority for OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY in the following order:
14648      * NET_CAPABILITY_OEM_PRIVATE
14649      * This preference should only apply to OEM_PRIVATE networks.
14650      */
14651     @Test
14652     public void testMultilayerForPreferenceOemPrivateOnlyEvaluatesCorrectly()
14653             throws Exception {
14654         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
14655                 OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY;
14656 
14657         // Arrange PackageManager mocks
14658         final UidRangeParcel[] uidRanges =
14659                 toUidRangeStableParcels(uidRangesForUids(TEST_PACKAGE_UID));
14660         setupSetOemNetworkPreferenceForPreferenceTest(networkPref, uidRanges, TEST_PACKAGE_NAME);
14661 
14662         // Verify the starting state. This preference doesn't support using the fallback network
14663         // therefore should be on the disconnected network as it has no networks to connect to.
14664         verifySetOemNetworkPreferenceForPreference(uidRanges,
14665                 mService.mNoServiceNetwork.network.getNetId(), 1 /* times */,
14666                 OEM_PREF_ANY_NET_ID, 0 /* times */,
14667                 false /* shouldDestroyNetwork */);
14668 
14669         // Bring up metered cellular. This should not apply to this preference.
14670         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true);
14671         verifySetOemNetworkPreferenceForPreference(uidRanges,
14672                 OEM_PREF_ANY_NET_ID, 0 /* times */,
14673                 OEM_PREF_ANY_NET_ID, 0 /* times */,
14674                 false /* shouldDestroyNetwork */);
14675 
14676         // Bring up unmetered Wi-Fi. This should not apply to this preference.
14677         setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, true);
14678         verifySetOemNetworkPreferenceForPreference(uidRanges,
14679                 OEM_PREF_ANY_NET_ID, 0 /* times */,
14680                 OEM_PREF_ANY_NET_ID, 0 /* times */,
14681                 false /* shouldDestroyNetwork */);
14682 
14683         // Bring up ethernet with OEM_PRIVATE. This will satisfy NET_CAPABILITY_OEM_PRIVATE.
14684         startOemManagedNetwork(false);
14685         verifySetOemNetworkPreferenceForPreference(uidRanges,
14686                 mEthernetAgent.getNetwork().netId, 1 /* times */,
14687                 mService.mNoServiceNetwork.network.getNetId(), 1 /* times */,
14688                 false /* shouldDestroyNetwork */);
14689 
14690         // Disconnecting OEM_PRIVATE should result in no connectivity.
14691         stopOemManagedNetwork();
14692         verifySetOemNetworkPreferenceForPreference(uidRanges,
14693                 mService.mNoServiceNetwork.network.getNetId(), 1 /* times */,
14694                 mEthernetAgent.getNetwork().netId, 0 /* times */,
14695                 true /* shouldDestroyNetwork */);
14696     }
14697 
14698     @Test
14699     public void testMultilayerForMultipleUsersEvaluatesCorrectly()
14700             throws Exception {
14701         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
14702                 OEM_NETWORK_PREFERENCE_OEM_PAID;
14703 
14704         // Arrange users
14705         final int secondUser = 10;
14706         final UserHandle secondUserHandle = new UserHandle(secondUser);
14707         doReturn(asList(PRIMARY_USER_HANDLE, secondUserHandle)).when(mUserManager)
14708                 .getUserHandles(anyBoolean());
14709 
14710         // Arrange PackageManager mocks
14711         final int secondUserTestPackageUid = UserHandle.getUid(secondUser, TEST_PACKAGE_UID);
14712         final UidRangeParcel[] uidRanges =
14713                 toUidRangeStableParcels(
14714                         uidRangesForUids(TEST_PACKAGE_UID, secondUserTestPackageUid));
14715         mockGetApplicationInfo(TEST_PACKAGE_NAME, secondUserTestPackageUid, secondUserHandle);
14716         setupSetOemNetworkPreferenceForPreferenceTest(networkPref, uidRanges, TEST_PACKAGE_NAME);
14717 
14718         // Verify the starting state. No networks should be connected.
14719         verifySetOemNetworkPreferenceForPreference(uidRanges,
14720                 OEM_PREF_ANY_NET_ID, 0 /* times */,
14721                 OEM_PREF_ANY_NET_ID, 0 /* times */,
14722                 false /* shouldDestroyNetwork */);
14723 
14724         // Test that we correctly add the expected values for multiple users.
14725         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true);
14726         verifySetOemNetworkPreferenceForPreference(uidRanges,
14727                 mCellAgent.getNetwork().netId, 1 /* times */,
14728                 OEM_PREF_ANY_NET_ID, 0 /* times */,
14729                 false /* shouldDestroyNetwork */);
14730 
14731         // Test that we correctly remove the expected values for multiple users.
14732         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, false);
14733         verifySetOemNetworkPreferenceForPreference(uidRanges,
14734                 OEM_PREF_ANY_NET_ID, 0 /* times */,
14735                 mCellAgent.getNetwork().netId, 0 /* times */,
14736                 true /* shouldDestroyNetwork */);
14737     }
14738 
14739     @Test
14740     public void testMultilayerForBroadcastedUsersEvaluatesCorrectly()
14741             throws Exception {
14742         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
14743                 OEM_NETWORK_PREFERENCE_OEM_PAID;
14744 
14745         // Arrange users
14746         final int secondUser = 10;
14747         final UserHandle secondUserHandle = new UserHandle(secondUser);
14748         doReturn(asList(PRIMARY_USER_HANDLE)).when(mUserManager).getUserHandles(anyBoolean());
14749 
14750         // Arrange PackageManager mocks
14751         final int secondUserTestPackageUid = UserHandle.getUid(secondUser, TEST_PACKAGE_UID);
14752         final UidRangeParcel[] uidRangesSingleUser =
14753                 toUidRangeStableParcels(uidRangesForUids(TEST_PACKAGE_UID));
14754         final UidRangeParcel[] uidRangesBothUsers =
14755                 toUidRangeStableParcels(
14756                         uidRangesForUids(TEST_PACKAGE_UID, secondUserTestPackageUid));
14757         mockGetApplicationInfo(TEST_PACKAGE_NAME, secondUserTestPackageUid, secondUserHandle);
14758         setupSetOemNetworkPreferenceForPreferenceTest(
14759                 networkPref, uidRangesSingleUser, TEST_PACKAGE_NAME);
14760 
14761         // Verify the starting state. No networks should be connected.
14762         verifySetOemNetworkPreferenceForPreference(uidRangesSingleUser,
14763                 OEM_PREF_ANY_NET_ID, 0 /* times */,
14764                 OEM_PREF_ANY_NET_ID, 0 /* times */,
14765                 false /* shouldDestroyNetwork */);
14766 
14767         // Test that we correctly add the expected values for multiple users.
14768         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true);
14769         verifySetOemNetworkPreferenceForPreference(uidRangesSingleUser,
14770                 mCellAgent.getNetwork().netId, 1 /* times */,
14771                 OEM_PREF_ANY_NET_ID, 0 /* times */,
14772                 false /* shouldDestroyNetwork */);
14773 
14774         // Send a broadcast indicating a user was added.
14775         doReturn(asList(PRIMARY_USER_HANDLE, secondUserHandle)).when(mUserManager)
14776                 .getUserHandles(anyBoolean());
14777         final Intent addedIntent = new Intent(ACTION_USER_ADDED);
14778         addedIntent.putExtra(Intent.EXTRA_USER, UserHandle.of(secondUser));
14779         processBroadcast(addedIntent);
14780 
14781         // Test that we correctly add values for all users and remove for the single user.
14782         verifySetOemNetworkPreferenceForPreference(uidRangesBothUsers, uidRangesSingleUser,
14783                 mCellAgent.getNetwork().netId, 1 /* times */,
14784                 mCellAgent.getNetwork().netId, 1 /* times */,
14785                 false /* shouldDestroyNetwork */);
14786 
14787         // Send a broadcast indicating a user was removed.
14788         doReturn(asList(PRIMARY_USER_HANDLE)).when(mUserManager).getUserHandles(anyBoolean());
14789         final Intent removedIntent = new Intent(ACTION_USER_REMOVED);
14790         removedIntent.putExtra(Intent.EXTRA_USER, UserHandle.of(secondUser));
14791         processBroadcast(removedIntent);
14792 
14793         // Test that we correctly add values for the single user and remove for the all users.
14794         verifySetOemNetworkPreferenceForPreference(uidRangesSingleUser, uidRangesBothUsers,
14795                 mCellAgent.getNetwork().netId, 1 /* times */,
14796                 mCellAgent.getNetwork().netId, 1 /* times */,
14797                 false /* shouldDestroyNetwork */);
14798     }
14799 
14800     @Test
14801     public void testMultilayerForPackageChangesEvaluatesCorrectly()
14802             throws Exception {
14803         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
14804                 OEM_NETWORK_PREFERENCE_OEM_PAID;
14805         final String packageScheme = "package:";
14806 
14807         // Arrange PackageManager mocks
14808         final String packageToInstall = "package.to.install";
14809         final int packageToInstallUid = 81387;
14810         final UidRangeParcel[] uidRangesSinglePackage =
14811                 toUidRangeStableParcels(uidRangesForUids(TEST_PACKAGE_UID));
14812         mockGetApplicationInfo(TEST_PACKAGE_NAME, TEST_PACKAGE_UID);
14813         mockGetApplicationInfoThrowsNameNotFound(packageToInstall, PRIMARY_USER_HANDLE);
14814         setOemNetworkPreference(networkPref, TEST_PACKAGE_NAME, packageToInstall);
14815         grantUsingBackgroundNetworksPermissionForUid(Binder.getCallingUid(), packageToInstall);
14816 
14817         // Verify the starting state. No networks should be connected.
14818         verifySetOemNetworkPreferenceForPreference(uidRangesSinglePackage,
14819                 OEM_PREF_ANY_NET_ID, 0 /* times */,
14820                 OEM_PREF_ANY_NET_ID, 0 /* times */,
14821                 false /* shouldDestroyNetwork */);
14822 
14823         // Test that we correctly add the expected values for installed packages.
14824         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true);
14825         verifySetOemNetworkPreferenceForPreference(uidRangesSinglePackage,
14826                 mCellAgent.getNetwork().netId, 1 /* times */,
14827                 OEM_PREF_ANY_NET_ID, 0 /* times */,
14828                 false /* shouldDestroyNetwork */);
14829 
14830         // Set the system to recognize the package to be installed
14831         mockGetApplicationInfo(packageToInstall, packageToInstallUid);
14832         final UidRangeParcel[] uidRangesAllPackages =
14833                 toUidRangeStableParcels(uidRangesForUids(TEST_PACKAGE_UID, packageToInstallUid));
14834 
14835         // Send a broadcast indicating a package was installed.
14836         final Intent addedIntent = new Intent(ACTION_PACKAGE_ADDED);
14837         addedIntent.setData(Uri.parse(packageScheme + packageToInstall));
14838         processBroadcast(addedIntent);
14839 
14840         // Test the single package is removed and the combined packages are added.
14841         verifySetOemNetworkPreferenceForPreference(uidRangesAllPackages, uidRangesSinglePackage,
14842                 mCellAgent.getNetwork().netId, 1 /* times */,
14843                 mCellAgent.getNetwork().netId, 1 /* times */,
14844                 false /* shouldDestroyNetwork */);
14845 
14846         // Set the system to no longer recognize the package to be installed
14847         mockGetApplicationInfoThrowsNameNotFound(packageToInstall, PRIMARY_USER_HANDLE);
14848 
14849         // Send a broadcast indicating a package was removed.
14850         final Intent removedIntent = new Intent(ACTION_PACKAGE_REMOVED);
14851         removedIntent.setData(Uri.parse(packageScheme + packageToInstall));
14852         processBroadcast(removedIntent);
14853 
14854         // Test the combined packages are removed and the single package is added.
14855         verifySetOemNetworkPreferenceForPreference(uidRangesSinglePackage, uidRangesAllPackages,
14856                 mCellAgent.getNetwork().netId, 1 /* times */,
14857                 mCellAgent.getNetwork().netId, 1 /* times */,
14858                 false /* shouldDestroyNetwork */);
14859 
14860         // Set the system to change the installed package's uid
14861         final int replacedTestPackageUid = TEST_PACKAGE_UID + 1;
14862         mockGetApplicationInfo(TEST_PACKAGE_NAME, replacedTestPackageUid);
14863         final UidRangeParcel[] uidRangesReplacedPackage =
14864                 toUidRangeStableParcels(uidRangesForUids(replacedTestPackageUid));
14865 
14866         // Send a broadcast indicating a package was replaced.
14867         final Intent replacedIntent = new Intent(ACTION_PACKAGE_REPLACED);
14868         replacedIntent.setData(Uri.parse(packageScheme + TEST_PACKAGE_NAME));
14869         processBroadcast(replacedIntent);
14870 
14871         // Test the original uid is removed and is replaced with the new uid.
14872         verifySetOemNetworkPreferenceForPreference(uidRangesReplacedPackage, uidRangesSinglePackage,
14873                 mCellAgent.getNetwork().netId, 1 /* times */,
14874                 mCellAgent.getNetwork().netId, 1 /* times */,
14875                 false /* shouldDestroyNetwork */);
14876     }
14877 
14878     /**
14879      * Test network priority for preference OEM_NETWORK_PREFERENCE_OEM_PAID in the following order:
14880      * NET_CAPABILITY_NOT_METERED -> NET_CAPABILITY_OEM_PAID -> fallback
14881      */
14882     @Test
14883     public void testMultipleDefaultNetworksTracksOemNetworkPreferenceOemPaidCorrectly()
14884             throws Exception {
14885         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
14886                 OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PAID;
14887         setupMultipleDefaultNetworksForOemNetworkPreferenceCurrentUidTest(networkPref);
14888         final int expectedDefaultRequestSize = 2;
14889         final int expectedOemPrefRequestSize = 3;
14890         registerDefaultNetworkCallbacks();
14891 
14892         // The fallback as well as the OEM preference should now be tracked.
14893         assertEquals(expectedDefaultRequestSize, mService.mDefaultNetworkRequests.size());
14894 
14895         // Test lowest to highest priority requests.
14896         // Bring up metered cellular. This will satisfy the fallback network.
14897         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true);
14898         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
14899                 mCellAgent.getNetwork(),
14900                 mCellAgent.getNetwork());
14901 
14902         // Bring up ethernet with OEM_PAID. This will satisfy NET_CAPABILITY_OEM_PAID.
14903         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, true);
14904         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
14905                 mCellAgent.getNetwork(),
14906                 mEthernetAgent.getNetwork());
14907 
14908         // Bring up unmetered Wi-Fi. This will satisfy NET_CAPABILITY_NOT_METERED.
14909         setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, true);
14910         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
14911                 mWiFiAgent.getNetwork(),
14912                 mWiFiAgent.getNetwork());
14913 
14914         // Disconnecting unmetered Wi-Fi will put the pref on OEM_PAID and fallback on cellular.
14915         setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, false);
14916         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
14917                 mCellAgent.getNetwork(),
14918                 mEthernetAgent.getNetwork());
14919 
14920         // Disconnecting cellular should keep OEM network on OEM_PAID and fallback will be null.
14921         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, false);
14922         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
14923                 null,
14924                 mEthernetAgent.getNetwork());
14925 
14926         // Disconnecting OEM_PAID will put both on null as it is the last network.
14927         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, false);
14928         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
14929                 null,
14930                 null);
14931 
14932         // default callbacks will be unregistered in tearDown
14933     }
14934 
14935     @Test
14936     public void testNetworkFactoryRequestsWithMultilayerRequest()
14937             throws Exception {
14938         // First use OEM_PAID preference to create a multi-layer request : 1. listen for
14939         // unmetered, 2. request network with cap OEM_PAID, 3, request the default network for
14940         // fallback.
14941         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
14942                 OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PAID;
14943         setupMultipleDefaultNetworksForOemNetworkPreferenceCurrentUidTest(networkPref);
14944 
14945         final HandlerThread handlerThread = new HandlerThread("MockFactory");
14946         handlerThread.start();
14947         NetworkCapabilities internetFilter = new NetworkCapabilities()
14948                 .addCapability(NET_CAPABILITY_INTERNET)
14949                 .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED);
14950         final MockNetworkFactory internetFactory = new MockNetworkFactory(handlerThread.getLooper(),
14951                 mServiceContext, "internetFactory", internetFilter, mCsHandlerThread);
14952         internetFactory.setScoreFilter(40);
14953         internetFactory.register();
14954         // Default internet request only. The unmetered request is never sent to factories (it's a
14955         // LISTEN, not requestable). The 3rd (fallback) request in OEM_PAID NRI is TRACK_DEFAULT
14956         // which is also not sent to factories. Finally, the OEM_PAID request doesn't match the
14957         // internetFactory filter.
14958         internetFactory.expectRequestAdds(1);
14959         internetFactory.assertRequestCountEquals(1);
14960 
14961         NetworkCapabilities oemPaidFilter = new NetworkCapabilities()
14962                 .addCapability(NET_CAPABILITY_INTERNET)
14963                 .addCapability(NET_CAPABILITY_OEM_PAID)
14964                 .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
14965                 .removeCapability(NET_CAPABILITY_NOT_RESTRICTED);
14966         final MockNetworkFactory oemPaidFactory = new MockNetworkFactory(handlerThread.getLooper(),
14967                 mServiceContext, "oemPaidFactory", oemPaidFilter, mCsHandlerThread);
14968         oemPaidFactory.setScoreFilter(40);
14969         oemPaidFactory.register();
14970         oemPaidFactory.expectRequestAdd(); // Because nobody satisfies the request
14971 
14972         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
14973         mCellAgent.connect(true);
14974 
14975         // A network connected that satisfies the default internet request. For the OEM_PAID
14976         // preference, this is not as good as an OEM_PAID network, so even if the score of
14977         // the network is better than the factory announced, it still should try to bring up
14978         // the network.
14979         expectNoRequestChanged(oemPaidFactory);
14980         oemPaidFactory.assertRequestCountEquals(1);
14981         // The internet factory however is outscored, and should lose its requests.
14982         internetFactory.expectRequestRemove();
14983         internetFactory.assertRequestCountEquals(0);
14984 
14985         final NetworkCapabilities oemPaidNc = new NetworkCapabilities();
14986         oemPaidNc.addCapability(NET_CAPABILITY_OEM_PAID);
14987         oemPaidNc.removeCapability(NET_CAPABILITY_NOT_RESTRICTED);
14988         final TestNetworkAgentWrapper oemPaidAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR,
14989                 new LinkProperties(), oemPaidNc);
14990         oemPaidAgent.connect(true);
14991 
14992         // The oemPaidAgent has score 50/cell transport, so it beats what the oemPaidFactory can
14993         // provide, therefore it loses the request.
14994         oemPaidFactory.expectRequestRemove();
14995         oemPaidFactory.assertRequestCountEquals(0);
14996         expectNoRequestChanged(internetFactory);
14997         internetFactory.assertRequestCountEquals(0);
14998 
14999         oemPaidAgent.setScore(new NetworkScore.Builder().setLegacyInt(20).setExiting(true).build());
15000         // Now the that the agent is weak, the oemPaidFactory can beat the existing network for the
15001         // OEM_PAID request. The internet factory however can't beat a network that has OEM_PAID
15002         // for the preference request, so it doesn't see the request.
15003         oemPaidFactory.expectRequestAdd();
15004         oemPaidFactory.assertRequestCountEquals(1);
15005         expectNoRequestChanged(internetFactory);
15006         internetFactory.assertRequestCountEquals(0);
15007 
15008         mCellAgent.disconnect();
15009         // The network satisfying the default internet request has disconnected, so the
15010         // internetFactory sees the default request again. However there is a network with OEM_PAID
15011         // connected, so the 2nd OEM_PAID req is already satisfied, so the oemPaidFactory doesn't
15012         // care about networks that don't have OEM_PAID.
15013         expectNoRequestChanged(oemPaidFactory);
15014         oemPaidFactory.assertRequestCountEquals(1);
15015         internetFactory.expectRequestAdd();
15016         internetFactory.assertRequestCountEquals(1);
15017 
15018         // Cell connects again, still with score 50. Back to the previous state.
15019         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
15020         mCellAgent.connect(true);
15021         expectNoRequestChanged(oemPaidFactory);
15022         oemPaidFactory.assertRequestCountEquals(1);
15023         internetFactory.expectRequestRemove();
15024         internetFactory.assertRequestCountEquals(0);
15025 
15026         // Create a request that holds the upcoming wifi network.
15027         final TestNetworkCallback wifiCallback = new TestNetworkCallback();
15028         mCm.requestNetwork(new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI).build(),
15029                 wifiCallback);
15030 
15031         // Now WiFi connects and it's unmetered, but it's weaker than cell.
15032         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
15033         mWiFiAgent.addCapability(NET_CAPABILITY_NOT_METERED);
15034         mWiFiAgent.setScore(new NetworkScore.Builder().setLegacyInt(30).setExiting(true)
15035                 .build()); // Not the best Internet network, but unmetered
15036         mWiFiAgent.connect(true);
15037 
15038         // The OEM_PAID preference prefers an unmetered network to an OEM_PAID network, so
15039         // the oemPaidFactory can't beat wifi no matter how high its score.
15040         oemPaidFactory.expectRequestRemove();
15041         expectNoRequestChanged(internetFactory);
15042 
15043         mCellAgent.disconnect();
15044         // Now that the best internet network (cell, with its 50 score compared to 30 for WiFi
15045         // at this point), the default internet request is satisfied by a network worse than
15046         // the internetFactory announced, so it gets the request. However, there is still an
15047         // unmetered network, so the oemPaidNetworkFactory still can't beat this.
15048         expectNoRequestChanged(oemPaidFactory);
15049         internetFactory.expectRequestAdd();
15050         mCm.unregisterNetworkCallback(wifiCallback);
15051     }
15052 
15053     /**
15054      * Test network priority for OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK in the following order:
15055      * NET_CAPABILITY_NOT_METERED -> NET_CAPABILITY_OEM_PAID
15056      */
15057     @Test
15058     public void testMultipleDefaultNetworksTracksOemNetworkPreferenceOemPaidNoFallbackCorrectly()
15059             throws Exception {
15060         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
15061                 OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK;
15062         setupMultipleDefaultNetworksForOemNetworkPreferenceCurrentUidTest(networkPref);
15063         final int expectedDefaultRequestSize = 2;
15064         final int expectedOemPrefRequestSize = 2;
15065         registerDefaultNetworkCallbacks();
15066 
15067         // The fallback as well as the OEM preference should now be tracked.
15068         assertEquals(expectedDefaultRequestSize, mService.mDefaultNetworkRequests.size());
15069 
15070         // Test lowest to highest priority requests.
15071         // Bring up metered cellular. This will satisfy the fallback network but not the pref.
15072         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true);
15073         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
15074                 mCellAgent.getNetwork(),
15075                 mService.mNoServiceNetwork.network());
15076 
15077         // Bring up ethernet with OEM_PAID. This will satisfy NET_CAPABILITY_OEM_PAID.
15078         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, true);
15079         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
15080                 mCellAgent.getNetwork(),
15081                 mEthernetAgent.getNetwork());
15082 
15083         // Bring up unmetered Wi-Fi. This will satisfy NET_CAPABILITY_NOT_METERED.
15084         setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, true);
15085         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
15086                 mWiFiAgent.getNetwork(),
15087                 mWiFiAgent.getNetwork());
15088 
15089         // Disconnecting unmetered Wi-Fi will put the OEM pref on OEM_PAID and fallback on cellular.
15090         setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, false);
15091         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
15092                 mCellAgent.getNetwork(),
15093                 mEthernetAgent.getNetwork());
15094 
15095         // Disconnecting cellular should keep OEM network on OEM_PAID and fallback will be null.
15096         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, false);
15097         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
15098                 null,
15099                 mEthernetAgent.getNetwork());
15100 
15101         // Disconnecting OEM_PAID puts the fallback on null and the pref on the disconnected net.
15102         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, false);
15103         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
15104                 null,
15105                 mService.mNoServiceNetwork.network());
15106 
15107         // default callbacks will be unregistered in tearDown
15108     }
15109 
15110     /**
15111      * Test network priority for OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY in the following order:
15112      * NET_CAPABILITY_OEM_PAID
15113      * This preference should only apply to OEM_PAID networks.
15114      */
15115     @Test
15116     public void testMultipleDefaultNetworksTracksOemNetworkPreferenceOemPaidOnlyCorrectly()
15117             throws Exception {
15118         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
15119                 OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY;
15120         setupMultipleDefaultNetworksForOemNetworkPreferenceCurrentUidTest(networkPref);
15121         final int expectedDefaultRequestSize = 2;
15122         final int expectedOemPrefRequestSize = 1;
15123         registerDefaultNetworkCallbacks();
15124 
15125         // The fallback as well as the OEM preference should now be tracked.
15126         assertEquals(expectedDefaultRequestSize, mService.mDefaultNetworkRequests.size());
15127 
15128         // Test lowest to highest priority requests.
15129         // Bring up metered cellular. This will satisfy the fallback network.
15130         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true);
15131         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
15132                 mCellAgent.getNetwork(),
15133                 mService.mNoServiceNetwork.network());
15134 
15135         // Bring up ethernet with OEM_PAID. This will satisfy NET_CAPABILITY_OEM_PAID.
15136         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, true);
15137         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
15138                 mCellAgent.getNetwork(),
15139                 mEthernetAgent.getNetwork());
15140 
15141         // Bring up unmetered Wi-Fi. The OEM network shouldn't change, the fallback will take Wi-Fi.
15142         setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, true);
15143         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
15144                 mWiFiAgent.getNetwork(),
15145                 mEthernetAgent.getNetwork());
15146 
15147         // Disconnecting unmetered Wi-Fi shouldn't change the OEM network with fallback on cellular.
15148         setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, false);
15149         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
15150                 mCellAgent.getNetwork(),
15151                 mEthernetAgent.getNetwork());
15152 
15153         // Disconnecting OEM_PAID will keep the fallback on cellular and nothing for OEM_PAID.
15154         // OEM_PAID_ONLY not supporting a fallback now uses the disconnected network.
15155         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, false);
15156         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
15157                 mCellAgent.getNetwork(),
15158                 mService.mNoServiceNetwork.network());
15159 
15160         // Disconnecting cellular will put the fallback on null and the pref on disconnected.
15161         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, false);
15162         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
15163                 null,
15164                 mService.mNoServiceNetwork.network());
15165 
15166         // default callbacks will be unregistered in tearDown
15167     }
15168 
15169     /**
15170      * Test network priority for OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY in the following order:
15171      * NET_CAPABILITY_OEM_PRIVATE
15172      * This preference should only apply to OEM_PRIVATE networks.
15173      */
15174     @Test
15175     public void testMultipleDefaultNetworksTracksOemNetworkPreferenceOemPrivateOnlyCorrectly()
15176             throws Exception {
15177         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
15178                 OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY;
15179         setupMultipleDefaultNetworksForOemNetworkPreferenceCurrentUidTest(networkPref);
15180         final int expectedDefaultRequestSize = 2;
15181         final int expectedOemPrefRequestSize = 1;
15182         registerDefaultNetworkCallbacks();
15183 
15184         // The fallback as well as the OEM preference should now be tracked.
15185         assertEquals(expectedDefaultRequestSize, mService.mDefaultNetworkRequests.size());
15186 
15187         // Test lowest to highest priority requests.
15188         // Bring up metered cellular. This will satisfy the fallback network.
15189         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true);
15190         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
15191                 mCellAgent.getNetwork(),
15192                 mService.mNoServiceNetwork.network());
15193 
15194         // Bring up ethernet with OEM_PRIVATE. This will satisfy NET_CAPABILITY_OEM_PRIVATE.
15195         startOemManagedNetwork(false);
15196         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
15197                 mCellAgent.getNetwork(),
15198                 mEthernetAgent.getNetwork());
15199 
15200         // Bring up unmetered Wi-Fi. The OEM network shouldn't change, the fallback will take Wi-Fi.
15201         setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, true);
15202         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
15203                 mWiFiAgent.getNetwork(),
15204                 mEthernetAgent.getNetwork());
15205 
15206         // Disconnecting unmetered Wi-Fi shouldn't change the OEM network with fallback on cellular.
15207         setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, false);
15208         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
15209                 mCellAgent.getNetwork(),
15210                 mEthernetAgent.getNetwork());
15211 
15212         // Disconnecting OEM_PRIVATE will keep the fallback on cellular.
15213         // OEM_PRIVATE_ONLY not supporting a fallback now uses to the disconnected network.
15214         stopOemManagedNetwork();
15215         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
15216                 mCellAgent.getNetwork(),
15217                 mService.mNoServiceNetwork.network());
15218 
15219         // Disconnecting cellular will put the fallback on null and pref on disconnected.
15220         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, false);
15221         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
15222                 null,
15223                 mService.mNoServiceNetwork.network());
15224 
15225         // default callbacks will be unregistered in tearDown
15226     }
15227 
15228     @Test
15229     public void testCapabilityWithOemNetworkPreference() throws Exception {
15230         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
15231                 OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY;
15232         setupMultipleDefaultNetworksForOemNetworkPreferenceNotCurrentUidTest(networkPref);
15233         registerDefaultNetworkCallbacks();
15234 
15235         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true);
15236 
15237         mSystemDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
15238         mDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
15239 
15240         mCellAgent.addCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED);
15241         mSystemDefaultNetworkCallback.expectCaps(mCellAgent,
15242                 c -> c.hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED));
15243         mDefaultNetworkCallback.expectCaps(mCellAgent,
15244                 c -> c.hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED));
15245 
15246         // default callbacks will be unregistered in tearDown
15247     }
15248 
15249     @Test
15250     public void testSetOemNetworkPreferenceLogsRequest() throws Exception {
15251         mServiceContext.setPermission(DUMP, PERMISSION_GRANTED);
15252         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
15253                 OEM_NETWORK_PREFERENCE_OEM_PAID;
15254         final StringWriter stringWriter = new StringWriter();
15255         final String logIdentifier = "UPDATE INITIATED: OemNetworkPreferences";
15256         final Pattern pattern = Pattern.compile(logIdentifier);
15257 
15258         final int expectedNumLogs = 2;
15259         final UidRangeParcel[] uidRanges =
15260                 toUidRangeStableParcels(uidRangesForUids(TEST_PACKAGE_UID));
15261 
15262         // Call twice to generate two logs.
15263         setupSetOemNetworkPreferenceForPreferenceTest(networkPref, uidRanges, TEST_PACKAGE_NAME);
15264         setupSetOemNetworkPreferenceForPreferenceTest(networkPref, uidRanges, TEST_PACKAGE_NAME);
15265         mService.dump(new FileDescriptor(), new PrintWriter(stringWriter), new String[0]);
15266 
15267         final String dumpOutput = stringWriter.toString();
15268         final Matcher matcher = pattern.matcher(dumpOutput);
15269         int count = 0;
15270         while (matcher.find()) {
15271             count++;
15272         }
15273         assertEquals(expectedNumLogs, count);
15274     }
15275 
15276     @Test
15277     public void testGetAllNetworkStateSnapshots() throws Exception {
15278         verifyNoNetwork();
15279 
15280         // Setup test cellular network with specified LinkProperties and NetworkCapabilities,
15281         // verify the content of the snapshot matches.
15282         final LinkProperties cellLp = new LinkProperties();
15283         final LinkAddress myIpv4Addr = new LinkAddress(InetAddress.getByName("192.0.2.129"), 25);
15284         final LinkAddress myIpv6Addr = new LinkAddress(InetAddress.getByName("2001:db8::1"), 64);
15285         cellLp.setInterfaceName("test01");
15286         cellLp.addLinkAddress(myIpv4Addr);
15287         cellLp.addLinkAddress(myIpv6Addr);
15288         cellLp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
15289         cellLp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
15290         cellLp.addRoute(new RouteInfo(myIpv4Addr, null));
15291         cellLp.addRoute(new RouteInfo(myIpv6Addr, null));
15292         final NetworkCapabilities cellNcTemplate = new NetworkCapabilities.Builder()
15293                 .addTransportType(TRANSPORT_CELLULAR).addCapability(NET_CAPABILITY_MMS).build();
15294 
15295         final TestNetworkCallback cellCb = new TestNetworkCallback();
15296         mCm.requestNetwork(new NetworkRequest.Builder().addCapability(NET_CAPABILITY_MMS).build(),
15297                 cellCb);
15298         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp, cellNcTemplate);
15299         mCellAgent.connect(true);
15300         cellCb.expectAvailableCallbacksUnvalidated(mCellAgent);
15301         List<NetworkStateSnapshot> snapshots = mCm.getAllNetworkStateSnapshots();
15302         assertLength(1, snapshots);
15303 
15304         // Compose the expected cellular snapshot for verification.
15305         final NetworkCapabilities cellNc =
15306                 mCm.getNetworkCapabilities(mCellAgent.getNetwork());
15307         final NetworkStateSnapshot cellSnapshot = new NetworkStateSnapshot(
15308                 mCellAgent.getNetwork(), cellNc, cellLp,
15309                 null, ConnectivityManager.TYPE_MOBILE);
15310         assertEquals(cellSnapshot, snapshots.get(0));
15311 
15312         // Connect wifi and verify the snapshots.
15313         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
15314         mWiFiAgent.connect(true);
15315         waitForIdle();
15316         // Compose the expected wifi snapshot for verification.
15317         final NetworkCapabilities wifiNc =
15318                 mCm.getNetworkCapabilities(mWiFiAgent.getNetwork());
15319         final NetworkStateSnapshot wifiSnapshot = new NetworkStateSnapshot(
15320                 mWiFiAgent.getNetwork(), wifiNc, new LinkProperties(), null,
15321                 ConnectivityManager.TYPE_WIFI);
15322 
15323         snapshots = mCm.getAllNetworkStateSnapshots();
15324         assertLength(2, snapshots);
15325         assertContainsAll(snapshots, cellSnapshot, wifiSnapshot);
15326 
15327         // Set cellular as suspended, verify the snapshots will contain suspended networks.
15328         mCellAgent.suspend();
15329         waitForIdle();
15330         final NetworkCapabilities cellSuspendedNc =
15331                 mCm.getNetworkCapabilities(mCellAgent.getNetwork());
15332         assertFalse(cellSuspendedNc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
15333         final NetworkStateSnapshot cellSuspendedSnapshot = new NetworkStateSnapshot(
15334                 mCellAgent.getNetwork(), cellSuspendedNc, cellLp,
15335                 null, ConnectivityManager.TYPE_MOBILE);
15336         snapshots = mCm.getAllNetworkStateSnapshots();
15337         assertLength(2, snapshots);
15338         assertContainsAll(snapshots, cellSuspendedSnapshot, wifiSnapshot);
15339 
15340         // Disconnect wifi, verify the snapshots contain only cellular.
15341         mWiFiAgent.disconnect();
15342         waitForIdle();
15343         snapshots = mCm.getAllNetworkStateSnapshots();
15344         assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetwork());
15345         assertLength(1, snapshots);
15346         assertEquals(cellSuspendedSnapshot, snapshots.get(0));
15347 
15348         mCellAgent.resume();
15349         waitForIdle();
15350         snapshots = mCm.getAllNetworkStateSnapshots();
15351         assertLength(1, snapshots);
15352         assertEquals(cellSnapshot, snapshots.get(0));
15353 
15354         mCellAgent.disconnect();
15355         waitForIdle();
15356         verifyNoNetwork();
15357         mCm.unregisterNetworkCallback(cellCb);
15358     }
15359 
15360     // Cannot be part of MockNetworkFactory since it requires method of the test.
15361     private void expectNoRequestChanged(@NonNull MockNetworkFactory factory) {
15362         waitForIdle();
15363         factory.assertNoRequestChanged();
15364     }
15365 
15366     @Test
15367     public void testRegisterBestMatchingNetworkCallback_noIssueToFactory() throws Exception {
15368         // Prepare mock mms factory.
15369         final HandlerThread handlerThread = new HandlerThread("MockCellularFactory");
15370         handlerThread.start();
15371         NetworkCapabilities filter = new NetworkCapabilities()
15372                 .addTransportType(TRANSPORT_CELLULAR)
15373                 .addCapability(NET_CAPABILITY_MMS);
15374         final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
15375                 mServiceContext, "testFactory", filter, mCsHandlerThread);
15376         testFactory.setScoreFilter(40);
15377 
15378         try {
15379             // Register the factory. It doesn't see the default request because its filter does
15380             // not include INTERNET.
15381             testFactory.register();
15382             expectNoRequestChanged(testFactory);
15383             testFactory.assertRequestCountEquals(0);
15384             // The factory won't try to start the network since the default request doesn't
15385             // match the filter (no INTERNET capability).
15386             assertFalse(testFactory.getMyStartRequested());
15387 
15388             // Register callback for listening best matching network. Verify that the request won't
15389             // be sent to factory.
15390             final TestNetworkCallback bestMatchingCb = new TestNetworkCallback();
15391             mCm.registerBestMatchingNetworkCallback(
15392                     new NetworkRequest.Builder().addCapability(NET_CAPABILITY_MMS).build(),
15393                     bestMatchingCb, mCsHandlerThread.getThreadHandler());
15394             bestMatchingCb.assertNoCallback();
15395             expectNoRequestChanged(testFactory);
15396             testFactory.assertRequestCountEquals(0);
15397             assertFalse(testFactory.getMyStartRequested());
15398 
15399             // Fire a normal mms request, verify the factory will only see the request.
15400             final TestNetworkCallback mmsNetworkCallback = new TestNetworkCallback();
15401             final NetworkRequest mmsRequest = new NetworkRequest.Builder()
15402                     .addCapability(NET_CAPABILITY_MMS).build();
15403             mCm.requestNetwork(mmsRequest, mmsNetworkCallback);
15404             testFactory.expectRequestAdd();
15405             testFactory.assertRequestCountEquals(1);
15406             assertTrue(testFactory.getMyStartRequested());
15407 
15408             // Unregister best matching callback, verify factory see no change.
15409             mCm.unregisterNetworkCallback(bestMatchingCb);
15410             expectNoRequestChanged(testFactory);
15411             testFactory.assertRequestCountEquals(1);
15412             assertTrue(testFactory.getMyStartRequested());
15413         } finally {
15414             testFactory.terminate();
15415         }
15416     }
15417 
15418     @Test
15419     public void testRegisterBestMatchingNetworkCallback_trackBestNetwork() throws Exception {
15420         final TestNetworkCallback bestMatchingCb = new TestNetworkCallback();
15421         mCm.registerBestMatchingNetworkCallback(
15422                 new NetworkRequest.Builder().addCapability(NET_CAPABILITY_TRUSTED).build(),
15423                 bestMatchingCb, mCsHandlerThread.getThreadHandler());
15424 
15425         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
15426         mCellAgent.connect(true);
15427         bestMatchingCb.expectAvailableThenValidatedCallbacks(mCellAgent);
15428 
15429         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
15430         mWiFiAgent.connect(true);
15431         bestMatchingCb.expectAvailableDoubleValidatedCallbacks(mWiFiAgent);
15432 
15433         // Change something on cellular to trigger capabilities changed, since the callback
15434         // only cares about the best network, verify it received nothing from cellular.
15435         mCellAgent.addCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED);
15436         bestMatchingCb.assertNoCallback();
15437 
15438         // Make cellular the best network again, verify the callback now tracks cellular.
15439         mWiFiAgent.adjustScore(-50);
15440         bestMatchingCb.expectAvailableCallbacksValidated(mCellAgent);
15441 
15442         // Make cellular temporary non-trusted, which will not satisfying the request.
15443         // Verify the callback switch from/to the other network accordingly.
15444         mCellAgent.removeCapability(NET_CAPABILITY_TRUSTED);
15445         bestMatchingCb.expectAvailableCallbacksValidated(mWiFiAgent);
15446         mCellAgent.addCapability(NET_CAPABILITY_TRUSTED);
15447         bestMatchingCb.expectAvailableDoubleValidatedCallbacks(mCellAgent);
15448 
15449         // Verify the callback doesn't care about wifi disconnect.
15450         mWiFiAgent.disconnect();
15451         bestMatchingCb.assertNoCallback();
15452         mCellAgent.disconnect();
15453         bestMatchingCb.expect(LOST, mCellAgent);
15454     }
15455 
15456     private UidRangeParcel[] uidRangeFor(final UserHandle handle) {
15457         final UidRange range = UidRange.createForUser(handle);
15458         return new UidRangeParcel[] { new UidRangeParcel(range.start, range.stop) };
15459     }
15460 
15461     private UidRangeParcel[] uidRangeFor(final UserHandle handle,
15462             ProfileNetworkPreference profileNetworkPreference) {
15463         final Set<UidRange> uidRangeSet;
15464         UidRange range = UidRange.createForUser(handle);
15465         if (profileNetworkPreference.getIncludedUids().length != 0) {
15466             uidRangeSet = UidRangeUtils.convertArrayToUidRange(
15467                     profileNetworkPreference.getIncludedUids());
15468 
15469         } else if (profileNetworkPreference.getExcludedUids().length != 0)  {
15470             uidRangeSet = UidRangeUtils.removeRangeSetFromUidRange(
15471                     range, UidRangeUtils.convertArrayToUidRange(
15472                             profileNetworkPreference.getExcludedUids()));
15473         } else {
15474             uidRangeSet = new ArraySet<>();
15475             uidRangeSet.add(range);
15476         }
15477         UidRangeParcel[] uidRangeParcels = new UidRangeParcel[uidRangeSet.size()];
15478         int i = 0;
15479         for (UidRange range1 : uidRangeSet) {
15480             uidRangeParcels[i] = new UidRangeParcel(range1.start, range1.stop);
15481             i++;
15482         }
15483         return uidRangeParcels;
15484     }
15485 
15486     private static class TestOnCompleteListener implements Runnable {
15487         final class OnComplete {}
15488         final ArrayTrackRecord<OnComplete>.ReadHead mHistory =
15489                 new ArrayTrackRecord<OnComplete>().newReadHead();
15490 
15491         @Override
15492         public void run() {
15493             mHistory.add(new OnComplete());
15494         }
15495 
15496         public void expectOnComplete() {
15497             assertNotNull(mHistory.poll(TIMEOUT_MS, it -> true));
15498         }
15499     }
15500 
15501     private TestNetworkAgentWrapper makeEnterpriseNetworkAgent() throws Exception {
15502         final NetworkCapabilities workNc = new NetworkCapabilities();
15503         workNc.addCapability(NET_CAPABILITY_ENTERPRISE);
15504         workNc.removeCapability(NET_CAPABILITY_NOT_RESTRICTED);
15505         return new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, new LinkProperties(), workNc);
15506     }
15507 
15508     private TestNetworkAgentWrapper makeEnterpriseNetworkAgent(int enterpriseId) throws Exception {
15509         final NetworkCapabilities workNc = new NetworkCapabilities();
15510         workNc.addCapability(NET_CAPABILITY_ENTERPRISE);
15511         workNc.removeCapability(NET_CAPABILITY_NOT_RESTRICTED);
15512         workNc.addEnterpriseId(enterpriseId);
15513         return new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, new LinkProperties(), workNc);
15514     }
15515 
15516     private TestNetworkCallback mEnterpriseCallback;
15517     private UserHandle setupEnterpriseNetwork() {
15518         final UserHandle userHandle = UserHandle.of(TEST_WORK_PROFILE_USER_ID);
15519         mServiceContext.setWorkProfile(userHandle, true);
15520 
15521         // File a request to avoid the enterprise network being disconnected as soon as the default
15522         // request goes away – it would make impossible to test that networkRemoveUidRanges
15523         // is called, as the network would disconnect first for lack of a request.
15524         mEnterpriseCallback = new TestNetworkCallback();
15525         final NetworkRequest keepUpRequest = new NetworkRequest.Builder()
15526                 .addCapability(NET_CAPABILITY_ENTERPRISE)
15527                 .build();
15528         mCm.requestNetwork(keepUpRequest, mEnterpriseCallback);
15529         return userHandle;
15530     }
15531 
15532     private void maybeTearDownEnterpriseNetwork() {
15533         if (null != mEnterpriseCallback) {
15534             mCm.unregisterNetworkCallback(mEnterpriseCallback);
15535         }
15536     }
15537 
15538     /**
15539      * Make sure per profile network preferences behave as expected for a given
15540      * profile network preference.
15541      */
15542     private void doTestPreferenceForUserNetworkUpDownForGivenPreference(
15543             ProfileNetworkPreference profileNetworkPreference,
15544             boolean connectWorkProfileAgentAhead,
15545             UserHandle testHandle,
15546             TestNetworkCallback profileDefaultNetworkCallback,
15547             TestNetworkCallback disAllowProfileDefaultNetworkCallback) throws Exception {
15548         final InOrder inOrder = inOrder(mMockNetd, mMockDnsResolver);
15549 
15550         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
15551         mCellAgent.connect(true);
15552 
15553         mSystemDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
15554         mDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
15555         profileDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
15556         if (disAllowProfileDefaultNetworkCallback != null) {
15557             disAllowProfileDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
15558         }
15559         inOrder.verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
15560                 mCellAgent.getNetwork().netId, INetd.PERMISSION_NONE));
15561 
15562         final TestNetworkAgentWrapper workAgent =
15563                 makeEnterpriseNetworkAgent(profileNetworkPreference.getPreferenceEnterpriseId());
15564         if (mService.shouldCreateNetworksImmediately()) {
15565             expectNativeNetworkCreated(workAgent.getNetwork().netId, INetd.PERMISSION_SYSTEM,
15566                     null /* iface */, inOrder);
15567         }
15568         if (connectWorkProfileAgentAhead) {
15569             workAgent.connect(false);
15570             if (!mService.shouldCreateNetworksImmediately()) {
15571                 expectNativeNetworkCreated(workAgent.getNetwork().netId, INetd.PERMISSION_SYSTEM,
15572                         null /* iface */, inOrder);
15573             }
15574         }
15575 
15576         final TestOnCompleteListener listener = new TestOnCompleteListener();
15577         mCm.setProfileNetworkPreferences(testHandle, List.of(profileNetworkPreference),
15578                 r -> r.run(), listener);
15579         listener.expectOnComplete();
15580         boolean allowFallback = true;
15581         if (profileNetworkPreference.getPreference()
15582                 == PROFILE_NETWORK_PREFERENCE_ENTERPRISE_NO_FALLBACK) {
15583             allowFallback = false;
15584         }
15585         if (allowFallback && !connectWorkProfileAgentAhead) {
15586             // Setting a network preference for this user will create a new set of routing rules for
15587             // the UID range that corresponds to this user, inorder to define the default network
15588             // for these apps separately. This is true because the multi-layer request relevant to
15589             // this UID range contains a TRACK_DEFAULT, so the range will be moved through
15590             // UID-specific rules to the correct network – in this case the system default network.
15591             // The case where the default network for the profile happens to be the same as the
15592             // system default is not handled specially, the rules are always active as long as
15593             // a preference is set.
15594             inOrder.verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
15595                     mCellAgent.getNetwork().netId,
15596                     uidRangeFor(testHandle, profileNetworkPreference),
15597                     PREFERENCE_ORDER_PROFILE));
15598         }
15599 
15600         // The enterprise network is not ready yet.
15601         assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback);
15602         if (allowFallback && !connectWorkProfileAgentAhead) {
15603             assertNoCallbacks(profileDefaultNetworkCallback);
15604         } else if (!connectWorkProfileAgentAhead) {
15605             profileDefaultNetworkCallback.expect(LOST, mCellAgent);
15606             if (disAllowProfileDefaultNetworkCallback != null) {
15607                 assertNoCallbacks(disAllowProfileDefaultNetworkCallback);
15608             }
15609         }
15610 
15611         if (!connectWorkProfileAgentAhead) {
15612             workAgent.connect(false);
15613             if (!mService.shouldCreateNetworksImmediately()) {
15614                 inOrder.verify(mMockNetd).networkCreate(
15615                         nativeNetworkConfigPhysical(workAgent.getNetwork().netId,
15616                                 INetd.PERMISSION_SYSTEM));
15617             }
15618         }
15619 
15620         profileDefaultNetworkCallback.expectAvailableCallbacksUnvalidated(workAgent);
15621         if (disAllowProfileDefaultNetworkCallback != null) {
15622             disAllowProfileDefaultNetworkCallback.assertNoCallback();
15623         }
15624         mSystemDefaultNetworkCallback.assertNoCallback();
15625         mDefaultNetworkCallback.assertNoCallback();
15626         inOrder.verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
15627                 workAgent.getNetwork().netId,
15628                 uidRangeFor(testHandle, profileNetworkPreference),
15629                 PREFERENCE_ORDER_PROFILE));
15630 
15631         if (allowFallback && !connectWorkProfileAgentAhead) {
15632             inOrder.verify(mMockNetd).networkRemoveUidRangesParcel(new NativeUidRangeConfig(
15633                     mCellAgent.getNetwork().netId,
15634                     uidRangeFor(testHandle, profileNetworkPreference),
15635                     PREFERENCE_ORDER_PROFILE));
15636         }
15637 
15638         // Make sure changes to the work agent send callbacks to the app in the work profile, but
15639         // not to the other apps.
15640         workAgent.setNetworkValid(true /* privateDnsProbeSent */);
15641         workAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
15642         profileDefaultNetworkCallback.expectCaps(workAgent,
15643                 c -> c.hasCapability(NET_CAPABILITY_VALIDATED)
15644                         && c.hasCapability(NET_CAPABILITY_ENTERPRISE)
15645                         && c.hasEnterpriseId(profileNetworkPreference.getPreferenceEnterpriseId())
15646                         && c.getEnterpriseIds().length == 1);
15647         if (disAllowProfileDefaultNetworkCallback != null) {
15648             assertNoCallbacks(disAllowProfileDefaultNetworkCallback);
15649         }
15650         assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback);
15651 
15652         workAgent.addCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED);
15653         profileDefaultNetworkCallback.expectCaps(workAgent,
15654                 c -> c.hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED));
15655         if (disAllowProfileDefaultNetworkCallback != null) {
15656             assertNoCallbacks(disAllowProfileDefaultNetworkCallback);
15657         }
15658         assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback);
15659 
15660         // Conversely, change a capability on the system-wide default network and make sure
15661         // that only the apps outside of the work profile receive the callbacks.
15662         mCellAgent.addCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED);
15663         mSystemDefaultNetworkCallback.expectCaps(mCellAgent,
15664                 c -> c.hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED));
15665         mDefaultNetworkCallback.expectCaps(mCellAgent,
15666                 c -> c.hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED));
15667         if (disAllowProfileDefaultNetworkCallback != null) {
15668             disAllowProfileDefaultNetworkCallback.expectCaps(mCellAgent,
15669                     c -> c.hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED));
15670         }
15671         profileDefaultNetworkCallback.assertNoCallback();
15672 
15673         // Disconnect and reconnect the system-wide default network and make sure that the
15674         // apps on this network see the appropriate callbacks, and the app on the work profile
15675         // doesn't because it continues to use the enterprise network.
15676         mCellAgent.disconnect();
15677         mSystemDefaultNetworkCallback.expect(LOST, mCellAgent);
15678         mDefaultNetworkCallback.expect(LOST, mCellAgent);
15679         if (disAllowProfileDefaultNetworkCallback != null) {
15680             disAllowProfileDefaultNetworkCallback.expect(LOST, mCellAgent);
15681         }
15682         profileDefaultNetworkCallback.assertNoCallback();
15683         inOrder.verify(mMockNetd).networkDestroy(mCellAgent.getNetwork().netId);
15684 
15685         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
15686         mCellAgent.connect(true);
15687         mSystemDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
15688         mDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
15689         if (disAllowProfileDefaultNetworkCallback != null) {
15690             disAllowProfileDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
15691 
15692         }
15693         profileDefaultNetworkCallback.assertNoCallback();
15694         inOrder.verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
15695                 mCellAgent.getNetwork().netId, INetd.PERMISSION_NONE));
15696 
15697         // When the agent disconnects, test that the app on the work profile falls back to the
15698         // default network.
15699         workAgent.disconnect();
15700         profileDefaultNetworkCallback.expect(LOST, workAgent);
15701         if (allowFallback) {
15702             profileDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellAgent);
15703             if (disAllowProfileDefaultNetworkCallback != null) {
15704                 assertNoCallbacks(disAllowProfileDefaultNetworkCallback);
15705             }
15706         }
15707         assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback);
15708         if (allowFallback) {
15709             inOrder.verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
15710                     mCellAgent.getNetwork().netId,
15711                     uidRangeFor(testHandle, profileNetworkPreference),
15712                     PREFERENCE_ORDER_PROFILE));
15713         }
15714         inOrder.verify(mMockNetd).networkDestroy(workAgent.getNetwork().netId);
15715 
15716         mCellAgent.disconnect();
15717         mSystemDefaultNetworkCallback.expect(LOST, mCellAgent);
15718         mDefaultNetworkCallback.expect(LOST, mCellAgent);
15719         if (disAllowProfileDefaultNetworkCallback != null) {
15720             disAllowProfileDefaultNetworkCallback.expect(LOST, mCellAgent);
15721         }
15722         if (allowFallback) {
15723             profileDefaultNetworkCallback.expect(LOST, mCellAgent);
15724         }
15725 
15726         // Waiting for the handler to be idle before checking for networkDestroy is necessary
15727         // here because ConnectivityService calls onLost before the network is fully torn down.
15728         waitForIdle();
15729         inOrder.verify(mMockNetd).networkDestroy(mCellAgent.getNetwork().netId);
15730 
15731         // If the control comes here, callbacks seem to behave correctly in the presence of
15732         // a default network when the enterprise network goes up and down. Now, make sure they
15733         // also behave correctly in the absence of a system-wide default network.
15734         final TestNetworkAgentWrapper workAgent2 =
15735                 makeEnterpriseNetworkAgent(profileNetworkPreference.getPreferenceEnterpriseId());
15736         workAgent2.connect(false);
15737 
15738         profileDefaultNetworkCallback.expectAvailableCallbacksUnvalidated(workAgent2);
15739         if (disAllowProfileDefaultNetworkCallback != null) {
15740             assertNoCallbacks(disAllowProfileDefaultNetworkCallback);
15741         }
15742         assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback);
15743         inOrder.verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
15744                 workAgent2.getNetwork().netId, INetd.PERMISSION_SYSTEM));
15745         inOrder.verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
15746                 workAgent2.getNetwork().netId,
15747                 uidRangeFor(testHandle, profileNetworkPreference), PREFERENCE_ORDER_PROFILE));
15748 
15749         workAgent2.setNetworkValid(true /* privateDnsProbeSent */);
15750         workAgent2.mNetworkMonitor.forceReevaluation(Process.myUid());
15751         profileDefaultNetworkCallback.expectCaps(workAgent2,
15752                 c -> c.hasCapability(NET_CAPABILITY_ENTERPRISE)
15753                         && !c.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)
15754                         && c.hasEnterpriseId(profileNetworkPreference.getPreferenceEnterpriseId())
15755                         && c.getEnterpriseIds().length == 1);
15756         if (disAllowProfileDefaultNetworkCallback != null) {
15757             assertNoCallbacks(disAllowProfileDefaultNetworkCallback);
15758         }
15759         assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback);
15760         inOrder.verify(mMockNetd, never()).networkAddUidRangesParcel(any());
15761 
15762         // When the agent disconnects, test that the app on the work profile fall back to the
15763         // default network.
15764         workAgent2.disconnect();
15765         profileDefaultNetworkCallback.expect(LOST, workAgent2);
15766         if (disAllowProfileDefaultNetworkCallback != null) {
15767             assertNoCallbacks(disAllowProfileDefaultNetworkCallback);
15768         }
15769         assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback);
15770         inOrder.verify(mMockNetd).networkDestroy(workAgent2.getNetwork().netId);
15771 
15772         assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback,
15773                 profileDefaultNetworkCallback);
15774 
15775         // Callbacks will be unregistered by tearDown()
15776     }
15777 
15778     /**
15779      * Make sure per-profile networking preference behaves as expected when the enterprise network
15780      * goes up and down while the preference is active. Make sure they behave as expected whether
15781      * there is a general default network or not.
15782      */
15783     @Test
15784     public void testPreferenceForUserNetworkUpDown() throws Exception {
15785         final UserHandle testHandle = setupEnterpriseNetwork();
15786         registerDefaultNetworkCallbacks();
15787         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder =
15788                 new ProfileNetworkPreference.Builder();
15789         profileNetworkPreferenceBuilder.setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE);
15790         profileNetworkPreferenceBuilder.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1);
15791         doTestPreferenceForUserNetworkUpDownForGivenPreference(
15792                 profileNetworkPreferenceBuilder.build(), false,
15793                 testHandle, mProfileDefaultNetworkCallback, null);
15794     }
15795 
15796     /**
15797      * Make sure per-profile networking preference behaves as expected when the enterprise network
15798      * goes up and down while the preference is active. Make sure they behave as expected whether
15799      * there is a general default network or not when configured to not fallback to default network.
15800      */
15801     @Test
15802     public void testPreferenceForUserNetworkUpDownWithNoFallback() throws Exception {
15803         final UserHandle testHandle = setupEnterpriseNetwork();
15804         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder =
15805                 new ProfileNetworkPreference.Builder();
15806         profileNetworkPreferenceBuilder.setPreference(
15807                 PROFILE_NETWORK_PREFERENCE_ENTERPRISE_NO_FALLBACK);
15808         profileNetworkPreferenceBuilder.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1);
15809         registerDefaultNetworkCallbacks();
15810         doTestPreferenceForUserNetworkUpDownForGivenPreference(
15811                 profileNetworkPreferenceBuilder.build(), false,
15812                 testHandle, mProfileDefaultNetworkCallback, null);
15813     }
15814 
15815     /**
15816      * Make sure per-profile networking preference behaves as expected when the enterprise network
15817      * goes up and down while the preference is active. Make sure they behave as expected whether
15818      * there is a general default network or not when configured to not fallback to default network
15819      * along with already connected enterprise work agent
15820      */
15821     @Test
15822     public void testPreferenceForUserNetworkUpDownWithNoFallbackWithAlreadyConnectedWorkAgent()
15823             throws Exception {
15824         final UserHandle testHandle = setupEnterpriseNetwork();
15825         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder =
15826                 new ProfileNetworkPreference.Builder();
15827         profileNetworkPreferenceBuilder.setPreference(
15828                 PROFILE_NETWORK_PREFERENCE_ENTERPRISE_NO_FALLBACK);
15829         profileNetworkPreferenceBuilder.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1);
15830         registerDefaultNetworkCallbacks();
15831         doTestPreferenceForUserNetworkUpDownForGivenPreference(
15832                 profileNetworkPreferenceBuilder.build(), true, testHandle,
15833                 mProfileDefaultNetworkCallback, null);
15834     }
15835 
15836     /**
15837      * Make sure per-profile networking preference for specific uid of test handle
15838      * behaves as expected
15839      */
15840     @Test
15841     public void testPreferenceForDefaultUidOfTestHandle() throws Exception {
15842         final UserHandle testHandle = setupEnterpriseNetwork();
15843         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder =
15844                 new ProfileNetworkPreference.Builder();
15845         profileNetworkPreferenceBuilder.setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE);
15846         profileNetworkPreferenceBuilder.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1);
15847         profileNetworkPreferenceBuilder.setIncludedUids(
15848                 new int[]{testHandle.getUid(TEST_WORK_PROFILE_APP_UID)});
15849         registerDefaultNetworkCallbacks();
15850         doTestPreferenceForUserNetworkUpDownForGivenPreference(
15851                 profileNetworkPreferenceBuilder.build(), false, testHandle,
15852                 mProfileDefaultNetworkCallback, null);
15853     }
15854 
15855     /**
15856      * Make sure per-profile networking preference for specific uid of test handle
15857      * behaves as expected
15858      */
15859     @Test
15860     public void testPreferenceForSpecificUidOfOnlyOneApp() throws Exception {
15861         final UserHandle testHandle = setupEnterpriseNetwork();
15862         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder =
15863                 new ProfileNetworkPreference.Builder();
15864         profileNetworkPreferenceBuilder.setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE);
15865         profileNetworkPreferenceBuilder.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1);
15866         profileNetworkPreferenceBuilder.setIncludedUids(
15867                 new int[]{testHandle.getUid(TEST_WORK_PROFILE_APP_UID_2)});
15868         registerDefaultNetworkCallbacks();
15869         doTestPreferenceForUserNetworkUpDownForGivenPreference(
15870                 profileNetworkPreferenceBuilder.build(), false,
15871                 testHandle, mProfileDefaultNetworkCallbackAsAppUid2, null);
15872     }
15873 
15874     /**
15875      * Make sure per-profile networking preference for specific uid of test handle
15876      * behaves as expected
15877      */
15878     @Test
15879     public void testPreferenceForDisallowSpecificUidOfApp() throws Exception {
15880         final UserHandle testHandle = setupEnterpriseNetwork();
15881         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder =
15882                 new ProfileNetworkPreference.Builder();
15883         profileNetworkPreferenceBuilder.setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE);
15884         profileNetworkPreferenceBuilder.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1);
15885         profileNetworkPreferenceBuilder.setExcludedUids(
15886                 new int[]{testHandle.getUid(TEST_WORK_PROFILE_APP_UID_2)});
15887         registerDefaultNetworkCallbacks();
15888         doTestPreferenceForUserNetworkUpDownForGivenPreference(
15889                 profileNetworkPreferenceBuilder.build(), false,
15890                 testHandle, mProfileDefaultNetworkCallback,
15891                 mProfileDefaultNetworkCallbackAsAppUid2);
15892     }
15893 
15894     /**
15895      * Make sure per-profile networking preference for specific uid of test handle
15896      * invalid uid inputs
15897      */
15898     @Test
15899     public void testPreferenceForInvalidUids() throws Exception {
15900         final UserHandle testHandle = setupEnterpriseNetwork();
15901         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder =
15902                 new ProfileNetworkPreference.Builder();
15903         profileNetworkPreferenceBuilder.setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE);
15904         profileNetworkPreferenceBuilder.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1);
15905         profileNetworkPreferenceBuilder.setExcludedUids(
15906                 new int[]{testHandle.getUid(0) - 1});
15907         final TestOnCompleteListener listener = new TestOnCompleteListener();
15908         Assert.assertThrows(IllegalArgumentException.class, () -> mCm.setProfileNetworkPreferences(
15909                 testHandle, List.of(profileNetworkPreferenceBuilder.build()),
15910                 r -> r.run(), listener));
15911 
15912         profileNetworkPreferenceBuilder.setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE);
15913         profileNetworkPreferenceBuilder.setIncludedUids(
15914                 new int[]{testHandle.getUid(0) - 1});
15915         Assert.assertThrows(IllegalArgumentException.class,
15916                 () -> mCm.setProfileNetworkPreferences(
15917                         testHandle, List.of(profileNetworkPreferenceBuilder.build()),
15918                         r -> r.run(), listener));
15919 
15920 
15921         profileNetworkPreferenceBuilder.setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE);
15922         profileNetworkPreferenceBuilder.setIncludedUids(
15923                 new int[]{testHandle.getUid(0) - 1});
15924         profileNetworkPreferenceBuilder.setExcludedUids(
15925                 new int[]{testHandle.getUid(TEST_WORK_PROFILE_APP_UID_2)});
15926         Assert.assertThrows(IllegalArgumentException.class,
15927                 () -> mCm.setProfileNetworkPreferences(
15928                         testHandle, List.of(profileNetworkPreferenceBuilder.build()),
15929                         r -> r.run(), listener));
15930 
15931         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder2 =
15932                 new ProfileNetworkPreference.Builder();
15933         profileNetworkPreferenceBuilder2.setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE);
15934         profileNetworkPreferenceBuilder2.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1);
15935         profileNetworkPreferenceBuilder2.setIncludedUids(
15936                 new int[]{testHandle.getUid(TEST_WORK_PROFILE_APP_UID_2)});
15937         profileNetworkPreferenceBuilder.setIncludedUids(
15938                 new int[]{testHandle.getUid(TEST_WORK_PROFILE_APP_UID_2)});
15939         Assert.assertThrows(IllegalArgumentException.class,
15940                 () -> mCm.setProfileNetworkPreferences(
15941                         testHandle, List.of(profileNetworkPreferenceBuilder.build(),
15942                                 profileNetworkPreferenceBuilder2.build()),
15943                         r -> r.run(), listener));
15944 
15945         profileNetworkPreferenceBuilder2.setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE);
15946         profileNetworkPreferenceBuilder2.setExcludedUids(
15947                 new int[]{testHandle.getUid(TEST_WORK_PROFILE_APP_UID_2)});
15948         profileNetworkPreferenceBuilder.setExcludedUids(
15949                 new int[]{testHandle.getUid(TEST_WORK_PROFILE_APP_UID_2)});
15950         Assert.assertThrows(IllegalArgumentException.class,
15951                 () -> mCm.setProfileNetworkPreferences(
15952                         testHandle, List.of(profileNetworkPreferenceBuilder.build(),
15953                                 profileNetworkPreferenceBuilder2.build()),
15954                         r -> r.run(), listener));
15955 
15956         profileNetworkPreferenceBuilder2.setPreference(
15957                 PROFILE_NETWORK_PREFERENCE_ENTERPRISE_NO_FALLBACK);
15958         profileNetworkPreferenceBuilder2.setExcludedUids(
15959                 new int[]{testHandle.getUid(TEST_WORK_PROFILE_APP_UID_2)});
15960         profileNetworkPreferenceBuilder.setExcludedUids(
15961                 new int[]{testHandle.getUid(TEST_WORK_PROFILE_APP_UID_2)});
15962         Assert.assertThrows(IllegalArgumentException.class,
15963                 () -> mCm.setProfileNetworkPreferences(
15964                         testHandle, List.of(profileNetworkPreferenceBuilder.build(),
15965                                 profileNetworkPreferenceBuilder2.build()),
15966                         r -> r.run(), listener));
15967     }
15968 
15969     /**
15970      * Make sure per-profile networking preference behaves as expected when the enterprise network
15971      * goes up and down while the preference is active. Make sure they behave as expected whether
15972      * there is a general default network or not when configured to fallback to default network
15973      * along with already connected enterprise work agent
15974      */
15975     @Test
15976     public void testPreferenceForUserNetworkUpDownWithFallbackWithAlreadyConnectedWorkAgent()
15977             throws Exception {
15978         final UserHandle testHandle = setupEnterpriseNetwork();
15979         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder =
15980                 new ProfileNetworkPreference.Builder();
15981         profileNetworkPreferenceBuilder.setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE);
15982         profileNetworkPreferenceBuilder.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1);
15983         registerDefaultNetworkCallbacks();
15984         doTestPreferenceForUserNetworkUpDownForGivenPreference(
15985                 profileNetworkPreferenceBuilder.build(), true,
15986                 testHandle, mProfileDefaultNetworkCallback,
15987                 null);
15988     }
15989 
15990     /**
15991      * Make sure per-profile networking preference behaves as expected when the enterprise network
15992      * goes up and down while the preference is active for a given enterprise identifier
15993      */
15994     @Test
15995     public void testPreferenceForUserNetworkUpDownWithDefaultEnterpriseId()
15996             throws Exception {
15997         final UserHandle testHandle = setupEnterpriseNetwork();
15998         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder =
15999                 new ProfileNetworkPreference.Builder();
16000         profileNetworkPreferenceBuilder.setPreference(
16001                 PROFILE_NETWORK_PREFERENCE_ENTERPRISE_NO_FALLBACK);
16002         profileNetworkPreferenceBuilder.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1);
16003         registerDefaultNetworkCallbacks();
16004         doTestPreferenceForUserNetworkUpDownForGivenPreference(
16005                 profileNetworkPreferenceBuilder.build(), true,
16006                 testHandle, mProfileDefaultNetworkCallback,
16007                 null);
16008     }
16009 
16010     /**
16011      * Make sure per-profile networking preference behaves as expected when the enterprise network
16012      * goes up and down while the preference is active for a given enterprise identifier
16013      */
16014     @Test
16015     public void testPreferenceForUserNetworkUpDownWithId2()
16016             throws Exception {
16017         final UserHandle testHandle = setupEnterpriseNetwork();
16018         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder =
16019                 new ProfileNetworkPreference.Builder();
16020         profileNetworkPreferenceBuilder.setPreference(
16021                 PROFILE_NETWORK_PREFERENCE_ENTERPRISE_NO_FALLBACK);
16022         profileNetworkPreferenceBuilder.setPreferenceEnterpriseId(
16023                 NET_ENTERPRISE_ID_2);
16024         registerDefaultNetworkCallbacks();
16025         doTestPreferenceForUserNetworkUpDownForGivenPreference(
16026                 profileNetworkPreferenceBuilder.build(), true,
16027                 testHandle, mProfileDefaultNetworkCallback, null);
16028     }
16029 
16030     /**
16031      * Make sure per-profile networking preference behaves as expected when the enterprise network
16032      * goes up and down while the preference is active for a given enterprise identifier
16033      */
16034     @Test
16035     public void testPreferenceForUserNetworkUpDownWithInvalidId()
16036             throws Exception {
16037         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder =
16038                 new ProfileNetworkPreference.Builder();
16039         profileNetworkPreferenceBuilder.setPreference(
16040                 PROFILE_NETWORK_PREFERENCE_ENTERPRISE_NO_FALLBACK);
16041         profileNetworkPreferenceBuilder.setPreferenceEnterpriseId(0);
16042         registerDefaultNetworkCallbacks();
16043         assertThrows("Should not be able to set invalid enterprise id",
16044                 IllegalStateException.class, () -> profileNetworkPreferenceBuilder.build());
16045     }
16046 
16047     /**
16048      * Make sure per-profile networking preference throws exception when default preference
16049      * is set along with enterprise preference.
16050      */
16051     @Test
16052     public void testPreferenceWithInvalidPreferenceDefaultAndEnterpriseTogether()
16053             throws Exception {
16054         final UserHandle testHandle = setupEnterpriseNetwork();
16055         mServiceContext.setWorkProfile(testHandle, true);
16056 
16057         final int testWorkProfileAppUid1 =
16058                 UserHandle.getUid(testHandle.getIdentifier(), TEST_APP_ID);
16059         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder1 =
16060                 new ProfileNetworkPreference.Builder();
16061         profileNetworkPreferenceBuilder1.setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE);
16062         profileNetworkPreferenceBuilder1.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1);
16063         profileNetworkPreferenceBuilder1.setIncludedUids(new int[]{testWorkProfileAppUid1});
16064 
16065         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder2 =
16066                 new ProfileNetworkPreference.Builder();
16067         profileNetworkPreferenceBuilder2.setPreference(PROFILE_NETWORK_PREFERENCE_DEFAULT);
16068         final TestOnCompleteListener listener = new TestOnCompleteListener();
16069         Assert.assertThrows(IllegalArgumentException.class,
16070                 () -> mCm.setProfileNetworkPreferences(
16071                         testHandle, List.of(profileNetworkPreferenceBuilder1.build(),
16072                                 profileNetworkPreferenceBuilder2.build()),
16073                         r -> r.run(), listener));
16074         Assert.assertThrows(IllegalArgumentException.class,
16075                 () -> mCm.setProfileNetworkPreferences(
16076                         testHandle, List.of(profileNetworkPreferenceBuilder2.build(),
16077                                 profileNetworkPreferenceBuilder1.build()),
16078                         r -> r.run(), listener));
16079     }
16080 
16081     /**
16082      * Make sure per profile network preferences behave as expected when two slices with
16083      * two different apps within same user profile is configured
16084      * Make sure per profile network preferences overrides with latest preference when
16085      * same user preference is set twice
16086      */
16087     @Test
16088     public void testSetPreferenceWithOverridingPreference()
16089             throws Exception {
16090         final InOrder inOrder = inOrder(mMockNetd);
16091         final UserHandle testHandle = setupEnterpriseNetwork();
16092         mServiceContext.setWorkProfile(testHandle, true);
16093         registerDefaultNetworkCallbacks();
16094 
16095         final TestNetworkCallback appCb1 = new TestNetworkCallback();
16096         final TestNetworkCallback appCb2 = new TestNetworkCallback();
16097         final TestNetworkCallback appCb3 = new TestNetworkCallback();
16098 
16099         final int testWorkProfileAppUid1 =
16100                 UserHandle.getUid(testHandle.getIdentifier(), TEST_APP_ID);
16101         final int testWorkProfileAppUid2 =
16102                 UserHandle.getUid(testHandle.getIdentifier(), TEST_APP_ID_2);
16103         final int testWorkProfileAppUid3 =
16104                 UserHandle.getUid(testHandle.getIdentifier(), TEST_APP_ID_3);
16105 
16106         registerDefaultNetworkCallbackAsUid(appCb1, testWorkProfileAppUid1);
16107         registerDefaultNetworkCallbackAsUid(appCb2, testWorkProfileAppUid2);
16108         registerDefaultNetworkCallbackAsUid(appCb3, testWorkProfileAppUid3);
16109 
16110         // Connect both a regular cell agent and an enterprise network first.
16111         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
16112         mCellAgent.connect(true);
16113 
16114         final TestNetworkAgentWrapper workAgent1 = makeEnterpriseNetworkAgent(NET_ENTERPRISE_ID_1);
16115         final TestNetworkAgentWrapper workAgent2 = makeEnterpriseNetworkAgent(NET_ENTERPRISE_ID_2);
16116         workAgent1.connect(true);
16117         workAgent2.connect(true);
16118 
16119         mSystemDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
16120         mDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
16121 
16122         appCb1.expectAvailableThenValidatedCallbacks(mCellAgent);
16123         appCb2.expectAvailableThenValidatedCallbacks(mCellAgent);
16124         appCb3.expectAvailableThenValidatedCallbacks(mCellAgent);
16125 
16126         verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
16127                 mCellAgent.getNetwork().netId, INetd.PERMISSION_NONE));
16128         verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
16129                 workAgent1.getNetwork().netId, INetd.PERMISSION_SYSTEM));
16130         verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
16131                 workAgent2.getNetwork().netId, INetd.PERMISSION_SYSTEM));
16132 
16133         final TestOnCompleteListener listener = new TestOnCompleteListener();
16134 
16135         // Set preferences for testHandle to map testWorkProfileAppUid1 to
16136         // NET_ENTERPRISE_ID_1 and testWorkProfileAppUid2 to NET_ENTERPRISE_ID_2.
16137         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder1 =
16138                 new ProfileNetworkPreference.Builder();
16139         profileNetworkPreferenceBuilder1.setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE);
16140         profileNetworkPreferenceBuilder1.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1);
16141         profileNetworkPreferenceBuilder1.setIncludedUids(new int[]{testWorkProfileAppUid1});
16142 
16143         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder2 =
16144                 new ProfileNetworkPreference.Builder();
16145         profileNetworkPreferenceBuilder2.setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE);
16146         profileNetworkPreferenceBuilder2.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_2);
16147         profileNetworkPreferenceBuilder2.setIncludedUids(new int[]{testWorkProfileAppUid2});
16148 
16149         mCm.setProfileNetworkPreferences(testHandle,
16150                 List.of(profileNetworkPreferenceBuilder1.build(),
16151                         profileNetworkPreferenceBuilder2.build()),
16152                 r -> r.run(), listener);
16153         listener.expectOnComplete();
16154         verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
16155                 workAgent2.getNetwork().netId,
16156                 uidRangeFor(testHandle, profileNetworkPreferenceBuilder2.build()),
16157                 PREFERENCE_ORDER_PROFILE));
16158         verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
16159                 workAgent1.getNetwork().netId,
16160                 uidRangeFor(testHandle, profileNetworkPreferenceBuilder1.build()),
16161                 PREFERENCE_ORDER_PROFILE));
16162 
16163         assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback);
16164         appCb1.expectAvailableCallbacksValidated(workAgent1);
16165         appCb2.expectAvailableCallbacksValidated(workAgent2);
16166 
16167         // Set preferences for testHandle to map testWorkProfileAppUid3 to
16168         // to NET_ENTERPRISE_ID_1.
16169         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder3 =
16170                 new ProfileNetworkPreference.Builder();
16171         profileNetworkPreferenceBuilder3.setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE);
16172         profileNetworkPreferenceBuilder3.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1);
16173         profileNetworkPreferenceBuilder3.setIncludedUids(new int[]{testWorkProfileAppUid3});
16174 
16175         mCm.setProfileNetworkPreferences(testHandle,
16176                 List.of(profileNetworkPreferenceBuilder3.build()),
16177                 r -> r.run(), listener);
16178         listener.expectOnComplete();
16179         verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
16180                 workAgent1.getNetwork().netId,
16181                 uidRangeFor(testHandle, profileNetworkPreferenceBuilder3.build()),
16182                 PREFERENCE_ORDER_PROFILE));
16183         verify(mMockNetd).networkRemoveUidRangesParcel(new NativeUidRangeConfig(
16184                 workAgent2.getNetwork().netId,
16185                 uidRangeFor(testHandle, profileNetworkPreferenceBuilder2.build()),
16186                 PREFERENCE_ORDER_PROFILE));
16187         verify(mMockNetd).networkRemoveUidRangesParcel(new NativeUidRangeConfig(
16188                 workAgent1.getNetwork().netId,
16189                 uidRangeFor(testHandle, profileNetworkPreferenceBuilder1.build()),
16190                 PREFERENCE_ORDER_PROFILE));
16191 
16192         assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback);
16193         appCb3.expectAvailableCallbacksValidated(workAgent1);
16194         appCb2.expectAvailableCallbacksValidated(mCellAgent);
16195         appCb1.expectAvailableCallbacksValidated(mCellAgent);
16196 
16197         // Set the preferences for testHandle to default.
16198         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder =
16199                 new ProfileNetworkPreference.Builder();
16200         profileNetworkPreferenceBuilder.setPreference(PROFILE_NETWORK_PREFERENCE_DEFAULT);
16201 
16202         mCm.setProfileNetworkPreferences(testHandle,
16203                 List.of(profileNetworkPreferenceBuilder.build()),
16204                 r -> r.run(), listener);
16205         listener.expectOnComplete();
16206         verify(mMockNetd).networkRemoveUidRangesParcel(new NativeUidRangeConfig(
16207                 workAgent1.getNetwork().netId,
16208                 uidRangeFor(testHandle, profileNetworkPreferenceBuilder3.build()),
16209                 PREFERENCE_ORDER_PROFILE));
16210 
16211         assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback, appCb1, appCb2);
16212         appCb3.expectAvailableCallbacksValidated(mCellAgent);
16213         workAgent2.disconnect();
16214         mCellAgent.disconnect();
16215 
16216         mCm.unregisterNetworkCallback(appCb1);
16217         mCm.unregisterNetworkCallback(appCb2);
16218         mCm.unregisterNetworkCallback(appCb3);
16219         // Other callbacks will be unregistered by tearDown()
16220     }
16221 
16222     /**
16223      * Make sure per profile network preferences behave as expected when multiple slices with
16224      * multiple different apps within same user profile is configured.
16225      */
16226     @Test
16227     public void testSetPreferenceWithMultiplePreferences()
16228             throws Exception {
16229         final InOrder inOrder = inOrder(mMockNetd);
16230 
16231         final UserHandle testHandle = setupEnterpriseNetwork();
16232         mServiceContext.setWorkProfile(testHandle, true);
16233         registerDefaultNetworkCallbacks();
16234 
16235         final TestNetworkCallback appCb1 = new TestNetworkCallback();
16236         final TestNetworkCallback appCb2 = new TestNetworkCallback();
16237         final TestNetworkCallback appCb3 = new TestNetworkCallback();
16238         final TestNetworkCallback appCb4 = new TestNetworkCallback();
16239         final TestNetworkCallback appCb5 = new TestNetworkCallback();
16240 
16241         final int testWorkProfileAppUid1 =
16242                 UserHandle.getUid(testHandle.getIdentifier(), TEST_APP_ID);
16243         final int testWorkProfileAppUid2 =
16244                 UserHandle.getUid(testHandle.getIdentifier(), TEST_APP_ID_2);
16245         final int testWorkProfileAppUid3 =
16246                 UserHandle.getUid(testHandle.getIdentifier(), TEST_APP_ID_3);
16247         final int testWorkProfileAppUid4 =
16248                 UserHandle.getUid(testHandle.getIdentifier(), TEST_APP_ID_4);
16249         final int testWorkProfileAppUid5 =
16250                 UserHandle.getUid(testHandle.getIdentifier(), TEST_APP_ID_5);
16251 
16252         registerDefaultNetworkCallbackAsUid(appCb1, testWorkProfileAppUid1);
16253         registerDefaultNetworkCallbackAsUid(appCb2, testWorkProfileAppUid2);
16254         registerDefaultNetworkCallbackAsUid(appCb3, testWorkProfileAppUid3);
16255         registerDefaultNetworkCallbackAsUid(appCb4, testWorkProfileAppUid4);
16256         registerDefaultNetworkCallbackAsUid(appCb5, testWorkProfileAppUid5);
16257 
16258         // Connect both a regular cell agent and an enterprise network first.
16259         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
16260         mCellAgent.connect(true);
16261 
16262         final TestNetworkAgentWrapper workAgent1 = makeEnterpriseNetworkAgent(NET_ENTERPRISE_ID_1);
16263         final TestNetworkAgentWrapper workAgent2 = makeEnterpriseNetworkAgent(NET_ENTERPRISE_ID_2);
16264         final TestNetworkAgentWrapper workAgent3 = makeEnterpriseNetworkAgent(NET_ENTERPRISE_ID_3);
16265         final TestNetworkAgentWrapper workAgent4 = makeEnterpriseNetworkAgent(NET_ENTERPRISE_ID_4);
16266         final TestNetworkAgentWrapper workAgent5 = makeEnterpriseNetworkAgent(NET_ENTERPRISE_ID_5);
16267 
16268         workAgent1.connect(true);
16269         workAgent2.connect(true);
16270         workAgent3.connect(true);
16271         workAgent4.connect(true);
16272         workAgent5.connect(true);
16273 
16274         mSystemDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
16275         mDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
16276         appCb1.expectAvailableThenValidatedCallbacks(mCellAgent);
16277         appCb2.expectAvailableThenValidatedCallbacks(mCellAgent);
16278         appCb3.expectAvailableThenValidatedCallbacks(mCellAgent);
16279         appCb4.expectAvailableThenValidatedCallbacks(mCellAgent);
16280         appCb5.expectAvailableThenValidatedCallbacks(mCellAgent);
16281 
16282         verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
16283                 mCellAgent.getNetwork().netId, INetd.PERMISSION_NONE));
16284         verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
16285                 workAgent1.getNetwork().netId, INetd.PERMISSION_SYSTEM));
16286         verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
16287                 workAgent2.getNetwork().netId, INetd.PERMISSION_SYSTEM));
16288         verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
16289                 workAgent3.getNetwork().netId, INetd.PERMISSION_SYSTEM));
16290         verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
16291                 workAgent4.getNetwork().netId, INetd.PERMISSION_SYSTEM));
16292         verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
16293                 workAgent5.getNetwork().netId, INetd.PERMISSION_SYSTEM));
16294 
16295         final TestOnCompleteListener listener = new TestOnCompleteListener();
16296 
16297         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder1 =
16298                 new ProfileNetworkPreference.Builder();
16299         profileNetworkPreferenceBuilder1.setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE);
16300         profileNetworkPreferenceBuilder1.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1);
16301         profileNetworkPreferenceBuilder1.setIncludedUids(new int[]{testWorkProfileAppUid1});
16302 
16303         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder2 =
16304                 new ProfileNetworkPreference.Builder();
16305         profileNetworkPreferenceBuilder2.setPreference(
16306                 PROFILE_NETWORK_PREFERENCE_ENTERPRISE_NO_FALLBACK);
16307         profileNetworkPreferenceBuilder2.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_2);
16308         profileNetworkPreferenceBuilder2.setIncludedUids(new int[]{testWorkProfileAppUid2});
16309 
16310         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder3 =
16311                 new ProfileNetworkPreference.Builder();
16312         profileNetworkPreferenceBuilder3.setPreference(
16313                 PROFILE_NETWORK_PREFERENCE_ENTERPRISE);
16314         profileNetworkPreferenceBuilder3.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_3);
16315         profileNetworkPreferenceBuilder3.setIncludedUids(new int[]{testWorkProfileAppUid3});
16316 
16317         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder4 =
16318                 new ProfileNetworkPreference.Builder();
16319         profileNetworkPreferenceBuilder4.setPreference(
16320                 PROFILE_NETWORK_PREFERENCE_ENTERPRISE_NO_FALLBACK);
16321         profileNetworkPreferenceBuilder4.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_4);
16322         profileNetworkPreferenceBuilder4.setIncludedUids(new int[]{testWorkProfileAppUid4});
16323 
16324         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder5 =
16325                 new ProfileNetworkPreference.Builder();
16326         profileNetworkPreferenceBuilder5.setPreference(
16327                 PROFILE_NETWORK_PREFERENCE_ENTERPRISE);
16328         profileNetworkPreferenceBuilder5.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_5);
16329         profileNetworkPreferenceBuilder5.setIncludedUids(new int[]{testWorkProfileAppUid5});
16330 
16331         mCm.setProfileNetworkPreferences(testHandle,
16332                 List.of(profileNetworkPreferenceBuilder1.build(),
16333                         profileNetworkPreferenceBuilder2.build(),
16334                         profileNetworkPreferenceBuilder3.build(),
16335                         profileNetworkPreferenceBuilder4.build(),
16336                         profileNetworkPreferenceBuilder5.build()),
16337                 r -> r.run(), listener);
16338 
16339         listener.expectOnComplete();
16340 
16341         verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
16342                 workAgent1.getNetwork().netId,
16343                 uidRangeFor(testHandle, profileNetworkPreferenceBuilder1.build()),
16344                 PREFERENCE_ORDER_PROFILE));
16345         verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
16346                 workAgent2.getNetwork().netId,
16347                 uidRangeFor(testHandle, profileNetworkPreferenceBuilder2.build()),
16348                 PREFERENCE_ORDER_PROFILE));
16349         verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
16350                 workAgent3.getNetwork().netId,
16351                 uidRangeFor(testHandle, profileNetworkPreferenceBuilder3.build()),
16352                 PREFERENCE_ORDER_PROFILE));
16353         verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
16354                 workAgent4.getNetwork().netId,
16355                 uidRangeFor(testHandle, profileNetworkPreferenceBuilder4.build()),
16356                 PREFERENCE_ORDER_PROFILE));
16357         verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
16358                 workAgent5.getNetwork().netId,
16359                 uidRangeFor(testHandle, profileNetworkPreferenceBuilder5.build()),
16360                 PREFERENCE_ORDER_PROFILE));
16361 
16362         assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback);
16363         appCb1.expectAvailableCallbacksValidated(workAgent1);
16364         appCb2.expectAvailableCallbacksValidated(workAgent2);
16365         appCb3.expectAvailableCallbacksValidated(workAgent3);
16366         appCb4.expectAvailableCallbacksValidated(workAgent4);
16367         appCb5.expectAvailableCallbacksValidated(workAgent5);
16368 
16369         workAgent1.disconnect();
16370         workAgent2.disconnect();
16371         workAgent3.disconnect();
16372         workAgent4.disconnect();
16373         workAgent5.disconnect();
16374 
16375         appCb1.expect(LOST, workAgent1);
16376         appCb2.expect(LOST, workAgent2);
16377         appCb3.expect(LOST, workAgent3);
16378         appCb4.expect(LOST, workAgent4);
16379         appCb5.expect(LOST, workAgent5);
16380 
16381         appCb1.expectAvailableCallbacksValidated(mCellAgent);
16382         appCb2.assertNoCallback();
16383         appCb3.expectAvailableCallbacksValidated(mCellAgent);
16384         appCb4.assertNoCallback();
16385         appCb5.expectAvailableCallbacksValidated(mCellAgent);
16386 
16387         verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
16388                 mCellAgent.getNetwork().netId,
16389                 uidRangeFor(testHandle, profileNetworkPreferenceBuilder1.build()),
16390                 PREFERENCE_ORDER_PROFILE));
16391         verify(mMockNetd, never()).networkAddUidRangesParcel(new NativeUidRangeConfig(
16392                 mCellAgent.getNetwork().netId,
16393                 uidRangeFor(testHandle, profileNetworkPreferenceBuilder2.build()),
16394                 PREFERENCE_ORDER_PROFILE));
16395         verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
16396                 mCellAgent.getNetwork().netId,
16397                 uidRangeFor(testHandle, profileNetworkPreferenceBuilder3.build()),
16398                 PREFERENCE_ORDER_PROFILE));
16399         verify(mMockNetd, never()).networkAddUidRangesParcel(new NativeUidRangeConfig(
16400                 mCellAgent.getNetwork().netId,
16401                 uidRangeFor(testHandle, profileNetworkPreferenceBuilder4.build()),
16402                 PREFERENCE_ORDER_PROFILE));
16403         verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
16404                 mCellAgent.getNetwork().netId,
16405                 uidRangeFor(testHandle, profileNetworkPreferenceBuilder5.build()),
16406                 PREFERENCE_ORDER_PROFILE));
16407 
16408         mSystemDefaultNetworkCallback.assertNoCallback();
16409         mDefaultNetworkCallback.assertNoCallback();
16410 
16411         // Set the preferences for testHandle to default.
16412         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder =
16413                 new ProfileNetworkPreference.Builder();
16414         profileNetworkPreferenceBuilder.setPreference(PROFILE_NETWORK_PREFERENCE_DEFAULT);
16415 
16416         mCm.setProfileNetworkPreferences(testHandle,
16417                 List.of(profileNetworkPreferenceBuilder.build()),
16418                 r -> r.run(), listener);
16419         listener.expectOnComplete();
16420         assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback, appCb1, appCb3,
16421                 appCb5);
16422         appCb2.expectAvailableCallbacksValidated(mCellAgent);
16423         appCb4.expectAvailableCallbacksValidated(mCellAgent);
16424         mCellAgent.disconnect();
16425 
16426         mCm.unregisterNetworkCallback(appCb1);
16427         mCm.unregisterNetworkCallback(appCb2);
16428         mCm.unregisterNetworkCallback(appCb3);
16429         mCm.unregisterNetworkCallback(appCb4);
16430         mCm.unregisterNetworkCallback(appCb5);
16431         // Other callbacks will be unregistered by tearDown()
16432     }
16433 
16434     /**
16435      * Test that, in a given networking context, calling setPreferenceForUser to set per-profile
16436      * defaults on then off works as expected.
16437      */
16438     @Test
16439     public void testSetPreferenceForUserOnOff() throws Exception {
16440         final InOrder inOrder = inOrder(mMockNetd);
16441         final UserHandle testHandle = setupEnterpriseNetwork();
16442 
16443         // Connect both a regular cell agent and an enterprise network first.
16444         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
16445         mCellAgent.connect(true);
16446 
16447         final TestNetworkAgentWrapper workAgent = makeEnterpriseNetworkAgent();
16448         workAgent.connect(true);
16449 
16450         final TestOnCompleteListener listener = new TestOnCompleteListener();
16451         mCm.setProfileNetworkPreference(testHandle, PROFILE_NETWORK_PREFERENCE_ENTERPRISE,
16452                 r -> r.run(), listener);
16453         listener.expectOnComplete();
16454         inOrder.verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
16455                 mCellAgent.getNetwork().netId, INetd.PERMISSION_NONE));
16456         inOrder.verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
16457                 workAgent.getNetwork().netId, uidRangeFor(testHandle), PREFERENCE_ORDER_PROFILE));
16458 
16459         registerDefaultNetworkCallbacks();
16460 
16461         mSystemDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellAgent);
16462         mDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellAgent);
16463         mProfileDefaultNetworkCallback.expectAvailableCallbacksValidated(workAgent);
16464 
16465         mCm.setProfileNetworkPreference(testHandle, PROFILE_NETWORK_PREFERENCE_DEFAULT,
16466                 r -> r.run(), listener);
16467         listener.expectOnComplete();
16468 
16469         mProfileDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellAgent);
16470         assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback);
16471         inOrder.verify(mMockNetd).networkRemoveUidRangesParcel(new NativeUidRangeConfig(
16472                 workAgent.getNetwork().netId, uidRangeFor(testHandle), PREFERENCE_ORDER_PROFILE));
16473 
16474         workAgent.disconnect();
16475         mCellAgent.disconnect();
16476 
16477         // Callbacks will be unregistered by tearDown()
16478     }
16479 
16480     /**
16481      * Test per-profile default networks for two different profiles concurrently.
16482      */
16483     @Test
16484     public void testSetPreferenceForTwoProfiles() throws Exception {
16485         final InOrder inOrder = inOrder(mMockNetd);
16486         final UserHandle testHandle2 = setupEnterpriseNetwork();
16487         final UserHandle testHandle4 = UserHandle.of(TEST_WORK_PROFILE_USER_ID + 2);
16488         mServiceContext.setWorkProfile(testHandle4, true);
16489         registerDefaultNetworkCallbacks();
16490 
16491         final TestNetworkCallback app4Cb = new TestNetworkCallback();
16492         final int testWorkProfileAppUid4 =
16493                 UserHandle.getUid(testHandle4.getIdentifier(), TEST_APP_ID);
16494         registerDefaultNetworkCallbackAsUid(app4Cb, testWorkProfileAppUid4);
16495 
16496         // Connect both a regular cell agent and an enterprise network first.
16497         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
16498         mCellAgent.connect(true);
16499 
16500         final TestNetworkAgentWrapper workAgent = makeEnterpriseNetworkAgent();
16501         workAgent.connect(true);
16502 
16503         mSystemDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
16504         mDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
16505         mProfileDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
16506         app4Cb.expectAvailableThenValidatedCallbacks(mCellAgent);
16507         inOrder.verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
16508                 mCellAgent.getNetwork().netId, INetd.PERMISSION_NONE));
16509         inOrder.verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
16510                 workAgent.getNetwork().netId, INetd.PERMISSION_SYSTEM));
16511 
16512         final TestOnCompleteListener listener = new TestOnCompleteListener();
16513         mCm.setProfileNetworkPreference(testHandle2, PROFILE_NETWORK_PREFERENCE_ENTERPRISE,
16514                 r -> r.run(), listener);
16515         listener.expectOnComplete();
16516         inOrder.verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
16517                 workAgent.getNetwork().netId, uidRangeFor(testHandle2), PREFERENCE_ORDER_PROFILE));
16518 
16519         mProfileDefaultNetworkCallback.expectAvailableCallbacksValidated(workAgent);
16520         assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback,
16521                 app4Cb);
16522 
16523         mCm.setProfileNetworkPreference(testHandle4, PROFILE_NETWORK_PREFERENCE_ENTERPRISE,
16524                 r -> r.run(), listener);
16525         listener.expectOnComplete();
16526         inOrder.verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
16527                 workAgent.getNetwork().netId, uidRangeFor(testHandle4), PREFERENCE_ORDER_PROFILE));
16528 
16529         app4Cb.expectAvailableCallbacksValidated(workAgent);
16530         assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback,
16531                 mProfileDefaultNetworkCallback);
16532 
16533         mCm.setProfileNetworkPreference(testHandle2, PROFILE_NETWORK_PREFERENCE_DEFAULT,
16534                 r -> r.run(), listener);
16535         listener.expectOnComplete();
16536         inOrder.verify(mMockNetd).networkRemoveUidRangesParcel(new NativeUidRangeConfig(
16537                 workAgent.getNetwork().netId, uidRangeFor(testHandle2), PREFERENCE_ORDER_PROFILE));
16538 
16539         mProfileDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellAgent);
16540         assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback,
16541                 app4Cb);
16542 
16543         workAgent.disconnect();
16544         mCellAgent.disconnect();
16545 
16546         mCm.unregisterNetworkCallback(app4Cb);
16547         // Other callbacks will be unregistered by tearDown()
16548     }
16549 
16550     @Test
16551     public void testProfilePreferenceRemovedUponUserRemoved() throws Exception {
16552         final InOrder inOrder = inOrder(mMockNetd);
16553         final UserHandle testHandle = setupEnterpriseNetwork();
16554 
16555         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
16556         mCellAgent.connect(true);
16557 
16558         final TestOnCompleteListener listener = new TestOnCompleteListener();
16559         mCm.setProfileNetworkPreference(testHandle, PROFILE_NETWORK_PREFERENCE_ENTERPRISE,
16560                 r -> r.run(), listener);
16561         listener.expectOnComplete();
16562         inOrder.verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
16563                 mCellAgent.getNetwork().netId, INetd.PERMISSION_NONE));
16564         inOrder.verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
16565                 mCellAgent.getNetwork().netId, uidRangeFor(testHandle),
16566                 PREFERENCE_ORDER_PROFILE));
16567 
16568         final Intent removedIntent = new Intent(ACTION_USER_REMOVED);
16569         removedIntent.putExtra(Intent.EXTRA_USER, testHandle);
16570         processBroadcast(removedIntent);
16571 
16572         inOrder.verify(mMockNetd).networkRemoveUidRangesParcel(new NativeUidRangeConfig(
16573                 mCellAgent.getNetwork().netId, uidRangeFor(testHandle),
16574                 PREFERENCE_ORDER_PROFILE));
16575     }
16576 
16577     @Test
16578     public void testProfileNetworkPreferenceBlocking_addUser() throws Exception {
16579         final InOrder inOrder = inOrder(mMockNetd);
16580         doReturn(asList(PRIMARY_USER_HANDLE)).when(mUserManager).getUserHandles(anyBoolean());
16581 
16582         // Only one network
16583         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
16584         mCellAgent.connect(true);
16585 
16586         // Verify uid ranges 0~99999 are allowed
16587         final ArraySet<UidRange> allowedRanges = new ArraySet<>();
16588         allowedRanges.add(PRIMARY_UIDRANGE);
16589         final NativeUidRangeConfig config1User = new NativeUidRangeConfig(
16590                 mCellAgent.getNetwork().netId,
16591                 toUidRangeStableParcels(allowedRanges),
16592                 0 /* subPriority */);
16593         if (mDeps.isAtLeastU()) {
16594             inOrder.verify(mMockNetd).setNetworkAllowlist(new NativeUidRangeConfig[]{config1User});
16595         } else {
16596             inOrder.verify(mMockNetd, never()).setNetworkAllowlist(any());
16597         }
16598 
16599         doReturn(asList(PRIMARY_USER_HANDLE, SECONDARY_USER_HANDLE))
16600                 .when(mUserManager).getUserHandles(anyBoolean());
16601         final Intent addedIntent = new Intent(ACTION_USER_ADDED);
16602         addedIntent.putExtra(Intent.EXTRA_USER, UserHandle.of(SECONDARY_USER));
16603         processBroadcast(addedIntent);
16604 
16605         // Make sure the allow list has been updated.
16606         allowedRanges.add(UidRange.createForUser(SECONDARY_USER_HANDLE));
16607         final NativeUidRangeConfig config2Users = new NativeUidRangeConfig(
16608                 mCellAgent.getNetwork().netId,
16609                 toUidRangeStableParcels(allowedRanges),
16610                 0 /* subPriority */);
16611         if (mDeps.isAtLeastU()) {
16612             inOrder.verify(mMockNetd).setNetworkAllowlist(new NativeUidRangeConfig[]{config2Users});
16613         } else {
16614             inOrder.verify(mMockNetd, never()).setNetworkAllowlist(any());
16615         }
16616     }
16617 
16618     @Test
16619     public void testProfileNetworkPreferenceBlocking_changePreference() throws Exception {
16620         final InOrder inOrder = inOrder(mMockNetd);
16621         final UserHandle testHandle = setupEnterpriseNetwork();
16622         doReturn(asList(PRIMARY_USER_HANDLE, testHandle))
16623                 .when(mUserManager).getUserHandles(anyBoolean());
16624 
16625         // Start with 1 default network and 1 enterprise network, both networks should
16626         // not be restricted since the blocking preference is not set yet.
16627         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
16628         mCellAgent.connect(true);
16629 
16630         // Verify uid ranges 0~99999, 200000~299999 are all allowed for cellular.
16631         final UidRange profileUidRange =
16632                 UidRange.createForUser(UserHandle.of(TEST_WORK_PROFILE_USER_ID));
16633         ArraySet<UidRange> allowedAllUidRanges = new ArraySet<>();
16634         allowedAllUidRanges.add(PRIMARY_UIDRANGE);
16635         allowedAllUidRanges.add(profileUidRange);
16636         final UidRangeParcel[] allowAllUidRangesParcel = toUidRangeStableParcels(
16637                 allowedAllUidRanges);
16638         final NativeUidRangeConfig cellAllAllowedConfig = new NativeUidRangeConfig(
16639                 mCellAgent.getNetwork().netId,
16640                 allowAllUidRangesParcel,
16641                 0 /* subPriority */);
16642         if (mDeps.isAtLeastU()) {
16643             inOrder.verify(mMockNetd).setNetworkAllowlist(
16644                     new NativeUidRangeConfig[]{cellAllAllowedConfig});
16645         } else {
16646             inOrder.verify(mMockNetd, never()).setNetworkAllowlist(any());
16647         }
16648 
16649         // Verify the same uid ranges are also applied for enterprise network.
16650         final TestNetworkAgentWrapper enterpriseAgent = makeEnterpriseNetworkAgent(
16651                 NET_ENTERPRISE_ID_1);
16652         enterpriseAgent.connect(true);
16653         final NativeUidRangeConfig enterpriseAllAllowedConfig = new NativeUidRangeConfig(
16654                 enterpriseAgent.getNetwork().netId,
16655                 allowAllUidRangesParcel,
16656                 0 /* subPriority */);
16657         // Network agents are stored in an ArraySet which does not guarantee the order and
16658         // making the order of the list undeterministic. Thus, verify this in order insensitive way.
16659         final ArgumentCaptor<NativeUidRangeConfig[]> configsCaptor = ArgumentCaptor.forClass(
16660                 NativeUidRangeConfig[].class);
16661         if (mDeps.isAtLeastU()) {
16662             inOrder.verify(mMockNetd).setNetworkAllowlist(configsCaptor.capture());
16663             assertContainsAll(List.of(configsCaptor.getValue()),
16664                     List.of(cellAllAllowedConfig, enterpriseAllAllowedConfig));
16665         } else {
16666             inOrder.verify(mMockNetd, never()).setNetworkAllowlist(any());
16667         }
16668 
16669         // Setup profile preference which only applies to test app uid on the managed profile.
16670         ProfileNetworkPreference.Builder prefBuilder = new ProfileNetworkPreference.Builder();
16671         prefBuilder.setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE_BLOCKING)
16672                 .setIncludedUids(new int[]{testHandle.getUid(TEST_WORK_PROFILE_APP_UID)})
16673                 .setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1);
16674         final TestOnCompleteListener listener = new TestOnCompleteListener();
16675         mCm.setProfileNetworkPreferences(testHandle,
16676                 List.of(prefBuilder.build()),
16677                 r -> r.run(), listener);
16678         listener.expectOnComplete();
16679 
16680         // Verify Netd is called for the preferences changed.
16681         // Cell: 0~99999, 200000~TEST_APP_UID-1, TEST_APP_UID+1~299999
16682         // Enterprise: 0~99999, 200000~299999
16683         final ArraySet<UidRange> excludeAppRanges = new ArraySet<>();
16684         excludeAppRanges.add(PRIMARY_UIDRANGE);
16685         excludeAppRanges.addAll(UidRangeUtils.removeRangeSetFromUidRange(
16686                 profileUidRange,
16687                 new ArraySet(new UidRange[]{
16688                         (new UidRange(TEST_WORK_PROFILE_APP_UID, TEST_WORK_PROFILE_APP_UID))})
16689         ));
16690         final UidRangeParcel[] excludeAppRangesParcel = toUidRangeStableParcels(excludeAppRanges);
16691         final NativeUidRangeConfig cellExcludeAppConfig = new NativeUidRangeConfig(
16692                 mCellAgent.getNetwork().netId,
16693                 excludeAppRangesParcel,
16694                 0 /* subPriority */);
16695         if (mDeps.isAtLeastU()) {
16696             inOrder.verify(mMockNetd).setNetworkAllowlist(configsCaptor.capture());
16697             assertContainsAll(List.of(configsCaptor.getValue()),
16698                     List.of(cellExcludeAppConfig, enterpriseAllAllowedConfig));
16699         } else {
16700             inOrder.verify(mMockNetd, never()).setNetworkAllowlist(any());
16701         }
16702 
16703         // Verify unset by giving all allowed set for all users when the preference got removed.
16704         mCm.setProfileNetworkPreference(testHandle, PROFILE_NETWORK_PREFERENCE_ENTERPRISE,
16705                 r -> r.run(), listener);
16706         listener.expectOnComplete();
16707         if (mDeps.isAtLeastU()) {
16708             inOrder.verify(mMockNetd).setNetworkAllowlist(configsCaptor.capture());
16709             assertContainsAll(List.of(configsCaptor.getValue()),
16710                     List.of(cellAllAllowedConfig, enterpriseAllAllowedConfig));
16711         } else {
16712             inOrder.verify(mMockNetd, never()).setNetworkAllowlist(any());
16713         }
16714 
16715         // Verify issuing with cellular set only when a network with enterprise capability
16716         // disconnects.
16717         enterpriseAgent.disconnect();
16718         waitForIdle();
16719         if (mDeps.isAtLeastU()) {
16720             inOrder.verify(mMockNetd).setNetworkAllowlist(
16721                     new NativeUidRangeConfig[]{cellAllAllowedConfig});
16722         } else {
16723             inOrder.verify(mMockNetd, never()).setNetworkAllowlist(any());
16724         }
16725     }
16726 
16727     @Test
16728     public void testProfileNetworkPreferenceBlocking_networkChanges() throws Exception {
16729         final InOrder inOrder = inOrder(mMockNetd);
16730         final UserHandle testHandle = setupEnterpriseNetwork();
16731         doReturn(asList(PRIMARY_USER_HANDLE, testHandle))
16732                 .when(mUserManager).getUserHandles(anyBoolean());
16733 
16734         // Setup profile preference which only applies to test app uid on the managed profile.
16735         ProfileNetworkPreference.Builder prefBuilder = new ProfileNetworkPreference.Builder();
16736         prefBuilder.setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE_BLOCKING)
16737                 .setIncludedUids(new int[]{testHandle.getUid(TEST_WORK_PROFILE_APP_UID)})
16738                 .setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1);
16739         final TestOnCompleteListener listener = new TestOnCompleteListener();
16740         mCm.setProfileNetworkPreferences(testHandle,
16741                 List.of(prefBuilder.build()),
16742                 r -> r.run(), listener);
16743         listener.expectOnComplete();
16744         if (mDeps.isAtLeastU()) {
16745             inOrder.verify(mMockNetd).setNetworkAllowlist(new NativeUidRangeConfig[]{});
16746         } else {
16747             inOrder.verify(mMockNetd, never()).setNetworkAllowlist(any());
16748         }
16749 
16750         // Start with 1 default network, which should be restricted since the blocking
16751         // preference is already set.
16752         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
16753         mCellAgent.connect(true);
16754 
16755         // Verify cellular network applies to the allow list.
16756         // Cell: 0~99999, 200000~TEST_APP_UID-1, TEST_APP_UID+1~299999
16757         // Enterprise: 0~99999, 200000~299999
16758         final ArraySet<UidRange> excludeAppRanges = new ArraySet<>();
16759         final UidRange profileUidRange =
16760                 UidRange.createForUser(UserHandle.of(TEST_WORK_PROFILE_USER_ID));
16761         excludeAppRanges.add(PRIMARY_UIDRANGE);
16762         excludeAppRanges.addAll(UidRangeUtils.removeRangeSetFromUidRange(
16763                 profileUidRange,
16764                 new ArraySet(new UidRange[]{
16765                         (new UidRange(TEST_WORK_PROFILE_APP_UID, TEST_WORK_PROFILE_APP_UID))})
16766         ));
16767         final UidRangeParcel[] excludeAppRangesParcel = toUidRangeStableParcels(excludeAppRanges);
16768         final NativeUidRangeConfig cellExcludeAppConfig = new NativeUidRangeConfig(
16769                 mCellAgent.getNetwork().netId,
16770                 excludeAppRangesParcel,
16771                 0 /* subPriority */);
16772         if (mDeps.isAtLeastU()) {
16773             inOrder.verify(mMockNetd).setNetworkAllowlist(
16774                     new NativeUidRangeConfig[]{cellExcludeAppConfig});
16775         } else {
16776             inOrder.verify(mMockNetd, never()).setNetworkAllowlist(any());
16777         }
16778 
16779         // Verify enterprise network is not blocked for test app.
16780         final TestNetworkAgentWrapper enterpriseAgent = makeEnterpriseNetworkAgent(
16781                 NET_ENTERPRISE_ID_1);
16782         enterpriseAgent.connect(true);
16783         ArraySet<UidRange> allowedAllUidRanges = new ArraySet<>();
16784         allowedAllUidRanges.add(PRIMARY_UIDRANGE);
16785         allowedAllUidRanges.add(profileUidRange);
16786         final UidRangeParcel[] allowAllUidRangesParcel = toUidRangeStableParcels(
16787                 allowedAllUidRanges);
16788         final NativeUidRangeConfig enterpriseAllAllowedConfig = new NativeUidRangeConfig(
16789                 enterpriseAgent.getNetwork().netId,
16790                 allowAllUidRangesParcel,
16791                 0 /* subPriority */);
16792         // Network agents are stored in an ArraySet which does not guarantee the order and
16793         // making the order of the list undeterministic. Thus, verify this in order insensitive way.
16794         final ArgumentCaptor<NativeUidRangeConfig[]> configsCaptor = ArgumentCaptor.forClass(
16795                 NativeUidRangeConfig[].class);
16796         if (mDeps.isAtLeastU()) {
16797             inOrder.verify(mMockNetd).setNetworkAllowlist(configsCaptor.capture());
16798             assertContainsAll(List.of(configsCaptor.getValue()),
16799                     List.of(enterpriseAllAllowedConfig, cellExcludeAppConfig));
16800         } else {
16801             inOrder.verify(mMockNetd, never()).setNetworkAllowlist(any());
16802         }
16803 
16804         // Verify issuing with cellular set only when enterprise network disconnects.
16805         enterpriseAgent.disconnect();
16806         waitForIdle();
16807         if (mDeps.isAtLeastU()) {
16808             inOrder.verify(mMockNetd).setNetworkAllowlist(
16809                     new NativeUidRangeConfig[]{cellExcludeAppConfig});
16810         } else {
16811             inOrder.verify(mMockNetd, never()).setNetworkAllowlist(any());
16812         }
16813 
16814         mCellAgent.disconnect();
16815         waitForIdle();
16816         if (mDeps.isAtLeastU()) {
16817             inOrder.verify(mMockNetd).setNetworkAllowlist(new NativeUidRangeConfig[]{});
16818         } else {
16819             inOrder.verify(mMockNetd, never()).setNetworkAllowlist(any());
16820         }
16821     }
16822 
16823     /**
16824      * Make sure wrong preferences for per-profile default networking are rejected.
16825      */
16826     @Test
16827     public void testProfileNetworkPrefWrongPreference() throws Exception {
16828         final UserHandle testHandle = UserHandle.of(TEST_WORK_PROFILE_USER_ID);
16829         mServiceContext.setWorkProfile(testHandle, true);
16830         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder =
16831                 new ProfileNetworkPreference.Builder();
16832         profileNetworkPreferenceBuilder.setPreference(
16833                 PROFILE_NETWORK_PREFERENCE_ENTERPRISE_BLOCKING + 1);
16834         profileNetworkPreferenceBuilder.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1);
16835         assertThrows("Should not be able to set an illegal preference",
16836                 IllegalArgumentException.class,
16837                 () -> mCm.setProfileNetworkPreferences(testHandle,
16838                         List.of(profileNetworkPreferenceBuilder.build()),
16839                         null, null));
16840     }
16841 
16842     /**
16843      * Make sure requests for per-profile default networking for a non-work profile are
16844      * rejected
16845      */
16846     @Test
16847     public void testProfileNetworkPrefWrongProfile() throws Exception {
16848         final UserHandle testHandle = UserHandle.of(TEST_WORK_PROFILE_USER_ID);
16849         mServiceContext.setWorkProfile(testHandle, false);
16850         mServiceContext.setDeviceOwner(testHandle, null);
16851         assertThrows("Should not be able to set a user pref for a non-work profile "
16852                 + "and non device owner",
16853                 IllegalArgumentException.class , () ->
16854                         mCm.setProfileNetworkPreference(testHandle,
16855                                 PROFILE_NETWORK_PREFERENCE_ENTERPRISE, null, null));
16856     }
16857 
16858     /**
16859      * Make sure requests for per-profile default networking for a device owner is
16860      * accepted on T and not accepted on S
16861      */
16862     @Test
16863     public void testProfileNetworkDeviceOwner() throws Exception {
16864         final UserHandle testHandle = UserHandle.of(TEST_WORK_PROFILE_USER_ID);
16865         mServiceContext.setWorkProfile(testHandle, false);
16866         mServiceContext.setDeviceOwner(testHandle, "deviceOwnerPackage");
16867         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder =
16868                 new ProfileNetworkPreference.Builder();
16869         profileNetworkPreferenceBuilder.setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE);
16870         profileNetworkPreferenceBuilder.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1);
16871         final TestOnCompleteListener listener = new TestOnCompleteListener();
16872         if (mDeps.isAtLeastT()) {
16873             mCm.setProfileNetworkPreferences(testHandle,
16874                     List.of(profileNetworkPreferenceBuilder.build()),
16875                     r -> r.run(), listener);
16876         } else {
16877             // S should not allow setting preference on device owner
16878             assertThrows("Should not be able to set a user pref for a non-work profile on S",
16879                     IllegalArgumentException.class , () ->
16880                             mCm.setProfileNetworkPreferences(testHandle,
16881                                     List.of(profileNetworkPreferenceBuilder.build()),
16882                                     r -> r.run(), listener));
16883         }
16884     }
16885 
16886     @Test
16887     public void testSubIdsClearedWithoutNetworkFactoryPermission() throws Exception {
16888         mServiceContext.setPermission(NETWORK_FACTORY, PERMISSION_DENIED);
16889         final NetworkCapabilities nc = new NetworkCapabilities();
16890         nc.setSubscriptionIds(Collections.singleton(Process.myUid()));
16891 
16892         final NetworkCapabilities result =
16893                 mService.networkCapabilitiesRestrictedForCallerPermissions(
16894                         nc, Process.myPid(), Process.myUid());
16895         assertTrue(result.getSubscriptionIds().isEmpty());
16896     }
16897 
16898     @Test
16899     public void testSubIdsExistWithNetworkFactoryPermission() throws Exception {
16900         mServiceContext.setPermission(NETWORK_FACTORY, PERMISSION_GRANTED);
16901 
16902         final Set<Integer> subIds = Collections.singleton(Process.myUid());
16903         final NetworkCapabilities nc = new NetworkCapabilities();
16904         nc.setSubscriptionIds(subIds);
16905 
16906         final NetworkCapabilities result =
16907                 mService.networkCapabilitiesRestrictedForCallerPermissions(
16908                         nc, Process.myPid(), Process.myUid());
16909         assertEquals(subIds, result.getSubscriptionIds());
16910     }
16911 
16912     private NetworkRequest getRequestWithSubIds() {
16913         return new NetworkRequest.Builder()
16914                 .setSubscriptionIds(Collections.singleton(Process.myUid()))
16915                 .build();
16916     }
16917 
16918     @Test
16919     public void testNetworkRequestWithSubIdsWithNetworkFactoryPermission() throws Exception {
16920         mServiceContext.setPermission(NETWORK_FACTORY, PERMISSION_GRANTED);
16921         final PendingIntent pendingIntent = PendingIntent.getBroadcast(
16922                 mContext, 0 /* requestCode */, new Intent("a"), FLAG_IMMUTABLE);
16923         final NetworkCallback networkCallback1 = new NetworkCallback();
16924         final NetworkCallback networkCallback2 = new NetworkCallback();
16925 
16926         mCm.requestNetwork(getRequestWithSubIds(), networkCallback1);
16927         mCm.requestNetwork(getRequestWithSubIds(), pendingIntent);
16928         mCm.registerNetworkCallback(getRequestWithSubIds(), networkCallback2);
16929 
16930         mCm.unregisterNetworkCallback(networkCallback1);
16931         mCm.releaseNetworkRequest(pendingIntent);
16932         mCm.unregisterNetworkCallback(networkCallback2);
16933     }
16934 
16935     @Test
16936     public void testNetworkRequestWithSubIdsWithoutNetworkFactoryPermission() throws Exception {
16937         mServiceContext.setPermission(NETWORK_FACTORY, PERMISSION_DENIED);
16938         final PendingIntent pendingIntent = PendingIntent.getBroadcast(
16939                 mContext, 0 /* requestCode */, new Intent("a"), FLAG_IMMUTABLE);
16940 
16941         final Class<SecurityException> expected = SecurityException.class;
16942         assertThrows(
16943                 expected, () -> mCm.requestNetwork(getRequestWithSubIds(), new NetworkCallback()));
16944         assertThrows(expected, () -> mCm.requestNetwork(getRequestWithSubIds(), pendingIntent));
16945         assertThrows(
16946                 expected,
16947                 () -> mCm.registerNetworkCallback(getRequestWithSubIds(), new NetworkCallback()));
16948     }
16949 
16950     @Test
16951     public void testAllowedUids() throws Exception {
16952         final int preferenceOrder =
16953                 ConnectivityService.PREFERENCE_ORDER_IRRELEVANT_BECAUSE_NOT_DEFAULT;
16954         mServiceContext.setPermission(NETWORK_FACTORY, PERMISSION_GRANTED);
16955         mServiceContext.setPermission(MANAGE_TEST_NETWORKS, PERMISSION_GRANTED);
16956         final TestNetworkCallback cb = new TestNetworkCallback();
16957         mCm.requestNetwork(new NetworkRequest.Builder()
16958                         .clearCapabilities()
16959                         .addTransportType(TRANSPORT_TEST)
16960                         .build(),
16961                 cb);
16962 
16963         final ArraySet<Integer> uids = new ArraySet<>();
16964         uids.add(200);
16965         final NetworkCapabilities nc = new NetworkCapabilities.Builder()
16966                 .addTransportType(TRANSPORT_TEST)
16967                 .removeCapability(NET_CAPABILITY_NOT_RESTRICTED)
16968                 .setAllowedUids(uids)
16969                 .build();
16970         final TestNetworkAgentWrapper agent = new TestNetworkAgentWrapper(TRANSPORT_TEST,
16971                 new LinkProperties(), nc);
16972         agent.connect(true);
16973         cb.expectAvailableThenValidatedCallbacks(agent);
16974 
16975         final InOrder inOrder = inOrder(mMockNetd);
16976         final NativeUidRangeConfig uids200Parcel = new NativeUidRangeConfig(
16977                 agent.getNetwork().getNetId(),
16978                 intToUidRangeStableParcels(uids),
16979                 preferenceOrder);
16980         if (mDeps.isAtLeastT()) {
16981             inOrder.verify(mMockNetd, times(1)).networkAddUidRangesParcel(uids200Parcel);
16982         }
16983 
16984         uids.add(300);
16985         uids.add(400);
16986         nc.setAllowedUids(uids);
16987         agent.setNetworkCapabilities(nc, true /* sendToConnectivityService */);
16988         if (mDeps.isAtLeastT()) {
16989             cb.expectCaps(agent, c -> c.getAllowedUids().equals(uids));
16990         } else {
16991             cb.assertNoCallback();
16992         }
16993 
16994         uids.remove(200);
16995         final NativeUidRangeConfig uids300400Parcel = new NativeUidRangeConfig(
16996                 agent.getNetwork().getNetId(),
16997                 intToUidRangeStableParcels(uids),
16998                 preferenceOrder);
16999         if (mDeps.isAtLeastT()) {
17000             inOrder.verify(mMockNetd, times(1)).networkAddUidRangesParcel(uids300400Parcel);
17001         }
17002 
17003         nc.setAllowedUids(uids);
17004         agent.setNetworkCapabilities(nc, true /* sendToConnectivityService */);
17005         if (mDeps.isAtLeastT()) {
17006             cb.expectCaps(agent, c -> c.getAllowedUids().equals(uids));
17007             inOrder.verify(mMockNetd, times(1)).networkRemoveUidRangesParcel(uids200Parcel);
17008         } else {
17009             cb.assertNoCallback();
17010         }
17011 
17012         uids.clear();
17013         uids.add(600);
17014         nc.setAllowedUids(uids);
17015         agent.setNetworkCapabilities(nc, true /* sendToConnectivityService */);
17016         if (mDeps.isAtLeastT()) {
17017             cb.expectCaps(agent, c -> c.getAllowedUids().equals(uids));
17018         } else {
17019             cb.assertNoCallback();
17020         }
17021         final NativeUidRangeConfig uids600Parcel = new NativeUidRangeConfig(
17022                 agent.getNetwork().getNetId(),
17023                 intToUidRangeStableParcels(uids),
17024                 preferenceOrder);
17025         if (mDeps.isAtLeastT()) {
17026             inOrder.verify(mMockNetd, times(1)).networkAddUidRangesParcel(uids600Parcel);
17027             inOrder.verify(mMockNetd, times(1)).networkRemoveUidRangesParcel(uids300400Parcel);
17028         }
17029 
17030         uids.clear();
17031         nc.setAllowedUids(uids);
17032         agent.setNetworkCapabilities(nc, true /* sendToConnectivityService */);
17033         if (mDeps.isAtLeastT()) {
17034             cb.expectCaps(agent, c -> c.getAllowedUids().isEmpty());
17035             inOrder.verify(mMockNetd, times(1)).networkRemoveUidRangesParcel(uids600Parcel);
17036         } else {
17037             cb.assertNoCallback();
17038             verify(mMockNetd, never()).networkAddUidRangesParcel(any());
17039             verify(mMockNetd, never()).networkRemoveUidRangesParcel(any());
17040         }
17041 
17042     }
17043 
17044     @Test
17045     public void testAutomotiveEthernetAllowedUids() throws Exception {
17046         mServiceContext.setPermission(NETWORK_FACTORY, PERMISSION_GRANTED);
17047         mServiceContext.setPermission(MANAGE_TEST_NETWORKS, PERMISSION_GRANTED);
17048 
17049         // Has automotive feature.
17050         validateAutomotiveEthernetAllowedUids(true);
17051 
17052         // No automotive feature.
17053         validateAutomotiveEthernetAllowedUids(false);
17054     }
17055 
17056     private void validateAutomotiveEthernetAllowedUids(final boolean hasAutomotiveFeature)
17057             throws Exception {
17058         mockHasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, hasAutomotiveFeature);
17059 
17060         // Simulate a restricted ethernet network.
17061         final NetworkCapabilities.Builder ncb = new NetworkCapabilities.Builder()
17062                 .addTransportType(TRANSPORT_ETHERNET)
17063                 .addCapability(NET_CAPABILITY_INTERNET)
17064                 .addCapability(NET_CAPABILITY_NOT_SUSPENDED)
17065                 .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
17066                 .removeCapability(NET_CAPABILITY_NOT_RESTRICTED);
17067 
17068         mEthernetAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET,
17069                 new LinkProperties(), ncb.build());
17070 
17071         final ArraySet<Integer> serviceUidSet = new ArraySet<>();
17072         serviceUidSet.add(TEST_PACKAGE_UID);
17073 
17074         final TestNetworkCallback cb = new TestNetworkCallback();
17075 
17076         mCm.requestNetwork(new NetworkRequest.Builder()
17077                 .addTransportType(TRANSPORT_ETHERNET)
17078                 .removeCapability(NET_CAPABILITY_NOT_RESTRICTED)
17079                 .build(), cb);
17080         mEthernetAgent.connect(true);
17081         cb.expectAvailableThenValidatedCallbacks(mEthernetAgent);
17082 
17083         // Cell gets to set the service UID as access UID
17084         ncb.setAllowedUids(serviceUidSet);
17085         mEthernetAgent.setNetworkCapabilities(ncb.build(), true /* sendToCS */);
17086         if (mDeps.isAtLeastT() && hasAutomotiveFeature) {
17087             cb.expectCaps(mEthernetAgent, c -> c.getAllowedUids().equals(serviceUidSet));
17088         } else {
17089             // S and no automotive feature must ignore access UIDs.
17090             cb.assertNoCallback(TEST_CALLBACK_TIMEOUT_MS);
17091         }
17092 
17093         mEthernetAgent.disconnect();
17094         cb.expect(LOST, mEthernetAgent);
17095         mCm.unregisterNetworkCallback(cb);
17096     }
17097 
17098     @Test
17099     public void testCbsAllowedUids() throws Exception {
17100         mServiceContext.setPermission(NETWORK_FACTORY, PERMISSION_GRANTED);
17101         mServiceContext.setPermission(MANAGE_TEST_NETWORKS, PERMISSION_GRANTED);
17102 
17103         // In this test TEST_PACKAGE_UID will be the UID of the carrier service UID.
17104         doReturn(true).when(mCarrierPrivilegeAuthenticator)
17105                 .hasCarrierPrivilegeForNetworkCapabilities(eq(TEST_PACKAGE_UID), any());
17106 
17107         // Simulate a restricted telephony network. The telephony factory is entitled to set
17108         // the access UID to the service package on any of its restricted networks.
17109         final NetworkCapabilities.Builder ncb = new NetworkCapabilities.Builder()
17110                 .addTransportType(TRANSPORT_CELLULAR)
17111                 .addCapability(NET_CAPABILITY_INTERNET)
17112                 .addCapability(NET_CAPABILITY_NOT_SUSPENDED)
17113                 .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
17114                 .removeCapability(NET_CAPABILITY_NOT_RESTRICTED)
17115                 .setNetworkSpecifier(new TelephonyNetworkSpecifier(1 /* subid */));
17116 
17117         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR,
17118                 new LinkProperties(), ncb.build());
17119 
17120         final ArraySet<Integer> serviceUidSet = new ArraySet<>();
17121         serviceUidSet.add(TEST_PACKAGE_UID);
17122         final ArraySet<Integer> nonServiceUidSet = new ArraySet<>();
17123         nonServiceUidSet.add(TEST_PACKAGE_UID2);
17124         final ArraySet<Integer> serviceUidSetPlus = new ArraySet<>();
17125         serviceUidSetPlus.add(TEST_PACKAGE_UID);
17126         serviceUidSetPlus.add(TEST_PACKAGE_UID2);
17127 
17128         final TestNetworkCallback cb = new TestNetworkCallback();
17129 
17130         // Cell gets to set the service UID as access UID
17131         mCm.requestNetwork(new NetworkRequest.Builder()
17132                 .addTransportType(TRANSPORT_CELLULAR)
17133                 .removeCapability(NET_CAPABILITY_NOT_RESTRICTED)
17134                 .build(), cb);
17135         mCellAgent.connect(true);
17136         cb.expectAvailableThenValidatedCallbacks(mCellAgent);
17137         ncb.setAllowedUids(serviceUidSet);
17138         mCellAgent.setNetworkCapabilities(ncb.build(), true /* sendToCS */);
17139         if (mDeps.isAtLeastT()) {
17140             cb.expectCaps(mCellAgent, c -> c.getAllowedUids().equals(serviceUidSet));
17141         } else {
17142             // S must ignore access UIDs.
17143             cb.assertNoCallback(TEST_CALLBACK_TIMEOUT_MS);
17144         }
17145 
17146         // ...but not to some other UID. Rejection sets UIDs to the empty set
17147         ncb.setAllowedUids(nonServiceUidSet);
17148         mCellAgent.setNetworkCapabilities(ncb.build(), true /* sendToCS */);
17149         if (mDeps.isAtLeastT()) {
17150             cb.expectCaps(mCellAgent, c -> c.getAllowedUids().isEmpty());
17151         } else {
17152             // S must ignore access UIDs.
17153             cb.assertNoCallback(TEST_CALLBACK_TIMEOUT_MS);
17154         }
17155 
17156         // ...and also not to multiple UIDs even including the service UID
17157         ncb.setAllowedUids(serviceUidSetPlus);
17158         mCellAgent.setNetworkCapabilities(ncb.build(), true /* sendToCS */);
17159         cb.assertNoCallback(TEST_CALLBACK_TIMEOUT_MS);
17160 
17161         mCellAgent.disconnect();
17162         cb.expect(LOST, mCellAgent);
17163         mCm.unregisterNetworkCallback(cb);
17164 
17165         // Must be unset before touching the transports, because remove and add transport types
17166         // check the specifier on the builder immediately, contradicting normal builder semantics
17167         // TODO : fix the builder
17168         ncb.setNetworkSpecifier(null);
17169         ncb.removeTransportType(TRANSPORT_CELLULAR);
17170         ncb.addTransportType(TRANSPORT_WIFI);
17171         // Wifi does not get to set access UID, even to the correct UID
17172         mCm.requestNetwork(new NetworkRequest.Builder()
17173                 .addTransportType(TRANSPORT_WIFI)
17174                 .removeCapability(NET_CAPABILITY_NOT_RESTRICTED)
17175                 .build(), cb);
17176         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, new LinkProperties(), ncb.build());
17177         mWiFiAgent.connect(true);
17178         cb.expectAvailableThenValidatedCallbacks(mWiFiAgent);
17179         ncb.setAllowedUids(serviceUidSet);
17180         mWiFiAgent.setNetworkCapabilities(ncb.build(), true /* sendToCS */);
17181         cb.assertNoCallback(TEST_CALLBACK_TIMEOUT_MS);
17182         mCm.unregisterNetworkCallback(cb);
17183     }
17184 
17185     @Test
17186     public void testSanitizedCapabilitiesFromAgentDoesNotMutateArgument()
17187             throws Exception {
17188         // This NetworkCapabilities builds an usual object to maximize the chance that this requires
17189         // sanitization, so we have a high chance to detect any changes to the original.
17190         final NetworkCapabilities unsanitized = new NetworkCapabilities.Builder()
17191                 .withoutDefaultCapabilities()
17192                 .addTransportType(TRANSPORT_WIFI)
17193                 .addCapability(NET_CAPABILITY_INTERNET)
17194                 .setOwnerUid(12345)
17195                 .setAdministratorUids(new int[] {12345, 23456, 34567})
17196                 .setLinkUpstreamBandwidthKbps(20)
17197                 .setLinkDownstreamBandwidthKbps(10)
17198                 .setNetworkSpecifier(new EthernetNetworkSpecifier("foobar"))
17199                 .setTransportInfo(new WifiInfo.Builder().setBssid("AA:AA:AA:AA:AA:AA").build())
17200                 .setSignalStrength(-75)
17201                 .setSsid("SSID1")
17202                 .setRequestorUid(98765)
17203                 .setRequestorPackageName("TestPackage")
17204                 .setSubscriptionIds(Collections.singleton(Process.myUid()))
17205                 .setUids(UidRange.toIntRanges(uidRangesForUids(
17206                         UserHandle.getUid(PRIMARY_USER, 10100),
17207                         UserHandle.getUid(SECONDARY_USER, 10101),
17208                         UserHandle.getUid(TERTIARY_USER, 10043))))
17209                 .setAllowedUids(Set.of(45678, 56789, 65432))
17210                 .setUnderlyingNetworks(List.of(new Network(99999)))
17211                 .build();
17212         final NetworkCapabilities copyOfUnsanitized = new NetworkCapabilities(unsanitized);
17213         final NetworkInfo info = new NetworkInfo(TYPE_MOBILE, TelephonyManager.NETWORK_TYPE_LTE,
17214                 ConnectivityManager.getNetworkTypeName(TYPE_MOBILE),
17215                 TelephonyManager.getNetworkTypeName(TelephonyManager.NETWORK_TYPE_LTE));
17216         final NetworkAgentInfo agent = fakeNai(unsanitized, info);
17217         agent.setDeclaredCapabilities(unsanitized);
17218         final NetworkCapabilities sanitized = agent.getDeclaredCapabilitiesSanitized(
17219                 null /* carrierPrivilegeAuthenticator */);
17220         assertEquals(copyOfUnsanitized, unsanitized);
17221         assertNotEquals(sanitized, unsanitized);
17222     }
17223 
17224     /**
17225      * Validate request counts are counted accurately on setProfileNetworkPreference on set/replace.
17226      */
17227     @Test
17228     public void testProfileNetworkPrefCountsRequestsCorrectlyOnSet() throws Exception {
17229         final UserHandle testHandle = setupEnterpriseNetwork();
17230         final TestOnCompleteListener listener = new TestOnCompleteListener();
17231         // Leave one request available so the profile preference can be set.
17232         withRequestCountersAcquired(1 /* countToLeaveAvailable */, () -> {
17233             withPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
17234                     Process.myPid(), Process.myUid(), () -> {
17235                         // Set initially to test the limit prior to having existing requests.
17236                         mCm.setProfileNetworkPreference(testHandle,
17237                                 PROFILE_NETWORK_PREFERENCE_ENTERPRISE,
17238                                 Runnable::run, listener);
17239                     });
17240             listener.expectOnComplete();
17241 
17242             // Simulate filing requests as some app on the work profile
17243             final int otherAppUid = UserHandle.getUid(TEST_WORK_PROFILE_USER_ID,
17244                     UserHandle.getAppId(Process.myUid() + 1));
17245             final int remainingCount = ConnectivityService.MAX_NETWORK_REQUESTS_PER_UID
17246                     - mService.mNetworkRequestCounter.get(otherAppUid)
17247                     - 1;
17248             final NetworkCallback[] callbacks = new NetworkCallback[remainingCount];
17249             doAsUid(otherAppUid, () -> {
17250                 for (int i = 0; i < remainingCount; ++i) {
17251                     callbacks[i] = new TestNetworkCallback();
17252                     mCm.registerDefaultNetworkCallback(callbacks[i]);
17253                 }
17254             });
17255 
17256             withPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
17257                     Process.myPid(), Process.myUid(), () -> {
17258                         // re-set so as to test the limit as part of replacing existing requests.
17259                         mCm.setProfileNetworkPreference(testHandle,
17260                                 PROFILE_NETWORK_PREFERENCE_ENTERPRISE, Runnable::run, listener);
17261                     });
17262             listener.expectOnComplete();
17263 
17264             doAsUid(otherAppUid, () -> {
17265                 for (final NetworkCallback callback : callbacks) {
17266                     mCm.unregisterNetworkCallback(callback);
17267                 }
17268             });
17269         });
17270     }
17271 
17272     /**
17273      * Validate request counts are counted accurately on setOemNetworkPreference on set/replace.
17274      */
17275     @Test
17276     public void testSetOemNetworkPreferenceCountsRequestsCorrectlyOnSet() throws Exception {
17277         mockHasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, true);
17278         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
17279                 OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY;
17280         // Leave one request available so the OEM preference can be set.
17281         withRequestCountersAcquired(1 /* countToLeaveAvailable */, () ->
17282                 withPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, () -> {
17283                     // Set initially to test the limit prior to having existing requests.
17284                     final TestOemListenerCallback listener = new TestOemListenerCallback();
17285                     mService.setOemNetworkPreference(
17286                             createDefaultOemNetworkPreferences(networkPref), listener);
17287                     listener.expectOnComplete();
17288 
17289                     // re-set so as to test the limit as part of replacing existing requests.
17290                     mService.setOemNetworkPreference(
17291                             createDefaultOemNetworkPreferences(networkPref), listener);
17292                     listener.expectOnComplete();
17293                 }));
17294     }
17295 
17296     private void withRequestCountersAcquired(final int countToLeaveAvailable,
17297             @NonNull final ThrowingRunnable r) throws Exception {
17298         final ArraySet<TestNetworkCallback> callbacks = new ArraySet<>();
17299         try {
17300             final int requestCount = mService.mSystemNetworkRequestCounter.get(Process.myUid());
17301             // The limit is hit when total requests = limit - 1, and exceeded with a crash when
17302             // total requests >= limit.
17303             final int countToFile =
17304                     MAX_NETWORK_REQUESTS_PER_SYSTEM_UID - requestCount - countToLeaveAvailable;
17305             // Need permission so registerDefaultNetworkCallback uses mSystemNetworkRequestCounter
17306             withPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, () -> {
17307                 for (int i = 1; i < countToFile; i++) {
17308                     final TestNetworkCallback cb = new TestNetworkCallback();
17309                     mCm.registerDefaultNetworkCallback(cb);
17310                     callbacks.add(cb);
17311                 }
17312                 assertEquals(MAX_NETWORK_REQUESTS_PER_SYSTEM_UID - 1 - countToLeaveAvailable,
17313                         mService.mSystemNetworkRequestCounter.get(Process.myUid()));
17314             });
17315             // Code to run to check if it triggers a max request count limit error.
17316             r.run();
17317         } finally {
17318             for (final TestNetworkCallback cb : callbacks) {
17319                 mCm.unregisterNetworkCallback(cb);
17320             }
17321         }
17322     }
17323 
17324     private void assertCreateNrisFromMobileDataPreferredUids(Set<Integer> uids) {
17325         final Set<NetworkRequestInfo> nris =
17326                 mService.createNrisFromMobileDataPreferredUids(uids);
17327         final NetworkRequestInfo nri = nris.iterator().next();
17328         // Verify that one NRI is created with multilayer requests. Because one NRI can contain
17329         // multiple uid ranges, so it only need create one NRI here.
17330         assertEquals(1, nris.size());
17331         assertTrue(nri.isMultilayerRequest());
17332         assertEquals(nri.getUids(), uidRangesForUids(uids));
17333         assertEquals(PREFERENCE_ORDER_MOBILE_DATA_PREFERERRED, nri.mPreferenceOrder);
17334     }
17335 
17336     /**
17337      * Test createNrisFromMobileDataPreferredUids returns correct NetworkRequestInfo.
17338      */
17339     @Test
17340     public void testCreateNrisFromMobileDataPreferredUids() {
17341         // Verify that empty uid set should not create any NRI for it.
17342         final Set<NetworkRequestInfo> nrisNoUid =
17343                 mService.createNrisFromMobileDataPreferredUids(new ArraySet<>());
17344         assertEquals(0, nrisNoUid.size());
17345 
17346         final int uid1 = PRIMARY_USER_HANDLE.getUid(TEST_PACKAGE_UID);
17347         final int uid2 = PRIMARY_USER_HANDLE.getUid(TEST_PACKAGE_UID2);
17348         final int uid3 = SECONDARY_USER_HANDLE.getUid(TEST_PACKAGE_UID);
17349         assertCreateNrisFromMobileDataPreferredUids(Set.of(uid1));
17350         assertCreateNrisFromMobileDataPreferredUids(Set.of(uid1, uid3));
17351         assertCreateNrisFromMobileDataPreferredUids(Set.of(uid1, uid2));
17352     }
17353 
17354     private void setAndUpdateMobileDataPreferredUids(Set<Integer> uids) {
17355         ConnectivitySettingsManager.setMobileDataPreferredUids(mServiceContext, uids);
17356         mService.updateMobileDataPreferredUids();
17357         waitForIdle();
17358     }
17359 
17360     /**
17361      * Test that MOBILE_DATA_PREFERRED_UIDS changes will send correct net id and uid ranges to netd.
17362      */
17363     @Test
17364     public void testMobileDataPreferredUidsChanged() throws Exception {
17365         final InOrder inorder = inOrder(mMockNetd);
17366         registerDefaultNetworkCallbacks();
17367         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
17368         mCellAgent.connect(true);
17369         mDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
17370         mTestPackageDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
17371 
17372         final int cellNetId = mCellAgent.getNetwork().netId;
17373         inorder.verify(mMockNetd, times(1)).networkCreate(nativeNetworkConfigPhysical(
17374                 cellNetId, INetd.PERMISSION_NONE));
17375 
17376         // Initial mobile data preferred uids status.
17377         setAndUpdateMobileDataPreferredUids(Set.of());
17378         inorder.verify(mMockNetd, never()).networkAddUidRangesParcel(any());
17379         inorder.verify(mMockNetd, never()).networkRemoveUidRangesParcel(any());
17380 
17381         // Set MOBILE_DATA_PREFERRED_UIDS setting and verify that net id and uid ranges send to netd
17382         final Set<Integer> uids1 = Set.of(PRIMARY_USER_HANDLE.getUid(TEST_PACKAGE_UID));
17383         final UidRangeParcel[] uidRanges1 = toUidRangeStableParcels(uidRangesForUids(uids1));
17384         final NativeUidRangeConfig config1 = new NativeUidRangeConfig(cellNetId, uidRanges1,
17385                 PREFERENCE_ORDER_MOBILE_DATA_PREFERERRED);
17386         setAndUpdateMobileDataPreferredUids(uids1);
17387         inorder.verify(mMockNetd, times(1)).networkAddUidRangesParcel(config1);
17388         inorder.verify(mMockNetd, never()).networkRemoveUidRangesParcel(any());
17389 
17390         // Set MOBILE_DATA_PREFERRED_UIDS setting again and verify that old rules are removed and
17391         // new rules are added.
17392         final Set<Integer> uids2 = Set.of(PRIMARY_USER_HANDLE.getUid(TEST_PACKAGE_UID),
17393                 PRIMARY_USER_HANDLE.getUid(TEST_PACKAGE_UID2),
17394                 SECONDARY_USER_HANDLE.getUid(TEST_PACKAGE_UID));
17395         final UidRangeParcel[] uidRanges2 = toUidRangeStableParcels(uidRangesForUids(uids2));
17396         final NativeUidRangeConfig config2 = new NativeUidRangeConfig(cellNetId, uidRanges2,
17397                 PREFERENCE_ORDER_MOBILE_DATA_PREFERERRED);
17398         setAndUpdateMobileDataPreferredUids(uids2);
17399         inorder.verify(mMockNetd, times(1)).networkRemoveUidRangesParcel(config1);
17400         inorder.verify(mMockNetd, times(1)).networkAddUidRangesParcel(config2);
17401 
17402         // Clear MOBILE_DATA_PREFERRED_UIDS setting again and verify that old rules are removed and
17403         // new rules are not added.
17404         setAndUpdateMobileDataPreferredUids(Set.of());
17405         inorder.verify(mMockNetd, times(1)).networkRemoveUidRangesParcel(config2);
17406         inorder.verify(mMockNetd, never()).networkAddUidRangesParcel(any());
17407     }
17408 
17409     /**
17410      * Make sure mobile data preferred uids feature behaves as expected when the mobile network
17411      * goes up and down while the uids is set. Make sure they behave as expected whether
17412      * there is a general default network or not.
17413      */
17414     @Test
17415     public void testMobileDataPreferenceForMobileNetworkUpDown() throws Exception {
17416         final InOrder inorder = inOrder(mMockNetd);
17417         // File a request for cell to ensure it doesn't go down.
17418         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
17419         final NetworkRequest cellRequest = new NetworkRequest.Builder()
17420                 .addTransportType(TRANSPORT_CELLULAR).build();
17421         mCm.requestNetwork(cellRequest, cellNetworkCallback);
17422         cellNetworkCallback.assertNoCallback();
17423 
17424         registerDefaultNetworkCallbacks();
17425         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
17426         mWiFiAgent.connect(true);
17427         mDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mWiFiAgent);
17428         mTestPackageDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mWiFiAgent);
17429         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_PACKAGE_UID));
17430 
17431         final int wifiNetId = mWiFiAgent.getNetwork().netId;
17432         inorder.verify(mMockNetd, times(1)).networkCreate(nativeNetworkConfigPhysical(
17433                 wifiNetId, INetd.PERMISSION_NONE));
17434 
17435         // Initial mobile data preferred uids status.
17436         setAndUpdateMobileDataPreferredUids(Set.of());
17437         inorder.verify(mMockNetd, never()).networkAddUidRangesParcel(any());
17438         inorder.verify(mMockNetd, never()).networkRemoveUidRangesParcel(any());
17439 
17440         // Set MOBILE_DATA_PREFERRED_UIDS setting and verify that wifi net id and uid ranges send to
17441         // netd.
17442         final Set<Integer> uids = Set.of(PRIMARY_USER_HANDLE.getUid(TEST_PACKAGE_UID));
17443         final UidRangeParcel[] uidRanges = toUidRangeStableParcels(uidRangesForUids(uids));
17444         final NativeUidRangeConfig wifiConfig = new NativeUidRangeConfig(wifiNetId, uidRanges,
17445                 PREFERENCE_ORDER_MOBILE_DATA_PREFERERRED);
17446         setAndUpdateMobileDataPreferredUids(uids);
17447         inorder.verify(mMockNetd, times(1)).networkAddUidRangesParcel(wifiConfig);
17448         inorder.verify(mMockNetd, never()).networkRemoveUidRangesParcel(any());
17449 
17450         // Cellular network connected. mTestPackageDefaultNetworkCallback should receive
17451         // callback with cellular network and net id and uid ranges should be updated to netd.
17452         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
17453         mCellAgent.connect(true);
17454         cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
17455         mDefaultNetworkCallback.assertNoCallback();
17456         mTestPackageDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
17457         assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_PACKAGE_UID));
17458 
17459         final int cellNetId = mCellAgent.getNetwork().netId;
17460         final NativeUidRangeConfig cellConfig = new NativeUidRangeConfig(cellNetId, uidRanges,
17461                 PREFERENCE_ORDER_MOBILE_DATA_PREFERERRED);
17462         inorder.verify(mMockNetd, times(1)).networkCreate(nativeNetworkConfigPhysical(
17463                 cellNetId, INetd.PERMISSION_NONE));
17464         inorder.verify(mMockNetd, times(1)).networkAddUidRangesParcel(cellConfig);
17465         inorder.verify(mMockNetd, times(1)).networkRemoveUidRangesParcel(wifiConfig);
17466 
17467         // Cellular network disconnected. mTestPackageDefaultNetworkCallback should receive
17468         // callback with wifi network from fallback request.
17469         mCellAgent.disconnect();
17470         mDefaultNetworkCallback.assertNoCallback();
17471         cellNetworkCallback.expect(LOST, mCellAgent);
17472         mTestPackageDefaultNetworkCallback.expect(LOST, mCellAgent);
17473         mTestPackageDefaultNetworkCallback.expectAvailableCallbacksValidated(mWiFiAgent);
17474         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_PACKAGE_UID));
17475         inorder.verify(mMockNetd, times(1)).networkAddUidRangesParcel(wifiConfig);
17476         inorder.verify(mMockNetd, never()).networkRemoveUidRangesParcel(any());
17477         inorder.verify(mMockNetd).networkDestroy(cellNetId);
17478 
17479         // Cellular network comes back. mTestPackageDefaultNetworkCallback should receive
17480         // callback with cellular network.
17481         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
17482         mCellAgent.connect(true);
17483         cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
17484         mDefaultNetworkCallback.assertNoCallback();
17485         mTestPackageDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
17486         assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_PACKAGE_UID));
17487 
17488         final int cellNetId2 = mCellAgent.getNetwork().netId;
17489         final NativeUidRangeConfig cellConfig2 = new NativeUidRangeConfig(cellNetId2, uidRanges,
17490                 PREFERENCE_ORDER_MOBILE_DATA_PREFERERRED);
17491         inorder.verify(mMockNetd, times(1)).networkCreate(nativeNetworkConfigPhysical(
17492                 cellNetId2, INetd.PERMISSION_NONE));
17493         inorder.verify(mMockNetd, times(1)).networkAddUidRangesParcel(cellConfig2);
17494         inorder.verify(mMockNetd, times(1)).networkRemoveUidRangesParcel(wifiConfig);
17495 
17496         // Wifi network disconnected. mTestPackageDefaultNetworkCallback should not receive
17497         // any callback.
17498         mWiFiAgent.disconnect();
17499         mDefaultNetworkCallback.expect(LOST, mWiFiAgent);
17500         mDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellAgent);
17501         mTestPackageDefaultNetworkCallback.assertNoCallback();
17502         assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_PACKAGE_UID));
17503         waitForIdle();
17504         inorder.verify(mMockNetd, never()).networkAddUidRangesParcel(any());
17505         inorder.verify(mMockNetd, never()).networkRemoveUidRangesParcel(any());
17506         inorder.verify(mMockNetd).networkDestroy(wifiNetId);
17507 
17508         mCm.unregisterNetworkCallback(cellNetworkCallback);
17509     }
17510 
17511     @Test
17512     public void testMultilayerRequestsOfSetMobileDataPreferredUids() throws Exception {
17513         // First set mobile data preferred uid to create a multi-layer requests: 1. request for
17514         // cellular, 2. track the default network for fallback.
17515         setAndUpdateMobileDataPreferredUids(
17516                 Set.of(PRIMARY_USER_HANDLE.getUid(TEST_PACKAGE_UID)));
17517 
17518         final HandlerThread handlerThread = new HandlerThread("MockFactory");
17519         handlerThread.start();
17520         final NetworkCapabilities cellFilter = new NetworkCapabilities()
17521                 .addTransportType(TRANSPORT_CELLULAR)
17522                 .addCapability(NET_CAPABILITY_INTERNET)
17523                 .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED);
17524         final MockNetworkFactory cellFactory = new MockNetworkFactory(handlerThread.getLooper(),
17525                 mServiceContext, "cellFactory", cellFilter, mCsHandlerThread);
17526         cellFactory.setScoreFilter(40);
17527 
17528         try {
17529             cellFactory.register();
17530             // Default internet request and the mobile data preferred request.
17531             cellFactory.expectRequestAdds(2);
17532             cellFactory.assertRequestCountEquals(2);
17533 
17534             mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
17535             mWiFiAgent.connect(true);
17536 
17537             // The cellFactory however is outscored, and should lose default internet request.
17538             // But it should still see mobile data preferred request.
17539             cellFactory.expectRequestRemove();
17540             cellFactory.assertRequestCountEquals(1);
17541 
17542             mWiFiAgent.disconnect();
17543             // The network satisfying the default internet request has disconnected, so the
17544             // cellFactory sees the default internet requests again.
17545             cellFactory.expectRequestAdd();
17546             cellFactory.assertRequestCountEquals(2);
17547         } finally {
17548             cellFactory.terminate();
17549             handlerThread.quitSafely();
17550             handlerThread.join();
17551         }
17552     }
17553 
17554     /**
17555      * Validate request counts are counted accurately on MOBILE_DATA_PREFERRED_UIDS change
17556      * on set/replace.
17557      */
17558     @Test
17559     public void testMobileDataPreferredUidsChangedCountsRequestsCorrectlyOnSet() throws Exception {
17560         ConnectivitySettingsManager.setMobileDataPreferredUids(mServiceContext,
17561                 Set.of(PRIMARY_USER_HANDLE.getUid(TEST_PACKAGE_UID)));
17562         // Leave one request available so MDO preference set up above can be set.
17563         withRequestCountersAcquired(1 /* countToLeaveAvailable */, () ->
17564                 withPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
17565                         Process.myPid(), Process.myUid(), () -> {
17566                             // Set initially to test the limit prior to having existing requests.
17567                             mService.updateMobileDataPreferredUids();
17568                             waitForIdle();
17569 
17570                             // re-set so as to test the limit as part of replacing existing requests
17571                             mService.updateMobileDataPreferredUids();
17572                             waitForIdle();
17573                         }));
17574     }
17575 
17576     @Test
17577     public void testAllNetworkPreferencesCanCoexist()
17578             throws Exception {
17579         final InOrder inorder = inOrder(mMockNetd);
17580         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
17581                 OEM_NETWORK_PREFERENCE_OEM_PAID;
17582         final UserHandle testHandle = setupEnterpriseNetwork();
17583 
17584         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true);
17585         final int cellNetId = mCellAgent.getNetwork().netId;
17586         inorder.verify(mMockNetd, times(1)).networkCreate(nativeNetworkConfigPhysical(
17587                 cellNetId, INetd.PERMISSION_NONE));
17588 
17589         // Set oem network preference
17590         final int[] uids1 = new int[] { PRIMARY_USER_HANDLE.getUid(TEST_PACKAGE_UID) };
17591         final UidRangeParcel[] uidRanges1 = toUidRangeStableParcels(uidRangesForUids(uids1));
17592         final NativeUidRangeConfig config1 = new NativeUidRangeConfig(cellNetId, uidRanges1,
17593                 PREFERENCE_ORDER_OEM);
17594         setupSetOemNetworkPreferenceForPreferenceTest(networkPref, uidRanges1, TEST_PACKAGE_NAME);
17595         inorder.verify(mMockNetd, times(1)).networkAddUidRangesParcel(config1);
17596         inorder.verify(mMockNetd, never()).networkRemoveUidRangesParcel(any());
17597 
17598         // Set user profile network preference
17599         final TestNetworkAgentWrapper workAgent = makeEnterpriseNetworkAgent();
17600         workAgent.connect(true);
17601 
17602         final TestOnCompleteListener listener = new TestOnCompleteListener();
17603         mCm.setProfileNetworkPreference(testHandle, PROFILE_NETWORK_PREFERENCE_ENTERPRISE,
17604                 r -> r.run(), listener);
17605         listener.expectOnComplete();
17606         final NativeUidRangeConfig config2 = new NativeUidRangeConfig(workAgent.getNetwork().netId,
17607                 uidRangeFor(testHandle), PREFERENCE_ORDER_PROFILE);
17608         inorder.verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
17609                 workAgent.getNetwork().netId, INetd.PERMISSION_SYSTEM));
17610         inorder.verify(mMockNetd, never()).networkRemoveUidRangesParcel(any());
17611         inorder.verify(mMockNetd).networkAddUidRangesParcel(config2);
17612 
17613         // Set MOBILE_DATA_PREFERRED_UIDS setting
17614         final Set<Integer> uids2 = Set.of(PRIMARY_USER_HANDLE.getUid(TEST_PACKAGE_UID2));
17615         final UidRangeParcel[] uidRanges2 = toUidRangeStableParcels(uidRangesForUids(uids2));
17616         final NativeUidRangeConfig config3 = new NativeUidRangeConfig(cellNetId, uidRanges2,
17617                 PREFERENCE_ORDER_MOBILE_DATA_PREFERERRED);
17618         setAndUpdateMobileDataPreferredUids(uids2);
17619         inorder.verify(mMockNetd, never()).networkRemoveUidRangesParcel(any());
17620         inorder.verify(mMockNetd, times(1)).networkAddUidRangesParcel(config3);
17621 
17622         // Set oem network preference again with different uid.
17623         final Set<Integer> uids3 = Set.of(PRIMARY_USER_HANDLE.getUid(TEST_PACKAGE_UID3));
17624         final UidRangeParcel[] uidRanges3 = toUidRangeStableParcels(uidRangesForUids(uids3));
17625         final NativeUidRangeConfig config4 = new NativeUidRangeConfig(cellNetId, uidRanges3,
17626                 PREFERENCE_ORDER_OEM);
17627         setupSetOemNetworkPreferenceForPreferenceTest(networkPref, uidRanges3, "com.android.test");
17628         inorder.verify(mMockNetd, times(1)).networkRemoveUidRangesParcel(config1);
17629         inorder.verify(mMockNetd, times(1)).networkAddUidRangesParcel(config4);
17630 
17631         // Remove user profile network preference
17632         mCm.setProfileNetworkPreference(testHandle, PROFILE_NETWORK_PREFERENCE_DEFAULT,
17633                 r -> r.run(), listener);
17634         listener.expectOnComplete();
17635         inorder.verify(mMockNetd, times(1)).networkRemoveUidRangesParcel(config2);
17636         inorder.verify(mMockNetd, never()).networkAddUidRangesParcel(any());
17637 
17638         // Set MOBILE_DATA_PREFERRED_UIDS setting again with same uid as oem network preference.
17639         final NativeUidRangeConfig config6 = new NativeUidRangeConfig(cellNetId, uidRanges3,
17640                 PREFERENCE_ORDER_MOBILE_DATA_PREFERERRED);
17641         setAndUpdateMobileDataPreferredUids(uids3);
17642         inorder.verify(mMockNetd, times(1)).networkRemoveUidRangesParcel(config3);
17643         inorder.verify(mMockNetd, times(1)).networkAddUidRangesParcel(config6);
17644     }
17645 
17646     @Test
17647     public void testNetworkCallbackAndActiveNetworkForUid_AllNetworkPreferencesEnabled()
17648             throws Exception {
17649         // File a request for cell to ensure it doesn't go down.
17650         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
17651         final NetworkRequest cellRequest = new NetworkRequest.Builder()
17652                 .addTransportType(TRANSPORT_CELLULAR).build();
17653         mCm.requestNetwork(cellRequest, cellNetworkCallback);
17654         cellNetworkCallback.assertNoCallback();
17655 
17656         // Register callbacks and have wifi network as default network.
17657         registerDefaultNetworkCallbacks();
17658         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
17659         mWiFiAgent.connect(true);
17660         mDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mWiFiAgent);
17661         mProfileDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mWiFiAgent);
17662         mTestPackageDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mWiFiAgent);
17663         assertEquals(mWiFiAgent.getNetwork(),
17664                 mCm.getActiveNetworkForUid(TEST_WORK_PROFILE_APP_UID));
17665         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_PACKAGE_UID));
17666 
17667         // Set MOBILE_DATA_PREFERRED_UIDS setting with TEST_WORK_PROFILE_APP_UID and
17668         // TEST_PACKAGE_UID. Both mProfileDefaultNetworkCallback and
17669         // mTestPackageDefaultNetworkCallback should receive callback with cell network.
17670         setAndUpdateMobileDataPreferredUids(Set.of(TEST_WORK_PROFILE_APP_UID, TEST_PACKAGE_UID));
17671         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
17672         mCellAgent.connect(true);
17673         cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
17674         mDefaultNetworkCallback.assertNoCallback();
17675         mProfileDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
17676         mTestPackageDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
17677         assertEquals(mCellAgent.getNetwork(),
17678                 mCm.getActiveNetworkForUid(TEST_WORK_PROFILE_APP_UID));
17679         assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_PACKAGE_UID));
17680 
17681         // Set user profile network preference with test profile. mProfileDefaultNetworkCallback
17682         // should receive callback with higher priority network preference (enterprise network).
17683         // The others should have no callbacks.
17684         final UserHandle testHandle = setupEnterpriseNetwork();
17685         final TestNetworkAgentWrapper workAgent = makeEnterpriseNetworkAgent();
17686         workAgent.connect(true);
17687         final TestOnCompleteListener listener = new TestOnCompleteListener();
17688         mCm.setProfileNetworkPreference(testHandle, PROFILE_NETWORK_PREFERENCE_ENTERPRISE,
17689                 r -> r.run(), listener);
17690         listener.expectOnComplete();
17691         assertNoCallbacks(mDefaultNetworkCallback, mTestPackageDefaultNetworkCallback);
17692         mProfileDefaultNetworkCallback.expectAvailableCallbacksValidated(workAgent);
17693         assertEquals(workAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_WORK_PROFILE_APP_UID));
17694         assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_PACKAGE_UID));
17695 
17696         // Set oem network preference with TEST_PACKAGE_UID. mTestPackageDefaultNetworkCallback
17697         // should receive callback with higher priority network preference (current default network)
17698         // and the others should have no callbacks.
17699         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
17700                 OEM_NETWORK_PREFERENCE_OEM_PAID;
17701         final int[] uids1 = new int[] { TEST_PACKAGE_UID };
17702         final UidRangeParcel[] uidRanges1 = toUidRangeStableParcels(uidRangesForUids(uids1));
17703         setupSetOemNetworkPreferenceForPreferenceTest(networkPref, uidRanges1, TEST_PACKAGE_NAME);
17704         assertNoCallbacks(mDefaultNetworkCallback, mProfileDefaultNetworkCallback);
17705         mTestPackageDefaultNetworkCallback.expectAvailableCallbacksValidated(mWiFiAgent);
17706         assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_PACKAGE_UID));
17707         assertEquals(workAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_WORK_PROFILE_APP_UID));
17708 
17709         // Set oem network preference with TEST_WORK_PROFILE_APP_UID. Both
17710         // mProfileDefaultNetworkCallback and mTestPackageDefaultNetworkCallback should receive
17711         // callback.
17712         final int[] uids2 = new int[] { TEST_WORK_PROFILE_APP_UID };
17713         final UidRangeParcel[] uidRanges2 = toUidRangeStableParcels(uidRangesForUids(uids2));
17714         doReturn(Arrays.asList(testHandle)).when(mUserManager).getUserHandles(anyBoolean());
17715         setupSetOemNetworkPreferenceForPreferenceTest(
17716                 networkPref, uidRanges2, "com.android.test", testHandle);
17717         mDefaultNetworkCallback.assertNoCallback();
17718         mProfileDefaultNetworkCallback.expectAvailableCallbacksValidated(mWiFiAgent);
17719         mTestPackageDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellAgent);
17720         assertEquals(mWiFiAgent.getNetwork(),
17721                 mCm.getActiveNetworkForUid(TEST_WORK_PROFILE_APP_UID));
17722         assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_PACKAGE_UID));
17723 
17724         // Remove oem network preference, mProfileDefaultNetworkCallback should receive callback
17725         // with current highest priority network preference (enterprise network) and the others
17726         // should have no callbacks.
17727         final TestOemListenerCallback oemPrefListener = new TestOemListenerCallback();
17728         mService.setOemNetworkPreference(
17729                 new OemNetworkPreferences.Builder().build(), oemPrefListener);
17730         oemPrefListener.expectOnComplete();
17731         assertNoCallbacks(mDefaultNetworkCallback, mTestPackageDefaultNetworkCallback);
17732         mProfileDefaultNetworkCallback.expectAvailableCallbacksValidated(workAgent);
17733         assertEquals(workAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_WORK_PROFILE_APP_UID));
17734         assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_PACKAGE_UID));
17735 
17736         // Remove user profile network preference.
17737         mCm.setProfileNetworkPreference(testHandle, PROFILE_NETWORK_PREFERENCE_DEFAULT,
17738                 r -> r.run(), listener);
17739         listener.expectOnComplete();
17740         assertNoCallbacks(mDefaultNetworkCallback, mTestPackageDefaultNetworkCallback);
17741         mProfileDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellAgent);
17742         assertEquals(mCellAgent.getNetwork(),
17743                 mCm.getActiveNetworkForUid(TEST_WORK_PROFILE_APP_UID));
17744         assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_PACKAGE_UID));
17745 
17746         // Disconnect wifi
17747         mWiFiAgent.disconnect();
17748         assertNoCallbacks(mProfileDefaultNetworkCallback, mTestPackageDefaultNetworkCallback);
17749         mDefaultNetworkCallback.expect(LOST, mWiFiAgent);
17750         mDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellAgent);
17751     }
17752 
17753     @Test
17754     public void testRequestRouteToHostAddress_PackageDoesNotBelongToCaller() {
17755         assertThrows(SecurityException.class, () -> mService.requestRouteToHostAddress(
17756                 ConnectivityManager.TYPE_NONE, null /* hostAddress */, "com.not.package.owner",
17757                 null /* callingAttributionTag */));
17758     }
17759 
17760     @Test @IgnoreUpTo(SC_V2)
17761     public void testUpdateRateLimit_EnableDisable() throws Exception {
17762         final LinkProperties wifiLp = new LinkProperties();
17763         wifiLp.setInterfaceName(WIFI_IFNAME);
17764         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp);
17765         mWiFiAgent.connect(true);
17766 
17767         final LinkProperties cellLp = new LinkProperties();
17768         cellLp.setInterfaceName(MOBILE_IFNAME);
17769         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
17770         mCellAgent.connect(false);
17771 
17772         waitForIdle();
17773 
17774         final ArrayTrackRecord<Pair<String, Long>>.ReadHead readHeadWifi =
17775                 mDeps.mRateLimitHistory.newReadHead();
17776         final ArrayTrackRecord<Pair<String, Long>>.ReadHead readHeadCell =
17777                 mDeps.mRateLimitHistory.newReadHead();
17778 
17779         // set rate limit to 8MBit/s => 1MB/s
17780         final int rateLimitInBytesPerSec = 1 * 1000 * 1000;
17781         setIngressRateLimit(rateLimitInBytesPerSec);
17782 
17783         assertNotNull(readHeadWifi.poll(TIMEOUT_MS,
17784                 it -> it.first == wifiLp.getInterfaceName()
17785                         && it.second == rateLimitInBytesPerSec));
17786         assertNotNull(readHeadCell.poll(TIMEOUT_MS,
17787                 it -> it.first == cellLp.getInterfaceName()
17788                         && it.second == rateLimitInBytesPerSec));
17789 
17790         // disable rate limiting
17791         setIngressRateLimit(-1);
17792 
17793         assertNotNull(readHeadWifi.poll(TIMEOUT_MS,
17794                 it -> it.first == wifiLp.getInterfaceName() && it.second == -1));
17795         assertNotNull(readHeadCell.poll(TIMEOUT_MS,
17796                 it -> it.first == cellLp.getInterfaceName() && it.second == -1));
17797     }
17798 
17799     @Test @IgnoreUpTo(SC_V2)
17800     public void testUpdateRateLimit_WhenNewNetworkIsAdded() throws Exception {
17801         final LinkProperties wifiLp = new LinkProperties();
17802         wifiLp.setInterfaceName(WIFI_IFNAME);
17803         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp);
17804         mWiFiAgent.connect(true);
17805 
17806         waitForIdle();
17807 
17808         final ArrayTrackRecord<Pair<String, Long>>.ReadHead readHead =
17809                 mDeps.mRateLimitHistory.newReadHead();
17810 
17811         // set rate limit to 8MBit/s => 1MB/s
17812         final int rateLimitInBytesPerSec = 1 * 1000 * 1000;
17813         setIngressRateLimit(rateLimitInBytesPerSec);
17814         assertNotNull(readHead.poll(TIMEOUT_MS, it -> it.first == wifiLp.getInterfaceName()
17815                 && it.second == rateLimitInBytesPerSec));
17816 
17817         final LinkProperties cellLp = new LinkProperties();
17818         cellLp.setInterfaceName(MOBILE_IFNAME);
17819         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
17820         mCellAgent.connect(false);
17821         assertNotNull(readHead.poll(TIMEOUT_MS, it -> it.first == cellLp.getInterfaceName()
17822                 && it.second == rateLimitInBytesPerSec));
17823     }
17824 
17825     @Test @IgnoreUpTo(SC_V2)
17826     public void testUpdateRateLimit_OnlyAffectsInternetCapableNetworks() throws Exception {
17827         final LinkProperties wifiLp = new LinkProperties();
17828         wifiLp.setInterfaceName(WIFI_IFNAME);
17829 
17830         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp);
17831         mWiFiAgent.connectWithoutInternet();
17832 
17833         waitForIdle();
17834 
17835         setIngressRateLimit(1000);
17836         setIngressRateLimit(-1);
17837 
17838         final ArrayTrackRecord<Pair<String, Long>>.ReadHead readHeadWifi =
17839                 mDeps.mRateLimitHistory.newReadHead();
17840         assertNull(readHeadWifi.poll(TIMEOUT_MS, it -> it.first == wifiLp.getInterfaceName()));
17841     }
17842 
17843     @Test @IgnoreUpTo(SC_V2)
17844     public void testUpdateRateLimit_DisconnectingResetsRateLimit()
17845             throws Exception {
17846         // Steps:
17847         // - connect network
17848         // - set rate limit
17849         // - disconnect network (interface still exists)
17850         // - disable rate limit
17851         // - connect network
17852         // - ensure network interface is not rate limited
17853         final LinkProperties wifiLp = new LinkProperties();
17854         wifiLp.setInterfaceName(WIFI_IFNAME);
17855         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp);
17856         mWiFiAgent.connect(true);
17857         waitForIdle();
17858 
17859         final ArrayTrackRecord<Pair<String, Long>>.ReadHead readHeadWifi =
17860                 mDeps.mRateLimitHistory.newReadHead();
17861 
17862         int rateLimitInBytesPerSec = 1000;
17863         setIngressRateLimit(rateLimitInBytesPerSec);
17864         assertNotNull(readHeadWifi.poll(TIMEOUT_MS,
17865                 it -> it.first == wifiLp.getInterfaceName()
17866                         && it.second == rateLimitInBytesPerSec));
17867 
17868         mWiFiAgent.disconnect();
17869         assertNotNull(readHeadWifi.poll(TIMEOUT_MS,
17870                 it -> it.first == wifiLp.getInterfaceName() && it.second == -1));
17871 
17872         setIngressRateLimit(-1);
17873 
17874         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp);
17875         mWiFiAgent.connect(true);
17876         assertNull(readHeadWifi.poll(TIMEOUT_MS, it -> it.first == wifiLp.getInterfaceName()));
17877     }
17878 
17879     @Test @IgnoreUpTo(SC_V2)
17880     public void testUpdateRateLimit_UpdateExistingRateLimit() throws Exception {
17881         final LinkProperties wifiLp = new LinkProperties();
17882         wifiLp.setInterfaceName(WIFI_IFNAME);
17883         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp);
17884         mWiFiAgent.connect(true);
17885         waitForIdle();
17886 
17887         final ArrayTrackRecord<Pair<String, Long>>.ReadHead readHeadWifi =
17888                 mDeps.mRateLimitHistory.newReadHead();
17889 
17890         // update an active ingress rate limit
17891         setIngressRateLimit(1000);
17892         setIngressRateLimit(2000);
17893 
17894         // verify the following order of execution:
17895         // 1. ingress rate limit set to 1000.
17896         // 2. ingress rate limit disabled (triggered by updating active rate limit).
17897         // 3. ingress rate limit set to 2000.
17898         assertNotNull(readHeadWifi.poll(TIMEOUT_MS,
17899                 it -> it.first == wifiLp.getInterfaceName()
17900                         && it.second == 1000));
17901         assertNotNull(readHeadWifi.poll(TIMEOUT_MS,
17902                 it -> it.first == wifiLp.getInterfaceName()
17903                         && it.second == -1));
17904         assertNotNull(readHeadWifi.poll(TIMEOUT_MS,
17905                 it -> it.first == wifiLp.getInterfaceName()
17906                         && it.second == 2000));
17907     }
17908 
17909     @Test @IgnoreAfter(SC_V2)
17910     public void testUpdateRateLimit_DoesNothingBeforeT() throws Exception {
17911         final LinkProperties wifiLp = new LinkProperties();
17912         wifiLp.setInterfaceName(WIFI_IFNAME);
17913         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp);
17914         mWiFiAgent.connect(true);
17915         waitForIdle();
17916 
17917         final ArrayTrackRecord<Pair<String, Long>>.ReadHead readHead =
17918                 mDeps.mRateLimitHistory.newReadHead();
17919 
17920         setIngressRateLimit(1000);
17921         waitForIdle();
17922 
17923         assertNull(readHead.poll(TEST_CALLBACK_TIMEOUT_MS, it -> true));
17924     }
17925 
17926     @Test
17927     public void testOfferNetwork_ChecksArgumentsOutsideOfHandler() throws Exception {
17928         final TestableNetworkOfferCallback callback = new TestableNetworkOfferCallback(
17929                 TIMEOUT_MS /* timeout */, TEST_CALLBACK_TIMEOUT_MS /* noCallbackTimeout */);
17930         final NetworkProvider testProvider = new NetworkProvider(mServiceContext,
17931                 mCsHandlerThread.getLooper(), "Test provider");
17932         final NetworkCapabilities caps = new NetworkCapabilities.Builder()
17933                 .addCapability(NET_CAPABILITY_INTERNET)
17934                 .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
17935                 .build();
17936 
17937         final NetworkScore score = new NetworkScore.Builder().build();
17938         testProvider.registerNetworkOffer(score, caps, r -> r.run(), callback);
17939         testProvider.unregisterNetworkOffer(callback);
17940 
17941         assertThrows(NullPointerException.class,
17942                 () -> mService.offerNetwork(100, score, caps, null));
17943         assertThrows(NullPointerException.class, () -> mService.unofferNetwork(null));
17944     }
17945 
17946     public void doTestIgnoreValidationAfterRoam(int resValue, final boolean enabled)
17947             throws Exception {
17948         doReturn(resValue).when(mResources)
17949                 .getInteger(R.integer.config_validationFailureAfterRoamIgnoreTimeMillis);
17950 
17951         final String bssid1 = "AA:AA:AA:AA:AA:AA";
17952         final String bssid2 = "BB:BB:BB:BB:BB:BB";
17953         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
17954         mCellAgent.connect(true);
17955         NetworkCapabilities wifiNc1 = new NetworkCapabilities()
17956                 .addCapability(NET_CAPABILITY_INTERNET)
17957                 .addCapability(NET_CAPABILITY_NOT_VPN)
17958                 .addCapability(NET_CAPABILITY_NOT_RESTRICTED)
17959                 .addCapability(NET_CAPABILITY_TRUSTED)
17960                 .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
17961                 .addTransportType(TRANSPORT_WIFI)
17962                 .setTransportInfo(new WifiInfo.Builder().setBssid(bssid1).build());
17963         NetworkCapabilities wifiNc2 = new NetworkCapabilities(wifiNc1)
17964                 .setTransportInfo(new WifiInfo.Builder().setBssid(bssid2).build());
17965         final LinkProperties wifiLp = new LinkProperties();
17966         wifiLp.setInterfaceName(WIFI_IFNAME);
17967         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp, wifiNc1);
17968         mWiFiAgent.connect(true);
17969 
17970         // The default network will be switching to Wi-Fi Network.
17971         final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
17972         final NetworkRequest wifiRequest = new NetworkRequest.Builder()
17973                 .addTransportType(TRANSPORT_WIFI).build();
17974         mCm.requestNetwork(wifiRequest, wifiNetworkCallback);
17975         wifiNetworkCallback.expectAvailableCallbacksValidated(mWiFiAgent);
17976         registerDefaultNetworkCallbacks();
17977         mDefaultNetworkCallback.expectAvailableCallbacksValidated(mWiFiAgent);
17978 
17979         // There is a bug in the current code where ignoring validation after roam will not
17980         // correctly change the default network if the result if the validation is partial or
17981         // captive portal. TODO : fix the bug and reinstate this code.
17982         if (false) {
17983             // Wi-Fi roaming from wifiNc1 to wifiNc2 but the network is now behind a captive portal.
17984             mWiFiAgent.setNetworkCapabilities(wifiNc2, true /* sendToConnectivityService */);
17985             // The only thing changed in this CAPS is the BSSID, which can't be tested for in this
17986             // test because it's redacted.
17987             wifiNetworkCallback.expectCaps(mWiFiAgent);
17988             mDefaultNetworkCallback.expectCaps(mWiFiAgent);
17989             mWiFiAgent.setNetworkPortal(TEST_REDIRECT_URL, false /* privateDnsProbeSent */);
17990             mCm.reportNetworkConnectivity(mWiFiAgent.getNetwork(), false);
17991             // Wi-Fi is now detected to have a portal : cell should become the default network.
17992             mDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellAgent);
17993             wifiNetworkCallback.expectCaps(mWiFiAgent,
17994                     c -> !c.hasCapability(NET_CAPABILITY_VALIDATED));
17995             wifiNetworkCallback.expectCaps(mWiFiAgent,
17996                     c -> c.hasCapability(NET_CAPABILITY_CAPTIVE_PORTAL));
17997 
17998             // Wi-Fi becomes valid again. The default network goes back to Wi-Fi.
17999             mWiFiAgent.setNetworkValid(false /* privateDnsProbeSent */);
18000             mCm.reportNetworkConnectivity(mWiFiAgent.getNetwork(), true);
18001             mDefaultNetworkCallback.expectAvailableCallbacksValidated(mWiFiAgent);
18002             wifiNetworkCallback.expectCaps(mWiFiAgent,
18003                     c -> !c.hasCapability(NET_CAPABILITY_CAPTIVE_PORTAL));
18004 
18005             // Wi-Fi roaming from wifiNc2 to wifiNc1, and the network now has partial connectivity.
18006             mWiFiAgent.setNetworkCapabilities(wifiNc1, true);
18007             wifiNetworkCallback.expectCaps(mWiFiAgent);
18008             mDefaultNetworkCallback.expectCaps(mWiFiAgent);
18009             mWiFiAgent.setNetworkPartial();
18010             mCm.reportNetworkConnectivity(mWiFiAgent.getNetwork(), false);
18011             // Wi-Fi now only offers partial connectivity, so in the absence of accepting partial
18012             // connectivity explicitly for this network, it loses default status to cell.
18013             mDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellAgent);
18014             wifiNetworkCallback.expectCaps(mWiFiAgent,
18015                     c -> c.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY));
18016 
18017             // Wi-Fi becomes valid again. The default network goes back to Wi-Fi.
18018             mWiFiAgent.setNetworkValid(false /* privateDnsProbeSent */);
18019             mCm.reportNetworkConnectivity(mWiFiAgent.getNetwork(), true);
18020             mDefaultNetworkCallback.expectAvailableCallbacksValidated(mWiFiAgent);
18021             wifiNetworkCallback.expectCaps(mWiFiAgent,
18022                     c -> !c.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY));
18023         }
18024         mCm.unregisterNetworkCallback(wifiNetworkCallback);
18025 
18026         // Wi-Fi roams from wifiNc1 to wifiNc2, and now becomes really invalid. If validation
18027         // failures after roam are not ignored, this will cause cell to become the default network.
18028         // If they are ignored, this will not cause a switch until later.
18029         mWiFiAgent.setNetworkCapabilities(wifiNc2, true);
18030         mDefaultNetworkCallback.expectCaps(mWiFiAgent);
18031         mWiFiAgent.setNetworkInvalid(false /* invalidBecauseOfPrivateDns */);
18032         mCm.reportNetworkConnectivity(mWiFiAgent.getNetwork(), false);
18033 
18034         if (enabled) {
18035             // Network validation failed, but the result will be ignored.
18036             assertTrue(mCm.getNetworkCapabilities(mWiFiAgent.getNetwork()).hasCapability(
18037                     NET_CAPABILITY_VALIDATED));
18038             mWiFiAgent.setNetworkValid(false);
18039 
18040             // Behavior of after config_validationFailureAfterRoamIgnoreTimeMillis
18041             ConditionVariable waitForValidationBlock = new ConditionVariable();
18042             doReturn(50).when(mResources)
18043                     .getInteger(R.integer.config_validationFailureAfterRoamIgnoreTimeMillis);
18044             // Wi-Fi roaming from wifiNc2 to wifiNc1.
18045             mWiFiAgent.setNetworkCapabilities(wifiNc1, true);
18046             mWiFiAgent.setNetworkInvalid(false);
18047             waitForValidationBlock.block(150);
18048             mCm.reportNetworkConnectivity(mWiFiAgent.getNetwork(), false);
18049             mDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellAgent);
18050         } else {
18051             mDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellAgent);
18052         }
18053 
18054         // Wi-Fi is still connected and would become the default network if cell were to
18055         // disconnect. This assertion ensures that the switch to cellular was not caused by
18056         // Wi-Fi disconnecting (e.g., because the capability change to wifiNc2 caused it
18057         // to stop satisfying the default request).
18058         mCellAgent.disconnect();
18059         mDefaultNetworkCallback.expect(LOST, mCellAgent);
18060         mDefaultNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
18061 
18062     }
18063 
18064     @Test
18065     public void testIgnoreValidationAfterRoamDisabled() throws Exception {
18066         doTestIgnoreValidationAfterRoam(-1, false /* enabled */);
18067     }
18068 
18069     @Test
18070     public void testIgnoreValidationAfterRoamEnabled() throws Exception {
18071         final boolean enabled = !mDeps.isAtLeastT();
18072         doTestIgnoreValidationAfterRoam(5_000, enabled);
18073     }
18074 
18075     @Test
18076     public void testShouldIgnoreValidationFailureAfterRoam() {
18077         // Always disabled on T+.
18078         assumeFalse(mDeps.isAtLeastT());
18079 
18080         NetworkAgentInfo nai = fakeWifiNai(new NetworkCapabilities());
18081 
18082         // Enabled, but never roamed.
18083         doReturn(5_000).when(mResources)
18084                 .getInteger(R.integer.config_validationFailureAfterRoamIgnoreTimeMillis);
18085         assertEquals(0, nai.lastRoamTime);
18086         assertFalse(mService.shouldIgnoreValidationFailureAfterRoam(nai));
18087 
18088         // Roamed recently.
18089         nai.lastRoamTime = SystemClock.elapsedRealtime() - 500 /* ms */;
18090         assertTrue(mService.shouldIgnoreValidationFailureAfterRoam(nai));
18091 
18092         // Disabled due to invalid setting (maximum is 10 seconds).
18093         doReturn(15_000).when(mResources)
18094                 .getInteger(R.integer.config_validationFailureAfterRoamIgnoreTimeMillis);
18095         assertFalse(mService.shouldIgnoreValidationFailureAfterRoam(nai));
18096 
18097         // Disabled.
18098         doReturn(-1).when(mResources)
18099                 .getInteger(R.integer.config_validationFailureAfterRoamIgnoreTimeMillis);
18100         assertFalse(mService.shouldIgnoreValidationFailureAfterRoam(nai));
18101     }
18102 
18103 
18104     @Test
18105     public void testLegacyTetheringApiGuardWithProperPermission() throws Exception {
18106         final String testIface = "test0";
18107         mServiceContext.setPermission(ACCESS_NETWORK_STATE, PERMISSION_DENIED);
18108         assertThrows(SecurityException.class, () -> mService.getLastTetherError(testIface));
18109         assertThrows(SecurityException.class, () -> mService.getTetherableIfaces());
18110         assertThrows(SecurityException.class, () -> mService.getTetheredIfaces());
18111         assertThrows(SecurityException.class, () -> mService.getTetheringErroredIfaces());
18112         assertThrows(SecurityException.class, () -> mService.getTetherableUsbRegexs());
18113         assertThrows(SecurityException.class, () -> mService.getTetherableWifiRegexs());
18114 
18115         withPermission(ACCESS_NETWORK_STATE, () -> {
18116             mService.getLastTetherError(testIface);
18117             verify(mTetheringManager).getLastTetherError(testIface);
18118 
18119             mService.getTetherableIfaces();
18120             verify(mTetheringManager).getTetherableIfaces();
18121 
18122             mService.getTetheredIfaces();
18123             verify(mTetheringManager).getTetheredIfaces();
18124 
18125             mService.getTetheringErroredIfaces();
18126             verify(mTetheringManager).getTetheringErroredIfaces();
18127 
18128             mService.getTetherableUsbRegexs();
18129             verify(mTetheringManager).getTetherableUsbRegexs();
18130 
18131             mService.getTetherableWifiRegexs();
18132             verify(mTetheringManager).getTetherableWifiRegexs();
18133         });
18134     }
18135 
18136     private void verifyMtuSetOnWifiInterface(int mtu) throws Exception {
18137         verify(mMockNetd, times(1)).interfaceSetMtu(WIFI_IFNAME, mtu);
18138     }
18139 
18140     private void verifyMtuNeverSetOnWifiInterface() throws Exception {
18141         verify(mMockNetd, never()).interfaceSetMtu(eq(WIFI_IFNAME), anyInt());
18142     }
18143 
18144     private void verifyMtuSetOnWifiInterfaceOnlyUpToT(int mtu) throws Exception {
18145         if (!mService.shouldCreateNetworksImmediately()) {
18146             verify(mMockNetd, times(1)).interfaceSetMtu(WIFI_IFNAME, mtu);
18147         } else {
18148             verify(mMockNetd, never()).interfaceSetMtu(eq(WIFI_IFNAME), anyInt());
18149         }
18150     }
18151 
18152     private void verifyMtuSetOnWifiInterfaceOnlyStartingFromU(int mtu) throws Exception {
18153         if (mService.shouldCreateNetworksImmediately()) {
18154             verify(mMockNetd, times(1)).interfaceSetMtu(WIFI_IFNAME, mtu);
18155         } else {
18156             verify(mMockNetd, never()).interfaceSetMtu(eq(WIFI_IFNAME), anyInt());
18157         }
18158     }
18159 
18160     @Test
18161     public void testSendLinkPropertiesSetInterfaceMtuBeforeConnect() throws Exception {
18162         final int mtu = 1281;
18163         LinkProperties lp = new LinkProperties();
18164         lp.setInterfaceName(WIFI_IFNAME);
18165         lp.setMtu(mtu);
18166 
18167         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
18168         mWiFiAgent.sendLinkProperties(lp);
18169         waitForIdle();
18170         verifyMtuSetOnWifiInterface(mtu);
18171         reset(mMockNetd);
18172 
18173         mWiFiAgent.connect(false /* validated */);
18174         // Before U, the MTU is always (re-)applied when the network connects.
18175         verifyMtuSetOnWifiInterfaceOnlyUpToT(mtu);
18176     }
18177 
18178     @Test
18179     public void testSendLinkPropertiesUpdateInterfaceMtuBeforeConnect() throws Exception {
18180         final int mtu = 1327;
18181         LinkProperties lp = new LinkProperties();
18182         lp.setInterfaceName(WIFI_IFNAME);
18183         lp.setMtu(mtu);
18184 
18185         // Registering an agent with an MTU only sets the MTU on U+.
18186         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, lp);
18187         waitForIdle();
18188         verifyMtuSetOnWifiInterfaceOnlyStartingFromU(mtu);
18189         reset(mMockNetd);
18190 
18191         // Future updates with the same MTU don't set the MTU even on T when it's not set initially.
18192         mWiFiAgent.sendLinkProperties(lp);
18193         waitForIdle();
18194         verifyMtuNeverSetOnWifiInterface();
18195 
18196         // Updating with a different MTU does work.
18197         lp.setMtu(mtu + 1);
18198         mWiFiAgent.sendLinkProperties(lp);
18199         waitForIdle();
18200         verifyMtuSetOnWifiInterface(mtu + 1);
18201         reset(mMockNetd);
18202 
18203         mWiFiAgent.connect(false /* validated */);
18204         // Before U, the MTU is always (re-)applied when the network connects.
18205         verifyMtuSetOnWifiInterfaceOnlyUpToT(mtu + 1);
18206     }
18207 
18208     @Test
18209     public void testSendLinkPropertiesUpdateInterfaceMtuAfterConnect() throws Exception {
18210         final int mtu = 1327;
18211         LinkProperties lp = new LinkProperties();
18212         lp.setInterfaceName(WIFI_IFNAME);
18213         lp.setMtu(mtu);
18214 
18215         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
18216         mWiFiAgent.connect(false /* validated */);
18217         verifyMtuNeverSetOnWifiInterface();
18218 
18219         mWiFiAgent.sendLinkProperties(lp);
18220         waitForIdle();
18221         // The MTU is always (re-)applied when the network connects.
18222         verifyMtuSetOnWifiInterface(mtu);
18223     }
18224 
18225     @Test
18226     public void testSendLinkPropertiesSetInterfaceMtu_DifferentMtu() throws Exception {
18227         final int mtu = 1328, mtu2 = 1500;
18228         LinkProperties lp = new LinkProperties();
18229         lp.setInterfaceName(WIFI_IFNAME);
18230         lp.setMtu(mtu);
18231 
18232         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, lp);
18233         mWiFiAgent.connect(false /* validated */);
18234         verifyMtuSetOnWifiInterface(mtu);
18235         reset(mMockNetd);
18236 
18237         LinkProperties lp2 = new LinkProperties(lp);
18238         lp2.setMtu(mtu2);
18239         mWiFiAgent.sendLinkProperties(lp2);
18240         waitForIdle();
18241         verifyMtuSetOnWifiInterface(mtu2);
18242     }
18243 
18244     @Test
18245     public void testSendLinkPropertiesSetInterfaceMtu_IdenticalMtuAndIface() throws Exception {
18246         final int mtu = 1329;
18247         LinkProperties lp = new LinkProperties();
18248         lp.setInterfaceName(WIFI_IFNAME);
18249         lp.setMtu(mtu);
18250 
18251         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, lp);
18252         mWiFiAgent.connect(false /* validated */);
18253         verifyMtuSetOnWifiInterface(mtu);
18254         reset(mMockNetd);
18255 
18256         mWiFiAgent.sendLinkProperties(new LinkProperties(lp));
18257         waitForIdle();
18258         verifyMtuNeverSetOnWifiInterface();
18259     }
18260 
18261     @Test
18262     public void testSendLinkPropertiesSetInterfaceMtu_IdenticalMtuAndNullIface() throws Exception {
18263         final int mtu = 1330;
18264         LinkProperties lp = new LinkProperties();
18265         lp.setInterfaceName(WIFI_IFNAME);
18266         lp.setMtu(mtu);
18267 
18268         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, lp);
18269         mWiFiAgent.connect(false /* validated */);
18270         verifyMtuSetOnWifiInterface(mtu);
18271         reset(mMockNetd);
18272 
18273         LinkProperties lp2 = new LinkProperties(lp);
18274         lp2.setInterfaceName(null);
18275         mWiFiAgent.sendLinkProperties(new LinkProperties(lp2));
18276         waitForIdle();
18277         verifyMtuNeverSetOnWifiInterface();
18278     }
18279 
18280     @Test
18281     public void testSendLinkPropertiesSetInterfaceMtu_IdenticalMtuDiffIface() throws Exception {
18282         final int mtu = 1331;
18283         LinkProperties lp = new LinkProperties();
18284         lp.setInterfaceName(WIFI_IFNAME);
18285         lp.setMtu(mtu);
18286 
18287         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, lp);
18288         mWiFiAgent.connect(false /* validated */);
18289         verifyMtuSetOnWifiInterface(mtu);
18290         reset(mMockNetd);
18291 
18292         final String ifaceName2 = WIFI_IFNAME + "_2";
18293         LinkProperties lp2 = new LinkProperties(lp);
18294         lp2.setInterfaceName(ifaceName2);
18295 
18296         mWiFiAgent.sendLinkProperties(new LinkProperties(lp2));
18297         waitForIdle();
18298         verify(mMockNetd, times(1)).interfaceSetMtu(eq(ifaceName2), eq(mtu));
18299         verifyMtuNeverSetOnWifiInterface();
18300     }
18301 
18302     @Test
18303     public void testCreateDeliveryGroupKeyForConnectivityAction() throws Exception {
18304         final NetworkInfo info = new NetworkInfo(0 /* type */, 2 /* subtype */,
18305                 "MOBILE" /* typeName */, "LTE" /* subtypeName */);
18306         assertEquals("0;2;null", createDeliveryGroupKeyForConnectivityAction(info));
18307 
18308         info.setExtraInfo("test_info");
18309         assertEquals("0;2;test_info", createDeliveryGroupKeyForConnectivityAction(info));
18310     }
18311 
18312     @Test
18313     public void testNetdWakeupAddInterfaceForWifiTransport() throws Exception {
18314         final LinkProperties wifiLp = new LinkProperties();
18315         wifiLp.setInterfaceName(WIFI_IFNAME);
18316         mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp);
18317         mWiFiAgent.connect(false /* validated */);
18318 
18319         final String expectedPrefix = makeNflogPrefix(WIFI_IFNAME,
18320                 mWiFiAgent.getNetwork().getNetworkHandle());
18321         verify(mMockNetd).wakeupAddInterface(WIFI_IFNAME, expectedPrefix, PACKET_WAKEUP_MARK_MASK,
18322                 PACKET_WAKEUP_MARK_MASK);
18323     }
18324 
18325     @Test
18326     public void testNetdWakeupAddInterfaceForCellularTransport() throws Exception {
18327         final LinkProperties cellLp = new LinkProperties();
18328         cellLp.setInterfaceName(MOBILE_IFNAME);
18329         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
18330         mCellAgent.connect(false /* validated */);
18331 
18332         if (mDeps.isAtLeastU()) {
18333             final String expectedPrefix = makeNflogPrefix(MOBILE_IFNAME,
18334                     mCellAgent.getNetwork().getNetworkHandle());
18335             verify(mMockNetd).wakeupAddInterface(MOBILE_IFNAME, expectedPrefix,
18336                     PACKET_WAKEUP_MARK_MASK, PACKET_WAKEUP_MARK_MASK);
18337         } else {
18338             verify(mMockNetd, never()).wakeupAddInterface(eq(MOBILE_IFNAME), anyString(), anyInt(),
18339                     anyInt());
18340         }
18341     }
18342 
18343     @Test
18344     public void testNetdWakeupAddInterfaceForEthernetTransport() throws Exception {
18345         final String ethernetIface = "eth42";
18346 
18347         final LinkProperties ethLp = new LinkProperties();
18348         ethLp.setInterfaceName(ethernetIface);
18349         mEthernetAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET, ethLp);
18350         mEthernetAgent.connect(false /* validated */);
18351 
18352         verify(mMockNetd, never()).wakeupAddInterface(eq(ethernetIface), anyString(), anyInt(),
18353                 anyInt());
18354     }
18355 
18356     private static final int TEST_FROZEN_UID = 1000;
18357     private static final int TEST_UNFROZEN_UID = 2000;
18358 
18359     /**
18360      * Send a UidFrozenStateChanged message to ConnectivityService. Verify that only the frozen UID
18361      * gets passed to socketDestroy().
18362      */
18363     @Test
18364     @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
18365     public void testFrozenUidSocketDestroy() throws Exception {
18366         ArgumentCaptor<UidFrozenStateChangedCallback> callbackArg =
18367                 ArgumentCaptor.forClass(UidFrozenStateChangedCallback.class);
18368 
18369         verify(mActivityManager).registerUidFrozenStateChangedCallback(any(),
18370                 callbackArg.capture());
18371 
18372         final int[] uids = {TEST_FROZEN_UID, TEST_UNFROZEN_UID};
18373         final int[] frozenStates = {UID_FROZEN_STATE_FROZEN, UID_FROZEN_STATE_UNFROZEN};
18374 
18375         callbackArg.getValue().onUidFrozenStateChanged(uids, frozenStates);
18376 
18377         waitForIdle();
18378 
18379         final Set<Integer> exemptUids = new ArraySet();
18380         final UidRange frozenUidRange = new UidRange(TEST_FROZEN_UID, TEST_FROZEN_UID);
18381         final Set<UidRange> ranges = Collections.singleton(frozenUidRange);
18382 
18383         verify(mDestroySocketsWrapper).destroyLiveTcpSockets(eq(UidRange.toIntRanges(ranges)),
18384                 eq(exemptUids));
18385     }
18386 
18387     @Test
18388     public void testDisconnectSuspendedNetworkStopClatd() throws Exception {
18389         final TestNetworkCallback networkCallback = new TestNetworkCallback();
18390         final NetworkRequest networkRequest = new NetworkRequest.Builder()
18391                 .addCapability(NET_CAPABILITY_DUN)
18392                 .build();
18393         mCm.requestNetwork(networkRequest, networkCallback);
18394 
18395         final IpPrefix nat64Prefix = new IpPrefix(InetAddress.getByName("64:ff9b::"), 96);
18396         NetworkCapabilities nc = new NetworkCapabilities().addCapability(NET_CAPABILITY_DUN);
18397         final LinkProperties lp = new LinkProperties();
18398         lp.setInterfaceName(MOBILE_IFNAME);
18399         lp.addLinkAddress(new LinkAddress("2001:db8:1::1/64"));
18400         lp.setNat64Prefix(nat64Prefix);
18401         mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, lp, nc);
18402         mCellAgent.connect(true /* validated */, false /* hasInternet */,
18403                 false /* privateDnsProbeSent */);
18404 
18405         verifyClatdStart(null /* inOrder */, MOBILE_IFNAME, mCellAgent.getNetwork().netId,
18406                 nat64Prefix.toString());
18407 
18408         mCellAgent.suspend();
18409         mCm.unregisterNetworkCallback(networkCallback);
18410         mCellAgent.expectDisconnected();
18411         waitForIdle();
18412 
18413         verifyClatdStop(null /* inOrder */, MOBILE_IFNAME);
18414     }
18415 }
18416