• 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_STACK;
31 import static android.Manifest.permission.PACKET_KEEPALIVE_OFFLOAD;
32 import static android.app.PendingIntent.FLAG_IMMUTABLE;
33 import static android.content.Intent.ACTION_PACKAGE_ADDED;
34 import static android.content.Intent.ACTION_PACKAGE_REMOVED;
35 import static android.content.Intent.ACTION_PACKAGE_REPLACED;
36 import static android.content.Intent.ACTION_USER_ADDED;
37 import static android.content.Intent.ACTION_USER_REMOVED;
38 import static android.content.Intent.ACTION_USER_UNLOCKED;
39 import static android.content.pm.PackageInfo.REQUESTED_PERMISSION_GRANTED;
40 import static android.content.pm.PackageManager.FEATURE_ETHERNET;
41 import static android.content.pm.PackageManager.FEATURE_WIFI;
42 import static android.content.pm.PackageManager.FEATURE_WIFI_DIRECT;
43 import static android.content.pm.PackageManager.GET_PERMISSIONS;
44 import static android.content.pm.PackageManager.PERMISSION_DENIED;
45 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
46 import static android.net.ConnectivityManager.ACTION_CAPTIVE_PORTAL_SIGN_IN;
47 import static android.net.ConnectivityManager.BLOCKED_METERED_REASON_DATA_SAVER;
48 import static android.net.ConnectivityManager.BLOCKED_METERED_REASON_MASK;
49 import static android.net.ConnectivityManager.BLOCKED_METERED_REASON_USER_RESTRICTED;
50 import static android.net.ConnectivityManager.BLOCKED_REASON_BATTERY_SAVER;
51 import static android.net.ConnectivityManager.BLOCKED_REASON_NONE;
52 import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
53 import static android.net.ConnectivityManager.EXTRA_NETWORK_INFO;
54 import static android.net.ConnectivityManager.EXTRA_NETWORK_TYPE;
55 import static android.net.ConnectivityManager.FIREWALL_CHAIN_DOZABLE;
56 import static android.net.ConnectivityManager.FIREWALL_CHAIN_LOCKDOWN_VPN;
57 import static android.net.ConnectivityManager.FIREWALL_CHAIN_LOW_POWER_STANDBY;
58 import static android.net.ConnectivityManager.FIREWALL_CHAIN_OEM_DENY_1;
59 import static android.net.ConnectivityManager.FIREWALL_CHAIN_OEM_DENY_2;
60 import static android.net.ConnectivityManager.FIREWALL_CHAIN_OEM_DENY_3;
61 import static android.net.ConnectivityManager.FIREWALL_CHAIN_POWERSAVE;
62 import static android.net.ConnectivityManager.FIREWALL_CHAIN_RESTRICTED;
63 import static android.net.ConnectivityManager.FIREWALL_CHAIN_STANDBY;
64 import static android.net.ConnectivityManager.FIREWALL_RULE_ALLOW;
65 import static android.net.ConnectivityManager.FIREWALL_RULE_DEFAULT;
66 import static android.net.ConnectivityManager.FIREWALL_RULE_DENY;
67 import static android.net.ConnectivityManager.PROFILE_NETWORK_PREFERENCE_DEFAULT;
68 import static android.net.ConnectivityManager.PROFILE_NETWORK_PREFERENCE_ENTERPRISE;
69 import static android.net.ConnectivityManager.PROFILE_NETWORK_PREFERENCE_ENTERPRISE_NO_FALLBACK;
70 import static android.net.ConnectivityManager.TYPE_ETHERNET;
71 import static android.net.ConnectivityManager.TYPE_MOBILE;
72 import static android.net.ConnectivityManager.TYPE_MOBILE_FOTA;
73 import static android.net.ConnectivityManager.TYPE_MOBILE_MMS;
74 import static android.net.ConnectivityManager.TYPE_MOBILE_SUPL;
75 import static android.net.ConnectivityManager.TYPE_PROXY;
76 import static android.net.ConnectivityManager.TYPE_VPN;
77 import static android.net.ConnectivityManager.TYPE_WIFI;
78 import static android.net.ConnectivitySettingsManager.PRIVATE_DNS_MODE_OFF;
79 import static android.net.ConnectivitySettingsManager.PRIVATE_DNS_MODE_OPPORTUNISTIC;
80 import static android.net.ConnectivitySettingsManager.PRIVATE_DNS_MODE_PROVIDER_HOSTNAME;
81 import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_DNS;
82 import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_FALLBACK;
83 import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_HTTP;
84 import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_HTTPS;
85 import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_PRIVDNS;
86 import static android.net.INetworkMonitor.NETWORK_VALIDATION_RESULT_PARTIAL;
87 import static android.net.INetworkMonitor.NETWORK_VALIDATION_RESULT_VALID;
88 import static android.net.NetworkCapabilities.NET_CAPABILITY_BIP;
89 import static android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL;
90 import static android.net.NetworkCapabilities.NET_CAPABILITY_CBS;
91 import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN;
92 import static android.net.NetworkCapabilities.NET_CAPABILITY_EIMS;
93 import static android.net.NetworkCapabilities.NET_CAPABILITY_ENTERPRISE;
94 import static android.net.NetworkCapabilities.NET_CAPABILITY_FOREGROUND;
95 import static android.net.NetworkCapabilities.NET_CAPABILITY_FOTA;
96 import static android.net.NetworkCapabilities.NET_CAPABILITY_IA;
97 import static android.net.NetworkCapabilities.NET_CAPABILITY_IMS;
98 import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
99 import static android.net.NetworkCapabilities.NET_CAPABILITY_MMS;
100 import static android.net.NetworkCapabilities.NET_CAPABILITY_MMTEL;
101 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED;
102 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
103 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
104 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING;
105 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED;
106 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED;
107 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN;
108 import static android.net.NetworkCapabilities.NET_CAPABILITY_OEM_PAID;
109 import static android.net.NetworkCapabilities.NET_CAPABILITY_OEM_PRIVATE;
110 import static android.net.NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVITY;
111 import static android.net.NetworkCapabilities.NET_CAPABILITY_RCS;
112 import static android.net.NetworkCapabilities.NET_CAPABILITY_SUPL;
113 import static android.net.NetworkCapabilities.NET_CAPABILITY_TEMPORARILY_NOT_METERED;
114 import static android.net.NetworkCapabilities.NET_CAPABILITY_TRUSTED;
115 import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
116 import static android.net.NetworkCapabilities.NET_CAPABILITY_VSIM;
117 import static android.net.NetworkCapabilities.NET_CAPABILITY_WIFI_P2P;
118 import static android.net.NetworkCapabilities.NET_CAPABILITY_XCAP;
119 import static android.net.NetworkCapabilities.NET_ENTERPRISE_ID_1;
120 import static android.net.NetworkCapabilities.NET_ENTERPRISE_ID_2;
121 import static android.net.NetworkCapabilities.NET_ENTERPRISE_ID_3;
122 import static android.net.NetworkCapabilities.NET_ENTERPRISE_ID_4;
123 import static android.net.NetworkCapabilities.NET_ENTERPRISE_ID_5;
124 import static android.net.NetworkCapabilities.REDACT_FOR_ACCESS_FINE_LOCATION;
125 import static android.net.NetworkCapabilities.REDACT_FOR_LOCAL_MAC_ADDRESS;
126 import static android.net.NetworkCapabilities.REDACT_FOR_NETWORK_SETTINGS;
127 import static android.net.NetworkCapabilities.REDACT_NONE;
128 import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
129 import static android.net.NetworkCapabilities.TRANSPORT_ETHERNET;
130 import static android.net.NetworkCapabilities.TRANSPORT_TEST;
131 import static android.net.NetworkCapabilities.TRANSPORT_VPN;
132 import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
133 import static android.net.NetworkCapabilities.TRANSPORT_WIFI_AWARE;
134 import static android.net.NetworkScore.KEEP_CONNECTED_FOR_HANDOVER;
135 import static android.net.OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PAID;
136 import static android.net.OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK;
137 import static android.net.OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY;
138 import static android.net.OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY;
139 import static android.net.OemNetworkPreferences.OEM_NETWORK_PREFERENCE_TEST;
140 import static android.net.OemNetworkPreferences.OEM_NETWORK_PREFERENCE_TEST_ONLY;
141 import static android.net.OemNetworkPreferences.OEM_NETWORK_PREFERENCE_UNINITIALIZED;
142 import static android.net.RouteInfo.RTN_UNREACHABLE;
143 import static android.net.resolv.aidl.IDnsResolverUnsolicitedEventListener.PREFIX_OPERATION_ADDED;
144 import static android.net.resolv.aidl.IDnsResolverUnsolicitedEventListener.PREFIX_OPERATION_REMOVED;
145 import static android.net.resolv.aidl.IDnsResolverUnsolicitedEventListener.VALIDATION_RESULT_FAILURE;
146 import static android.net.resolv.aidl.IDnsResolverUnsolicitedEventListener.VALIDATION_RESULT_SUCCESS;
147 import static android.os.Process.INVALID_UID;
148 import static android.system.OsConstants.IPPROTO_TCP;
149 
150 import static com.android.server.ConnectivityService.MAX_NETWORK_REQUESTS_PER_SYSTEM_UID;
151 import static com.android.server.ConnectivityService.PREFERENCE_ORDER_MOBILE_DATA_PREFERERRED;
152 import static com.android.server.ConnectivityService.PREFERENCE_ORDER_OEM;
153 import static com.android.server.ConnectivityService.PREFERENCE_ORDER_PROFILE;
154 import static com.android.server.ConnectivityService.PREFERENCE_ORDER_VPN;
155 import static com.android.server.ConnectivityServiceTestUtils.transportToLegacyType;
156 import static com.android.testutils.ConcurrentUtils.await;
157 import static com.android.testutils.ConcurrentUtils.durationOf;
158 import static com.android.testutils.DevSdkIgnoreRule.IgnoreAfter;
159 import static com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
160 import static com.android.testutils.DevSdkIgnoreRuleKt.SC_V2;
161 import static com.android.testutils.ExceptionUtils.ignoreExceptions;
162 import static com.android.testutils.HandlerUtils.waitForIdleSerialExecutor;
163 import static com.android.testutils.MiscAsserts.assertContainsAll;
164 import static com.android.testutils.MiscAsserts.assertContainsExactly;
165 import static com.android.testutils.MiscAsserts.assertEmpty;
166 import static com.android.testutils.MiscAsserts.assertLength;
167 import static com.android.testutils.MiscAsserts.assertRunsInAtMost;
168 import static com.android.testutils.MiscAsserts.assertSameElements;
169 import static com.android.testutils.MiscAsserts.assertThrows;
170 import static com.android.testutils.TestPermissionUtil.runAsShell;
171 
172 import static org.junit.Assert.assertEquals;
173 import static org.junit.Assert.assertFalse;
174 import static org.junit.Assert.assertNotEquals;
175 import static org.junit.Assert.assertNotNull;
176 import static org.junit.Assert.assertNull;
177 import static org.junit.Assert.assertTrue;
178 import static org.junit.Assert.fail;
179 import static org.junit.Assume.assumeFalse;
180 import static org.junit.Assume.assumeTrue;
181 import static org.mockito.AdditionalMatchers.aryEq;
182 import static org.mockito.ArgumentMatchers.anyBoolean;
183 import static org.mockito.ArgumentMatchers.anyLong;
184 import static org.mockito.ArgumentMatchers.anyString;
185 import static org.mockito.ArgumentMatchers.argThat;
186 import static org.mockito.ArgumentMatchers.eq;
187 import static org.mockito.ArgumentMatchers.isNull;
188 import static org.mockito.Matchers.anyInt;
189 import static org.mockito.Mockito.any;
190 import static org.mockito.Mockito.atLeastOnce;
191 import static org.mockito.Mockito.doAnswer;
192 import static org.mockito.Mockito.doNothing;
193 import static org.mockito.Mockito.doReturn;
194 import static org.mockito.Mockito.doThrow;
195 import static org.mockito.Mockito.inOrder;
196 import static org.mockito.Mockito.mock;
197 import static org.mockito.Mockito.never;
198 import static org.mockito.Mockito.reset;
199 import static org.mockito.Mockito.spy;
200 import static org.mockito.Mockito.timeout;
201 import static org.mockito.Mockito.times;
202 import static org.mockito.Mockito.verify;
203 import static org.mockito.Mockito.verifyNoMoreInteractions;
204 
205 import static java.util.Arrays.asList;
206 
207 import android.Manifest;
208 import android.annotation.NonNull;
209 import android.annotation.Nullable;
210 import android.app.AlarmManager;
211 import android.app.AppOpsManager;
212 import android.app.NotificationManager;
213 import android.app.PendingIntent;
214 import android.app.admin.DevicePolicyManager;
215 import android.app.usage.NetworkStatsManager;
216 import android.content.BroadcastReceiver;
217 import android.content.ComponentName;
218 import android.content.ContentProvider;
219 import android.content.ContentResolver;
220 import android.content.Context;
221 import android.content.Intent;
222 import android.content.IntentFilter;
223 import android.content.pm.ApplicationInfo;
224 import android.content.pm.PackageInfo;
225 import android.content.pm.PackageManager;
226 import android.content.pm.ResolveInfo;
227 import android.content.pm.ServiceInfo;
228 import android.content.pm.UserInfo;
229 import android.content.res.Resources;
230 import android.location.LocationManager;
231 import android.net.CaptivePortalData;
232 import android.net.ConnectionInfo;
233 import android.net.ConnectivityDiagnosticsManager.DataStallReport;
234 import android.net.ConnectivityManager;
235 import android.net.ConnectivityManager.NetworkCallback;
236 import android.net.ConnectivityManager.PacketKeepalive;
237 import android.net.ConnectivityManager.PacketKeepaliveCallback;
238 import android.net.ConnectivityManager.TooManyRequestsException;
239 import android.net.ConnectivityResources;
240 import android.net.ConnectivitySettingsManager;
241 import android.net.ConnectivityThread;
242 import android.net.DataStallReportParcelable;
243 import android.net.EthernetManager;
244 import android.net.IConnectivityDiagnosticsCallback;
245 import android.net.IDnsResolver;
246 import android.net.INetd;
247 import android.net.INetworkMonitor;
248 import android.net.INetworkMonitorCallbacks;
249 import android.net.IOnCompleteListener;
250 import android.net.IQosCallback;
251 import android.net.InetAddresses;
252 import android.net.InterfaceConfigurationParcel;
253 import android.net.IpPrefix;
254 import android.net.IpSecManager;
255 import android.net.IpSecManager.UdpEncapsulationSocket;
256 import android.net.LinkAddress;
257 import android.net.LinkProperties;
258 import android.net.MatchAllNetworkSpecifier;
259 import android.net.NativeNetworkConfig;
260 import android.net.NativeNetworkType;
261 import android.net.Network;
262 import android.net.NetworkAgent;
263 import android.net.NetworkAgentConfig;
264 import android.net.NetworkCapabilities;
265 import android.net.NetworkFactory;
266 import android.net.NetworkInfo;
267 import android.net.NetworkInfo.DetailedState;
268 import android.net.NetworkPolicyManager;
269 import android.net.NetworkPolicyManager.NetworkPolicyCallback;
270 import android.net.NetworkProvider;
271 import android.net.NetworkRequest;
272 import android.net.NetworkScore;
273 import android.net.NetworkSpecifier;
274 import android.net.NetworkStack;
275 import android.net.NetworkStateSnapshot;
276 import android.net.NetworkTestResultParcelable;
277 import android.net.OemNetworkPreferences;
278 import android.net.PacProxyManager;
279 import android.net.ProfileNetworkPreference;
280 import android.net.Proxy;
281 import android.net.ProxyInfo;
282 import android.net.QosCallbackException;
283 import android.net.QosFilter;
284 import android.net.QosSession;
285 import android.net.ResolverParamsParcel;
286 import android.net.RouteInfo;
287 import android.net.RouteInfoParcel;
288 import android.net.SocketKeepalive;
289 import android.net.TelephonyNetworkSpecifier;
290 import android.net.TetheringManager;
291 import android.net.TransportInfo;
292 import android.net.UidRange;
293 import android.net.UidRangeParcel;
294 import android.net.UnderlyingNetworkInfo;
295 import android.net.Uri;
296 import android.net.VpnManager;
297 import android.net.VpnTransportInfo;
298 import android.net.metrics.IpConnectivityLog;
299 import android.net.netd.aidl.NativeUidRangeConfig;
300 import android.net.networkstack.NetworkStackClientBase;
301 import android.net.resolv.aidl.Nat64PrefixEventParcel;
302 import android.net.resolv.aidl.PrivateDnsValidationEventParcel;
303 import android.net.shared.NetworkMonitorUtils;
304 import android.net.shared.PrivateDnsConfig;
305 import android.net.util.MultinetworkPolicyTracker;
306 import android.net.wifi.WifiInfo;
307 import android.os.BadParcelableException;
308 import android.os.BatteryStatsManager;
309 import android.os.Binder;
310 import android.os.Build;
311 import android.os.Bundle;
312 import android.os.ConditionVariable;
313 import android.os.Handler;
314 import android.os.HandlerThread;
315 import android.os.IBinder;
316 import android.os.INetworkManagementService;
317 import android.os.Looper;
318 import android.os.Messenger;
319 import android.os.Parcel;
320 import android.os.ParcelFileDescriptor;
321 import android.os.Parcelable;
322 import android.os.PersistableBundle;
323 import android.os.Process;
324 import android.os.RemoteException;
325 import android.os.ServiceSpecificException;
326 import android.os.SystemClock;
327 import android.os.SystemConfigManager;
328 import android.os.UserHandle;
329 import android.os.UserManager;
330 import android.provider.Settings;
331 import android.security.Credentials;
332 import android.system.Os;
333 import android.telephony.TelephonyManager;
334 import android.telephony.data.EpsBearerQosSessionAttributes;
335 import android.telephony.data.NrQosSessionAttributes;
336 import android.test.mock.MockContentResolver;
337 import android.text.TextUtils;
338 import android.util.ArraySet;
339 import android.util.Log;
340 import android.util.Pair;
341 import android.util.Range;
342 import android.util.SparseArray;
343 
344 import androidx.test.InstrumentationRegistry;
345 import androidx.test.filters.SmallTest;
346 
347 import com.android.connectivity.resources.R;
348 import com.android.internal.annotations.GuardedBy;
349 import com.android.internal.app.IBatteryStats;
350 import com.android.internal.net.VpnConfig;
351 import com.android.internal.net.VpnProfile;
352 import com.android.internal.util.WakeupMessage;
353 import com.android.internal.util.test.BroadcastInterceptingContext;
354 import com.android.internal.util.test.FakeSettingsProvider;
355 import com.android.modules.utils.build.SdkLevel;
356 import com.android.net.module.util.ArrayTrackRecord;
357 import com.android.net.module.util.CollectionUtils;
358 import com.android.net.module.util.LocationPermissionChecker;
359 import com.android.networkstack.apishim.NetworkAgentConfigShimImpl;
360 import com.android.networkstack.apishim.api29.ConstantsShim;
361 import com.android.server.ConnectivityService.ConnectivityDiagnosticsCallbackInfo;
362 import com.android.server.ConnectivityService.NetworkRequestInfo;
363 import com.android.server.ConnectivityServiceTest.ConnectivityServiceDependencies.ReportedInterfaces;
364 import com.android.server.connectivity.CarrierPrivilegeAuthenticator;
365 import com.android.server.connectivity.ClatCoordinator;
366 import com.android.server.connectivity.ConnectivityFlags;
367 import com.android.server.connectivity.MockableSystemProperties;
368 import com.android.server.connectivity.Nat464Xlat;
369 import com.android.server.connectivity.NetworkAgentInfo;
370 import com.android.server.connectivity.NetworkNotificationManager.NotificationType;
371 import com.android.server.connectivity.ProxyTracker;
372 import com.android.server.connectivity.QosCallbackTracker;
373 import com.android.server.connectivity.UidRangeUtils;
374 import com.android.server.connectivity.Vpn;
375 import com.android.server.connectivity.VpnProfileStore;
376 import com.android.server.net.NetworkPinner;
377 import com.android.testutils.DevSdkIgnoreRule;
378 import com.android.testutils.DevSdkIgnoreRunner;
379 import com.android.testutils.ExceptionUtils;
380 import com.android.testutils.HandlerUtils;
381 import com.android.testutils.RecorderCallback.CallbackEntry;
382 import com.android.testutils.TestableNetworkCallback;
383 import com.android.testutils.TestableNetworkOfferCallback;
384 
385 import org.junit.After;
386 import org.junit.Assert;
387 import org.junit.Before;
388 import org.junit.Ignore;
389 import org.junit.Rule;
390 import org.junit.Test;
391 import org.junit.runner.RunWith;
392 import org.mockito.AdditionalAnswers;
393 import org.mockito.ArgumentCaptor;
394 import org.mockito.InOrder;
395 import org.mockito.Mock;
396 import org.mockito.MockitoAnnotations;
397 import org.mockito.Spy;
398 import org.mockito.stubbing.Answer;
399 
400 import java.io.FileDescriptor;
401 import java.io.IOException;
402 import java.io.PrintWriter;
403 import java.io.StringWriter;
404 import java.net.DatagramSocket;
405 import java.net.Inet4Address;
406 import java.net.Inet6Address;
407 import java.net.InetAddress;
408 import java.net.InetSocketAddress;
409 import java.net.Socket;
410 import java.nio.charset.StandardCharsets;
411 import java.util.ArrayList;
412 import java.util.Arrays;
413 import java.util.Collection;
414 import java.util.Collections;
415 import java.util.Comparator;
416 import java.util.HashMap;
417 import java.util.HashSet;
418 import java.util.List;
419 import java.util.Map;
420 import java.util.Objects;
421 import java.util.Set;
422 import java.util.concurrent.CompletableFuture;
423 import java.util.concurrent.CountDownLatch;
424 import java.util.concurrent.Executor;
425 import java.util.concurrent.ExecutorService;
426 import java.util.concurrent.Executors;
427 import java.util.concurrent.LinkedBlockingQueue;
428 import java.util.concurrent.TimeUnit;
429 import java.util.concurrent.TimeoutException;
430 import java.util.concurrent.atomic.AtomicBoolean;
431 import java.util.concurrent.atomic.AtomicReference;
432 import java.util.function.Predicate;
433 import java.util.function.Supplier;
434 import java.util.regex.Matcher;
435 import java.util.regex.Pattern;
436 import java.util.stream.Collectors;
437 
438 import kotlin.reflect.KClass;
439 
440 /**
441  * Tests for {@link ConnectivityService}.
442  *
443  * Build, install and run with:
444  *  runtest frameworks-net -c com.android.server.ConnectivityServiceTest
445  */
446 @RunWith(DevSdkIgnoreRunner.class)
447 @SmallTest
448 @DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
449 public class ConnectivityServiceTest {
450     private static final String TAG = "ConnectivityServiceTest";
451 
452     @Rule
453     public final DevSdkIgnoreRule ignoreRule = new DevSdkIgnoreRule();
454 
455     private static final int TIMEOUT_MS = 2_000;
456     // Broadcasts can take a long time to be delivered. The test will not wait for that long unless
457     // there is a failure, so use a long timeout.
458     private static final int BROADCAST_TIMEOUT_MS = 30_000;
459     private static final int TEST_LINGER_DELAY_MS = 400;
460     private static final int TEST_NASCENT_DELAY_MS = 300;
461     // Chosen to be less than the linger and nascent timeout. This ensures that we can distinguish
462     // between a LOST callback that arrives immediately and a LOST callback that arrives after
463     // the linger/nascent timeout. For this, our assertions should run fast enough to leave
464     // less than (mService.mLingerDelayMs - TEST_CALLBACK_TIMEOUT_MS) between the time callbacks are
465     // supposedly fired, and the time we call expectCallback.
466     private static final int TEST_CALLBACK_TIMEOUT_MS = 250;
467     // Chosen to be less than TEST_CALLBACK_TIMEOUT_MS. This ensures that requests have time to
468     // complete before callbacks are verified.
469     private static final int TEST_REQUEST_TIMEOUT_MS = 150;
470 
471     private static final int UNREASONABLY_LONG_ALARM_WAIT_MS = 1000;
472 
473     private static final long TIMESTAMP = 1234L;
474 
475     private static final int NET_ID = 110;
476     private static final int OEM_PREF_ANY_NET_ID = -1;
477     // Set a non-zero value to verify the flow to set tcp init rwnd value.
478     private static final int TEST_TCP_INIT_RWND = 60;
479 
480     // Used for testing the per-work-profile default network.
481     private static final int TEST_APP_ID = 103;
482     private static final int TEST_WORK_PROFILE_USER_ID = 2;
483     private static final int TEST_WORK_PROFILE_APP_UID =
484             UserHandle.getUid(TEST_WORK_PROFILE_USER_ID, TEST_APP_ID);
485     private static final int TEST_APP_ID_2 = 104;
486     private static final int TEST_WORK_PROFILE_APP_UID_2 =
487             UserHandle.getUid(TEST_WORK_PROFILE_USER_ID, TEST_APP_ID_2);
488     private static final int TEST_APP_ID_3 = 105;
489     private static final int TEST_APP_ID_4 = 106;
490     private static final int TEST_APP_ID_5 = 107;
491 
492     private static final String CLAT_PREFIX = "v4-";
493     private static final String MOBILE_IFNAME = "test_rmnet_data0";
494     private static final String CLAT_MOBILE_IFNAME = CLAT_PREFIX + MOBILE_IFNAME;
495     private static final String WIFI_IFNAME = "test_wlan0";
496     private static final String WIFI_WOL_IFNAME = "test_wlan_wol";
497     private static final String VPN_IFNAME = "tun10042";
498     private static final String TEST_PACKAGE_NAME = "com.android.test.package";
499     private static final int TEST_PACKAGE_UID = 123;
500     private static final int TEST_PACKAGE_UID2 = 321;
501     private static final int TEST_PACKAGE_UID3 = 456;
502     private static final String ALWAYS_ON_PACKAGE = "com.android.test.alwaysonvpn";
503 
504     private static final String INTERFACE_NAME = "interface";
505 
506     private static final String TEST_VENUE_URL_NA_PASSPOINT = "https://android.com/";
507     private static final String TEST_VENUE_URL_NA_OTHER = "https://example.com/";
508     private static final String TEST_TERMS_AND_CONDITIONS_URL_NA_PASSPOINT =
509             "https://android.com/terms/";
510     private static final String TEST_TERMS_AND_CONDITIONS_URL_NA_OTHER =
511             "https://example.com/terms/";
512     private static final String TEST_VENUE_URL_CAPPORT = "https://android.com/capport/";
513     private static final String TEST_USER_PORTAL_API_URL_CAPPORT =
514             "https://android.com/user/api/capport/";
515     private static final String TEST_FRIENDLY_NAME = "Network friendly name";
516     private static final String TEST_REDIRECT_URL = "http://example.com/firstPath";
517 
518     private MockContext mServiceContext;
519     private HandlerThread mCsHandlerThread;
520     private HandlerThread mVMSHandlerThread;
521     private ConnectivityServiceDependencies mDeps;
522     private ConnectivityService mService;
523     private WrappedConnectivityManager mCm;
524     private TestNetworkAgentWrapper mWiFiNetworkAgent;
525     private TestNetworkAgentWrapper mCellNetworkAgent;
526     private TestNetworkAgentWrapper mEthernetNetworkAgent;
527     private MockVpn mMockVpn;
528     private Context mContext;
529     private NetworkPolicyCallback mPolicyCallback;
530     private WrappedMultinetworkPolicyTracker mPolicyTracker;
531     private ProxyTracker mProxyTracker;
532     private HandlerThread mAlarmManagerThread;
533     private TestNetIdManager mNetIdManager;
534     private QosCallbackMockHelper mQosCallbackMockHelper;
535     private QosCallbackTracker mQosCallbackTracker;
536     private VpnManagerService mVpnManagerService;
537     private TestNetworkCallback mDefaultNetworkCallback;
538     private TestNetworkCallback mSystemDefaultNetworkCallback;
539     private TestNetworkCallback mProfileDefaultNetworkCallback;
540     private TestNetworkCallback mTestPackageDefaultNetworkCallback;
541     private TestNetworkCallback mProfileDefaultNetworkCallbackAsAppUid2;
542     private TestNetworkCallback mTestPackageDefaultNetworkCallback2;
543 
544     // State variables required to emulate NetworkPolicyManagerService behaviour.
545     private int mBlockedReasons = BLOCKED_REASON_NONE;
546 
547     @Mock DeviceIdleInternal mDeviceIdleInternal;
548     @Mock INetworkManagementService mNetworkManagementService;
549     @Mock NetworkStatsManager mStatsManager;
550     @Mock IDnsResolver mMockDnsResolver;
551     @Mock INetd mMockNetd;
552     @Mock NetworkStackClientBase mNetworkStack;
553     @Mock PackageManager mPackageManager;
554     @Mock UserManager mUserManager;
555     @Mock NotificationManager mNotificationManager;
556     @Mock AlarmManager mAlarmManager;
557     @Mock IConnectivityDiagnosticsCallback mConnectivityDiagnosticsCallback;
558     @Mock IBinder mIBinder;
559     @Mock LocationManager mLocationManager;
560     @Mock AppOpsManager mAppOpsManager;
561     @Mock TelephonyManager mTelephonyManager;
562     @Mock EthernetManager mEthernetManager;
563     @Mock NetworkPolicyManager mNetworkPolicyManager;
564     @Mock VpnProfileStore mVpnProfileStore;
565     @Mock SystemConfigManager mSystemConfigManager;
566     @Mock DevicePolicyManager mDevicePolicyManager;
567     @Mock Resources mResources;
568     @Mock ClatCoordinator mClatCoordinator;
569     @Mock PacProxyManager mPacProxyManager;
570     @Mock BpfNetMaps mBpfNetMaps;
571     @Mock CarrierPrivilegeAuthenticator mCarrierPrivilegeAuthenticator;
572     @Mock TetheringManager mTetheringManager;
573 
574     // BatteryStatsManager is final and cannot be mocked with regular mockito, so just mock the
575     // underlying binder calls.
576     final BatteryStatsManager mBatteryStatsManager =
577             new BatteryStatsManager(mock(IBatteryStats.class));
578 
579     private ArgumentCaptor<ResolverParamsParcel> mResolverParamsParcelCaptor =
580             ArgumentCaptor.forClass(ResolverParamsParcel.class);
581 
582     // This class exists to test bindProcessToNetwork and getBoundNetworkForProcess. These methods
583     // do not go through ConnectivityService but talk to netd directly, so they don't automatically
584     // reflect the state of our test ConnectivityService.
585     private class WrappedConnectivityManager extends ConnectivityManager {
586         private Network mFakeBoundNetwork;
587 
bindProcessToNetwork(Network network)588         public synchronized boolean bindProcessToNetwork(Network network) {
589             mFakeBoundNetwork = network;
590             return true;
591         }
592 
getBoundNetworkForProcess()593         public synchronized Network getBoundNetworkForProcess() {
594             return mFakeBoundNetwork;
595         }
596 
WrappedConnectivityManager(Context context, ConnectivityService service)597         public WrappedConnectivityManager(Context context, ConnectivityService service) {
598             super(context, service);
599         }
600     }
601 
602     private class MockContext extends BroadcastInterceptingContext {
603         private final MockContentResolver mContentResolver;
604 
605         @Spy private Resources mInternalResources;
606         private final LinkedBlockingQueue<Intent> mStartedActivities = new LinkedBlockingQueue<>();
607 
608         // Map of permission name -> PermissionManager.Permission_{GRANTED|DENIED} constant
609         // For permissions granted across the board, the key is only the permission name.
610         // For permissions only granted to a combination of uid/pid, the key
611         // is "<permission name>,<pid>,<uid>". PID+UID permissons have priority over generic ones.
612         private final HashMap<String, Integer> mMockedPermissions = new HashMap<>();
613 
mockStringResource(int resId)614         private void mockStringResource(int resId) {
615             doAnswer((inv) -> {
616                 return "Mock string resource ID=" + inv.getArgument(0);
617             }).when(mInternalResources).getString(resId);
618         }
619 
MockContext(Context base, ContentProvider settingsProvider)620         MockContext(Context base, ContentProvider settingsProvider) {
621             super(base);
622 
623             mInternalResources = spy(base.getResources());
624             doReturn(new String[] {
625                     "wifi,1,1,1,-1,true",
626                     "mobile,0,0,0,-1,true",
627                     "mobile_mms,2,0,2,60000,true",
628                     "mobile_supl,3,0,2,60000,true",
629             }).when(mInternalResources)
630                     .getStringArray(com.android.internal.R.array.networkAttributes);
631 
632             final int[] stringResourcesToMock = new int[] {
633                 com.android.internal.R.string.config_customVpnAlwaysOnDisconnectedDialogComponent,
634                 com.android.internal.R.string.vpn_lockdown_config,
635                 com.android.internal.R.string.vpn_lockdown_connected,
636                 com.android.internal.R.string.vpn_lockdown_connecting,
637                 com.android.internal.R.string.vpn_lockdown_disconnected,
638                 com.android.internal.R.string.vpn_lockdown_error,
639             };
640             for (int resId : stringResourcesToMock) {
641                 mockStringResource(resId);
642             }
643 
644             mContentResolver = new MockContentResolver();
645             mContentResolver.addProvider(Settings.AUTHORITY, settingsProvider);
646         }
647 
648         @Override
startActivityAsUser(Intent intent, UserHandle handle)649         public void startActivityAsUser(Intent intent, UserHandle handle) {
650             mStartedActivities.offer(intent);
651         }
652 
expectStartActivityIntent(int timeoutMs)653         public Intent expectStartActivityIntent(int timeoutMs) {
654             Intent intent = null;
655             try {
656                 intent = mStartedActivities.poll(timeoutMs, TimeUnit.MILLISECONDS);
657             } catch (InterruptedException e) {}
658             assertNotNull("Did not receive sign-in intent after " + timeoutMs + "ms", intent);
659             return intent;
660         }
661 
expectNoStartActivityIntent(int timeoutMs)662         public void expectNoStartActivityIntent(int timeoutMs) {
663             try {
664                 assertNull("Received unexpected Intent to start activity",
665                         mStartedActivities.poll(timeoutMs, TimeUnit.MILLISECONDS));
666             } catch (InterruptedException e) {}
667         }
668 
669         @Override
startService(Intent service)670         public ComponentName startService(Intent service) {
671             final String action = service.getAction();
672             if (!VpnConfig.SERVICE_INTERFACE.equals(action)
673                     && !ConstantsShim.ACTION_VPN_MANAGER_EVENT.equals(action)) {
674                 fail("Attempt to start unknown service, action=" + action);
675             }
676             return new ComponentName(service.getPackage(), "com.android.test.Service");
677         }
678 
679         @Override
getSystemService(String name)680         public Object getSystemService(String name) {
681             if (Context.CONNECTIVITY_SERVICE.equals(name)) return mCm;
682             if (Context.NOTIFICATION_SERVICE.equals(name)) return mNotificationManager;
683             if (Context.USER_SERVICE.equals(name)) return mUserManager;
684             if (Context.ALARM_SERVICE.equals(name)) return mAlarmManager;
685             if (Context.LOCATION_SERVICE.equals(name)) return mLocationManager;
686             if (Context.APP_OPS_SERVICE.equals(name)) return mAppOpsManager;
687             if (Context.TELEPHONY_SERVICE.equals(name)) return mTelephonyManager;
688             if (Context.ETHERNET_SERVICE.equals(name)) return mEthernetManager;
689             if (Context.NETWORK_POLICY_SERVICE.equals(name)) return mNetworkPolicyManager;
690             if (Context.DEVICE_POLICY_SERVICE.equals(name)) return mDevicePolicyManager;
691             if (Context.SYSTEM_CONFIG_SERVICE.equals(name)) return mSystemConfigManager;
692             if (Context.NETWORK_STATS_SERVICE.equals(name)) return mStatsManager;
693             if (Context.BATTERY_STATS_SERVICE.equals(name)) return mBatteryStatsManager;
694             if (Context.PAC_PROXY_SERVICE.equals(name)) return mPacProxyManager;
695             if (Context.TETHERING_SERVICE.equals(name)) return mTetheringManager;
696             return super.getSystemService(name);
697         }
698 
699         final HashMap<UserHandle, UserManager> mUserManagers = new HashMap<>();
700         @Override
createContextAsUser(UserHandle user, int flags)701         public Context createContextAsUser(UserHandle user, int flags) {
702             final Context asUser = mock(Context.class, AdditionalAnswers.delegatesTo(this));
703             doReturn(user).when(asUser).getUser();
704             doAnswer((inv) -> {
705                 final UserManager um = mUserManagers.computeIfAbsent(user,
706                         u -> mock(UserManager.class, AdditionalAnswers.delegatesTo(mUserManager)));
707                 return um;
708             }).when(asUser).getSystemService(Context.USER_SERVICE);
709             return asUser;
710         }
711 
setWorkProfile(@onNull final UserHandle userHandle, boolean value)712         public void setWorkProfile(@NonNull final UserHandle userHandle, boolean value) {
713             // This relies on all contexts for a given user returning the same UM mock
714             final UserManager umMock = createContextAsUser(userHandle, 0 /* flags */)
715                     .getSystemService(UserManager.class);
716             doReturn(value).when(umMock).isManagedProfile();
717             doReturn(value).when(mUserManager).isManagedProfile(eq(userHandle.getIdentifier()));
718         }
719 
setDeviceOwner(@onNull final UserHandle userHandle, String value)720         public void setDeviceOwner(@NonNull final UserHandle userHandle, String value) {
721             // This relies on all contexts for a given user returning the same UM mock
722             final DevicePolicyManager dpmMock = createContextAsUser(userHandle, 0 /* flags */)
723                     .getSystemService(DevicePolicyManager.class);
724             doReturn(value).when(dpmMock).getDeviceOwner();
725             doReturn(value).when(mDevicePolicyManager).getDeviceOwner();
726         }
727 
728         @Override
getContentResolver()729         public ContentResolver getContentResolver() {
730             return mContentResolver;
731         }
732 
733         @Override
getResources()734         public Resources getResources() {
735             return mInternalResources;
736         }
737 
738         @Override
getPackageManager()739         public PackageManager getPackageManager() {
740             return mPackageManager;
741         }
742 
checkMockedPermission(String permission, int pid, int uid, Supplier<Integer> ifAbsent)743         private int checkMockedPermission(String permission, int pid, int uid,
744                 Supplier<Integer> ifAbsent) {
745             final Integer granted = mMockedPermissions.get(permission + "," + pid + "," + uid);
746             if (null != granted) {
747                 return granted;
748             }
749             final Integer allGranted = mMockedPermissions.get(permission);
750             if (null != allGranted) {
751                 return allGranted;
752             }
753             return ifAbsent.get();
754         }
755 
756         @Override
checkPermission(String permission, int pid, int uid)757         public int checkPermission(String permission, int pid, int uid) {
758             return checkMockedPermission(permission, pid, uid,
759                     () -> super.checkPermission(permission, pid, uid));
760         }
761 
762         @Override
checkCallingOrSelfPermission(String permission)763         public int checkCallingOrSelfPermission(String permission) {
764             return checkMockedPermission(permission, Process.myPid(), Process.myUid(),
765                     () -> super.checkCallingOrSelfPermission(permission));
766         }
767 
768         @Override
enforceCallingOrSelfPermission(String permission, String message)769         public void enforceCallingOrSelfPermission(String permission, String message) {
770             final Integer granted = checkMockedPermission(permission,
771                     Process.myPid(), Process.myUid(),
772                     () -> {
773                         super.enforceCallingOrSelfPermission(permission, message);
774                         // enforce will crash if the permission is not granted
775                         return PERMISSION_GRANTED;
776                     });
777 
778             if (!granted.equals(PERMISSION_GRANTED)) {
779                 throw new SecurityException("[Test] permission denied: " + permission);
780             }
781         }
782 
783         /**
784          * Mock checks for the specified permission, and have them behave as per {@code granted}.
785          *
786          * This will apply across the board no matter what the checked UID and PID are.
787          *
788          * <p>Passing null reverts to default behavior, which does a real permission check on the
789          * test package.
790          * @param granted One of {@link PackageManager#PERMISSION_GRANTED} or
791          *                {@link PackageManager#PERMISSION_DENIED}.
792          */
setPermission(String permission, Integer granted)793         public void setPermission(String permission, Integer granted) {
794             mMockedPermissions.put(permission, granted);
795         }
796 
797         /**
798          * Mock checks for the specified permission, and have them behave as per {@code granted}.
799          *
800          * This will only apply to the passed UID and PID.
801          *
802          * <p>Passing null reverts to default behavior, which does a real permission check on the
803          * test package.
804          * @param granted One of {@link PackageManager#PERMISSION_GRANTED} or
805          *                {@link PackageManager#PERMISSION_DENIED}.
806          */
setPermission(String permission, int pid, int uid, Integer granted)807         public void setPermission(String permission, int pid, int uid, Integer granted) {
808             final String key = permission + "," + pid + "," + uid;
809             mMockedPermissions.put(key, granted);
810         }
811 
812         @Override
registerReceiverForAllUsers(@ullable BroadcastReceiver receiver, @NonNull IntentFilter filter, @Nullable String broadcastPermission, @Nullable Handler scheduler)813         public Intent registerReceiverForAllUsers(@Nullable BroadcastReceiver receiver,
814                 @NonNull IntentFilter filter, @Nullable String broadcastPermission,
815                 @Nullable Handler scheduler) {
816             // TODO: ensure MultinetworkPolicyTracker's BroadcastReceiver is tested; just returning
817             // null should not pass the test
818             return null;
819         }
820     }
821 
822     // This was only added in the T SDK, but this test needs to build against the R+S SDKs, too.
toSdkSandboxUid(int appUid)823     private static int toSdkSandboxUid(int appUid) {
824         final int firstSdkSandboxUid = 20000;
825         return appUid + (firstSdkSandboxUid - Process.FIRST_APPLICATION_UID);
826     }
827 
828     // This function assumes the UID range for user 0 ([1, 99999])
uidRangeParcelsExcludingUids(Integer... excludedUids)829     private static UidRangeParcel[] uidRangeParcelsExcludingUids(Integer... excludedUids) {
830         int start = 1;
831         Arrays.sort(excludedUids);
832         List<UidRangeParcel> parcels = new ArrayList<UidRangeParcel>();
833         for (int excludedUid : excludedUids) {
834             if (excludedUid == start) {
835                 start++;
836             } else {
837                 parcels.add(new UidRangeParcel(start, excludedUid - 1));
838                 start = excludedUid + 1;
839             }
840         }
841         if (start <= 99999) {
842             parcels.add(new UidRangeParcel(start, 99999));
843         }
844 
845         return parcels.toArray(new UidRangeParcel[0]);
846     }
847 
waitForIdle()848     private void waitForIdle() {
849         HandlerUtils.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
850         waitForIdle(mCellNetworkAgent, TIMEOUT_MS);
851         waitForIdle(mWiFiNetworkAgent, TIMEOUT_MS);
852         waitForIdle(mEthernetNetworkAgent, TIMEOUT_MS);
853         HandlerUtils.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
854         HandlerUtils.waitForIdle(ConnectivityThread.get(), TIMEOUT_MS);
855     }
856 
waitForIdle(TestNetworkAgentWrapper agent, long timeoutMs)857     private void waitForIdle(TestNetworkAgentWrapper agent, long timeoutMs) {
858         if (agent == null) {
859             return;
860         }
861         agent.waitForIdle(timeoutMs);
862     }
863 
864     @Test
testWaitForIdle()865     public void testWaitForIdle() throws Exception {
866         final int attempts = 50;  // Causes the test to take about 200ms on bullhead-eng.
867 
868         // Tests that waitForIdle returns immediately if the service is already idle.
869         for (int i = 0; i < attempts; i++) {
870             waitForIdle();
871         }
872 
873         // Bring up a network that we can use to send messages to ConnectivityService.
874         ExpectedBroadcast b = expectConnectivityAction(TYPE_WIFI, DetailedState.CONNECTED);
875         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
876         mWiFiNetworkAgent.connect(false);
877         b.expectBroadcast();
878         Network n = mWiFiNetworkAgent.getNetwork();
879         assertNotNull(n);
880 
881         // Tests that calling waitForIdle waits for messages to be processed.
882         for (int i = 0; i < attempts; i++) {
883             mWiFiNetworkAgent.setSignalStrength(i);
884             waitForIdle();
885             assertEquals(i, mCm.getNetworkCapabilities(n).getSignalStrength());
886         }
887     }
888 
889     // This test has an inherent race condition in it, and cannot be enabled for continuous testing
890     // or presubmit tests. It is kept for manual runs and documentation purposes.
891     @Ignore
verifyThatNotWaitingForIdleCausesRaceConditions()892     public void verifyThatNotWaitingForIdleCausesRaceConditions() throws Exception {
893         // Bring up a network that we can use to send messages to ConnectivityService.
894         ExpectedBroadcast b = expectConnectivityAction(TYPE_WIFI, DetailedState.CONNECTED);
895         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
896         mWiFiNetworkAgent.connect(false);
897         b.expectBroadcast();
898         Network n = mWiFiNetworkAgent.getNetwork();
899         assertNotNull(n);
900 
901         // Ensure that not calling waitForIdle causes a race condition.
902         final int attempts = 50;  // Causes the test to take about 200ms on bullhead-eng.
903         for (int i = 0; i < attempts; i++) {
904             mWiFiNetworkAgent.setSignalStrength(i);
905             if (i != mCm.getNetworkCapabilities(n).getSignalStrength()) {
906                 // We hit a race condition, as expected. Pass the test.
907                 return;
908             }
909         }
910 
911         // No race? There is a bug in this test.
912         fail("expected race condition at least once in " + attempts + " attempts");
913     }
914 
915     private class TestNetworkAgentWrapper extends NetworkAgentWrapper {
916         private static final int VALIDATION_RESULT_INVALID = 0;
917 
918         private static final long DATA_STALL_TIMESTAMP = 10L;
919         private static final int DATA_STALL_DETECTION_METHOD = 1;
920 
921         private INetworkMonitor mNetworkMonitor;
922         private INetworkMonitorCallbacks mNmCallbacks;
923         private int mNmValidationResult = VALIDATION_RESULT_INVALID;
924         private int mProbesCompleted;
925         private int mProbesSucceeded;
926         private String mNmValidationRedirectUrl = null;
927         private boolean mNmProvNotificationRequested = false;
928         private Runnable mCreatedCallback;
929         private Runnable mUnwantedCallback;
930         private Runnable mDisconnectedCallback;
931 
932         private final ConditionVariable mNetworkStatusReceived = new ConditionVariable();
933         // Contains the redirectUrl from networkStatus(). Before reading, wait for
934         // mNetworkStatusReceived.
935         private String mRedirectUrl;
936 
TestNetworkAgentWrapper(int transport)937         TestNetworkAgentWrapper(int transport) throws Exception {
938             this(transport, new LinkProperties(), null /* ncTemplate */, null /* provider */);
939         }
940 
TestNetworkAgentWrapper(int transport, LinkProperties linkProperties)941         TestNetworkAgentWrapper(int transport, LinkProperties linkProperties)
942                 throws Exception {
943             this(transport, linkProperties, null /* ncTemplate */, null /* provider */);
944         }
945 
TestNetworkAgentWrapper(int transport, LinkProperties linkProperties, NetworkCapabilities ncTemplate)946         private TestNetworkAgentWrapper(int transport, LinkProperties linkProperties,
947                 NetworkCapabilities ncTemplate) throws Exception {
948             this(transport, linkProperties, ncTemplate, null /* provider */);
949         }
950 
TestNetworkAgentWrapper(int transport, LinkProperties linkProperties, NetworkCapabilities ncTemplate, NetworkProvider provider)951         private TestNetworkAgentWrapper(int transport, LinkProperties linkProperties,
952                 NetworkCapabilities ncTemplate, NetworkProvider provider) throws Exception {
953             super(transport, linkProperties, ncTemplate, provider, mServiceContext);
954 
955             // Waits for the NetworkAgent to be registered, which includes the creation of the
956             // NetworkMonitor.
957             waitForIdle(TIMEOUT_MS);
958             HandlerUtils.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
959             HandlerUtils.waitForIdle(ConnectivityThread.get(), TIMEOUT_MS);
960         }
961 
962         class TestInstrumentedNetworkAgent extends InstrumentedNetworkAgent {
TestInstrumentedNetworkAgent(NetworkAgentWrapper wrapper, LinkProperties lp, NetworkAgentConfig nac, NetworkProvider provider)963             TestInstrumentedNetworkAgent(NetworkAgentWrapper wrapper, LinkProperties lp,
964                     NetworkAgentConfig nac, NetworkProvider provider) {
965                 super(wrapper, lp, nac, provider);
966             }
967 
968             @Override
networkStatus(int status, String redirectUrl)969             public void networkStatus(int status, String redirectUrl) {
970                 mRedirectUrl = redirectUrl;
971                 mNetworkStatusReceived.open();
972             }
973 
974             @Override
onNetworkCreated()975             public void onNetworkCreated() {
976                 super.onNetworkCreated();
977                 if (mCreatedCallback != null) mCreatedCallback.run();
978             }
979 
980             @Override
onNetworkUnwanted()981             public void onNetworkUnwanted() {
982                 super.onNetworkUnwanted();
983                 if (mUnwantedCallback != null) mUnwantedCallback.run();
984             }
985 
986             @Override
onNetworkDestroyed()987             public void onNetworkDestroyed() {
988                 super.onNetworkDestroyed();
989                 if (mDisconnectedCallback != null) mDisconnectedCallback.run();
990             }
991         }
992 
993         @Override
makeNetworkAgent(LinkProperties linkProperties, NetworkAgentConfig nac, NetworkProvider provider)994         protected InstrumentedNetworkAgent makeNetworkAgent(LinkProperties linkProperties,
995                 NetworkAgentConfig nac, NetworkProvider provider) throws Exception {
996             mNetworkMonitor = mock(INetworkMonitor.class);
997 
998             final Answer validateAnswer = inv -> {
999                 new Thread(ignoreExceptions(this::onValidationRequested)).start();
1000                 return null;
1001             };
1002 
1003             doAnswer(validateAnswer).when(mNetworkMonitor).notifyNetworkConnected(any(), any());
1004             doAnswer(validateAnswer).when(mNetworkMonitor).notifyNetworkConnectedParcel(any());
1005             doAnswer(validateAnswer).when(mNetworkMonitor).forceReevaluation(anyInt());
1006 
1007             final ArgumentCaptor<Network> nmNetworkCaptor = ArgumentCaptor.forClass(Network.class);
1008             final ArgumentCaptor<INetworkMonitorCallbacks> nmCbCaptor =
1009                     ArgumentCaptor.forClass(INetworkMonitorCallbacks.class);
1010             doNothing().when(mNetworkStack).makeNetworkMonitor(
1011                     nmNetworkCaptor.capture(),
1012                     any() /* name */,
1013                     nmCbCaptor.capture());
1014 
1015             final InstrumentedNetworkAgent na =
1016                     new TestInstrumentedNetworkAgent(this, linkProperties, nac, provider);
1017 
1018             assertEquals(na.getNetwork().netId, nmNetworkCaptor.getValue().netId);
1019             mNmCallbacks = nmCbCaptor.getValue();
1020 
1021             mNmCallbacks.onNetworkMonitorCreated(mNetworkMonitor);
1022 
1023             return na;
1024         }
1025 
onValidationRequested()1026         private void onValidationRequested() throws Exception {
1027             if (SdkLevel.isAtLeastT()) {
1028                 verify(mNetworkMonitor).notifyNetworkConnectedParcel(any());
1029             } else {
1030                 verify(mNetworkMonitor).notifyNetworkConnected(any(), any());
1031             }
1032             if (mNmProvNotificationRequested
1033                     && ((mNmValidationResult & NETWORK_VALIDATION_RESULT_VALID) != 0)) {
1034                 mNmCallbacks.hideProvisioningNotification();
1035                 mNmProvNotificationRequested = false;
1036             }
1037 
1038             mNmCallbacks.notifyProbeStatusChanged(mProbesCompleted, mProbesSucceeded);
1039             final NetworkTestResultParcelable p = new NetworkTestResultParcelable();
1040             p.result = mNmValidationResult;
1041             p.probesAttempted = mProbesCompleted;
1042             p.probesSucceeded = mProbesSucceeded;
1043             p.redirectUrl = mNmValidationRedirectUrl;
1044             p.timestampMillis = TIMESTAMP;
1045             mNmCallbacks.notifyNetworkTestedWithExtras(p);
1046 
1047             if (mNmValidationRedirectUrl != null) {
1048                 mNmCallbacks.showProvisioningNotification(
1049                         "test_provisioning_notif_action", TEST_PACKAGE_NAME);
1050                 mNmProvNotificationRequested = true;
1051             }
1052         }
1053 
1054         /**
1055          * Connect without adding any internet capability.
1056          */
connectWithoutInternet()1057         public void connectWithoutInternet() {
1058             super.connect();
1059         }
1060 
1061         /**
1062          * Transition this NetworkAgent to CONNECTED state with NET_CAPABILITY_INTERNET.
1063          * @param validated Indicate if network should pretend to be validated.
1064          */
connect(boolean validated)1065         public void connect(boolean validated) {
1066             connect(validated, true, false /* isStrictMode */);
1067         }
1068 
1069         /**
1070          * Transition this NetworkAgent to CONNECTED state.
1071          * @param validated Indicate if network should pretend to be validated.
1072          * @param hasInternet Indicate if network should pretend to have NET_CAPABILITY_INTERNET.
1073          */
connect(boolean validated, boolean hasInternet, boolean isStrictMode)1074         public void connect(boolean validated, boolean hasInternet, boolean isStrictMode) {
1075             ConnectivityManager.NetworkCallback callback = null;
1076             final ConditionVariable validatedCv = new ConditionVariable();
1077             if (validated) {
1078                 setNetworkValid(isStrictMode);
1079                 NetworkRequest request = new NetworkRequest.Builder()
1080                         .addTransportType(getNetworkCapabilities().getTransportTypes()[0])
1081                         .clearCapabilities()
1082                         .build();
1083                 callback = new ConnectivityManager.NetworkCallback() {
1084                     public void onCapabilitiesChanged(Network network,
1085                             NetworkCapabilities networkCapabilities) {
1086                         if (network.equals(getNetwork()) &&
1087                                 networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED)) {
1088                             validatedCv.open();
1089                         }
1090                     }
1091                 };
1092                 mCm.registerNetworkCallback(request, callback);
1093             }
1094             if (hasInternet) {
1095                 addCapability(NET_CAPABILITY_INTERNET);
1096             }
1097 
1098             connectWithoutInternet();
1099 
1100             if (validated) {
1101                 // Wait for network to validate.
1102                 waitFor(validatedCv);
1103                 setNetworkInvalid(isStrictMode);
1104             }
1105 
1106             if (callback != null) mCm.unregisterNetworkCallback(callback);
1107         }
1108 
connectWithCaptivePortal(String redirectUrl, boolean isStrictMode)1109         public void connectWithCaptivePortal(String redirectUrl, boolean isStrictMode) {
1110             setNetworkPortal(redirectUrl, isStrictMode);
1111             connect(false, true /* hasInternet */, isStrictMode);
1112         }
1113 
connectWithPartialConnectivity()1114         public void connectWithPartialConnectivity() {
1115             setNetworkPartial();
1116             connect(false);
1117         }
1118 
connectWithPartialValidConnectivity(boolean isStrictMode)1119         public void connectWithPartialValidConnectivity(boolean isStrictMode) {
1120             setNetworkPartialValid(isStrictMode);
1121             connect(false, true /* hasInternet */, isStrictMode);
1122         }
1123 
setNetworkValid(boolean isStrictMode)1124         void setNetworkValid(boolean isStrictMode) {
1125             mNmValidationResult = NETWORK_VALIDATION_RESULT_VALID;
1126             mNmValidationRedirectUrl = null;
1127             int probesSucceeded = NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_HTTPS;
1128             if (isStrictMode) {
1129                 probesSucceeded |= NETWORK_VALIDATION_PROBE_PRIVDNS;
1130             }
1131             // The probesCompleted equals to probesSucceeded for the case of valid network, so put
1132             // the same value into two different parameter of the method.
1133             setProbesStatus(probesSucceeded, probesSucceeded);
1134         }
1135 
setNetworkInvalid(boolean isStrictMode)1136         void setNetworkInvalid(boolean isStrictMode) {
1137             mNmValidationResult = VALIDATION_RESULT_INVALID;
1138             mNmValidationRedirectUrl = null;
1139             int probesCompleted = NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_HTTPS
1140                     | NETWORK_VALIDATION_PROBE_HTTP;
1141             int probesSucceeded = 0;
1142             // If the isStrictMode is true, it means the network is invalid when NetworkMonitor
1143             // tried to validate the private DNS but failed.
1144             if (isStrictMode) {
1145                 probesCompleted &= ~NETWORK_VALIDATION_PROBE_HTTP;
1146                 probesSucceeded = probesCompleted;
1147                 probesCompleted |= NETWORK_VALIDATION_PROBE_PRIVDNS;
1148             }
1149             setProbesStatus(probesCompleted, probesSucceeded);
1150         }
1151 
setNetworkPortal(String redirectUrl, boolean isStrictMode)1152         void setNetworkPortal(String redirectUrl, boolean isStrictMode) {
1153             setNetworkInvalid(isStrictMode);
1154             mNmValidationRedirectUrl = redirectUrl;
1155             // Suppose the portal is found when NetworkMonitor probes NETWORK_VALIDATION_PROBE_HTTP
1156             // in the beginning, so the NETWORK_VALIDATION_PROBE_HTTPS hasn't probed yet.
1157             int probesCompleted = NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_HTTP;
1158             int probesSucceeded = VALIDATION_RESULT_INVALID;
1159             if (isStrictMode) {
1160                 probesCompleted |= NETWORK_VALIDATION_PROBE_PRIVDNS;
1161             }
1162             setProbesStatus(probesCompleted, probesSucceeded);
1163         }
1164 
setNetworkPartial()1165         void setNetworkPartial() {
1166             mNmValidationResult = NETWORK_VALIDATION_RESULT_PARTIAL;
1167             mNmValidationRedirectUrl = null;
1168             int probesCompleted = NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_HTTPS
1169                     | NETWORK_VALIDATION_PROBE_FALLBACK;
1170             int probesSucceeded = NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_FALLBACK;
1171             setProbesStatus(probesCompleted, probesSucceeded);
1172         }
1173 
setNetworkPartialValid(boolean isStrictMode)1174         void setNetworkPartialValid(boolean isStrictMode) {
1175             setNetworkPartial();
1176             mNmValidationResult |= NETWORK_VALIDATION_RESULT_VALID;
1177             int probesCompleted = NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_HTTPS
1178                     | NETWORK_VALIDATION_PROBE_HTTP;
1179             int probesSucceeded = NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_HTTP;
1180             // Suppose the partial network cannot pass the private DNS validation as well, so only
1181             // add NETWORK_VALIDATION_PROBE_DNS in probesCompleted but not probesSucceeded.
1182             if (isStrictMode) {
1183                 probesCompleted |= NETWORK_VALIDATION_PROBE_PRIVDNS;
1184             }
1185             setProbesStatus(probesCompleted, probesSucceeded);
1186         }
1187 
setProbesStatus(int probesCompleted, int probesSucceeded)1188         void setProbesStatus(int probesCompleted, int probesSucceeded) {
1189             mProbesCompleted = probesCompleted;
1190             mProbesSucceeded = probesSucceeded;
1191         }
1192 
notifyCapportApiDataChanged(CaptivePortalData data)1193         void notifyCapportApiDataChanged(CaptivePortalData data) {
1194             try {
1195                 mNmCallbacks.notifyCaptivePortalDataChanged(data);
1196             } catch (RemoteException e) {
1197                 throw new AssertionError("This cannot happen", e);
1198             }
1199         }
1200 
waitForRedirectUrl()1201         public String waitForRedirectUrl() {
1202             assertTrue(mNetworkStatusReceived.block(TIMEOUT_MS));
1203             return mRedirectUrl;
1204         }
1205 
expectDisconnected()1206         public void expectDisconnected() {
1207             expectDisconnected(TIMEOUT_MS);
1208         }
1209 
expectPreventReconnectReceived()1210         public void expectPreventReconnectReceived() {
1211             expectPreventReconnectReceived(TIMEOUT_MS);
1212         }
1213 
notifyDataStallSuspected()1214         void notifyDataStallSuspected() throws Exception {
1215             final DataStallReportParcelable p = new DataStallReportParcelable();
1216             p.detectionMethod = DATA_STALL_DETECTION_METHOD;
1217             p.timestampMillis = DATA_STALL_TIMESTAMP;
1218             mNmCallbacks.notifyDataStallSuspected(p);
1219         }
1220 
setCreatedCallback(Runnable r)1221         public void setCreatedCallback(Runnable r) {
1222             mCreatedCallback = r;
1223         }
1224 
setUnwantedCallback(Runnable r)1225         public void setUnwantedCallback(Runnable r) {
1226             mUnwantedCallback = r;
1227         }
1228 
setDisconnectedCallback(Runnable r)1229         public void setDisconnectedCallback(Runnable r) {
1230             mDisconnectedCallback = r;
1231         }
1232     }
1233 
1234     /**
1235      * A NetworkFactory that allows to wait until any in-flight NetworkRequest add or remove
1236      * operations have been processed and test for them.
1237      */
1238     private static class MockNetworkFactory extends NetworkFactory {
1239         private final AtomicBoolean mNetworkStarted = new AtomicBoolean(false);
1240 
1241         static class RequestEntry {
1242             @NonNull
1243             public final NetworkRequest request;
1244 
RequestEntry(@onNull final NetworkRequest request)1245             RequestEntry(@NonNull final NetworkRequest request) {
1246                 this.request = request;
1247             }
1248 
1249             static final class Add extends RequestEntry {
Add(@onNull final NetworkRequest request)1250                 Add(@NonNull final NetworkRequest request) {
1251                     super(request);
1252                 }
1253             }
1254 
1255             static final class Remove extends RequestEntry {
Remove(@onNull final NetworkRequest request)1256                 Remove(@NonNull final NetworkRequest request) {
1257                     super(request);
1258                 }
1259             }
1260 
1261             @Override
toString()1262             public String toString() {
1263                 return "RequestEntry [ " + getClass().getName() + " : " + request + " ]";
1264             }
1265         }
1266 
1267         // History of received requests adds and removes.
1268         private final ArrayTrackRecord<RequestEntry>.ReadHead mRequestHistory =
1269                 new ArrayTrackRecord<RequestEntry>().newReadHead();
1270 
failIfNull(@ullable final T obj, @Nullable final String message)1271         private static <T> T failIfNull(@Nullable final T obj, @Nullable final String message) {
1272             if (null == obj) fail(null != message ? message : "Must not be null");
1273             return obj;
1274         }
1275 
expectRequestAdd()1276         public RequestEntry.Add expectRequestAdd() {
1277             return failIfNull((RequestEntry.Add) mRequestHistory.poll(TIMEOUT_MS,
1278                     it -> it instanceof RequestEntry.Add), "Expected request add");
1279         }
1280 
expectRequestAdds(final int count)1281         public void expectRequestAdds(final int count) {
1282             for (int i = count; i > 0; --i) {
1283                 expectRequestAdd();
1284             }
1285         }
1286 
expectRequestRemove()1287         public RequestEntry.Remove expectRequestRemove() {
1288             return failIfNull((RequestEntry.Remove) mRequestHistory.poll(TIMEOUT_MS,
1289                     it -> it instanceof RequestEntry.Remove), "Expected request remove");
1290         }
1291 
expectRequestRemoves(final int count)1292         public void expectRequestRemoves(final int count) {
1293             for (int i = count; i > 0; --i) {
1294                 expectRequestRemove();
1295             }
1296         }
1297 
1298         // Used to collect the networks requests managed by this factory. This is a duplicate of
1299         // the internal information stored in the NetworkFactory (which is private).
1300         private SparseArray<NetworkRequest> mNetworkRequests = new SparseArray<>();
1301         private final HandlerThread mHandlerSendingRequests;
1302 
MockNetworkFactory(Looper looper, Context context, String logTag, NetworkCapabilities filter, HandlerThread threadSendingRequests)1303         public MockNetworkFactory(Looper looper, Context context, String logTag,
1304                 NetworkCapabilities filter, HandlerThread threadSendingRequests) {
1305             super(looper, context, logTag, filter);
1306             mHandlerSendingRequests = threadSendingRequests;
1307         }
1308 
getMyRequestCount()1309         public int getMyRequestCount() {
1310             return getRequestCount();
1311         }
1312 
startNetwork()1313         protected void startNetwork() {
1314             mNetworkStarted.set(true);
1315         }
1316 
stopNetwork()1317         protected void stopNetwork() {
1318             mNetworkStarted.set(false);
1319         }
1320 
getMyStartRequested()1321         public boolean getMyStartRequested() {
1322             return mNetworkStarted.get();
1323         }
1324 
1325 
1326         @Override
needNetworkFor(NetworkRequest request)1327         protected void needNetworkFor(NetworkRequest request) {
1328             mNetworkRequests.put(request.requestId, request);
1329             super.needNetworkFor(request);
1330             mRequestHistory.add(new RequestEntry.Add(request));
1331         }
1332 
1333         @Override
releaseNetworkFor(NetworkRequest request)1334         protected void releaseNetworkFor(NetworkRequest request) {
1335             mNetworkRequests.remove(request.requestId);
1336             super.releaseNetworkFor(request);
1337             mRequestHistory.add(new RequestEntry.Remove(request));
1338         }
1339 
assertRequestCountEquals(final int count)1340         public void assertRequestCountEquals(final int count) {
1341             assertEquals(count, getMyRequestCount());
1342         }
1343 
1344         // Trigger releasing the request as unfulfillable
triggerUnfulfillable(NetworkRequest r)1345         public void triggerUnfulfillable(NetworkRequest r) {
1346             super.releaseRequestAsUnfulfillableByAnyFactory(r);
1347         }
1348 
assertNoRequestChanged()1349         public void assertNoRequestChanged() {
1350             // Make sure there are no remaining requests unaccounted for.
1351             HandlerUtils.waitForIdle(mHandlerSendingRequests, TIMEOUT_MS);
1352             assertNull(mRequestHistory.poll(0, r -> true));
1353         }
1354     }
1355 
uidRangesForUids(int... uids)1356     private Set<UidRange> uidRangesForUids(int... uids) {
1357         final ArraySet<UidRange> ranges = new ArraySet<>();
1358         for (final int uid : uids) {
1359             ranges.add(new UidRange(uid, uid));
1360         }
1361         return ranges;
1362     }
1363 
uidRangesForUids(Collection<Integer> uids)1364     private Set<UidRange> uidRangesForUids(Collection<Integer> uids) {
1365         return uidRangesForUids(CollectionUtils.toIntArray(uids));
1366     }
1367 
startHandlerThreadAndReturnLooper()1368     private static Looper startHandlerThreadAndReturnLooper() {
1369         final HandlerThread handlerThread = new HandlerThread("MockVpnThread");
1370         handlerThread.start();
1371         return handlerThread.getLooper();
1372     }
1373 
1374     private class MockVpn extends Vpn implements TestableNetworkCallback.HasNetwork {
1375         // Careful ! This is different from mNetworkAgent, because MockNetworkAgent does
1376         // not inherit from NetworkAgent.
1377         private TestNetworkAgentWrapper mMockNetworkAgent;
1378         private boolean mAgentRegistered = false;
1379 
1380         private int mVpnType = VpnManager.TYPE_VPN_SERVICE;
1381         private UnderlyingNetworkInfo mUnderlyingNetworkInfo;
1382 
1383         // These ConditionVariables allow tests to wait for LegacyVpnRunner to be stopped/started.
1384         // TODO: this scheme is ad-hoc and error-prone because it does not fail if, for example, the
1385         // test expects two starts in a row, or even if the production code calls start twice in a
1386         // row. find a better solution. Simply putting a method to create a LegacyVpnRunner into
1387         // Vpn.Dependencies doesn't work because LegacyVpnRunner is not a static class and has
1388         // extensive access into the internals of Vpn.
1389         private ConditionVariable mStartLegacyVpnCv = new ConditionVariable();
1390         private ConditionVariable mStopVpnRunnerCv = new ConditionVariable();
1391 
MockVpn(int userId)1392         public MockVpn(int userId) {
1393             super(startHandlerThreadAndReturnLooper(), mServiceContext,
1394                     new Dependencies() {
1395                         @Override
1396                         public boolean isCallerSystem() {
1397                             return true;
1398                         }
1399 
1400                         @Override
1401                         public DeviceIdleInternal getDeviceIdleInternal() {
1402                             return mDeviceIdleInternal;
1403                         }
1404                     },
1405                     mNetworkManagementService, mMockNetd, userId, mVpnProfileStore,
1406                     new SystemServices(mServiceContext) {
1407                         @Override
1408                         public String settingsSecureGetStringForUser(String key, int userId) {
1409                             switch (key) {
1410                                 // Settings keys not marked as @Readable are not readable from
1411                                 // non-privileged apps, unless marked as testOnly=true
1412                                 // (atest refuses to install testOnly=true apps), even if mocked
1413                                 // in the content provider, because
1414                                 // Settings.Secure.NameValueCache#getStringForUser checks the key
1415                                 // before querying the mock settings provider.
1416                                 case Settings.Secure.ALWAYS_ON_VPN_APP:
1417                                     return null;
1418                                 default:
1419                                     return super.settingsSecureGetStringForUser(key, userId);
1420                             }
1421                         }
1422                     }, new Ikev2SessionCreator());
1423         }
1424 
setUids(Set<UidRange> uids)1425         public void setUids(Set<UidRange> uids) {
1426             mNetworkCapabilities.setUids(UidRange.toIntRanges(uids));
1427             if (mAgentRegistered) {
1428                 mMockNetworkAgent.setNetworkCapabilities(mNetworkCapabilities, true);
1429             }
1430         }
1431 
setVpnType(int vpnType)1432         public void setVpnType(int vpnType) {
1433             mVpnType = vpnType;
1434         }
1435 
1436         @Override
getNetwork()1437         public Network getNetwork() {
1438             return (mMockNetworkAgent == null) ? null : mMockNetworkAgent.getNetwork();
1439         }
1440 
getNetworkAgentConfig()1441         public NetworkAgentConfig getNetworkAgentConfig() {
1442             return null == mMockNetworkAgent ? null : mMockNetworkAgent.getNetworkAgentConfig();
1443         }
1444 
1445         @Override
getActiveVpnType()1446         public int getActiveVpnType() {
1447             return mVpnType;
1448         }
1449 
makeLinkProperties()1450         private LinkProperties makeLinkProperties() {
1451             final LinkProperties lp = new LinkProperties();
1452             lp.setInterfaceName(VPN_IFNAME);
1453             return lp;
1454         }
1455 
registerAgent(boolean isAlwaysMetered, Set<UidRange> uids, LinkProperties lp)1456         private void registerAgent(boolean isAlwaysMetered, Set<UidRange> uids, LinkProperties lp)
1457                 throws Exception {
1458             if (mAgentRegistered) throw new IllegalStateException("already registered");
1459             updateState(NetworkInfo.DetailedState.CONNECTING, "registerAgent");
1460             mConfig = new VpnConfig();
1461             mConfig.session = "MySession12345";
1462             setUids(uids);
1463             if (!isAlwaysMetered) mNetworkCapabilities.addCapability(NET_CAPABILITY_NOT_METERED);
1464             mInterface = VPN_IFNAME;
1465             mNetworkCapabilities.setTransportInfo(new VpnTransportInfo(getActiveVpnType(),
1466                     mConfig.session));
1467             mMockNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN, lp,
1468                     mNetworkCapabilities);
1469             mMockNetworkAgent.waitForIdle(TIMEOUT_MS);
1470 
1471             verify(mMockNetd, times(1)).networkAddUidRangesParcel(
1472                     new NativeUidRangeConfig(mMockVpn.getNetwork().getNetId(),
1473                             toUidRangeStableParcels(uids), PREFERENCE_ORDER_VPN));
1474             verify(mMockNetd, never()).networkRemoveUidRangesParcel(argThat(config ->
1475                     mMockVpn.getNetwork().getNetId() == config.netId
1476                             && PREFERENCE_ORDER_VPN == config.subPriority));
1477             mAgentRegistered = true;
1478             verify(mMockNetd).networkCreate(nativeNetworkConfigVpn(getNetwork().netId,
1479                     !mMockNetworkAgent.isBypassableVpn(), mVpnType));
1480             updateState(NetworkInfo.DetailedState.CONNECTED, "registerAgent");
1481             mNetworkCapabilities.set(mMockNetworkAgent.getNetworkCapabilities());
1482             mNetworkAgent = mMockNetworkAgent.getNetworkAgent();
1483         }
1484 
registerAgent(Set<UidRange> uids)1485         private void registerAgent(Set<UidRange> uids) throws Exception {
1486             registerAgent(false /* isAlwaysMetered */, uids, makeLinkProperties());
1487         }
1488 
connect(boolean validated, boolean hasInternet, boolean isStrictMode)1489         private void connect(boolean validated, boolean hasInternet, boolean isStrictMode) {
1490             mMockNetworkAgent.connect(validated, hasInternet, isStrictMode);
1491         }
1492 
connect(boolean validated)1493         private void connect(boolean validated) {
1494             mMockNetworkAgent.connect(validated);
1495         }
1496 
getAgent()1497         private TestNetworkAgentWrapper getAgent() {
1498             return mMockNetworkAgent;
1499         }
1500 
setOwnerAndAdminUid(int uid)1501         private void setOwnerAndAdminUid(int uid) throws Exception {
1502             mNetworkCapabilities.setOwnerUid(uid);
1503             mNetworkCapabilities.setAdministratorUids(new int[]{uid});
1504         }
1505 
establish(LinkProperties lp, int uid, Set<UidRange> ranges, boolean validated, boolean hasInternet, boolean isStrictMode)1506         public void establish(LinkProperties lp, int uid, Set<UidRange> ranges, boolean validated,
1507                 boolean hasInternet, boolean isStrictMode) throws Exception {
1508             setOwnerAndAdminUid(uid);
1509             registerAgent(false, ranges, lp);
1510             connect(validated, hasInternet, isStrictMode);
1511             waitForIdle();
1512         }
1513 
establish(LinkProperties lp, int uid, Set<UidRange> ranges)1514         public void establish(LinkProperties lp, int uid, Set<UidRange> ranges) throws Exception {
1515             establish(lp, uid, ranges, true, true, false);
1516         }
1517 
establishForMyUid(LinkProperties lp)1518         public void establishForMyUid(LinkProperties lp) throws Exception {
1519             final int uid = Process.myUid();
1520             establish(lp, uid, uidRangesForUids(uid), true, true, false);
1521         }
1522 
establishForMyUid(boolean validated, boolean hasInternet, boolean isStrictMode)1523         public void establishForMyUid(boolean validated, boolean hasInternet, boolean isStrictMode)
1524                 throws Exception {
1525             final int uid = Process.myUid();
1526             establish(makeLinkProperties(), uid, uidRangesForUids(uid), validated, hasInternet,
1527                     isStrictMode);
1528         }
1529 
establishForMyUid()1530         public void establishForMyUid() throws Exception {
1531             establishForMyUid(makeLinkProperties());
1532         }
1533 
sendLinkProperties(LinkProperties lp)1534         public void sendLinkProperties(LinkProperties lp) {
1535             mMockNetworkAgent.sendLinkProperties(lp);
1536         }
1537 
disconnect()1538         public void disconnect() {
1539             if (mMockNetworkAgent != null) {
1540                 mMockNetworkAgent.disconnect();
1541                 updateState(NetworkInfo.DetailedState.DISCONNECTED, "disconnect");
1542             }
1543             mAgentRegistered = false;
1544             setUids(null);
1545             // Remove NET_CAPABILITY_INTERNET or MockNetworkAgent will refuse to connect later on.
1546             mNetworkCapabilities.removeCapability(NET_CAPABILITY_INTERNET);
1547             mInterface = null;
1548         }
1549 
1550         @Override
startLegacyVpnRunner()1551         public void startLegacyVpnRunner() {
1552             mStartLegacyVpnCv.open();
1553         }
1554 
expectStartLegacyVpnRunner()1555         public void expectStartLegacyVpnRunner() {
1556             assertTrue("startLegacyVpnRunner not called after " + TIMEOUT_MS + " ms",
1557                     mStartLegacyVpnCv.block(TIMEOUT_MS));
1558 
1559             // startLegacyVpn calls stopVpnRunnerPrivileged, which will open mStopVpnRunnerCv, just
1560             // before calling startLegacyVpnRunner. Restore mStopVpnRunnerCv, so the test can expect
1561             // that the VpnRunner is stopped and immediately restarted by calling
1562             // expectStartLegacyVpnRunner() and expectStopVpnRunnerPrivileged() back-to-back.
1563             mStopVpnRunnerCv = new ConditionVariable();
1564         }
1565 
1566         @Override
stopVpnRunnerPrivileged()1567         public void stopVpnRunnerPrivileged() {
1568             if (mVpnRunner != null) {
1569                 super.stopVpnRunnerPrivileged();
1570                 disconnect();
1571                 mStartLegacyVpnCv = new ConditionVariable();
1572             }
1573             mVpnRunner = null;
1574             mStopVpnRunnerCv.open();
1575         }
1576 
expectStopVpnRunnerPrivileged()1577         public void expectStopVpnRunnerPrivileged() {
1578             assertTrue("stopVpnRunnerPrivileged not called after " + TIMEOUT_MS + " ms",
1579                     mStopVpnRunnerCv.block(TIMEOUT_MS));
1580         }
1581 
1582         @Override
getUnderlyingNetworkInfo()1583         public synchronized UnderlyingNetworkInfo getUnderlyingNetworkInfo() {
1584             if (mUnderlyingNetworkInfo != null) return mUnderlyingNetworkInfo;
1585 
1586             return super.getUnderlyingNetworkInfo();
1587         }
1588 
setUnderlyingNetworkInfo( UnderlyingNetworkInfo underlyingNetworkInfo)1589         private synchronized void setUnderlyingNetworkInfo(
1590                 UnderlyingNetworkInfo underlyingNetworkInfo) {
1591             mUnderlyingNetworkInfo = underlyingNetworkInfo;
1592         }
1593     }
1594 
toUidRangeStableParcels(final @NonNull Set<UidRange> ranges)1595     private UidRangeParcel[] toUidRangeStableParcels(final @NonNull Set<UidRange> ranges) {
1596         return ranges.stream().map(
1597                 r -> new UidRangeParcel(r.start, r.stop)).toArray(UidRangeParcel[]::new);
1598     }
1599 
intToUidRangeStableParcels(final @NonNull Set<Integer> ranges)1600     private UidRangeParcel[] intToUidRangeStableParcels(final @NonNull Set<Integer> ranges) {
1601         return ranges.stream().map(r -> new UidRangeParcel(r, r)).toArray(UidRangeParcel[]::new);
1602     }
1603 
makeVpnManagerService()1604     private VpnManagerService makeVpnManagerService() {
1605         final VpnManagerService.Dependencies deps = new VpnManagerService.Dependencies() {
1606             public int getCallingUid() {
1607                 return mDeps.getCallingUid();
1608             }
1609 
1610             public HandlerThread makeHandlerThread() {
1611                 return mVMSHandlerThread;
1612             }
1613 
1614             @Override
1615             public VpnProfileStore getVpnProfileStore() {
1616                 return mVpnProfileStore;
1617             }
1618 
1619             public INetd getNetd() {
1620                 return mMockNetd;
1621             }
1622 
1623             public INetworkManagementService getINetworkManagementService() {
1624                 return mNetworkManagementService;
1625             }
1626         };
1627         return new VpnManagerService(mServiceContext, deps);
1628     }
1629 
assertVpnTransportInfo(NetworkCapabilities nc, int type)1630     private void assertVpnTransportInfo(NetworkCapabilities nc, int type) {
1631         assertNotNull(nc);
1632         final TransportInfo ti = nc.getTransportInfo();
1633         assertTrue("VPN TransportInfo is not a VpnTransportInfo: " + ti,
1634                 ti instanceof VpnTransportInfo);
1635         assertEquals(type, ((VpnTransportInfo) ti).getType());
1636 
1637     }
1638 
processBroadcast(Intent intent)1639     private void processBroadcast(Intent intent) {
1640         mServiceContext.sendBroadcast(intent);
1641         HandlerUtils.waitForIdle(mVMSHandlerThread, TIMEOUT_MS);
1642         waitForIdle();
1643     }
1644 
mockVpn(int uid)1645     private void mockVpn(int uid) {
1646         synchronized (mVpnManagerService.mVpns) {
1647             int userId = UserHandle.getUserId(uid);
1648             mMockVpn = new MockVpn(userId);
1649             // Every running user always has a Vpn in the mVpns array, even if no VPN is running.
1650             mVpnManagerService.mVpns.put(userId, mMockVpn);
1651         }
1652     }
1653 
mockUidNetworkingBlocked()1654     private void mockUidNetworkingBlocked() {
1655         doAnswer(i -> isUidBlocked(mBlockedReasons, i.getArgument(1))
1656         ).when(mNetworkPolicyManager).isUidNetworkingBlocked(anyInt(), anyBoolean());
1657     }
1658 
isUidBlocked(int blockedReasons, boolean meteredNetwork)1659     private boolean isUidBlocked(int blockedReasons, boolean meteredNetwork) {
1660         final int blockedOnAllNetworksReason = (blockedReasons & ~BLOCKED_METERED_REASON_MASK);
1661         if (blockedOnAllNetworksReason != BLOCKED_REASON_NONE) {
1662             return true;
1663         }
1664         if (meteredNetwork) {
1665             return blockedReasons != BLOCKED_REASON_NONE;
1666         }
1667         return false;
1668     }
1669 
setBlockedReasonChanged(int blockedReasons)1670     private void setBlockedReasonChanged(int blockedReasons) {
1671         mBlockedReasons = blockedReasons;
1672         mPolicyCallback.onUidBlockedReasonChanged(Process.myUid(), blockedReasons);
1673     }
1674 
getNat464Xlat(NetworkAgentWrapper mna)1675     private Nat464Xlat getNat464Xlat(NetworkAgentWrapper mna) {
1676         return mService.getNetworkAgentInfoForNetwork(mna.getNetwork()).clatd;
1677     }
1678 
1679     private class WrappedMultinetworkPolicyTracker extends MultinetworkPolicyTracker {
1680         volatile int mConfigMeteredMultipathPreference;
1681 
WrappedMultinetworkPolicyTracker(Context c, Handler h, Runnable r)1682         WrappedMultinetworkPolicyTracker(Context c, Handler h, Runnable r) {
1683             super(c, h, r);
1684         }
1685 
1686         @Override
getResourcesForActiveSubId()1687         protected Resources getResourcesForActiveSubId() {
1688             return mResources;
1689         }
1690 
1691         @Override
configMeteredMultipathPreference()1692         public int configMeteredMultipathPreference() {
1693             return mConfigMeteredMultipathPreference;
1694         }
1695     }
1696 
1697     /**
1698      * Wait up to TIMEOUT_MS for {@code conditionVariable} to open.
1699      * Fails if TIMEOUT_MS goes by before {@code conditionVariable} opens.
1700      */
waitFor(ConditionVariable conditionVariable)1701     static private void waitFor(ConditionVariable conditionVariable) {
1702         if (conditionVariable.block(TIMEOUT_MS)) {
1703             return;
1704         }
1705         fail("ConditionVariable was blocked for more than " + TIMEOUT_MS + "ms");
1706     }
1707 
doAsUid(final int uid, @NonNull final Supplier<T> what)1708     private <T> T doAsUid(final int uid, @NonNull final Supplier<T> what) {
1709         mDeps.setCallingUid(uid);
1710         try {
1711             return what.get();
1712         } finally {
1713             mDeps.setCallingUid(null);
1714         }
1715     }
1716 
doAsUid(final int uid, @NonNull final Runnable what)1717     private void doAsUid(final int uid, @NonNull final Runnable what) {
1718         doAsUid(uid, () -> {
1719             what.run(); return Void.TYPE;
1720         });
1721     }
1722 
registerNetworkCallbackAsUid(NetworkRequest request, NetworkCallback callback, int uid)1723     private void registerNetworkCallbackAsUid(NetworkRequest request, NetworkCallback callback,
1724             int uid) {
1725         doAsUid(uid, () -> {
1726             mCm.registerNetworkCallback(request, callback);
1727         });
1728     }
1729 
registerDefaultNetworkCallbackAsUid(@onNull final NetworkCallback callback, final int uid)1730     private void registerDefaultNetworkCallbackAsUid(@NonNull final NetworkCallback callback,
1731             final int uid) {
1732         doAsUid(uid, () -> {
1733             mCm.registerDefaultNetworkCallback(callback);
1734             waitForIdle();
1735         });
1736     }
1737 
1738     private interface ExceptionalRunnable {
run()1739         void run() throws Exception;
1740     }
1741 
withPermission(String permission, ExceptionalRunnable r)1742     private void withPermission(String permission, ExceptionalRunnable r) throws Exception {
1743         try {
1744             mServiceContext.setPermission(permission, PERMISSION_GRANTED);
1745             r.run();
1746         } finally {
1747             mServiceContext.setPermission(permission, null);
1748         }
1749     }
1750 
withPermission(String permission, int pid, int uid, ExceptionalRunnable r)1751     private void withPermission(String permission, int pid, int uid, ExceptionalRunnable r)
1752             throws Exception {
1753         try {
1754             mServiceContext.setPermission(permission, pid, uid, PERMISSION_GRANTED);
1755             r.run();
1756         } finally {
1757             mServiceContext.setPermission(permission, pid, uid, null);
1758         }
1759     }
1760 
1761     private static final int PRIMARY_USER = 0;
1762     private static final int SECONDARY_USER = 10;
1763     private static final int TERTIARY_USER = 11;
1764     private static final UidRange PRIMARY_UIDRANGE =
1765             UidRange.createForUser(UserHandle.of(PRIMARY_USER));
1766     private static final int APP1_UID = UserHandle.getUid(PRIMARY_USER, 10100);
1767     private static final int APP2_UID = UserHandle.getUid(PRIMARY_USER, 10101);
1768     private static final int VPN_UID = UserHandle.getUid(PRIMARY_USER, 10043);
1769     private static final UserInfo PRIMARY_USER_INFO = new UserInfo(PRIMARY_USER, "",
1770             UserInfo.FLAG_PRIMARY);
1771     private static final UserHandle PRIMARY_USER_HANDLE = new UserHandle(PRIMARY_USER);
1772     private static final UserHandle SECONDARY_USER_HANDLE = new UserHandle(SECONDARY_USER);
1773     private static final UserHandle TERTIARY_USER_HANDLE = new UserHandle(TERTIARY_USER);
1774 
1775     private static final int RESTRICTED_USER = 1;
1776     private static final UserInfo RESTRICTED_USER_INFO = new UserInfo(RESTRICTED_USER, "",
1777             UserInfo.FLAG_RESTRICTED);
1778     static {
1779         RESTRICTED_USER_INFO.restrictedProfileParentId = PRIMARY_USER;
1780     }
1781 
1782     @Before
setUp()1783     public void setUp() throws Exception {
1784         mNetIdManager = new TestNetIdManager();
1785 
1786         mContext = InstrumentationRegistry.getContext();
1787 
1788         MockitoAnnotations.initMocks(this);
1789 
1790         doReturn(asList(PRIMARY_USER_INFO)).when(mUserManager).getAliveUsers();
1791         doReturn(asList(PRIMARY_USER_HANDLE)).when(mUserManager).getUserHandles(anyBoolean());
1792         doReturn(PRIMARY_USER_INFO).when(mUserManager).getUserInfo(PRIMARY_USER);
1793         // canHaveRestrictedProfile does not take a userId. It applies to the userId of the context
1794         // it was started from, i.e., PRIMARY_USER.
1795         doReturn(true).when(mUserManager).canHaveRestrictedProfile();
1796         doReturn(RESTRICTED_USER_INFO).when(mUserManager).getUserInfo(RESTRICTED_USER);
1797 
1798         final ApplicationInfo applicationInfo = new ApplicationInfo();
1799         applicationInfo.targetSdkVersion = Build.VERSION_CODES.Q;
1800         doReturn(applicationInfo).when(mPackageManager)
1801                 .getApplicationInfoAsUser(anyString(), anyInt(), any());
1802         doReturn(applicationInfo.targetSdkVersion).when(mPackageManager)
1803                 .getTargetSdkVersion(anyString());
1804         doReturn(new int[0]).when(mSystemConfigManager).getSystemPermissionUids(anyString());
1805 
1806         // InstrumentationTestRunner prepares a looper, but AndroidJUnitRunner does not.
1807         // http://b/25897652 .
1808         if (Looper.myLooper() == null) {
1809             Looper.prepare();
1810         }
1811         mockDefaultPackages();
1812         mockHasSystemFeature(FEATURE_WIFI, true);
1813         mockHasSystemFeature(FEATURE_WIFI_DIRECT, true);
1814         mockHasSystemFeature(FEATURE_ETHERNET, true);
1815         doReturn(true).when(mTelephonyManager).isDataCapable();
1816 
1817         FakeSettingsProvider.clearSettingsProvider();
1818         mServiceContext = new MockContext(InstrumentationRegistry.getContext(),
1819                 new FakeSettingsProvider());
1820         mServiceContext.setUseRegisteredHandlers(true);
1821         mServiceContext.setPermission(NETWORK_FACTORY, PERMISSION_GRANTED);
1822         mServiceContext.setPermission(NETWORK_STACK, PERMISSION_GRANTED);
1823         mServiceContext.setPermission(CONTROL_OEM_PAID_NETWORK_PREFERENCE, PERMISSION_GRANTED);
1824         mServiceContext.setPermission(PACKET_KEEPALIVE_OFFLOAD, PERMISSION_GRANTED);
1825         mServiceContext.setPermission(CONNECTIVITY_USE_RESTRICTED_NETWORKS, PERMISSION_GRANTED);
1826 
1827         mAlarmManagerThread = new HandlerThread("TestAlarmManager");
1828         mAlarmManagerThread.start();
1829         initAlarmManager(mAlarmManager, mAlarmManagerThread.getThreadHandler());
1830 
1831         mCsHandlerThread = new HandlerThread("TestConnectivityService");
1832         mVMSHandlerThread = new HandlerThread("TestVpnManagerService");
1833         mProxyTracker = new ProxyTracker(mServiceContext, mock(Handler.class),
1834                 16 /* EVENT_PROXY_HAS_CHANGED */);
1835 
1836         initMockedResources();
1837         final Context mockResContext = mock(Context.class);
1838         doReturn(mResources).when(mockResContext).getResources();
1839         ConnectivityResources.setResourcesContextForTest(mockResContext);
1840         mDeps = new ConnectivityServiceDependencies(mockResContext);
1841 
1842         mService = new ConnectivityService(mServiceContext,
1843                 mMockDnsResolver,
1844                 mock(IpConnectivityLog.class),
1845                 mMockNetd,
1846                 mDeps);
1847         mService.mLingerDelayMs = TEST_LINGER_DELAY_MS;
1848         mService.mNascentDelayMs = TEST_NASCENT_DELAY_MS;
1849 
1850         final ArgumentCaptor<NetworkPolicyCallback> policyCallbackCaptor =
1851                 ArgumentCaptor.forClass(NetworkPolicyCallback.class);
1852         verify(mNetworkPolicyManager).registerNetworkPolicyCallback(any(),
1853                 policyCallbackCaptor.capture());
1854         mPolicyCallback = policyCallbackCaptor.getValue();
1855 
1856         // Create local CM before sending system ready so that we can answer
1857         // getSystemService() correctly.
1858         mCm = new WrappedConnectivityManager(InstrumentationRegistry.getContext(), mService);
1859         mService.systemReadyInternal();
1860         mVpnManagerService = makeVpnManagerService();
1861         mVpnManagerService.systemReady();
1862         mockVpn(Process.myUid());
1863         mCm.bindProcessToNetwork(null);
1864         mQosCallbackTracker = mock(QosCallbackTracker.class);
1865 
1866         // Ensure that the default setting for Captive Portals is used for most tests
1867         setCaptivePortalMode(ConnectivitySettingsManager.CAPTIVE_PORTAL_MODE_PROMPT);
1868         setAlwaysOnNetworks(false);
1869         setPrivateDnsSettings(PRIVATE_DNS_MODE_OFF, "ignored.example.com");
1870     }
1871 
initMockedResources()1872     private void initMockedResources() {
1873         doReturn(60000).when(mResources).getInteger(R.integer.config_networkTransitionTimeout);
1874         doReturn("").when(mResources).getString(R.string.config_networkCaptivePortalServerUrl);
1875         doReturn(new String[]{ WIFI_WOL_IFNAME }).when(mResources).getStringArray(
1876                 R.array.config_wakeonlan_supported_interfaces);
1877         doReturn(new String[] { "0,1", "1,3" }).when(mResources).getStringArray(
1878                 R.array.config_networkSupportedKeepaliveCount);
1879         doReturn(new String[0]).when(mResources).getStringArray(
1880                 R.array.config_networkNotifySwitches);
1881         doReturn(new int[]{10, 11, 12, 14, 15}).when(mResources).getIntArray(
1882                 R.array.config_protectedNetworks);
1883         // We don't test the actual notification value strings, so just return an empty array.
1884         // It doesn't matter what the values are as long as it's not null.
1885         doReturn(new String[0]).when(mResources)
1886                 .getStringArray(R.array.network_switch_type_name);
1887 
1888         doReturn(R.array.config_networkSupportedKeepaliveCount).when(mResources)
1889                 .getIdentifier(eq("config_networkSupportedKeepaliveCount"), eq("array"), any());
1890         doReturn(R.array.network_switch_type_name).when(mResources)
1891                 .getIdentifier(eq("network_switch_type_name"), eq("array"), any());
1892         doReturn(R.integer.config_networkAvoidBadWifi).when(mResources)
1893                 .getIdentifier(eq("config_networkAvoidBadWifi"), eq("integer"), any());
1894         doReturn(1).when(mResources).getInteger(R.integer.config_networkAvoidBadWifi);
1895         doReturn(true).when(mResources)
1896                 .getBoolean(R.bool.config_cellular_radio_timesharing_capable);
1897     }
1898 
1899     class ConnectivityServiceDependencies extends ConnectivityService.Dependencies {
1900         final ConnectivityResources mConnRes;
1901         @Mock final MockableSystemProperties mSystemProperties;
1902 
ConnectivityServiceDependencies(final Context mockResContext)1903         ConnectivityServiceDependencies(final Context mockResContext) {
1904             mSystemProperties = mock(MockableSystemProperties.class);
1905             doReturn(false).when(mSystemProperties).getBoolean("ro.radio.noril", false);
1906 
1907             mConnRes = new ConnectivityResources(mockResContext);
1908         }
1909 
1910         @Override
getSystemProperties()1911         public MockableSystemProperties getSystemProperties() {
1912             return mSystemProperties;
1913         }
1914 
1915         @Override
makeHandlerThread()1916         public HandlerThread makeHandlerThread() {
1917             return mCsHandlerThread;
1918         }
1919 
1920         @Override
getNetworkStack()1921         public NetworkStackClientBase getNetworkStack() {
1922             return mNetworkStack;
1923         }
1924 
1925         @Override
makeProxyTracker(final Context context, final Handler handler)1926         public ProxyTracker makeProxyTracker(final Context context, final Handler handler) {
1927             return mProxyTracker;
1928         }
1929 
1930         @Override
makeNetIdManager()1931         public NetIdManager makeNetIdManager() {
1932             return mNetIdManager;
1933         }
1934 
1935         @Override
queryUserAccess(final int uid, final Network network, final ConnectivityService cs)1936         public boolean queryUserAccess(final int uid, final Network network,
1937                 final ConnectivityService cs) {
1938             return true;
1939         }
1940 
1941         @Override
makeMultinetworkPolicyTracker(final Context c, final Handler h, final Runnable r)1942         public MultinetworkPolicyTracker makeMultinetworkPolicyTracker(final Context c,
1943                 final Handler h, final Runnable r) {
1944             if (null != mPolicyTracker) {
1945                 throw new IllegalStateException("Multinetwork policy tracker already initialized");
1946             }
1947             mPolicyTracker = new WrappedMultinetworkPolicyTracker(mServiceContext, h, r);
1948             return mPolicyTracker;
1949         }
1950 
1951         @Override
getResources(final Context ctx)1952         public ConnectivityResources getResources(final Context ctx) {
1953             return mConnRes;
1954         }
1955 
1956         @Override
makeLocationPermissionChecker(final Context context)1957         public LocationPermissionChecker makeLocationPermissionChecker(final Context context) {
1958             return new LocationPermissionChecker(context) {
1959                 @Override
1960                 protected int getCurrentUser() {
1961                     return runAsShell(CREATE_USERS, () -> super.getCurrentUser());
1962                 }
1963             };
1964         }
1965 
1966         @Override
makeCarrierPrivilegeAuthenticator( @onNull final Context context, @NonNull final TelephonyManager tm)1967         public CarrierPrivilegeAuthenticator makeCarrierPrivilegeAuthenticator(
1968                 @NonNull final Context context, @NonNull final TelephonyManager tm) {
1969             return SdkLevel.isAtLeastT() ? mCarrierPrivilegeAuthenticator : null;
1970         }
1971 
1972         @Override
intentFilterEquals(final PendingIntent a, final PendingIntent b)1973         public boolean intentFilterEquals(final PendingIntent a, final PendingIntent b) {
1974             return runAsShell(GET_INTENT_SENDER_INTENT, () -> a.intentFilterEquals(b));
1975         }
1976 
1977         @GuardedBy("this")
1978         private Integer mCallingUid = null;
1979 
1980         @Override
getCallingUid()1981         public int getCallingUid() {
1982             synchronized (this) {
1983                 if (null != mCallingUid) return mCallingUid;
1984                 return super.getCallingUid();
1985             }
1986         }
1987 
1988         // Pass null for the real calling UID
setCallingUid(final Integer uid)1989         public void setCallingUid(final Integer uid) {
1990             synchronized (this) {
1991                 mCallingUid = uid;
1992             }
1993         }
1994 
1995         @GuardedBy("this")
1996         private boolean mCellular464XlatEnabled = true;
1997 
1998         @Override
getCellular464XlatEnabled()1999         public boolean getCellular464XlatEnabled() {
2000             synchronized (this) {
2001                 return mCellular464XlatEnabled;
2002             }
2003         }
2004 
setCellular464XlatEnabled(final boolean enabled)2005         public void setCellular464XlatEnabled(final boolean enabled) {
2006             synchronized (this) {
2007                 mCellular464XlatEnabled = enabled;
2008             }
2009         }
2010 
2011         @GuardedBy("this")
2012         private Integer mConnectionOwnerUid = null;
2013 
2014         @Override
getConnectionOwnerUid(final int protocol, final InetSocketAddress local, final InetSocketAddress remote)2015         public int getConnectionOwnerUid(final int protocol, final InetSocketAddress local,
2016                 final InetSocketAddress remote) {
2017             synchronized (this) {
2018                 if (null != mConnectionOwnerUid) return mConnectionOwnerUid;
2019                 return super.getConnectionOwnerUid(protocol, local, remote);
2020             }
2021         }
2022 
2023         // Pass null to get the production implementation of getConnectionOwnerUid
setConnectionOwnerUid(final Integer uid)2024         public void setConnectionOwnerUid(final Integer uid) {
2025             synchronized (this) {
2026                 mConnectionOwnerUid = uid;
2027             }
2028         }
2029 
2030         final class ReportedInterfaces {
2031             public final Context context;
2032             public final String iface;
2033             public final int[] transportTypes;
ReportedInterfaces(final Context c, final String i, final int[] t)2034             ReportedInterfaces(final Context c, final String i, final int[] t) {
2035                 context = c;
2036                 iface = i;
2037                 transportTypes = t;
2038             }
2039 
contentEquals(final Context c, final String i, final int[] t)2040             public boolean contentEquals(final Context c, final String i, final int[] t) {
2041                 return Objects.equals(context, c) && Objects.equals(iface, i)
2042                         && Arrays.equals(transportTypes, t);
2043             }
2044         }
2045 
2046         final ArrayTrackRecord<ReportedInterfaces> mReportedInterfaceHistory =
2047                 new ArrayTrackRecord<>();
2048 
2049         @Override
reportNetworkInterfaceForTransports(final Context context, final String iface, final int[] transportTypes)2050         public void reportNetworkInterfaceForTransports(final Context context, final String iface,
2051                 final int[] transportTypes) {
2052             mReportedInterfaceHistory.add(new ReportedInterfaces(context, iface, transportTypes));
2053             super.reportNetworkInterfaceForTransports(context, iface, transportTypes);
2054         }
2055 
2056         @Override
isFeatureEnabled(Context context, String name, boolean defaultEnabled)2057         public boolean isFeatureEnabled(Context context, String name, boolean defaultEnabled) {
2058             switch (name) {
2059                 case ConnectivityFlags.NO_REMATCH_ALL_REQUESTS_ON_REGISTER:
2060                     return true;
2061                 default:
2062                     return super.isFeatureEnabled(context, name, defaultEnabled);
2063             }
2064         }
2065 
2066         @Override
getBpfNetMaps(INetd netd)2067         public BpfNetMaps getBpfNetMaps(INetd netd) {
2068             return mBpfNetMaps;
2069         }
2070 
2071         @Override
getClatCoordinator(INetd netd)2072         public ClatCoordinator getClatCoordinator(INetd netd) {
2073             return mClatCoordinator;
2074         }
2075 
2076         final ArrayTrackRecord<Pair<String, Long>> mRateLimitHistory = new ArrayTrackRecord<>();
2077         final Map<String, Long> mActiveRateLimit = new HashMap<>();
2078 
2079         @Override
enableIngressRateLimit(final String iface, final long rateInBytesPerSecond)2080         public void enableIngressRateLimit(final String iface, final long rateInBytesPerSecond) {
2081             mRateLimitHistory.add(new Pair<>(iface, rateInBytesPerSecond));
2082             // Due to a TC limitation, the rate limit needs to be removed before it can be
2083             // updated. Check that this happened.
2084             assertEquals(-1L, (long) mActiveRateLimit.getOrDefault(iface, -1L));
2085             mActiveRateLimit.put(iface, rateInBytesPerSecond);
2086             // verify that clsact qdisc has already been created, otherwise attaching a tc police
2087             // filter will fail.
2088             try {
2089                 verify(mMockNetd).networkAddInterface(anyInt(), eq(iface));
2090             } catch (RemoteException e) {
2091                 fail(e.getMessage());
2092             }
2093         }
2094 
2095         @Override
disableIngressRateLimit(final String iface)2096         public void disableIngressRateLimit(final String iface) {
2097             mRateLimitHistory.add(new Pair<>(iface, -1L));
2098             assertNotEquals(-1L, (long) mActiveRateLimit.getOrDefault(iface, -1L));
2099             mActiveRateLimit.put(iface, -1L);
2100         }
2101     }
2102 
2103     private static void initAlarmManager(final AlarmManager am, final Handler alarmHandler) {
2104         doAnswer(inv -> {
2105             final long when = inv.getArgument(1);
2106             final WakeupMessage wakeupMsg = inv.getArgument(3);
2107             final Handler handler = inv.getArgument(4);
2108 
2109             long delayMs = when - SystemClock.elapsedRealtime();
2110             if (delayMs < 0) delayMs = 0;
2111             if (delayMs > UNREASONABLY_LONG_ALARM_WAIT_MS) {
2112                 fail("Attempting to send msg more than " + UNREASONABLY_LONG_ALARM_WAIT_MS
2113                         + "ms into the future: " + delayMs);
2114             }
2115             alarmHandler.postDelayed(() -> handler.post(wakeupMsg::onAlarm), wakeupMsg /* token */,
2116                     delayMs);
2117 
2118             return null;
2119         }).when(am).setExact(eq(AlarmManager.ELAPSED_REALTIME_WAKEUP), anyLong(), anyString(),
2120                 any(WakeupMessage.class), any());
2121 
2122         doAnswer(inv -> {
2123             final WakeupMessage wakeupMsg = inv.getArgument(0);
2124             alarmHandler.removeCallbacksAndMessages(wakeupMsg /* token */);
2125             return null;
2126         }).when(am).cancel(any(WakeupMessage.class));
2127     }
2128 
2129     @After
2130     public void tearDown() throws Exception {
2131         unregisterDefaultNetworkCallbacks();
2132         maybeTearDownEnterpriseNetwork();
2133         setAlwaysOnNetworks(false);
2134         if (mCellNetworkAgent != null) {
2135             mCellNetworkAgent.disconnect();
2136             mCellNetworkAgent = null;
2137         }
2138         if (mWiFiNetworkAgent != null) {
2139             mWiFiNetworkAgent.disconnect();
2140             mWiFiNetworkAgent = null;
2141         }
2142         if (mEthernetNetworkAgent != null) {
2143             mEthernetNetworkAgent.disconnect();
2144             mEthernetNetworkAgent = null;
2145         }
2146 
2147         if (mQosCallbackMockHelper != null) {
2148             mQosCallbackMockHelper.tearDown();
2149             mQosCallbackMockHelper = null;
2150         }
2151         mMockVpn.disconnect();
2152         waitForIdle();
2153 
2154         FakeSettingsProvider.clearSettingsProvider();
2155         ConnectivityResources.setResourcesContextForTest(null);
2156 
2157         mCsHandlerThread.quitSafely();
2158         mAlarmManagerThread.quitSafely();
2159     }
2160 
2161     private void mockDefaultPackages() throws Exception {
2162         final String myPackageName = mContext.getPackageName();
2163         final PackageInfo myPackageInfo = mContext.getPackageManager().getPackageInfo(
2164                 myPackageName, PackageManager.GET_PERMISSIONS);
2165         doReturn(new String[] {myPackageName}).when(mPackageManager)
2166                 .getPackagesForUid(Binder.getCallingUid());
2167         doReturn(myPackageInfo).when(mPackageManager).getPackageInfoAsUser(
2168                 eq(myPackageName), anyInt(), eq(UserHandle.getCallingUserId()));
2169 
2170         doReturn(asList(new PackageInfo[] {
2171                 buildPackageInfo(/* SYSTEM */ false, APP1_UID),
2172                 buildPackageInfo(/* SYSTEM */ false, APP2_UID),
2173                 buildPackageInfo(/* SYSTEM */ false, VPN_UID)
2174         })).when(mPackageManager).getInstalledPackagesAsUser(eq(GET_PERMISSIONS), anyInt());
2175 
2176         // Create a fake always-on VPN package.
2177         final int userId = UserHandle.getCallingUserId();
2178         final ApplicationInfo applicationInfo = new ApplicationInfo();
2179         applicationInfo.targetSdkVersion = Build.VERSION_CODES.R;  // Always-on supported in N+.
2180         doReturn(applicationInfo).when(mPackageManager).getApplicationInfoAsUser(
2181                 eq(ALWAYS_ON_PACKAGE), anyInt(), eq(userId));
2182 
2183         // Minimal mocking to keep Vpn#isAlwaysOnPackageSupported happy.
2184         ResolveInfo rInfo = new ResolveInfo();
2185         rInfo.serviceInfo = new ServiceInfo();
2186         rInfo.serviceInfo.metaData = new Bundle();
2187         final List<ResolveInfo> services = asList(new ResolveInfo[]{rInfo});
2188         doReturn(services).when(mPackageManager).queryIntentServicesAsUser(
2189                 any(), eq(PackageManager.GET_META_DATA), eq(userId));
2190         doReturn(Process.myUid()).when(mPackageManager).getPackageUidAsUser(
2191                 TEST_PACKAGE_NAME, userId);
2192         doReturn(VPN_UID).when(mPackageManager).getPackageUidAsUser(ALWAYS_ON_PACKAGE, userId);
2193     }
2194 
2195     private void verifyActiveNetwork(int transport) {
2196         // Test getActiveNetworkInfo()
2197         assertNotNull(mCm.getActiveNetworkInfo());
2198         assertEquals(transportToLegacyType(transport), mCm.getActiveNetworkInfo().getType());
2199         // Test getActiveNetwork()
2200         assertNotNull(mCm.getActiveNetwork());
2201         assertEquals(mCm.getActiveNetwork(), mCm.getActiveNetworkForUid(Process.myUid()));
2202         if (!NetworkCapabilities.isValidTransport(transport)) {
2203             throw new IllegalStateException("Unknown transport " + transport);
2204         }
2205         switch (transport) {
2206             case TRANSPORT_WIFI:
2207                 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2208                 break;
2209             case TRANSPORT_CELLULAR:
2210                 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2211                 break;
2212             case TRANSPORT_ETHERNET:
2213                 assertEquals(mEthernetNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2214                 break;
2215             default:
2216                 break;
2217         }
2218         // Test getNetworkInfo(Network)
2219         assertNotNull(mCm.getNetworkInfo(mCm.getActiveNetwork()));
2220         assertEquals(transportToLegacyType(transport),
2221                 mCm.getNetworkInfo(mCm.getActiveNetwork()).getType());
2222         assertNotNull(mCm.getActiveNetworkInfoForUid(Process.myUid()));
2223         // Test getNetworkCapabilities(Network)
2224         assertNotNull(mCm.getNetworkCapabilities(mCm.getActiveNetwork()));
2225         assertTrue(mCm.getNetworkCapabilities(mCm.getActiveNetwork()).hasTransport(transport));
2226     }
2227 
2228     private void verifyNoNetwork() {
2229         waitForIdle();
2230         // Test getActiveNetworkInfo()
2231         assertNull(mCm.getActiveNetworkInfo());
2232         // Test getActiveNetwork()
2233         assertNull(mCm.getActiveNetwork());
2234         assertNull(mCm.getActiveNetworkForUid(Process.myUid()));
2235         // Test getAllNetworks()
2236         assertEmpty(mCm.getAllNetworks());
2237         assertEmpty(mCm.getAllNetworkStateSnapshots());
2238     }
2239 
2240     /**
2241      * Class to simplify expecting broadcasts using BroadcastInterceptingContext.
2242      * Ensures that the receiver is unregistered after the expected broadcast is received. This
2243      * cannot be done in the BroadcastReceiver itself because BroadcastInterceptingContext runs
2244      * the receivers' receive method while iterating over the list of receivers, and unregistering
2245      * the receiver during iteration throws ConcurrentModificationException.
2246      */
2247     private class ExpectedBroadcast extends CompletableFuture<Intent>  {
2248         private final BroadcastReceiver mReceiver;
2249 
2250         ExpectedBroadcast(BroadcastReceiver receiver) {
2251             mReceiver = receiver;
2252         }
2253 
2254         public Intent expectBroadcast(int timeoutMs) throws Exception {
2255             try {
2256                 return get(timeoutMs, TimeUnit.MILLISECONDS);
2257             } catch (TimeoutException e) {
2258                 fail("Expected broadcast not received after " + timeoutMs + " ms");
2259                 return null;
2260             } finally {
2261                 mServiceContext.unregisterReceiver(mReceiver);
2262             }
2263         }
2264 
2265         public Intent expectBroadcast() throws Exception {
2266             return expectBroadcast(BROADCAST_TIMEOUT_MS);
2267         }
2268 
2269         public void expectNoBroadcast(int timeoutMs) throws Exception {
2270             waitForIdle();
2271             try {
2272                 final Intent intent = get(timeoutMs, TimeUnit.MILLISECONDS);
2273                 fail("Unexpected broadcast: " + intent.getAction() + " " + intent.getExtras());
2274             } catch (TimeoutException expected) {
2275             } finally {
2276                 mServiceContext.unregisterReceiver(mReceiver);
2277             }
2278         }
2279     }
2280 
2281     /** Expects that {@code count} CONNECTIVITY_ACTION broadcasts are received. */
2282     private ExpectedBroadcast registerConnectivityBroadcast(final int count) {
2283         return registerConnectivityBroadcastThat(count, intent -> true);
2284     }
2285 
2286     private ExpectedBroadcast registerConnectivityBroadcastThat(final int count,
2287             @NonNull final Predicate<Intent> filter) {
2288         final IntentFilter intentFilter = new IntentFilter(CONNECTIVITY_ACTION);
2289         // AtomicReference allows receiver to access expected even though it is constructed later.
2290         final AtomicReference<ExpectedBroadcast> expectedRef = new AtomicReference<>();
2291         final BroadcastReceiver receiver = new BroadcastReceiver() {
2292             private int mRemaining = count;
2293             public void onReceive(Context context, Intent intent) {
2294                 final int type = intent.getIntExtra(EXTRA_NETWORK_TYPE, -1);
2295                 final NetworkInfo ni = intent.getParcelableExtra(EXTRA_NETWORK_INFO);
2296                 Log.d(TAG, "Received CONNECTIVITY_ACTION type=" + type + " ni=" + ni);
2297                 if (!filter.test(intent)) return;
2298                 if (--mRemaining == 0) {
2299                     expectedRef.get().complete(intent);
2300                 }
2301             }
2302         };
2303         final ExpectedBroadcast expected = new ExpectedBroadcast(receiver);
2304         expectedRef.set(expected);
2305         mServiceContext.registerReceiver(receiver, intentFilter);
2306         return expected;
2307     }
2308 
2309     private ExpectedBroadcast expectProxyChangeAction(ProxyInfo proxy) {
2310         return registerPacProxyBroadcastThat(intent -> {
2311             final ProxyInfo actualProxy = (ProxyInfo) intent.getExtra(Proxy.EXTRA_PROXY_INFO,
2312                     ProxyInfo.buildPacProxy(Uri.EMPTY));
2313             return proxy.equals(actualProxy);
2314         });
2315     }
2316 
2317     private ExpectedBroadcast registerPacProxyBroadcast() {
2318         return registerPacProxyBroadcastThat(intent -> true);
2319     }
2320 
2321     private ExpectedBroadcast registerPacProxyBroadcastThat(
2322             @NonNull final Predicate<Intent> filter) {
2323         final IntentFilter intentFilter = new IntentFilter(Proxy.PROXY_CHANGE_ACTION);
2324         // AtomicReference allows receiver to access expected even though it is constructed later.
2325         final AtomicReference<ExpectedBroadcast> expectedRef = new AtomicReference<>();
2326         final BroadcastReceiver receiver = new BroadcastReceiver() {
2327             public void onReceive(Context context, Intent intent) {
2328                 final ProxyInfo proxy = (ProxyInfo) intent.getExtra(
2329                             Proxy.EXTRA_PROXY_INFO, ProxyInfo.buildPacProxy(Uri.EMPTY));
2330                 Log.d(TAG, "Receive PROXY_CHANGE_ACTION, proxy = " + proxy);
2331                 if (filter.test(intent)) {
2332                     expectedRef.get().complete(intent);
2333                 }
2334             }
2335         };
2336         final ExpectedBroadcast expected = new ExpectedBroadcast(receiver);
2337         expectedRef.set(expected);
2338         mServiceContext.registerReceiver(receiver, intentFilter);
2339         return expected;
2340     }
2341 
2342     private boolean extraInfoInBroadcastHasExpectedNullness(NetworkInfo ni) {
2343         final DetailedState state = ni.getDetailedState();
2344         if (state == DetailedState.CONNECTED && ni.getExtraInfo() == null) return false;
2345         // Expect a null extraInfo if the network is CONNECTING, because a CONNECTIVITY_ACTION
2346         // broadcast with a state of CONNECTING only happens due to legacy VPN lockdown, which also
2347         // nulls out extraInfo.
2348         if (state == DetailedState.CONNECTING && ni.getExtraInfo() != null) return false;
2349         // Can't make any assertions about DISCONNECTED broadcasts. When a network actually
2350         // disconnects, disconnectAndDestroyNetwork sets its state to DISCONNECTED and its extraInfo
2351         // to null. But if the DISCONNECTED broadcast is just simulated by LegacyTypeTracker due to
2352         // a network switch, extraInfo will likely be populated.
2353         // This is likely a bug in CS, but likely not one we can fix without impacting apps.
2354         return true;
2355     }
2356 
2357     private ExpectedBroadcast expectConnectivityAction(int type, NetworkInfo.DetailedState state) {
2358         return registerConnectivityBroadcastThat(1, intent -> {
2359             final int actualType = intent.getIntExtra(EXTRA_NETWORK_TYPE, -1);
2360             final NetworkInfo ni = intent.getParcelableExtra(EXTRA_NETWORK_INFO);
2361             return type == actualType
2362                     && state == ni.getDetailedState()
2363                     && extraInfoInBroadcastHasExpectedNullness(ni);
2364         });
2365     }
2366 
2367     @Test
2368     public void testNetworkTypes() {
2369         // Ensure that our mocks for the networkAttributes config variable work as expected. If they
2370         // don't, then tests that depend on CONNECTIVITY_ACTION broadcasts for these network types
2371         // will fail. Failing here is much easier to debug.
2372         assertTrue(mCm.isNetworkSupported(TYPE_WIFI));
2373         assertTrue(mCm.isNetworkSupported(TYPE_MOBILE));
2374         assertTrue(mCm.isNetworkSupported(TYPE_MOBILE_MMS));
2375         assertTrue(mCm.isNetworkSupported(TYPE_MOBILE_FOTA));
2376         assertFalse(mCm.isNetworkSupported(TYPE_PROXY));
2377 
2378         // Check that TYPE_ETHERNET is supported. Unlike the asserts above, which only validate our
2379         // mocks, this assert exercises the ConnectivityService code path that ensures that
2380         // TYPE_ETHERNET is supported if the ethernet service is running.
2381         assertTrue(mCm.isNetworkSupported(TYPE_ETHERNET));
2382     }
2383 
2384     @Test
2385     public void testNetworkFeature() throws Exception {
2386         // Connect the cell agent and wait for the connected broadcast.
2387         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
2388         mCellNetworkAgent.addCapability(NET_CAPABILITY_SUPL);
2389         ExpectedBroadcast b = expectConnectivityAction(TYPE_MOBILE, DetailedState.CONNECTED);
2390         mCellNetworkAgent.connect(true);
2391         b.expectBroadcast();
2392 
2393         // Build legacy request for SUPL.
2394         final NetworkCapabilities legacyCaps = new NetworkCapabilities();
2395         legacyCaps.addTransportType(TRANSPORT_CELLULAR);
2396         legacyCaps.addCapability(NET_CAPABILITY_SUPL);
2397         final NetworkRequest legacyRequest = new NetworkRequest(legacyCaps, TYPE_MOBILE_SUPL,
2398                 ConnectivityManager.REQUEST_ID_UNSET, NetworkRequest.Type.REQUEST);
2399 
2400         // File request, withdraw it and make sure no broadcast is sent
2401         b = registerConnectivityBroadcast(1);
2402         final TestNetworkCallback callback = new TestNetworkCallback();
2403         mCm.requestNetwork(legacyRequest, callback);
2404         callback.expectCallback(CallbackEntry.AVAILABLE, mCellNetworkAgent);
2405         mCm.unregisterNetworkCallback(callback);
2406         b.expectNoBroadcast(800);  // 800ms long enough to at least flake if this is sent
2407 
2408         // Disconnect the network and expect mobile disconnected broadcast.
2409         b = expectConnectivityAction(TYPE_MOBILE, DetailedState.DISCONNECTED);
2410         mCellNetworkAgent.disconnect();
2411         b.expectBroadcast();
2412     }
2413 
2414     @Test
2415     public void testLingering() throws Exception {
2416         verifyNoNetwork();
2417         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
2418         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
2419         assertNull(mCm.getActiveNetworkInfo());
2420         assertNull(mCm.getActiveNetwork());
2421         // Test bringing up validated cellular.
2422         ExpectedBroadcast b = expectConnectivityAction(TYPE_MOBILE, DetailedState.CONNECTED);
2423         mCellNetworkAgent.connect(true);
2424         b.expectBroadcast();
2425         verifyActiveNetwork(TRANSPORT_CELLULAR);
2426         assertLength(2, mCm.getAllNetworks());
2427         assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) ||
2428                 mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork()));
2429         assertTrue(mCm.getAllNetworks()[0].equals(mWiFiNetworkAgent.getNetwork()) ||
2430                 mCm.getAllNetworks()[1].equals(mWiFiNetworkAgent.getNetwork()));
2431         // Test bringing up validated WiFi.
2432         b = registerConnectivityBroadcast(2);
2433         mWiFiNetworkAgent.connect(true);
2434         b.expectBroadcast();
2435         verifyActiveNetwork(TRANSPORT_WIFI);
2436         assertLength(2, mCm.getAllNetworks());
2437         assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) ||
2438                 mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork()));
2439         assertTrue(mCm.getAllNetworks()[0].equals(mCellNetworkAgent.getNetwork()) ||
2440                 mCm.getAllNetworks()[1].equals(mCellNetworkAgent.getNetwork()));
2441         // Test cellular linger timeout.
2442         mCellNetworkAgent.expectDisconnected();
2443         waitForIdle();
2444         assertLength(1, mCm.getAllNetworks());
2445         verifyActiveNetwork(TRANSPORT_WIFI);
2446         assertLength(1, mCm.getAllNetworks());
2447         assertEquals(mCm.getAllNetworks()[0], mCm.getActiveNetwork());
2448         // Test WiFi disconnect.
2449         b = registerConnectivityBroadcast(1);
2450         mWiFiNetworkAgent.disconnect();
2451         b.expectBroadcast();
2452         verifyNoNetwork();
2453     }
2454 
2455     /**
2456      * Verify a newly created network will be inactive instead of torn down even if no one is
2457      * requesting.
2458      */
2459     @Test
2460     public void testNewNetworkInactive() throws Exception {
2461         // Create a callback that monitoring the testing network.
2462         final TestNetworkCallback listenCallback = new TestNetworkCallback();
2463         mCm.registerNetworkCallback(new NetworkRequest.Builder().build(), listenCallback);
2464 
2465         // 1. Create a network that is not requested by anyone, and does not satisfy any of the
2466         // default requests. Verify that the network will be inactive instead of torn down.
2467         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
2468         mWiFiNetworkAgent.connectWithoutInternet();
2469         listenCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2470         listenCallback.assertNoCallback();
2471 
2472         // Verify that the network will be torn down after nascent expiry. A small period of time
2473         // is added in case of flakiness.
2474         final int nascentTimeoutMs =
2475                 mService.mNascentDelayMs + mService.mNascentDelayMs / 4;
2476         listenCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent, nascentTimeoutMs);
2477 
2478         // 2. Create a network that is satisfied by a request comes later.
2479         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
2480         mWiFiNetworkAgent.connectWithoutInternet();
2481         listenCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2482         final NetworkRequest wifiRequest = new NetworkRequest.Builder()
2483                 .addTransportType(TRANSPORT_WIFI).build();
2484         final TestNetworkCallback wifiCallback = new TestNetworkCallback();
2485         mCm.requestNetwork(wifiRequest, wifiCallback);
2486         wifiCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2487 
2488         // Verify that the network will be kept since the request is still satisfied. And is able
2489         // to get disconnected as usual if the request is released after the nascent timer expires.
2490         listenCallback.assertNoCallback(nascentTimeoutMs);
2491         mCm.unregisterNetworkCallback(wifiCallback);
2492         listenCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
2493 
2494         // 3. Create a network that is satisfied by a request comes later.
2495         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
2496         mWiFiNetworkAgent.connectWithoutInternet();
2497         listenCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2498         mCm.requestNetwork(wifiRequest, wifiCallback);
2499         wifiCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2500 
2501         // Verify that the network will still be torn down after the request gets removed.
2502         mCm.unregisterNetworkCallback(wifiCallback);
2503         listenCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
2504 
2505         // There is no need to ensure that LOSING is never sent in the common case that the
2506         // network immediately satisfies a request that was already present, because it is already
2507         // verified anywhere whenever {@code TestNetworkCallback#expectAvailable*} is called.
2508 
2509         mCm.unregisterNetworkCallback(listenCallback);
2510     }
2511 
2512     /**
2513      * Verify a newly created network will be inactive and switch to background if only background
2514      * request is satisfied.
2515      */
2516     @Test
2517     public void testNewNetworkInactive_bgNetwork() throws Exception {
2518         // Create a callback that monitoring the wifi network.
2519         final TestNetworkCallback wifiListenCallback = new TestNetworkCallback();
2520         mCm.registerNetworkCallback(new NetworkRequest.Builder()
2521                 .addTransportType(TRANSPORT_WIFI).build(), wifiListenCallback);
2522 
2523         // Create callbacks that can monitor background and foreground mobile networks.
2524         // This is done by granting using background networks permission before registration. Thus,
2525         // the service will not add {@code NET_CAPABILITY_FOREGROUND} by default.
2526         grantUsingBackgroundNetworksPermissionForUid(Binder.getCallingUid());
2527         final TestNetworkCallback bgMobileListenCallback = new TestNetworkCallback();
2528         final TestNetworkCallback fgMobileListenCallback = new TestNetworkCallback();
2529         mCm.registerNetworkCallback(new NetworkRequest.Builder()
2530                 .addTransportType(TRANSPORT_CELLULAR).build(), bgMobileListenCallback);
2531         mCm.registerNetworkCallback(new NetworkRequest.Builder()
2532                 .addTransportType(TRANSPORT_CELLULAR)
2533                 .addCapability(NET_CAPABILITY_FOREGROUND).build(), fgMobileListenCallback);
2534 
2535         // Connect wifi, which satisfies default request.
2536         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
2537         mWiFiNetworkAgent.connect(true);
2538         wifiListenCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
2539 
2540         // Connect a cellular network, verify that satisfies only the background callback.
2541         setAlwaysOnNetworks(true);
2542         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
2543         mCellNetworkAgent.connect(true);
2544         bgMobileListenCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2545         fgMobileListenCallback.assertNoCallback();
2546         assertFalse(isForegroundNetwork(mCellNetworkAgent));
2547 
2548         mCellNetworkAgent.disconnect();
2549         bgMobileListenCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
2550         fgMobileListenCallback.assertNoCallback();
2551 
2552         mCm.unregisterNetworkCallback(wifiListenCallback);
2553         mCm.unregisterNetworkCallback(bgMobileListenCallback);
2554         mCm.unregisterNetworkCallback(fgMobileListenCallback);
2555     }
2556 
2557     @Test
2558     public void testBinderDeathAfterUnregister() throws Exception {
2559         final NetworkCapabilities caps = new NetworkCapabilities.Builder()
2560                 .addTransportType(TRANSPORT_WIFI)
2561                 .build();
2562         final Handler handler = new Handler(ConnectivityThread.getInstanceLooper());
2563         final Messenger messenger = new Messenger(handler);
2564         final CompletableFuture<Binder.DeathRecipient> deathRecipient = new CompletableFuture<>();
2565         final Binder binder = new Binder() {
2566             private DeathRecipient mDeathRecipient;
2567             @Override
2568             public void linkToDeath(@NonNull final DeathRecipient recipient, final int flags) {
2569                 synchronized (this) {
2570                     mDeathRecipient = recipient;
2571                 }
2572                 super.linkToDeath(recipient, flags);
2573                 deathRecipient.complete(recipient);
2574             }
2575 
2576             @Override
2577             public boolean unlinkToDeath(@NonNull final DeathRecipient recipient, final int flags) {
2578                 synchronized (this) {
2579                     if (null == mDeathRecipient) {
2580                         throw new IllegalStateException();
2581                     }
2582                     mDeathRecipient = null;
2583                 }
2584                 return super.unlinkToDeath(recipient, flags);
2585             }
2586         };
2587         final NetworkRequest request = mService.listenForNetwork(caps, messenger, binder,
2588                 NetworkCallback.FLAG_NONE, mContext.getOpPackageName(),
2589                 mContext.getAttributionTag());
2590         mService.releaseNetworkRequest(request);
2591         deathRecipient.get().binderDied();
2592         // Wait for the release message to be processed.
2593         waitForIdle();
2594         // After waitForIdle(), the message was processed and the service didn't crash.
2595     }
2596 
2597     // TODO : migrate to @Parameterized
2598     @Test
2599     public void testValidatedCellularOutscoresUnvalidatedWiFi_CanTimeShare() throws Exception {
2600         // The behavior of this test should be the same whether the radio can time share or not.
2601         doTestValidatedCellularOutscoresUnvalidatedWiFi(true);
2602     }
2603 
2604     // TODO : migrate to @Parameterized
2605     @Test
2606     public void testValidatedCellularOutscoresUnvalidatedWiFi_CannotTimeShare() throws Exception {
2607         doTestValidatedCellularOutscoresUnvalidatedWiFi(false);
2608     }
2609 
2610     public void doTestValidatedCellularOutscoresUnvalidatedWiFi(
2611             final boolean cellRadioTimesharingCapable) throws Exception {
2612         mService.mCellularRadioTimesharingCapable = cellRadioTimesharingCapable;
2613         // Test bringing up unvalidated WiFi
2614         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
2615         ExpectedBroadcast b = registerConnectivityBroadcast(1);
2616         mWiFiNetworkAgent.connect(false);
2617         b.expectBroadcast();
2618         verifyActiveNetwork(TRANSPORT_WIFI);
2619         // Test bringing up unvalidated cellular
2620         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
2621         mCellNetworkAgent.connect(false);
2622         waitForIdle();
2623         verifyActiveNetwork(TRANSPORT_WIFI);
2624         // Test cellular disconnect.
2625         mCellNetworkAgent.disconnect();
2626         waitForIdle();
2627         verifyActiveNetwork(TRANSPORT_WIFI);
2628         // Test bringing up validated cellular
2629         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
2630         b = registerConnectivityBroadcast(2);
2631         mCellNetworkAgent.connect(true);
2632         b.expectBroadcast();
2633         verifyActiveNetwork(TRANSPORT_CELLULAR);
2634         // Test cellular disconnect.
2635         b = registerConnectivityBroadcast(2);
2636         mCellNetworkAgent.disconnect();
2637         b.expectBroadcast();
2638         verifyActiveNetwork(TRANSPORT_WIFI);
2639         // Test WiFi disconnect.
2640         b = registerConnectivityBroadcast(1);
2641         mWiFiNetworkAgent.disconnect();
2642         b.expectBroadcast();
2643         verifyNoNetwork();
2644     }
2645 
2646     // TODO : migrate to @Parameterized
2647     @Test
2648     public void testUnvalidatedWifiOutscoresUnvalidatedCellular_CanTimeShare() throws Exception {
2649         doTestUnvalidatedWifiOutscoresUnvalidatedCellular(true);
2650     }
2651 
2652     // TODO : migrate to @Parameterized
2653     @Test
2654     public void testUnvalidatedWifiOutscoresUnvalidatedCellular_CannotTimeShare() throws Exception {
2655         doTestUnvalidatedWifiOutscoresUnvalidatedCellular(false);
2656     }
2657 
2658     public void doTestUnvalidatedWifiOutscoresUnvalidatedCellular(
2659             final boolean cellRadioTimesharingCapable) throws Exception {
2660         mService.mCellularRadioTimesharingCapable = cellRadioTimesharingCapable;
2661         // Test bringing up unvalidated cellular.
2662         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
2663         ExpectedBroadcast b = registerConnectivityBroadcast(1);
2664         mCellNetworkAgent.connect(false);
2665         b.expectBroadcast();
2666         verifyActiveNetwork(TRANSPORT_CELLULAR);
2667         // Test bringing up unvalidated WiFi.
2668         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
2669         b = registerConnectivityBroadcast(2);
2670         mWiFiNetworkAgent.connect(false);
2671         b.expectBroadcast();
2672         verifyActiveNetwork(TRANSPORT_WIFI);
2673         // Test WiFi disconnect.
2674         b = registerConnectivityBroadcast(2);
2675         mWiFiNetworkAgent.disconnect();
2676         b.expectBroadcast();
2677         verifyActiveNetwork(TRANSPORT_CELLULAR);
2678         // Test cellular disconnect.
2679         b = registerConnectivityBroadcast(1);
2680         mCellNetworkAgent.disconnect();
2681         b.expectBroadcast();
2682         verifyNoNetwork();
2683     }
2684 
2685     // TODO : migrate to @Parameterized
2686     @Test
2687     public void testUnlingeringDoesNotValidate_CanTimeShare() throws Exception {
2688         doTestUnlingeringDoesNotValidate(true);
2689     }
2690 
2691     // TODO : migrate to @Parameterized
2692     @Test
2693     public void testUnlingeringDoesNotValidate_CannotTimeShare() throws Exception {
2694         doTestUnlingeringDoesNotValidate(false);
2695     }
2696 
2697     public void doTestUnlingeringDoesNotValidate(
2698             final boolean cellRadioTimesharingCapable) throws Exception {
2699         mService.mCellularRadioTimesharingCapable = cellRadioTimesharingCapable;
2700         // Test bringing up unvalidated WiFi.
2701         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
2702         ExpectedBroadcast b = registerConnectivityBroadcast(1);
2703         mWiFiNetworkAgent.connect(false);
2704         b.expectBroadcast();
2705         verifyActiveNetwork(TRANSPORT_WIFI);
2706         assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
2707                 NET_CAPABILITY_VALIDATED));
2708         // Test bringing up validated cellular.
2709         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
2710         b = registerConnectivityBroadcast(2);
2711         mCellNetworkAgent.connect(true);
2712         b.expectBroadcast();
2713         verifyActiveNetwork(TRANSPORT_CELLULAR);
2714         assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
2715                 NET_CAPABILITY_VALIDATED));
2716         // Test cellular disconnect.
2717         b = registerConnectivityBroadcast(2);
2718         mCellNetworkAgent.disconnect();
2719         b.expectBroadcast();
2720         verifyActiveNetwork(TRANSPORT_WIFI);
2721         // Unlingering a network should not cause it to be marked as validated.
2722         assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
2723                 NET_CAPABILITY_VALIDATED));
2724     }
2725 
2726     // TODO : migrate to @Parameterized
2727     @Test
2728     public void testRequestMigrationToSameTransport_CanTimeShare() throws Exception {
2729         // Simulate a device where the cell radio is capable of time sharing
2730         mService.mCellularRadioTimesharingCapable = true;
2731         doTestRequestMigrationToSameTransport(TRANSPORT_CELLULAR, true);
2732         doTestRequestMigrationToSameTransport(TRANSPORT_WIFI, true);
2733         doTestRequestMigrationToSameTransport(TRANSPORT_ETHERNET, true);
2734     }
2735 
2736     // TODO : migrate to @Parameterized
2737     @Test
2738     public void testRequestMigrationToSameTransport_CannotTimeShare() throws Exception {
2739         // Simulate a device where the cell radio is not capable of time sharing
2740         mService.mCellularRadioTimesharingCapable = false;
2741         doTestRequestMigrationToSameTransport(TRANSPORT_CELLULAR, false);
2742         doTestRequestMigrationToSameTransport(TRANSPORT_WIFI, true);
2743         doTestRequestMigrationToSameTransport(TRANSPORT_ETHERNET, true);
2744     }
2745 
2746     public void doTestRequestMigrationToSameTransport(final int transport,
2747             final boolean expectLingering) throws Exception {
2748         // To speed up tests the linger delay is very short by default in tests but this
2749         // test needs to make sure the delay is not incurred so a longer value is safer (it
2750         // reduces the risk that a bug exists but goes undetected). The alarm manager in the test
2751         // throws and crashes CS if this is set to anything more than the below constant though.
2752         mService.mLingerDelayMs = UNREASONABLY_LONG_ALARM_WAIT_MS;
2753 
2754         final TestNetworkCallback generalCb = new TestNetworkCallback();
2755         final TestNetworkCallback defaultCb = new TestNetworkCallback();
2756         mCm.registerNetworkCallback(
2757                 new NetworkRequest.Builder().addTransportType(transport | transport).build(),
2758                 generalCb);
2759         mCm.registerDefaultNetworkCallback(defaultCb);
2760 
2761         // Bring up net agent 1
2762         final TestNetworkAgentWrapper net1 = new TestNetworkAgentWrapper(transport);
2763         net1.connect(true);
2764         // Make sure the default request is on net 1
2765         generalCb.expectAvailableThenValidatedCallbacks(net1);
2766         defaultCb.expectAvailableThenValidatedCallbacks(net1);
2767 
2768         // Bring up net 2 with primary and mms
2769         final TestNetworkAgentWrapper net2 = new TestNetworkAgentWrapper(transport);
2770         net2.addCapability(NET_CAPABILITY_MMS);
2771         net2.setScore(new NetworkScore.Builder().setTransportPrimary(true).build());
2772         net2.connect(true);
2773 
2774         // Make sure the default request goes to net 2
2775         generalCb.expectAvailableCallbacksUnvalidated(net2);
2776         if (expectLingering) {
2777             generalCb.expectCallback(CallbackEntry.LOSING, net1);
2778         }
2779         generalCb.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, net2);
2780         defaultCb.expectAvailableDoubleValidatedCallbacks(net2);
2781 
2782         // Make sure cell 1 is unwanted immediately if the radio can't time share, but only
2783         // after some delay if it can.
2784         if (expectLingering) {
2785             net1.assertNotDisconnected(TEST_CALLBACK_TIMEOUT_MS); // always incurs the timeout
2786             generalCb.assertNoCallback();
2787             // assertNotDisconnected waited for TEST_CALLBACK_TIMEOUT_MS, so waiting for the
2788             // linger period gives TEST_CALLBACK_TIMEOUT_MS time for the event to process.
2789             net1.expectDisconnected(UNREASONABLY_LONG_ALARM_WAIT_MS);
2790         } else {
2791             net1.expectDisconnected(TEST_CALLBACK_TIMEOUT_MS);
2792         }
2793         net1.disconnect();
2794         generalCb.expectCallback(CallbackEntry.LOST, net1);
2795 
2796         // Remove primary from net 2
2797         net2.setScore(new NetworkScore.Builder().build());
2798         // Request MMS
2799         final TestNetworkCallback mmsCallback = new TestNetworkCallback();
2800         mCm.requestNetwork(new NetworkRequest.Builder().addCapability(NET_CAPABILITY_MMS).build(),
2801                 mmsCallback);
2802         mmsCallback.expectAvailableCallbacksValidated(net2);
2803 
2804         // Bring up net 3 with primary but without MMS
2805         final TestNetworkAgentWrapper net3 = new TestNetworkAgentWrapper(transport);
2806         net3.setScore(new NetworkScore.Builder().setTransportPrimary(true).build());
2807         net3.connect(true);
2808 
2809         // Make sure default goes to net 3, but the MMS request doesn't
2810         generalCb.expectAvailableThenValidatedCallbacks(net3);
2811         defaultCb.expectAvailableDoubleValidatedCallbacks(net3);
2812         mmsCallback.assertNoCallback();
2813         net2.assertNotDisconnected(TEST_CALLBACK_TIMEOUT_MS); // Always incurs the timeout
2814 
2815         // Revoke MMS request and make sure net 2 is torn down with the appropriate delay
2816         mCm.unregisterNetworkCallback(mmsCallback);
2817         if (expectLingering) {
2818             // If the radio can time share, the linger delay hasn't elapsed yet, so apps will
2819             // get LOSING. If the radio can't time share, this is a hard loss, since the last
2820             // request keeping up this network has been removed and the network isn't lingering
2821             // for any other request.
2822             generalCb.expectCallback(CallbackEntry.LOSING, net2);
2823             net2.assertNotDisconnected(TEST_CALLBACK_TIMEOUT_MS);
2824             generalCb.assertNoCallback();
2825             net2.expectDisconnected(UNREASONABLY_LONG_ALARM_WAIT_MS);
2826         } else {
2827             net2.expectDisconnected(TEST_CALLBACK_TIMEOUT_MS);
2828         }
2829         net2.disconnect();
2830         generalCb.expectCallback(CallbackEntry.LOST, net2);
2831         defaultCb.assertNoCallback();
2832 
2833         net3.disconnect();
2834         mCm.unregisterNetworkCallback(defaultCb);
2835         mCm.unregisterNetworkCallback(generalCb);
2836     }
2837 
2838     // TODO : migrate to @Parameterized
2839     @Test
2840     public void testCellularOutscoresWeakWifi_CanTimeShare() throws Exception {
2841         // The behavior of this test should be the same whether the radio can time share or not.
2842         doTestCellularOutscoresWeakWifi(true);
2843     }
2844 
2845     // TODO : migrate to @Parameterized
2846     @Test
2847     public void testCellularOutscoresWeakWifi_CannotTimeShare() throws Exception {
2848         doTestCellularOutscoresWeakWifi(false);
2849     }
2850 
2851     public void doTestCellularOutscoresWeakWifi(
2852             final boolean cellRadioTimesharingCapable) throws Exception {
2853         mService.mCellularRadioTimesharingCapable = cellRadioTimesharingCapable;
2854         // Test bringing up validated cellular.
2855         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
2856         ExpectedBroadcast b = registerConnectivityBroadcast(1);
2857         mCellNetworkAgent.connect(true);
2858         b.expectBroadcast();
2859         verifyActiveNetwork(TRANSPORT_CELLULAR);
2860         // Test bringing up validated WiFi.
2861         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
2862         b = registerConnectivityBroadcast(2);
2863         mWiFiNetworkAgent.connect(true);
2864         b.expectBroadcast();
2865         verifyActiveNetwork(TRANSPORT_WIFI);
2866         // Test WiFi getting really weak.
2867         b = registerConnectivityBroadcast(2);
2868         mWiFiNetworkAgent.adjustScore(-11);
2869         b.expectBroadcast();
2870         verifyActiveNetwork(TRANSPORT_CELLULAR);
2871         // Test WiFi restoring signal strength.
2872         b = registerConnectivityBroadcast(2);
2873         mWiFiNetworkAgent.adjustScore(11);
2874         b.expectBroadcast();
2875         verifyActiveNetwork(TRANSPORT_WIFI);
2876     }
2877 
2878     // TODO : migrate to @Parameterized
2879     @Test
2880     public void testReapingNetwork_CanTimeShare() throws Exception {
2881         doTestReapingNetwork(true);
2882     }
2883 
2884     // TODO : migrate to @Parameterized
2885     @Test
2886     public void testReapingNetwork_CannotTimeShare() throws Exception {
2887         doTestReapingNetwork(false);
2888     }
2889 
2890     public void doTestReapingNetwork(
2891             final boolean cellRadioTimesharingCapable) throws Exception {
2892         mService.mCellularRadioTimesharingCapable = cellRadioTimesharingCapable;
2893         // Test bringing up WiFi without NET_CAPABILITY_INTERNET.
2894         // Expect it to be torn down immediately because it satisfies no requests.
2895         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
2896         mWiFiNetworkAgent.connectWithoutInternet();
2897         mWiFiNetworkAgent.expectDisconnected();
2898         // Test bringing up cellular without NET_CAPABILITY_INTERNET.
2899         // Expect it to be torn down immediately because it satisfies no requests.
2900         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
2901         mCellNetworkAgent.connectWithoutInternet();
2902         mCellNetworkAgent.expectDisconnected();
2903         // Test bringing up validated WiFi.
2904         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
2905         final ExpectedBroadcast b = expectConnectivityAction(TYPE_WIFI, DetailedState.CONNECTED);
2906         mWiFiNetworkAgent.connect(true);
2907         b.expectBroadcast();
2908         verifyActiveNetwork(TRANSPORT_WIFI);
2909         // Test bringing up unvalidated cellular.
2910         // Expect it to be torn down because it could never be the highest scoring network
2911         // satisfying the default request even if it validated.
2912         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
2913         mCellNetworkAgent.connect(false);
2914         mCellNetworkAgent.expectDisconnected();
2915         verifyActiveNetwork(TRANSPORT_WIFI);
2916         mWiFiNetworkAgent.disconnect();
2917         mWiFiNetworkAgent.expectDisconnected();
2918     }
2919 
2920     // TODO : migrate to @Parameterized
2921     @Test
2922     public void testCellularFallback_CanTimeShare() throws Exception {
2923         doTestCellularFallback(true);
2924     }
2925 
2926     // TODO : migrate to @Parameterized
2927     @Test
2928     public void testCellularFallback_CannotTimeShare() throws Exception {
2929         doTestCellularFallback(false);
2930     }
2931 
2932     public void doTestCellularFallback(
2933             final boolean cellRadioTimesharingCapable) throws Exception {
2934         mService.mCellularRadioTimesharingCapable = cellRadioTimesharingCapable;
2935         // Test bringing up validated cellular.
2936         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
2937         ExpectedBroadcast b = registerConnectivityBroadcast(1);
2938         mCellNetworkAgent.connect(true);
2939         b.expectBroadcast();
2940         verifyActiveNetwork(TRANSPORT_CELLULAR);
2941         // Test bringing up validated WiFi.
2942         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
2943         b = registerConnectivityBroadcast(2);
2944         mWiFiNetworkAgent.connect(true);
2945         b.expectBroadcast();
2946         verifyActiveNetwork(TRANSPORT_WIFI);
2947         // Reevaluate WiFi (it'll instantly fail DNS).
2948         b = registerConnectivityBroadcast(2);
2949         assertTrue(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
2950                 NET_CAPABILITY_VALIDATED));
2951         mCm.reportBadNetwork(mWiFiNetworkAgent.getNetwork());
2952         // Should quickly fall back to Cellular.
2953         b.expectBroadcast();
2954         assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
2955                 NET_CAPABILITY_VALIDATED));
2956         verifyActiveNetwork(TRANSPORT_CELLULAR);
2957         // Reevaluate cellular (it'll instantly fail DNS).
2958         b = registerConnectivityBroadcast(2);
2959         assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
2960                 NET_CAPABILITY_VALIDATED));
2961         mCm.reportBadNetwork(mCellNetworkAgent.getNetwork());
2962         // Should quickly fall back to WiFi.
2963         b.expectBroadcast();
2964         assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
2965                 NET_CAPABILITY_VALIDATED));
2966         assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
2967                 NET_CAPABILITY_VALIDATED));
2968         verifyActiveNetwork(TRANSPORT_WIFI);
2969     }
2970 
2971     // TODO : migrate to @Parameterized
2972     @Test
2973     public void testWiFiFallback_CanTimeShare() throws Exception {
2974         doTestWiFiFallback(true);
2975     }
2976 
2977     // TODO : migrate to @Parameterized
2978     @Test
2979     public void testWiFiFallback_CannotTimeShare() throws Exception {
2980         doTestWiFiFallback(false);
2981     }
2982 
2983     public void doTestWiFiFallback(
2984             final boolean cellRadioTimesharingCapable) throws Exception {
2985         mService.mCellularRadioTimesharingCapable = cellRadioTimesharingCapable;
2986         // Test bringing up unvalidated WiFi.
2987         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
2988         ExpectedBroadcast b = registerConnectivityBroadcast(1);
2989         mWiFiNetworkAgent.connect(false);
2990         b.expectBroadcast();
2991         verifyActiveNetwork(TRANSPORT_WIFI);
2992         // Test bringing up validated cellular.
2993         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
2994         b = registerConnectivityBroadcast(2);
2995         mCellNetworkAgent.connect(true);
2996         b.expectBroadcast();
2997         verifyActiveNetwork(TRANSPORT_CELLULAR);
2998         // Reevaluate cellular (it'll instantly fail DNS).
2999         b = registerConnectivityBroadcast(2);
3000         assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
3001                 NET_CAPABILITY_VALIDATED));
3002         mCm.reportBadNetwork(mCellNetworkAgent.getNetwork());
3003         // Should quickly fall back to WiFi.
3004         b.expectBroadcast();
3005         assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
3006                 NET_CAPABILITY_VALIDATED));
3007         verifyActiveNetwork(TRANSPORT_WIFI);
3008     }
3009 
3010     @Test
3011     public void testRequiresValidation() {
3012         assertTrue(NetworkMonitorUtils.isValidationRequired(
3013                 NetworkAgentConfigShimImpl.newInstance(null),
3014                 mCm.getDefaultRequest().networkCapabilities));
3015     }
3016 
3017     /**
3018      * Utility NetworkCallback for testing. The caller must explicitly test for all the callbacks
3019      * this class receives, by calling expectCallback() exactly once each time a callback is
3020      * received. assertNoCallback may be called at any time.
3021      */
3022     private class TestNetworkCallback extends TestableNetworkCallback {
3023         TestNetworkCallback() {
3024             super(TEST_CALLBACK_TIMEOUT_MS);
3025         }
3026 
3027         @Override
3028         public void assertNoCallback() {
3029             // TODO: better support this use case in TestableNetworkCallback
3030             waitForIdle();
3031             assertNoCallback(0 /* timeout */);
3032         }
3033 
3034         @Override
3035         public <T extends CallbackEntry> T expectCallback(final KClass<T> type, final HasNetwork n,
3036                 final long timeoutMs) {
3037             final T callback = super.expectCallback(type, n, timeoutMs);
3038             if (callback instanceof CallbackEntry.Losing) {
3039                 // TODO : move this to the specific test(s) needing this rather than here.
3040                 final CallbackEntry.Losing losing = (CallbackEntry.Losing) callback;
3041                 final int maxMsToLive = losing.getMaxMsToLive();
3042                 String msg = String.format(
3043                         "Invalid linger time value %d, must be between %d and %d",
3044                         maxMsToLive, 0, mService.mLingerDelayMs);
3045                 assertTrue(msg, 0 <= maxMsToLive && maxMsToLive <= mService.mLingerDelayMs);
3046             }
3047             return callback;
3048         }
3049     }
3050 
3051     // Can't be part of TestNetworkCallback because "cannot be declared static; static methods can
3052     // only be declared in a static or top level type".
3053     static void assertNoCallbacks(TestNetworkCallback ... callbacks) {
3054         for (TestNetworkCallback c : callbacks) {
3055             c.assertNoCallback();
3056         }
3057     }
3058 
3059     static void expectOnLost(TestNetworkAgentWrapper network, TestNetworkCallback ... callbacks) {
3060         for (TestNetworkCallback c : callbacks) {
3061             c.expectCallback(CallbackEntry.LOST, network);
3062         }
3063     }
3064 
3065     static void expectAvailableCallbacksUnvalidatedWithSpecifier(TestNetworkAgentWrapper network,
3066             NetworkSpecifier specifier, TestNetworkCallback ... callbacks) {
3067         for (TestNetworkCallback c : callbacks) {
3068             c.expectCallback(CallbackEntry.AVAILABLE, network);
3069             c.expectCapabilitiesThat(network, (nc) ->
3070                     !nc.hasCapability(NET_CAPABILITY_VALIDATED)
3071                             && Objects.equals(specifier, nc.getNetworkSpecifier()));
3072             c.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, network);
3073             c.expectCallback(CallbackEntry.BLOCKED_STATUS, network);
3074         }
3075     }
3076 
3077     @Test
3078     public void testStateChangeNetworkCallbacks() throws Exception {
3079         final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback();
3080         final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
3081         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
3082         final NetworkRequest genericRequest = new NetworkRequest.Builder()
3083                 .clearCapabilities().build();
3084         final NetworkRequest wifiRequest = new NetworkRequest.Builder()
3085                 .addTransportType(TRANSPORT_WIFI).build();
3086         final NetworkRequest cellRequest = new NetworkRequest.Builder()
3087                 .addTransportType(TRANSPORT_CELLULAR).build();
3088         mCm.registerNetworkCallback(genericRequest, genericNetworkCallback);
3089         mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
3090         mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
3091 
3092         // Test unvalidated networks
3093         ExpectedBroadcast b = registerConnectivityBroadcast(1);
3094         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
3095         mCellNetworkAgent.connect(false);
3096         genericNetworkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
3097         cellNetworkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
3098         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
3099         b.expectBroadcast();
3100         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
3101 
3102         // This should not trigger spurious onAvailable() callbacks, b/21762680.
3103         mCellNetworkAgent.adjustScore(-1);
3104         waitForIdle();
3105         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
3106         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
3107 
3108         b = registerConnectivityBroadcast(2);
3109         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3110         mWiFiNetworkAgent.connect(false);
3111         genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
3112         wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
3113         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
3114         b.expectBroadcast();
3115         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
3116 
3117         b = registerConnectivityBroadcast(2);
3118         mWiFiNetworkAgent.disconnect();
3119         genericNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
3120         wifiNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
3121         cellNetworkCallback.assertNoCallback();
3122         b.expectBroadcast();
3123         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
3124 
3125         b = registerConnectivityBroadcast(1);
3126         mCellNetworkAgent.disconnect();
3127         genericNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
3128         cellNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
3129         b.expectBroadcast();
3130         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
3131 
3132         // Test validated networks
3133         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
3134         mCellNetworkAgent.connect(true);
3135         genericNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
3136         cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
3137         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
3138         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
3139 
3140         // This should not trigger spurious onAvailable() callbacks, b/21762680.
3141         mCellNetworkAgent.adjustScore(-1);
3142         waitForIdle();
3143         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
3144         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
3145 
3146         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3147         mWiFiNetworkAgent.connect(true);
3148         genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
3149         genericNetworkCallback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
3150         genericNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
3151         wifiNetworkCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
3152         cellNetworkCallback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
3153         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
3154         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
3155 
3156         mWiFiNetworkAgent.disconnect();
3157         genericNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
3158         wifiNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
3159         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
3160 
3161         mCellNetworkAgent.disconnect();
3162         genericNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
3163         cellNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
3164         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
3165     }
3166 
3167     private void doNetworkCallbacksSanitizationTest(boolean sanitized) throws Exception {
3168         final TestNetworkCallback callback = new TestNetworkCallback();
3169         final TestNetworkCallback defaultCallback = new TestNetworkCallback();
3170         final NetworkRequest wifiRequest = new NetworkRequest.Builder()
3171                 .addTransportType(TRANSPORT_WIFI).build();
3172         mCm.registerNetworkCallback(wifiRequest, callback);
3173         mCm.registerDefaultNetworkCallback(defaultCallback);
3174 
3175         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3176         mWiFiNetworkAgent.connect(false);
3177         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
3178         defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
3179 
3180         final LinkProperties newLp = new LinkProperties();
3181         final Uri capportUrl = Uri.parse("https://capport.example.com/api");
3182         final CaptivePortalData capportData = new CaptivePortalData.Builder()
3183                 .setCaptive(true).build();
3184 
3185         final Uri expectedCapportUrl = sanitized ? null : capportUrl;
3186         newLp.setCaptivePortalApiUrl(capportUrl);
3187         mWiFiNetworkAgent.sendLinkProperties(newLp);
3188         callback.expectLinkPropertiesThat(mWiFiNetworkAgent, lp ->
3189                 Objects.equals(expectedCapportUrl, lp.getCaptivePortalApiUrl()));
3190         defaultCallback.expectLinkPropertiesThat(mWiFiNetworkAgent, lp ->
3191                 Objects.equals(expectedCapportUrl, lp.getCaptivePortalApiUrl()));
3192 
3193         final CaptivePortalData expectedCapportData = sanitized ? null : capportData;
3194         mWiFiNetworkAgent.notifyCapportApiDataChanged(capportData);
3195         callback.expectLinkPropertiesThat(mWiFiNetworkAgent, lp ->
3196                 Objects.equals(expectedCapportData, lp.getCaptivePortalData()));
3197         defaultCallback.expectLinkPropertiesThat(mWiFiNetworkAgent, lp ->
3198                 Objects.equals(expectedCapportData, lp.getCaptivePortalData()));
3199 
3200         final LinkProperties lp = mCm.getLinkProperties(mWiFiNetworkAgent.getNetwork());
3201         assertEquals(expectedCapportUrl, lp.getCaptivePortalApiUrl());
3202         assertEquals(expectedCapportData, lp.getCaptivePortalData());
3203     }
3204 
3205     @Test
3206     public void networkCallbacksSanitizationTest_Sanitize() throws Exception {
3207         mServiceContext.setPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
3208                 PERMISSION_DENIED);
3209         mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_DENIED);
3210         doNetworkCallbacksSanitizationTest(true /* sanitized */);
3211     }
3212 
3213     @Test
3214     public void networkCallbacksSanitizationTest_NoSanitize_NetworkStack() throws Exception {
3215         mServiceContext.setPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
3216                 PERMISSION_GRANTED);
3217         mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_DENIED);
3218         doNetworkCallbacksSanitizationTest(false /* sanitized */);
3219     }
3220 
3221     @Test
3222     public void networkCallbacksSanitizationTest_NoSanitize_Settings() throws Exception {
3223         mServiceContext.setPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
3224                 PERMISSION_DENIED);
3225         mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_GRANTED);
3226         doNetworkCallbacksSanitizationTest(false /* sanitized */);
3227     }
3228 
3229     @Test
3230     public void testOwnerUidCannotChange() throws Exception {
3231         final NetworkCapabilities ncTemplate = new NetworkCapabilities();
3232         final int originalOwnerUid = Process.myUid();
3233         ncTemplate.setOwnerUid(originalOwnerUid);
3234 
3235         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, new LinkProperties(),
3236                 ncTemplate);
3237         mWiFiNetworkAgent.connect(false);
3238         waitForIdle();
3239 
3240         // Send ConnectivityService an update to the mWiFiNetworkAgent's capabilities that changes
3241         // the owner UID and an unrelated capability.
3242         NetworkCapabilities agentCapabilities = mWiFiNetworkAgent.getNetworkCapabilities();
3243         assertEquals(originalOwnerUid, agentCapabilities.getOwnerUid());
3244         agentCapabilities.setOwnerUid(42);
3245         assertFalse(agentCapabilities.hasCapability(NET_CAPABILITY_NOT_CONGESTED));
3246         agentCapabilities.addCapability(NET_CAPABILITY_NOT_CONGESTED);
3247         mWiFiNetworkAgent.setNetworkCapabilities(agentCapabilities, true);
3248         waitForIdle();
3249 
3250         // Owner UIDs are not visible without location permission.
3251         setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
3252                 Manifest.permission.ACCESS_FINE_LOCATION);
3253 
3254         // Check that the capability change has been applied but the owner UID is not modified.
3255         NetworkCapabilities nc = mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork());
3256         assertEquals(originalOwnerUid, nc.getOwnerUid());
3257         assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_CONGESTED));
3258     }
3259 
3260     @Test
3261     public void testMultipleLingering() throws Exception {
3262         // This test would be flaky with the default 120ms timer: that is short enough that
3263         // lingered networks are torn down before assertions can be run. We don't want to mock the
3264         // lingering timer to keep the WakeupMessage logic realistic: this has already proven useful
3265         // in detecting races.
3266         mService.mLingerDelayMs = 300;
3267 
3268         NetworkRequest request = new NetworkRequest.Builder()
3269                 .clearCapabilities().addCapability(NET_CAPABILITY_NOT_METERED)
3270                 .build();
3271         TestNetworkCallback callback = new TestNetworkCallback();
3272         mCm.registerNetworkCallback(request, callback);
3273 
3274         TestNetworkCallback defaultCallback = new TestNetworkCallback();
3275         mCm.registerDefaultNetworkCallback(defaultCallback);
3276 
3277         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
3278         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3279         mEthernetNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
3280 
3281         mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
3282         mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
3283         mEthernetNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
3284 
3285         mCellNetworkAgent.connect(true);
3286         callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
3287         defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
3288         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
3289         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
3290 
3291         mWiFiNetworkAgent.connect(true);
3292         // We get AVAILABLE on wifi when wifi connects and satisfies our unmetered request.
3293         // We then get LOSING when wifi validates and cell is outscored.
3294         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
3295         // TODO: Investigate sending validated before losing.
3296         callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
3297         callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
3298         defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
3299         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
3300         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
3301 
3302         mEthernetNetworkAgent.connect(true);
3303         callback.expectAvailableCallbacksUnvalidated(mEthernetNetworkAgent);
3304         // TODO: Investigate sending validated before losing.
3305         callback.expectCallback(CallbackEntry.LOSING, mWiFiNetworkAgent);
3306         callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mEthernetNetworkAgent);
3307         defaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent);
3308         assertEquals(mEthernetNetworkAgent.getNetwork(), mCm.getActiveNetwork());
3309         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
3310 
3311         mEthernetNetworkAgent.disconnect();
3312         callback.expectCallback(CallbackEntry.LOST, mEthernetNetworkAgent);
3313         defaultCallback.expectCallback(CallbackEntry.LOST, mEthernetNetworkAgent);
3314         defaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
3315         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
3316 
3317         for (int i = 0; i < 4; i++) {
3318             TestNetworkAgentWrapper oldNetwork, newNetwork;
3319             if (i % 2 == 0) {
3320                 mWiFiNetworkAgent.adjustScore(-15);
3321                 oldNetwork = mWiFiNetworkAgent;
3322                 newNetwork = mCellNetworkAgent;
3323             } else {
3324                 mWiFiNetworkAgent.adjustScore(15);
3325                 oldNetwork = mCellNetworkAgent;
3326                 newNetwork = mWiFiNetworkAgent;
3327 
3328             }
3329             callback.expectCallback(CallbackEntry.LOSING, oldNetwork);
3330             // TODO: should we send an AVAILABLE callback to newNetwork, to indicate that it is no
3331             // longer lingering?
3332             defaultCallback.expectAvailableCallbacksValidated(newNetwork);
3333             assertEquals(newNetwork.getNetwork(), mCm.getActiveNetwork());
3334         }
3335         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
3336 
3337         // Verify that if a network no longer satisfies a request, we send LOST and not LOSING, even
3338         // if the network is still up.
3339         mWiFiNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
3340         // We expect a notification about the capabilities change, and nothing else.
3341         defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_METERED, mWiFiNetworkAgent);
3342         defaultCallback.assertNoCallback();
3343         callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
3344         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
3345 
3346         // Wifi no longer satisfies our listen, which is for an unmetered network.
3347         // But because its score is 55, it's still up (and the default network).
3348         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
3349 
3350         // Disconnect our test networks.
3351         mWiFiNetworkAgent.disconnect();
3352         defaultCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
3353         defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
3354         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
3355         mCellNetworkAgent.disconnect();
3356         defaultCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
3357         waitForIdle();
3358         assertEquals(null, mCm.getActiveNetwork());
3359 
3360         mCm.unregisterNetworkCallback(callback);
3361         waitForIdle();
3362 
3363         // Check that a network is only lingered or torn down if it would not satisfy a request even
3364         // if it validated.
3365         request = new NetworkRequest.Builder().clearCapabilities().build();
3366         callback = new TestNetworkCallback();
3367 
3368         mCm.registerNetworkCallback(request, callback);
3369 
3370         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
3371         mCellNetworkAgent.connect(false);   // Score: 10
3372         callback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
3373         defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
3374         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
3375         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
3376 
3377         // Bring up wifi with a score of 20.
3378         // Cell stays up because it would satisfy the default request if it validated.
3379         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3380         mWiFiNetworkAgent.connect(false);   // Score: 20
3381         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
3382         defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
3383         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
3384         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
3385 
3386         mWiFiNetworkAgent.disconnect();
3387         callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
3388         defaultCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
3389         defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
3390         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
3391         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
3392 
3393         // Bring up wifi, then validate it. Previous versions would immediately tear down cell, but
3394         // it's arguably correct to linger it, since it was the default network before it validated.
3395         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3396         mWiFiNetworkAgent.connect(true);
3397         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
3398         // TODO: Investigate sending validated before losing.
3399         callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
3400         callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
3401         defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
3402         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
3403         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
3404 
3405         mWiFiNetworkAgent.disconnect();
3406         callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
3407         defaultCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
3408         defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
3409         mCellNetworkAgent.disconnect();
3410         callback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
3411         defaultCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
3412         waitForIdle();
3413         assertEquals(null, mCm.getActiveNetwork());
3414 
3415         // If a network is lingering, and we add and remove a request from it, resume lingering.
3416         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
3417         mCellNetworkAgent.connect(true);
3418         callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
3419         defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
3420         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
3421         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3422         mWiFiNetworkAgent.connect(true);
3423         defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
3424         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
3425         // TODO: Investigate sending validated before losing.
3426         callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
3427         callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
3428         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
3429 
3430         NetworkRequest cellRequest = new NetworkRequest.Builder()
3431                 .addTransportType(TRANSPORT_CELLULAR).build();
3432         NetworkCallback noopCallback = new NetworkCallback();
3433         mCm.requestNetwork(cellRequest, noopCallback);
3434         // TODO: should this cause an AVAILABLE callback, to indicate that the network is no longer
3435         // lingering?
3436         mCm.unregisterNetworkCallback(noopCallback);
3437         callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
3438 
3439         // Similar to the above: lingering can start even after the lingered request is removed.
3440         // Disconnect wifi and switch to cell.
3441         mWiFiNetworkAgent.disconnect();
3442         callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
3443         defaultCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
3444         defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
3445         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
3446 
3447         // Cell is now the default network. Pin it with a cell-specific request.
3448         noopCallback = new NetworkCallback();  // Can't reuse NetworkCallbacks. http://b/20701525
3449         mCm.requestNetwork(cellRequest, noopCallback);
3450 
3451         // Now connect wifi, and expect it to become the default network.
3452         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3453         mWiFiNetworkAgent.connect(true);
3454         callback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
3455         defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
3456         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
3457         // The default request is lingering on cell, but nothing happens to cell, and we send no
3458         // callbacks for it, because it's kept up by cellRequest.
3459         callback.assertNoCallback();
3460         // Now unregister cellRequest and expect cell to start lingering.
3461         mCm.unregisterNetworkCallback(noopCallback);
3462         callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
3463 
3464         // Let linger run its course.
3465         callback.assertNoCallback();
3466         final int lingerTimeoutMs = mService.mLingerDelayMs + mService.mLingerDelayMs / 4;
3467         callback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent, lingerTimeoutMs);
3468 
3469         // Register a TRACK_DEFAULT request and check that it does not affect lingering.
3470         TestNetworkCallback trackDefaultCallback = new TestNetworkCallback();
3471         mCm.registerDefaultNetworkCallback(trackDefaultCallback);
3472         trackDefaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
3473         mEthernetNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
3474         mEthernetNetworkAgent.connect(true);
3475         callback.expectAvailableCallbacksUnvalidated(mEthernetNetworkAgent);
3476         callback.expectCallback(CallbackEntry.LOSING, mWiFiNetworkAgent);
3477         callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mEthernetNetworkAgent);
3478         trackDefaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent);
3479         defaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent);
3480         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
3481 
3482         // Let linger run its course.
3483         callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent, lingerTimeoutMs);
3484 
3485         // Clean up.
3486         mEthernetNetworkAgent.disconnect();
3487         callback.expectCallback(CallbackEntry.LOST, mEthernetNetworkAgent);
3488         defaultCallback.expectCallback(CallbackEntry.LOST, mEthernetNetworkAgent);
3489         trackDefaultCallback.expectCallback(CallbackEntry.LOST, mEthernetNetworkAgent);
3490 
3491         mCm.unregisterNetworkCallback(callback);
3492         mCm.unregisterNetworkCallback(defaultCallback);
3493         mCm.unregisterNetworkCallback(trackDefaultCallback);
3494     }
3495 
3496     private void grantUsingBackgroundNetworksPermissionForUid(final int uid) throws Exception {
3497         grantUsingBackgroundNetworksPermissionForUid(uid, mContext.getPackageName());
3498     }
3499 
3500     private void grantUsingBackgroundNetworksPermissionForUid(
3501             final int uid, final String packageName) throws Exception {
3502         doReturn(buildPackageInfo(true /* hasSystemPermission */, uid)).when(mPackageManager)
3503                 .getPackageInfo(eq(packageName), eq(GET_PERMISSIONS));
3504         mService.mPermissionMonitor.onPackageAdded(packageName, uid);
3505     }
3506 
3507     @Test
3508     public void testNetworkGoesIntoBackgroundAfterLinger() throws Exception {
3509         setAlwaysOnNetworks(true);
3510         grantUsingBackgroundNetworksPermissionForUid(Binder.getCallingUid());
3511         NetworkRequest request = new NetworkRequest.Builder()
3512                 .clearCapabilities()
3513                 .build();
3514         TestNetworkCallback callback = new TestNetworkCallback();
3515         mCm.registerNetworkCallback(request, callback);
3516 
3517         TestNetworkCallback defaultCallback = new TestNetworkCallback();
3518         mCm.registerDefaultNetworkCallback(defaultCallback);
3519 
3520         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
3521         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3522 
3523         mCellNetworkAgent.connect(true);
3524         callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
3525         defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
3526 
3527         // Wifi comes up and cell lingers.
3528         mWiFiNetworkAgent.connect(true);
3529         defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
3530         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
3531         callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
3532         callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
3533 
3534         // File a request for cellular, then release it.
3535         NetworkRequest cellRequest = new NetworkRequest.Builder()
3536                 .addTransportType(TRANSPORT_CELLULAR).build();
3537         NetworkCallback noopCallback = new NetworkCallback();
3538         mCm.requestNetwork(cellRequest, noopCallback);
3539         mCm.unregisterNetworkCallback(noopCallback);
3540         callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
3541 
3542         // Let linger run its course.
3543         callback.assertNoCallback();
3544         final int lingerTimeoutMs = TEST_LINGER_DELAY_MS + TEST_LINGER_DELAY_MS / 4;
3545         callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent,
3546                 lingerTimeoutMs);
3547 
3548         // Clean up.
3549         mCm.unregisterNetworkCallback(defaultCallback);
3550         mCm.unregisterNetworkCallback(callback);
3551     }
3552 
3553     private NativeNetworkConfig nativeNetworkConfigPhysical(int netId, int permission) {
3554         return new NativeNetworkConfig(netId, NativeNetworkType.PHYSICAL, permission,
3555                 /*secure=*/ false, VpnManager.TYPE_VPN_NONE, /*excludeLocalRoutes=*/ false);
3556     }
3557 
3558     private NativeNetworkConfig nativeNetworkConfigVpn(int netId, boolean secure, int vpnType) {
3559         return new NativeNetworkConfig(netId, NativeNetworkType.VIRTUAL, INetd.PERMISSION_NONE,
3560                 secure, vpnType, /*excludeLocalRoutes=*/ false);
3561     }
3562 
3563     @Test
3564     public void testNetworkAgentCallbacks() throws Exception {
3565         // Keeps track of the order of events that happen in this test.
3566         final LinkedBlockingQueue<String> eventOrder = new LinkedBlockingQueue<>();
3567 
3568         final NetworkRequest request = new NetworkRequest.Builder()
3569                 .addTransportType(TRANSPORT_WIFI).build();
3570         final TestNetworkCallback callback = new TestNetworkCallback();
3571         final AtomicReference<Network> wifiNetwork = new AtomicReference<>();
3572         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3573 
3574         // Expectations for state when various callbacks fire. These expectations run on the handler
3575         // thread and not on the test thread because they need to prevent the handler thread from
3576         // advancing while they examine state.
3577 
3578         // 1. When onCreated fires, netd has been told to create the network.
3579         mWiFiNetworkAgent.setCreatedCallback(() -> {
3580             eventOrder.offer("onNetworkCreated");
3581             wifiNetwork.set(mWiFiNetworkAgent.getNetwork());
3582             assertNotNull(wifiNetwork.get());
3583             try {
3584                 verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
3585                         wifiNetwork.get().getNetId(), INetd.PERMISSION_NONE));
3586             } catch (RemoteException impossible) {
3587                 fail();
3588             }
3589         });
3590 
3591         // 2. onNetworkUnwanted isn't precisely ordered with respect to any particular events. Just
3592         //    check that it is fired at some point after disconnect.
3593         mWiFiNetworkAgent.setUnwantedCallback(() -> eventOrder.offer("onNetworkUnwanted"));
3594 
3595         // 3. While the teardown timer is running, connectivity APIs report the network is gone, but
3596         //    netd has not yet been told to destroy it.
3597         final Runnable duringTeardown = () -> {
3598             eventOrder.offer("timePasses");
3599             assertNull(mCm.getLinkProperties(wifiNetwork.get()));
3600             try {
3601                 verify(mMockNetd, never()).networkDestroy(wifiNetwork.get().getNetId());
3602             } catch (RemoteException impossible) {
3603                 fail();
3604             }
3605         };
3606 
3607         // 4. After onNetworkDisconnected is called, connectivity APIs report the network is gone,
3608         // and netd has been told to destroy it.
3609         mWiFiNetworkAgent.setDisconnectedCallback(() -> {
3610             eventOrder.offer("onNetworkDisconnected");
3611             assertNull(mCm.getLinkProperties(wifiNetwork.get()));
3612             try {
3613                 verify(mMockNetd).networkDestroy(wifiNetwork.get().getNetId());
3614             } catch (RemoteException impossible) {
3615                 fail();
3616             }
3617         });
3618 
3619         // Connect a network, and file a request for it after it has come up, to ensure the nascent
3620         // timer is cleared and the test does not have to wait for it. Filing the request after the
3621         // network has come up is necessary because ConnectivityService does not appear to clear the
3622         // nascent timer if the first request satisfied by the network was filed before the network
3623         // connected.
3624         // TODO: fix this bug, file the request before connecting, and remove the waitForIdle.
3625         mWiFiNetworkAgent.connectWithoutInternet();
3626         waitForIdle();
3627         mCm.requestNetwork(request, callback);
3628         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
3629 
3630         // Set teardown delay and make sure CS has processed it.
3631         mWiFiNetworkAgent.getNetworkAgent().setTeardownDelayMillis(300);
3632         waitForIdle();
3633 
3634         // Post the duringTeardown lambda to the handler so it fires while teardown is in progress.
3635         // The delay must be long enough it will run after the unregisterNetworkCallback has torn
3636         // down the network and started the teardown timer, and short enough that the lambda is
3637         // scheduled to run before the teardown timer.
3638         final Handler h = new Handler(mCsHandlerThread.getLooper());
3639         h.postDelayed(duringTeardown, 150);
3640 
3641         // Disconnect the network and check that events happened in the right order.
3642         mCm.unregisterNetworkCallback(callback);
3643         assertEquals("onNetworkCreated", eventOrder.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
3644         assertEquals("onNetworkUnwanted", eventOrder.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
3645         assertEquals("timePasses", eventOrder.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
3646         assertEquals("onNetworkDisconnected", eventOrder.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
3647 
3648         mCm.unregisterNetworkCallback(callback);
3649     }
3650 
3651     @Test
3652     public void testExplicitlySelected() throws Exception {
3653         NetworkRequest request = new NetworkRequest.Builder()
3654                 .clearCapabilities().addCapability(NET_CAPABILITY_INTERNET)
3655                 .build();
3656         TestNetworkCallback callback = new TestNetworkCallback();
3657         mCm.registerNetworkCallback(request, callback);
3658 
3659         // Bring up validated cell.
3660         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
3661         mCellNetworkAgent.connect(true);
3662         callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
3663 
3664         // Bring up unvalidated wifi with explicitlySelected=true.
3665         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3666         mWiFiNetworkAgent.explicitlySelected(true, false);
3667         mWiFiNetworkAgent.connect(false);
3668         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
3669 
3670         // Cell Remains the default.
3671         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
3672 
3673         // Lower wifi's score to below than cell, and check that it doesn't disconnect because
3674         // it's explicitly selected.
3675         mWiFiNetworkAgent.adjustScore(-40);
3676         mWiFiNetworkAgent.adjustScore(40);
3677         callback.assertNoCallback();
3678 
3679         // If the user chooses yes on the "No Internet access, stay connected?" dialog, we switch to
3680         // wifi even though it's unvalidated.
3681         mCm.setAcceptUnvalidated(mWiFiNetworkAgent.getNetwork(), true, false);
3682         callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
3683         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
3684 
3685         // Disconnect wifi, and then reconnect, again with explicitlySelected=true.
3686         mWiFiNetworkAgent.disconnect();
3687         callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
3688         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3689         mWiFiNetworkAgent.explicitlySelected(true, false);
3690         mWiFiNetworkAgent.connect(false);
3691         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
3692 
3693         // If the user chooses no on the "No Internet access, stay connected?" dialog, we ask the
3694         // network to disconnect.
3695         mCm.setAcceptUnvalidated(mWiFiNetworkAgent.getNetwork(), false, false);
3696         callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
3697 
3698         // Reconnect, again with explicitlySelected=true, but this time validate.
3699         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3700         mWiFiNetworkAgent.explicitlySelected(true, false);
3701         mWiFiNetworkAgent.connect(true);
3702         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
3703         callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
3704         callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
3705         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
3706 
3707         mEthernetNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
3708         mEthernetNetworkAgent.connect(true);
3709         callback.expectAvailableCallbacksUnvalidated(mEthernetNetworkAgent);
3710         callback.expectCallback(CallbackEntry.LOSING, mWiFiNetworkAgent);
3711         callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mEthernetNetworkAgent);
3712         assertEquals(mEthernetNetworkAgent.getNetwork(), mCm.getActiveNetwork());
3713         callback.assertNoCallback();
3714 
3715         // Disconnect wifi, and then reconnect as if the user had selected "yes, don't ask again"
3716         // (i.e., with explicitlySelected=true and acceptUnvalidated=true). Expect to switch to
3717         // wifi immediately.
3718         mWiFiNetworkAgent.disconnect();
3719         callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
3720         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3721         mWiFiNetworkAgent.explicitlySelected(true, true);
3722         mWiFiNetworkAgent.connect(false);
3723         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
3724         callback.expectCallback(CallbackEntry.LOSING, mEthernetNetworkAgent);
3725         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
3726         mEthernetNetworkAgent.disconnect();
3727         callback.expectCallback(CallbackEntry.LOST, mEthernetNetworkAgent);
3728 
3729         // Disconnect and reconnect with explicitlySelected=false and acceptUnvalidated=true.
3730         // Check that the network is not scored specially and that the device prefers cell data.
3731         mWiFiNetworkAgent.disconnect();
3732         callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
3733         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3734         mWiFiNetworkAgent.explicitlySelected(false, true);
3735         mWiFiNetworkAgent.connect(false);
3736         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
3737         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
3738 
3739         // Clean up.
3740         mWiFiNetworkAgent.disconnect();
3741         mCellNetworkAgent.disconnect();
3742 
3743         callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
3744         callback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
3745     }
3746 
3747     private void tryNetworkFactoryRequests(int capability) throws Exception {
3748         // Verify NOT_RESTRICTED is set appropriately
3749         final NetworkCapabilities nc = new NetworkRequest.Builder().addCapability(capability)
3750                 .build().networkCapabilities;
3751         if (capability == NET_CAPABILITY_CBS || capability == NET_CAPABILITY_DUN
3752                 || capability == NET_CAPABILITY_EIMS || capability == NET_CAPABILITY_FOTA
3753                 || capability == NET_CAPABILITY_IA || capability == NET_CAPABILITY_IMS
3754                 || capability == NET_CAPABILITY_RCS || capability == NET_CAPABILITY_XCAP
3755                 || capability == NET_CAPABILITY_VSIM || capability == NET_CAPABILITY_BIP
3756                 || capability == NET_CAPABILITY_ENTERPRISE || capability == NET_CAPABILITY_MMTEL) {
3757             assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
3758         } else {
3759             assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
3760         }
3761 
3762         NetworkCapabilities filter = new NetworkCapabilities();
3763         filter.addTransportType(TRANSPORT_CELLULAR);
3764         filter.addCapability(capability);
3765         // Add NOT_VCN_MANAGED capability into filter unconditionally since some requests will add
3766         // NOT_VCN_MANAGED automatically but not for NetworkCapabilities,
3767         // see {@code NetworkCapabilities#deduceNotVcnManagedCapability} for more details.
3768         filter.addCapability(NET_CAPABILITY_NOT_VCN_MANAGED);
3769         final HandlerThread handlerThread = new HandlerThread("testNetworkFactoryRequests");
3770         handlerThread.start();
3771         final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
3772                 mServiceContext, "testFactory", filter, mCsHandlerThread);
3773         testFactory.setScoreFilter(45);
3774         testFactory.register();
3775 
3776         final NetworkCallback networkCallback;
3777         if (capability != NET_CAPABILITY_INTERNET) {
3778             // If the capability passed in argument is part of the default request, then the
3779             // factory will see the default request. Otherwise the filter will prevent the
3780             // factory from seeing it. In that case, add a request so it can be tested.
3781             assertFalse(testFactory.getMyStartRequested());
3782             NetworkRequest request = new NetworkRequest.Builder().addCapability(capability).build();
3783             networkCallback = new NetworkCallback();
3784             mCm.requestNetwork(request, networkCallback);
3785         } else {
3786             networkCallback = null;
3787         }
3788         testFactory.expectRequestAdd();
3789         testFactory.assertRequestCountEquals(1);
3790         assertTrue(testFactory.getMyStartRequested());
3791 
3792         // Now bring in a higher scored network.
3793         TestNetworkAgentWrapper testAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
3794         // When testAgent connects, because of its score (50 legacy int / cell transport)
3795         // it will beat or equal the testFactory's offer, so the request will be removed.
3796         // Note the agent as validated only if the capability is INTERNET, as it's the only case
3797         // where it makes sense.
3798         testAgent.connect(NET_CAPABILITY_INTERNET == capability /* validated */);
3799         testAgent.addCapability(capability);
3800         testFactory.expectRequestRemove();
3801         testFactory.assertRequestCountEquals(0);
3802         assertFalse(testFactory.getMyStartRequested());
3803 
3804         // Add a request and make sure it's not sent to the factory, because the agent
3805         // is satisfying it better.
3806         final NetworkCallback cb = new ConnectivityManager.NetworkCallback();
3807         mCm.requestNetwork(new NetworkRequest.Builder().addCapability(capability).build(), cb);
3808         expectNoRequestChanged(testFactory);
3809         testFactory.assertRequestCountEquals(0);
3810         assertFalse(testFactory.getMyStartRequested());
3811 
3812         // If using legacy scores, make the test agent weak enough to have the exact same score as
3813         // the factory (50 for cell - 5 adjustment). Make sure the factory doesn't see the request.
3814         // If not using legacy score, this is a no-op and the "same score removes request" behavior
3815         // has already been tested above.
3816         testAgent.adjustScore(-5);
3817         expectNoRequestChanged(testFactory);
3818         assertFalse(testFactory.getMyStartRequested());
3819 
3820         // Make the test agent weak enough that the factory will see the two requests (the one that
3821         // was just sent, and either the default one or the one sent at the top of this test if
3822         // the default won't be seen).
3823         testAgent.setScore(new NetworkScore.Builder().setLegacyInt(2).setExiting(true).build());
3824         testFactory.expectRequestAdds(2);
3825         testFactory.assertRequestCountEquals(2);
3826         assertTrue(testFactory.getMyStartRequested());
3827 
3828         // Now unregister and make sure the request is removed.
3829         mCm.unregisterNetworkCallback(cb);
3830         testFactory.expectRequestRemove();
3831 
3832         // Bring in a bunch of requests.
3833         assertEquals(1, testFactory.getMyRequestCount());
3834         ConnectivityManager.NetworkCallback[] networkCallbacks =
3835                 new ConnectivityManager.NetworkCallback[10];
3836         for (int i = 0; i< networkCallbacks.length; i++) {
3837             networkCallbacks[i] = new ConnectivityManager.NetworkCallback();
3838             NetworkRequest.Builder builder = new NetworkRequest.Builder();
3839             builder.addCapability(capability);
3840             mCm.requestNetwork(builder.build(), networkCallbacks[i]);
3841         }
3842         testFactory.expectRequestAdds(10);
3843         testFactory.assertRequestCountEquals(11); // +1 for the default/test specific request
3844         assertTrue(testFactory.getMyStartRequested());
3845 
3846         // Remove the requests.
3847         for (int i = 0; i < networkCallbacks.length; i++) {
3848             mCm.unregisterNetworkCallback(networkCallbacks[i]);
3849         }
3850         testFactory.expectRequestRemoves(10);
3851         testFactory.assertRequestCountEquals(1);
3852         assertTrue(testFactory.getMyStartRequested());
3853 
3854         // Adjust the agent score up again. Expect the request to be withdrawn.
3855         testAgent.setScore(new NetworkScore.Builder().setLegacyInt(50).build());
3856         testFactory.expectRequestRemove();
3857         testFactory.assertRequestCountEquals(0);
3858         assertFalse(testFactory.getMyStartRequested());
3859 
3860         // Drop the higher scored network.
3861         testAgent.disconnect();
3862         testFactory.expectRequestAdd();
3863         testFactory.assertRequestCountEquals(1);
3864         assertEquals(1, testFactory.getMyRequestCount());
3865         assertTrue(testFactory.getMyStartRequested());
3866 
3867         testFactory.terminate();
3868         testFactory.assertNoRequestChanged();
3869         if (networkCallback != null) mCm.unregisterNetworkCallback(networkCallback);
3870         handlerThread.quit();
3871     }
3872 
3873     @Test
3874     public void testNetworkFactoryRequests() throws Exception {
3875         tryNetworkFactoryRequests(NET_CAPABILITY_MMS);
3876         tryNetworkFactoryRequests(NET_CAPABILITY_SUPL);
3877         tryNetworkFactoryRequests(NET_CAPABILITY_DUN);
3878         tryNetworkFactoryRequests(NET_CAPABILITY_FOTA);
3879         tryNetworkFactoryRequests(NET_CAPABILITY_IMS);
3880         tryNetworkFactoryRequests(NET_CAPABILITY_CBS);
3881         tryNetworkFactoryRequests(NET_CAPABILITY_WIFI_P2P);
3882         tryNetworkFactoryRequests(NET_CAPABILITY_IA);
3883         tryNetworkFactoryRequests(NET_CAPABILITY_RCS);
3884         tryNetworkFactoryRequests(NET_CAPABILITY_MMTEL);
3885         tryNetworkFactoryRequests(NET_CAPABILITY_XCAP);
3886         tryNetworkFactoryRequests(NET_CAPABILITY_ENTERPRISE);
3887         tryNetworkFactoryRequests(NET_CAPABILITY_EIMS);
3888         tryNetworkFactoryRequests(NET_CAPABILITY_NOT_METERED);
3889         tryNetworkFactoryRequests(NET_CAPABILITY_INTERNET);
3890         tryNetworkFactoryRequests(NET_CAPABILITY_TRUSTED);
3891         tryNetworkFactoryRequests(NET_CAPABILITY_NOT_VPN);
3892         tryNetworkFactoryRequests(NET_CAPABILITY_VSIM);
3893         tryNetworkFactoryRequests(NET_CAPABILITY_BIP);
3894         // Skipping VALIDATED and CAPTIVE_PORTAL as they're disallowed.
3895     }
3896 
3897     @Test
3898     public void testRegisterIgnoringScore() throws Exception {
3899         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3900         mWiFiNetworkAgent.setScore(new NetworkScore.Builder().setLegacyInt(90).build());
3901         mWiFiNetworkAgent.connect(true /* validated */);
3902 
3903         // Make sure the factory sees the default network
3904         final NetworkCapabilities filter = new NetworkCapabilities();
3905         filter.addTransportType(TRANSPORT_CELLULAR);
3906         filter.addCapability(NET_CAPABILITY_INTERNET);
3907         filter.addCapability(NET_CAPABILITY_NOT_VCN_MANAGED);
3908         final HandlerThread handlerThread = new HandlerThread("testNetworkFactoryRequests");
3909         handlerThread.start();
3910         final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
3911                 mServiceContext, "testFactory", filter, mCsHandlerThread);
3912         testFactory.register();
3913 
3914         final MockNetworkFactory testFactoryAll = new MockNetworkFactory(handlerThread.getLooper(),
3915                 mServiceContext, "testFactoryAll", filter, mCsHandlerThread);
3916         testFactoryAll.registerIgnoringScore();
3917 
3918         // The regular test factory should not see the request, because WiFi is stronger than cell.
3919         expectNoRequestChanged(testFactory);
3920         // With ignoringScore though the request is seen.
3921         testFactoryAll.expectRequestAdd();
3922 
3923         // The legacy int will be ignored anyway, set the only other knob to true
3924         mWiFiNetworkAgent.setScore(new NetworkScore.Builder().setLegacyInt(110)
3925                 .setTransportPrimary(true).build());
3926 
3927         expectNoRequestChanged(testFactory); // still not seeing the request
3928         expectNoRequestChanged(testFactoryAll); // still seeing the request
3929 
3930         mWiFiNetworkAgent.disconnect();
3931     }
3932 
3933     @Test
3934     public void testNetworkFactoryUnregister() throws Exception {
3935         // Make sure the factory sees the default network
3936         final NetworkCapabilities filter = new NetworkCapabilities();
3937         filter.addCapability(NET_CAPABILITY_INTERNET);
3938         filter.addCapability(NET_CAPABILITY_NOT_VCN_MANAGED);
3939 
3940         final HandlerThread handlerThread = new HandlerThread("testNetworkFactoryRequests");
3941         handlerThread.start();
3942 
3943         // Checks that calling setScoreFilter on a NetworkFactory immediately before closing it
3944         // does not crash.
3945         for (int i = 0; i < 100; i++) {
3946             final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
3947                     mServiceContext, "testFactory", filter, mCsHandlerThread);
3948             // Register the factory and don't be surprised when the default request arrives.
3949             testFactory.register();
3950             testFactory.expectRequestAdd();
3951 
3952             testFactory.setScoreFilter(42);
3953             testFactory.terminate();
3954             testFactory.assertNoRequestChanged();
3955 
3956             if (i % 2 == 0) {
3957                 try {
3958                     testFactory.register();
3959                     fail("Re-registering terminated NetworkFactory should throw");
3960                 } catch (IllegalStateException expected) {
3961                 }
3962             }
3963         }
3964         handlerThread.quit();
3965     }
3966 
3967     @Test
3968     public void testNoMutableNetworkRequests() throws Exception {
3969         final PendingIntent pendingIntent = PendingIntent.getBroadcast(
3970                 mContext, 0 /* requestCode */, new Intent("a"), FLAG_IMMUTABLE);
3971         final NetworkRequest request1 = new NetworkRequest.Builder()
3972                 .addCapability(NET_CAPABILITY_VALIDATED)
3973                 .build();
3974         final NetworkRequest request2 = new NetworkRequest.Builder()
3975                 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL)
3976                 .build();
3977 
3978         final Class<IllegalArgumentException> expected = IllegalArgumentException.class;
3979         assertThrows(expected, () -> mCm.requestNetwork(request1, new NetworkCallback()));
3980         assertThrows(expected, () -> mCm.requestNetwork(request1, pendingIntent));
3981         assertThrows(expected, () -> mCm.requestNetwork(request2, new NetworkCallback()));
3982         assertThrows(expected, () -> mCm.requestNetwork(request2, pendingIntent));
3983     }
3984 
3985     @Test
3986     public void testNoAllowedUidsInNetworkRequests() throws Exception {
3987         final PendingIntent pendingIntent = PendingIntent.getBroadcast(
3988                 mContext, 0 /* requestCode */, new Intent("a"), FLAG_IMMUTABLE);
3989         final NetworkRequest r = new NetworkRequest.Builder().build();
3990         final ArraySet<Integer> allowedUids = new ArraySet<>();
3991         allowedUids.add(6);
3992         allowedUids.add(9);
3993         r.networkCapabilities.setAllowedUids(allowedUids);
3994 
3995         final Handler handler = new Handler(ConnectivityThread.getInstanceLooper());
3996         final NetworkCallback cb = new NetworkCallback();
3997 
3998         final Class<IllegalArgumentException> expected = IllegalArgumentException.class;
3999         assertThrows(expected, () -> mCm.requestNetwork(r, cb));
4000         assertThrows(expected, () -> mCm.requestNetwork(r, pendingIntent));
4001         assertThrows(expected, () -> mCm.registerNetworkCallback(r, cb));
4002         assertThrows(expected, () -> mCm.registerNetworkCallback(r, cb, handler));
4003         assertThrows(expected, () -> mCm.registerNetworkCallback(r, pendingIntent));
4004         assertThrows(expected, () -> mCm.registerBestMatchingNetworkCallback(r, cb, handler));
4005 
4006         // Make sure that resetting the access UIDs to the empty set will allow calling
4007         // requestNetwork and registerNetworkCallback.
4008         r.networkCapabilities.setAllowedUids(Collections.emptySet());
4009         mCm.requestNetwork(r, cb);
4010         mCm.unregisterNetworkCallback(cb);
4011         mCm.registerNetworkCallback(r, cb);
4012         mCm.unregisterNetworkCallback(cb);
4013     }
4014 
4015     @Test
4016     public void testMMSonWiFi() throws Exception {
4017         // Test bringing up cellular without MMS NetworkRequest gets reaped
4018         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
4019         mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS);
4020         mCellNetworkAgent.connectWithoutInternet();
4021         mCellNetworkAgent.expectDisconnected();
4022         waitForIdle();
4023         assertEmpty(mCm.getAllNetworks());
4024         verifyNoNetwork();
4025 
4026         // Test bringing up validated WiFi.
4027         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4028         final ExpectedBroadcast b = expectConnectivityAction(TYPE_WIFI, DetailedState.CONNECTED);
4029         mWiFiNetworkAgent.connect(true);
4030         b.expectBroadcast();
4031         verifyActiveNetwork(TRANSPORT_WIFI);
4032 
4033         // Register MMS NetworkRequest
4034         NetworkRequest.Builder builder = new NetworkRequest.Builder();
4035         builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
4036         final TestNetworkCallback networkCallback = new TestNetworkCallback();
4037         mCm.requestNetwork(builder.build(), networkCallback);
4038 
4039         // Test bringing up unvalidated cellular with MMS
4040         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
4041         mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS);
4042         mCellNetworkAgent.connectWithoutInternet();
4043         networkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
4044         verifyActiveNetwork(TRANSPORT_WIFI);
4045 
4046         // Test releasing NetworkRequest disconnects cellular with MMS
4047         mCm.unregisterNetworkCallback(networkCallback);
4048         mCellNetworkAgent.expectDisconnected();
4049         verifyActiveNetwork(TRANSPORT_WIFI);
4050     }
4051 
4052     @Test
4053     public void testMMSonCell() throws Exception {
4054         // Test bringing up cellular without MMS
4055         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
4056         ExpectedBroadcast b = expectConnectivityAction(TYPE_MOBILE, DetailedState.CONNECTED);
4057         mCellNetworkAgent.connect(false);
4058         b.expectBroadcast();
4059         verifyActiveNetwork(TRANSPORT_CELLULAR);
4060 
4061         // Register MMS NetworkRequest
4062         NetworkRequest.Builder builder = new NetworkRequest.Builder();
4063         builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
4064         final TestNetworkCallback networkCallback = new TestNetworkCallback();
4065         mCm.requestNetwork(builder.build(), networkCallback);
4066 
4067         // Test bringing up MMS cellular network
4068         TestNetworkAgentWrapper
4069                 mmsNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
4070         mmsNetworkAgent.addCapability(NET_CAPABILITY_MMS);
4071         mmsNetworkAgent.connectWithoutInternet();
4072         networkCallback.expectAvailableCallbacksUnvalidated(mmsNetworkAgent);
4073         verifyActiveNetwork(TRANSPORT_CELLULAR);
4074 
4075         // Test releasing MMS NetworkRequest does not disconnect main cellular NetworkAgent
4076         mCm.unregisterNetworkCallback(networkCallback);
4077         mmsNetworkAgent.expectDisconnected();
4078         verifyActiveNetwork(TRANSPORT_CELLULAR);
4079     }
4080 
4081     @Test
4082     public void testPartialConnectivity() throws Exception {
4083         // Register network callback.
4084         NetworkRequest request = new NetworkRequest.Builder()
4085                 .clearCapabilities().addCapability(NET_CAPABILITY_INTERNET)
4086                 .build();
4087         TestNetworkCallback callback = new TestNetworkCallback();
4088         mCm.registerNetworkCallback(request, callback);
4089 
4090         // Bring up validated mobile data.
4091         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
4092         mCellNetworkAgent.connect(true);
4093         callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
4094 
4095         // Bring up wifi with partial connectivity.
4096         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4097         mWiFiNetworkAgent.connectWithPartialConnectivity();
4098         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
4099         callback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY, mWiFiNetworkAgent);
4100 
4101         // Mobile data should be the default network.
4102         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
4103         callback.assertNoCallback();
4104 
4105         // With HTTPS probe disabled, NetworkMonitor should pass the network validation with http
4106         // probe.
4107         mWiFiNetworkAgent.setNetworkPartialValid(false /* isStrictMode */);
4108         // If the user chooses yes to use this partial connectivity wifi, switch the default
4109         // network to wifi and check if wifi becomes valid or not.
4110         mCm.setAcceptPartialConnectivity(mWiFiNetworkAgent.getNetwork(), true /* accept */,
4111                 false /* always */);
4112         // If user accepts partial connectivity network,
4113         // NetworkMonitor#setAcceptPartialConnectivity() should be called too.
4114         waitForIdle();
4115         verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
4116 
4117         // Need a trigger point to let NetworkMonitor tell ConnectivityService that network is
4118         // validated.
4119         mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
4120         callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
4121         NetworkCapabilities nc = callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED,
4122                 mWiFiNetworkAgent);
4123         assertTrue(nc.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY));
4124         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
4125 
4126         // Disconnect and reconnect wifi with partial connectivity again.
4127         mWiFiNetworkAgent.disconnect();
4128         callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
4129         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4130         mWiFiNetworkAgent.connectWithPartialConnectivity();
4131         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
4132         callback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY, mWiFiNetworkAgent);
4133 
4134         // Mobile data should be the default network.
4135         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
4136 
4137         // If the user chooses no, disconnect wifi immediately.
4138         mCm.setAcceptPartialConnectivity(mWiFiNetworkAgent.getNetwork(), false/* accept */,
4139                 false /* always */);
4140         callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
4141 
4142         // If user accepted partial connectivity before, and device reconnects to that network
4143         // again, but now the network has full connectivity. The network shouldn't contain
4144         // NET_CAPABILITY_PARTIAL_CONNECTIVITY.
4145         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4146         // acceptUnvalidated is also used as setting for accepting partial networks.
4147         mWiFiNetworkAgent.explicitlySelected(true /* explicitlySelected */,
4148                 true /* acceptUnvalidated */);
4149         mWiFiNetworkAgent.connect(true);
4150 
4151         // If user accepted partial connectivity network before,
4152         // NetworkMonitor#setAcceptPartialConnectivity() will be called in
4153         // ConnectivityService#updateNetworkInfo().
4154         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
4155         verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
4156         callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
4157         nc = callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
4158         assertFalse(nc.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY));
4159 
4160         // Wifi should be the default network.
4161         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
4162         mWiFiNetworkAgent.disconnect();
4163         callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
4164 
4165         // The user accepted partial connectivity and selected "don't ask again". Now the user
4166         // reconnects to the partial connectivity network. Switch to wifi as soon as partial
4167         // connectivity is detected.
4168         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4169         mWiFiNetworkAgent.explicitlySelected(true /* explicitlySelected */,
4170                 true /* acceptUnvalidated */);
4171         mWiFiNetworkAgent.connectWithPartialConnectivity();
4172         // If user accepted partial connectivity network before,
4173         // NetworkMonitor#setAcceptPartialConnectivity() will be called in
4174         // ConnectivityService#updateNetworkInfo().
4175         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
4176         verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
4177         callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
4178         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
4179         callback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY, mWiFiNetworkAgent);
4180         mWiFiNetworkAgent.setNetworkValid(false /* isStrictMode */);
4181 
4182         // Need a trigger point to let NetworkMonitor tell ConnectivityService that network is
4183         // validated.
4184         mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
4185         callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
4186         mWiFiNetworkAgent.disconnect();
4187         callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
4188 
4189         // If the user accepted partial connectivity, and the device auto-reconnects to the partial
4190         // connectivity network, it should contain both PARTIAL_CONNECTIVITY and VALIDATED.
4191         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4192         mWiFiNetworkAgent.explicitlySelected(false /* explicitlySelected */,
4193                 true /* acceptUnvalidated */);
4194 
4195         // NetworkMonitor will immediately (once the HTTPS probe fails...) report the network as
4196         // valid, because ConnectivityService calls setAcceptPartialConnectivity before it calls
4197         // notifyNetworkConnected.
4198         mWiFiNetworkAgent.connectWithPartialValidConnectivity(false /* isStrictMode */);
4199         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
4200         verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
4201         callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
4202         callback.expectCapabilitiesWith(
4203                 NET_CAPABILITY_PARTIAL_CONNECTIVITY | NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
4204         mWiFiNetworkAgent.disconnect();
4205         callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
4206     }
4207 
4208     @Test
4209     public void testCaptivePortalOnPartialConnectivity() throws Exception {
4210         final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
4211         final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
4212                 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
4213         mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
4214 
4215         final TestNetworkCallback validatedCallback = new TestNetworkCallback();
4216         final NetworkRequest validatedRequest = new NetworkRequest.Builder()
4217                 .addCapability(NET_CAPABILITY_VALIDATED).build();
4218         mCm.registerNetworkCallback(validatedRequest, validatedCallback);
4219 
4220         // Bring up a network with a captive portal.
4221         // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
4222         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4223         String redirectUrl = "http://android.com/path";
4224         mWiFiNetworkAgent.connectWithCaptivePortal(redirectUrl, false /* isStrictMode */);
4225         captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
4226         assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), redirectUrl);
4227 
4228         // Check that startCaptivePortalApp sends the expected command to NetworkMonitor.
4229         mCm.startCaptivePortalApp(mWiFiNetworkAgent.getNetwork());
4230         verify(mWiFiNetworkAgent.mNetworkMonitor, timeout(TIMEOUT_MS).times(1))
4231                 .launchCaptivePortalApp();
4232 
4233         // Report that the captive portal is dismissed with partial connectivity, and check that
4234         // callbacks are fired.
4235         mWiFiNetworkAgent.setNetworkPartial();
4236         mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
4237         waitForIdle();
4238         captivePortalCallback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY,
4239                 mWiFiNetworkAgent);
4240 
4241         // Report partial connectivity is accepted.
4242         mWiFiNetworkAgent.setNetworkPartialValid(false /* isStrictMode */);
4243         mCm.setAcceptPartialConnectivity(mWiFiNetworkAgent.getNetwork(), true /* accept */,
4244                 false /* always */);
4245         waitForIdle();
4246         mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
4247         captivePortalCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
4248         validatedCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
4249         NetworkCapabilities nc =
4250                 validatedCallback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY,
4251                 mWiFiNetworkAgent);
4252 
4253         mCm.unregisterNetworkCallback(captivePortalCallback);
4254         mCm.unregisterNetworkCallback(validatedCallback);
4255     }
4256 
4257     @Test
4258     public void testCaptivePortal() throws Exception {
4259         final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
4260         final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
4261                 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
4262         mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
4263 
4264         final TestNetworkCallback validatedCallback = new TestNetworkCallback();
4265         final NetworkRequest validatedRequest = new NetworkRequest.Builder()
4266                 .addCapability(NET_CAPABILITY_VALIDATED).build();
4267         mCm.registerNetworkCallback(validatedRequest, validatedCallback);
4268 
4269         // Bring up a network with a captive portal.
4270         // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
4271         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4272         String firstRedirectUrl = "http://example.com/firstPath";
4273         mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl, false /* isStrictMode */);
4274         captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
4275         assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), firstRedirectUrl);
4276 
4277         // Take down network.
4278         // Expect onLost callback.
4279         mWiFiNetworkAgent.disconnect();
4280         captivePortalCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
4281 
4282         // Bring up a network with a captive portal.
4283         // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
4284         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4285         String secondRedirectUrl = "http://example.com/secondPath";
4286         mWiFiNetworkAgent.connectWithCaptivePortal(secondRedirectUrl, false /* isStrictMode */);
4287         captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
4288         assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), secondRedirectUrl);
4289 
4290         // Make captive portal disappear then revalidate.
4291         // Expect onLost callback because network no longer provides NET_CAPABILITY_CAPTIVE_PORTAL.
4292         mWiFiNetworkAgent.setNetworkValid(false /* isStrictMode */);
4293         mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
4294         captivePortalCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
4295 
4296         // Expect NET_CAPABILITY_VALIDATED onAvailable callback.
4297         validatedCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
4298 
4299         // Break network connectivity.
4300         // Expect NET_CAPABILITY_VALIDATED onLost callback.
4301         mWiFiNetworkAgent.setNetworkInvalid(false /* isStrictMode */);
4302         mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), false);
4303         validatedCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
4304     }
4305 
4306     @Test
4307     public void testCaptivePortalApp() throws Exception {
4308         final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
4309         final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
4310                 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
4311         mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
4312 
4313         final TestNetworkCallback validatedCallback = new TestNetworkCallback();
4314         final NetworkRequest validatedRequest = new NetworkRequest.Builder()
4315                 .addCapability(NET_CAPABILITY_VALIDATED).build();
4316         mCm.registerNetworkCallback(validatedRequest, validatedCallback);
4317 
4318         // Bring up wifi.
4319         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4320         mWiFiNetworkAgent.connect(true);
4321         validatedCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
4322         Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
4323 
4324         // Check that calling startCaptivePortalApp does nothing.
4325         final int fastTimeoutMs = 100;
4326         mCm.startCaptivePortalApp(wifiNetwork);
4327         waitForIdle();
4328         verify(mWiFiNetworkAgent.mNetworkMonitor, never()).launchCaptivePortalApp();
4329         mServiceContext.expectNoStartActivityIntent(fastTimeoutMs);
4330 
4331         // Turn into a captive portal.
4332         mWiFiNetworkAgent.setNetworkPortal("http://example.com", false /* isStrictMode */);
4333         mCm.reportNetworkConnectivity(wifiNetwork, false);
4334         captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
4335         validatedCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
4336 
4337         // Check that startCaptivePortalApp sends the expected command to NetworkMonitor.
4338         mCm.startCaptivePortalApp(wifiNetwork);
4339         waitForIdle();
4340         verify(mWiFiNetworkAgent.mNetworkMonitor).launchCaptivePortalApp();
4341 
4342         // NetworkMonitor uses startCaptivePortal(Network, Bundle) (startCaptivePortalAppInternal)
4343         final Bundle testBundle = new Bundle();
4344         final String testKey = "testkey";
4345         final String testValue = "testvalue";
4346         testBundle.putString(testKey, testValue);
4347         mServiceContext.setPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
4348                 PERMISSION_GRANTED);
4349         mCm.startCaptivePortalApp(wifiNetwork, testBundle);
4350         final Intent signInIntent = mServiceContext.expectStartActivityIntent(TIMEOUT_MS);
4351         assertEquals(ACTION_CAPTIVE_PORTAL_SIGN_IN, signInIntent.getAction());
4352         assertEquals(testValue, signInIntent.getStringExtra(testKey));
4353 
4354         // Report that the captive portal is dismissed, and check that callbacks are fired
4355         mWiFiNetworkAgent.setNetworkValid(false /* isStrictMode */);
4356         mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
4357         validatedCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
4358         captivePortalCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
4359 
4360         mCm.unregisterNetworkCallback(validatedCallback);
4361         mCm.unregisterNetworkCallback(captivePortalCallback);
4362     }
4363 
4364     @Test
4365     public void testAvoidOrIgnoreCaptivePortals() throws Exception {
4366         final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
4367         final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
4368                 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
4369         mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
4370 
4371         final TestNetworkCallback validatedCallback = new TestNetworkCallback();
4372         final NetworkRequest validatedRequest = new NetworkRequest.Builder()
4373                 .addCapability(NET_CAPABILITY_VALIDATED).build();
4374         mCm.registerNetworkCallback(validatedRequest, validatedCallback);
4375 
4376         setCaptivePortalMode(ConnectivitySettingsManager.CAPTIVE_PORTAL_MODE_AVOID);
4377         // Bring up a network with a captive portal.
4378         // Expect it to fail to connect and not result in any callbacks.
4379         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4380         String firstRedirectUrl = "http://example.com/firstPath";
4381 
4382         mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl, false /* isStrictMode */);
4383         mWiFiNetworkAgent.expectDisconnected();
4384         mWiFiNetworkAgent.expectPreventReconnectReceived();
4385 
4386         assertNoCallbacks(captivePortalCallback, validatedCallback);
4387     }
4388 
4389     @Test
4390     public void testCaptivePortalApi() throws Exception {
4391         mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_GRANTED);
4392 
4393         final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
4394         final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
4395                 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
4396         mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
4397 
4398         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4399         final String redirectUrl = "http://example.com/firstPath";
4400 
4401         mWiFiNetworkAgent.connectWithCaptivePortal(redirectUrl, false /* isStrictMode */);
4402         captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
4403 
4404         final CaptivePortalData testData = new CaptivePortalData.Builder()
4405                 .setUserPortalUrl(Uri.parse(redirectUrl))
4406                 .setBytesRemaining(12345L)
4407                 .build();
4408 
4409         mWiFiNetworkAgent.notifyCapportApiDataChanged(testData);
4410 
4411         captivePortalCallback.expectLinkPropertiesThat(mWiFiNetworkAgent,
4412                 lp -> testData.equals(lp.getCaptivePortalData()));
4413 
4414         final LinkProperties newLps = new LinkProperties();
4415         newLps.setMtu(1234);
4416         mWiFiNetworkAgent.sendLinkProperties(newLps);
4417         // CaptivePortalData is not lost and unchanged when LPs are received from the NetworkAgent
4418         captivePortalCallback.expectLinkPropertiesThat(mWiFiNetworkAgent,
4419                 lp -> testData.equals(lp.getCaptivePortalData()) && lp.getMtu() == 1234);
4420     }
4421 
4422     private TestNetworkCallback setupNetworkCallbackAndConnectToWifi() throws Exception {
4423         // Grant NETWORK_SETTINGS permission to be able to receive LinkProperties change callbacks
4424         // with sensitive (captive portal) data
4425         mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_GRANTED);
4426 
4427         final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
4428         final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
4429                 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
4430         mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
4431 
4432         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4433 
4434         mWiFiNetworkAgent.connectWithCaptivePortal(TEST_REDIRECT_URL, false /* isStrictMode */);
4435         captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
4436         return captivePortalCallback;
4437     }
4438 
4439     private class CaptivePortalTestData {
4440         CaptivePortalTestData(CaptivePortalData naPasspointData, CaptivePortalData capportData,
4441                 CaptivePortalData naOtherData, CaptivePortalData expectedMergedPasspointData,
4442                 CaptivePortalData expectedMergedOtherData) {
4443             mNaPasspointData = naPasspointData;
4444             mCapportData = capportData;
4445             mNaOtherData = naOtherData;
4446             mExpectedMergedPasspointData = expectedMergedPasspointData;
4447             mExpectedMergedOtherData = expectedMergedOtherData;
4448         }
4449 
4450         public final CaptivePortalData mNaPasspointData;
4451         public final CaptivePortalData mCapportData;
4452         public final CaptivePortalData mNaOtherData;
4453         public final CaptivePortalData mExpectedMergedPasspointData;
4454         public final CaptivePortalData mExpectedMergedOtherData;
4455 
4456     }
4457 
4458     private CaptivePortalTestData setupCaptivePortalData() {
4459         final CaptivePortalData capportData = new CaptivePortalData.Builder()
4460                 .setUserPortalUrl(Uri.parse(TEST_REDIRECT_URL))
4461                 .setVenueInfoUrl(Uri.parse(TEST_VENUE_URL_CAPPORT))
4462                 .setUserPortalUrl(Uri.parse(TEST_USER_PORTAL_API_URL_CAPPORT))
4463                 .setExpiryTime(1000000L)
4464                 .setBytesRemaining(12345L)
4465                 .build();
4466 
4467         final CaptivePortalData naPasspointData = new CaptivePortalData.Builder()
4468                 .setBytesRemaining(80802L)
4469                 .setVenueInfoUrl(Uri.parse(TEST_VENUE_URL_NA_PASSPOINT),
4470                         CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_PASSPOINT)
4471                 .setUserPortalUrl(Uri.parse(TEST_TERMS_AND_CONDITIONS_URL_NA_PASSPOINT),
4472                         CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_PASSPOINT)
4473                 .setVenueFriendlyName(TEST_FRIENDLY_NAME).build();
4474 
4475         final CaptivePortalData naOtherData = new CaptivePortalData.Builder()
4476                 .setBytesRemaining(80802L)
4477                 .setVenueInfoUrl(Uri.parse(TEST_VENUE_URL_NA_OTHER),
4478                         CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_OTHER)
4479                 .setUserPortalUrl(Uri.parse(TEST_TERMS_AND_CONDITIONS_URL_NA_OTHER),
4480                         CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_OTHER)
4481                 .setVenueFriendlyName(TEST_FRIENDLY_NAME).build();
4482 
4483         final CaptivePortalData expectedMergedPasspointData = new CaptivePortalData.Builder()
4484                 .setUserPortalUrl(Uri.parse(TEST_REDIRECT_URL))
4485                 .setBytesRemaining(12345L)
4486                 .setExpiryTime(1000000L)
4487                 .setVenueInfoUrl(Uri.parse(TEST_VENUE_URL_NA_PASSPOINT),
4488                         CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_PASSPOINT)
4489                 .setUserPortalUrl(Uri.parse(TEST_TERMS_AND_CONDITIONS_URL_NA_PASSPOINT),
4490                         CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_PASSPOINT)
4491                 .setVenueFriendlyName(TEST_FRIENDLY_NAME).build();
4492 
4493         final CaptivePortalData expectedMergedOtherData = new CaptivePortalData.Builder()
4494                 .setUserPortalUrl(Uri.parse(TEST_REDIRECT_URL))
4495                 .setBytesRemaining(12345L)
4496                 .setExpiryTime(1000000L)
4497                 .setVenueInfoUrl(Uri.parse(TEST_VENUE_URL_CAPPORT))
4498                 .setUserPortalUrl(Uri.parse(TEST_USER_PORTAL_API_URL_CAPPORT))
4499                 .setVenueFriendlyName(TEST_FRIENDLY_NAME).build();
4500         return new CaptivePortalTestData(naPasspointData, capportData, naOtherData,
4501                 expectedMergedPasspointData, expectedMergedOtherData);
4502     }
4503 
4504     @Test
4505     public void testMergeCaptivePortalApiWithFriendlyNameAndVenueUrl() throws Exception {
4506         final TestNetworkCallback captivePortalCallback = setupNetworkCallbackAndConnectToWifi();
4507         final CaptivePortalTestData captivePortalTestData = setupCaptivePortalData();
4508 
4509         // Baseline capport data
4510         mWiFiNetworkAgent.notifyCapportApiDataChanged(captivePortalTestData.mCapportData);
4511 
4512         captivePortalCallback.expectLinkPropertiesThat(mWiFiNetworkAgent,
4513                 lp -> captivePortalTestData.mCapportData.equals(lp.getCaptivePortalData()));
4514 
4515         // Venue URL, T&C URL and friendly name from Network agent with Passpoint source, confirm
4516         // that API data gets precedence on the bytes remaining.
4517         final LinkProperties linkProperties = new LinkProperties();
4518         linkProperties.setCaptivePortalData(captivePortalTestData.mNaPasspointData);
4519         mWiFiNetworkAgent.sendLinkProperties(linkProperties);
4520 
4521         // Make sure that the capport data is merged
4522         captivePortalCallback.expectLinkPropertiesThat(mWiFiNetworkAgent,
4523                 lp -> captivePortalTestData.mExpectedMergedPasspointData
4524                         .equals(lp.getCaptivePortalData()));
4525 
4526         // Now send this information from non-Passpoint source, confirm that Capport data takes
4527         // precedence
4528         linkProperties.setCaptivePortalData(captivePortalTestData.mNaOtherData);
4529         mWiFiNetworkAgent.sendLinkProperties(linkProperties);
4530 
4531         // Make sure that the capport data is merged
4532         captivePortalCallback.expectLinkPropertiesThat(mWiFiNetworkAgent,
4533                 lp -> captivePortalTestData.mExpectedMergedOtherData
4534                         .equals(lp.getCaptivePortalData()));
4535 
4536         // Create a new LP with no Network agent capport data
4537         final LinkProperties newLps = new LinkProperties();
4538         newLps.setMtu(1234);
4539         mWiFiNetworkAgent.sendLinkProperties(newLps);
4540         // CaptivePortalData is not lost and has the original values when LPs are received from the
4541         // NetworkAgent
4542         captivePortalCallback.expectLinkPropertiesThat(mWiFiNetworkAgent,
4543                 lp -> captivePortalTestData.mCapportData.equals(lp.getCaptivePortalData())
4544                         && lp.getMtu() == 1234);
4545 
4546         // Now send capport data only from the Network agent
4547         mWiFiNetworkAgent.notifyCapportApiDataChanged(null);
4548         captivePortalCallback.expectLinkPropertiesThat(mWiFiNetworkAgent,
4549                 lp -> lp.getCaptivePortalData() == null);
4550 
4551         newLps.setCaptivePortalData(captivePortalTestData.mNaPasspointData);
4552         mWiFiNetworkAgent.sendLinkProperties(newLps);
4553 
4554         // Make sure that only the network agent capport data is available
4555         captivePortalCallback.expectLinkPropertiesThat(mWiFiNetworkAgent,
4556                 lp -> captivePortalTestData.mNaPasspointData.equals(lp.getCaptivePortalData()));
4557     }
4558 
4559     @Test
4560     public void testMergeCaptivePortalDataFromNetworkAgentFirstThenCapport() throws Exception {
4561         final TestNetworkCallback captivePortalCallback = setupNetworkCallbackAndConnectToWifi();
4562         final CaptivePortalTestData captivePortalTestData = setupCaptivePortalData();
4563 
4564         // Venue URL and friendly name from Network agent, confirm that API data gets precedence
4565         // on the bytes remaining.
4566         final LinkProperties linkProperties = new LinkProperties();
4567         linkProperties.setCaptivePortalData(captivePortalTestData.mNaPasspointData);
4568         mWiFiNetworkAgent.sendLinkProperties(linkProperties);
4569 
4570         // Make sure that the data is saved correctly
4571         captivePortalCallback.expectLinkPropertiesThat(mWiFiNetworkAgent,
4572                 lp -> captivePortalTestData.mNaPasspointData.equals(lp.getCaptivePortalData()));
4573 
4574         // Expected merged data: Network agent data is preferred, and values that are not used by
4575         // it are merged from capport data
4576         mWiFiNetworkAgent.notifyCapportApiDataChanged(captivePortalTestData.mCapportData);
4577 
4578         // Make sure that the Capport data is merged correctly
4579         captivePortalCallback.expectLinkPropertiesThat(mWiFiNetworkAgent,
4580                 lp -> captivePortalTestData.mExpectedMergedPasspointData.equals(
4581                         lp.getCaptivePortalData()));
4582 
4583         // Now set the naData to null
4584         linkProperties.setCaptivePortalData(null);
4585         mWiFiNetworkAgent.sendLinkProperties(linkProperties);
4586 
4587         // Make sure that the Capport data is retained correctly
4588         captivePortalCallback.expectLinkPropertiesThat(mWiFiNetworkAgent,
4589                 lp -> captivePortalTestData.mCapportData.equals(lp.getCaptivePortalData()));
4590     }
4591 
4592     @Test
4593     public void testMergeCaptivePortalDataFromNetworkAgentOtherSourceFirstThenCapport()
4594             throws Exception {
4595         final TestNetworkCallback captivePortalCallback = setupNetworkCallbackAndConnectToWifi();
4596         final CaptivePortalTestData captivePortalTestData = setupCaptivePortalData();
4597 
4598         // Venue URL and friendly name from Network agent, confirm that API data gets precedence
4599         // on the bytes remaining.
4600         final LinkProperties linkProperties = new LinkProperties();
4601         linkProperties.setCaptivePortalData(captivePortalTestData.mNaOtherData);
4602         mWiFiNetworkAgent.sendLinkProperties(linkProperties);
4603 
4604         // Make sure that the data is saved correctly
4605         captivePortalCallback.expectLinkPropertiesThat(mWiFiNetworkAgent,
4606                 lp -> captivePortalTestData.mNaOtherData.equals(lp.getCaptivePortalData()));
4607 
4608         // Expected merged data: Network agent data is preferred, and values that are not used by
4609         // it are merged from capport data
4610         mWiFiNetworkAgent.notifyCapportApiDataChanged(captivePortalTestData.mCapportData);
4611 
4612         // Make sure that the Capport data is merged correctly
4613         captivePortalCallback.expectLinkPropertiesThat(mWiFiNetworkAgent,
4614                 lp -> captivePortalTestData.mExpectedMergedOtherData.equals(
4615                         lp.getCaptivePortalData()));
4616     }
4617 
4618     private NetworkRequest.Builder newWifiRequestBuilder() {
4619         return new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI);
4620     }
4621 
4622     /**
4623      * Verify request matching behavior with network specifiers.
4624      *
4625      * This test does not check updating the specifier on a live network because the specifier is
4626      * immutable and this triggers a WTF in
4627      * {@link ConnectivityService#mixInCapabilities(NetworkAgentInfo, NetworkCapabilities)}.
4628      */
4629     @Test
4630     public void testNetworkSpecifier() throws Exception {
4631         // A NetworkSpecifier subclass that matches all networks but must not be visible to apps.
4632         class ConfidentialMatchAllNetworkSpecifier extends NetworkSpecifier implements
4633                 Parcelable {
4634             @Override
4635             public boolean canBeSatisfiedBy(NetworkSpecifier other) {
4636                 return true;
4637             }
4638 
4639             @Override
4640             public int describeContents() {
4641                 return 0;
4642             }
4643 
4644             @Override
4645             public void writeToParcel(Parcel dest, int flags) {}
4646 
4647             @Override
4648             public NetworkSpecifier redact() {
4649                 return null;
4650             }
4651         }
4652 
4653         // A network specifier that matches either another LocalNetworkSpecifier with the same
4654         // string or a ConfidentialMatchAllNetworkSpecifier, and can be passed to apps as is.
4655         class LocalStringNetworkSpecifier extends NetworkSpecifier implements Parcelable {
4656             private String mString;
4657 
4658             LocalStringNetworkSpecifier(String string) {
4659                 mString = string;
4660             }
4661 
4662             @Override
4663             public boolean canBeSatisfiedBy(NetworkSpecifier other) {
4664                 if (other instanceof LocalStringNetworkSpecifier) {
4665                     return TextUtils.equals(mString,
4666                             ((LocalStringNetworkSpecifier) other).mString);
4667                 }
4668                 if (other instanceof ConfidentialMatchAllNetworkSpecifier) return true;
4669                 return false;
4670             }
4671 
4672             @Override
4673             public int describeContents() {
4674                 return 0;
4675             }
4676             @Override
4677             public void writeToParcel(Parcel dest, int flags) {}
4678         }
4679 
4680 
4681         NetworkRequest rEmpty1 = newWifiRequestBuilder().build();
4682         NetworkRequest rEmpty2 = newWifiRequestBuilder().setNetworkSpecifier((String) null).build();
4683         NetworkRequest rEmpty3 = newWifiRequestBuilder().setNetworkSpecifier("").build();
4684         NetworkRequest rEmpty4 = newWifiRequestBuilder().setNetworkSpecifier(
4685             (NetworkSpecifier) null).build();
4686         NetworkRequest rFoo = newWifiRequestBuilder().setNetworkSpecifier(
4687                 new LocalStringNetworkSpecifier("foo")).build();
4688         NetworkRequest rBar = newWifiRequestBuilder().setNetworkSpecifier(
4689                 new LocalStringNetworkSpecifier("bar")).build();
4690 
4691         TestNetworkCallback cEmpty1 = new TestNetworkCallback();
4692         TestNetworkCallback cEmpty2 = new TestNetworkCallback();
4693         TestNetworkCallback cEmpty3 = new TestNetworkCallback();
4694         TestNetworkCallback cEmpty4 = new TestNetworkCallback();
4695         TestNetworkCallback cFoo = new TestNetworkCallback();
4696         TestNetworkCallback cBar = new TestNetworkCallback();
4697         TestNetworkCallback[] emptyCallbacks = new TestNetworkCallback[] {
4698                 cEmpty1, cEmpty2, cEmpty3, cEmpty4 };
4699 
4700         mCm.registerNetworkCallback(rEmpty1, cEmpty1);
4701         mCm.registerNetworkCallback(rEmpty2, cEmpty2);
4702         mCm.registerNetworkCallback(rEmpty3, cEmpty3);
4703         mCm.registerNetworkCallback(rEmpty4, cEmpty4);
4704         mCm.registerNetworkCallback(rFoo, cFoo);
4705         mCm.registerNetworkCallback(rBar, cBar);
4706 
4707         LocalStringNetworkSpecifier nsFoo = new LocalStringNetworkSpecifier("foo");
4708         LocalStringNetworkSpecifier nsBar = new LocalStringNetworkSpecifier("bar");
4709 
4710         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4711         mWiFiNetworkAgent.connect(false);
4712         expectAvailableCallbacksUnvalidatedWithSpecifier(mWiFiNetworkAgent, null /* specifier */,
4713                 cEmpty1, cEmpty2, cEmpty3, cEmpty4);
4714         assertNoCallbacks(cFoo, cBar);
4715 
4716         mWiFiNetworkAgent.disconnect();
4717         expectOnLost(mWiFiNetworkAgent, cEmpty1, cEmpty2, cEmpty3, cEmpty4);
4718 
4719         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4720         mWiFiNetworkAgent.setNetworkSpecifier(nsFoo);
4721         mWiFiNetworkAgent.connect(false);
4722         expectAvailableCallbacksUnvalidatedWithSpecifier(mWiFiNetworkAgent, nsFoo,
4723                 cEmpty1, cEmpty2, cEmpty3, cEmpty4, cFoo);
4724         cBar.assertNoCallback();
4725         assertEquals(nsFoo,
4726                 mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier());
4727         assertNoCallbacks(cEmpty1, cEmpty2, cEmpty3, cEmpty4, cFoo);
4728 
4729         mWiFiNetworkAgent.disconnect();
4730         expectOnLost(mWiFiNetworkAgent, cEmpty1, cEmpty2, cEmpty3, cEmpty4, cFoo);
4731 
4732         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4733         mWiFiNetworkAgent.setNetworkSpecifier(nsBar);
4734         mWiFiNetworkAgent.connect(false);
4735         expectAvailableCallbacksUnvalidatedWithSpecifier(mWiFiNetworkAgent, nsBar,
4736                 cEmpty1, cEmpty2, cEmpty3, cEmpty4, cBar);
4737         cFoo.assertNoCallback();
4738         assertEquals(nsBar,
4739                 mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier());
4740 
4741         mWiFiNetworkAgent.disconnect();
4742         expectOnLost(mWiFiNetworkAgent, cEmpty1, cEmpty2, cEmpty3, cEmpty4, cBar);
4743         cFoo.assertNoCallback();
4744 
4745         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4746         mWiFiNetworkAgent.setNetworkSpecifier(new ConfidentialMatchAllNetworkSpecifier());
4747         mWiFiNetworkAgent.connect(false);
4748         expectAvailableCallbacksUnvalidatedWithSpecifier(mWiFiNetworkAgent, null /* specifier */,
4749                 cEmpty1, cEmpty2, cEmpty3, cEmpty4, cFoo, cBar);
4750         assertNull(
4751                 mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier());
4752 
4753         mWiFiNetworkAgent.disconnect();
4754         expectOnLost(mWiFiNetworkAgent, cEmpty1, cEmpty2, cEmpty3, cEmpty4, cFoo, cBar);
4755     }
4756 
4757     /**
4758      * @return the context's attribution tag
4759      */
4760     private String getAttributionTag() {
4761         return mContext.getAttributionTag();
4762     }
4763 
4764     @Test
4765     public void testInvalidNetworkSpecifier() {
4766         assertThrows(IllegalArgumentException.class, () -> {
4767             NetworkRequest.Builder builder = new NetworkRequest.Builder();
4768             builder.setNetworkSpecifier(new MatchAllNetworkSpecifier());
4769         });
4770 
4771         assertThrows(IllegalArgumentException.class, () -> {
4772             NetworkCapabilities networkCapabilities = new NetworkCapabilities();
4773             networkCapabilities.addTransportType(TRANSPORT_WIFI)
4774                     .setNetworkSpecifier(new MatchAllNetworkSpecifier());
4775             mService.requestNetwork(Process.INVALID_UID, networkCapabilities,
4776                     NetworkRequest.Type.REQUEST.ordinal(), null, 0, null,
4777                     ConnectivityManager.TYPE_WIFI, NetworkCallback.FLAG_NONE,
4778                     mContext.getPackageName(), getAttributionTag());
4779         });
4780 
4781         class NonParcelableSpecifier extends NetworkSpecifier {
4782             @Override
4783             public boolean canBeSatisfiedBy(NetworkSpecifier other) {
4784                 return false;
4785             }
4786         };
4787         class ParcelableSpecifier extends NonParcelableSpecifier implements Parcelable {
4788             @Override public int describeContents() { return 0; }
4789             @Override public void writeToParcel(Parcel p, int flags) {}
4790         }
4791 
4792         final NetworkRequest.Builder builder =
4793                 new NetworkRequest.Builder().addTransportType(TRANSPORT_ETHERNET);
4794         assertThrows(ClassCastException.class, () -> {
4795             builder.setNetworkSpecifier(new NonParcelableSpecifier());
4796             Parcel parcelW = Parcel.obtain();
4797             builder.build().writeToParcel(parcelW, 0);
4798         });
4799 
4800         final NetworkRequest nr =
4801                 new NetworkRequest.Builder().addTransportType(TRANSPORT_ETHERNET)
4802                 .setNetworkSpecifier(new ParcelableSpecifier())
4803                 .build();
4804         assertNotNull(nr);
4805 
4806         assertThrows(BadParcelableException.class, () -> {
4807             Parcel parcelW = Parcel.obtain();
4808             nr.writeToParcel(parcelW, 0);
4809             byte[] bytes = parcelW.marshall();
4810             parcelW.recycle();
4811 
4812             Parcel parcelR = Parcel.obtain();
4813             parcelR.unmarshall(bytes, 0, bytes.length);
4814             parcelR.setDataPosition(0);
4815             NetworkRequest rereadNr = NetworkRequest.CREATOR.createFromParcel(parcelR);
4816         });
4817     }
4818 
4819     @Test
4820     public void testNetworkRequestUidSpoofSecurityException() throws Exception {
4821         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4822         mWiFiNetworkAgent.connect(false);
4823         NetworkRequest networkRequest = newWifiRequestBuilder().build();
4824         TestNetworkCallback networkCallback = new TestNetworkCallback();
4825         doThrow(new SecurityException()).when(mAppOpsManager).checkPackage(anyInt(), anyString());
4826         assertThrows(SecurityException.class, () -> {
4827             mCm.requestNetwork(networkRequest, networkCallback);
4828         });
4829     }
4830 
4831     @Test
4832     public void testInvalidSignalStrength() {
4833         NetworkRequest r = new NetworkRequest.Builder()
4834                 .addCapability(NET_CAPABILITY_INTERNET)
4835                 .addTransportType(TRANSPORT_WIFI)
4836                 .setSignalStrength(-75)
4837                 .build();
4838         // Registering a NetworkCallback with signal strength but w/o NETWORK_SIGNAL_STRENGTH_WAKEUP
4839         // permission should get SecurityException.
4840         assertThrows(SecurityException.class, () ->
4841                 mCm.registerNetworkCallback(r, new NetworkCallback()));
4842 
4843         assertThrows(SecurityException.class, () ->
4844                 mCm.registerNetworkCallback(r, PendingIntent.getService(
4845                         mServiceContext, 0 /* requestCode */, new Intent(), FLAG_IMMUTABLE)));
4846 
4847         // Requesting a Network with signal strength should get IllegalArgumentException.
4848         assertThrows(IllegalArgumentException.class, () ->
4849                 mCm.requestNetwork(r, new NetworkCallback()));
4850 
4851         assertThrows(IllegalArgumentException.class, () ->
4852                 mCm.requestNetwork(r, PendingIntent.getService(
4853                         mServiceContext, 0 /* requestCode */, new Intent(), FLAG_IMMUTABLE)));
4854     }
4855 
4856     @Test
4857     public void testRegisterDefaultNetworkCallback() throws Exception {
4858         // NETWORK_SETTINGS is necessary to call registerSystemDefaultNetworkCallback.
4859         mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_GRANTED);
4860 
4861         final TestNetworkCallback defaultNetworkCallback = new TestNetworkCallback();
4862         mCm.registerDefaultNetworkCallback(defaultNetworkCallback);
4863         defaultNetworkCallback.assertNoCallback();
4864 
4865         final Handler handler = new Handler(ConnectivityThread.getInstanceLooper());
4866         final TestNetworkCallback systemDefaultCallback = new TestNetworkCallback();
4867         mCm.registerSystemDefaultNetworkCallback(systemDefaultCallback, handler);
4868         systemDefaultCallback.assertNoCallback();
4869 
4870         // Create a TRANSPORT_CELLULAR request to keep the mobile interface up
4871         // whenever Wi-Fi is up. Without this, the mobile network agent is
4872         // reaped before any other activity can take place.
4873         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
4874         final NetworkRequest cellRequest = new NetworkRequest.Builder()
4875                 .addTransportType(TRANSPORT_CELLULAR).build();
4876         mCm.requestNetwork(cellRequest, cellNetworkCallback);
4877         cellNetworkCallback.assertNoCallback();
4878 
4879         // Bring up cell and expect CALLBACK_AVAILABLE.
4880         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
4881         mCellNetworkAgent.connect(true);
4882         cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
4883         defaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
4884         systemDefaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
4885         assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
4886         assertEquals(systemDefaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
4887 
4888         // Bring up wifi and expect CALLBACK_AVAILABLE.
4889         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4890         mWiFiNetworkAgent.connect(true);
4891         cellNetworkCallback.assertNoCallback();
4892         defaultNetworkCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
4893         systemDefaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
4894         assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
4895         assertEquals(systemDefaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
4896 
4897         // Bring down cell. Expect no default network callback, since it wasn't the default.
4898         mCellNetworkAgent.disconnect();
4899         cellNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
4900         defaultNetworkCallback.assertNoCallback();
4901         systemDefaultCallback.assertNoCallback();
4902         assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
4903         assertEquals(systemDefaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
4904 
4905         // Bring up cell. Expect no default network callback, since it won't be the default.
4906         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
4907         mCellNetworkAgent.connect(true);
4908         cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
4909         defaultNetworkCallback.assertNoCallback();
4910         systemDefaultCallback.assertNoCallback();
4911         assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
4912         assertEquals(systemDefaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
4913 
4914         // Bring down wifi. Expect the default network callback to notified of LOST wifi
4915         // followed by AVAILABLE cell.
4916         mWiFiNetworkAgent.disconnect();
4917         cellNetworkCallback.assertNoCallback();
4918         defaultNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
4919         defaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
4920         systemDefaultCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
4921         systemDefaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
4922         mCellNetworkAgent.disconnect();
4923         cellNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
4924         defaultNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
4925         systemDefaultCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
4926         waitForIdle();
4927         assertEquals(null, mCm.getActiveNetwork());
4928 
4929         mMockVpn.establishForMyUid();
4930         assertUidRangesUpdatedForMyUid(true);
4931         defaultNetworkCallback.expectAvailableThenValidatedCallbacks(mMockVpn);
4932         systemDefaultCallback.assertNoCallback();
4933         assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
4934         assertEquals(null, systemDefaultCallback.getLastAvailableNetwork());
4935 
4936         mMockVpn.disconnect();
4937         defaultNetworkCallback.expectCallback(CallbackEntry.LOST, mMockVpn);
4938         systemDefaultCallback.assertNoCallback();
4939         waitForIdle();
4940         assertEquals(null, mCm.getActiveNetwork());
4941     }
4942 
4943     @Test
4944     public void testAdditionalStateCallbacks() throws Exception {
4945         // File a network request for mobile.
4946         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
4947         final NetworkRequest cellRequest = new NetworkRequest.Builder()
4948                 .addTransportType(TRANSPORT_CELLULAR).build();
4949         mCm.requestNetwork(cellRequest, cellNetworkCallback);
4950 
4951         // Bring up the mobile network.
4952         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
4953         mCellNetworkAgent.connect(true);
4954 
4955         // We should get onAvailable(), onCapabilitiesChanged(), and
4956         // onLinkPropertiesChanged() in rapid succession. Additionally, we
4957         // should get onCapabilitiesChanged() when the mobile network validates.
4958         cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
4959         cellNetworkCallback.assertNoCallback();
4960 
4961         // Update LinkProperties.
4962         final LinkProperties lp = new LinkProperties();
4963         lp.setInterfaceName("foonet_data0");
4964         mCellNetworkAgent.sendLinkProperties(lp);
4965         // We should get onLinkPropertiesChanged().
4966         cellNetworkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED,
4967                 mCellNetworkAgent);
4968         cellNetworkCallback.assertNoCallback();
4969 
4970         // Suspend the network.
4971         mCellNetworkAgent.suspend();
4972         cellNetworkCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_SUSPENDED,
4973                 mCellNetworkAgent);
4974         cellNetworkCallback.expectCallback(CallbackEntry.SUSPENDED, mCellNetworkAgent);
4975         cellNetworkCallback.assertNoCallback();
4976         assertEquals(NetworkInfo.State.SUSPENDED, mCm.getActiveNetworkInfo().getState());
4977 
4978         // Register a garden variety default network request.
4979         TestNetworkCallback dfltNetworkCallback = new TestNetworkCallback();
4980         mCm.registerDefaultNetworkCallback(dfltNetworkCallback);
4981         // We should get onAvailable(), onCapabilitiesChanged(), onLinkPropertiesChanged(),
4982         // as well as onNetworkSuspended() in rapid succession.
4983         dfltNetworkCallback.expectAvailableAndSuspendedCallbacks(mCellNetworkAgent, true);
4984         dfltNetworkCallback.assertNoCallback();
4985         mCm.unregisterNetworkCallback(dfltNetworkCallback);
4986 
4987         mCellNetworkAgent.resume();
4988         cellNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_NOT_SUSPENDED,
4989                 mCellNetworkAgent);
4990         cellNetworkCallback.expectCallback(CallbackEntry.RESUMED, mCellNetworkAgent);
4991         cellNetworkCallback.assertNoCallback();
4992         assertEquals(NetworkInfo.State.CONNECTED, mCm.getActiveNetworkInfo().getState());
4993 
4994         dfltNetworkCallback = new TestNetworkCallback();
4995         mCm.registerDefaultNetworkCallback(dfltNetworkCallback);
4996         // This time onNetworkSuspended should not be called.
4997         dfltNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
4998         dfltNetworkCallback.assertNoCallback();
4999 
5000         mCm.unregisterNetworkCallback(dfltNetworkCallback);
5001         mCm.unregisterNetworkCallback(cellNetworkCallback);
5002     }
5003 
5004     @Test
5005     public void testRegisterPrivilegedDefaultCallbacksRequireNetworkSettings() throws Exception {
5006         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
5007         mCellNetworkAgent.connect(false /* validated */);
5008 
5009         final Handler handler = new Handler(ConnectivityThread.getInstanceLooper());
5010         final TestNetworkCallback callback = new TestNetworkCallback();
5011         assertThrows(SecurityException.class,
5012                 () -> mCm.registerSystemDefaultNetworkCallback(callback, handler));
5013         callback.assertNoCallback();
5014         assertThrows(SecurityException.class,
5015                 () -> mCm.registerDefaultNetworkCallbackForUid(APP1_UID, callback, handler));
5016         callback.assertNoCallback();
5017 
5018         mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_GRANTED);
5019         mCm.registerSystemDefaultNetworkCallback(callback, handler);
5020         callback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
5021         mCm.unregisterNetworkCallback(callback);
5022 
5023         mCm.registerDefaultNetworkCallbackForUid(APP1_UID, callback, handler);
5024         callback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
5025         mCm.unregisterNetworkCallback(callback);
5026     }
5027 
5028     @Test
5029     public void testNetworkCallbackWithNullUids() throws Exception {
5030         final NetworkRequest request = new NetworkRequest.Builder()
5031                 .removeCapability(NET_CAPABILITY_NOT_VPN)
5032                 .build();
5033         final TestNetworkCallback callback = new TestNetworkCallback();
5034         mCm.registerNetworkCallback(request, callback);
5035 
5036         // Attempt to file a callback for networks applying to another UID. This does not actually
5037         // work, because this code does not currently have permission to do so. The callback behaves
5038         // exactly the same as the one registered just above.
5039         final int otherUid = UserHandle.getUid(RESTRICTED_USER, VPN_UID);
5040         final NetworkRequest otherUidRequest = new NetworkRequest.Builder()
5041                 .removeCapability(NET_CAPABILITY_NOT_VPN)
5042                 .setUids(UidRange.toIntRanges(uidRangesForUids(otherUid)))
5043                 .build();
5044         final TestNetworkCallback otherUidCallback = new TestNetworkCallback();
5045         mCm.registerNetworkCallback(otherUidRequest, otherUidCallback);
5046 
5047         final NetworkRequest includeOtherUidsRequest = new NetworkRequest.Builder()
5048                 .removeCapability(NET_CAPABILITY_NOT_VPN)
5049                 .setIncludeOtherUidNetworks(true)
5050                 .build();
5051         final TestNetworkCallback includeOtherUidsCallback = new TestNetworkCallback();
5052         mCm.registerNetworkCallback(includeOtherUidsRequest, includeOtherUidsCallback);
5053 
5054         // Both callbacks see a network with no specifier that applies to their UID.
5055         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
5056         mWiFiNetworkAgent.connect(false /* validated */);
5057         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
5058         otherUidCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
5059         includeOtherUidsCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
5060         mWiFiNetworkAgent.disconnect();
5061         callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
5062         otherUidCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
5063         includeOtherUidsCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
5064 
5065         // Only the includeOtherUidsCallback sees a VPN that does not apply to its UID.
5066         final UidRange range = UidRange.createForUser(UserHandle.of(RESTRICTED_USER));
5067         final Set<UidRange> vpnRanges = Collections.singleton(range);
5068         mMockVpn.establish(new LinkProperties(), VPN_UID, vpnRanges);
5069         includeOtherUidsCallback.expectAvailableThenValidatedCallbacks(mMockVpn);
5070         callback.assertNoCallback();
5071         otherUidCallback.assertNoCallback();
5072 
5073         mMockVpn.disconnect();
5074         includeOtherUidsCallback.expectCallback(CallbackEntry.LOST, mMockVpn);
5075         callback.assertNoCallback();
5076         otherUidCallback.assertNoCallback();
5077     }
5078 
5079     private static class RedactableNetworkSpecifier extends NetworkSpecifier {
5080         public static final int ID_INVALID = -1;
5081 
5082         public final int networkId;
5083 
5084         RedactableNetworkSpecifier(int networkId) {
5085             this.networkId = networkId;
5086         }
5087 
5088         @Override
5089         public boolean canBeSatisfiedBy(NetworkSpecifier other) {
5090             return other instanceof RedactableNetworkSpecifier
5091                     && this.networkId == ((RedactableNetworkSpecifier) other).networkId;
5092         }
5093 
5094         @Override
5095         public NetworkSpecifier redact() {
5096             return new RedactableNetworkSpecifier(ID_INVALID);
5097         }
5098     }
5099 
5100     @Test
5101     public void testNetworkCallbackWithNullUidsRedactsSpecifier() throws Exception {
5102         final RedactableNetworkSpecifier specifier = new RedactableNetworkSpecifier(42);
5103         final NetworkRequest request = new NetworkRequest.Builder()
5104                 .addCapability(NET_CAPABILITY_INTERNET)
5105                 .addTransportType(TRANSPORT_WIFI)
5106                 .setNetworkSpecifier(specifier)
5107                 .build();
5108         final TestNetworkCallback callback = new TestNetworkCallback();
5109         mCm.registerNetworkCallback(request, callback);
5110 
5111         // Attempt to file a callback for networks applying to another UID. This does not actually
5112         // work, because this code does not currently have permission to do so. The callback behaves
5113         // exactly the same as the one registered just above.
5114         final int otherUid = UserHandle.getUid(RESTRICTED_USER, VPN_UID);
5115         final NetworkRequest otherUidRequest = new NetworkRequest.Builder()
5116                 .addCapability(NET_CAPABILITY_INTERNET)
5117                 .addTransportType(TRANSPORT_WIFI)
5118                 .setNetworkSpecifier(specifier)
5119                 .setUids(UidRange.toIntRanges(uidRangesForUids(otherUid)))
5120                 .build();
5121         final TestNetworkCallback otherUidCallback = new TestNetworkCallback();
5122         mCm.registerNetworkCallback(otherUidRequest, otherUidCallback);
5123 
5124         final NetworkRequest includeOtherUidsRequest = new NetworkRequest.Builder()
5125                 .addCapability(NET_CAPABILITY_INTERNET)
5126                 .addTransportType(TRANSPORT_WIFI)
5127                 .setNetworkSpecifier(specifier)
5128                 .setIncludeOtherUidNetworks(true)
5129                 .build();
5130         final TestNetworkCallback includeOtherUidsCallback = new TestNetworkCallback();
5131         mCm.registerNetworkCallback(includeOtherUidsRequest, callback);
5132 
5133         // Only the regular callback sees the network, because callbacks filed with no UID have
5134         // their specifiers redacted.
5135         final LinkProperties emptyLp = new LinkProperties();
5136         final NetworkCapabilities ncTemplate = new NetworkCapabilities()
5137                 .addTransportType(TRANSPORT_WIFI)
5138                 .setNetworkSpecifier(specifier);
5139         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, emptyLp, ncTemplate);
5140         mWiFiNetworkAgent.connect(false /* validated */);
5141         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
5142         otherUidCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
5143         includeOtherUidsCallback.assertNoCallback();
5144     }
5145 
5146     private void setCaptivePortalMode(int mode) {
5147         ContentResolver cr = mServiceContext.getContentResolver();
5148         Settings.Global.putInt(cr, ConnectivitySettingsManager.CAPTIVE_PORTAL_MODE, mode);
5149     }
5150 
5151     private void setAlwaysOnNetworks(boolean enable) {
5152         ContentResolver cr = mServiceContext.getContentResolver();
5153         Settings.Global.putInt(cr, ConnectivitySettingsManager.MOBILE_DATA_ALWAYS_ON,
5154                 enable ? 1 : 0);
5155         mService.updateAlwaysOnNetworks();
5156         waitForIdle();
5157     }
5158 
5159     private void setPrivateDnsSettings(int mode, String specifier) {
5160         ConnectivitySettingsManager.setPrivateDnsMode(mServiceContext, mode);
5161         ConnectivitySettingsManager.setPrivateDnsHostname(mServiceContext, specifier);
5162         mService.updatePrivateDnsSettings();
5163         waitForIdle();
5164     }
5165 
5166     private void setIngressRateLimit(int rateLimitInBytesPerSec) {
5167         ConnectivitySettingsManager.setIngressRateLimitInBytesPerSecond(mServiceContext,
5168                 rateLimitInBytesPerSec);
5169         mService.updateIngressRateLimit();
5170         waitForIdle();
5171     }
5172 
5173     private boolean isForegroundNetwork(TestNetworkAgentWrapper network) {
5174         NetworkCapabilities nc = mCm.getNetworkCapabilities(network.getNetwork());
5175         assertNotNull(nc);
5176         return nc.hasCapability(NET_CAPABILITY_FOREGROUND);
5177     }
5178 
5179     @Test
5180     public void testBackgroundNetworks() throws Exception {
5181         // Create a cellular background request.
5182         grantUsingBackgroundNetworksPermissionForUid(Binder.getCallingUid());
5183         final TestNetworkCallback cellBgCallback = new TestNetworkCallback();
5184         mCm.requestBackgroundNetwork(new NetworkRequest.Builder()
5185                 .addTransportType(TRANSPORT_CELLULAR).build(),
5186                 cellBgCallback, mCsHandlerThread.getThreadHandler());
5187 
5188         // Make callbacks for monitoring.
5189         final NetworkRequest request = new NetworkRequest.Builder().build();
5190         final NetworkRequest fgRequest = new NetworkRequest.Builder()
5191                 .addCapability(NET_CAPABILITY_FOREGROUND).build();
5192         final TestNetworkCallback callback = new TestNetworkCallback();
5193         final TestNetworkCallback fgCallback = new TestNetworkCallback();
5194         mCm.registerNetworkCallback(request, callback);
5195         mCm.registerNetworkCallback(fgRequest, fgCallback);
5196 
5197         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
5198         mCellNetworkAgent.connect(true);
5199         callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
5200         fgCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
5201         assertTrue(isForegroundNetwork(mCellNetworkAgent));
5202 
5203         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
5204         mWiFiNetworkAgent.connect(true);
5205 
5206         // When wifi connects, cell lingers.
5207         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
5208         callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
5209         callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
5210         fgCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
5211         fgCallback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
5212         fgCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
5213         assertTrue(isForegroundNetwork(mCellNetworkAgent));
5214         assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
5215 
5216         // When lingering is complete, cell is still there but is now in the background.
5217         waitForIdle();
5218         int timeoutMs = TEST_LINGER_DELAY_MS + TEST_LINGER_DELAY_MS / 4;
5219         fgCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent, timeoutMs);
5220         // Expect a network capabilities update sans FOREGROUND.
5221         callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
5222         assertFalse(isForegroundNetwork(mCellNetworkAgent));
5223         assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
5224 
5225         // File a cell request and check that cell comes into the foreground.
5226         final NetworkRequest cellRequest = new NetworkRequest.Builder()
5227                 .addTransportType(TRANSPORT_CELLULAR).build();
5228         final TestNetworkCallback cellCallback = new TestNetworkCallback();
5229         mCm.requestNetwork(cellRequest, cellCallback);
5230         cellCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
5231         fgCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
5232         // Expect a network capabilities update with FOREGROUND, because the most recent
5233         // request causes its state to change.
5234         cellCallback.expectCapabilitiesWith(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
5235         callback.expectCapabilitiesWith(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
5236         assertTrue(isForegroundNetwork(mCellNetworkAgent));
5237         assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
5238 
5239         // Release the request. The network immediately goes into the background, since it was not
5240         // lingering.
5241         mCm.unregisterNetworkCallback(cellCallback);
5242         fgCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
5243         // Expect a network capabilities update sans FOREGROUND.
5244         callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
5245         assertFalse(isForegroundNetwork(mCellNetworkAgent));
5246         assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
5247 
5248         // Disconnect wifi and check that cell is foreground again.
5249         mWiFiNetworkAgent.disconnect();
5250         callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
5251         fgCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
5252         fgCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
5253         assertTrue(isForegroundNetwork(mCellNetworkAgent));
5254 
5255         mCm.unregisterNetworkCallback(callback);
5256         mCm.unregisterNetworkCallback(fgCallback);
5257         mCm.unregisterNetworkCallback(cellBgCallback);
5258     }
5259 
5260     @Ignore // This test has instrinsic chances of spurious failures: ignore for continuous testing.
5261     public void benchmarkRequestRegistrationAndCallbackDispatch() throws Exception {
5262         // TODO: turn this unit test into a real benchmarking test.
5263         // Benchmarks connecting and switching performance in the presence of a large number of
5264         // NetworkRequests.
5265         // 1. File NUM_REQUESTS requests.
5266         // 2. Have a network connect. Wait for NUM_REQUESTS onAvailable callbacks to fire.
5267         // 3. Have a new network connect and outscore the previous. Wait for NUM_REQUESTS onLosing
5268         //    and NUM_REQUESTS onAvailable callbacks to fire.
5269         // See how long it took.
5270         final int NUM_REQUESTS = 90;
5271         final int REGISTER_TIME_LIMIT_MS = 200;
5272         final int CONNECT_TIME_LIMIT_MS = 60;
5273         final int SWITCH_TIME_LIMIT_MS = 60;
5274         final int UNREGISTER_TIME_LIMIT_MS = 20;
5275 
5276         final NetworkRequest request = new NetworkRequest.Builder().clearCapabilities().build();
5277         final NetworkCallback[] callbacks = new NetworkCallback[NUM_REQUESTS];
5278         final CountDownLatch availableLatch = new CountDownLatch(NUM_REQUESTS);
5279         final CountDownLatch losingLatch = new CountDownLatch(NUM_REQUESTS);
5280 
5281         for (int i = 0; i < NUM_REQUESTS; i++) {
5282             callbacks[i] = new NetworkCallback() {
5283                 @Override public void onAvailable(Network n) { availableLatch.countDown(); }
5284                 @Override public void onLosing(Network n, int t) { losingLatch.countDown(); }
5285             };
5286         }
5287 
5288         assertRunsInAtMost("Registering callbacks", REGISTER_TIME_LIMIT_MS, () -> {
5289             for (NetworkCallback cb : callbacks) {
5290                 mCm.registerNetworkCallback(request, cb);
5291             }
5292         });
5293 
5294         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
5295         // Don't request that the network validate, because otherwise connect() will block until
5296         // the network gets NET_CAPABILITY_VALIDATED, after all the callbacks below have fired,
5297         // and we won't actually measure anything.
5298         mCellNetworkAgent.connect(false);
5299 
5300         long onAvailableDispatchingDuration = durationOf(() -> {
5301             await(availableLatch, 10 * CONNECT_TIME_LIMIT_MS);
5302         });
5303         Log.d(TAG, String.format("Dispatched %d of %d onAvailable callbacks in %dms",
5304                 NUM_REQUESTS - availableLatch.getCount(), NUM_REQUESTS,
5305                 onAvailableDispatchingDuration));
5306         assertTrue(String.format("Dispatching %d onAvailable callbacks in %dms, expected %dms",
5307                 NUM_REQUESTS, onAvailableDispatchingDuration, CONNECT_TIME_LIMIT_MS),
5308                 onAvailableDispatchingDuration <= CONNECT_TIME_LIMIT_MS);
5309 
5310         // Give wifi a high enough score that we'll linger cell when wifi comes up.
5311         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
5312         mWiFiNetworkAgent.adjustScore(40);
5313         mWiFiNetworkAgent.connect(false);
5314 
5315         long onLostDispatchingDuration = durationOf(() -> {
5316             await(losingLatch, 10 * SWITCH_TIME_LIMIT_MS);
5317         });
5318         Log.d(TAG, String.format("Dispatched %d of %d onLosing callbacks in %dms",
5319                 NUM_REQUESTS - losingLatch.getCount(), NUM_REQUESTS, onLostDispatchingDuration));
5320         assertTrue(String.format("Dispatching %d onLosing callbacks in %dms, expected %dms",
5321                 NUM_REQUESTS, onLostDispatchingDuration, SWITCH_TIME_LIMIT_MS),
5322                 onLostDispatchingDuration <= SWITCH_TIME_LIMIT_MS);
5323 
5324         assertRunsInAtMost("Unregistering callbacks", UNREGISTER_TIME_LIMIT_MS, () -> {
5325             for (NetworkCallback cb : callbacks) {
5326                 mCm.unregisterNetworkCallback(cb);
5327             }
5328         });
5329     }
5330 
5331     @Test
5332     public void testMobileDataAlwaysOn() throws Exception {
5333         grantUsingBackgroundNetworksPermissionForUid(Binder.getCallingUid());
5334         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
5335         final NetworkRequest cellRequest = new NetworkRequest.Builder()
5336                 .addTransportType(TRANSPORT_CELLULAR).build();
5337         mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
5338 
5339         final HandlerThread handlerThread = new HandlerThread("MobileDataAlwaysOnFactory");
5340         handlerThread.start();
5341         NetworkCapabilities filter = new NetworkCapabilities()
5342                 .addTransportType(TRANSPORT_CELLULAR)
5343                 .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
5344                 .addCapability(NET_CAPABILITY_INTERNET);
5345         final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
5346                 mServiceContext, "testFactory", filter, mCsHandlerThread);
5347         testFactory.setScoreFilter(40);
5348 
5349         // Register the factory and expect it to start looking for a network.
5350         testFactory.register();
5351 
5352         try {
5353             // Expect the factory to receive the default network request.
5354             testFactory.expectRequestAdd();
5355             testFactory.assertRequestCountEquals(1);
5356             assertTrue(testFactory.getMyStartRequested());
5357 
5358             // Bring up wifi. The factory stops looking for a network.
5359             mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
5360             // Score 60 - 40 penalty for not validated yet, then 60 when it validates
5361             mWiFiNetworkAgent.connect(true);
5362             // The network connects with a low score, so the offer can still beat it and
5363             // nothing happens. Then the network validates, and the offer with its filter score
5364             // of 40 can no longer beat it and the request is removed.
5365             testFactory.expectRequestRemove();
5366             testFactory.assertRequestCountEquals(0);
5367 
5368             assertFalse(testFactory.getMyStartRequested());
5369 
5370             // Turn on mobile data always on. This request will not match the wifi request, so
5371             // it will be sent to the test factory whose filters allow to see it.
5372             setAlwaysOnNetworks(true);
5373             testFactory.expectRequestAdd();
5374             testFactory.assertRequestCountEquals(1);
5375 
5376             assertTrue(testFactory.getMyStartRequested());
5377 
5378             // Bring up cell data and check that the factory stops looking.
5379             assertLength(1, mCm.getAllNetworks());
5380             mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
5381             mCellNetworkAgent.connect(false);
5382             cellNetworkCallback.expectAvailableCallbacks(mCellNetworkAgent, false, false, false,
5383                     TEST_CALLBACK_TIMEOUT_MS);
5384             // When cell connects, it will satisfy the "mobile always on request" right away
5385             // by virtue of being the only network that can satisfy the request. However, its
5386             // score is low (50 - 40 = 10) so the test factory can still hope to beat it.
5387             expectNoRequestChanged(testFactory);
5388 
5389             // Next, cell validates. This gives it a score of 50 and the test factory can't
5390             // hope to beat that according to its filters. It will see the message that its
5391             // offer is now unnecessary.
5392             mCellNetworkAgent.setNetworkValid(true);
5393             // Need a trigger point to let NetworkMonitor tell ConnectivityService that network is
5394             // validated – see testPartialConnectivity.
5395             mCm.reportNetworkConnectivity(mCellNetworkAgent.getNetwork(), true);
5396             cellNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mCellNetworkAgent);
5397             testFactory.expectRequestRemove();
5398             testFactory.assertRequestCountEquals(0);
5399             // Accordingly, the factory shouldn't be started.
5400             assertFalse(testFactory.getMyStartRequested());
5401 
5402             // Check that cell data stays up.
5403             waitForIdle();
5404             verifyActiveNetwork(TRANSPORT_WIFI);
5405             assertLength(2, mCm.getAllNetworks());
5406 
5407             // Cell disconnects. There is still the "mobile data always on" request outstanding,
5408             // and the test factory should see it now that it isn't hopelessly outscored.
5409             mCellNetworkAgent.disconnect();
5410             cellNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
5411             // Wait for the network to be removed from internal structures before
5412             // calling synchronous getter
5413             waitForIdle();
5414             assertLength(1, mCm.getAllNetworks());
5415             testFactory.expectRequestAdd();
5416             testFactory.assertRequestCountEquals(1);
5417 
5418             // Reconnect cell validated, see the request disappear again. Then withdraw the
5419             // mobile always on request. This will tear down cell, and there shouldn't be a
5420             // blip where the test factory briefly sees the request or anything.
5421             mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
5422             mCellNetworkAgent.connect(true);
5423             cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
5424             waitForIdle();
5425             assertLength(2, mCm.getAllNetworks());
5426             testFactory.expectRequestRemove();
5427             testFactory.assertRequestCountEquals(0);
5428             setAlwaysOnNetworks(false);
5429             expectNoRequestChanged(testFactory);
5430             testFactory.assertRequestCountEquals(0);
5431             assertFalse(testFactory.getMyStartRequested());
5432             // ...  and cell data to be torn down immediately since it is no longer nascent.
5433             cellNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
5434             waitForIdle();
5435             assertLength(1, mCm.getAllNetworks());
5436             testFactory.terminate();
5437             testFactory.assertNoRequestChanged();
5438         } finally {
5439             mCm.unregisterNetworkCallback(cellNetworkCallback);
5440             handlerThread.quit();
5441         }
5442     }
5443 
5444     @Test
5445     public void testSetAllowBadWifiUntil() throws Exception {
5446         runAsShell(NETWORK_SETTINGS,
5447                 () -> mService.setTestAllowBadWifiUntil(System.currentTimeMillis() + 5_000L));
5448         waitForIdle();
5449         testAvoidBadWifiConfig_controlledBySettings();
5450 
5451         runAsShell(NETWORK_SETTINGS,
5452                 () -> mService.setTestAllowBadWifiUntil(System.currentTimeMillis() - 5_000L));
5453         waitForIdle();
5454         testAvoidBadWifiConfig_ignoreSettings();
5455     }
5456 
5457     private void testAvoidBadWifiConfig_controlledBySettings() {
5458         final ContentResolver cr = mServiceContext.getContentResolver();
5459         final String settingName = ConnectivitySettingsManager.NETWORK_AVOID_BAD_WIFI;
5460 
5461         Settings.Global.putString(cr, settingName, "0");
5462         mPolicyTracker.reevaluate();
5463         waitForIdle();
5464         assertFalse(mService.avoidBadWifi());
5465         assertFalse(mPolicyTracker.shouldNotifyWifiUnvalidated());
5466 
5467         Settings.Global.putString(cr, settingName, "1");
5468         mPolicyTracker.reevaluate();
5469         waitForIdle();
5470         assertTrue(mService.avoidBadWifi());
5471         assertFalse(mPolicyTracker.shouldNotifyWifiUnvalidated());
5472 
5473         Settings.Global.putString(cr, settingName, null);
5474         mPolicyTracker.reevaluate();
5475         waitForIdle();
5476         assertFalse(mService.avoidBadWifi());
5477         assertTrue(mPolicyTracker.shouldNotifyWifiUnvalidated());
5478     }
5479 
5480     private void testAvoidBadWifiConfig_ignoreSettings() {
5481         final ContentResolver cr = mServiceContext.getContentResolver();
5482         final String settingName = ConnectivitySettingsManager.NETWORK_AVOID_BAD_WIFI;
5483 
5484         String[] values = new String[] {null, "0", "1"};
5485         for (int i = 0; i < values.length; i++) {
5486             Settings.Global.putString(cr, settingName, values[i]);
5487             mPolicyTracker.reevaluate();
5488             waitForIdle();
5489             String msg = String.format("config=false, setting=%s", values[i]);
5490             assertTrue(mService.avoidBadWifi());
5491             assertFalse(msg, mPolicyTracker.shouldNotifyWifiUnvalidated());
5492         }
5493     }
5494 
5495     @Test
5496     public void testAvoidBadWifiSetting() throws Exception {
5497         doReturn(1).when(mResources).getInteger(R.integer.config_networkAvoidBadWifi);
5498         testAvoidBadWifiConfig_ignoreSettings();
5499 
5500         doReturn(0).when(mResources).getInteger(R.integer.config_networkAvoidBadWifi);
5501         testAvoidBadWifiConfig_controlledBySettings();
5502     }
5503 
5504     @Test
5505     public void testOffersAvoidsBadWifi() throws Exception {
5506         // Normal mode : the carrier doesn't restrict moving away from bad wifi.
5507         // This has getAvoidBadWifi return true.
5508         doReturn(1).when(mResources).getInteger(R.integer.config_networkAvoidBadWifi);
5509         // Don't request cell separately for the purposes of this test.
5510         setAlwaysOnNetworks(false);
5511 
5512         final NetworkProvider cellProvider = new NetworkProvider(mServiceContext,
5513                 mCsHandlerThread.getLooper(), "Cell provider");
5514         final NetworkProvider wifiProvider = new NetworkProvider(mServiceContext,
5515                 mCsHandlerThread.getLooper(), "Wifi provider");
5516 
5517         mCm.registerNetworkProvider(cellProvider);
5518         mCm.registerNetworkProvider(wifiProvider);
5519 
5520         final NetworkScore cellScore = new NetworkScore.Builder().build();
5521         final NetworkScore wifiScore = new NetworkScore.Builder().build();
5522         final NetworkCapabilities defaultCaps = new NetworkCapabilities.Builder()
5523                 .addCapability(NET_CAPABILITY_INTERNET)
5524                 .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
5525                 .build();
5526         final NetworkCapabilities cellCaps = new NetworkCapabilities.Builder()
5527                 .addTransportType(TRANSPORT_CELLULAR)
5528                 .addCapability(NET_CAPABILITY_INTERNET)
5529                 .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
5530                 .build();
5531         final NetworkCapabilities wifiCaps = new NetworkCapabilities.Builder()
5532                 .addTransportType(TRANSPORT_WIFI)
5533                 .addCapability(NET_CAPABILITY_INTERNET)
5534                 .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
5535                 .build();
5536         final TestableNetworkOfferCallback cellCallback = new TestableNetworkOfferCallback(
5537                 TIMEOUT_MS /* timeout */, TEST_CALLBACK_TIMEOUT_MS /* noCallbackTimeout */);
5538         final TestableNetworkOfferCallback wifiCallback = new TestableNetworkOfferCallback(
5539                 TIMEOUT_MS /* timeout */, TEST_CALLBACK_TIMEOUT_MS /* noCallbackTimeout */);
5540 
5541         // Offer callbacks will run on the CS handler thread in this test.
5542         cellProvider.registerNetworkOffer(cellScore, cellCaps, r -> r.run(), cellCallback);
5543         wifiProvider.registerNetworkOffer(wifiScore, wifiCaps, r -> r.run(), wifiCallback);
5544 
5545         // Both providers see the default request.
5546         cellCallback.expectOnNetworkNeeded(defaultCaps);
5547         wifiCallback.expectOnNetworkNeeded(defaultCaps);
5548 
5549         // Listen to cell and wifi to know when agents are finished processing
5550         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
5551         final NetworkRequest cellRequest = new NetworkRequest.Builder()
5552                 .addTransportType(TRANSPORT_CELLULAR).build();
5553         mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
5554         final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
5555         final NetworkRequest wifiRequest = new NetworkRequest.Builder()
5556                 .addTransportType(TRANSPORT_WIFI).build();
5557         mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
5558 
5559         // Cell connects and validates.
5560         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR,
5561                 new LinkProperties(), null /* ncTemplate */, cellProvider);
5562         mCellNetworkAgent.connect(true);
5563         cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
5564         cellCallback.assertNoCallback();
5565         wifiCallback.assertNoCallback();
5566 
5567         // Bring up wifi. At first it's invalidated, so cell is still needed.
5568         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI,
5569                 new LinkProperties(), null /* ncTemplate */, wifiProvider);
5570         mWiFiNetworkAgent.connect(false);
5571         wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
5572         cellCallback.assertNoCallback();
5573         wifiCallback.assertNoCallback();
5574 
5575         // Wifi validates. Cell is no longer needed, because it's outscored.
5576         mWiFiNetworkAgent.setNetworkValid(true /* isStrictMode */);
5577         // Have CS reconsider the network (see testPartialConnectivity)
5578         mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
5579         wifiNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
5580         cellCallback.expectOnNetworkUnneeded(defaultCaps);
5581         wifiCallback.assertNoCallback();
5582 
5583         // Wifi is no longer validated. Cell is needed again.
5584         mWiFiNetworkAgent.setNetworkInvalid(true /* isStrictMode */);
5585         mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), false);
5586         wifiNetworkCallback.expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
5587         cellCallback.expectOnNetworkNeeded(defaultCaps);
5588         wifiCallback.assertNoCallback();
5589 
5590         // Disconnect wifi and pretend the carrier restricts moving away from bad wifi.
5591         mWiFiNetworkAgent.disconnect();
5592         wifiNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
5593         // This has getAvoidBadWifi return false. This test doesn't change the value of the
5594         // associated setting.
5595         doReturn(0).when(mResources).getInteger(R.integer.config_networkAvoidBadWifi);
5596         mPolicyTracker.reevaluate();
5597         waitForIdle();
5598 
5599         // Connect wifi again, cell is needed until wifi validates.
5600         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI,
5601                 new LinkProperties(), null /* ncTemplate */, wifiProvider);
5602         mWiFiNetworkAgent.connect(false);
5603         wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
5604         cellCallback.assertNoCallback();
5605         wifiCallback.assertNoCallback();
5606         mWiFiNetworkAgent.setNetworkValid(true /* isStrictMode */);
5607         mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
5608         wifiNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
5609         cellCallback.expectOnNetworkUnneeded(defaultCaps);
5610         wifiCallback.assertNoCallback();
5611 
5612         // Wifi loses validation. Because the device doesn't avoid bad wifis, cell is
5613         // not needed.
5614         mWiFiNetworkAgent.setNetworkInvalid(true /* isStrictMode */);
5615         mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), false);
5616         wifiNetworkCallback.expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
5617         cellCallback.assertNoCallback();
5618         wifiCallback.assertNoCallback();
5619     }
5620 
5621     @Test
5622     public void testAvoidBadWifi() throws Exception {
5623         final ContentResolver cr = mServiceContext.getContentResolver();
5624 
5625         // Pretend we're on a carrier that restricts switching away from bad wifi.
5626         doReturn(0).when(mResources).getInteger(R.integer.config_networkAvoidBadWifi);
5627 
5628         // File a request for cell to ensure it doesn't go down.
5629         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
5630         final NetworkRequest cellRequest = new NetworkRequest.Builder()
5631                 .addTransportType(TRANSPORT_CELLULAR).build();
5632         mCm.requestNetwork(cellRequest, cellNetworkCallback);
5633 
5634         TestNetworkCallback defaultCallback = new TestNetworkCallback();
5635         mCm.registerDefaultNetworkCallback(defaultCallback);
5636 
5637         NetworkRequest validatedWifiRequest = new NetworkRequest.Builder()
5638                 .addTransportType(TRANSPORT_WIFI)
5639                 .addCapability(NET_CAPABILITY_VALIDATED)
5640                 .build();
5641         TestNetworkCallback validatedWifiCallback = new TestNetworkCallback();
5642         mCm.registerNetworkCallback(validatedWifiRequest, validatedWifiCallback);
5643 
5644         Settings.Global.putInt(cr, ConnectivitySettingsManager.NETWORK_AVOID_BAD_WIFI, 0);
5645         mPolicyTracker.reevaluate();
5646 
5647         // Bring up validated cell.
5648         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
5649         mCellNetworkAgent.connect(true);
5650         cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
5651         defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
5652         Network cellNetwork = mCellNetworkAgent.getNetwork();
5653 
5654         // Bring up validated wifi.
5655         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
5656         mWiFiNetworkAgent.connect(true);
5657         defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
5658         validatedWifiCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
5659         Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
5660 
5661         // Fail validation on wifi.
5662         mWiFiNetworkAgent.setNetworkInvalid(false /* isStrictMode */);
5663         mCm.reportNetworkConnectivity(wifiNetwork, false);
5664         defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
5665         validatedWifiCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
5666 
5667         // Because avoid bad wifi is off, we don't switch to cellular.
5668         defaultCallback.assertNoCallback();
5669         assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
5670                 NET_CAPABILITY_VALIDATED));
5671         assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
5672                 NET_CAPABILITY_VALIDATED));
5673         assertEquals(mCm.getActiveNetwork(), wifiNetwork);
5674 
5675         // Simulate switching to a carrier that does not restrict avoiding bad wifi, and expect
5676         // that we switch back to cell.
5677         doReturn(1).when(mResources).getInteger(R.integer.config_networkAvoidBadWifi);
5678         mPolicyTracker.reevaluate();
5679         defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
5680         assertEquals(mCm.getActiveNetwork(), cellNetwork);
5681 
5682         // Switch back to a restrictive carrier.
5683         doReturn(0).when(mResources).getInteger(R.integer.config_networkAvoidBadWifi);
5684         mPolicyTracker.reevaluate();
5685         defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
5686         assertEquals(mCm.getActiveNetwork(), wifiNetwork);
5687 
5688         // Simulate the user selecting "switch" on the dialog, and check that we switch to cell.
5689         mCm.setAvoidUnvalidated(wifiNetwork);
5690         defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
5691         assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
5692                 NET_CAPABILITY_VALIDATED));
5693         assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
5694                 NET_CAPABILITY_VALIDATED));
5695         assertEquals(mCm.getActiveNetwork(), cellNetwork);
5696 
5697         // Disconnect and reconnect wifi to clear the one-time switch above.
5698         mWiFiNetworkAgent.disconnect();
5699         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
5700         mWiFiNetworkAgent.connect(true);
5701         defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
5702         validatedWifiCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
5703         wifiNetwork = mWiFiNetworkAgent.getNetwork();
5704 
5705         // Fail validation on wifi and expect the dialog to appear.
5706         mWiFiNetworkAgent.setNetworkInvalid(false /* isStrictMode */);
5707         mCm.reportNetworkConnectivity(wifiNetwork, false);
5708         defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
5709         validatedWifiCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
5710 
5711         // Simulate the user selecting "switch" and checking the don't ask again checkbox.
5712         Settings.Global.putInt(cr, ConnectivitySettingsManager.NETWORK_AVOID_BAD_WIFI, 1);
5713         mPolicyTracker.reevaluate();
5714 
5715         // We now switch to cell.
5716         defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
5717         assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
5718                 NET_CAPABILITY_VALIDATED));
5719         assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
5720                 NET_CAPABILITY_VALIDATED));
5721         assertEquals(mCm.getActiveNetwork(), cellNetwork);
5722 
5723         // Simulate the user turning the cellular fallback setting off and then on.
5724         // We switch to wifi and then to cell.
5725         Settings.Global.putString(cr, ConnectivitySettingsManager.NETWORK_AVOID_BAD_WIFI, null);
5726         mPolicyTracker.reevaluate();
5727         defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
5728         assertEquals(mCm.getActiveNetwork(), wifiNetwork);
5729         Settings.Global.putInt(cr, ConnectivitySettingsManager.NETWORK_AVOID_BAD_WIFI, 1);
5730         mPolicyTracker.reevaluate();
5731         defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
5732         assertEquals(mCm.getActiveNetwork(), cellNetwork);
5733 
5734         // If cell goes down, we switch to wifi.
5735         mCellNetworkAgent.disconnect();
5736         defaultCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
5737         defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
5738         validatedWifiCallback.assertNoCallback();
5739 
5740         mCm.unregisterNetworkCallback(cellNetworkCallback);
5741         mCm.unregisterNetworkCallback(validatedWifiCallback);
5742         mCm.unregisterNetworkCallback(defaultCallback);
5743     }
5744 
5745     @Test
5746     public void testMeteredMultipathPreferenceSetting() throws Exception {
5747         final ContentResolver cr = mServiceContext.getContentResolver();
5748         final String settingName = ConnectivitySettingsManager.NETWORK_METERED_MULTIPATH_PREFERENCE;
5749 
5750         for (int config : asList(0, 3, 2)) {
5751             for (String setting: asList(null, "0", "2", "1")) {
5752                 mPolicyTracker.mConfigMeteredMultipathPreference = config;
5753                 Settings.Global.putString(cr, settingName, setting);
5754                 mPolicyTracker.reevaluate();
5755                 waitForIdle();
5756 
5757                 final int expected = (setting != null) ? Integer.parseInt(setting) : config;
5758                 String msg = String.format("config=%d, setting=%s", config, setting);
5759                 assertEquals(msg, expected, mCm.getMultipathPreference(null));
5760             }
5761         }
5762     }
5763 
5764     /**
5765      * Validate that a satisfied network request does not trigger onUnavailable() once the
5766      * time-out period expires.
5767      */
5768     @Test
5769     public void testSatisfiedNetworkRequestDoesNotTriggerOnUnavailable() throws Exception {
5770         NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
5771                 NetworkCapabilities.TRANSPORT_WIFI).build();
5772         final TestNetworkCallback networkCallback = new TestNetworkCallback();
5773         mCm.requestNetwork(nr, networkCallback, TEST_REQUEST_TIMEOUT_MS);
5774 
5775         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
5776         mWiFiNetworkAgent.connect(false);
5777         networkCallback.expectAvailableCallbacks(mWiFiNetworkAgent, false, false, false,
5778                 TEST_CALLBACK_TIMEOUT_MS);
5779 
5780         // pass timeout and validate that UNAVAILABLE is not called
5781         networkCallback.assertNoCallback();
5782     }
5783 
5784     /**
5785      * Validate that a satisfied network request followed by a disconnected (lost) network does
5786      * not trigger onUnavailable() once the time-out period expires.
5787      */
5788     @Test
5789     public void testSatisfiedThenLostNetworkRequestDoesNotTriggerOnUnavailable() throws Exception {
5790         NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
5791                 NetworkCapabilities.TRANSPORT_WIFI).build();
5792         final TestNetworkCallback networkCallback = new TestNetworkCallback();
5793         mCm.requestNetwork(nr, networkCallback, TEST_REQUEST_TIMEOUT_MS);
5794 
5795         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
5796         mWiFiNetworkAgent.connect(false);
5797         networkCallback.expectAvailableCallbacks(mWiFiNetworkAgent, false, false, false,
5798                 TEST_CALLBACK_TIMEOUT_MS);
5799         mWiFiNetworkAgent.disconnect();
5800         networkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
5801 
5802         // Validate that UNAVAILABLE is not called
5803         networkCallback.assertNoCallback();
5804     }
5805 
5806     /**
5807      * Validate that when a time-out is specified for a network request the onUnavailable()
5808      * callback is called when time-out expires. Then validate that if network request is
5809      * (somehow) satisfied - the callback isn't called later.
5810      */
5811     @Test
5812     public void testTimedoutNetworkRequest() throws Exception {
5813         NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
5814                 NetworkCapabilities.TRANSPORT_WIFI).build();
5815         final TestNetworkCallback networkCallback = new TestNetworkCallback();
5816         final int timeoutMs = 10;
5817         mCm.requestNetwork(nr, networkCallback, timeoutMs);
5818 
5819         // pass timeout and validate that UNAVAILABLE is called
5820         networkCallback.expectCallback(CallbackEntry.UNAVAILABLE, (Network) null);
5821 
5822         // create a network satisfying request - validate that request not triggered
5823         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
5824         mWiFiNetworkAgent.connect(false);
5825         networkCallback.assertNoCallback();
5826     }
5827 
5828     /**
5829      * Validate that when a network request is unregistered (cancelled), no posterior event can
5830      * trigger the callback.
5831      */
5832     @Test
5833     public void testNoCallbackAfterUnregisteredNetworkRequest() throws Exception {
5834         NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
5835                 NetworkCapabilities.TRANSPORT_WIFI).build();
5836         final TestNetworkCallback networkCallback = new TestNetworkCallback();
5837         final int timeoutMs = 10;
5838 
5839         mCm.requestNetwork(nr, networkCallback, timeoutMs);
5840         mCm.unregisterNetworkCallback(networkCallback);
5841         // Regardless of the timeout, unregistering the callback in ConnectivityManager ensures
5842         // that this callback will not be called.
5843         networkCallback.assertNoCallback();
5844 
5845         // create a network satisfying request - validate that request not triggered
5846         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
5847         mWiFiNetworkAgent.connect(false);
5848         networkCallback.assertNoCallback();
5849     }
5850 
5851     @Test
5852     public void testUnfulfillableNetworkRequest() throws Exception {
5853         runUnfulfillableNetworkRequest(false);
5854     }
5855 
5856     @Test
5857     public void testUnfulfillableNetworkRequestAfterUnregister() throws Exception {
5858         runUnfulfillableNetworkRequest(true);
5859     }
5860 
5861     /**
5862      * Validate the callback flow for a factory releasing a request as unfulfillable.
5863      */
5864     private void runUnfulfillableNetworkRequest(boolean preUnregister) throws Exception {
5865         NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
5866                 NetworkCapabilities.TRANSPORT_WIFI).build();
5867         final TestNetworkCallback networkCallback = new TestNetworkCallback();
5868 
5869         final HandlerThread handlerThread = new HandlerThread("testUnfulfillableNetworkRequest");
5870         handlerThread.start();
5871         NetworkCapabilities filter = new NetworkCapabilities()
5872                 .addTransportType(TRANSPORT_WIFI)
5873                 .addCapability(NET_CAPABILITY_INTERNET)
5874                 .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED);
5875         final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
5876                 mServiceContext, "testFactory", filter, mCsHandlerThread);
5877         testFactory.setScoreFilter(40);
5878 
5879         // Register the factory and expect it to receive the default request.
5880         testFactory.register();
5881         testFactory.expectRequestAdd();
5882 
5883         try {
5884             // Now file the test request and expect it.
5885             mCm.requestNetwork(nr, networkCallback);
5886             final NetworkRequest newRequest = testFactory.expectRequestAdd().request;
5887 
5888             if (preUnregister) {
5889                 mCm.unregisterNetworkCallback(networkCallback);
5890 
5891                 // The request has been released : the factory should see it removed
5892                 // immediately.
5893                 testFactory.expectRequestRemove();
5894 
5895                 // Simulate the factory releasing the request as unfulfillable: no-op since
5896                 // the callback has already been unregistered (but a test that no exceptions are
5897                 // thrown).
5898                 testFactory.triggerUnfulfillable(newRequest);
5899             } else {
5900                 // Simulate the factory releasing the request as unfulfillable and expect
5901                 // onUnavailable!
5902                 testFactory.triggerUnfulfillable(newRequest);
5903 
5904                 networkCallback.expectCallback(CallbackEntry.UNAVAILABLE, (Network) null);
5905 
5906                 // Declaring a request unfulfillable releases it automatically.
5907                 testFactory.expectRequestRemove();
5908 
5909                 // unregister network callback - a no-op (since already freed by the
5910                 // on-unavailable), but should not fail or throw exceptions.
5911                 mCm.unregisterNetworkCallback(networkCallback);
5912 
5913                 // The factory should not see any further removal, as this request has
5914                 // already been removed.
5915             }
5916         } finally {
5917             testFactory.terminate();
5918             handlerThread.quit();
5919         }
5920     }
5921 
5922     /**
5923      * Validate the service throws if request with CBS but without carrier privilege.
5924      */
5925     @Test
5926     public void testCBSRequestWithoutCarrierPrivilege() throws Exception {
5927         final NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
5928                 TRANSPORT_CELLULAR).addCapability(NET_CAPABILITY_CBS).build();
5929         final TestNetworkCallback networkCallback = new TestNetworkCallback();
5930 
5931         mServiceContext.setPermission(CONNECTIVITY_USE_RESTRICTED_NETWORKS, PERMISSION_DENIED);
5932         // Now file the test request and expect the service throws.
5933         assertThrows(SecurityException.class, () -> mCm.requestNetwork(nr, networkCallback));
5934     }
5935 
5936     private static class TestKeepaliveCallback extends PacketKeepaliveCallback {
5937 
5938         public enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR }
5939 
5940         private class CallbackValue {
5941             public CallbackType callbackType;
5942             public int error;
5943 
5944             public CallbackValue(CallbackType type) {
5945                 this.callbackType = type;
5946                 this.error = PacketKeepalive.SUCCESS;
5947                 assertTrue("onError callback must have error", type != CallbackType.ON_ERROR);
5948             }
5949 
5950             public CallbackValue(CallbackType type, int error) {
5951                 this.callbackType = type;
5952                 this.error = error;
5953                 assertEquals("error can only be set for onError", type, CallbackType.ON_ERROR);
5954             }
5955 
5956             @Override
5957             public boolean equals(Object o) {
5958                 return o instanceof CallbackValue &&
5959                         this.callbackType == ((CallbackValue) o).callbackType &&
5960                         this.error == ((CallbackValue) o).error;
5961             }
5962 
5963             @Override
5964             public String toString() {
5965                 return String.format("%s(%s, %d)", getClass().getSimpleName(), callbackType, error);
5966             }
5967         }
5968 
5969         private final LinkedBlockingQueue<CallbackValue> mCallbacks = new LinkedBlockingQueue<>();
5970 
5971         @Override
5972         public void onStarted() {
5973             mCallbacks.add(new CallbackValue(CallbackType.ON_STARTED));
5974         }
5975 
5976         @Override
5977         public void onStopped() {
5978             mCallbacks.add(new CallbackValue(CallbackType.ON_STOPPED));
5979         }
5980 
5981         @Override
5982         public void onError(int error) {
5983             mCallbacks.add(new CallbackValue(CallbackType.ON_ERROR, error));
5984         }
5985 
5986         private void expectCallback(CallbackValue callbackValue) throws InterruptedException {
5987             assertEquals(callbackValue, mCallbacks.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
5988         }
5989 
5990         public void expectStarted() throws Exception {
5991             expectCallback(new CallbackValue(CallbackType.ON_STARTED));
5992         }
5993 
5994         public void expectStopped() throws Exception {
5995             expectCallback(new CallbackValue(CallbackType.ON_STOPPED));
5996         }
5997 
5998         public void expectError(int error) throws Exception {
5999             expectCallback(new CallbackValue(CallbackType.ON_ERROR, error));
6000         }
6001     }
6002 
6003     private static class TestSocketKeepaliveCallback extends SocketKeepalive.Callback {
6004 
6005         public enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR };
6006 
6007         private class CallbackValue {
6008             public CallbackType callbackType;
6009             public int error;
6010 
6011             CallbackValue(CallbackType type) {
6012                 this.callbackType = type;
6013                 this.error = SocketKeepalive.SUCCESS;
6014                 assertTrue("onError callback must have error", type != CallbackType.ON_ERROR);
6015             }
6016 
6017             CallbackValue(CallbackType type, int error) {
6018                 this.callbackType = type;
6019                 this.error = error;
6020                 assertEquals("error can only be set for onError", type, CallbackType.ON_ERROR);
6021             }
6022 
6023             @Override
6024             public boolean equals(Object o) {
6025                 return o instanceof CallbackValue
6026                         && this.callbackType == ((CallbackValue) o).callbackType
6027                         && this.error == ((CallbackValue) o).error;
6028             }
6029 
6030             @Override
6031             public String toString() {
6032                 return String.format("%s(%s, %d)", getClass().getSimpleName(), callbackType,
6033                         error);
6034             }
6035         }
6036 
6037         private LinkedBlockingQueue<CallbackValue> mCallbacks = new LinkedBlockingQueue<>();
6038         private final Executor mExecutor;
6039 
6040         TestSocketKeepaliveCallback(@NonNull Executor executor) {
6041             mExecutor = executor;
6042         }
6043 
6044         @Override
6045         public void onStarted() {
6046             mCallbacks.add(new CallbackValue(CallbackType.ON_STARTED));
6047         }
6048 
6049         @Override
6050         public void onStopped() {
6051             mCallbacks.add(new CallbackValue(CallbackType.ON_STOPPED));
6052         }
6053 
6054         @Override
6055         public void onError(int error) {
6056             mCallbacks.add(new CallbackValue(CallbackType.ON_ERROR, error));
6057         }
6058 
6059         private void expectCallback(CallbackValue callbackValue) throws InterruptedException {
6060             assertEquals(callbackValue, mCallbacks.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
6061 
6062         }
6063 
6064         public void expectStarted() throws InterruptedException {
6065             expectCallback(new CallbackValue(CallbackType.ON_STARTED));
6066         }
6067 
6068         public void expectStopped() throws InterruptedException {
6069             expectCallback(new CallbackValue(CallbackType.ON_STOPPED));
6070         }
6071 
6072         public void expectError(int error) throws InterruptedException {
6073             expectCallback(new CallbackValue(CallbackType.ON_ERROR, error));
6074         }
6075 
6076         public void assertNoCallback() {
6077             waitForIdleSerialExecutor(mExecutor, TIMEOUT_MS);
6078             CallbackValue cv = mCallbacks.peek();
6079             assertNull("Unexpected callback: " + cv, cv);
6080         }
6081     }
6082 
6083     private Network connectKeepaliveNetwork(LinkProperties lp) throws Exception {
6084         // Ensure the network is disconnected before anything else occurs
6085         if (mWiFiNetworkAgent != null) {
6086             assertNull(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()));
6087         }
6088 
6089         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
6090         ExpectedBroadcast b = expectConnectivityAction(TYPE_WIFI, DetailedState.CONNECTED);
6091         mWiFiNetworkAgent.connect(true);
6092         b.expectBroadcast();
6093         verifyActiveNetwork(TRANSPORT_WIFI);
6094         mWiFiNetworkAgent.sendLinkProperties(lp);
6095         waitForIdle();
6096         return mWiFiNetworkAgent.getNetwork();
6097     }
6098 
6099     @Test
6100     public void testPacketKeepalives() throws Exception {
6101         InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
6102         InetAddress notMyIPv4 = InetAddress.getByName("192.0.2.35");
6103         InetAddress myIPv6 = InetAddress.getByName("2001:db8::1");
6104         InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8");
6105         InetAddress dstIPv6 = InetAddress.getByName("2001:4860:4860::8888");
6106 
6107         final int validKaInterval = 15;
6108         final int invalidKaInterval = 9;
6109 
6110         LinkProperties lp = new LinkProperties();
6111         lp.setInterfaceName("wlan12");
6112         lp.addLinkAddress(new LinkAddress(myIPv6, 64));
6113         lp.addLinkAddress(new LinkAddress(myIPv4, 25));
6114         lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
6115         lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
6116 
6117         Network notMyNet = new Network(61234);
6118         Network myNet = connectKeepaliveNetwork(lp);
6119 
6120         TestKeepaliveCallback callback = new TestKeepaliveCallback();
6121         PacketKeepalive ka;
6122 
6123         // Attempt to start keepalives with invalid parameters and check for errors.
6124         ka = mCm.startNattKeepalive(notMyNet, validKaInterval, callback, myIPv4, 1234, dstIPv4);
6125         callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK);
6126 
6127         ka = mCm.startNattKeepalive(myNet, invalidKaInterval, callback, myIPv4, 1234, dstIPv4);
6128         callback.expectError(PacketKeepalive.ERROR_INVALID_INTERVAL);
6129 
6130         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 1234, dstIPv6);
6131         callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
6132 
6133         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv6, 1234, dstIPv4);
6134         callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
6135 
6136         // NAT-T is only supported for IPv4.
6137         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv6, 1234, dstIPv6);
6138         callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
6139 
6140         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 123456, dstIPv4);
6141         callback.expectError(PacketKeepalive.ERROR_INVALID_PORT);
6142 
6143         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 123456, dstIPv4);
6144         callback.expectError(PacketKeepalive.ERROR_INVALID_PORT);
6145 
6146         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
6147         callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
6148 
6149         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
6150         callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
6151 
6152         // Check that a started keepalive can be stopped.
6153         mWiFiNetworkAgent.setStartKeepaliveEvent(PacketKeepalive.SUCCESS);
6154         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
6155         callback.expectStarted();
6156         mWiFiNetworkAgent.setStopKeepaliveEvent(PacketKeepalive.SUCCESS);
6157         ka.stop();
6158         callback.expectStopped();
6159 
6160         // Check that deleting the IP address stops the keepalive.
6161         LinkProperties bogusLp = new LinkProperties(lp);
6162         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
6163         callback.expectStarted();
6164         bogusLp.removeLinkAddress(new LinkAddress(myIPv4, 25));
6165         bogusLp.addLinkAddress(new LinkAddress(notMyIPv4, 25));
6166         mWiFiNetworkAgent.sendLinkProperties(bogusLp);
6167         callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
6168         mWiFiNetworkAgent.sendLinkProperties(lp);
6169 
6170         // Check that a started keepalive is stopped correctly when the network disconnects.
6171         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
6172         callback.expectStarted();
6173         mWiFiNetworkAgent.disconnect();
6174         mWiFiNetworkAgent.expectDisconnected();
6175         callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK);
6176 
6177         // ... and that stopping it after that has no adverse effects.
6178         waitForIdle();
6179         final Network myNetAlias = myNet;
6180         assertNull(mCm.getNetworkCapabilities(myNetAlias));
6181         ka.stop();
6182 
6183         // Reconnect.
6184         myNet = connectKeepaliveNetwork(lp);
6185         mWiFiNetworkAgent.setStartKeepaliveEvent(PacketKeepalive.SUCCESS);
6186 
6187         // Check that keepalive slots start from 1 and increment. The first one gets slot 1.
6188         mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
6189         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
6190         callback.expectStarted();
6191 
6192         // The second one gets slot 2.
6193         mWiFiNetworkAgent.setExpectedKeepaliveSlot(2);
6194         TestKeepaliveCallback callback2 = new TestKeepaliveCallback();
6195         PacketKeepalive ka2 = mCm.startNattKeepalive(
6196                 myNet, validKaInterval, callback2, myIPv4, 6789, dstIPv4);
6197         callback2.expectStarted();
6198 
6199         // Now stop the first one and create a third. This also gets slot 1.
6200         ka.stop();
6201         callback.expectStopped();
6202 
6203         mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
6204         TestKeepaliveCallback callback3 = new TestKeepaliveCallback();
6205         PacketKeepalive ka3 = mCm.startNattKeepalive(
6206                 myNet, validKaInterval, callback3, myIPv4, 9876, dstIPv4);
6207         callback3.expectStarted();
6208 
6209         ka2.stop();
6210         callback2.expectStopped();
6211 
6212         ka3.stop();
6213         callback3.expectStopped();
6214     }
6215 
6216     // Helper method to prepare the executor and run test
6217     private void runTestWithSerialExecutors(ExceptionUtils.ThrowingConsumer<Executor> functor)
6218             throws Exception {
6219         final ExecutorService executorSingleThread = Executors.newSingleThreadExecutor();
6220         final Executor executorInline = (Runnable r) -> r.run();
6221         functor.accept(executorSingleThread);
6222         executorSingleThread.shutdown();
6223         functor.accept(executorInline);
6224     }
6225 
6226     @Test
6227     public void testNattSocketKeepalives() throws Exception {
6228         runTestWithSerialExecutors(executor -> doTestNattSocketKeepalivesWithExecutor(executor));
6229         runTestWithSerialExecutors(executor -> doTestNattSocketKeepalivesFdWithExecutor(executor));
6230     }
6231 
6232     private void doTestNattSocketKeepalivesWithExecutor(Executor executor) throws Exception {
6233         // TODO: 1. Move this outside of ConnectivityServiceTest.
6234         //       2. Make test to verify that Nat-T keepalive socket is created by IpSecService.
6235         //       3. Mock ipsec service.
6236         final InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
6237         final InetAddress notMyIPv4 = InetAddress.getByName("192.0.2.35");
6238         final InetAddress myIPv6 = InetAddress.getByName("2001:db8::1");
6239         final InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8");
6240         final InetAddress dstIPv6 = InetAddress.getByName("2001:4860:4860::8888");
6241 
6242         final int validKaInterval = 15;
6243         final int invalidKaInterval = 9;
6244 
6245         final IpSecManager mIpSec = (IpSecManager) mContext.getSystemService(Context.IPSEC_SERVICE);
6246         final UdpEncapsulationSocket testSocket = mIpSec.openUdpEncapsulationSocket();
6247         final int srcPort = testSocket.getPort();
6248 
6249         LinkProperties lp = new LinkProperties();
6250         lp.setInterfaceName("wlan12");
6251         lp.addLinkAddress(new LinkAddress(myIPv6, 64));
6252         lp.addLinkAddress(new LinkAddress(myIPv4, 25));
6253         lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
6254         lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
6255 
6256         Network notMyNet = new Network(61234);
6257         Network myNet = connectKeepaliveNetwork(lp);
6258 
6259         TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback(executor);
6260 
6261         // Attempt to start keepalives with invalid parameters and check for errors.
6262         // Invalid network.
6263         try (SocketKeepalive ka = mCm.createSocketKeepalive(
6264                 notMyNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
6265             ka.start(validKaInterval);
6266             callback.expectError(SocketKeepalive.ERROR_INVALID_NETWORK);
6267         }
6268 
6269         // Invalid interval.
6270         try (SocketKeepalive ka = mCm.createSocketKeepalive(
6271                 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
6272             ka.start(invalidKaInterval);
6273             callback.expectError(SocketKeepalive.ERROR_INVALID_INTERVAL);
6274         }
6275 
6276         // Invalid destination.
6277         try (SocketKeepalive ka = mCm.createSocketKeepalive(
6278                 myNet, testSocket, myIPv4, dstIPv6, executor, callback)) {
6279             ka.start(validKaInterval);
6280             callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
6281         }
6282 
6283         // Invalid source;
6284         try (SocketKeepalive ka = mCm.createSocketKeepalive(
6285                 myNet, testSocket, myIPv6, dstIPv4, executor, callback)) {
6286             ka.start(validKaInterval);
6287             callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
6288         }
6289 
6290         // NAT-T is only supported for IPv4.
6291         try (SocketKeepalive ka = mCm.createSocketKeepalive(
6292                 myNet, testSocket, myIPv6, dstIPv6, executor, callback)) {
6293             ka.start(validKaInterval);
6294             callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
6295         }
6296 
6297         // Basic check before testing started keepalive.
6298         try (SocketKeepalive ka = mCm.createSocketKeepalive(
6299                 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
6300             ka.start(validKaInterval);
6301             callback.expectError(SocketKeepalive.ERROR_UNSUPPORTED);
6302         }
6303 
6304         // Check that a started keepalive can be stopped.
6305         mWiFiNetworkAgent.setStartKeepaliveEvent(SocketKeepalive.SUCCESS);
6306         try (SocketKeepalive ka = mCm.createSocketKeepalive(
6307                 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
6308             ka.start(validKaInterval);
6309             callback.expectStarted();
6310             mWiFiNetworkAgent.setStopKeepaliveEvent(SocketKeepalive.SUCCESS);
6311             ka.stop();
6312             callback.expectStopped();
6313 
6314             // Check that keepalive could be restarted.
6315             ka.start(validKaInterval);
6316             callback.expectStarted();
6317             ka.stop();
6318             callback.expectStopped();
6319 
6320             // Check that keepalive can be restarted without waiting for callback.
6321             ka.start(validKaInterval);
6322             callback.expectStarted();
6323             ka.stop();
6324             ka.start(validKaInterval);
6325             callback.expectStopped();
6326             callback.expectStarted();
6327             ka.stop();
6328             callback.expectStopped();
6329         }
6330 
6331         // Check that deleting the IP address stops the keepalive.
6332         LinkProperties bogusLp = new LinkProperties(lp);
6333         try (SocketKeepalive ka = mCm.createSocketKeepalive(
6334                 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
6335             ka.start(validKaInterval);
6336             callback.expectStarted();
6337             bogusLp.removeLinkAddress(new LinkAddress(myIPv4, 25));
6338             bogusLp.addLinkAddress(new LinkAddress(notMyIPv4, 25));
6339             mWiFiNetworkAgent.sendLinkProperties(bogusLp);
6340             callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
6341             mWiFiNetworkAgent.sendLinkProperties(lp);
6342         }
6343 
6344         // Check that a started keepalive is stopped correctly when the network disconnects.
6345         try (SocketKeepalive ka = mCm.createSocketKeepalive(
6346                 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
6347             ka.start(validKaInterval);
6348             callback.expectStarted();
6349             mWiFiNetworkAgent.disconnect();
6350             mWiFiNetworkAgent.expectDisconnected();
6351             callback.expectError(SocketKeepalive.ERROR_INVALID_NETWORK);
6352 
6353             // ... and that stopping it after that has no adverse effects.
6354             waitForIdle();
6355             final Network myNetAlias = myNet;
6356             assertNull(mCm.getNetworkCapabilities(myNetAlias));
6357             ka.stop();
6358             callback.assertNoCallback();
6359         }
6360 
6361         // Reconnect.
6362         myNet = connectKeepaliveNetwork(lp);
6363         mWiFiNetworkAgent.setStartKeepaliveEvent(SocketKeepalive.SUCCESS);
6364 
6365         // Check that a stop followed by network disconnects does not result in crash.
6366         try (SocketKeepalive ka = mCm.createSocketKeepalive(
6367                 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
6368             ka.start(validKaInterval);
6369             callback.expectStarted();
6370             // Delay the response of keepalive events in networkAgent long enough to make sure
6371             // the follow-up network disconnection will be processed first.
6372             mWiFiNetworkAgent.setKeepaliveResponseDelay(3 * TIMEOUT_MS);
6373             ka.stop();
6374             // Call stop() twice shouldn't result in crash, b/182586681.
6375             ka.stop();
6376 
6377             // Make sure the stop has been processed. Wait for executor idle is needed to prevent
6378             // flaky since the actual stop call to the service is delegated to executor thread.
6379             waitForIdleSerialExecutor(executor, TIMEOUT_MS);
6380             waitForIdle();
6381 
6382             mWiFiNetworkAgent.disconnect();
6383             mWiFiNetworkAgent.expectDisconnected();
6384             callback.expectStopped();
6385             callback.assertNoCallback();
6386         }
6387 
6388         // Reconnect.
6389         waitForIdle();
6390         myNet = connectKeepaliveNetwork(lp);
6391         mWiFiNetworkAgent.setStartKeepaliveEvent(SocketKeepalive.SUCCESS);
6392 
6393         // Check that keepalive slots start from 1 and increment. The first one gets slot 1.
6394         mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
6395         int srcPort2 = 0;
6396         try (SocketKeepalive ka = mCm.createSocketKeepalive(
6397                 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
6398             ka.start(validKaInterval);
6399             callback.expectStarted();
6400 
6401             // The second one gets slot 2.
6402             mWiFiNetworkAgent.setExpectedKeepaliveSlot(2);
6403             final UdpEncapsulationSocket testSocket2 = mIpSec.openUdpEncapsulationSocket();
6404             srcPort2 = testSocket2.getPort();
6405             TestSocketKeepaliveCallback callback2 = new TestSocketKeepaliveCallback(executor);
6406             try (SocketKeepalive ka2 = mCm.createSocketKeepalive(
6407                     myNet, testSocket2, myIPv4, dstIPv4, executor, callback2)) {
6408                 ka2.start(validKaInterval);
6409                 callback2.expectStarted();
6410 
6411                 ka.stop();
6412                 callback.expectStopped();
6413 
6414                 ka2.stop();
6415                 callback2.expectStopped();
6416 
6417                 testSocket.close();
6418                 testSocket2.close();
6419             }
6420         }
6421 
6422         // Check that there is no port leaked after all keepalives and sockets are closed.
6423         // TODO: enable this check after ensuring a valid free port. See b/129512753#comment7.
6424         // assertFalse(isUdpPortInUse(srcPort));
6425         // assertFalse(isUdpPortInUse(srcPort2));
6426 
6427         mWiFiNetworkAgent.disconnect();
6428         mWiFiNetworkAgent.expectDisconnected();
6429         mWiFiNetworkAgent = null;
6430     }
6431 
6432     @Test
6433     public void testTcpSocketKeepalives() throws Exception {
6434         runTestWithSerialExecutors(executor -> doTestTcpSocketKeepalivesWithExecutor(executor));
6435     }
6436 
6437     private void doTestTcpSocketKeepalivesWithExecutor(Executor executor) throws Exception {
6438         final int srcPortV4 = 12345;
6439         final int srcPortV6 = 23456;
6440         final InetAddress myIPv4 = InetAddress.getByName("127.0.0.1");
6441         final InetAddress myIPv6 = InetAddress.getByName("::1");
6442 
6443         final int validKaInterval = 15;
6444 
6445         final LinkProperties lp = new LinkProperties();
6446         lp.setInterfaceName("wlan12");
6447         lp.addLinkAddress(new LinkAddress(myIPv6, 64));
6448         lp.addLinkAddress(new LinkAddress(myIPv4, 25));
6449         lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
6450         lp.addRoute(new RouteInfo(InetAddress.getByName("127.0.0.254")));
6451 
6452         final Network notMyNet = new Network(61234);
6453         final Network myNet = connectKeepaliveNetwork(lp);
6454 
6455         final Socket testSocketV4 = new Socket();
6456         final Socket testSocketV6 = new Socket();
6457 
6458         TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback(executor);
6459 
6460         // Attempt to start Tcp keepalives with invalid parameters and check for errors.
6461         // Invalid network.
6462         try (SocketKeepalive ka = mCm.createSocketKeepalive(
6463             notMyNet, testSocketV4, executor, callback)) {
6464             ka.start(validKaInterval);
6465             callback.expectError(SocketKeepalive.ERROR_INVALID_NETWORK);
6466         }
6467 
6468         // Invalid Socket (socket is not bound with IPv4 address).
6469         try (SocketKeepalive ka = mCm.createSocketKeepalive(
6470             myNet, testSocketV4, executor, callback)) {
6471             ka.start(validKaInterval);
6472             callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
6473         }
6474 
6475         // Invalid Socket (socket is not bound with IPv6 address).
6476         try (SocketKeepalive ka = mCm.createSocketKeepalive(
6477             myNet, testSocketV6, executor, callback)) {
6478             ka.start(validKaInterval);
6479             callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
6480         }
6481 
6482         // Bind the socket address
6483         testSocketV4.bind(new InetSocketAddress(myIPv4, srcPortV4));
6484         testSocketV6.bind(new InetSocketAddress(myIPv6, srcPortV6));
6485 
6486         // Invalid Socket (socket is bound with IPv4 address).
6487         try (SocketKeepalive ka = mCm.createSocketKeepalive(
6488             myNet, testSocketV4, executor, callback)) {
6489             ka.start(validKaInterval);
6490             callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
6491         }
6492 
6493         // Invalid Socket (socket is bound with IPv6 address).
6494         try (SocketKeepalive ka = mCm.createSocketKeepalive(
6495             myNet, testSocketV6, executor, callback)) {
6496             ka.start(validKaInterval);
6497             callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
6498         }
6499 
6500         testSocketV4.close();
6501         testSocketV6.close();
6502 
6503         mWiFiNetworkAgent.disconnect();
6504         mWiFiNetworkAgent.expectDisconnected();
6505         mWiFiNetworkAgent = null;
6506     }
6507 
6508     private void doTestNattSocketKeepalivesFdWithExecutor(Executor executor) throws Exception {
6509         final InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
6510         final InetAddress anyIPv4 = InetAddress.getByName("0.0.0.0");
6511         final InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8");
6512         final int validKaInterval = 15;
6513 
6514         // Prepare the target network.
6515         LinkProperties lp = new LinkProperties();
6516         lp.setInterfaceName("wlan12");
6517         lp.addLinkAddress(new LinkAddress(myIPv4, 25));
6518         lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
6519         Network myNet = connectKeepaliveNetwork(lp);
6520         mWiFiNetworkAgent.setStartKeepaliveEvent(SocketKeepalive.SUCCESS);
6521         mWiFiNetworkAgent.setStopKeepaliveEvent(SocketKeepalive.SUCCESS);
6522 
6523         TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback(executor);
6524 
6525         // Prepare the target file descriptor, keep only one instance.
6526         final IpSecManager mIpSec = (IpSecManager) mContext.getSystemService(Context.IPSEC_SERVICE);
6527         final UdpEncapsulationSocket testSocket = mIpSec.openUdpEncapsulationSocket();
6528         final int srcPort = testSocket.getPort();
6529         final ParcelFileDescriptor testPfd =
6530                 ParcelFileDescriptor.dup(testSocket.getFileDescriptor());
6531         testSocket.close();
6532         assertTrue(isUdpPortInUse(srcPort));
6533 
6534         // Start keepalive and explicit make the variable goes out of scope with try-with-resources
6535         // block.
6536         try (SocketKeepalive ka = mCm.createNattKeepalive(
6537                 myNet, testPfd, myIPv4, dstIPv4, executor, callback)) {
6538             ka.start(validKaInterval);
6539             callback.expectStarted();
6540             ka.stop();
6541             callback.expectStopped();
6542         }
6543 
6544         // Check that the ParcelFileDescriptor is still valid after keepalive stopped,
6545         // ErrnoException with EBADF will be thrown if the socket is closed when checking local
6546         // address.
6547         assertTrue(isUdpPortInUse(srcPort));
6548         final InetSocketAddress sa =
6549                 (InetSocketAddress) Os.getsockname(testPfd.getFileDescriptor());
6550         assertEquals(anyIPv4, sa.getAddress());
6551 
6552         testPfd.close();
6553         // TODO: enable this check after ensuring a valid free port. See b/129512753#comment7.
6554         // assertFalse(isUdpPortInUse(srcPort));
6555 
6556         mWiFiNetworkAgent.disconnect();
6557         mWiFiNetworkAgent.expectDisconnected();
6558         mWiFiNetworkAgent = null;
6559     }
6560 
6561     private static boolean isUdpPortInUse(int port) {
6562         try (DatagramSocket ignored = new DatagramSocket(port)) {
6563             return false;
6564         } catch (IOException alreadyInUse) {
6565             return true;
6566         }
6567     }
6568 
6569     @Test
6570     public void testGetCaptivePortalServerUrl() throws Exception {
6571         String url = mCm.getCaptivePortalServerUrl();
6572         assertEquals("http://connectivitycheck.gstatic.com/generate_204", url);
6573     }
6574 
6575     private static class TestNetworkPinner extends NetworkPinner {
6576         public static boolean awaitPin(int timeoutMs) throws InterruptedException {
6577             synchronized(sLock) {
6578                 if (sNetwork == null) {
6579                     sLock.wait(timeoutMs);
6580                 }
6581                 return sNetwork != null;
6582             }
6583         }
6584 
6585         public static boolean awaitUnpin(int timeoutMs) throws InterruptedException {
6586             synchronized(sLock) {
6587                 if (sNetwork != null) {
6588                     sLock.wait(timeoutMs);
6589                 }
6590                 return sNetwork == null;
6591             }
6592         }
6593     }
6594 
6595     private void assertPinnedToWifiWithCellDefault() {
6596         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess());
6597         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
6598     }
6599 
6600     private void assertPinnedToWifiWithWifiDefault() {
6601         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess());
6602         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
6603     }
6604 
6605     private void assertNotPinnedToWifi() {
6606         assertNull(mCm.getBoundNetworkForProcess());
6607         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
6608     }
6609 
6610     @Test
6611     public void testNetworkPinner() throws Exception {
6612         NetworkRequest wifiRequest = new NetworkRequest.Builder()
6613                 .addTransportType(TRANSPORT_WIFI)
6614                 .build();
6615         assertNull(mCm.getBoundNetworkForProcess());
6616 
6617         TestNetworkPinner.pin(mServiceContext, wifiRequest);
6618         assertNull(mCm.getBoundNetworkForProcess());
6619 
6620         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
6621         mCellNetworkAgent.connect(true);
6622         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
6623         mWiFiNetworkAgent.connect(false);
6624 
6625         // When wi-fi connects, expect to be pinned.
6626         assertTrue(TestNetworkPinner.awaitPin(100));
6627         assertPinnedToWifiWithCellDefault();
6628 
6629         // Disconnect and expect the pin to drop.
6630         mWiFiNetworkAgent.disconnect();
6631         assertTrue(TestNetworkPinner.awaitUnpin(100));
6632         assertNotPinnedToWifi();
6633 
6634         // Reconnecting does not cause the pin to come back.
6635         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
6636         mWiFiNetworkAgent.connect(false);
6637         assertFalse(TestNetworkPinner.awaitPin(100));
6638         assertNotPinnedToWifi();
6639 
6640         // Pinning while connected causes the pin to take effect immediately.
6641         TestNetworkPinner.pin(mServiceContext, wifiRequest);
6642         assertTrue(TestNetworkPinner.awaitPin(100));
6643         assertPinnedToWifiWithCellDefault();
6644 
6645         // Explicitly unpin and expect to use the default network again.
6646         TestNetworkPinner.unpin();
6647         assertNotPinnedToWifi();
6648 
6649         // Disconnect cell and wifi.
6650         ExpectedBroadcast b = registerConnectivityBroadcast(3);  // cell down, wifi up, wifi down.
6651         mCellNetworkAgent.disconnect();
6652         mWiFiNetworkAgent.disconnect();
6653         b.expectBroadcast();
6654 
6655         // Pinning takes effect even if the pinned network is the default when the pin is set...
6656         TestNetworkPinner.pin(mServiceContext, wifiRequest);
6657         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
6658         mWiFiNetworkAgent.connect(false);
6659         assertTrue(TestNetworkPinner.awaitPin(100));
6660         assertPinnedToWifiWithWifiDefault();
6661 
6662         // ... and is maintained even when that network is no longer the default.
6663         b = registerConnectivityBroadcast(1);
6664         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
6665         mCellNetworkAgent.connect(true);
6666         b.expectBroadcast();
6667         assertPinnedToWifiWithCellDefault();
6668     }
6669 
6670     @Test
6671     public void testNetworkCallbackMaximum() throws Exception {
6672         final int MAX_REQUESTS = 100;
6673         final int CALLBACKS = 87;
6674         final int DIFF_INTENTS = 10;
6675         final int SAME_INTENTS = 10;
6676         final int SYSTEM_ONLY_MAX_REQUESTS = 250;
6677         // Assert 1 (Default request filed before testing) + CALLBACKS + DIFF_INTENTS +
6678         // 1 (same intent) = MAX_REQUESTS - 1, since the capacity is MAX_REQUEST - 1.
6679         assertEquals(MAX_REQUESTS - 1, 1 + CALLBACKS + DIFF_INTENTS + 1);
6680 
6681         NetworkRequest networkRequest = new NetworkRequest.Builder().build();
6682         ArrayList<Object> registered = new ArrayList<>();
6683 
6684         for (int j = 0; j < CALLBACKS; j++) {
6685             final NetworkCallback cb = new NetworkCallback();
6686             if (j < CALLBACKS / 2) {
6687                 mCm.requestNetwork(networkRequest, cb);
6688             } else {
6689                 mCm.registerNetworkCallback(networkRequest, cb);
6690             }
6691             registered.add(cb);
6692         }
6693 
6694         // Since ConnectivityService will de-duplicate the request with the same intent,
6695         // register multiple times does not really increase multiple requests.
6696         final PendingIntent same_pi = PendingIntent.getBroadcast(mContext, 0 /* requestCode */,
6697                 new Intent("same"), FLAG_IMMUTABLE);
6698         for (int j = 0; j < SAME_INTENTS; j++) {
6699             mCm.registerNetworkCallback(networkRequest, same_pi);
6700             // Wait for the requests with the same intent to be de-duplicated. Because
6701             // ConnectivityService side incrementCountOrThrow in binder, decrementCount in handler
6702             // thread, waitForIdle is needed to ensure decrementCount being invoked for same intent
6703             // requests before doing further tests.
6704             waitForIdle();
6705         }
6706         for (int j = 0; j < SAME_INTENTS; j++) {
6707             mCm.requestNetwork(networkRequest, same_pi);
6708             // Wait for the requests with the same intent to be de-duplicated.
6709             // Refer to the reason above.
6710             waitForIdle();
6711         }
6712         registered.add(same_pi);
6713 
6714         for (int j = 0; j < DIFF_INTENTS; j++) {
6715             if (j < DIFF_INTENTS / 2) {
6716                 final PendingIntent pi = PendingIntent.getBroadcast(mContext, 0 /* requestCode */,
6717                         new Intent("a" + j), FLAG_IMMUTABLE);
6718                 mCm.requestNetwork(networkRequest, pi);
6719                 registered.add(pi);
6720             } else {
6721                 final PendingIntent pi = PendingIntent.getBroadcast(mContext, 0 /* requestCode */,
6722                         new Intent("b" + j), FLAG_IMMUTABLE);
6723                 mCm.registerNetworkCallback(networkRequest, pi);
6724                 registered.add(pi);
6725             }
6726         }
6727 
6728         // Test that the limit is enforced when MAX_REQUESTS simultaneous requests are added.
6729         assertThrows(TooManyRequestsException.class, () ->
6730                 mCm.requestNetwork(networkRequest, new NetworkCallback())
6731         );
6732         assertThrows(TooManyRequestsException.class, () ->
6733                 mCm.registerNetworkCallback(networkRequest, new NetworkCallback())
6734         );
6735         assertThrows(TooManyRequestsException.class, () ->
6736                 mCm.requestNetwork(networkRequest,
6737                         PendingIntent.getBroadcast(mContext, 0 /* requestCode */,
6738                                 new Intent("c"), FLAG_IMMUTABLE))
6739         );
6740         assertThrows(TooManyRequestsException.class, () ->
6741                 mCm.registerNetworkCallback(networkRequest,
6742                         PendingIntent.getBroadcast(mContext, 0 /* requestCode */,
6743                                 new Intent("d"), FLAG_IMMUTABLE))
6744         );
6745 
6746         // The system gets another SYSTEM_ONLY_MAX_REQUESTS slots.
6747         final Handler handler = new Handler(ConnectivityThread.getInstanceLooper());
6748         withPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, () -> {
6749             ArrayList<NetworkCallback> systemRegistered = new ArrayList<>();
6750             for (int i = 0; i < SYSTEM_ONLY_MAX_REQUESTS - 1; i++) {
6751                 NetworkCallback cb = new NetworkCallback();
6752                 if (i % 2 == 0) {
6753                     mCm.registerDefaultNetworkCallbackForUid(1000000 + i, cb, handler);
6754                 } else {
6755                     mCm.registerNetworkCallback(networkRequest, cb);
6756                 }
6757                 systemRegistered.add(cb);
6758             }
6759             waitForIdle();
6760 
6761             assertThrows(TooManyRequestsException.class, () ->
6762                     mCm.registerDefaultNetworkCallbackForUid(1001042, new NetworkCallback(),
6763                             handler));
6764             assertThrows(TooManyRequestsException.class, () ->
6765                     mCm.registerNetworkCallback(networkRequest, new NetworkCallback()));
6766 
6767             for (NetworkCallback callback : systemRegistered) {
6768                 mCm.unregisterNetworkCallback(callback);
6769             }
6770             waitForIdle();  // Wait for requests to be unregistered before giving up the permission.
6771         });
6772 
6773         for (Object o : registered) {
6774             if (o instanceof NetworkCallback) {
6775                 mCm.unregisterNetworkCallback((NetworkCallback) o);
6776             }
6777             if (o instanceof PendingIntent) {
6778                 mCm.unregisterNetworkCallback((PendingIntent) o);
6779             }
6780         }
6781         waitForIdle();
6782 
6783         // Test that the limit is not hit when MAX_REQUESTS requests are added and removed.
6784         for (int i = 0; i < MAX_REQUESTS; i++) {
6785             NetworkCallback networkCallback = new NetworkCallback();
6786             mCm.requestNetwork(networkRequest, networkCallback);
6787             mCm.unregisterNetworkCallback(networkCallback);
6788         }
6789         waitForIdle();
6790 
6791         for (int i = 0; i < MAX_REQUESTS; i++) {
6792             NetworkCallback networkCallback = new NetworkCallback();
6793             mCm.registerNetworkCallback(networkRequest, networkCallback);
6794             mCm.unregisterNetworkCallback(networkCallback);
6795         }
6796         waitForIdle();
6797 
6798         for (int i = 0; i < MAX_REQUESTS; i++) {
6799             NetworkCallback networkCallback = new NetworkCallback();
6800             mCm.registerDefaultNetworkCallback(networkCallback);
6801             mCm.unregisterNetworkCallback(networkCallback);
6802         }
6803         waitForIdle();
6804 
6805         for (int i = 0; i < MAX_REQUESTS; i++) {
6806             NetworkCallback networkCallback = new NetworkCallback();
6807             mCm.registerDefaultNetworkCallback(networkCallback);
6808             mCm.unregisterNetworkCallback(networkCallback);
6809         }
6810         waitForIdle();
6811 
6812         withPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, () -> {
6813             for (int i = 0; i < MAX_REQUESTS; i++) {
6814                 NetworkCallback networkCallback = new NetworkCallback();
6815                 mCm.registerDefaultNetworkCallbackForUid(1000000 + i, networkCallback,
6816                         new Handler(ConnectivityThread.getInstanceLooper()));
6817                 mCm.unregisterNetworkCallback(networkCallback);
6818             }
6819         });
6820         waitForIdle();
6821 
6822         for (int i = 0; i < MAX_REQUESTS; i++) {
6823             final PendingIntent pendingIntent = PendingIntent.getBroadcast(
6824                     mContext, 0 /* requestCode */, new Intent("e" + i), FLAG_IMMUTABLE);
6825             mCm.requestNetwork(networkRequest, pendingIntent);
6826             mCm.unregisterNetworkCallback(pendingIntent);
6827         }
6828         waitForIdle();
6829 
6830         for (int i = 0; i < MAX_REQUESTS; i++) {
6831             final PendingIntent pendingIntent = PendingIntent.getBroadcast(
6832                     mContext, 0 /* requestCode */, new Intent("f" + i), FLAG_IMMUTABLE);
6833             mCm.registerNetworkCallback(networkRequest, pendingIntent);
6834             mCm.unregisterNetworkCallback(pendingIntent);
6835         }
6836     }
6837 
6838     @Test
6839     public void testNetworkInfoOfTypeNone() throws Exception {
6840         ExpectedBroadcast b = registerConnectivityBroadcast(1);
6841 
6842         verifyNoNetwork();
6843         TestNetworkAgentWrapper wifiAware = new TestNetworkAgentWrapper(TRANSPORT_WIFI_AWARE);
6844         assertNull(mCm.getActiveNetworkInfo());
6845 
6846         Network[] allNetworks = mCm.getAllNetworks();
6847         assertLength(1, allNetworks);
6848         Network network = allNetworks[0];
6849         NetworkCapabilities capabilities = mCm.getNetworkCapabilities(network);
6850         assertTrue(capabilities.hasTransport(TRANSPORT_WIFI_AWARE));
6851 
6852         final NetworkRequest request =
6853                 new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI_AWARE).build();
6854         final TestNetworkCallback callback = new TestNetworkCallback();
6855         mCm.registerNetworkCallback(request, callback);
6856 
6857         // Bring up wifi aware network.
6858         wifiAware.connect(false, false, false /* isStrictMode */);
6859         callback.expectAvailableCallbacksUnvalidated(wifiAware);
6860 
6861         assertNull(mCm.getActiveNetworkInfo());
6862         assertNull(mCm.getActiveNetwork());
6863         // TODO: getAllNetworkInfo is dirty and returns a non-empty array right from the start
6864         // of this test. Fix it and uncomment the assert below.
6865         //assertEmpty(mCm.getAllNetworkInfo());
6866 
6867         // Disconnect wifi aware network.
6868         wifiAware.disconnect();
6869         callback.expectCallbackThat(TIMEOUT_MS, (info) -> info instanceof CallbackEntry.Lost);
6870         mCm.unregisterNetworkCallback(callback);
6871 
6872         verifyNoNetwork();
6873         b.expectNoBroadcast(10);
6874     }
6875 
6876     @Test
6877     public void testDeprecatedAndUnsupportedOperations() throws Exception {
6878         final int TYPE_NONE = ConnectivityManager.TYPE_NONE;
6879         assertNull(mCm.getNetworkInfo(TYPE_NONE));
6880         assertNull(mCm.getNetworkForType(TYPE_NONE));
6881         assertNull(mCm.getLinkProperties(TYPE_NONE));
6882         assertFalse(mCm.isNetworkSupported(TYPE_NONE));
6883 
6884         assertThrows(IllegalArgumentException.class,
6885                 () -> mCm.networkCapabilitiesForType(TYPE_NONE));
6886 
6887         Class<UnsupportedOperationException> unsupported = UnsupportedOperationException.class;
6888         assertThrows(unsupported, () -> mCm.startUsingNetworkFeature(TYPE_WIFI, ""));
6889         assertThrows(unsupported, () -> mCm.stopUsingNetworkFeature(TYPE_WIFI, ""));
6890         // TODO: let test context have configuration application target sdk version
6891         // and test that pre-M requesting for TYPE_NONE sends back APN_REQUEST_FAILED
6892         assertThrows(unsupported, () -> mCm.startUsingNetworkFeature(TYPE_NONE, ""));
6893         assertThrows(unsupported, () -> mCm.stopUsingNetworkFeature(TYPE_NONE, ""));
6894         assertThrows(unsupported, () -> mCm.requestRouteToHostAddress(TYPE_NONE, null));
6895     }
6896 
6897     @Test
6898     public void testLinkPropertiesEnsuresDirectlyConnectedRoutes() throws Exception {
6899         final NetworkRequest networkRequest = new NetworkRequest.Builder()
6900                 .addTransportType(TRANSPORT_WIFI).build();
6901         final TestNetworkCallback networkCallback = new TestNetworkCallback();
6902         mCm.registerNetworkCallback(networkRequest, networkCallback);
6903 
6904         LinkProperties lp = new LinkProperties();
6905         lp.setInterfaceName(WIFI_IFNAME);
6906         LinkAddress myIpv4Address = new LinkAddress("192.168.12.3/24");
6907         RouteInfo myIpv4DefaultRoute = new RouteInfo((IpPrefix) null,
6908                 InetAddresses.parseNumericAddress("192.168.12.1"), lp.getInterfaceName());
6909         lp.addLinkAddress(myIpv4Address);
6910         lp.addRoute(myIpv4DefaultRoute);
6911 
6912         // Verify direct routes are added when network agent is first registered in
6913         // ConnectivityService.
6914         TestNetworkAgentWrapper networkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, lp);
6915         networkAgent.connect(true);
6916         networkCallback.expectCallback(CallbackEntry.AVAILABLE, networkAgent);
6917         networkCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, networkAgent);
6918         CallbackEntry.LinkPropertiesChanged cbi =
6919                 networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED,
6920                 networkAgent);
6921         networkCallback.expectCallback(CallbackEntry.BLOCKED_STATUS, networkAgent);
6922         networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, networkAgent);
6923         networkCallback.assertNoCallback();
6924         checkDirectlyConnectedRoutes(cbi.getLp(), asList(myIpv4Address),
6925                 asList(myIpv4DefaultRoute));
6926         checkDirectlyConnectedRoutes(mCm.getLinkProperties(networkAgent.getNetwork()),
6927                 asList(myIpv4Address), asList(myIpv4DefaultRoute));
6928 
6929         // Verify direct routes are added during subsequent link properties updates.
6930         LinkProperties newLp = new LinkProperties(lp);
6931         LinkAddress myIpv6Address1 = new LinkAddress("fe80::cafe/64");
6932         LinkAddress myIpv6Address2 = new LinkAddress("2001:db8::2/64");
6933         newLp.addLinkAddress(myIpv6Address1);
6934         newLp.addLinkAddress(myIpv6Address2);
6935         networkAgent.sendLinkProperties(newLp);
6936         cbi = networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, networkAgent);
6937         networkCallback.assertNoCallback();
6938         checkDirectlyConnectedRoutes(cbi.getLp(),
6939                 asList(myIpv4Address, myIpv6Address1, myIpv6Address2),
6940                 asList(myIpv4DefaultRoute));
6941         mCm.unregisterNetworkCallback(networkCallback);
6942     }
6943 
6944     private void expectNotifyNetworkStatus(List<Network> defaultNetworks, String defaultIface,
6945             Integer vpnUid, String vpnIfname, List<String> underlyingIfaces) throws Exception {
6946         ArgumentCaptor<List<Network>> defaultNetworksCaptor = ArgumentCaptor.forClass(List.class);
6947         ArgumentCaptor<List<UnderlyingNetworkInfo>> vpnInfosCaptor =
6948                 ArgumentCaptor.forClass(List.class);
6949 
6950         verify(mStatsManager, atLeastOnce()).notifyNetworkStatus(defaultNetworksCaptor.capture(),
6951                 any(List.class), eq(defaultIface), vpnInfosCaptor.capture());
6952 
6953         assertSameElements(defaultNetworks, defaultNetworksCaptor.getValue());
6954 
6955         List<UnderlyingNetworkInfo> infos = vpnInfosCaptor.getValue();
6956         if (vpnUid != null) {
6957             assertEquals("Should have exactly one VPN:", 1, infos.size());
6958             UnderlyingNetworkInfo info = infos.get(0);
6959             assertEquals("Unexpected VPN owner:", (int) vpnUid, info.getOwnerUid());
6960             assertEquals("Unexpected VPN interface:", vpnIfname, info.getInterface());
6961             assertSameElements(underlyingIfaces, info.getUnderlyingInterfaces());
6962         } else {
6963             assertEquals(0, infos.size());
6964             return;
6965         }
6966     }
6967 
6968     private void expectNotifyNetworkStatus(
6969             List<Network> defaultNetworks, String defaultIface) throws Exception {
6970         expectNotifyNetworkStatus(defaultNetworks, defaultIface, null, null, List.of());
6971     }
6972 
6973     @Test
6974     public void testStatsIfacesChanged() throws Exception {
6975         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
6976         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
6977 
6978         final List<Network> onlyCell = List.of(mCellNetworkAgent.getNetwork());
6979         final List<Network> onlyWifi = List.of(mWiFiNetworkAgent.getNetwork());
6980 
6981         LinkProperties cellLp = new LinkProperties();
6982         cellLp.setInterfaceName(MOBILE_IFNAME);
6983         LinkProperties wifiLp = new LinkProperties();
6984         wifiLp.setInterfaceName(WIFI_IFNAME);
6985 
6986         // Simple connection should have updated ifaces
6987         mCellNetworkAgent.connect(false);
6988         mCellNetworkAgent.sendLinkProperties(cellLp);
6989         waitForIdle();
6990         expectNotifyNetworkStatus(onlyCell, MOBILE_IFNAME);
6991         reset(mStatsManager);
6992 
6993         // Default network switch should update ifaces.
6994         mWiFiNetworkAgent.connect(false);
6995         mWiFiNetworkAgent.sendLinkProperties(wifiLp);
6996         waitForIdle();
6997         assertEquals(wifiLp, mService.getActiveLinkProperties());
6998         expectNotifyNetworkStatus(onlyWifi, WIFI_IFNAME);
6999         reset(mStatsManager);
7000 
7001         // Disconnect should update ifaces.
7002         mWiFiNetworkAgent.disconnect();
7003         waitForIdle();
7004         expectNotifyNetworkStatus(onlyCell, MOBILE_IFNAME);
7005         reset(mStatsManager);
7006 
7007         // Metered change should update ifaces
7008         mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
7009         waitForIdle();
7010         expectNotifyNetworkStatus(onlyCell, MOBILE_IFNAME);
7011         reset(mStatsManager);
7012 
7013         mCellNetworkAgent.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
7014         waitForIdle();
7015         expectNotifyNetworkStatus(onlyCell, MOBILE_IFNAME);
7016         reset(mStatsManager);
7017 
7018         // Temp metered change shouldn't update ifaces
7019         mCellNetworkAgent.addCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED);
7020         waitForIdle();
7021         verify(mStatsManager, never()).notifyNetworkStatus(eq(onlyCell),
7022                 any(List.class), eq(MOBILE_IFNAME), any(List.class));
7023         reset(mStatsManager);
7024 
7025         // Roaming change should update ifaces
7026         mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING);
7027         waitForIdle();
7028         expectNotifyNetworkStatus(onlyCell, MOBILE_IFNAME);
7029         reset(mStatsManager);
7030 
7031         // Test VPNs.
7032         final LinkProperties lp = new LinkProperties();
7033         lp.setInterfaceName(VPN_IFNAME);
7034 
7035         mMockVpn.establishForMyUid(lp);
7036         assertUidRangesUpdatedForMyUid(true);
7037 
7038         final List<Network> cellAndVpn =
7039                 List.of(mCellNetworkAgent.getNetwork(), mMockVpn.getNetwork());
7040 
7041         // A VPN with default (null) underlying networks sets the underlying network's interfaces...
7042         expectNotifyNetworkStatus(cellAndVpn, MOBILE_IFNAME, Process.myUid(), VPN_IFNAME,
7043                 List.of(MOBILE_IFNAME));
7044 
7045         // ...and updates them as the default network switches.
7046         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
7047         mWiFiNetworkAgent.connect(false);
7048         mWiFiNetworkAgent.sendLinkProperties(wifiLp);
7049         final Network[] onlyNull = new Network[]{null};
7050         final List<Network> wifiAndVpn =
7051                 List.of(mWiFiNetworkAgent.getNetwork(), mMockVpn.getNetwork());
7052         final List<Network> cellAndWifi =
7053                 List.of(mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork());
7054         final Network[] cellNullAndWifi =
7055                 new Network[]{mCellNetworkAgent.getNetwork(), null, mWiFiNetworkAgent.getNetwork()};
7056 
7057         waitForIdle();
7058         assertEquals(wifiLp, mService.getActiveLinkProperties());
7059         expectNotifyNetworkStatus(wifiAndVpn, WIFI_IFNAME, Process.myUid(), VPN_IFNAME,
7060                 List.of(WIFI_IFNAME));
7061         reset(mStatsManager);
7062 
7063         // A VPN that sets its underlying networks passes the underlying interfaces, and influences
7064         // the default interface sent to NetworkStatsService by virtue of applying to the system
7065         // server UID (or, in this test, to the test's UID). This is the reason for sending
7066         // MOBILE_IFNAME even though the default network is wifi.
7067         // TODO: fix this to pass in the actual default network interface. Whether or not the VPN
7068         // applies to the system server UID should not have any bearing on network stats.
7069         mMockVpn.setUnderlyingNetworks(onlyCell.toArray(new Network[0]));
7070         waitForIdle();
7071         expectNotifyNetworkStatus(wifiAndVpn, MOBILE_IFNAME, Process.myUid(), VPN_IFNAME,
7072                 List.of(MOBILE_IFNAME));
7073         reset(mStatsManager);
7074 
7075         mMockVpn.setUnderlyingNetworks(cellAndWifi.toArray(new Network[0]));
7076         waitForIdle();
7077         expectNotifyNetworkStatus(wifiAndVpn, MOBILE_IFNAME, Process.myUid(), VPN_IFNAME,
7078                 List.of(MOBILE_IFNAME, WIFI_IFNAME));
7079         reset(mStatsManager);
7080 
7081         // Null underlying networks are ignored.
7082         mMockVpn.setUnderlyingNetworks(cellNullAndWifi);
7083         waitForIdle();
7084         expectNotifyNetworkStatus(wifiAndVpn, MOBILE_IFNAME, Process.myUid(), VPN_IFNAME,
7085                 List.of(MOBILE_IFNAME, WIFI_IFNAME));
7086         reset(mStatsManager);
7087 
7088         // If an underlying network disconnects, that interface should no longer be underlying.
7089         // This doesn't actually work because disconnectAndDestroyNetwork only notifies
7090         // NetworkStatsService before the underlying network is actually removed. So the underlying
7091         // network will only be removed if notifyIfacesChangedForNetworkStats is called again. This
7092         // could result in incorrect data usage measurements if the interface used by the
7093         // disconnected network is reused by a system component that does not register an agent for
7094         // it (e.g., tethering).
7095         mCellNetworkAgent.disconnect();
7096         waitForIdle();
7097         assertNull(mService.getLinkProperties(mCellNetworkAgent.getNetwork()));
7098         expectNotifyNetworkStatus(wifiAndVpn, MOBILE_IFNAME, Process.myUid(), VPN_IFNAME,
7099                 List.of(MOBILE_IFNAME, WIFI_IFNAME));
7100 
7101         // Confirm that we never tell NetworkStatsService that cell is no longer the underlying
7102         // network for the VPN...
7103         verify(mStatsManager, never()).notifyNetworkStatus(any(List.class),
7104                 any(List.class), any() /* anyString() doesn't match null */,
7105                 argThat(infos -> infos.get(0).getUnderlyingInterfaces().size() == 1
7106                         && WIFI_IFNAME.equals(infos.get(0).getUnderlyingInterfaces().get(0))));
7107         verifyNoMoreInteractions(mStatsManager);
7108         reset(mStatsManager);
7109 
7110         // ... but if something else happens that causes notifyIfacesChangedForNetworkStats to be
7111         // called again, it does. For example, connect Ethernet, but with a low score, such that it
7112         // does not become the default network.
7113         mEthernetNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
7114         mEthernetNetworkAgent.setScore(
7115                 new NetworkScore.Builder().setLegacyInt(30).setExiting(true).build());
7116         mEthernetNetworkAgent.connect(false);
7117         waitForIdle();
7118         verify(mStatsManager).notifyNetworkStatus(any(List.class),
7119                 any(List.class), any() /* anyString() doesn't match null */,
7120                 argThat(vpnInfos -> vpnInfos.get(0).getUnderlyingInterfaces().size() == 1
7121                         && WIFI_IFNAME.equals(vpnInfos.get(0).getUnderlyingInterfaces().get(0))));
7122         mEthernetNetworkAgent.disconnect();
7123         waitForIdle();
7124         reset(mStatsManager);
7125 
7126         // When a VPN declares no underlying networks (i.e., no connectivity), getAllVpnInfo
7127         // does not return the VPN, so CS does not pass it to NetworkStatsService. This causes
7128         // NetworkStatsFactory#adjustForTunAnd464Xlat not to attempt any VPN data migration, which
7129         // is probably a performance improvement (though it's very unlikely that a VPN would declare
7130         // no underlying networks).
7131         // Also, for the same reason as above, the active interface passed in is null.
7132         mMockVpn.setUnderlyingNetworks(new Network[0]);
7133         waitForIdle();
7134         expectNotifyNetworkStatus(wifiAndVpn, null);
7135         reset(mStatsManager);
7136 
7137         // Specifying only a null underlying network is the same as no networks.
7138         mMockVpn.setUnderlyingNetworks(onlyNull);
7139         waitForIdle();
7140         expectNotifyNetworkStatus(wifiAndVpn, null);
7141         reset(mStatsManager);
7142 
7143         // Specifying networks that are all disconnected is the same as specifying no networks.
7144         mMockVpn.setUnderlyingNetworks(onlyCell.toArray(new Network[0]));
7145         waitForIdle();
7146         expectNotifyNetworkStatus(wifiAndVpn, null);
7147         reset(mStatsManager);
7148 
7149         // Passing in null again means follow the default network again.
7150         mMockVpn.setUnderlyingNetworks(null);
7151         waitForIdle();
7152         expectNotifyNetworkStatus(wifiAndVpn, WIFI_IFNAME, Process.myUid(), VPN_IFNAME,
7153                 List.of(WIFI_IFNAME));
7154         reset(mStatsManager);
7155     }
7156 
7157     @Test
7158     public void testAdminUidsRedacted() throws Exception {
7159         final int[] adminUids = new int[] {Process.myUid() + 1};
7160         final NetworkCapabilities ncTemplate = new NetworkCapabilities();
7161         ncTemplate.setAdministratorUids(adminUids);
7162         mCellNetworkAgent =
7163                 new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, new LinkProperties(), ncTemplate);
7164         mCellNetworkAgent.connect(false /* validated */);
7165 
7166         // Verify case where caller has permission
7167         mServiceContext.setPermission(
7168                 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, PERMISSION_GRANTED);
7169         TestNetworkCallback callback = new TestNetworkCallback();
7170         mCm.registerDefaultNetworkCallback(callback);
7171         callback.expectCallback(CallbackEntry.AVAILABLE, mCellNetworkAgent);
7172         callback.expectCapabilitiesThat(
7173                 mCellNetworkAgent, nc -> Arrays.equals(adminUids, nc.getAdministratorUids()));
7174         mCm.unregisterNetworkCallback(callback);
7175 
7176         // Verify case where caller does NOT have permission
7177         mServiceContext.setPermission(
7178                 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, PERMISSION_DENIED);
7179         mServiceContext.setPermission(NETWORK_STACK, PERMISSION_DENIED);
7180         callback = new TestNetworkCallback();
7181         mCm.registerDefaultNetworkCallback(callback);
7182         callback.expectCallback(CallbackEntry.AVAILABLE, mCellNetworkAgent);
7183         callback.expectCapabilitiesThat(
7184                 mCellNetworkAgent, nc -> nc.getAdministratorUids().length == 0);
7185     }
7186 
7187     @Test
7188     public void testNonVpnUnderlyingNetworks() throws Exception {
7189         // Ensure wifi and cellular are not torn down.
7190         for (int transport : new int[]{TRANSPORT_CELLULAR, TRANSPORT_WIFI}) {
7191             final NetworkRequest request = new NetworkRequest.Builder()
7192                     .addTransportType(transport)
7193                     .removeCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
7194                     .build();
7195             mCm.requestNetwork(request, new NetworkCallback());
7196         }
7197 
7198         // Connect a VCN-managed wifi network.
7199         final LinkProperties wifiLp = new LinkProperties();
7200         wifiLp.setInterfaceName(WIFI_IFNAME);
7201         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp);
7202         mWiFiNetworkAgent.removeCapability(NET_CAPABILITY_NOT_VCN_MANAGED);
7203         mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
7204         mWiFiNetworkAgent.connect(true /* validated */);
7205 
7206         final List<Network> none = List.of();
7207         expectNotifyNetworkStatus(none, null);  // Wifi is not the default network
7208 
7209         // Create a virtual network based on the wifi network.
7210         final int ownerUid = 10042;
7211         NetworkCapabilities nc = new NetworkCapabilities.Builder()
7212                 .setOwnerUid(ownerUid)
7213                 .setAdministratorUids(new int[]{ownerUid})
7214                 .build();
7215         final String vcnIface = "ipsec42";
7216         final LinkProperties lp = new LinkProperties();
7217         lp.setInterfaceName(vcnIface);
7218         final TestNetworkAgentWrapper vcn = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, lp, nc);
7219         vcn.setUnderlyingNetworks(List.of(mWiFiNetworkAgent.getNetwork()));
7220         vcn.connect(false /* validated */);
7221 
7222         final TestNetworkCallback callback = new TestNetworkCallback();
7223         mCm.registerDefaultNetworkCallback(callback);
7224         callback.expectAvailableCallbacksUnvalidated(vcn);
7225 
7226         // The underlying wifi network's capabilities are not propagated to the virtual network,
7227         // but NetworkStatsService is informed of the underlying interface.
7228         nc = mCm.getNetworkCapabilities(vcn.getNetwork());
7229         assertFalse(nc.hasTransport(TRANSPORT_WIFI));
7230         assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED));
7231         final List<Network> onlyVcn = List.of(vcn.getNetwork());
7232         expectNotifyNetworkStatus(onlyVcn, vcnIface, ownerUid, vcnIface, List.of(WIFI_IFNAME));
7233 
7234         // Add NOT_METERED to the underlying network, check that it is not propagated.
7235         mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
7236         callback.assertNoCallback();
7237         nc = mCm.getNetworkCapabilities(vcn.getNetwork());
7238         assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED));
7239 
7240         // Switch underlying networks.
7241         final LinkProperties cellLp = new LinkProperties();
7242         cellLp.setInterfaceName(MOBILE_IFNAME);
7243         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
7244         mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_VCN_MANAGED);
7245         mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_ROAMING);
7246         mCellNetworkAgent.connect(false /* validated */);
7247         vcn.setUnderlyingNetworks(List.of(mCellNetworkAgent.getNetwork()));
7248 
7249         // The underlying capability changes do not propagate to the virtual network, but
7250         // NetworkStatsService is informed of the new underlying interface.
7251         callback.assertNoCallback();
7252         nc = mCm.getNetworkCapabilities(vcn.getNetwork());
7253         assertFalse(nc.hasTransport(TRANSPORT_WIFI));
7254         assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_ROAMING));
7255         expectNotifyNetworkStatus(onlyVcn, vcnIface, ownerUid, vcnIface, List.of(MOBILE_IFNAME));
7256     }
7257 
7258     @Test
7259     public void testBasicDnsConfigurationPushed() throws Exception {
7260         setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
7261 
7262         // Clear any interactions that occur as a result of CS starting up.
7263         reset(mMockDnsResolver);
7264 
7265         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
7266         waitForIdle();
7267         verify(mMockDnsResolver, never()).setResolverConfiguration(any());
7268         verifyNoMoreInteractions(mMockDnsResolver);
7269 
7270         final LinkProperties cellLp = new LinkProperties();
7271         cellLp.setInterfaceName(MOBILE_IFNAME);
7272         // Add IPv4 and IPv6 default routes, because DNS-over-TLS code does
7273         // "is-reachable" testing in order to not program netd with unreachable
7274         // nameservers that it might try repeated to validate.
7275         cellLp.addLinkAddress(new LinkAddress("192.0.2.4/24"));
7276         cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("192.0.2.4"),
7277                 MOBILE_IFNAME));
7278         cellLp.addLinkAddress(new LinkAddress("2001:db8:1::1/64"));
7279         cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("2001:db8:1::1"),
7280                 MOBILE_IFNAME));
7281         mCellNetworkAgent.sendLinkProperties(cellLp);
7282         mCellNetworkAgent.connect(false);
7283         waitForIdle();
7284 
7285         verify(mMockDnsResolver, times(1)).createNetworkCache(
7286                 eq(mCellNetworkAgent.getNetwork().netId));
7287         // CS tells dnsresolver about the empty DNS config for this network.
7288         verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(any());
7289         reset(mMockDnsResolver);
7290 
7291         cellLp.addDnsServer(InetAddress.getByName("2001:db8::1"));
7292         mCellNetworkAgent.sendLinkProperties(cellLp);
7293         waitForIdle();
7294         verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
7295                 mResolverParamsParcelCaptor.capture());
7296         ResolverParamsParcel resolvrParams = mResolverParamsParcelCaptor.getValue();
7297         assertEquals(1, resolvrParams.servers.length);
7298         assertTrue(CollectionUtils.contains(resolvrParams.servers, "2001:db8::1"));
7299         // Opportunistic mode.
7300         assertTrue(CollectionUtils.contains(resolvrParams.tlsServers, "2001:db8::1"));
7301         reset(mMockDnsResolver);
7302 
7303         cellLp.addDnsServer(InetAddress.getByName("192.0.2.1"));
7304         mCellNetworkAgent.sendLinkProperties(cellLp);
7305         waitForIdle();
7306         verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
7307                 mResolverParamsParcelCaptor.capture());
7308         resolvrParams = mResolverParamsParcelCaptor.getValue();
7309         assertEquals(2, resolvrParams.servers.length);
7310         assertTrue(new ArraySet<>(resolvrParams.servers).containsAll(
7311                 asList("2001:db8::1", "192.0.2.1")));
7312         // Opportunistic mode.
7313         assertEquals(2, resolvrParams.tlsServers.length);
7314         assertTrue(new ArraySet<>(resolvrParams.tlsServers).containsAll(
7315                 asList("2001:db8::1", "192.0.2.1")));
7316         reset(mMockDnsResolver);
7317 
7318         final String TLS_SPECIFIER = "tls.example.com";
7319         final String TLS_SERVER6 = "2001:db8:53::53";
7320         final InetAddress[] TLS_IPS = new InetAddress[]{ InetAddress.getByName(TLS_SERVER6) };
7321         final String[] TLS_SERVERS = new String[]{ TLS_SERVER6 };
7322         mCellNetworkAgent.mNmCallbacks.notifyPrivateDnsConfigResolved(
7323                 new PrivateDnsConfig(TLS_SPECIFIER, TLS_IPS).toParcel());
7324 
7325         waitForIdle();
7326         verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
7327                 mResolverParamsParcelCaptor.capture());
7328         resolvrParams = mResolverParamsParcelCaptor.getValue();
7329         assertEquals(2, resolvrParams.servers.length);
7330         assertTrue(new ArraySet<>(resolvrParams.servers).containsAll(
7331                 asList("2001:db8::1", "192.0.2.1")));
7332         reset(mMockDnsResolver);
7333     }
7334 
7335     @Test
7336     public void testDnsConfigurationTransTypesPushed() throws Exception {
7337         // Clear any interactions that occur as a result of CS starting up.
7338         reset(mMockDnsResolver);
7339 
7340         final NetworkRequest request = new NetworkRequest.Builder()
7341                 .clearCapabilities().addCapability(NET_CAPABILITY_INTERNET)
7342                 .build();
7343         final TestNetworkCallback callback = new TestNetworkCallback();
7344         mCm.registerNetworkCallback(request, callback);
7345 
7346         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
7347         mWiFiNetworkAgent.connect(false);
7348         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
7349         verify(mMockDnsResolver, times(1)).createNetworkCache(
7350                 eq(mWiFiNetworkAgent.getNetwork().netId));
7351         verify(mMockDnsResolver, times(2)).setResolverConfiguration(
7352                 mResolverParamsParcelCaptor.capture());
7353         final ResolverParamsParcel resolverParams = mResolverParamsParcelCaptor.getValue();
7354         assertContainsExactly(resolverParams.transportTypes, TRANSPORT_WIFI);
7355         reset(mMockDnsResolver);
7356     }
7357 
7358     @Test
7359     public void testPrivateDnsNotification() throws Exception {
7360         NetworkRequest request = new NetworkRequest.Builder()
7361                 .clearCapabilities().addCapability(NET_CAPABILITY_INTERNET)
7362                 .build();
7363         TestNetworkCallback callback = new TestNetworkCallback();
7364         mCm.registerNetworkCallback(request, callback);
7365         // Bring up wifi.
7366         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
7367         mWiFiNetworkAgent.connect(false);
7368         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
7369         // Private DNS resolution failed, checking if the notification will be shown or not.
7370         mWiFiNetworkAgent.setNetworkInvalid(true /* isStrictMode */);
7371         mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
7372         waitForIdle();
7373         // If network validation failed, NetworkMonitor will re-evaluate the network.
7374         // ConnectivityService should filter the redundant notification. This part is trying to
7375         // simulate that situation and check if ConnectivityService could filter that case.
7376         mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
7377         waitForIdle();
7378         verify(mNotificationManager, timeout(TIMEOUT_MS).times(1)).notify(anyString(),
7379                 eq(NotificationType.PRIVATE_DNS_BROKEN.eventId), any());
7380         // If private DNS resolution successful, the PRIVATE_DNS_BROKEN notification shouldn't be
7381         // shown.
7382         mWiFiNetworkAgent.setNetworkValid(true /* isStrictMode */);
7383         mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
7384         waitForIdle();
7385         verify(mNotificationManager, timeout(TIMEOUT_MS).times(1)).cancel(anyString(),
7386                 eq(NotificationType.PRIVATE_DNS_BROKEN.eventId));
7387         // If private DNS resolution failed again, the PRIVATE_DNS_BROKEN notification should be
7388         // shown again.
7389         mWiFiNetworkAgent.setNetworkInvalid(true /* isStrictMode */);
7390         mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
7391         waitForIdle();
7392         verify(mNotificationManager, timeout(TIMEOUT_MS).times(2)).notify(anyString(),
7393                 eq(NotificationType.PRIVATE_DNS_BROKEN.eventId), any());
7394     }
7395 
7396     @Test
7397     public void testPrivateDnsSettingsChange() throws Exception {
7398         // Clear any interactions that occur as a result of CS starting up.
7399         reset(mMockDnsResolver);
7400 
7401         // The default on Android is opportunistic mode ("Automatic").
7402         setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
7403 
7404         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
7405         final NetworkRequest cellRequest = new NetworkRequest.Builder()
7406                 .addTransportType(TRANSPORT_CELLULAR).build();
7407         mCm.requestNetwork(cellRequest, cellNetworkCallback);
7408 
7409         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
7410         waitForIdle();
7411         // CS tells netd about the empty DNS config for this network.
7412         verify(mMockDnsResolver, never()).setResolverConfiguration(any());
7413         verifyNoMoreInteractions(mMockDnsResolver);
7414 
7415         final LinkProperties cellLp = new LinkProperties();
7416         cellLp.setInterfaceName(MOBILE_IFNAME);
7417         // Add IPv4 and IPv6 default routes, because DNS-over-TLS code does
7418         // "is-reachable" testing in order to not program netd with unreachable
7419         // nameservers that it might try repeated to validate.
7420         cellLp.addLinkAddress(new LinkAddress("192.0.2.4/24"));
7421         cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("192.0.2.4"),
7422                 MOBILE_IFNAME));
7423         cellLp.addLinkAddress(new LinkAddress("2001:db8:1::1/64"));
7424         cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("2001:db8:1::1"),
7425                 MOBILE_IFNAME));
7426         cellLp.addDnsServer(InetAddress.getByName("2001:db8::1"));
7427         cellLp.addDnsServer(InetAddress.getByName("192.0.2.1"));
7428 
7429         mCellNetworkAgent.sendLinkProperties(cellLp);
7430         mCellNetworkAgent.connect(false);
7431         waitForIdle();
7432         verify(mMockDnsResolver, times(1)).createNetworkCache(
7433                 eq(mCellNetworkAgent.getNetwork().netId));
7434         verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
7435                 mResolverParamsParcelCaptor.capture());
7436         ResolverParamsParcel resolvrParams = mResolverParamsParcelCaptor.getValue();
7437         assertEquals(2, resolvrParams.tlsServers.length);
7438         assertTrue(new ArraySet<>(resolvrParams.tlsServers).containsAll(
7439                 asList("2001:db8::1", "192.0.2.1")));
7440         // Opportunistic mode.
7441         assertEquals(2, resolvrParams.tlsServers.length);
7442         assertTrue(new ArraySet<>(resolvrParams.tlsServers).containsAll(
7443                 asList("2001:db8::1", "192.0.2.1")));
7444         reset(mMockDnsResolver);
7445         cellNetworkCallback.expectCallback(CallbackEntry.AVAILABLE, mCellNetworkAgent);
7446         cellNetworkCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED,
7447                 mCellNetworkAgent);
7448         CallbackEntry.LinkPropertiesChanged cbi = cellNetworkCallback.expectCallback(
7449                 CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
7450         cellNetworkCallback.expectCallback(CallbackEntry.BLOCKED_STATUS, mCellNetworkAgent);
7451         cellNetworkCallback.assertNoCallback();
7452         assertFalse(cbi.getLp().isPrivateDnsActive());
7453         assertNull(cbi.getLp().getPrivateDnsServerName());
7454 
7455         setPrivateDnsSettings(PRIVATE_DNS_MODE_OFF, "ignored.example.com");
7456         verify(mMockDnsResolver, times(1)).setResolverConfiguration(
7457                 mResolverParamsParcelCaptor.capture());
7458         resolvrParams = mResolverParamsParcelCaptor.getValue();
7459         assertEquals(2, resolvrParams.servers.length);
7460         assertTrue(new ArraySet<>(resolvrParams.servers).containsAll(
7461                 asList("2001:db8::1", "192.0.2.1")));
7462         reset(mMockDnsResolver);
7463         cellNetworkCallback.assertNoCallback();
7464 
7465         setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
7466         verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
7467                 mResolverParamsParcelCaptor.capture());
7468         resolvrParams = mResolverParamsParcelCaptor.getValue();
7469         assertEquals(2, resolvrParams.servers.length);
7470         assertTrue(new ArraySet<>(resolvrParams.servers).containsAll(
7471                 asList("2001:db8::1", "192.0.2.1")));
7472         assertEquals(2, resolvrParams.tlsServers.length);
7473         assertTrue(new ArraySet<>(resolvrParams.tlsServers).containsAll(
7474                 asList("2001:db8::1", "192.0.2.1")));
7475         reset(mMockDnsResolver);
7476         cellNetworkCallback.assertNoCallback();
7477 
7478         setPrivateDnsSettings(PRIVATE_DNS_MODE_PROVIDER_HOSTNAME, "strict.example.com");
7479         // Can't test dns configuration for strict mode without properly mocking
7480         // out the DNS lookups, but can test that LinkProperties is updated.
7481         cbi = cellNetworkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED,
7482                 mCellNetworkAgent);
7483         cellNetworkCallback.assertNoCallback();
7484         assertTrue(cbi.getLp().isPrivateDnsActive());
7485         assertEquals("strict.example.com", cbi.getLp().getPrivateDnsServerName());
7486     }
7487 
7488     private PrivateDnsValidationEventParcel makePrivateDnsValidationEvent(
7489             final int netId, final String ipAddress, final String hostname, final int validation) {
7490         final PrivateDnsValidationEventParcel event = new PrivateDnsValidationEventParcel();
7491         event.netId = netId;
7492         event.ipAddress = ipAddress;
7493         event.hostname = hostname;
7494         event.validation = validation;
7495         return event;
7496     }
7497 
7498     @Test
7499     public void testLinkPropertiesWithPrivateDnsValidationEvents() throws Exception {
7500         // The default on Android is opportunistic mode ("Automatic").
7501         setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
7502 
7503         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
7504         final NetworkRequest cellRequest = new NetworkRequest.Builder()
7505                 .addTransportType(TRANSPORT_CELLULAR).build();
7506         mCm.requestNetwork(cellRequest, cellNetworkCallback);
7507 
7508         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
7509         waitForIdle();
7510         LinkProperties lp = new LinkProperties();
7511         mCellNetworkAgent.sendLinkProperties(lp);
7512         mCellNetworkAgent.connect(false);
7513         waitForIdle();
7514         cellNetworkCallback.expectCallback(CallbackEntry.AVAILABLE, mCellNetworkAgent);
7515         cellNetworkCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED,
7516                 mCellNetworkAgent);
7517         CallbackEntry.LinkPropertiesChanged cbi = cellNetworkCallback.expectCallback(
7518                 CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
7519         cellNetworkCallback.expectCallback(CallbackEntry.BLOCKED_STATUS, mCellNetworkAgent);
7520         cellNetworkCallback.assertNoCallback();
7521         assertFalse(cbi.getLp().isPrivateDnsActive());
7522         assertNull(cbi.getLp().getPrivateDnsServerName());
7523         Set<InetAddress> dnsServers = new HashSet<>();
7524         checkDnsServers(cbi.getLp(), dnsServers);
7525 
7526         // Send a validation event for a server that is not part of the current
7527         // resolver config. The validation event should be ignored.
7528         mService.mResolverUnsolEventCallback.onPrivateDnsValidationEvent(
7529                 makePrivateDnsValidationEvent(mCellNetworkAgent.getNetwork().netId, "",
7530                         "145.100.185.18", VALIDATION_RESULT_SUCCESS));
7531         cellNetworkCallback.assertNoCallback();
7532 
7533         // Add a dns server to the LinkProperties.
7534         LinkProperties lp2 = new LinkProperties(lp);
7535         lp2.addDnsServer(InetAddress.getByName("145.100.185.16"));
7536         mCellNetworkAgent.sendLinkProperties(lp2);
7537         cbi = cellNetworkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED,
7538                 mCellNetworkAgent);
7539         cellNetworkCallback.assertNoCallback();
7540         assertFalse(cbi.getLp().isPrivateDnsActive());
7541         assertNull(cbi.getLp().getPrivateDnsServerName());
7542         dnsServers.add(InetAddress.getByName("145.100.185.16"));
7543         checkDnsServers(cbi.getLp(), dnsServers);
7544 
7545         // Send a validation event containing a hostname that is not part of
7546         // the current resolver config. The validation event should be ignored.
7547         mService.mResolverUnsolEventCallback.onPrivateDnsValidationEvent(
7548                 makePrivateDnsValidationEvent(mCellNetworkAgent.getNetwork().netId,
7549                         "145.100.185.16", "hostname", VALIDATION_RESULT_SUCCESS));
7550         cellNetworkCallback.assertNoCallback();
7551 
7552         // Send a validation event where validation failed.
7553         mService.mResolverUnsolEventCallback.onPrivateDnsValidationEvent(
7554                 makePrivateDnsValidationEvent(mCellNetworkAgent.getNetwork().netId,
7555                         "145.100.185.16", "", VALIDATION_RESULT_FAILURE));
7556         cellNetworkCallback.assertNoCallback();
7557 
7558         // Send a validation event where validation succeeded for a server in
7559         // the current resolver config. A LinkProperties callback with updated
7560         // private dns fields should be sent.
7561         mService.mResolverUnsolEventCallback.onPrivateDnsValidationEvent(
7562                 makePrivateDnsValidationEvent(mCellNetworkAgent.getNetwork().netId,
7563                         "145.100.185.16", "", VALIDATION_RESULT_SUCCESS));
7564         cbi = cellNetworkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED,
7565                 mCellNetworkAgent);
7566         cellNetworkCallback.assertNoCallback();
7567         assertTrue(cbi.getLp().isPrivateDnsActive());
7568         assertNull(cbi.getLp().getPrivateDnsServerName());
7569         checkDnsServers(cbi.getLp(), dnsServers);
7570 
7571         // The private dns fields in LinkProperties should be preserved when
7572         // the network agent sends unrelated changes.
7573         LinkProperties lp3 = new LinkProperties(lp2);
7574         lp3.setMtu(1300);
7575         mCellNetworkAgent.sendLinkProperties(lp3);
7576         cbi = cellNetworkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED,
7577                 mCellNetworkAgent);
7578         cellNetworkCallback.assertNoCallback();
7579         assertTrue(cbi.getLp().isPrivateDnsActive());
7580         assertNull(cbi.getLp().getPrivateDnsServerName());
7581         checkDnsServers(cbi.getLp(), dnsServers);
7582         assertEquals(1300, cbi.getLp().getMtu());
7583 
7584         // Removing the only validated server should affect the private dns
7585         // fields in LinkProperties.
7586         LinkProperties lp4 = new LinkProperties(lp3);
7587         lp4.removeDnsServer(InetAddress.getByName("145.100.185.16"));
7588         mCellNetworkAgent.sendLinkProperties(lp4);
7589         cbi = cellNetworkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED,
7590                 mCellNetworkAgent);
7591         cellNetworkCallback.assertNoCallback();
7592         assertFalse(cbi.getLp().isPrivateDnsActive());
7593         assertNull(cbi.getLp().getPrivateDnsServerName());
7594         dnsServers.remove(InetAddress.getByName("145.100.185.16"));
7595         checkDnsServers(cbi.getLp(), dnsServers);
7596         assertEquals(1300, cbi.getLp().getMtu());
7597     }
7598 
7599     private void checkDirectlyConnectedRoutes(Object callbackObj,
7600             Collection<LinkAddress> linkAddresses, Collection<RouteInfo> otherRoutes) {
7601         assertTrue(callbackObj instanceof LinkProperties);
7602         LinkProperties lp = (LinkProperties) callbackObj;
7603 
7604         Set<RouteInfo> expectedRoutes = new ArraySet<>();
7605         expectedRoutes.addAll(otherRoutes);
7606         for (LinkAddress address : linkAddresses) {
7607             RouteInfo localRoute = new RouteInfo(address, null, lp.getInterfaceName());
7608             // Duplicates in linkAddresses are considered failures
7609             assertTrue(expectedRoutes.add(localRoute));
7610         }
7611         List<RouteInfo> observedRoutes = lp.getRoutes();
7612         assertEquals(expectedRoutes.size(), observedRoutes.size());
7613         assertTrue(observedRoutes.containsAll(expectedRoutes));
7614     }
7615 
7616     private static void checkDnsServers(Object callbackObj, Set<InetAddress> dnsServers) {
7617         assertTrue(callbackObj instanceof LinkProperties);
7618         LinkProperties lp = (LinkProperties) callbackObj;
7619         assertEquals(dnsServers.size(), lp.getDnsServers().size());
7620         assertTrue(lp.getDnsServers().containsAll(dnsServers));
7621     }
7622 
7623     @Test
7624     public void testApplyUnderlyingCapabilities() throws Exception {
7625         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
7626         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
7627         mCellNetworkAgent.connect(false /* validated */);
7628         mWiFiNetworkAgent.connect(false /* validated */);
7629 
7630         final NetworkCapabilities cellNc = new NetworkCapabilities()
7631                 .addTransportType(TRANSPORT_CELLULAR)
7632                 .addCapability(NET_CAPABILITY_INTERNET)
7633                 .addCapability(NET_CAPABILITY_NOT_CONGESTED)
7634                 .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
7635                 .setLinkDownstreamBandwidthKbps(10);
7636         final NetworkCapabilities wifiNc = new NetworkCapabilities()
7637                 .addTransportType(TRANSPORT_WIFI)
7638                 .addCapability(NET_CAPABILITY_INTERNET)
7639                 .addCapability(NET_CAPABILITY_NOT_METERED)
7640                 .addCapability(NET_CAPABILITY_NOT_ROAMING)
7641                 .addCapability(NET_CAPABILITY_NOT_CONGESTED)
7642                 .addCapability(NET_CAPABILITY_NOT_SUSPENDED)
7643                 .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
7644                 .setLinkUpstreamBandwidthKbps(20);
7645         mCellNetworkAgent.setNetworkCapabilities(cellNc, true /* sendToConnectivityService */);
7646         mWiFiNetworkAgent.setNetworkCapabilities(wifiNc, true /* sendToConnectivityService */);
7647         waitForIdle();
7648 
7649         final Network mobile = mCellNetworkAgent.getNetwork();
7650         final Network wifi = mWiFiNetworkAgent.getNetwork();
7651 
7652         final NetworkCapabilities initialCaps = new NetworkCapabilities();
7653         initialCaps.addTransportType(TRANSPORT_VPN);
7654         initialCaps.addCapability(NET_CAPABILITY_INTERNET);
7655         initialCaps.removeCapability(NET_CAPABILITY_NOT_VPN);
7656         final ArrayList<Network> emptyUnderlyingNetworks = new ArrayList<Network>();
7657         final ArrayList<Network> underlyingNetworksContainMobile = new ArrayList<Network>();
7658         underlyingNetworksContainMobile.add(mobile);
7659         final ArrayList<Network> underlyingNetworksContainWifi = new ArrayList<Network>();
7660         underlyingNetworksContainWifi.add(wifi);
7661         final ArrayList<Network> underlyingNetworksContainMobileAndMobile =
7662                 new ArrayList<Network>();
7663         underlyingNetworksContainMobileAndMobile.add(mobile);
7664         underlyingNetworksContainMobileAndMobile.add(wifi);
7665 
7666         final NetworkCapabilities withNoUnderlying = new NetworkCapabilities();
7667         withNoUnderlying.addCapability(NET_CAPABILITY_INTERNET);
7668         withNoUnderlying.addCapability(NET_CAPABILITY_NOT_CONGESTED);
7669         withNoUnderlying.addCapability(NET_CAPABILITY_NOT_ROAMING);
7670         withNoUnderlying.addCapability(NET_CAPABILITY_NOT_SUSPENDED);
7671         withNoUnderlying.addTransportType(TRANSPORT_VPN);
7672         withNoUnderlying.removeCapability(NET_CAPABILITY_NOT_VPN);
7673         withNoUnderlying.setUnderlyingNetworks(emptyUnderlyingNetworks);
7674 
7675         final NetworkCapabilities withMobileUnderlying = new NetworkCapabilities(withNoUnderlying);
7676         withMobileUnderlying.addTransportType(TRANSPORT_CELLULAR);
7677         withMobileUnderlying.removeCapability(NET_CAPABILITY_NOT_ROAMING);
7678         withMobileUnderlying.removeCapability(NET_CAPABILITY_NOT_SUSPENDED);
7679         withMobileUnderlying.setLinkDownstreamBandwidthKbps(10);
7680         withMobileUnderlying.setUnderlyingNetworks(underlyingNetworksContainMobile);
7681 
7682         final NetworkCapabilities withWifiUnderlying = new NetworkCapabilities(withNoUnderlying);
7683         withWifiUnderlying.addTransportType(TRANSPORT_WIFI);
7684         withWifiUnderlying.addCapability(NET_CAPABILITY_NOT_METERED);
7685         withWifiUnderlying.setLinkUpstreamBandwidthKbps(20);
7686         withWifiUnderlying.setUnderlyingNetworks(underlyingNetworksContainWifi);
7687 
7688         final NetworkCapabilities withWifiAndMobileUnderlying =
7689                 new NetworkCapabilities(withNoUnderlying);
7690         withWifiAndMobileUnderlying.addTransportType(TRANSPORT_CELLULAR);
7691         withWifiAndMobileUnderlying.addTransportType(TRANSPORT_WIFI);
7692         withWifiAndMobileUnderlying.removeCapability(NET_CAPABILITY_NOT_METERED);
7693         withWifiAndMobileUnderlying.removeCapability(NET_CAPABILITY_NOT_ROAMING);
7694         withWifiAndMobileUnderlying.setLinkDownstreamBandwidthKbps(10);
7695         withWifiAndMobileUnderlying.setLinkUpstreamBandwidthKbps(20);
7696         withWifiAndMobileUnderlying.setUnderlyingNetworks(underlyingNetworksContainMobileAndMobile);
7697 
7698         final NetworkCapabilities initialCapsNotMetered = new NetworkCapabilities(initialCaps);
7699         initialCapsNotMetered.addCapability(NET_CAPABILITY_NOT_METERED);
7700 
7701         NetworkCapabilities caps = new NetworkCapabilities(initialCaps);
7702         mService.applyUnderlyingCapabilities(new Network[]{}, initialCapsNotMetered, caps);
7703         assertEquals(withNoUnderlying, caps);
7704         assertEquals(0, new ArrayList<>(caps.getUnderlyingNetworks()).size());
7705 
7706         caps = new NetworkCapabilities(initialCaps);
7707         mService.applyUnderlyingCapabilities(new Network[]{null}, initialCapsNotMetered, caps);
7708         assertEquals(withNoUnderlying, caps);
7709         assertEquals(0, new ArrayList<>(caps.getUnderlyingNetworks()).size());
7710 
7711         caps = new NetworkCapabilities(initialCaps);
7712         mService.applyUnderlyingCapabilities(new Network[]{mobile}, initialCapsNotMetered, caps);
7713         assertEquals(withMobileUnderlying, caps);
7714         assertEquals(1, new ArrayList<>(caps.getUnderlyingNetworks()).size());
7715         assertEquals(mobile, new ArrayList<>(caps.getUnderlyingNetworks()).get(0));
7716 
7717         caps = new NetworkCapabilities(initialCaps);
7718         mService.applyUnderlyingCapabilities(new Network[]{wifi}, initialCapsNotMetered, caps);
7719         assertEquals(withWifiUnderlying, caps);
7720         assertEquals(1, new ArrayList<>(caps.getUnderlyingNetworks()).size());
7721         assertEquals(wifi, new ArrayList<>(caps.getUnderlyingNetworks()).get(0));
7722 
7723         withWifiUnderlying.removeCapability(NET_CAPABILITY_NOT_METERED);
7724         caps = new NetworkCapabilities(initialCaps);
7725         mService.applyUnderlyingCapabilities(new Network[]{wifi}, initialCaps, caps);
7726         assertEquals(withWifiUnderlying, caps);
7727         assertEquals(1, new ArrayList<>(caps.getUnderlyingNetworks()).size());
7728         assertEquals(wifi, new ArrayList<>(caps.getUnderlyingNetworks()).get(0));
7729 
7730         caps = new NetworkCapabilities(initialCaps);
7731         mService.applyUnderlyingCapabilities(new Network[]{mobile, wifi}, initialCaps, caps);
7732         assertEquals(withWifiAndMobileUnderlying, caps);
7733         assertEquals(2, new ArrayList<>(caps.getUnderlyingNetworks()).size());
7734         assertEquals(mobile, new ArrayList<>(caps.getUnderlyingNetworks()).get(0));
7735         assertEquals(wifi, new ArrayList<>(caps.getUnderlyingNetworks()).get(1));
7736 
7737         withWifiUnderlying.addCapability(NET_CAPABILITY_NOT_METERED);
7738         caps = new NetworkCapabilities(initialCaps);
7739         mService.applyUnderlyingCapabilities(new Network[]{null, mobile, null, wifi},
7740                 initialCapsNotMetered, caps);
7741         assertEquals(withWifiAndMobileUnderlying, caps);
7742         assertEquals(2, new ArrayList<>(caps.getUnderlyingNetworks()).size());
7743         assertEquals(mobile, new ArrayList<>(caps.getUnderlyingNetworks()).get(0));
7744         assertEquals(wifi, new ArrayList<>(caps.getUnderlyingNetworks()).get(1));
7745 
7746         caps = new NetworkCapabilities(initialCaps);
7747         mService.applyUnderlyingCapabilities(new Network[]{null, mobile, null, wifi},
7748                 initialCapsNotMetered, caps);
7749         assertEquals(withWifiAndMobileUnderlying, caps);
7750         assertEquals(2, new ArrayList<>(caps.getUnderlyingNetworks()).size());
7751         assertEquals(mobile, new ArrayList<>(caps.getUnderlyingNetworks()).get(0));
7752         assertEquals(wifi, new ArrayList<>(caps.getUnderlyingNetworks()).get(1));
7753 
7754         caps = new NetworkCapabilities(initialCaps);
7755         mService.applyUnderlyingCapabilities(null, initialCapsNotMetered, caps);
7756         assertEquals(withWifiUnderlying, caps);
7757         assertEquals(1, new ArrayList<>(caps.getUnderlyingNetworks()).size());
7758         assertEquals(wifi, new ArrayList<>(caps.getUnderlyingNetworks()).get(0));
7759     }
7760 
7761     @Test
7762     public void testVpnConnectDisconnectUnderlyingNetwork() throws Exception {
7763         final TestNetworkCallback callback = new TestNetworkCallback();
7764         final NetworkRequest request = new NetworkRequest.Builder()
7765                 .removeCapability(NET_CAPABILITY_NOT_VPN).build();
7766 
7767         runAsShell(NETWORK_SETTINGS, () -> {
7768             mCm.registerNetworkCallback(request, callback);
7769 
7770             // Bring up a VPN that specifies an underlying network that does not exist yet.
7771             // Note: it's sort of meaningless for a VPN app to declare a network that doesn't exist
7772             // yet, (and doing so is difficult without using reflection) but it's good to test that
7773             // the code behaves approximately correctly.
7774             mMockVpn.establishForMyUid(false, true, false);
7775             callback.expectAvailableCallbacksUnvalidated(mMockVpn);
7776             assertUidRangesUpdatedForMyUid(true);
7777             final Network wifiNetwork = new Network(mNetIdManager.peekNextNetId());
7778             mMockVpn.setUnderlyingNetworks(new Network[]{wifiNetwork});
7779             // onCapabilitiesChanged() should be called because
7780             // NetworkCapabilities#mUnderlyingNetworks is updated.
7781             CallbackEntry ce = callback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED,
7782                     mMockVpn);
7783             final NetworkCapabilities vpnNc1 = ((CallbackEntry.CapabilitiesChanged) ce).getCaps();
7784             // Since the wifi network hasn't brought up,
7785             // ConnectivityService#applyUnderlyingCapabilities cannot find it. Update
7786             // NetworkCapabilities#mUnderlyingNetworks to an empty array, and it will be updated to
7787             // the correct underlying networks once the wifi network brings up. But this case
7788             // shouldn't happen in reality since no one could get the network which hasn't brought
7789             // up. For the empty array of underlying networks, it should be happened for 2 cases,
7790             // the first one is that the VPN app declares an empty array for its underlying
7791             // networks, the second one is that the underlying networks are torn down.
7792             //
7793             // It shouldn't be null since the null value means the underlying networks of this
7794             // network should follow the default network.
7795             final ArrayList<Network> underlyingNetwork = new ArrayList<>();
7796             assertEquals(underlyingNetwork, vpnNc1.getUnderlyingNetworks());
7797             // Since the wifi network isn't exist, applyUnderlyingCapabilities()
7798             assertTrue(mCm.getNetworkCapabilities(mMockVpn.getNetwork())
7799                     .hasTransport(TRANSPORT_VPN));
7800             assertFalse(mCm.getNetworkCapabilities(mMockVpn.getNetwork())
7801                     .hasTransport(TRANSPORT_WIFI));
7802 
7803             // Make that underlying network connect, and expect to see its capabilities immediately
7804             // reflected in the VPN's capabilities.
7805             mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
7806             assertEquals(wifiNetwork, mWiFiNetworkAgent.getNetwork());
7807             mWiFiNetworkAgent.connect(false);
7808             // TODO: the callback for the VPN happens before any callbacks are called for the wifi
7809             // network that has just connected. There appear to be two issues here:
7810             // 1. The VPN code will accept an underlying network as soon as getNetworkCapabilities()
7811             //    for it returns non-null (which happens very early, during
7812             //    handleRegisterNetworkAgent).
7813             //    This is not correct because that that point the network is not connected and
7814             //    cannot pass any traffic.
7815             // 2. When a network connects, updateNetworkInfo propagates underlying network
7816             //    capabilities before rematching networks.
7817             // Given that this scenario can't really happen, this is probably fine for now.
7818             ce = callback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, mMockVpn);
7819             final NetworkCapabilities vpnNc2 = ((CallbackEntry.CapabilitiesChanged) ce).getCaps();
7820             // The wifi network is brought up, NetworkCapabilities#mUnderlyingNetworks is updated to
7821             // it.
7822             underlyingNetwork.add(wifiNetwork);
7823             assertEquals(underlyingNetwork, vpnNc2.getUnderlyingNetworks());
7824             callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
7825             assertTrue(mCm.getNetworkCapabilities(mMockVpn.getNetwork())
7826                     .hasTransport(TRANSPORT_VPN));
7827             assertTrue(mCm.getNetworkCapabilities(mMockVpn.getNetwork())
7828                     .hasTransport(TRANSPORT_WIFI));
7829 
7830             // Disconnect the network, and expect to see the VPN capabilities change accordingly.
7831             mWiFiNetworkAgent.disconnect();
7832             callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
7833             callback.expectCapabilitiesThat(mMockVpn, (nc) ->
7834                     nc.getTransportTypes().length == 1 && nc.hasTransport(TRANSPORT_VPN));
7835 
7836             mMockVpn.disconnect();
7837             mCm.unregisterNetworkCallback(callback);
7838         });
7839     }
7840 
7841     private void assertGetNetworkInfoOfGetActiveNetworkIsConnected(boolean expectedConnectivity) {
7842         // What Chromium used to do before https://chromium-review.googlesource.com/2605304
7843         assertEquals("Unexpected result for getActiveNetworkInfo(getActiveNetwork())",
7844                 expectedConnectivity, mCm.getNetworkInfo(mCm.getActiveNetwork()).isConnected());
7845     }
7846 
7847     @Test
7848     public void testVpnUnderlyingNetworkSuspended() throws Exception {
7849         final TestNetworkCallback callback = new TestNetworkCallback();
7850         mCm.registerDefaultNetworkCallback(callback);
7851 
7852         // Connect a VPN.
7853         mMockVpn.establishForMyUid(false /* validated */, true /* hasInternet */,
7854                 false /* isStrictMode */);
7855         callback.expectAvailableCallbacksUnvalidated(mMockVpn);
7856 
7857         // Connect cellular data.
7858         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
7859         mCellNetworkAgent.connect(false /* validated */);
7860         callback.expectCapabilitiesThat(mMockVpn,
7861                 nc -> nc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)
7862                         && nc.hasTransport(TRANSPORT_CELLULAR));
7863         callback.assertNoCallback();
7864 
7865         assertTrue(mCm.getNetworkCapabilities(mMockVpn.getNetwork())
7866                 .hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
7867         assertNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
7868         assertNetworkInfo(TYPE_WIFI, DetailedState.DISCONNECTED);
7869         assertNetworkInfo(TYPE_VPN, DetailedState.CONNECTED);
7870         assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
7871         assertGetNetworkInfoOfGetActiveNetworkIsConnected(true);
7872 
7873         // Suspend the cellular network and expect the VPN to be suspended.
7874         mCellNetworkAgent.suspend();
7875         callback.expectCapabilitiesThat(mMockVpn,
7876                 nc -> !nc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)
7877                         && nc.hasTransport(TRANSPORT_CELLULAR));
7878         callback.expectCallback(CallbackEntry.SUSPENDED, mMockVpn);
7879         callback.assertNoCallback();
7880 
7881         assertFalse(mCm.getNetworkCapabilities(mMockVpn.getNetwork())
7882                 .hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
7883         assertNetworkInfo(TYPE_MOBILE, DetailedState.SUSPENDED);
7884         assertNetworkInfo(TYPE_WIFI, DetailedState.DISCONNECTED);
7885         assertNetworkInfo(TYPE_VPN, DetailedState.SUSPENDED);
7886         assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.SUSPENDED);
7887         // VPN's main underlying network is suspended, so no connectivity.
7888         assertGetNetworkInfoOfGetActiveNetworkIsConnected(false);
7889 
7890         // Switch to another network. The VPN should no longer be suspended.
7891         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
7892         mWiFiNetworkAgent.connect(false /* validated */);
7893         callback.expectCapabilitiesThat(mMockVpn,
7894                 nc -> nc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)
7895                         && nc.hasTransport(TRANSPORT_WIFI));
7896         callback.expectCallback(CallbackEntry.RESUMED, mMockVpn);
7897         callback.assertNoCallback();
7898 
7899         assertTrue(mCm.getNetworkCapabilities(mMockVpn.getNetwork())
7900                 .hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
7901         assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED);
7902         assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
7903         assertNetworkInfo(TYPE_VPN, DetailedState.CONNECTED);
7904         assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
7905         assertGetNetworkInfoOfGetActiveNetworkIsConnected(true);
7906 
7907         // Unsuspend cellular and then switch back to it. The VPN remains not suspended.
7908         mCellNetworkAgent.resume();
7909         callback.assertNoCallback();
7910         mWiFiNetworkAgent.disconnect();
7911         callback.expectCapabilitiesThat(mMockVpn,
7912                 nc -> nc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)
7913                         && nc.hasTransport(TRANSPORT_CELLULAR));
7914         // Spurious double callback?
7915         callback.expectCapabilitiesThat(mMockVpn,
7916                 nc -> nc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)
7917                         && nc.hasTransport(TRANSPORT_CELLULAR));
7918         callback.assertNoCallback();
7919 
7920         assertTrue(mCm.getNetworkCapabilities(mMockVpn.getNetwork())
7921                 .hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
7922         assertNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
7923         assertNetworkInfo(TYPE_WIFI, DetailedState.DISCONNECTED);
7924         assertNetworkInfo(TYPE_VPN, DetailedState.CONNECTED);
7925         assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
7926         assertGetNetworkInfoOfGetActiveNetworkIsConnected(true);
7927 
7928         // Suspend cellular and expect no connectivity.
7929         mCellNetworkAgent.suspend();
7930         callback.expectCapabilitiesThat(mMockVpn,
7931                 nc -> !nc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)
7932                         && nc.hasTransport(TRANSPORT_CELLULAR));
7933         callback.expectCallback(CallbackEntry.SUSPENDED, mMockVpn);
7934         callback.assertNoCallback();
7935 
7936         assertFalse(mCm.getNetworkCapabilities(mMockVpn.getNetwork())
7937                 .hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
7938         assertNetworkInfo(TYPE_MOBILE, DetailedState.SUSPENDED);
7939         assertNetworkInfo(TYPE_WIFI, DetailedState.DISCONNECTED);
7940         assertNetworkInfo(TYPE_VPN, DetailedState.SUSPENDED);
7941         assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.SUSPENDED);
7942         assertGetNetworkInfoOfGetActiveNetworkIsConnected(false);
7943 
7944         // Resume cellular and expect that connectivity comes back.
7945         mCellNetworkAgent.resume();
7946         callback.expectCapabilitiesThat(mMockVpn,
7947                 nc -> nc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)
7948                         && nc.hasTransport(TRANSPORT_CELLULAR));
7949         callback.expectCallback(CallbackEntry.RESUMED, mMockVpn);
7950         callback.assertNoCallback();
7951 
7952         assertTrue(mCm.getNetworkCapabilities(mMockVpn.getNetwork())
7953                 .hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
7954         assertNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
7955         assertNetworkInfo(TYPE_WIFI, DetailedState.DISCONNECTED);
7956         assertNetworkInfo(TYPE_VPN, DetailedState.CONNECTED);
7957         assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
7958         assertGetNetworkInfoOfGetActiveNetworkIsConnected(true);
7959     }
7960 
7961     @Test
7962     public void testVpnNetworkActive() throws Exception {
7963         // NETWORK_SETTINGS is necessary to call registerSystemDefaultNetworkCallback.
7964         mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_GRANTED);
7965 
7966         final int uid = Process.myUid();
7967 
7968         final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback();
7969         final TestNetworkCallback genericNotVpnNetworkCallback = new TestNetworkCallback();
7970         final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
7971         final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
7972         final TestNetworkCallback defaultCallback = new TestNetworkCallback();
7973         final TestNetworkCallback systemDefaultCallback = new TestNetworkCallback();
7974         final NetworkRequest genericNotVpnRequest = new NetworkRequest.Builder().build();
7975         final NetworkRequest genericRequest = new NetworkRequest.Builder()
7976                 .removeCapability(NET_CAPABILITY_NOT_VPN).build();
7977         final NetworkRequest wifiRequest = new NetworkRequest.Builder()
7978                 .addTransportType(TRANSPORT_WIFI).build();
7979         final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder()
7980                 .removeCapability(NET_CAPABILITY_NOT_VPN)
7981                 .addTransportType(TRANSPORT_VPN).build();
7982         mCm.registerNetworkCallback(genericRequest, genericNetworkCallback);
7983         mCm.registerNetworkCallback(genericNotVpnRequest, genericNotVpnNetworkCallback);
7984         mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
7985         mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
7986         mCm.registerDefaultNetworkCallback(defaultCallback);
7987         mCm.registerSystemDefaultNetworkCallback(systemDefaultCallback,
7988                 new Handler(ConnectivityThread.getInstanceLooper()));
7989         defaultCallback.assertNoCallback();
7990 
7991         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
7992         mWiFiNetworkAgent.connect(false);
7993 
7994         genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
7995         genericNotVpnNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
7996         wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
7997         defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
7998         systemDefaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
7999         vpnNetworkCallback.assertNoCallback();
8000         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
8001 
8002         final Set<UidRange> ranges = uidRangesForUids(uid);
8003         mMockVpn.registerAgent(ranges);
8004         mMockVpn.setUnderlyingNetworks(new Network[0]);
8005 
8006         // VPN networks do not satisfy the default request and are automatically validated
8007         // by NetworkMonitor
8008         assertFalse(NetworkMonitorUtils.isValidationRequired(
8009                 NetworkAgentConfigShimImpl.newInstance(mMockVpn.getNetworkAgentConfig()),
8010                 mMockVpn.getAgent().getNetworkCapabilities()));
8011         mMockVpn.getAgent().setNetworkValid(false /* isStrictMode */);
8012 
8013         mMockVpn.connect(false);
8014 
8015         genericNetworkCallback.expectAvailableThenValidatedCallbacks(mMockVpn);
8016         genericNotVpnNetworkCallback.assertNoCallback();
8017         wifiNetworkCallback.assertNoCallback();
8018         vpnNetworkCallback.expectAvailableThenValidatedCallbacks(mMockVpn);
8019         defaultCallback.expectAvailableThenValidatedCallbacks(mMockVpn);
8020         systemDefaultCallback.assertNoCallback();
8021         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
8022         assertEquals(mWiFiNetworkAgent.getNetwork(),
8023                 systemDefaultCallback.getLastAvailableNetwork());
8024 
8025         ranges.clear();
8026         mMockVpn.setUids(ranges);
8027 
8028         genericNetworkCallback.expectCallback(CallbackEntry.LOST, mMockVpn);
8029         genericNotVpnNetworkCallback.assertNoCallback();
8030         wifiNetworkCallback.assertNoCallback();
8031         vpnNetworkCallback.expectCallback(CallbackEntry.LOST, mMockVpn);
8032 
8033         // TODO : The default network callback should actually get a LOST call here (also see the
8034         // comment below for AVAILABLE). This is because ConnectivityService does not look at UID
8035         // ranges at all when determining whether a network should be rematched. In practice, VPNs
8036         // can't currently update their UIDs without disconnecting, so this does not matter too
8037         // much, but that is the reason the test here has to check for an update to the
8038         // capabilities instead of the expected LOST then AVAILABLE.
8039         defaultCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, mMockVpn);
8040         systemDefaultCallback.assertNoCallback();
8041 
8042         ranges.add(new UidRange(uid, uid));
8043         mMockVpn.setUids(ranges);
8044 
8045         genericNetworkCallback.expectAvailableCallbacksValidated(mMockVpn);
8046         genericNotVpnNetworkCallback.assertNoCallback();
8047         wifiNetworkCallback.assertNoCallback();
8048         vpnNetworkCallback.expectAvailableCallbacksValidated(mMockVpn);
8049         // TODO : Here like above, AVAILABLE would be correct, but because this can't actually
8050         // happen outside of the test, ConnectivityService does not rematch callbacks.
8051         defaultCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, mMockVpn);
8052         systemDefaultCallback.assertNoCallback();
8053 
8054         mWiFiNetworkAgent.disconnect();
8055 
8056         genericNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
8057         genericNotVpnNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
8058         wifiNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
8059         vpnNetworkCallback.assertNoCallback();
8060         defaultCallback.assertNoCallback();
8061         systemDefaultCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
8062 
8063         mMockVpn.disconnect();
8064 
8065         genericNetworkCallback.expectCallback(CallbackEntry.LOST, mMockVpn);
8066         genericNotVpnNetworkCallback.assertNoCallback();
8067         wifiNetworkCallback.assertNoCallback();
8068         vpnNetworkCallback.expectCallback(CallbackEntry.LOST, mMockVpn);
8069         defaultCallback.expectCallback(CallbackEntry.LOST, mMockVpn);
8070         systemDefaultCallback.assertNoCallback();
8071         assertEquals(null, mCm.getActiveNetwork());
8072 
8073         mCm.unregisterNetworkCallback(genericNetworkCallback);
8074         mCm.unregisterNetworkCallback(wifiNetworkCallback);
8075         mCm.unregisterNetworkCallback(vpnNetworkCallback);
8076         mCm.unregisterNetworkCallback(defaultCallback);
8077         mCm.unregisterNetworkCallback(systemDefaultCallback);
8078     }
8079 
8080     @Test
8081     public void testVpnWithoutInternet() throws Exception {
8082         final int uid = Process.myUid();
8083 
8084         final TestNetworkCallback defaultCallback = new TestNetworkCallback();
8085         mCm.registerDefaultNetworkCallback(defaultCallback);
8086 
8087         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
8088         mWiFiNetworkAgent.connect(true);
8089 
8090         defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
8091         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
8092 
8093         mMockVpn.establishForMyUid(true /* validated */, false /* hasInternet */,
8094                 false /* isStrictMode */);
8095         assertUidRangesUpdatedForMyUid(true);
8096 
8097         defaultCallback.assertNoCallback();
8098         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
8099 
8100         mMockVpn.disconnect();
8101         defaultCallback.assertNoCallback();
8102 
8103         mCm.unregisterNetworkCallback(defaultCallback);
8104     }
8105 
8106     @Test
8107     public void testVpnWithInternet() throws Exception {
8108         final int uid = Process.myUid();
8109 
8110         final TestNetworkCallback defaultCallback = new TestNetworkCallback();
8111         mCm.registerDefaultNetworkCallback(defaultCallback);
8112 
8113         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
8114         mWiFiNetworkAgent.connect(true);
8115 
8116         defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
8117         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
8118 
8119         mMockVpn.establishForMyUid(true /* validated */, true /* hasInternet */,
8120                 false /* isStrictMode */);
8121         assertUidRangesUpdatedForMyUid(true);
8122 
8123         defaultCallback.expectAvailableThenValidatedCallbacks(mMockVpn);
8124         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
8125 
8126         mMockVpn.disconnect();
8127         defaultCallback.expectCallback(CallbackEntry.LOST, mMockVpn);
8128         defaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
8129 
8130         mCm.unregisterNetworkCallback(defaultCallback);
8131     }
8132 
8133     @Test
8134     public void testVpnUnvalidated() throws Exception {
8135         final TestNetworkCallback callback = new TestNetworkCallback();
8136         mCm.registerDefaultNetworkCallback(callback);
8137 
8138         // Bring up Ethernet.
8139         mEthernetNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
8140         mEthernetNetworkAgent.connect(true);
8141         callback.expectAvailableThenValidatedCallbacks(mEthernetNetworkAgent);
8142         callback.assertNoCallback();
8143 
8144         // Bring up a VPN that has the INTERNET capability, initially unvalidated.
8145         mMockVpn.establishForMyUid(false /* validated */, true /* hasInternet */,
8146                 false /* isStrictMode */);
8147         assertUidRangesUpdatedForMyUid(true);
8148 
8149         // Even though the VPN is unvalidated, it becomes the default network for our app.
8150         callback.expectAvailableCallbacksUnvalidated(mMockVpn);
8151         callback.assertNoCallback();
8152 
8153         assertEquals(mMockVpn.getNetwork(), mCm.getActiveNetwork());
8154 
8155         NetworkCapabilities nc = mCm.getNetworkCapabilities(mMockVpn.getNetwork());
8156         assertFalse(nc.hasCapability(NET_CAPABILITY_VALIDATED));
8157         assertTrue(nc.hasCapability(NET_CAPABILITY_INTERNET));
8158 
8159         assertFalse(NetworkMonitorUtils.isValidationRequired(
8160                 NetworkAgentConfigShimImpl.newInstance(mMockVpn.getNetworkAgentConfig()),
8161                 mMockVpn.getAgent().getNetworkCapabilities()));
8162         assertTrue(NetworkMonitorUtils.isPrivateDnsValidationRequired(
8163                 mMockVpn.getAgent().getNetworkCapabilities()));
8164 
8165         // Pretend that the VPN network validates.
8166         mMockVpn.getAgent().setNetworkValid(false /* isStrictMode */);
8167         mMockVpn.getAgent().mNetworkMonitor.forceReevaluation(Process.myUid());
8168         // Expect to see the validated capability, but no other changes, because the VPN is already
8169         // the default network for the app.
8170         callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mMockVpn);
8171         callback.assertNoCallback();
8172 
8173         mMockVpn.disconnect();
8174         callback.expectCallback(CallbackEntry.LOST, mMockVpn);
8175         callback.expectAvailableCallbacksValidated(mEthernetNetworkAgent);
8176     }
8177 
8178     @Test
8179     public void testVpnStartsWithUnderlyingCaps() throws Exception {
8180         final int uid = Process.myUid();
8181 
8182         final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
8183         final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder()
8184                 .removeCapability(NET_CAPABILITY_NOT_VPN)
8185                 .addTransportType(TRANSPORT_VPN)
8186                 .build();
8187         mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
8188         vpnNetworkCallback.assertNoCallback();
8189 
8190         // Connect cell. It will become the default network, and in the absence of setting
8191         // underlying networks explicitly it will become the sole underlying network for the vpn.
8192         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
8193         mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_SUSPENDED);
8194         mCellNetworkAgent.connect(true);
8195 
8196         mMockVpn.establishForMyUid(true /* validated */, false /* hasInternet */,
8197                 false /* isStrictMode */);
8198         assertUidRangesUpdatedForMyUid(true);
8199 
8200         vpnNetworkCallback.expectAvailableCallbacks(mMockVpn.getNetwork(),
8201                 false /* suspended */, false /* validated */, false /* blocked */, TIMEOUT_MS);
8202         vpnNetworkCallback.expectCapabilitiesThat(mMockVpn.getNetwork(), TIMEOUT_MS,
8203                 nc -> nc.hasCapability(NET_CAPABILITY_VALIDATED));
8204 
8205         final NetworkCapabilities nc = mCm.getNetworkCapabilities(mMockVpn.getNetwork());
8206         assertTrue(nc.hasTransport(TRANSPORT_VPN));
8207         assertTrue(nc.hasTransport(TRANSPORT_CELLULAR));
8208         assertFalse(nc.hasTransport(TRANSPORT_WIFI));
8209         assertTrue(nc.hasCapability(NET_CAPABILITY_VALIDATED));
8210         assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED));
8211         assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
8212 
8213         assertVpnTransportInfo(nc, VpnManager.TYPE_VPN_SERVICE);
8214     }
8215 
8216     private void assertDefaultNetworkCapabilities(int userId, NetworkAgentWrapper... networks) {
8217         final NetworkCapabilities[] defaultCaps = mService.getDefaultNetworkCapabilitiesForUser(
8218                 userId, "com.android.calling.package", "com.test");
8219         final String defaultCapsString = Arrays.toString(defaultCaps);
8220         assertEquals(defaultCapsString, defaultCaps.length, networks.length);
8221         final Set<NetworkCapabilities> defaultCapsSet = new ArraySet<>(defaultCaps);
8222         for (NetworkAgentWrapper network : networks) {
8223             final NetworkCapabilities nc = mCm.getNetworkCapabilities(network.getNetwork());
8224             final String msg = "Did not find " + nc + " in " + Arrays.toString(defaultCaps);
8225             assertTrue(msg, defaultCapsSet.contains(nc));
8226         }
8227     }
8228 
8229     @Test
8230     public void testVpnSetUnderlyingNetworks() throws Exception {
8231         final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
8232         final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder()
8233                 .removeCapability(NET_CAPABILITY_NOT_VPN)
8234                 .addTransportType(TRANSPORT_VPN)
8235                 .build();
8236         NetworkCapabilities nc;
8237         mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
8238         vpnNetworkCallback.assertNoCallback();
8239 
8240         mMockVpn.establishForMyUid(true /* validated */, false /* hasInternet */,
8241                 false /* isStrictMode */);
8242         assertUidRangesUpdatedForMyUid(true);
8243 
8244         vpnNetworkCallback.expectAvailableThenValidatedCallbacks(mMockVpn);
8245         nc = mCm.getNetworkCapabilities(mMockVpn.getNetwork());
8246         assertTrue(nc.hasTransport(TRANSPORT_VPN));
8247         assertFalse(nc.hasTransport(TRANSPORT_CELLULAR));
8248         assertFalse(nc.hasTransport(TRANSPORT_WIFI));
8249         // For safety reasons a VPN without underlying networks is considered metered.
8250         assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED));
8251         // A VPN without underlying networks is not suspended.
8252         assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
8253         assertVpnTransportInfo(nc, VpnManager.TYPE_VPN_SERVICE);
8254 
8255         final int userId = UserHandle.getUserId(Process.myUid());
8256         assertDefaultNetworkCapabilities(userId /* no networks */);
8257 
8258         // Connect cell and use it as an underlying network.
8259         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
8260         mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_SUSPENDED);
8261         mCellNetworkAgent.connect(true);
8262 
8263         mMockVpn.setUnderlyingNetworks(
8264                 new Network[] { mCellNetworkAgent.getNetwork() });
8265 
8266         vpnNetworkCallback.expectCapabilitiesThat(mMockVpn,
8267                 (caps) -> caps.hasTransport(TRANSPORT_VPN)
8268                 && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
8269                 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED)
8270                 && caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
8271         assertDefaultNetworkCapabilities(userId, mCellNetworkAgent);
8272 
8273         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
8274         mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
8275         mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_SUSPENDED);
8276         mWiFiNetworkAgent.connect(true);
8277 
8278         mMockVpn.setUnderlyingNetworks(
8279                 new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() });
8280 
8281         vpnNetworkCallback.expectCapabilitiesThat(mMockVpn,
8282                 (caps) -> caps.hasTransport(TRANSPORT_VPN)
8283                 && caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
8284                 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED)
8285                 && caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
8286         assertDefaultNetworkCapabilities(userId, mCellNetworkAgent, mWiFiNetworkAgent);
8287 
8288         // Don't disconnect, but note the VPN is not using wifi any more.
8289         mMockVpn.setUnderlyingNetworks(
8290                 new Network[] { mCellNetworkAgent.getNetwork() });
8291 
8292         vpnNetworkCallback.expectCapabilitiesThat(mMockVpn,
8293                 (caps) -> caps.hasTransport(TRANSPORT_VPN)
8294                 && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
8295                 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED)
8296                 && caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
8297         // The return value of getDefaultNetworkCapabilitiesForUser always includes the default
8298         // network (wifi) as well as the underlying networks (cell).
8299         assertDefaultNetworkCapabilities(userId, mCellNetworkAgent, mWiFiNetworkAgent);
8300 
8301         // Remove NOT_SUSPENDED from the only network and observe VPN is now suspended.
8302         mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_SUSPENDED);
8303         vpnNetworkCallback.expectCapabilitiesThat(mMockVpn,
8304                 (caps) -> caps.hasTransport(TRANSPORT_VPN)
8305                 && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
8306                 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED)
8307                 && !caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
8308         vpnNetworkCallback.expectCallback(CallbackEntry.SUSPENDED, mMockVpn);
8309 
8310         // Add NOT_SUSPENDED again and observe VPN is no longer suspended.
8311         mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_SUSPENDED);
8312         vpnNetworkCallback.expectCapabilitiesThat(mMockVpn,
8313                 (caps) -> caps.hasTransport(TRANSPORT_VPN)
8314                 && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
8315                 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED)
8316                 && caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
8317         vpnNetworkCallback.expectCallback(CallbackEntry.RESUMED, mMockVpn);
8318 
8319         // Use Wifi but not cell. Note the VPN is now unmetered and not suspended.
8320         mMockVpn.setUnderlyingNetworks(
8321                 new Network[] { mWiFiNetworkAgent.getNetwork() });
8322 
8323         vpnNetworkCallback.expectCapabilitiesThat(mMockVpn,
8324                 (caps) -> caps.hasTransport(TRANSPORT_VPN)
8325                 && !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
8326                 && caps.hasCapability(NET_CAPABILITY_NOT_METERED)
8327                 && caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
8328         assertDefaultNetworkCapabilities(userId, mWiFiNetworkAgent);
8329 
8330         // Use both again.
8331         mMockVpn.setUnderlyingNetworks(
8332                 new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() });
8333 
8334         vpnNetworkCallback.expectCapabilitiesThat(mMockVpn,
8335                 (caps) -> caps.hasTransport(TRANSPORT_VPN)
8336                 && caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
8337                 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED)
8338                 && caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
8339         assertDefaultNetworkCapabilities(userId, mCellNetworkAgent, mWiFiNetworkAgent);
8340 
8341         // Cell is suspended again. As WiFi is not, this should not cause a callback.
8342         mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_SUSPENDED);
8343         vpnNetworkCallback.assertNoCallback();
8344 
8345         // Stop using WiFi. The VPN is suspended again.
8346         mMockVpn.setUnderlyingNetworks(
8347                 new Network[] { mCellNetworkAgent.getNetwork() });
8348         vpnNetworkCallback.expectCapabilitiesThat(mMockVpn,
8349                 (caps) -> caps.hasTransport(TRANSPORT_VPN)
8350                 && caps.hasTransport(TRANSPORT_CELLULAR)
8351                 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED)
8352                 && !caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
8353         vpnNetworkCallback.expectCallback(CallbackEntry.SUSPENDED, mMockVpn);
8354         assertDefaultNetworkCapabilities(userId, mCellNetworkAgent, mWiFiNetworkAgent);
8355 
8356         // Use both again.
8357         mMockVpn.setUnderlyingNetworks(
8358                 new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() });
8359 
8360         vpnNetworkCallback.expectCapabilitiesThat(mMockVpn,
8361                 (caps) -> caps.hasTransport(TRANSPORT_VPN)
8362                 && caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
8363                 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED)
8364                 && caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
8365         vpnNetworkCallback.expectCallback(CallbackEntry.RESUMED, mMockVpn);
8366         assertDefaultNetworkCapabilities(userId, mCellNetworkAgent, mWiFiNetworkAgent);
8367 
8368         // Disconnect cell. Receive update without even removing the dead network from the
8369         // underlying networks – it's dead anyway. Not metered any more.
8370         mCellNetworkAgent.disconnect();
8371         vpnNetworkCallback.expectCapabilitiesThat(mMockVpn,
8372                 (caps) -> caps.hasTransport(TRANSPORT_VPN)
8373                 && !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
8374                 && caps.hasCapability(NET_CAPABILITY_NOT_METERED));
8375         assertDefaultNetworkCapabilities(userId, mWiFiNetworkAgent);
8376 
8377         // Disconnect wifi too. No underlying networks means this is now metered.
8378         mWiFiNetworkAgent.disconnect();
8379         vpnNetworkCallback.expectCapabilitiesThat(mMockVpn,
8380                 (caps) -> caps.hasTransport(TRANSPORT_VPN)
8381                 && !caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
8382                 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED));
8383         // When a network disconnects, the callbacks are fired before all state is updated, so for a
8384         // short time, synchronous calls will behave as if the network is still connected. Wait for
8385         // things to settle.
8386         waitForIdle();
8387         assertDefaultNetworkCapabilities(userId /* no networks */);
8388 
8389         mMockVpn.disconnect();
8390     }
8391 
8392     @Test
8393     public void testNullUnderlyingNetworks() throws Exception {
8394         final int uid = Process.myUid();
8395 
8396         final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
8397         final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder()
8398                 .removeCapability(NET_CAPABILITY_NOT_VPN)
8399                 .addTransportType(TRANSPORT_VPN)
8400                 .build();
8401         NetworkCapabilities nc;
8402         mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
8403         vpnNetworkCallback.assertNoCallback();
8404 
8405         mMockVpn.establishForMyUid(true /* validated */, false /* hasInternet */,
8406                 false /* isStrictMode */);
8407         assertUidRangesUpdatedForMyUid(true);
8408 
8409         vpnNetworkCallback.expectAvailableThenValidatedCallbacks(mMockVpn);
8410         nc = mCm.getNetworkCapabilities(mMockVpn.getNetwork());
8411         assertTrue(nc.hasTransport(TRANSPORT_VPN));
8412         assertFalse(nc.hasTransport(TRANSPORT_CELLULAR));
8413         assertFalse(nc.hasTransport(TRANSPORT_WIFI));
8414         // By default, VPN is set to track default network (i.e. its underlying networks is null).
8415         // In case of no default network, VPN is considered metered.
8416         assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED));
8417         assertVpnTransportInfo(nc, VpnManager.TYPE_VPN_SERVICE);
8418 
8419         // Connect to Cell; Cell is the default network.
8420         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
8421         mCellNetworkAgent.connect(true);
8422 
8423         vpnNetworkCallback.expectCapabilitiesThat(mMockVpn,
8424                 (caps) -> caps.hasTransport(TRANSPORT_VPN)
8425                 && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
8426                 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED));
8427 
8428         // Connect to WiFi; WiFi is the new default.
8429         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
8430         mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
8431         mWiFiNetworkAgent.connect(true);
8432 
8433         vpnNetworkCallback.expectCapabilitiesThat(mMockVpn,
8434                 (caps) -> caps.hasTransport(TRANSPORT_VPN)
8435                 && !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
8436                 && caps.hasCapability(NET_CAPABILITY_NOT_METERED));
8437 
8438         // Disconnect Cell. The default network did not change, so there shouldn't be any changes in
8439         // the capabilities.
8440         mCellNetworkAgent.disconnect();
8441 
8442         // Disconnect wifi too. Now we have no default network.
8443         mWiFiNetworkAgent.disconnect();
8444 
8445         vpnNetworkCallback.expectCapabilitiesThat(mMockVpn,
8446                 (caps) -> caps.hasTransport(TRANSPORT_VPN)
8447                 && !caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
8448                 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED));
8449 
8450         mMockVpn.disconnect();
8451     }
8452 
8453     @Test
8454     public void testRestrictedProfileAffectsVpnUidRanges() throws Exception {
8455         // NETWORK_SETTINGS is necessary to see the UID ranges in NetworkCapabilities.
8456         mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_GRANTED);
8457 
8458         final NetworkRequest request = new NetworkRequest.Builder()
8459                 .removeCapability(NET_CAPABILITY_NOT_VPN)
8460                 .build();
8461         final TestNetworkCallback callback = new TestNetworkCallback();
8462         mCm.registerNetworkCallback(request, callback);
8463 
8464         // Bring up a VPN
8465         mMockVpn.establishForMyUid();
8466         assertUidRangesUpdatedForMyUid(true);
8467         callback.expectAvailableThenValidatedCallbacks(mMockVpn);
8468         callback.assertNoCallback();
8469 
8470         final int uid = Process.myUid();
8471         NetworkCapabilities nc = mCm.getNetworkCapabilities(mMockVpn.getNetwork());
8472         assertNotNull("nc=" + nc, nc.getUids());
8473         assertEquals(nc.getUids(), UidRange.toIntRanges(uidRangesForUids(uid)));
8474         assertVpnTransportInfo(nc, VpnManager.TYPE_VPN_SERVICE);
8475 
8476         // Set an underlying network and expect to see the VPN transports change.
8477         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
8478         mWiFiNetworkAgent.connect(true);
8479         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
8480         callback.expectCapabilitiesThat(mMockVpn, (caps)
8481                 -> caps.hasTransport(TRANSPORT_VPN)
8482                 && caps.hasTransport(TRANSPORT_WIFI));
8483         callback.expectCapabilitiesThat(mWiFiNetworkAgent, (caps)
8484                 -> caps.hasCapability(NET_CAPABILITY_VALIDATED));
8485 
8486         doReturn(UserHandle.getUid(RESTRICTED_USER, VPN_UID)).when(mPackageManager)
8487                 .getPackageUidAsUser(ALWAYS_ON_PACKAGE, RESTRICTED_USER);
8488 
8489         final Intent addedIntent = new Intent(ACTION_USER_ADDED);
8490         addedIntent.putExtra(Intent.EXTRA_USER, UserHandle.of(RESTRICTED_USER));
8491         addedIntent.putExtra(Intent.EXTRA_USER_HANDLE, RESTRICTED_USER);
8492 
8493         // Send a USER_ADDED broadcast for it.
8494         processBroadcast(addedIntent);
8495 
8496         // Expect that the VPN UID ranges contain both |uid| and the UID range for the newly-added
8497         // restricted user.
8498         final UidRange rRange = UidRange.createForUser(UserHandle.of(RESTRICTED_USER));
8499         final Range<Integer> restrictUidRange = new Range<Integer>(rRange.start, rRange.stop);
8500         final Range<Integer> singleUidRange = new Range<Integer>(uid, uid);
8501         callback.expectCapabilitiesThat(mMockVpn, (caps)
8502                 -> caps.getUids().size() == 2
8503                 && caps.getUids().contains(singleUidRange)
8504                 && caps.getUids().contains(restrictUidRange)
8505                 && caps.hasTransport(TRANSPORT_VPN)
8506                 && caps.hasTransport(TRANSPORT_WIFI));
8507 
8508         // Change the VPN's capabilities somehow (specifically, disconnect wifi).
8509         mWiFiNetworkAgent.disconnect();
8510         callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
8511         callback.expectCapabilitiesThat(mMockVpn, (caps)
8512                 -> caps.getUids().size() == 2
8513                 && caps.getUids().contains(singleUidRange)
8514                 && caps.getUids().contains(restrictUidRange)
8515                 && caps.hasTransport(TRANSPORT_VPN)
8516                 && !caps.hasTransport(TRANSPORT_WIFI));
8517 
8518         // Send a USER_REMOVED broadcast and expect to lose the UID range for the restricted user.
8519         final Intent removedIntent = new Intent(ACTION_USER_REMOVED);
8520         removedIntent.putExtra(Intent.EXTRA_USER, UserHandle.of(RESTRICTED_USER));
8521         removedIntent.putExtra(Intent.EXTRA_USER_HANDLE, RESTRICTED_USER);
8522         processBroadcast(removedIntent);
8523 
8524         // Expect that the VPN gains the UID range for the restricted user, and that the capability
8525         // change made just before that (i.e., loss of TRANSPORT_WIFI) is preserved.
8526         callback.expectCapabilitiesThat(mMockVpn, (caps)
8527                 -> caps.getUids().size() == 1
8528                 && caps.getUids().contains(singleUidRange)
8529                 && caps.hasTransport(TRANSPORT_VPN)
8530                 && !caps.hasTransport(TRANSPORT_WIFI));
8531     }
8532 
8533     @Test
8534     public void testLockdownVpnWithRestrictedProfiles() throws Exception {
8535         // For ConnectivityService#setAlwaysOnVpnPackage.
8536         mServiceContext.setPermission(
8537                 Manifest.permission.CONTROL_ALWAYS_ON_VPN, PERMISSION_GRANTED);
8538         // For call Vpn#setAlwaysOnPackage.
8539         mServiceContext.setPermission(
8540                 Manifest.permission.CONTROL_VPN, PERMISSION_GRANTED);
8541         // Necessary to see the UID ranges in NetworkCapabilities.
8542         mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_GRANTED);
8543 
8544         final NetworkRequest request = new NetworkRequest.Builder()
8545                 .removeCapability(NET_CAPABILITY_NOT_VPN)
8546                 .build();
8547         final TestNetworkCallback callback = new TestNetworkCallback();
8548         mCm.registerNetworkCallback(request, callback);
8549 
8550         final int uid = Process.myUid();
8551 
8552         // Connect wifi and check that UIDs in the main and restricted profiles have network access.
8553         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
8554         mWiFiNetworkAgent.connect(true /* validated */);
8555         final int restrictedUid = UserHandle.getUid(RESTRICTED_USER, 42 /* appId */);
8556         assertNotNull(mCm.getActiveNetworkForUid(uid));
8557         assertNotNull(mCm.getActiveNetworkForUid(restrictedUid));
8558 
8559         // Enable always-on VPN lockdown. The main user loses network access because no VPN is up.
8560         final ArrayList<String> allowList = new ArrayList<>();
8561         mVpnManagerService.setAlwaysOnVpnPackage(PRIMARY_USER, ALWAYS_ON_PACKAGE,
8562                 true /* lockdown */, allowList);
8563         waitForIdle();
8564         assertNull(mCm.getActiveNetworkForUid(uid));
8565         // This is arguably overspecified: a UID that is not running doesn't have an active network.
8566         // But it's useful to check that non-default users do not lose network access, and to prove
8567         // that the loss of connectivity below is indeed due to the restricted profile coming up.
8568         assertNotNull(mCm.getActiveNetworkForUid(restrictedUid));
8569 
8570         // Start the restricted profile, and check that the UID within it loses network access.
8571         doReturn(UserHandle.getUid(RESTRICTED_USER, VPN_UID)).when(mPackageManager)
8572                 .getPackageUidAsUser(ALWAYS_ON_PACKAGE, RESTRICTED_USER);
8573         doReturn(asList(PRIMARY_USER_INFO, RESTRICTED_USER_INFO)).when(mUserManager)
8574                 .getAliveUsers();
8575         // TODO: check that VPN app within restricted profile still has access, etc.
8576         final Intent addedIntent = new Intent(ACTION_USER_ADDED);
8577         addedIntent.putExtra(Intent.EXTRA_USER, UserHandle.of(RESTRICTED_USER));
8578         addedIntent.putExtra(Intent.EXTRA_USER_HANDLE, RESTRICTED_USER);
8579         processBroadcast(addedIntent);
8580         assertNull(mCm.getActiveNetworkForUid(uid));
8581         assertNull(mCm.getActiveNetworkForUid(restrictedUid));
8582 
8583         // Stop the restricted profile, and check that the UID within it has network access again.
8584         doReturn(asList(PRIMARY_USER_INFO)).when(mUserManager).getAliveUsers();
8585 
8586         // Send a USER_REMOVED broadcast and expect to lose the UID range for the restricted user.
8587         final Intent removedIntent = new Intent(ACTION_USER_REMOVED);
8588         removedIntent.putExtra(Intent.EXTRA_USER, UserHandle.of(RESTRICTED_USER));
8589         removedIntent.putExtra(Intent.EXTRA_USER_HANDLE, RESTRICTED_USER);
8590         processBroadcast(removedIntent);
8591         assertNull(mCm.getActiveNetworkForUid(uid));
8592         assertNotNull(mCm.getActiveNetworkForUid(restrictedUid));
8593 
8594         mVpnManagerService.setAlwaysOnVpnPackage(PRIMARY_USER, null, false /* lockdown */,
8595                 allowList);
8596         waitForIdle();
8597     }
8598 
8599     @Test
8600     public void testIsActiveNetworkMeteredOverWifi() throws Exception {
8601         // Returns true by default when no network is available.
8602         assertTrue(mCm.isActiveNetworkMetered());
8603         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
8604         mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
8605         mWiFiNetworkAgent.connect(true);
8606         waitForIdle();
8607 
8608         assertFalse(mCm.isActiveNetworkMetered());
8609     }
8610 
8611     @Test
8612     public void testIsActiveNetworkMeteredOverCell() throws Exception {
8613         // Returns true by default when no network is available.
8614         assertTrue(mCm.isActiveNetworkMetered());
8615         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
8616         mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
8617         mCellNetworkAgent.connect(true);
8618         waitForIdle();
8619 
8620         assertTrue(mCm.isActiveNetworkMetered());
8621     }
8622 
8623     @Test
8624     public void testIsActiveNetworkMeteredOverVpnTrackingPlatformDefault() throws Exception {
8625         // Returns true by default when no network is available.
8626         assertTrue(mCm.isActiveNetworkMetered());
8627         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
8628         mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
8629         mCellNetworkAgent.connect(true);
8630         waitForIdle();
8631         assertTrue(mCm.isActiveNetworkMetered());
8632 
8633         // Connect VPN network. By default it is using current default network (Cell).
8634         mMockVpn.establishForMyUid();
8635         assertUidRangesUpdatedForMyUid(true);
8636 
8637         // Ensure VPN is now the active network.
8638         assertEquals(mMockVpn.getNetwork(), mCm.getActiveNetwork());
8639 
8640         // Expect VPN to be metered.
8641         assertTrue(mCm.isActiveNetworkMetered());
8642 
8643         // Connect WiFi.
8644         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
8645         mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
8646         mWiFiNetworkAgent.connect(true);
8647         waitForIdle();
8648         // VPN should still be the active network.
8649         assertEquals(mMockVpn.getNetwork(), mCm.getActiveNetwork());
8650 
8651         // Expect VPN to be unmetered as it should now be using WiFi (new default).
8652         assertFalse(mCm.isActiveNetworkMetered());
8653 
8654         // Disconnecting Cell should not affect VPN's meteredness.
8655         mCellNetworkAgent.disconnect();
8656         waitForIdle();
8657 
8658         assertFalse(mCm.isActiveNetworkMetered());
8659 
8660         // Disconnect WiFi; Now there is no platform default network.
8661         mWiFiNetworkAgent.disconnect();
8662         waitForIdle();
8663 
8664         // VPN without any underlying networks is treated as metered.
8665         assertTrue(mCm.isActiveNetworkMetered());
8666 
8667         mMockVpn.disconnect();
8668     }
8669 
8670     @Test
8671     public void testIsActiveNetworkMeteredOverVpnSpecifyingUnderlyingNetworks() throws Exception {
8672         // Returns true by default when no network is available.
8673         assertTrue(mCm.isActiveNetworkMetered());
8674         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
8675         mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
8676         mCellNetworkAgent.connect(true);
8677         waitForIdle();
8678         assertTrue(mCm.isActiveNetworkMetered());
8679 
8680         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
8681         mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
8682         mWiFiNetworkAgent.connect(true);
8683         waitForIdle();
8684         assertFalse(mCm.isActiveNetworkMetered());
8685 
8686         // Connect VPN network.
8687         mMockVpn.establishForMyUid();
8688         assertUidRangesUpdatedForMyUid(true);
8689 
8690         // Ensure VPN is now the active network.
8691         assertEquals(mMockVpn.getNetwork(), mCm.getActiveNetwork());
8692         // VPN is using Cell
8693         mMockVpn.setUnderlyingNetworks(
8694                 new Network[] { mCellNetworkAgent.getNetwork() });
8695         waitForIdle();
8696 
8697         // Expect VPN to be metered.
8698         assertTrue(mCm.isActiveNetworkMetered());
8699 
8700         // VPN is now using WiFi
8701         mMockVpn.setUnderlyingNetworks(
8702                 new Network[] { mWiFiNetworkAgent.getNetwork() });
8703         waitForIdle();
8704 
8705         // Expect VPN to be unmetered
8706         assertFalse(mCm.isActiveNetworkMetered());
8707 
8708         // VPN is using Cell | WiFi.
8709         mMockVpn.setUnderlyingNetworks(
8710                 new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() });
8711         waitForIdle();
8712 
8713         // Expect VPN to be metered.
8714         assertTrue(mCm.isActiveNetworkMetered());
8715 
8716         // VPN is using WiFi | Cell.
8717         mMockVpn.setUnderlyingNetworks(
8718                 new Network[] { mWiFiNetworkAgent.getNetwork(), mCellNetworkAgent.getNetwork() });
8719         waitForIdle();
8720 
8721         // Order should not matter and VPN should still be metered.
8722         assertTrue(mCm.isActiveNetworkMetered());
8723 
8724         // VPN is not using any underlying networks.
8725         mMockVpn.setUnderlyingNetworks(new Network[0]);
8726         waitForIdle();
8727 
8728         // VPN without underlying networks is treated as metered.
8729         assertTrue(mCm.isActiveNetworkMetered());
8730 
8731         mMockVpn.disconnect();
8732     }
8733 
8734     @Test
8735     public void testIsActiveNetworkMeteredOverAlwaysMeteredVpn() throws Exception {
8736         // Returns true by default when no network is available.
8737         assertTrue(mCm.isActiveNetworkMetered());
8738         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
8739         mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
8740         mWiFiNetworkAgent.connect(true);
8741         waitForIdle();
8742         assertFalse(mCm.isActiveNetworkMetered());
8743 
8744         // Connect VPN network.
8745         mMockVpn.registerAgent(true /* isAlwaysMetered */, uidRangesForUids(Process.myUid()),
8746                 new LinkProperties());
8747         mMockVpn.connect(true);
8748         waitForIdle();
8749         assertEquals(mMockVpn.getNetwork(), mCm.getActiveNetwork());
8750 
8751         // VPN is tracking current platform default (WiFi).
8752         mMockVpn.setUnderlyingNetworks(null);
8753         waitForIdle();
8754 
8755         // Despite VPN using WiFi (which is unmetered), VPN itself is marked as always metered.
8756         assertTrue(mCm.isActiveNetworkMetered());
8757 
8758 
8759         // VPN explicitly declares WiFi as its underlying network.
8760         mMockVpn.setUnderlyingNetworks(
8761                 new Network[] { mWiFiNetworkAgent.getNetwork() });
8762         waitForIdle();
8763 
8764         // Doesn't really matter whether VPN declares its underlying networks explicitly.
8765         assertTrue(mCm.isActiveNetworkMetered());
8766 
8767         // With WiFi lost, VPN is basically without any underlying networks. And in that case it is
8768         // anyways suppose to be metered.
8769         mWiFiNetworkAgent.disconnect();
8770         waitForIdle();
8771 
8772         assertTrue(mCm.isActiveNetworkMetered());
8773 
8774         mMockVpn.disconnect();
8775     }
8776 
8777     private class DetailedBlockedStatusCallback extends TestNetworkCallback {
8778         public void expectAvailableThenValidatedCallbacks(HasNetwork n, int blockedStatus) {
8779             super.expectAvailableThenValidatedCallbacks(n.getNetwork(), blockedStatus, TIMEOUT_MS);
8780         }
8781         public void expectBlockedStatusCallback(HasNetwork n, int blockedStatus) {
8782             // This doesn't work:
8783             // super.expectBlockedStatusCallback(blockedStatus, n.getNetwork());
8784             super.expectBlockedStatusCallback(blockedStatus, n.getNetwork(), TIMEOUT_MS);
8785         }
8786         public void onBlockedStatusChanged(Network network, int blockedReasons) {
8787             getHistory().add(new CallbackEntry.BlockedStatusInt(network, blockedReasons));
8788         }
8789     }
8790 
8791     @Test
8792     public void testNetworkBlockedStatus() throws Exception {
8793         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
8794         final NetworkRequest cellRequest = new NetworkRequest.Builder()
8795                 .addTransportType(TRANSPORT_CELLULAR)
8796                 .build();
8797         mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
8798         final DetailedBlockedStatusCallback detailedCallback = new DetailedBlockedStatusCallback();
8799         mCm.registerNetworkCallback(cellRequest, detailedCallback);
8800 
8801         mockUidNetworkingBlocked();
8802 
8803         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
8804         mCellNetworkAgent.connect(true);
8805         cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
8806         detailedCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent,
8807                 BLOCKED_REASON_NONE);
8808         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
8809         assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
8810         assertNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
8811         assertExtraInfoFromCmPresent(mCellNetworkAgent);
8812 
8813         setBlockedReasonChanged(BLOCKED_REASON_BATTERY_SAVER);
8814         cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
8815         detailedCallback.expectBlockedStatusCallback(mCellNetworkAgent,
8816                 BLOCKED_REASON_BATTERY_SAVER);
8817         assertNull(mCm.getActiveNetwork());
8818         assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
8819         assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
8820         assertExtraInfoFromCmBlocked(mCellNetworkAgent);
8821 
8822         // If blocked state does not change but blocked reason does, the boolean callback is called.
8823         // TODO: investigate de-duplicating.
8824         setBlockedReasonChanged(BLOCKED_METERED_REASON_USER_RESTRICTED);
8825         cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
8826         detailedCallback.expectBlockedStatusCallback(mCellNetworkAgent,
8827                 BLOCKED_METERED_REASON_USER_RESTRICTED);
8828 
8829         setBlockedReasonChanged(BLOCKED_REASON_NONE);
8830         cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
8831         detailedCallback.expectBlockedStatusCallback(mCellNetworkAgent, BLOCKED_REASON_NONE);
8832         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
8833         assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
8834         assertNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
8835         assertExtraInfoFromCmPresent(mCellNetworkAgent);
8836 
8837         setBlockedReasonChanged(BLOCKED_METERED_REASON_DATA_SAVER);
8838         cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
8839         detailedCallback.expectBlockedStatusCallback(mCellNetworkAgent,
8840                 BLOCKED_METERED_REASON_DATA_SAVER);
8841         assertNull(mCm.getActiveNetwork());
8842         assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
8843         assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
8844         assertExtraInfoFromCmBlocked(mCellNetworkAgent);
8845 
8846         // Restrict the network based on UID rule and NOT_METERED capability change.
8847         mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
8848         cellNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_NOT_METERED, mCellNetworkAgent);
8849         cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
8850         detailedCallback.expectCapabilitiesWith(NET_CAPABILITY_NOT_METERED, mCellNetworkAgent);
8851         detailedCallback.expectBlockedStatusCallback(mCellNetworkAgent, BLOCKED_REASON_NONE);
8852         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
8853         assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
8854         assertNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
8855         assertExtraInfoFromCmPresent(mCellNetworkAgent);
8856 
8857         mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
8858         cellNetworkCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_METERED,
8859                 mCellNetworkAgent);
8860         cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
8861         detailedCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_METERED,
8862                 mCellNetworkAgent);
8863         detailedCallback.expectBlockedStatusCallback(mCellNetworkAgent,
8864                 BLOCKED_METERED_REASON_DATA_SAVER);
8865         assertNull(mCm.getActiveNetwork());
8866         assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
8867         assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
8868         assertExtraInfoFromCmBlocked(mCellNetworkAgent);
8869 
8870         setBlockedReasonChanged(BLOCKED_REASON_NONE);
8871         cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
8872         detailedCallback.expectBlockedStatusCallback(mCellNetworkAgent, BLOCKED_REASON_NONE);
8873         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
8874         assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
8875         assertNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
8876         assertExtraInfoFromCmPresent(mCellNetworkAgent);
8877 
8878         setBlockedReasonChanged(BLOCKED_REASON_NONE);
8879         cellNetworkCallback.assertNoCallback();
8880         detailedCallback.assertNoCallback();
8881 
8882         // Restrict background data. Networking is not blocked because the network is unmetered.
8883         setBlockedReasonChanged(BLOCKED_METERED_REASON_DATA_SAVER);
8884         cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
8885         detailedCallback.expectBlockedStatusCallback(mCellNetworkAgent,
8886                 BLOCKED_METERED_REASON_DATA_SAVER);
8887         assertNull(mCm.getActiveNetwork());
8888         assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
8889         assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
8890         assertExtraInfoFromCmBlocked(mCellNetworkAgent);
8891         setBlockedReasonChanged(BLOCKED_METERED_REASON_DATA_SAVER);
8892         cellNetworkCallback.assertNoCallback();
8893 
8894         setBlockedReasonChanged(BLOCKED_REASON_NONE);
8895         cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
8896         detailedCallback.expectBlockedStatusCallback(mCellNetworkAgent, BLOCKED_REASON_NONE);
8897         assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
8898         assertNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
8899         assertExtraInfoFromCmPresent(mCellNetworkAgent);
8900 
8901         setBlockedReasonChanged(BLOCKED_REASON_NONE);
8902         cellNetworkCallback.assertNoCallback();
8903         detailedCallback.assertNoCallback();
8904         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
8905         assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
8906         assertNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
8907         assertExtraInfoFromCmPresent(mCellNetworkAgent);
8908 
8909         mCm.unregisterNetworkCallback(cellNetworkCallback);
8910     }
8911 
8912     @Test
8913     public void testNetworkBlockedStatusBeforeAndAfterConnect() throws Exception {
8914         final TestNetworkCallback defaultCallback = new TestNetworkCallback();
8915         mCm.registerDefaultNetworkCallback(defaultCallback);
8916         mockUidNetworkingBlocked();
8917 
8918         // No Networkcallbacks invoked before any network is active.
8919         setBlockedReasonChanged(BLOCKED_REASON_BATTERY_SAVER);
8920         setBlockedReasonChanged(BLOCKED_REASON_NONE);
8921         setBlockedReasonChanged(BLOCKED_METERED_REASON_DATA_SAVER);
8922         defaultCallback.assertNoCallback();
8923 
8924         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
8925         mCellNetworkAgent.connect(true);
8926         defaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mCellNetworkAgent);
8927         defaultCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mCellNetworkAgent);
8928 
8929         // Allow to use the network after switching to NOT_METERED network.
8930         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
8931         mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
8932         mWiFiNetworkAgent.connect(true);
8933         defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
8934 
8935         // Switch to METERED network. Restrict the use of the network.
8936         mWiFiNetworkAgent.disconnect();
8937         defaultCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
8938         defaultCallback.expectAvailableCallbacksValidatedAndBlocked(mCellNetworkAgent);
8939 
8940         // Network becomes NOT_METERED.
8941         mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
8942         defaultCallback.expectCapabilitiesWith(NET_CAPABILITY_NOT_METERED, mCellNetworkAgent);
8943         defaultCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
8944 
8945         // Verify there's no Networkcallbacks invoked after data saver on/off.
8946         setBlockedReasonChanged(BLOCKED_METERED_REASON_DATA_SAVER);
8947         setBlockedReasonChanged(BLOCKED_REASON_NONE);
8948         defaultCallback.assertNoCallback();
8949 
8950         mCellNetworkAgent.disconnect();
8951         defaultCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
8952         defaultCallback.assertNoCallback();
8953 
8954         mCm.unregisterNetworkCallback(defaultCallback);
8955     }
8956 
8957     private void expectNetworkRejectNonSecureVpn(InOrder inOrder, boolean add,
8958             UidRangeParcel... expected) throws Exception {
8959         inOrder.verify(mMockNetd).networkRejectNonSecureVpn(eq(add), aryEq(expected));
8960     }
8961 
8962     private void checkNetworkInfo(NetworkInfo ni, int type, DetailedState state) {
8963         assertNotNull(ni);
8964         assertEquals(type, ni.getType());
8965         assertEquals(ConnectivityManager.getNetworkTypeName(type), state, ni.getDetailedState());
8966         if (state == DetailedState.CONNECTED || state == DetailedState.SUSPENDED) {
8967             assertNotNull(ni.getExtraInfo());
8968         } else {
8969             // Technically speaking, a network that's in CONNECTING state will generally have a
8970             // non-null extraInfo. This doesn't actually happen in this test because it never calls
8971             // a legacy API while a network is connecting. When a network is in CONNECTING state
8972             // because of legacy lockdown VPN, its extraInfo is always null.
8973             assertNull(ni.getExtraInfo());
8974         }
8975     }
8976 
8977     private void assertActiveNetworkInfo(int type, DetailedState state) {
8978         checkNetworkInfo(mCm.getActiveNetworkInfo(), type, state);
8979     }
8980     private void assertNetworkInfo(int type, DetailedState state) {
8981         checkNetworkInfo(mCm.getNetworkInfo(type), type, state);
8982     }
8983 
8984     private void assertExtraInfoFromCm(TestNetworkAgentWrapper network, boolean present) {
8985         final NetworkInfo niForNetwork = mCm.getNetworkInfo(network.getNetwork());
8986         final NetworkInfo niForType = mCm.getNetworkInfo(network.getLegacyType());
8987         if (present) {
8988             assertEquals(network.getExtraInfo(), niForNetwork.getExtraInfo());
8989             assertEquals(network.getExtraInfo(), niForType.getExtraInfo());
8990         } else {
8991             assertNull(niForNetwork.getExtraInfo());
8992             assertNull(niForType.getExtraInfo());
8993         }
8994     }
8995 
8996     private void assertExtraInfoFromCmBlocked(TestNetworkAgentWrapper network) {
8997         assertExtraInfoFromCm(network, false);
8998     }
8999 
9000     private void assertExtraInfoFromCmPresent(TestNetworkAgentWrapper network) {
9001         assertExtraInfoFromCm(network, true);
9002     }
9003 
9004     // Checks that each of the |agents| receive a blocked status change callback with the specified
9005     // |blocked| value, in any order. This is needed because when an event affects multiple
9006     // networks, ConnectivityService does not guarantee the order in which callbacks are fired.
9007     private void assertBlockedCallbackInAnyOrder(TestNetworkCallback callback, boolean blocked,
9008             TestNetworkAgentWrapper... agents) {
9009         final List<Network> expectedNetworks = asList(agents).stream()
9010                 .map((agent) -> agent.getNetwork())
9011                 .collect(Collectors.toList());
9012 
9013         // Expect exactly one blocked callback for each agent.
9014         for (int i = 0; i < agents.length; i++) {
9015             CallbackEntry e = callback.expectCallbackThat(TIMEOUT_MS, (c) ->
9016                     c instanceof CallbackEntry.BlockedStatus
9017                             && ((CallbackEntry.BlockedStatus) c).getBlocked() == blocked);
9018             Network network = e.getNetwork();
9019             assertTrue("Received unexpected blocked callback for network " + network,
9020                     expectedNetworks.remove(network));
9021         }
9022     }
9023 
9024     @Test
9025     public void testNetworkBlockedStatusAlwaysOnVpn() throws Exception {
9026         mServiceContext.setPermission(
9027                 Manifest.permission.CONTROL_ALWAYS_ON_VPN, PERMISSION_GRANTED);
9028         mServiceContext.setPermission(
9029                 Manifest.permission.CONTROL_VPN, PERMISSION_GRANTED);
9030         mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_GRANTED);
9031 
9032         final TestNetworkCallback callback = new TestNetworkCallback();
9033         final NetworkRequest request = new NetworkRequest.Builder()
9034                 .removeCapability(NET_CAPABILITY_NOT_VPN)
9035                 .build();
9036         mCm.registerNetworkCallback(request, callback);
9037 
9038         final TestNetworkCallback defaultCallback = new TestNetworkCallback();
9039         mCm.registerDefaultNetworkCallback(defaultCallback);
9040 
9041         final TestNetworkCallback vpnUidCallback = new TestNetworkCallback();
9042         final NetworkRequest vpnUidRequest = new NetworkRequest.Builder().build();
9043         registerNetworkCallbackAsUid(vpnUidRequest, vpnUidCallback, VPN_UID);
9044 
9045         final TestNetworkCallback vpnUidDefaultCallback = new TestNetworkCallback();
9046         registerDefaultNetworkCallbackAsUid(vpnUidDefaultCallback, VPN_UID);
9047 
9048         final TestNetworkCallback vpnDefaultCallbackAsUid = new TestNetworkCallback();
9049         mCm.registerDefaultNetworkCallbackForUid(VPN_UID, vpnDefaultCallbackAsUid,
9050                 new Handler(ConnectivityThread.getInstanceLooper()));
9051 
9052         final int uid = Process.myUid();
9053         final int userId = UserHandle.getUserId(uid);
9054         final ArrayList<String> allowList = new ArrayList<>();
9055         mVpnManagerService.setAlwaysOnVpnPackage(userId, ALWAYS_ON_PACKAGE, true /* lockdown */,
9056                 allowList);
9057         waitForIdle();
9058 
9059         final Set<Integer> excludedUids = new ArraySet<Integer>();
9060         excludedUids.add(VPN_UID);
9061         if (SdkLevel.isAtLeastT()) {
9062             // On T onwards, the corresponding SDK sandbox UID should also be excluded
9063             excludedUids.add(toSdkSandboxUid(VPN_UID));
9064         }
9065         final UidRangeParcel[] uidRangeParcels = uidRangeParcelsExcludingUids(
9066                 excludedUids.toArray(new Integer[0]));
9067         InOrder inOrder = inOrder(mMockNetd);
9068         expectNetworkRejectNonSecureVpn(inOrder, true, uidRangeParcels);
9069 
9070         // Connect a network when lockdown is active, expect to see it blocked.
9071         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
9072         mWiFiNetworkAgent.connect(false /* validated */);
9073         callback.expectAvailableCallbacksUnvalidatedAndBlocked(mWiFiNetworkAgent);
9074         defaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mWiFiNetworkAgent);
9075         vpnUidCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
9076         vpnUidDefaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
9077         vpnDefaultCallbackAsUid.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
9078         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
9079         assertNull(mCm.getActiveNetwork());
9080         assertActiveNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED);
9081         // Mobile is BLOCKED even though it's not actually connected.
9082         assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
9083         assertNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED);
9084 
9085         // Disable lockdown, expect to see the network unblocked.
9086         mVpnManagerService.setAlwaysOnVpnPackage(userId, null, false /* lockdown */, allowList);
9087         callback.expectBlockedStatusCallback(false, mWiFiNetworkAgent);
9088         defaultCallback.expectBlockedStatusCallback(false, mWiFiNetworkAgent);
9089         vpnUidCallback.assertNoCallback();
9090         vpnUidDefaultCallback.assertNoCallback();
9091         vpnDefaultCallbackAsUid.assertNoCallback();
9092         expectNetworkRejectNonSecureVpn(inOrder, false, uidRangeParcels);
9093         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
9094         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
9095         assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
9096         assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED);
9097         assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
9098 
9099         // Add our UID to the allowlist and re-enable lockdown, expect network is not blocked.
9100         allowList.add(TEST_PACKAGE_NAME);
9101         mVpnManagerService.setAlwaysOnVpnPackage(userId, ALWAYS_ON_PACKAGE, true /* lockdown */,
9102                 allowList);
9103         callback.assertNoCallback();
9104         defaultCallback.assertNoCallback();
9105         vpnUidCallback.assertNoCallback();
9106         vpnUidDefaultCallback.assertNoCallback();
9107         vpnDefaultCallbackAsUid.assertNoCallback();
9108 
9109         excludedUids.add(uid);
9110         if (SdkLevel.isAtLeastT()) {
9111             // On T onwards, the corresponding SDK sandbox UID should also be excluded
9112             excludedUids.add(toSdkSandboxUid(uid));
9113         }
9114         final UidRangeParcel[] uidRangeParcelsAlsoExcludingUs = uidRangeParcelsExcludingUids(
9115                 excludedUids.toArray(new Integer[0]));
9116         expectNetworkRejectNonSecureVpn(inOrder, true, uidRangeParcelsAlsoExcludingUs);
9117         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
9118         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
9119         assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
9120         assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED);
9121         assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
9122 
9123         // Connect a new network, expect it to be unblocked.
9124         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
9125         mCellNetworkAgent.connect(false /* validated */);
9126         callback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
9127         defaultCallback.assertNoCallback();
9128         vpnUidCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
9129         vpnUidDefaultCallback.assertNoCallback();
9130         vpnDefaultCallbackAsUid.assertNoCallback();
9131         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
9132         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
9133         assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
9134         // Cellular is DISCONNECTED because it's not the default and there are no requests for it.
9135         assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED);
9136         assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
9137 
9138         // Disable lockdown, remove our UID from the allowlist, and re-enable lockdown.
9139         // Everything should now be blocked.
9140         mVpnManagerService.setAlwaysOnVpnPackage(userId, null, false /* lockdown */, allowList);
9141         waitForIdle();
9142         expectNetworkRejectNonSecureVpn(inOrder, false, uidRangeParcelsAlsoExcludingUs);
9143         allowList.clear();
9144         mVpnManagerService.setAlwaysOnVpnPackage(userId, ALWAYS_ON_PACKAGE, true /* lockdown */,
9145                 allowList);
9146         waitForIdle();
9147         expectNetworkRejectNonSecureVpn(inOrder, true, uidRangeParcels);
9148         defaultCallback.expectBlockedStatusCallback(true, mWiFiNetworkAgent);
9149         assertBlockedCallbackInAnyOrder(callback, true, mWiFiNetworkAgent, mCellNetworkAgent);
9150         vpnUidCallback.assertNoCallback();
9151         vpnUidDefaultCallback.assertNoCallback();
9152         vpnDefaultCallbackAsUid.assertNoCallback();
9153         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
9154         assertNull(mCm.getActiveNetwork());
9155         assertActiveNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED);
9156         assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
9157         assertNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED);
9158 
9159         // Disable lockdown. Everything is unblocked.
9160         mVpnManagerService.setAlwaysOnVpnPackage(userId, null, false /* lockdown */, allowList);
9161         defaultCallback.expectBlockedStatusCallback(false, mWiFiNetworkAgent);
9162         assertBlockedCallbackInAnyOrder(callback, false, mWiFiNetworkAgent, mCellNetworkAgent);
9163         vpnUidCallback.assertNoCallback();
9164         vpnUidDefaultCallback.assertNoCallback();
9165         vpnDefaultCallbackAsUid.assertNoCallback();
9166         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
9167         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
9168         assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
9169         assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED);
9170         assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
9171 
9172         // Enable and disable an always-on VPN package without lockdown. Expect no changes.
9173         reset(mMockNetd);
9174         mVpnManagerService.setAlwaysOnVpnPackage(userId, ALWAYS_ON_PACKAGE, false /* lockdown */,
9175                 allowList);
9176         inOrder.verify(mMockNetd, never()).networkRejectNonSecureVpn(anyBoolean(), any());
9177         callback.assertNoCallback();
9178         defaultCallback.assertNoCallback();
9179         vpnUidCallback.assertNoCallback();
9180         vpnUidDefaultCallback.assertNoCallback();
9181         vpnDefaultCallbackAsUid.assertNoCallback();
9182         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
9183         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
9184         assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
9185         assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED);
9186         assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
9187 
9188         mVpnManagerService.setAlwaysOnVpnPackage(userId, null, false /* lockdown */, allowList);
9189         inOrder.verify(mMockNetd, never()).networkRejectNonSecureVpn(anyBoolean(), any());
9190         callback.assertNoCallback();
9191         defaultCallback.assertNoCallback();
9192         vpnUidCallback.assertNoCallback();
9193         vpnUidDefaultCallback.assertNoCallback();
9194         vpnDefaultCallbackAsUid.assertNoCallback();
9195         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
9196         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
9197         assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
9198         assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED);
9199         assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
9200 
9201         // Enable lockdown and connect a VPN. The VPN is not blocked.
9202         mVpnManagerService.setAlwaysOnVpnPackage(userId, ALWAYS_ON_PACKAGE, true /* lockdown */,
9203                 allowList);
9204         defaultCallback.expectBlockedStatusCallback(true, mWiFiNetworkAgent);
9205         assertBlockedCallbackInAnyOrder(callback, true, mWiFiNetworkAgent, mCellNetworkAgent);
9206         vpnUidCallback.assertNoCallback();
9207         vpnUidDefaultCallback.assertNoCallback();
9208         vpnDefaultCallbackAsUid.assertNoCallback();
9209         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
9210         assertNull(mCm.getActiveNetwork());
9211         assertActiveNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED);
9212         assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
9213         assertNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED);
9214 
9215         mMockVpn.establishForMyUid();
9216         assertUidRangesUpdatedForMyUid(true);
9217         defaultCallback.expectAvailableThenValidatedCallbacks(mMockVpn);
9218         vpnUidCallback.assertNoCallback();  // vpnUidCallback has NOT_VPN capability.
9219         vpnUidDefaultCallback.assertNoCallback();  // VPN does not apply to VPN_UID
9220         vpnDefaultCallbackAsUid.assertNoCallback();
9221         assertEquals(mMockVpn.getNetwork(), mCm.getActiveNetwork());
9222         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
9223         assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
9224         assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED);
9225         assertNetworkInfo(TYPE_VPN, DetailedState.CONNECTED);
9226         assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
9227 
9228         mMockVpn.disconnect();
9229         defaultCallback.expectCallback(CallbackEntry.LOST, mMockVpn);
9230         defaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mWiFiNetworkAgent);
9231         vpnUidCallback.assertNoCallback();
9232         vpnUidDefaultCallback.assertNoCallback();
9233         vpnDefaultCallbackAsUid.assertNoCallback();
9234         assertNull(mCm.getActiveNetwork());
9235 
9236         mCm.unregisterNetworkCallback(callback);
9237         mCm.unregisterNetworkCallback(defaultCallback);
9238         mCm.unregisterNetworkCallback(vpnUidCallback);
9239         mCm.unregisterNetworkCallback(vpnUidDefaultCallback);
9240         mCm.unregisterNetworkCallback(vpnDefaultCallbackAsUid);
9241     }
9242 
9243     @Test
9244     public void testVpnExcludesOwnUid() throws Exception {
9245         // required for registerDefaultNetworkCallbackForUid.
9246         mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_GRANTED);
9247 
9248         // Connect Wi-Fi.
9249         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
9250         mWiFiNetworkAgent.connect(true /* validated */);
9251 
9252         // Connect a VPN that excludes its UID from its UID ranges.
9253         final LinkProperties lp = new LinkProperties();
9254         lp.setInterfaceName(VPN_IFNAME);
9255         final int myUid = Process.myUid();
9256         final Set<UidRange> ranges = new ArraySet<>();
9257         ranges.add(new UidRange(0, myUid - 1));
9258         ranges.add(new UidRange(myUid + 1, UserHandle.PER_USER_RANGE - 1));
9259         mMockVpn.setUnderlyingNetworks(new Network[]{mWiFiNetworkAgent.getNetwork()});
9260         mMockVpn.establish(lp, myUid, ranges);
9261 
9262         // Wait for validation before registering callbacks.
9263         waitForIdle();
9264 
9265         final int otherUid = myUid + 1;
9266         final Handler h = new Handler(ConnectivityThread.getInstanceLooper());
9267         final TestNetworkCallback otherUidCb = new TestNetworkCallback();
9268         final TestNetworkCallback defaultCb = new TestNetworkCallback();
9269         final TestNetworkCallback perUidCb = new TestNetworkCallback();
9270         registerDefaultNetworkCallbackAsUid(otherUidCb, otherUid);
9271         mCm.registerDefaultNetworkCallback(defaultCb, h);
9272         doAsUid(Process.SYSTEM_UID,
9273                 () -> mCm.registerDefaultNetworkCallbackForUid(myUid, perUidCb, h));
9274 
9275         otherUidCb.expectAvailableCallbacksValidated(mMockVpn);
9276         // BUG (b/195265065): the default network for the VPN app is actually Wi-Fi, not the VPN.
9277         defaultCb.expectAvailableCallbacksValidated(mMockVpn);
9278         perUidCb.expectAvailableCallbacksValidated(mMockVpn);
9279         // getActiveNetwork is not affected by this bug.
9280         assertEquals(mMockVpn.getNetwork(), mCm.getActiveNetworkForUid(myUid + 1));
9281         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
9282         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(myUid));
9283 
9284         doAsUid(otherUid, () -> mCm.unregisterNetworkCallback(otherUidCb));
9285         mCm.unregisterNetworkCallback(defaultCb);
9286         doAsUid(Process.SYSTEM_UID, () -> mCm.unregisterNetworkCallback(perUidCb));
9287     }
9288 
9289     private void setupLegacyLockdownVpn() {
9290         final String profileName = "testVpnProfile";
9291         final byte[] profileTag = profileName.getBytes(StandardCharsets.UTF_8);
9292         doReturn(profileTag).when(mVpnProfileStore).get(Credentials.LOCKDOWN_VPN);
9293 
9294         final VpnProfile profile = new VpnProfile(profileName);
9295         profile.name = "My VPN";
9296         profile.server = "192.0.2.1";
9297         profile.dnsServers = "8.8.8.8";
9298         profile.type = VpnProfile.TYPE_IPSEC_XAUTH_PSK;
9299         final byte[] encodedProfile = profile.encode();
9300         doReturn(encodedProfile).when(mVpnProfileStore).get(Credentials.VPN + profileName);
9301     }
9302 
9303     private void establishLegacyLockdownVpn(Network underlying) throws Exception {
9304         // The legacy lockdown VPN only supports userId 0, and must have an underlying network.
9305         assertNotNull(underlying);
9306         mMockVpn.setVpnType(VpnManager.TYPE_VPN_LEGACY);
9307         // The legacy lockdown VPN only supports userId 0.
9308         final Set<UidRange> ranges = Collections.singleton(PRIMARY_UIDRANGE);
9309         mMockVpn.registerAgent(ranges);
9310         mMockVpn.setUnderlyingNetworks(new Network[]{underlying});
9311         mMockVpn.connect(true);
9312     }
9313 
9314     @Test
9315     public void testLegacyLockdownVpn() throws Exception {
9316         mServiceContext.setPermission(
9317                 Manifest.permission.CONTROL_VPN, PERMISSION_GRANTED);
9318         // For LockdownVpnTracker to call registerSystemDefaultNetworkCallback.
9319         mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_GRANTED);
9320 
9321         final NetworkRequest request = new NetworkRequest.Builder().clearCapabilities().build();
9322         final TestNetworkCallback callback = new TestNetworkCallback();
9323         mCm.registerNetworkCallback(request, callback);
9324 
9325         final TestNetworkCallback defaultCallback = new TestNetworkCallback();
9326         mCm.registerDefaultNetworkCallback(defaultCallback);
9327 
9328         final TestNetworkCallback systemDefaultCallback = new TestNetworkCallback();
9329         mCm.registerSystemDefaultNetworkCallback(systemDefaultCallback,
9330                 new Handler(ConnectivityThread.getInstanceLooper()));
9331 
9332         // Pretend lockdown VPN was configured.
9333         setupLegacyLockdownVpn();
9334 
9335         // LockdownVpnTracker disables the Vpn teardown code and enables lockdown.
9336         // Check the VPN's state before it does so.
9337         assertTrue(mMockVpn.getEnableTeardown());
9338         assertFalse(mMockVpn.getLockdown());
9339 
9340         // Send a USER_UNLOCKED broadcast so CS starts LockdownVpnTracker.
9341         final int userId = UserHandle.getUserId(Process.myUid());
9342         final Intent addedIntent = new Intent(ACTION_USER_UNLOCKED);
9343         addedIntent.putExtra(Intent.EXTRA_USER, UserHandle.of(userId));
9344         addedIntent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
9345         processBroadcast(addedIntent);
9346 
9347         // Lockdown VPN disables teardown and enables lockdown.
9348         assertFalse(mMockVpn.getEnableTeardown());
9349         assertTrue(mMockVpn.getLockdown());
9350 
9351         // Bring up a network.
9352         // Expect nothing to happen because the network does not have an IPv4 default route: legacy
9353         // VPN only supports IPv4.
9354         final LinkProperties cellLp = new LinkProperties();
9355         cellLp.setInterfaceName("rmnet0");
9356         cellLp.addLinkAddress(new LinkAddress("2001:db8::1/64"));
9357         cellLp.addRoute(new RouteInfo(new IpPrefix("::/0"), null, "rmnet0"));
9358         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
9359         mCellNetworkAgent.connect(false /* validated */);
9360         callback.expectAvailableCallbacksUnvalidatedAndBlocked(mCellNetworkAgent);
9361         defaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mCellNetworkAgent);
9362         systemDefaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mCellNetworkAgent);
9363         waitForIdle();
9364         assertNull(mMockVpn.getAgent());
9365 
9366         // Add an IPv4 address. Ideally the VPN should start, but it doesn't because nothing calls
9367         // LockdownVpnTracker#handleStateChangedLocked. This is a bug.
9368         // TODO: consider fixing this.
9369         cellLp.addLinkAddress(new LinkAddress("192.0.2.2/25"));
9370         cellLp.addRoute(new RouteInfo(new IpPrefix("0.0.0.0/0"), null, "rmnet0"));
9371         mCellNetworkAgent.sendLinkProperties(cellLp);
9372         callback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
9373         defaultCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
9374         systemDefaultCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED,
9375                 mCellNetworkAgent);
9376         waitForIdle();
9377         assertNull(mMockVpn.getAgent());
9378 
9379         // Disconnect, then try again with a network that supports IPv4 at connection time.
9380         // Expect lockdown VPN to come up.
9381         ExpectedBroadcast b1 = expectConnectivityAction(TYPE_MOBILE, DetailedState.DISCONNECTED);
9382         mCellNetworkAgent.disconnect();
9383         callback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
9384         defaultCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
9385         systemDefaultCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
9386         b1.expectBroadcast();
9387 
9388         // When lockdown VPN is active, the NetworkInfo state in CONNECTIVITY_ACTION is overwritten
9389         // with the state of the VPN network. So expect a CONNECTING broadcast.
9390         b1 = expectConnectivityAction(TYPE_MOBILE, DetailedState.CONNECTING);
9391         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
9392         mCellNetworkAgent.connect(false /* validated */);
9393         callback.expectAvailableCallbacksUnvalidatedAndBlocked(mCellNetworkAgent);
9394         defaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mCellNetworkAgent);
9395         systemDefaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mCellNetworkAgent);
9396         b1.expectBroadcast();
9397         assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
9398         assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
9399         assertNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED);
9400         assertNetworkInfo(TYPE_VPN, DetailedState.BLOCKED);
9401         assertExtraInfoFromCmBlocked(mCellNetworkAgent);
9402 
9403         // TODO: it would be nice if we could simply rely on the production code here, and have
9404         // LockdownVpnTracker start the VPN, have the VPN code register its NetworkAgent with
9405         // ConnectivityService, etc. That would require duplicating a fair bit of code from the
9406         // Vpn tests around how to mock out LegacyVpnRunner. But even if we did that, this does not
9407         // work for at least two reasons:
9408         // 1. In this test, calling registerNetworkAgent does not actually result in an agent being
9409         //    registered. This is because nothing calls onNetworkMonitorCreated, which is what
9410         //    actually ends up causing handleRegisterNetworkAgent to be called. Code in this test
9411         //    that wants to register an agent must use TestNetworkAgentWrapper.
9412         // 2. Even if we exposed Vpn#agentConnect to the test, and made MockVpn#agentConnect call
9413         //    the TestNetworkAgentWrapper code, this would deadlock because the
9414         //    TestNetworkAgentWrapper code cannot be called on the handler thread since it calls
9415         //    waitForIdle().
9416         mMockVpn.expectStartLegacyVpnRunner();
9417         b1 = expectConnectivityAction(TYPE_VPN, DetailedState.CONNECTED);
9418         ExpectedBroadcast b2 = expectConnectivityAction(TYPE_MOBILE, DetailedState.CONNECTED);
9419         establishLegacyLockdownVpn(mCellNetworkAgent.getNetwork());
9420         callback.expectAvailableThenValidatedCallbacks(mMockVpn);
9421         defaultCallback.expectAvailableThenValidatedCallbacks(mMockVpn);
9422         systemDefaultCallback.assertNoCallback();
9423         NetworkCapabilities vpnNc = mCm.getNetworkCapabilities(mMockVpn.getNetwork());
9424         b1.expectBroadcast();
9425         b2.expectBroadcast();
9426         assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
9427         assertNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
9428         assertNetworkInfo(TYPE_WIFI, DetailedState.DISCONNECTED);
9429         assertNetworkInfo(TYPE_VPN, DetailedState.CONNECTED);
9430         assertExtraInfoFromCmPresent(mCellNetworkAgent);
9431         assertTrue(vpnNc.hasTransport(TRANSPORT_VPN));
9432         assertTrue(vpnNc.hasTransport(TRANSPORT_CELLULAR));
9433         assertFalse(vpnNc.hasTransport(TRANSPORT_WIFI));
9434         assertFalse(vpnNc.hasCapability(NET_CAPABILITY_NOT_METERED));
9435         assertVpnTransportInfo(vpnNc, VpnManager.TYPE_VPN_LEGACY);
9436 
9437         // Switch default network from cell to wifi. Expect VPN to disconnect and reconnect.
9438         final LinkProperties wifiLp = new LinkProperties();
9439         wifiLp.setInterfaceName("wlan0");
9440         wifiLp.addLinkAddress(new LinkAddress("192.0.2.163/25"));
9441         wifiLp.addRoute(new RouteInfo(new IpPrefix("0.0.0.0/0"), null, "wlan0"));
9442         final NetworkCapabilities wifiNc = new NetworkCapabilities();
9443         wifiNc.addTransportType(TRANSPORT_WIFI);
9444         wifiNc.addCapability(NET_CAPABILITY_NOT_METERED);
9445         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp, wifiNc);
9446 
9447         b1 = expectConnectivityAction(TYPE_MOBILE, DetailedState.DISCONNECTED);
9448         // Wifi is CONNECTING because the VPN isn't up yet.
9449         b2 = expectConnectivityAction(TYPE_WIFI, DetailedState.CONNECTING);
9450         ExpectedBroadcast b3 = expectConnectivityAction(TYPE_VPN, DetailedState.DISCONNECTED);
9451         mWiFiNetworkAgent.connect(false /* validated */);
9452         b1.expectBroadcast();
9453         b2.expectBroadcast();
9454         b3.expectBroadcast();
9455         mMockVpn.expectStopVpnRunnerPrivileged();
9456         mMockVpn.expectStartLegacyVpnRunner();
9457 
9458         // TODO: why is wifi not blocked? Is it because when this callback is sent, the VPN is still
9459         // connected, so the network is not considered blocked by the lockdown UID ranges? But the
9460         // fact that a VPN is connected should only result in the VPN itself being unblocked, not
9461         // any other network. Bug in isUidBlockedByVpn?
9462         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
9463         callback.expectCallback(CallbackEntry.LOST, mMockVpn);
9464         defaultCallback.expectCallback(CallbackEntry.LOST, mMockVpn);
9465         defaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mWiFiNetworkAgent);
9466         systemDefaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
9467 
9468         // While the VPN is reconnecting on the new network, everything is blocked.
9469         assertActiveNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED);
9470         assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
9471         assertNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED);
9472         assertNetworkInfo(TYPE_VPN, DetailedState.BLOCKED);
9473         assertExtraInfoFromCmBlocked(mWiFiNetworkAgent);
9474 
9475         // The VPN comes up again on wifi.
9476         b1 = expectConnectivityAction(TYPE_VPN, DetailedState.CONNECTED);
9477         b2 = expectConnectivityAction(TYPE_WIFI, DetailedState.CONNECTED);
9478         establishLegacyLockdownVpn(mWiFiNetworkAgent.getNetwork());
9479         callback.expectAvailableThenValidatedCallbacks(mMockVpn);
9480         defaultCallback.expectAvailableThenValidatedCallbacks(mMockVpn);
9481         systemDefaultCallback.assertNoCallback();
9482         b1.expectBroadcast();
9483         b2.expectBroadcast();
9484         assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
9485         assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED);
9486         assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
9487         assertNetworkInfo(TYPE_VPN, DetailedState.CONNECTED);
9488         assertExtraInfoFromCmPresent(mWiFiNetworkAgent);
9489         vpnNc = mCm.getNetworkCapabilities(mMockVpn.getNetwork());
9490         assertTrue(vpnNc.hasTransport(TRANSPORT_VPN));
9491         assertTrue(vpnNc.hasTransport(TRANSPORT_WIFI));
9492         assertFalse(vpnNc.hasTransport(TRANSPORT_CELLULAR));
9493         assertTrue(vpnNc.hasCapability(NET_CAPABILITY_NOT_METERED));
9494 
9495         // Disconnect cell. Nothing much happens since it's not the default network.
9496         mCellNetworkAgent.disconnect();
9497         callback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
9498         defaultCallback.assertNoCallback();
9499         systemDefaultCallback.assertNoCallback();
9500 
9501         assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
9502         assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED);
9503         assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
9504         assertNetworkInfo(TYPE_VPN, DetailedState.CONNECTED);
9505         assertExtraInfoFromCmPresent(mWiFiNetworkAgent);
9506 
9507         b1 = expectConnectivityAction(TYPE_WIFI, DetailedState.DISCONNECTED);
9508         b2 = expectConnectivityAction(TYPE_VPN, DetailedState.DISCONNECTED);
9509         mWiFiNetworkAgent.disconnect();
9510         callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
9511         systemDefaultCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
9512         b1.expectBroadcast();
9513         callback.expectCapabilitiesThat(mMockVpn, nc -> !nc.hasTransport(TRANSPORT_WIFI));
9514         mMockVpn.expectStopVpnRunnerPrivileged();
9515         callback.expectCallback(CallbackEntry.LOST, mMockVpn);
9516         b2.expectBroadcast();
9517     }
9518 
9519     @Test
9520     public void testLockdownSetFirewallUidRule() throws Exception {
9521         // For ConnectivityService#setAlwaysOnVpnPackage.
9522         mServiceContext.setPermission(
9523                 Manifest.permission.CONTROL_ALWAYS_ON_VPN, PERMISSION_GRANTED);
9524         // Needed to call Vpn#setAlwaysOnPackage.
9525         mServiceContext.setPermission(Manifest.permission.CONTROL_VPN, PERMISSION_GRANTED);
9526         // Needed to call Vpn#isAlwaysOnPackageSupported.
9527         mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_GRANTED);
9528 
9529         // Enable Lockdown
9530         final ArrayList<String> allowList = new ArrayList<>();
9531         mVpnManagerService.setAlwaysOnVpnPackage(PRIMARY_USER, ALWAYS_ON_PACKAGE,
9532                 true /* lockdown */, allowList);
9533         waitForIdle();
9534 
9535         // Lockdown rule is set to apps uids
9536         verify(mBpfNetMaps).setUidRule(
9537                 eq(FIREWALL_CHAIN_LOCKDOWN_VPN), eq(APP1_UID), eq(FIREWALL_RULE_DENY));
9538         verify(mBpfNetMaps).setUidRule(
9539                 eq(FIREWALL_CHAIN_LOCKDOWN_VPN), eq(APP2_UID), eq(FIREWALL_RULE_DENY));
9540 
9541         reset(mBpfNetMaps);
9542 
9543         // Disable lockdown
9544         mVpnManagerService.setAlwaysOnVpnPackage(PRIMARY_USER, null, false /* lockdown */,
9545                 allowList);
9546         waitForIdle();
9547 
9548         // Lockdown rule is removed from apps uids
9549         verify(mBpfNetMaps).setUidRule(
9550                 eq(FIREWALL_CHAIN_LOCKDOWN_VPN), eq(APP1_UID), eq(FIREWALL_RULE_ALLOW));
9551         verify(mBpfNetMaps).setUidRule(
9552                 eq(FIREWALL_CHAIN_LOCKDOWN_VPN), eq(APP2_UID), eq(FIREWALL_RULE_ALLOW));
9553 
9554         // Interface rules are not changed by Lockdown mode enable/disable
9555         verify(mBpfNetMaps, never()).addUidInterfaceRules(any(), any());
9556         verify(mBpfNetMaps, never()).removeUidInterfaceRules(any());
9557     }
9558 
9559     private void doTestSetUidFirewallRule(final int chain, final int defaultRule) {
9560         final int uid = 1001;
9561         mCm.setUidFirewallRule(chain, uid, FIREWALL_RULE_ALLOW);
9562         verify(mBpfNetMaps).setUidRule(chain, uid, FIREWALL_RULE_ALLOW);
9563         reset(mBpfNetMaps);
9564 
9565         mCm.setUidFirewallRule(chain, uid, FIREWALL_RULE_DENY);
9566         verify(mBpfNetMaps).setUidRule(chain, uid, FIREWALL_RULE_DENY);
9567         reset(mBpfNetMaps);
9568 
9569         mCm.setUidFirewallRule(chain, uid, FIREWALL_RULE_DEFAULT);
9570         verify(mBpfNetMaps).setUidRule(chain, uid, defaultRule);
9571         reset(mBpfNetMaps);
9572     }
9573 
9574     @Test @IgnoreUpTo(SC_V2)
9575     public void testSetUidFirewallRule() throws Exception {
9576         doTestSetUidFirewallRule(FIREWALL_CHAIN_DOZABLE, FIREWALL_RULE_DENY);
9577         doTestSetUidFirewallRule(FIREWALL_CHAIN_STANDBY, FIREWALL_RULE_ALLOW);
9578         doTestSetUidFirewallRule(FIREWALL_CHAIN_POWERSAVE, FIREWALL_RULE_DENY);
9579         doTestSetUidFirewallRule(FIREWALL_CHAIN_RESTRICTED, FIREWALL_RULE_DENY);
9580         doTestSetUidFirewallRule(FIREWALL_CHAIN_LOW_POWER_STANDBY, FIREWALL_RULE_DENY);
9581         doTestSetUidFirewallRule(FIREWALL_CHAIN_OEM_DENY_1, FIREWALL_RULE_ALLOW);
9582         doTestSetUidFirewallRule(FIREWALL_CHAIN_OEM_DENY_2, FIREWALL_RULE_ALLOW);
9583         doTestSetUidFirewallRule(FIREWALL_CHAIN_OEM_DENY_3, FIREWALL_RULE_ALLOW);
9584     }
9585 
9586     @Test @IgnoreUpTo(SC_V2)
9587     public void testSetFirewallChainEnabled() throws Exception {
9588         final List<Integer> firewallChains = Arrays.asList(
9589                 FIREWALL_CHAIN_DOZABLE,
9590                 FIREWALL_CHAIN_STANDBY,
9591                 FIREWALL_CHAIN_POWERSAVE,
9592                 FIREWALL_CHAIN_RESTRICTED,
9593                 FIREWALL_CHAIN_LOW_POWER_STANDBY,
9594                 FIREWALL_CHAIN_OEM_DENY_1,
9595                 FIREWALL_CHAIN_OEM_DENY_2,
9596                 FIREWALL_CHAIN_OEM_DENY_3);
9597         for (final int chain: firewallChains) {
9598             mCm.setFirewallChainEnabled(chain, true /* enabled */);
9599             verify(mBpfNetMaps).setChildChain(chain, true /* enable */);
9600             reset(mBpfNetMaps);
9601 
9602             mCm.setFirewallChainEnabled(chain, false /* enabled */);
9603             verify(mBpfNetMaps).setChildChain(chain, false /* enable */);
9604             reset(mBpfNetMaps);
9605         }
9606     }
9607 
9608     private void doTestReplaceFirewallChain(final int chain, final String chainName,
9609             final boolean allowList) {
9610         final int[] uids = new int[] {1001, 1002};
9611         mCm.replaceFirewallChain(chain, uids);
9612         verify(mBpfNetMaps).replaceUidChain(chainName, allowList, uids);
9613         reset(mBpfNetMaps);
9614     }
9615 
9616     @Test @IgnoreUpTo(SC_V2)
9617     public void testReplaceFirewallChain() {
9618         doTestReplaceFirewallChain(FIREWALL_CHAIN_DOZABLE, "fw_dozable", true);
9619         doTestReplaceFirewallChain(FIREWALL_CHAIN_STANDBY, "fw_standby", false);
9620         doTestReplaceFirewallChain(FIREWALL_CHAIN_POWERSAVE, "fw_powersave",  true);
9621         doTestReplaceFirewallChain(FIREWALL_CHAIN_RESTRICTED, "fw_restricted", true);
9622         doTestReplaceFirewallChain(FIREWALL_CHAIN_LOW_POWER_STANDBY, "fw_low_power_standby", true);
9623         doTestReplaceFirewallChain(FIREWALL_CHAIN_OEM_DENY_1, "fw_oem_deny_1", false);
9624         doTestReplaceFirewallChain(FIREWALL_CHAIN_OEM_DENY_2, "fw_oem_deny_2", false);
9625         doTestReplaceFirewallChain(FIREWALL_CHAIN_OEM_DENY_3, "fw_oem_deny_3", false);
9626     }
9627 
9628     @Test @IgnoreUpTo(SC_V2)
9629     public void testInvalidFirewallChain() throws Exception {
9630         final int uid = 1001;
9631         final Class<IllegalArgumentException> expected = IllegalArgumentException.class;
9632         assertThrows(expected,
9633                 () -> mCm.setUidFirewallRule(-1 /* chain */, uid, FIREWALL_RULE_ALLOW));
9634         assertThrows(expected,
9635                 () -> mCm.setUidFirewallRule(100 /* chain */, uid, FIREWALL_RULE_ALLOW));
9636         assertThrows(expected, () -> mCm.replaceFirewallChain(-1 /* chain */, new int[]{uid}));
9637         assertThrows(expected, () -> mCm.replaceFirewallChain(100 /* chain */, new int[]{uid}));
9638     }
9639 
9640     @Test @IgnoreUpTo(SC_V2)
9641     public void testInvalidFirewallRule() throws Exception {
9642         final Class<IllegalArgumentException> expected = IllegalArgumentException.class;
9643         assertThrows(expected,
9644                 () -> mCm.setUidFirewallRule(FIREWALL_CHAIN_DOZABLE,
9645                         1001 /* uid */, -1 /* rule */));
9646         assertThrows(expected,
9647                 () -> mCm.setUidFirewallRule(FIREWALL_CHAIN_DOZABLE,
9648                         1001 /* uid */, 100 /* rule */));
9649     }
9650 
9651     /**
9652      * Test mutable and requestable network capabilities such as
9653      * {@link NetworkCapabilities#NET_CAPABILITY_TRUSTED} and
9654      * {@link NetworkCapabilities#NET_CAPABILITY_NOT_VCN_MANAGED}. Verify that the
9655      * {@code ConnectivityService} re-assign the networks accordingly.
9656      */
9657     @Test
9658     public final void testLoseMutableAndRequestableCaps() throws Exception {
9659         final int[] testCaps = new int [] {
9660                 NET_CAPABILITY_TRUSTED,
9661                 NET_CAPABILITY_NOT_VCN_MANAGED
9662         };
9663         for (final int testCap : testCaps) {
9664             // Create requests with and without the testing capability.
9665             final TestNetworkCallback callbackWithCap = new TestNetworkCallback();
9666             final TestNetworkCallback callbackWithoutCap = new TestNetworkCallback();
9667             mCm.requestNetwork(new NetworkRequest.Builder().addCapability(testCap).build(),
9668                     callbackWithCap);
9669             mCm.requestNetwork(new NetworkRequest.Builder().removeCapability(testCap).build(),
9670                     callbackWithoutCap);
9671 
9672             // Setup networks with testing capability and verify the default network changes.
9673             mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
9674             mCellNetworkAgent.addCapability(testCap);
9675             mCellNetworkAgent.connect(true);
9676             callbackWithCap.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
9677             callbackWithoutCap.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
9678             verify(mMockNetd).networkSetDefault(eq(mCellNetworkAgent.getNetwork().netId));
9679             reset(mMockNetd);
9680 
9681             mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
9682             mWiFiNetworkAgent.addCapability(testCap);
9683             mWiFiNetworkAgent.connect(true);
9684             callbackWithCap.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
9685             callbackWithoutCap.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
9686             verify(mMockNetd).networkSetDefault(eq(mWiFiNetworkAgent.getNetwork().netId));
9687             reset(mMockNetd);
9688 
9689             // Remove the testing capability on wifi, verify the callback and default network
9690             // changes back to cellular.
9691             mWiFiNetworkAgent.removeCapability(testCap);
9692             callbackWithCap.expectAvailableCallbacksValidated(mCellNetworkAgent);
9693             callbackWithoutCap.expectCapabilitiesWithout(testCap, mWiFiNetworkAgent);
9694             verify(mMockNetd).networkSetDefault(eq(mCellNetworkAgent.getNetwork().netId));
9695             reset(mMockNetd);
9696 
9697             mCellNetworkAgent.removeCapability(testCap);
9698             callbackWithCap.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
9699             callbackWithoutCap.assertNoCallback();
9700             verify(mMockNetd).networkClearDefault();
9701 
9702             mCm.unregisterNetworkCallback(callbackWithCap);
9703             mCm.unregisterNetworkCallback(callbackWithoutCap);
9704         }
9705     }
9706 
9707     @Test
9708     public final void testBatteryStatsNetworkType() throws Exception {
9709         final LinkProperties cellLp = new LinkProperties();
9710         cellLp.setInterfaceName("cell0");
9711         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
9712         mCellNetworkAgent.connect(true);
9713         waitForIdle();
9714         final ArrayTrackRecord<ReportedInterfaces>.ReadHead readHead =
9715                 mDeps.mReportedInterfaceHistory.newReadHead();
9716         assertNotNull(readHead.poll(TIMEOUT_MS, ri -> ri.contentEquals(mServiceContext,
9717                 cellLp.getInterfaceName(),
9718                 new int[] { TRANSPORT_CELLULAR })));
9719 
9720         final LinkProperties wifiLp = new LinkProperties();
9721         wifiLp.setInterfaceName("wifi0");
9722         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp);
9723         mWiFiNetworkAgent.connect(true);
9724         waitForIdle();
9725         assertNotNull(readHead.poll(TIMEOUT_MS, ri -> ri.contentEquals(mServiceContext,
9726                 wifiLp.getInterfaceName(),
9727                 new int[] { TRANSPORT_WIFI })));
9728 
9729         mCellNetworkAgent.disconnect();
9730         mWiFiNetworkAgent.disconnect();
9731 
9732         cellLp.setInterfaceName("wifi0");
9733         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
9734         mCellNetworkAgent.connect(true);
9735         waitForIdle();
9736         assertNotNull(readHead.poll(TIMEOUT_MS, ri -> ri.contentEquals(mServiceContext,
9737                 cellLp.getInterfaceName(),
9738                 new int[] { TRANSPORT_CELLULAR })));
9739         mCellNetworkAgent.disconnect();
9740     }
9741 
9742     /**
9743      * Make simulated InterfaceConfigParcel for Nat464Xlat to query clat lower layer info.
9744      */
9745     private InterfaceConfigurationParcel getClatInterfaceConfigParcel(LinkAddress la) {
9746         final InterfaceConfigurationParcel cfg = new InterfaceConfigurationParcel();
9747         cfg.hwAddr = "11:22:33:44:55:66";
9748         cfg.ipv4Addr = la.getAddress().getHostAddress();
9749         cfg.prefixLength = la.getPrefixLength();
9750         return cfg;
9751     }
9752 
9753     /**
9754      * Make expected stack link properties, copied from Nat464Xlat.
9755      */
9756     private LinkProperties makeClatLinkProperties(LinkAddress la) {
9757         LinkAddress clatAddress = la;
9758         LinkProperties stacked = new LinkProperties();
9759         stacked.setInterfaceName(CLAT_MOBILE_IFNAME);
9760         RouteInfo ipv4Default = new RouteInfo(
9761                 new LinkAddress(Inet4Address.ANY, 0),
9762                 clatAddress.getAddress(), CLAT_MOBILE_IFNAME);
9763         stacked.addRoute(ipv4Default);
9764         stacked.addLinkAddress(clatAddress);
9765         return stacked;
9766     }
9767 
9768     private Nat64PrefixEventParcel makeNat64PrefixEvent(final int netId, final int prefixOperation,
9769             final String prefixAddress, final int prefixLength) {
9770         final Nat64PrefixEventParcel event = new Nat64PrefixEventParcel();
9771         event.netId = netId;
9772         event.prefixOperation = prefixOperation;
9773         event.prefixAddress = prefixAddress;
9774         event.prefixLength = prefixLength;
9775         return event;
9776     }
9777 
9778     private <T> T verifyWithOrder(@Nullable InOrder inOrder, @NonNull T t) {
9779         if (inOrder != null) {
9780             return inOrder.verify(t);
9781         } else {
9782             return verify(t);
9783         }
9784     }
9785 
9786     private <T> T verifyNeverWithOrder(@Nullable InOrder inOrder, @NonNull T t) {
9787         if (inOrder != null) {
9788             return inOrder.verify(t, never());
9789         } else {
9790             return verify(t, never());
9791         }
9792     }
9793 
9794     private void verifyClatdStart(@Nullable InOrder inOrder, @NonNull String iface, int netId,
9795             @NonNull String nat64Prefix) throws Exception {
9796         if (SdkLevel.isAtLeastT()) {
9797             verifyWithOrder(inOrder, mClatCoordinator)
9798                 .clatStart(eq(iface), eq(netId), eq(new IpPrefix(nat64Prefix)));
9799         } else {
9800             verifyWithOrder(inOrder, mMockNetd).clatdStart(eq(iface), eq(nat64Prefix));
9801         }
9802     }
9803 
9804     private void verifyNeverClatdStart(@Nullable InOrder inOrder, @NonNull String iface)
9805             throws Exception {
9806         if (SdkLevel.isAtLeastT()) {
9807             verifyNeverWithOrder(inOrder, mClatCoordinator).clatStart(eq(iface), anyInt(), any());
9808         } else {
9809             verifyNeverWithOrder(inOrder, mMockNetd).clatdStart(eq(iface), anyString());
9810         }
9811     }
9812 
9813     private void verifyClatdStop(@Nullable InOrder inOrder, @NonNull String iface)
9814             throws Exception {
9815         if (SdkLevel.isAtLeastT()) {
9816             verifyWithOrder(inOrder, mClatCoordinator).clatStop();
9817         } else {
9818             verifyWithOrder(inOrder, mMockNetd).clatdStop(eq(iface));
9819         }
9820     }
9821 
9822     private void verifyNeverClatdStop(@Nullable InOrder inOrder, @NonNull String iface)
9823             throws Exception {
9824         if (SdkLevel.isAtLeastT()) {
9825             verifyNeverWithOrder(inOrder, mClatCoordinator).clatStop();
9826         } else {
9827             verifyNeverWithOrder(inOrder, mMockNetd).clatdStop(eq(iface));
9828         }
9829     }
9830 
9831     @Test
9832     public void testStackedLinkProperties() throws Exception {
9833         final LinkAddress myIpv4 = new LinkAddress("1.2.3.4/24");
9834         final LinkAddress myIpv6 = new LinkAddress("2001:db8:1::1/64");
9835         final String kNat64PrefixString = "2001:db8:64:64:64:64::";
9836         final IpPrefix kNat64Prefix = new IpPrefix(InetAddress.getByName(kNat64PrefixString), 96);
9837         final String kOtherNat64PrefixString = "64:ff9b::";
9838         final IpPrefix kOtherNat64Prefix = new IpPrefix(
9839                 InetAddress.getByName(kOtherNat64PrefixString), 96);
9840         final RouteInfo ipv6Default =
9841                 new RouteInfo((IpPrefix) null, myIpv6.getAddress(), MOBILE_IFNAME);
9842         final RouteInfo ipv6Subnet = new RouteInfo(myIpv6, null, MOBILE_IFNAME);
9843         final RouteInfo ipv4Subnet = new RouteInfo(myIpv4, null, MOBILE_IFNAME);
9844         final RouteInfo stackedDefault =
9845                 new RouteInfo((IpPrefix) null, myIpv4.getAddress(), CLAT_MOBILE_IFNAME);
9846 
9847         final NetworkRequest networkRequest = new NetworkRequest.Builder()
9848                 .addTransportType(TRANSPORT_CELLULAR)
9849                 .addCapability(NET_CAPABILITY_INTERNET)
9850                 .build();
9851         final TestNetworkCallback networkCallback = new TestNetworkCallback();
9852         mCm.registerNetworkCallback(networkRequest, networkCallback);
9853 
9854         // Prepare ipv6 only link properties.
9855         final LinkProperties cellLp = new LinkProperties();
9856         cellLp.setInterfaceName(MOBILE_IFNAME);
9857         cellLp.addLinkAddress(myIpv6);
9858         cellLp.addRoute(ipv6Default);
9859         cellLp.addRoute(ipv6Subnet);
9860         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
9861         reset(mMockDnsResolver);
9862         reset(mMockNetd);
9863         reset(mClatCoordinator);
9864 
9865         // Connect with ipv6 link properties. Expect prefix discovery to be started.
9866         mCellNetworkAgent.connect(true);
9867         int cellNetId = mCellNetworkAgent.getNetwork().netId;
9868         waitForIdle();
9869 
9870         verify(mMockNetd, times(1)).networkCreate(nativeNetworkConfigPhysical(cellNetId,
9871                 INetd.PERMISSION_NONE));
9872         assertRoutesAdded(cellNetId, ipv6Subnet, ipv6Default);
9873         verify(mMockDnsResolver, times(1)).createNetworkCache(eq(cellNetId));
9874         verify(mMockNetd, times(1)).networkAddInterface(cellNetId, MOBILE_IFNAME);
9875         final ArrayTrackRecord<ReportedInterfaces>.ReadHead readHead =
9876                 mDeps.mReportedInterfaceHistory.newReadHead();
9877         assertNotNull(readHead.poll(TIMEOUT_MS, ri -> ri.contentEquals(mServiceContext,
9878                 cellLp.getInterfaceName(),
9879                 new int[] { TRANSPORT_CELLULAR })));
9880 
9881         networkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
9882         verify(mMockDnsResolver, times(1)).startPrefix64Discovery(cellNetId);
9883 
9884         // Switching default network updates TCP buffer sizes.
9885         verifyTcpBufferSizeChange(ConnectivityService.DEFAULT_TCP_BUFFER_SIZES);
9886         // Add an IPv4 address. Expect prefix discovery to be stopped. Netd doesn't tell us that
9887         // the NAT64 prefix was removed because one was never discovered.
9888         cellLp.addLinkAddress(myIpv4);
9889         mCellNetworkAgent.sendLinkProperties(cellLp);
9890         networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
9891         assertRoutesAdded(cellNetId, ipv4Subnet);
9892         verify(mMockDnsResolver, times(1)).stopPrefix64Discovery(cellNetId);
9893         verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(any());
9894 
9895         // Make sure BatteryStats was not told about any v4- interfaces, as none should have
9896         // come online yet.
9897         waitForIdle();
9898         assertNull(readHead.poll(0 /* timeout */, ri -> mServiceContext.equals(ri.context)
9899                 && ri.iface != null && ri.iface.startsWith("v4-")));
9900 
9901         verifyNoMoreInteractions(mMockNetd);
9902         verifyNoMoreInteractions(mClatCoordinator);
9903         verifyNoMoreInteractions(mMockDnsResolver);
9904         reset(mMockNetd);
9905         reset(mClatCoordinator);
9906         reset(mMockDnsResolver);
9907         doReturn(getClatInterfaceConfigParcel(myIpv4)).when(mMockNetd)
9908                 .interfaceGetCfg(CLAT_MOBILE_IFNAME);
9909 
9910         // Remove IPv4 address. Expect prefix discovery to be started again.
9911         cellLp.removeLinkAddress(myIpv4);
9912         mCellNetworkAgent.sendLinkProperties(cellLp);
9913         networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
9914         verify(mMockDnsResolver, times(1)).startPrefix64Discovery(cellNetId);
9915         assertRoutesRemoved(cellNetId, ipv4Subnet);
9916 
9917         // When NAT64 prefix discovery succeeds, LinkProperties are updated and clatd is started.
9918         Nat464Xlat clat = getNat464Xlat(mCellNetworkAgent);
9919         assertNull(mCm.getLinkProperties(mCellNetworkAgent.getNetwork()).getNat64Prefix());
9920         mService.mResolverUnsolEventCallback.onNat64PrefixEvent(
9921                 makeNat64PrefixEvent(cellNetId, PREFIX_OPERATION_ADDED, kNat64PrefixString, 96));
9922         LinkProperties lpBeforeClat = networkCallback.expectCallback(
9923                 CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent).getLp();
9924         assertEquals(0, lpBeforeClat.getStackedLinks().size());
9925         assertEquals(kNat64Prefix, lpBeforeClat.getNat64Prefix());
9926         verifyClatdStart(null /* inOrder */, MOBILE_IFNAME, cellNetId, kNat64Prefix.toString());
9927 
9928         // Clat iface comes up. Expect stacked link to be added.
9929         clat.interfaceLinkStateChanged(CLAT_MOBILE_IFNAME, true);
9930         networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
9931         List<LinkProperties> stackedLps = mCm.getLinkProperties(mCellNetworkAgent.getNetwork())
9932                 .getStackedLinks();
9933         assertEquals(makeClatLinkProperties(myIpv4), stackedLps.get(0));
9934         assertRoutesAdded(cellNetId, stackedDefault);
9935         verify(mMockNetd, times(1)).networkAddInterface(cellNetId, CLAT_MOBILE_IFNAME);
9936         // Change trivial linkproperties and see if stacked link is preserved.
9937         cellLp.addDnsServer(InetAddress.getByName("8.8.8.8"));
9938         mCellNetworkAgent.sendLinkProperties(cellLp);
9939         networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
9940 
9941         List<LinkProperties> stackedLpsAfterChange =
9942                 mCm.getLinkProperties(mCellNetworkAgent.getNetwork()).getStackedLinks();
9943         assertNotEquals(stackedLpsAfterChange, Collections.EMPTY_LIST);
9944         assertEquals(makeClatLinkProperties(myIpv4), stackedLpsAfterChange.get(0));
9945 
9946         verify(mMockDnsResolver, times(1)).setResolverConfiguration(
9947                 mResolverParamsParcelCaptor.capture());
9948         ResolverParamsParcel resolvrParams = mResolverParamsParcelCaptor.getValue();
9949         assertEquals(1, resolvrParams.servers.length);
9950         assertTrue(CollectionUtils.contains(resolvrParams.servers, "8.8.8.8"));
9951 
9952         for (final LinkProperties stackedLp : stackedLpsAfterChange) {
9953             assertNotNull(readHead.poll(TIMEOUT_MS, ri -> ri.contentEquals(mServiceContext,
9954                     stackedLp.getInterfaceName(),
9955                     new int[] { TRANSPORT_CELLULAR })));
9956         }
9957         reset(mMockNetd);
9958         reset(mClatCoordinator);
9959         doReturn(getClatInterfaceConfigParcel(myIpv4)).when(mMockNetd)
9960                 .interfaceGetCfg(CLAT_MOBILE_IFNAME);
9961         // Change the NAT64 prefix without first removing it.
9962         // Expect clatd to be stopped and started with the new prefix.
9963         mService.mResolverUnsolEventCallback.onNat64PrefixEvent(makeNat64PrefixEvent(
9964                 cellNetId, PREFIX_OPERATION_ADDED, kOtherNat64PrefixString, 96));
9965         networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
9966                 (lp) -> lp.getStackedLinks().size() == 0);
9967         verifyClatdStop(null /* inOrder */, MOBILE_IFNAME);
9968         assertRoutesRemoved(cellNetId, stackedDefault);
9969         verify(mMockNetd, times(1)).networkRemoveInterface(cellNetId, CLAT_MOBILE_IFNAME);
9970 
9971         verifyClatdStart(null /* inOrder */, MOBILE_IFNAME, cellNetId,
9972                 kOtherNat64Prefix.toString());
9973         networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
9974                 (lp) -> lp.getNat64Prefix().equals(kOtherNat64Prefix));
9975         clat.interfaceLinkStateChanged(CLAT_MOBILE_IFNAME, true);
9976         networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
9977                 (lp) -> lp.getStackedLinks().size() == 1);
9978         assertRoutesAdded(cellNetId, stackedDefault);
9979         verify(mMockNetd, times(1)).networkAddInterface(cellNetId, CLAT_MOBILE_IFNAME);
9980         reset(mMockNetd);
9981         reset(mClatCoordinator);
9982 
9983         // Add ipv4 address, expect that clatd and prefix discovery are stopped and stacked
9984         // linkproperties are cleaned up.
9985         cellLp.addLinkAddress(myIpv4);
9986         cellLp.addRoute(ipv4Subnet);
9987         mCellNetworkAgent.sendLinkProperties(cellLp);
9988         networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
9989         assertRoutesAdded(cellNetId, ipv4Subnet);
9990         verifyClatdStop(null /* inOrder */, MOBILE_IFNAME);
9991         verify(mMockDnsResolver, times(1)).stopPrefix64Discovery(cellNetId);
9992 
9993         // As soon as stop is called, the linkproperties lose the stacked interface.
9994         networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
9995         LinkProperties actualLpAfterIpv4 = mCm.getLinkProperties(mCellNetworkAgent.getNetwork());
9996         LinkProperties expected = new LinkProperties(cellLp);
9997         expected.setNat64Prefix(kOtherNat64Prefix);
9998         assertEquals(expected, actualLpAfterIpv4);
9999         assertEquals(0, actualLpAfterIpv4.getStackedLinks().size());
10000         assertRoutesRemoved(cellNetId, stackedDefault);
10001 
10002         // The interface removed callback happens but has no effect after stop is called.
10003         clat.interfaceRemoved(CLAT_MOBILE_IFNAME);
10004         networkCallback.assertNoCallback();
10005         verify(mMockNetd, times(1)).networkRemoveInterface(cellNetId, CLAT_MOBILE_IFNAME);
10006         verifyNoMoreInteractions(mMockNetd);
10007         verifyNoMoreInteractions(mClatCoordinator);
10008         verifyNoMoreInteractions(mMockDnsResolver);
10009         reset(mMockNetd);
10010         reset(mClatCoordinator);
10011         reset(mMockDnsResolver);
10012         doReturn(getClatInterfaceConfigParcel(myIpv4)).when(mMockNetd)
10013                 .interfaceGetCfg(CLAT_MOBILE_IFNAME);
10014 
10015         // Stopping prefix discovery causes netd to tell us that the NAT64 prefix is gone.
10016         mService.mResolverUnsolEventCallback.onNat64PrefixEvent(makeNat64PrefixEvent(
10017                 cellNetId, PREFIX_OPERATION_REMOVED, kOtherNat64PrefixString, 96));
10018         networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
10019                 (lp) -> lp.getNat64Prefix() == null);
10020 
10021         // Remove IPv4 address and expect prefix discovery and clatd to be started again.
10022         cellLp.removeLinkAddress(myIpv4);
10023         cellLp.removeRoute(new RouteInfo(myIpv4, null, MOBILE_IFNAME));
10024         cellLp.removeDnsServer(InetAddress.getByName("8.8.8.8"));
10025         mCellNetworkAgent.sendLinkProperties(cellLp);
10026         networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
10027         assertRoutesRemoved(cellNetId, ipv4Subnet);  // Directly-connected routes auto-added.
10028         verify(mMockDnsResolver, times(1)).startPrefix64Discovery(cellNetId);
10029         mService.mResolverUnsolEventCallback.onNat64PrefixEvent(makeNat64PrefixEvent(
10030                 cellNetId, PREFIX_OPERATION_ADDED, kNat64PrefixString, 96));
10031         networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
10032         verifyClatdStart(null /* inOrder */, MOBILE_IFNAME, cellNetId, kNat64Prefix.toString());
10033 
10034         // Clat iface comes up. Expect stacked link to be added.
10035         clat.interfaceLinkStateChanged(CLAT_MOBILE_IFNAME, true);
10036         networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
10037                 (lp) -> lp.getStackedLinks().size() == 1 && lp.getNat64Prefix() != null);
10038         assertRoutesAdded(cellNetId, stackedDefault);
10039         verify(mMockNetd, times(1)).networkAddInterface(cellNetId, CLAT_MOBILE_IFNAME);
10040 
10041         // NAT64 prefix is removed. Expect that clat is stopped.
10042         mService.mResolverUnsolEventCallback.onNat64PrefixEvent(makeNat64PrefixEvent(
10043                 cellNetId, PREFIX_OPERATION_REMOVED, kNat64PrefixString, 96));
10044         networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
10045                 (lp) -> lp.getStackedLinks().size() == 0 && lp.getNat64Prefix() == null);
10046         assertRoutesRemoved(cellNetId, ipv4Subnet, stackedDefault);
10047 
10048         // Stop has no effect because clat is already stopped.
10049         verifyClatdStop(null /* inOrder */, MOBILE_IFNAME);
10050         networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
10051                 (lp) -> lp.getStackedLinks().size() == 0);
10052         verify(mMockNetd, times(1)).networkRemoveInterface(cellNetId, CLAT_MOBILE_IFNAME);
10053         verify(mMockNetd, times(1)).interfaceGetCfg(CLAT_MOBILE_IFNAME);
10054         // Clean up.
10055         mCellNetworkAgent.disconnect();
10056         networkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
10057         networkCallback.assertNoCallback();
10058         verify(mMockNetd, times(1)).idletimerRemoveInterface(eq(MOBILE_IFNAME), anyInt(),
10059                 eq(Integer.toString(TRANSPORT_CELLULAR)));
10060         verify(mMockNetd).networkDestroy(cellNetId);
10061         verifyNoMoreInteractions(mMockNetd);
10062         verifyNoMoreInteractions(mClatCoordinator);
10063         reset(mMockNetd);
10064         reset(mClatCoordinator);
10065 
10066         // Test disconnecting a network that is running 464xlat.
10067 
10068         // Connect a network with a NAT64 prefix.
10069         doReturn(getClatInterfaceConfigParcel(myIpv4)).when(mMockNetd)
10070                 .interfaceGetCfg(CLAT_MOBILE_IFNAME);
10071         cellLp.setNat64Prefix(kNat64Prefix);
10072         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
10073         mCellNetworkAgent.connect(false /* validated */);
10074         networkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
10075         cellNetId = mCellNetworkAgent.getNetwork().netId;
10076         verify(mMockNetd, times(1)).networkCreate(nativeNetworkConfigPhysical(cellNetId,
10077                 INetd.PERMISSION_NONE));
10078         assertRoutesAdded(cellNetId, ipv6Subnet, ipv6Default);
10079 
10080         // Clatd is started and clat iface comes up. Expect stacked link to be added.
10081         verifyClatdStart(null /* inOrder */, MOBILE_IFNAME, cellNetId, kNat64Prefix.toString());
10082         clat = getNat464Xlat(mCellNetworkAgent);
10083         clat.interfaceLinkStateChanged(CLAT_MOBILE_IFNAME, true /* up */);
10084         networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
10085                 (lp) -> lp.getStackedLinks().size() == 1
10086                         && lp.getNat64Prefix().equals(kNat64Prefix));
10087         verify(mMockNetd).networkAddInterface(cellNetId, CLAT_MOBILE_IFNAME);
10088         // assertRoutesAdded sees all calls since last mMockNetd reset, so expect IPv6 routes again.
10089         assertRoutesAdded(cellNetId, ipv6Subnet, ipv6Default, stackedDefault);
10090         reset(mMockNetd);
10091         reset(mClatCoordinator);
10092 
10093         // Disconnect the network. clat is stopped and the network is destroyed.
10094         mCellNetworkAgent.disconnect();
10095         networkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
10096         networkCallback.assertNoCallback();
10097         verifyClatdStop(null /* inOrder */, MOBILE_IFNAME);
10098         verify(mMockNetd).idletimerRemoveInterface(eq(MOBILE_IFNAME), anyInt(),
10099                 eq(Integer.toString(TRANSPORT_CELLULAR)));
10100         verify(mMockNetd).networkDestroy(cellNetId);
10101         verifyNoMoreInteractions(mMockNetd);
10102         verifyNoMoreInteractions(mClatCoordinator);
10103 
10104         mCm.unregisterNetworkCallback(networkCallback);
10105     }
10106 
10107     private void expectNat64PrefixChange(TestableNetworkCallback callback,
10108             TestNetworkAgentWrapper agent, IpPrefix prefix) {
10109         callback.expectLinkPropertiesThat(agent, x -> Objects.equals(x.getNat64Prefix(), prefix));
10110     }
10111 
10112     @Test
10113     public void testNat64PrefixMultipleSources() throws Exception {
10114         final String iface = "wlan0";
10115         final String pref64FromRaStr = "64:ff9b::";
10116         final String pref64FromDnsStr = "2001:db8:64::";
10117         final IpPrefix pref64FromRa = new IpPrefix(InetAddress.getByName(pref64FromRaStr), 96);
10118         final IpPrefix pref64FromDns = new IpPrefix(InetAddress.getByName(pref64FromDnsStr), 96);
10119         final IpPrefix newPref64FromRa = new IpPrefix("2001:db8:64:64:64:64::/96");
10120 
10121         final NetworkRequest request = new NetworkRequest.Builder()
10122                 .addCapability(NET_CAPABILITY_INTERNET)
10123                 .build();
10124         final TestNetworkCallback callback = new TestNetworkCallback();
10125         mCm.registerNetworkCallback(request, callback);
10126 
10127         final LinkProperties baseLp = new LinkProperties();
10128         baseLp.setInterfaceName(iface);
10129         baseLp.addLinkAddress(new LinkAddress("2001:db8:1::1/64"));
10130         baseLp.addDnsServer(InetAddress.getByName("2001:4860:4860::6464"));
10131 
10132         reset(mMockNetd, mMockDnsResolver);
10133         InOrder inOrder = inOrder(mMockNetd, mMockDnsResolver, mClatCoordinator);
10134 
10135         // If a network already has a NAT64 prefix on connect, clatd is started immediately and
10136         // prefix discovery is never started.
10137         LinkProperties lp = new LinkProperties(baseLp);
10138         lp.setNat64Prefix(pref64FromRa);
10139         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, lp);
10140         mWiFiNetworkAgent.connect(false);
10141         final Network network = mWiFiNetworkAgent.getNetwork();
10142         int netId = network.getNetId();
10143         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
10144         verifyClatdStart(inOrder, iface, netId, pref64FromRa.toString());
10145         inOrder.verify(mMockDnsResolver).setPrefix64(netId, pref64FromRa.toString());
10146         inOrder.verify(mMockDnsResolver, never()).startPrefix64Discovery(netId);
10147         callback.assertNoCallback();
10148         assertEquals(pref64FromRa, mCm.getLinkProperties(network).getNat64Prefix());
10149 
10150         // If the RA prefix is withdrawn, clatd is stopped and prefix discovery is started.
10151         lp.setNat64Prefix(null);
10152         mWiFiNetworkAgent.sendLinkProperties(lp);
10153         expectNat64PrefixChange(callback, mWiFiNetworkAgent, null);
10154         verifyClatdStop(inOrder, iface);
10155         inOrder.verify(mMockDnsResolver).setPrefix64(netId, "");
10156         inOrder.verify(mMockDnsResolver).startPrefix64Discovery(netId);
10157 
10158         // If the RA prefix appears while DNS discovery is in progress, discovery is stopped and
10159         // clatd is started with the prefix from the RA.
10160         lp.setNat64Prefix(pref64FromRa);
10161         mWiFiNetworkAgent.sendLinkProperties(lp);
10162         expectNat64PrefixChange(callback, mWiFiNetworkAgent, pref64FromRa);
10163         verifyClatdStart(inOrder, iface, netId, pref64FromRa.toString());
10164         inOrder.verify(mMockDnsResolver).stopPrefix64Discovery(netId);
10165         inOrder.verify(mMockDnsResolver).setPrefix64(netId, pref64FromRa.toString());
10166 
10167         // Withdraw the RA prefix so we can test the case where an RA prefix appears after DNS
10168         // discovery has succeeded.
10169         lp.setNat64Prefix(null);
10170         mWiFiNetworkAgent.sendLinkProperties(lp);
10171         expectNat64PrefixChange(callback, mWiFiNetworkAgent, null);
10172         verifyClatdStop(inOrder, iface);
10173         inOrder.verify(mMockDnsResolver).setPrefix64(netId, "");
10174         inOrder.verify(mMockDnsResolver).startPrefix64Discovery(netId);
10175 
10176         mService.mResolverUnsolEventCallback.onNat64PrefixEvent(
10177                 makeNat64PrefixEvent(netId, PREFIX_OPERATION_ADDED, pref64FromDnsStr, 96));
10178         expectNat64PrefixChange(callback, mWiFiNetworkAgent, pref64FromDns);
10179         verifyClatdStart(inOrder, iface, netId, pref64FromDns.toString());
10180 
10181         // If an RA advertises the same prefix that was discovered by DNS, nothing happens: prefix
10182         // discovery is not stopped, and there are no callbacks.
10183         lp.setNat64Prefix(pref64FromDns);
10184         mWiFiNetworkAgent.sendLinkProperties(lp);
10185         callback.assertNoCallback();
10186         verifyNeverClatdStop(inOrder, iface);
10187         verifyNeverClatdStart(inOrder, iface);
10188         inOrder.verify(mMockDnsResolver, never()).stopPrefix64Discovery(netId);
10189         inOrder.verify(mMockDnsResolver, never()).startPrefix64Discovery(netId);
10190         inOrder.verify(mMockDnsResolver, never()).setPrefix64(eq(netId), anyString());
10191 
10192         // If the RA is later withdrawn, nothing happens again.
10193         lp.setNat64Prefix(null);
10194         mWiFiNetworkAgent.sendLinkProperties(lp);
10195         callback.assertNoCallback();
10196         verifyNeverClatdStop(inOrder, iface);
10197         verifyNeverClatdStart(inOrder, iface);
10198         inOrder.verify(mMockDnsResolver, never()).stopPrefix64Discovery(netId);
10199         inOrder.verify(mMockDnsResolver, never()).startPrefix64Discovery(netId);
10200         inOrder.verify(mMockDnsResolver, never()).setPrefix64(eq(netId), anyString());
10201 
10202         // If the RA prefix changes, clatd is restarted and prefix discovery is stopped.
10203         lp.setNat64Prefix(pref64FromRa);
10204         mWiFiNetworkAgent.sendLinkProperties(lp);
10205         expectNat64PrefixChange(callback, mWiFiNetworkAgent, pref64FromRa);
10206         verifyClatdStop(inOrder, iface);
10207         inOrder.verify(mMockDnsResolver).stopPrefix64Discovery(netId);
10208 
10209         // Stopping prefix discovery results in a prefix removed notification.
10210         mService.mResolverUnsolEventCallback.onNat64PrefixEvent(
10211                 makeNat64PrefixEvent(netId, PREFIX_OPERATION_REMOVED, pref64FromDnsStr, 96));
10212 
10213         verifyClatdStart(inOrder, iface, netId, pref64FromRa.toString());
10214         inOrder.verify(mMockDnsResolver).setPrefix64(netId, pref64FromRa.toString());
10215         inOrder.verify(mMockDnsResolver, never()).startPrefix64Discovery(netId);
10216 
10217         // If the RA prefix changes, clatd is restarted and prefix discovery is not started.
10218         lp.setNat64Prefix(newPref64FromRa);
10219         mWiFiNetworkAgent.sendLinkProperties(lp);
10220         expectNat64PrefixChange(callback, mWiFiNetworkAgent, newPref64FromRa);
10221         verifyClatdStop(inOrder, iface);
10222         inOrder.verify(mMockDnsResolver).setPrefix64(netId, "");
10223         verifyClatdStart(inOrder, iface, netId, newPref64FromRa.toString());
10224         inOrder.verify(mMockDnsResolver).setPrefix64(netId, newPref64FromRa.toString());
10225         inOrder.verify(mMockDnsResolver, never()).stopPrefix64Discovery(netId);
10226         inOrder.verify(mMockDnsResolver, never()).startPrefix64Discovery(netId);
10227 
10228         // If the RA prefix changes to the same value, nothing happens.
10229         lp.setNat64Prefix(newPref64FromRa);
10230         mWiFiNetworkAgent.sendLinkProperties(lp);
10231         callback.assertNoCallback();
10232         assertEquals(newPref64FromRa, mCm.getLinkProperties(network).getNat64Prefix());
10233         verifyNeverClatdStop(inOrder, iface);
10234         verifyNeverClatdStart(inOrder, iface);
10235         inOrder.verify(mMockDnsResolver, never()).stopPrefix64Discovery(netId);
10236         inOrder.verify(mMockDnsResolver, never()).startPrefix64Discovery(netId);
10237         inOrder.verify(mMockDnsResolver, never()).setPrefix64(eq(netId), anyString());
10238 
10239         // The transition between no prefix and DNS prefix is tested in testStackedLinkProperties.
10240 
10241         // If the same prefix is learned first by DNS and then by RA, and clat is later stopped,
10242         // (e.g., because the network disconnects) setPrefix64(netid, "") is never called.
10243         lp.setNat64Prefix(null);
10244         mWiFiNetworkAgent.sendLinkProperties(lp);
10245         expectNat64PrefixChange(callback, mWiFiNetworkAgent, null);
10246         verifyClatdStop(inOrder, iface);
10247         inOrder.verify(mMockDnsResolver).setPrefix64(netId, "");
10248         inOrder.verify(mMockDnsResolver).startPrefix64Discovery(netId);
10249         mService.mResolverUnsolEventCallback.onNat64PrefixEvent(
10250                 makeNat64PrefixEvent(netId, PREFIX_OPERATION_ADDED, pref64FromDnsStr, 96));
10251         expectNat64PrefixChange(callback, mWiFiNetworkAgent, pref64FromDns);
10252         verifyClatdStart(inOrder, iface, netId, pref64FromDns.toString());
10253         inOrder.verify(mMockDnsResolver, never()).setPrefix64(eq(netId), any());
10254 
10255         lp.setNat64Prefix(pref64FromDns);
10256         mWiFiNetworkAgent.sendLinkProperties(lp);
10257         callback.assertNoCallback();
10258         verifyNeverClatdStop(inOrder, iface);
10259         verifyNeverClatdStart(inOrder, iface);
10260         inOrder.verify(mMockDnsResolver, never()).stopPrefix64Discovery(netId);
10261         inOrder.verify(mMockDnsResolver, never()).startPrefix64Discovery(netId);
10262         inOrder.verify(mMockDnsResolver, never()).setPrefix64(eq(netId), anyString());
10263 
10264         // When tearing down a network, clat state is only updated after CALLBACK_LOST is fired, but
10265         // before CONNECTIVITY_ACTION is sent. Wait for CONNECTIVITY_ACTION before verifying that
10266         // clat has been stopped, or the test will be flaky.
10267         ExpectedBroadcast b = expectConnectivityAction(TYPE_WIFI, DetailedState.DISCONNECTED);
10268         mWiFiNetworkAgent.disconnect();
10269         callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
10270         b.expectBroadcast();
10271 
10272         verifyClatdStop(inOrder, iface);
10273         inOrder.verify(mMockDnsResolver).stopPrefix64Discovery(netId);
10274         inOrder.verify(mMockDnsResolver, never()).setPrefix64(eq(netId), anyString());
10275 
10276         mCm.unregisterNetworkCallback(callback);
10277     }
10278 
10279     @Test
10280     public void testWith464XlatDisable() throws Exception {
10281         mDeps.setCellular464XlatEnabled(false);
10282 
10283         final TestNetworkCallback callback = new TestNetworkCallback();
10284         final TestNetworkCallback defaultCallback = new TestNetworkCallback();
10285         final NetworkRequest networkRequest = new NetworkRequest.Builder()
10286                 .addCapability(NET_CAPABILITY_INTERNET)
10287                 .build();
10288         mCm.registerNetworkCallback(networkRequest, callback);
10289         mCm.registerDefaultNetworkCallback(defaultCallback);
10290 
10291         // Bring up validated cell.
10292         final LinkProperties cellLp = new LinkProperties();
10293         cellLp.setInterfaceName(MOBILE_IFNAME);
10294         cellLp.addLinkAddress(new LinkAddress("2001:db8:1::1/64"));
10295         cellLp.addRoute(new RouteInfo(new IpPrefix("::/0"), null, MOBILE_IFNAME));
10296         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
10297 
10298         mCellNetworkAgent.sendLinkProperties(cellLp);
10299         mCellNetworkAgent.connect(true);
10300         callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
10301         defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
10302         final int cellNetId = mCellNetworkAgent.getNetwork().netId;
10303         waitForIdle();
10304 
10305         verify(mMockDnsResolver, never()).startPrefix64Discovery(cellNetId);
10306         Nat464Xlat clat = getNat464Xlat(mCellNetworkAgent);
10307         assertTrue("Nat464Xlat was not IDLE", !clat.isStarted());
10308 
10309         // This cannot happen because prefix discovery cannot succeed if it is never started.
10310         mService.mResolverUnsolEventCallback.onNat64PrefixEvent(
10311                 makeNat64PrefixEvent(cellNetId, PREFIX_OPERATION_ADDED, "64:ff9b::", 96));
10312 
10313         // ... but still, check that even if it did, clatd would not be started.
10314         verify(mMockNetd, never()).clatdStart(anyString(), anyString());
10315         assertTrue("Nat464Xlat was not IDLE", !clat.isStarted());
10316     }
10317 
10318     @Test
10319     public void testDataActivityTracking() throws Exception {
10320         final TestNetworkCallback networkCallback = new TestNetworkCallback();
10321         final NetworkRequest networkRequest = new NetworkRequest.Builder()
10322                 .addCapability(NET_CAPABILITY_INTERNET)
10323                 .build();
10324         mCm.registerNetworkCallback(networkRequest, networkCallback);
10325 
10326         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
10327         final LinkProperties cellLp = new LinkProperties();
10328         cellLp.setInterfaceName(MOBILE_IFNAME);
10329         mCellNetworkAgent.sendLinkProperties(cellLp);
10330         mCellNetworkAgent.connect(true);
10331         networkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
10332         verify(mMockNetd, times(1)).idletimerAddInterface(eq(MOBILE_IFNAME), anyInt(),
10333                 eq(Integer.toString(TRANSPORT_CELLULAR)));
10334 
10335         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
10336         final LinkProperties wifiLp = new LinkProperties();
10337         wifiLp.setInterfaceName(WIFI_IFNAME);
10338         mWiFiNetworkAgent.sendLinkProperties(wifiLp);
10339 
10340         // Network switch
10341         mWiFiNetworkAgent.connect(true);
10342         networkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
10343         networkCallback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
10344         networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
10345         verify(mMockNetd, times(1)).idletimerAddInterface(eq(WIFI_IFNAME), anyInt(),
10346                 eq(Integer.toString(TRANSPORT_WIFI)));
10347         verify(mMockNetd, times(1)).idletimerRemoveInterface(eq(MOBILE_IFNAME), anyInt(),
10348                 eq(Integer.toString(TRANSPORT_CELLULAR)));
10349 
10350         // Disconnect wifi and switch back to cell
10351         reset(mMockNetd);
10352         mWiFiNetworkAgent.disconnect();
10353         networkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
10354         assertNoCallbacks(networkCallback);
10355         verify(mMockNetd, times(1)).idletimerRemoveInterface(eq(WIFI_IFNAME), anyInt(),
10356                 eq(Integer.toString(TRANSPORT_WIFI)));
10357         verify(mMockNetd, times(1)).idletimerAddInterface(eq(MOBILE_IFNAME), anyInt(),
10358                 eq(Integer.toString(TRANSPORT_CELLULAR)));
10359 
10360         // reconnect wifi
10361         reset(mMockNetd);
10362         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
10363         wifiLp.setInterfaceName(WIFI_IFNAME);
10364         mWiFiNetworkAgent.sendLinkProperties(wifiLp);
10365         mWiFiNetworkAgent.connect(true);
10366         networkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
10367         networkCallback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
10368         networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
10369         verify(mMockNetd, times(1)).idletimerAddInterface(eq(WIFI_IFNAME), anyInt(),
10370                 eq(Integer.toString(TRANSPORT_WIFI)));
10371         verify(mMockNetd, times(1)).idletimerRemoveInterface(eq(MOBILE_IFNAME), anyInt(),
10372                 eq(Integer.toString(TRANSPORT_CELLULAR)));
10373 
10374         // Disconnect cell
10375         reset(mMockNetd);
10376         mCellNetworkAgent.disconnect();
10377         networkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
10378         // LOST callback is triggered earlier than removing idle timer. Broadcast should also be
10379         // sent as network being switched. Ensure rule removal for cell will not be triggered
10380         // unexpectedly before network being removed.
10381         waitForIdle();
10382         verify(mMockNetd, times(0)).idletimerRemoveInterface(eq(MOBILE_IFNAME), anyInt(),
10383                 eq(Integer.toString(TRANSPORT_CELLULAR)));
10384         verify(mMockNetd, times(1)).networkDestroy(eq(mCellNetworkAgent.getNetwork().netId));
10385         verify(mMockDnsResolver, times(1))
10386                 .destroyNetworkCache(eq(mCellNetworkAgent.getNetwork().netId));
10387 
10388         // Disconnect wifi
10389         ExpectedBroadcast b = expectConnectivityAction(TYPE_WIFI, DetailedState.DISCONNECTED);
10390         mWiFiNetworkAgent.disconnect();
10391         b.expectBroadcast();
10392         verify(mMockNetd, times(1)).idletimerRemoveInterface(eq(WIFI_IFNAME), anyInt(),
10393                 eq(Integer.toString(TRANSPORT_WIFI)));
10394 
10395         // Clean up
10396         mCm.unregisterNetworkCallback(networkCallback);
10397     }
10398 
10399     private void verifyTcpBufferSizeChange(String tcpBufferSizes) throws Exception {
10400         String[] values = tcpBufferSizes.split(",");
10401         String rmemValues = String.join(" ", values[0], values[1], values[2]);
10402         String wmemValues = String.join(" ", values[3], values[4], values[5]);
10403         verify(mMockNetd, atLeastOnce()).setTcpRWmemorySize(rmemValues, wmemValues);
10404         reset(mMockNetd);
10405     }
10406 
10407     @Test
10408     public void testTcpBufferReset() throws Exception {
10409         final String testTcpBufferSizes = "1,2,3,4,5,6";
10410         final NetworkRequest networkRequest = new NetworkRequest.Builder()
10411                 .addTransportType(TRANSPORT_CELLULAR)
10412                 .addCapability(NET_CAPABILITY_INTERNET)
10413                 .build();
10414         final TestNetworkCallback networkCallback = new TestNetworkCallback();
10415         mCm.registerNetworkCallback(networkRequest, networkCallback);
10416 
10417         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
10418         reset(mMockNetd);
10419         // Switching default network updates TCP buffer sizes.
10420         mCellNetworkAgent.connect(false);
10421         networkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
10422         verifyTcpBufferSizeChange(ConnectivityService.DEFAULT_TCP_BUFFER_SIZES);
10423         // Change link Properties should have updated tcp buffer size.
10424         LinkProperties lp = new LinkProperties();
10425         lp.setTcpBufferSizes(testTcpBufferSizes);
10426         mCellNetworkAgent.sendLinkProperties(lp);
10427         networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
10428         verifyTcpBufferSizeChange(testTcpBufferSizes);
10429         // Clean up.
10430         mCellNetworkAgent.disconnect();
10431         networkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
10432         networkCallback.assertNoCallback();
10433         mCm.unregisterNetworkCallback(networkCallback);
10434     }
10435 
10436     @Test
10437     public void testGetGlobalProxyForNetwork() throws Exception {
10438         final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
10439         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
10440         final Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
10441         mProxyTracker.setGlobalProxy(testProxyInfo);
10442         assertEquals(testProxyInfo, mService.getProxyForNetwork(wifiNetwork));
10443     }
10444 
10445     @Test
10446     public void testGetProxyForActiveNetwork() throws Exception {
10447         final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
10448         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
10449         mWiFiNetworkAgent.connect(true);
10450         waitForIdle();
10451         assertNull(mService.getProxyForNetwork(null));
10452 
10453         final LinkProperties testLinkProperties = new LinkProperties();
10454         testLinkProperties.setHttpProxy(testProxyInfo);
10455 
10456         mWiFiNetworkAgent.sendLinkProperties(testLinkProperties);
10457         waitForIdle();
10458 
10459         assertEquals(testProxyInfo, mService.getProxyForNetwork(null));
10460     }
10461 
10462     @Test
10463     public void testGetProxyForVPN() throws Exception {
10464         final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
10465 
10466         // Set up a WiFi network with no proxy
10467         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
10468         mWiFiNetworkAgent.connect(true);
10469         waitForIdle();
10470         assertNull(mService.getProxyForNetwork(null));
10471 
10472         // Connect a VPN network with a proxy.
10473         LinkProperties testLinkProperties = new LinkProperties();
10474         testLinkProperties.setHttpProxy(testProxyInfo);
10475         mMockVpn.establishForMyUid(testLinkProperties);
10476         assertUidRangesUpdatedForMyUid(true);
10477 
10478         // Test that the VPN network returns a proxy, and the WiFi does not.
10479         assertEquals(testProxyInfo, mService.getProxyForNetwork(mMockVpn.getNetwork()));
10480         assertEquals(testProxyInfo, mService.getProxyForNetwork(null));
10481         assertNull(mService.getProxyForNetwork(mWiFiNetworkAgent.getNetwork()));
10482 
10483         // Test that the VPN network returns no proxy when it is set to null.
10484         testLinkProperties.setHttpProxy(null);
10485         mMockVpn.sendLinkProperties(testLinkProperties);
10486         waitForIdle();
10487         assertNull(mService.getProxyForNetwork(mMockVpn.getNetwork()));
10488         assertNull(mService.getProxyForNetwork(null));
10489 
10490         // Set WiFi proxy and check that the vpn proxy is still null.
10491         testLinkProperties.setHttpProxy(testProxyInfo);
10492         mWiFiNetworkAgent.sendLinkProperties(testLinkProperties);
10493         waitForIdle();
10494         assertNull(mService.getProxyForNetwork(null));
10495 
10496         // Disconnect from VPN and check that the active network, which is now the WiFi, has the
10497         // correct proxy setting.
10498         mMockVpn.disconnect();
10499         waitForIdle();
10500         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
10501         assertEquals(testProxyInfo, mService.getProxyForNetwork(mWiFiNetworkAgent.getNetwork()));
10502         assertEquals(testProxyInfo, mService.getProxyForNetwork(null));
10503     }
10504 
10505     @Test
10506     public void testFullyRoutedVpnResultsInInterfaceFilteringRules() throws Exception {
10507         LinkProperties lp = new LinkProperties();
10508         lp.setInterfaceName("tun0");
10509         lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
10510         lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), RTN_UNREACHABLE));
10511         // The uid range needs to cover the test app so the network is visible to it.
10512         final Set<UidRange> vpnRange = Collections.singleton(PRIMARY_UIDRANGE);
10513         mMockVpn.establish(lp, VPN_UID, vpnRange);
10514         assertVpnUidRangesUpdated(true, vpnRange, VPN_UID);
10515 
10516         // A connected VPN should have interface rules set up. There are two expected invocations,
10517         // one during the VPN initial connection, one during the VPN LinkProperties update.
10518         ArgumentCaptor<int[]> uidCaptor = ArgumentCaptor.forClass(int[].class);
10519         verify(mBpfNetMaps, times(2)).addUidInterfaceRules(eq("tun0"), uidCaptor.capture());
10520         assertContainsExactly(uidCaptor.getAllValues().get(0), APP1_UID, APP2_UID);
10521         assertContainsExactly(uidCaptor.getAllValues().get(1), APP1_UID, APP2_UID);
10522         assertTrue(mService.mPermissionMonitor.getVpnInterfaceUidRanges("tun0").equals(vpnRange));
10523 
10524         mMockVpn.disconnect();
10525         waitForIdle();
10526 
10527         // Disconnected VPN should have interface rules removed
10528         verify(mBpfNetMaps).removeUidInterfaceRules(uidCaptor.capture());
10529         assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
10530         assertNull(mService.mPermissionMonitor.getVpnInterfaceUidRanges("tun0"));
10531     }
10532 
10533     @Test
10534     public void testLegacyVpnSetInterfaceFilteringRuleWithWildcard() throws Exception {
10535         LinkProperties lp = new LinkProperties();
10536         lp.setInterfaceName("tun0");
10537         lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
10538         lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
10539         // The uid range needs to cover the test app so the network is visible to it.
10540         final Set<UidRange> vpnRange = Collections.singleton(PRIMARY_UIDRANGE);
10541         mMockVpn.establish(lp, Process.SYSTEM_UID, vpnRange);
10542         assertVpnUidRangesUpdated(true, vpnRange, Process.SYSTEM_UID);
10543 
10544         // A connected Legacy VPN should have interface rules with null interface.
10545         // Null Interface is a wildcard and this accepts traffic from all the interfaces.
10546         // There are two expected invocations, one during the VPN initial connection,
10547         // one during the VPN LinkProperties update.
10548         ArgumentCaptor<int[]> uidCaptor = ArgumentCaptor.forClass(int[].class);
10549         verify(mBpfNetMaps, times(2)).addUidInterfaceRules(
10550                 eq(null) /* iface */, uidCaptor.capture());
10551         assertContainsExactly(uidCaptor.getAllValues().get(0), APP1_UID, APP2_UID, VPN_UID);
10552         assertContainsExactly(uidCaptor.getAllValues().get(1), APP1_UID, APP2_UID, VPN_UID);
10553         assertEquals(mService.mPermissionMonitor.getVpnInterfaceUidRanges(null /* iface */),
10554                 vpnRange);
10555 
10556         mMockVpn.disconnect();
10557         waitForIdle();
10558 
10559         // Disconnected VPN should have interface rules removed
10560         verify(mBpfNetMaps).removeUidInterfaceRules(uidCaptor.capture());
10561         assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID, VPN_UID);
10562         assertNull(mService.mPermissionMonitor.getVpnInterfaceUidRanges(null /* iface */));
10563     }
10564 
10565     @Test
10566     public void testLocalIpv4OnlyVpnSetInterfaceFilteringRuleWithWildcard() throws Exception {
10567         LinkProperties lp = new LinkProperties();
10568         lp.setInterfaceName("tun0");
10569         lp.addRoute(new RouteInfo(new IpPrefix("192.0.2.0/24"), null, "tun0"));
10570         lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), RTN_UNREACHABLE));
10571         // The uid range needs to cover the test app so the network is visible to it.
10572         final Set<UidRange> vpnRange = Collections.singleton(PRIMARY_UIDRANGE);
10573         mMockVpn.establish(lp, Process.SYSTEM_UID, vpnRange);
10574         assertVpnUidRangesUpdated(true, vpnRange, Process.SYSTEM_UID);
10575 
10576         // IPv6 unreachable route should not be misinterpreted as a default route
10577         // A connected VPN should have interface rules with null interface.
10578         // Null Interface is a wildcard and this accepts traffic from all the interfaces.
10579         // There are two expected invocations, one during the VPN initial connection,
10580         // one during the VPN LinkProperties update.
10581         ArgumentCaptor<int[]> uidCaptor = ArgumentCaptor.forClass(int[].class);
10582         verify(mBpfNetMaps, times(2)).addUidInterfaceRules(
10583                 eq(null) /* iface */, uidCaptor.capture());
10584         assertContainsExactly(uidCaptor.getAllValues().get(0), APP1_UID, APP2_UID, VPN_UID);
10585         assertContainsExactly(uidCaptor.getAllValues().get(1), APP1_UID, APP2_UID, VPN_UID);
10586         assertEquals(mService.mPermissionMonitor.getVpnInterfaceUidRanges(null /* iface */),
10587                 vpnRange);
10588 
10589         mMockVpn.disconnect();
10590         waitForIdle();
10591 
10592         // Disconnected VPN should have interface rules removed
10593         verify(mBpfNetMaps).removeUidInterfaceRules(uidCaptor.capture());
10594         assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID, VPN_UID);
10595         assertNull(mService.mPermissionMonitor.getVpnInterfaceUidRanges(null /* iface */));
10596     }
10597 
10598     @Test
10599     public void testVpnHandoverChangesInterfaceFilteringRule() throws Exception {
10600         LinkProperties lp = new LinkProperties();
10601         lp.setInterfaceName("tun0");
10602         lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
10603         lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
10604         // The uid range needs to cover the test app so the network is visible to it.
10605         final Set<UidRange> vpnRange = Collections.singleton(PRIMARY_UIDRANGE);
10606         mMockVpn.establish(lp, VPN_UID, vpnRange);
10607         assertVpnUidRangesUpdated(true, vpnRange, VPN_UID);
10608 
10609         // Connected VPN should have interface rules set up. There are two expected invocations,
10610         // one during VPN uid update, one during VPN LinkProperties update
10611         ArgumentCaptor<int[]> uidCaptor = ArgumentCaptor.forClass(int[].class);
10612         verify(mBpfNetMaps, times(2)).addUidInterfaceRules(eq("tun0"), uidCaptor.capture());
10613         assertContainsExactly(uidCaptor.getAllValues().get(0), APP1_UID, APP2_UID);
10614         assertContainsExactly(uidCaptor.getAllValues().get(1), APP1_UID, APP2_UID);
10615 
10616         reset(mBpfNetMaps);
10617         InOrder inOrder = inOrder(mBpfNetMaps);
10618         lp.setInterfaceName("tun1");
10619         mMockVpn.sendLinkProperties(lp);
10620         waitForIdle();
10621         // VPN handover (switch to a new interface) should result in rules being updated (old rules
10622         // removed first, then new rules added)
10623         inOrder.verify(mBpfNetMaps).removeUidInterfaceRules(uidCaptor.capture());
10624         assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
10625         inOrder.verify(mBpfNetMaps).addUidInterfaceRules(eq("tun1"), uidCaptor.capture());
10626         assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
10627 
10628         reset(mBpfNetMaps);
10629         lp = new LinkProperties();
10630         lp.setInterfaceName("tun1");
10631         lp.addRoute(new RouteInfo(new IpPrefix("192.0.2.0/24"), null, "tun1"));
10632         mMockVpn.sendLinkProperties(lp);
10633         waitForIdle();
10634         // VPN not routing everything should no longer have interface filtering rules
10635         verify(mBpfNetMaps).removeUidInterfaceRules(uidCaptor.capture());
10636         assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
10637 
10638         reset(mBpfNetMaps);
10639         lp = new LinkProperties();
10640         lp.setInterfaceName("tun1");
10641         lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), RTN_UNREACHABLE));
10642         lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
10643         mMockVpn.sendLinkProperties(lp);
10644         waitForIdle();
10645         // Back to routing all IPv6 traffic should have filtering rules
10646         verify(mBpfNetMaps).addUidInterfaceRules(eq("tun1"), uidCaptor.capture());
10647         assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
10648     }
10649 
10650     @Test
10651     public void testStartVpnProfileFromDiffPackage() throws Exception {
10652         final String notMyVpnPkg = "com.not.my.vpn";
10653         assertThrows(
10654                 SecurityException.class, () -> mVpnManagerService.startVpnProfile(notMyVpnPkg));
10655     }
10656 
10657     @Test
10658     public void testStopVpnProfileFromDiffPackage() throws Exception {
10659         final String notMyVpnPkg = "com.not.my.vpn";
10660         assertThrows(SecurityException.class, () -> mVpnManagerService.stopVpnProfile(notMyVpnPkg));
10661     }
10662 
10663     @Test
10664     public void testUidUpdateChangesInterfaceFilteringRule() throws Exception {
10665         LinkProperties lp = new LinkProperties();
10666         lp.setInterfaceName("tun0");
10667         lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), RTN_UNREACHABLE));
10668         lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
10669         // The uid range needs to cover the test app so the network is visible to it.
10670         final UidRange vpnRange = PRIMARY_UIDRANGE;
10671         final Set<UidRange> vpnRanges = Collections.singleton(vpnRange);
10672         mMockVpn.establish(lp, VPN_UID, vpnRanges);
10673         assertVpnUidRangesUpdated(true, vpnRanges, VPN_UID);
10674 
10675         reset(mBpfNetMaps);
10676         InOrder inOrder = inOrder(mBpfNetMaps);
10677 
10678         // Update to new range which is old range minus APP1, i.e. only APP2
10679         final Set<UidRange> newRanges = new HashSet<>(asList(
10680                 new UidRange(vpnRange.start, APP1_UID - 1),
10681                 new UidRange(APP1_UID + 1, vpnRange.stop)));
10682         mMockVpn.setUids(newRanges);
10683         waitForIdle();
10684 
10685         ArgumentCaptor<int[]> uidCaptor = ArgumentCaptor.forClass(int[].class);
10686         // Verify old rules are removed before new rules are added
10687         inOrder.verify(mBpfNetMaps).removeUidInterfaceRules(uidCaptor.capture());
10688         assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
10689         inOrder.verify(mBpfNetMaps).addUidInterfaceRules(eq("tun0"), uidCaptor.capture());
10690         assertContainsExactly(uidCaptor.getValue(), APP2_UID);
10691     }
10692 
10693     @Test
10694     public void testLinkPropertiesWithWakeOnLanForActiveNetwork() throws Exception {
10695         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
10696 
10697         LinkProperties wifiLp = new LinkProperties();
10698         wifiLp.setInterfaceName(WIFI_WOL_IFNAME);
10699         wifiLp.setWakeOnLanSupported(false);
10700 
10701         // Default network switch should update ifaces.
10702         mWiFiNetworkAgent.connect(false);
10703         mWiFiNetworkAgent.sendLinkProperties(wifiLp);
10704         waitForIdle();
10705 
10706         // ConnectivityService should have changed the WakeOnLanSupported to true
10707         wifiLp.setWakeOnLanSupported(true);
10708         assertEquals(wifiLp, mService.getActiveLinkProperties());
10709     }
10710 
10711     @Test
10712     public void testLegacyExtraInfoSentToNetworkMonitor() throws Exception {
10713         class TestNetworkAgent extends NetworkAgent {
10714             TestNetworkAgent(Context context, Looper looper, NetworkAgentConfig config) {
10715                 super(context, looper, "MockAgent", new NetworkCapabilities(),
10716                         new LinkProperties(), 40 , config, null /* provider */);
10717             }
10718         }
10719         final NetworkAgent naNoExtraInfo = new TestNetworkAgent(
10720                 mServiceContext, mCsHandlerThread.getLooper(), new NetworkAgentConfig());
10721         naNoExtraInfo.register();
10722         verify(mNetworkStack).makeNetworkMonitor(any(), isNull(String.class), any());
10723         naNoExtraInfo.unregister();
10724 
10725         reset(mNetworkStack);
10726         final NetworkAgentConfig config =
10727                 new NetworkAgentConfig.Builder().setLegacyExtraInfo("legacyinfo").build();
10728         final NetworkAgent naExtraInfo = new TestNetworkAgent(
10729                 mServiceContext, mCsHandlerThread.getLooper(), config);
10730         naExtraInfo.register();
10731         verify(mNetworkStack).makeNetworkMonitor(any(), eq("legacyinfo"), any());
10732         naExtraInfo.unregister();
10733     }
10734 
10735     // To avoid granting location permission bypass.
10736     private void denyAllLocationPrivilegedPermissions() {
10737         mServiceContext.setPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
10738                 PERMISSION_DENIED);
10739         mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_DENIED);
10740         mServiceContext.setPermission(NETWORK_STACK, PERMISSION_DENIED);
10741         mServiceContext.setPermission(Manifest.permission.NETWORK_SETUP_WIZARD,
10742                 PERMISSION_DENIED);
10743     }
10744 
10745     private void setupLocationPermissions(
10746             int targetSdk, boolean locationToggle, String op, String perm) throws Exception {
10747         denyAllLocationPrivilegedPermissions();
10748 
10749         final ApplicationInfo applicationInfo = new ApplicationInfo();
10750         applicationInfo.targetSdkVersion = targetSdk;
10751         doReturn(applicationInfo).when(mPackageManager)
10752                 .getApplicationInfoAsUser(anyString(), anyInt(), any());
10753         doReturn(targetSdk).when(mPackageManager).getTargetSdkVersion(any());
10754 
10755         doReturn(locationToggle).when(mLocationManager).isLocationEnabledForUser(any());
10756 
10757         if (op != null) {
10758             doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOpsManager).noteOp(
10759                     eq(op), eq(Process.myUid()), eq(mContext.getPackageName()),
10760                     eq(getAttributionTag()), anyString());
10761         }
10762 
10763         if (perm != null) {
10764             mServiceContext.setPermission(perm, PERMISSION_GRANTED);
10765         }
10766     }
10767 
10768     private int getOwnerUidNetCapsPermission(int ownerUid, int callerUid,
10769             boolean includeLocationSensitiveInfo) {
10770         final NetworkCapabilities netCap = new NetworkCapabilities().setOwnerUid(ownerUid);
10771 
10772         return mService.createWithLocationInfoSanitizedIfNecessaryWhenParceled(
10773                 netCap, includeLocationSensitiveInfo, Process.myUid(), callerUid,
10774                 mContext.getPackageName(), getAttributionTag())
10775                 .getOwnerUid();
10776     }
10777 
10778     private void verifyTransportInfoCopyNetCapsPermission(
10779             int callerUid, boolean includeLocationSensitiveInfo,
10780             boolean shouldMakeCopyWithLocationSensitiveFieldsParcelable) {
10781         final TransportInfo transportInfo = mock(TransportInfo.class);
10782         doReturn(REDACT_FOR_ACCESS_FINE_LOCATION).when(transportInfo).getApplicableRedactions();
10783         final NetworkCapabilities netCap =
10784                 new NetworkCapabilities().setTransportInfo(transportInfo);
10785 
10786         mService.createWithLocationInfoSanitizedIfNecessaryWhenParceled(
10787                 netCap, includeLocationSensitiveInfo, Process.myPid(), callerUid,
10788                 mContext.getPackageName(), getAttributionTag());
10789         if (shouldMakeCopyWithLocationSensitiveFieldsParcelable) {
10790             verify(transportInfo).makeCopy(REDACT_NONE);
10791         } else {
10792             verify(transportInfo).makeCopy(REDACT_FOR_ACCESS_FINE_LOCATION);
10793         }
10794     }
10795 
10796     private void verifyOwnerUidAndTransportInfoNetCapsPermission(
10797             boolean shouldInclLocationSensitiveOwnerUidWithoutIncludeFlag,
10798             boolean shouldInclLocationSensitiveOwnerUidWithIncludeFlag,
10799             boolean shouldInclLocationSensitiveTransportInfoWithoutIncludeFlag,
10800             boolean shouldInclLocationSensitiveTransportInfoWithIncludeFlag) {
10801         final int myUid = Process.myUid();
10802 
10803         final int expectedOwnerUidWithoutIncludeFlag =
10804                 shouldInclLocationSensitiveOwnerUidWithoutIncludeFlag
10805                         ? myUid : INVALID_UID;
10806         assertEquals(expectedOwnerUidWithoutIncludeFlag, getOwnerUidNetCapsPermission(
10807                 myUid, myUid, false /* includeLocationSensitiveInfo */));
10808 
10809         final int expectedOwnerUidWithIncludeFlag =
10810                 shouldInclLocationSensitiveOwnerUidWithIncludeFlag ? myUid : INVALID_UID;
10811         assertEquals(expectedOwnerUidWithIncludeFlag, getOwnerUidNetCapsPermission(
10812                 myUid, myUid, true /* includeLocationSensitiveInfo */));
10813 
10814         verifyTransportInfoCopyNetCapsPermission(myUid,
10815                 false, /* includeLocationSensitiveInfo */
10816                 shouldInclLocationSensitiveTransportInfoWithoutIncludeFlag);
10817 
10818         verifyTransportInfoCopyNetCapsPermission(myUid,
10819                 true, /* includeLocationSensitiveInfo */
10820                 shouldInclLocationSensitiveTransportInfoWithIncludeFlag);
10821 
10822     }
10823 
10824     private void verifyOwnerUidAndTransportInfoNetCapsPermissionPreS() {
10825         verifyOwnerUidAndTransportInfoNetCapsPermission(
10826                 // Ensure that owner uid is included even if the request asks to remove it (which is
10827                 // the default) since the app has necessary permissions and targetSdk < S.
10828                 true, /* shouldInclLocationSensitiveOwnerUidWithoutIncludeFlag */
10829                 true, /* shouldInclLocationSensitiveOwnerUidWithIncludeFlag */
10830                 // Ensure that location info is removed if the request asks to remove it even if the
10831                 // app has necessary permissions.
10832                 false, /* shouldInclLocationSensitiveTransportInfoWithoutIncludeFlag */
10833                 true /* shouldInclLocationSensitiveTransportInfoWithIncludeFlag */
10834         );
10835     }
10836 
10837     @Test
10838     public void testCreateWithLocationInfoSanitizedWithFineLocationAfterQPreS()
10839             throws Exception {
10840         setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
10841                 Manifest.permission.ACCESS_FINE_LOCATION);
10842 
10843         verifyOwnerUidAndTransportInfoNetCapsPermissionPreS();
10844     }
10845 
10846     @Test
10847     public void testCreateWithLocationInfoSanitizedWithFineLocationPreSWithAndWithoutCallbackFlag()
10848             throws Exception {
10849         setupLocationPermissions(Build.VERSION_CODES.R, true, AppOpsManager.OPSTR_FINE_LOCATION,
10850                 Manifest.permission.ACCESS_FINE_LOCATION);
10851 
10852         verifyOwnerUidAndTransportInfoNetCapsPermissionPreS();
10853     }
10854 
10855     @Test
10856     public void
10857             testCreateWithLocationInfoSanitizedWithFineLocationAfterSWithAndWithoutCallbackFlag()
10858             throws Exception {
10859         setupLocationPermissions(Build.VERSION_CODES.S, true, AppOpsManager.OPSTR_FINE_LOCATION,
10860                 Manifest.permission.ACCESS_FINE_LOCATION);
10861 
10862         verifyOwnerUidAndTransportInfoNetCapsPermission(
10863                 // Ensure that the owner UID is removed if the request asks us to remove it even
10864                 // if the app has necessary permissions since targetSdk >= S.
10865                 false, /* shouldInclLocationSensitiveOwnerUidWithoutIncludeFlag */
10866                 true, /* shouldInclLocationSensitiveOwnerUidWithIncludeFlag */
10867                 // Ensure that location info is removed if the request asks to remove it even if the
10868                 // app has necessary permissions.
10869                 false, /* shouldInclLocationSensitiveTransportInfoWithoutIncludeFlag */
10870                 true /* shouldInclLocationSensitiveTransportInfoWithIncludeFlag */
10871         );
10872     }
10873 
10874     @Test
10875     public void testCreateWithLocationInfoSanitizedWithCoarseLocationPreQ()
10876             throws Exception {
10877         setupLocationPermissions(Build.VERSION_CODES.P, true, AppOpsManager.OPSTR_COARSE_LOCATION,
10878                 Manifest.permission.ACCESS_COARSE_LOCATION);
10879 
10880         verifyOwnerUidAndTransportInfoNetCapsPermissionPreS();
10881     }
10882 
10883     private void verifyOwnerUidAndTransportInfoNetCapsNotIncluded() {
10884         verifyOwnerUidAndTransportInfoNetCapsPermission(
10885                 false, /* shouldInclLocationSensitiveOwnerUidWithoutIncludeFlag */
10886                 false, /* shouldInclLocationSensitiveOwnerUidWithIncludeFlag */
10887                 false, /* shouldInclLocationSensitiveTransportInfoWithoutIncludeFlag */
10888                 false /* shouldInclLocationSensitiveTransportInfoWithIncludeFlag */
10889         );
10890     }
10891 
10892     @Test
10893     public void testCreateWithLocationInfoSanitizedLocationOff() throws Exception {
10894         // Test that even with fine location permission, and UIDs matching, the UID is sanitized.
10895         setupLocationPermissions(Build.VERSION_CODES.Q, false, AppOpsManager.OPSTR_FINE_LOCATION,
10896                 Manifest.permission.ACCESS_FINE_LOCATION);
10897 
10898         verifyOwnerUidAndTransportInfoNetCapsNotIncluded();
10899     }
10900 
10901     @Test
10902     public void testCreateWithLocationInfoSanitizedWrongUid() throws Exception {
10903         // Test that even with fine location permission, not being the owner leads to sanitization.
10904         setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
10905                 Manifest.permission.ACCESS_FINE_LOCATION);
10906 
10907         final int myUid = Process.myUid();
10908         assertEquals(Process.INVALID_UID,
10909                 getOwnerUidNetCapsPermission(myUid + 1, myUid,
10910                         true /* includeLocationSensitiveInfo */));
10911     }
10912 
10913     @Test
10914     public void testCreateWithLocationInfoSanitizedWithCoarseLocationAfterQ()
10915             throws Exception {
10916         // Test that not having fine location permission leads to sanitization.
10917         setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_COARSE_LOCATION,
10918                 Manifest.permission.ACCESS_COARSE_LOCATION);
10919 
10920         verifyOwnerUidAndTransportInfoNetCapsNotIncluded();
10921     }
10922 
10923     @Test
10924     public void testCreateWithLocationInfoSanitizedWithCoarseLocationAfterS()
10925             throws Exception {
10926         // Test that not having fine location permission leads to sanitization.
10927         setupLocationPermissions(Build.VERSION_CODES.S, true, AppOpsManager.OPSTR_COARSE_LOCATION,
10928                 Manifest.permission.ACCESS_COARSE_LOCATION);
10929 
10930         verifyOwnerUidAndTransportInfoNetCapsNotIncluded();
10931     }
10932 
10933     @Test
10934     public void testCreateForCallerWithLocalMacAddressSanitizedWithLocalMacAddressPermission()
10935             throws Exception {
10936         mServiceContext.setPermission(Manifest.permission.LOCAL_MAC_ADDRESS, PERMISSION_GRANTED);
10937 
10938         final TransportInfo transportInfo = mock(TransportInfo.class);
10939         doReturn(REDACT_FOR_ACCESS_FINE_LOCATION | REDACT_FOR_LOCAL_MAC_ADDRESS)
10940                 .when(transportInfo).getApplicableRedactions();
10941         final NetworkCapabilities netCap =
10942                 new NetworkCapabilities().setTransportInfo(transportInfo);
10943 
10944         mService.createWithLocationInfoSanitizedIfNecessaryWhenParceled(
10945                 netCap, false /* includeLocationSensitiveInfoInTransportInfo */,
10946                 Process.myPid(), Process.myUid(),
10947                 mContext.getPackageName(), getAttributionTag());
10948         // don't redact MAC_ADDRESS fields, only location sensitive fields.
10949         verify(transportInfo).makeCopy(REDACT_FOR_ACCESS_FINE_LOCATION);
10950     }
10951 
10952     @Test
10953     public void testCreateForCallerWithLocalMacAddressSanitizedWithoutLocalMacAddressPermission()
10954             throws Exception {
10955         mServiceContext.setPermission(Manifest.permission.LOCAL_MAC_ADDRESS, PERMISSION_DENIED);
10956 
10957         final TransportInfo transportInfo = mock(TransportInfo.class);
10958         doReturn(REDACT_FOR_ACCESS_FINE_LOCATION | REDACT_FOR_LOCAL_MAC_ADDRESS)
10959                 .when(transportInfo).getApplicableRedactions();
10960         final NetworkCapabilities netCap =
10961                 new NetworkCapabilities().setTransportInfo(transportInfo);
10962 
10963         mService.createWithLocationInfoSanitizedIfNecessaryWhenParceled(
10964                 netCap, false /* includeLocationSensitiveInfoInTransportInfo */,
10965                 Process.myPid(), Process.myUid(),
10966                 mContext.getPackageName(), getAttributionTag());
10967         // redact both MAC_ADDRESS & location sensitive fields.
10968         verify(transportInfo).makeCopy(REDACT_FOR_ACCESS_FINE_LOCATION
10969                 | REDACT_FOR_LOCAL_MAC_ADDRESS);
10970     }
10971 
10972     @Test
10973     public void testCreateForCallerWithLocalMacAddressSanitizedWithSettingsPermission()
10974             throws Exception {
10975         mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_GRANTED);
10976 
10977         final TransportInfo transportInfo = mock(TransportInfo.class);
10978         doReturn(REDACT_FOR_ACCESS_FINE_LOCATION | REDACT_FOR_NETWORK_SETTINGS)
10979                 .when(transportInfo).getApplicableRedactions();
10980         final NetworkCapabilities netCap =
10981                 new NetworkCapabilities().setTransportInfo(transportInfo);
10982 
10983         mService.createWithLocationInfoSanitizedIfNecessaryWhenParceled(
10984                 netCap, false /* includeLocationSensitiveInfoInTransportInfo */,
10985                 Process.myPid(), Process.myUid(),
10986                 mContext.getPackageName(), getAttributionTag());
10987         // don't redact NETWORK_SETTINGS fields, only location sensitive fields.
10988         verify(transportInfo).makeCopy(REDACT_FOR_ACCESS_FINE_LOCATION);
10989     }
10990 
10991     @Test
10992     public void testCreateForCallerWithLocalMacAddressSanitizedWithoutSettingsPermission()
10993             throws Exception {
10994         mServiceContext.setPermission(Manifest.permission.LOCAL_MAC_ADDRESS, PERMISSION_DENIED);
10995 
10996         final TransportInfo transportInfo = mock(TransportInfo.class);
10997         doReturn(REDACT_FOR_ACCESS_FINE_LOCATION | REDACT_FOR_NETWORK_SETTINGS)
10998                 .when(transportInfo).getApplicableRedactions();
10999         final NetworkCapabilities netCap =
11000                 new NetworkCapabilities().setTransportInfo(transportInfo);
11001 
11002         mService.createWithLocationInfoSanitizedIfNecessaryWhenParceled(
11003                 netCap, false /* includeLocationSensitiveInfoInTransportInfo */,
11004                 Process.myPid(), Process.myUid(),
11005                 mContext.getPackageName(), getAttributionTag());
11006         // redact both NETWORK_SETTINGS & location sensitive fields.
11007         verify(transportInfo).makeCopy(
11008                 REDACT_FOR_ACCESS_FINE_LOCATION | REDACT_FOR_NETWORK_SETTINGS);
11009     }
11010 
11011     /**
11012      * Test TransportInfo to verify redaction mechanism.
11013      */
11014     private static class TestTransportInfo implements TransportInfo {
11015         public final boolean locationRedacted;
11016         public final boolean localMacAddressRedacted;
11017         public final boolean settingsRedacted;
11018 
11019         TestTransportInfo() {
11020             locationRedacted = false;
11021             localMacAddressRedacted = false;
11022             settingsRedacted = false;
11023         }
11024 
11025         TestTransportInfo(boolean locationRedacted, boolean localMacAddressRedacted,
11026                 boolean settingsRedacted) {
11027             this.locationRedacted = locationRedacted;
11028             this.localMacAddressRedacted =
11029                     localMacAddressRedacted;
11030             this.settingsRedacted = settingsRedacted;
11031         }
11032 
11033         @Override
11034         public TransportInfo makeCopy(@NetworkCapabilities.RedactionType long redactions) {
11035             return new TestTransportInfo(
11036                     locationRedacted | (redactions & REDACT_FOR_ACCESS_FINE_LOCATION) != 0,
11037                     localMacAddressRedacted | (redactions & REDACT_FOR_LOCAL_MAC_ADDRESS) != 0,
11038                     settingsRedacted | (redactions & REDACT_FOR_NETWORK_SETTINGS) != 0
11039             );
11040         }
11041 
11042         @Override
11043         public @NetworkCapabilities.RedactionType long getApplicableRedactions() {
11044             return REDACT_FOR_ACCESS_FINE_LOCATION | REDACT_FOR_LOCAL_MAC_ADDRESS
11045                     | REDACT_FOR_NETWORK_SETTINGS;
11046         }
11047 
11048         @Override
11049         public boolean equals(Object other) {
11050             if (!(other instanceof TestTransportInfo)) return false;
11051             TestTransportInfo that = (TestTransportInfo) other;
11052             return that.locationRedacted == this.locationRedacted
11053                     && that.localMacAddressRedacted == this.localMacAddressRedacted
11054                     && that.settingsRedacted == this.settingsRedacted;
11055         }
11056 
11057         @Override
11058         public int hashCode() {
11059             return Objects.hash(locationRedacted, localMacAddressRedacted, settingsRedacted);
11060         }
11061 
11062         @Override
11063         public String toString() {
11064             return String.format(
11065                     "TestTransportInfo{locationRedacted=%s macRedacted=%s settingsRedacted=%s}",
11066                     locationRedacted, localMacAddressRedacted, settingsRedacted);
11067         }
11068     }
11069 
11070     private TestTransportInfo getTestTransportInfo(NetworkCapabilities nc) {
11071         return (TestTransportInfo) nc.getTransportInfo();
11072     }
11073 
11074     private TestTransportInfo getTestTransportInfo(TestNetworkAgentWrapper n) {
11075         final NetworkCapabilities nc = mCm.getNetworkCapabilities(n.getNetwork());
11076         assertNotNull(nc);
11077         return getTestTransportInfo(nc);
11078     }
11079 
11080 
11081     private void verifyNetworkCallbackLocationDataInclusionUsingTransportInfoAndOwnerUidInNetCaps(
11082             @NonNull TestNetworkCallback wifiNetworkCallback, int actualOwnerUid,
11083             @NonNull TransportInfo actualTransportInfo, int expectedOwnerUid,
11084             @NonNull TransportInfo expectedTransportInfo) throws Exception {
11085         doReturn(Build.VERSION_CODES.S).when(mPackageManager).getTargetSdkVersion(anyString());
11086         final NetworkCapabilities ncTemplate =
11087                 new NetworkCapabilities()
11088                         .addTransportType(TRANSPORT_WIFI)
11089                         .setOwnerUid(actualOwnerUid);
11090 
11091         final NetworkRequest wifiRequest = new NetworkRequest.Builder()
11092                 .addTransportType(TRANSPORT_WIFI).build();
11093         mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
11094 
11095         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, new LinkProperties(),
11096                 ncTemplate);
11097         mWiFiNetworkAgent.connect(false);
11098 
11099         wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
11100 
11101         // Send network capabilities update with TransportInfo to trigger capabilities changed
11102         // callback.
11103         mWiFiNetworkAgent.setNetworkCapabilities(
11104                 ncTemplate.setTransportInfo(actualTransportInfo), true);
11105 
11106         wifiNetworkCallback.expectCapabilitiesThat(mWiFiNetworkAgent,
11107                 nc -> Objects.equals(expectedOwnerUid, nc.getOwnerUid())
11108                         && Objects.equals(expectedTransportInfo, nc.getTransportInfo()));
11109     }
11110 
11111     @Test
11112     public void testVerifyLocationDataIsNotIncludedWhenInclFlagNotSet() throws Exception {
11113         final TestNetworkCallback wifiNetworkCallack = new TestNetworkCallback();
11114         final int ownerUid = Process.myUid();
11115         final TransportInfo transportInfo = new TestTransportInfo();
11116         // Even though the test uid holds privileged permissions, mask location fields since
11117         // the callback did not explicitly opt-in to get location data.
11118         final TransportInfo sanitizedTransportInfo = new TestTransportInfo(
11119                 true, /* locationRedacted */
11120                 true, /* localMacAddressRedacted */
11121                 true /* settingsRedacted */
11122         );
11123         // Should not expect location data since the callback does not set the flag for including
11124         // location data.
11125         verifyNetworkCallbackLocationDataInclusionUsingTransportInfoAndOwnerUidInNetCaps(
11126                 wifiNetworkCallack, ownerUid, transportInfo, INVALID_UID, sanitizedTransportInfo);
11127     }
11128 
11129     @Test
11130     public void testTransportInfoRedactionInSynchronousCalls() throws Exception {
11131         final NetworkCapabilities ncTemplate = new NetworkCapabilities()
11132                 .addTransportType(TRANSPORT_WIFI)
11133                 .setTransportInfo(new TestTransportInfo());
11134 
11135         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, new LinkProperties(),
11136                 ncTemplate);
11137         mWiFiNetworkAgent.connect(true /* validated; waits for callback */);
11138 
11139         // NETWORK_SETTINGS redaction is controlled by the NETWORK_SETTINGS permission
11140         assertTrue(getTestTransportInfo(mWiFiNetworkAgent).settingsRedacted);
11141         withPermission(NETWORK_SETTINGS, () -> {
11142             assertFalse(getTestTransportInfo(mWiFiNetworkAgent).settingsRedacted);
11143         });
11144         assertTrue(getTestTransportInfo(mWiFiNetworkAgent).settingsRedacted);
11145 
11146         // LOCAL_MAC_ADDRESS redaction is controlled by the LOCAL_MAC_ADDRESS permission
11147         assertTrue(getTestTransportInfo(mWiFiNetworkAgent).localMacAddressRedacted);
11148         withPermission(LOCAL_MAC_ADDRESS, () -> {
11149             assertFalse(getTestTransportInfo(mWiFiNetworkAgent).localMacAddressRedacted);
11150         });
11151         assertTrue(getTestTransportInfo(mWiFiNetworkAgent).localMacAddressRedacted);
11152 
11153         // Synchronous getNetworkCapabilities calls never return unredacted location-sensitive
11154         // information.
11155         assertTrue(getTestTransportInfo(mWiFiNetworkAgent).locationRedacted);
11156         setupLocationPermissions(Build.VERSION_CODES.S, true, AppOpsManager.OPSTR_FINE_LOCATION,
11157                 Manifest.permission.ACCESS_FINE_LOCATION);
11158         assertTrue(getTestTransportInfo(mWiFiNetworkAgent).locationRedacted);
11159         denyAllLocationPrivilegedPermissions();
11160         assertTrue(getTestTransportInfo(mWiFiNetworkAgent).locationRedacted);
11161     }
11162 
11163     private void setupConnectionOwnerUid(int vpnOwnerUid, @VpnManager.VpnType int vpnType)
11164             throws Exception {
11165         final Set<UidRange> vpnRange = Collections.singleton(PRIMARY_UIDRANGE);
11166         mMockVpn.setVpnType(vpnType);
11167         mMockVpn.establish(new LinkProperties(), vpnOwnerUid, vpnRange);
11168         assertVpnUidRangesUpdated(true, vpnRange, vpnOwnerUid);
11169 
11170         final UnderlyingNetworkInfo underlyingNetworkInfo =
11171                 new UnderlyingNetworkInfo(vpnOwnerUid, VPN_IFNAME, new ArrayList<>());
11172         mMockVpn.setUnderlyingNetworkInfo(underlyingNetworkInfo);
11173         mDeps.setConnectionOwnerUid(42);
11174     }
11175 
11176     private void setupConnectionOwnerUidAsVpnApp(int vpnOwnerUid, @VpnManager.VpnType int vpnType)
11177             throws Exception {
11178         setupConnectionOwnerUid(vpnOwnerUid, vpnType);
11179 
11180         // Test as VPN app
11181         mServiceContext.setPermission(NETWORK_STACK, PERMISSION_DENIED);
11182         mServiceContext.setPermission(
11183                 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, PERMISSION_DENIED);
11184     }
11185 
11186     private ConnectionInfo getTestConnectionInfo() throws Exception {
11187         return new ConnectionInfo(
11188                 IPPROTO_TCP,
11189                 new InetSocketAddress(InetAddresses.parseNumericAddress("1.2.3.4"), 1234),
11190                 new InetSocketAddress(InetAddresses.parseNumericAddress("2.3.4.5"), 2345));
11191     }
11192 
11193     @Test
11194     public void testGetConnectionOwnerUidPlatformVpn() throws Exception {
11195         final int myUid = Process.myUid();
11196         setupConnectionOwnerUidAsVpnApp(myUid, VpnManager.TYPE_VPN_PLATFORM);
11197 
11198         assertEquals(INVALID_UID, mService.getConnectionOwnerUid(getTestConnectionInfo()));
11199     }
11200 
11201     @Test
11202     public void testGetConnectionOwnerUidVpnServiceWrongUser() throws Exception {
11203         final int myUid = Process.myUid();
11204         setupConnectionOwnerUidAsVpnApp(myUid + 1, VpnManager.TYPE_VPN_SERVICE);
11205 
11206         assertEquals(INVALID_UID, mService.getConnectionOwnerUid(getTestConnectionInfo()));
11207     }
11208 
11209     @Test
11210     public void testGetConnectionOwnerUidVpnServiceDoesNotThrow() throws Exception {
11211         final int myUid = Process.myUid();
11212         setupConnectionOwnerUidAsVpnApp(myUid, VpnManager.TYPE_VPN_SERVICE);
11213 
11214         assertEquals(42, mService.getConnectionOwnerUid(getTestConnectionInfo()));
11215     }
11216 
11217     @Test
11218     public void testGetConnectionOwnerUidVpnServiceNetworkStackDoesNotThrow() throws Exception {
11219         final int myUid = Process.myUid();
11220         setupConnectionOwnerUid(myUid, VpnManager.TYPE_VPN_SERVICE);
11221         mServiceContext.setPermission(NETWORK_STACK, PERMISSION_GRANTED);
11222 
11223         assertEquals(42, mService.getConnectionOwnerUid(getTestConnectionInfo()));
11224     }
11225 
11226     @Test
11227     public void testGetConnectionOwnerUidVpnServiceMainlineNetworkStackDoesNotThrow()
11228             throws Exception {
11229         final int myUid = Process.myUid();
11230         setupConnectionOwnerUid(myUid, VpnManager.TYPE_VPN_SERVICE);
11231         mServiceContext.setPermission(
11232                 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, PERMISSION_GRANTED);
11233 
11234         assertEquals(42, mService.getConnectionOwnerUid(getTestConnectionInfo()));
11235     }
11236 
11237     private static PackageInfo buildPackageInfo(boolean hasSystemPermission, int uid) {
11238         final PackageInfo packageInfo = new PackageInfo();
11239         if (hasSystemPermission) {
11240             packageInfo.requestedPermissions = new String[] {
11241                     CHANGE_NETWORK_STATE, CONNECTIVITY_USE_RESTRICTED_NETWORKS };
11242             packageInfo.requestedPermissionsFlags = new int[] {
11243                     REQUESTED_PERMISSION_GRANTED, REQUESTED_PERMISSION_GRANTED };
11244         } else {
11245             packageInfo.requestedPermissions = new String[0];
11246         }
11247         packageInfo.applicationInfo = new ApplicationInfo();
11248         packageInfo.applicationInfo.privateFlags = 0;
11249         packageInfo.applicationInfo.uid = UserHandle.getUid(UserHandle.USER_SYSTEM,
11250                 UserHandle.getAppId(uid));
11251         return packageInfo;
11252     }
11253 
11254     @Test
11255     public void testRegisterConnectivityDiagnosticsCallbackInvalidRequest() throws Exception {
11256         final NetworkRequest request =
11257                 new NetworkRequest(
11258                         new NetworkCapabilities(), TYPE_ETHERNET, 0, NetworkRequest.Type.NONE);
11259         try {
11260             mService.registerConnectivityDiagnosticsCallback(
11261                     mConnectivityDiagnosticsCallback, request, mContext.getPackageName());
11262             fail("registerConnectivityDiagnosticsCallback should throw on invalid NetworkRequest");
11263         } catch (IllegalArgumentException expected) {
11264         }
11265     }
11266 
11267     private void assertRouteInfoParcelMatches(RouteInfo route, RouteInfoParcel parcel) {
11268         assertEquals(route.getDestination().toString(), parcel.destination);
11269         assertEquals(route.getInterface(), parcel.ifName);
11270         assertEquals(route.getMtu(), parcel.mtu);
11271 
11272         switch (route.getType()) {
11273             case RouteInfo.RTN_UNICAST:
11274                 if (route.hasGateway()) {
11275                     assertEquals(route.getGateway().getHostAddress(), parcel.nextHop);
11276                 } else {
11277                     assertEquals(INetd.NEXTHOP_NONE, parcel.nextHop);
11278                 }
11279                 break;
11280             case RouteInfo.RTN_UNREACHABLE:
11281                 assertEquals(INetd.NEXTHOP_UNREACHABLE, parcel.nextHop);
11282                 break;
11283             case RouteInfo.RTN_THROW:
11284                 assertEquals(INetd.NEXTHOP_THROW, parcel.nextHop);
11285                 break;
11286             default:
11287                 assertEquals(INetd.NEXTHOP_NONE, parcel.nextHop);
11288                 break;
11289         }
11290     }
11291 
11292     private void assertRoutesAdded(int netId, RouteInfo... routes) throws Exception {
11293         // TODO: add @JavaDerive(equals=true) to RouteInfoParcel, use eq() directly, and delete
11294         // assertRouteInfoParcelMatches above.
11295         ArgumentCaptor<RouteInfoParcel> captor = ArgumentCaptor.forClass(RouteInfoParcel.class);
11296         verify(mMockNetd, times(routes.length)).networkAddRouteParcel(eq(netId), captor.capture());
11297         for (int i = 0; i < routes.length; i++) {
11298             assertRouteInfoParcelMatches(routes[i], captor.getAllValues().get(i));
11299         }
11300     }
11301 
11302     private void assertRoutesRemoved(int netId, RouteInfo... routes) throws Exception {
11303         ArgumentCaptor<RouteInfoParcel> captor = ArgumentCaptor.forClass(RouteInfoParcel.class);
11304         verify(mMockNetd, times(routes.length)).networkRemoveRouteParcel(eq(netId),
11305                 captor.capture());
11306         for (int i = 0; i < routes.length; i++) {
11307             assertRouteInfoParcelMatches(routes[i], captor.getAllValues().get(i));
11308         }
11309     }
11310 
11311     @Test
11312     public void testRegisterUnregisterConnectivityDiagnosticsCallback() throws Exception {
11313         final NetworkRequest wifiRequest =
11314                 new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI).build();
11315         doReturn(mIBinder).when(mConnectivityDiagnosticsCallback).asBinder();
11316 
11317         mService.registerConnectivityDiagnosticsCallback(
11318                 mConnectivityDiagnosticsCallback, wifiRequest, mContext.getPackageName());
11319 
11320         // Block until all other events are done processing.
11321         HandlerUtils.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
11322 
11323         verify(mIBinder).linkToDeath(any(ConnectivityDiagnosticsCallbackInfo.class), anyInt());
11324         verify(mConnectivityDiagnosticsCallback).asBinder();
11325         assertTrue(mService.mConnectivityDiagnosticsCallbacks.containsKey(mIBinder));
11326 
11327         mService.unregisterConnectivityDiagnosticsCallback(mConnectivityDiagnosticsCallback);
11328         verify(mIBinder, timeout(TIMEOUT_MS))
11329                 .unlinkToDeath(any(ConnectivityDiagnosticsCallbackInfo.class), anyInt());
11330         assertFalse(mService.mConnectivityDiagnosticsCallbacks.containsKey(mIBinder));
11331         verify(mConnectivityDiagnosticsCallback, atLeastOnce()).asBinder();
11332     }
11333 
11334     @Test
11335     public void testRegisterDuplicateConnectivityDiagnosticsCallback() throws Exception {
11336         final NetworkRequest wifiRequest =
11337                 new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI).build();
11338         doReturn(mIBinder).when(mConnectivityDiagnosticsCallback).asBinder();
11339 
11340         mService.registerConnectivityDiagnosticsCallback(
11341                 mConnectivityDiagnosticsCallback, wifiRequest, mContext.getPackageName());
11342 
11343         // Block until all other events are done processing.
11344         HandlerUtils.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
11345 
11346         verify(mIBinder).linkToDeath(any(ConnectivityDiagnosticsCallbackInfo.class), anyInt());
11347         verify(mConnectivityDiagnosticsCallback).asBinder();
11348         assertTrue(mService.mConnectivityDiagnosticsCallbacks.containsKey(mIBinder));
11349 
11350         // Register the same callback again
11351         mService.registerConnectivityDiagnosticsCallback(
11352                 mConnectivityDiagnosticsCallback, wifiRequest, mContext.getPackageName());
11353 
11354         // Block until all other events are done processing.
11355         HandlerUtils.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
11356 
11357         assertTrue(mService.mConnectivityDiagnosticsCallbacks.containsKey(mIBinder));
11358     }
11359 
11360     @Test(expected = NullPointerException.class)
11361     public void testRegisterConnectivityDiagnosticsCallbackNullCallback() {
11362         mService.registerConnectivityDiagnosticsCallback(
11363                 null /* callback */,
11364                 new NetworkRequest.Builder().build(),
11365                 mContext.getPackageName());
11366     }
11367 
11368     @Test(expected = NullPointerException.class)
11369     public void testRegisterConnectivityDiagnosticsCallbackNullNetworkRequest() {
11370         mService.registerConnectivityDiagnosticsCallback(
11371                 mConnectivityDiagnosticsCallback,
11372                 null /* request */,
11373                 mContext.getPackageName());
11374     }
11375 
11376     @Test(expected = NullPointerException.class)
11377     public void testRegisterConnectivityDiagnosticsCallbackNullPackageName() {
11378         mService.registerConnectivityDiagnosticsCallback(
11379                 mConnectivityDiagnosticsCallback,
11380                 new NetworkRequest.Builder().build(),
11381                 null /* callingPackageName */);
11382     }
11383 
11384     @Test(expected = NullPointerException.class)
11385     public void testUnregisterConnectivityDiagnosticsCallbackNullPackageName() {
11386         mService.unregisterConnectivityDiagnosticsCallback(null /* callback */);
11387     }
11388 
11389     public NetworkAgentInfo fakeMobileNai(NetworkCapabilities nc) {
11390         final NetworkCapabilities cellNc = new NetworkCapabilities.Builder(nc)
11391                 .addTransportType(TRANSPORT_CELLULAR).build();
11392         final NetworkInfo info = new NetworkInfo(TYPE_MOBILE, TelephonyManager.NETWORK_TYPE_LTE,
11393                 ConnectivityManager.getNetworkTypeName(TYPE_MOBILE),
11394                 TelephonyManager.getNetworkTypeName(TelephonyManager.NETWORK_TYPE_LTE));
11395         return fakeNai(cellNc, info);
11396     }
11397 
11398     private NetworkAgentInfo fakeWifiNai(NetworkCapabilities nc) {
11399         final NetworkCapabilities wifiNc = new NetworkCapabilities.Builder(nc)
11400                 .addTransportType(TRANSPORT_WIFI).build();
11401         final NetworkInfo info = new NetworkInfo(TYPE_WIFI, 0 /* subtype */,
11402                 ConnectivityManager.getNetworkTypeName(TYPE_WIFI), "" /* subtypeName */);
11403         return fakeNai(wifiNc, info);
11404     }
11405 
11406     private NetworkAgentInfo fakeVpnNai(NetworkCapabilities nc) {
11407         final NetworkCapabilities vpnNc = new NetworkCapabilities.Builder(nc)
11408                 .addTransportType(TRANSPORT_VPN).build();
11409         final NetworkInfo info = new NetworkInfo(TYPE_VPN, 0 /* subtype */,
11410                 ConnectivityManager.getNetworkTypeName(TYPE_VPN), "" /* subtypeName */);
11411         return fakeNai(vpnNc, info);
11412     }
11413 
11414     private NetworkAgentInfo fakeNai(NetworkCapabilities nc, NetworkInfo networkInfo) {
11415         return new NetworkAgentInfo(null, new Network(NET_ID), networkInfo, new LinkProperties(),
11416                 nc, new NetworkScore.Builder().setLegacyInt(0).build(),
11417                 mServiceContext, null, new NetworkAgentConfig(), mService, null, null, 0,
11418                 INVALID_UID, TEST_LINGER_DELAY_MS, mQosCallbackTracker,
11419                 new ConnectivityService.Dependencies());
11420     }
11421 
11422     @Test
11423     public void testCheckConnectivityDiagnosticsPermissionsNetworkStack() throws Exception {
11424         final NetworkAgentInfo naiWithoutUid = fakeMobileNai(new NetworkCapabilities());
11425 
11426         mServiceContext.setPermission(NETWORK_STACK, PERMISSION_GRANTED);
11427         assertTrue(
11428                 "NetworkStack permission not applied",
11429                 mService.checkConnectivityDiagnosticsPermissions(
11430                         Process.myPid(), Process.myUid(), naiWithoutUid,
11431                         mContext.getOpPackageName()));
11432     }
11433 
11434     @Test
11435     public void testCheckConnectivityDiagnosticsPermissionsWrongUidPackageName() throws Exception {
11436         final int wrongUid = Process.myUid() + 1;
11437 
11438         final NetworkCapabilities nc = new NetworkCapabilities();
11439         nc.setAdministratorUids(new int[] {wrongUid});
11440         final NetworkAgentInfo naiWithUid = fakeWifiNai(nc);
11441 
11442         mServiceContext.setPermission(NETWORK_STACK, PERMISSION_DENIED);
11443 
11444         assertFalse(
11445                 "Mismatched uid/package name should not pass the location permission check",
11446                 mService.checkConnectivityDiagnosticsPermissions(
11447                         Process.myPid() + 1, wrongUid, naiWithUid, mContext.getOpPackageName()));
11448     }
11449 
11450     private void verifyConnectivityDiagnosticsPermissionsWithNetworkAgentInfo(
11451             NetworkAgentInfo info, boolean expectPermission) {
11452         mServiceContext.setPermission(NETWORK_STACK, PERMISSION_DENIED);
11453 
11454         assertEquals(
11455                 "Unexpected ConnDiags permission",
11456                 expectPermission,
11457                 mService.checkConnectivityDiagnosticsPermissions(
11458                         Process.myPid(), Process.myUid(), info, mContext.getOpPackageName()));
11459     }
11460 
11461     @Test
11462     public void testCheckConnectivityDiagnosticsPermissionsCellularNoLocationPermission()
11463             throws Exception {
11464         final NetworkCapabilities nc = new NetworkCapabilities();
11465         nc.setAdministratorUids(new int[] {Process.myUid()});
11466         final NetworkAgentInfo naiWithUid = fakeMobileNai(nc);
11467 
11468         verifyConnectivityDiagnosticsPermissionsWithNetworkAgentInfo(naiWithUid,
11469                 true /* expectPermission */);
11470     }
11471 
11472     @Test
11473     public void testCheckConnectivityDiagnosticsPermissionsWifiNoLocationPermission()
11474             throws Exception {
11475         final NetworkCapabilities nc = new NetworkCapabilities();
11476         nc.setAdministratorUids(new int[] {Process.myUid()});
11477         final NetworkAgentInfo naiWithUid = fakeWifiNai(nc);
11478 
11479         verifyConnectivityDiagnosticsPermissionsWithNetworkAgentInfo(naiWithUid,
11480                 false /* expectPermission */);
11481     }
11482 
11483     @Test
11484     public void testCheckConnectivityDiagnosticsPermissionsActiveVpn() throws Exception {
11485         final NetworkAgentInfo naiWithoutUid = fakeMobileNai(new NetworkCapabilities());
11486 
11487         mMockVpn.establishForMyUid();
11488         assertUidRangesUpdatedForMyUid(true);
11489 
11490         // Wait for networks to connect and broadcasts to be sent before removing permissions.
11491         waitForIdle();
11492         setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
11493                 Manifest.permission.ACCESS_FINE_LOCATION);
11494 
11495         assertTrue(mMockVpn.setUnderlyingNetworks(new Network[] {naiWithoutUid.network}));
11496         waitForIdle();
11497         assertTrue(
11498                 "Active VPN permission not applied",
11499                 mService.checkConnectivityDiagnosticsPermissions(
11500                         Process.myPid(), Process.myUid(), naiWithoutUid,
11501                         mContext.getOpPackageName()));
11502 
11503         assertTrue(mMockVpn.setUnderlyingNetworks(null));
11504         waitForIdle();
11505         assertFalse(
11506                 "VPN shouldn't receive callback on non-underlying network",
11507                 mService.checkConnectivityDiagnosticsPermissions(
11508                         Process.myPid(), Process.myUid(), naiWithoutUid,
11509                         mContext.getOpPackageName()));
11510     }
11511 
11512     @Test
11513     public void testCheckConnectivityDiagnosticsPermissionsNetworkAdministrator() throws Exception {
11514         final NetworkCapabilities nc = new NetworkCapabilities();
11515         nc.setAdministratorUids(new int[] {Process.myUid()});
11516         final NetworkAgentInfo naiWithUid = fakeMobileNai(nc);
11517 
11518         setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
11519                 Manifest.permission.ACCESS_FINE_LOCATION);
11520         mServiceContext.setPermission(NETWORK_STACK, PERMISSION_DENIED);
11521 
11522         assertTrue(
11523                 "NetworkCapabilities administrator uid permission not applied",
11524                 mService.checkConnectivityDiagnosticsPermissions(
11525                         Process.myPid(), Process.myUid(), naiWithUid, mContext.getOpPackageName()));
11526     }
11527 
11528     @Test
11529     public void testCheckConnectivityDiagnosticsPermissionsFails() throws Exception {
11530         final NetworkCapabilities nc = new NetworkCapabilities();
11531         nc.setOwnerUid(Process.myUid());
11532         nc.setAdministratorUids(new int[] {Process.myUid()});
11533         final NetworkAgentInfo naiWithUid = fakeMobileNai(nc);
11534 
11535         setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
11536                 Manifest.permission.ACCESS_FINE_LOCATION);
11537         mServiceContext.setPermission(NETWORK_STACK, PERMISSION_DENIED);
11538 
11539         // Use wrong pid and uid
11540         assertFalse(
11541                 "Permissions allowed when they shouldn't be granted",
11542                 mService.checkConnectivityDiagnosticsPermissions(
11543                         Process.myPid() + 1, Process.myUid() + 1, naiWithUid,
11544                         mContext.getOpPackageName()));
11545     }
11546 
11547     @Test
11548     public void testUnderlyingNetworksWillBeSetInNetworkAgentInfoConstructor() throws Exception {
11549         assumeTrue(SdkLevel.isAtLeastT());
11550         final Network network1 = new Network(100);
11551         final Network network2 = new Network(101);
11552         final List<Network> underlyingNetworks = new ArrayList<>();
11553         final NetworkCapabilities ncWithEmptyUnderlyingNetworks = new NetworkCapabilities.Builder()
11554                 .setUnderlyingNetworks(underlyingNetworks)
11555                 .build();
11556         final NetworkAgentInfo vpnNaiWithEmptyUnderlyingNetworks =
11557                 fakeVpnNai(ncWithEmptyUnderlyingNetworks);
11558         assertEquals(underlyingNetworks,
11559                 Arrays.asList(vpnNaiWithEmptyUnderlyingNetworks.declaredUnderlyingNetworks));
11560 
11561         underlyingNetworks.add(network1);
11562         underlyingNetworks.add(network2);
11563         final NetworkCapabilities ncWithUnderlyingNetworks = new NetworkCapabilities.Builder()
11564                 .setUnderlyingNetworks(underlyingNetworks)
11565                 .build();
11566         final NetworkAgentInfo vpnNaiWithUnderlyingNetwokrs = fakeVpnNai(ncWithUnderlyingNetworks);
11567         assertEquals(underlyingNetworks,
11568                 Arrays.asList(vpnNaiWithUnderlyingNetwokrs.declaredUnderlyingNetworks));
11569 
11570         final NetworkCapabilities ncWithoutUnderlyingNetworks = new NetworkCapabilities.Builder()
11571                 .build();
11572         final NetworkAgentInfo vpnNaiWithoutUnderlyingNetwokrs =
11573                 fakeVpnNai(ncWithoutUnderlyingNetworks);
11574         assertNull(vpnNaiWithoutUnderlyingNetwokrs.declaredUnderlyingNetworks);
11575     }
11576 
11577     @Test
11578     public void testRegisterConnectivityDiagnosticsCallbackCallsOnConnectivityReport()
11579             throws Exception {
11580         // Set up the Network, which leads to a ConnectivityReport being cached for the network.
11581         final TestNetworkCallback callback = new TestNetworkCallback();
11582         mCm.registerDefaultNetworkCallback(callback);
11583         final LinkProperties linkProperties = new LinkProperties();
11584         linkProperties.setInterfaceName(INTERFACE_NAME);
11585         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, linkProperties);
11586         mCellNetworkAgent.connect(true);
11587         callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
11588         callback.assertNoCallback();
11589 
11590         final NetworkRequest request = new NetworkRequest.Builder().build();
11591         doReturn(mIBinder).when(mConnectivityDiagnosticsCallback).asBinder();
11592 
11593         mServiceContext.setPermission(NETWORK_STACK, PERMISSION_GRANTED);
11594 
11595         mService.registerConnectivityDiagnosticsCallback(
11596                 mConnectivityDiagnosticsCallback, request, mContext.getPackageName());
11597 
11598         verify(mConnectivityDiagnosticsCallback, timeout(TIMEOUT_MS))
11599                 .onConnectivityReportAvailable(argThat(report -> {
11600                     return INTERFACE_NAME.equals(report.getLinkProperties().getInterfaceName())
11601                             && report.getNetworkCapabilities().hasTransport(TRANSPORT_CELLULAR);
11602                 }));
11603     }
11604 
11605     private void setUpConnectivityDiagnosticsCallback() throws Exception {
11606         final NetworkRequest request = new NetworkRequest.Builder().build();
11607         doReturn(mIBinder).when(mConnectivityDiagnosticsCallback).asBinder();
11608 
11609         mServiceContext.setPermission(NETWORK_STACK, PERMISSION_GRANTED);
11610 
11611         mService.registerConnectivityDiagnosticsCallback(
11612                 mConnectivityDiagnosticsCallback, request, mContext.getPackageName());
11613 
11614         // Block until all other events are done processing.
11615         HandlerUtils.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
11616 
11617         // Connect the cell agent verify that it notifies TestNetworkCallback that it is available
11618         final TestNetworkCallback callback = new TestNetworkCallback();
11619         mCm.registerDefaultNetworkCallback(callback);
11620 
11621         final NetworkCapabilities ncTemplate = new NetworkCapabilities()
11622                 .addTransportType(TRANSPORT_CELLULAR)
11623                 .setTransportInfo(new TestTransportInfo());
11624         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, new LinkProperties(),
11625                 ncTemplate);
11626         mCellNetworkAgent.connect(true);
11627         callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
11628         callback.assertNoCallback();
11629 
11630         // Make sure a report is sent and that the caps are suitably redacted.
11631         verify(mConnectivityDiagnosticsCallback, timeout(TIMEOUT_MS))
11632                 .onConnectivityReportAvailable(argThat(report ->
11633                         areConnDiagCapsRedacted(report.getNetworkCapabilities())));
11634         reset(mConnectivityDiagnosticsCallback);
11635     }
11636 
11637     private boolean areConnDiagCapsRedacted(NetworkCapabilities nc) {
11638         TestTransportInfo ti = getTestTransportInfo(nc);
11639         return nc.getUids() == null
11640                 && nc.getAdministratorUids().length == 0
11641                 && nc.getOwnerUid() == Process.INVALID_UID
11642                 && ti.locationRedacted
11643                 && ti.localMacAddressRedacted
11644                 && ti.settingsRedacted;
11645     }
11646 
11647     @Test
11648     public void testConnectivityDiagnosticsCallbackOnDataStallSuspected() throws Exception {
11649         setUpConnectivityDiagnosticsCallback();
11650 
11651         // Trigger notifyDataStallSuspected() on the INetworkMonitorCallbacks instance in the
11652         // cellular network agent
11653         mCellNetworkAgent.notifyDataStallSuspected();
11654 
11655         // Verify onDataStallSuspected fired
11656         verify(mConnectivityDiagnosticsCallback, timeout(TIMEOUT_MS)).onDataStallSuspected(
11657                 argThat(report -> areConnDiagCapsRedacted(report.getNetworkCapabilities())));
11658     }
11659 
11660     @Test
11661     public void testConnectivityDiagnosticsCallbackOnConnectivityReported() throws Exception {
11662         setUpConnectivityDiagnosticsCallback();
11663 
11664         final Network n = mCellNetworkAgent.getNetwork();
11665         final boolean hasConnectivity = true;
11666         mService.reportNetworkConnectivity(n, hasConnectivity);
11667 
11668         // Verify onNetworkConnectivityReported fired
11669         verify(mConnectivityDiagnosticsCallback, timeout(TIMEOUT_MS))
11670                 .onNetworkConnectivityReported(eq(n), eq(hasConnectivity));
11671         verify(mConnectivityDiagnosticsCallback, timeout(TIMEOUT_MS))
11672                 .onConnectivityReportAvailable(
11673                         argThat(report ->
11674                                 areConnDiagCapsRedacted(report.getNetworkCapabilities())));
11675 
11676         final boolean noConnectivity = false;
11677         mService.reportNetworkConnectivity(n, noConnectivity);
11678 
11679         // Wait for onNetworkConnectivityReported to fire
11680         verify(mConnectivityDiagnosticsCallback, timeout(TIMEOUT_MS))
11681                 .onNetworkConnectivityReported(eq(n), eq(noConnectivity));
11682 
11683         // Also expect a ConnectivityReport after NetworkMonitor asynchronously re-validates
11684         verify(mConnectivityDiagnosticsCallback, timeout(TIMEOUT_MS).times(2))
11685                 .onConnectivityReportAvailable(
11686                         argThat(report ->
11687                                 areConnDiagCapsRedacted(report.getNetworkCapabilities())));
11688     }
11689 
11690     @Test
11691     public void testConnectivityDiagnosticsCallbackOnConnectivityReportedSeparateUid()
11692             throws Exception {
11693         setUpConnectivityDiagnosticsCallback();
11694 
11695         // report known Connectivity from a different uid. Verify that network is not re-validated
11696         // and this callback is not notified.
11697         final Network n = mCellNetworkAgent.getNetwork();
11698         final boolean hasConnectivity = true;
11699         doAsUid(Process.myUid() + 1, () -> mService.reportNetworkConnectivity(n, hasConnectivity));
11700 
11701         // Block until all other events are done processing.
11702         HandlerUtils.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
11703 
11704         // Verify onNetworkConnectivityReported did not fire
11705         verify(mConnectivityDiagnosticsCallback, never())
11706                 .onNetworkConnectivityReported(any(), anyBoolean());
11707         verify(mConnectivityDiagnosticsCallback, never())
11708                 .onConnectivityReportAvailable(any());
11709 
11710         // report different Connectivity from a different uid. Verify that network is re-validated
11711         // and that this callback is notified.
11712         final boolean noConnectivity = false;
11713         doAsUid(Process.myUid() + 1, () -> mService.reportNetworkConnectivity(n, noConnectivity));
11714 
11715         // Wait for onNetworkConnectivityReported to fire
11716         verify(mConnectivityDiagnosticsCallback, timeout(TIMEOUT_MS))
11717                 .onNetworkConnectivityReported(eq(n), eq(noConnectivity));
11718 
11719         // Also expect a ConnectivityReport after NetworkMonitor asynchronously re-validates
11720         verify(mConnectivityDiagnosticsCallback, timeout(TIMEOUT_MS))
11721                 .onConnectivityReportAvailable(
11722                         argThat(report ->
11723                                 areConnDiagCapsRedacted(report.getNetworkCapabilities())));
11724     }
11725 
11726     @Test(expected = NullPointerException.class)
11727     public void testSimulateDataStallNullNetwork() {
11728         mService.simulateDataStall(
11729                 DataStallReport.DETECTION_METHOD_DNS_EVENTS,
11730                 0L /* timestampMillis */,
11731                 null /* network */,
11732                 new PersistableBundle());
11733     }
11734 
11735     @Test(expected = NullPointerException.class)
11736     public void testSimulateDataStallNullPersistableBundle() {
11737         mService.simulateDataStall(
11738                 DataStallReport.DETECTION_METHOD_DNS_EVENTS,
11739                 0L /* timestampMillis */,
11740                 mock(Network.class),
11741                 null /* extras */);
11742     }
11743 
11744     @Test
11745     public void testRouteAddDeleteUpdate() throws Exception {
11746         final NetworkRequest request = new NetworkRequest.Builder().build();
11747         final TestNetworkCallback networkCallback = new TestNetworkCallback();
11748         mCm.registerNetworkCallback(request, networkCallback);
11749         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
11750         reset(mMockNetd);
11751         mCellNetworkAgent.connect(false);
11752         networkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
11753         final int netId = mCellNetworkAgent.getNetwork().netId;
11754 
11755         final String iface = "rmnet_data0";
11756         final InetAddress gateway = InetAddress.getByName("fe80::5678");
11757         RouteInfo direct = RouteInfo.makeHostRoute(gateway, iface);
11758         RouteInfo rio1 = new RouteInfo(new IpPrefix("2001:db8:1::/48"), gateway, iface);
11759         RouteInfo rio2 = new RouteInfo(new IpPrefix("2001:db8:2::/48"), gateway, iface);
11760         RouteInfo defaultRoute = new RouteInfo((IpPrefix) null, gateway, iface);
11761         RouteInfo defaultWithMtu = new RouteInfo(null, gateway, iface, RouteInfo.RTN_UNICAST,
11762                                                  1280 /* mtu */);
11763 
11764         // Send LinkProperties and check that we ask netd to add routes.
11765         LinkProperties lp = new LinkProperties();
11766         lp.setInterfaceName(iface);
11767         lp.addRoute(direct);
11768         lp.addRoute(rio1);
11769         lp.addRoute(defaultRoute);
11770         mCellNetworkAgent.sendLinkProperties(lp);
11771         networkCallback.expectLinkPropertiesThat(mCellNetworkAgent, x -> x.getRoutes().size() == 3);
11772 
11773         assertRoutesAdded(netId, direct, rio1, defaultRoute);
11774         reset(mMockNetd);
11775 
11776         // Send updated LinkProperties and check that we ask netd to add, remove, update routes.
11777         assertTrue(lp.getRoutes().contains(defaultRoute));
11778         lp.removeRoute(rio1);
11779         lp.addRoute(rio2);
11780         lp.addRoute(defaultWithMtu);
11781         // Ensure adding the same route with a different MTU replaces the previous route.
11782         assertFalse(lp.getRoutes().contains(defaultRoute));
11783         assertTrue(lp.getRoutes().contains(defaultWithMtu));
11784 
11785         mCellNetworkAgent.sendLinkProperties(lp);
11786         networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
11787                 x -> x.getRoutes().contains(rio2));
11788 
11789         assertRoutesRemoved(netId, rio1);
11790         assertRoutesAdded(netId, rio2);
11791 
11792         ArgumentCaptor<RouteInfoParcel> captor = ArgumentCaptor.forClass(RouteInfoParcel.class);
11793         verify(mMockNetd).networkUpdateRouteParcel(eq(netId), captor.capture());
11794         assertRouteInfoParcelMatches(defaultWithMtu, captor.getValue());
11795 
11796 
11797         mCm.unregisterNetworkCallback(networkCallback);
11798     }
11799 
11800     @Test
11801     public void testDumpDoesNotCrash() {
11802         mServiceContext.setPermission(DUMP, PERMISSION_GRANTED);
11803         // Filing a couple requests prior to testing the dump.
11804         final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback();
11805         final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
11806         final NetworkRequest genericRequest = new NetworkRequest.Builder()
11807                 .clearCapabilities().build();
11808         final NetworkRequest wifiRequest = new NetworkRequest.Builder()
11809                 .addTransportType(TRANSPORT_WIFI).build();
11810         mCm.registerNetworkCallback(genericRequest, genericNetworkCallback);
11811         mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
11812         final StringWriter stringWriter = new StringWriter();
11813 
11814         mService.dump(new FileDescriptor(), new PrintWriter(stringWriter), new String[0]);
11815 
11816         assertFalse(stringWriter.toString().isEmpty());
11817     }
11818 
11819     @Test
11820     public void testRequestsSortedByIdSortsCorrectly() {
11821         final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback();
11822         final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
11823         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
11824         final NetworkRequest genericRequest = new NetworkRequest.Builder()
11825                 .clearCapabilities().build();
11826         final NetworkRequest wifiRequest = new NetworkRequest.Builder()
11827                 .addTransportType(TRANSPORT_WIFI).build();
11828         final NetworkRequest cellRequest = new NetworkRequest.Builder()
11829                 .addTransportType(TRANSPORT_CELLULAR).build();
11830         mCm.registerNetworkCallback(genericRequest, genericNetworkCallback);
11831         mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
11832         mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
11833         waitForIdle();
11834 
11835         final NetworkRequestInfo[] nriOutput = mService.requestsSortedById();
11836 
11837         assertTrue(nriOutput.length > 1);
11838         for (int i = 0; i < nriOutput.length - 1; i++) {
11839             final boolean isRequestIdInOrder =
11840                     nriOutput[i].mRequests.get(0).requestId
11841                             < nriOutput[i + 1].mRequests.get(0).requestId;
11842             assertTrue(isRequestIdInOrder);
11843         }
11844     }
11845 
11846     private void assertUidRangesUpdatedForMyUid(boolean add) throws Exception {
11847         final int uid = Process.myUid();
11848         assertVpnUidRangesUpdated(add, uidRangesForUids(uid), uid);
11849     }
11850 
11851     private void assertVpnUidRangesUpdated(boolean add, Set<UidRange> vpnRanges, int exemptUid)
11852             throws Exception {
11853         InOrder inOrder = inOrder(mMockNetd);
11854         ArgumentCaptor<int[]> exemptUidCaptor = ArgumentCaptor.forClass(int[].class);
11855 
11856         inOrder.verify(mMockNetd, times(1)).socketDestroy(eq(toUidRangeStableParcels(vpnRanges)),
11857                 exemptUidCaptor.capture());
11858         assertContainsExactly(exemptUidCaptor.getValue(), Process.VPN_UID, exemptUid);
11859 
11860         if (add) {
11861             inOrder.verify(mMockNetd, times(1)).networkAddUidRangesParcel(
11862                     new NativeUidRangeConfig(mMockVpn.getNetwork().getNetId(),
11863                             toUidRangeStableParcels(vpnRanges), PREFERENCE_ORDER_VPN));
11864         } else {
11865             inOrder.verify(mMockNetd, times(1)).networkRemoveUidRangesParcel(
11866                     new NativeUidRangeConfig(mMockVpn.getNetwork().getNetId(),
11867                             toUidRangeStableParcels(vpnRanges), PREFERENCE_ORDER_VPN));
11868         }
11869 
11870         inOrder.verify(mMockNetd, times(1)).socketDestroy(eq(toUidRangeStableParcels(vpnRanges)),
11871                 exemptUidCaptor.capture());
11872         assertContainsExactly(exemptUidCaptor.getValue(), Process.VPN_UID, exemptUid);
11873     }
11874 
11875     @Test
11876     public void testVpnUidRangesUpdate() throws Exception {
11877         // Set up a WiFi network without proxy.
11878         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
11879         mWiFiNetworkAgent.connect(true);
11880         assertNull(mService.getProxyForNetwork(null));
11881         assertNull(mCm.getDefaultProxy());
11882 
11883         final ExpectedBroadcast b1 = registerPacProxyBroadcast();
11884         final LinkProperties lp = new LinkProperties();
11885         lp.setInterfaceName("tun0");
11886         lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
11887         lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
11888         final UidRange vpnRange = PRIMARY_UIDRANGE;
11889         final Set<UidRange> vpnRanges = Collections.singleton(vpnRange);
11890         mMockVpn.establish(lp, VPN_UID, vpnRanges);
11891         assertVpnUidRangesUpdated(true, vpnRanges, VPN_UID);
11892         // VPN is connected but proxy is not set, so there is no need to send proxy broadcast.
11893         b1.expectNoBroadcast(500);
11894 
11895         // Update to new range which is old range minus APP1, i.e. only APP2
11896         final ExpectedBroadcast b2 = registerPacProxyBroadcast();
11897         final Set<UidRange> newRanges = new HashSet<>(asList(
11898                 new UidRange(vpnRange.start, APP1_UID - 1),
11899                 new UidRange(APP1_UID + 1, vpnRange.stop)));
11900         mMockVpn.setUids(newRanges);
11901         waitForIdle();
11902 
11903         assertVpnUidRangesUpdated(true, newRanges, VPN_UID);
11904         assertVpnUidRangesUpdated(false, vpnRanges, VPN_UID);
11905 
11906         // Uid has changed but proxy is not set, so there is no need to send proxy broadcast.
11907         b2.expectNoBroadcast(500);
11908 
11909         final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
11910         final ExpectedBroadcast b3 = registerPacProxyBroadcast();
11911         lp.setHttpProxy(testProxyInfo);
11912         mMockVpn.sendLinkProperties(lp);
11913         waitForIdle();
11914         // Proxy is set, so send a proxy broadcast.
11915         b3.expectBroadcast();
11916 
11917         final ExpectedBroadcast b4 = registerPacProxyBroadcast();
11918         mMockVpn.setUids(vpnRanges);
11919         waitForIdle();
11920         // Uid has changed and proxy is already set, so send a proxy broadcast.
11921         b4.expectBroadcast();
11922 
11923         final ExpectedBroadcast b5 = registerPacProxyBroadcast();
11924         // Proxy is removed, send a proxy broadcast.
11925         lp.setHttpProxy(null);
11926         mMockVpn.sendLinkProperties(lp);
11927         waitForIdle();
11928         b5.expectBroadcast();
11929 
11930         // Proxy is added in WiFi(default network), setDefaultProxy will be called.
11931         final LinkProperties wifiLp = mCm.getLinkProperties(mWiFiNetworkAgent.getNetwork());
11932         assertNotNull(wifiLp);
11933         final ExpectedBroadcast b6 = expectProxyChangeAction(testProxyInfo);
11934         wifiLp.setHttpProxy(testProxyInfo);
11935         mWiFiNetworkAgent.sendLinkProperties(wifiLp);
11936         waitForIdle();
11937         b6.expectBroadcast();
11938     }
11939 
11940     @Test
11941     public void testProxyBroadcastWillBeSentWhenVpnHasProxyAndConnects() throws Exception {
11942         // Set up a WiFi network without proxy.
11943         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
11944         mWiFiNetworkAgent.connect(true);
11945         assertNull(mService.getProxyForNetwork(null));
11946         assertNull(mCm.getDefaultProxy());
11947 
11948         final LinkProperties lp = new LinkProperties();
11949         lp.setInterfaceName("tun0");
11950         lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
11951         lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
11952         final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
11953         lp.setHttpProxy(testProxyInfo);
11954         final UidRange vpnRange = PRIMARY_UIDRANGE;
11955         final Set<UidRange> vpnRanges = Collections.singleton(vpnRange);
11956         final ExpectedBroadcast b1 = registerPacProxyBroadcast();
11957         mMockVpn.setOwnerAndAdminUid(VPN_UID);
11958         mMockVpn.registerAgent(false, vpnRanges, lp);
11959         // In any case, the proxy broadcast won't be sent before VPN goes into CONNECTED state.
11960         // Otherwise, the app that calls ConnectivityManager#getDefaultProxy() when it receives the
11961         // proxy broadcast will get null.
11962         b1.expectNoBroadcast(500);
11963 
11964         final ExpectedBroadcast b2 = registerPacProxyBroadcast();
11965         mMockVpn.connect(true /* validated */, true /* hasInternet */, false /* isStrictMode */);
11966         waitForIdle();
11967         assertVpnUidRangesUpdated(true, vpnRanges, VPN_UID);
11968         // Vpn is connected with proxy, so the proxy broadcast will be sent to inform the apps to
11969         // update their proxy data.
11970         b2.expectBroadcast();
11971     }
11972 
11973     @Test
11974     public void testProxyBroadcastWillBeSentWhenTheProxyOfNonDefaultNetworkHasChanged()
11975             throws Exception {
11976         // Set up a CELLULAR network without proxy.
11977         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
11978         mCellNetworkAgent.connect(true);
11979         assertNull(mService.getProxyForNetwork(null));
11980         assertNull(mCm.getDefaultProxy());
11981         // CELLULAR network should be the default network.
11982         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
11983 
11984         // Set up a WiFi network without proxy.
11985         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
11986         mWiFiNetworkAgent.connect(true);
11987         assertNull(mService.getProxyForNetwork(null));
11988         assertNull(mCm.getDefaultProxy());
11989         // WiFi network should be the default network.
11990         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
11991         // CELLULAR network is not the default network.
11992         assertNotEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
11993 
11994         // CELLULAR network is not the system default network, but it might be a per-app default
11995         // network. The proxy broadcast should be sent once its proxy has changed.
11996         final LinkProperties cellularLp = new LinkProperties();
11997         cellularLp.setInterfaceName(MOBILE_IFNAME);
11998         final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
11999         final ExpectedBroadcast b = registerPacProxyBroadcast();
12000         cellularLp.setHttpProxy(testProxyInfo);
12001         mCellNetworkAgent.sendLinkProperties(cellularLp);
12002         b.expectBroadcast();
12003     }
12004 
12005     @Test
12006     public void testInvalidRequestTypes() {
12007         final int[] invalidReqTypeInts = new int[]{-1, NetworkRequest.Type.NONE.ordinal(),
12008                 NetworkRequest.Type.LISTEN.ordinal(), NetworkRequest.Type.values().length};
12009         final NetworkCapabilities nc = new NetworkCapabilities().addTransportType(TRANSPORT_WIFI);
12010 
12011         for (int reqTypeInt : invalidReqTypeInts) {
12012             assertThrows("Expect throws for invalid request type " + reqTypeInt,
12013                     IllegalArgumentException.class,
12014                     () -> mService.requestNetwork(Process.INVALID_UID, nc, reqTypeInt, null, 0,
12015                             null, ConnectivityManager.TYPE_NONE, NetworkCallback.FLAG_NONE,
12016                             mContext.getPackageName(), getAttributionTag())
12017             );
12018         }
12019     }
12020 
12021     @Test
12022     public void testKeepConnected() throws Exception {
12023         setAlwaysOnNetworks(false);
12024         registerDefaultNetworkCallbacks();
12025         final TestNetworkCallback allNetworksCb = new TestNetworkCallback();
12026         final NetworkRequest allNetworksRequest = new NetworkRequest.Builder().clearCapabilities()
12027                 .build();
12028         mCm.registerNetworkCallback(allNetworksRequest, allNetworksCb);
12029 
12030         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
12031         mCellNetworkAgent.connect(true /* validated */);
12032 
12033         mDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
12034         allNetworksCb.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
12035 
12036         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
12037         mWiFiNetworkAgent.connect(true /* validated */);
12038 
12039         mDefaultNetworkCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
12040         // While the default callback doesn't see the network before it's validated, the listen
12041         // sees the network come up and validate later
12042         allNetworksCb.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
12043         allNetworksCb.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
12044         allNetworksCb.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
12045         allNetworksCb.expectCallback(CallbackEntry.LOST, mCellNetworkAgent,
12046                 TEST_LINGER_DELAY_MS * 2);
12047 
12048         // The cell network has disconnected (see LOST above) because it was outscored and
12049         // had no requests (see setAlwaysOnNetworks(false) above)
12050         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
12051         final NetworkScore score = new NetworkScore.Builder().setLegacyInt(30).build();
12052         mCellNetworkAgent.setScore(score);
12053         mCellNetworkAgent.connect(false /* validated */);
12054 
12055         // The cell network gets torn down right away.
12056         allNetworksCb.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
12057         allNetworksCb.expectCallback(CallbackEntry.LOST, mCellNetworkAgent,
12058                 TEST_NASCENT_DELAY_MS * 2);
12059         allNetworksCb.assertNoCallback();
12060 
12061         // Now create a cell network with KEEP_CONNECTED_FOR_HANDOVER and make sure it's
12062         // not disconnected immediately when outscored.
12063         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
12064         final NetworkScore scoreKeepup = new NetworkScore.Builder().setLegacyInt(30)
12065                 .setKeepConnectedReason(KEEP_CONNECTED_FOR_HANDOVER).build();
12066         mCellNetworkAgent.setScore(scoreKeepup);
12067         mCellNetworkAgent.connect(true /* validated */);
12068 
12069         allNetworksCb.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
12070         mDefaultNetworkCallback.assertNoCallback();
12071 
12072         mWiFiNetworkAgent.disconnect();
12073 
12074         allNetworksCb.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
12075         mDefaultNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
12076         mDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
12077 
12078         // Reconnect a WiFi network and make sure the cell network is still not torn down.
12079         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
12080         mWiFiNetworkAgent.connect(true /* validated */);
12081 
12082         allNetworksCb.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
12083         mDefaultNetworkCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
12084 
12085         // Now remove the reason to keep connected and make sure the network lingers and is
12086         // torn down.
12087         mCellNetworkAgent.setScore(new NetworkScore.Builder().setLegacyInt(30).build());
12088         allNetworksCb.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent,
12089                 TEST_NASCENT_DELAY_MS * 2);
12090         allNetworksCb.expectCallback(CallbackEntry.LOST, mCellNetworkAgent,
12091                 TEST_LINGER_DELAY_MS * 2);
12092         mDefaultNetworkCallback.assertNoCallback();
12093 
12094         mCm.unregisterNetworkCallback(allNetworksCb);
12095         // mDefaultNetworkCallback will be unregistered by tearDown()
12096     }
12097 
12098     private class QosCallbackMockHelper {
12099         @NonNull public final QosFilter mFilter;
12100         @NonNull public final IQosCallback mCallback;
12101         @NonNull public final TestNetworkAgentWrapper mAgentWrapper;
12102         @NonNull private final List<IQosCallback> mCallbacks = new ArrayList();
12103 
12104         QosCallbackMockHelper() throws Exception {
12105             Log.d(TAG, "QosCallbackMockHelper: ");
12106             mFilter = mock(QosFilter.class);
12107 
12108             // Ensure the network is disconnected before anything else occurs
12109             assertNull(mCellNetworkAgent);
12110 
12111             mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
12112             mCellNetworkAgent.connect(true);
12113 
12114             verifyActiveNetwork(TRANSPORT_CELLULAR);
12115             waitForIdle();
12116             final Network network = mCellNetworkAgent.getNetwork();
12117 
12118             final Pair<IQosCallback, IBinder> pair = createQosCallback();
12119             mCallback = pair.first;
12120 
12121             doReturn(network).when(mFilter).getNetwork();
12122             doReturn(QosCallbackException.EX_TYPE_FILTER_NONE).when(mFilter).validate();
12123             mAgentWrapper = mCellNetworkAgent;
12124         }
12125 
12126         void registerQosCallback(@NonNull final QosFilter filter,
12127                 @NonNull final IQosCallback callback) {
12128             mCallbacks.add(callback);
12129             final NetworkAgentInfo nai =
12130                     mService.getNetworkAgentInfoForNetwork(filter.getNetwork());
12131             mService.registerQosCallbackInternal(filter, callback, nai);
12132         }
12133 
12134         void tearDown() {
12135             for (int i = 0; i < mCallbacks.size(); i++) {
12136                 mService.unregisterQosCallback(mCallbacks.get(i));
12137             }
12138         }
12139     }
12140 
12141     private Pair<IQosCallback, IBinder> createQosCallback() {
12142         final IQosCallback callback = mock(IQosCallback.class);
12143         final IBinder binder = mock(Binder.class);
12144         doReturn(binder).when(callback).asBinder();
12145         doReturn(true).when(binder).isBinderAlive();
12146         return new Pair<>(callback, binder);
12147     }
12148 
12149 
12150     @Test
12151     public void testQosCallbackRegistration() throws Exception {
12152         mQosCallbackMockHelper = new QosCallbackMockHelper();
12153         final NetworkAgentWrapper wrapper = mQosCallbackMockHelper.mAgentWrapper;
12154 
12155         doReturn(QosCallbackException.EX_TYPE_FILTER_NONE)
12156                 .when(mQosCallbackMockHelper.mFilter).validate();
12157         mQosCallbackMockHelper.registerQosCallback(
12158                 mQosCallbackMockHelper.mFilter, mQosCallbackMockHelper.mCallback);
12159 
12160         final NetworkAgentWrapper.CallbackType.OnQosCallbackRegister cbRegister1 =
12161                 (NetworkAgentWrapper.CallbackType.OnQosCallbackRegister)
12162                         wrapper.getCallbackHistory().poll(1000, x -> true);
12163         assertNotNull(cbRegister1);
12164 
12165         final int registerCallbackId = cbRegister1.mQosCallbackId;
12166         mService.unregisterQosCallback(mQosCallbackMockHelper.mCallback);
12167         final NetworkAgentWrapper.CallbackType.OnQosCallbackUnregister cbUnregister;
12168         cbUnregister = (NetworkAgentWrapper.CallbackType.OnQosCallbackUnregister)
12169                 wrapper.getCallbackHistory().poll(1000, x -> true);
12170         assertNotNull(cbUnregister);
12171         assertEquals(registerCallbackId, cbUnregister.mQosCallbackId);
12172         assertNull(wrapper.getCallbackHistory().poll(200, x -> true));
12173     }
12174 
12175     @Test
12176     public void testQosCallbackNoRegistrationOnValidationError() throws Exception {
12177         mQosCallbackMockHelper = new QosCallbackMockHelper();
12178 
12179         doReturn(QosCallbackException.EX_TYPE_FILTER_NETWORK_RELEASED)
12180                 .when(mQosCallbackMockHelper.mFilter).validate();
12181         mQosCallbackMockHelper.registerQosCallback(
12182                 mQosCallbackMockHelper.mFilter, mQosCallbackMockHelper.mCallback);
12183         waitForIdle();
12184         verify(mQosCallbackMockHelper.mCallback)
12185                 .onError(eq(QosCallbackException.EX_TYPE_FILTER_NETWORK_RELEASED));
12186     }
12187 
12188     @Test
12189     public void testQosCallbackAvailableAndLost() throws Exception {
12190         mQosCallbackMockHelper = new QosCallbackMockHelper();
12191         final int sessionId = 10;
12192         final int qosCallbackId = 1;
12193 
12194         doReturn(QosCallbackException.EX_TYPE_FILTER_NONE)
12195                 .when(mQosCallbackMockHelper.mFilter).validate();
12196         mQosCallbackMockHelper.registerQosCallback(
12197                 mQosCallbackMockHelper.mFilter, mQosCallbackMockHelper.mCallback);
12198         waitForIdle();
12199 
12200         final EpsBearerQosSessionAttributes attributes = new EpsBearerQosSessionAttributes(
12201                 1, 2, 3, 4, 5, new ArrayList<>());
12202         mQosCallbackMockHelper.mAgentWrapper.getNetworkAgent()
12203                 .sendQosSessionAvailable(qosCallbackId, sessionId, attributes);
12204         waitForIdle();
12205 
12206         verify(mQosCallbackMockHelper.mCallback).onQosEpsBearerSessionAvailable(argThat(session ->
12207                 session.getSessionId() == sessionId
12208                         && session.getSessionType() == QosSession.TYPE_EPS_BEARER), eq(attributes));
12209 
12210         mQosCallbackMockHelper.mAgentWrapper.getNetworkAgent()
12211                 .sendQosSessionLost(qosCallbackId, sessionId, QosSession.TYPE_EPS_BEARER);
12212         waitForIdle();
12213         verify(mQosCallbackMockHelper.mCallback).onQosSessionLost(argThat(session ->
12214                 session.getSessionId() == sessionId
12215                         && session.getSessionType() == QosSession.TYPE_EPS_BEARER));
12216     }
12217 
12218     @Test
12219     public void testNrQosCallbackAvailableAndLost() throws Exception {
12220         mQosCallbackMockHelper = new QosCallbackMockHelper();
12221         final int sessionId = 10;
12222         final int qosCallbackId = 1;
12223 
12224         doReturn(QosCallbackException.EX_TYPE_FILTER_NONE)
12225                 .when(mQosCallbackMockHelper.mFilter).validate();
12226         mQosCallbackMockHelper.registerQosCallback(
12227                 mQosCallbackMockHelper.mFilter, mQosCallbackMockHelper.mCallback);
12228         waitForIdle();
12229 
12230         final NrQosSessionAttributes attributes = new NrQosSessionAttributes(
12231                 1, 2, 3, 4, 5, 6, 7, new ArrayList<>());
12232         mQosCallbackMockHelper.mAgentWrapper.getNetworkAgent()
12233                 .sendQosSessionAvailable(qosCallbackId, sessionId, attributes);
12234         waitForIdle();
12235 
12236         verify(mQosCallbackMockHelper.mCallback).onNrQosSessionAvailable(argThat(session ->
12237                 session.getSessionId() == sessionId
12238                         && session.getSessionType() == QosSession.TYPE_NR_BEARER), eq(attributes));
12239 
12240         mQosCallbackMockHelper.mAgentWrapper.getNetworkAgent()
12241                 .sendQosSessionLost(qosCallbackId, sessionId, QosSession.TYPE_NR_BEARER);
12242         waitForIdle();
12243         verify(mQosCallbackMockHelper.mCallback).onQosSessionLost(argThat(session ->
12244                 session.getSessionId() == sessionId
12245                         && session.getSessionType() == QosSession.TYPE_NR_BEARER));
12246     }
12247 
12248     @Test
12249     public void testQosCallbackTooManyRequests() throws Exception {
12250         mQosCallbackMockHelper = new QosCallbackMockHelper();
12251 
12252         doReturn(QosCallbackException.EX_TYPE_FILTER_NONE)
12253                 .when(mQosCallbackMockHelper.mFilter).validate();
12254         for (int i = 0; i < 100; i++) {
12255             final Pair<IQosCallback, IBinder> pair = createQosCallback();
12256 
12257             try {
12258                 mQosCallbackMockHelper.registerQosCallback(
12259                         mQosCallbackMockHelper.mFilter, pair.first);
12260             } catch (ServiceSpecificException e) {
12261                 assertEquals(e.errorCode, ConnectivityManager.Errors.TOO_MANY_REQUESTS);
12262                 if (i < 50) {
12263                     fail("TOO_MANY_REQUESTS thrown too early, the count is " + i);
12264                 }
12265 
12266                 // As long as there is at least 50 requests, it is safe to assume it works.
12267                 // Note: The count isn't being tested precisely against 100 because the counter
12268                 // is shared with request network.
12269                 return;
12270             }
12271         }
12272         fail("TOO_MANY_REQUESTS never thrown");
12273     }
12274 
12275     private void mockGetApplicationInfo(@NonNull final String packageName, final int uid) {
12276         mockGetApplicationInfo(packageName, uid, PRIMARY_USER_HANDLE);
12277     }
12278 
12279     private void mockGetApplicationInfo(@NonNull final String packageName, final int uid,
12280             @NonNull final UserHandle user) {
12281         final ApplicationInfo applicationInfo = new ApplicationInfo();
12282         applicationInfo.uid = uid;
12283         try {
12284             doReturn(applicationInfo).when(mPackageManager).getApplicationInfoAsUser(
12285                     eq(packageName), anyInt(), eq(user));
12286         } catch (Exception e) {
12287             fail(e.getMessage());
12288         }
12289     }
12290 
12291     private void mockGetApplicationInfoThrowsNameNotFound(@NonNull final String packageName,
12292             @NonNull final UserHandle user)
12293             throws Exception {
12294         doThrow(new PackageManager.NameNotFoundException(packageName)).when(
12295                 mPackageManager).getApplicationInfoAsUser(eq(packageName), anyInt(), eq(user));
12296     }
12297 
12298     private void mockHasSystemFeature(@NonNull final String featureName, final boolean hasFeature) {
12299         doReturn(hasFeature).when(mPackageManager).hasSystemFeature(eq(featureName));
12300     }
12301 
12302     private Range<Integer> getNriFirstUidRange(@NonNull final NetworkRequestInfo nri) {
12303         return nri.mRequests.get(0).networkCapabilities.getUids().iterator().next();
12304     }
12305 
12306     private OemNetworkPreferences createDefaultOemNetworkPreferences(
12307             @OemNetworkPreferences.OemNetworkPreference final int preference) {
12308         // Arrange PackageManager mocks
12309         mockGetApplicationInfo(TEST_PACKAGE_NAME, TEST_PACKAGE_UID);
12310 
12311         // Build OemNetworkPreferences object
12312         return new OemNetworkPreferences.Builder()
12313                 .addNetworkPreference(TEST_PACKAGE_NAME, preference)
12314                 .build();
12315     }
12316 
12317     @Test
12318     public void testOemNetworkRequestFactoryPreferenceUninitializedThrowsError() {
12319         @OemNetworkPreferences.OemNetworkPreference final int prefToTest =
12320                 OEM_NETWORK_PREFERENCE_UNINITIALIZED;
12321 
12322         // Act on OemNetworkRequestFactory.createNrisFromOemNetworkPreferences()
12323         assertThrows(IllegalArgumentException.class,
12324                 () -> mService.new OemNetworkRequestFactory()
12325                         .createNrisFromOemNetworkPreferences(
12326                                 createDefaultOemNetworkPreferences(prefToTest)));
12327     }
12328 
12329     @Test
12330     public void testOemNetworkRequestFactoryPreferenceOemPaid()
12331             throws Exception {
12332         // Expectations
12333         final int expectedNumOfNris = 1;
12334         final int expectedNumOfRequests = 3;
12335 
12336         @OemNetworkPreferences.OemNetworkPreference final int prefToTest =
12337                 OEM_NETWORK_PREFERENCE_OEM_PAID;
12338 
12339         // Act on OemNetworkRequestFactory.createNrisFromOemNetworkPreferences()
12340         final ArraySet<NetworkRequestInfo> nris =
12341                 mService.new OemNetworkRequestFactory()
12342                         .createNrisFromOemNetworkPreferences(
12343                                 createDefaultOemNetworkPreferences(prefToTest));
12344         final NetworkRequestInfo nri = nris.iterator().next();
12345         assertEquals(PREFERENCE_ORDER_OEM, nri.mPreferenceOrder);
12346         final List<NetworkRequest> mRequests = nri.mRequests;
12347         assertEquals(expectedNumOfNris, nris.size());
12348         assertEquals(expectedNumOfRequests, mRequests.size());
12349         assertTrue(mRequests.get(0).isListen());
12350         assertTrue(mRequests.get(0).hasCapability(NET_CAPABILITY_NOT_METERED));
12351         assertTrue(mRequests.get(0).hasCapability(NET_CAPABILITY_VALIDATED));
12352         assertTrue(mRequests.get(1).isRequest());
12353         assertTrue(mRequests.get(1).hasCapability(NET_CAPABILITY_OEM_PAID));
12354         assertEquals(NetworkRequest.Type.TRACK_DEFAULT, mRequests.get(2).type);
12355         assertTrue(mService.getDefaultRequest().networkCapabilities.equalsNetCapabilities(
12356                 mRequests.get(2).networkCapabilities));
12357     }
12358 
12359     @Test
12360     public void testOemNetworkRequestFactoryPreferenceOemPaidNoFallback()
12361             throws Exception {
12362         // Expectations
12363         final int expectedNumOfNris = 1;
12364         final int expectedNumOfRequests = 2;
12365 
12366         @OemNetworkPreferences.OemNetworkPreference final int prefToTest =
12367                 OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK;
12368 
12369         // Act on OemNetworkRequestFactory.createNrisFromOemNetworkPreferences()
12370         final ArraySet<NetworkRequestInfo> nris =
12371                 mService.new OemNetworkRequestFactory()
12372                         .createNrisFromOemNetworkPreferences(
12373                                 createDefaultOemNetworkPreferences(prefToTest));
12374         final NetworkRequestInfo nri = nris.iterator().next();
12375         assertEquals(PREFERENCE_ORDER_OEM, nri.mPreferenceOrder);
12376         final List<NetworkRequest> mRequests = nri.mRequests;
12377         assertEquals(expectedNumOfNris, nris.size());
12378         assertEquals(expectedNumOfRequests, mRequests.size());
12379         assertTrue(mRequests.get(0).isListen());
12380         assertTrue(mRequests.get(0).hasCapability(NET_CAPABILITY_NOT_METERED));
12381         assertTrue(mRequests.get(0).hasCapability(NET_CAPABILITY_VALIDATED));
12382         assertTrue(mRequests.get(1).isRequest());
12383         assertTrue(mRequests.get(1).hasCapability(NET_CAPABILITY_OEM_PAID));
12384     }
12385 
12386     @Test
12387     public void testOemNetworkRequestFactoryPreferenceOemPaidOnly()
12388             throws Exception {
12389         // Expectations
12390         final int expectedNumOfNris = 1;
12391         final int expectedNumOfRequests = 1;
12392 
12393         @OemNetworkPreferences.OemNetworkPreference final int prefToTest =
12394                 OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY;
12395 
12396         // Act on OemNetworkRequestFactory.createNrisFromOemNetworkPreferences()
12397         final ArraySet<NetworkRequestInfo> nris =
12398                 mService.new OemNetworkRequestFactory()
12399                         .createNrisFromOemNetworkPreferences(
12400                                 createDefaultOemNetworkPreferences(prefToTest));
12401         final NetworkRequestInfo nri = nris.iterator().next();
12402         assertEquals(PREFERENCE_ORDER_OEM, nri.mPreferenceOrder);
12403         final List<NetworkRequest> mRequests = nri.mRequests;
12404         assertEquals(expectedNumOfNris, nris.size());
12405         assertEquals(expectedNumOfRequests, mRequests.size());
12406         assertTrue(mRequests.get(0).isRequest());
12407         assertTrue(mRequests.get(0).hasCapability(NET_CAPABILITY_OEM_PAID));
12408     }
12409 
12410     @Test
12411     public void testOemNetworkRequestFactoryPreferenceOemPrivateOnly()
12412             throws Exception {
12413         // Expectations
12414         final int expectedNumOfNris = 1;
12415         final int expectedNumOfRequests = 1;
12416 
12417         @OemNetworkPreferences.OemNetworkPreference final int prefToTest =
12418                 OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY;
12419 
12420         // Act on OemNetworkRequestFactory.createNrisFromOemNetworkPreferences()
12421         final ArraySet<NetworkRequestInfo> nris =
12422                 mService.new OemNetworkRequestFactory()
12423                         .createNrisFromOemNetworkPreferences(
12424                                 createDefaultOemNetworkPreferences(prefToTest));
12425         final NetworkRequestInfo nri = nris.iterator().next();
12426         assertEquals(PREFERENCE_ORDER_OEM, nri.mPreferenceOrder);
12427         final List<NetworkRequest> mRequests = nri.mRequests;
12428         assertEquals(expectedNumOfNris, nris.size());
12429         assertEquals(expectedNumOfRequests, mRequests.size());
12430         assertTrue(mRequests.get(0).isRequest());
12431         assertTrue(mRequests.get(0).hasCapability(NET_CAPABILITY_OEM_PRIVATE));
12432         assertFalse(mRequests.get(0).hasCapability(NET_CAPABILITY_OEM_PAID));
12433     }
12434 
12435     @Test
12436     public void testOemNetworkRequestFactoryCreatesCorrectNumOfNris()
12437             throws Exception {
12438         // Expectations
12439         final int expectedNumOfNris = 2;
12440 
12441         // Arrange PackageManager mocks
12442         final String testPackageName2 = "com.google.apps.dialer";
12443         mockGetApplicationInfo(TEST_PACKAGE_NAME, TEST_PACKAGE_UID);
12444         mockGetApplicationInfo(testPackageName2, TEST_PACKAGE_UID);
12445 
12446         // Build OemNetworkPreferences object
12447         final int testOemPref = OEM_NETWORK_PREFERENCE_OEM_PAID;
12448         final int testOemPref2 = OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK;
12449         final OemNetworkPreferences pref = new OemNetworkPreferences.Builder()
12450                 .addNetworkPreference(TEST_PACKAGE_NAME, testOemPref)
12451                 .addNetworkPreference(testPackageName2, testOemPref2)
12452                 .build();
12453 
12454         // Act on OemNetworkRequestFactory.createNrisFromOemNetworkPreferences()
12455         final ArraySet<NetworkRequestInfo> nris =
12456                 mService.new OemNetworkRequestFactory().createNrisFromOemNetworkPreferences(pref);
12457 
12458         assertNotNull(nris);
12459         assertEquals(expectedNumOfNris, nris.size());
12460     }
12461 
12462     @Test
12463     public void testOemNetworkRequestFactoryMultiplePrefsCorrectlySetsUids()
12464             throws Exception {
12465         // Arrange PackageManager mocks
12466         final String testPackageName2 = "com.google.apps.dialer";
12467         final int testPackageNameUid2 = 456;
12468         mockGetApplicationInfo(TEST_PACKAGE_NAME, TEST_PACKAGE_UID);
12469         mockGetApplicationInfo(testPackageName2, testPackageNameUid2);
12470 
12471         // Build OemNetworkPreferences object
12472         final int testOemPref = OEM_NETWORK_PREFERENCE_OEM_PAID;
12473         final int testOemPref2 = OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK;
12474         final OemNetworkPreferences pref = new OemNetworkPreferences.Builder()
12475                 .addNetworkPreference(TEST_PACKAGE_NAME, testOemPref)
12476                 .addNetworkPreference(testPackageName2, testOemPref2)
12477                 .build();
12478 
12479         // Act on OemNetworkRequestFactory.createNrisFromOemNetworkPreferences()
12480         final List<NetworkRequestInfo> nris =
12481                 new ArrayList<>(
12482                         mService.new OemNetworkRequestFactory().createNrisFromOemNetworkPreferences(
12483                                 pref));
12484 
12485         // Sort by uid to access nris by index
12486         nris.sort(Comparator.comparingInt(nri -> getNriFirstUidRange(nri).getLower()));
12487         assertEquals(TEST_PACKAGE_UID, (int) getNriFirstUidRange(nris.get(0)).getLower());
12488         assertEquals(TEST_PACKAGE_UID, (int) getNriFirstUidRange(nris.get(0)).getUpper());
12489         assertEquals(testPackageNameUid2, (int) getNriFirstUidRange(nris.get(1)).getLower());
12490         assertEquals(testPackageNameUid2, (int) getNriFirstUidRange(nris.get(1)).getUpper());
12491     }
12492 
12493     @Test
12494     public void testOemNetworkRequestFactoryMultipleUsersSetsUids()
12495             throws Exception {
12496         // Arrange users
12497         final int secondUserTestPackageUid = UserHandle.getUid(SECONDARY_USER, TEST_PACKAGE_UID);
12498         final int thirdUserTestPackageUid = UserHandle.getUid(TERTIARY_USER, TEST_PACKAGE_UID);
12499         doReturn(asList(PRIMARY_USER_HANDLE, SECONDARY_USER_HANDLE, TERTIARY_USER_HANDLE))
12500                 .when(mUserManager).getUserHandles(anyBoolean());
12501 
12502         // Arrange PackageManager mocks testing for users who have and don't have a package.
12503         mockGetApplicationInfoThrowsNameNotFound(TEST_PACKAGE_NAME, PRIMARY_USER_HANDLE);
12504         mockGetApplicationInfo(TEST_PACKAGE_NAME, secondUserTestPackageUid, SECONDARY_USER_HANDLE);
12505         mockGetApplicationInfo(TEST_PACKAGE_NAME, thirdUserTestPackageUid, TERTIARY_USER_HANDLE);
12506 
12507         // Build OemNetworkPreferences object
12508         final int testOemPref = OEM_NETWORK_PREFERENCE_OEM_PAID;
12509         final OemNetworkPreferences pref = new OemNetworkPreferences.Builder()
12510                 .addNetworkPreference(TEST_PACKAGE_NAME, testOemPref)
12511                 .build();
12512 
12513         // Act on OemNetworkRequestFactory.createNrisFromOemNetworkPreferences()
12514         final List<NetworkRequestInfo> nris =
12515                 new ArrayList<>(
12516                         mService.new OemNetworkRequestFactory().createNrisFromOemNetworkPreferences(
12517                                 pref));
12518 
12519         // UIDs for users with installed packages should be present.
12520         // Three users exist, but only two have the test package installed.
12521         final int expectedUidSize = 2;
12522         final List<Range<Integer>> uids =
12523                 new ArrayList<>(nris.get(0).mRequests.get(0).networkCapabilities.getUids());
12524         assertEquals(expectedUidSize, uids.size());
12525 
12526         // Sort by uid to access nris by index
12527         uids.sort(Comparator.comparingInt(uid -> uid.getLower()));
12528         assertEquals(secondUserTestPackageUid, (int) uids.get(0).getLower());
12529         assertEquals(secondUserTestPackageUid, (int) uids.get(0).getUpper());
12530         assertEquals(thirdUserTestPackageUid, (int) uids.get(1).getLower());
12531         assertEquals(thirdUserTestPackageUid, (int) uids.get(1).getUpper());
12532     }
12533 
12534     @Test
12535     public void testOemNetworkRequestFactoryAddsPackagesToCorrectPreference()
12536             throws Exception {
12537         // Expectations
12538         final int expectedNumOfNris = 1;
12539         final int expectedNumOfAppUids = 2;
12540 
12541         // Arrange PackageManager mocks
12542         final String testPackageName2 = "com.google.apps.dialer";
12543         final int testPackageNameUid2 = 456;
12544         mockGetApplicationInfo(TEST_PACKAGE_NAME, TEST_PACKAGE_UID);
12545         mockGetApplicationInfo(testPackageName2, testPackageNameUid2);
12546 
12547         // Build OemNetworkPreferences object
12548         final int testOemPref = OEM_NETWORK_PREFERENCE_OEM_PAID;
12549         final OemNetworkPreferences pref = new OemNetworkPreferences.Builder()
12550                 .addNetworkPreference(TEST_PACKAGE_NAME, testOemPref)
12551                 .addNetworkPreference(testPackageName2, testOemPref)
12552                 .build();
12553 
12554         // Act on OemNetworkRequestFactory.createNrisFromOemNetworkPreferences()
12555         final ArraySet<NetworkRequestInfo> nris =
12556                 mService.new OemNetworkRequestFactory().createNrisFromOemNetworkPreferences(pref);
12557 
12558         assertEquals(expectedNumOfNris, nris.size());
12559         assertEquals(expectedNumOfAppUids,
12560                 nris.iterator().next().mRequests.get(0).networkCapabilities.getUids().size());
12561     }
12562 
12563     @Test
12564     public void testSetOemNetworkPreferenceNullListenerAndPrefParamThrowsNpe() {
12565         mockHasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, true);
12566 
12567         // Act on ConnectivityService.setOemNetworkPreference()
12568         assertThrows(NullPointerException.class,
12569                 () -> mService.setOemNetworkPreference(
12570                         null,
12571                         null));
12572     }
12573 
12574     @Test
12575     public void testSetOemNetworkPreferenceFailsForNonAutomotive()
12576             throws Exception {
12577         mockHasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, false);
12578         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
12579                 OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY;
12580 
12581         // Act on ConnectivityService.setOemNetworkPreference()
12582         assertThrows(UnsupportedOperationException.class,
12583                 () -> mService.setOemNetworkPreference(
12584                         createDefaultOemNetworkPreferences(networkPref),
12585                         null));
12586     }
12587 
12588     @Test
12589     public void testSetOemNetworkPreferenceFailsForTestRequestWithoutPermission() {
12590         // Calling setOemNetworkPreference() with a test pref requires the permission
12591         // MANAGE_TEST_NETWORKS.
12592         mockHasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, false);
12593         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
12594                 OEM_NETWORK_PREFERENCE_TEST;
12595 
12596         // Act on ConnectivityService.setOemNetworkPreference()
12597         assertThrows(SecurityException.class,
12598                 () -> mService.setOemNetworkPreference(
12599                         createDefaultOemNetworkPreferences(networkPref),
12600                         null));
12601     }
12602 
12603     @Test
12604     public void testSetOemNetworkPreferenceFailsForInvalidTestRequest() {
12605         assertSetOemNetworkPreferenceFailsForInvalidTestRequest(OEM_NETWORK_PREFERENCE_TEST);
12606     }
12607 
12608     @Test
12609     public void testSetOemNetworkPreferenceFailsForInvalidTestOnlyRequest() {
12610         assertSetOemNetworkPreferenceFailsForInvalidTestRequest(OEM_NETWORK_PREFERENCE_TEST_ONLY);
12611     }
12612 
12613     private void assertSetOemNetworkPreferenceFailsForInvalidTestRequest(
12614             @OemNetworkPreferences.OemNetworkPreference final int oemNetworkPreferenceForTest) {
12615         mockHasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, true);
12616         final String secondPackage = "does.not.matter";
12617 
12618         // A valid test request would only have a single mapping.
12619         final OemNetworkPreferences pref = new OemNetworkPreferences.Builder()
12620                 .addNetworkPreference(TEST_PACKAGE_NAME, oemNetworkPreferenceForTest)
12621                 .addNetworkPreference(secondPackage, oemNetworkPreferenceForTest)
12622                 .build();
12623 
12624         // Act on ConnectivityService.setOemNetworkPreference()
12625         assertThrows(IllegalArgumentException.class,
12626                 () -> mService.setOemNetworkPreference(pref, null));
12627     }
12628 
12629     private void setOemNetworkPreferenceAgentConnected(final int transportType,
12630             final boolean connectAgent) throws Exception {
12631         switch(transportType) {
12632             // Corresponds to a metered cellular network. Will be used for the default network.
12633             case TRANSPORT_CELLULAR:
12634                 if (!connectAgent) {
12635                     mCellNetworkAgent.disconnect();
12636                     break;
12637                 }
12638                 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
12639                 mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
12640                 mCellNetworkAgent.connect(true);
12641                 break;
12642             // Corresponds to a restricted ethernet network with OEM_PAID/OEM_PRIVATE.
12643             case TRANSPORT_ETHERNET:
12644                 if (!connectAgent) {
12645                     stopOemManagedNetwork();
12646                     break;
12647                 }
12648                 startOemManagedNetwork(true);
12649                 break;
12650             // Corresponds to unmetered Wi-Fi.
12651             case TRANSPORT_WIFI:
12652                 if (!connectAgent) {
12653                     mWiFiNetworkAgent.disconnect();
12654                     break;
12655                 }
12656                 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
12657                 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
12658                 mWiFiNetworkAgent.connect(true);
12659                 break;
12660             default:
12661                 throw new AssertionError("Unsupported transport type passed in.");
12662 
12663         }
12664         waitForIdle();
12665     }
12666 
12667     private void startOemManagedNetwork(final boolean isOemPaid) throws Exception {
12668         mEthernetNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
12669         mEthernetNetworkAgent.addCapability(
12670                 isOemPaid ? NET_CAPABILITY_OEM_PAID : NET_CAPABILITY_OEM_PRIVATE);
12671         mEthernetNetworkAgent.removeCapability(NET_CAPABILITY_NOT_RESTRICTED);
12672         mEthernetNetworkAgent.connect(true);
12673     }
12674 
12675     private void stopOemManagedNetwork() {
12676         mEthernetNetworkAgent.disconnect();
12677         waitForIdle();
12678     }
12679 
12680     private void verifyMultipleDefaultNetworksTracksCorrectly(
12681             final int expectedOemRequestsSize,
12682             @NonNull final Network expectedDefaultNetwork,
12683             @NonNull final Network expectedPerAppNetwork) {
12684         // The current test setup assumes two tracked default network requests; one for the default
12685         // network and the other for the OEM network preference being tested. This will be validated
12686         // each time to confirm it doesn't change under test.
12687         final int expectedDefaultNetworkRequestsSize = 2;
12688         assertEquals(expectedDefaultNetworkRequestsSize, mService.mDefaultNetworkRequests.size());
12689         for (final NetworkRequestInfo defaultRequest : mService.mDefaultNetworkRequests) {
12690             final Network defaultNetwork = defaultRequest.getSatisfier() == null
12691                     ? null : defaultRequest.getSatisfier().network();
12692             // If this is the default request.
12693             if (defaultRequest == mService.mDefaultRequest) {
12694                 assertEquals(
12695                         expectedDefaultNetwork,
12696                         defaultNetwork);
12697                 // Make sure this value doesn't change.
12698                 assertEquals(1, defaultRequest.mRequests.size());
12699                 continue;
12700             }
12701             assertEquals(expectedPerAppNetwork, defaultNetwork);
12702             assertEquals(expectedOemRequestsSize, defaultRequest.mRequests.size());
12703         }
12704         verifyMultipleDefaultCallbacks(expectedDefaultNetwork, expectedPerAppNetwork);
12705     }
12706 
12707     /**
12708      * Verify default callbacks for 'available' fire as expected. This will only run if
12709      * registerDefaultNetworkCallbacks() was executed prior and will only be different if the
12710      * setOemNetworkPreference() per-app API was used for the current process.
12711      * @param expectedSystemDefault the expected network for the system default.
12712      * @param expectedPerAppDefault the expected network for the current process's default.
12713      */
12714     private void verifyMultipleDefaultCallbacks(
12715             @NonNull final Network expectedSystemDefault,
12716             @NonNull final Network expectedPerAppDefault) {
12717         if (null != mSystemDefaultNetworkCallback && null != expectedSystemDefault
12718                 && mService.mNoServiceNetwork.network() != expectedSystemDefault) {
12719             // getLastAvailableNetwork() is used as this method can be called successively with
12720             // the same network to validate therefore expectAvailableThenValidatedCallbacks
12721             // can't be used.
12722             assertEquals(mSystemDefaultNetworkCallback.getLastAvailableNetwork(),
12723                     expectedSystemDefault);
12724         }
12725         if (null != mDefaultNetworkCallback && null != expectedPerAppDefault
12726                 && mService.mNoServiceNetwork.network() != expectedPerAppDefault) {
12727             assertEquals(mDefaultNetworkCallback.getLastAvailableNetwork(),
12728                     expectedPerAppDefault);
12729         }
12730     }
12731 
12732     private void registerDefaultNetworkCallbacks() {
12733         if (mSystemDefaultNetworkCallback != null || mDefaultNetworkCallback != null
12734                 || mProfileDefaultNetworkCallback != null
12735                 || mProfileDefaultNetworkCallbackAsAppUid2 != null
12736                 || mTestPackageDefaultNetworkCallback2 != null
12737                 || mTestPackageDefaultNetworkCallback != null) {
12738             throw new IllegalStateException("Default network callbacks already registered");
12739         }
12740 
12741         // Using Manifest.permission.NETWORK_SETTINGS for registerSystemDefaultNetworkCallback()
12742         mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_GRANTED);
12743         mSystemDefaultNetworkCallback = new TestNetworkCallback();
12744         mDefaultNetworkCallback = new TestNetworkCallback();
12745         mProfileDefaultNetworkCallback = new TestNetworkCallback();
12746         mTestPackageDefaultNetworkCallback = new TestNetworkCallback();
12747         mProfileDefaultNetworkCallbackAsAppUid2 = new TestNetworkCallback();
12748         mTestPackageDefaultNetworkCallback2 = new TestNetworkCallback();
12749         mCm.registerSystemDefaultNetworkCallback(mSystemDefaultNetworkCallback,
12750                 new Handler(ConnectivityThread.getInstanceLooper()));
12751         mCm.registerDefaultNetworkCallback(mDefaultNetworkCallback);
12752         registerDefaultNetworkCallbackAsUid(mProfileDefaultNetworkCallback,
12753                 TEST_WORK_PROFILE_APP_UID);
12754         registerDefaultNetworkCallbackAsUid(mTestPackageDefaultNetworkCallback, TEST_PACKAGE_UID);
12755         registerDefaultNetworkCallbackAsUid(mProfileDefaultNetworkCallbackAsAppUid2,
12756                 TEST_WORK_PROFILE_APP_UID_2);
12757         registerDefaultNetworkCallbackAsUid(mTestPackageDefaultNetworkCallback2,
12758                 TEST_PACKAGE_UID2);
12759         // TODO: test using ConnectivityManager#registerDefaultNetworkCallbackAsUid as well.
12760         mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_DENIED);
12761     }
12762 
12763     private void unregisterDefaultNetworkCallbacks() {
12764         if (null != mDefaultNetworkCallback) {
12765             mCm.unregisterNetworkCallback(mDefaultNetworkCallback);
12766         }
12767         if (null != mSystemDefaultNetworkCallback) {
12768             mCm.unregisterNetworkCallback(mSystemDefaultNetworkCallback);
12769         }
12770         if (null != mProfileDefaultNetworkCallback) {
12771             mCm.unregisterNetworkCallback(mProfileDefaultNetworkCallback);
12772         }
12773         if (null != mTestPackageDefaultNetworkCallback) {
12774             mCm.unregisterNetworkCallback(mTestPackageDefaultNetworkCallback);
12775         }
12776         if (null != mProfileDefaultNetworkCallbackAsAppUid2) {
12777             mCm.unregisterNetworkCallback(mProfileDefaultNetworkCallbackAsAppUid2);
12778         }
12779         if (null != mTestPackageDefaultNetworkCallback2) {
12780             mCm.unregisterNetworkCallback(mTestPackageDefaultNetworkCallback2);
12781         }
12782     }
12783 
12784     private void setupMultipleDefaultNetworksForOemNetworkPreferenceNotCurrentUidTest(
12785             @OemNetworkPreferences.OemNetworkPreference final int networkPrefToSetup)
12786             throws Exception {
12787         final int testPackageNameUid = TEST_PACKAGE_UID;
12788         final String testPackageName = "per.app.defaults.package";
12789         setupMultipleDefaultNetworksForOemNetworkPreferenceTest(
12790                 networkPrefToSetup, testPackageNameUid, testPackageName);
12791     }
12792 
12793     private void setupMultipleDefaultNetworksForOemNetworkPreferenceCurrentUidTest(
12794             @OemNetworkPreferences.OemNetworkPreference final int networkPrefToSetup)
12795             throws Exception {
12796         final int testPackageNameUid = Process.myUid();
12797         final String testPackageName = "per.app.defaults.package";
12798         setupMultipleDefaultNetworksForOemNetworkPreferenceTest(
12799                 networkPrefToSetup, testPackageNameUid, testPackageName);
12800     }
12801 
12802     private void setupMultipleDefaultNetworksForOemNetworkPreferenceTest(
12803             @OemNetworkPreferences.OemNetworkPreference final int networkPrefToSetup,
12804             final int testPackageUid, @NonNull final String testPackageName) throws Exception {
12805         // Only the default request should be included at start.
12806         assertEquals(1, mService.mDefaultNetworkRequests.size());
12807 
12808         final UidRangeParcel[] uidRanges =
12809                 toUidRangeStableParcels(uidRangesForUids(testPackageUid));
12810         setupSetOemNetworkPreferenceForPreferenceTest(
12811                 networkPrefToSetup, uidRanges, testPackageName);
12812     }
12813 
12814     private void setupSetOemNetworkPreferenceForPreferenceTest(
12815             @OemNetworkPreferences.OemNetworkPreference final int networkPrefToSetup,
12816             @NonNull final UidRangeParcel[] uidRanges,
12817             @NonNull final String testPackageName) throws Exception {
12818         setupSetOemNetworkPreferenceForPreferenceTest(networkPrefToSetup, uidRanges,
12819                 testPackageName, PRIMARY_USER_HANDLE, true /* hasAutomotiveFeature */);
12820     }
12821 
12822     private void setupSetOemNetworkPreferenceForPreferenceTest(
12823             @OemNetworkPreferences.OemNetworkPreference final int networkPrefToSetup,
12824             @NonNull final UidRangeParcel[] uidRanges,
12825             @NonNull final String testPackageName,
12826             @NonNull final UserHandle user) throws Exception {
12827         setupSetOemNetworkPreferenceForPreferenceTest(networkPrefToSetup, uidRanges,
12828                 testPackageName, user, true /* hasAutomotiveFeature */);
12829     }
12830 
12831     private void setupSetOemNetworkPreferenceForPreferenceTest(
12832             @OemNetworkPreferences.OemNetworkPreference final int networkPrefToSetup,
12833             @NonNull final UidRangeParcel[] uidRanges,
12834             @NonNull final String testPackageName,
12835             @NonNull final UserHandle user,
12836             final boolean hasAutomotiveFeature) throws Exception {
12837         mockHasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, hasAutomotiveFeature);
12838 
12839         // These tests work off a single UID therefore using 'start' is valid.
12840         mockGetApplicationInfo(testPackageName, uidRanges[0].start, user);
12841 
12842         setOemNetworkPreference(networkPrefToSetup, testPackageName);
12843     }
12844 
12845     private void setOemNetworkPreference(final int networkPrefToSetup,
12846             @NonNull final String... testPackageNames)
12847             throws Exception {
12848         mockHasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, true);
12849 
12850         // Build OemNetworkPreferences object
12851         final OemNetworkPreferences.Builder builder = new OemNetworkPreferences.Builder();
12852         for (final String packageName : testPackageNames) {
12853             builder.addNetworkPreference(packageName, networkPrefToSetup);
12854         }
12855         final OemNetworkPreferences pref = builder.build();
12856 
12857         // Act on ConnectivityService.setOemNetworkPreference()
12858         final TestOemListenerCallback oemPrefListener = new TestOemListenerCallback();
12859         mService.setOemNetworkPreference(pref, oemPrefListener);
12860 
12861         // Verify call returned successfully
12862         oemPrefListener.expectOnComplete();
12863     }
12864 
12865     private static class TestOemListenerCallback implements IOnCompleteListener {
12866         final CompletableFuture<Object> mDone = new CompletableFuture<>();
12867 
12868         @Override
12869         public void onComplete() {
12870             mDone.complete(new Object());
12871         }
12872 
12873         void expectOnComplete() {
12874             try {
12875                 mDone.get(TIMEOUT_MS, TimeUnit.MILLISECONDS);
12876             } catch (TimeoutException e) {
12877                 fail("Expected onComplete() not received after " + TIMEOUT_MS + " ms");
12878             } catch (Exception e) {
12879                 fail(e.getMessage());
12880             }
12881         }
12882 
12883         @Override
12884         public IBinder asBinder() {
12885             return null;
12886         }
12887     }
12888 
12889     @Test
12890     public void testMultiDefaultGetActiveNetworkIsCorrect() throws Exception {
12891         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
12892                 OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY;
12893         final int expectedOemPrefRequestSize = 1;
12894         registerDefaultNetworkCallbacks();
12895 
12896         // Setup the test process to use networkPref for their default network.
12897         setupMultipleDefaultNetworksForOemNetworkPreferenceCurrentUidTest(networkPref);
12898 
12899         // Bring up ethernet with OEM_PAID. This will satisfy NET_CAPABILITY_OEM_PAID.
12900         // The active network for the default should be null at this point as this is a retricted
12901         // network.
12902         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, true);
12903         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
12904                 null,
12905                 mEthernetNetworkAgent.getNetwork());
12906 
12907         // Verify that the active network is correct
12908         verifyActiveNetwork(TRANSPORT_ETHERNET);
12909         // default NCs will be unregistered in tearDown
12910     }
12911 
12912     @Test
12913     public void testMultiDefaultIsActiveNetworkMeteredIsCorrect() throws Exception {
12914         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
12915                 OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY;
12916         final int expectedOemPrefRequestSize = 1;
12917         registerDefaultNetworkCallbacks();
12918 
12919         // Setup the test process to use networkPref for their default network.
12920         setupMultipleDefaultNetworksForOemNetworkPreferenceCurrentUidTest(networkPref);
12921 
12922         // Returns true by default when no network is available.
12923         assertTrue(mCm.isActiveNetworkMetered());
12924 
12925         // Connect to an unmetered restricted network that will only be available to the OEM pref.
12926         mEthernetNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
12927         mEthernetNetworkAgent.addCapability(NET_CAPABILITY_OEM_PAID);
12928         mEthernetNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
12929         mEthernetNetworkAgent.removeCapability(NET_CAPABILITY_NOT_RESTRICTED);
12930         mEthernetNetworkAgent.connect(true);
12931         waitForIdle();
12932 
12933         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
12934                 null,
12935                 mEthernetNetworkAgent.getNetwork());
12936 
12937         assertFalse(mCm.isActiveNetworkMetered());
12938         // default NCs will be unregistered in tearDown
12939     }
12940 
12941     @Test
12942     public void testPerAppDefaultRegisterDefaultNetworkCallback() throws Exception {
12943         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
12944                 OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY;
12945         final int expectedOemPrefRequestSize = 1;
12946         final TestNetworkCallback defaultNetworkCallback = new TestNetworkCallback();
12947 
12948         // Register the default network callback before the pref is already set. This means that
12949         // the policy will be applied to the callback on setOemNetworkPreference().
12950         mCm.registerDefaultNetworkCallback(defaultNetworkCallback);
12951         defaultNetworkCallback.assertNoCallback();
12952 
12953         final TestNetworkCallback otherUidDefaultCallback = new TestNetworkCallback();
12954         withPermission(NETWORK_SETTINGS, () ->
12955                 mCm.registerDefaultNetworkCallbackForUid(TEST_PACKAGE_UID, otherUidDefaultCallback,
12956                         new Handler(ConnectivityThread.getInstanceLooper())));
12957 
12958         // Setup the test process to use networkPref for their default network.
12959         setupMultipleDefaultNetworksForOemNetworkPreferenceCurrentUidTest(networkPref);
12960 
12961         // Bring up ethernet with OEM_PAID. This will satisfy NET_CAPABILITY_OEM_PAID.
12962         // The active nai for the default is null at this point as this is a restricted network.
12963         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, true);
12964         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
12965                 null,
12966                 mEthernetNetworkAgent.getNetwork());
12967 
12968         // At this point with a restricted network used, the available callback should trigger.
12969         defaultNetworkCallback.expectAvailableThenValidatedCallbacks(mEthernetNetworkAgent);
12970         assertEquals(defaultNetworkCallback.getLastAvailableNetwork(),
12971                 mEthernetNetworkAgent.getNetwork());
12972         otherUidDefaultCallback.assertNoCallback();
12973 
12974         // Now bring down the default network which should trigger a LOST callback.
12975         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, false);
12976 
12977         // At this point, with no network is available, the lost callback should trigger
12978         defaultNetworkCallback.expectCallback(CallbackEntry.LOST, mEthernetNetworkAgent);
12979         otherUidDefaultCallback.assertNoCallback();
12980 
12981         // Confirm we can unregister without issues.
12982         mCm.unregisterNetworkCallback(defaultNetworkCallback);
12983         mCm.unregisterNetworkCallback(otherUidDefaultCallback);
12984     }
12985 
12986     @Test
12987     public void testPerAppDefaultRegisterDefaultNetworkCallbackAfterPrefSet() throws Exception {
12988         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
12989                 OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY;
12990         final int expectedOemPrefRequestSize = 1;
12991         final TestNetworkCallback defaultNetworkCallback = new TestNetworkCallback();
12992 
12993         // Setup the test process to use networkPref for their default network.
12994         setupMultipleDefaultNetworksForOemNetworkPreferenceCurrentUidTest(networkPref);
12995 
12996         // Register the default network callback after the pref is already set. This means that
12997         // the policy will be applied to the callback on requestNetwork().
12998         mCm.registerDefaultNetworkCallback(defaultNetworkCallback);
12999         defaultNetworkCallback.assertNoCallback();
13000 
13001         final TestNetworkCallback otherUidDefaultCallback = new TestNetworkCallback();
13002         withPermission(NETWORK_SETTINGS, () ->
13003                 mCm.registerDefaultNetworkCallbackForUid(TEST_PACKAGE_UID, otherUidDefaultCallback,
13004                         new Handler(ConnectivityThread.getInstanceLooper())));
13005 
13006         // Bring up ethernet with OEM_PAID. This will satisfy NET_CAPABILITY_OEM_PAID.
13007         // The active nai for the default is null at this point as this is a restricted network.
13008         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, true);
13009         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
13010                 null,
13011                 mEthernetNetworkAgent.getNetwork());
13012 
13013         // At this point with a restricted network used, the available callback should trigger
13014         defaultNetworkCallback.expectAvailableThenValidatedCallbacks(mEthernetNetworkAgent);
13015         assertEquals(defaultNetworkCallback.getLastAvailableNetwork(),
13016                 mEthernetNetworkAgent.getNetwork());
13017         otherUidDefaultCallback.assertNoCallback();
13018 
13019         // Now bring down the default network which should trigger a LOST callback.
13020         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, false);
13021         otherUidDefaultCallback.assertNoCallback();
13022 
13023         // At this point, with no network is available, the lost callback should trigger
13024         defaultNetworkCallback.expectCallback(CallbackEntry.LOST, mEthernetNetworkAgent);
13025         otherUidDefaultCallback.assertNoCallback();
13026 
13027         // Confirm we can unregister without issues.
13028         mCm.unregisterNetworkCallback(defaultNetworkCallback);
13029         mCm.unregisterNetworkCallback(otherUidDefaultCallback);
13030     }
13031 
13032     @Test
13033     public void testPerAppDefaultRegisterDefaultNetworkCallbackDoesNotFire() throws Exception {
13034         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
13035                 OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY;
13036         final int expectedOemPrefRequestSize = 1;
13037         final TestNetworkCallback defaultNetworkCallback = new TestNetworkCallback();
13038         final int userId = UserHandle.getUserId(Process.myUid());
13039 
13040         mCm.registerDefaultNetworkCallback(defaultNetworkCallback);
13041         defaultNetworkCallback.assertNoCallback();
13042 
13043         final TestNetworkCallback otherUidDefaultCallback = new TestNetworkCallback();
13044         withPermission(NETWORK_SETTINGS, () ->
13045                 mCm.registerDefaultNetworkCallbackForUid(TEST_PACKAGE_UID, otherUidDefaultCallback,
13046                         new Handler(ConnectivityThread.getInstanceLooper())));
13047 
13048         // Setup a process different than the test process to use the default network. This means
13049         // that the defaultNetworkCallback won't be tracked by the per-app policy.
13050         setupMultipleDefaultNetworksForOemNetworkPreferenceNotCurrentUidTest(networkPref);
13051 
13052         // Bring up ethernet with OEM_PAID. This will satisfy NET_CAPABILITY_OEM_PAID.
13053         // The active nai for the default is null at this point as this is a restricted network.
13054         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, true);
13055         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
13056                 null,
13057                 mEthernetNetworkAgent.getNetwork());
13058 
13059         // As this callback does not have access to the OEM_PAID network, it will not fire.
13060         defaultNetworkCallback.assertNoCallback();
13061         assertDefaultNetworkCapabilities(userId /* no networks */);
13062 
13063         // The other UID does have access, and gets a callback.
13064         otherUidDefaultCallback.expectAvailableThenValidatedCallbacks(mEthernetNetworkAgent);
13065 
13066         // Bring up unrestricted cellular. This should now satisfy the default network.
13067         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true);
13068         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
13069                 mCellNetworkAgent.getNetwork(),
13070                 mEthernetNetworkAgent.getNetwork());
13071 
13072         // At this point with an unrestricted network used, the available callback should trigger
13073         // The other UID is unaffected and remains on the paid network.
13074         defaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
13075         assertEquals(defaultNetworkCallback.getLastAvailableNetwork(),
13076                 mCellNetworkAgent.getNetwork());
13077         assertDefaultNetworkCapabilities(userId, mCellNetworkAgent);
13078         otherUidDefaultCallback.assertNoCallback();
13079 
13080         // Now bring down the per-app network.
13081         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, false);
13082 
13083         // Since the callback didn't use the per-app network, only the other UID gets a callback.
13084         // Because the preference specifies no fallback, it does not switch to cellular.
13085         defaultNetworkCallback.assertNoCallback();
13086         otherUidDefaultCallback.expectCallback(CallbackEntry.LOST, mEthernetNetworkAgent);
13087 
13088         // Now bring down the default network.
13089         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, false);
13090 
13091         // As this callback was tracking the default, this should now trigger.
13092         defaultNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
13093         otherUidDefaultCallback.assertNoCallback();
13094 
13095         // Confirm we can unregister without issues.
13096         mCm.unregisterNetworkCallback(defaultNetworkCallback);
13097         mCm.unregisterNetworkCallback(otherUidDefaultCallback);
13098     }
13099 
13100     /**
13101      * This method assumes that the same uidRanges input will be used to verify that dependencies
13102      * are called as expected.
13103      */
13104     private void verifySetOemNetworkPreferenceForPreference(
13105             @NonNull final UidRangeParcel[] uidRanges,
13106             final int addUidRangesNetId,
13107             final int addUidRangesTimes,
13108             final int removeUidRangesNetId,
13109             final int removeUidRangesTimes,
13110             final boolean shouldDestroyNetwork) throws RemoteException {
13111         verifySetOemNetworkPreferenceForPreference(uidRanges, uidRanges,
13112                 addUidRangesNetId, addUidRangesTimes, removeUidRangesNetId, removeUidRangesTimes,
13113                 shouldDestroyNetwork);
13114     }
13115 
13116     private void verifySetOemNetworkPreferenceForPreference(
13117             @NonNull final UidRangeParcel[] addedUidRanges,
13118             @NonNull final UidRangeParcel[] removedUidRanges,
13119             final int addUidRangesNetId,
13120             final int addUidRangesTimes,
13121             final int removeUidRangesNetId,
13122             final int removeUidRangesTimes,
13123             final boolean shouldDestroyNetwork) throws RemoteException {
13124         final boolean useAnyIdForAdd = OEM_PREF_ANY_NET_ID == addUidRangesNetId;
13125         final boolean useAnyIdForRemove = OEM_PREF_ANY_NET_ID == removeUidRangesNetId;
13126 
13127         // Validate that add/remove uid range (with oem priority) to/from netd.
13128         verify(mMockNetd, times(addUidRangesTimes)).networkAddUidRangesParcel(argThat(config ->
13129                 (useAnyIdForAdd ? true : addUidRangesNetId == config.netId)
13130                         && Arrays.equals(addedUidRanges, config.uidRanges)
13131                         && PREFERENCE_ORDER_OEM == config.subPriority));
13132         verify(mMockNetd, times(removeUidRangesTimes)).networkRemoveUidRangesParcel(
13133                 argThat(config -> (useAnyIdForRemove ? true : removeUidRangesNetId == config.netId)
13134                         && Arrays.equals(removedUidRanges, config.uidRanges)
13135                         && PREFERENCE_ORDER_OEM == config.subPriority));
13136         if (shouldDestroyNetwork) {
13137             verify(mMockNetd, times(1))
13138                     .networkDestroy((useAnyIdForRemove ? anyInt() : eq(removeUidRangesNetId)));
13139         }
13140         reset(mMockNetd);
13141     }
13142 
13143     /**
13144      * Test the tracked default requests allows test requests without standard setup.
13145      */
13146     @Test
13147     public void testSetOemNetworkPreferenceAllowsValidTestRequestWithoutChecks() throws Exception {
13148         @OemNetworkPreferences.OemNetworkPreference int networkPref =
13149                 OEM_NETWORK_PREFERENCE_TEST;
13150         validateSetOemNetworkPreferenceAllowsValidTestPrefRequest(networkPref);
13151     }
13152 
13153     /**
13154      * Test the tracked default requests allows test only requests without standard setup.
13155      */
13156     @Test
13157     public void testSetOemNetworkPreferenceAllowsValidTestOnlyRequestWithoutChecks()
13158             throws Exception {
13159         @OemNetworkPreferences.OemNetworkPreference int networkPref =
13160                 OEM_NETWORK_PREFERENCE_TEST_ONLY;
13161         validateSetOemNetworkPreferenceAllowsValidTestPrefRequest(networkPref);
13162     }
13163 
13164     private void validateSetOemNetworkPreferenceAllowsValidTestPrefRequest(int networkPref)
13165             throws Exception {
13166         // The caller must have the MANAGE_TEST_NETWORKS permission.
13167         final int testPackageUid = 123;
13168         final String validTestPackageName = "does.not.matter";
13169         final UidRangeParcel[] uidRanges =
13170                 toUidRangeStableParcels(uidRangesForUids(testPackageUid));
13171         mServiceContext.setPermission(
13172                 Manifest.permission.MANAGE_TEST_NETWORKS, PERMISSION_GRANTED);
13173 
13174         // Put the system into a state in which setOemNetworkPreference() would normally fail. This
13175         // will confirm that a valid test request can bypass these checks.
13176         mockHasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, false);
13177         mServiceContext.setPermission(
13178                 Manifest.permission.CONTROL_OEM_PAID_NETWORK_PREFERENCE, PERMISSION_DENIED);
13179 
13180         // Validate the starting requests only includes the system default request.
13181         assertEquals(1, mService.mDefaultNetworkRequests.size());
13182 
13183         // Add an OEM default network request to track.
13184         setupSetOemNetworkPreferenceForPreferenceTest(
13185                 networkPref, uidRanges, validTestPackageName, PRIMARY_USER_HANDLE,
13186                 false /* hasAutomotiveFeature */);
13187 
13188         // Two requests should now exist; the system default and the test request.
13189         assertEquals(2, mService.mDefaultNetworkRequests.size());
13190     }
13191 
13192     /**
13193      * Test the tracked default requests clear previous OEM requests on setOemNetworkPreference().
13194      */
13195     @Test
13196     public void testSetOemNetworkPreferenceClearPreviousOemValues() throws Exception {
13197         @OemNetworkPreferences.OemNetworkPreference int networkPref =
13198                 OEM_NETWORK_PREFERENCE_OEM_PAID;
13199         final int testPackageUid = 123;
13200         final String testPackageName = "com.google.apps.contacts";
13201         final UidRangeParcel[] uidRanges =
13202                 toUidRangeStableParcels(uidRangesForUids(testPackageUid));
13203 
13204         // Validate the starting requests only includes the system default request.
13205         assertEquals(1, mService.mDefaultNetworkRequests.size());
13206 
13207         // Add an OEM default network request to track.
13208         setupSetOemNetworkPreferenceForPreferenceTest(networkPref, uidRanges, testPackageName);
13209 
13210         // Two requests should exist, one for the fallback and one for the pref.
13211         assertEquals(2, mService.mDefaultNetworkRequests.size());
13212 
13213         networkPref = OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY;
13214         setupSetOemNetworkPreferenceForPreferenceTest(networkPref, uidRanges, testPackageName);
13215 
13216         // Two requests should still exist validating the previous per-app request was replaced.
13217         assertEquals(2, mService.mDefaultNetworkRequests.size());
13218     }
13219 
13220     /**
13221      * Test network priority for preference OEM_NETWORK_PREFERENCE_OEM_PAID in the following order:
13222      * NET_CAPABILITY_NOT_METERED -> NET_CAPABILITY_OEM_PAID -> fallback
13223      */
13224     @Test
13225     public void testMultilayerForPreferenceOemPaidEvaluatesCorrectly()
13226             throws Exception {
13227         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
13228                 OEM_NETWORK_PREFERENCE_OEM_PAID;
13229 
13230         // Arrange PackageManager mocks
13231         final UidRangeParcel[] uidRanges =
13232                 toUidRangeStableParcels(uidRangesForUids(TEST_PACKAGE_UID));
13233         setupSetOemNetworkPreferenceForPreferenceTest(networkPref, uidRanges, TEST_PACKAGE_NAME);
13234 
13235         // Verify the starting state. No networks should be connected.
13236         verifySetOemNetworkPreferenceForPreference(uidRanges,
13237                 OEM_PREF_ANY_NET_ID, 0 /* times */,
13238                 OEM_PREF_ANY_NET_ID, 0 /* times */,
13239                 false /* shouldDestroyNetwork */);
13240 
13241         // Test lowest to highest priority requests.
13242         // Bring up metered cellular. This will satisfy the fallback network.
13243         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true);
13244         verifySetOemNetworkPreferenceForPreference(uidRanges,
13245                 mCellNetworkAgent.getNetwork().netId, 1 /* times */,
13246                 OEM_PREF_ANY_NET_ID, 0 /* times */,
13247                 false /* shouldDestroyNetwork */);
13248 
13249         // Bring up ethernet with OEM_PAID. This will satisfy NET_CAPABILITY_OEM_PAID.
13250         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, true);
13251         verifySetOemNetworkPreferenceForPreference(uidRanges,
13252                 mEthernetNetworkAgent.getNetwork().netId, 1 /* times */,
13253                 mCellNetworkAgent.getNetwork().netId, 1 /* times */,
13254                 false /* shouldDestroyNetwork */);
13255 
13256         // Bring up unmetered Wi-Fi. This will satisfy NET_CAPABILITY_NOT_METERED.
13257         setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, true);
13258         verifySetOemNetworkPreferenceForPreference(uidRanges,
13259                 mWiFiNetworkAgent.getNetwork().netId, 1 /* times */,
13260                 mEthernetNetworkAgent.getNetwork().netId, 1 /* times */,
13261                 false /* shouldDestroyNetwork */);
13262 
13263         // Disconnecting OEM_PAID should have no effect as it is lower in priority then unmetered.
13264         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, false);
13265         // netd should not be called as default networks haven't changed.
13266         verifySetOemNetworkPreferenceForPreference(uidRanges,
13267                 OEM_PREF_ANY_NET_ID, 0 /* times */,
13268                 OEM_PREF_ANY_NET_ID, 0 /* times */,
13269                 false /* shouldDestroyNetwork */);
13270 
13271         // Disconnecting unmetered should put PANS on lowest priority fallback request.
13272         setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, false);
13273         verifySetOemNetworkPreferenceForPreference(uidRanges,
13274                 mCellNetworkAgent.getNetwork().netId, 1 /* times */,
13275                 mWiFiNetworkAgent.getNetwork().netId, 0 /* times */,
13276                 true /* shouldDestroyNetwork */);
13277 
13278         // Disconnecting the fallback network should result in no connectivity.
13279         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, false);
13280         verifySetOemNetworkPreferenceForPreference(uidRanges,
13281                 OEM_PREF_ANY_NET_ID, 0 /* times */,
13282                 mCellNetworkAgent.getNetwork().netId, 0 /* times */,
13283                 true /* shouldDestroyNetwork */);
13284     }
13285 
13286     /**
13287      * Test network priority for OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK in the following order:
13288      * NET_CAPABILITY_NOT_METERED -> NET_CAPABILITY_OEM_PAID
13289      */
13290     @Test
13291     public void testMultilayerForPreferenceOemPaidNoFallbackEvaluatesCorrectly()
13292             throws Exception {
13293         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
13294                 OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK;
13295 
13296         // Arrange PackageManager mocks
13297         final UidRangeParcel[] uidRanges =
13298                 toUidRangeStableParcels(uidRangesForUids(TEST_PACKAGE_UID));
13299         setupSetOemNetworkPreferenceForPreferenceTest(networkPref, uidRanges, TEST_PACKAGE_NAME);
13300 
13301         // Verify the starting state. This preference doesn't support using the fallback network
13302         // therefore should be on the disconnected network as it has no networks to connect to.
13303         verifySetOemNetworkPreferenceForPreference(uidRanges,
13304                 mService.mNoServiceNetwork.network.getNetId(), 1 /* times */,
13305                 OEM_PREF_ANY_NET_ID, 0 /* times */,
13306                 false /* shouldDestroyNetwork */);
13307 
13308         // Test lowest to highest priority requests.
13309         // Bring up metered cellular. This will satisfy the fallback network.
13310         // This preference should not use this network as it doesn't support fallback usage.
13311         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true);
13312         verifySetOemNetworkPreferenceForPreference(uidRanges,
13313                 OEM_PREF_ANY_NET_ID, 0 /* times */,
13314                 OEM_PREF_ANY_NET_ID, 0 /* times */,
13315                 false /* shouldDestroyNetwork */);
13316 
13317         // Bring up ethernet with OEM_PAID. This will satisfy NET_CAPABILITY_OEM_PAID.
13318         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, true);
13319         verifySetOemNetworkPreferenceForPreference(uidRanges,
13320                 mEthernetNetworkAgent.getNetwork().netId, 1 /* times */,
13321                 mService.mNoServiceNetwork.network.getNetId(), 1 /* times */,
13322                 false /* shouldDestroyNetwork */);
13323 
13324         // Bring up unmetered Wi-Fi. This will satisfy NET_CAPABILITY_NOT_METERED.
13325         setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, true);
13326         verifySetOemNetworkPreferenceForPreference(uidRanges,
13327                 mWiFiNetworkAgent.getNetwork().netId, 1 /* times */,
13328                 mEthernetNetworkAgent.getNetwork().netId, 1 /* times */,
13329                 false /* shouldDestroyNetwork */);
13330 
13331         // Disconnecting unmetered should put PANS on OEM_PAID.
13332         setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, false);
13333         verifySetOemNetworkPreferenceForPreference(uidRanges,
13334                 mEthernetNetworkAgent.getNetwork().netId, 1 /* times */,
13335                 mWiFiNetworkAgent.getNetwork().netId, 0 /* times */,
13336                 true /* shouldDestroyNetwork */);
13337 
13338         // Disconnecting OEM_PAID should result in no connectivity.
13339         // OEM_PAID_NO_FALLBACK not supporting a fallback now uses the disconnected network.
13340         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, false);
13341         verifySetOemNetworkPreferenceForPreference(uidRanges,
13342                 mService.mNoServiceNetwork.network.getNetId(), 1 /* times */,
13343                 mEthernetNetworkAgent.getNetwork().netId, 0 /* times */,
13344                 true /* shouldDestroyNetwork */);
13345     }
13346 
13347     /**
13348      * Test network priority for OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY in the following order:
13349      * NET_CAPABILITY_OEM_PAID
13350      * This preference should only apply to OEM_PAID networks.
13351      */
13352     @Test
13353     public void testMultilayerForPreferenceOemPaidOnlyEvaluatesCorrectly()
13354             throws Exception {
13355         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
13356                 OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY;
13357 
13358         // Arrange PackageManager mocks
13359         final UidRangeParcel[] uidRanges =
13360                 toUidRangeStableParcels(uidRangesForUids(TEST_PACKAGE_UID));
13361         setupSetOemNetworkPreferenceForPreferenceTest(networkPref, uidRanges, TEST_PACKAGE_NAME);
13362 
13363         // Verify the starting state. This preference doesn't support using the fallback network
13364         // therefore should be on the disconnected network as it has no networks to connect to.
13365         verifySetOemNetworkPreferenceForPreference(uidRanges,
13366                 mService.mNoServiceNetwork.network.getNetId(), 1 /* times */,
13367                 OEM_PREF_ANY_NET_ID, 0 /* times */,
13368                 false /* shouldDestroyNetwork */);
13369 
13370         // Bring up metered cellular. This should not apply to this preference.
13371         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true);
13372         verifySetOemNetworkPreferenceForPreference(uidRanges,
13373                 OEM_PREF_ANY_NET_ID, 0 /* times */,
13374                 OEM_PREF_ANY_NET_ID, 0 /* times */,
13375                 false /* shouldDestroyNetwork */);
13376 
13377         // Bring up unmetered Wi-Fi. This should not apply to this preference.
13378         setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, true);
13379         verifySetOemNetworkPreferenceForPreference(uidRanges,
13380                 OEM_PREF_ANY_NET_ID, 0 /* times */,
13381                 OEM_PREF_ANY_NET_ID, 0 /* times */,
13382                 false /* shouldDestroyNetwork */);
13383 
13384         // Bring up ethernet with OEM_PAID. This will satisfy NET_CAPABILITY_OEM_PAID.
13385         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, true);
13386         verifySetOemNetworkPreferenceForPreference(uidRanges,
13387                 mEthernetNetworkAgent.getNetwork().netId, 1 /* times */,
13388                 mService.mNoServiceNetwork.network.getNetId(), 1 /* times */,
13389                 false /* shouldDestroyNetwork */);
13390 
13391         // Disconnecting OEM_PAID should result in no connectivity.
13392         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, false);
13393         verifySetOemNetworkPreferenceForPreference(uidRanges,
13394                 mService.mNoServiceNetwork.network.getNetId(), 1 /* times */,
13395                 mEthernetNetworkAgent.getNetwork().netId, 0 /* times */,
13396                 true /* shouldDestroyNetwork */);
13397     }
13398 
13399     /**
13400      * Test network priority for OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY in the following order:
13401      * NET_CAPABILITY_OEM_PRIVATE
13402      * This preference should only apply to OEM_PRIVATE networks.
13403      */
13404     @Test
13405     public void testMultilayerForPreferenceOemPrivateOnlyEvaluatesCorrectly()
13406             throws Exception {
13407         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
13408                 OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY;
13409 
13410         // Arrange PackageManager mocks
13411         final UidRangeParcel[] uidRanges =
13412                 toUidRangeStableParcels(uidRangesForUids(TEST_PACKAGE_UID));
13413         setupSetOemNetworkPreferenceForPreferenceTest(networkPref, uidRanges, TEST_PACKAGE_NAME);
13414 
13415         // Verify the starting state. This preference doesn't support using the fallback network
13416         // therefore should be on the disconnected network as it has no networks to connect to.
13417         verifySetOemNetworkPreferenceForPreference(uidRanges,
13418                 mService.mNoServiceNetwork.network.getNetId(), 1 /* times */,
13419                 OEM_PREF_ANY_NET_ID, 0 /* times */,
13420                 false /* shouldDestroyNetwork */);
13421 
13422         // Bring up metered cellular. This should not apply to this preference.
13423         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true);
13424         verifySetOemNetworkPreferenceForPreference(uidRanges,
13425                 OEM_PREF_ANY_NET_ID, 0 /* times */,
13426                 OEM_PREF_ANY_NET_ID, 0 /* times */,
13427                 false /* shouldDestroyNetwork */);
13428 
13429         // Bring up unmetered Wi-Fi. This should not apply to this preference.
13430         setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, true);
13431         verifySetOemNetworkPreferenceForPreference(uidRanges,
13432                 OEM_PREF_ANY_NET_ID, 0 /* times */,
13433                 OEM_PREF_ANY_NET_ID, 0 /* times */,
13434                 false /* shouldDestroyNetwork */);
13435 
13436         // Bring up ethernet with OEM_PRIVATE. This will satisfy NET_CAPABILITY_OEM_PRIVATE.
13437         startOemManagedNetwork(false);
13438         verifySetOemNetworkPreferenceForPreference(uidRanges,
13439                 mEthernetNetworkAgent.getNetwork().netId, 1 /* times */,
13440                 mService.mNoServiceNetwork.network.getNetId(), 1 /* times */,
13441                 false /* shouldDestroyNetwork */);
13442 
13443         // Disconnecting OEM_PRIVATE should result in no connectivity.
13444         stopOemManagedNetwork();
13445         verifySetOemNetworkPreferenceForPreference(uidRanges,
13446                 mService.mNoServiceNetwork.network.getNetId(), 1 /* times */,
13447                 mEthernetNetworkAgent.getNetwork().netId, 0 /* times */,
13448                 true /* shouldDestroyNetwork */);
13449     }
13450 
13451     @Test
13452     public void testMultilayerForMultipleUsersEvaluatesCorrectly()
13453             throws Exception {
13454         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
13455                 OEM_NETWORK_PREFERENCE_OEM_PAID;
13456 
13457         // Arrange users
13458         final int secondUser = 10;
13459         final UserHandle secondUserHandle = new UserHandle(secondUser);
13460         doReturn(asList(PRIMARY_USER_HANDLE, secondUserHandle)).when(mUserManager)
13461                 .getUserHandles(anyBoolean());
13462 
13463         // Arrange PackageManager mocks
13464         final int secondUserTestPackageUid = UserHandle.getUid(secondUser, TEST_PACKAGE_UID);
13465         final UidRangeParcel[] uidRanges =
13466                 toUidRangeStableParcels(
13467                         uidRangesForUids(TEST_PACKAGE_UID, secondUserTestPackageUid));
13468         mockGetApplicationInfo(TEST_PACKAGE_NAME, secondUserTestPackageUid, secondUserHandle);
13469         setupSetOemNetworkPreferenceForPreferenceTest(networkPref, uidRanges, TEST_PACKAGE_NAME);
13470 
13471         // Verify the starting state. No networks should be connected.
13472         verifySetOemNetworkPreferenceForPreference(uidRanges,
13473                 OEM_PREF_ANY_NET_ID, 0 /* times */,
13474                 OEM_PREF_ANY_NET_ID, 0 /* times */,
13475                 false /* shouldDestroyNetwork */);
13476 
13477         // Test that we correctly add the expected values for multiple users.
13478         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true);
13479         verifySetOemNetworkPreferenceForPreference(uidRanges,
13480                 mCellNetworkAgent.getNetwork().netId, 1 /* times */,
13481                 OEM_PREF_ANY_NET_ID, 0 /* times */,
13482                 false /* shouldDestroyNetwork */);
13483 
13484         // Test that we correctly remove the expected values for multiple users.
13485         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, false);
13486         verifySetOemNetworkPreferenceForPreference(uidRanges,
13487                 OEM_PREF_ANY_NET_ID, 0 /* times */,
13488                 mCellNetworkAgent.getNetwork().netId, 0 /* times */,
13489                 true /* shouldDestroyNetwork */);
13490     }
13491 
13492     @Test
13493     public void testMultilayerForBroadcastedUsersEvaluatesCorrectly()
13494             throws Exception {
13495         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
13496                 OEM_NETWORK_PREFERENCE_OEM_PAID;
13497 
13498         // Arrange users
13499         final int secondUser = 10;
13500         final UserHandle secondUserHandle = new UserHandle(secondUser);
13501         doReturn(asList(PRIMARY_USER_HANDLE)).when(mUserManager).getUserHandles(anyBoolean());
13502 
13503         // Arrange PackageManager mocks
13504         final int secondUserTestPackageUid = UserHandle.getUid(secondUser, TEST_PACKAGE_UID);
13505         final UidRangeParcel[] uidRangesSingleUser =
13506                 toUidRangeStableParcels(uidRangesForUids(TEST_PACKAGE_UID));
13507         final UidRangeParcel[] uidRangesBothUsers =
13508                 toUidRangeStableParcels(
13509                         uidRangesForUids(TEST_PACKAGE_UID, secondUserTestPackageUid));
13510         mockGetApplicationInfo(TEST_PACKAGE_NAME, secondUserTestPackageUid, secondUserHandle);
13511         setupSetOemNetworkPreferenceForPreferenceTest(
13512                 networkPref, uidRangesSingleUser, TEST_PACKAGE_NAME);
13513 
13514         // Verify the starting state. No networks should be connected.
13515         verifySetOemNetworkPreferenceForPreference(uidRangesSingleUser,
13516                 OEM_PREF_ANY_NET_ID, 0 /* times */,
13517                 OEM_PREF_ANY_NET_ID, 0 /* times */,
13518                 false /* shouldDestroyNetwork */);
13519 
13520         // Test that we correctly add the expected values for multiple users.
13521         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true);
13522         verifySetOemNetworkPreferenceForPreference(uidRangesSingleUser,
13523                 mCellNetworkAgent.getNetwork().netId, 1 /* times */,
13524                 OEM_PREF_ANY_NET_ID, 0 /* times */,
13525                 false /* shouldDestroyNetwork */);
13526 
13527         // Send a broadcast indicating a user was added.
13528         doReturn(asList(PRIMARY_USER_HANDLE, secondUserHandle)).when(mUserManager)
13529                 .getUserHandles(anyBoolean());
13530         final Intent addedIntent = new Intent(ACTION_USER_ADDED);
13531         addedIntent.putExtra(Intent.EXTRA_USER, UserHandle.of(secondUser));
13532         processBroadcast(addedIntent);
13533 
13534         // Test that we correctly add values for all users and remove for the single user.
13535         verifySetOemNetworkPreferenceForPreference(uidRangesBothUsers, uidRangesSingleUser,
13536                 mCellNetworkAgent.getNetwork().netId, 1 /* times */,
13537                 mCellNetworkAgent.getNetwork().netId, 1 /* times */,
13538                 false /* shouldDestroyNetwork */);
13539 
13540         // Send a broadcast indicating a user was removed.
13541         doReturn(asList(PRIMARY_USER_HANDLE)).when(mUserManager).getUserHandles(anyBoolean());
13542         final Intent removedIntent = new Intent(ACTION_USER_REMOVED);
13543         removedIntent.putExtra(Intent.EXTRA_USER, UserHandle.of(secondUser));
13544         processBroadcast(removedIntent);
13545 
13546         // Test that we correctly add values for the single user and remove for the all users.
13547         verifySetOemNetworkPreferenceForPreference(uidRangesSingleUser, uidRangesBothUsers,
13548                 mCellNetworkAgent.getNetwork().netId, 1 /* times */,
13549                 mCellNetworkAgent.getNetwork().netId, 1 /* times */,
13550                 false /* shouldDestroyNetwork */);
13551     }
13552 
13553     @Test
13554     public void testMultilayerForPackageChangesEvaluatesCorrectly()
13555             throws Exception {
13556         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
13557                 OEM_NETWORK_PREFERENCE_OEM_PAID;
13558         final String packageScheme = "package:";
13559 
13560         // Arrange PackageManager mocks
13561         final String packageToInstall = "package.to.install";
13562         final int packageToInstallUid = 81387;
13563         final UidRangeParcel[] uidRangesSinglePackage =
13564                 toUidRangeStableParcels(uidRangesForUids(TEST_PACKAGE_UID));
13565         mockGetApplicationInfo(TEST_PACKAGE_NAME, TEST_PACKAGE_UID);
13566         mockGetApplicationInfoThrowsNameNotFound(packageToInstall, PRIMARY_USER_HANDLE);
13567         setOemNetworkPreference(networkPref, TEST_PACKAGE_NAME, packageToInstall);
13568         grantUsingBackgroundNetworksPermissionForUid(Binder.getCallingUid(), packageToInstall);
13569 
13570         // Verify the starting state. No networks should be connected.
13571         verifySetOemNetworkPreferenceForPreference(uidRangesSinglePackage,
13572                 OEM_PREF_ANY_NET_ID, 0 /* times */,
13573                 OEM_PREF_ANY_NET_ID, 0 /* times */,
13574                 false /* shouldDestroyNetwork */);
13575 
13576         // Test that we correctly add the expected values for installed packages.
13577         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true);
13578         verifySetOemNetworkPreferenceForPreference(uidRangesSinglePackage,
13579                 mCellNetworkAgent.getNetwork().netId, 1 /* times */,
13580                 OEM_PREF_ANY_NET_ID, 0 /* times */,
13581                 false /* shouldDestroyNetwork */);
13582 
13583         // Set the system to recognize the package to be installed
13584         mockGetApplicationInfo(packageToInstall, packageToInstallUid);
13585         final UidRangeParcel[] uidRangesAllPackages =
13586                 toUidRangeStableParcels(uidRangesForUids(TEST_PACKAGE_UID, packageToInstallUid));
13587 
13588         // Send a broadcast indicating a package was installed.
13589         final Intent addedIntent = new Intent(ACTION_PACKAGE_ADDED);
13590         addedIntent.setData(Uri.parse(packageScheme + packageToInstall));
13591         processBroadcast(addedIntent);
13592 
13593         // Test the single package is removed and the combined packages are added.
13594         verifySetOemNetworkPreferenceForPreference(uidRangesAllPackages, uidRangesSinglePackage,
13595                 mCellNetworkAgent.getNetwork().netId, 1 /* times */,
13596                 mCellNetworkAgent.getNetwork().netId, 1 /* times */,
13597                 false /* shouldDestroyNetwork */);
13598 
13599         // Set the system to no longer recognize the package to be installed
13600         mockGetApplicationInfoThrowsNameNotFound(packageToInstall, PRIMARY_USER_HANDLE);
13601 
13602         // Send a broadcast indicating a package was removed.
13603         final Intent removedIntent = new Intent(ACTION_PACKAGE_REMOVED);
13604         removedIntent.setData(Uri.parse(packageScheme + packageToInstall));
13605         processBroadcast(removedIntent);
13606 
13607         // Test the combined packages are removed and the single package is added.
13608         verifySetOemNetworkPreferenceForPreference(uidRangesSinglePackage, uidRangesAllPackages,
13609                 mCellNetworkAgent.getNetwork().netId, 1 /* times */,
13610                 mCellNetworkAgent.getNetwork().netId, 1 /* times */,
13611                 false /* shouldDestroyNetwork */);
13612 
13613         // Set the system to change the installed package's uid
13614         final int replacedTestPackageUid = TEST_PACKAGE_UID + 1;
13615         mockGetApplicationInfo(TEST_PACKAGE_NAME, replacedTestPackageUid);
13616         final UidRangeParcel[] uidRangesReplacedPackage =
13617                 toUidRangeStableParcels(uidRangesForUids(replacedTestPackageUid));
13618 
13619         // Send a broadcast indicating a package was replaced.
13620         final Intent replacedIntent = new Intent(ACTION_PACKAGE_REPLACED);
13621         replacedIntent.setData(Uri.parse(packageScheme + TEST_PACKAGE_NAME));
13622         processBroadcast(replacedIntent);
13623 
13624         // Test the original uid is removed and is replaced with the new uid.
13625         verifySetOemNetworkPreferenceForPreference(uidRangesReplacedPackage, uidRangesSinglePackage,
13626                 mCellNetworkAgent.getNetwork().netId, 1 /* times */,
13627                 mCellNetworkAgent.getNetwork().netId, 1 /* times */,
13628                 false /* shouldDestroyNetwork */);
13629     }
13630 
13631     /**
13632      * Test network priority for preference OEM_NETWORK_PREFERENCE_OEM_PAID in the following order:
13633      * NET_CAPABILITY_NOT_METERED -> NET_CAPABILITY_OEM_PAID -> fallback
13634      */
13635     @Test
13636     public void testMultipleDefaultNetworksTracksOemNetworkPreferenceOemPaidCorrectly()
13637             throws Exception {
13638         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
13639                 OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PAID;
13640         setupMultipleDefaultNetworksForOemNetworkPreferenceCurrentUidTest(networkPref);
13641         final int expectedDefaultRequestSize = 2;
13642         final int expectedOemPrefRequestSize = 3;
13643         registerDefaultNetworkCallbacks();
13644 
13645         // The fallback as well as the OEM preference should now be tracked.
13646         assertEquals(expectedDefaultRequestSize, mService.mDefaultNetworkRequests.size());
13647 
13648         // Test lowest to highest priority requests.
13649         // Bring up metered cellular. This will satisfy the fallback network.
13650         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true);
13651         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
13652                 mCellNetworkAgent.getNetwork(),
13653                 mCellNetworkAgent.getNetwork());
13654 
13655         // Bring up ethernet with OEM_PAID. This will satisfy NET_CAPABILITY_OEM_PAID.
13656         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, true);
13657         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
13658                 mCellNetworkAgent.getNetwork(),
13659                 mEthernetNetworkAgent.getNetwork());
13660 
13661         // Bring up unmetered Wi-Fi. This will satisfy NET_CAPABILITY_NOT_METERED.
13662         setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, true);
13663         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
13664                 mWiFiNetworkAgent.getNetwork(),
13665                 mWiFiNetworkAgent.getNetwork());
13666 
13667         // Disconnecting unmetered Wi-Fi will put the pref on OEM_PAID and fallback on cellular.
13668         setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, false);
13669         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
13670                 mCellNetworkAgent.getNetwork(),
13671                 mEthernetNetworkAgent.getNetwork());
13672 
13673         // Disconnecting cellular should keep OEM network on OEM_PAID and fallback will be null.
13674         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, false);
13675         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
13676                 null,
13677                 mEthernetNetworkAgent.getNetwork());
13678 
13679         // Disconnecting OEM_PAID will put both on null as it is the last network.
13680         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, false);
13681         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
13682                 null,
13683                 null);
13684 
13685         // default callbacks will be unregistered in tearDown
13686     }
13687 
13688     @Test
13689     public void testNetworkFactoryRequestsWithMultilayerRequest()
13690             throws Exception {
13691         // First use OEM_PAID preference to create a multi-layer request : 1. listen for
13692         // unmetered, 2. request network with cap OEM_PAID, 3, request the default network for
13693         // fallback.
13694         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
13695                 OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PAID;
13696         setupMultipleDefaultNetworksForOemNetworkPreferenceCurrentUidTest(networkPref);
13697 
13698         final HandlerThread handlerThread = new HandlerThread("MockFactory");
13699         handlerThread.start();
13700         NetworkCapabilities internetFilter = new NetworkCapabilities()
13701                 .addCapability(NET_CAPABILITY_INTERNET)
13702                 .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED);
13703         final MockNetworkFactory internetFactory = new MockNetworkFactory(handlerThread.getLooper(),
13704                 mServiceContext, "internetFactory", internetFilter, mCsHandlerThread);
13705         internetFactory.setScoreFilter(40);
13706         internetFactory.register();
13707         // Default internet request only. The unmetered request is never sent to factories (it's a
13708         // LISTEN, not requestable). The 3rd (fallback) request in OEM_PAID NRI is TRACK_DEFAULT
13709         // which is also not sent to factories. Finally, the OEM_PAID request doesn't match the
13710         // internetFactory filter.
13711         internetFactory.expectRequestAdds(1);
13712         internetFactory.assertRequestCountEquals(1);
13713 
13714         NetworkCapabilities oemPaidFilter = new NetworkCapabilities()
13715                 .addCapability(NET_CAPABILITY_INTERNET)
13716                 .addCapability(NET_CAPABILITY_OEM_PAID)
13717                 .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
13718                 .removeCapability(NET_CAPABILITY_NOT_RESTRICTED);
13719         final MockNetworkFactory oemPaidFactory = new MockNetworkFactory(handlerThread.getLooper(),
13720                 mServiceContext, "oemPaidFactory", oemPaidFilter, mCsHandlerThread);
13721         oemPaidFactory.setScoreFilter(40);
13722         oemPaidFactory.register();
13723         oemPaidFactory.expectRequestAdd(); // Because nobody satisfies the request
13724 
13725         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
13726         mCellNetworkAgent.connect(true);
13727 
13728         // A network connected that satisfies the default internet request. For the OEM_PAID
13729         // preference, this is not as good as an OEM_PAID network, so even if the score of
13730         // the network is better than the factory announced, it still should try to bring up
13731         // the network.
13732         expectNoRequestChanged(oemPaidFactory);
13733         oemPaidFactory.assertRequestCountEquals(1);
13734         // The internet factory however is outscored, and should lose its requests.
13735         internetFactory.expectRequestRemove();
13736         internetFactory.assertRequestCountEquals(0);
13737 
13738         final NetworkCapabilities oemPaidNc = new NetworkCapabilities();
13739         oemPaidNc.addCapability(NET_CAPABILITY_OEM_PAID);
13740         oemPaidNc.removeCapability(NET_CAPABILITY_NOT_RESTRICTED);
13741         final TestNetworkAgentWrapper oemPaidAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR,
13742                 new LinkProperties(), oemPaidNc);
13743         oemPaidAgent.connect(true);
13744 
13745         // The oemPaidAgent has score 50/cell transport, so it beats what the oemPaidFactory can
13746         // provide, therefore it loses the request.
13747         oemPaidFactory.expectRequestRemove();
13748         oemPaidFactory.assertRequestCountEquals(0);
13749         expectNoRequestChanged(internetFactory);
13750         internetFactory.assertRequestCountEquals(0);
13751 
13752         oemPaidAgent.setScore(new NetworkScore.Builder().setLegacyInt(20).setExiting(true).build());
13753         // Now the that the agent is weak, the oemPaidFactory can beat the existing network for the
13754         // OEM_PAID request. The internet factory however can't beat a network that has OEM_PAID
13755         // for the preference request, so it doesn't see the request.
13756         oemPaidFactory.expectRequestAdd();
13757         oemPaidFactory.assertRequestCountEquals(1);
13758         expectNoRequestChanged(internetFactory);
13759         internetFactory.assertRequestCountEquals(0);
13760 
13761         mCellNetworkAgent.disconnect();
13762         // The network satisfying the default internet request has disconnected, so the
13763         // internetFactory sees the default request again. However there is a network with OEM_PAID
13764         // connected, so the 2nd OEM_PAID req is already satisfied, so the oemPaidFactory doesn't
13765         // care about networks that don't have OEM_PAID.
13766         expectNoRequestChanged(oemPaidFactory);
13767         oemPaidFactory.assertRequestCountEquals(1);
13768         internetFactory.expectRequestAdd();
13769         internetFactory.assertRequestCountEquals(1);
13770 
13771         // Cell connects again, still with score 50. Back to the previous state.
13772         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
13773         mCellNetworkAgent.connect(true);
13774         expectNoRequestChanged(oemPaidFactory);
13775         oemPaidFactory.assertRequestCountEquals(1);
13776         internetFactory.expectRequestRemove();
13777         internetFactory.assertRequestCountEquals(0);
13778 
13779         // Create a request that holds the upcoming wifi network.
13780         final TestNetworkCallback wifiCallback = new TestNetworkCallback();
13781         mCm.requestNetwork(new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI).build(),
13782                 wifiCallback);
13783 
13784         // Now WiFi connects and it's unmetered, but it's weaker than cell.
13785         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
13786         mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
13787         mWiFiNetworkAgent.setScore(new NetworkScore.Builder().setLegacyInt(30).setExiting(true)
13788                 .build()); // Not the best Internet network, but unmetered
13789         mWiFiNetworkAgent.connect(true);
13790 
13791         // The OEM_PAID preference prefers an unmetered network to an OEM_PAID network, so
13792         // the oemPaidFactory can't beat wifi no matter how high its score.
13793         oemPaidFactory.expectRequestRemove();
13794         expectNoRequestChanged(internetFactory);
13795 
13796         mCellNetworkAgent.disconnect();
13797         // Now that the best internet network (cell, with its 50 score compared to 30 for WiFi
13798         // at this point), the default internet request is satisfied by a network worse than
13799         // the internetFactory announced, so it gets the request. However, there is still an
13800         // unmetered network, so the oemPaidNetworkFactory still can't beat this.
13801         expectNoRequestChanged(oemPaidFactory);
13802         internetFactory.expectRequestAdd();
13803         mCm.unregisterNetworkCallback(wifiCallback);
13804     }
13805 
13806     /**
13807      * Test network priority for OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK in the following order:
13808      * NET_CAPABILITY_NOT_METERED -> NET_CAPABILITY_OEM_PAID
13809      */
13810     @Test
13811     public void testMultipleDefaultNetworksTracksOemNetworkPreferenceOemPaidNoFallbackCorrectly()
13812             throws Exception {
13813         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
13814                 OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK;
13815         setupMultipleDefaultNetworksForOemNetworkPreferenceCurrentUidTest(networkPref);
13816         final int expectedDefaultRequestSize = 2;
13817         final int expectedOemPrefRequestSize = 2;
13818         registerDefaultNetworkCallbacks();
13819 
13820         // The fallback as well as the OEM preference should now be tracked.
13821         assertEquals(expectedDefaultRequestSize, mService.mDefaultNetworkRequests.size());
13822 
13823         // Test lowest to highest priority requests.
13824         // Bring up metered cellular. This will satisfy the fallback network but not the pref.
13825         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true);
13826         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
13827                 mCellNetworkAgent.getNetwork(),
13828                 mService.mNoServiceNetwork.network());
13829 
13830         // Bring up ethernet with OEM_PAID. This will satisfy NET_CAPABILITY_OEM_PAID.
13831         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, true);
13832         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
13833                 mCellNetworkAgent.getNetwork(),
13834                 mEthernetNetworkAgent.getNetwork());
13835 
13836         // Bring up unmetered Wi-Fi. This will satisfy NET_CAPABILITY_NOT_METERED.
13837         setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, true);
13838         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
13839                 mWiFiNetworkAgent.getNetwork(),
13840                 mWiFiNetworkAgent.getNetwork());
13841 
13842         // Disconnecting unmetered Wi-Fi will put the OEM pref on OEM_PAID and fallback on cellular.
13843         setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, false);
13844         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
13845                 mCellNetworkAgent.getNetwork(),
13846                 mEthernetNetworkAgent.getNetwork());
13847 
13848         // Disconnecting cellular should keep OEM network on OEM_PAID and fallback will be null.
13849         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, false);
13850         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
13851                 null,
13852                 mEthernetNetworkAgent.getNetwork());
13853 
13854         // Disconnecting OEM_PAID puts the fallback on null and the pref on the disconnected net.
13855         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, false);
13856         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
13857                 null,
13858                 mService.mNoServiceNetwork.network());
13859 
13860         // default callbacks will be unregistered in tearDown
13861     }
13862 
13863     /**
13864      * Test network priority for OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY in the following order:
13865      * NET_CAPABILITY_OEM_PAID
13866      * This preference should only apply to OEM_PAID networks.
13867      */
13868     @Test
13869     public void testMultipleDefaultNetworksTracksOemNetworkPreferenceOemPaidOnlyCorrectly()
13870             throws Exception {
13871         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
13872                 OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY;
13873         setupMultipleDefaultNetworksForOemNetworkPreferenceCurrentUidTest(networkPref);
13874         final int expectedDefaultRequestSize = 2;
13875         final int expectedOemPrefRequestSize = 1;
13876         registerDefaultNetworkCallbacks();
13877 
13878         // The fallback as well as the OEM preference should now be tracked.
13879         assertEquals(expectedDefaultRequestSize, mService.mDefaultNetworkRequests.size());
13880 
13881         // Test lowest to highest priority requests.
13882         // Bring up metered cellular. This will satisfy the fallback network.
13883         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true);
13884         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
13885                 mCellNetworkAgent.getNetwork(),
13886                 mService.mNoServiceNetwork.network());
13887 
13888         // Bring up ethernet with OEM_PAID. This will satisfy NET_CAPABILITY_OEM_PAID.
13889         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, true);
13890         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
13891                 mCellNetworkAgent.getNetwork(),
13892                 mEthernetNetworkAgent.getNetwork());
13893 
13894         // Bring up unmetered Wi-Fi. The OEM network shouldn't change, the fallback will take Wi-Fi.
13895         setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, true);
13896         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
13897                 mWiFiNetworkAgent.getNetwork(),
13898                 mEthernetNetworkAgent.getNetwork());
13899 
13900         // Disconnecting unmetered Wi-Fi shouldn't change the OEM network with fallback on cellular.
13901         setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, false);
13902         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
13903                 mCellNetworkAgent.getNetwork(),
13904                 mEthernetNetworkAgent.getNetwork());
13905 
13906         // Disconnecting OEM_PAID will keep the fallback on cellular and nothing for OEM_PAID.
13907         // OEM_PAID_ONLY not supporting a fallback now uses the disconnected network.
13908         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, false);
13909         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
13910                 mCellNetworkAgent.getNetwork(),
13911                 mService.mNoServiceNetwork.network());
13912 
13913         // Disconnecting cellular will put the fallback on null and the pref on disconnected.
13914         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, false);
13915         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
13916                 null,
13917                 mService.mNoServiceNetwork.network());
13918 
13919         // default callbacks will be unregistered in tearDown
13920     }
13921 
13922     /**
13923      * Test network priority for OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY in the following order:
13924      * NET_CAPABILITY_OEM_PRIVATE
13925      * This preference should only apply to OEM_PRIVATE networks.
13926      */
13927     @Test
13928     public void testMultipleDefaultNetworksTracksOemNetworkPreferenceOemPrivateOnlyCorrectly()
13929             throws Exception {
13930         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
13931                 OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY;
13932         setupMultipleDefaultNetworksForOemNetworkPreferenceCurrentUidTest(networkPref);
13933         final int expectedDefaultRequestSize = 2;
13934         final int expectedOemPrefRequestSize = 1;
13935         registerDefaultNetworkCallbacks();
13936 
13937         // The fallback as well as the OEM preference should now be tracked.
13938         assertEquals(expectedDefaultRequestSize, mService.mDefaultNetworkRequests.size());
13939 
13940         // Test lowest to highest priority requests.
13941         // Bring up metered cellular. This will satisfy the fallback network.
13942         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true);
13943         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
13944                 mCellNetworkAgent.getNetwork(),
13945                 mService.mNoServiceNetwork.network());
13946 
13947         // Bring up ethernet with OEM_PRIVATE. This will satisfy NET_CAPABILITY_OEM_PRIVATE.
13948         startOemManagedNetwork(false);
13949         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
13950                 mCellNetworkAgent.getNetwork(),
13951                 mEthernetNetworkAgent.getNetwork());
13952 
13953         // Bring up unmetered Wi-Fi. The OEM network shouldn't change, the fallback will take Wi-Fi.
13954         setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, true);
13955         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
13956                 mWiFiNetworkAgent.getNetwork(),
13957                 mEthernetNetworkAgent.getNetwork());
13958 
13959         // Disconnecting unmetered Wi-Fi shouldn't change the OEM network with fallback on cellular.
13960         setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, false);
13961         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
13962                 mCellNetworkAgent.getNetwork(),
13963                 mEthernetNetworkAgent.getNetwork());
13964 
13965         // Disconnecting OEM_PRIVATE will keep the fallback on cellular.
13966         // OEM_PRIVATE_ONLY not supporting a fallback now uses to the disconnected network.
13967         stopOemManagedNetwork();
13968         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
13969                 mCellNetworkAgent.getNetwork(),
13970                 mService.mNoServiceNetwork.network());
13971 
13972         // Disconnecting cellular will put the fallback on null and pref on disconnected.
13973         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, false);
13974         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
13975                 null,
13976                 mService.mNoServiceNetwork.network());
13977 
13978         // default callbacks will be unregistered in tearDown
13979     }
13980 
13981     @Test
13982     public void testCapabilityWithOemNetworkPreference() throws Exception {
13983         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
13984                 OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY;
13985         setupMultipleDefaultNetworksForOemNetworkPreferenceNotCurrentUidTest(networkPref);
13986         registerDefaultNetworkCallbacks();
13987 
13988         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true);
13989 
13990         mSystemDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
13991         mDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
13992 
13993         mCellNetworkAgent.addCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED);
13994         mSystemDefaultNetworkCallback.expectCapabilitiesThat(mCellNetworkAgent, nc ->
13995                 nc.hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED));
13996         mDefaultNetworkCallback.expectCapabilitiesThat(mCellNetworkAgent, nc ->
13997                 nc.hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED));
13998 
13999         // default callbacks will be unregistered in tearDown
14000     }
14001 
14002     @Test
14003     public void testSetOemNetworkPreferenceLogsRequest() throws Exception {
14004         mServiceContext.setPermission(DUMP, PERMISSION_GRANTED);
14005         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
14006                 OEM_NETWORK_PREFERENCE_OEM_PAID;
14007         final StringWriter stringWriter = new StringWriter();
14008         final String logIdentifier = "UPDATE INITIATED: OemNetworkPreferences";
14009         final Pattern pattern = Pattern.compile(logIdentifier);
14010 
14011         final int expectedNumLogs = 2;
14012         final UidRangeParcel[] uidRanges =
14013                 toUidRangeStableParcels(uidRangesForUids(TEST_PACKAGE_UID));
14014 
14015         // Call twice to generate two logs.
14016         setupSetOemNetworkPreferenceForPreferenceTest(networkPref, uidRanges, TEST_PACKAGE_NAME);
14017         setupSetOemNetworkPreferenceForPreferenceTest(networkPref, uidRanges, TEST_PACKAGE_NAME);
14018         mService.dump(new FileDescriptor(), new PrintWriter(stringWriter), new String[0]);
14019 
14020         final String dumpOutput = stringWriter.toString();
14021         final Matcher matcher = pattern.matcher(dumpOutput);
14022         int count = 0;
14023         while (matcher.find()) {
14024             count++;
14025         }
14026         assertEquals(expectedNumLogs, count);
14027     }
14028 
14029     @Test
14030     public void testGetAllNetworkStateSnapshots() throws Exception {
14031         verifyNoNetwork();
14032 
14033         // Setup test cellular network with specified LinkProperties and NetworkCapabilities,
14034         // verify the content of the snapshot matches.
14035         final LinkProperties cellLp = new LinkProperties();
14036         final LinkAddress myIpv4Addr = new LinkAddress(InetAddress.getByName("192.0.2.129"), 25);
14037         final LinkAddress myIpv6Addr = new LinkAddress(InetAddress.getByName("2001:db8::1"), 64);
14038         cellLp.setInterfaceName("test01");
14039         cellLp.addLinkAddress(myIpv4Addr);
14040         cellLp.addLinkAddress(myIpv6Addr);
14041         cellLp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
14042         cellLp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
14043         cellLp.addRoute(new RouteInfo(myIpv4Addr, null));
14044         cellLp.addRoute(new RouteInfo(myIpv6Addr, null));
14045         final NetworkCapabilities cellNcTemplate = new NetworkCapabilities.Builder()
14046                 .addTransportType(TRANSPORT_CELLULAR).addCapability(NET_CAPABILITY_MMS).build();
14047 
14048         final TestNetworkCallback cellCb = new TestNetworkCallback();
14049         mCm.requestNetwork(new NetworkRequest.Builder().addCapability(NET_CAPABILITY_MMS).build(),
14050                 cellCb);
14051         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp, cellNcTemplate);
14052         mCellNetworkAgent.connect(true);
14053         cellCb.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
14054         List<NetworkStateSnapshot> snapshots = mCm.getAllNetworkStateSnapshots();
14055         assertLength(1, snapshots);
14056 
14057         // Compose the expected cellular snapshot for verification.
14058         final NetworkCapabilities cellNc =
14059                 mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork());
14060         final NetworkStateSnapshot cellSnapshot = new NetworkStateSnapshot(
14061                 mCellNetworkAgent.getNetwork(), cellNc, cellLp,
14062                 null, ConnectivityManager.TYPE_MOBILE);
14063         assertEquals(cellSnapshot, snapshots.get(0));
14064 
14065         // Connect wifi and verify the snapshots.
14066         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
14067         mWiFiNetworkAgent.connect(true);
14068         waitForIdle();
14069         // Compose the expected wifi snapshot for verification.
14070         final NetworkCapabilities wifiNc =
14071                 mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork());
14072         final NetworkStateSnapshot wifiSnapshot = new NetworkStateSnapshot(
14073                 mWiFiNetworkAgent.getNetwork(), wifiNc, new LinkProperties(), null,
14074                 ConnectivityManager.TYPE_WIFI);
14075 
14076         snapshots = mCm.getAllNetworkStateSnapshots();
14077         assertLength(2, snapshots);
14078         assertContainsAll(snapshots, cellSnapshot, wifiSnapshot);
14079 
14080         // Set cellular as suspended, verify the snapshots will contain suspended networks.
14081         mCellNetworkAgent.suspend();
14082         waitForIdle();
14083         final NetworkCapabilities cellSuspendedNc =
14084                 mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork());
14085         assertFalse(cellSuspendedNc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
14086         final NetworkStateSnapshot cellSuspendedSnapshot = new NetworkStateSnapshot(
14087                 mCellNetworkAgent.getNetwork(), cellSuspendedNc, cellLp,
14088                 null, ConnectivityManager.TYPE_MOBILE);
14089         snapshots = mCm.getAllNetworkStateSnapshots();
14090         assertLength(2, snapshots);
14091         assertContainsAll(snapshots, cellSuspendedSnapshot, wifiSnapshot);
14092 
14093         // Disconnect wifi, verify the snapshots contain only cellular.
14094         mWiFiNetworkAgent.disconnect();
14095         waitForIdle();
14096         snapshots = mCm.getAllNetworkStateSnapshots();
14097         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
14098         assertLength(1, snapshots);
14099         assertEquals(cellSuspendedSnapshot, snapshots.get(0));
14100 
14101         mCellNetworkAgent.resume();
14102         waitForIdle();
14103         snapshots = mCm.getAllNetworkStateSnapshots();
14104         assertLength(1, snapshots);
14105         assertEquals(cellSnapshot, snapshots.get(0));
14106 
14107         mCellNetworkAgent.disconnect();
14108         waitForIdle();
14109         verifyNoNetwork();
14110         mCm.unregisterNetworkCallback(cellCb);
14111     }
14112 
14113     // Cannot be part of MockNetworkFactory since it requires method of the test.
14114     private void expectNoRequestChanged(@NonNull MockNetworkFactory factory) {
14115         waitForIdle();
14116         factory.assertNoRequestChanged();
14117     }
14118 
14119     @Test
14120     public void testRegisterBestMatchingNetworkCallback_noIssueToFactory() throws Exception {
14121         // Prepare mock mms factory.
14122         final HandlerThread handlerThread = new HandlerThread("MockCellularFactory");
14123         handlerThread.start();
14124         NetworkCapabilities filter = new NetworkCapabilities()
14125                 .addTransportType(TRANSPORT_CELLULAR)
14126                 .addCapability(NET_CAPABILITY_MMS);
14127         final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
14128                 mServiceContext, "testFactory", filter, mCsHandlerThread);
14129         testFactory.setScoreFilter(40);
14130 
14131         try {
14132             // Register the factory. It doesn't see the default request because its filter does
14133             // not include INTERNET.
14134             testFactory.register();
14135             expectNoRequestChanged(testFactory);
14136             testFactory.assertRequestCountEquals(0);
14137             // The factory won't try to start the network since the default request doesn't
14138             // match the filter (no INTERNET capability).
14139             assertFalse(testFactory.getMyStartRequested());
14140 
14141             // Register callback for listening best matching network. Verify that the request won't
14142             // be sent to factory.
14143             final TestNetworkCallback bestMatchingCb = new TestNetworkCallback();
14144             mCm.registerBestMatchingNetworkCallback(
14145                     new NetworkRequest.Builder().addCapability(NET_CAPABILITY_MMS).build(),
14146                     bestMatchingCb, mCsHandlerThread.getThreadHandler());
14147             bestMatchingCb.assertNoCallback();
14148             expectNoRequestChanged(testFactory);
14149             testFactory.assertRequestCountEquals(0);
14150             assertFalse(testFactory.getMyStartRequested());
14151 
14152             // Fire a normal mms request, verify the factory will only see the request.
14153             final TestNetworkCallback mmsNetworkCallback = new TestNetworkCallback();
14154             final NetworkRequest mmsRequest = new NetworkRequest.Builder()
14155                     .addCapability(NET_CAPABILITY_MMS).build();
14156             mCm.requestNetwork(mmsRequest, mmsNetworkCallback);
14157             testFactory.expectRequestAdd();
14158             testFactory.assertRequestCountEquals(1);
14159             assertTrue(testFactory.getMyStartRequested());
14160 
14161             // Unregister best matching callback, verify factory see no change.
14162             mCm.unregisterNetworkCallback(bestMatchingCb);
14163             expectNoRequestChanged(testFactory);
14164             testFactory.assertRequestCountEquals(1);
14165             assertTrue(testFactory.getMyStartRequested());
14166         } finally {
14167             testFactory.terminate();
14168         }
14169     }
14170 
14171     @Test
14172     public void testRegisterBestMatchingNetworkCallback_trackBestNetwork() throws Exception {
14173         final TestNetworkCallback bestMatchingCb = new TestNetworkCallback();
14174         mCm.registerBestMatchingNetworkCallback(
14175                 new NetworkRequest.Builder().addCapability(NET_CAPABILITY_TRUSTED).build(),
14176                 bestMatchingCb, mCsHandlerThread.getThreadHandler());
14177 
14178         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
14179         mCellNetworkAgent.connect(true);
14180         bestMatchingCb.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
14181 
14182         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
14183         mWiFiNetworkAgent.connect(true);
14184         bestMatchingCb.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
14185 
14186         // Change something on cellular to trigger capabilities changed, since the callback
14187         // only cares about the best network, verify it received nothing from cellular.
14188         mCellNetworkAgent.addCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED);
14189         bestMatchingCb.assertNoCallback();
14190 
14191         // Make cellular the best network again, verify the callback now tracks cellular.
14192         mWiFiNetworkAgent.adjustScore(-50);
14193         bestMatchingCb.expectAvailableCallbacksValidated(mCellNetworkAgent);
14194 
14195         // Make cellular temporary non-trusted, which will not satisfying the request.
14196         // Verify the callback switch from/to the other network accordingly.
14197         mCellNetworkAgent.removeCapability(NET_CAPABILITY_TRUSTED);
14198         bestMatchingCb.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
14199         mCellNetworkAgent.addCapability(NET_CAPABILITY_TRUSTED);
14200         bestMatchingCb.expectAvailableDoubleValidatedCallbacks(mCellNetworkAgent);
14201 
14202         // Verify the callback doesn't care about wifi disconnect.
14203         mWiFiNetworkAgent.disconnect();
14204         bestMatchingCb.assertNoCallback();
14205         mCellNetworkAgent.disconnect();
14206         bestMatchingCb.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
14207     }
14208 
14209     private UidRangeParcel[] uidRangeFor(final UserHandle handle) {
14210         final UidRange range = UidRange.createForUser(handle);
14211         return new UidRangeParcel[] { new UidRangeParcel(range.start, range.stop) };
14212     }
14213 
14214     private UidRangeParcel[] uidRangeFor(final UserHandle handle,
14215             ProfileNetworkPreference profileNetworkPreference) {
14216         final Set<UidRange> uidRangeSet;
14217         UidRange range = UidRange.createForUser(handle);
14218         if (profileNetworkPreference.getIncludedUids().length != 0) {
14219             uidRangeSet = UidRangeUtils.convertArrayToUidRange(
14220                     profileNetworkPreference.getIncludedUids());
14221 
14222         } else if (profileNetworkPreference.getExcludedUids().length != 0)  {
14223             uidRangeSet = UidRangeUtils.removeRangeSetFromUidRange(
14224                     range, UidRangeUtils.convertArrayToUidRange(
14225                             profileNetworkPreference.getExcludedUids()));
14226         } else {
14227             uidRangeSet = new ArraySet<>();
14228             uidRangeSet.add(range);
14229         }
14230         UidRangeParcel[] uidRangeParcels = new UidRangeParcel[uidRangeSet.size()];
14231         int i = 0;
14232         for (UidRange range1 : uidRangeSet) {
14233             uidRangeParcels[i] = new UidRangeParcel(range1.start, range1.stop);
14234             i++;
14235         }
14236         return uidRangeParcels;
14237     }
14238 
14239     private static class TestOnCompleteListener implements Runnable {
14240         final class OnComplete {}
14241         final ArrayTrackRecord<OnComplete>.ReadHead mHistory =
14242                 new ArrayTrackRecord<OnComplete>().newReadHead();
14243 
14244         @Override
14245         public void run() {
14246             mHistory.add(new OnComplete());
14247         }
14248 
14249         public void expectOnComplete() {
14250             assertNotNull(mHistory.poll(TIMEOUT_MS, it -> true));
14251         }
14252     }
14253 
14254     private TestNetworkAgentWrapper makeEnterpriseNetworkAgent() throws Exception {
14255         final NetworkCapabilities workNc = new NetworkCapabilities();
14256         workNc.addCapability(NET_CAPABILITY_ENTERPRISE);
14257         workNc.removeCapability(NET_CAPABILITY_NOT_RESTRICTED);
14258         return new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, new LinkProperties(), workNc);
14259     }
14260 
14261     private TestNetworkAgentWrapper makeEnterpriseNetworkAgent(int enterpriseId) throws Exception {
14262         final NetworkCapabilities workNc = new NetworkCapabilities();
14263         workNc.addCapability(NET_CAPABILITY_ENTERPRISE);
14264         workNc.removeCapability(NET_CAPABILITY_NOT_RESTRICTED);
14265         workNc.addEnterpriseId(enterpriseId);
14266         return new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, new LinkProperties(), workNc);
14267     }
14268 
14269     private TestNetworkCallback mEnterpriseCallback;
14270     private UserHandle setupEnterpriseNetwork() {
14271         final UserHandle userHandle = UserHandle.of(TEST_WORK_PROFILE_USER_ID);
14272         mServiceContext.setWorkProfile(userHandle, true);
14273 
14274         // File a request to avoid the enterprise network being disconnected as soon as the default
14275         // request goes away – it would make impossible to test that networkRemoveUidRanges
14276         // is called, as the network would disconnect first for lack of a request.
14277         mEnterpriseCallback = new TestNetworkCallback();
14278         final NetworkRequest keepUpRequest = new NetworkRequest.Builder()
14279                 .addCapability(NET_CAPABILITY_ENTERPRISE)
14280                 .build();
14281         mCm.requestNetwork(keepUpRequest, mEnterpriseCallback);
14282         return userHandle;
14283     }
14284 
14285     private void maybeTearDownEnterpriseNetwork() {
14286         if (null != mEnterpriseCallback) {
14287             mCm.unregisterNetworkCallback(mEnterpriseCallback);
14288         }
14289     }
14290 
14291     /**
14292      * Make sure per profile network preferences behave as expected for a given
14293      * profile network preference.
14294      */
14295     public void testPreferenceForUserNetworkUpDownForGivenPreference(
14296             ProfileNetworkPreference profileNetworkPreference,
14297             boolean connectWorkProfileAgentAhead,
14298             UserHandle testHandle,
14299             TestNetworkCallback profileDefaultNetworkCallback,
14300             TestNetworkCallback disAllowProfileDefaultNetworkCallback) throws Exception {
14301         final InOrder inOrder = inOrder(mMockNetd);
14302 
14303         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
14304         mCellNetworkAgent.connect(true);
14305 
14306         mSystemDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
14307         mDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
14308         profileDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
14309         if (disAllowProfileDefaultNetworkCallback != null) {
14310             disAllowProfileDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(
14311                     mCellNetworkAgent);
14312         }
14313         inOrder.verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
14314                 mCellNetworkAgent.getNetwork().netId, INetd.PERMISSION_NONE));
14315 
14316         final TestNetworkAgentWrapper workAgent =
14317                 makeEnterpriseNetworkAgent(profileNetworkPreference.getPreferenceEnterpriseId());
14318         if (connectWorkProfileAgentAhead) {
14319             workAgent.connect(false);
14320         }
14321 
14322         final TestOnCompleteListener listener = new TestOnCompleteListener();
14323         mCm.setProfileNetworkPreferences(testHandle, List.of(profileNetworkPreference),
14324                 r -> r.run(), listener);
14325         listener.expectOnComplete();
14326         boolean allowFallback = true;
14327         if (profileNetworkPreference.getPreference()
14328                 == PROFILE_NETWORK_PREFERENCE_ENTERPRISE_NO_FALLBACK) {
14329             allowFallback = false;
14330         }
14331         if (allowFallback && !connectWorkProfileAgentAhead) {
14332             // Setting a network preference for this user will create a new set of routing rules for
14333             // the UID range that corresponds to this user, inorder to define the default network
14334             // for these apps separately. This is true because the multi-layer request relevant to
14335             // this UID range contains a TRACK_DEFAULT, so the range will be moved through
14336             // UID-specific rules to the correct network – in this case the system default network.
14337             // The case where the default network for the profile happens to be the same as the
14338             // system default is not handled specially, the rules are always active as long as
14339             // a preference is set.
14340             inOrder.verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
14341                     mCellNetworkAgent.getNetwork().netId,
14342                     uidRangeFor(testHandle, profileNetworkPreference),
14343                     PREFERENCE_ORDER_PROFILE));
14344         }
14345 
14346         // The enterprise network is not ready yet.
14347         assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback);
14348         if (allowFallback && !connectWorkProfileAgentAhead) {
14349             assertNoCallbacks(profileDefaultNetworkCallback);
14350         } else if (!connectWorkProfileAgentAhead) {
14351             profileDefaultNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
14352             if (disAllowProfileDefaultNetworkCallback != null) {
14353                 assertNoCallbacks(disAllowProfileDefaultNetworkCallback);
14354             }
14355         }
14356 
14357         if (!connectWorkProfileAgentAhead) {
14358             workAgent.connect(false);
14359         }
14360 
14361         profileDefaultNetworkCallback.expectAvailableCallbacksUnvalidated(workAgent);
14362         if (disAllowProfileDefaultNetworkCallback != null) {
14363             disAllowProfileDefaultNetworkCallback.assertNoCallback();
14364         }
14365         mSystemDefaultNetworkCallback.assertNoCallback();
14366         mDefaultNetworkCallback.assertNoCallback();
14367         inOrder.verify(mMockNetd).networkCreate(
14368                 nativeNetworkConfigPhysical(workAgent.getNetwork().netId, INetd.PERMISSION_SYSTEM));
14369         inOrder.verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
14370                 workAgent.getNetwork().netId,
14371                 uidRangeFor(testHandle, profileNetworkPreference),
14372                 PREFERENCE_ORDER_PROFILE));
14373 
14374         if (allowFallback && !connectWorkProfileAgentAhead) {
14375             inOrder.verify(mMockNetd).networkRemoveUidRangesParcel(new NativeUidRangeConfig(
14376                     mCellNetworkAgent.getNetwork().netId,
14377                     uidRangeFor(testHandle, profileNetworkPreference),
14378                     PREFERENCE_ORDER_PROFILE));
14379         }
14380 
14381         // Make sure changes to the work agent send callbacks to the app in the work profile, but
14382         // not to the other apps.
14383         workAgent.setNetworkValid(true /* isStrictMode */);
14384         workAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
14385         profileDefaultNetworkCallback.expectCapabilitiesThat(workAgent,
14386                 nc -> nc.hasCapability(NET_CAPABILITY_VALIDATED)
14387                         && nc.hasCapability(NET_CAPABILITY_ENTERPRISE)
14388                         && nc.hasEnterpriseId(
14389                                 profileNetworkPreference.getPreferenceEnterpriseId())
14390                         && nc.getEnterpriseIds().length == 1);
14391         if (disAllowProfileDefaultNetworkCallback != null) {
14392             assertNoCallbacks(disAllowProfileDefaultNetworkCallback);
14393         }
14394         assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback);
14395 
14396         workAgent.addCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED);
14397         profileDefaultNetworkCallback.expectCapabilitiesThat(workAgent, nc ->
14398                 nc.hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED));
14399         if (disAllowProfileDefaultNetworkCallback != null) {
14400             assertNoCallbacks(disAllowProfileDefaultNetworkCallback);
14401         }
14402         assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback);
14403 
14404         // Conversely, change a capability on the system-wide default network and make sure
14405         // that only the apps outside of the work profile receive the callbacks.
14406         mCellNetworkAgent.addCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED);
14407         mSystemDefaultNetworkCallback.expectCapabilitiesThat(mCellNetworkAgent, nc ->
14408                 nc.hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED));
14409         mDefaultNetworkCallback.expectCapabilitiesThat(mCellNetworkAgent, nc ->
14410                 nc.hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED));
14411         if (disAllowProfileDefaultNetworkCallback != null) {
14412             disAllowProfileDefaultNetworkCallback.expectCapabilitiesThat(mCellNetworkAgent, nc ->
14413                     nc.hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED));
14414         }
14415         profileDefaultNetworkCallback.assertNoCallback();
14416 
14417         // Disconnect and reconnect the system-wide default network and make sure that the
14418         // apps on this network see the appropriate callbacks, and the app on the work profile
14419         // doesn't because it continues to use the enterprise network.
14420         mCellNetworkAgent.disconnect();
14421         mSystemDefaultNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
14422         mDefaultNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
14423         if (disAllowProfileDefaultNetworkCallback != null) {
14424             disAllowProfileDefaultNetworkCallback.expectCallback(
14425                     CallbackEntry.LOST, mCellNetworkAgent);
14426         }
14427         profileDefaultNetworkCallback.assertNoCallback();
14428         inOrder.verify(mMockNetd).networkDestroy(mCellNetworkAgent.getNetwork().netId);
14429 
14430         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
14431         mCellNetworkAgent.connect(true);
14432         mSystemDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
14433         mDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
14434         if (disAllowProfileDefaultNetworkCallback != null) {
14435             disAllowProfileDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(
14436                     mCellNetworkAgent);
14437 
14438         }
14439         profileDefaultNetworkCallback.assertNoCallback();
14440         inOrder.verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
14441                 mCellNetworkAgent.getNetwork().netId, INetd.PERMISSION_NONE));
14442 
14443         // When the agent disconnects, test that the app on the work profile falls back to the
14444         // default network.
14445         workAgent.disconnect();
14446         profileDefaultNetworkCallback.expectCallback(CallbackEntry.LOST, workAgent);
14447         if (allowFallback) {
14448             profileDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
14449             if (disAllowProfileDefaultNetworkCallback != null) {
14450                 assertNoCallbacks(disAllowProfileDefaultNetworkCallback);
14451             }
14452         }
14453         assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback);
14454         if (allowFallback) {
14455             inOrder.verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
14456                     mCellNetworkAgent.getNetwork().netId,
14457                     uidRangeFor(testHandle, profileNetworkPreference),
14458                     PREFERENCE_ORDER_PROFILE));
14459         }
14460         inOrder.verify(mMockNetd).networkDestroy(workAgent.getNetwork().netId);
14461 
14462         mCellNetworkAgent.disconnect();
14463         mSystemDefaultNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
14464         mDefaultNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
14465         if (disAllowProfileDefaultNetworkCallback != null) {
14466             disAllowProfileDefaultNetworkCallback.expectCallback(
14467                     CallbackEntry.LOST, mCellNetworkAgent);
14468         }
14469         if (allowFallback) {
14470             profileDefaultNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
14471         }
14472 
14473         // Waiting for the handler to be idle before checking for networkDestroy is necessary
14474         // here because ConnectivityService calls onLost before the network is fully torn down.
14475         waitForIdle();
14476         inOrder.verify(mMockNetd).networkDestroy(mCellNetworkAgent.getNetwork().netId);
14477 
14478         // If the control comes here, callbacks seem to behave correctly in the presence of
14479         // a default network when the enterprise network goes up and down. Now, make sure they
14480         // also behave correctly in the absence of a system-wide default network.
14481         final TestNetworkAgentWrapper workAgent2 =
14482                 makeEnterpriseNetworkAgent(profileNetworkPreference.getPreferenceEnterpriseId());
14483         workAgent2.connect(false);
14484 
14485         profileDefaultNetworkCallback.expectAvailableCallbacksUnvalidated(workAgent2);
14486         if (disAllowProfileDefaultNetworkCallback != null) {
14487             assertNoCallbacks(disAllowProfileDefaultNetworkCallback);
14488         }
14489         assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback);
14490         inOrder.verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
14491                 workAgent2.getNetwork().netId, INetd.PERMISSION_SYSTEM));
14492         inOrder.verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
14493                 workAgent2.getNetwork().netId,
14494                 uidRangeFor(testHandle, profileNetworkPreference), PREFERENCE_ORDER_PROFILE));
14495 
14496         workAgent2.setNetworkValid(true /* isStrictMode */);
14497         workAgent2.mNetworkMonitor.forceReevaluation(Process.myUid());
14498         profileDefaultNetworkCallback.expectCapabilitiesThat(workAgent2,
14499                 nc -> nc.hasCapability(NET_CAPABILITY_ENTERPRISE)
14500                         && !nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)
14501                         && nc.hasEnterpriseId(
14502                         profileNetworkPreference.getPreferenceEnterpriseId())
14503                         && nc.getEnterpriseIds().length == 1);
14504         if (disAllowProfileDefaultNetworkCallback != null) {
14505             assertNoCallbacks(disAllowProfileDefaultNetworkCallback);
14506         }
14507         assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback);
14508         inOrder.verify(mMockNetd, never()).networkAddUidRangesParcel(any());
14509 
14510         // When the agent disconnects, test that the app on the work profile fall back to the
14511         // default network.
14512         workAgent2.disconnect();
14513         profileDefaultNetworkCallback.expectCallback(CallbackEntry.LOST, workAgent2);
14514         if (disAllowProfileDefaultNetworkCallback != null) {
14515             assertNoCallbacks(disAllowProfileDefaultNetworkCallback);
14516         }
14517         assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback);
14518         inOrder.verify(mMockNetd).networkDestroy(workAgent2.getNetwork().netId);
14519 
14520         assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback,
14521                 profileDefaultNetworkCallback);
14522 
14523         // Callbacks will be unregistered by tearDown()
14524     }
14525 
14526     /**
14527      * Make sure per-profile networking preference behaves as expected when the enterprise network
14528      * goes up and down while the preference is active. Make sure they behave as expected whether
14529      * there is a general default network or not.
14530      */
14531     @Test
14532     public void testPreferenceForUserNetworkUpDown() throws Exception {
14533         final UserHandle testHandle = setupEnterpriseNetwork();
14534         registerDefaultNetworkCallbacks();
14535         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder =
14536                 new ProfileNetworkPreference.Builder();
14537         profileNetworkPreferenceBuilder.setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE);
14538         profileNetworkPreferenceBuilder.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1);
14539         testPreferenceForUserNetworkUpDownForGivenPreference(
14540                 profileNetworkPreferenceBuilder.build(), false,
14541                 testHandle, mProfileDefaultNetworkCallback, null);
14542     }
14543 
14544     /**
14545      * Make sure per-profile networking preference behaves as expected when the enterprise network
14546      * goes up and down while the preference is active. Make sure they behave as expected whether
14547      * there is a general default network or not when configured to not fallback to default network.
14548      */
14549     @Test
14550     public void testPreferenceForUserNetworkUpDownWithNoFallback() throws Exception {
14551         final UserHandle testHandle = setupEnterpriseNetwork();
14552         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder =
14553                 new ProfileNetworkPreference.Builder();
14554         profileNetworkPreferenceBuilder.setPreference(
14555                 PROFILE_NETWORK_PREFERENCE_ENTERPRISE_NO_FALLBACK);
14556         profileNetworkPreferenceBuilder.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1);
14557         registerDefaultNetworkCallbacks();
14558         testPreferenceForUserNetworkUpDownForGivenPreference(
14559                 profileNetworkPreferenceBuilder.build(), false,
14560                 testHandle, mProfileDefaultNetworkCallback, null);
14561     }
14562 
14563     /**
14564      * Make sure per-profile networking preference behaves as expected when the enterprise network
14565      * goes up and down while the preference is active. Make sure they behave as expected whether
14566      * there is a general default network or not when configured to not fallback to default network
14567      * along with already connected enterprise work agent
14568      */
14569     @Test
14570     public void testPreferenceForUserNetworkUpDownWithNoFallbackWithAlreadyConnectedWorkAgent()
14571             throws Exception {
14572         final UserHandle testHandle = setupEnterpriseNetwork();
14573         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder =
14574                 new ProfileNetworkPreference.Builder();
14575         profileNetworkPreferenceBuilder.setPreference(
14576                 PROFILE_NETWORK_PREFERENCE_ENTERPRISE_NO_FALLBACK);
14577         profileNetworkPreferenceBuilder.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1);
14578         registerDefaultNetworkCallbacks();
14579         testPreferenceForUserNetworkUpDownForGivenPreference(
14580                 profileNetworkPreferenceBuilder.build(), true, testHandle,
14581                 mProfileDefaultNetworkCallback, null);
14582     }
14583 
14584     /**
14585      * Make sure per-profile networking preference for specific uid of test handle
14586      * behaves as expected
14587      */
14588     @Test
14589     public void testPreferenceForDefaultUidOfTestHandle() throws Exception {
14590         final UserHandle testHandle = setupEnterpriseNetwork();
14591         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder =
14592                 new ProfileNetworkPreference.Builder();
14593         profileNetworkPreferenceBuilder.setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE);
14594         profileNetworkPreferenceBuilder.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1);
14595         profileNetworkPreferenceBuilder.setIncludedUids(
14596                 new int[]{testHandle.getUid(TEST_WORK_PROFILE_APP_UID)});
14597         registerDefaultNetworkCallbacks();
14598         testPreferenceForUserNetworkUpDownForGivenPreference(
14599                 profileNetworkPreferenceBuilder.build(), false, testHandle,
14600                 mProfileDefaultNetworkCallback, null);
14601     }
14602 
14603     /**
14604      * Make sure per-profile networking preference for specific uid of test handle
14605      * behaves as expected
14606      */
14607     @Test
14608     public void testPreferenceForSpecificUidOfOnlyOneApp() throws Exception {
14609         final UserHandle testHandle = setupEnterpriseNetwork();
14610         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder =
14611                 new ProfileNetworkPreference.Builder();
14612         profileNetworkPreferenceBuilder.setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE);
14613         profileNetworkPreferenceBuilder.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1);
14614         profileNetworkPreferenceBuilder.setIncludedUids(
14615                 new int[]{testHandle.getUid(TEST_WORK_PROFILE_APP_UID_2)});
14616         registerDefaultNetworkCallbacks();
14617         testPreferenceForUserNetworkUpDownForGivenPreference(
14618                 profileNetworkPreferenceBuilder.build(), false,
14619                 testHandle, mProfileDefaultNetworkCallbackAsAppUid2, null);
14620     }
14621 
14622     /**
14623      * Make sure per-profile networking preference for specific uid of test handle
14624      * behaves as expected
14625      */
14626     @Test
14627     public void testPreferenceForDisallowSpecificUidOfApp() throws Exception {
14628         final UserHandle testHandle = setupEnterpriseNetwork();
14629         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder =
14630                 new ProfileNetworkPreference.Builder();
14631         profileNetworkPreferenceBuilder.setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE);
14632         profileNetworkPreferenceBuilder.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1);
14633         profileNetworkPreferenceBuilder.setExcludedUids(
14634                 new int[]{testHandle.getUid(TEST_WORK_PROFILE_APP_UID_2)});
14635         registerDefaultNetworkCallbacks();
14636         testPreferenceForUserNetworkUpDownForGivenPreference(
14637                 profileNetworkPreferenceBuilder.build(), false,
14638                 testHandle, mProfileDefaultNetworkCallback,
14639                 mProfileDefaultNetworkCallbackAsAppUid2);
14640     }
14641 
14642     /**
14643      * Make sure per-profile networking preference for specific uid of test handle
14644      * invalid uid inputs
14645      */
14646     @Test
14647     public void testPreferenceForInvalidUids() throws Exception {
14648         final UserHandle testHandle = setupEnterpriseNetwork();
14649         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder =
14650                 new ProfileNetworkPreference.Builder();
14651         profileNetworkPreferenceBuilder.setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE);
14652         profileNetworkPreferenceBuilder.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1);
14653         profileNetworkPreferenceBuilder.setExcludedUids(
14654                 new int[]{testHandle.getUid(0) - 1});
14655         final TestOnCompleteListener listener = new TestOnCompleteListener();
14656         Assert.assertThrows(IllegalArgumentException.class, () -> mCm.setProfileNetworkPreferences(
14657                 testHandle, List.of(profileNetworkPreferenceBuilder.build()),
14658                 r -> r.run(), listener));
14659 
14660         profileNetworkPreferenceBuilder.setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE);
14661         profileNetworkPreferenceBuilder.setIncludedUids(
14662                 new int[]{testHandle.getUid(0) - 1});
14663         Assert.assertThrows(IllegalArgumentException.class,
14664                 () -> mCm.setProfileNetworkPreferences(
14665                         testHandle, List.of(profileNetworkPreferenceBuilder.build()),
14666                         r -> r.run(), listener));
14667 
14668 
14669         profileNetworkPreferenceBuilder.setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE);
14670         profileNetworkPreferenceBuilder.setIncludedUids(
14671                 new int[]{testHandle.getUid(0) - 1});
14672         profileNetworkPreferenceBuilder.setExcludedUids(
14673                 new int[]{testHandle.getUid(TEST_WORK_PROFILE_APP_UID_2)});
14674         Assert.assertThrows(IllegalArgumentException.class,
14675                 () -> mCm.setProfileNetworkPreferences(
14676                         testHandle, List.of(profileNetworkPreferenceBuilder.build()),
14677                         r -> r.run(), listener));
14678 
14679         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder2 =
14680                 new ProfileNetworkPreference.Builder();
14681         profileNetworkPreferenceBuilder2.setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE);
14682         profileNetworkPreferenceBuilder2.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1);
14683         profileNetworkPreferenceBuilder2.setIncludedUids(
14684                 new int[]{testHandle.getUid(TEST_WORK_PROFILE_APP_UID_2)});
14685         profileNetworkPreferenceBuilder.setIncludedUids(
14686                 new int[]{testHandle.getUid(TEST_WORK_PROFILE_APP_UID_2)});
14687         Assert.assertThrows(IllegalArgumentException.class,
14688                 () -> mCm.setProfileNetworkPreferences(
14689                         testHandle, List.of(profileNetworkPreferenceBuilder.build(),
14690                                 profileNetworkPreferenceBuilder2.build()),
14691                         r -> r.run(), listener));
14692 
14693         profileNetworkPreferenceBuilder2.setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE);
14694         profileNetworkPreferenceBuilder2.setExcludedUids(
14695                 new int[]{testHandle.getUid(TEST_WORK_PROFILE_APP_UID_2)});
14696         profileNetworkPreferenceBuilder.setExcludedUids(
14697                 new int[]{testHandle.getUid(TEST_WORK_PROFILE_APP_UID_2)});
14698         Assert.assertThrows(IllegalArgumentException.class,
14699                 () -> mCm.setProfileNetworkPreferences(
14700                         testHandle, List.of(profileNetworkPreferenceBuilder.build(),
14701                                 profileNetworkPreferenceBuilder2.build()),
14702                         r -> r.run(), listener));
14703 
14704         profileNetworkPreferenceBuilder2.setPreference(
14705                 PROFILE_NETWORK_PREFERENCE_ENTERPRISE_NO_FALLBACK);
14706         profileNetworkPreferenceBuilder2.setExcludedUids(
14707                 new int[]{testHandle.getUid(TEST_WORK_PROFILE_APP_UID_2)});
14708         profileNetworkPreferenceBuilder.setExcludedUids(
14709                 new int[]{testHandle.getUid(TEST_WORK_PROFILE_APP_UID_2)});
14710         Assert.assertThrows(IllegalArgumentException.class,
14711                 () -> mCm.setProfileNetworkPreferences(
14712                         testHandle, List.of(profileNetworkPreferenceBuilder.build(),
14713                                 profileNetworkPreferenceBuilder2.build()),
14714                         r -> r.run(), listener));
14715     }
14716 
14717     /**
14718      * Make sure per-profile networking preference behaves as expected when the enterprise network
14719      * goes up and down while the preference is active. Make sure they behave as expected whether
14720      * there is a general default network or not when configured to fallback to default network
14721      * along with already connected enterprise work agent
14722      */
14723     @Test
14724     public void testPreferenceForUserNetworkUpDownWithFallbackWithAlreadyConnectedWorkAgent()
14725             throws Exception {
14726         final UserHandle testHandle = setupEnterpriseNetwork();
14727         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder =
14728                 new ProfileNetworkPreference.Builder();
14729         profileNetworkPreferenceBuilder.setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE);
14730         profileNetworkPreferenceBuilder.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1);
14731         registerDefaultNetworkCallbacks();
14732         testPreferenceForUserNetworkUpDownForGivenPreference(
14733                 profileNetworkPreferenceBuilder.build(), true,
14734                 testHandle, mProfileDefaultNetworkCallback,
14735                 null);
14736     }
14737 
14738     /**
14739      * Make sure per-profile networking preference behaves as expected when the enterprise network
14740      * goes up and down while the preference is active for a given enterprise identifier
14741      */
14742     @Test
14743     public void testPreferenceForUserNetworkUpDownWithDefaultEnterpriseId()
14744             throws Exception {
14745         final UserHandle testHandle = setupEnterpriseNetwork();
14746         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder =
14747                 new ProfileNetworkPreference.Builder();
14748         profileNetworkPreferenceBuilder.setPreference(
14749                 PROFILE_NETWORK_PREFERENCE_ENTERPRISE_NO_FALLBACK);
14750         profileNetworkPreferenceBuilder.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1);
14751         registerDefaultNetworkCallbacks();
14752         testPreferenceForUserNetworkUpDownForGivenPreference(
14753                 profileNetworkPreferenceBuilder.build(), true,
14754                 testHandle, mProfileDefaultNetworkCallback,
14755                 null);
14756     }
14757 
14758     /**
14759      * Make sure per-profile networking preference behaves as expected when the enterprise network
14760      * goes up and down while the preference is active for a given enterprise identifier
14761      */
14762     @Test
14763     public void testPreferenceForUserNetworkUpDownWithId2()
14764             throws Exception {
14765         final UserHandle testHandle = setupEnterpriseNetwork();
14766         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder =
14767                 new ProfileNetworkPreference.Builder();
14768         profileNetworkPreferenceBuilder.setPreference(
14769                 PROFILE_NETWORK_PREFERENCE_ENTERPRISE_NO_FALLBACK);
14770         profileNetworkPreferenceBuilder.setPreferenceEnterpriseId(
14771                 NET_ENTERPRISE_ID_2);
14772         registerDefaultNetworkCallbacks();
14773         testPreferenceForUserNetworkUpDownForGivenPreference(
14774                 profileNetworkPreferenceBuilder.build(), true,
14775                 testHandle, mProfileDefaultNetworkCallback, null);
14776     }
14777 
14778     /**
14779      * Make sure per-profile networking preference behaves as expected when the enterprise network
14780      * goes up and down while the preference is active for a given enterprise identifier
14781      */
14782     @Test
14783     public void testPreferenceForUserNetworkUpDownWithInvalidId()
14784             throws Exception {
14785         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder =
14786                 new ProfileNetworkPreference.Builder();
14787         profileNetworkPreferenceBuilder.setPreference(
14788                 PROFILE_NETWORK_PREFERENCE_ENTERPRISE_NO_FALLBACK);
14789         profileNetworkPreferenceBuilder.setPreferenceEnterpriseId(0);
14790         registerDefaultNetworkCallbacks();
14791         assertThrows("Should not be able to set invalid enterprise id",
14792                 IllegalStateException.class, () -> profileNetworkPreferenceBuilder.build());
14793     }
14794 
14795     /**
14796      * Make sure per-profile networking preference throws exception when default preference
14797      * is set along with enterprise preference.
14798      */
14799     @Test
14800     public void testPreferenceWithInvalidPreferenceDefaultAndEnterpriseTogether()
14801             throws Exception {
14802         final UserHandle testHandle = setupEnterpriseNetwork();
14803         mServiceContext.setWorkProfile(testHandle, true);
14804 
14805         final int testWorkProfileAppUid1 =
14806                 UserHandle.getUid(testHandle.getIdentifier(), TEST_APP_ID);
14807         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder1 =
14808                 new ProfileNetworkPreference.Builder();
14809         profileNetworkPreferenceBuilder1.setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE);
14810         profileNetworkPreferenceBuilder1.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1);
14811         profileNetworkPreferenceBuilder1.setIncludedUids(new int[]{testWorkProfileAppUid1});
14812 
14813         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder2 =
14814                 new ProfileNetworkPreference.Builder();
14815         profileNetworkPreferenceBuilder2.setPreference(PROFILE_NETWORK_PREFERENCE_DEFAULT);
14816         final TestOnCompleteListener listener = new TestOnCompleteListener();
14817         Assert.assertThrows(IllegalArgumentException.class,
14818                 () -> mCm.setProfileNetworkPreferences(
14819                         testHandle, List.of(profileNetworkPreferenceBuilder1.build(),
14820                                 profileNetworkPreferenceBuilder2.build()),
14821                         r -> r.run(), listener));
14822         Assert.assertThrows(IllegalArgumentException.class,
14823                 () -> mCm.setProfileNetworkPreferences(
14824                         testHandle, List.of(profileNetworkPreferenceBuilder2.build(),
14825                                 profileNetworkPreferenceBuilder1.build()),
14826                         r -> r.run(), listener));
14827     }
14828 
14829     /**
14830      * Make sure per profile network preferences behave as expected when two slices with
14831      * two different apps within same user profile is configured
14832      * Make sure per profile network preferences overrides with latest preference when
14833      * same user preference is set twice
14834      */
14835     @Test
14836     public void testSetPreferenceWithOverridingPreference()
14837             throws Exception {
14838         final InOrder inOrder = inOrder(mMockNetd);
14839         final UserHandle testHandle = setupEnterpriseNetwork();
14840         mServiceContext.setWorkProfile(testHandle, true);
14841         registerDefaultNetworkCallbacks();
14842 
14843         final TestNetworkCallback appCb1 = new TestNetworkCallback();
14844         final TestNetworkCallback appCb2 = new TestNetworkCallback();
14845         final TestNetworkCallback appCb3 = new TestNetworkCallback();
14846 
14847         final int testWorkProfileAppUid1 =
14848                 UserHandle.getUid(testHandle.getIdentifier(), TEST_APP_ID);
14849         final int testWorkProfileAppUid2 =
14850                 UserHandle.getUid(testHandle.getIdentifier(), TEST_APP_ID_2);
14851         final int testWorkProfileAppUid3 =
14852                 UserHandle.getUid(testHandle.getIdentifier(), TEST_APP_ID_3);
14853 
14854         registerDefaultNetworkCallbackAsUid(appCb1, testWorkProfileAppUid1);
14855         registerDefaultNetworkCallbackAsUid(appCb2, testWorkProfileAppUid2);
14856         registerDefaultNetworkCallbackAsUid(appCb3, testWorkProfileAppUid3);
14857 
14858         // Connect both a regular cell agent and an enterprise network first.
14859         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
14860         mCellNetworkAgent.connect(true);
14861 
14862         final TestNetworkAgentWrapper workAgent1 = makeEnterpriseNetworkAgent(NET_ENTERPRISE_ID_1);
14863         final TestNetworkAgentWrapper workAgent2 = makeEnterpriseNetworkAgent(NET_ENTERPRISE_ID_2);
14864         workAgent1.connect(true);
14865         workAgent2.connect(true);
14866 
14867         mSystemDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
14868         mDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
14869 
14870         appCb1.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
14871         appCb2.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
14872         appCb3.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
14873 
14874         verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
14875                 mCellNetworkAgent.getNetwork().netId, INetd.PERMISSION_NONE));
14876         verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
14877                 workAgent1.getNetwork().netId, INetd.PERMISSION_SYSTEM));
14878         verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
14879                 workAgent2.getNetwork().netId, INetd.PERMISSION_SYSTEM));
14880 
14881         final TestOnCompleteListener listener = new TestOnCompleteListener();
14882 
14883         // Set preferences for testHandle to map testWorkProfileAppUid1 to
14884         // NET_ENTERPRISE_ID_1 and testWorkProfileAppUid2 to NET_ENTERPRISE_ID_2.
14885         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder1 =
14886                 new ProfileNetworkPreference.Builder();
14887         profileNetworkPreferenceBuilder1.setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE);
14888         profileNetworkPreferenceBuilder1.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1);
14889         profileNetworkPreferenceBuilder1.setIncludedUids(new int[]{testWorkProfileAppUid1});
14890 
14891         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder2 =
14892                 new ProfileNetworkPreference.Builder();
14893         profileNetworkPreferenceBuilder2.setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE);
14894         profileNetworkPreferenceBuilder2.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_2);
14895         profileNetworkPreferenceBuilder2.setIncludedUids(new int[]{testWorkProfileAppUid2});
14896 
14897         mCm.setProfileNetworkPreferences(testHandle,
14898                 List.of(profileNetworkPreferenceBuilder1.build(),
14899                         profileNetworkPreferenceBuilder2.build()),
14900                 r -> r.run(), listener);
14901         listener.expectOnComplete();
14902         verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
14903                 workAgent2.getNetwork().netId,
14904                 uidRangeFor(testHandle, profileNetworkPreferenceBuilder2.build()),
14905                 PREFERENCE_ORDER_PROFILE));
14906         verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
14907                 workAgent1.getNetwork().netId,
14908                 uidRangeFor(testHandle, profileNetworkPreferenceBuilder1.build()),
14909                 PREFERENCE_ORDER_PROFILE));
14910 
14911         assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback);
14912         appCb1.expectAvailableCallbacksValidated(workAgent1);
14913         appCb2.expectAvailableCallbacksValidated(workAgent2);
14914 
14915         // Set preferences for testHandle to map testWorkProfileAppUid3 to
14916         // to NET_ENTERPRISE_ID_1.
14917         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder3 =
14918                 new ProfileNetworkPreference.Builder();
14919         profileNetworkPreferenceBuilder3.setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE);
14920         profileNetworkPreferenceBuilder3.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1);
14921         profileNetworkPreferenceBuilder3.setIncludedUids(new int[]{testWorkProfileAppUid3});
14922 
14923         mCm.setProfileNetworkPreferences(testHandle,
14924                 List.of(profileNetworkPreferenceBuilder3.build()),
14925                 r -> r.run(), listener);
14926         listener.expectOnComplete();
14927         verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
14928                 workAgent1.getNetwork().netId,
14929                 uidRangeFor(testHandle, profileNetworkPreferenceBuilder3.build()),
14930                 PREFERENCE_ORDER_PROFILE));
14931         verify(mMockNetd).networkRemoveUidRangesParcel(new NativeUidRangeConfig(
14932                 workAgent2.getNetwork().netId,
14933                 uidRangeFor(testHandle, profileNetworkPreferenceBuilder2.build()),
14934                 PREFERENCE_ORDER_PROFILE));
14935         verify(mMockNetd).networkRemoveUidRangesParcel(new NativeUidRangeConfig(
14936                 workAgent1.getNetwork().netId,
14937                 uidRangeFor(testHandle, profileNetworkPreferenceBuilder1.build()),
14938                 PREFERENCE_ORDER_PROFILE));
14939 
14940         assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback);
14941         appCb3.expectAvailableCallbacksValidated(workAgent1);
14942         appCb2.expectAvailableCallbacksValidated(mCellNetworkAgent);
14943         appCb1.expectAvailableCallbacksValidated(mCellNetworkAgent);
14944 
14945         // Set the preferences for testHandle to default.
14946         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder =
14947                 new ProfileNetworkPreference.Builder();
14948         profileNetworkPreferenceBuilder.setPreference(PROFILE_NETWORK_PREFERENCE_DEFAULT);
14949 
14950         mCm.setProfileNetworkPreferences(testHandle,
14951                 List.of(profileNetworkPreferenceBuilder.build()),
14952                 r -> r.run(), listener);
14953         listener.expectOnComplete();
14954         verify(mMockNetd).networkRemoveUidRangesParcel(new NativeUidRangeConfig(
14955                 workAgent1.getNetwork().netId,
14956                 uidRangeFor(testHandle, profileNetworkPreferenceBuilder3.build()),
14957                 PREFERENCE_ORDER_PROFILE));
14958 
14959         assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback, appCb1, appCb2);
14960         appCb3.expectAvailableCallbacksValidated(mCellNetworkAgent);
14961         workAgent2.disconnect();
14962         mCellNetworkAgent.disconnect();
14963 
14964         mCm.unregisterNetworkCallback(appCb1);
14965         mCm.unregisterNetworkCallback(appCb2);
14966         mCm.unregisterNetworkCallback(appCb3);
14967         // Other callbacks will be unregistered by tearDown()
14968     }
14969 
14970     /**
14971      * Make sure per profile network preferences behave as expected when multiple slices with
14972      * multiple different apps within same user profile is configured.
14973      */
14974     @Test
14975     public void testSetPreferenceWithMultiplePreferences()
14976             throws Exception {
14977         final InOrder inOrder = inOrder(mMockNetd);
14978 
14979         final UserHandle testHandle = setupEnterpriseNetwork();
14980         mServiceContext.setWorkProfile(testHandle, true);
14981         registerDefaultNetworkCallbacks();
14982 
14983         final TestNetworkCallback appCb1 = new TestNetworkCallback();
14984         final TestNetworkCallback appCb2 = new TestNetworkCallback();
14985         final TestNetworkCallback appCb3 = new TestNetworkCallback();
14986         final TestNetworkCallback appCb4 = new TestNetworkCallback();
14987         final TestNetworkCallback appCb5 = new TestNetworkCallback();
14988 
14989         final int testWorkProfileAppUid1 =
14990                 UserHandle.getUid(testHandle.getIdentifier(), TEST_APP_ID);
14991         final int testWorkProfileAppUid2 =
14992                 UserHandle.getUid(testHandle.getIdentifier(), TEST_APP_ID_2);
14993         final int testWorkProfileAppUid3 =
14994                 UserHandle.getUid(testHandle.getIdentifier(), TEST_APP_ID_3);
14995         final int testWorkProfileAppUid4 =
14996                 UserHandle.getUid(testHandle.getIdentifier(), TEST_APP_ID_4);
14997         final int testWorkProfileAppUid5 =
14998                 UserHandle.getUid(testHandle.getIdentifier(), TEST_APP_ID_5);
14999 
15000         registerDefaultNetworkCallbackAsUid(appCb1, testWorkProfileAppUid1);
15001         registerDefaultNetworkCallbackAsUid(appCb2, testWorkProfileAppUid2);
15002         registerDefaultNetworkCallbackAsUid(appCb3, testWorkProfileAppUid3);
15003         registerDefaultNetworkCallbackAsUid(appCb4, testWorkProfileAppUid4);
15004         registerDefaultNetworkCallbackAsUid(appCb5, testWorkProfileAppUid5);
15005 
15006         // Connect both a regular cell agent and an enterprise network first.
15007         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
15008         mCellNetworkAgent.connect(true);
15009 
15010         final TestNetworkAgentWrapper workAgent1 = makeEnterpriseNetworkAgent(NET_ENTERPRISE_ID_1);
15011         final TestNetworkAgentWrapper workAgent2 = makeEnterpriseNetworkAgent(NET_ENTERPRISE_ID_2);
15012         final TestNetworkAgentWrapper workAgent3 = makeEnterpriseNetworkAgent(NET_ENTERPRISE_ID_3);
15013         final TestNetworkAgentWrapper workAgent4 = makeEnterpriseNetworkAgent(NET_ENTERPRISE_ID_4);
15014         final TestNetworkAgentWrapper workAgent5 = makeEnterpriseNetworkAgent(NET_ENTERPRISE_ID_5);
15015 
15016         workAgent1.connect(true);
15017         workAgent2.connect(true);
15018         workAgent3.connect(true);
15019         workAgent4.connect(true);
15020         workAgent5.connect(true);
15021 
15022         mSystemDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
15023         mDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
15024         appCb1.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
15025         appCb2.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
15026         appCb3.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
15027         appCb4.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
15028         appCb5.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
15029 
15030         verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
15031                 mCellNetworkAgent.getNetwork().netId, INetd.PERMISSION_NONE));
15032         verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
15033                 workAgent1.getNetwork().netId, INetd.PERMISSION_SYSTEM));
15034         verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
15035                 workAgent2.getNetwork().netId, INetd.PERMISSION_SYSTEM));
15036         verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
15037                 workAgent3.getNetwork().netId, INetd.PERMISSION_SYSTEM));
15038         verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
15039                 workAgent4.getNetwork().netId, INetd.PERMISSION_SYSTEM));
15040         verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
15041                 workAgent5.getNetwork().netId, INetd.PERMISSION_SYSTEM));
15042 
15043         final TestOnCompleteListener listener = new TestOnCompleteListener();
15044 
15045         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder1 =
15046                 new ProfileNetworkPreference.Builder();
15047         profileNetworkPreferenceBuilder1.setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE);
15048         profileNetworkPreferenceBuilder1.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1);
15049         profileNetworkPreferenceBuilder1.setIncludedUids(new int[]{testWorkProfileAppUid1});
15050 
15051         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder2 =
15052                 new ProfileNetworkPreference.Builder();
15053         profileNetworkPreferenceBuilder2.setPreference(
15054                 PROFILE_NETWORK_PREFERENCE_ENTERPRISE_NO_FALLBACK);
15055         profileNetworkPreferenceBuilder2.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_2);
15056         profileNetworkPreferenceBuilder2.setIncludedUids(new int[]{testWorkProfileAppUid2});
15057 
15058         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder3 =
15059                 new ProfileNetworkPreference.Builder();
15060         profileNetworkPreferenceBuilder3.setPreference(
15061                 PROFILE_NETWORK_PREFERENCE_ENTERPRISE);
15062         profileNetworkPreferenceBuilder3.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_3);
15063         profileNetworkPreferenceBuilder3.setIncludedUids(new int[]{testWorkProfileAppUid3});
15064 
15065         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder4 =
15066                 new ProfileNetworkPreference.Builder();
15067         profileNetworkPreferenceBuilder4.setPreference(
15068                 PROFILE_NETWORK_PREFERENCE_ENTERPRISE_NO_FALLBACK);
15069         profileNetworkPreferenceBuilder4.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_4);
15070         profileNetworkPreferenceBuilder4.setIncludedUids(new int[]{testWorkProfileAppUid4});
15071 
15072         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder5 =
15073                 new ProfileNetworkPreference.Builder();
15074         profileNetworkPreferenceBuilder5.setPreference(
15075                 PROFILE_NETWORK_PREFERENCE_ENTERPRISE);
15076         profileNetworkPreferenceBuilder5.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_5);
15077         profileNetworkPreferenceBuilder5.setIncludedUids(new int[]{testWorkProfileAppUid5});
15078 
15079         mCm.setProfileNetworkPreferences(testHandle,
15080                 List.of(profileNetworkPreferenceBuilder1.build(),
15081                         profileNetworkPreferenceBuilder2.build(),
15082                         profileNetworkPreferenceBuilder3.build(),
15083                         profileNetworkPreferenceBuilder4.build(),
15084                         profileNetworkPreferenceBuilder5.build()),
15085                 r -> r.run(), listener);
15086 
15087         listener.expectOnComplete();
15088 
15089         verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
15090                 workAgent1.getNetwork().netId,
15091                 uidRangeFor(testHandle, profileNetworkPreferenceBuilder1.build()),
15092                 PREFERENCE_ORDER_PROFILE));
15093         verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
15094                 workAgent2.getNetwork().netId,
15095                 uidRangeFor(testHandle, profileNetworkPreferenceBuilder2.build()),
15096                 PREFERENCE_ORDER_PROFILE));
15097         verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
15098                 workAgent3.getNetwork().netId,
15099                 uidRangeFor(testHandle, profileNetworkPreferenceBuilder3.build()),
15100                 PREFERENCE_ORDER_PROFILE));
15101         verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
15102                 workAgent4.getNetwork().netId,
15103                 uidRangeFor(testHandle, profileNetworkPreferenceBuilder4.build()),
15104                 PREFERENCE_ORDER_PROFILE));
15105         verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
15106                 workAgent5.getNetwork().netId,
15107                 uidRangeFor(testHandle, profileNetworkPreferenceBuilder5.build()),
15108                 PREFERENCE_ORDER_PROFILE));
15109 
15110         assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback);
15111         appCb1.expectAvailableCallbacksValidated(workAgent1);
15112         appCb2.expectAvailableCallbacksValidated(workAgent2);
15113         appCb3.expectAvailableCallbacksValidated(workAgent3);
15114         appCb4.expectAvailableCallbacksValidated(workAgent4);
15115         appCb5.expectAvailableCallbacksValidated(workAgent5);
15116 
15117         workAgent1.disconnect();
15118         workAgent2.disconnect();
15119         workAgent3.disconnect();
15120         workAgent4.disconnect();
15121         workAgent5.disconnect();
15122 
15123         appCb1.expectCallback(CallbackEntry.LOST, workAgent1);
15124         appCb2.expectCallback(CallbackEntry.LOST, workAgent2);
15125         appCb3.expectCallback(CallbackEntry.LOST, workAgent3);
15126         appCb4.expectCallback(CallbackEntry.LOST, workAgent4);
15127         appCb5.expectCallback(CallbackEntry.LOST, workAgent5);
15128 
15129         appCb1.expectAvailableCallbacksValidated(mCellNetworkAgent);
15130         appCb2.assertNoCallback();
15131         appCb3.expectAvailableCallbacksValidated(mCellNetworkAgent);
15132         appCb4.assertNoCallback();
15133         appCb5.expectAvailableCallbacksValidated(mCellNetworkAgent);
15134 
15135         verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
15136                 mCellNetworkAgent.getNetwork().netId,
15137                 uidRangeFor(testHandle, profileNetworkPreferenceBuilder1.build()),
15138                 PREFERENCE_ORDER_PROFILE));
15139         verify(mMockNetd, never()).networkAddUidRangesParcel(new NativeUidRangeConfig(
15140                 mCellNetworkAgent.getNetwork().netId,
15141                 uidRangeFor(testHandle, profileNetworkPreferenceBuilder2.build()),
15142                 PREFERENCE_ORDER_PROFILE));
15143         verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
15144                 mCellNetworkAgent.getNetwork().netId,
15145                 uidRangeFor(testHandle, profileNetworkPreferenceBuilder3.build()),
15146                 PREFERENCE_ORDER_PROFILE));
15147         verify(mMockNetd, never()).networkAddUidRangesParcel(new NativeUidRangeConfig(
15148                 mCellNetworkAgent.getNetwork().netId,
15149                 uidRangeFor(testHandle, profileNetworkPreferenceBuilder4.build()),
15150                 PREFERENCE_ORDER_PROFILE));
15151         verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
15152                 mCellNetworkAgent.getNetwork().netId,
15153                 uidRangeFor(testHandle, profileNetworkPreferenceBuilder5.build()),
15154                 PREFERENCE_ORDER_PROFILE));
15155 
15156         mSystemDefaultNetworkCallback.assertNoCallback();
15157         mDefaultNetworkCallback.assertNoCallback();
15158 
15159         // Set the preferences for testHandle to default.
15160         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder =
15161                 new ProfileNetworkPreference.Builder();
15162         profileNetworkPreferenceBuilder.setPreference(PROFILE_NETWORK_PREFERENCE_DEFAULT);
15163 
15164         mCm.setProfileNetworkPreferences(testHandle,
15165                 List.of(profileNetworkPreferenceBuilder.build()),
15166                 r -> r.run(), listener);
15167         listener.expectOnComplete();
15168         assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback, appCb1, appCb3,
15169                 appCb5);
15170         appCb2.expectAvailableCallbacksValidated(mCellNetworkAgent);
15171         appCb4.expectAvailableCallbacksValidated(mCellNetworkAgent);
15172         mCellNetworkAgent.disconnect();
15173 
15174         mCm.unregisterNetworkCallback(appCb1);
15175         mCm.unregisterNetworkCallback(appCb2);
15176         mCm.unregisterNetworkCallback(appCb3);
15177         mCm.unregisterNetworkCallback(appCb4);
15178         mCm.unregisterNetworkCallback(appCb5);
15179         // Other callbacks will be unregistered by tearDown()
15180     }
15181 
15182     /**
15183      * Test that, in a given networking context, calling setPreferenceForUser to set per-profile
15184      * defaults on then off works as expected.
15185      */
15186     @Test
15187     public void testSetPreferenceForUserOnOff() throws Exception {
15188         final InOrder inOrder = inOrder(mMockNetd);
15189         final UserHandle testHandle = setupEnterpriseNetwork();
15190 
15191         // Connect both a regular cell agent and an enterprise network first.
15192         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
15193         mCellNetworkAgent.connect(true);
15194 
15195         final TestNetworkAgentWrapper workAgent = makeEnterpriseNetworkAgent();
15196         workAgent.connect(true);
15197 
15198         final TestOnCompleteListener listener = new TestOnCompleteListener();
15199         mCm.setProfileNetworkPreference(testHandle, PROFILE_NETWORK_PREFERENCE_ENTERPRISE,
15200                 r -> r.run(), listener);
15201         listener.expectOnComplete();
15202         inOrder.verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
15203                 mCellNetworkAgent.getNetwork().netId, INetd.PERMISSION_NONE));
15204         inOrder.verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
15205                 workAgent.getNetwork().netId, uidRangeFor(testHandle), PREFERENCE_ORDER_PROFILE));
15206 
15207         registerDefaultNetworkCallbacks();
15208 
15209         mSystemDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
15210         mDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
15211         mProfileDefaultNetworkCallback.expectAvailableCallbacksValidated(workAgent);
15212 
15213         mCm.setProfileNetworkPreference(testHandle, PROFILE_NETWORK_PREFERENCE_DEFAULT,
15214                 r -> r.run(), listener);
15215         listener.expectOnComplete();
15216 
15217         mProfileDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
15218         assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback);
15219         inOrder.verify(mMockNetd).networkRemoveUidRangesParcel(new NativeUidRangeConfig(
15220                 workAgent.getNetwork().netId, uidRangeFor(testHandle), PREFERENCE_ORDER_PROFILE));
15221 
15222         workAgent.disconnect();
15223         mCellNetworkAgent.disconnect();
15224 
15225         // Callbacks will be unregistered by tearDown()
15226     }
15227 
15228     /**
15229      * Test per-profile default networks for two different profiles concurrently.
15230      */
15231     @Test
15232     public void testSetPreferenceForTwoProfiles() throws Exception {
15233         final InOrder inOrder = inOrder(mMockNetd);
15234         final UserHandle testHandle2 = setupEnterpriseNetwork();
15235         final UserHandle testHandle4 = UserHandle.of(TEST_WORK_PROFILE_USER_ID + 2);
15236         mServiceContext.setWorkProfile(testHandle4, true);
15237         registerDefaultNetworkCallbacks();
15238 
15239         final TestNetworkCallback app4Cb = new TestNetworkCallback();
15240         final int testWorkProfileAppUid4 =
15241                 UserHandle.getUid(testHandle4.getIdentifier(), TEST_APP_ID);
15242         registerDefaultNetworkCallbackAsUid(app4Cb, testWorkProfileAppUid4);
15243 
15244         // Connect both a regular cell agent and an enterprise network first.
15245         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
15246         mCellNetworkAgent.connect(true);
15247 
15248         final TestNetworkAgentWrapper workAgent = makeEnterpriseNetworkAgent();
15249         workAgent.connect(true);
15250 
15251         mSystemDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
15252         mDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
15253         mProfileDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
15254         app4Cb.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
15255         inOrder.verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
15256                 mCellNetworkAgent.getNetwork().netId, INetd.PERMISSION_NONE));
15257         inOrder.verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
15258                 workAgent.getNetwork().netId, INetd.PERMISSION_SYSTEM));
15259 
15260         final TestOnCompleteListener listener = new TestOnCompleteListener();
15261         mCm.setProfileNetworkPreference(testHandle2, PROFILE_NETWORK_PREFERENCE_ENTERPRISE,
15262                 r -> r.run(), listener);
15263         listener.expectOnComplete();
15264         inOrder.verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
15265                 workAgent.getNetwork().netId, uidRangeFor(testHandle2), PREFERENCE_ORDER_PROFILE));
15266 
15267         mProfileDefaultNetworkCallback.expectAvailableCallbacksValidated(workAgent);
15268         assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback,
15269                 app4Cb);
15270 
15271         mCm.setProfileNetworkPreference(testHandle4, PROFILE_NETWORK_PREFERENCE_ENTERPRISE,
15272                 r -> r.run(), listener);
15273         listener.expectOnComplete();
15274         inOrder.verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
15275                 workAgent.getNetwork().netId, uidRangeFor(testHandle4), PREFERENCE_ORDER_PROFILE));
15276 
15277         app4Cb.expectAvailableCallbacksValidated(workAgent);
15278         assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback,
15279                 mProfileDefaultNetworkCallback);
15280 
15281         mCm.setProfileNetworkPreference(testHandle2, PROFILE_NETWORK_PREFERENCE_DEFAULT,
15282                 r -> r.run(), listener);
15283         listener.expectOnComplete();
15284         inOrder.verify(mMockNetd).networkRemoveUidRangesParcel(new NativeUidRangeConfig(
15285                 workAgent.getNetwork().netId, uidRangeFor(testHandle2), PREFERENCE_ORDER_PROFILE));
15286 
15287         mProfileDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
15288         assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback,
15289                 app4Cb);
15290 
15291         workAgent.disconnect();
15292         mCellNetworkAgent.disconnect();
15293 
15294         mCm.unregisterNetworkCallback(app4Cb);
15295         // Other callbacks will be unregistered by tearDown()
15296     }
15297 
15298     @Test
15299     public void testProfilePreferenceRemovedUponUserRemoved() throws Exception {
15300         final InOrder inOrder = inOrder(mMockNetd);
15301         final UserHandle testHandle = setupEnterpriseNetwork();
15302 
15303         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
15304         mCellNetworkAgent.connect(true);
15305 
15306         final TestOnCompleteListener listener = new TestOnCompleteListener();
15307         mCm.setProfileNetworkPreference(testHandle, PROFILE_NETWORK_PREFERENCE_ENTERPRISE,
15308                 r -> r.run(), listener);
15309         listener.expectOnComplete();
15310         inOrder.verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
15311                 mCellNetworkAgent.getNetwork().netId, INetd.PERMISSION_NONE));
15312         inOrder.verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
15313                 mCellNetworkAgent.getNetwork().netId, uidRangeFor(testHandle),
15314                 PREFERENCE_ORDER_PROFILE));
15315 
15316         final Intent removedIntent = new Intent(ACTION_USER_REMOVED);
15317         removedIntent.putExtra(Intent.EXTRA_USER, testHandle);
15318         processBroadcast(removedIntent);
15319 
15320         inOrder.verify(mMockNetd).networkRemoveUidRangesParcel(new NativeUidRangeConfig(
15321                 mCellNetworkAgent.getNetwork().netId, uidRangeFor(testHandle),
15322                 PREFERENCE_ORDER_PROFILE));
15323     }
15324 
15325     /**
15326      * Make sure wrong preferences for per-profile default networking are rejected.
15327      */
15328     @Test
15329     public void testProfileNetworkPrefWrongPreference() throws Exception {
15330         final UserHandle testHandle = UserHandle.of(TEST_WORK_PROFILE_USER_ID);
15331         mServiceContext.setWorkProfile(testHandle, true);
15332         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder =
15333                 new ProfileNetworkPreference.Builder();
15334         profileNetworkPreferenceBuilder.setPreference(
15335                 PROFILE_NETWORK_PREFERENCE_ENTERPRISE_NO_FALLBACK + 1);
15336         profileNetworkPreferenceBuilder.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1);
15337         assertThrows("Should not be able to set an illegal preference",
15338                 IllegalArgumentException.class,
15339                 () -> mCm.setProfileNetworkPreferences(testHandle,
15340                         List.of(profileNetworkPreferenceBuilder.build()),
15341                         null, null));
15342     }
15343 
15344     /**
15345      * Make sure requests for per-profile default networking for a non-work profile are
15346      * rejected
15347      */
15348     @Test
15349     public void testProfileNetworkPrefWrongProfile() throws Exception {
15350         final UserHandle testHandle = UserHandle.of(TEST_WORK_PROFILE_USER_ID);
15351         mServiceContext.setWorkProfile(testHandle, false);
15352         mServiceContext.setDeviceOwner(testHandle, null);
15353         assertThrows("Should not be able to set a user pref for a non-work profile "
15354                 + "and non device owner",
15355                 IllegalArgumentException.class , () ->
15356                         mCm.setProfileNetworkPreference(testHandle,
15357                                 PROFILE_NETWORK_PREFERENCE_ENTERPRISE, null, null));
15358     }
15359 
15360     /**
15361      * Make sure requests for per-profile default networking for a device owner is
15362      * accepted on T and not accepted on S
15363      */
15364     @Test
15365     public void testProfileNetworkDeviceOwner() throws Exception {
15366         final UserHandle testHandle = UserHandle.of(TEST_WORK_PROFILE_USER_ID);
15367         mServiceContext.setWorkProfile(testHandle, false);
15368         mServiceContext.setDeviceOwner(testHandle, "deviceOwnerPackage");
15369         ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder =
15370                 new ProfileNetworkPreference.Builder();
15371         profileNetworkPreferenceBuilder.setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE);
15372         profileNetworkPreferenceBuilder.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1);
15373         final TestOnCompleteListener listener = new TestOnCompleteListener();
15374         if (SdkLevel.isAtLeastT()) {
15375             mCm.setProfileNetworkPreferences(testHandle,
15376                     List.of(profileNetworkPreferenceBuilder.build()),
15377                     r -> r.run(), listener);
15378         } else {
15379             // S should not allow setting preference on device owner
15380             assertThrows("Should not be able to set a user pref for a non-work profile on S",
15381                     IllegalArgumentException.class , () ->
15382                             mCm.setProfileNetworkPreferences(testHandle,
15383                                     List.of(profileNetworkPreferenceBuilder.build()),
15384                                     r -> r.run(), listener));
15385         }
15386     }
15387 
15388     @Test
15389     public void testSubIdsClearedWithoutNetworkFactoryPermission() throws Exception {
15390         mServiceContext.setPermission(NETWORK_FACTORY, PERMISSION_DENIED);
15391         final NetworkCapabilities nc = new NetworkCapabilities();
15392         nc.setSubscriptionIds(Collections.singleton(Process.myUid()));
15393 
15394         final NetworkCapabilities result =
15395                 mService.networkCapabilitiesRestrictedForCallerPermissions(
15396                         nc, Process.myPid(), Process.myUid());
15397         assertTrue(result.getSubscriptionIds().isEmpty());
15398     }
15399 
15400     @Test
15401     public void testSubIdsExistWithNetworkFactoryPermission() throws Exception {
15402         mServiceContext.setPermission(NETWORK_FACTORY, PERMISSION_GRANTED);
15403 
15404         final Set<Integer> subIds = Collections.singleton(Process.myUid());
15405         final NetworkCapabilities nc = new NetworkCapabilities();
15406         nc.setSubscriptionIds(subIds);
15407 
15408         final NetworkCapabilities result =
15409                 mService.networkCapabilitiesRestrictedForCallerPermissions(
15410                         nc, Process.myPid(), Process.myUid());
15411         assertEquals(subIds, result.getSubscriptionIds());
15412     }
15413 
15414     private NetworkRequest getRequestWithSubIds() {
15415         return new NetworkRequest.Builder()
15416                 .setSubscriptionIds(Collections.singleton(Process.myUid()))
15417                 .build();
15418     }
15419 
15420     @Test
15421     public void testNetworkRequestWithSubIdsWithNetworkFactoryPermission() throws Exception {
15422         mServiceContext.setPermission(NETWORK_FACTORY, PERMISSION_GRANTED);
15423         final PendingIntent pendingIntent = PendingIntent.getBroadcast(
15424                 mContext, 0 /* requestCode */, new Intent("a"), FLAG_IMMUTABLE);
15425         final NetworkCallback networkCallback1 = new NetworkCallback();
15426         final NetworkCallback networkCallback2 = new NetworkCallback();
15427 
15428         mCm.requestNetwork(getRequestWithSubIds(), networkCallback1);
15429         mCm.requestNetwork(getRequestWithSubIds(), pendingIntent);
15430         mCm.registerNetworkCallback(getRequestWithSubIds(), networkCallback2);
15431 
15432         mCm.unregisterNetworkCallback(networkCallback1);
15433         mCm.releaseNetworkRequest(pendingIntent);
15434         mCm.unregisterNetworkCallback(networkCallback2);
15435     }
15436 
15437     @Test
15438     public void testNetworkRequestWithSubIdsWithoutNetworkFactoryPermission() throws Exception {
15439         mServiceContext.setPermission(NETWORK_FACTORY, PERMISSION_DENIED);
15440         final PendingIntent pendingIntent = PendingIntent.getBroadcast(
15441                 mContext, 0 /* requestCode */, new Intent("a"), FLAG_IMMUTABLE);
15442 
15443         final Class<SecurityException> expected = SecurityException.class;
15444         assertThrows(
15445                 expected, () -> mCm.requestNetwork(getRequestWithSubIds(), new NetworkCallback()));
15446         assertThrows(expected, () -> mCm.requestNetwork(getRequestWithSubIds(), pendingIntent));
15447         assertThrows(
15448                 expected,
15449                 () -> mCm.registerNetworkCallback(getRequestWithSubIds(), new NetworkCallback()));
15450     }
15451 
15452     @Test
15453     public void testAllowedUids() throws Exception {
15454         final int preferenceOrder =
15455                 ConnectivityService.PREFERENCE_ORDER_IRRELEVANT_BECAUSE_NOT_DEFAULT;
15456         mServiceContext.setPermission(NETWORK_FACTORY, PERMISSION_GRANTED);
15457         mServiceContext.setPermission(MANAGE_TEST_NETWORKS, PERMISSION_GRANTED);
15458         final TestNetworkCallback cb = new TestNetworkCallback();
15459         mCm.requestNetwork(new NetworkRequest.Builder()
15460                         .clearCapabilities()
15461                         .addTransportType(TRANSPORT_TEST)
15462                         .build(),
15463                 cb);
15464 
15465         final ArraySet<Integer> uids = new ArraySet<>();
15466         uids.add(200);
15467         final NetworkCapabilities nc = new NetworkCapabilities.Builder()
15468                 .addTransportType(TRANSPORT_TEST)
15469                 .removeCapability(NET_CAPABILITY_NOT_RESTRICTED)
15470                 .setAllowedUids(uids)
15471                 .build();
15472         final TestNetworkAgentWrapper agent = new TestNetworkAgentWrapper(TRANSPORT_TEST,
15473                 new LinkProperties(), nc);
15474         agent.connect(true);
15475         cb.expectAvailableThenValidatedCallbacks(agent);
15476 
15477         final InOrder inOrder = inOrder(mMockNetd);
15478         final NativeUidRangeConfig uids200Parcel = new NativeUidRangeConfig(
15479                 agent.getNetwork().getNetId(),
15480                 intToUidRangeStableParcels(uids),
15481                 preferenceOrder);
15482         if (SdkLevel.isAtLeastT()) {
15483             inOrder.verify(mMockNetd, times(1)).networkAddUidRangesParcel(uids200Parcel);
15484         }
15485 
15486         uids.add(300);
15487         uids.add(400);
15488         nc.setAllowedUids(uids);
15489         agent.setNetworkCapabilities(nc, true /* sendToConnectivityService */);
15490         if (SdkLevel.isAtLeastT()) {
15491             cb.expectCapabilitiesThat(agent, caps -> caps.getAllowedUids().equals(uids));
15492         } else {
15493             cb.assertNoCallback();
15494         }
15495 
15496         uids.remove(200);
15497         final NativeUidRangeConfig uids300400Parcel = new NativeUidRangeConfig(
15498                 agent.getNetwork().getNetId(),
15499                 intToUidRangeStableParcels(uids),
15500                 preferenceOrder);
15501         if (SdkLevel.isAtLeastT()) {
15502             inOrder.verify(mMockNetd, times(1)).networkAddUidRangesParcel(uids300400Parcel);
15503         }
15504 
15505         nc.setAllowedUids(uids);
15506         agent.setNetworkCapabilities(nc, true /* sendToConnectivityService */);
15507         if (SdkLevel.isAtLeastT()) {
15508             cb.expectCapabilitiesThat(agent, caps -> caps.getAllowedUids().equals(uids));
15509             inOrder.verify(mMockNetd, times(1)).networkRemoveUidRangesParcel(uids200Parcel);
15510         } else {
15511             cb.assertNoCallback();
15512         }
15513 
15514         uids.clear();
15515         uids.add(600);
15516         nc.setAllowedUids(uids);
15517         agent.setNetworkCapabilities(nc, true /* sendToConnectivityService */);
15518         if (SdkLevel.isAtLeastT()) {
15519             cb.expectCapabilitiesThat(agent, caps -> caps.getAllowedUids().equals(uids));
15520         } else {
15521             cb.assertNoCallback();
15522         }
15523         final NativeUidRangeConfig uids600Parcel = new NativeUidRangeConfig(
15524                 agent.getNetwork().getNetId(),
15525                 intToUidRangeStableParcels(uids),
15526                 preferenceOrder);
15527         if (SdkLevel.isAtLeastT()) {
15528             inOrder.verify(mMockNetd, times(1)).networkAddUidRangesParcel(uids600Parcel);
15529             inOrder.verify(mMockNetd, times(1)).networkRemoveUidRangesParcel(uids300400Parcel);
15530         }
15531 
15532         uids.clear();
15533         nc.setAllowedUids(uids);
15534         agent.setNetworkCapabilities(nc, true /* sendToConnectivityService */);
15535         if (SdkLevel.isAtLeastT()) {
15536             cb.expectCapabilitiesThat(agent, caps -> caps.getAllowedUids().isEmpty());
15537             inOrder.verify(mMockNetd, times(1)).networkRemoveUidRangesParcel(uids600Parcel);
15538         } else {
15539             cb.assertNoCallback();
15540             verify(mMockNetd, never()).networkAddUidRangesParcel(any());
15541             verify(mMockNetd, never()).networkRemoveUidRangesParcel(any());
15542         }
15543 
15544     }
15545 
15546     @Test
15547     public void testAutomotiveEthernetAllowedUids() throws Exception {
15548         mServiceContext.setPermission(NETWORK_FACTORY, PERMISSION_GRANTED);
15549         mServiceContext.setPermission(MANAGE_TEST_NETWORKS, PERMISSION_GRANTED);
15550 
15551         // In this test the automotive feature will be enabled.
15552         mockHasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, true);
15553 
15554         // Simulate a restricted ethernet network.
15555         final NetworkCapabilities.Builder agentNetCaps = new NetworkCapabilities.Builder()
15556                 .addTransportType(TRANSPORT_ETHERNET)
15557                 .addCapability(NET_CAPABILITY_INTERNET)
15558                 .addCapability(NET_CAPABILITY_NOT_SUSPENDED)
15559                 .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
15560                 .removeCapability(NET_CAPABILITY_NOT_RESTRICTED);
15561 
15562         mEthernetNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET,
15563                 new LinkProperties(), agentNetCaps.build());
15564         validateAllowedUids(mEthernetNetworkAgent, TRANSPORT_ETHERNET, agentNetCaps, true);
15565     }
15566 
15567     @Test
15568     public void testCbsAllowedUids() throws Exception {
15569         mServiceContext.setPermission(NETWORK_FACTORY, PERMISSION_GRANTED);
15570         mServiceContext.setPermission(MANAGE_TEST_NETWORKS, PERMISSION_GRANTED);
15571 
15572         // In this test TEST_PACKAGE_UID will be the UID of the carrier service UID.
15573         doReturn(true).when(mCarrierPrivilegeAuthenticator)
15574                 .hasCarrierPrivilegeForNetworkCapabilities(eq(TEST_PACKAGE_UID), any());
15575 
15576         // Simulate a restricted telephony network. The telephony factory is entitled to set
15577         // the access UID to the service package on any of its restricted networks.
15578         final NetworkCapabilities.Builder agentNetCaps = new NetworkCapabilities.Builder()
15579                 .addTransportType(TRANSPORT_CELLULAR)
15580                 .addCapability(NET_CAPABILITY_INTERNET)
15581                 .addCapability(NET_CAPABILITY_NOT_SUSPENDED)
15582                 .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
15583                 .removeCapability(NET_CAPABILITY_NOT_RESTRICTED)
15584                 .setNetworkSpecifier(new TelephonyNetworkSpecifier(1 /* subid */));
15585 
15586         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR,
15587                 new LinkProperties(), agentNetCaps.build());
15588         validateAllowedUids(mCellNetworkAgent, TRANSPORT_CELLULAR, agentNetCaps, false);
15589     }
15590 
15591     private void validateAllowedUids(final TestNetworkAgentWrapper testAgent,
15592             @NetworkCapabilities.Transport final int transportUnderTest,
15593             final NetworkCapabilities.Builder ncb, final boolean forAutomotive) throws Exception {
15594         final ArraySet<Integer> serviceUidSet = new ArraySet<>();
15595         serviceUidSet.add(TEST_PACKAGE_UID);
15596         final ArraySet<Integer> nonServiceUidSet = new ArraySet<>();
15597         nonServiceUidSet.add(TEST_PACKAGE_UID2);
15598         final ArraySet<Integer> serviceUidSetPlus = new ArraySet<>();
15599         serviceUidSetPlus.add(TEST_PACKAGE_UID);
15600         serviceUidSetPlus.add(TEST_PACKAGE_UID2);
15601 
15602         final TestNetworkCallback cb = new TestNetworkCallback();
15603 
15604         /* Test setting UIDs */
15605         // Cell gets to set the service UID as access UID
15606         mCm.requestNetwork(new NetworkRequest.Builder()
15607                 .addTransportType(transportUnderTest)
15608                 .removeCapability(NET_CAPABILITY_NOT_RESTRICTED)
15609                 .build(), cb);
15610         testAgent.connect(true);
15611         cb.expectAvailableThenValidatedCallbacks(testAgent);
15612         ncb.setAllowedUids(serviceUidSet);
15613         testAgent.setNetworkCapabilities(ncb.build(), true /* sendToCS */);
15614         if (SdkLevel.isAtLeastT()) {
15615             cb.expectCapabilitiesThat(testAgent,
15616                     caps -> caps.getAllowedUids().equals(serviceUidSet));
15617         } else {
15618             // S must ignore access UIDs.
15619             cb.assertNoCallback(TEST_CALLBACK_TIMEOUT_MS);
15620         }
15621 
15622         /* Test setting UIDs is rejected when expected */
15623         if (forAutomotive) {
15624             mockHasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, false);
15625         }
15626 
15627         // ...but not to some other UID. Rejection sets UIDs to the empty set
15628         ncb.setAllowedUids(nonServiceUidSet);
15629         testAgent.setNetworkCapabilities(ncb.build(), true /* sendToCS */);
15630         if (SdkLevel.isAtLeastT()) {
15631             cb.expectCapabilitiesThat(testAgent,
15632                     caps -> caps.getAllowedUids().isEmpty());
15633         } else {
15634             // S must ignore access UIDs.
15635             cb.assertNoCallback(TEST_CALLBACK_TIMEOUT_MS);
15636         }
15637 
15638         // ...and also not to multiple UIDs even including the service UID
15639         ncb.setAllowedUids(serviceUidSetPlus);
15640         testAgent.setNetworkCapabilities(ncb.build(), true /* sendToCS */);
15641         cb.assertNoCallback(TEST_CALLBACK_TIMEOUT_MS);
15642 
15643         testAgent.disconnect();
15644         cb.expectCallback(CallbackEntry.LOST, testAgent);
15645         mCm.unregisterNetworkCallback(cb);
15646 
15647         // Must be unset before touching the transports, because remove and add transport types
15648         // check the specifier on the builder immediately, contradicting normal builder semantics
15649         // TODO : fix the builder
15650         ncb.setNetworkSpecifier(null);
15651         ncb.removeTransportType(transportUnderTest);
15652         ncb.addTransportType(TRANSPORT_WIFI);
15653         // Wifi does not get to set access UID, even to the correct UID
15654         mCm.requestNetwork(new NetworkRequest.Builder()
15655                 .addTransportType(TRANSPORT_WIFI)
15656                 .removeCapability(NET_CAPABILITY_NOT_RESTRICTED)
15657                 .build(), cb);
15658         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI,
15659                 new LinkProperties(), ncb.build());
15660         mWiFiNetworkAgent.connect(true);
15661         cb.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
15662         ncb.setAllowedUids(serviceUidSet);
15663         mWiFiNetworkAgent.setNetworkCapabilities(ncb.build(), true /* sendToCS */);
15664         cb.assertNoCallback(TEST_CALLBACK_TIMEOUT_MS);
15665         mCm.unregisterNetworkCallback(cb);
15666     }
15667 
15668     /**
15669      * Validate request counts are counted accurately on setProfileNetworkPreference on set/replace.
15670      */
15671     @Test
15672     public void testProfileNetworkPrefCountsRequestsCorrectlyOnSet() throws Exception {
15673         final UserHandle testHandle = setupEnterpriseNetwork();
15674         final TestOnCompleteListener listener = new TestOnCompleteListener();
15675         // Leave one request available so the profile preference can be set.
15676         testRequestCountLimits(1 /* countToLeaveAvailable */, () -> {
15677             withPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
15678                     Process.myPid(), Process.myUid(), () -> {
15679                         // Set initially to test the limit prior to having existing requests.
15680                         mCm.setProfileNetworkPreference(testHandle,
15681                                 PROFILE_NETWORK_PREFERENCE_ENTERPRISE,
15682                                 Runnable::run, listener);
15683                     });
15684             listener.expectOnComplete();
15685 
15686             // Simulate filing requests as some app on the work profile
15687             final int otherAppUid = UserHandle.getUid(TEST_WORK_PROFILE_USER_ID,
15688                     UserHandle.getAppId(Process.myUid() + 1));
15689             final int remainingCount = ConnectivityService.MAX_NETWORK_REQUESTS_PER_UID
15690                     - mService.mNetworkRequestCounter.mUidToNetworkRequestCount.get(otherAppUid)
15691                     - 1;
15692             final NetworkCallback[] callbacks = new NetworkCallback[remainingCount];
15693             doAsUid(otherAppUid, () -> {
15694                 for (int i = 0; i < remainingCount; ++i) {
15695                     callbacks[i] = new TestableNetworkCallback();
15696                     mCm.registerDefaultNetworkCallback(callbacks[i]);
15697                 }
15698             });
15699 
15700             withPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
15701                     Process.myPid(), Process.myUid(), () -> {
15702                         // re-set so as to test the limit as part of replacing existing requests.
15703                         mCm.setProfileNetworkPreference(testHandle,
15704                                 PROFILE_NETWORK_PREFERENCE_ENTERPRISE, Runnable::run, listener);
15705                     });
15706             listener.expectOnComplete();
15707 
15708             doAsUid(otherAppUid, () -> {
15709                 for (final NetworkCallback callback : callbacks) {
15710                     mCm.unregisterNetworkCallback(callback);
15711                 }
15712             });
15713         });
15714     }
15715 
15716     /**
15717      * Validate request counts are counted accurately on setOemNetworkPreference on set/replace.
15718      */
15719     @Test
15720     public void testSetOemNetworkPreferenceCountsRequestsCorrectlyOnSet() throws Exception {
15721         mockHasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, true);
15722         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
15723                 OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY;
15724         // Leave one request available so the OEM preference can be set.
15725         testRequestCountLimits(1 /* countToLeaveAvailable */, () ->
15726                 withPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, () -> {
15727                     // Set initially to test the limit prior to having existing requests.
15728                     final TestOemListenerCallback listener = new TestOemListenerCallback();
15729                     mService.setOemNetworkPreference(
15730                             createDefaultOemNetworkPreferences(networkPref), listener);
15731                     listener.expectOnComplete();
15732 
15733                     // re-set so as to test the limit as part of replacing existing requests.
15734                     mService.setOemNetworkPreference(
15735                             createDefaultOemNetworkPreferences(networkPref), listener);
15736                     listener.expectOnComplete();
15737                 }));
15738     }
15739 
15740     private void testRequestCountLimits(final int countToLeaveAvailable,
15741             @NonNull final ExceptionalRunnable r) throws Exception {
15742         final ArraySet<TestNetworkCallback> callbacks = new ArraySet<>();
15743         try {
15744             final int requestCount = mService.mSystemNetworkRequestCounter
15745                     .mUidToNetworkRequestCount.get(Process.myUid());
15746             // The limit is hit when total requests = limit - 1, and exceeded with a crash when
15747             // total requests >= limit.
15748             final int countToFile =
15749                     MAX_NETWORK_REQUESTS_PER_SYSTEM_UID - requestCount - countToLeaveAvailable;
15750             // Need permission so registerDefaultNetworkCallback uses mSystemNetworkRequestCounter
15751             withPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, () -> {
15752                 for (int i = 1; i < countToFile; i++) {
15753                     final TestNetworkCallback cb = new TestNetworkCallback();
15754                     mCm.registerDefaultNetworkCallback(cb);
15755                     callbacks.add(cb);
15756                 }
15757                 assertEquals(MAX_NETWORK_REQUESTS_PER_SYSTEM_UID - 1 - countToLeaveAvailable,
15758                         mService.mSystemNetworkRequestCounter
15759                               .mUidToNetworkRequestCount.get(Process.myUid()));
15760             });
15761             // Code to run to check if it triggers a max request count limit error.
15762             r.run();
15763         } finally {
15764             for (final TestNetworkCallback cb : callbacks) {
15765                 mCm.unregisterNetworkCallback(cb);
15766             }
15767         }
15768     }
15769 
15770     private void assertCreateNrisFromMobileDataPreferredUids(Set<Integer> uids) {
15771         final Set<NetworkRequestInfo> nris =
15772                 mService.createNrisFromMobileDataPreferredUids(uids);
15773         final NetworkRequestInfo nri = nris.iterator().next();
15774         // Verify that one NRI is created with multilayer requests. Because one NRI can contain
15775         // multiple uid ranges, so it only need create one NRI here.
15776         assertEquals(1, nris.size());
15777         assertTrue(nri.isMultilayerRequest());
15778         assertEquals(nri.getUids(), uidRangesForUids(uids));
15779         assertEquals(PREFERENCE_ORDER_MOBILE_DATA_PREFERERRED, nri.mPreferenceOrder);
15780     }
15781 
15782     /**
15783      * Test createNrisFromMobileDataPreferredUids returns correct NetworkRequestInfo.
15784      */
15785     @Test
15786     public void testCreateNrisFromMobileDataPreferredUids() {
15787         // Verify that empty uid set should not create any NRI for it.
15788         final Set<NetworkRequestInfo> nrisNoUid =
15789                 mService.createNrisFromMobileDataPreferredUids(new ArraySet<>());
15790         assertEquals(0, nrisNoUid.size());
15791 
15792         final int uid1 = PRIMARY_USER_HANDLE.getUid(TEST_PACKAGE_UID);
15793         final int uid2 = PRIMARY_USER_HANDLE.getUid(TEST_PACKAGE_UID2);
15794         final int uid3 = SECONDARY_USER_HANDLE.getUid(TEST_PACKAGE_UID);
15795         assertCreateNrisFromMobileDataPreferredUids(Set.of(uid1));
15796         assertCreateNrisFromMobileDataPreferredUids(Set.of(uid1, uid3));
15797         assertCreateNrisFromMobileDataPreferredUids(Set.of(uid1, uid2));
15798     }
15799 
15800     private void setAndUpdateMobileDataPreferredUids(Set<Integer> uids) {
15801         ConnectivitySettingsManager.setMobileDataPreferredUids(mServiceContext, uids);
15802         mService.updateMobileDataPreferredUids();
15803         waitForIdle();
15804     }
15805 
15806     /**
15807      * Test that MOBILE_DATA_PREFERRED_UIDS changes will send correct net id and uid ranges to netd.
15808      */
15809     @Test
15810     public void testMobileDataPreferredUidsChanged() throws Exception {
15811         final InOrder inorder = inOrder(mMockNetd);
15812         registerDefaultNetworkCallbacks();
15813         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
15814         mCellNetworkAgent.connect(true);
15815         mDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
15816         mTestPackageDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
15817 
15818         final int cellNetId = mCellNetworkAgent.getNetwork().netId;
15819         inorder.verify(mMockNetd, times(1)).networkCreate(nativeNetworkConfigPhysical(
15820                 cellNetId, INetd.PERMISSION_NONE));
15821 
15822         // Initial mobile data preferred uids status.
15823         setAndUpdateMobileDataPreferredUids(Set.of());
15824         inorder.verify(mMockNetd, never()).networkAddUidRangesParcel(any());
15825         inorder.verify(mMockNetd, never()).networkRemoveUidRangesParcel(any());
15826 
15827         // Set MOBILE_DATA_PREFERRED_UIDS setting and verify that net id and uid ranges send to netd
15828         final Set<Integer> uids1 = Set.of(PRIMARY_USER_HANDLE.getUid(TEST_PACKAGE_UID));
15829         final UidRangeParcel[] uidRanges1 = toUidRangeStableParcels(uidRangesForUids(uids1));
15830         final NativeUidRangeConfig config1 = new NativeUidRangeConfig(cellNetId, uidRanges1,
15831                 PREFERENCE_ORDER_MOBILE_DATA_PREFERERRED);
15832         setAndUpdateMobileDataPreferredUids(uids1);
15833         inorder.verify(mMockNetd, times(1)).networkAddUidRangesParcel(config1);
15834         inorder.verify(mMockNetd, never()).networkRemoveUidRangesParcel(any());
15835 
15836         // Set MOBILE_DATA_PREFERRED_UIDS setting again and verify that old rules are removed and
15837         // new rules are added.
15838         final Set<Integer> uids2 = Set.of(PRIMARY_USER_HANDLE.getUid(TEST_PACKAGE_UID),
15839                 PRIMARY_USER_HANDLE.getUid(TEST_PACKAGE_UID2),
15840                 SECONDARY_USER_HANDLE.getUid(TEST_PACKAGE_UID));
15841         final UidRangeParcel[] uidRanges2 = toUidRangeStableParcels(uidRangesForUids(uids2));
15842         final NativeUidRangeConfig config2 = new NativeUidRangeConfig(cellNetId, uidRanges2,
15843                 PREFERENCE_ORDER_MOBILE_DATA_PREFERERRED);
15844         setAndUpdateMobileDataPreferredUids(uids2);
15845         inorder.verify(mMockNetd, times(1)).networkRemoveUidRangesParcel(config1);
15846         inorder.verify(mMockNetd, times(1)).networkAddUidRangesParcel(config2);
15847 
15848         // Clear MOBILE_DATA_PREFERRED_UIDS setting again and verify that old rules are removed and
15849         // new rules are not added.
15850         setAndUpdateMobileDataPreferredUids(Set.of());
15851         inorder.verify(mMockNetd, times(1)).networkRemoveUidRangesParcel(config2);
15852         inorder.verify(mMockNetd, never()).networkAddUidRangesParcel(any());
15853     }
15854 
15855     /**
15856      * Make sure mobile data preferred uids feature behaves as expected when the mobile network
15857      * goes up and down while the uids is set. Make sure they behave as expected whether
15858      * there is a general default network or not.
15859      */
15860     @Test
15861     public void testMobileDataPreferenceForMobileNetworkUpDown() throws Exception {
15862         final InOrder inorder = inOrder(mMockNetd);
15863         // File a request for cell to ensure it doesn't go down.
15864         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
15865         final NetworkRequest cellRequest = new NetworkRequest.Builder()
15866                 .addTransportType(TRANSPORT_CELLULAR).build();
15867         mCm.requestNetwork(cellRequest, cellNetworkCallback);
15868         cellNetworkCallback.assertNoCallback();
15869 
15870         registerDefaultNetworkCallbacks();
15871         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
15872         mWiFiNetworkAgent.connect(true);
15873         mDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
15874         mTestPackageDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
15875         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_PACKAGE_UID));
15876 
15877         final int wifiNetId = mWiFiNetworkAgent.getNetwork().netId;
15878         inorder.verify(mMockNetd, times(1)).networkCreate(nativeNetworkConfigPhysical(
15879                 wifiNetId, INetd.PERMISSION_NONE));
15880 
15881         // Initial mobile data preferred uids status.
15882         setAndUpdateMobileDataPreferredUids(Set.of());
15883         inorder.verify(mMockNetd, never()).networkAddUidRangesParcel(any());
15884         inorder.verify(mMockNetd, never()).networkRemoveUidRangesParcel(any());
15885 
15886         // Set MOBILE_DATA_PREFERRED_UIDS setting and verify that wifi net id and uid ranges send to
15887         // netd.
15888         final Set<Integer> uids = Set.of(PRIMARY_USER_HANDLE.getUid(TEST_PACKAGE_UID));
15889         final UidRangeParcel[] uidRanges = toUidRangeStableParcels(uidRangesForUids(uids));
15890         final NativeUidRangeConfig wifiConfig = new NativeUidRangeConfig(wifiNetId, uidRanges,
15891                 PREFERENCE_ORDER_MOBILE_DATA_PREFERERRED);
15892         setAndUpdateMobileDataPreferredUids(uids);
15893         inorder.verify(mMockNetd, times(1)).networkAddUidRangesParcel(wifiConfig);
15894         inorder.verify(mMockNetd, never()).networkRemoveUidRangesParcel(any());
15895 
15896         // Cellular network connected. mTestPackageDefaultNetworkCallback should receive
15897         // callback with cellular network and net id and uid ranges should be updated to netd.
15898         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
15899         mCellNetworkAgent.connect(true);
15900         cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
15901         mDefaultNetworkCallback.assertNoCallback();
15902         mTestPackageDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
15903         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_PACKAGE_UID));
15904 
15905         final int cellNetId = mCellNetworkAgent.getNetwork().netId;
15906         final NativeUidRangeConfig cellConfig = new NativeUidRangeConfig(cellNetId, uidRanges,
15907                 PREFERENCE_ORDER_MOBILE_DATA_PREFERERRED);
15908         inorder.verify(mMockNetd, times(1)).networkCreate(nativeNetworkConfigPhysical(
15909                 cellNetId, INetd.PERMISSION_NONE));
15910         inorder.verify(mMockNetd, times(1)).networkAddUidRangesParcel(cellConfig);
15911         inorder.verify(mMockNetd, times(1)).networkRemoveUidRangesParcel(wifiConfig);
15912 
15913         // Cellular network disconnected. mTestPackageDefaultNetworkCallback should receive
15914         // callback with wifi network from fallback request.
15915         mCellNetworkAgent.disconnect();
15916         mDefaultNetworkCallback.assertNoCallback();
15917         cellNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
15918         mTestPackageDefaultNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
15919         mTestPackageDefaultNetworkCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
15920         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_PACKAGE_UID));
15921         inorder.verify(mMockNetd, times(1)).networkAddUidRangesParcel(wifiConfig);
15922         inorder.verify(mMockNetd, never()).networkRemoveUidRangesParcel(any());
15923         inorder.verify(mMockNetd).networkDestroy(cellNetId);
15924 
15925         // Cellular network comes back. mTestPackageDefaultNetworkCallback should receive
15926         // callback with cellular network.
15927         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
15928         mCellNetworkAgent.connect(true);
15929         cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
15930         mDefaultNetworkCallback.assertNoCallback();
15931         mTestPackageDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
15932         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_PACKAGE_UID));
15933 
15934         final int cellNetId2 = mCellNetworkAgent.getNetwork().netId;
15935         final NativeUidRangeConfig cellConfig2 = new NativeUidRangeConfig(cellNetId2, uidRanges,
15936                 PREFERENCE_ORDER_MOBILE_DATA_PREFERERRED);
15937         inorder.verify(mMockNetd, times(1)).networkCreate(nativeNetworkConfigPhysical(
15938                 cellNetId2, INetd.PERMISSION_NONE));
15939         inorder.verify(mMockNetd, times(1)).networkAddUidRangesParcel(cellConfig2);
15940         inorder.verify(mMockNetd, times(1)).networkRemoveUidRangesParcel(wifiConfig);
15941 
15942         // Wifi network disconnected. mTestPackageDefaultNetworkCallback should not receive
15943         // any callback.
15944         mWiFiNetworkAgent.disconnect();
15945         mDefaultNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
15946         mDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
15947         mTestPackageDefaultNetworkCallback.assertNoCallback();
15948         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_PACKAGE_UID));
15949         waitForIdle();
15950         inorder.verify(mMockNetd, never()).networkAddUidRangesParcel(any());
15951         inorder.verify(mMockNetd, never()).networkRemoveUidRangesParcel(any());
15952         inorder.verify(mMockNetd).networkDestroy(wifiNetId);
15953 
15954         mCm.unregisterNetworkCallback(cellNetworkCallback);
15955     }
15956 
15957     @Test
15958     public void testMultilayerRequestsOfSetMobileDataPreferredUids() throws Exception {
15959         // First set mobile data preferred uid to create a multi-layer requests: 1. request for
15960         // cellular, 2. track the default network for fallback.
15961         setAndUpdateMobileDataPreferredUids(
15962                 Set.of(PRIMARY_USER_HANDLE.getUid(TEST_PACKAGE_UID)));
15963 
15964         final HandlerThread handlerThread = new HandlerThread("MockFactory");
15965         handlerThread.start();
15966         final NetworkCapabilities cellFilter = new NetworkCapabilities()
15967                 .addTransportType(TRANSPORT_CELLULAR)
15968                 .addCapability(NET_CAPABILITY_INTERNET)
15969                 .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED);
15970         final MockNetworkFactory cellFactory = new MockNetworkFactory(handlerThread.getLooper(),
15971                 mServiceContext, "cellFactory", cellFilter, mCsHandlerThread);
15972         cellFactory.setScoreFilter(40);
15973 
15974         try {
15975             cellFactory.register();
15976             // Default internet request and the mobile data preferred request.
15977             cellFactory.expectRequestAdds(2);
15978             cellFactory.assertRequestCountEquals(2);
15979 
15980             mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
15981             mWiFiNetworkAgent.connect(true);
15982 
15983             // The cellFactory however is outscored, and should lose default internet request.
15984             // But it should still see mobile data preferred request.
15985             cellFactory.expectRequestRemove();
15986             cellFactory.assertRequestCountEquals(1);
15987 
15988             mWiFiNetworkAgent.disconnect();
15989             // The network satisfying the default internet request has disconnected, so the
15990             // cellFactory sees the default internet requests again.
15991             cellFactory.expectRequestAdd();
15992             cellFactory.assertRequestCountEquals(2);
15993         } finally {
15994             cellFactory.terminate();
15995             handlerThread.quitSafely();
15996         }
15997     }
15998 
15999     /**
16000      * Validate request counts are counted accurately on MOBILE_DATA_PREFERRED_UIDS change
16001      * on set/replace.
16002      */
16003     @Test
16004     public void testMobileDataPreferredUidsChangedCountsRequestsCorrectlyOnSet() throws Exception {
16005         ConnectivitySettingsManager.setMobileDataPreferredUids(mServiceContext,
16006                 Set.of(PRIMARY_USER_HANDLE.getUid(TEST_PACKAGE_UID)));
16007         // Leave one request available so MDO preference set up above can be set.
16008         testRequestCountLimits(1 /* countToLeaveAvailable */, () ->
16009                 withPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
16010                         Process.myPid(), Process.myUid(), () -> {
16011                             // Set initially to test the limit prior to having existing requests.
16012                             mService.updateMobileDataPreferredUids();
16013                             waitForIdle();
16014 
16015                             // re-set so as to test the limit as part of replacing existing requests
16016                             mService.updateMobileDataPreferredUids();
16017                             waitForIdle();
16018                         }));
16019     }
16020 
16021     @Test
16022     public void testAllNetworkPreferencesCanCoexist()
16023             throws Exception {
16024         final InOrder inorder = inOrder(mMockNetd);
16025         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
16026                 OEM_NETWORK_PREFERENCE_OEM_PAID;
16027         final UserHandle testHandle = setupEnterpriseNetwork();
16028 
16029         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true);
16030         final int cellNetId = mCellNetworkAgent.getNetwork().netId;
16031         inorder.verify(mMockNetd, times(1)).networkCreate(nativeNetworkConfigPhysical(
16032                 cellNetId, INetd.PERMISSION_NONE));
16033 
16034         // Set oem network preference
16035         final int[] uids1 = new int[] { PRIMARY_USER_HANDLE.getUid(TEST_PACKAGE_UID) };
16036         final UidRangeParcel[] uidRanges1 = toUidRangeStableParcels(uidRangesForUids(uids1));
16037         final NativeUidRangeConfig config1 = new NativeUidRangeConfig(cellNetId, uidRanges1,
16038                 PREFERENCE_ORDER_OEM);
16039         setupSetOemNetworkPreferenceForPreferenceTest(networkPref, uidRanges1, TEST_PACKAGE_NAME);
16040         inorder.verify(mMockNetd, times(1)).networkAddUidRangesParcel(config1);
16041         inorder.verify(mMockNetd, never()).networkRemoveUidRangesParcel(any());
16042 
16043         // Set user profile network preference
16044         final TestNetworkAgentWrapper workAgent = makeEnterpriseNetworkAgent();
16045         workAgent.connect(true);
16046 
16047         final TestOnCompleteListener listener = new TestOnCompleteListener();
16048         mCm.setProfileNetworkPreference(testHandle, PROFILE_NETWORK_PREFERENCE_ENTERPRISE,
16049                 r -> r.run(), listener);
16050         listener.expectOnComplete();
16051         final NativeUidRangeConfig config2 = new NativeUidRangeConfig(workAgent.getNetwork().netId,
16052                 uidRangeFor(testHandle), PREFERENCE_ORDER_PROFILE);
16053         inorder.verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
16054                 workAgent.getNetwork().netId, INetd.PERMISSION_SYSTEM));
16055         inorder.verify(mMockNetd, never()).networkRemoveUidRangesParcel(any());
16056         inorder.verify(mMockNetd).networkAddUidRangesParcel(config2);
16057 
16058         // Set MOBILE_DATA_PREFERRED_UIDS setting
16059         final Set<Integer> uids2 = Set.of(PRIMARY_USER_HANDLE.getUid(TEST_PACKAGE_UID2));
16060         final UidRangeParcel[] uidRanges2 = toUidRangeStableParcels(uidRangesForUids(uids2));
16061         final NativeUidRangeConfig config3 = new NativeUidRangeConfig(cellNetId, uidRanges2,
16062                 PREFERENCE_ORDER_MOBILE_DATA_PREFERERRED);
16063         setAndUpdateMobileDataPreferredUids(uids2);
16064         inorder.verify(mMockNetd, never()).networkRemoveUidRangesParcel(any());
16065         inorder.verify(mMockNetd, times(1)).networkAddUidRangesParcel(config3);
16066 
16067         // Set oem network preference again with different uid.
16068         final Set<Integer> uids3 = Set.of(PRIMARY_USER_HANDLE.getUid(TEST_PACKAGE_UID3));
16069         final UidRangeParcel[] uidRanges3 = toUidRangeStableParcels(uidRangesForUids(uids3));
16070         final NativeUidRangeConfig config4 = new NativeUidRangeConfig(cellNetId, uidRanges3,
16071                 PREFERENCE_ORDER_OEM);
16072         setupSetOemNetworkPreferenceForPreferenceTest(networkPref, uidRanges3, "com.android.test");
16073         inorder.verify(mMockNetd, times(1)).networkRemoveUidRangesParcel(config1);
16074         inorder.verify(mMockNetd, times(1)).networkAddUidRangesParcel(config4);
16075 
16076         // Remove user profile network preference
16077         mCm.setProfileNetworkPreference(testHandle, PROFILE_NETWORK_PREFERENCE_DEFAULT,
16078                 r -> r.run(), listener);
16079         listener.expectOnComplete();
16080         inorder.verify(mMockNetd, times(1)).networkRemoveUidRangesParcel(config2);
16081         inorder.verify(mMockNetd, never()).networkAddUidRangesParcel(any());
16082 
16083         // Set MOBILE_DATA_PREFERRED_UIDS setting again with same uid as oem network preference.
16084         final NativeUidRangeConfig config6 = new NativeUidRangeConfig(cellNetId, uidRanges3,
16085                 PREFERENCE_ORDER_MOBILE_DATA_PREFERERRED);
16086         setAndUpdateMobileDataPreferredUids(uids3);
16087         inorder.verify(mMockNetd, times(1)).networkRemoveUidRangesParcel(config3);
16088         inorder.verify(mMockNetd, times(1)).networkAddUidRangesParcel(config6);
16089     }
16090 
16091     @Test
16092     public void testNetworkCallbackAndActiveNetworkForUid_AllNetworkPreferencesEnabled()
16093             throws Exception {
16094         // File a request for cell to ensure it doesn't go down.
16095         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
16096         final NetworkRequest cellRequest = new NetworkRequest.Builder()
16097                 .addTransportType(TRANSPORT_CELLULAR).build();
16098         mCm.requestNetwork(cellRequest, cellNetworkCallback);
16099         cellNetworkCallback.assertNoCallback();
16100 
16101         // Register callbacks and have wifi network as default network.
16102         registerDefaultNetworkCallbacks();
16103         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
16104         mWiFiNetworkAgent.connect(true);
16105         mDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
16106         mProfileDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
16107         mTestPackageDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
16108         assertEquals(mWiFiNetworkAgent.getNetwork(),
16109                 mCm.getActiveNetworkForUid(TEST_WORK_PROFILE_APP_UID));
16110         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_PACKAGE_UID));
16111 
16112         // Set MOBILE_DATA_PREFERRED_UIDS setting with TEST_WORK_PROFILE_APP_UID and
16113         // TEST_PACKAGE_UID. Both mProfileDefaultNetworkCallback and
16114         // mTestPackageDefaultNetworkCallback should receive callback with cell network.
16115         setAndUpdateMobileDataPreferredUids(Set.of(TEST_WORK_PROFILE_APP_UID, TEST_PACKAGE_UID));
16116         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
16117         mCellNetworkAgent.connect(true);
16118         cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
16119         mDefaultNetworkCallback.assertNoCallback();
16120         mProfileDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
16121         mTestPackageDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
16122         assertEquals(mCellNetworkAgent.getNetwork(),
16123                 mCm.getActiveNetworkForUid(TEST_WORK_PROFILE_APP_UID));
16124         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_PACKAGE_UID));
16125 
16126         // Set user profile network preference with test profile. mProfileDefaultNetworkCallback
16127         // should receive callback with higher priority network preference (enterprise network).
16128         // The others should have no callbacks.
16129         final UserHandle testHandle = setupEnterpriseNetwork();
16130         final TestNetworkAgentWrapper workAgent = makeEnterpriseNetworkAgent();
16131         workAgent.connect(true);
16132         final TestOnCompleteListener listener = new TestOnCompleteListener();
16133         mCm.setProfileNetworkPreference(testHandle, PROFILE_NETWORK_PREFERENCE_ENTERPRISE,
16134                 r -> r.run(), listener);
16135         listener.expectOnComplete();
16136         assertNoCallbacks(mDefaultNetworkCallback, mTestPackageDefaultNetworkCallback);
16137         mProfileDefaultNetworkCallback.expectAvailableCallbacksValidated(workAgent);
16138         assertEquals(workAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_WORK_PROFILE_APP_UID));
16139         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_PACKAGE_UID));
16140 
16141         // Set oem network preference with TEST_PACKAGE_UID. mTestPackageDefaultNetworkCallback
16142         // should receive callback with higher priority network preference (current default network)
16143         // and the others should have no callbacks.
16144         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
16145                 OEM_NETWORK_PREFERENCE_OEM_PAID;
16146         final int[] uids1 = new int[] { TEST_PACKAGE_UID };
16147         final UidRangeParcel[] uidRanges1 = toUidRangeStableParcels(uidRangesForUids(uids1));
16148         setupSetOemNetworkPreferenceForPreferenceTest(networkPref, uidRanges1, TEST_PACKAGE_NAME);
16149         assertNoCallbacks(mDefaultNetworkCallback, mProfileDefaultNetworkCallback);
16150         mTestPackageDefaultNetworkCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
16151         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_PACKAGE_UID));
16152         assertEquals(workAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_WORK_PROFILE_APP_UID));
16153 
16154         // Set oem network preference with TEST_WORK_PROFILE_APP_UID. Both
16155         // mProfileDefaultNetworkCallback and mTestPackageDefaultNetworkCallback should receive
16156         // callback.
16157         final int[] uids2 = new int[] { TEST_WORK_PROFILE_APP_UID };
16158         final UidRangeParcel[] uidRanges2 = toUidRangeStableParcels(uidRangesForUids(uids2));
16159         doReturn(Arrays.asList(testHandle)).when(mUserManager).getUserHandles(anyBoolean());
16160         setupSetOemNetworkPreferenceForPreferenceTest(
16161                 networkPref, uidRanges2, "com.android.test", testHandle);
16162         mDefaultNetworkCallback.assertNoCallback();
16163         mProfileDefaultNetworkCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
16164         mTestPackageDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
16165         assertEquals(mWiFiNetworkAgent.getNetwork(),
16166                 mCm.getActiveNetworkForUid(TEST_WORK_PROFILE_APP_UID));
16167         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_PACKAGE_UID));
16168 
16169         // Remove oem network preference, mProfileDefaultNetworkCallback should receive callback
16170         // with current highest priority network preference (enterprise network) and the others
16171         // should have no callbacks.
16172         final TestOemListenerCallback oemPrefListener = new TestOemListenerCallback();
16173         mService.setOemNetworkPreference(
16174                 new OemNetworkPreferences.Builder().build(), oemPrefListener);
16175         oemPrefListener.expectOnComplete();
16176         assertNoCallbacks(mDefaultNetworkCallback, mTestPackageDefaultNetworkCallback);
16177         mProfileDefaultNetworkCallback.expectAvailableCallbacksValidated(workAgent);
16178         assertEquals(workAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_WORK_PROFILE_APP_UID));
16179         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_PACKAGE_UID));
16180 
16181         // Remove user profile network preference.
16182         mCm.setProfileNetworkPreference(testHandle, PROFILE_NETWORK_PREFERENCE_DEFAULT,
16183                 r -> r.run(), listener);
16184         listener.expectOnComplete();
16185         assertNoCallbacks(mDefaultNetworkCallback, mTestPackageDefaultNetworkCallback);
16186         mProfileDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
16187         assertEquals(mCellNetworkAgent.getNetwork(),
16188                 mCm.getActiveNetworkForUid(TEST_WORK_PROFILE_APP_UID));
16189         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_PACKAGE_UID));
16190 
16191         // Disconnect wifi
16192         mWiFiNetworkAgent.disconnect();
16193         assertNoCallbacks(mProfileDefaultNetworkCallback, mTestPackageDefaultNetworkCallback);
16194         mDefaultNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
16195         mDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
16196     }
16197 
16198     @Test
16199     public void testRequestRouteToHostAddress_PackageDoesNotBelongToCaller() {
16200         assertThrows(SecurityException.class, () -> mService.requestRouteToHostAddress(
16201                 ConnectivityManager.TYPE_NONE, null /* hostAddress */, "com.not.package.owner",
16202                 null /* callingAttributionTag */));
16203     }
16204 
16205     @Test @IgnoreUpTo(SC_V2)
16206     public void testUpdateRateLimit_EnableDisable() throws Exception {
16207         final LinkProperties wifiLp = new LinkProperties();
16208         wifiLp.setInterfaceName(WIFI_IFNAME);
16209         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp);
16210         mWiFiNetworkAgent.connect(true);
16211 
16212         final LinkProperties cellLp = new LinkProperties();
16213         cellLp.setInterfaceName(MOBILE_IFNAME);
16214         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
16215         mCellNetworkAgent.connect(false);
16216 
16217         waitForIdle();
16218 
16219         final ArrayTrackRecord<Pair<String, Long>>.ReadHead readHeadWifi =
16220                 mDeps.mRateLimitHistory.newReadHead();
16221         final ArrayTrackRecord<Pair<String, Long>>.ReadHead readHeadCell =
16222                 mDeps.mRateLimitHistory.newReadHead();
16223 
16224         // set rate limit to 8MBit/s => 1MB/s
16225         final int rateLimitInBytesPerSec = 1 * 1000 * 1000;
16226         setIngressRateLimit(rateLimitInBytesPerSec);
16227 
16228         assertNotNull(readHeadWifi.poll(TIMEOUT_MS,
16229                 it -> it.first == wifiLp.getInterfaceName()
16230                         && it.second == rateLimitInBytesPerSec));
16231         assertNotNull(readHeadCell.poll(TIMEOUT_MS,
16232                 it -> it.first == cellLp.getInterfaceName()
16233                         && it.second == rateLimitInBytesPerSec));
16234 
16235         // disable rate limiting
16236         setIngressRateLimit(-1);
16237 
16238         assertNotNull(readHeadWifi.poll(TIMEOUT_MS,
16239                 it -> it.first == wifiLp.getInterfaceName() && it.second == -1));
16240         assertNotNull(readHeadCell.poll(TIMEOUT_MS,
16241                 it -> it.first == cellLp.getInterfaceName() && it.second == -1));
16242     }
16243 
16244     @Test @IgnoreUpTo(SC_V2)
16245     public void testUpdateRateLimit_WhenNewNetworkIsAdded() throws Exception {
16246         final LinkProperties wifiLp = new LinkProperties();
16247         wifiLp.setInterfaceName(WIFI_IFNAME);
16248         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp);
16249         mWiFiNetworkAgent.connect(true);
16250 
16251         waitForIdle();
16252 
16253         final ArrayTrackRecord<Pair<String, Long>>.ReadHead readHead =
16254                 mDeps.mRateLimitHistory.newReadHead();
16255 
16256         // set rate limit to 8MBit/s => 1MB/s
16257         final int rateLimitInBytesPerSec = 1 * 1000 * 1000;
16258         setIngressRateLimit(rateLimitInBytesPerSec);
16259         assertNotNull(readHead.poll(TIMEOUT_MS, it -> it.first == wifiLp.getInterfaceName()
16260                 && it.second == rateLimitInBytesPerSec));
16261 
16262         final LinkProperties cellLp = new LinkProperties();
16263         cellLp.setInterfaceName(MOBILE_IFNAME);
16264         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
16265         mCellNetworkAgent.connect(false);
16266         assertNotNull(readHead.poll(TIMEOUT_MS, it -> it.first == cellLp.getInterfaceName()
16267                 && it.second == rateLimitInBytesPerSec));
16268     }
16269 
16270     @Test @IgnoreUpTo(SC_V2)
16271     public void testUpdateRateLimit_OnlyAffectsInternetCapableNetworks() throws Exception {
16272         final LinkProperties wifiLp = new LinkProperties();
16273         wifiLp.setInterfaceName(WIFI_IFNAME);
16274 
16275         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp);
16276         mWiFiNetworkAgent.connectWithoutInternet();
16277 
16278         waitForIdle();
16279 
16280         setIngressRateLimit(1000);
16281         setIngressRateLimit(-1);
16282 
16283         final ArrayTrackRecord<Pair<String, Long>>.ReadHead readHeadWifi =
16284                 mDeps.mRateLimitHistory.newReadHead();
16285         assertNull(readHeadWifi.poll(TIMEOUT_MS, it -> it.first == wifiLp.getInterfaceName()));
16286     }
16287 
16288     @Test @IgnoreUpTo(SC_V2)
16289     public void testUpdateRateLimit_DisconnectingResetsRateLimit()
16290             throws Exception {
16291         // Steps:
16292         // - connect network
16293         // - set rate limit
16294         // - disconnect network (interface still exists)
16295         // - disable rate limit
16296         // - connect network
16297         // - ensure network interface is not rate limited
16298         final LinkProperties wifiLp = new LinkProperties();
16299         wifiLp.setInterfaceName(WIFI_IFNAME);
16300         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp);
16301         mWiFiNetworkAgent.connect(true);
16302         waitForIdle();
16303 
16304         final ArrayTrackRecord<Pair<String, Long>>.ReadHead readHeadWifi =
16305                 mDeps.mRateLimitHistory.newReadHead();
16306 
16307         int rateLimitInBytesPerSec = 1000;
16308         setIngressRateLimit(rateLimitInBytesPerSec);
16309         assertNotNull(readHeadWifi.poll(TIMEOUT_MS,
16310                 it -> it.first == wifiLp.getInterfaceName()
16311                         && it.second == rateLimitInBytesPerSec));
16312 
16313         mWiFiNetworkAgent.disconnect();
16314         assertNotNull(readHeadWifi.poll(TIMEOUT_MS,
16315                 it -> it.first == wifiLp.getInterfaceName() && it.second == -1));
16316 
16317         setIngressRateLimit(-1);
16318 
16319         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp);
16320         mWiFiNetworkAgent.connect(true);
16321         assertNull(readHeadWifi.poll(TIMEOUT_MS, it -> it.first == wifiLp.getInterfaceName()));
16322     }
16323 
16324     @Test @IgnoreUpTo(SC_V2)
16325     public void testUpdateRateLimit_UpdateExistingRateLimit() throws Exception {
16326         final LinkProperties wifiLp = new LinkProperties();
16327         wifiLp.setInterfaceName(WIFI_IFNAME);
16328         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp);
16329         mWiFiNetworkAgent.connect(true);
16330         waitForIdle();
16331 
16332         final ArrayTrackRecord<Pair<String, Long>>.ReadHead readHeadWifi =
16333                 mDeps.mRateLimitHistory.newReadHead();
16334 
16335         // update an active ingress rate limit
16336         setIngressRateLimit(1000);
16337         setIngressRateLimit(2000);
16338 
16339         // verify the following order of execution:
16340         // 1. ingress rate limit set to 1000.
16341         // 2. ingress rate limit disabled (triggered by updating active rate limit).
16342         // 3. ingress rate limit set to 2000.
16343         assertNotNull(readHeadWifi.poll(TIMEOUT_MS,
16344                 it -> it.first == wifiLp.getInterfaceName()
16345                         && it.second == 1000));
16346         assertNotNull(readHeadWifi.poll(TIMEOUT_MS,
16347                 it -> it.first == wifiLp.getInterfaceName()
16348                         && it.second == -1));
16349         assertNotNull(readHeadWifi.poll(TIMEOUT_MS,
16350                 it -> it.first == wifiLp.getInterfaceName()
16351                         && it.second == 2000));
16352     }
16353 
16354     @Test @IgnoreAfter(SC_V2)
16355     public void testUpdateRateLimit_DoesNothingBeforeT() throws Exception {
16356         final LinkProperties wifiLp = new LinkProperties();
16357         wifiLp.setInterfaceName(WIFI_IFNAME);
16358         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp);
16359         mWiFiNetworkAgent.connect(true);
16360         waitForIdle();
16361 
16362         final ArrayTrackRecord<Pair<String, Long>>.ReadHead readHead =
16363                 mDeps.mRateLimitHistory.newReadHead();
16364 
16365         setIngressRateLimit(1000);
16366         waitForIdle();
16367 
16368         assertNull(readHead.poll(TEST_CALLBACK_TIMEOUT_MS, it -> true));
16369     }
16370 
16371     @Test
16372     public void testIgnoreValidationAfterRoamDisabled() throws Exception {
16373         assumeFalse(SdkLevel.isAtLeastT());
16374         // testIgnoreValidationAfterRoam off
16375         doReturn(-1).when(mResources)
16376                 .getInteger(R.integer.config_validationFailureAfterRoamIgnoreTimeMillis);
16377 
16378         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
16379         mCellNetworkAgent.connect(true);
16380         NetworkCapabilities wifiNc1 = new NetworkCapabilities()
16381                 .addTransportType(TRANSPORT_WIFI)
16382                 .setTransportInfo(new WifiInfo.Builder().setBssid("AA:AA:AA:AA:AA:AA").build());
16383         NetworkCapabilities wifiNc2 = new NetworkCapabilities()
16384                 .addTransportType(TRANSPORT_WIFI)
16385                 .setTransportInfo(new WifiInfo.Builder().setBssid("BB:BB:BB:BB:BB:BB").build());
16386         final LinkProperties wifiLp = new LinkProperties();
16387         wifiLp.setInterfaceName(WIFI_IFNAME);
16388         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp, wifiNc1);
16389         mWiFiNetworkAgent.connect(true);
16390 
16391         // The default network will be switching to Wi-Fi Network.
16392         final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
16393         final NetworkRequest wifiRequest = new NetworkRequest.Builder()
16394                 .addTransportType(TRANSPORT_WIFI).build();
16395         mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
16396         wifiNetworkCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
16397         registerDefaultNetworkCallbacks();
16398         mDefaultNetworkCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
16399 
16400         // Wi-Fi roaming from wifiNc1 to wifiNc2.
16401         mWiFiNetworkAgent.setNetworkCapabilities(wifiNc2, true);
16402         mWiFiNetworkAgent.setNetworkInvalid(false);
16403         mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), false);
16404         mDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
16405     }
16406 
16407     @Test
16408     public void testIgnoreValidationAfterRoamEnabled() throws Exception {
16409         assumeFalse(SdkLevel.isAtLeastT());
16410         // testIgnoreValidationAfterRoam on
16411         doReturn(5000).when(mResources)
16412                 .getInteger(R.integer.config_validationFailureAfterRoamIgnoreTimeMillis);
16413 
16414         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
16415         mCellNetworkAgent.connect(true);
16416         NetworkCapabilities wifiNc1 = new NetworkCapabilities()
16417                 .addTransportType(TRANSPORT_WIFI)
16418                 .setTransportInfo(new WifiInfo.Builder().setBssid("AA:AA:AA:AA:AA:AA").build());
16419         NetworkCapabilities wifiNc2 = new NetworkCapabilities()
16420                 .addTransportType(TRANSPORT_WIFI)
16421                 .setTransportInfo(new WifiInfo.Builder().setBssid("BB:BB:BB:BB:BB:BB").build());
16422         final LinkProperties wifiLp = new LinkProperties();
16423         wifiLp.setInterfaceName(WIFI_IFNAME);
16424         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp, wifiNc1);
16425         mWiFiNetworkAgent.connect(true);
16426 
16427         // The default network will be switching to Wi-Fi Network.
16428         final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
16429         final NetworkRequest wifiRequest = new NetworkRequest.Builder()
16430                 .addTransportType(TRANSPORT_WIFI).build();
16431         mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
16432         wifiNetworkCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
16433         registerDefaultNetworkCallbacks();
16434         mDefaultNetworkCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
16435 
16436         // Wi-Fi roaming from wifiNc1 to wifiNc2.
16437         mWiFiNetworkAgent.setNetworkCapabilities(wifiNc2, true);
16438         mWiFiNetworkAgent.setNetworkInvalid(false);
16439         mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), false);
16440 
16441         // Network validation failed, but the result will be ignored.
16442         assertTrue(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
16443                 NET_CAPABILITY_VALIDATED));
16444         mWiFiNetworkAgent.setNetworkValid(false);
16445 
16446         // Behavior of after config_validationFailureAfterRoamIgnoreTimeMillis
16447         ConditionVariable waitForValidationBlock = new ConditionVariable();
16448         doReturn(50).when(mResources)
16449                 .getInteger(R.integer.config_validationFailureAfterRoamIgnoreTimeMillis);
16450         // Wi-Fi roaming from wifiNc2 to wifiNc1.
16451         mWiFiNetworkAgent.setNetworkCapabilities(wifiNc1, true);
16452         mWiFiNetworkAgent.setNetworkInvalid(false);
16453         waitForValidationBlock.block(150);
16454         mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), false);
16455         mDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
16456     }
16457 
16458     @Test
16459     public void testLegacyTetheringApiGuardWithProperPermission() throws Exception {
16460         final String testIface = "test0";
16461         mServiceContext.setPermission(ACCESS_NETWORK_STATE, PERMISSION_DENIED);
16462         assertThrows(SecurityException.class, () -> mService.getLastTetherError(testIface));
16463         assertThrows(SecurityException.class, () -> mService.getTetherableIfaces());
16464         assertThrows(SecurityException.class, () -> mService.getTetheredIfaces());
16465         assertThrows(SecurityException.class, () -> mService.getTetheringErroredIfaces());
16466         assertThrows(SecurityException.class, () -> mService.getTetherableUsbRegexs());
16467         assertThrows(SecurityException.class, () -> mService.getTetherableWifiRegexs());
16468 
16469         withPermission(ACCESS_NETWORK_STATE, () -> {
16470             mService.getLastTetherError(testIface);
16471             verify(mTetheringManager).getLastTetherError(testIface);
16472 
16473             mService.getTetherableIfaces();
16474             verify(mTetheringManager).getTetherableIfaces();
16475 
16476             mService.getTetheredIfaces();
16477             verify(mTetheringManager).getTetheredIfaces();
16478 
16479             mService.getTetheringErroredIfaces();
16480             verify(mTetheringManager).getTetheringErroredIfaces();
16481 
16482             mService.getTetherableUsbRegexs();
16483             verify(mTetheringManager).getTetherableUsbRegexs();
16484 
16485             mService.getTetherableWifiRegexs();
16486             verify(mTetheringManager).getTetherableWifiRegexs();
16487         });
16488     }
16489 }
16490