1 /*
2  * Copyright (C) 2012 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.server;
18 
19 import static android.Manifest.permission.CHANGE_NETWORK_STATE;
20 import static android.Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS;
21 import static android.Manifest.permission.CONTROL_OEM_PAID_NETWORK_PREFERENCE;
22 import static android.Manifest.permission.CREATE_USERS;
23 import static android.Manifest.permission.DUMP;
24 import static android.Manifest.permission.GET_INTENT_SENDER_INTENT;
25 import static android.Manifest.permission.LOCAL_MAC_ADDRESS;
26 import static android.Manifest.permission.NETWORK_FACTORY;
27 import static android.Manifest.permission.NETWORK_SETTINGS;
28 import static android.Manifest.permission.NETWORK_STACK;
29 import static android.Manifest.permission.PACKET_KEEPALIVE_OFFLOAD;
30 import static android.app.PendingIntent.FLAG_IMMUTABLE;
31 import static android.content.Intent.ACTION_PACKAGE_ADDED;
32 import static android.content.Intent.ACTION_PACKAGE_REMOVED;
33 import static android.content.Intent.ACTION_PACKAGE_REPLACED;
34 import static android.content.Intent.ACTION_USER_ADDED;
35 import static android.content.Intent.ACTION_USER_REMOVED;
36 import static android.content.Intent.ACTION_USER_UNLOCKED;
37 import static android.content.pm.PackageInfo.REQUESTED_PERMISSION_GRANTED;
38 import static android.content.pm.PackageManager.FEATURE_WIFI;
39 import static android.content.pm.PackageManager.FEATURE_WIFI_DIRECT;
40 import static android.content.pm.PackageManager.GET_PERMISSIONS;
41 import static android.content.pm.PackageManager.MATCH_ANY_USER;
42 import static android.content.pm.PackageManager.PERMISSION_DENIED;
43 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
44 import static android.net.ConnectivityManager.ACTION_CAPTIVE_PORTAL_SIGN_IN;
45 import static android.net.ConnectivityManager.BLOCKED_METERED_REASON_DATA_SAVER;
46 import static android.net.ConnectivityManager.BLOCKED_METERED_REASON_MASK;
47 import static android.net.ConnectivityManager.BLOCKED_METERED_REASON_USER_RESTRICTED;
48 import static android.net.ConnectivityManager.BLOCKED_REASON_BATTERY_SAVER;
49 import static android.net.ConnectivityManager.BLOCKED_REASON_NONE;
50 import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
51 import static android.net.ConnectivityManager.EXTRA_NETWORK_INFO;
52 import static android.net.ConnectivityManager.EXTRA_NETWORK_TYPE;
53 import static android.net.ConnectivityManager.PROFILE_NETWORK_PREFERENCE_DEFAULT;
54 import static android.net.ConnectivityManager.PROFILE_NETWORK_PREFERENCE_ENTERPRISE;
55 import static android.net.ConnectivityManager.TYPE_ETHERNET;
56 import static android.net.ConnectivityManager.TYPE_MOBILE;
57 import static android.net.ConnectivityManager.TYPE_MOBILE_FOTA;
58 import static android.net.ConnectivityManager.TYPE_MOBILE_MMS;
59 import static android.net.ConnectivityManager.TYPE_MOBILE_SUPL;
60 import static android.net.ConnectivityManager.TYPE_PROXY;
61 import static android.net.ConnectivityManager.TYPE_VPN;
62 import static android.net.ConnectivityManager.TYPE_WIFI;
63 import static android.net.ConnectivitySettingsManager.PRIVATE_DNS_MODE_OFF;
64 import static android.net.ConnectivitySettingsManager.PRIVATE_DNS_MODE_OPPORTUNISTIC;
65 import static android.net.ConnectivitySettingsManager.PRIVATE_DNS_MODE_PROVIDER_HOSTNAME;
66 import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_DNS;
67 import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_FALLBACK;
68 import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_HTTP;
69 import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_HTTPS;
70 import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_PRIVDNS;
71 import static android.net.INetworkMonitor.NETWORK_VALIDATION_RESULT_PARTIAL;
72 import static android.net.INetworkMonitor.NETWORK_VALIDATION_RESULT_VALID;
73 import static android.net.NetworkCapabilities.NET_CAPABILITY_BIP;
74 import static android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL;
75 import static android.net.NetworkCapabilities.NET_CAPABILITY_CBS;
76 import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN;
77 import static android.net.NetworkCapabilities.NET_CAPABILITY_EIMS;
78 import static android.net.NetworkCapabilities.NET_CAPABILITY_ENTERPRISE;
79 import static android.net.NetworkCapabilities.NET_CAPABILITY_FOREGROUND;
80 import static android.net.NetworkCapabilities.NET_CAPABILITY_FOTA;
81 import static android.net.NetworkCapabilities.NET_CAPABILITY_IA;
82 import static android.net.NetworkCapabilities.NET_CAPABILITY_IMS;
83 import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
84 import static android.net.NetworkCapabilities.NET_CAPABILITY_MMS;
85 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED;
86 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
87 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
88 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING;
89 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED;
90 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED;
91 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN;
92 import static android.net.NetworkCapabilities.NET_CAPABILITY_OEM_PAID;
93 import static android.net.NetworkCapabilities.NET_CAPABILITY_OEM_PRIVATE;
94 import static android.net.NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVITY;
95 import static android.net.NetworkCapabilities.NET_CAPABILITY_RCS;
96 import static android.net.NetworkCapabilities.NET_CAPABILITY_SUPL;
97 import static android.net.NetworkCapabilities.NET_CAPABILITY_TEMPORARILY_NOT_METERED;
98 import static android.net.NetworkCapabilities.NET_CAPABILITY_TRUSTED;
99 import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
100 import static android.net.NetworkCapabilities.NET_CAPABILITY_VSIM;
101 import static android.net.NetworkCapabilities.NET_CAPABILITY_WIFI_P2P;
102 import static android.net.NetworkCapabilities.NET_CAPABILITY_XCAP;
103 import static android.net.NetworkCapabilities.REDACT_FOR_ACCESS_FINE_LOCATION;
104 import static android.net.NetworkCapabilities.REDACT_FOR_LOCAL_MAC_ADDRESS;
105 import static android.net.NetworkCapabilities.REDACT_FOR_NETWORK_SETTINGS;
106 import static android.net.NetworkCapabilities.REDACT_NONE;
107 import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
108 import static android.net.NetworkCapabilities.TRANSPORT_ETHERNET;
109 import static android.net.NetworkCapabilities.TRANSPORT_VPN;
110 import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
111 import static android.net.NetworkCapabilities.TRANSPORT_WIFI_AWARE;
112 import static android.net.NetworkScore.KEEP_CONNECTED_FOR_HANDOVER;
113 import static android.net.OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PAID;
114 import static android.net.OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK;
115 import static android.net.OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY;
116 import static android.net.OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY;
117 import static android.net.OemNetworkPreferences.OEM_NETWORK_PREFERENCE_TEST;
118 import static android.net.OemNetworkPreferences.OEM_NETWORK_PREFERENCE_TEST_ONLY;
119 import static android.net.OemNetworkPreferences.OEM_NETWORK_PREFERENCE_UNINITIALIZED;
120 import static android.net.RouteInfo.RTN_UNREACHABLE;
121 import static android.net.resolv.aidl.IDnsResolverUnsolicitedEventListener.PREFIX_OPERATION_ADDED;
122 import static android.net.resolv.aidl.IDnsResolverUnsolicitedEventListener.PREFIX_OPERATION_REMOVED;
123 import static android.net.resolv.aidl.IDnsResolverUnsolicitedEventListener.VALIDATION_RESULT_FAILURE;
124 import static android.net.resolv.aidl.IDnsResolverUnsolicitedEventListener.VALIDATION_RESULT_SUCCESS;
125 import static android.os.Process.INVALID_UID;
126 import static android.system.OsConstants.IPPROTO_TCP;
127 
128 import static com.android.server.ConnectivityService.MAX_NETWORK_REQUESTS_PER_SYSTEM_UID;
129 import static com.android.server.ConnectivityService.PREFERENCE_PRIORITY_MOBILE_DATA_PREFERERRED;
130 import static com.android.server.ConnectivityService.PREFERENCE_PRIORITY_OEM;
131 import static com.android.server.ConnectivityService.PREFERENCE_PRIORITY_PROFILE;
132 import static com.android.server.ConnectivityService.PREFERENCE_PRIORITY_VPN;
133 import static com.android.server.ConnectivityServiceTestUtils.transportToLegacyType;
134 import static com.android.testutils.ConcurrentUtils.await;
135 import static com.android.testutils.ConcurrentUtils.durationOf;
136 import static com.android.testutils.ExceptionUtils.ignoreExceptions;
137 import static com.android.testutils.HandlerUtils.waitForIdleSerialExecutor;
138 import static com.android.testutils.MiscAsserts.assertContainsAll;
139 import static com.android.testutils.MiscAsserts.assertContainsExactly;
140 import static com.android.testutils.MiscAsserts.assertEmpty;
141 import static com.android.testutils.MiscAsserts.assertLength;
142 import static com.android.testutils.MiscAsserts.assertRunsInAtMost;
143 import static com.android.testutils.MiscAsserts.assertSameElements;
144 import static com.android.testutils.MiscAsserts.assertThrows;
145 import static com.android.testutils.TestPermissionUtil.runAsShell;
146 
147 import static org.junit.Assert.assertEquals;
148 import static org.junit.Assert.assertFalse;
149 import static org.junit.Assert.assertNotEquals;
150 import static org.junit.Assert.assertNotNull;
151 import static org.junit.Assert.assertNull;
152 import static org.junit.Assert.assertTrue;
153 import static org.junit.Assert.fail;
154 import static org.mockito.AdditionalMatchers.aryEq;
155 import static org.mockito.ArgumentMatchers.anyBoolean;
156 import static org.mockito.ArgumentMatchers.anyLong;
157 import static org.mockito.ArgumentMatchers.anyString;
158 import static org.mockito.ArgumentMatchers.argThat;
159 import static org.mockito.ArgumentMatchers.eq;
160 import static org.mockito.ArgumentMatchers.isNull;
161 import static org.mockito.ArgumentMatchers.startsWith;
162 import static org.mockito.Matchers.anyInt;
163 import static org.mockito.Mockito.any;
164 import static org.mockito.Mockito.atLeastOnce;
165 import static org.mockito.Mockito.doAnswer;
166 import static org.mockito.Mockito.doNothing;
167 import static org.mockito.Mockito.doReturn;
168 import static org.mockito.Mockito.doThrow;
169 import static org.mockito.Mockito.inOrder;
170 import static org.mockito.Mockito.mock;
171 import static org.mockito.Mockito.never;
172 import static org.mockito.Mockito.reset;
173 import static org.mockito.Mockito.spy;
174 import static org.mockito.Mockito.timeout;
175 import static org.mockito.Mockito.times;
176 import static org.mockito.Mockito.verify;
177 import static org.mockito.Mockito.verifyNoMoreInteractions;
178 import static org.mockito.Mockito.when;
179 
180 import android.Manifest;
181 import android.annotation.NonNull;
182 import android.annotation.Nullable;
183 import android.app.AlarmManager;
184 import android.app.AppOpsManager;
185 import android.app.NotificationManager;
186 import android.app.PendingIntent;
187 import android.app.usage.NetworkStatsManager;
188 import android.content.BroadcastReceiver;
189 import android.content.ComponentName;
190 import android.content.ContentProvider;
191 import android.content.ContentResolver;
192 import android.content.Context;
193 import android.content.Intent;
194 import android.content.IntentFilter;
195 import android.content.pm.ApplicationInfo;
196 import android.content.pm.PackageInfo;
197 import android.content.pm.PackageManager;
198 import android.content.pm.ResolveInfo;
199 import android.content.pm.ServiceInfo;
200 import android.content.pm.UserInfo;
201 import android.content.res.Resources;
202 import android.location.LocationManager;
203 import android.net.CaptivePortalData;
204 import android.net.ConnectionInfo;
205 import android.net.ConnectivityManager;
206 import android.net.ConnectivityManager.NetworkCallback;
207 import android.net.ConnectivityManager.PacketKeepalive;
208 import android.net.ConnectivityManager.PacketKeepaliveCallback;
209 import android.net.ConnectivityManager.TooManyRequestsException;
210 import android.net.ConnectivityResources;
211 import android.net.ConnectivitySettingsManager;
212 import android.net.ConnectivityThread;
213 import android.net.DataStallReportParcelable;
214 import android.net.EthernetManager;
215 import android.net.IConnectivityDiagnosticsCallback;
216 import android.net.IDnsResolver;
217 import android.net.INetd;
218 import android.net.INetworkMonitor;
219 import android.net.INetworkMonitorCallbacks;
220 import android.net.IOnCompleteListener;
221 import android.net.IQosCallback;
222 import android.net.InetAddresses;
223 import android.net.InterfaceConfigurationParcel;
224 import android.net.IpPrefix;
225 import android.net.IpSecManager;
226 import android.net.IpSecManager.UdpEncapsulationSocket;
227 import android.net.LinkAddress;
228 import android.net.LinkProperties;
229 import android.net.MatchAllNetworkSpecifier;
230 import android.net.NativeNetworkConfig;
231 import android.net.NativeNetworkType;
232 import android.net.Network;
233 import android.net.NetworkAgent;
234 import android.net.NetworkAgentConfig;
235 import android.net.NetworkCapabilities;
236 import android.net.NetworkFactory;
237 import android.net.NetworkInfo;
238 import android.net.NetworkInfo.DetailedState;
239 import android.net.NetworkPolicyManager;
240 import android.net.NetworkPolicyManager.NetworkPolicyCallback;
241 import android.net.NetworkRequest;
242 import android.net.NetworkScore;
243 import android.net.NetworkSpecifier;
244 import android.net.NetworkStack;
245 import android.net.NetworkStateSnapshot;
246 import android.net.NetworkTestResultParcelable;
247 import android.net.OemNetworkPreferences;
248 import android.net.ProxyInfo;
249 import android.net.QosCallbackException;
250 import android.net.QosFilter;
251 import android.net.QosSession;
252 import android.net.ResolverParamsParcel;
253 import android.net.RouteInfo;
254 import android.net.RouteInfoParcel;
255 import android.net.SocketKeepalive;
256 import android.net.TransportInfo;
257 import android.net.UidRange;
258 import android.net.UidRangeParcel;
259 import android.net.UnderlyingNetworkInfo;
260 import android.net.Uri;
261 import android.net.VpnManager;
262 import android.net.VpnTransportInfo;
263 import android.net.metrics.IpConnectivityLog;
264 import android.net.netd.aidl.NativeUidRangeConfig;
265 import android.net.networkstack.NetworkStackClientBase;
266 import android.net.resolv.aidl.Nat64PrefixEventParcel;
267 import android.net.resolv.aidl.PrivateDnsValidationEventParcel;
268 import android.net.shared.NetworkMonitorUtils;
269 import android.net.shared.PrivateDnsConfig;
270 import android.net.util.MultinetworkPolicyTracker;
271 import android.os.BadParcelableException;
272 import android.os.BatteryStatsManager;
273 import android.os.Binder;
274 import android.os.Build;
275 import android.os.Bundle;
276 import android.os.ConditionVariable;
277 import android.os.Handler;
278 import android.os.HandlerThread;
279 import android.os.IBinder;
280 import android.os.INetworkManagementService;
281 import android.os.Looper;
282 import android.os.Messenger;
283 import android.os.Parcel;
284 import android.os.ParcelFileDescriptor;
285 import android.os.Parcelable;
286 import android.os.Process;
287 import android.os.RemoteException;
288 import android.os.ServiceSpecificException;
289 import android.os.SystemClock;
290 import android.os.SystemConfigManager;
291 import android.os.UserHandle;
292 import android.os.UserManager;
293 import android.provider.Settings;
294 import android.security.Credentials;
295 import android.system.Os;
296 import android.telephony.TelephonyManager;
297 import android.telephony.data.EpsBearerQosSessionAttributes;
298 import android.telephony.data.NrQosSessionAttributes;
299 import android.test.mock.MockContentResolver;
300 import android.text.TextUtils;
301 import android.util.ArraySet;
302 import android.util.Log;
303 import android.util.Pair;
304 import android.util.Range;
305 import android.util.SparseArray;
306 
307 import androidx.test.InstrumentationRegistry;
308 import androidx.test.filters.SmallTest;
309 
310 import com.android.connectivity.resources.R;
311 import com.android.internal.app.IBatteryStats;
312 import com.android.internal.net.VpnConfig;
313 import com.android.internal.net.VpnProfile;
314 import com.android.internal.util.ArrayUtils;
315 import com.android.internal.util.WakeupMessage;
316 import com.android.internal.util.test.BroadcastInterceptingContext;
317 import com.android.internal.util.test.FakeSettingsProvider;
318 import com.android.net.module.util.ArrayTrackRecord;
319 import com.android.net.module.util.CollectionUtils;
320 import com.android.net.module.util.LocationPermissionChecker;
321 import com.android.server.ConnectivityService.ConnectivityDiagnosticsCallbackInfo;
322 import com.android.server.ConnectivityService.NetworkRequestInfo;
323 import com.android.server.connectivity.MockableSystemProperties;
324 import com.android.server.connectivity.Nat464Xlat;
325 import com.android.server.connectivity.NetworkAgentInfo;
326 import com.android.server.connectivity.NetworkNotificationManager.NotificationType;
327 import com.android.server.connectivity.ProxyTracker;
328 import com.android.server.connectivity.QosCallbackTracker;
329 import com.android.server.connectivity.Vpn;
330 import com.android.server.connectivity.VpnProfileStore;
331 import com.android.server.net.NetworkPinner;
332 import com.android.testutils.DevSdkIgnoreRule;
333 import com.android.testutils.DevSdkIgnoreRunner;
334 import com.android.testutils.ExceptionUtils;
335 import com.android.testutils.HandlerUtils;
336 import com.android.testutils.RecorderCallback.CallbackEntry;
337 import com.android.testutils.TestableNetworkCallback;
338 
339 import org.junit.After;
340 import org.junit.Before;
341 import org.junit.Ignore;
342 import org.junit.Test;
343 import org.junit.runner.RunWith;
344 import org.mockito.AdditionalAnswers;
345 import org.mockito.ArgumentCaptor;
346 import org.mockito.InOrder;
347 import org.mockito.Mock;
348 import org.mockito.MockitoAnnotations;
349 import org.mockito.Spy;
350 import org.mockito.stubbing.Answer;
351 
352 import java.io.FileDescriptor;
353 import java.io.IOException;
354 import java.io.PrintWriter;
355 import java.io.StringWriter;
356 import java.net.DatagramSocket;
357 import java.net.Inet4Address;
358 import java.net.Inet6Address;
359 import java.net.InetAddress;
360 import java.net.InetSocketAddress;
361 import java.net.Socket;
362 import java.nio.charset.StandardCharsets;
363 import java.util.ArrayList;
364 import java.util.Arrays;
365 import java.util.Collection;
366 import java.util.Collections;
367 import java.util.Comparator;
368 import java.util.HashMap;
369 import java.util.HashSet;
370 import java.util.List;
371 import java.util.Objects;
372 import java.util.Set;
373 import java.util.concurrent.CompletableFuture;
374 import java.util.concurrent.CountDownLatch;
375 import java.util.concurrent.Executor;
376 import java.util.concurrent.ExecutorService;
377 import java.util.concurrent.Executors;
378 import java.util.concurrent.LinkedBlockingQueue;
379 import java.util.concurrent.TimeUnit;
380 import java.util.concurrent.TimeoutException;
381 import java.util.concurrent.atomic.AtomicBoolean;
382 import java.util.concurrent.atomic.AtomicReference;
383 import java.util.function.Predicate;
384 import java.util.function.Supplier;
385 import java.util.regex.Matcher;
386 import java.util.regex.Pattern;
387 import java.util.stream.Collectors;
388 
389 import kotlin.reflect.KClass;
390 
391 /**
392  * Tests for {@link ConnectivityService}.
393  *
394  * Build, install and run with:
395  *  runtest frameworks-net -c com.android.server.ConnectivityServiceTest
396  */
397 @RunWith(DevSdkIgnoreRunner.class)
398 @SmallTest
399 @DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
400 public class ConnectivityServiceTest {
401     private static final String TAG = "ConnectivityServiceTest";
402 
403     private static final int TIMEOUT_MS = 2_000;
404     // Broadcasts can take a long time to be delivered. The test will not wait for that long unless
405     // there is a failure, so use a long timeout.
406     private static final int BROADCAST_TIMEOUT_MS = 30_000;
407     private static final int TEST_LINGER_DELAY_MS = 400;
408     private static final int TEST_NASCENT_DELAY_MS = 300;
409     // Chosen to be less than the linger and nascent timeout. This ensures that we can distinguish
410     // between a LOST callback that arrives immediately and a LOST callback that arrives after
411     // the linger/nascent timeout. For this, our assertions should run fast enough to leave
412     // less than (mService.mLingerDelayMs - TEST_CALLBACK_TIMEOUT_MS) between the time callbacks are
413     // supposedly fired, and the time we call expectCallback.
414     private static final int TEST_CALLBACK_TIMEOUT_MS = 250;
415     // Chosen to be less than TEST_CALLBACK_TIMEOUT_MS. This ensures that requests have time to
416     // complete before callbacks are verified.
417     private static final int TEST_REQUEST_TIMEOUT_MS = 150;
418 
419     private static final int UNREASONABLY_LONG_ALARM_WAIT_MS = 1000;
420 
421     private static final long TIMESTAMP = 1234L;
422 
423     private static final int NET_ID = 110;
424     private static final int OEM_PREF_ANY_NET_ID = -1;
425     // Set a non-zero value to verify the flow to set tcp init rwnd value.
426     private static final int TEST_TCP_INIT_RWND = 60;
427 
428     // Used for testing the per-work-profile default network.
429     private static final int TEST_APP_ID = 103;
430     private static final int TEST_WORK_PROFILE_USER_ID = 2;
431     private static final int TEST_WORK_PROFILE_APP_UID =
432             UserHandle.getUid(TEST_WORK_PROFILE_USER_ID, TEST_APP_ID);
433     private static final String CLAT_PREFIX = "v4-";
434     private static final String MOBILE_IFNAME = "test_rmnet_data0";
435     private static final String CLAT_MOBILE_IFNAME = CLAT_PREFIX + MOBILE_IFNAME;
436     private static final String WIFI_IFNAME = "test_wlan0";
437     private static final String WIFI_WOL_IFNAME = "test_wlan_wol";
438     private static final String VPN_IFNAME = "tun10042";
439     private static final String TEST_PACKAGE_NAME = "com.android.test.package";
440     private static final int TEST_PACKAGE_UID = 123;
441     private static final int TEST_PACKAGE_UID2 = 321;
442     private static final int TEST_PACKAGE_UID3 = 456;
443     private static final String ALWAYS_ON_PACKAGE = "com.android.test.alwaysonvpn";
444 
445     private static final String INTERFACE_NAME = "interface";
446 
447     private static final String TEST_VENUE_URL_NA_PASSPOINT = "https://android.com/";
448     private static final String TEST_VENUE_URL_NA_OTHER = "https://example.com/";
449     private static final String TEST_TERMS_AND_CONDITIONS_URL_NA_PASSPOINT =
450             "https://android.com/terms/";
451     private static final String TEST_TERMS_AND_CONDITIONS_URL_NA_OTHER =
452             "https://example.com/terms/";
453     private static final String TEST_VENUE_URL_CAPPORT = "https://android.com/capport/";
454     private static final String TEST_USER_PORTAL_API_URL_CAPPORT =
455             "https://android.com/user/api/capport/";
456     private static final String TEST_FRIENDLY_NAME = "Network friendly name";
457     private static final String TEST_REDIRECT_URL = "http://example.com/firstPath";
458 
459     private MockContext mServiceContext;
460     private HandlerThread mCsHandlerThread;
461     private HandlerThread mVMSHandlerThread;
462     private ConnectivityService.Dependencies mDeps;
463     private ConnectivityService mService;
464     private WrappedConnectivityManager mCm;
465     private TestNetworkAgentWrapper mWiFiNetworkAgent;
466     private TestNetworkAgentWrapper mCellNetworkAgent;
467     private TestNetworkAgentWrapper mEthernetNetworkAgent;
468     private MockVpn mMockVpn;
469     private Context mContext;
470     private NetworkPolicyCallback mPolicyCallback;
471     private WrappedMultinetworkPolicyTracker mPolicyTracker;
472     private HandlerThread mAlarmManagerThread;
473     private TestNetIdManager mNetIdManager;
474     private QosCallbackMockHelper mQosCallbackMockHelper;
475     private QosCallbackTracker mQosCallbackTracker;
476     private VpnManagerService mVpnManagerService;
477     private TestNetworkCallback mDefaultNetworkCallback;
478     private TestNetworkCallback mSystemDefaultNetworkCallback;
479     private TestNetworkCallback mProfileDefaultNetworkCallback;
480     private TestNetworkCallback mTestPackageDefaultNetworkCallback;
481 
482     // State variables required to emulate NetworkPolicyManagerService behaviour.
483     private int mBlockedReasons = BLOCKED_REASON_NONE;
484 
485     @Mock DeviceIdleInternal mDeviceIdleInternal;
486     @Mock INetworkManagementService mNetworkManagementService;
487     @Mock NetworkStatsManager mStatsManager;
488     @Mock IDnsResolver mMockDnsResolver;
489     @Mock INetd mMockNetd;
490     @Mock NetworkStackClientBase mNetworkStack;
491     @Mock PackageManager mPackageManager;
492     @Mock UserManager mUserManager;
493     @Mock NotificationManager mNotificationManager;
494     @Mock AlarmManager mAlarmManager;
495     @Mock IConnectivityDiagnosticsCallback mConnectivityDiagnosticsCallback;
496     @Mock IBinder mIBinder;
497     @Mock LocationManager mLocationManager;
498     @Mock AppOpsManager mAppOpsManager;
499     @Mock TelephonyManager mTelephonyManager;
500     @Mock MockableSystemProperties mSystemProperties;
501     @Mock EthernetManager mEthernetManager;
502     @Mock NetworkPolicyManager mNetworkPolicyManager;
503     @Mock VpnProfileStore mVpnProfileStore;
504     @Mock SystemConfigManager mSystemConfigManager;
505     @Mock Resources mResources;
506     @Mock ProxyTracker mProxyTracker;
507 
508     // BatteryStatsManager is final and cannot be mocked with regular mockito, so just mock the
509     // underlying binder calls.
510     final BatteryStatsManager mBatteryStatsManager =
511             new BatteryStatsManager(mock(IBatteryStats.class));
512 
513     private ArgumentCaptor<ResolverParamsParcel> mResolverParamsParcelCaptor =
514             ArgumentCaptor.forClass(ResolverParamsParcel.class);
515 
516     // This class exists to test bindProcessToNetwork and getBoundNetworkForProcess. These methods
517     // do not go through ConnectivityService but talk to netd directly, so they don't automatically
518     // reflect the state of our test ConnectivityService.
519     private class WrappedConnectivityManager extends ConnectivityManager {
520         private Network mFakeBoundNetwork;
521 
522         public synchronized boolean bindProcessToNetwork(Network network) {
523             mFakeBoundNetwork = network;
524             return true;
525         }
526 
527         public synchronized Network getBoundNetworkForProcess() {
528             return mFakeBoundNetwork;
529         }
530 
531         public WrappedConnectivityManager(Context context, ConnectivityService service) {
532             super(context, service);
533         }
534     }
535 
536     private class MockContext extends BroadcastInterceptingContext {
537         private final MockContentResolver mContentResolver;
538 
539         @Spy private Resources mInternalResources;
540         private final LinkedBlockingQueue<Intent> mStartedActivities = new LinkedBlockingQueue<>();
541 
542         // Map of permission name -> PermissionManager.Permission_{GRANTED|DENIED} constant
543         // For permissions granted across the board, the key is only the permission name.
544         // For permissions only granted to a combination of uid/pid, the key
545         // is "<permission name>,<pid>,<uid>". PID+UID permissons have priority over generic ones.
546         private final HashMap<String, Integer> mMockedPermissions = new HashMap<>();
547 
548         MockContext(Context base, ContentProvider settingsProvider) {
549             super(base);
550 
551             mInternalResources = spy(base.getResources());
552             when(mInternalResources.getStringArray(com.android.internal.R.array.networkAttributes))
553                     .thenReturn(new String[] {
554                             "wifi,1,1,1,-1,true",
555                             "mobile,0,0,0,-1,true",
556                             "mobile_mms,2,0,2,60000,true",
557                             "mobile_supl,3,0,2,60000,true",
558                     });
559 
560             mContentResolver = new MockContentResolver();
561             mContentResolver.addProvider(Settings.AUTHORITY, settingsProvider);
562         }
563 
564         @Override
565         public void startActivityAsUser(Intent intent, UserHandle handle) {
566             mStartedActivities.offer(intent);
567         }
568 
569         public Intent expectStartActivityIntent(int timeoutMs) {
570             Intent intent = null;
571             try {
572                 intent = mStartedActivities.poll(timeoutMs, TimeUnit.MILLISECONDS);
573             } catch (InterruptedException e) {}
574             assertNotNull("Did not receive sign-in intent after " + timeoutMs + "ms", intent);
575             return intent;
576         }
577 
578         public void expectNoStartActivityIntent(int timeoutMs) {
579             try {
580                 assertNull("Received unexpected Intent to start activity",
581                         mStartedActivities.poll(timeoutMs, TimeUnit.MILLISECONDS));
582             } catch (InterruptedException e) {}
583         }
584 
585         @Override
586         public ComponentName startService(Intent service) {
587             final String action = service.getAction();
588             if (!VpnConfig.SERVICE_INTERFACE.equals(action)) {
589                 fail("Attempt to start unknown service, action=" + action);
590             }
591             return new ComponentName(service.getPackage(), "com.android.test.Service");
592         }
593 
594         @Override
595         public Object getSystemService(String name) {
596             if (Context.CONNECTIVITY_SERVICE.equals(name)) return mCm;
597             if (Context.NOTIFICATION_SERVICE.equals(name)) return mNotificationManager;
598             if (Context.USER_SERVICE.equals(name)) return mUserManager;
599             if (Context.ALARM_SERVICE.equals(name)) return mAlarmManager;
600             if (Context.LOCATION_SERVICE.equals(name)) return mLocationManager;
601             if (Context.APP_OPS_SERVICE.equals(name)) return mAppOpsManager;
602             if (Context.TELEPHONY_SERVICE.equals(name)) return mTelephonyManager;
603             if (Context.ETHERNET_SERVICE.equals(name)) return mEthernetManager;
604             if (Context.NETWORK_POLICY_SERVICE.equals(name)) return mNetworkPolicyManager;
605             if (Context.SYSTEM_CONFIG_SERVICE.equals(name)) return mSystemConfigManager;
606             if (Context.NETWORK_STATS_SERVICE.equals(name)) return mStatsManager;
607             if (Context.BATTERY_STATS_SERVICE.equals(name)) return mBatteryStatsManager;
608             return super.getSystemService(name);
609         }
610 
611         final HashMap<UserHandle, UserManager> mUserManagers = new HashMap<>();
612         @Override
613         public Context createContextAsUser(UserHandle user, int flags) {
614             final Context asUser = mock(Context.class, AdditionalAnswers.delegatesTo(this));
615             doReturn(user).when(asUser).getUser();
616             doAnswer((inv) -> {
617                 final UserManager um = mUserManagers.computeIfAbsent(user,
618                         u -> mock(UserManager.class, AdditionalAnswers.delegatesTo(mUserManager)));
619                 return um;
620             }).when(asUser).getSystemService(Context.USER_SERVICE);
621             return asUser;
622         }
623 
624         public void setWorkProfile(@NonNull final UserHandle userHandle, boolean value) {
625             // This relies on all contexts for a given user returning the same UM mock
626             final UserManager umMock = createContextAsUser(userHandle, 0 /* flags */)
627                     .getSystemService(UserManager.class);
628             doReturn(value).when(umMock).isManagedProfile();
629             doReturn(value).when(mUserManager).isManagedProfile(eq(userHandle.getIdentifier()));
630         }
631 
632         @Override
633         public ContentResolver getContentResolver() {
634             return mContentResolver;
635         }
636 
637         @Override
638         public Resources getResources() {
639             return mInternalResources;
640         }
641 
642         @Override
643         public PackageManager getPackageManager() {
644             return mPackageManager;
645         }
646 
647         private int checkMockedPermission(String permission, int pid, int uid,
648                 Supplier<Integer> ifAbsent) {
649             final Integer granted = mMockedPermissions.get(permission + "," + pid + "," + uid);
650             if (null != granted) {
651                 return granted;
652             }
653             final Integer allGranted = mMockedPermissions.get(permission);
654             if (null != allGranted) {
655                 return allGranted;
656             }
657             return ifAbsent.get();
658         }
659 
660         @Override
661         public int checkPermission(String permission, int pid, int uid) {
662             return checkMockedPermission(permission, pid, uid,
663                     () -> super.checkPermission(permission, pid, uid));
664         }
665 
666         @Override
667         public int checkCallingOrSelfPermission(String permission) {
668             return checkMockedPermission(permission, Process.myPid(), Process.myUid(),
669                     () -> super.checkCallingOrSelfPermission(permission));
670         }
671 
672         @Override
673         public void enforceCallingOrSelfPermission(String permission, String message) {
674             final Integer granted = checkMockedPermission(permission,
675                     Process.myPid(), Process.myUid(),
676                     () -> {
677                         super.enforceCallingOrSelfPermission(permission, message);
678                         // enforce will crash if the permission is not granted
679                         return PERMISSION_GRANTED;
680                     });
681 
682             if (!granted.equals(PERMISSION_GRANTED)) {
683                 throw new SecurityException("[Test] permission denied: " + permission);
684             }
685         }
686 
687         /**
688          * Mock checks for the specified permission, and have them behave as per {@code granted}.
689          *
690          * This will apply across the board no matter what the checked UID and PID are.
691          *
692          * <p>Passing null reverts to default behavior, which does a real permission check on the
693          * test package.
694          * @param granted One of {@link PackageManager#PERMISSION_GRANTED} or
695          *                {@link PackageManager#PERMISSION_DENIED}.
696          */
697         public void setPermission(String permission, Integer granted) {
698             mMockedPermissions.put(permission, granted);
699         }
700 
701         /**
702          * Mock checks for the specified permission, and have them behave as per {@code granted}.
703          *
704          * This will only apply to the passed UID and PID.
705          *
706          * <p>Passing null reverts to default behavior, which does a real permission check on the
707          * test package.
708          * @param granted One of {@link PackageManager#PERMISSION_GRANTED} or
709          *                {@link PackageManager#PERMISSION_DENIED}.
710          */
711         public void setPermission(String permission, int pid, int uid, Integer granted) {
712             final String key = permission + "," + pid + "," + uid;
713             mMockedPermissions.put(key, granted);
714         }
715 
716         @Override
717         public Intent registerReceiverForAllUsers(@Nullable BroadcastReceiver receiver,
718                 @NonNull IntentFilter filter, @Nullable String broadcastPermission,
719                 @Nullable Handler scheduler) {
720             // TODO: ensure MultinetworkPolicyTracker's BroadcastReceiver is tested; just returning
721             // null should not pass the test
722             return null;
723         }
724     }
725 
726     private void waitForIdle() {
727         HandlerUtils.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
728         waitForIdle(mCellNetworkAgent, TIMEOUT_MS);
729         waitForIdle(mWiFiNetworkAgent, TIMEOUT_MS);
730         waitForIdle(mEthernetNetworkAgent, TIMEOUT_MS);
731         HandlerUtils.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
732         HandlerUtils.waitForIdle(ConnectivityThread.get(), TIMEOUT_MS);
733     }
734 
735     private void waitForIdle(TestNetworkAgentWrapper agent, long timeoutMs) {
736         if (agent == null) {
737             return;
738         }
739         agent.waitForIdle(timeoutMs);
740     }
741 
742     @Test
743     public void testWaitForIdle() throws Exception {
744         final int attempts = 50;  // Causes the test to take about 200ms on bullhead-eng.
745 
746         // Tests that waitForIdle returns immediately if the service is already idle.
747         for (int i = 0; i < attempts; i++) {
748             waitForIdle();
749         }
750 
751         // Bring up a network that we can use to send messages to ConnectivityService.
752         ExpectedBroadcast b = expectConnectivityAction(TYPE_WIFI, DetailedState.CONNECTED);
753         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
754         mWiFiNetworkAgent.connect(false);
755         b.expectBroadcast();
756         Network n = mWiFiNetworkAgent.getNetwork();
757         assertNotNull(n);
758 
759         // Tests that calling waitForIdle waits for messages to be processed.
760         for (int i = 0; i < attempts; i++) {
761             mWiFiNetworkAgent.setSignalStrength(i);
762             waitForIdle();
763             assertEquals(i, mCm.getNetworkCapabilities(n).getSignalStrength());
764         }
765     }
766 
767     // This test has an inherent race condition in it, and cannot be enabled for continuous testing
768     // or presubmit tests. It is kept for manual runs and documentation purposes.
769     @Ignore
770     public void verifyThatNotWaitingForIdleCausesRaceConditions() throws Exception {
771         // Bring up a network that we can use to send messages to ConnectivityService.
772         ExpectedBroadcast b = expectConnectivityAction(TYPE_WIFI, DetailedState.CONNECTED);
773         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
774         mWiFiNetworkAgent.connect(false);
775         b.expectBroadcast();
776         Network n = mWiFiNetworkAgent.getNetwork();
777         assertNotNull(n);
778 
779         // Ensure that not calling waitForIdle causes a race condition.
780         final int attempts = 50;  // Causes the test to take about 200ms on bullhead-eng.
781         for (int i = 0; i < attempts; i++) {
782             mWiFiNetworkAgent.setSignalStrength(i);
783             if (i != mCm.getNetworkCapabilities(n).getSignalStrength()) {
784                 // We hit a race condition, as expected. Pass the test.
785                 return;
786             }
787         }
788 
789         // No race? There is a bug in this test.
790         fail("expected race condition at least once in " + attempts + " attempts");
791     }
792 
793     private class TestNetworkAgentWrapper extends NetworkAgentWrapper {
794         private static final int VALIDATION_RESULT_INVALID = 0;
795 
796         private static final long DATA_STALL_TIMESTAMP = 10L;
797         private static final int DATA_STALL_DETECTION_METHOD = 1;
798 
799         private INetworkMonitor mNetworkMonitor;
800         private INetworkMonitorCallbacks mNmCallbacks;
801         private int mNmValidationResult = VALIDATION_RESULT_INVALID;
802         private int mProbesCompleted;
803         private int mProbesSucceeded;
804         private String mNmValidationRedirectUrl = null;
805         private boolean mNmProvNotificationRequested = false;
806         private Runnable mCreatedCallback;
807         private Runnable mUnwantedCallback;
808         private Runnable mDisconnectedCallback;
809 
810         private final ConditionVariable mNetworkStatusReceived = new ConditionVariable();
811         // Contains the redirectUrl from networkStatus(). Before reading, wait for
812         // mNetworkStatusReceived.
813         private String mRedirectUrl;
814 
815         TestNetworkAgentWrapper(int transport) throws Exception {
816             this(transport, new LinkProperties(), null);
817         }
818 
819         TestNetworkAgentWrapper(int transport, LinkProperties linkProperties)
820                 throws Exception {
821             this(transport, linkProperties, null);
822         }
823 
824         private TestNetworkAgentWrapper(int transport, LinkProperties linkProperties,
825                 NetworkCapabilities ncTemplate) throws Exception {
826             super(transport, linkProperties, ncTemplate, mServiceContext);
827 
828             // Waits for the NetworkAgent to be registered, which includes the creation of the
829             // NetworkMonitor.
830             waitForIdle(TIMEOUT_MS);
831             HandlerUtils.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
832             HandlerUtils.waitForIdle(ConnectivityThread.get(), TIMEOUT_MS);
833         }
834 
835         @Override
836         protected InstrumentedNetworkAgent makeNetworkAgent(LinkProperties linkProperties,
837                 NetworkAgentConfig nac) throws Exception {
838             mNetworkMonitor = mock(INetworkMonitor.class);
839 
840             final Answer validateAnswer = inv -> {
841                 new Thread(ignoreExceptions(this::onValidationRequested)).start();
842                 return null;
843             };
844 
845             doAnswer(validateAnswer).when(mNetworkMonitor).notifyNetworkConnected(any(), any());
846             doAnswer(validateAnswer).when(mNetworkMonitor).forceReevaluation(anyInt());
847 
848             final ArgumentCaptor<Network> nmNetworkCaptor = ArgumentCaptor.forClass(Network.class);
849             final ArgumentCaptor<INetworkMonitorCallbacks> nmCbCaptor =
850                     ArgumentCaptor.forClass(INetworkMonitorCallbacks.class);
851             doNothing().when(mNetworkStack).makeNetworkMonitor(
852                     nmNetworkCaptor.capture(),
853                     any() /* name */,
854                     nmCbCaptor.capture());
855 
856             final InstrumentedNetworkAgent na =
857                     new InstrumentedNetworkAgent(this, linkProperties, nac) {
858                 @Override
859                 public void networkStatus(int status, String redirectUrl) {
860                     mRedirectUrl = redirectUrl;
861                     mNetworkStatusReceived.open();
862                 }
863 
864                 @Override
865                 public void onNetworkCreated() {
866                     super.onNetworkCreated();
867                     if (mCreatedCallback != null) mCreatedCallback.run();
868                 }
869 
870                 @Override
871                 public void onNetworkUnwanted() {
872                     super.onNetworkUnwanted();
873                     if (mUnwantedCallback != null) mUnwantedCallback.run();
874                 }
875 
876                 @Override
877                 public void onNetworkDestroyed() {
878                     super.onNetworkDestroyed();
879                     if (mDisconnectedCallback != null) mDisconnectedCallback.run();
880                 }
881             };
882 
883             assertEquals(na.getNetwork().netId, nmNetworkCaptor.getValue().netId);
884             mNmCallbacks = nmCbCaptor.getValue();
885 
886             mNmCallbacks.onNetworkMonitorCreated(mNetworkMonitor);
887 
888             return na;
889         }
890 
891         private void onValidationRequested() throws Exception {
892             if (mNmProvNotificationRequested
893                     && ((mNmValidationResult & NETWORK_VALIDATION_RESULT_VALID) != 0)) {
894                 mNmCallbacks.hideProvisioningNotification();
895                 mNmProvNotificationRequested = false;
896             }
897 
898             mNmCallbacks.notifyProbeStatusChanged(mProbesCompleted, mProbesSucceeded);
899             final NetworkTestResultParcelable p = new NetworkTestResultParcelable();
900             p.result = mNmValidationResult;
901             p.probesAttempted = mProbesCompleted;
902             p.probesSucceeded = mProbesSucceeded;
903             p.redirectUrl = mNmValidationRedirectUrl;
904             p.timestampMillis = TIMESTAMP;
905             mNmCallbacks.notifyNetworkTestedWithExtras(p);
906 
907             if (mNmValidationRedirectUrl != null) {
908                 mNmCallbacks.showProvisioningNotification(
909                         "test_provisioning_notif_action", TEST_PACKAGE_NAME);
910                 mNmProvNotificationRequested = true;
911             }
912         }
913 
914         /**
915          * Connect without adding any internet capability.
916          */
917         public void connectWithoutInternet() {
918             super.connect();
919         }
920 
921         /**
922          * Transition this NetworkAgent to CONNECTED state with NET_CAPABILITY_INTERNET.
923          * @param validated Indicate if network should pretend to be validated.
924          */
925         public void connect(boolean validated) {
926             connect(validated, true, false /* isStrictMode */);
927         }
928 
929         /**
930          * Transition this NetworkAgent to CONNECTED state.
931          * @param validated Indicate if network should pretend to be validated.
932          * @param hasInternet Indicate if network should pretend to have NET_CAPABILITY_INTERNET.
933          */
934         public void connect(boolean validated, boolean hasInternet, boolean isStrictMode) {
935             assertFalse(getNetworkCapabilities().hasCapability(NET_CAPABILITY_INTERNET));
936 
937             ConnectivityManager.NetworkCallback callback = null;
938             final ConditionVariable validatedCv = new ConditionVariable();
939             if (validated) {
940                 setNetworkValid(isStrictMode);
941                 NetworkRequest request = new NetworkRequest.Builder()
942                         .addTransportType(getNetworkCapabilities().getTransportTypes()[0])
943                         .clearCapabilities()
944                         .build();
945                 callback = new ConnectivityManager.NetworkCallback() {
946                     public void onCapabilitiesChanged(Network network,
947                             NetworkCapabilities networkCapabilities) {
948                         if (network.equals(getNetwork()) &&
949                                 networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED)) {
950                             validatedCv.open();
951                         }
952                     }
953                 };
954                 mCm.registerNetworkCallback(request, callback);
955             }
956             if (hasInternet) {
957                 addCapability(NET_CAPABILITY_INTERNET);
958             }
959 
960             connectWithoutInternet();
961 
962             if (validated) {
963                 // Wait for network to validate.
964                 waitFor(validatedCv);
965                 setNetworkInvalid(isStrictMode);
966             }
967 
968             if (callback != null) mCm.unregisterNetworkCallback(callback);
969         }
970 
971         public void connectWithCaptivePortal(String redirectUrl, boolean isStrictMode) {
972             setNetworkPortal(redirectUrl, isStrictMode);
973             connect(false, true /* hasInternet */, isStrictMode);
974         }
975 
976         public void connectWithPartialConnectivity() {
977             setNetworkPartial();
978             connect(false);
979         }
980 
981         public void connectWithPartialValidConnectivity(boolean isStrictMode) {
982             setNetworkPartialValid(isStrictMode);
983             connect(false, true /* hasInternet */, isStrictMode);
984         }
985 
986         void setNetworkValid(boolean isStrictMode) {
987             mNmValidationResult = NETWORK_VALIDATION_RESULT_VALID;
988             mNmValidationRedirectUrl = null;
989             int probesSucceeded = NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_HTTPS;
990             if (isStrictMode) {
991                 probesSucceeded |= NETWORK_VALIDATION_PROBE_PRIVDNS;
992             }
993             // The probesCompleted equals to probesSucceeded for the case of valid network, so put
994             // the same value into two different parameter of the method.
995             setProbesStatus(probesSucceeded, probesSucceeded);
996         }
997 
998         void setNetworkInvalid(boolean isStrictMode) {
999             mNmValidationResult = VALIDATION_RESULT_INVALID;
1000             mNmValidationRedirectUrl = null;
1001             int probesCompleted = NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_HTTPS
1002                     | NETWORK_VALIDATION_PROBE_HTTP;
1003             int probesSucceeded = 0;
1004             // If the isStrictMode is true, it means the network is invalid when NetworkMonitor
1005             // tried to validate the private DNS but failed.
1006             if (isStrictMode) {
1007                 probesCompleted &= ~NETWORK_VALIDATION_PROBE_HTTP;
1008                 probesSucceeded = probesCompleted;
1009                 probesCompleted |= NETWORK_VALIDATION_PROBE_PRIVDNS;
1010             }
1011             setProbesStatus(probesCompleted, probesSucceeded);
1012         }
1013 
1014         void setNetworkPortal(String redirectUrl, boolean isStrictMode) {
1015             setNetworkInvalid(isStrictMode);
1016             mNmValidationRedirectUrl = redirectUrl;
1017             // Suppose the portal is found when NetworkMonitor probes NETWORK_VALIDATION_PROBE_HTTP
1018             // in the beginning, so the NETWORK_VALIDATION_PROBE_HTTPS hasn't probed yet.
1019             int probesCompleted = NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_HTTP;
1020             int probesSucceeded = VALIDATION_RESULT_INVALID;
1021             if (isStrictMode) {
1022                 probesCompleted |= NETWORK_VALIDATION_PROBE_PRIVDNS;
1023             }
1024             setProbesStatus(probesCompleted, probesSucceeded);
1025         }
1026 
1027         void setNetworkPartial() {
1028             mNmValidationResult = NETWORK_VALIDATION_RESULT_PARTIAL;
1029             mNmValidationRedirectUrl = null;
1030             int probesCompleted = NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_HTTPS
1031                     | NETWORK_VALIDATION_PROBE_FALLBACK;
1032             int probesSucceeded = NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_FALLBACK;
1033             setProbesStatus(probesCompleted, probesSucceeded);
1034         }
1035 
1036         void setNetworkPartialValid(boolean isStrictMode) {
1037             setNetworkPartial();
1038             mNmValidationResult |= NETWORK_VALIDATION_RESULT_VALID;
1039             int probesCompleted = NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_HTTPS
1040                     | NETWORK_VALIDATION_PROBE_HTTP;
1041             int probesSucceeded = NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_HTTP;
1042             // Suppose the partial network cannot pass the private DNS validation as well, so only
1043             // add NETWORK_VALIDATION_PROBE_DNS in probesCompleted but not probesSucceeded.
1044             if (isStrictMode) {
1045                 probesCompleted |= NETWORK_VALIDATION_PROBE_PRIVDNS;
1046             }
1047             setProbesStatus(probesCompleted, probesSucceeded);
1048         }
1049 
1050         void setProbesStatus(int probesCompleted, int probesSucceeded) {
1051             mProbesCompleted = probesCompleted;
1052             mProbesSucceeded = probesSucceeded;
1053         }
1054 
1055         void notifyCapportApiDataChanged(CaptivePortalData data) {
1056             try {
1057                 mNmCallbacks.notifyCaptivePortalDataChanged(data);
1058             } catch (RemoteException e) {
1059                 throw new AssertionError("This cannot happen", e);
1060             }
1061         }
1062 
1063         public String waitForRedirectUrl() {
1064             assertTrue(mNetworkStatusReceived.block(TIMEOUT_MS));
1065             return mRedirectUrl;
1066         }
1067 
1068         public void expectDisconnected() {
1069             expectDisconnected(TIMEOUT_MS);
1070         }
1071 
1072         public void expectPreventReconnectReceived() {
1073             expectPreventReconnectReceived(TIMEOUT_MS);
1074         }
1075 
1076         void notifyDataStallSuspected() throws Exception {
1077             final DataStallReportParcelable p = new DataStallReportParcelable();
1078             p.detectionMethod = DATA_STALL_DETECTION_METHOD;
1079             p.timestampMillis = DATA_STALL_TIMESTAMP;
1080             mNmCallbacks.notifyDataStallSuspected(p);
1081         }
1082 
1083         public void setCreatedCallback(Runnable r) {
1084             mCreatedCallback = r;
1085         }
1086 
1087         public void setUnwantedCallback(Runnable r) {
1088             mUnwantedCallback = r;
1089         }
1090 
1091         public void setDisconnectedCallback(Runnable r) {
1092             mDisconnectedCallback = r;
1093         }
1094     }
1095 
1096     /**
1097      * A NetworkFactory that allows to wait until any in-flight NetworkRequest add or remove
1098      * operations have been processed and test for them.
1099      */
1100     private static class MockNetworkFactory extends NetworkFactory {
1101         private final AtomicBoolean mNetworkStarted = new AtomicBoolean(false);
1102 
1103         static class RequestEntry {
1104             @NonNull
1105             public final NetworkRequest request;
1106 
1107             RequestEntry(@NonNull final NetworkRequest request) {
1108                 this.request = request;
1109             }
1110 
1111             static final class Add extends RequestEntry {
1112                 Add(@NonNull final NetworkRequest request) {
1113                     super(request);
1114                 }
1115             }
1116 
1117             static final class Remove extends RequestEntry {
1118                 Remove(@NonNull final NetworkRequest request) {
1119                     super(request);
1120                 }
1121             }
1122 
1123             @Override
1124             public String toString() {
1125                 return "RequestEntry [ " + getClass().getName() + " : " + request + " ]";
1126             }
1127         }
1128 
1129         // History of received requests adds and removes.
1130         private final ArrayTrackRecord<RequestEntry>.ReadHead mRequestHistory =
1131                 new ArrayTrackRecord<RequestEntry>().newReadHead();
1132 
1133         private static <T> T failIfNull(@Nullable final T obj, @Nullable final String message) {
1134             if (null == obj) fail(null != message ? message : "Must not be null");
1135             return obj;
1136         }
1137 
1138         public RequestEntry.Add expectRequestAdd() {
1139             return failIfNull((RequestEntry.Add) mRequestHistory.poll(TIMEOUT_MS,
1140                     it -> it instanceof RequestEntry.Add), "Expected request add");
1141         }
1142 
1143         public void expectRequestAdds(final int count) {
1144             for (int i = count; i > 0; --i) {
1145                 expectRequestAdd();
1146             }
1147         }
1148 
1149         public RequestEntry.Remove expectRequestRemove() {
1150             return failIfNull((RequestEntry.Remove) mRequestHistory.poll(TIMEOUT_MS,
1151                     it -> it instanceof RequestEntry.Remove), "Expected request remove");
1152         }
1153 
1154         public void expectRequestRemoves(final int count) {
1155             for (int i = count; i > 0; --i) {
1156                 expectRequestRemove();
1157             }
1158         }
1159 
1160         // Used to collect the networks requests managed by this factory. This is a duplicate of
1161         // the internal information stored in the NetworkFactory (which is private).
1162         private SparseArray<NetworkRequest> mNetworkRequests = new SparseArray<>();
1163         private final HandlerThread mHandlerSendingRequests;
1164 
1165         public MockNetworkFactory(Looper looper, Context context, String logTag,
1166                 NetworkCapabilities filter, HandlerThread threadSendingRequests) {
1167             super(looper, context, logTag, filter);
1168             mHandlerSendingRequests = threadSendingRequests;
1169         }
1170 
1171         public int getMyRequestCount() {
1172             return getRequestCount();
1173         }
1174 
1175         protected void startNetwork() {
1176             mNetworkStarted.set(true);
1177         }
1178 
1179         protected void stopNetwork() {
1180             mNetworkStarted.set(false);
1181         }
1182 
1183         public boolean getMyStartRequested() {
1184             return mNetworkStarted.get();
1185         }
1186 
1187 
1188         @Override
1189         protected void needNetworkFor(NetworkRequest request) {
1190             mNetworkRequests.put(request.requestId, request);
1191             super.needNetworkFor(request);
1192             mRequestHistory.add(new RequestEntry.Add(request));
1193         }
1194 
1195         @Override
1196         protected void releaseNetworkFor(NetworkRequest request) {
1197             mNetworkRequests.remove(request.requestId);
1198             super.releaseNetworkFor(request);
1199             mRequestHistory.add(new RequestEntry.Remove(request));
1200         }
1201 
1202         public void assertRequestCountEquals(final int count) {
1203             assertEquals(count, getMyRequestCount());
1204         }
1205 
1206         @Override
1207         public void terminate() {
1208             super.terminate();
1209             // Make sure there are no remaining requests unaccounted for.
1210             HandlerUtils.waitForIdle(mHandlerSendingRequests, TIMEOUT_MS);
1211             assertNull(mRequestHistory.poll(0, r -> true));
1212         }
1213 
1214         // Trigger releasing the request as unfulfillable
1215         public void triggerUnfulfillable(NetworkRequest r) {
1216             super.releaseRequestAsUnfulfillableByAnyFactory(r);
1217         }
1218 
1219         public void assertNoRequestChanged() {
1220             assertNull(mRequestHistory.poll(0, r -> true));
1221         }
1222     }
1223 
1224     private Set<UidRange> uidRangesForUids(int... uids) {
1225         final ArraySet<UidRange> ranges = new ArraySet<>();
1226         for (final int uid : uids) {
1227             ranges.add(new UidRange(uid, uid));
1228         }
1229         return ranges;
1230     }
1231 
1232     private Set<UidRange> uidRangesForUids(Collection<Integer> uids) {
1233         return uidRangesForUids(CollectionUtils.toIntArray(uids));
1234     }
1235 
1236     private static Looper startHandlerThreadAndReturnLooper() {
1237         final HandlerThread handlerThread = new HandlerThread("MockVpnThread");
1238         handlerThread.start();
1239         return handlerThread.getLooper();
1240     }
1241 
1242     private class MockVpn extends Vpn implements TestableNetworkCallback.HasNetwork {
1243         // Careful ! This is different from mNetworkAgent, because MockNetworkAgent does
1244         // not inherit from NetworkAgent.
1245         private TestNetworkAgentWrapper mMockNetworkAgent;
1246         private boolean mAgentRegistered = false;
1247 
1248         private int mVpnType = VpnManager.TYPE_VPN_SERVICE;
1249         private UnderlyingNetworkInfo mUnderlyingNetworkInfo;
1250 
1251         // These ConditionVariables allow tests to wait for LegacyVpnRunner to be stopped/started.
1252         // TODO: this scheme is ad-hoc and error-prone because it does not fail if, for example, the
1253         // test expects two starts in a row, or even if the production code calls start twice in a
1254         // row. find a better solution. Simply putting a method to create a LegacyVpnRunner into
1255         // Vpn.Dependencies doesn't work because LegacyVpnRunner is not a static class and has
1256         // extensive access into the internals of Vpn.
1257         private ConditionVariable mStartLegacyVpnCv = new ConditionVariable();
1258         private ConditionVariable mStopVpnRunnerCv = new ConditionVariable();
1259 
1260         public MockVpn(int userId) {
1261             super(startHandlerThreadAndReturnLooper(), mServiceContext,
1262                     new Dependencies() {
1263                         @Override
1264                         public boolean isCallerSystem() {
1265                             return true;
1266                         }
1267 
1268                         @Override
1269                         public DeviceIdleInternal getDeviceIdleInternal() {
1270                             return mDeviceIdleInternal;
1271                         }
1272                     },
1273                     mNetworkManagementService, mMockNetd, userId, mVpnProfileStore,
1274                     new SystemServices(mServiceContext) {
1275                         @Override
1276                         public String settingsSecureGetStringForUser(String key, int userId) {
1277                             switch (key) {
1278                                 // Settings keys not marked as @Readable are not readable from
1279                                 // non-privileged apps, unless marked as testOnly=true
1280                                 // (atest refuses to install testOnly=true apps), even if mocked
1281                                 // in the content provider, because
1282                                 // Settings.Secure.NameValueCache#getStringForUser checks the key
1283                                 // before querying the mock settings provider.
1284                                 case Settings.Secure.ALWAYS_ON_VPN_APP:
1285                                     return null;
1286                                 default:
1287                                     return super.settingsSecureGetStringForUser(key, userId);
1288                             }
1289                         }
1290                     }, new Ikev2SessionCreator());
1291         }
1292 
1293         public void setUids(Set<UidRange> uids) {
1294             mNetworkCapabilities.setUids(UidRange.toIntRanges(uids));
1295             if (mAgentRegistered) {
1296                 mMockNetworkAgent.setNetworkCapabilities(mNetworkCapabilities, true);
1297             }
1298         }
1299 
1300         public void setVpnType(int vpnType) {
1301             mVpnType = vpnType;
1302         }
1303 
1304         @Override
1305         public Network getNetwork() {
1306             return (mMockNetworkAgent == null) ? null : mMockNetworkAgent.getNetwork();
1307         }
1308 
1309         @Override
1310         public int getActiveVpnType() {
1311             return mVpnType;
1312         }
1313 
1314         private LinkProperties makeLinkProperties() {
1315             final LinkProperties lp = new LinkProperties();
1316             lp.setInterfaceName(VPN_IFNAME);
1317             return lp;
1318         }
1319 
1320         private void registerAgent(boolean isAlwaysMetered, Set<UidRange> uids, LinkProperties lp)
1321                 throws Exception {
1322             if (mAgentRegistered) throw new IllegalStateException("already registered");
1323             updateState(NetworkInfo.DetailedState.CONNECTING, "registerAgent");
1324             mConfig = new VpnConfig();
1325             mConfig.session = "MySession12345";
1326             setUids(uids);
1327             if (!isAlwaysMetered) mNetworkCapabilities.addCapability(NET_CAPABILITY_NOT_METERED);
1328             mInterface = VPN_IFNAME;
1329             mNetworkCapabilities.setTransportInfo(new VpnTransportInfo(getActiveVpnType(),
1330                     mConfig.session));
1331             mMockNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN, lp,
1332                     mNetworkCapabilities);
1333             mMockNetworkAgent.waitForIdle(TIMEOUT_MS);
1334 
1335             verify(mMockNetd, times(1)).networkAddUidRangesParcel(
1336                     new NativeUidRangeConfig(mMockVpn.getNetwork().getNetId(),
1337                             toUidRangeStableParcels(uids), PREFERENCE_PRIORITY_VPN));
1338             verify(mMockNetd, never()).networkRemoveUidRangesParcel(argThat(config ->
1339                     mMockVpn.getNetwork().getNetId() == config.netId
1340                             && PREFERENCE_PRIORITY_VPN == config.subPriority));
1341             mAgentRegistered = true;
1342             verify(mMockNetd).networkCreate(nativeNetworkConfigVpn(getNetwork().netId,
1343                     !mMockNetworkAgent.isBypassableVpn(), mVpnType));
1344             updateState(NetworkInfo.DetailedState.CONNECTED, "registerAgent");
1345             mNetworkCapabilities.set(mMockNetworkAgent.getNetworkCapabilities());
1346             mNetworkAgent = mMockNetworkAgent.getNetworkAgent();
1347         }
1348 
1349         private void registerAgent(Set<UidRange> uids) throws Exception {
1350             registerAgent(false /* isAlwaysMetered */, uids, makeLinkProperties());
1351         }
1352 
1353         private void connect(boolean validated, boolean hasInternet, boolean isStrictMode) {
1354             mMockNetworkAgent.connect(validated, hasInternet, isStrictMode);
1355         }
1356 
1357         private void connect(boolean validated) {
1358             mMockNetworkAgent.connect(validated);
1359         }
1360 
1361         private TestNetworkAgentWrapper getAgent() {
1362             return mMockNetworkAgent;
1363         }
1364 
1365         private void setOwnerAndAdminUid(int uid) throws Exception {
1366             mNetworkCapabilities.setOwnerUid(uid);
1367             mNetworkCapabilities.setAdministratorUids(new int[]{uid});
1368         }
1369 
1370         public void establish(LinkProperties lp, int uid, Set<UidRange> ranges, boolean validated,
1371                 boolean hasInternet, boolean isStrictMode) throws Exception {
1372             setOwnerAndAdminUid(uid);
1373             registerAgent(false, ranges, lp);
1374             connect(validated, hasInternet, isStrictMode);
1375             waitForIdle();
1376         }
1377 
1378         public void establish(LinkProperties lp, int uid, Set<UidRange> ranges) throws Exception {
1379             establish(lp, uid, ranges, true, true, false);
1380         }
1381 
1382         public void establishForMyUid(LinkProperties lp) throws Exception {
1383             final int uid = Process.myUid();
1384             establish(lp, uid, uidRangesForUids(uid), true, true, false);
1385         }
1386 
1387         public void establishForMyUid(boolean validated, boolean hasInternet, boolean isStrictMode)
1388                 throws Exception {
1389             final int uid = Process.myUid();
1390             establish(makeLinkProperties(), uid, uidRangesForUids(uid), validated, hasInternet,
1391                     isStrictMode);
1392         }
1393 
1394         public void establishForMyUid() throws Exception {
1395             establishForMyUid(makeLinkProperties());
1396         }
1397 
1398         public void sendLinkProperties(LinkProperties lp) {
1399             mMockNetworkAgent.sendLinkProperties(lp);
1400         }
1401 
1402         public void disconnect() {
1403             if (mMockNetworkAgent != null) {
1404                 mMockNetworkAgent.disconnect();
1405                 updateState(NetworkInfo.DetailedState.DISCONNECTED, "disconnect");
1406             }
1407             mAgentRegistered = false;
1408             setUids(null);
1409             // Remove NET_CAPABILITY_INTERNET or MockNetworkAgent will refuse to connect later on.
1410             mNetworkCapabilities.removeCapability(NET_CAPABILITY_INTERNET);
1411             mInterface = null;
1412         }
1413 
1414         @Override
1415         public void startLegacyVpnRunner() {
1416             mStartLegacyVpnCv.open();
1417         }
1418 
1419         public void expectStartLegacyVpnRunner() {
1420             assertTrue("startLegacyVpnRunner not called after " + TIMEOUT_MS + " ms",
1421                     mStartLegacyVpnCv.block(TIMEOUT_MS));
1422 
1423             // startLegacyVpn calls stopVpnRunnerPrivileged, which will open mStopVpnRunnerCv, just
1424             // before calling startLegacyVpnRunner. Restore mStopVpnRunnerCv, so the test can expect
1425             // that the VpnRunner is stopped and immediately restarted by calling
1426             // expectStartLegacyVpnRunner() and expectStopVpnRunnerPrivileged() back-to-back.
1427             mStopVpnRunnerCv = new ConditionVariable();
1428         }
1429 
1430         @Override
1431         public void stopVpnRunnerPrivileged() {
1432             if (mVpnRunner != null) {
1433                 super.stopVpnRunnerPrivileged();
1434                 disconnect();
1435                 mStartLegacyVpnCv = new ConditionVariable();
1436             }
1437             mVpnRunner = null;
1438             mStopVpnRunnerCv.open();
1439         }
1440 
1441         public void expectStopVpnRunnerPrivileged() {
1442             assertTrue("stopVpnRunnerPrivileged not called after " + TIMEOUT_MS + " ms",
1443                     mStopVpnRunnerCv.block(TIMEOUT_MS));
1444         }
1445 
1446         @Override
1447         public synchronized UnderlyingNetworkInfo getUnderlyingNetworkInfo() {
1448             if (mUnderlyingNetworkInfo != null) return mUnderlyingNetworkInfo;
1449 
1450             return super.getUnderlyingNetworkInfo();
1451         }
1452 
1453         private synchronized void setUnderlyingNetworkInfo(
1454                 UnderlyingNetworkInfo underlyingNetworkInfo) {
1455             mUnderlyingNetworkInfo = underlyingNetworkInfo;
1456         }
1457     }
1458 
1459     private UidRangeParcel[] toUidRangeStableParcels(final @NonNull Set<UidRange> ranges) {
1460         return ranges.stream().map(
1461                 r -> new UidRangeParcel(r.start, r.stop)).toArray(UidRangeParcel[]::new);
1462     }
1463 
1464     private VpnManagerService makeVpnManagerService() {
1465         final VpnManagerService.Dependencies deps = new VpnManagerService.Dependencies() {
1466             public int getCallingUid() {
1467                 return mDeps.getCallingUid();
1468             }
1469 
1470             public HandlerThread makeHandlerThread() {
1471                 return mVMSHandlerThread;
1472             }
1473 
1474             @Override
1475             public VpnProfileStore getVpnProfileStore() {
1476                 return mVpnProfileStore;
1477             }
1478 
1479             public INetd getNetd() {
1480                 return mMockNetd;
1481             }
1482 
1483             public INetworkManagementService getINetworkManagementService() {
1484                 return mNetworkManagementService;
1485             }
1486         };
1487         return new VpnManagerService(mServiceContext, deps);
1488     }
1489 
1490     private void assertVpnTransportInfo(NetworkCapabilities nc, int type) {
1491         assertNotNull(nc);
1492         final TransportInfo ti = nc.getTransportInfo();
1493         assertTrue("VPN TransportInfo is not a VpnTransportInfo: " + ti,
1494                 ti instanceof VpnTransportInfo);
1495         assertEquals(type, ((VpnTransportInfo) ti).getType());
1496 
1497     }
1498 
1499     private void processBroadcast(Intent intent) {
1500         mServiceContext.sendBroadcast(intent);
1501         HandlerUtils.waitForIdle(mVMSHandlerThread, TIMEOUT_MS);
1502         waitForIdle();
1503     }
1504 
1505     private void mockVpn(int uid) {
1506         synchronized (mVpnManagerService.mVpns) {
1507             int userId = UserHandle.getUserId(uid);
1508             mMockVpn = new MockVpn(userId);
1509             // Every running user always has a Vpn in the mVpns array, even if no VPN is running.
1510             mVpnManagerService.mVpns.put(userId, mMockVpn);
1511         }
1512     }
1513 
1514     private void mockUidNetworkingBlocked() {
1515         doAnswer(i -> isUidBlocked(mBlockedReasons, i.getArgument(1))
1516         ).when(mNetworkPolicyManager).isUidNetworkingBlocked(anyInt(), anyBoolean());
1517     }
1518 
1519     private boolean isUidBlocked(int blockedReasons, boolean meteredNetwork) {
1520         final int blockedOnAllNetworksReason = (blockedReasons & ~BLOCKED_METERED_REASON_MASK);
1521         if (blockedOnAllNetworksReason != BLOCKED_REASON_NONE) {
1522             return true;
1523         }
1524         if (meteredNetwork) {
1525             return blockedReasons != BLOCKED_REASON_NONE;
1526         }
1527         return false;
1528     }
1529 
1530     private void setBlockedReasonChanged(int blockedReasons) {
1531         mBlockedReasons = blockedReasons;
1532         mPolicyCallback.onUidBlockedReasonChanged(Process.myUid(), blockedReasons);
1533     }
1534 
1535     private Nat464Xlat getNat464Xlat(NetworkAgentWrapper mna) {
1536         return mService.getNetworkAgentInfoForNetwork(mna.getNetwork()).clatd;
1537     }
1538 
1539     private class WrappedMultinetworkPolicyTracker extends MultinetworkPolicyTracker {
1540         volatile int mConfigMeteredMultipathPreference;
1541 
1542         WrappedMultinetworkPolicyTracker(Context c, Handler h, Runnable r) {
1543             super(c, h, r);
1544         }
1545 
1546         @Override
1547         protected Resources getResourcesForActiveSubId() {
1548             return mResources;
1549         }
1550 
1551         @Override
1552         public int configMeteredMultipathPreference() {
1553             return mConfigMeteredMultipathPreference;
1554         }
1555     }
1556 
1557     /**
1558      * Wait up to TIMEOUT_MS for {@code conditionVariable} to open.
1559      * Fails if TIMEOUT_MS goes by before {@code conditionVariable} opens.
1560      */
1561     static private void waitFor(ConditionVariable conditionVariable) {
1562         if (conditionVariable.block(TIMEOUT_MS)) {
1563             return;
1564         }
1565         fail("ConditionVariable was blocked for more than " + TIMEOUT_MS + "ms");
1566     }
1567 
1568     private <T> T doAsUid(final int uid, @NonNull final Supplier<T> what) {
1569         when(mDeps.getCallingUid()).thenReturn(uid);
1570         try {
1571             return what.get();
1572         } finally {
1573             returnRealCallingUid();
1574         }
1575     }
1576 
1577     private void doAsUid(final int uid, @NonNull final Runnable what) {
1578         doAsUid(uid, () -> {
1579             what.run(); return Void.TYPE;
1580         });
1581     }
1582 
1583     private void registerNetworkCallbackAsUid(NetworkRequest request, NetworkCallback callback,
1584             int uid) {
1585         doAsUid(uid, () -> {
1586             mCm.registerNetworkCallback(request, callback);
1587         });
1588     }
1589 
1590     private void registerDefaultNetworkCallbackAsUid(@NonNull final NetworkCallback callback,
1591             final int uid) {
1592         doAsUid(uid, () -> {
1593             mCm.registerDefaultNetworkCallback(callback);
1594             waitForIdle();
1595         });
1596     }
1597 
1598     private interface ExceptionalRunnable {
1599         void run() throws Exception;
1600     }
1601 
1602     private void withPermission(String permission, ExceptionalRunnable r) throws Exception {
1603         try {
1604             mServiceContext.setPermission(permission, PERMISSION_GRANTED);
1605             r.run();
1606         } finally {
1607             mServiceContext.setPermission(permission, null);
1608         }
1609     }
1610 
1611     private void withPermission(String permission, int pid, int uid, ExceptionalRunnable r)
1612             throws Exception {
1613         try {
1614             mServiceContext.setPermission(permission, pid, uid, PERMISSION_GRANTED);
1615             r.run();
1616         } finally {
1617             mServiceContext.setPermission(permission, pid, uid, null);
1618         }
1619     }
1620 
1621     private static final int PRIMARY_USER = 0;
1622     private static final int SECONDARY_USER = 10;
1623     private static final int TERTIARY_USER = 11;
1624     private static final UidRange PRIMARY_UIDRANGE =
1625             UidRange.createForUser(UserHandle.of(PRIMARY_USER));
1626     private static final int APP1_UID = UserHandle.getUid(PRIMARY_USER, 10100);
1627     private static final int APP2_UID = UserHandle.getUid(PRIMARY_USER, 10101);
1628     private static final int VPN_UID = UserHandle.getUid(PRIMARY_USER, 10043);
1629     private static final UserInfo PRIMARY_USER_INFO = new UserInfo(PRIMARY_USER, "",
1630             UserInfo.FLAG_PRIMARY);
1631     private static final UserHandle PRIMARY_USER_HANDLE = new UserHandle(PRIMARY_USER);
1632     private static final UserHandle SECONDARY_USER_HANDLE = new UserHandle(SECONDARY_USER);
1633     private static final UserHandle TERTIARY_USER_HANDLE = new UserHandle(TERTIARY_USER);
1634 
1635     private static final int RESTRICTED_USER = 1;
1636     private static final UserInfo RESTRICTED_USER_INFO = new UserInfo(RESTRICTED_USER, "",
1637             UserInfo.FLAG_RESTRICTED);
1638     static {
1639         RESTRICTED_USER_INFO.restrictedProfileParentId = PRIMARY_USER;
1640     }
1641 
1642     @Before
1643     public void setUp() throws Exception {
1644         mNetIdManager = new TestNetIdManager();
1645 
1646         mContext = InstrumentationRegistry.getContext();
1647 
1648         MockitoAnnotations.initMocks(this);
1649 
1650         when(mUserManager.getAliveUsers()).thenReturn(Arrays.asList(PRIMARY_USER_INFO));
1651         when(mUserManager.getUserHandles(anyBoolean())).thenReturn(
1652                 Arrays.asList(PRIMARY_USER_HANDLE));
1653         when(mUserManager.getUserInfo(PRIMARY_USER)).thenReturn(PRIMARY_USER_INFO);
1654         // canHaveRestrictedProfile does not take a userId. It applies to the userId of the context
1655         // it was started from, i.e., PRIMARY_USER.
1656         when(mUserManager.canHaveRestrictedProfile()).thenReturn(true);
1657         when(mUserManager.getUserInfo(RESTRICTED_USER)).thenReturn(RESTRICTED_USER_INFO);
1658 
1659         final ApplicationInfo applicationInfo = new ApplicationInfo();
1660         applicationInfo.targetSdkVersion = Build.VERSION_CODES.Q;
1661         when(mPackageManager.getApplicationInfoAsUser(anyString(), anyInt(), any()))
1662                 .thenReturn(applicationInfo);
1663         when(mPackageManager.getTargetSdkVersion(anyString()))
1664                 .thenReturn(applicationInfo.targetSdkVersion);
1665         when(mSystemConfigManager.getSystemPermissionUids(anyString())).thenReturn(new int[0]);
1666 
1667         // InstrumentationTestRunner prepares a looper, but AndroidJUnitRunner does not.
1668         // http://b/25897652 .
1669         if (Looper.myLooper() == null) {
1670             Looper.prepare();
1671         }
1672         mockDefaultPackages();
1673         mockHasSystemFeature(FEATURE_WIFI, true);
1674         mockHasSystemFeature(FEATURE_WIFI_DIRECT, true);
1675         doReturn(true).when(mTelephonyManager).isDataCapable();
1676 
1677         FakeSettingsProvider.clearSettingsProvider();
1678         mServiceContext = new MockContext(InstrumentationRegistry.getContext(),
1679                 new FakeSettingsProvider());
1680         mServiceContext.setUseRegisteredHandlers(true);
1681         mServiceContext.setPermission(NETWORK_FACTORY, PERMISSION_GRANTED);
1682         mServiceContext.setPermission(NETWORK_STACK, PERMISSION_GRANTED);
1683         mServiceContext.setPermission(CONTROL_OEM_PAID_NETWORK_PREFERENCE, PERMISSION_GRANTED);
1684         mServiceContext.setPermission(PACKET_KEEPALIVE_OFFLOAD, PERMISSION_GRANTED);
1685         mServiceContext.setPermission(CONNECTIVITY_USE_RESTRICTED_NETWORKS, PERMISSION_GRANTED);
1686 
1687         mAlarmManagerThread = new HandlerThread("TestAlarmManager");
1688         mAlarmManagerThread.start();
1689         initAlarmManager(mAlarmManager, mAlarmManagerThread.getThreadHandler());
1690 
1691         mCsHandlerThread = new HandlerThread("TestConnectivityService");
1692         mVMSHandlerThread = new HandlerThread("TestVpnManagerService");
1693         mDeps = makeDependencies();
1694         returnRealCallingUid();
1695         mService = new ConnectivityService(mServiceContext,
1696                 mMockDnsResolver,
1697                 mock(IpConnectivityLog.class),
1698                 mMockNetd,
1699                 mDeps);
1700         mService.mLingerDelayMs = TEST_LINGER_DELAY_MS;
1701         mService.mNascentDelayMs = TEST_NASCENT_DELAY_MS;
1702         verify(mDeps).makeMultinetworkPolicyTracker(any(), any(), any());
1703 
1704         final ArgumentCaptor<NetworkPolicyCallback> policyCallbackCaptor =
1705                 ArgumentCaptor.forClass(NetworkPolicyCallback.class);
1706         verify(mNetworkPolicyManager).registerNetworkPolicyCallback(any(),
1707                 policyCallbackCaptor.capture());
1708         mPolicyCallback = policyCallbackCaptor.getValue();
1709 
1710         // Create local CM before sending system ready so that we can answer
1711         // getSystemService() correctly.
1712         mCm = new WrappedConnectivityManager(InstrumentationRegistry.getContext(), mService);
1713         mService.systemReadyInternal();
1714         mVpnManagerService = makeVpnManagerService();
1715         mVpnManagerService.systemReady();
1716         mockVpn(Process.myUid());
1717         mCm.bindProcessToNetwork(null);
1718         mQosCallbackTracker = mock(QosCallbackTracker.class);
1719 
1720         // Ensure that the default setting for Captive Portals is used for most tests
1721         setCaptivePortalMode(ConnectivitySettingsManager.CAPTIVE_PORTAL_MODE_PROMPT);
1722         setAlwaysOnNetworks(false);
1723         setPrivateDnsSettings(PRIVATE_DNS_MODE_OFF, "ignored.example.com");
1724     }
1725 
1726     private void returnRealCallingUid() {
1727         doAnswer((invocationOnMock) -> Binder.getCallingUid()).when(mDeps).getCallingUid();
1728     }
1729 
1730     private ConnectivityService.Dependencies makeDependencies() {
1731         doReturn(false).when(mSystemProperties).getBoolean("ro.radio.noril", false);
1732         final ConnectivityService.Dependencies deps = mock(ConnectivityService.Dependencies.class);
1733         doReturn(mCsHandlerThread).when(deps).makeHandlerThread();
1734         doReturn(mNetIdManager).when(deps).makeNetIdManager();
1735         doReturn(mNetworkStack).when(deps).getNetworkStack();
1736         doReturn(mSystemProperties).when(deps).getSystemProperties();
1737         doReturn(mProxyTracker).when(deps).makeProxyTracker(any(), any());
1738         doReturn(true).when(deps).queryUserAccess(anyInt(), any(), any());
1739         doAnswer(inv -> {
1740             mPolicyTracker = new WrappedMultinetworkPolicyTracker(
1741                     inv.getArgument(0), inv.getArgument(1), inv.getArgument(2));
1742             return mPolicyTracker;
1743         }).when(deps).makeMultinetworkPolicyTracker(any(), any(), any());
1744         doReturn(true).when(deps).getCellular464XlatEnabled();
1745         doAnswer(inv ->
1746             new LocationPermissionChecker(inv.getArgument(0)) {
1747                 @Override
1748                 protected int getCurrentUser() {
1749                     return runAsShell(CREATE_USERS, () -> super.getCurrentUser());
1750                 }
1751             }).when(deps).makeLocationPermissionChecker(any());
1752 
1753         doReturn(60000).when(mResources).getInteger(R.integer.config_networkTransitionTimeout);
1754         doReturn("").when(mResources).getString(R.string.config_networkCaptivePortalServerUrl);
1755         doReturn(new String[]{ WIFI_WOL_IFNAME }).when(mResources).getStringArray(
1756                 R.array.config_wakeonlan_supported_interfaces);
1757         doReturn(new String[] { "0,1", "1,3" }).when(mResources).getStringArray(
1758                 R.array.config_networkSupportedKeepaliveCount);
1759         doReturn(new String[0]).when(mResources).getStringArray(
1760                 R.array.config_networkNotifySwitches);
1761         doReturn(new int[]{10, 11, 12, 14, 15}).when(mResources).getIntArray(
1762                 R.array.config_protectedNetworks);
1763         // We don't test the actual notification value strings, so just return an empty array.
1764         // It doesn't matter what the values are as long as it's not null.
1765         doReturn(new String[0]).when(mResources).getStringArray(R.array.network_switch_type_name);
1766 
1767         doReturn(R.array.config_networkSupportedKeepaliveCount).when(mResources)
1768                 .getIdentifier(eq("config_networkSupportedKeepaliveCount"), eq("array"), any());
1769         doReturn(R.array.network_switch_type_name).when(mResources)
1770                 .getIdentifier(eq("network_switch_type_name"), eq("array"), any());
1771         doReturn(R.integer.config_networkAvoidBadWifi).when(mResources)
1772                 .getIdentifier(eq("config_networkAvoidBadWifi"), eq("integer"), any());
1773         doReturn(1).when(mResources).getInteger(R.integer.config_networkAvoidBadWifi);
1774 
1775         final ConnectivityResources connRes = mock(ConnectivityResources.class);
1776         doReturn(mResources).when(connRes).get();
1777         doReturn(connRes).when(deps).getResources(any());
1778 
1779         final Context mockResContext = mock(Context.class);
1780         doReturn(mResources).when(mockResContext).getResources();
1781         ConnectivityResources.setResourcesContextForTest(mockResContext);
1782 
1783         doAnswer(inv -> {
1784             final PendingIntent a = inv.getArgument(0);
1785             final PendingIntent b = inv.getArgument(1);
1786             return runAsShell(GET_INTENT_SENDER_INTENT, () -> a.intentFilterEquals(b));
1787         }).when(deps).intentFilterEquals(any(), any());
1788 
1789         return deps;
1790     }
1791 
1792     private static void initAlarmManager(final AlarmManager am, final Handler alarmHandler) {
1793         doAnswer(inv -> {
1794             final long when = inv.getArgument(1);
1795             final WakeupMessage wakeupMsg = inv.getArgument(3);
1796             final Handler handler = inv.getArgument(4);
1797 
1798             long delayMs = when - SystemClock.elapsedRealtime();
1799             if (delayMs < 0) delayMs = 0;
1800             if (delayMs > UNREASONABLY_LONG_ALARM_WAIT_MS) {
1801                 fail("Attempting to send msg more than " + UNREASONABLY_LONG_ALARM_WAIT_MS
1802                         + "ms into the future: " + delayMs);
1803             }
1804             alarmHandler.postDelayed(() -> handler.post(wakeupMsg::onAlarm), wakeupMsg /* token */,
1805                     delayMs);
1806 
1807             return null;
1808         }).when(am).setExact(eq(AlarmManager.ELAPSED_REALTIME_WAKEUP), anyLong(), anyString(),
1809                 any(WakeupMessage.class), any());
1810 
1811         doAnswer(inv -> {
1812             final WakeupMessage wakeupMsg = inv.getArgument(0);
1813             alarmHandler.removeCallbacksAndMessages(wakeupMsg /* token */);
1814             return null;
1815         }).when(am).cancel(any(WakeupMessage.class));
1816     }
1817 
1818     @After
1819     public void tearDown() throws Exception {
1820         unregisterDefaultNetworkCallbacks();
1821         maybeTearDownEnterpriseNetwork();
1822         setAlwaysOnNetworks(false);
1823         if (mCellNetworkAgent != null) {
1824             mCellNetworkAgent.disconnect();
1825             mCellNetworkAgent = null;
1826         }
1827         if (mWiFiNetworkAgent != null) {
1828             mWiFiNetworkAgent.disconnect();
1829             mWiFiNetworkAgent = null;
1830         }
1831         if (mEthernetNetworkAgent != null) {
1832             mEthernetNetworkAgent.disconnect();
1833             mEthernetNetworkAgent = null;
1834         }
1835 
1836         if (mQosCallbackMockHelper != null) {
1837             mQosCallbackMockHelper.tearDown();
1838             mQosCallbackMockHelper = null;
1839         }
1840         mMockVpn.disconnect();
1841         waitForIdle();
1842 
1843         FakeSettingsProvider.clearSettingsProvider();
1844         ConnectivityResources.setResourcesContextForTest(null);
1845 
1846         mCsHandlerThread.quitSafely();
1847         mAlarmManagerThread.quitSafely();
1848     }
1849 
1850     private void mockDefaultPackages() throws Exception {
1851         final String myPackageName = mContext.getPackageName();
1852         final PackageInfo myPackageInfo = mContext.getPackageManager().getPackageInfo(
1853                 myPackageName, PackageManager.GET_PERMISSIONS);
1854         when(mPackageManager.getPackagesForUid(Binder.getCallingUid())).thenReturn(
1855                 new String[] {myPackageName});
1856         when(mPackageManager.getPackageInfoAsUser(eq(myPackageName), anyInt(),
1857                 eq(UserHandle.getCallingUserId()))).thenReturn(myPackageInfo);
1858 
1859         when(mPackageManager.getInstalledPackages(eq(GET_PERMISSIONS | MATCH_ANY_USER))).thenReturn(
1860                 Arrays.asList(new PackageInfo[] {
1861                         buildPackageInfo(/* SYSTEM */ false, APP1_UID),
1862                         buildPackageInfo(/* SYSTEM */ false, APP2_UID),
1863                         buildPackageInfo(/* SYSTEM */ false, VPN_UID)
1864                 }));
1865 
1866         // Create a fake always-on VPN package.
1867         final int userId = UserHandle.getCallingUserId();
1868         final ApplicationInfo applicationInfo = new ApplicationInfo();
1869         applicationInfo.targetSdkVersion = Build.VERSION_CODES.R;  // Always-on supported in N+.
1870         when(mPackageManager.getApplicationInfoAsUser(eq(ALWAYS_ON_PACKAGE), anyInt(),
1871                 eq(userId))).thenReturn(applicationInfo);
1872 
1873         // Minimal mocking to keep Vpn#isAlwaysOnPackageSupported happy.
1874         ResolveInfo rInfo = new ResolveInfo();
1875         rInfo.serviceInfo = new ServiceInfo();
1876         rInfo.serviceInfo.metaData = new Bundle();
1877         final List<ResolveInfo> services = Arrays.asList(new ResolveInfo[]{rInfo});
1878         when(mPackageManager.queryIntentServicesAsUser(any(), eq(PackageManager.GET_META_DATA),
1879                 eq(userId))).thenReturn(services);
1880         when(mPackageManager.getPackageUidAsUser(TEST_PACKAGE_NAME, userId))
1881                 .thenReturn(Process.myUid());
1882         when(mPackageManager.getPackageUidAsUser(ALWAYS_ON_PACKAGE, userId))
1883                 .thenReturn(VPN_UID);
1884     }
1885 
1886     private void verifyActiveNetwork(int transport) {
1887         // Test getActiveNetworkInfo()
1888         assertNotNull(mCm.getActiveNetworkInfo());
1889         assertEquals(transportToLegacyType(transport), mCm.getActiveNetworkInfo().getType());
1890         // Test getActiveNetwork()
1891         assertNotNull(mCm.getActiveNetwork());
1892         assertEquals(mCm.getActiveNetwork(), mCm.getActiveNetworkForUid(Process.myUid()));
1893         if (!NetworkCapabilities.isValidTransport(transport)) {
1894             throw new IllegalStateException("Unknown transport " + transport);
1895         }
1896         switch (transport) {
1897             case TRANSPORT_WIFI:
1898                 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1899                 break;
1900             case TRANSPORT_CELLULAR:
1901                 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1902                 break;
1903             case TRANSPORT_ETHERNET:
1904                 assertEquals(mEthernetNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1905                 break;
1906             default:
1907                 break;
1908         }
1909         // Test getNetworkInfo(Network)
1910         assertNotNull(mCm.getNetworkInfo(mCm.getActiveNetwork()));
1911         assertEquals(transportToLegacyType(transport),
1912                 mCm.getNetworkInfo(mCm.getActiveNetwork()).getType());
1913         assertNotNull(mCm.getActiveNetworkInfoForUid(Process.myUid()));
1914         // Test getNetworkCapabilities(Network)
1915         assertNotNull(mCm.getNetworkCapabilities(mCm.getActiveNetwork()));
1916         assertTrue(mCm.getNetworkCapabilities(mCm.getActiveNetwork()).hasTransport(transport));
1917     }
1918 
1919     private void verifyNoNetwork() {
1920         waitForIdle();
1921         // Test getActiveNetworkInfo()
1922         assertNull(mCm.getActiveNetworkInfo());
1923         // Test getActiveNetwork()
1924         assertNull(mCm.getActiveNetwork());
1925         assertNull(mCm.getActiveNetworkForUid(Process.myUid()));
1926         // Test getAllNetworks()
1927         assertEmpty(mCm.getAllNetworks());
1928         assertEmpty(mCm.getAllNetworkStateSnapshots());
1929     }
1930 
1931     /**
1932      * Class to simplify expecting broadcasts using BroadcastInterceptingContext.
1933      * Ensures that the receiver is unregistered after the expected broadcast is received. This
1934      * cannot be done in the BroadcastReceiver itself because BroadcastInterceptingContext runs
1935      * the receivers' receive method while iterating over the list of receivers, and unregistering
1936      * the receiver during iteration throws ConcurrentModificationException.
1937      */
1938     private class ExpectedBroadcast extends CompletableFuture<Intent>  {
1939         private final BroadcastReceiver mReceiver;
1940 
1941         ExpectedBroadcast(BroadcastReceiver receiver) {
1942             mReceiver = receiver;
1943         }
1944 
1945         public Intent expectBroadcast(int timeoutMs) throws Exception {
1946             try {
1947                 return get(timeoutMs, TimeUnit.MILLISECONDS);
1948             } catch (TimeoutException e) {
1949                 fail("Expected broadcast not received after " + timeoutMs + " ms");
1950                 return null;
1951             } finally {
1952                 mServiceContext.unregisterReceiver(mReceiver);
1953             }
1954         }
1955 
1956         public Intent expectBroadcast() throws Exception {
1957             return expectBroadcast(BROADCAST_TIMEOUT_MS);
1958         }
1959 
1960         public void expectNoBroadcast(int timeoutMs) throws Exception {
1961             waitForIdle();
1962             try {
1963                 final Intent intent = get(timeoutMs, TimeUnit.MILLISECONDS);
1964                 fail("Unexpected broadcast: " + intent.getAction() + " " + intent.getExtras());
1965             } catch (TimeoutException expected) {
1966             } finally {
1967                 mServiceContext.unregisterReceiver(mReceiver);
1968             }
1969         }
1970     }
1971 
1972     /** Expects that {@code count} CONNECTIVITY_ACTION broadcasts are received. */
1973     private ExpectedBroadcast registerConnectivityBroadcast(final int count) {
1974         return registerConnectivityBroadcastThat(count, intent -> true);
1975     }
1976 
1977     private ExpectedBroadcast registerConnectivityBroadcastThat(final int count,
1978             @NonNull final Predicate<Intent> filter) {
1979         final IntentFilter intentFilter = new IntentFilter(CONNECTIVITY_ACTION);
1980         // AtomicReference allows receiver to access expected even though it is constructed later.
1981         final AtomicReference<ExpectedBroadcast> expectedRef = new AtomicReference<>();
1982         final BroadcastReceiver receiver = new BroadcastReceiver() {
1983             private int mRemaining = count;
1984             public void onReceive(Context context, Intent intent) {
1985                 final int type = intent.getIntExtra(EXTRA_NETWORK_TYPE, -1);
1986                 final NetworkInfo ni = intent.getParcelableExtra(EXTRA_NETWORK_INFO);
1987                 Log.d(TAG, "Received CONNECTIVITY_ACTION type=" + type + " ni=" + ni);
1988                 if (!filter.test(intent)) return;
1989                 if (--mRemaining == 0) {
1990                     expectedRef.get().complete(intent);
1991                 }
1992             }
1993         };
1994         final ExpectedBroadcast expected = new ExpectedBroadcast(receiver);
1995         expectedRef.set(expected);
1996         mServiceContext.registerReceiver(receiver, intentFilter);
1997         return expected;
1998     }
1999 
2000     private boolean extraInfoInBroadcastHasExpectedNullness(NetworkInfo ni) {
2001         final DetailedState state = ni.getDetailedState();
2002         if (state == DetailedState.CONNECTED && ni.getExtraInfo() == null) return false;
2003         // Expect a null extraInfo if the network is CONNECTING, because a CONNECTIVITY_ACTION
2004         // broadcast with a state of CONNECTING only happens due to legacy VPN lockdown, which also
2005         // nulls out extraInfo.
2006         if (state == DetailedState.CONNECTING && ni.getExtraInfo() != null) return false;
2007         // Can't make any assertions about DISCONNECTED broadcasts. When a network actually
2008         // disconnects, disconnectAndDestroyNetwork sets its state to DISCONNECTED and its extraInfo
2009         // to null. But if the DISCONNECTED broadcast is just simulated by LegacyTypeTracker due to
2010         // a network switch, extraInfo will likely be populated.
2011         // This is likely a bug in CS, but likely not one we can fix without impacting apps.
2012         return true;
2013     }
2014 
2015     private ExpectedBroadcast expectConnectivityAction(int type, NetworkInfo.DetailedState state) {
2016         return registerConnectivityBroadcastThat(1, intent -> {
2017             final int actualType = intent.getIntExtra(EXTRA_NETWORK_TYPE, -1);
2018             final NetworkInfo ni = intent.getParcelableExtra(EXTRA_NETWORK_INFO);
2019             return type == actualType
2020                     && state == ni.getDetailedState()
2021                     && extraInfoInBroadcastHasExpectedNullness(ni);
2022         });
2023     }
2024 
2025     @Test
2026     public void testNetworkTypes() {
2027         // Ensure that our mocks for the networkAttributes config variable work as expected. If they
2028         // don't, then tests that depend on CONNECTIVITY_ACTION broadcasts for these network types
2029         // will fail. Failing here is much easier to debug.
2030         assertTrue(mCm.isNetworkSupported(TYPE_WIFI));
2031         assertTrue(mCm.isNetworkSupported(TYPE_MOBILE));
2032         assertTrue(mCm.isNetworkSupported(TYPE_MOBILE_MMS));
2033         assertTrue(mCm.isNetworkSupported(TYPE_MOBILE_FOTA));
2034         assertFalse(mCm.isNetworkSupported(TYPE_PROXY));
2035 
2036         // Check that TYPE_ETHERNET is supported. Unlike the asserts above, which only validate our
2037         // mocks, this assert exercises the ConnectivityService code path that ensures that
2038         // TYPE_ETHERNET is supported if the ethernet service is running.
2039         assertTrue(mCm.isNetworkSupported(TYPE_ETHERNET));
2040     }
2041 
2042     @Test
2043     public void testNetworkFeature() throws Exception {
2044         // Connect the cell agent and wait for the connected broadcast.
2045         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
2046         mCellNetworkAgent.addCapability(NET_CAPABILITY_SUPL);
2047         ExpectedBroadcast b = expectConnectivityAction(TYPE_MOBILE, DetailedState.CONNECTED);
2048         mCellNetworkAgent.connect(true);
2049         b.expectBroadcast();
2050 
2051         // Build legacy request for SUPL.
2052         final NetworkCapabilities legacyCaps = new NetworkCapabilities();
2053         legacyCaps.addTransportType(TRANSPORT_CELLULAR);
2054         legacyCaps.addCapability(NET_CAPABILITY_SUPL);
2055         final NetworkRequest legacyRequest = new NetworkRequest(legacyCaps, TYPE_MOBILE_SUPL,
2056                 ConnectivityManager.REQUEST_ID_UNSET, NetworkRequest.Type.REQUEST);
2057 
2058         // File request, withdraw it and make sure no broadcast is sent
2059         b = registerConnectivityBroadcast(1);
2060         final TestNetworkCallback callback = new TestNetworkCallback();
2061         mCm.requestNetwork(legacyRequest, callback);
2062         callback.expectCallback(CallbackEntry.AVAILABLE, mCellNetworkAgent);
2063         mCm.unregisterNetworkCallback(callback);
2064         b.expectNoBroadcast(800);  // 800ms long enough to at least flake if this is sent
2065 
2066         // Disconnect the network and expect mobile disconnected broadcast.
2067         b = expectConnectivityAction(TYPE_MOBILE, DetailedState.DISCONNECTED);
2068         mCellNetworkAgent.disconnect();
2069         b.expectBroadcast();
2070     }
2071 
2072     @Test
2073     public void testLingering() throws Exception {
2074         verifyNoNetwork();
2075         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
2076         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
2077         assertNull(mCm.getActiveNetworkInfo());
2078         assertNull(mCm.getActiveNetwork());
2079         // Test bringing up validated cellular.
2080         ExpectedBroadcast b = expectConnectivityAction(TYPE_MOBILE, DetailedState.CONNECTED);
2081         mCellNetworkAgent.connect(true);
2082         b.expectBroadcast();
2083         verifyActiveNetwork(TRANSPORT_CELLULAR);
2084         assertLength(2, mCm.getAllNetworks());
2085         assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) ||
2086                 mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork()));
2087         assertTrue(mCm.getAllNetworks()[0].equals(mWiFiNetworkAgent.getNetwork()) ||
2088                 mCm.getAllNetworks()[1].equals(mWiFiNetworkAgent.getNetwork()));
2089         // Test bringing up validated WiFi.
2090         b = registerConnectivityBroadcast(2);
2091         mWiFiNetworkAgent.connect(true);
2092         b.expectBroadcast();
2093         verifyActiveNetwork(TRANSPORT_WIFI);
2094         assertLength(2, mCm.getAllNetworks());
2095         assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) ||
2096                 mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork()));
2097         assertTrue(mCm.getAllNetworks()[0].equals(mCellNetworkAgent.getNetwork()) ||
2098                 mCm.getAllNetworks()[1].equals(mCellNetworkAgent.getNetwork()));
2099         // Test cellular linger timeout.
2100         mCellNetworkAgent.expectDisconnected();
2101         waitForIdle();
2102         assertLength(1, mCm.getAllNetworks());
2103         verifyActiveNetwork(TRANSPORT_WIFI);
2104         assertLength(1, mCm.getAllNetworks());
2105         assertEquals(mCm.getAllNetworks()[0], mCm.getActiveNetwork());
2106         // Test WiFi disconnect.
2107         b = registerConnectivityBroadcast(1);
2108         mWiFiNetworkAgent.disconnect();
2109         b.expectBroadcast();
2110         verifyNoNetwork();
2111     }
2112 
2113     /**
2114      * Verify a newly created network will be inactive instead of torn down even if no one is
2115      * requesting.
2116      */
2117     @Test
2118     public void testNewNetworkInactive() throws Exception {
2119         // Create a callback that monitoring the testing network.
2120         final TestNetworkCallback listenCallback = new TestNetworkCallback();
2121         mCm.registerNetworkCallback(new NetworkRequest.Builder().build(), listenCallback);
2122 
2123         // 1. Create a network that is not requested by anyone, and does not satisfy any of the
2124         // default requests. Verify that the network will be inactive instead of torn down.
2125         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
2126         mWiFiNetworkAgent.connectWithoutInternet();
2127         listenCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2128         listenCallback.assertNoCallback();
2129 
2130         // Verify that the network will be torn down after nascent expiry. A small period of time
2131         // is added in case of flakiness.
2132         final int nascentTimeoutMs =
2133                 mService.mNascentDelayMs + mService.mNascentDelayMs / 4;
2134         listenCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent, nascentTimeoutMs);
2135 
2136         // 2. Create a network that is satisfied by a request comes later.
2137         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
2138         mWiFiNetworkAgent.connectWithoutInternet();
2139         listenCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2140         final NetworkRequest wifiRequest = new NetworkRequest.Builder()
2141                 .addTransportType(TRANSPORT_WIFI).build();
2142         final TestNetworkCallback wifiCallback = new TestNetworkCallback();
2143         mCm.requestNetwork(wifiRequest, wifiCallback);
2144         wifiCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2145 
2146         // Verify that the network will be kept since the request is still satisfied. And is able
2147         // to get disconnected as usual if the request is released after the nascent timer expires.
2148         listenCallback.assertNoCallback(nascentTimeoutMs);
2149         mCm.unregisterNetworkCallback(wifiCallback);
2150         listenCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
2151 
2152         // 3. Create a network that is satisfied by a request comes later.
2153         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
2154         mWiFiNetworkAgent.connectWithoutInternet();
2155         listenCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2156         mCm.requestNetwork(wifiRequest, wifiCallback);
2157         wifiCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2158 
2159         // Verify that the network will still be torn down after the request gets removed.
2160         mCm.unregisterNetworkCallback(wifiCallback);
2161         listenCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
2162 
2163         // There is no need to ensure that LOSING is never sent in the common case that the
2164         // network immediately satisfies a request that was already present, because it is already
2165         // verified anywhere whenever {@code TestNetworkCallback#expectAvailable*} is called.
2166 
2167         mCm.unregisterNetworkCallback(listenCallback);
2168     }
2169 
2170     /**
2171      * Verify a newly created network will be inactive and switch to background if only background
2172      * request is satisfied.
2173      */
2174     @Test
2175     public void testNewNetworkInactive_bgNetwork() throws Exception {
2176         // Create a callback that monitoring the wifi network.
2177         final TestNetworkCallback wifiListenCallback = new TestNetworkCallback();
2178         mCm.registerNetworkCallback(new NetworkRequest.Builder()
2179                 .addTransportType(TRANSPORT_WIFI).build(), wifiListenCallback);
2180 
2181         // Create callbacks that can monitor background and foreground mobile networks.
2182         // This is done by granting using background networks permission before registration. Thus,
2183         // the service will not add {@code NET_CAPABILITY_FOREGROUND} by default.
2184         grantUsingBackgroundNetworksPermissionForUid(Binder.getCallingUid());
2185         final TestNetworkCallback bgMobileListenCallback = new TestNetworkCallback();
2186         final TestNetworkCallback fgMobileListenCallback = new TestNetworkCallback();
2187         mCm.registerNetworkCallback(new NetworkRequest.Builder()
2188                 .addTransportType(TRANSPORT_CELLULAR).build(), bgMobileListenCallback);
2189         mCm.registerNetworkCallback(new NetworkRequest.Builder()
2190                 .addTransportType(TRANSPORT_CELLULAR)
2191                 .addCapability(NET_CAPABILITY_FOREGROUND).build(), fgMobileListenCallback);
2192 
2193         // Connect wifi, which satisfies default request.
2194         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
2195         mWiFiNetworkAgent.connect(true);
2196         wifiListenCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
2197 
2198         // Connect a cellular network, verify that satisfies only the background callback.
2199         setAlwaysOnNetworks(true);
2200         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
2201         mCellNetworkAgent.connect(true);
2202         bgMobileListenCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2203         fgMobileListenCallback.assertNoCallback();
2204         assertFalse(isForegroundNetwork(mCellNetworkAgent));
2205 
2206         mCellNetworkAgent.disconnect();
2207         bgMobileListenCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
2208         fgMobileListenCallback.assertNoCallback();
2209 
2210         mCm.unregisterNetworkCallback(wifiListenCallback);
2211         mCm.unregisterNetworkCallback(bgMobileListenCallback);
2212         mCm.unregisterNetworkCallback(fgMobileListenCallback);
2213     }
2214 
2215     @Test
2216     public void testBinderDeathAfterUnregister() throws Exception {
2217         final NetworkCapabilities caps = new NetworkCapabilities.Builder()
2218                 .addTransportType(TRANSPORT_WIFI)
2219                 .build();
2220         final Handler handler = new Handler(ConnectivityThread.getInstanceLooper());
2221         final Messenger messenger = new Messenger(handler);
2222         final CompletableFuture<Binder.DeathRecipient> deathRecipient = new CompletableFuture<>();
2223         final Binder binder = new Binder() {
2224             private DeathRecipient mDeathRecipient;
2225             @Override
2226             public void linkToDeath(@NonNull final DeathRecipient recipient, final int flags) {
2227                 synchronized (this) {
2228                     mDeathRecipient = recipient;
2229                 }
2230                 super.linkToDeath(recipient, flags);
2231                 deathRecipient.complete(recipient);
2232             }
2233 
2234             @Override
2235             public boolean unlinkToDeath(@NonNull final DeathRecipient recipient, final int flags) {
2236                 synchronized (this) {
2237                     if (null == mDeathRecipient) {
2238                         throw new IllegalStateException();
2239                     }
2240                     mDeathRecipient = null;
2241                 }
2242                 return super.unlinkToDeath(recipient, flags);
2243             }
2244         };
2245         final NetworkRequest request = mService.listenForNetwork(caps, messenger, binder,
2246                 NetworkCallback.FLAG_NONE, mContext.getOpPackageName(),
2247                 mContext.getAttributionTag());
2248         mService.releaseNetworkRequest(request);
2249         deathRecipient.get().binderDied();
2250         // Wait for the release message to be processed.
2251         waitForIdle();
2252     }
2253 
2254     @Test
2255     public void testValidatedCellularOutscoresUnvalidatedWiFi() throws Exception {
2256         // Test bringing up unvalidated WiFi
2257         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
2258         ExpectedBroadcast b = registerConnectivityBroadcast(1);
2259         mWiFiNetworkAgent.connect(false);
2260         b.expectBroadcast();
2261         verifyActiveNetwork(TRANSPORT_WIFI);
2262         // Test bringing up unvalidated cellular
2263         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
2264         mCellNetworkAgent.connect(false);
2265         waitForIdle();
2266         verifyActiveNetwork(TRANSPORT_WIFI);
2267         // Test cellular disconnect.
2268         mCellNetworkAgent.disconnect();
2269         waitForIdle();
2270         verifyActiveNetwork(TRANSPORT_WIFI);
2271         // Test bringing up validated cellular
2272         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
2273         b = registerConnectivityBroadcast(2);
2274         mCellNetworkAgent.connect(true);
2275         b.expectBroadcast();
2276         verifyActiveNetwork(TRANSPORT_CELLULAR);
2277         // Test cellular disconnect.
2278         b = registerConnectivityBroadcast(2);
2279         mCellNetworkAgent.disconnect();
2280         b.expectBroadcast();
2281         verifyActiveNetwork(TRANSPORT_WIFI);
2282         // Test WiFi disconnect.
2283         b = registerConnectivityBroadcast(1);
2284         mWiFiNetworkAgent.disconnect();
2285         b.expectBroadcast();
2286         verifyNoNetwork();
2287     }
2288 
2289     @Test
2290     public void testUnvalidatedWifiOutscoresUnvalidatedCellular() throws Exception {
2291         // Test bringing up unvalidated cellular.
2292         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
2293         ExpectedBroadcast b = registerConnectivityBroadcast(1);
2294         mCellNetworkAgent.connect(false);
2295         b.expectBroadcast();
2296         verifyActiveNetwork(TRANSPORT_CELLULAR);
2297         // Test bringing up unvalidated WiFi.
2298         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
2299         b = registerConnectivityBroadcast(2);
2300         mWiFiNetworkAgent.connect(false);
2301         b.expectBroadcast();
2302         verifyActiveNetwork(TRANSPORT_WIFI);
2303         // Test WiFi disconnect.
2304         b = registerConnectivityBroadcast(2);
2305         mWiFiNetworkAgent.disconnect();
2306         b.expectBroadcast();
2307         verifyActiveNetwork(TRANSPORT_CELLULAR);
2308         // Test cellular disconnect.
2309         b = registerConnectivityBroadcast(1);
2310         mCellNetworkAgent.disconnect();
2311         b.expectBroadcast();
2312         verifyNoNetwork();
2313     }
2314 
2315     @Test
2316     public void testUnlingeringDoesNotValidate() throws Exception {
2317         // Test bringing up unvalidated WiFi.
2318         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
2319         ExpectedBroadcast b = registerConnectivityBroadcast(1);
2320         mWiFiNetworkAgent.connect(false);
2321         b.expectBroadcast();
2322         verifyActiveNetwork(TRANSPORT_WIFI);
2323         assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
2324                 NET_CAPABILITY_VALIDATED));
2325         // Test bringing up validated cellular.
2326         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
2327         b = registerConnectivityBroadcast(2);
2328         mCellNetworkAgent.connect(true);
2329         b.expectBroadcast();
2330         verifyActiveNetwork(TRANSPORT_CELLULAR);
2331         assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
2332                 NET_CAPABILITY_VALIDATED));
2333         // Test cellular disconnect.
2334         b = registerConnectivityBroadcast(2);
2335         mCellNetworkAgent.disconnect();
2336         b.expectBroadcast();
2337         verifyActiveNetwork(TRANSPORT_WIFI);
2338         // Unlingering a network should not cause it to be marked as validated.
2339         assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
2340                 NET_CAPABILITY_VALIDATED));
2341     }
2342 
2343     @Test
2344     public void testCellularOutscoresWeakWifi() throws Exception {
2345         // Test bringing up validated cellular.
2346         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
2347         ExpectedBroadcast b = registerConnectivityBroadcast(1);
2348         mCellNetworkAgent.connect(true);
2349         b.expectBroadcast();
2350         verifyActiveNetwork(TRANSPORT_CELLULAR);
2351         // Test bringing up validated WiFi.
2352         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
2353         b = registerConnectivityBroadcast(2);
2354         mWiFiNetworkAgent.connect(true);
2355         b.expectBroadcast();
2356         verifyActiveNetwork(TRANSPORT_WIFI);
2357         // Test WiFi getting really weak.
2358         b = registerConnectivityBroadcast(2);
2359         mWiFiNetworkAgent.adjustScore(-11);
2360         b.expectBroadcast();
2361         verifyActiveNetwork(TRANSPORT_CELLULAR);
2362         // Test WiFi restoring signal strength.
2363         b = registerConnectivityBroadcast(2);
2364         mWiFiNetworkAgent.adjustScore(11);
2365         b.expectBroadcast();
2366         verifyActiveNetwork(TRANSPORT_WIFI);
2367     }
2368 
2369     @Test
2370     public void testReapingNetwork() throws Exception {
2371         // Test bringing up WiFi without NET_CAPABILITY_INTERNET.
2372         // Expect it to be torn down immediately because it satisfies no requests.
2373         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
2374         mWiFiNetworkAgent.connectWithoutInternet();
2375         mWiFiNetworkAgent.expectDisconnected();
2376         // Test bringing up cellular without NET_CAPABILITY_INTERNET.
2377         // Expect it to be torn down immediately because it satisfies no requests.
2378         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
2379         mCellNetworkAgent.connectWithoutInternet();
2380         mCellNetworkAgent.expectDisconnected();
2381         // Test bringing up validated WiFi.
2382         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
2383         final ExpectedBroadcast b = expectConnectivityAction(TYPE_WIFI, DetailedState.CONNECTED);
2384         mWiFiNetworkAgent.connect(true);
2385         b.expectBroadcast();
2386         verifyActiveNetwork(TRANSPORT_WIFI);
2387         // Test bringing up unvalidated cellular.
2388         // Expect it to be torn down because it could never be the highest scoring network
2389         // satisfying the default request even if it validated.
2390         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
2391         mCellNetworkAgent.connect(false);
2392         mCellNetworkAgent.expectDisconnected();
2393         verifyActiveNetwork(TRANSPORT_WIFI);
2394         mWiFiNetworkAgent.disconnect();
2395         mWiFiNetworkAgent.expectDisconnected();
2396     }
2397 
2398     @Test
2399     public void testCellularFallback() throws Exception {
2400         // Test bringing up validated cellular.
2401         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
2402         ExpectedBroadcast b = registerConnectivityBroadcast(1);
2403         mCellNetworkAgent.connect(true);
2404         b.expectBroadcast();
2405         verifyActiveNetwork(TRANSPORT_CELLULAR);
2406         // Test bringing up validated WiFi.
2407         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
2408         b = registerConnectivityBroadcast(2);
2409         mWiFiNetworkAgent.connect(true);
2410         b.expectBroadcast();
2411         verifyActiveNetwork(TRANSPORT_WIFI);
2412         // Reevaluate WiFi (it'll instantly fail DNS).
2413         b = registerConnectivityBroadcast(2);
2414         assertTrue(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
2415                 NET_CAPABILITY_VALIDATED));
2416         mCm.reportBadNetwork(mWiFiNetworkAgent.getNetwork());
2417         // Should quickly fall back to Cellular.
2418         b.expectBroadcast();
2419         assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
2420                 NET_CAPABILITY_VALIDATED));
2421         verifyActiveNetwork(TRANSPORT_CELLULAR);
2422         // Reevaluate cellular (it'll instantly fail DNS).
2423         b = registerConnectivityBroadcast(2);
2424         assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
2425                 NET_CAPABILITY_VALIDATED));
2426         mCm.reportBadNetwork(mCellNetworkAgent.getNetwork());
2427         // Should quickly fall back to WiFi.
2428         b.expectBroadcast();
2429         assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
2430                 NET_CAPABILITY_VALIDATED));
2431         assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
2432                 NET_CAPABILITY_VALIDATED));
2433         verifyActiveNetwork(TRANSPORT_WIFI);
2434     }
2435 
2436     @Test
2437     public void testWiFiFallback() throws Exception {
2438         // Test bringing up unvalidated WiFi.
2439         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
2440         ExpectedBroadcast b = registerConnectivityBroadcast(1);
2441         mWiFiNetworkAgent.connect(false);
2442         b.expectBroadcast();
2443         verifyActiveNetwork(TRANSPORT_WIFI);
2444         // Test bringing up validated cellular.
2445         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
2446         b = registerConnectivityBroadcast(2);
2447         mCellNetworkAgent.connect(true);
2448         b.expectBroadcast();
2449         verifyActiveNetwork(TRANSPORT_CELLULAR);
2450         // Reevaluate cellular (it'll instantly fail DNS).
2451         b = registerConnectivityBroadcast(2);
2452         assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
2453                 NET_CAPABILITY_VALIDATED));
2454         mCm.reportBadNetwork(mCellNetworkAgent.getNetwork());
2455         // Should quickly fall back to WiFi.
2456         b.expectBroadcast();
2457         assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
2458                 NET_CAPABILITY_VALIDATED));
2459         verifyActiveNetwork(TRANSPORT_WIFI);
2460     }
2461 
2462     @Test
2463     public void testRequiresValidation() {
2464         assertTrue(NetworkMonitorUtils.isValidationRequired(
2465                 mCm.getDefaultRequest().networkCapabilities));
2466     }
2467 
2468     /**
2469      * Utility NetworkCallback for testing. The caller must explicitly test for all the callbacks
2470      * this class receives, by calling expectCallback() exactly once each time a callback is
2471      * received. assertNoCallback may be called at any time.
2472      */
2473     private class TestNetworkCallback extends TestableNetworkCallback {
2474         TestNetworkCallback() {
2475             super(TEST_CALLBACK_TIMEOUT_MS);
2476         }
2477 
2478         @Override
2479         public void assertNoCallback() {
2480             // TODO: better support this use case in TestableNetworkCallback
2481             waitForIdle();
2482             assertNoCallback(0 /* timeout */);
2483         }
2484 
2485         @Override
2486         public <T extends CallbackEntry> T expectCallback(final KClass<T> type, final HasNetwork n,
2487                 final long timeoutMs) {
2488             final T callback = super.expectCallback(type, n, timeoutMs);
2489             if (callback instanceof CallbackEntry.Losing) {
2490                 // TODO : move this to the specific test(s) needing this rather than here.
2491                 final CallbackEntry.Losing losing = (CallbackEntry.Losing) callback;
2492                 final int maxMsToLive = losing.getMaxMsToLive();
2493                 String msg = String.format(
2494                         "Invalid linger time value %d, must be between %d and %d",
2495                         maxMsToLive, 0, mService.mLingerDelayMs);
2496                 assertTrue(msg, 0 <= maxMsToLive && maxMsToLive <= mService.mLingerDelayMs);
2497             }
2498             return callback;
2499         }
2500     }
2501 
2502     // Can't be part of TestNetworkCallback because "cannot be declared static; static methods can
2503     // only be declared in a static or top level type".
2504     static void assertNoCallbacks(TestNetworkCallback ... callbacks) {
2505         for (TestNetworkCallback c : callbacks) {
2506             c.assertNoCallback();
2507         }
2508     }
2509 
2510     static void expectOnLost(TestNetworkAgentWrapper network, TestNetworkCallback ... callbacks) {
2511         for (TestNetworkCallback c : callbacks) {
2512             c.expectCallback(CallbackEntry.LOST, network);
2513         }
2514     }
2515 
2516     static void expectAvailableCallbacksUnvalidatedWithSpecifier(TestNetworkAgentWrapper network,
2517             NetworkSpecifier specifier, TestNetworkCallback ... callbacks) {
2518         for (TestNetworkCallback c : callbacks) {
2519             c.expectCallback(CallbackEntry.AVAILABLE, network);
2520             c.expectCapabilitiesThat(network, (nc) ->
2521                     !nc.hasCapability(NET_CAPABILITY_VALIDATED)
2522                             && Objects.equals(specifier, nc.getNetworkSpecifier()));
2523             c.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, network);
2524             c.expectCallback(CallbackEntry.BLOCKED_STATUS, network);
2525         }
2526     }
2527 
2528     @Test
2529     public void testStateChangeNetworkCallbacks() throws Exception {
2530         final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback();
2531         final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
2532         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
2533         final NetworkRequest genericRequest = new NetworkRequest.Builder()
2534                 .clearCapabilities().build();
2535         final NetworkRequest wifiRequest = new NetworkRequest.Builder()
2536                 .addTransportType(TRANSPORT_WIFI).build();
2537         final NetworkRequest cellRequest = new NetworkRequest.Builder()
2538                 .addTransportType(TRANSPORT_CELLULAR).build();
2539         mCm.registerNetworkCallback(genericRequest, genericNetworkCallback);
2540         mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
2541         mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
2542 
2543         // Test unvalidated networks
2544         ExpectedBroadcast b = registerConnectivityBroadcast(1);
2545         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
2546         mCellNetworkAgent.connect(false);
2547         genericNetworkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
2548         cellNetworkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
2549         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2550         b.expectBroadcast();
2551         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
2552 
2553         // This should not trigger spurious onAvailable() callbacks, b/21762680.
2554         mCellNetworkAgent.adjustScore(-1);
2555         waitForIdle();
2556         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
2557         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2558 
2559         b = registerConnectivityBroadcast(2);
2560         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
2561         mWiFiNetworkAgent.connect(false);
2562         genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2563         wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2564         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2565         b.expectBroadcast();
2566         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
2567 
2568         b = registerConnectivityBroadcast(2);
2569         mWiFiNetworkAgent.disconnect();
2570         genericNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
2571         wifiNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
2572         cellNetworkCallback.assertNoCallback();
2573         b.expectBroadcast();
2574         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
2575 
2576         b = registerConnectivityBroadcast(1);
2577         mCellNetworkAgent.disconnect();
2578         genericNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
2579         cellNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
2580         b.expectBroadcast();
2581         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
2582 
2583         // Test validated networks
2584         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
2585         mCellNetworkAgent.connect(true);
2586         genericNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2587         cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2588         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2589         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
2590 
2591         // This should not trigger spurious onAvailable() callbacks, b/21762680.
2592         mCellNetworkAgent.adjustScore(-1);
2593         waitForIdle();
2594         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
2595         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2596 
2597         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
2598         mWiFiNetworkAgent.connect(true);
2599         genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2600         genericNetworkCallback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
2601         genericNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
2602         wifiNetworkCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
2603         cellNetworkCallback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
2604         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2605         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
2606 
2607         mWiFiNetworkAgent.disconnect();
2608         genericNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
2609         wifiNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
2610         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
2611 
2612         mCellNetworkAgent.disconnect();
2613         genericNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
2614         cellNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
2615         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
2616     }
2617 
2618     private void doNetworkCallbacksSanitizationTest(boolean sanitized) throws Exception {
2619         final TestNetworkCallback callback = new TestNetworkCallback();
2620         final TestNetworkCallback defaultCallback = new TestNetworkCallback();
2621         final NetworkRequest wifiRequest = new NetworkRequest.Builder()
2622                 .addTransportType(TRANSPORT_WIFI).build();
2623         mCm.registerNetworkCallback(wifiRequest, callback);
2624         mCm.registerDefaultNetworkCallback(defaultCallback);
2625 
2626         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
2627         mWiFiNetworkAgent.connect(false);
2628         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2629         defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2630 
2631         final LinkProperties newLp = new LinkProperties();
2632         final Uri capportUrl = Uri.parse("https://capport.example.com/api");
2633         final CaptivePortalData capportData = new CaptivePortalData.Builder()
2634                 .setCaptive(true).build();
2635 
2636         final Uri expectedCapportUrl = sanitized ? null : capportUrl;
2637         newLp.setCaptivePortalApiUrl(capportUrl);
2638         mWiFiNetworkAgent.sendLinkProperties(newLp);
2639         callback.expectLinkPropertiesThat(mWiFiNetworkAgent, lp ->
2640                 Objects.equals(expectedCapportUrl, lp.getCaptivePortalApiUrl()));
2641         defaultCallback.expectLinkPropertiesThat(mWiFiNetworkAgent, lp ->
2642                 Objects.equals(expectedCapportUrl, lp.getCaptivePortalApiUrl()));
2643 
2644         final CaptivePortalData expectedCapportData = sanitized ? null : capportData;
2645         mWiFiNetworkAgent.notifyCapportApiDataChanged(capportData);
2646         callback.expectLinkPropertiesThat(mWiFiNetworkAgent, lp ->
2647                 Objects.equals(expectedCapportData, lp.getCaptivePortalData()));
2648         defaultCallback.expectLinkPropertiesThat(mWiFiNetworkAgent, lp ->
2649                 Objects.equals(expectedCapportData, lp.getCaptivePortalData()));
2650 
2651         final LinkProperties lp = mCm.getLinkProperties(mWiFiNetworkAgent.getNetwork());
2652         assertEquals(expectedCapportUrl, lp.getCaptivePortalApiUrl());
2653         assertEquals(expectedCapportData, lp.getCaptivePortalData());
2654     }
2655 
2656     @Test
2657     public void networkCallbacksSanitizationTest_Sanitize() throws Exception {
2658         mServiceContext.setPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
2659                 PERMISSION_DENIED);
2660         mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_DENIED);
2661         doNetworkCallbacksSanitizationTest(true /* sanitized */);
2662     }
2663 
2664     @Test
2665     public void networkCallbacksSanitizationTest_NoSanitize_NetworkStack() throws Exception {
2666         mServiceContext.setPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
2667                 PERMISSION_GRANTED);
2668         mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_DENIED);
2669         doNetworkCallbacksSanitizationTest(false /* sanitized */);
2670     }
2671 
2672     @Test
2673     public void networkCallbacksSanitizationTest_NoSanitize_Settings() throws Exception {
2674         mServiceContext.setPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
2675                 PERMISSION_DENIED);
2676         mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_GRANTED);
2677         doNetworkCallbacksSanitizationTest(false /* sanitized */);
2678     }
2679 
2680     @Test
2681     public void testOwnerUidCannotChange() throws Exception {
2682         final NetworkCapabilities ncTemplate = new NetworkCapabilities();
2683         final int originalOwnerUid = Process.myUid();
2684         ncTemplate.setOwnerUid(originalOwnerUid);
2685 
2686         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, new LinkProperties(),
2687                 ncTemplate);
2688         mWiFiNetworkAgent.connect(false);
2689         waitForIdle();
2690 
2691         // Send ConnectivityService an update to the mWiFiNetworkAgent's capabilities that changes
2692         // the owner UID and an unrelated capability.
2693         NetworkCapabilities agentCapabilities = mWiFiNetworkAgent.getNetworkCapabilities();
2694         assertEquals(originalOwnerUid, agentCapabilities.getOwnerUid());
2695         agentCapabilities.setOwnerUid(42);
2696         assertFalse(agentCapabilities.hasCapability(NET_CAPABILITY_NOT_CONGESTED));
2697         agentCapabilities.addCapability(NET_CAPABILITY_NOT_CONGESTED);
2698         mWiFiNetworkAgent.setNetworkCapabilities(agentCapabilities, true);
2699         waitForIdle();
2700 
2701         // Owner UIDs are not visible without location permission.
2702         setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
2703                 Manifest.permission.ACCESS_FINE_LOCATION);
2704 
2705         // Check that the capability change has been applied but the owner UID is not modified.
2706         NetworkCapabilities nc = mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork());
2707         assertEquals(originalOwnerUid, nc.getOwnerUid());
2708         assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_CONGESTED));
2709     }
2710 
2711     @Test
2712     public void testMultipleLingering() throws Exception {
2713         // This test would be flaky with the default 120ms timer: that is short enough that
2714         // lingered networks are torn down before assertions can be run. We don't want to mock the
2715         // lingering timer to keep the WakeupMessage logic realistic: this has already proven useful
2716         // in detecting races.
2717         mService.mLingerDelayMs = 300;
2718 
2719         NetworkRequest request = new NetworkRequest.Builder()
2720                 .clearCapabilities().addCapability(NET_CAPABILITY_NOT_METERED)
2721                 .build();
2722         TestNetworkCallback callback = new TestNetworkCallback();
2723         mCm.registerNetworkCallback(request, callback);
2724 
2725         TestNetworkCallback defaultCallback = new TestNetworkCallback();
2726         mCm.registerDefaultNetworkCallback(defaultCallback);
2727 
2728         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
2729         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
2730         mEthernetNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
2731 
2732         mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
2733         mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
2734         mEthernetNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
2735 
2736         mCellNetworkAgent.connect(true);
2737         callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2738         defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2739         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2740         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
2741 
2742         mWiFiNetworkAgent.connect(true);
2743         // We get AVAILABLE on wifi when wifi connects and satisfies our unmetered request.
2744         // We then get LOSING when wifi validates and cell is outscored.
2745         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2746         // TODO: Investigate sending validated before losing.
2747         callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
2748         callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
2749         defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
2750         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2751         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
2752 
2753         mEthernetNetworkAgent.connect(true);
2754         callback.expectAvailableCallbacksUnvalidated(mEthernetNetworkAgent);
2755         // TODO: Investigate sending validated before losing.
2756         callback.expectCallback(CallbackEntry.LOSING, mWiFiNetworkAgent);
2757         callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mEthernetNetworkAgent);
2758         defaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent);
2759         assertEquals(mEthernetNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2760         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
2761 
2762         mEthernetNetworkAgent.disconnect();
2763         callback.expectCallback(CallbackEntry.LOST, mEthernetNetworkAgent);
2764         defaultCallback.expectCallback(CallbackEntry.LOST, mEthernetNetworkAgent);
2765         defaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
2766         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
2767 
2768         for (int i = 0; i < 4; i++) {
2769             TestNetworkAgentWrapper oldNetwork, newNetwork;
2770             if (i % 2 == 0) {
2771                 mWiFiNetworkAgent.adjustScore(-15);
2772                 oldNetwork = mWiFiNetworkAgent;
2773                 newNetwork = mCellNetworkAgent;
2774             } else {
2775                 mWiFiNetworkAgent.adjustScore(15);
2776                 oldNetwork = mCellNetworkAgent;
2777                 newNetwork = mWiFiNetworkAgent;
2778 
2779             }
2780             callback.expectCallback(CallbackEntry.LOSING, oldNetwork);
2781             // TODO: should we send an AVAILABLE callback to newNetwork, to indicate that it is no
2782             // longer lingering?
2783             defaultCallback.expectAvailableCallbacksValidated(newNetwork);
2784             assertEquals(newNetwork.getNetwork(), mCm.getActiveNetwork());
2785         }
2786         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2787 
2788         // Verify that if a network no longer satisfies a request, we send LOST and not LOSING, even
2789         // if the network is still up.
2790         mWiFiNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
2791         // We expect a notification about the capabilities change, and nothing else.
2792         defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_METERED, mWiFiNetworkAgent);
2793         defaultCallback.assertNoCallback();
2794         callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
2795         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
2796 
2797         // Wifi no longer satisfies our listen, which is for an unmetered network.
2798         // But because its score is 55, it's still up (and the default network).
2799         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2800 
2801         // Disconnect our test networks.
2802         mWiFiNetworkAgent.disconnect();
2803         defaultCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
2804         defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
2805         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
2806         mCellNetworkAgent.disconnect();
2807         defaultCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
2808         waitForIdle();
2809         assertEquals(null, mCm.getActiveNetwork());
2810 
2811         mCm.unregisterNetworkCallback(callback);
2812         waitForIdle();
2813 
2814         // Check that a network is only lingered or torn down if it would not satisfy a request even
2815         // if it validated.
2816         request = new NetworkRequest.Builder().clearCapabilities().build();
2817         callback = new TestNetworkCallback();
2818 
2819         mCm.registerNetworkCallback(request, callback);
2820 
2821         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
2822         mCellNetworkAgent.connect(false);   // Score: 10
2823         callback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
2824         defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
2825         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2826         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
2827 
2828         // Bring up wifi with a score of 20.
2829         // Cell stays up because it would satisfy the default request if it validated.
2830         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
2831         mWiFiNetworkAgent.connect(false);   // Score: 20
2832         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2833         defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2834         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2835         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
2836 
2837         mWiFiNetworkAgent.disconnect();
2838         callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
2839         defaultCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
2840         defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
2841         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2842         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
2843 
2844         // Bring up wifi, then validate it. Previous versions would immediately tear down cell, but
2845         // it's arguably correct to linger it, since it was the default network before it validated.
2846         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
2847         mWiFiNetworkAgent.connect(true);
2848         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2849         // TODO: Investigate sending validated before losing.
2850         callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
2851         callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
2852         defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
2853         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2854         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
2855 
2856         mWiFiNetworkAgent.disconnect();
2857         callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
2858         defaultCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
2859         defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
2860         mCellNetworkAgent.disconnect();
2861         callback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
2862         defaultCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
2863         waitForIdle();
2864         assertEquals(null, mCm.getActiveNetwork());
2865 
2866         // If a network is lingering, and we add and remove a request from it, resume lingering.
2867         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
2868         mCellNetworkAgent.connect(true);
2869         callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2870         defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2871         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
2872         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
2873         mWiFiNetworkAgent.connect(true);
2874         defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
2875         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2876         // TODO: Investigate sending validated before losing.
2877         callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
2878         callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
2879         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
2880 
2881         NetworkRequest cellRequest = new NetworkRequest.Builder()
2882                 .addTransportType(TRANSPORT_CELLULAR).build();
2883         NetworkCallback noopCallback = new NetworkCallback();
2884         mCm.requestNetwork(cellRequest, noopCallback);
2885         // TODO: should this cause an AVAILABLE callback, to indicate that the network is no longer
2886         // lingering?
2887         mCm.unregisterNetworkCallback(noopCallback);
2888         callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
2889 
2890         // Similar to the above: lingering can start even after the lingered request is removed.
2891         // Disconnect wifi and switch to cell.
2892         mWiFiNetworkAgent.disconnect();
2893         callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
2894         defaultCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
2895         defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
2896         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
2897 
2898         // Cell is now the default network. Pin it with a cell-specific request.
2899         noopCallback = new NetworkCallback();  // Can't reuse NetworkCallbacks. http://b/20701525
2900         mCm.requestNetwork(cellRequest, noopCallback);
2901 
2902         // Now connect wifi, and expect it to become the default network.
2903         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
2904         mWiFiNetworkAgent.connect(true);
2905         callback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
2906         defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
2907         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
2908         // The default request is lingering on cell, but nothing happens to cell, and we send no
2909         // callbacks for it, because it's kept up by cellRequest.
2910         callback.assertNoCallback();
2911         // Now unregister cellRequest and expect cell to start lingering.
2912         mCm.unregisterNetworkCallback(noopCallback);
2913         callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
2914 
2915         // Let linger run its course.
2916         callback.assertNoCallback();
2917         final int lingerTimeoutMs = mService.mLingerDelayMs + mService.mLingerDelayMs / 4;
2918         callback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent, lingerTimeoutMs);
2919 
2920         // Register a TRACK_DEFAULT request and check that it does not affect lingering.
2921         TestNetworkCallback trackDefaultCallback = new TestNetworkCallback();
2922         mCm.registerDefaultNetworkCallback(trackDefaultCallback);
2923         trackDefaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
2924         mEthernetNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
2925         mEthernetNetworkAgent.connect(true);
2926         callback.expectAvailableCallbacksUnvalidated(mEthernetNetworkAgent);
2927         callback.expectCallback(CallbackEntry.LOSING, mWiFiNetworkAgent);
2928         callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mEthernetNetworkAgent);
2929         trackDefaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent);
2930         defaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent);
2931         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
2932 
2933         // Let linger run its course.
2934         callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent, lingerTimeoutMs);
2935 
2936         // Clean up.
2937         mEthernetNetworkAgent.disconnect();
2938         callback.expectCallback(CallbackEntry.LOST, mEthernetNetworkAgent);
2939         defaultCallback.expectCallback(CallbackEntry.LOST, mEthernetNetworkAgent);
2940         trackDefaultCallback.expectCallback(CallbackEntry.LOST, mEthernetNetworkAgent);
2941 
2942         mCm.unregisterNetworkCallback(callback);
2943         mCm.unregisterNetworkCallback(defaultCallback);
2944         mCm.unregisterNetworkCallback(trackDefaultCallback);
2945     }
2946 
2947     private void grantUsingBackgroundNetworksPermissionForUid(final int uid) throws Exception {
2948         grantUsingBackgroundNetworksPermissionForUid(uid, mContext.getPackageName());
2949     }
2950 
2951     private void grantUsingBackgroundNetworksPermissionForUid(
2952             final int uid, final String packageName) throws Exception {
2953         when(mPackageManager.getPackageInfo(
2954                 eq(packageName), eq(GET_PERMISSIONS | MATCH_ANY_USER)))
2955                 .thenReturn(buildPackageInfo(true /* hasSystemPermission */, uid));
2956         mService.mPermissionMonitor.onPackageAdded(packageName, uid);
2957     }
2958 
2959     @Test
2960     public void testNetworkGoesIntoBackgroundAfterLinger() throws Exception {
2961         setAlwaysOnNetworks(true);
2962         grantUsingBackgroundNetworksPermissionForUid(Binder.getCallingUid());
2963         NetworkRequest request = new NetworkRequest.Builder()
2964                 .clearCapabilities()
2965                 .build();
2966         TestNetworkCallback callback = new TestNetworkCallback();
2967         mCm.registerNetworkCallback(request, callback);
2968 
2969         TestNetworkCallback defaultCallback = new TestNetworkCallback();
2970         mCm.registerDefaultNetworkCallback(defaultCallback);
2971 
2972         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
2973         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
2974 
2975         mCellNetworkAgent.connect(true);
2976         callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2977         defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2978 
2979         // Wifi comes up and cell lingers.
2980         mWiFiNetworkAgent.connect(true);
2981         defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
2982         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2983         callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
2984         callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
2985 
2986         // File a request for cellular, then release it.
2987         NetworkRequest cellRequest = new NetworkRequest.Builder()
2988                 .addTransportType(TRANSPORT_CELLULAR).build();
2989         NetworkCallback noopCallback = new NetworkCallback();
2990         mCm.requestNetwork(cellRequest, noopCallback);
2991         mCm.unregisterNetworkCallback(noopCallback);
2992         callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
2993 
2994         // Let linger run its course.
2995         callback.assertNoCallback();
2996         final int lingerTimeoutMs = TEST_LINGER_DELAY_MS + TEST_LINGER_DELAY_MS / 4;
2997         callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent,
2998                 lingerTimeoutMs);
2999 
3000         // Clean up.
3001         mCm.unregisterNetworkCallback(defaultCallback);
3002         mCm.unregisterNetworkCallback(callback);
3003     }
3004 
3005     private NativeNetworkConfig nativeNetworkConfigPhysical(int netId, int permission) {
3006         return new NativeNetworkConfig(netId, NativeNetworkType.PHYSICAL, permission,
3007                 /*secure=*/ false, VpnManager.TYPE_VPN_NONE);
3008     }
3009 
3010     private NativeNetworkConfig nativeNetworkConfigVpn(int netId, boolean secure, int vpnType) {
3011         return new NativeNetworkConfig(netId, NativeNetworkType.VIRTUAL, INetd.PERMISSION_NONE,
3012                 secure, vpnType);
3013     }
3014 
3015     @Test
3016     public void testNetworkAgentCallbacks() throws Exception {
3017         // Keeps track of the order of events that happen in this test.
3018         final LinkedBlockingQueue<String> eventOrder = new LinkedBlockingQueue<>();
3019 
3020         final NetworkRequest request = new NetworkRequest.Builder()
3021                 .addTransportType(TRANSPORT_WIFI).build();
3022         final TestNetworkCallback callback = new TestNetworkCallback();
3023         final AtomicReference<Network> wifiNetwork = new AtomicReference<>();
3024         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3025 
3026         // Expectations for state when various callbacks fire. These expectations run on the handler
3027         // thread and not on the test thread because they need to prevent the handler thread from
3028         // advancing while they examine state.
3029 
3030         // 1. When onCreated fires, netd has been told to create the network.
3031         mWiFiNetworkAgent.setCreatedCallback(() -> {
3032             eventOrder.offer("onNetworkCreated");
3033             wifiNetwork.set(mWiFiNetworkAgent.getNetwork());
3034             assertNotNull(wifiNetwork.get());
3035             try {
3036                 verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
3037                         wifiNetwork.get().getNetId(), INetd.PERMISSION_NONE));
3038             } catch (RemoteException impossible) {
3039                 fail();
3040             }
3041         });
3042 
3043         // 2. onNetworkUnwanted isn't precisely ordered with respect to any particular events. Just
3044         //    check that it is fired at some point after disconnect.
3045         mWiFiNetworkAgent.setUnwantedCallback(() -> eventOrder.offer("onNetworkUnwanted"));
3046 
3047         // 3. While the teardown timer is running, connectivity APIs report the network is gone, but
3048         //    netd has not yet been told to destroy it.
3049         final Runnable duringTeardown = () -> {
3050             eventOrder.offer("timePasses");
3051             assertNull(mCm.getLinkProperties(wifiNetwork.get()));
3052             try {
3053                 verify(mMockNetd, never()).networkDestroy(wifiNetwork.get().getNetId());
3054             } catch (RemoteException impossible) {
3055                 fail();
3056             }
3057         };
3058 
3059         // 4. After onNetworkDisconnected is called, connectivity APIs report the network is gone,
3060         // and netd has been told to destroy it.
3061         mWiFiNetworkAgent.setDisconnectedCallback(() -> {
3062             eventOrder.offer("onNetworkDisconnected");
3063             assertNull(mCm.getLinkProperties(wifiNetwork.get()));
3064             try {
3065                 verify(mMockNetd).networkDestroy(wifiNetwork.get().getNetId());
3066             } catch (RemoteException impossible) {
3067                 fail();
3068             }
3069         });
3070 
3071         // Connect a network, and file a request for it after it has come up, to ensure the nascent
3072         // timer is cleared and the test does not have to wait for it. Filing the request after the
3073         // network has come up is necessary because ConnectivityService does not appear to clear the
3074         // nascent timer if the first request satisfied by the network was filed before the network
3075         // connected.
3076         // TODO: fix this bug, file the request before connecting, and remove the waitForIdle.
3077         mWiFiNetworkAgent.connectWithoutInternet();
3078         waitForIdle();
3079         mCm.requestNetwork(request, callback);
3080         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
3081 
3082         // Set teardown delay and make sure CS has processed it.
3083         mWiFiNetworkAgent.getNetworkAgent().setTeardownDelayMillis(300);
3084         waitForIdle();
3085 
3086         // Post the duringTeardown lambda to the handler so it fires while teardown is in progress.
3087         // The delay must be long enough it will run after the unregisterNetworkCallback has torn
3088         // down the network and started the teardown timer, and short enough that the lambda is
3089         // scheduled to run before the teardown timer.
3090         final Handler h = new Handler(mCsHandlerThread.getLooper());
3091         h.postDelayed(duringTeardown, 150);
3092 
3093         // Disconnect the network and check that events happened in the right order.
3094         mCm.unregisterNetworkCallback(callback);
3095         assertEquals("onNetworkCreated", eventOrder.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
3096         assertEquals("onNetworkUnwanted", eventOrder.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
3097         assertEquals("timePasses", eventOrder.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
3098         assertEquals("onNetworkDisconnected", eventOrder.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
3099 
3100         mCm.unregisterNetworkCallback(callback);
3101     }
3102 
3103     @Test
3104     public void testExplicitlySelected() throws Exception {
3105         NetworkRequest request = new NetworkRequest.Builder()
3106                 .clearCapabilities().addCapability(NET_CAPABILITY_INTERNET)
3107                 .build();
3108         TestNetworkCallback callback = new TestNetworkCallback();
3109         mCm.registerNetworkCallback(request, callback);
3110 
3111         // Bring up validated cell.
3112         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
3113         mCellNetworkAgent.connect(true);
3114         callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
3115 
3116         // Bring up unvalidated wifi with explicitlySelected=true.
3117         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3118         mWiFiNetworkAgent.explicitlySelected(true, false);
3119         mWiFiNetworkAgent.connect(false);
3120         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
3121 
3122         // Cell Remains the default.
3123         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
3124 
3125         // Lower wifi's score to below than cell, and check that it doesn't disconnect because
3126         // it's explicitly selected.
3127         mWiFiNetworkAgent.adjustScore(-40);
3128         mWiFiNetworkAgent.adjustScore(40);
3129         callback.assertNoCallback();
3130 
3131         // If the user chooses yes on the "No Internet access, stay connected?" dialog, we switch to
3132         // wifi even though it's unvalidated.
3133         mCm.setAcceptUnvalidated(mWiFiNetworkAgent.getNetwork(), true, false);
3134         callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
3135         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
3136 
3137         // Disconnect wifi, and then reconnect, again with explicitlySelected=true.
3138         mWiFiNetworkAgent.disconnect();
3139         callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
3140         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3141         mWiFiNetworkAgent.explicitlySelected(true, false);
3142         mWiFiNetworkAgent.connect(false);
3143         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
3144 
3145         // If the user chooses no on the "No Internet access, stay connected?" dialog, we ask the
3146         // network to disconnect.
3147         mCm.setAcceptUnvalidated(mWiFiNetworkAgent.getNetwork(), false, false);
3148         callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
3149 
3150         // Reconnect, again with explicitlySelected=true, but this time validate.
3151         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3152         mWiFiNetworkAgent.explicitlySelected(true, false);
3153         mWiFiNetworkAgent.connect(true);
3154         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
3155         callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
3156         callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
3157         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
3158 
3159         mEthernetNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
3160         mEthernetNetworkAgent.connect(true);
3161         callback.expectAvailableCallbacksUnvalidated(mEthernetNetworkAgent);
3162         callback.expectCallback(CallbackEntry.LOSING, mWiFiNetworkAgent);
3163         callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mEthernetNetworkAgent);
3164         assertEquals(mEthernetNetworkAgent.getNetwork(), mCm.getActiveNetwork());
3165         callback.assertNoCallback();
3166 
3167         // Disconnect wifi, and then reconnect as if the user had selected "yes, don't ask again"
3168         // (i.e., with explicitlySelected=true and acceptUnvalidated=true). Expect to switch to
3169         // wifi immediately.
3170         mWiFiNetworkAgent.disconnect();
3171         callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
3172         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3173         mWiFiNetworkAgent.explicitlySelected(true, true);
3174         mWiFiNetworkAgent.connect(false);
3175         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
3176         callback.expectCallback(CallbackEntry.LOSING, mEthernetNetworkAgent);
3177         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
3178         mEthernetNetworkAgent.disconnect();
3179         callback.expectCallback(CallbackEntry.LOST, mEthernetNetworkAgent);
3180 
3181         // Disconnect and reconnect with explicitlySelected=false and acceptUnvalidated=true.
3182         // Check that the network is not scored specially and that the device prefers cell data.
3183         mWiFiNetworkAgent.disconnect();
3184         callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
3185         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3186         mWiFiNetworkAgent.explicitlySelected(false, true);
3187         mWiFiNetworkAgent.connect(false);
3188         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
3189         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
3190 
3191         // Clean up.
3192         mWiFiNetworkAgent.disconnect();
3193         mCellNetworkAgent.disconnect();
3194 
3195         callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
3196         callback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
3197     }
3198 
3199     private void tryNetworkFactoryRequests(int capability) throws Exception {
3200         // Verify NOT_RESTRICTED is set appropriately
3201         final NetworkCapabilities nc = new NetworkRequest.Builder().addCapability(capability)
3202                 .build().networkCapabilities;
3203         if (capability == NET_CAPABILITY_CBS || capability == NET_CAPABILITY_DUN
3204                 || capability == NET_CAPABILITY_EIMS || capability == NET_CAPABILITY_FOTA
3205                 || capability == NET_CAPABILITY_IA || capability == NET_CAPABILITY_IMS
3206                 || capability == NET_CAPABILITY_RCS || capability == NET_CAPABILITY_XCAP
3207                 || capability == NET_CAPABILITY_VSIM || capability == NET_CAPABILITY_BIP
3208                 || capability == NET_CAPABILITY_ENTERPRISE) {
3209             assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
3210         } else {
3211             assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
3212         }
3213 
3214         NetworkCapabilities filter = new NetworkCapabilities();
3215         filter.addTransportType(TRANSPORT_CELLULAR);
3216         filter.addCapability(capability);
3217         // Add NOT_VCN_MANAGED capability into filter unconditionally since some requests will add
3218         // NOT_VCN_MANAGED automatically but not for NetworkCapabilities,
3219         // see {@code NetworkCapabilities#deduceNotVcnManagedCapability} for more details.
3220         filter.addCapability(NET_CAPABILITY_NOT_VCN_MANAGED);
3221         final HandlerThread handlerThread = new HandlerThread("testNetworkFactoryRequests");
3222         handlerThread.start();
3223         final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
3224                 mServiceContext, "testFactory", filter, mCsHandlerThread);
3225         testFactory.setScoreFilter(45);
3226         testFactory.register();
3227 
3228         final NetworkCallback networkCallback;
3229         if (capability != NET_CAPABILITY_INTERNET) {
3230             // If the capability passed in argument is part of the default request, then the
3231             // factory will see the default request. Otherwise the filter will prevent the
3232             // factory from seeing it. In that case, add a request so it can be tested.
3233             assertFalse(testFactory.getMyStartRequested());
3234             NetworkRequest request = new NetworkRequest.Builder().addCapability(capability).build();
3235             networkCallback = new NetworkCallback();
3236             mCm.requestNetwork(request, networkCallback);
3237         } else {
3238             networkCallback = null;
3239         }
3240         testFactory.expectRequestAdd();
3241         testFactory.assertRequestCountEquals(1);
3242         assertTrue(testFactory.getMyStartRequested());
3243 
3244         // Now bring in a higher scored network.
3245         TestNetworkAgentWrapper testAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
3246         // When testAgent connects, because of its score (50 legacy int / cell transport)
3247         // it will beat or equal the testFactory's offer, so the request will be removed.
3248         // Note the agent as validated only if the capability is INTERNET, as it's the only case
3249         // where it makes sense.
3250         testAgent.connect(NET_CAPABILITY_INTERNET == capability /* validated */);
3251         testAgent.addCapability(capability);
3252         testFactory.expectRequestRemove();
3253         testFactory.assertRequestCountEquals(0);
3254         assertFalse(testFactory.getMyStartRequested());
3255 
3256         // Add a request and make sure it's not sent to the factory, because the agent
3257         // is satisfying it better.
3258         final NetworkCallback cb = new ConnectivityManager.NetworkCallback();
3259         mCm.requestNetwork(new NetworkRequest.Builder().addCapability(capability).build(), cb);
3260         expectNoRequestChanged(testFactory);
3261         testFactory.assertRequestCountEquals(0);
3262         assertFalse(testFactory.getMyStartRequested());
3263 
3264         // If using legacy scores, make the test agent weak enough to have the exact same score as
3265         // the factory (50 for cell - 5 adjustment). Make sure the factory doesn't see the request.
3266         // If not using legacy score, this is a no-op and the "same score removes request" behavior
3267         // has already been tested above.
3268         testAgent.adjustScore(-5);
3269         expectNoRequestChanged(testFactory);
3270         assertFalse(testFactory.getMyStartRequested());
3271 
3272         // Make the test agent weak enough that the factory will see the two requests (the one that
3273         // was just sent, and either the default one or the one sent at the top of this test if
3274         // the default won't be seen).
3275         testAgent.setScore(new NetworkScore.Builder().setLegacyInt(2).setExiting(true).build());
3276         testFactory.expectRequestAdds(2);
3277         testFactory.assertRequestCountEquals(2);
3278         assertTrue(testFactory.getMyStartRequested());
3279 
3280         // Now unregister and make sure the request is removed.
3281         mCm.unregisterNetworkCallback(cb);
3282         testFactory.expectRequestRemove();
3283 
3284         // Bring in a bunch of requests.
3285         assertEquals(1, testFactory.getMyRequestCount());
3286         ConnectivityManager.NetworkCallback[] networkCallbacks =
3287                 new ConnectivityManager.NetworkCallback[10];
3288         for (int i = 0; i< networkCallbacks.length; i++) {
3289             networkCallbacks[i] = new ConnectivityManager.NetworkCallback();
3290             NetworkRequest.Builder builder = new NetworkRequest.Builder();
3291             builder.addCapability(capability);
3292             mCm.requestNetwork(builder.build(), networkCallbacks[i]);
3293         }
3294         testFactory.expectRequestAdds(10);
3295         testFactory.assertRequestCountEquals(11); // +1 for the default/test specific request
3296         assertTrue(testFactory.getMyStartRequested());
3297 
3298         // Remove the requests.
3299         for (int i = 0; i < networkCallbacks.length; i++) {
3300             mCm.unregisterNetworkCallback(networkCallbacks[i]);
3301         }
3302         testFactory.expectRequestRemoves(10);
3303         testFactory.assertRequestCountEquals(1);
3304         assertTrue(testFactory.getMyStartRequested());
3305 
3306         // Adjust the agent score up again. Expect the request to be withdrawn.
3307         testAgent.setScore(new NetworkScore.Builder().setLegacyInt(50).build());
3308         testFactory.expectRequestRemove();
3309         testFactory.assertRequestCountEquals(0);
3310         assertFalse(testFactory.getMyStartRequested());
3311 
3312         // Drop the higher scored network.
3313         testAgent.disconnect();
3314         testFactory.expectRequestAdd();
3315         testFactory.assertRequestCountEquals(1);
3316         assertEquals(1, testFactory.getMyRequestCount());
3317         assertTrue(testFactory.getMyStartRequested());
3318 
3319         testFactory.terminate();
3320         if (networkCallback != null) mCm.unregisterNetworkCallback(networkCallback);
3321         handlerThread.quit();
3322     }
3323 
3324     @Test
3325     public void testNetworkFactoryRequests() throws Exception {
3326         tryNetworkFactoryRequests(NET_CAPABILITY_MMS);
3327         tryNetworkFactoryRequests(NET_CAPABILITY_SUPL);
3328         tryNetworkFactoryRequests(NET_CAPABILITY_DUN);
3329         tryNetworkFactoryRequests(NET_CAPABILITY_FOTA);
3330         tryNetworkFactoryRequests(NET_CAPABILITY_IMS);
3331         tryNetworkFactoryRequests(NET_CAPABILITY_CBS);
3332         tryNetworkFactoryRequests(NET_CAPABILITY_WIFI_P2P);
3333         tryNetworkFactoryRequests(NET_CAPABILITY_IA);
3334         tryNetworkFactoryRequests(NET_CAPABILITY_RCS);
3335         tryNetworkFactoryRequests(NET_CAPABILITY_XCAP);
3336         tryNetworkFactoryRequests(NET_CAPABILITY_ENTERPRISE);
3337         tryNetworkFactoryRequests(NET_CAPABILITY_EIMS);
3338         tryNetworkFactoryRequests(NET_CAPABILITY_NOT_METERED);
3339         tryNetworkFactoryRequests(NET_CAPABILITY_INTERNET);
3340         tryNetworkFactoryRequests(NET_CAPABILITY_TRUSTED);
3341         tryNetworkFactoryRequests(NET_CAPABILITY_NOT_VPN);
3342         tryNetworkFactoryRequests(NET_CAPABILITY_VSIM);
3343         tryNetworkFactoryRequests(NET_CAPABILITY_BIP);
3344         // Skipping VALIDATED and CAPTIVE_PORTAL as they're disallowed.
3345     }
3346 
3347     @Test
3348     public void testRegisterIgnoringScore() throws Exception {
3349         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3350         mWiFiNetworkAgent.setScore(new NetworkScore.Builder().setLegacyInt(90).build());
3351         mWiFiNetworkAgent.connect(true /* validated */);
3352 
3353         // Make sure the factory sees the default network
3354         final NetworkCapabilities filter = new NetworkCapabilities();
3355         filter.addTransportType(TRANSPORT_CELLULAR);
3356         filter.addCapability(NET_CAPABILITY_INTERNET);
3357         filter.addCapability(NET_CAPABILITY_NOT_VCN_MANAGED);
3358         final HandlerThread handlerThread = new HandlerThread("testNetworkFactoryRequests");
3359         handlerThread.start();
3360         final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
3361                 mServiceContext, "testFactory", filter, mCsHandlerThread);
3362         testFactory.register();
3363 
3364         final MockNetworkFactory testFactoryAll = new MockNetworkFactory(handlerThread.getLooper(),
3365                 mServiceContext, "testFactoryAll", filter, mCsHandlerThread);
3366         testFactoryAll.registerIgnoringScore();
3367 
3368         // The regular test factory should not see the request, because WiFi is stronger than cell.
3369         expectNoRequestChanged(testFactory);
3370         // With ignoringScore though the request is seen.
3371         testFactoryAll.expectRequestAdd();
3372 
3373         // The legacy int will be ignored anyway, set the only other knob to true
3374         mWiFiNetworkAgent.setScore(new NetworkScore.Builder().setLegacyInt(110)
3375                 .setTransportPrimary(true).build());
3376 
3377         expectNoRequestChanged(testFactory); // still not seeing the request
3378         expectNoRequestChanged(testFactoryAll); // still seeing the request
3379 
3380         mWiFiNetworkAgent.disconnect();
3381     }
3382 
3383     @Test
3384     public void testNetworkFactoryUnregister() throws Exception {
3385         // Make sure the factory sees the default network
3386         final NetworkCapabilities filter = new NetworkCapabilities();
3387         filter.addCapability(NET_CAPABILITY_INTERNET);
3388         filter.addCapability(NET_CAPABILITY_NOT_VCN_MANAGED);
3389 
3390         final HandlerThread handlerThread = new HandlerThread("testNetworkFactoryRequests");
3391         handlerThread.start();
3392 
3393         // Checks that calling setScoreFilter on a NetworkFactory immediately before closing it
3394         // does not crash.
3395         for (int i = 0; i < 100; i++) {
3396             final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
3397                     mServiceContext, "testFactory", filter, mCsHandlerThread);
3398             // Register the factory and don't be surprised when the default request arrives.
3399             testFactory.register();
3400             testFactory.expectRequestAdd();
3401 
3402             testFactory.setScoreFilter(42);
3403             testFactory.terminate();
3404 
3405             if (i % 2 == 0) {
3406                 try {
3407                     testFactory.register();
3408                     fail("Re-registering terminated NetworkFactory should throw");
3409                 } catch (IllegalStateException expected) {
3410                 }
3411             }
3412         }
3413         handlerThread.quit();
3414     }
3415 
3416     @Test
3417     public void testNoMutableNetworkRequests() throws Exception {
3418         final PendingIntent pendingIntent = PendingIntent.getBroadcast(
3419                 mContext, 0 /* requestCode */, new Intent("a"), FLAG_IMMUTABLE);
3420         NetworkRequest request1 = new NetworkRequest.Builder()
3421                 .addCapability(NET_CAPABILITY_VALIDATED)
3422                 .build();
3423         NetworkRequest request2 = new NetworkRequest.Builder()
3424                 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL)
3425                 .build();
3426 
3427         Class<IllegalArgumentException> expected = IllegalArgumentException.class;
3428         assertThrows(expected, () -> mCm.requestNetwork(request1, new NetworkCallback()));
3429         assertThrows(expected, () -> mCm.requestNetwork(request1, pendingIntent));
3430         assertThrows(expected, () -> mCm.requestNetwork(request2, new NetworkCallback()));
3431         assertThrows(expected, () -> mCm.requestNetwork(request2, pendingIntent));
3432     }
3433 
3434     @Test
3435     public void testMMSonWiFi() throws Exception {
3436         // Test bringing up cellular without MMS NetworkRequest gets reaped
3437         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
3438         mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS);
3439         mCellNetworkAgent.connectWithoutInternet();
3440         mCellNetworkAgent.expectDisconnected();
3441         waitForIdle();
3442         assertEmpty(mCm.getAllNetworks());
3443         verifyNoNetwork();
3444 
3445         // Test bringing up validated WiFi.
3446         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3447         final ExpectedBroadcast b = expectConnectivityAction(TYPE_WIFI, DetailedState.CONNECTED);
3448         mWiFiNetworkAgent.connect(true);
3449         b.expectBroadcast();
3450         verifyActiveNetwork(TRANSPORT_WIFI);
3451 
3452         // Register MMS NetworkRequest
3453         NetworkRequest.Builder builder = new NetworkRequest.Builder();
3454         builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
3455         final TestNetworkCallback networkCallback = new TestNetworkCallback();
3456         mCm.requestNetwork(builder.build(), networkCallback);
3457 
3458         // Test bringing up unvalidated cellular with MMS
3459         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
3460         mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS);
3461         mCellNetworkAgent.connectWithoutInternet();
3462         networkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
3463         verifyActiveNetwork(TRANSPORT_WIFI);
3464 
3465         // Test releasing NetworkRequest disconnects cellular with MMS
3466         mCm.unregisterNetworkCallback(networkCallback);
3467         mCellNetworkAgent.expectDisconnected();
3468         verifyActiveNetwork(TRANSPORT_WIFI);
3469     }
3470 
3471     @Test
3472     public void testMMSonCell() throws Exception {
3473         // Test bringing up cellular without MMS
3474         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
3475         ExpectedBroadcast b = expectConnectivityAction(TYPE_MOBILE, DetailedState.CONNECTED);
3476         mCellNetworkAgent.connect(false);
3477         b.expectBroadcast();
3478         verifyActiveNetwork(TRANSPORT_CELLULAR);
3479 
3480         // Register MMS NetworkRequest
3481         NetworkRequest.Builder builder = new NetworkRequest.Builder();
3482         builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
3483         final TestNetworkCallback networkCallback = new TestNetworkCallback();
3484         mCm.requestNetwork(builder.build(), networkCallback);
3485 
3486         // Test bringing up MMS cellular network
3487         TestNetworkAgentWrapper
3488                 mmsNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
3489         mmsNetworkAgent.addCapability(NET_CAPABILITY_MMS);
3490         mmsNetworkAgent.connectWithoutInternet();
3491         networkCallback.expectAvailableCallbacksUnvalidated(mmsNetworkAgent);
3492         verifyActiveNetwork(TRANSPORT_CELLULAR);
3493 
3494         // Test releasing MMS NetworkRequest does not disconnect main cellular NetworkAgent
3495         mCm.unregisterNetworkCallback(networkCallback);
3496         mmsNetworkAgent.expectDisconnected();
3497         verifyActiveNetwork(TRANSPORT_CELLULAR);
3498     }
3499 
3500     @Test
3501     public void testPartialConnectivity() throws Exception {
3502         // Register network callback.
3503         NetworkRequest request = new NetworkRequest.Builder()
3504                 .clearCapabilities().addCapability(NET_CAPABILITY_INTERNET)
3505                 .build();
3506         TestNetworkCallback callback = new TestNetworkCallback();
3507         mCm.registerNetworkCallback(request, callback);
3508 
3509         // Bring up validated mobile data.
3510         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
3511         mCellNetworkAgent.connect(true);
3512         callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
3513 
3514         // Bring up wifi with partial connectivity.
3515         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3516         mWiFiNetworkAgent.connectWithPartialConnectivity();
3517         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
3518         callback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY, mWiFiNetworkAgent);
3519 
3520         // Mobile data should be the default network.
3521         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
3522         callback.assertNoCallback();
3523 
3524         // With HTTPS probe disabled, NetworkMonitor should pass the network validation with http
3525         // probe.
3526         mWiFiNetworkAgent.setNetworkPartialValid(false /* isStrictMode */);
3527         // If the user chooses yes to use this partial connectivity wifi, switch the default
3528         // network to wifi and check if wifi becomes valid or not.
3529         mCm.setAcceptPartialConnectivity(mWiFiNetworkAgent.getNetwork(), true /* accept */,
3530                 false /* always */);
3531         // If user accepts partial connectivity network,
3532         // NetworkMonitor#setAcceptPartialConnectivity() should be called too.
3533         waitForIdle();
3534         verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
3535 
3536         // Need a trigger point to let NetworkMonitor tell ConnectivityService that network is
3537         // validated.
3538         mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
3539         callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
3540         NetworkCapabilities nc = callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED,
3541                 mWiFiNetworkAgent);
3542         assertTrue(nc.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY));
3543         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
3544 
3545         // Disconnect and reconnect wifi with partial connectivity again.
3546         mWiFiNetworkAgent.disconnect();
3547         callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
3548         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3549         mWiFiNetworkAgent.connectWithPartialConnectivity();
3550         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
3551         callback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY, mWiFiNetworkAgent);
3552 
3553         // Mobile data should be the default network.
3554         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
3555 
3556         // If the user chooses no, disconnect wifi immediately.
3557         mCm.setAcceptPartialConnectivity(mWiFiNetworkAgent.getNetwork(), false/* accept */,
3558                 false /* always */);
3559         callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
3560 
3561         // If user accepted partial connectivity before, and device reconnects to that network
3562         // again, but now the network has full connectivity. The network shouldn't contain
3563         // NET_CAPABILITY_PARTIAL_CONNECTIVITY.
3564         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3565         // acceptUnvalidated is also used as setting for accepting partial networks.
3566         mWiFiNetworkAgent.explicitlySelected(true /* explicitlySelected */,
3567                 true /* acceptUnvalidated */);
3568         mWiFiNetworkAgent.connect(true);
3569 
3570         // If user accepted partial connectivity network before,
3571         // NetworkMonitor#setAcceptPartialConnectivity() will be called in
3572         // ConnectivityService#updateNetworkInfo().
3573         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
3574         verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
3575         callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
3576         nc = callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
3577         assertFalse(nc.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY));
3578 
3579         // Wifi should be the default network.
3580         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
3581         mWiFiNetworkAgent.disconnect();
3582         callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
3583 
3584         // The user accepted partial connectivity and selected "don't ask again". Now the user
3585         // reconnects to the partial connectivity network. Switch to wifi as soon as partial
3586         // connectivity is detected.
3587         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3588         mWiFiNetworkAgent.explicitlySelected(true /* explicitlySelected */,
3589                 true /* acceptUnvalidated */);
3590         mWiFiNetworkAgent.connectWithPartialConnectivity();
3591         // If user accepted partial connectivity network before,
3592         // NetworkMonitor#setAcceptPartialConnectivity() will be called in
3593         // ConnectivityService#updateNetworkInfo().
3594         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
3595         verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
3596         callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
3597         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
3598         callback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY, mWiFiNetworkAgent);
3599         mWiFiNetworkAgent.setNetworkValid(false /* isStrictMode */);
3600 
3601         // Need a trigger point to let NetworkMonitor tell ConnectivityService that network is
3602         // validated.
3603         mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
3604         callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
3605         mWiFiNetworkAgent.disconnect();
3606         callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
3607 
3608         // If the user accepted partial connectivity, and the device auto-reconnects to the partial
3609         // connectivity network, it should contain both PARTIAL_CONNECTIVITY and VALIDATED.
3610         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3611         mWiFiNetworkAgent.explicitlySelected(false /* explicitlySelected */,
3612                 true /* acceptUnvalidated */);
3613 
3614         // NetworkMonitor will immediately (once the HTTPS probe fails...) report the network as
3615         // valid, because ConnectivityService calls setAcceptPartialConnectivity before it calls
3616         // notifyNetworkConnected.
3617         mWiFiNetworkAgent.connectWithPartialValidConnectivity(false /* isStrictMode */);
3618         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
3619         verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
3620         callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
3621         callback.expectCapabilitiesWith(
3622                 NET_CAPABILITY_PARTIAL_CONNECTIVITY | NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
3623         mWiFiNetworkAgent.disconnect();
3624         callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
3625     }
3626 
3627     @Test
3628     public void testCaptivePortalOnPartialConnectivity() throws Exception {
3629         final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
3630         final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
3631                 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
3632         mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
3633 
3634         final TestNetworkCallback validatedCallback = new TestNetworkCallback();
3635         final NetworkRequest validatedRequest = new NetworkRequest.Builder()
3636                 .addCapability(NET_CAPABILITY_VALIDATED).build();
3637         mCm.registerNetworkCallback(validatedRequest, validatedCallback);
3638 
3639         // Bring up a network with a captive portal.
3640         // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
3641         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3642         String redirectUrl = "http://android.com/path";
3643         mWiFiNetworkAgent.connectWithCaptivePortal(redirectUrl, false /* isStrictMode */);
3644         captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
3645         assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), redirectUrl);
3646 
3647         // Check that startCaptivePortalApp sends the expected command to NetworkMonitor.
3648         mCm.startCaptivePortalApp(mWiFiNetworkAgent.getNetwork());
3649         verify(mWiFiNetworkAgent.mNetworkMonitor, timeout(TIMEOUT_MS).times(1))
3650                 .launchCaptivePortalApp();
3651 
3652         // Report that the captive portal is dismissed with partial connectivity, and check that
3653         // callbacks are fired.
3654         mWiFiNetworkAgent.setNetworkPartial();
3655         mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
3656         waitForIdle();
3657         captivePortalCallback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY,
3658                 mWiFiNetworkAgent);
3659 
3660         // Report partial connectivity is accepted.
3661         mWiFiNetworkAgent.setNetworkPartialValid(false /* isStrictMode */);
3662         mCm.setAcceptPartialConnectivity(mWiFiNetworkAgent.getNetwork(), true /* accept */,
3663                 false /* always */);
3664         waitForIdle();
3665         mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
3666         captivePortalCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
3667         validatedCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
3668         NetworkCapabilities nc =
3669                 validatedCallback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY,
3670                 mWiFiNetworkAgent);
3671 
3672         mCm.unregisterNetworkCallback(captivePortalCallback);
3673         mCm.unregisterNetworkCallback(validatedCallback);
3674     }
3675 
3676     @Test
3677     public void testCaptivePortal() throws Exception {
3678         final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
3679         final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
3680                 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
3681         mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
3682 
3683         final TestNetworkCallback validatedCallback = new TestNetworkCallback();
3684         final NetworkRequest validatedRequest = new NetworkRequest.Builder()
3685                 .addCapability(NET_CAPABILITY_VALIDATED).build();
3686         mCm.registerNetworkCallback(validatedRequest, validatedCallback);
3687 
3688         // Bring up a network with a captive portal.
3689         // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
3690         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3691         String firstRedirectUrl = "http://example.com/firstPath";
3692         mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl, false /* isStrictMode */);
3693         captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
3694         assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), firstRedirectUrl);
3695 
3696         // Take down network.
3697         // Expect onLost callback.
3698         mWiFiNetworkAgent.disconnect();
3699         captivePortalCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
3700 
3701         // Bring up a network with a captive portal.
3702         // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
3703         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3704         String secondRedirectUrl = "http://example.com/secondPath";
3705         mWiFiNetworkAgent.connectWithCaptivePortal(secondRedirectUrl, false /* isStrictMode */);
3706         captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
3707         assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), secondRedirectUrl);
3708 
3709         // Make captive portal disappear then revalidate.
3710         // Expect onLost callback because network no longer provides NET_CAPABILITY_CAPTIVE_PORTAL.
3711         mWiFiNetworkAgent.setNetworkValid(false /* isStrictMode */);
3712         mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
3713         captivePortalCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
3714 
3715         // Expect NET_CAPABILITY_VALIDATED onAvailable callback.
3716         validatedCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
3717 
3718         // Break network connectivity.
3719         // Expect NET_CAPABILITY_VALIDATED onLost callback.
3720         mWiFiNetworkAgent.setNetworkInvalid(false /* isStrictMode */);
3721         mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), false);
3722         validatedCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
3723     }
3724 
3725     @Test
3726     public void testCaptivePortalApp() throws Exception {
3727         final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
3728         final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
3729                 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
3730         mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
3731 
3732         final TestNetworkCallback validatedCallback = new TestNetworkCallback();
3733         final NetworkRequest validatedRequest = new NetworkRequest.Builder()
3734                 .addCapability(NET_CAPABILITY_VALIDATED).build();
3735         mCm.registerNetworkCallback(validatedRequest, validatedCallback);
3736 
3737         // Bring up wifi.
3738         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3739         mWiFiNetworkAgent.connect(true);
3740         validatedCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
3741         Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
3742 
3743         // Check that calling startCaptivePortalApp does nothing.
3744         final int fastTimeoutMs = 100;
3745         mCm.startCaptivePortalApp(wifiNetwork);
3746         waitForIdle();
3747         verify(mWiFiNetworkAgent.mNetworkMonitor, never()).launchCaptivePortalApp();
3748         mServiceContext.expectNoStartActivityIntent(fastTimeoutMs);
3749 
3750         // Turn into a captive portal.
3751         mWiFiNetworkAgent.setNetworkPortal("http://example.com", false /* isStrictMode */);
3752         mCm.reportNetworkConnectivity(wifiNetwork, false);
3753         captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
3754         validatedCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
3755 
3756         // Check that startCaptivePortalApp sends the expected command to NetworkMonitor.
3757         mCm.startCaptivePortalApp(wifiNetwork);
3758         waitForIdle();
3759         verify(mWiFiNetworkAgent.mNetworkMonitor).launchCaptivePortalApp();
3760 
3761         // NetworkMonitor uses startCaptivePortal(Network, Bundle) (startCaptivePortalAppInternal)
3762         final Bundle testBundle = new Bundle();
3763         final String testKey = "testkey";
3764         final String testValue = "testvalue";
3765         testBundle.putString(testKey, testValue);
3766         mServiceContext.setPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
3767                 PERMISSION_GRANTED);
3768         mCm.startCaptivePortalApp(wifiNetwork, testBundle);
3769         final Intent signInIntent = mServiceContext.expectStartActivityIntent(TIMEOUT_MS);
3770         assertEquals(ACTION_CAPTIVE_PORTAL_SIGN_IN, signInIntent.getAction());
3771         assertEquals(testValue, signInIntent.getStringExtra(testKey));
3772 
3773         // Report that the captive portal is dismissed, and check that callbacks are fired
3774         mWiFiNetworkAgent.setNetworkValid(false /* isStrictMode */);
3775         mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
3776         validatedCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
3777         captivePortalCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
3778 
3779         mCm.unregisterNetworkCallback(validatedCallback);
3780         mCm.unregisterNetworkCallback(captivePortalCallback);
3781     }
3782 
3783     @Test
3784     public void testAvoidOrIgnoreCaptivePortals() throws Exception {
3785         final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
3786         final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
3787                 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
3788         mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
3789 
3790         final TestNetworkCallback validatedCallback = new TestNetworkCallback();
3791         final NetworkRequest validatedRequest = new NetworkRequest.Builder()
3792                 .addCapability(NET_CAPABILITY_VALIDATED).build();
3793         mCm.registerNetworkCallback(validatedRequest, validatedCallback);
3794 
3795         setCaptivePortalMode(ConnectivitySettingsManager.CAPTIVE_PORTAL_MODE_AVOID);
3796         // Bring up a network with a captive portal.
3797         // Expect it to fail to connect and not result in any callbacks.
3798         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3799         String firstRedirectUrl = "http://example.com/firstPath";
3800 
3801         mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl, false /* isStrictMode */);
3802         mWiFiNetworkAgent.expectDisconnected();
3803         mWiFiNetworkAgent.expectPreventReconnectReceived();
3804 
3805         assertNoCallbacks(captivePortalCallback, validatedCallback);
3806     }
3807 
3808     @Test
3809     public void testCaptivePortalApi() throws Exception {
3810         mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_GRANTED);
3811 
3812         final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
3813         final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
3814                 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
3815         mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
3816 
3817         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3818         final String redirectUrl = "http://example.com/firstPath";
3819 
3820         mWiFiNetworkAgent.connectWithCaptivePortal(redirectUrl, false /* isStrictMode */);
3821         captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
3822 
3823         final CaptivePortalData testData = new CaptivePortalData.Builder()
3824                 .setUserPortalUrl(Uri.parse(redirectUrl))
3825                 .setBytesRemaining(12345L)
3826                 .build();
3827 
3828         mWiFiNetworkAgent.notifyCapportApiDataChanged(testData);
3829 
3830         captivePortalCallback.expectLinkPropertiesThat(mWiFiNetworkAgent,
3831                 lp -> testData.equals(lp.getCaptivePortalData()));
3832 
3833         final LinkProperties newLps = new LinkProperties();
3834         newLps.setMtu(1234);
3835         mWiFiNetworkAgent.sendLinkProperties(newLps);
3836         // CaptivePortalData is not lost and unchanged when LPs are received from the NetworkAgent
3837         captivePortalCallback.expectLinkPropertiesThat(mWiFiNetworkAgent,
3838                 lp -> testData.equals(lp.getCaptivePortalData()) && lp.getMtu() == 1234);
3839     }
3840 
3841     private TestNetworkCallback setupNetworkCallbackAndConnectToWifi() throws Exception {
3842         // Grant NETWORK_SETTINGS permission to be able to receive LinkProperties change callbacks
3843         // with sensitive (captive portal) data
3844         mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_GRANTED);
3845 
3846         final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
3847         final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
3848                 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
3849         mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
3850 
3851         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
3852 
3853         mWiFiNetworkAgent.connectWithCaptivePortal(TEST_REDIRECT_URL, false /* isStrictMode */);
3854         captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
3855         return captivePortalCallback;
3856     }
3857 
3858     private class CaptivePortalTestData {
3859         CaptivePortalTestData(CaptivePortalData naPasspointData, CaptivePortalData capportData,
3860                 CaptivePortalData naOtherData, CaptivePortalData expectedMergedPasspointData,
3861                 CaptivePortalData expectedMergedOtherData) {
3862             mNaPasspointData = naPasspointData;
3863             mCapportData = capportData;
3864             mNaOtherData = naOtherData;
3865             mExpectedMergedPasspointData = expectedMergedPasspointData;
3866             mExpectedMergedOtherData = expectedMergedOtherData;
3867         }
3868 
3869         public final CaptivePortalData mNaPasspointData;
3870         public final CaptivePortalData mCapportData;
3871         public final CaptivePortalData mNaOtherData;
3872         public final CaptivePortalData mExpectedMergedPasspointData;
3873         public final CaptivePortalData mExpectedMergedOtherData;
3874 
3875     }
3876 
3877     private CaptivePortalTestData setupCaptivePortalData() {
3878         final CaptivePortalData capportData = new CaptivePortalData.Builder()
3879                 .setUserPortalUrl(Uri.parse(TEST_REDIRECT_URL))
3880                 .setVenueInfoUrl(Uri.parse(TEST_VENUE_URL_CAPPORT))
3881                 .setUserPortalUrl(Uri.parse(TEST_USER_PORTAL_API_URL_CAPPORT))
3882                 .setExpiryTime(1000000L)
3883                 .setBytesRemaining(12345L)
3884                 .build();
3885 
3886         final CaptivePortalData naPasspointData = new CaptivePortalData.Builder()
3887                 .setBytesRemaining(80802L)
3888                 .setVenueInfoUrl(Uri.parse(TEST_VENUE_URL_NA_PASSPOINT),
3889                         CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_PASSPOINT)
3890                 .setUserPortalUrl(Uri.parse(TEST_TERMS_AND_CONDITIONS_URL_NA_PASSPOINT),
3891                         CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_PASSPOINT)
3892                 .setVenueFriendlyName(TEST_FRIENDLY_NAME).build();
3893 
3894         final CaptivePortalData naOtherData = new CaptivePortalData.Builder()
3895                 .setBytesRemaining(80802L)
3896                 .setVenueInfoUrl(Uri.parse(TEST_VENUE_URL_NA_OTHER),
3897                         CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_OTHER)
3898                 .setUserPortalUrl(Uri.parse(TEST_TERMS_AND_CONDITIONS_URL_NA_OTHER),
3899                         CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_OTHER)
3900                 .setVenueFriendlyName(TEST_FRIENDLY_NAME).build();
3901 
3902         final CaptivePortalData expectedMergedPasspointData = new CaptivePortalData.Builder()
3903                 .setUserPortalUrl(Uri.parse(TEST_REDIRECT_URL))
3904                 .setBytesRemaining(12345L)
3905                 .setExpiryTime(1000000L)
3906                 .setVenueInfoUrl(Uri.parse(TEST_VENUE_URL_NA_PASSPOINT),
3907                         CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_PASSPOINT)
3908                 .setUserPortalUrl(Uri.parse(TEST_TERMS_AND_CONDITIONS_URL_NA_PASSPOINT),
3909                         CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_PASSPOINT)
3910                 .setVenueFriendlyName(TEST_FRIENDLY_NAME).build();
3911 
3912         final CaptivePortalData expectedMergedOtherData = new CaptivePortalData.Builder()
3913                 .setUserPortalUrl(Uri.parse(TEST_REDIRECT_URL))
3914                 .setBytesRemaining(12345L)
3915                 .setExpiryTime(1000000L)
3916                 .setVenueInfoUrl(Uri.parse(TEST_VENUE_URL_CAPPORT))
3917                 .setUserPortalUrl(Uri.parse(TEST_USER_PORTAL_API_URL_CAPPORT))
3918                 .setVenueFriendlyName(TEST_FRIENDLY_NAME).build();
3919         return new CaptivePortalTestData(naPasspointData, capportData, naOtherData,
3920                 expectedMergedPasspointData, expectedMergedOtherData);
3921     }
3922 
3923     @Test
3924     public void testMergeCaptivePortalApiWithFriendlyNameAndVenueUrl() throws Exception {
3925         final TestNetworkCallback captivePortalCallback = setupNetworkCallbackAndConnectToWifi();
3926         final CaptivePortalTestData captivePortalTestData = setupCaptivePortalData();
3927 
3928         // Baseline capport data
3929         mWiFiNetworkAgent.notifyCapportApiDataChanged(captivePortalTestData.mCapportData);
3930 
3931         captivePortalCallback.expectLinkPropertiesThat(mWiFiNetworkAgent,
3932                 lp -> captivePortalTestData.mCapportData.equals(lp.getCaptivePortalData()));
3933 
3934         // Venue URL, T&C URL and friendly name from Network agent with Passpoint source, confirm
3935         // that API data gets precedence on the bytes remaining.
3936         final LinkProperties linkProperties = new LinkProperties();
3937         linkProperties.setCaptivePortalData(captivePortalTestData.mNaPasspointData);
3938         mWiFiNetworkAgent.sendLinkProperties(linkProperties);
3939 
3940         // Make sure that the capport data is merged
3941         captivePortalCallback.expectLinkPropertiesThat(mWiFiNetworkAgent,
3942                 lp -> captivePortalTestData.mExpectedMergedPasspointData
3943                         .equals(lp.getCaptivePortalData()));
3944 
3945         // Now send this information from non-Passpoint source, confirm that Capport data takes
3946         // precedence
3947         linkProperties.setCaptivePortalData(captivePortalTestData.mNaOtherData);
3948         mWiFiNetworkAgent.sendLinkProperties(linkProperties);
3949 
3950         // Make sure that the capport data is merged
3951         captivePortalCallback.expectLinkPropertiesThat(mWiFiNetworkAgent,
3952                 lp -> captivePortalTestData.mExpectedMergedOtherData
3953                         .equals(lp.getCaptivePortalData()));
3954 
3955         // Create a new LP with no Network agent capport data
3956         final LinkProperties newLps = new LinkProperties();
3957         newLps.setMtu(1234);
3958         mWiFiNetworkAgent.sendLinkProperties(newLps);
3959         // CaptivePortalData is not lost and has the original values when LPs are received from the
3960         // NetworkAgent
3961         captivePortalCallback.expectLinkPropertiesThat(mWiFiNetworkAgent,
3962                 lp -> captivePortalTestData.mCapportData.equals(lp.getCaptivePortalData())
3963                         && lp.getMtu() == 1234);
3964 
3965         // Now send capport data only from the Network agent
3966         mWiFiNetworkAgent.notifyCapportApiDataChanged(null);
3967         captivePortalCallback.expectLinkPropertiesThat(mWiFiNetworkAgent,
3968                 lp -> lp.getCaptivePortalData() == null);
3969 
3970         newLps.setCaptivePortalData(captivePortalTestData.mNaPasspointData);
3971         mWiFiNetworkAgent.sendLinkProperties(newLps);
3972 
3973         // Make sure that only the network agent capport data is available
3974         captivePortalCallback.expectLinkPropertiesThat(mWiFiNetworkAgent,
3975                 lp -> captivePortalTestData.mNaPasspointData.equals(lp.getCaptivePortalData()));
3976     }
3977 
3978     @Test
3979     public void testMergeCaptivePortalDataFromNetworkAgentFirstThenCapport() throws Exception {
3980         final TestNetworkCallback captivePortalCallback = setupNetworkCallbackAndConnectToWifi();
3981         final CaptivePortalTestData captivePortalTestData = setupCaptivePortalData();
3982 
3983         // Venue URL and friendly name from Network agent, confirm that API data gets precedence
3984         // on the bytes remaining.
3985         final LinkProperties linkProperties = new LinkProperties();
3986         linkProperties.setCaptivePortalData(captivePortalTestData.mNaPasspointData);
3987         mWiFiNetworkAgent.sendLinkProperties(linkProperties);
3988 
3989         // Make sure that the data is saved correctly
3990         captivePortalCallback.expectLinkPropertiesThat(mWiFiNetworkAgent,
3991                 lp -> captivePortalTestData.mNaPasspointData.equals(lp.getCaptivePortalData()));
3992 
3993         // Expected merged data: Network agent data is preferred, and values that are not used by
3994         // it are merged from capport data
3995         mWiFiNetworkAgent.notifyCapportApiDataChanged(captivePortalTestData.mCapportData);
3996 
3997         // Make sure that the Capport data is merged correctly
3998         captivePortalCallback.expectLinkPropertiesThat(mWiFiNetworkAgent,
3999                 lp -> captivePortalTestData.mExpectedMergedPasspointData.equals(
4000                         lp.getCaptivePortalData()));
4001 
4002         // Now set the naData to null
4003         linkProperties.setCaptivePortalData(null);
4004         mWiFiNetworkAgent.sendLinkProperties(linkProperties);
4005 
4006         // Make sure that the Capport data is retained correctly
4007         captivePortalCallback.expectLinkPropertiesThat(mWiFiNetworkAgent,
4008                 lp -> captivePortalTestData.mCapportData.equals(lp.getCaptivePortalData()));
4009     }
4010 
4011     @Test
4012     public void testMergeCaptivePortalDataFromNetworkAgentOtherSourceFirstThenCapport()
4013             throws Exception {
4014         final TestNetworkCallback captivePortalCallback = setupNetworkCallbackAndConnectToWifi();
4015         final CaptivePortalTestData captivePortalTestData = setupCaptivePortalData();
4016 
4017         // Venue URL and friendly name from Network agent, confirm that API data gets precedence
4018         // on the bytes remaining.
4019         final LinkProperties linkProperties = new LinkProperties();
4020         linkProperties.setCaptivePortalData(captivePortalTestData.mNaOtherData);
4021         mWiFiNetworkAgent.sendLinkProperties(linkProperties);
4022 
4023         // Make sure that the data is saved correctly
4024         captivePortalCallback.expectLinkPropertiesThat(mWiFiNetworkAgent,
4025                 lp -> captivePortalTestData.mNaOtherData.equals(lp.getCaptivePortalData()));
4026 
4027         // Expected merged data: Network agent data is preferred, and values that are not used by
4028         // it are merged from capport data
4029         mWiFiNetworkAgent.notifyCapportApiDataChanged(captivePortalTestData.mCapportData);
4030 
4031         // Make sure that the Capport data is merged correctly
4032         captivePortalCallback.expectLinkPropertiesThat(mWiFiNetworkAgent,
4033                 lp -> captivePortalTestData.mExpectedMergedOtherData.equals(
4034                         lp.getCaptivePortalData()));
4035     }
4036 
4037     private NetworkRequest.Builder newWifiRequestBuilder() {
4038         return new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI);
4039     }
4040 
4041     /**
4042      * Verify request matching behavior with network specifiers.
4043      *
4044      * This test does not check updating the specifier on a live network because the specifier is
4045      * immutable and this triggers a WTF in
4046      * {@link ConnectivityService#mixInCapabilities(NetworkAgentInfo, NetworkCapabilities)}.
4047      */
4048     @Test
4049     public void testNetworkSpecifier() throws Exception {
4050         // A NetworkSpecifier subclass that matches all networks but must not be visible to apps.
4051         class ConfidentialMatchAllNetworkSpecifier extends NetworkSpecifier implements
4052                 Parcelable {
4053             @Override
4054             public boolean canBeSatisfiedBy(NetworkSpecifier other) {
4055                 return true;
4056             }
4057 
4058             @Override
4059             public int describeContents() {
4060                 return 0;
4061             }
4062 
4063             @Override
4064             public void writeToParcel(Parcel dest, int flags) {}
4065 
4066             @Override
4067             public NetworkSpecifier redact() {
4068                 return null;
4069             }
4070         }
4071 
4072         // A network specifier that matches either another LocalNetworkSpecifier with the same
4073         // string or a ConfidentialMatchAllNetworkSpecifier, and can be passed to apps as is.
4074         class LocalStringNetworkSpecifier extends NetworkSpecifier implements Parcelable {
4075             private String mString;
4076 
4077             LocalStringNetworkSpecifier(String string) {
4078                 mString = string;
4079             }
4080 
4081             @Override
4082             public boolean canBeSatisfiedBy(NetworkSpecifier other) {
4083                 if (other instanceof LocalStringNetworkSpecifier) {
4084                     return TextUtils.equals(mString,
4085                             ((LocalStringNetworkSpecifier) other).mString);
4086                 }
4087                 if (other instanceof ConfidentialMatchAllNetworkSpecifier) return true;
4088                 return false;
4089             }
4090 
4091             @Override
4092             public int describeContents() {
4093                 return 0;
4094             }
4095             @Override
4096             public void writeToParcel(Parcel dest, int flags) {}
4097         }
4098 
4099 
4100         NetworkRequest rEmpty1 = newWifiRequestBuilder().build();
4101         NetworkRequest rEmpty2 = newWifiRequestBuilder().setNetworkSpecifier((String) null).build();
4102         NetworkRequest rEmpty3 = newWifiRequestBuilder().setNetworkSpecifier("").build();
4103         NetworkRequest rEmpty4 = newWifiRequestBuilder().setNetworkSpecifier(
4104             (NetworkSpecifier) null).build();
4105         NetworkRequest rFoo = newWifiRequestBuilder().setNetworkSpecifier(
4106                 new LocalStringNetworkSpecifier("foo")).build();
4107         NetworkRequest rBar = newWifiRequestBuilder().setNetworkSpecifier(
4108                 new LocalStringNetworkSpecifier("bar")).build();
4109 
4110         TestNetworkCallback cEmpty1 = new TestNetworkCallback();
4111         TestNetworkCallback cEmpty2 = new TestNetworkCallback();
4112         TestNetworkCallback cEmpty3 = new TestNetworkCallback();
4113         TestNetworkCallback cEmpty4 = new TestNetworkCallback();
4114         TestNetworkCallback cFoo = new TestNetworkCallback();
4115         TestNetworkCallback cBar = new TestNetworkCallback();
4116         TestNetworkCallback[] emptyCallbacks = new TestNetworkCallback[] {
4117                 cEmpty1, cEmpty2, cEmpty3, cEmpty4 };
4118 
4119         mCm.registerNetworkCallback(rEmpty1, cEmpty1);
4120         mCm.registerNetworkCallback(rEmpty2, cEmpty2);
4121         mCm.registerNetworkCallback(rEmpty3, cEmpty3);
4122         mCm.registerNetworkCallback(rEmpty4, cEmpty4);
4123         mCm.registerNetworkCallback(rFoo, cFoo);
4124         mCm.registerNetworkCallback(rBar, cBar);
4125 
4126         LocalStringNetworkSpecifier nsFoo = new LocalStringNetworkSpecifier("foo");
4127         LocalStringNetworkSpecifier nsBar = new LocalStringNetworkSpecifier("bar");
4128 
4129         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4130         mWiFiNetworkAgent.connect(false);
4131         expectAvailableCallbacksUnvalidatedWithSpecifier(mWiFiNetworkAgent, null /* specifier */,
4132                 cEmpty1, cEmpty2, cEmpty3, cEmpty4);
4133         assertNoCallbacks(cFoo, cBar);
4134 
4135         mWiFiNetworkAgent.disconnect();
4136         expectOnLost(mWiFiNetworkAgent, cEmpty1, cEmpty2, cEmpty3, cEmpty4);
4137 
4138         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4139         mWiFiNetworkAgent.setNetworkSpecifier(nsFoo);
4140         mWiFiNetworkAgent.connect(false);
4141         expectAvailableCallbacksUnvalidatedWithSpecifier(mWiFiNetworkAgent, nsFoo,
4142                 cEmpty1, cEmpty2, cEmpty3, cEmpty4, cFoo);
4143         cBar.assertNoCallback();
4144         assertEquals(nsFoo,
4145                 mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier());
4146         assertNoCallbacks(cEmpty1, cEmpty2, cEmpty3, cEmpty4, cFoo);
4147 
4148         mWiFiNetworkAgent.disconnect();
4149         expectOnLost(mWiFiNetworkAgent, cEmpty1, cEmpty2, cEmpty3, cEmpty4, cFoo);
4150 
4151         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4152         mWiFiNetworkAgent.setNetworkSpecifier(nsBar);
4153         mWiFiNetworkAgent.connect(false);
4154         expectAvailableCallbacksUnvalidatedWithSpecifier(mWiFiNetworkAgent, nsBar,
4155                 cEmpty1, cEmpty2, cEmpty3, cEmpty4, cBar);
4156         cFoo.assertNoCallback();
4157         assertEquals(nsBar,
4158                 mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier());
4159 
4160         mWiFiNetworkAgent.disconnect();
4161         expectOnLost(mWiFiNetworkAgent, cEmpty1, cEmpty2, cEmpty3, cEmpty4, cBar);
4162         cFoo.assertNoCallback();
4163 
4164         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4165         mWiFiNetworkAgent.setNetworkSpecifier(new ConfidentialMatchAllNetworkSpecifier());
4166         mWiFiNetworkAgent.connect(false);
4167         expectAvailableCallbacksUnvalidatedWithSpecifier(mWiFiNetworkAgent, null /* specifier */,
4168                 cEmpty1, cEmpty2, cEmpty3, cEmpty4, cFoo, cBar);
4169         assertNull(
4170                 mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier());
4171 
4172         mWiFiNetworkAgent.disconnect();
4173         expectOnLost(mWiFiNetworkAgent, cEmpty1, cEmpty2, cEmpty3, cEmpty4, cFoo, cBar);
4174     }
4175 
4176     /**
4177      * @return the context's attribution tag
4178      */
4179     private String getAttributionTag() {
4180         return mContext.getAttributionTag();
4181     }
4182 
4183     @Test
4184     public void testInvalidNetworkSpecifier() {
4185         assertThrows(IllegalArgumentException.class, () -> {
4186             NetworkRequest.Builder builder = new NetworkRequest.Builder();
4187             builder.setNetworkSpecifier(new MatchAllNetworkSpecifier());
4188         });
4189 
4190         assertThrows(IllegalArgumentException.class, () -> {
4191             NetworkCapabilities networkCapabilities = new NetworkCapabilities();
4192             networkCapabilities.addTransportType(TRANSPORT_WIFI)
4193                     .setNetworkSpecifier(new MatchAllNetworkSpecifier());
4194             mService.requestNetwork(Process.INVALID_UID, networkCapabilities,
4195                     NetworkRequest.Type.REQUEST.ordinal(), null, 0, null,
4196                     ConnectivityManager.TYPE_WIFI, NetworkCallback.FLAG_NONE,
4197                     mContext.getPackageName(), getAttributionTag());
4198         });
4199 
4200         class NonParcelableSpecifier extends NetworkSpecifier {
4201             @Override
4202             public boolean canBeSatisfiedBy(NetworkSpecifier other) {
4203                 return false;
4204             }
4205         };
4206         class ParcelableSpecifier extends NonParcelableSpecifier implements Parcelable {
4207             @Override public int describeContents() { return 0; }
4208             @Override public void writeToParcel(Parcel p, int flags) {}
4209         }
4210 
4211         final NetworkRequest.Builder builder =
4212                 new NetworkRequest.Builder().addTransportType(TRANSPORT_ETHERNET);
4213         assertThrows(ClassCastException.class, () -> {
4214             builder.setNetworkSpecifier(new NonParcelableSpecifier());
4215             Parcel parcelW = Parcel.obtain();
4216             builder.build().writeToParcel(parcelW, 0);
4217         });
4218 
4219         final NetworkRequest nr =
4220                 new NetworkRequest.Builder().addTransportType(TRANSPORT_ETHERNET)
4221                 .setNetworkSpecifier(new ParcelableSpecifier())
4222                 .build();
4223         assertNotNull(nr);
4224 
4225         assertThrows(BadParcelableException.class, () -> {
4226             Parcel parcelW = Parcel.obtain();
4227             nr.writeToParcel(parcelW, 0);
4228             byte[] bytes = parcelW.marshall();
4229             parcelW.recycle();
4230 
4231             Parcel parcelR = Parcel.obtain();
4232             parcelR.unmarshall(bytes, 0, bytes.length);
4233             parcelR.setDataPosition(0);
4234             NetworkRequest rereadNr = NetworkRequest.CREATOR.createFromParcel(parcelR);
4235         });
4236     }
4237 
4238     @Test
4239     public void testNetworkRequestUidSpoofSecurityException() throws Exception {
4240         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4241         mWiFiNetworkAgent.connect(false);
4242         NetworkRequest networkRequest = newWifiRequestBuilder().build();
4243         TestNetworkCallback networkCallback = new TestNetworkCallback();
4244         doThrow(new SecurityException()).when(mAppOpsManager).checkPackage(anyInt(), anyString());
4245         assertThrows(SecurityException.class, () -> {
4246             mCm.requestNetwork(networkRequest, networkCallback);
4247         });
4248     }
4249 
4250     @Test
4251     public void testInvalidSignalStrength() {
4252         NetworkRequest r = new NetworkRequest.Builder()
4253                 .addCapability(NET_CAPABILITY_INTERNET)
4254                 .addTransportType(TRANSPORT_WIFI)
4255                 .setSignalStrength(-75)
4256                 .build();
4257         // Registering a NetworkCallback with signal strength but w/o NETWORK_SIGNAL_STRENGTH_WAKEUP
4258         // permission should get SecurityException.
4259         assertThrows(SecurityException.class, () ->
4260                 mCm.registerNetworkCallback(r, new NetworkCallback()));
4261 
4262         assertThrows(SecurityException.class, () ->
4263                 mCm.registerNetworkCallback(r, PendingIntent.getService(
4264                         mServiceContext, 0 /* requestCode */, new Intent(), FLAG_IMMUTABLE)));
4265 
4266         // Requesting a Network with signal strength should get IllegalArgumentException.
4267         assertThrows(IllegalArgumentException.class, () ->
4268                 mCm.requestNetwork(r, new NetworkCallback()));
4269 
4270         assertThrows(IllegalArgumentException.class, () ->
4271                 mCm.requestNetwork(r, PendingIntent.getService(
4272                         mServiceContext, 0 /* requestCode */, new Intent(), FLAG_IMMUTABLE)));
4273     }
4274 
4275     @Test
4276     public void testRegisterDefaultNetworkCallback() throws Exception {
4277         // NETWORK_SETTINGS is necessary to call registerSystemDefaultNetworkCallback.
4278         mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_GRANTED);
4279 
4280         final TestNetworkCallback defaultNetworkCallback = new TestNetworkCallback();
4281         mCm.registerDefaultNetworkCallback(defaultNetworkCallback);
4282         defaultNetworkCallback.assertNoCallback();
4283 
4284         final Handler handler = new Handler(ConnectivityThread.getInstanceLooper());
4285         final TestNetworkCallback systemDefaultCallback = new TestNetworkCallback();
4286         mCm.registerSystemDefaultNetworkCallback(systemDefaultCallback, handler);
4287         systemDefaultCallback.assertNoCallback();
4288 
4289         // Create a TRANSPORT_CELLULAR request to keep the mobile interface up
4290         // whenever Wi-Fi is up. Without this, the mobile network agent is
4291         // reaped before any other activity can take place.
4292         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
4293         final NetworkRequest cellRequest = new NetworkRequest.Builder()
4294                 .addTransportType(TRANSPORT_CELLULAR).build();
4295         mCm.requestNetwork(cellRequest, cellNetworkCallback);
4296         cellNetworkCallback.assertNoCallback();
4297 
4298         // Bring up cell and expect CALLBACK_AVAILABLE.
4299         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
4300         mCellNetworkAgent.connect(true);
4301         cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
4302         defaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
4303         systemDefaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
4304         assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
4305         assertEquals(systemDefaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
4306 
4307         // Bring up wifi and expect CALLBACK_AVAILABLE.
4308         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4309         mWiFiNetworkAgent.connect(true);
4310         cellNetworkCallback.assertNoCallback();
4311         defaultNetworkCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
4312         systemDefaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
4313         assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
4314         assertEquals(systemDefaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
4315 
4316         // Bring down cell. Expect no default network callback, since it wasn't the default.
4317         mCellNetworkAgent.disconnect();
4318         cellNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
4319         defaultNetworkCallback.assertNoCallback();
4320         systemDefaultCallback.assertNoCallback();
4321         assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
4322         assertEquals(systemDefaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
4323 
4324         // Bring up cell. Expect no default network callback, since it won't be the default.
4325         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
4326         mCellNetworkAgent.connect(true);
4327         cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
4328         defaultNetworkCallback.assertNoCallback();
4329         systemDefaultCallback.assertNoCallback();
4330         assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
4331         assertEquals(systemDefaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
4332 
4333         // Bring down wifi. Expect the default network callback to notified of LOST wifi
4334         // followed by AVAILABLE cell.
4335         mWiFiNetworkAgent.disconnect();
4336         cellNetworkCallback.assertNoCallback();
4337         defaultNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
4338         defaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
4339         systemDefaultCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
4340         systemDefaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
4341         mCellNetworkAgent.disconnect();
4342         cellNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
4343         defaultNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
4344         systemDefaultCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
4345         waitForIdle();
4346         assertEquals(null, mCm.getActiveNetwork());
4347 
4348         mMockVpn.establishForMyUid();
4349         assertUidRangesUpdatedForMyUid(true);
4350         defaultNetworkCallback.expectAvailableThenValidatedCallbacks(mMockVpn);
4351         systemDefaultCallback.assertNoCallback();
4352         assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
4353         assertEquals(null, systemDefaultCallback.getLastAvailableNetwork());
4354 
4355         mMockVpn.disconnect();
4356         defaultNetworkCallback.expectCallback(CallbackEntry.LOST, mMockVpn);
4357         systemDefaultCallback.assertNoCallback();
4358         waitForIdle();
4359         assertEquals(null, mCm.getActiveNetwork());
4360     }
4361 
4362     @Test
4363     public void testAdditionalStateCallbacks() throws Exception {
4364         // File a network request for mobile.
4365         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
4366         final NetworkRequest cellRequest = new NetworkRequest.Builder()
4367                 .addTransportType(TRANSPORT_CELLULAR).build();
4368         mCm.requestNetwork(cellRequest, cellNetworkCallback);
4369 
4370         // Bring up the mobile network.
4371         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
4372         mCellNetworkAgent.connect(true);
4373 
4374         // We should get onAvailable(), onCapabilitiesChanged(), and
4375         // onLinkPropertiesChanged() in rapid succession. Additionally, we
4376         // should get onCapabilitiesChanged() when the mobile network validates.
4377         cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
4378         cellNetworkCallback.assertNoCallback();
4379 
4380         // Update LinkProperties.
4381         final LinkProperties lp = new LinkProperties();
4382         lp.setInterfaceName("foonet_data0");
4383         mCellNetworkAgent.sendLinkProperties(lp);
4384         // We should get onLinkPropertiesChanged().
4385         cellNetworkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED,
4386                 mCellNetworkAgent);
4387         cellNetworkCallback.assertNoCallback();
4388 
4389         // Suspend the network.
4390         mCellNetworkAgent.suspend();
4391         cellNetworkCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_SUSPENDED,
4392                 mCellNetworkAgent);
4393         cellNetworkCallback.expectCallback(CallbackEntry.SUSPENDED, mCellNetworkAgent);
4394         cellNetworkCallback.assertNoCallback();
4395         assertEquals(NetworkInfo.State.SUSPENDED, mCm.getActiveNetworkInfo().getState());
4396 
4397         // Register a garden variety default network request.
4398         TestNetworkCallback dfltNetworkCallback = new TestNetworkCallback();
4399         mCm.registerDefaultNetworkCallback(dfltNetworkCallback);
4400         // We should get onAvailable(), onCapabilitiesChanged(), onLinkPropertiesChanged(),
4401         // as well as onNetworkSuspended() in rapid succession.
4402         dfltNetworkCallback.expectAvailableAndSuspendedCallbacks(mCellNetworkAgent, true);
4403         dfltNetworkCallback.assertNoCallback();
4404         mCm.unregisterNetworkCallback(dfltNetworkCallback);
4405 
4406         mCellNetworkAgent.resume();
4407         cellNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_NOT_SUSPENDED,
4408                 mCellNetworkAgent);
4409         cellNetworkCallback.expectCallback(CallbackEntry.RESUMED, mCellNetworkAgent);
4410         cellNetworkCallback.assertNoCallback();
4411         assertEquals(NetworkInfo.State.CONNECTED, mCm.getActiveNetworkInfo().getState());
4412 
4413         dfltNetworkCallback = new TestNetworkCallback();
4414         mCm.registerDefaultNetworkCallback(dfltNetworkCallback);
4415         // This time onNetworkSuspended should not be called.
4416         dfltNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
4417         dfltNetworkCallback.assertNoCallback();
4418 
4419         mCm.unregisterNetworkCallback(dfltNetworkCallback);
4420         mCm.unregisterNetworkCallback(cellNetworkCallback);
4421     }
4422 
4423     @Test
4424     public void testRegisterPrivilegedDefaultCallbacksRequireNetworkSettings() throws Exception {
4425         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
4426         mCellNetworkAgent.connect(false /* validated */);
4427 
4428         final Handler handler = new Handler(ConnectivityThread.getInstanceLooper());
4429         final TestNetworkCallback callback = new TestNetworkCallback();
4430         assertThrows(SecurityException.class,
4431                 () -> mCm.registerSystemDefaultNetworkCallback(callback, handler));
4432         callback.assertNoCallback();
4433         assertThrows(SecurityException.class,
4434                 () -> mCm.registerDefaultNetworkCallbackForUid(APP1_UID, callback, handler));
4435         callback.assertNoCallback();
4436 
4437         mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_GRANTED);
4438         mCm.registerSystemDefaultNetworkCallback(callback, handler);
4439         callback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
4440         mCm.unregisterNetworkCallback(callback);
4441 
4442         mCm.registerDefaultNetworkCallbackForUid(APP1_UID, callback, handler);
4443         callback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
4444         mCm.unregisterNetworkCallback(callback);
4445     }
4446 
4447     @Test
4448     public void testNetworkCallbackWithNullUids() throws Exception {
4449         final NetworkRequest request = new NetworkRequest.Builder()
4450                 .removeCapability(NET_CAPABILITY_NOT_VPN)
4451                 .build();
4452         final TestNetworkCallback callback = new TestNetworkCallback();
4453         mCm.registerNetworkCallback(request, callback);
4454 
4455         // Attempt to file a callback for networks applying to another UID. This does not actually
4456         // work, because this code does not currently have permission to do so. The callback behaves
4457         // exactly the same as the one registered just above.
4458         final int otherUid = UserHandle.getUid(RESTRICTED_USER, VPN_UID);
4459         final NetworkRequest otherUidRequest = new NetworkRequest.Builder()
4460                 .removeCapability(NET_CAPABILITY_NOT_VPN)
4461                 .setUids(UidRange.toIntRanges(uidRangesForUids(otherUid)))
4462                 .build();
4463         final TestNetworkCallback otherUidCallback = new TestNetworkCallback();
4464         mCm.registerNetworkCallback(otherUidRequest, otherUidCallback);
4465 
4466         final NetworkRequest includeOtherUidsRequest = new NetworkRequest.Builder()
4467                 .removeCapability(NET_CAPABILITY_NOT_VPN)
4468                 .setIncludeOtherUidNetworks(true)
4469                 .build();
4470         final TestNetworkCallback includeOtherUidsCallback = new TestNetworkCallback();
4471         mCm.registerNetworkCallback(includeOtherUidsRequest, includeOtherUidsCallback);
4472 
4473         // Both callbacks see a network with no specifier that applies to their UID.
4474         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4475         mWiFiNetworkAgent.connect(false /* validated */);
4476         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
4477         otherUidCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
4478         includeOtherUidsCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
4479         mWiFiNetworkAgent.disconnect();
4480         callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
4481         otherUidCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
4482         includeOtherUidsCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
4483 
4484         // Only the includeOtherUidsCallback sees a VPN that does not apply to its UID.
4485         final UidRange range = UidRange.createForUser(UserHandle.of(RESTRICTED_USER));
4486         final Set<UidRange> vpnRanges = Collections.singleton(range);
4487         mMockVpn.establish(new LinkProperties(), VPN_UID, vpnRanges);
4488         includeOtherUidsCallback.expectAvailableThenValidatedCallbacks(mMockVpn);
4489         callback.assertNoCallback();
4490         otherUidCallback.assertNoCallback();
4491 
4492         mMockVpn.disconnect();
4493         includeOtherUidsCallback.expectCallback(CallbackEntry.LOST, mMockVpn);
4494         callback.assertNoCallback();
4495         otherUidCallback.assertNoCallback();
4496     }
4497 
4498     private static class RedactableNetworkSpecifier extends NetworkSpecifier {
4499         public static final int ID_INVALID = -1;
4500 
4501         public final int networkId;
4502 
4503         RedactableNetworkSpecifier(int networkId) {
4504             this.networkId = networkId;
4505         }
4506 
4507         @Override
4508         public boolean canBeSatisfiedBy(NetworkSpecifier other) {
4509             return other instanceof RedactableNetworkSpecifier
4510                     && this.networkId == ((RedactableNetworkSpecifier) other).networkId;
4511         }
4512 
4513         @Override
4514         public NetworkSpecifier redact() {
4515             return new RedactableNetworkSpecifier(ID_INVALID);
4516         }
4517     }
4518 
4519     @Test
4520     public void testNetworkCallbackWithNullUidsRedactsSpecifier() throws Exception {
4521         final RedactableNetworkSpecifier specifier = new RedactableNetworkSpecifier(42);
4522         final NetworkRequest request = new NetworkRequest.Builder()
4523                 .addCapability(NET_CAPABILITY_INTERNET)
4524                 .addTransportType(TRANSPORT_WIFI)
4525                 .setNetworkSpecifier(specifier)
4526                 .build();
4527         final TestNetworkCallback callback = new TestNetworkCallback();
4528         mCm.registerNetworkCallback(request, callback);
4529 
4530         // Attempt to file a callback for networks applying to another UID. This does not actually
4531         // work, because this code does not currently have permission to do so. The callback behaves
4532         // exactly the same as the one registered just above.
4533         final int otherUid = UserHandle.getUid(RESTRICTED_USER, VPN_UID);
4534         final NetworkRequest otherUidRequest = new NetworkRequest.Builder()
4535                 .addCapability(NET_CAPABILITY_INTERNET)
4536                 .addTransportType(TRANSPORT_WIFI)
4537                 .setNetworkSpecifier(specifier)
4538                 .setUids(UidRange.toIntRanges(uidRangesForUids(otherUid)))
4539                 .build();
4540         final TestNetworkCallback otherUidCallback = new TestNetworkCallback();
4541         mCm.registerNetworkCallback(otherUidRequest, otherUidCallback);
4542 
4543         final NetworkRequest includeOtherUidsRequest = new NetworkRequest.Builder()
4544                 .addCapability(NET_CAPABILITY_INTERNET)
4545                 .addTransportType(TRANSPORT_WIFI)
4546                 .setNetworkSpecifier(specifier)
4547                 .setIncludeOtherUidNetworks(true)
4548                 .build();
4549         final TestNetworkCallback includeOtherUidsCallback = new TestNetworkCallback();
4550         mCm.registerNetworkCallback(includeOtherUidsRequest, callback);
4551 
4552         // Only the regular callback sees the network, because callbacks filed with no UID have
4553         // their specifiers redacted.
4554         final LinkProperties emptyLp = new LinkProperties();
4555         final NetworkCapabilities ncTemplate = new NetworkCapabilities()
4556                 .addTransportType(TRANSPORT_WIFI)
4557                 .setNetworkSpecifier(specifier);
4558         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, emptyLp, ncTemplate);
4559         mWiFiNetworkAgent.connect(false /* validated */);
4560         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
4561         otherUidCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
4562         includeOtherUidsCallback.assertNoCallback();
4563     }
4564 
4565     private void setCaptivePortalMode(int mode) {
4566         ContentResolver cr = mServiceContext.getContentResolver();
4567         Settings.Global.putInt(cr, ConnectivitySettingsManager.CAPTIVE_PORTAL_MODE, mode);
4568     }
4569 
4570     private void setAlwaysOnNetworks(boolean enable) {
4571         ContentResolver cr = mServiceContext.getContentResolver();
4572         Settings.Global.putInt(cr, ConnectivitySettingsManager.MOBILE_DATA_ALWAYS_ON,
4573                 enable ? 1 : 0);
4574         mService.updateAlwaysOnNetworks();
4575         waitForIdle();
4576     }
4577 
4578     private void setPrivateDnsSettings(int mode, String specifier) {
4579         ConnectivitySettingsManager.setPrivateDnsMode(mServiceContext, mode);
4580         ConnectivitySettingsManager.setPrivateDnsHostname(mServiceContext, specifier);
4581         mService.updatePrivateDnsSettings();
4582         waitForIdle();
4583     }
4584 
4585     private boolean isForegroundNetwork(TestNetworkAgentWrapper network) {
4586         NetworkCapabilities nc = mCm.getNetworkCapabilities(network.getNetwork());
4587         assertNotNull(nc);
4588         return nc.hasCapability(NET_CAPABILITY_FOREGROUND);
4589     }
4590 
4591     @Test
4592     public void testBackgroundNetworks() throws Exception {
4593         // Create a cellular background request.
4594         grantUsingBackgroundNetworksPermissionForUid(Binder.getCallingUid());
4595         final TestNetworkCallback cellBgCallback = new TestNetworkCallback();
4596         mCm.requestBackgroundNetwork(new NetworkRequest.Builder()
4597                 .addTransportType(TRANSPORT_CELLULAR).build(),
4598                 cellBgCallback, mCsHandlerThread.getThreadHandler());
4599 
4600         // Make callbacks for monitoring.
4601         final NetworkRequest request = new NetworkRequest.Builder().build();
4602         final NetworkRequest fgRequest = new NetworkRequest.Builder()
4603                 .addCapability(NET_CAPABILITY_FOREGROUND).build();
4604         final TestNetworkCallback callback = new TestNetworkCallback();
4605         final TestNetworkCallback fgCallback = new TestNetworkCallback();
4606         mCm.registerNetworkCallback(request, callback);
4607         mCm.registerNetworkCallback(fgRequest, fgCallback);
4608 
4609         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
4610         mCellNetworkAgent.connect(true);
4611         callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
4612         fgCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
4613         assertTrue(isForegroundNetwork(mCellNetworkAgent));
4614 
4615         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4616         mWiFiNetworkAgent.connect(true);
4617 
4618         // When wifi connects, cell lingers.
4619         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
4620         callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
4621         callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
4622         fgCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
4623         fgCallback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
4624         fgCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
4625         assertTrue(isForegroundNetwork(mCellNetworkAgent));
4626         assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
4627 
4628         // When lingering is complete, cell is still there but is now in the background.
4629         waitForIdle();
4630         int timeoutMs = TEST_LINGER_DELAY_MS + TEST_LINGER_DELAY_MS / 4;
4631         fgCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent, timeoutMs);
4632         // Expect a network capabilities update sans FOREGROUND.
4633         callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
4634         assertFalse(isForegroundNetwork(mCellNetworkAgent));
4635         assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
4636 
4637         // File a cell request and check that cell comes into the foreground.
4638         final NetworkRequest cellRequest = new NetworkRequest.Builder()
4639                 .addTransportType(TRANSPORT_CELLULAR).build();
4640         final TestNetworkCallback cellCallback = new TestNetworkCallback();
4641         mCm.requestNetwork(cellRequest, cellCallback);
4642         cellCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
4643         fgCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
4644         // Expect a network capabilities update with FOREGROUND, because the most recent
4645         // request causes its state to change.
4646         cellCallback.expectCapabilitiesWith(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
4647         callback.expectCapabilitiesWith(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
4648         assertTrue(isForegroundNetwork(mCellNetworkAgent));
4649         assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
4650 
4651         // Release the request. The network immediately goes into the background, since it was not
4652         // lingering.
4653         mCm.unregisterNetworkCallback(cellCallback);
4654         fgCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
4655         // Expect a network capabilities update sans FOREGROUND.
4656         callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
4657         assertFalse(isForegroundNetwork(mCellNetworkAgent));
4658         assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
4659 
4660         // Disconnect wifi and check that cell is foreground again.
4661         mWiFiNetworkAgent.disconnect();
4662         callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
4663         fgCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
4664         fgCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
4665         assertTrue(isForegroundNetwork(mCellNetworkAgent));
4666 
4667         mCm.unregisterNetworkCallback(callback);
4668         mCm.unregisterNetworkCallback(fgCallback);
4669         mCm.unregisterNetworkCallback(cellBgCallback);
4670     }
4671 
4672     @Ignore // This test has instrinsic chances of spurious failures: ignore for continuous testing.
4673     public void benchmarkRequestRegistrationAndCallbackDispatch() throws Exception {
4674         // TODO: turn this unit test into a real benchmarking test.
4675         // Benchmarks connecting and switching performance in the presence of a large number of
4676         // NetworkRequests.
4677         // 1. File NUM_REQUESTS requests.
4678         // 2. Have a network connect. Wait for NUM_REQUESTS onAvailable callbacks to fire.
4679         // 3. Have a new network connect and outscore the previous. Wait for NUM_REQUESTS onLosing
4680         //    and NUM_REQUESTS onAvailable callbacks to fire.
4681         // See how long it took.
4682         final int NUM_REQUESTS = 90;
4683         final int REGISTER_TIME_LIMIT_MS = 200;
4684         final int CONNECT_TIME_LIMIT_MS = 60;
4685         final int SWITCH_TIME_LIMIT_MS = 60;
4686         final int UNREGISTER_TIME_LIMIT_MS = 20;
4687 
4688         final NetworkRequest request = new NetworkRequest.Builder().clearCapabilities().build();
4689         final NetworkCallback[] callbacks = new NetworkCallback[NUM_REQUESTS];
4690         final CountDownLatch availableLatch = new CountDownLatch(NUM_REQUESTS);
4691         final CountDownLatch losingLatch = new CountDownLatch(NUM_REQUESTS);
4692 
4693         for (int i = 0; i < NUM_REQUESTS; i++) {
4694             callbacks[i] = new NetworkCallback() {
4695                 @Override public void onAvailable(Network n) { availableLatch.countDown(); }
4696                 @Override public void onLosing(Network n, int t) { losingLatch.countDown(); }
4697             };
4698         }
4699 
4700         assertRunsInAtMost("Registering callbacks", REGISTER_TIME_LIMIT_MS, () -> {
4701             for (NetworkCallback cb : callbacks) {
4702                 mCm.registerNetworkCallback(request, cb);
4703             }
4704         });
4705 
4706         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
4707         // Don't request that the network validate, because otherwise connect() will block until
4708         // the network gets NET_CAPABILITY_VALIDATED, after all the callbacks below have fired,
4709         // and we won't actually measure anything.
4710         mCellNetworkAgent.connect(false);
4711 
4712         long onAvailableDispatchingDuration = durationOf(() -> {
4713             await(availableLatch, 10 * CONNECT_TIME_LIMIT_MS);
4714         });
4715         Log.d(TAG, String.format("Dispatched %d of %d onAvailable callbacks in %dms",
4716                 NUM_REQUESTS - availableLatch.getCount(), NUM_REQUESTS,
4717                 onAvailableDispatchingDuration));
4718         assertTrue(String.format("Dispatching %d onAvailable callbacks in %dms, expected %dms",
4719                 NUM_REQUESTS, onAvailableDispatchingDuration, CONNECT_TIME_LIMIT_MS),
4720                 onAvailableDispatchingDuration <= CONNECT_TIME_LIMIT_MS);
4721 
4722         // Give wifi a high enough score that we'll linger cell when wifi comes up.
4723         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4724         mWiFiNetworkAgent.adjustScore(40);
4725         mWiFiNetworkAgent.connect(false);
4726 
4727         long onLostDispatchingDuration = durationOf(() -> {
4728             await(losingLatch, 10 * SWITCH_TIME_LIMIT_MS);
4729         });
4730         Log.d(TAG, String.format("Dispatched %d of %d onLosing callbacks in %dms",
4731                 NUM_REQUESTS - losingLatch.getCount(), NUM_REQUESTS, onLostDispatchingDuration));
4732         assertTrue(String.format("Dispatching %d onLosing callbacks in %dms, expected %dms",
4733                 NUM_REQUESTS, onLostDispatchingDuration, SWITCH_TIME_LIMIT_MS),
4734                 onLostDispatchingDuration <= SWITCH_TIME_LIMIT_MS);
4735 
4736         assertRunsInAtMost("Unregistering callbacks", UNREGISTER_TIME_LIMIT_MS, () -> {
4737             for (NetworkCallback cb : callbacks) {
4738                 mCm.unregisterNetworkCallback(cb);
4739             }
4740         });
4741     }
4742 
4743     @Test
4744     public void testMobileDataAlwaysOn() throws Exception {
4745         grantUsingBackgroundNetworksPermissionForUid(Binder.getCallingUid());
4746         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
4747         final NetworkRequest cellRequest = new NetworkRequest.Builder()
4748                 .addTransportType(TRANSPORT_CELLULAR).build();
4749         mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
4750 
4751         final HandlerThread handlerThread = new HandlerThread("MobileDataAlwaysOnFactory");
4752         handlerThread.start();
4753         NetworkCapabilities filter = new NetworkCapabilities()
4754                 .addTransportType(TRANSPORT_CELLULAR)
4755                 .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
4756                 .addCapability(NET_CAPABILITY_INTERNET);
4757         final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
4758                 mServiceContext, "testFactory", filter, mCsHandlerThread);
4759         testFactory.setScoreFilter(40);
4760 
4761         // Register the factory and expect it to start looking for a network.
4762         testFactory.register();
4763 
4764         try {
4765             // Expect the factory to receive the default network request.
4766             testFactory.expectRequestAdd();
4767             testFactory.assertRequestCountEquals(1);
4768             assertTrue(testFactory.getMyStartRequested());
4769 
4770             // Bring up wifi. The factory stops looking for a network.
4771             mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4772             // Score 60 - 40 penalty for not validated yet, then 60 when it validates
4773             mWiFiNetworkAgent.connect(true);
4774             // The network connects with a low score, so the offer can still beat it and
4775             // nothing happens. Then the network validates, and the offer with its filter score
4776             // of 40 can no longer beat it and the request is removed.
4777             testFactory.expectRequestRemove();
4778             testFactory.assertRequestCountEquals(0);
4779 
4780             assertFalse(testFactory.getMyStartRequested());
4781 
4782             // Turn on mobile data always on. This request will not match the wifi request, so
4783             // it will be sent to the test factory whose filters allow to see it.
4784             setAlwaysOnNetworks(true);
4785             testFactory.expectRequestAdd();
4786             testFactory.assertRequestCountEquals(1);
4787 
4788             assertTrue(testFactory.getMyStartRequested());
4789 
4790             // Bring up cell data and check that the factory stops looking.
4791             assertLength(1, mCm.getAllNetworks());
4792             mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
4793             mCellNetworkAgent.connect(false);
4794             cellNetworkCallback.expectAvailableCallbacks(mCellNetworkAgent, false, false, false,
4795                     TEST_CALLBACK_TIMEOUT_MS);
4796             // When cell connects, it will satisfy the "mobile always on request" right away
4797             // by virtue of being the only network that can satisfy the request. However, its
4798             // score is low (50 - 40 = 10) so the test factory can still hope to beat it.
4799             expectNoRequestChanged(testFactory);
4800 
4801             // Next, cell validates. This gives it a score of 50 and the test factory can't
4802             // hope to beat that according to its filters. It will see the message that its
4803             // offer is now unnecessary.
4804             mCellNetworkAgent.setNetworkValid(true);
4805             // Need a trigger point to let NetworkMonitor tell ConnectivityService that network is
4806             // validated – see testPartialConnectivity.
4807             mCm.reportNetworkConnectivity(mCellNetworkAgent.getNetwork(), true);
4808             cellNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mCellNetworkAgent);
4809             testFactory.expectRequestRemove();
4810             testFactory.assertRequestCountEquals(0);
4811             // Accordingly, the factory shouldn't be started.
4812             assertFalse(testFactory.getMyStartRequested());
4813 
4814             // Check that cell data stays up.
4815             waitForIdle();
4816             verifyActiveNetwork(TRANSPORT_WIFI);
4817             assertLength(2, mCm.getAllNetworks());
4818 
4819             // Cell disconnects. There is still the "mobile data always on" request outstanding,
4820             // and the test factory should see it now that it isn't hopelessly outscored.
4821             mCellNetworkAgent.disconnect();
4822             cellNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
4823             assertLength(1, mCm.getAllNetworks());
4824             testFactory.expectRequestAdd();
4825             testFactory.assertRequestCountEquals(1);
4826 
4827             // Reconnect cell validated, see the request disappear again. Then withdraw the
4828             // mobile always on request. This will tear down cell, and there shouldn't be a
4829             // blip where the test factory briefly sees the request or anything.
4830             mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
4831             mCellNetworkAgent.connect(true);
4832             cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
4833             assertLength(2, mCm.getAllNetworks());
4834             testFactory.expectRequestRemove();
4835             testFactory.assertRequestCountEquals(0);
4836             setAlwaysOnNetworks(false);
4837             expectNoRequestChanged(testFactory);
4838             testFactory.assertRequestCountEquals(0);
4839             assertFalse(testFactory.getMyStartRequested());
4840             // ...  and cell data to be torn down immediately since it is no longer nascent.
4841             cellNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
4842             waitForIdle();
4843             assertLength(1, mCm.getAllNetworks());
4844         } finally {
4845             testFactory.terminate();
4846             mCm.unregisterNetworkCallback(cellNetworkCallback);
4847             handlerThread.quit();
4848         }
4849     }
4850 
4851     @Test
4852     public void testSetAllowBadWifiUntil() throws Exception {
4853         runAsShell(NETWORK_SETTINGS,
4854                 () -> mService.setTestAllowBadWifiUntil(System.currentTimeMillis() + 5_000L));
4855         waitForIdle();
4856         testAvoidBadWifiConfig_controlledBySettings();
4857 
4858         runAsShell(NETWORK_SETTINGS,
4859                 () -> mService.setTestAllowBadWifiUntil(System.currentTimeMillis() - 5_000L));
4860         waitForIdle();
4861         testAvoidBadWifiConfig_ignoreSettings();
4862     }
4863 
4864     private void testAvoidBadWifiConfig_controlledBySettings() {
4865         final ContentResolver cr = mServiceContext.getContentResolver();
4866         final String settingName = ConnectivitySettingsManager.NETWORK_AVOID_BAD_WIFI;
4867 
4868         Settings.Global.putString(cr, settingName, "0");
4869         mPolicyTracker.reevaluate();
4870         waitForIdle();
4871         assertFalse(mService.avoidBadWifi());
4872         assertFalse(mPolicyTracker.shouldNotifyWifiUnvalidated());
4873 
4874         Settings.Global.putString(cr, settingName, "1");
4875         mPolicyTracker.reevaluate();
4876         waitForIdle();
4877         assertTrue(mService.avoidBadWifi());
4878         assertFalse(mPolicyTracker.shouldNotifyWifiUnvalidated());
4879 
4880         Settings.Global.putString(cr, settingName, null);
4881         mPolicyTracker.reevaluate();
4882         waitForIdle();
4883         assertFalse(mService.avoidBadWifi());
4884         assertTrue(mPolicyTracker.shouldNotifyWifiUnvalidated());
4885     }
4886 
4887     private void testAvoidBadWifiConfig_ignoreSettings() {
4888         final ContentResolver cr = mServiceContext.getContentResolver();
4889         final String settingName = ConnectivitySettingsManager.NETWORK_AVOID_BAD_WIFI;
4890 
4891         String[] values = new String[] {null, "0", "1"};
4892         for (int i = 0; i < values.length; i++) {
4893             Settings.Global.putString(cr, settingName, values[i]);
4894             mPolicyTracker.reevaluate();
4895             waitForIdle();
4896             String msg = String.format("config=false, setting=%s", values[i]);
4897             assertTrue(mService.avoidBadWifi());
4898             assertFalse(msg, mPolicyTracker.shouldNotifyWifiUnvalidated());
4899         }
4900     }
4901 
4902     @Test
4903     public void testAvoidBadWifiSetting() throws Exception {
4904         final ContentResolver cr = mServiceContext.getContentResolver();
4905         final String settingName = ConnectivitySettingsManager.NETWORK_AVOID_BAD_WIFI;
4906 
4907         doReturn(1).when(mResources).getInteger(R.integer.config_networkAvoidBadWifi);
4908         testAvoidBadWifiConfig_ignoreSettings();
4909 
4910         doReturn(0).when(mResources).getInteger(R.integer.config_networkAvoidBadWifi);
4911         testAvoidBadWifiConfig_controlledBySettings();
4912     }
4913 
4914     @Ignore("Refactoring in progress b/178071397")
4915     @Test
4916     public void testAvoidBadWifi() throws Exception {
4917         final ContentResolver cr = mServiceContext.getContentResolver();
4918 
4919         // Pretend we're on a carrier that restricts switching away from bad wifi.
4920         doReturn(0).when(mResources).getInteger(R.integer.config_networkAvoidBadWifi);
4921 
4922         // File a request for cell to ensure it doesn't go down.
4923         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
4924         final NetworkRequest cellRequest = new NetworkRequest.Builder()
4925                 .addTransportType(TRANSPORT_CELLULAR).build();
4926         mCm.requestNetwork(cellRequest, cellNetworkCallback);
4927 
4928         TestNetworkCallback defaultCallback = new TestNetworkCallback();
4929         mCm.registerDefaultNetworkCallback(defaultCallback);
4930 
4931         NetworkRequest validatedWifiRequest = new NetworkRequest.Builder()
4932                 .addTransportType(TRANSPORT_WIFI)
4933                 .addCapability(NET_CAPABILITY_VALIDATED)
4934                 .build();
4935         TestNetworkCallback validatedWifiCallback = new TestNetworkCallback();
4936         mCm.registerNetworkCallback(validatedWifiRequest, validatedWifiCallback);
4937 
4938         Settings.Global.putInt(cr, ConnectivitySettingsManager.NETWORK_AVOID_BAD_WIFI, 0);
4939         mPolicyTracker.reevaluate();
4940 
4941         // Bring up validated cell.
4942         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
4943         mCellNetworkAgent.connect(true);
4944         cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
4945         defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
4946         Network cellNetwork = mCellNetworkAgent.getNetwork();
4947 
4948         // Bring up validated wifi.
4949         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4950         mWiFiNetworkAgent.connect(true);
4951         defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
4952         validatedWifiCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
4953         Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
4954 
4955         // Fail validation on wifi.
4956         mWiFiNetworkAgent.setNetworkInvalid(false /* isStrictMode */);
4957         mCm.reportNetworkConnectivity(wifiNetwork, false);
4958         defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
4959         validatedWifiCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
4960 
4961         // Because avoid bad wifi is off, we don't switch to cellular.
4962         defaultCallback.assertNoCallback();
4963         assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
4964                 NET_CAPABILITY_VALIDATED));
4965         assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
4966                 NET_CAPABILITY_VALIDATED));
4967         assertEquals(mCm.getActiveNetwork(), wifiNetwork);
4968 
4969         // Simulate switching to a carrier that does not restrict avoiding bad wifi, and expect
4970         // that we switch back to cell.
4971         doReturn(1).when(mResources).getInteger(R.integer.config_networkAvoidBadWifi);
4972         mPolicyTracker.reevaluate();
4973         defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
4974         assertEquals(mCm.getActiveNetwork(), cellNetwork);
4975 
4976         // Switch back to a restrictive carrier.
4977         doReturn(0).when(mResources).getInteger(R.integer.config_networkAvoidBadWifi);
4978         mPolicyTracker.reevaluate();
4979         defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
4980         assertEquals(mCm.getActiveNetwork(), wifiNetwork);
4981 
4982         // Simulate the user selecting "switch" on the dialog, and check that we switch to cell.
4983         mCm.setAvoidUnvalidated(wifiNetwork);
4984         defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
4985         assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
4986                 NET_CAPABILITY_VALIDATED));
4987         assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
4988                 NET_CAPABILITY_VALIDATED));
4989         assertEquals(mCm.getActiveNetwork(), cellNetwork);
4990 
4991         // Disconnect and reconnect wifi to clear the one-time switch above.
4992         mWiFiNetworkAgent.disconnect();
4993         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4994         mWiFiNetworkAgent.connect(true);
4995         defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
4996         validatedWifiCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
4997         wifiNetwork = mWiFiNetworkAgent.getNetwork();
4998 
4999         // Fail validation on wifi and expect the dialog to appear.
5000         mWiFiNetworkAgent.setNetworkInvalid(false /* isStrictMode */);
5001         mCm.reportNetworkConnectivity(wifiNetwork, false);
5002         defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
5003         validatedWifiCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
5004 
5005         // Simulate the user selecting "switch" and checking the don't ask again checkbox.
5006         Settings.Global.putInt(cr, ConnectivitySettingsManager.NETWORK_AVOID_BAD_WIFI, 1);
5007         mPolicyTracker.reevaluate();
5008 
5009         // We now switch to cell.
5010         defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
5011         assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
5012                 NET_CAPABILITY_VALIDATED));
5013         assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
5014                 NET_CAPABILITY_VALIDATED));
5015         assertEquals(mCm.getActiveNetwork(), cellNetwork);
5016 
5017         // Simulate the user turning the cellular fallback setting off and then on.
5018         // We switch to wifi and then to cell.
5019         Settings.Global.putString(cr, ConnectivitySettingsManager.NETWORK_AVOID_BAD_WIFI, null);
5020         mPolicyTracker.reevaluate();
5021         defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
5022         assertEquals(mCm.getActiveNetwork(), wifiNetwork);
5023         Settings.Global.putInt(cr, ConnectivitySettingsManager.NETWORK_AVOID_BAD_WIFI, 1);
5024         mPolicyTracker.reevaluate();
5025         defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
5026         assertEquals(mCm.getActiveNetwork(), cellNetwork);
5027 
5028         // If cell goes down, we switch to wifi.
5029         mCellNetworkAgent.disconnect();
5030         defaultCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
5031         defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
5032         validatedWifiCallback.assertNoCallback();
5033 
5034         mCm.unregisterNetworkCallback(cellNetworkCallback);
5035         mCm.unregisterNetworkCallback(validatedWifiCallback);
5036         mCm.unregisterNetworkCallback(defaultCallback);
5037     }
5038 
5039     @Test
5040     public void testMeteredMultipathPreferenceSetting() throws Exception {
5041         final ContentResolver cr = mServiceContext.getContentResolver();
5042         final String settingName = ConnectivitySettingsManager.NETWORK_METERED_MULTIPATH_PREFERENCE;
5043 
5044         for (int config : Arrays.asList(0, 3, 2)) {
5045             for (String setting: Arrays.asList(null, "0", "2", "1")) {
5046                 mPolicyTracker.mConfigMeteredMultipathPreference = config;
5047                 Settings.Global.putString(cr, settingName, setting);
5048                 mPolicyTracker.reevaluate();
5049                 waitForIdle();
5050 
5051                 final int expected = (setting != null) ? Integer.parseInt(setting) : config;
5052                 String msg = String.format("config=%d, setting=%s", config, setting);
5053                 assertEquals(msg, expected, mCm.getMultipathPreference(null));
5054             }
5055         }
5056     }
5057 
5058     /**
5059      * Validate that a satisfied network request does not trigger onUnavailable() once the
5060      * time-out period expires.
5061      */
5062     @Test
5063     public void testSatisfiedNetworkRequestDoesNotTriggerOnUnavailable() throws Exception {
5064         NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
5065                 NetworkCapabilities.TRANSPORT_WIFI).build();
5066         final TestNetworkCallback networkCallback = new TestNetworkCallback();
5067         mCm.requestNetwork(nr, networkCallback, TEST_REQUEST_TIMEOUT_MS);
5068 
5069         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
5070         mWiFiNetworkAgent.connect(false);
5071         networkCallback.expectAvailableCallbacks(mWiFiNetworkAgent, false, false, false,
5072                 TEST_CALLBACK_TIMEOUT_MS);
5073 
5074         // pass timeout and validate that UNAVAILABLE is not called
5075         networkCallback.assertNoCallback();
5076     }
5077 
5078     /**
5079      * Validate that a satisfied network request followed by a disconnected (lost) network does
5080      * not trigger onUnavailable() once the time-out period expires.
5081      */
5082     @Test
5083     public void testSatisfiedThenLostNetworkRequestDoesNotTriggerOnUnavailable() throws Exception {
5084         NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
5085                 NetworkCapabilities.TRANSPORT_WIFI).build();
5086         final TestNetworkCallback networkCallback = new TestNetworkCallback();
5087         mCm.requestNetwork(nr, networkCallback, TEST_REQUEST_TIMEOUT_MS);
5088 
5089         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
5090         mWiFiNetworkAgent.connect(false);
5091         networkCallback.expectAvailableCallbacks(mWiFiNetworkAgent, false, false, false,
5092                 TEST_CALLBACK_TIMEOUT_MS);
5093         mWiFiNetworkAgent.disconnect();
5094         networkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
5095 
5096         // Validate that UNAVAILABLE is not called
5097         networkCallback.assertNoCallback();
5098     }
5099 
5100     /**
5101      * Validate that when a time-out is specified for a network request the onUnavailable()
5102      * callback is called when time-out expires. Then validate that if network request is
5103      * (somehow) satisfied - the callback isn't called later.
5104      */
5105     @Test
5106     public void testTimedoutNetworkRequest() throws Exception {
5107         NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
5108                 NetworkCapabilities.TRANSPORT_WIFI).build();
5109         final TestNetworkCallback networkCallback = new TestNetworkCallback();
5110         final int timeoutMs = 10;
5111         mCm.requestNetwork(nr, networkCallback, timeoutMs);
5112 
5113         // pass timeout and validate that UNAVAILABLE is called
5114         networkCallback.expectCallback(CallbackEntry.UNAVAILABLE, (Network) null);
5115 
5116         // create a network satisfying request - validate that request not triggered
5117         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
5118         mWiFiNetworkAgent.connect(false);
5119         networkCallback.assertNoCallback();
5120     }
5121 
5122     /**
5123      * Validate that when a network request is unregistered (cancelled), no posterior event can
5124      * trigger the callback.
5125      */
5126     @Test
5127     public void testNoCallbackAfterUnregisteredNetworkRequest() throws Exception {
5128         NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
5129                 NetworkCapabilities.TRANSPORT_WIFI).build();
5130         final TestNetworkCallback networkCallback = new TestNetworkCallback();
5131         final int timeoutMs = 10;
5132 
5133         mCm.requestNetwork(nr, networkCallback, timeoutMs);
5134         mCm.unregisterNetworkCallback(networkCallback);
5135         // Regardless of the timeout, unregistering the callback in ConnectivityManager ensures
5136         // that this callback will not be called.
5137         networkCallback.assertNoCallback();
5138 
5139         // create a network satisfying request - validate that request not triggered
5140         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
5141         mWiFiNetworkAgent.connect(false);
5142         networkCallback.assertNoCallback();
5143     }
5144 
5145     @Test
5146     public void testUnfulfillableNetworkRequest() throws Exception {
5147         runUnfulfillableNetworkRequest(false);
5148     }
5149 
5150     @Test
5151     public void testUnfulfillableNetworkRequestAfterUnregister() throws Exception {
5152         runUnfulfillableNetworkRequest(true);
5153     }
5154 
5155     /**
5156      * Validate the callback flow for a factory releasing a request as unfulfillable.
5157      */
5158     private void runUnfulfillableNetworkRequest(boolean preUnregister) throws Exception {
5159         NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
5160                 NetworkCapabilities.TRANSPORT_WIFI).build();
5161         final TestNetworkCallback networkCallback = new TestNetworkCallback();
5162 
5163         final HandlerThread handlerThread = new HandlerThread("testUnfulfillableNetworkRequest");
5164         handlerThread.start();
5165         NetworkCapabilities filter = new NetworkCapabilities()
5166                 .addTransportType(TRANSPORT_WIFI)
5167                 .addCapability(NET_CAPABILITY_INTERNET)
5168                 .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED);
5169         final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
5170                 mServiceContext, "testFactory", filter, mCsHandlerThread);
5171         testFactory.setScoreFilter(40);
5172 
5173         // Register the factory and expect it to receive the default request.
5174         testFactory.register();
5175         testFactory.expectRequestAdd();
5176 
5177         try {
5178             // Now file the test request and expect it.
5179             mCm.requestNetwork(nr, networkCallback);
5180             final NetworkRequest newRequest = testFactory.expectRequestAdd().request;
5181 
5182             if (preUnregister) {
5183                 mCm.unregisterNetworkCallback(networkCallback);
5184 
5185                 // The request has been released : the factory should see it removed
5186                 // immediately.
5187                 testFactory.expectRequestRemove();
5188 
5189                 // Simulate the factory releasing the request as unfulfillable: no-op since
5190                 // the callback has already been unregistered (but a test that no exceptions are
5191                 // thrown).
5192                 testFactory.triggerUnfulfillable(newRequest);
5193             } else {
5194                 // Simulate the factory releasing the request as unfulfillable and expect
5195                 // onUnavailable!
5196                 testFactory.triggerUnfulfillable(newRequest);
5197 
5198                 networkCallback.expectCallback(CallbackEntry.UNAVAILABLE, (Network) null);
5199 
5200                 // Declaring a request unfulfillable releases it automatically.
5201                 testFactory.expectRequestRemove();
5202 
5203                 // unregister network callback - a no-op (since already freed by the
5204                 // on-unavailable), but should not fail or throw exceptions.
5205                 mCm.unregisterNetworkCallback(networkCallback);
5206 
5207                 // The factory should not see any further removal, as this request has
5208                 // already been removed.
5209             }
5210         } finally {
5211             testFactory.terminate();
5212             handlerThread.quit();
5213         }
5214     }
5215 
5216     private static class TestKeepaliveCallback extends PacketKeepaliveCallback {
5217 
5218         public enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR }
5219 
5220         private class CallbackValue {
5221             public CallbackType callbackType;
5222             public int error;
5223 
5224             public CallbackValue(CallbackType type) {
5225                 this.callbackType = type;
5226                 this.error = PacketKeepalive.SUCCESS;
5227                 assertTrue("onError callback must have error", type != CallbackType.ON_ERROR);
5228             }
5229 
5230             public CallbackValue(CallbackType type, int error) {
5231                 this.callbackType = type;
5232                 this.error = error;
5233                 assertEquals("error can only be set for onError", type, CallbackType.ON_ERROR);
5234             }
5235 
5236             @Override
5237             public boolean equals(Object o) {
5238                 return o instanceof CallbackValue &&
5239                         this.callbackType == ((CallbackValue) o).callbackType &&
5240                         this.error == ((CallbackValue) o).error;
5241             }
5242 
5243             @Override
5244             public String toString() {
5245                 return String.format("%s(%s, %d)", getClass().getSimpleName(), callbackType, error);
5246             }
5247         }
5248 
5249         private final LinkedBlockingQueue<CallbackValue> mCallbacks = new LinkedBlockingQueue<>();
5250 
5251         @Override
5252         public void onStarted() {
5253             mCallbacks.add(new CallbackValue(CallbackType.ON_STARTED));
5254         }
5255 
5256         @Override
5257         public void onStopped() {
5258             mCallbacks.add(new CallbackValue(CallbackType.ON_STOPPED));
5259         }
5260 
5261         @Override
5262         public void onError(int error) {
5263             mCallbacks.add(new CallbackValue(CallbackType.ON_ERROR, error));
5264         }
5265 
5266         private void expectCallback(CallbackValue callbackValue) throws InterruptedException {
5267             assertEquals(callbackValue, mCallbacks.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
5268         }
5269 
5270         public void expectStarted() throws Exception {
5271             expectCallback(new CallbackValue(CallbackType.ON_STARTED));
5272         }
5273 
5274         public void expectStopped() throws Exception {
5275             expectCallback(new CallbackValue(CallbackType.ON_STOPPED));
5276         }
5277 
5278         public void expectError(int error) throws Exception {
5279             expectCallback(new CallbackValue(CallbackType.ON_ERROR, error));
5280         }
5281     }
5282 
5283     private static class TestSocketKeepaliveCallback extends SocketKeepalive.Callback {
5284 
5285         public enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR };
5286 
5287         private class CallbackValue {
5288             public CallbackType callbackType;
5289             public int error;
5290 
5291             CallbackValue(CallbackType type) {
5292                 this.callbackType = type;
5293                 this.error = SocketKeepalive.SUCCESS;
5294                 assertTrue("onError callback must have error", type != CallbackType.ON_ERROR);
5295             }
5296 
5297             CallbackValue(CallbackType type, int error) {
5298                 this.callbackType = type;
5299                 this.error = error;
5300                 assertEquals("error can only be set for onError", type, CallbackType.ON_ERROR);
5301             }
5302 
5303             @Override
5304             public boolean equals(Object o) {
5305                 return o instanceof CallbackValue
5306                         && this.callbackType == ((CallbackValue) o).callbackType
5307                         && this.error == ((CallbackValue) o).error;
5308             }
5309 
5310             @Override
5311             public String toString() {
5312                 return String.format("%s(%s, %d)", getClass().getSimpleName(), callbackType,
5313                         error);
5314             }
5315         }
5316 
5317         private LinkedBlockingQueue<CallbackValue> mCallbacks = new LinkedBlockingQueue<>();
5318         private final Executor mExecutor;
5319 
5320         TestSocketKeepaliveCallback(@NonNull Executor executor) {
5321             mExecutor = executor;
5322         }
5323 
5324         @Override
5325         public void onStarted() {
5326             mCallbacks.add(new CallbackValue(CallbackType.ON_STARTED));
5327         }
5328 
5329         @Override
5330         public void onStopped() {
5331             mCallbacks.add(new CallbackValue(CallbackType.ON_STOPPED));
5332         }
5333 
5334         @Override
5335         public void onError(int error) {
5336             mCallbacks.add(new CallbackValue(CallbackType.ON_ERROR, error));
5337         }
5338 
5339         private void expectCallback(CallbackValue callbackValue) throws InterruptedException {
5340             assertEquals(callbackValue, mCallbacks.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
5341 
5342         }
5343 
5344         public void expectStarted() throws InterruptedException {
5345             expectCallback(new CallbackValue(CallbackType.ON_STARTED));
5346         }
5347 
5348         public void expectStopped() throws InterruptedException {
5349             expectCallback(new CallbackValue(CallbackType.ON_STOPPED));
5350         }
5351 
5352         public void expectError(int error) throws InterruptedException {
5353             expectCallback(new CallbackValue(CallbackType.ON_ERROR, error));
5354         }
5355 
5356         public void assertNoCallback() {
5357             waitForIdleSerialExecutor(mExecutor, TIMEOUT_MS);
5358             CallbackValue cv = mCallbacks.peek();
5359             assertNull("Unexpected callback: " + cv, cv);
5360         }
5361     }
5362 
5363     private Network connectKeepaliveNetwork(LinkProperties lp) throws Exception {
5364         // Ensure the network is disconnected before anything else occurs
5365         if (mWiFiNetworkAgent != null) {
5366             assertNull(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()));
5367         }
5368 
5369         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
5370         ExpectedBroadcast b = expectConnectivityAction(TYPE_WIFI, DetailedState.CONNECTED);
5371         mWiFiNetworkAgent.connect(true);
5372         b.expectBroadcast();
5373         verifyActiveNetwork(TRANSPORT_WIFI);
5374         mWiFiNetworkAgent.sendLinkProperties(lp);
5375         waitForIdle();
5376         return mWiFiNetworkAgent.getNetwork();
5377     }
5378 
5379     @Test
5380     public void testPacketKeepalives() throws Exception {
5381         InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
5382         InetAddress notMyIPv4 = InetAddress.getByName("192.0.2.35");
5383         InetAddress myIPv6 = InetAddress.getByName("2001:db8::1");
5384         InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8");
5385         InetAddress dstIPv6 = InetAddress.getByName("2001:4860:4860::8888");
5386 
5387         final int validKaInterval = 15;
5388         final int invalidKaInterval = 9;
5389 
5390         LinkProperties lp = new LinkProperties();
5391         lp.setInterfaceName("wlan12");
5392         lp.addLinkAddress(new LinkAddress(myIPv6, 64));
5393         lp.addLinkAddress(new LinkAddress(myIPv4, 25));
5394         lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
5395         lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
5396 
5397         Network notMyNet = new Network(61234);
5398         Network myNet = connectKeepaliveNetwork(lp);
5399 
5400         TestKeepaliveCallback callback = new TestKeepaliveCallback();
5401         PacketKeepalive ka;
5402 
5403         // Attempt to start keepalives with invalid parameters and check for errors.
5404         ka = mCm.startNattKeepalive(notMyNet, validKaInterval, callback, myIPv4, 1234, dstIPv4);
5405         callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK);
5406 
5407         ka = mCm.startNattKeepalive(myNet, invalidKaInterval, callback, myIPv4, 1234, dstIPv4);
5408         callback.expectError(PacketKeepalive.ERROR_INVALID_INTERVAL);
5409 
5410         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 1234, dstIPv6);
5411         callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
5412 
5413         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv6, 1234, dstIPv4);
5414         callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
5415 
5416         // NAT-T is only supported for IPv4.
5417         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv6, 1234, dstIPv6);
5418         callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
5419 
5420         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 123456, dstIPv4);
5421         callback.expectError(PacketKeepalive.ERROR_INVALID_PORT);
5422 
5423         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 123456, dstIPv4);
5424         callback.expectError(PacketKeepalive.ERROR_INVALID_PORT);
5425 
5426         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
5427         callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
5428 
5429         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
5430         callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
5431 
5432         // Check that a started keepalive can be stopped.
5433         mWiFiNetworkAgent.setStartKeepaliveEvent(PacketKeepalive.SUCCESS);
5434         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
5435         callback.expectStarted();
5436         mWiFiNetworkAgent.setStopKeepaliveEvent(PacketKeepalive.SUCCESS);
5437         ka.stop();
5438         callback.expectStopped();
5439 
5440         // Check that deleting the IP address stops the keepalive.
5441         LinkProperties bogusLp = new LinkProperties(lp);
5442         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
5443         callback.expectStarted();
5444         bogusLp.removeLinkAddress(new LinkAddress(myIPv4, 25));
5445         bogusLp.addLinkAddress(new LinkAddress(notMyIPv4, 25));
5446         mWiFiNetworkAgent.sendLinkProperties(bogusLp);
5447         callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
5448         mWiFiNetworkAgent.sendLinkProperties(lp);
5449 
5450         // Check that a started keepalive is stopped correctly when the network disconnects.
5451         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
5452         callback.expectStarted();
5453         mWiFiNetworkAgent.disconnect();
5454         mWiFiNetworkAgent.expectDisconnected();
5455         callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK);
5456 
5457         // ... and that stopping it after that has no adverse effects.
5458         waitForIdle();
5459         final Network myNetAlias = myNet;
5460         assertNull(mCm.getNetworkCapabilities(myNetAlias));
5461         ka.stop();
5462 
5463         // Reconnect.
5464         myNet = connectKeepaliveNetwork(lp);
5465         mWiFiNetworkAgent.setStartKeepaliveEvent(PacketKeepalive.SUCCESS);
5466 
5467         // Check that keepalive slots start from 1 and increment. The first one gets slot 1.
5468         mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
5469         ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
5470         callback.expectStarted();
5471 
5472         // The second one gets slot 2.
5473         mWiFiNetworkAgent.setExpectedKeepaliveSlot(2);
5474         TestKeepaliveCallback callback2 = new TestKeepaliveCallback();
5475         PacketKeepalive ka2 = mCm.startNattKeepalive(
5476                 myNet, validKaInterval, callback2, myIPv4, 6789, dstIPv4);
5477         callback2.expectStarted();
5478 
5479         // Now stop the first one and create a third. This also gets slot 1.
5480         ka.stop();
5481         callback.expectStopped();
5482 
5483         mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
5484         TestKeepaliveCallback callback3 = new TestKeepaliveCallback();
5485         PacketKeepalive ka3 = mCm.startNattKeepalive(
5486                 myNet, validKaInterval, callback3, myIPv4, 9876, dstIPv4);
5487         callback3.expectStarted();
5488 
5489         ka2.stop();
5490         callback2.expectStopped();
5491 
5492         ka3.stop();
5493         callback3.expectStopped();
5494     }
5495 
5496     // Helper method to prepare the executor and run test
5497     private void runTestWithSerialExecutors(ExceptionUtils.ThrowingConsumer<Executor> functor)
5498             throws Exception {
5499         final ExecutorService executorSingleThread = Executors.newSingleThreadExecutor();
5500         final Executor executorInline = (Runnable r) -> r.run();
5501         functor.accept(executorSingleThread);
5502         executorSingleThread.shutdown();
5503         functor.accept(executorInline);
5504     }
5505 
5506     @Test
5507     public void testNattSocketKeepalives() throws Exception {
5508         runTestWithSerialExecutors(executor -> doTestNattSocketKeepalivesWithExecutor(executor));
5509         runTestWithSerialExecutors(executor -> doTestNattSocketKeepalivesFdWithExecutor(executor));
5510     }
5511 
5512     private void doTestNattSocketKeepalivesWithExecutor(Executor executor) throws Exception {
5513         // TODO: 1. Move this outside of ConnectivityServiceTest.
5514         //       2. Make test to verify that Nat-T keepalive socket is created by IpSecService.
5515         //       3. Mock ipsec service.
5516         final InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
5517         final InetAddress notMyIPv4 = InetAddress.getByName("192.0.2.35");
5518         final InetAddress myIPv6 = InetAddress.getByName("2001:db8::1");
5519         final InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8");
5520         final InetAddress dstIPv6 = InetAddress.getByName("2001:4860:4860::8888");
5521 
5522         final int validKaInterval = 15;
5523         final int invalidKaInterval = 9;
5524 
5525         final IpSecManager mIpSec = (IpSecManager) mContext.getSystemService(Context.IPSEC_SERVICE);
5526         final UdpEncapsulationSocket testSocket = mIpSec.openUdpEncapsulationSocket();
5527         final int srcPort = testSocket.getPort();
5528 
5529         LinkProperties lp = new LinkProperties();
5530         lp.setInterfaceName("wlan12");
5531         lp.addLinkAddress(new LinkAddress(myIPv6, 64));
5532         lp.addLinkAddress(new LinkAddress(myIPv4, 25));
5533         lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
5534         lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
5535 
5536         Network notMyNet = new Network(61234);
5537         Network myNet = connectKeepaliveNetwork(lp);
5538 
5539         TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback(executor);
5540 
5541         // Attempt to start keepalives with invalid parameters and check for errors.
5542         // Invalid network.
5543         try (SocketKeepalive ka = mCm.createSocketKeepalive(
5544                 notMyNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
5545             ka.start(validKaInterval);
5546             callback.expectError(SocketKeepalive.ERROR_INVALID_NETWORK);
5547         }
5548 
5549         // Invalid interval.
5550         try (SocketKeepalive ka = mCm.createSocketKeepalive(
5551                 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
5552             ka.start(invalidKaInterval);
5553             callback.expectError(SocketKeepalive.ERROR_INVALID_INTERVAL);
5554         }
5555 
5556         // Invalid destination.
5557         try (SocketKeepalive ka = mCm.createSocketKeepalive(
5558                 myNet, testSocket, myIPv4, dstIPv6, executor, callback)) {
5559             ka.start(validKaInterval);
5560             callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
5561         }
5562 
5563         // Invalid source;
5564         try (SocketKeepalive ka = mCm.createSocketKeepalive(
5565                 myNet, testSocket, myIPv6, dstIPv4, executor, callback)) {
5566             ka.start(validKaInterval);
5567             callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
5568         }
5569 
5570         // NAT-T is only supported for IPv4.
5571         try (SocketKeepalive ka = mCm.createSocketKeepalive(
5572                 myNet, testSocket, myIPv6, dstIPv6, executor, callback)) {
5573             ka.start(validKaInterval);
5574             callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
5575         }
5576 
5577         // Basic check before testing started keepalive.
5578         try (SocketKeepalive ka = mCm.createSocketKeepalive(
5579                 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
5580             ka.start(validKaInterval);
5581             callback.expectError(SocketKeepalive.ERROR_UNSUPPORTED);
5582         }
5583 
5584         // Check that a started keepalive can be stopped.
5585         mWiFiNetworkAgent.setStartKeepaliveEvent(SocketKeepalive.SUCCESS);
5586         try (SocketKeepalive ka = mCm.createSocketKeepalive(
5587                 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
5588             ka.start(validKaInterval);
5589             callback.expectStarted();
5590             mWiFiNetworkAgent.setStopKeepaliveEvent(SocketKeepalive.SUCCESS);
5591             ka.stop();
5592             callback.expectStopped();
5593 
5594             // Check that keepalive could be restarted.
5595             ka.start(validKaInterval);
5596             callback.expectStarted();
5597             ka.stop();
5598             callback.expectStopped();
5599 
5600             // Check that keepalive can be restarted without waiting for callback.
5601             ka.start(validKaInterval);
5602             callback.expectStarted();
5603             ka.stop();
5604             ka.start(validKaInterval);
5605             callback.expectStopped();
5606             callback.expectStarted();
5607             ka.stop();
5608             callback.expectStopped();
5609         }
5610 
5611         // Check that deleting the IP address stops the keepalive.
5612         LinkProperties bogusLp = new LinkProperties(lp);
5613         try (SocketKeepalive ka = mCm.createSocketKeepalive(
5614                 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
5615             ka.start(validKaInterval);
5616             callback.expectStarted();
5617             bogusLp.removeLinkAddress(new LinkAddress(myIPv4, 25));
5618             bogusLp.addLinkAddress(new LinkAddress(notMyIPv4, 25));
5619             mWiFiNetworkAgent.sendLinkProperties(bogusLp);
5620             callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
5621             mWiFiNetworkAgent.sendLinkProperties(lp);
5622         }
5623 
5624         // Check that a started keepalive is stopped correctly when the network disconnects.
5625         try (SocketKeepalive ka = mCm.createSocketKeepalive(
5626                 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
5627             ka.start(validKaInterval);
5628             callback.expectStarted();
5629             mWiFiNetworkAgent.disconnect();
5630             mWiFiNetworkAgent.expectDisconnected();
5631             callback.expectError(SocketKeepalive.ERROR_INVALID_NETWORK);
5632 
5633             // ... and that stopping it after that has no adverse effects.
5634             waitForIdle();
5635             final Network myNetAlias = myNet;
5636             assertNull(mCm.getNetworkCapabilities(myNetAlias));
5637             ka.stop();
5638             callback.assertNoCallback();
5639         }
5640 
5641         // Reconnect.
5642         myNet = connectKeepaliveNetwork(lp);
5643         mWiFiNetworkAgent.setStartKeepaliveEvent(SocketKeepalive.SUCCESS);
5644 
5645         // Check that a stop followed by network disconnects does not result in crash.
5646         try (SocketKeepalive ka = mCm.createSocketKeepalive(
5647                 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
5648             ka.start(validKaInterval);
5649             callback.expectStarted();
5650             // Delay the response of keepalive events in networkAgent long enough to make sure
5651             // the follow-up network disconnection will be processed first.
5652             mWiFiNetworkAgent.setKeepaliveResponseDelay(3 * TIMEOUT_MS);
5653             ka.stop();
5654             // Call stop() twice shouldn't result in crash, b/182586681.
5655             ka.stop();
5656 
5657             // Make sure the stop has been processed. Wait for executor idle is needed to prevent
5658             // flaky since the actual stop call to the service is delegated to executor thread.
5659             waitForIdleSerialExecutor(executor, TIMEOUT_MS);
5660             waitForIdle();
5661 
5662             mWiFiNetworkAgent.disconnect();
5663             mWiFiNetworkAgent.expectDisconnected();
5664             callback.expectStopped();
5665             callback.assertNoCallback();
5666         }
5667 
5668         // Reconnect.
5669         waitForIdle();
5670         myNet = connectKeepaliveNetwork(lp);
5671         mWiFiNetworkAgent.setStartKeepaliveEvent(SocketKeepalive.SUCCESS);
5672 
5673         // Check that keepalive slots start from 1 and increment. The first one gets slot 1.
5674         mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
5675         int srcPort2 = 0;
5676         try (SocketKeepalive ka = mCm.createSocketKeepalive(
5677                 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
5678             ka.start(validKaInterval);
5679             callback.expectStarted();
5680 
5681             // The second one gets slot 2.
5682             mWiFiNetworkAgent.setExpectedKeepaliveSlot(2);
5683             final UdpEncapsulationSocket testSocket2 = mIpSec.openUdpEncapsulationSocket();
5684             srcPort2 = testSocket2.getPort();
5685             TestSocketKeepaliveCallback callback2 = new TestSocketKeepaliveCallback(executor);
5686             try (SocketKeepalive ka2 = mCm.createSocketKeepalive(
5687                     myNet, testSocket2, myIPv4, dstIPv4, executor, callback2)) {
5688                 ka2.start(validKaInterval);
5689                 callback2.expectStarted();
5690 
5691                 ka.stop();
5692                 callback.expectStopped();
5693 
5694                 ka2.stop();
5695                 callback2.expectStopped();
5696 
5697                 testSocket.close();
5698                 testSocket2.close();
5699             }
5700         }
5701 
5702         // Check that there is no port leaked after all keepalives and sockets are closed.
5703         // TODO: enable this check after ensuring a valid free port. See b/129512753#comment7.
5704         // assertFalse(isUdpPortInUse(srcPort));
5705         // assertFalse(isUdpPortInUse(srcPort2));
5706 
5707         mWiFiNetworkAgent.disconnect();
5708         mWiFiNetworkAgent.expectDisconnected();
5709         mWiFiNetworkAgent = null;
5710     }
5711 
5712     @Test
5713     public void testTcpSocketKeepalives() throws Exception {
5714         runTestWithSerialExecutors(executor -> doTestTcpSocketKeepalivesWithExecutor(executor));
5715     }
5716 
5717     private void doTestTcpSocketKeepalivesWithExecutor(Executor executor) throws Exception {
5718         final int srcPortV4 = 12345;
5719         final int srcPortV6 = 23456;
5720         final InetAddress myIPv4 = InetAddress.getByName("127.0.0.1");
5721         final InetAddress myIPv6 = InetAddress.getByName("::1");
5722 
5723         final int validKaInterval = 15;
5724 
5725         final LinkProperties lp = new LinkProperties();
5726         lp.setInterfaceName("wlan12");
5727         lp.addLinkAddress(new LinkAddress(myIPv6, 64));
5728         lp.addLinkAddress(new LinkAddress(myIPv4, 25));
5729         lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
5730         lp.addRoute(new RouteInfo(InetAddress.getByName("127.0.0.254")));
5731 
5732         final Network notMyNet = new Network(61234);
5733         final Network myNet = connectKeepaliveNetwork(lp);
5734 
5735         final Socket testSocketV4 = new Socket();
5736         final Socket testSocketV6 = new Socket();
5737 
5738         TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback(executor);
5739 
5740         // Attempt to start Tcp keepalives with invalid parameters and check for errors.
5741         // Invalid network.
5742         try (SocketKeepalive ka = mCm.createSocketKeepalive(
5743             notMyNet, testSocketV4, executor, callback)) {
5744             ka.start(validKaInterval);
5745             callback.expectError(SocketKeepalive.ERROR_INVALID_NETWORK);
5746         }
5747 
5748         // Invalid Socket (socket is not bound with IPv4 address).
5749         try (SocketKeepalive ka = mCm.createSocketKeepalive(
5750             myNet, testSocketV4, executor, callback)) {
5751             ka.start(validKaInterval);
5752             callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
5753         }
5754 
5755         // Invalid Socket (socket is not bound with IPv6 address).
5756         try (SocketKeepalive ka = mCm.createSocketKeepalive(
5757             myNet, testSocketV6, executor, callback)) {
5758             ka.start(validKaInterval);
5759             callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
5760         }
5761 
5762         // Bind the socket address
5763         testSocketV4.bind(new InetSocketAddress(myIPv4, srcPortV4));
5764         testSocketV6.bind(new InetSocketAddress(myIPv6, srcPortV6));
5765 
5766         // Invalid Socket (socket is bound with IPv4 address).
5767         try (SocketKeepalive ka = mCm.createSocketKeepalive(
5768             myNet, testSocketV4, executor, callback)) {
5769             ka.start(validKaInterval);
5770             callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
5771         }
5772 
5773         // Invalid Socket (socket is bound with IPv6 address).
5774         try (SocketKeepalive ka = mCm.createSocketKeepalive(
5775             myNet, testSocketV6, executor, callback)) {
5776             ka.start(validKaInterval);
5777             callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
5778         }
5779 
5780         testSocketV4.close();
5781         testSocketV6.close();
5782 
5783         mWiFiNetworkAgent.disconnect();
5784         mWiFiNetworkAgent.expectDisconnected();
5785         mWiFiNetworkAgent = null;
5786     }
5787 
5788     private void doTestNattSocketKeepalivesFdWithExecutor(Executor executor) throws Exception {
5789         final InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
5790         final InetAddress anyIPv4 = InetAddress.getByName("0.0.0.0");
5791         final InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8");
5792         final int validKaInterval = 15;
5793 
5794         // Prepare the target network.
5795         LinkProperties lp = new LinkProperties();
5796         lp.setInterfaceName("wlan12");
5797         lp.addLinkAddress(new LinkAddress(myIPv4, 25));
5798         lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
5799         Network myNet = connectKeepaliveNetwork(lp);
5800         mWiFiNetworkAgent.setStartKeepaliveEvent(SocketKeepalive.SUCCESS);
5801         mWiFiNetworkAgent.setStopKeepaliveEvent(SocketKeepalive.SUCCESS);
5802 
5803         TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback(executor);
5804 
5805         // Prepare the target file descriptor, keep only one instance.
5806         final IpSecManager mIpSec = (IpSecManager) mContext.getSystemService(Context.IPSEC_SERVICE);
5807         final UdpEncapsulationSocket testSocket = mIpSec.openUdpEncapsulationSocket();
5808         final int srcPort = testSocket.getPort();
5809         final ParcelFileDescriptor testPfd =
5810                 ParcelFileDescriptor.dup(testSocket.getFileDescriptor());
5811         testSocket.close();
5812         assertTrue(isUdpPortInUse(srcPort));
5813 
5814         // Start keepalive and explicit make the variable goes out of scope with try-with-resources
5815         // block.
5816         try (SocketKeepalive ka = mCm.createNattKeepalive(
5817                 myNet, testPfd, myIPv4, dstIPv4, executor, callback)) {
5818             ka.start(validKaInterval);
5819             callback.expectStarted();
5820             ka.stop();
5821             callback.expectStopped();
5822         }
5823 
5824         // Check that the ParcelFileDescriptor is still valid after keepalive stopped,
5825         // ErrnoException with EBADF will be thrown if the socket is closed when checking local
5826         // address.
5827         assertTrue(isUdpPortInUse(srcPort));
5828         final InetSocketAddress sa =
5829                 (InetSocketAddress) Os.getsockname(testPfd.getFileDescriptor());
5830         assertEquals(anyIPv4, sa.getAddress());
5831 
5832         testPfd.close();
5833         // TODO: enable this check after ensuring a valid free port. See b/129512753#comment7.
5834         // assertFalse(isUdpPortInUse(srcPort));
5835 
5836         mWiFiNetworkAgent.disconnect();
5837         mWiFiNetworkAgent.expectDisconnected();
5838         mWiFiNetworkAgent = null;
5839     }
5840 
5841     private static boolean isUdpPortInUse(int port) {
5842         try (DatagramSocket ignored = new DatagramSocket(port)) {
5843             return false;
5844         } catch (IOException alreadyInUse) {
5845             return true;
5846         }
5847     }
5848 
5849     @Test
5850     public void testGetCaptivePortalServerUrl() throws Exception {
5851         String url = mCm.getCaptivePortalServerUrl();
5852         assertEquals("http://connectivitycheck.gstatic.com/generate_204", url);
5853     }
5854 
5855     private static class TestNetworkPinner extends NetworkPinner {
5856         public static boolean awaitPin(int timeoutMs) throws InterruptedException {
5857             synchronized(sLock) {
5858                 if (sNetwork == null) {
5859                     sLock.wait(timeoutMs);
5860                 }
5861                 return sNetwork != null;
5862             }
5863         }
5864 
5865         public static boolean awaitUnpin(int timeoutMs) throws InterruptedException {
5866             synchronized(sLock) {
5867                 if (sNetwork != null) {
5868                     sLock.wait(timeoutMs);
5869                 }
5870                 return sNetwork == null;
5871             }
5872         }
5873     }
5874 
5875     private void assertPinnedToWifiWithCellDefault() {
5876         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess());
5877         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
5878     }
5879 
5880     private void assertPinnedToWifiWithWifiDefault() {
5881         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess());
5882         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
5883     }
5884 
5885     private void assertNotPinnedToWifi() {
5886         assertNull(mCm.getBoundNetworkForProcess());
5887         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
5888     }
5889 
5890     @Test
5891     public void testNetworkPinner() throws Exception {
5892         NetworkRequest wifiRequest = new NetworkRequest.Builder()
5893                 .addTransportType(TRANSPORT_WIFI)
5894                 .build();
5895         assertNull(mCm.getBoundNetworkForProcess());
5896 
5897         TestNetworkPinner.pin(mServiceContext, wifiRequest);
5898         assertNull(mCm.getBoundNetworkForProcess());
5899 
5900         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
5901         mCellNetworkAgent.connect(true);
5902         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
5903         mWiFiNetworkAgent.connect(false);
5904 
5905         // When wi-fi connects, expect to be pinned.
5906         assertTrue(TestNetworkPinner.awaitPin(100));
5907         assertPinnedToWifiWithCellDefault();
5908 
5909         // Disconnect and expect the pin to drop.
5910         mWiFiNetworkAgent.disconnect();
5911         assertTrue(TestNetworkPinner.awaitUnpin(100));
5912         assertNotPinnedToWifi();
5913 
5914         // Reconnecting does not cause the pin to come back.
5915         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
5916         mWiFiNetworkAgent.connect(false);
5917         assertFalse(TestNetworkPinner.awaitPin(100));
5918         assertNotPinnedToWifi();
5919 
5920         // Pinning while connected causes the pin to take effect immediately.
5921         TestNetworkPinner.pin(mServiceContext, wifiRequest);
5922         assertTrue(TestNetworkPinner.awaitPin(100));
5923         assertPinnedToWifiWithCellDefault();
5924 
5925         // Explicitly unpin and expect to use the default network again.
5926         TestNetworkPinner.unpin();
5927         assertNotPinnedToWifi();
5928 
5929         // Disconnect cell and wifi.
5930         ExpectedBroadcast b = registerConnectivityBroadcast(3);  // cell down, wifi up, wifi down.
5931         mCellNetworkAgent.disconnect();
5932         mWiFiNetworkAgent.disconnect();
5933         b.expectBroadcast();
5934 
5935         // Pinning takes effect even if the pinned network is the default when the pin is set...
5936         TestNetworkPinner.pin(mServiceContext, wifiRequest);
5937         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
5938         mWiFiNetworkAgent.connect(false);
5939         assertTrue(TestNetworkPinner.awaitPin(100));
5940         assertPinnedToWifiWithWifiDefault();
5941 
5942         // ... and is maintained even when that network is no longer the default.
5943         b = registerConnectivityBroadcast(1);
5944         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
5945         mCellNetworkAgent.connect(true);
5946         b.expectBroadcast();
5947         assertPinnedToWifiWithCellDefault();
5948     }
5949 
5950     @Test
5951     public void testNetworkCallbackMaximum() throws Exception {
5952         final int MAX_REQUESTS = 100;
5953         final int CALLBACKS = 87;
5954         final int DIFF_INTENTS = 10;
5955         final int SAME_INTENTS = 10;
5956         final int SYSTEM_ONLY_MAX_REQUESTS = 250;
5957         // Assert 1 (Default request filed before testing) + CALLBACKS + DIFF_INTENTS +
5958         // 1 (same intent) = MAX_REQUESTS - 1, since the capacity is MAX_REQUEST - 1.
5959         assertEquals(MAX_REQUESTS - 1, 1 + CALLBACKS + DIFF_INTENTS + 1);
5960 
5961         NetworkRequest networkRequest = new NetworkRequest.Builder().build();
5962         ArrayList<Object> registered = new ArrayList<>();
5963 
5964         for (int j = 0; j < CALLBACKS; j++) {
5965             final NetworkCallback cb = new NetworkCallback();
5966             if (j < CALLBACKS / 2) {
5967                 mCm.requestNetwork(networkRequest, cb);
5968             } else {
5969                 mCm.registerNetworkCallback(networkRequest, cb);
5970             }
5971             registered.add(cb);
5972         }
5973 
5974         // Since ConnectivityService will de-duplicate the request with the same intent,
5975         // register multiple times does not really increase multiple requests.
5976         final PendingIntent same_pi = PendingIntent.getBroadcast(mContext, 0 /* requestCode */,
5977                 new Intent("same"), FLAG_IMMUTABLE);
5978         for (int j = 0; j < SAME_INTENTS; j++) {
5979             mCm.registerNetworkCallback(networkRequest, same_pi);
5980             // Wait for the requests with the same intent to be de-duplicated. Because
5981             // ConnectivityService side incrementCountOrThrow in binder, decrementCount in handler
5982             // thread, waitForIdle is needed to ensure decrementCount being invoked for same intent
5983             // requests before doing further tests.
5984             waitForIdle();
5985         }
5986         for (int j = 0; j < SAME_INTENTS; j++) {
5987             mCm.requestNetwork(networkRequest, same_pi);
5988             // Wait for the requests with the same intent to be de-duplicated.
5989             // Refer to the reason above.
5990             waitForIdle();
5991         }
5992         registered.add(same_pi);
5993 
5994         for (int j = 0; j < DIFF_INTENTS; j++) {
5995             if (j < DIFF_INTENTS / 2) {
5996                 final PendingIntent pi = PendingIntent.getBroadcast(mContext, 0 /* requestCode */,
5997                         new Intent("a" + j), FLAG_IMMUTABLE);
5998                 mCm.requestNetwork(networkRequest, pi);
5999                 registered.add(pi);
6000             } else {
6001                 final PendingIntent pi = PendingIntent.getBroadcast(mContext, 0 /* requestCode */,
6002                         new Intent("b" + j), FLAG_IMMUTABLE);
6003                 mCm.registerNetworkCallback(networkRequest, pi);
6004                 registered.add(pi);
6005             }
6006         }
6007 
6008         // Test that the limit is enforced when MAX_REQUESTS simultaneous requests are added.
6009         assertThrows(TooManyRequestsException.class, () ->
6010                 mCm.requestNetwork(networkRequest, new NetworkCallback())
6011         );
6012         assertThrows(TooManyRequestsException.class, () ->
6013                 mCm.registerNetworkCallback(networkRequest, new NetworkCallback())
6014         );
6015         assertThrows(TooManyRequestsException.class, () ->
6016                 mCm.requestNetwork(networkRequest,
6017                         PendingIntent.getBroadcast(mContext, 0 /* requestCode */,
6018                                 new Intent("c"), FLAG_IMMUTABLE))
6019         );
6020         assertThrows(TooManyRequestsException.class, () ->
6021                 mCm.registerNetworkCallback(networkRequest,
6022                         PendingIntent.getBroadcast(mContext, 0 /* requestCode */,
6023                                 new Intent("d"), FLAG_IMMUTABLE))
6024         );
6025 
6026         // The system gets another SYSTEM_ONLY_MAX_REQUESTS slots.
6027         final Handler handler = new Handler(ConnectivityThread.getInstanceLooper());
6028         withPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, () -> {
6029             ArrayList<NetworkCallback> systemRegistered = new ArrayList<>();
6030             for (int i = 0; i < SYSTEM_ONLY_MAX_REQUESTS - 1; i++) {
6031                 NetworkCallback cb = new NetworkCallback();
6032                 if (i % 2 == 0) {
6033                     mCm.registerDefaultNetworkCallbackForUid(1000000 + i, cb, handler);
6034                 } else {
6035                     mCm.registerNetworkCallback(networkRequest, cb);
6036                 }
6037                 systemRegistered.add(cb);
6038             }
6039             waitForIdle();
6040 
6041             assertThrows(TooManyRequestsException.class, () ->
6042                     mCm.registerDefaultNetworkCallbackForUid(1001042, new NetworkCallback(),
6043                             handler));
6044             assertThrows(TooManyRequestsException.class, () ->
6045                     mCm.registerNetworkCallback(networkRequest, new NetworkCallback()));
6046 
6047             for (NetworkCallback callback : systemRegistered) {
6048                 mCm.unregisterNetworkCallback(callback);
6049             }
6050             waitForIdle();  // Wait for requests to be unregistered before giving up the permission.
6051         });
6052 
6053         for (Object o : registered) {
6054             if (o instanceof NetworkCallback) {
6055                 mCm.unregisterNetworkCallback((NetworkCallback) o);
6056             }
6057             if (o instanceof PendingIntent) {
6058                 mCm.unregisterNetworkCallback((PendingIntent) o);
6059             }
6060         }
6061         waitForIdle();
6062 
6063         // Test that the limit is not hit when MAX_REQUESTS requests are added and removed.
6064         for (int i = 0; i < MAX_REQUESTS; i++) {
6065             NetworkCallback networkCallback = new NetworkCallback();
6066             mCm.requestNetwork(networkRequest, networkCallback);
6067             mCm.unregisterNetworkCallback(networkCallback);
6068         }
6069         waitForIdle();
6070 
6071         for (int i = 0; i < MAX_REQUESTS; i++) {
6072             NetworkCallback networkCallback = new NetworkCallback();
6073             mCm.registerNetworkCallback(networkRequest, networkCallback);
6074             mCm.unregisterNetworkCallback(networkCallback);
6075         }
6076         waitForIdle();
6077 
6078         for (int i = 0; i < MAX_REQUESTS; i++) {
6079             NetworkCallback networkCallback = new NetworkCallback();
6080             mCm.registerDefaultNetworkCallback(networkCallback);
6081             mCm.unregisterNetworkCallback(networkCallback);
6082         }
6083         waitForIdle();
6084 
6085         for (int i = 0; i < MAX_REQUESTS; i++) {
6086             NetworkCallback networkCallback = new NetworkCallback();
6087             mCm.registerDefaultNetworkCallback(networkCallback);
6088             mCm.unregisterNetworkCallback(networkCallback);
6089         }
6090         waitForIdle();
6091 
6092         withPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, () -> {
6093             for (int i = 0; i < MAX_REQUESTS; i++) {
6094                 NetworkCallback networkCallback = new NetworkCallback();
6095                 mCm.registerDefaultNetworkCallbackForUid(1000000 + i, networkCallback,
6096                         new Handler(ConnectivityThread.getInstanceLooper()));
6097                 mCm.unregisterNetworkCallback(networkCallback);
6098             }
6099         });
6100         waitForIdle();
6101 
6102         for (int i = 0; i < MAX_REQUESTS; i++) {
6103             final PendingIntent pendingIntent = PendingIntent.getBroadcast(
6104                     mContext, 0 /* requestCode */, new Intent("e" + i), FLAG_IMMUTABLE);
6105             mCm.requestNetwork(networkRequest, pendingIntent);
6106             mCm.unregisterNetworkCallback(pendingIntent);
6107         }
6108         waitForIdle();
6109 
6110         for (int i = 0; i < MAX_REQUESTS; i++) {
6111             final PendingIntent pendingIntent = PendingIntent.getBroadcast(
6112                     mContext, 0 /* requestCode */, new Intent("f" + i), FLAG_IMMUTABLE);
6113             mCm.registerNetworkCallback(networkRequest, pendingIntent);
6114             mCm.unregisterNetworkCallback(pendingIntent);
6115         }
6116     }
6117 
6118     @Test
6119     public void testNetworkInfoOfTypeNone() throws Exception {
6120         ExpectedBroadcast b = registerConnectivityBroadcast(1);
6121 
6122         verifyNoNetwork();
6123         TestNetworkAgentWrapper wifiAware = new TestNetworkAgentWrapper(TRANSPORT_WIFI_AWARE);
6124         assertNull(mCm.getActiveNetworkInfo());
6125 
6126         Network[] allNetworks = mCm.getAllNetworks();
6127         assertLength(1, allNetworks);
6128         Network network = allNetworks[0];
6129         NetworkCapabilities capabilities = mCm.getNetworkCapabilities(network);
6130         assertTrue(capabilities.hasTransport(TRANSPORT_WIFI_AWARE));
6131 
6132         final NetworkRequest request =
6133                 new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI_AWARE).build();
6134         final TestNetworkCallback callback = new TestNetworkCallback();
6135         mCm.registerNetworkCallback(request, callback);
6136 
6137         // Bring up wifi aware network.
6138         wifiAware.connect(false, false, false /* isStrictMode */);
6139         callback.expectAvailableCallbacksUnvalidated(wifiAware);
6140 
6141         assertNull(mCm.getActiveNetworkInfo());
6142         assertNull(mCm.getActiveNetwork());
6143         // TODO: getAllNetworkInfo is dirty and returns a non-empty array right from the start
6144         // of this test. Fix it and uncomment the assert below.
6145         //assertEmpty(mCm.getAllNetworkInfo());
6146 
6147         // Disconnect wifi aware network.
6148         wifiAware.disconnect();
6149         callback.expectCallbackThat(TIMEOUT_MS, (info) -> info instanceof CallbackEntry.Lost);
6150         mCm.unregisterNetworkCallback(callback);
6151 
6152         verifyNoNetwork();
6153         b.expectNoBroadcast(10);
6154     }
6155 
6156     @Test
6157     public void testDeprecatedAndUnsupportedOperations() throws Exception {
6158         final int TYPE_NONE = ConnectivityManager.TYPE_NONE;
6159         assertNull(mCm.getNetworkInfo(TYPE_NONE));
6160         assertNull(mCm.getNetworkForType(TYPE_NONE));
6161         assertNull(mCm.getLinkProperties(TYPE_NONE));
6162         assertFalse(mCm.isNetworkSupported(TYPE_NONE));
6163 
6164         assertThrows(IllegalArgumentException.class,
6165                 () -> mCm.networkCapabilitiesForType(TYPE_NONE));
6166 
6167         Class<UnsupportedOperationException> unsupported = UnsupportedOperationException.class;
6168         assertThrows(unsupported, () -> mCm.startUsingNetworkFeature(TYPE_WIFI, ""));
6169         assertThrows(unsupported, () -> mCm.stopUsingNetworkFeature(TYPE_WIFI, ""));
6170         // TODO: let test context have configuration application target sdk version
6171         // and test that pre-M requesting for TYPE_NONE sends back APN_REQUEST_FAILED
6172         assertThrows(unsupported, () -> mCm.startUsingNetworkFeature(TYPE_NONE, ""));
6173         assertThrows(unsupported, () -> mCm.stopUsingNetworkFeature(TYPE_NONE, ""));
6174         assertThrows(unsupported, () -> mCm.requestRouteToHostAddress(TYPE_NONE, null));
6175     }
6176 
6177     @Test
6178     public void testLinkPropertiesEnsuresDirectlyConnectedRoutes() throws Exception {
6179         final NetworkRequest networkRequest = new NetworkRequest.Builder()
6180                 .addTransportType(TRANSPORT_WIFI).build();
6181         final TestNetworkCallback networkCallback = new TestNetworkCallback();
6182         mCm.registerNetworkCallback(networkRequest, networkCallback);
6183 
6184         LinkProperties lp = new LinkProperties();
6185         lp.setInterfaceName(WIFI_IFNAME);
6186         LinkAddress myIpv4Address = new LinkAddress("192.168.12.3/24");
6187         RouteInfo myIpv4DefaultRoute = new RouteInfo((IpPrefix) null,
6188                 InetAddresses.parseNumericAddress("192.168.12.1"), lp.getInterfaceName());
6189         lp.addLinkAddress(myIpv4Address);
6190         lp.addRoute(myIpv4DefaultRoute);
6191 
6192         // Verify direct routes are added when network agent is first registered in
6193         // ConnectivityService.
6194         TestNetworkAgentWrapper networkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, lp);
6195         networkAgent.connect(true);
6196         networkCallback.expectCallback(CallbackEntry.AVAILABLE, networkAgent);
6197         networkCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, networkAgent);
6198         CallbackEntry.LinkPropertiesChanged cbi =
6199                 networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED,
6200                 networkAgent);
6201         networkCallback.expectCallback(CallbackEntry.BLOCKED_STATUS, networkAgent);
6202         networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, networkAgent);
6203         networkCallback.assertNoCallback();
6204         checkDirectlyConnectedRoutes(cbi.getLp(), Arrays.asList(myIpv4Address),
6205                 Arrays.asList(myIpv4DefaultRoute));
6206         checkDirectlyConnectedRoutes(mCm.getLinkProperties(networkAgent.getNetwork()),
6207                 Arrays.asList(myIpv4Address), Arrays.asList(myIpv4DefaultRoute));
6208 
6209         // Verify direct routes are added during subsequent link properties updates.
6210         LinkProperties newLp = new LinkProperties(lp);
6211         LinkAddress myIpv6Address1 = new LinkAddress("fe80::cafe/64");
6212         LinkAddress myIpv6Address2 = new LinkAddress("2001:db8::2/64");
6213         newLp.addLinkAddress(myIpv6Address1);
6214         newLp.addLinkAddress(myIpv6Address2);
6215         networkAgent.sendLinkProperties(newLp);
6216         cbi = networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, networkAgent);
6217         networkCallback.assertNoCallback();
6218         checkDirectlyConnectedRoutes(cbi.getLp(),
6219                 Arrays.asList(myIpv4Address, myIpv6Address1, myIpv6Address2),
6220                 Arrays.asList(myIpv4DefaultRoute));
6221         mCm.unregisterNetworkCallback(networkCallback);
6222     }
6223 
6224     private void expectNotifyNetworkStatus(List<Network> networks, String defaultIface,
6225             Integer vpnUid, String vpnIfname, List<String> underlyingIfaces) throws Exception {
6226         ArgumentCaptor<List<Network>> networksCaptor = ArgumentCaptor.forClass(List.class);
6227         ArgumentCaptor<List<UnderlyingNetworkInfo>> vpnInfosCaptor =
6228                 ArgumentCaptor.forClass(List.class);
6229 
6230         verify(mStatsManager, atLeastOnce()).notifyNetworkStatus(networksCaptor.capture(),
6231                 any(List.class), eq(defaultIface), vpnInfosCaptor.capture());
6232 
6233         assertSameElements(networks, networksCaptor.getValue());
6234 
6235         List<UnderlyingNetworkInfo> infos = vpnInfosCaptor.getValue();
6236         if (vpnUid != null) {
6237             assertEquals("Should have exactly one VPN:", 1, infos.size());
6238             UnderlyingNetworkInfo info = infos.get(0);
6239             assertEquals("Unexpected VPN owner:", (int) vpnUid, info.getOwnerUid());
6240             assertEquals("Unexpected VPN interface:", vpnIfname, info.getInterface());
6241             assertSameElements(underlyingIfaces, info.getUnderlyingInterfaces());
6242         } else {
6243             assertEquals(0, infos.size());
6244             return;
6245         }
6246     }
6247 
6248     private void expectNotifyNetworkStatus(
6249             List<Network> networks, String defaultIface) throws Exception {
6250         expectNotifyNetworkStatus(networks, defaultIface, null, null, List.of());
6251     }
6252 
6253     @Test
6254     public void testStatsIfacesChanged() throws Exception {
6255         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
6256         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
6257 
6258         final List<Network> onlyCell = List.of(mCellNetworkAgent.getNetwork());
6259         final List<Network> onlyWifi = List.of(mWiFiNetworkAgent.getNetwork());
6260 
6261         LinkProperties cellLp = new LinkProperties();
6262         cellLp.setInterfaceName(MOBILE_IFNAME);
6263         LinkProperties wifiLp = new LinkProperties();
6264         wifiLp.setInterfaceName(WIFI_IFNAME);
6265 
6266         // Simple connection should have updated ifaces
6267         mCellNetworkAgent.connect(false);
6268         mCellNetworkAgent.sendLinkProperties(cellLp);
6269         waitForIdle();
6270         expectNotifyNetworkStatus(onlyCell, MOBILE_IFNAME);
6271         reset(mStatsManager);
6272 
6273         // Default network switch should update ifaces.
6274         mWiFiNetworkAgent.connect(false);
6275         mWiFiNetworkAgent.sendLinkProperties(wifiLp);
6276         waitForIdle();
6277         assertEquals(wifiLp, mService.getActiveLinkProperties());
6278         expectNotifyNetworkStatus(onlyWifi, WIFI_IFNAME);
6279         reset(mStatsManager);
6280 
6281         // Disconnect should update ifaces.
6282         mWiFiNetworkAgent.disconnect();
6283         waitForIdle();
6284         expectNotifyNetworkStatus(onlyCell, MOBILE_IFNAME);
6285         reset(mStatsManager);
6286 
6287         // Metered change should update ifaces
6288         mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
6289         waitForIdle();
6290         expectNotifyNetworkStatus(onlyCell, MOBILE_IFNAME);
6291         reset(mStatsManager);
6292 
6293         mCellNetworkAgent.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
6294         waitForIdle();
6295         expectNotifyNetworkStatus(onlyCell, MOBILE_IFNAME);
6296         reset(mStatsManager);
6297 
6298         // Temp metered change shouldn't update ifaces
6299         mCellNetworkAgent.addCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED);
6300         waitForIdle();
6301         verify(mStatsManager, never()).notifyNetworkStatus(eq(onlyCell),
6302                 any(List.class), eq(MOBILE_IFNAME), any(List.class));
6303         reset(mStatsManager);
6304 
6305         // Roaming change should update ifaces
6306         mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING);
6307         waitForIdle();
6308         expectNotifyNetworkStatus(onlyCell, MOBILE_IFNAME);
6309         reset(mStatsManager);
6310 
6311         // Test VPNs.
6312         final LinkProperties lp = new LinkProperties();
6313         lp.setInterfaceName(VPN_IFNAME);
6314 
6315         mMockVpn.establishForMyUid(lp);
6316         assertUidRangesUpdatedForMyUid(true);
6317 
6318         final List<Network> cellAndVpn =
6319                 List.of(mCellNetworkAgent.getNetwork(), mMockVpn.getNetwork());
6320 
6321         // A VPN with default (null) underlying networks sets the underlying network's interfaces...
6322         expectNotifyNetworkStatus(cellAndVpn, MOBILE_IFNAME, Process.myUid(), VPN_IFNAME,
6323                 List.of(MOBILE_IFNAME));
6324 
6325         // ...and updates them as the default network switches.
6326         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
6327         mWiFiNetworkAgent.connect(false);
6328         mWiFiNetworkAgent.sendLinkProperties(wifiLp);
6329         final Network[] onlyNull = new Network[]{null};
6330         final List<Network> wifiAndVpn =
6331                 List.of(mWiFiNetworkAgent.getNetwork(), mMockVpn.getNetwork());
6332         final List<Network> cellAndWifi =
6333                 List.of(mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork());
6334         final Network[] cellNullAndWifi =
6335                 new Network[]{mCellNetworkAgent.getNetwork(), null, mWiFiNetworkAgent.getNetwork()};
6336 
6337         waitForIdle();
6338         assertEquals(wifiLp, mService.getActiveLinkProperties());
6339         expectNotifyNetworkStatus(wifiAndVpn, WIFI_IFNAME, Process.myUid(), VPN_IFNAME,
6340                 List.of(WIFI_IFNAME));
6341         reset(mStatsManager);
6342 
6343         // A VPN that sets its underlying networks passes the underlying interfaces, and influences
6344         // the default interface sent to NetworkStatsService by virtue of applying to the system
6345         // server UID (or, in this test, to the test's UID). This is the reason for sending
6346         // MOBILE_IFNAME even though the default network is wifi.
6347         // TODO: fix this to pass in the actual default network interface. Whether or not the VPN
6348         // applies to the system server UID should not have any bearing on network stats.
6349         mMockVpn.setUnderlyingNetworks(onlyCell.toArray(new Network[0]));
6350         waitForIdle();
6351         expectNotifyNetworkStatus(wifiAndVpn, MOBILE_IFNAME, Process.myUid(), VPN_IFNAME,
6352                 List.of(MOBILE_IFNAME));
6353         reset(mStatsManager);
6354 
6355         mMockVpn.setUnderlyingNetworks(cellAndWifi.toArray(new Network[0]));
6356         waitForIdle();
6357         expectNotifyNetworkStatus(wifiAndVpn, MOBILE_IFNAME, Process.myUid(), VPN_IFNAME,
6358                 List.of(MOBILE_IFNAME, WIFI_IFNAME));
6359         reset(mStatsManager);
6360 
6361         // Null underlying networks are ignored.
6362         mMockVpn.setUnderlyingNetworks(cellNullAndWifi);
6363         waitForIdle();
6364         expectNotifyNetworkStatus(wifiAndVpn, MOBILE_IFNAME, Process.myUid(), VPN_IFNAME,
6365                 List.of(MOBILE_IFNAME, WIFI_IFNAME));
6366         reset(mStatsManager);
6367 
6368         // If an underlying network disconnects, that interface should no longer be underlying.
6369         // This doesn't actually work because disconnectAndDestroyNetwork only notifies
6370         // NetworkStatsService before the underlying network is actually removed. So the underlying
6371         // network will only be removed if notifyIfacesChangedForNetworkStats is called again. This
6372         // could result in incorrect data usage measurements if the interface used by the
6373         // disconnected network is reused by a system component that does not register an agent for
6374         // it (e.g., tethering).
6375         mCellNetworkAgent.disconnect();
6376         waitForIdle();
6377         assertNull(mService.getLinkProperties(mCellNetworkAgent.getNetwork()));
6378         expectNotifyNetworkStatus(wifiAndVpn, MOBILE_IFNAME, Process.myUid(), VPN_IFNAME,
6379                 List.of(MOBILE_IFNAME, WIFI_IFNAME));
6380 
6381         // Confirm that we never tell NetworkStatsService that cell is no longer the underlying
6382         // network for the VPN...
6383         verify(mStatsManager, never()).notifyNetworkStatus(any(List.class),
6384                 any(List.class), any() /* anyString() doesn't match null */,
6385                 argThat(infos -> infos.get(0).getUnderlyingInterfaces().size() == 1
6386                         && WIFI_IFNAME.equals(infos.get(0).getUnderlyingInterfaces().get(0))));
6387         verifyNoMoreInteractions(mStatsManager);
6388         reset(mStatsManager);
6389 
6390         // ... but if something else happens that causes notifyIfacesChangedForNetworkStats to be
6391         // called again, it does. For example, connect Ethernet, but with a low score, such that it
6392         // does not become the default network.
6393         mEthernetNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
6394         mEthernetNetworkAgent.setScore(
6395                 new NetworkScore.Builder().setLegacyInt(30).setExiting(true).build());
6396         mEthernetNetworkAgent.connect(false);
6397         waitForIdle();
6398         verify(mStatsManager).notifyNetworkStatus(any(List.class),
6399                 any(List.class), any() /* anyString() doesn't match null */,
6400                 argThat(vpnInfos -> vpnInfos.get(0).getUnderlyingInterfaces().size() == 1
6401                         && WIFI_IFNAME.equals(vpnInfos.get(0).getUnderlyingInterfaces().get(0))));
6402         mEthernetNetworkAgent.disconnect();
6403         waitForIdle();
6404         reset(mStatsManager);
6405 
6406         // When a VPN declares no underlying networks (i.e., no connectivity), getAllVpnInfo
6407         // does not return the VPN, so CS does not pass it to NetworkStatsService. This causes
6408         // NetworkStatsFactory#adjustForTunAnd464Xlat not to attempt any VPN data migration, which
6409         // is probably a performance improvement (though it's very unlikely that a VPN would declare
6410         // no underlying networks).
6411         // Also, for the same reason as above, the active interface passed in is null.
6412         mMockVpn.setUnderlyingNetworks(new Network[0]);
6413         waitForIdle();
6414         expectNotifyNetworkStatus(wifiAndVpn, null);
6415         reset(mStatsManager);
6416 
6417         // Specifying only a null underlying network is the same as no networks.
6418         mMockVpn.setUnderlyingNetworks(onlyNull);
6419         waitForIdle();
6420         expectNotifyNetworkStatus(wifiAndVpn, null);
6421         reset(mStatsManager);
6422 
6423         // Specifying networks that are all disconnected is the same as specifying no networks.
6424         mMockVpn.setUnderlyingNetworks(onlyCell.toArray(new Network[0]));
6425         waitForIdle();
6426         expectNotifyNetworkStatus(wifiAndVpn, null);
6427         reset(mStatsManager);
6428 
6429         // Passing in null again means follow the default network again.
6430         mMockVpn.setUnderlyingNetworks(null);
6431         waitForIdle();
6432         expectNotifyNetworkStatus(wifiAndVpn, WIFI_IFNAME, Process.myUid(), VPN_IFNAME,
6433                 List.of(WIFI_IFNAME));
6434         reset(mStatsManager);
6435     }
6436 
6437     @Test
6438     public void testNonVpnUnderlyingNetworks() throws Exception {
6439         // Ensure wifi and cellular are not torn down.
6440         for (int transport : new int[]{TRANSPORT_CELLULAR, TRANSPORT_WIFI}) {
6441             final NetworkRequest request = new NetworkRequest.Builder()
6442                     .addTransportType(transport)
6443                     .removeCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
6444                     .build();
6445             mCm.requestNetwork(request, new NetworkCallback());
6446         }
6447 
6448         // Connect a VCN-managed wifi network.
6449         final LinkProperties wifiLp = new LinkProperties();
6450         wifiLp.setInterfaceName(WIFI_IFNAME);
6451         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp);
6452         mWiFiNetworkAgent.removeCapability(NET_CAPABILITY_NOT_VCN_MANAGED);
6453         mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
6454         mWiFiNetworkAgent.connect(true /* validated */);
6455 
6456         final List<Network> none = List.of();
6457         expectNotifyNetworkStatus(none, null);  // Wifi is not the default network
6458 
6459         // Create a virtual network based on the wifi network.
6460         final int ownerUid = 10042;
6461         NetworkCapabilities nc = new NetworkCapabilities.Builder()
6462                 .setOwnerUid(ownerUid)
6463                 .setAdministratorUids(new int[]{ownerUid})
6464                 .build();
6465         final String vcnIface = "ipsec42";
6466         final LinkProperties lp = new LinkProperties();
6467         lp.setInterfaceName(vcnIface);
6468         final TestNetworkAgentWrapper vcn = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, lp, nc);
6469         vcn.setUnderlyingNetworks(List.of(mWiFiNetworkAgent.getNetwork()));
6470         vcn.connect(false /* validated */);
6471 
6472         final TestNetworkCallback callback = new TestNetworkCallback();
6473         mCm.registerDefaultNetworkCallback(callback);
6474         callback.expectAvailableCallbacksUnvalidated(vcn);
6475 
6476         // The underlying wifi network's capabilities are not propagated to the virtual network,
6477         // but NetworkStatsService is informed of the underlying interface.
6478         nc = mCm.getNetworkCapabilities(vcn.getNetwork());
6479         assertFalse(nc.hasTransport(TRANSPORT_WIFI));
6480         assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED));
6481         final List<Network> onlyVcn = List.of(vcn.getNetwork());
6482         expectNotifyNetworkStatus(onlyVcn, vcnIface, ownerUid, vcnIface, List.of(WIFI_IFNAME));
6483 
6484         // Add NOT_METERED to the underlying network, check that it is not propagated.
6485         mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
6486         callback.assertNoCallback();
6487         nc = mCm.getNetworkCapabilities(vcn.getNetwork());
6488         assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED));
6489 
6490         // Switch underlying networks.
6491         final LinkProperties cellLp = new LinkProperties();
6492         cellLp.setInterfaceName(MOBILE_IFNAME);
6493         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
6494         mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_VCN_MANAGED);
6495         mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_ROAMING);
6496         mCellNetworkAgent.connect(false /* validated */);
6497         vcn.setUnderlyingNetworks(List.of(mCellNetworkAgent.getNetwork()));
6498 
6499         // The underlying capability changes do not propagate to the virtual network, but
6500         // NetworkStatsService is informed of the new underlying interface.
6501         callback.assertNoCallback();
6502         nc = mCm.getNetworkCapabilities(vcn.getNetwork());
6503         assertFalse(nc.hasTransport(TRANSPORT_WIFI));
6504         assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_ROAMING));
6505         expectNotifyNetworkStatus(onlyVcn, vcnIface, ownerUid, vcnIface, List.of(MOBILE_IFNAME));
6506     }
6507 
6508     @Test
6509     public void testBasicDnsConfigurationPushed() throws Exception {
6510         setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
6511 
6512         // Clear any interactions that occur as a result of CS starting up.
6513         reset(mMockDnsResolver);
6514 
6515         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
6516         waitForIdle();
6517         verify(mMockDnsResolver, never()).setResolverConfiguration(any());
6518         verifyNoMoreInteractions(mMockDnsResolver);
6519 
6520         final LinkProperties cellLp = new LinkProperties();
6521         cellLp.setInterfaceName(MOBILE_IFNAME);
6522         // Add IPv4 and IPv6 default routes, because DNS-over-TLS code does
6523         // "is-reachable" testing in order to not program netd with unreachable
6524         // nameservers that it might try repeated to validate.
6525         cellLp.addLinkAddress(new LinkAddress("192.0.2.4/24"));
6526         cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("192.0.2.4"),
6527                 MOBILE_IFNAME));
6528         cellLp.addLinkAddress(new LinkAddress("2001:db8:1::1/64"));
6529         cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("2001:db8:1::1"),
6530                 MOBILE_IFNAME));
6531         mCellNetworkAgent.sendLinkProperties(cellLp);
6532         mCellNetworkAgent.connect(false);
6533         waitForIdle();
6534 
6535         verify(mMockDnsResolver, times(1)).createNetworkCache(
6536                 eq(mCellNetworkAgent.getNetwork().netId));
6537         // CS tells dnsresolver about the empty DNS config for this network.
6538         verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(any());
6539         reset(mMockDnsResolver);
6540 
6541         cellLp.addDnsServer(InetAddress.getByName("2001:db8::1"));
6542         mCellNetworkAgent.sendLinkProperties(cellLp);
6543         waitForIdle();
6544         verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
6545                 mResolverParamsParcelCaptor.capture());
6546         ResolverParamsParcel resolvrParams = mResolverParamsParcelCaptor.getValue();
6547         assertEquals(1, resolvrParams.servers.length);
6548         assertTrue(ArrayUtils.contains(resolvrParams.servers, "2001:db8::1"));
6549         // Opportunistic mode.
6550         assertTrue(ArrayUtils.contains(resolvrParams.tlsServers, "2001:db8::1"));
6551         reset(mMockDnsResolver);
6552 
6553         cellLp.addDnsServer(InetAddress.getByName("192.0.2.1"));
6554         mCellNetworkAgent.sendLinkProperties(cellLp);
6555         waitForIdle();
6556         verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
6557                 mResolverParamsParcelCaptor.capture());
6558         resolvrParams = mResolverParamsParcelCaptor.getValue();
6559         assertEquals(2, resolvrParams.servers.length);
6560         assertTrue(ArrayUtils.containsAll(resolvrParams.servers,
6561                 new String[]{"2001:db8::1", "192.0.2.1"}));
6562         // Opportunistic mode.
6563         assertEquals(2, resolvrParams.tlsServers.length);
6564         assertTrue(ArrayUtils.containsAll(resolvrParams.tlsServers,
6565                 new String[]{"2001:db8::1", "192.0.2.1"}));
6566         reset(mMockDnsResolver);
6567 
6568         final String TLS_SPECIFIER = "tls.example.com";
6569         final String TLS_SERVER6 = "2001:db8:53::53";
6570         final InetAddress[] TLS_IPS = new InetAddress[]{ InetAddress.getByName(TLS_SERVER6) };
6571         final String[] TLS_SERVERS = new String[]{ TLS_SERVER6 };
6572         mCellNetworkAgent.mNmCallbacks.notifyPrivateDnsConfigResolved(
6573                 new PrivateDnsConfig(TLS_SPECIFIER, TLS_IPS).toParcel());
6574 
6575         waitForIdle();
6576         verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
6577                 mResolverParamsParcelCaptor.capture());
6578         resolvrParams = mResolverParamsParcelCaptor.getValue();
6579         assertEquals(2, resolvrParams.servers.length);
6580         assertTrue(ArrayUtils.containsAll(resolvrParams.servers,
6581                 new String[]{"2001:db8::1", "192.0.2.1"}));
6582         reset(mMockDnsResolver);
6583     }
6584 
6585     @Test
6586     public void testDnsConfigurationTransTypesPushed() throws Exception {
6587         // Clear any interactions that occur as a result of CS starting up.
6588         reset(mMockDnsResolver);
6589 
6590         final NetworkRequest request = new NetworkRequest.Builder()
6591                 .clearCapabilities().addCapability(NET_CAPABILITY_INTERNET)
6592                 .build();
6593         final TestNetworkCallback callback = new TestNetworkCallback();
6594         mCm.registerNetworkCallback(request, callback);
6595 
6596         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
6597         mWiFiNetworkAgent.connect(false);
6598         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
6599         verify(mMockDnsResolver, times(1)).createNetworkCache(
6600                 eq(mWiFiNetworkAgent.getNetwork().netId));
6601         verify(mMockDnsResolver, times(2)).setResolverConfiguration(
6602                 mResolverParamsParcelCaptor.capture());
6603         final ResolverParamsParcel resolverParams = mResolverParamsParcelCaptor.getValue();
6604         assertContainsExactly(resolverParams.transportTypes, TRANSPORT_WIFI);
6605         reset(mMockDnsResolver);
6606     }
6607 
6608     @Test
6609     public void testPrivateDnsNotification() throws Exception {
6610         NetworkRequest request = new NetworkRequest.Builder()
6611                 .clearCapabilities().addCapability(NET_CAPABILITY_INTERNET)
6612                 .build();
6613         TestNetworkCallback callback = new TestNetworkCallback();
6614         mCm.registerNetworkCallback(request, callback);
6615         // Bring up wifi.
6616         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
6617         mWiFiNetworkAgent.connect(false);
6618         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
6619         // Private DNS resolution failed, checking if the notification will be shown or not.
6620         mWiFiNetworkAgent.setNetworkInvalid(true /* isStrictMode */);
6621         mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
6622         waitForIdle();
6623         // If network validation failed, NetworkMonitor will re-evaluate the network.
6624         // ConnectivityService should filter the redundant notification. This part is trying to
6625         // simulate that situation and check if ConnectivityService could filter that case.
6626         mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
6627         waitForIdle();
6628         verify(mNotificationManager, timeout(TIMEOUT_MS).times(1)).notify(anyString(),
6629                 eq(NotificationType.PRIVATE_DNS_BROKEN.eventId), any());
6630         // If private DNS resolution successful, the PRIVATE_DNS_BROKEN notification shouldn't be
6631         // shown.
6632         mWiFiNetworkAgent.setNetworkValid(true /* isStrictMode */);
6633         mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
6634         waitForIdle();
6635         verify(mNotificationManager, timeout(TIMEOUT_MS).times(1)).cancel(anyString(),
6636                 eq(NotificationType.PRIVATE_DNS_BROKEN.eventId));
6637         // If private DNS resolution failed again, the PRIVATE_DNS_BROKEN notification should be
6638         // shown again.
6639         mWiFiNetworkAgent.setNetworkInvalid(true /* isStrictMode */);
6640         mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
6641         waitForIdle();
6642         verify(mNotificationManager, timeout(TIMEOUT_MS).times(2)).notify(anyString(),
6643                 eq(NotificationType.PRIVATE_DNS_BROKEN.eventId), any());
6644     }
6645 
6646     @Test
6647     public void testPrivateDnsSettingsChange() throws Exception {
6648         // Clear any interactions that occur as a result of CS starting up.
6649         reset(mMockDnsResolver);
6650 
6651         // The default on Android is opportunistic mode ("Automatic").
6652         setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
6653 
6654         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
6655         final NetworkRequest cellRequest = new NetworkRequest.Builder()
6656                 .addTransportType(TRANSPORT_CELLULAR).build();
6657         mCm.requestNetwork(cellRequest, cellNetworkCallback);
6658 
6659         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
6660         waitForIdle();
6661         // CS tells netd about the empty DNS config for this network.
6662         verify(mMockDnsResolver, never()).setResolverConfiguration(any());
6663         verifyNoMoreInteractions(mMockDnsResolver);
6664 
6665         final LinkProperties cellLp = new LinkProperties();
6666         cellLp.setInterfaceName(MOBILE_IFNAME);
6667         // Add IPv4 and IPv6 default routes, because DNS-over-TLS code does
6668         // "is-reachable" testing in order to not program netd with unreachable
6669         // nameservers that it might try repeated to validate.
6670         cellLp.addLinkAddress(new LinkAddress("192.0.2.4/24"));
6671         cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("192.0.2.4"),
6672                 MOBILE_IFNAME));
6673         cellLp.addLinkAddress(new LinkAddress("2001:db8:1::1/64"));
6674         cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("2001:db8:1::1"),
6675                 MOBILE_IFNAME));
6676         cellLp.addDnsServer(InetAddress.getByName("2001:db8::1"));
6677         cellLp.addDnsServer(InetAddress.getByName("192.0.2.1"));
6678 
6679         mCellNetworkAgent.sendLinkProperties(cellLp);
6680         mCellNetworkAgent.connect(false);
6681         waitForIdle();
6682         verify(mMockDnsResolver, times(1)).createNetworkCache(
6683                 eq(mCellNetworkAgent.getNetwork().netId));
6684         verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
6685                 mResolverParamsParcelCaptor.capture());
6686         ResolverParamsParcel resolvrParams = mResolverParamsParcelCaptor.getValue();
6687         assertEquals(2, resolvrParams.tlsServers.length);
6688         assertTrue(ArrayUtils.containsAll(resolvrParams.tlsServers,
6689                 new String[] { "2001:db8::1", "192.0.2.1" }));
6690         // Opportunistic mode.
6691         assertEquals(2, resolvrParams.tlsServers.length);
6692         assertTrue(ArrayUtils.containsAll(resolvrParams.tlsServers,
6693                 new String[] { "2001:db8::1", "192.0.2.1" }));
6694         reset(mMockDnsResolver);
6695         cellNetworkCallback.expectCallback(CallbackEntry.AVAILABLE, mCellNetworkAgent);
6696         cellNetworkCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED,
6697                 mCellNetworkAgent);
6698         CallbackEntry.LinkPropertiesChanged cbi = cellNetworkCallback.expectCallback(
6699                 CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
6700         cellNetworkCallback.expectCallback(CallbackEntry.BLOCKED_STATUS, mCellNetworkAgent);
6701         cellNetworkCallback.assertNoCallback();
6702         assertFalse(cbi.getLp().isPrivateDnsActive());
6703         assertNull(cbi.getLp().getPrivateDnsServerName());
6704 
6705         setPrivateDnsSettings(PRIVATE_DNS_MODE_OFF, "ignored.example.com");
6706         verify(mMockDnsResolver, times(1)).setResolverConfiguration(
6707                 mResolverParamsParcelCaptor.capture());
6708         resolvrParams = mResolverParamsParcelCaptor.getValue();
6709         assertEquals(2, resolvrParams.servers.length);
6710         assertTrue(ArrayUtils.containsAll(resolvrParams.servers,
6711                 new String[] { "2001:db8::1", "192.0.2.1" }));
6712         reset(mMockDnsResolver);
6713         cellNetworkCallback.assertNoCallback();
6714 
6715         setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
6716         verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
6717                 mResolverParamsParcelCaptor.capture());
6718         resolvrParams = mResolverParamsParcelCaptor.getValue();
6719         assertEquals(2, resolvrParams.servers.length);
6720         assertTrue(ArrayUtils.containsAll(resolvrParams.servers,
6721                 new String[] { "2001:db8::1", "192.0.2.1" }));
6722         assertEquals(2, resolvrParams.tlsServers.length);
6723         assertTrue(ArrayUtils.containsAll(resolvrParams.tlsServers,
6724                 new String[] { "2001:db8::1", "192.0.2.1" }));
6725         reset(mMockDnsResolver);
6726         cellNetworkCallback.assertNoCallback();
6727 
6728         setPrivateDnsSettings(PRIVATE_DNS_MODE_PROVIDER_HOSTNAME, "strict.example.com");
6729         // Can't test dns configuration for strict mode without properly mocking
6730         // out the DNS lookups, but can test that LinkProperties is updated.
6731         cbi = cellNetworkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED,
6732                 mCellNetworkAgent);
6733         cellNetworkCallback.assertNoCallback();
6734         assertTrue(cbi.getLp().isPrivateDnsActive());
6735         assertEquals("strict.example.com", cbi.getLp().getPrivateDnsServerName());
6736     }
6737 
6738     private PrivateDnsValidationEventParcel makePrivateDnsValidationEvent(
6739             final int netId, final String ipAddress, final String hostname, final int validation) {
6740         final PrivateDnsValidationEventParcel event = new PrivateDnsValidationEventParcel();
6741         event.netId = netId;
6742         event.ipAddress = ipAddress;
6743         event.hostname = hostname;
6744         event.validation = validation;
6745         return event;
6746     }
6747 
6748     @Test
6749     public void testLinkPropertiesWithPrivateDnsValidationEvents() throws Exception {
6750         // The default on Android is opportunistic mode ("Automatic").
6751         setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
6752 
6753         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
6754         final NetworkRequest cellRequest = new NetworkRequest.Builder()
6755                 .addTransportType(TRANSPORT_CELLULAR).build();
6756         mCm.requestNetwork(cellRequest, cellNetworkCallback);
6757 
6758         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
6759         waitForIdle();
6760         LinkProperties lp = new LinkProperties();
6761         mCellNetworkAgent.sendLinkProperties(lp);
6762         mCellNetworkAgent.connect(false);
6763         waitForIdle();
6764         cellNetworkCallback.expectCallback(CallbackEntry.AVAILABLE, mCellNetworkAgent);
6765         cellNetworkCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED,
6766                 mCellNetworkAgent);
6767         CallbackEntry.LinkPropertiesChanged cbi = cellNetworkCallback.expectCallback(
6768                 CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
6769         cellNetworkCallback.expectCallback(CallbackEntry.BLOCKED_STATUS, mCellNetworkAgent);
6770         cellNetworkCallback.assertNoCallback();
6771         assertFalse(cbi.getLp().isPrivateDnsActive());
6772         assertNull(cbi.getLp().getPrivateDnsServerName());
6773         Set<InetAddress> dnsServers = new HashSet<>();
6774         checkDnsServers(cbi.getLp(), dnsServers);
6775 
6776         // Send a validation event for a server that is not part of the current
6777         // resolver config. The validation event should be ignored.
6778         mService.mResolverUnsolEventCallback.onPrivateDnsValidationEvent(
6779                 makePrivateDnsValidationEvent(mCellNetworkAgent.getNetwork().netId, "",
6780                         "145.100.185.18", VALIDATION_RESULT_SUCCESS));
6781         cellNetworkCallback.assertNoCallback();
6782 
6783         // Add a dns server to the LinkProperties.
6784         LinkProperties lp2 = new LinkProperties(lp);
6785         lp2.addDnsServer(InetAddress.getByName("145.100.185.16"));
6786         mCellNetworkAgent.sendLinkProperties(lp2);
6787         cbi = cellNetworkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED,
6788                 mCellNetworkAgent);
6789         cellNetworkCallback.assertNoCallback();
6790         assertFalse(cbi.getLp().isPrivateDnsActive());
6791         assertNull(cbi.getLp().getPrivateDnsServerName());
6792         dnsServers.add(InetAddress.getByName("145.100.185.16"));
6793         checkDnsServers(cbi.getLp(), dnsServers);
6794 
6795         // Send a validation event containing a hostname that is not part of
6796         // the current resolver config. The validation event should be ignored.
6797         mService.mResolverUnsolEventCallback.onPrivateDnsValidationEvent(
6798                 makePrivateDnsValidationEvent(mCellNetworkAgent.getNetwork().netId,
6799                         "145.100.185.16", "hostname", VALIDATION_RESULT_SUCCESS));
6800         cellNetworkCallback.assertNoCallback();
6801 
6802         // Send a validation event where validation failed.
6803         mService.mResolverUnsolEventCallback.onPrivateDnsValidationEvent(
6804                 makePrivateDnsValidationEvent(mCellNetworkAgent.getNetwork().netId,
6805                         "145.100.185.16", "", VALIDATION_RESULT_FAILURE));
6806         cellNetworkCallback.assertNoCallback();
6807 
6808         // Send a validation event where validation succeeded for a server in
6809         // the current resolver config. A LinkProperties callback with updated
6810         // private dns fields should be sent.
6811         mService.mResolverUnsolEventCallback.onPrivateDnsValidationEvent(
6812                 makePrivateDnsValidationEvent(mCellNetworkAgent.getNetwork().netId,
6813                         "145.100.185.16", "", VALIDATION_RESULT_SUCCESS));
6814         cbi = cellNetworkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED,
6815                 mCellNetworkAgent);
6816         cellNetworkCallback.assertNoCallback();
6817         assertTrue(cbi.getLp().isPrivateDnsActive());
6818         assertNull(cbi.getLp().getPrivateDnsServerName());
6819         checkDnsServers(cbi.getLp(), dnsServers);
6820 
6821         // The private dns fields in LinkProperties should be preserved when
6822         // the network agent sends unrelated changes.
6823         LinkProperties lp3 = new LinkProperties(lp2);
6824         lp3.setMtu(1300);
6825         mCellNetworkAgent.sendLinkProperties(lp3);
6826         cbi = cellNetworkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED,
6827                 mCellNetworkAgent);
6828         cellNetworkCallback.assertNoCallback();
6829         assertTrue(cbi.getLp().isPrivateDnsActive());
6830         assertNull(cbi.getLp().getPrivateDnsServerName());
6831         checkDnsServers(cbi.getLp(), dnsServers);
6832         assertEquals(1300, cbi.getLp().getMtu());
6833 
6834         // Removing the only validated server should affect the private dns
6835         // fields in LinkProperties.
6836         LinkProperties lp4 = new LinkProperties(lp3);
6837         lp4.removeDnsServer(InetAddress.getByName("145.100.185.16"));
6838         mCellNetworkAgent.sendLinkProperties(lp4);
6839         cbi = cellNetworkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED,
6840                 mCellNetworkAgent);
6841         cellNetworkCallback.assertNoCallback();
6842         assertFalse(cbi.getLp().isPrivateDnsActive());
6843         assertNull(cbi.getLp().getPrivateDnsServerName());
6844         dnsServers.remove(InetAddress.getByName("145.100.185.16"));
6845         checkDnsServers(cbi.getLp(), dnsServers);
6846         assertEquals(1300, cbi.getLp().getMtu());
6847     }
6848 
6849     private void checkDirectlyConnectedRoutes(Object callbackObj,
6850             Collection<LinkAddress> linkAddresses, Collection<RouteInfo> otherRoutes) {
6851         assertTrue(callbackObj instanceof LinkProperties);
6852         LinkProperties lp = (LinkProperties) callbackObj;
6853 
6854         Set<RouteInfo> expectedRoutes = new ArraySet<>();
6855         expectedRoutes.addAll(otherRoutes);
6856         for (LinkAddress address : linkAddresses) {
6857             RouteInfo localRoute = new RouteInfo(address, null, lp.getInterfaceName());
6858             // Duplicates in linkAddresses are considered failures
6859             assertTrue(expectedRoutes.add(localRoute));
6860         }
6861         List<RouteInfo> observedRoutes = lp.getRoutes();
6862         assertEquals(expectedRoutes.size(), observedRoutes.size());
6863         assertTrue(observedRoutes.containsAll(expectedRoutes));
6864     }
6865 
6866     private static void checkDnsServers(Object callbackObj, Set<InetAddress> dnsServers) {
6867         assertTrue(callbackObj instanceof LinkProperties);
6868         LinkProperties lp = (LinkProperties) callbackObj;
6869         assertEquals(dnsServers.size(), lp.getDnsServers().size());
6870         assertTrue(lp.getDnsServers().containsAll(dnsServers));
6871     }
6872 
6873     @Test
6874     public void testApplyUnderlyingCapabilities() throws Exception {
6875         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
6876         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
6877         mCellNetworkAgent.connect(false /* validated */);
6878         mWiFiNetworkAgent.connect(false /* validated */);
6879 
6880         final NetworkCapabilities cellNc = new NetworkCapabilities()
6881                 .addTransportType(TRANSPORT_CELLULAR)
6882                 .addCapability(NET_CAPABILITY_INTERNET)
6883                 .addCapability(NET_CAPABILITY_NOT_CONGESTED)
6884                 .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
6885                 .setLinkDownstreamBandwidthKbps(10);
6886         final NetworkCapabilities wifiNc = new NetworkCapabilities()
6887                 .addTransportType(TRANSPORT_WIFI)
6888                 .addCapability(NET_CAPABILITY_INTERNET)
6889                 .addCapability(NET_CAPABILITY_NOT_METERED)
6890                 .addCapability(NET_CAPABILITY_NOT_ROAMING)
6891                 .addCapability(NET_CAPABILITY_NOT_CONGESTED)
6892                 .addCapability(NET_CAPABILITY_NOT_SUSPENDED)
6893                 .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
6894                 .setLinkUpstreamBandwidthKbps(20);
6895         mCellNetworkAgent.setNetworkCapabilities(cellNc, true /* sendToConnectivityService */);
6896         mWiFiNetworkAgent.setNetworkCapabilities(wifiNc, true /* sendToConnectivityService */);
6897         waitForIdle();
6898 
6899         final Network mobile = mCellNetworkAgent.getNetwork();
6900         final Network wifi = mWiFiNetworkAgent.getNetwork();
6901 
6902         final NetworkCapabilities initialCaps = new NetworkCapabilities();
6903         initialCaps.addTransportType(TRANSPORT_VPN);
6904         initialCaps.addCapability(NET_CAPABILITY_INTERNET);
6905         initialCaps.removeCapability(NET_CAPABILITY_NOT_VPN);
6906 
6907         final NetworkCapabilities withNoUnderlying = new NetworkCapabilities();
6908         withNoUnderlying.addCapability(NET_CAPABILITY_INTERNET);
6909         withNoUnderlying.addCapability(NET_CAPABILITY_NOT_CONGESTED);
6910         withNoUnderlying.addCapability(NET_CAPABILITY_NOT_ROAMING);
6911         withNoUnderlying.addCapability(NET_CAPABILITY_NOT_SUSPENDED);
6912         withNoUnderlying.addTransportType(TRANSPORT_VPN);
6913         withNoUnderlying.removeCapability(NET_CAPABILITY_NOT_VPN);
6914 
6915         final NetworkCapabilities withMobileUnderlying = new NetworkCapabilities(withNoUnderlying);
6916         withMobileUnderlying.addTransportType(TRANSPORT_CELLULAR);
6917         withMobileUnderlying.removeCapability(NET_CAPABILITY_NOT_ROAMING);
6918         withMobileUnderlying.removeCapability(NET_CAPABILITY_NOT_SUSPENDED);
6919         withMobileUnderlying.setLinkDownstreamBandwidthKbps(10);
6920 
6921         final NetworkCapabilities withWifiUnderlying = new NetworkCapabilities(withNoUnderlying);
6922         withWifiUnderlying.addTransportType(TRANSPORT_WIFI);
6923         withWifiUnderlying.addCapability(NET_CAPABILITY_NOT_METERED);
6924         withWifiUnderlying.setLinkUpstreamBandwidthKbps(20);
6925 
6926         final NetworkCapabilities withWifiAndMobileUnderlying =
6927                 new NetworkCapabilities(withNoUnderlying);
6928         withWifiAndMobileUnderlying.addTransportType(TRANSPORT_CELLULAR);
6929         withWifiAndMobileUnderlying.addTransportType(TRANSPORT_WIFI);
6930         withWifiAndMobileUnderlying.removeCapability(NET_CAPABILITY_NOT_METERED);
6931         withWifiAndMobileUnderlying.removeCapability(NET_CAPABILITY_NOT_ROAMING);
6932         withWifiAndMobileUnderlying.setLinkDownstreamBandwidthKbps(10);
6933         withWifiAndMobileUnderlying.setLinkUpstreamBandwidthKbps(20);
6934 
6935         final NetworkCapabilities initialCapsNotMetered = new NetworkCapabilities(initialCaps);
6936         initialCapsNotMetered.addCapability(NET_CAPABILITY_NOT_METERED);
6937 
6938         NetworkCapabilities caps = new NetworkCapabilities(initialCaps);
6939         mService.applyUnderlyingCapabilities(new Network[]{}, initialCapsNotMetered, caps);
6940         assertEquals(withNoUnderlying, caps);
6941 
6942         caps = new NetworkCapabilities(initialCaps);
6943         mService.applyUnderlyingCapabilities(new Network[]{null}, initialCapsNotMetered, caps);
6944         assertEquals(withNoUnderlying, caps);
6945 
6946         caps = new NetworkCapabilities(initialCaps);
6947         mService.applyUnderlyingCapabilities(new Network[]{mobile}, initialCapsNotMetered, caps);
6948         assertEquals(withMobileUnderlying, caps);
6949 
6950         mService.applyUnderlyingCapabilities(new Network[]{wifi}, initialCapsNotMetered, caps);
6951         assertEquals(withWifiUnderlying, caps);
6952 
6953         withWifiUnderlying.removeCapability(NET_CAPABILITY_NOT_METERED);
6954         caps = new NetworkCapabilities(initialCaps);
6955         mService.applyUnderlyingCapabilities(new Network[]{wifi}, initialCaps, caps);
6956         assertEquals(withWifiUnderlying, caps);
6957 
6958         caps = new NetworkCapabilities(initialCaps);
6959         mService.applyUnderlyingCapabilities(new Network[]{mobile, wifi}, initialCaps, caps);
6960         assertEquals(withWifiAndMobileUnderlying, caps);
6961 
6962         withWifiUnderlying.addCapability(NET_CAPABILITY_NOT_METERED);
6963         caps = new NetworkCapabilities(initialCaps);
6964         mService.applyUnderlyingCapabilities(new Network[]{null, mobile, null, wifi},
6965                 initialCapsNotMetered, caps);
6966         assertEquals(withWifiAndMobileUnderlying, caps);
6967 
6968         caps = new NetworkCapabilities(initialCaps);
6969         mService.applyUnderlyingCapabilities(new Network[]{null, mobile, null, wifi},
6970                 initialCapsNotMetered, caps);
6971         assertEquals(withWifiAndMobileUnderlying, caps);
6972 
6973         mService.applyUnderlyingCapabilities(null, initialCapsNotMetered, caps);
6974         assertEquals(withWifiUnderlying, caps);
6975     }
6976 
6977     @Test
6978     public void testVpnConnectDisconnectUnderlyingNetwork() throws Exception {
6979         final TestNetworkCallback callback = new TestNetworkCallback();
6980         final NetworkRequest request = new NetworkRequest.Builder()
6981                 .removeCapability(NET_CAPABILITY_NOT_VPN).build();
6982 
6983         mCm.registerNetworkCallback(request, callback);
6984 
6985         // Bring up a VPN that specifies an underlying network that does not exist yet.
6986         // Note: it's sort of meaningless for a VPN app to declare a network that doesn't exist yet,
6987         // (and doing so is difficult without using reflection) but it's good to test that the code
6988         // behaves approximately correctly.
6989         mMockVpn.establishForMyUid(false, true, false);
6990         assertUidRangesUpdatedForMyUid(true);
6991         final Network wifiNetwork = new Network(mNetIdManager.peekNextNetId());
6992         mMockVpn.setUnderlyingNetworks(new Network[]{wifiNetwork});
6993         callback.expectAvailableCallbacksUnvalidated(mMockVpn);
6994         assertTrue(mCm.getNetworkCapabilities(mMockVpn.getNetwork())
6995                 .hasTransport(TRANSPORT_VPN));
6996         assertFalse(mCm.getNetworkCapabilities(mMockVpn.getNetwork())
6997                 .hasTransport(TRANSPORT_WIFI));
6998 
6999         // Make that underlying network connect, and expect to see its capabilities immediately
7000         // reflected in the VPN's capabilities.
7001         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
7002         assertEquals(wifiNetwork, mWiFiNetworkAgent.getNetwork());
7003         mWiFiNetworkAgent.connect(false);
7004         // TODO: the callback for the VPN happens before any callbacks are called for the wifi
7005         // network that has just connected. There appear to be two issues here:
7006         // 1. The VPN code will accept an underlying network as soon as getNetworkCapabilities() for
7007         //    it returns non-null (which happens very early, during handleRegisterNetworkAgent).
7008         //    This is not correct because that that point the network is not connected and cannot
7009         //    pass any traffic.
7010         // 2. When a network connects, updateNetworkInfo propagates underlying network capabilities
7011         //    before rematching networks.
7012         // Given that this scenario can't really happen, this is probably fine for now.
7013         callback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, mMockVpn);
7014         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
7015         assertTrue(mCm.getNetworkCapabilities(mMockVpn.getNetwork())
7016                 .hasTransport(TRANSPORT_VPN));
7017         assertTrue(mCm.getNetworkCapabilities(mMockVpn.getNetwork())
7018                 .hasTransport(TRANSPORT_WIFI));
7019 
7020         // Disconnect the network, and expect to see the VPN capabilities change accordingly.
7021         mWiFiNetworkAgent.disconnect();
7022         callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
7023         callback.expectCapabilitiesThat(mMockVpn, (nc) ->
7024                 nc.getTransportTypes().length == 1 && nc.hasTransport(TRANSPORT_VPN));
7025 
7026         mMockVpn.disconnect();
7027         mCm.unregisterNetworkCallback(callback);
7028     }
7029 
7030     private void assertGetNetworkInfoOfGetActiveNetworkIsConnected(boolean expectedConnectivity) {
7031         // What Chromium used to do before https://chromium-review.googlesource.com/2605304
7032         assertEquals("Unexpected result for getActiveNetworkInfo(getActiveNetwork())",
7033                 expectedConnectivity, mCm.getNetworkInfo(mCm.getActiveNetwork()).isConnected());
7034     }
7035 
7036     @Test
7037     public void testVpnUnderlyingNetworkSuspended() throws Exception {
7038         final TestNetworkCallback callback = new TestNetworkCallback();
7039         mCm.registerDefaultNetworkCallback(callback);
7040 
7041         // Connect a VPN.
7042         mMockVpn.establishForMyUid(false /* validated */, true /* hasInternet */,
7043                 false /* isStrictMode */);
7044         callback.expectAvailableCallbacksUnvalidated(mMockVpn);
7045 
7046         // Connect cellular data.
7047         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
7048         mCellNetworkAgent.connect(false /* validated */);
7049         callback.expectCapabilitiesThat(mMockVpn,
7050                 nc -> nc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)
7051                         && nc.hasTransport(TRANSPORT_CELLULAR));
7052         callback.assertNoCallback();
7053 
7054         assertTrue(mCm.getNetworkCapabilities(mMockVpn.getNetwork())
7055                 .hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
7056         assertNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
7057         assertNetworkInfo(TYPE_WIFI, DetailedState.DISCONNECTED);
7058         assertNetworkInfo(TYPE_VPN, DetailedState.CONNECTED);
7059         assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
7060         assertGetNetworkInfoOfGetActiveNetworkIsConnected(true);
7061 
7062         // Suspend the cellular network and expect the VPN to be suspended.
7063         mCellNetworkAgent.suspend();
7064         callback.expectCapabilitiesThat(mMockVpn,
7065                 nc -> !nc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)
7066                         && nc.hasTransport(TRANSPORT_CELLULAR));
7067         callback.expectCallback(CallbackEntry.SUSPENDED, mMockVpn);
7068         callback.assertNoCallback();
7069 
7070         assertFalse(mCm.getNetworkCapabilities(mMockVpn.getNetwork())
7071                 .hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
7072         assertNetworkInfo(TYPE_MOBILE, DetailedState.SUSPENDED);
7073         assertNetworkInfo(TYPE_WIFI, DetailedState.DISCONNECTED);
7074         assertNetworkInfo(TYPE_VPN, DetailedState.SUSPENDED);
7075         assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.SUSPENDED);
7076         // VPN's main underlying network is suspended, so no connectivity.
7077         assertGetNetworkInfoOfGetActiveNetworkIsConnected(false);
7078 
7079         // Switch to another network. The VPN should no longer be suspended.
7080         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
7081         mWiFiNetworkAgent.connect(false /* validated */);
7082         callback.expectCapabilitiesThat(mMockVpn,
7083                 nc -> nc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)
7084                         && nc.hasTransport(TRANSPORT_WIFI));
7085         callback.expectCallback(CallbackEntry.RESUMED, mMockVpn);
7086         callback.assertNoCallback();
7087 
7088         assertTrue(mCm.getNetworkCapabilities(mMockVpn.getNetwork())
7089                 .hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
7090         assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED);
7091         assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
7092         assertNetworkInfo(TYPE_VPN, DetailedState.CONNECTED);
7093         assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
7094         assertGetNetworkInfoOfGetActiveNetworkIsConnected(true);
7095 
7096         // Unsuspend cellular and then switch back to it. The VPN remains not suspended.
7097         mCellNetworkAgent.resume();
7098         callback.assertNoCallback();
7099         mWiFiNetworkAgent.disconnect();
7100         callback.expectCapabilitiesThat(mMockVpn,
7101                 nc -> nc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)
7102                         && nc.hasTransport(TRANSPORT_CELLULAR));
7103         // Spurious double callback?
7104         callback.expectCapabilitiesThat(mMockVpn,
7105                 nc -> nc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)
7106                         && nc.hasTransport(TRANSPORT_CELLULAR));
7107         callback.assertNoCallback();
7108 
7109         assertTrue(mCm.getNetworkCapabilities(mMockVpn.getNetwork())
7110                 .hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
7111         assertNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
7112         assertNetworkInfo(TYPE_WIFI, DetailedState.DISCONNECTED);
7113         assertNetworkInfo(TYPE_VPN, DetailedState.CONNECTED);
7114         assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
7115         assertGetNetworkInfoOfGetActiveNetworkIsConnected(true);
7116 
7117         // Suspend cellular and expect no connectivity.
7118         mCellNetworkAgent.suspend();
7119         callback.expectCapabilitiesThat(mMockVpn,
7120                 nc -> !nc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)
7121                         && nc.hasTransport(TRANSPORT_CELLULAR));
7122         callback.expectCallback(CallbackEntry.SUSPENDED, mMockVpn);
7123         callback.assertNoCallback();
7124 
7125         assertFalse(mCm.getNetworkCapabilities(mMockVpn.getNetwork())
7126                 .hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
7127         assertNetworkInfo(TYPE_MOBILE, DetailedState.SUSPENDED);
7128         assertNetworkInfo(TYPE_WIFI, DetailedState.DISCONNECTED);
7129         assertNetworkInfo(TYPE_VPN, DetailedState.SUSPENDED);
7130         assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.SUSPENDED);
7131         assertGetNetworkInfoOfGetActiveNetworkIsConnected(false);
7132 
7133         // Resume cellular and expect that connectivity comes back.
7134         mCellNetworkAgent.resume();
7135         callback.expectCapabilitiesThat(mMockVpn,
7136                 nc -> nc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)
7137                         && nc.hasTransport(TRANSPORT_CELLULAR));
7138         callback.expectCallback(CallbackEntry.RESUMED, mMockVpn);
7139         callback.assertNoCallback();
7140 
7141         assertTrue(mCm.getNetworkCapabilities(mMockVpn.getNetwork())
7142                 .hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
7143         assertNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
7144         assertNetworkInfo(TYPE_WIFI, DetailedState.DISCONNECTED);
7145         assertNetworkInfo(TYPE_VPN, DetailedState.CONNECTED);
7146         assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
7147         assertGetNetworkInfoOfGetActiveNetworkIsConnected(true);
7148     }
7149 
7150     @Test
7151     public void testVpnNetworkActive() throws Exception {
7152         // NETWORK_SETTINGS is necessary to call registerSystemDefaultNetworkCallback.
7153         mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_GRANTED);
7154 
7155         final int uid = Process.myUid();
7156 
7157         final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback();
7158         final TestNetworkCallback genericNotVpnNetworkCallback = new TestNetworkCallback();
7159         final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
7160         final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
7161         final TestNetworkCallback defaultCallback = new TestNetworkCallback();
7162         final TestNetworkCallback systemDefaultCallback = new TestNetworkCallback();
7163         final NetworkRequest genericNotVpnRequest = new NetworkRequest.Builder().build();
7164         final NetworkRequest genericRequest = new NetworkRequest.Builder()
7165                 .removeCapability(NET_CAPABILITY_NOT_VPN).build();
7166         final NetworkRequest wifiRequest = new NetworkRequest.Builder()
7167                 .addTransportType(TRANSPORT_WIFI).build();
7168         final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder()
7169                 .removeCapability(NET_CAPABILITY_NOT_VPN)
7170                 .addTransportType(TRANSPORT_VPN).build();
7171         mCm.registerNetworkCallback(genericRequest, genericNetworkCallback);
7172         mCm.registerNetworkCallback(genericNotVpnRequest, genericNotVpnNetworkCallback);
7173         mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
7174         mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
7175         mCm.registerDefaultNetworkCallback(defaultCallback);
7176         mCm.registerSystemDefaultNetworkCallback(systemDefaultCallback,
7177                 new Handler(ConnectivityThread.getInstanceLooper()));
7178         defaultCallback.assertNoCallback();
7179 
7180         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
7181         mWiFiNetworkAgent.connect(false);
7182 
7183         genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
7184         genericNotVpnNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
7185         wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
7186         defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
7187         systemDefaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
7188         vpnNetworkCallback.assertNoCallback();
7189         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
7190 
7191         final Set<UidRange> ranges = uidRangesForUids(uid);
7192         mMockVpn.registerAgent(ranges);
7193         mMockVpn.setUnderlyingNetworks(new Network[0]);
7194 
7195         // VPN networks do not satisfy the default request and are automatically validated
7196         // by NetworkMonitor
7197         assertFalse(NetworkMonitorUtils.isValidationRequired(
7198                 mMockVpn.getAgent().getNetworkCapabilities()));
7199         mMockVpn.getAgent().setNetworkValid(false /* isStrictMode */);
7200 
7201         mMockVpn.connect(false);
7202 
7203         genericNetworkCallback.expectAvailableThenValidatedCallbacks(mMockVpn);
7204         genericNotVpnNetworkCallback.assertNoCallback();
7205         wifiNetworkCallback.assertNoCallback();
7206         vpnNetworkCallback.expectAvailableThenValidatedCallbacks(mMockVpn);
7207         defaultCallback.expectAvailableThenValidatedCallbacks(mMockVpn);
7208         systemDefaultCallback.assertNoCallback();
7209         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
7210         assertEquals(mWiFiNetworkAgent.getNetwork(),
7211                 systemDefaultCallback.getLastAvailableNetwork());
7212 
7213         ranges.clear();
7214         mMockVpn.setUids(ranges);
7215 
7216         genericNetworkCallback.expectCallback(CallbackEntry.LOST, mMockVpn);
7217         genericNotVpnNetworkCallback.assertNoCallback();
7218         wifiNetworkCallback.assertNoCallback();
7219         vpnNetworkCallback.expectCallback(CallbackEntry.LOST, mMockVpn);
7220 
7221         // TODO : The default network callback should actually get a LOST call here (also see the
7222         // comment below for AVAILABLE). This is because ConnectivityService does not look at UID
7223         // ranges at all when determining whether a network should be rematched. In practice, VPNs
7224         // can't currently update their UIDs without disconnecting, so this does not matter too
7225         // much, but that is the reason the test here has to check for an update to the
7226         // capabilities instead of the expected LOST then AVAILABLE.
7227         defaultCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, mMockVpn);
7228         systemDefaultCallback.assertNoCallback();
7229 
7230         ranges.add(new UidRange(uid, uid));
7231         mMockVpn.setUids(ranges);
7232 
7233         genericNetworkCallback.expectAvailableCallbacksValidated(mMockVpn);
7234         genericNotVpnNetworkCallback.assertNoCallback();
7235         wifiNetworkCallback.assertNoCallback();
7236         vpnNetworkCallback.expectAvailableCallbacksValidated(mMockVpn);
7237         // TODO : Here like above, AVAILABLE would be correct, but because this can't actually
7238         // happen outside of the test, ConnectivityService does not rematch callbacks.
7239         defaultCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, mMockVpn);
7240         systemDefaultCallback.assertNoCallback();
7241 
7242         mWiFiNetworkAgent.disconnect();
7243 
7244         genericNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
7245         genericNotVpnNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
7246         wifiNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
7247         vpnNetworkCallback.assertNoCallback();
7248         defaultCallback.assertNoCallback();
7249         systemDefaultCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
7250 
7251         mMockVpn.disconnect();
7252 
7253         genericNetworkCallback.expectCallback(CallbackEntry.LOST, mMockVpn);
7254         genericNotVpnNetworkCallback.assertNoCallback();
7255         wifiNetworkCallback.assertNoCallback();
7256         vpnNetworkCallback.expectCallback(CallbackEntry.LOST, mMockVpn);
7257         defaultCallback.expectCallback(CallbackEntry.LOST, mMockVpn);
7258         systemDefaultCallback.assertNoCallback();
7259         assertEquals(null, mCm.getActiveNetwork());
7260 
7261         mCm.unregisterNetworkCallback(genericNetworkCallback);
7262         mCm.unregisterNetworkCallback(wifiNetworkCallback);
7263         mCm.unregisterNetworkCallback(vpnNetworkCallback);
7264         mCm.unregisterNetworkCallback(defaultCallback);
7265         mCm.unregisterNetworkCallback(systemDefaultCallback);
7266     }
7267 
7268     @Test
7269     public void testVpnWithoutInternet() throws Exception {
7270         final int uid = Process.myUid();
7271 
7272         final TestNetworkCallback defaultCallback = new TestNetworkCallback();
7273         mCm.registerDefaultNetworkCallback(defaultCallback);
7274 
7275         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
7276         mWiFiNetworkAgent.connect(true);
7277 
7278         defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
7279         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
7280 
7281         mMockVpn.establishForMyUid(true /* validated */, false /* hasInternet */,
7282                 false /* isStrictMode */);
7283         assertUidRangesUpdatedForMyUid(true);
7284 
7285         defaultCallback.assertNoCallback();
7286         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
7287 
7288         mMockVpn.disconnect();
7289         defaultCallback.assertNoCallback();
7290 
7291         mCm.unregisterNetworkCallback(defaultCallback);
7292     }
7293 
7294     @Test
7295     public void testVpnWithInternet() throws Exception {
7296         final int uid = Process.myUid();
7297 
7298         final TestNetworkCallback defaultCallback = new TestNetworkCallback();
7299         mCm.registerDefaultNetworkCallback(defaultCallback);
7300 
7301         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
7302         mWiFiNetworkAgent.connect(true);
7303 
7304         defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
7305         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
7306 
7307         mMockVpn.establishForMyUid(true /* validated */, true /* hasInternet */,
7308                 false /* isStrictMode */);
7309         assertUidRangesUpdatedForMyUid(true);
7310 
7311         defaultCallback.expectAvailableThenValidatedCallbacks(mMockVpn);
7312         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
7313 
7314         mMockVpn.disconnect();
7315         defaultCallback.expectCallback(CallbackEntry.LOST, mMockVpn);
7316         defaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
7317 
7318         mCm.unregisterNetworkCallback(defaultCallback);
7319     }
7320 
7321     @Test
7322     public void testVpnUnvalidated() throws Exception {
7323         final TestNetworkCallback callback = new TestNetworkCallback();
7324         mCm.registerDefaultNetworkCallback(callback);
7325 
7326         // Bring up Ethernet.
7327         mEthernetNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
7328         mEthernetNetworkAgent.connect(true);
7329         callback.expectAvailableThenValidatedCallbacks(mEthernetNetworkAgent);
7330         callback.assertNoCallback();
7331 
7332         // Bring up a VPN that has the INTERNET capability, initially unvalidated.
7333         mMockVpn.establishForMyUid(false /* validated */, true /* hasInternet */,
7334                 false /* isStrictMode */);
7335         assertUidRangesUpdatedForMyUid(true);
7336 
7337         // Even though the VPN is unvalidated, it becomes the default network for our app.
7338         callback.expectAvailableCallbacksUnvalidated(mMockVpn);
7339         callback.assertNoCallback();
7340 
7341         assertEquals(mMockVpn.getNetwork(), mCm.getActiveNetwork());
7342 
7343         NetworkCapabilities nc = mCm.getNetworkCapabilities(mMockVpn.getNetwork());
7344         assertFalse(nc.hasCapability(NET_CAPABILITY_VALIDATED));
7345         assertTrue(nc.hasCapability(NET_CAPABILITY_INTERNET));
7346 
7347         assertFalse(NetworkMonitorUtils.isValidationRequired(
7348                 mMockVpn.getAgent().getNetworkCapabilities()));
7349         assertTrue(NetworkMonitorUtils.isPrivateDnsValidationRequired(
7350                 mMockVpn.getAgent().getNetworkCapabilities()));
7351 
7352         // Pretend that the VPN network validates.
7353         mMockVpn.getAgent().setNetworkValid(false /* isStrictMode */);
7354         mMockVpn.getAgent().mNetworkMonitor.forceReevaluation(Process.myUid());
7355         // Expect to see the validated capability, but no other changes, because the VPN is already
7356         // the default network for the app.
7357         callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mMockVpn);
7358         callback.assertNoCallback();
7359 
7360         mMockVpn.disconnect();
7361         callback.expectCallback(CallbackEntry.LOST, mMockVpn);
7362         callback.expectAvailableCallbacksValidated(mEthernetNetworkAgent);
7363     }
7364 
7365     @Test
7366     public void testVpnStartsWithUnderlyingCaps() throws Exception {
7367         final int uid = Process.myUid();
7368 
7369         final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
7370         final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder()
7371                 .removeCapability(NET_CAPABILITY_NOT_VPN)
7372                 .addTransportType(TRANSPORT_VPN)
7373                 .build();
7374         mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
7375         vpnNetworkCallback.assertNoCallback();
7376 
7377         // Connect cell. It will become the default network, and in the absence of setting
7378         // underlying networks explicitly it will become the sole underlying network for the vpn.
7379         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
7380         mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_SUSPENDED);
7381         mCellNetworkAgent.connect(true);
7382 
7383         mMockVpn.establishForMyUid(true /* validated */, false /* hasInternet */,
7384                 false /* isStrictMode */);
7385         assertUidRangesUpdatedForMyUid(true);
7386 
7387         vpnNetworkCallback.expectAvailableCallbacks(mMockVpn.getNetwork(),
7388                 false /* suspended */, false /* validated */, false /* blocked */, TIMEOUT_MS);
7389         vpnNetworkCallback.expectCapabilitiesThat(mMockVpn.getNetwork(), TIMEOUT_MS,
7390                 nc -> nc.hasCapability(NET_CAPABILITY_VALIDATED));
7391 
7392         final NetworkCapabilities nc = mCm.getNetworkCapabilities(mMockVpn.getNetwork());
7393         assertTrue(nc.hasTransport(TRANSPORT_VPN));
7394         assertTrue(nc.hasTransport(TRANSPORT_CELLULAR));
7395         assertFalse(nc.hasTransport(TRANSPORT_WIFI));
7396         assertTrue(nc.hasCapability(NET_CAPABILITY_VALIDATED));
7397         assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED));
7398         assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
7399 
7400         assertVpnTransportInfo(nc, VpnManager.TYPE_VPN_SERVICE);
7401     }
7402 
7403     private void assertDefaultNetworkCapabilities(int userId, NetworkAgentWrapper... networks) {
7404         final NetworkCapabilities[] defaultCaps = mService.getDefaultNetworkCapabilitiesForUser(
7405                 userId, "com.android.calling.package", "com.test");
7406         final String defaultCapsString = Arrays.toString(defaultCaps);
7407         assertEquals(defaultCapsString, defaultCaps.length, networks.length);
7408         final Set<NetworkCapabilities> defaultCapsSet = new ArraySet<>(defaultCaps);
7409         for (NetworkAgentWrapper network : networks) {
7410             final NetworkCapabilities nc = mCm.getNetworkCapabilities(network.getNetwork());
7411             final String msg = "Did not find " + nc + " in " + Arrays.toString(defaultCaps);
7412             assertTrue(msg, defaultCapsSet.contains(nc));
7413         }
7414     }
7415 
7416     @Test
7417     public void testVpnSetUnderlyingNetworks() throws Exception {
7418         final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
7419         final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder()
7420                 .removeCapability(NET_CAPABILITY_NOT_VPN)
7421                 .addTransportType(TRANSPORT_VPN)
7422                 .build();
7423         NetworkCapabilities nc;
7424         mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
7425         vpnNetworkCallback.assertNoCallback();
7426 
7427         mMockVpn.establishForMyUid(true /* validated */, false /* hasInternet */,
7428                 false /* isStrictMode */);
7429         assertUidRangesUpdatedForMyUid(true);
7430 
7431         vpnNetworkCallback.expectAvailableThenValidatedCallbacks(mMockVpn);
7432         nc = mCm.getNetworkCapabilities(mMockVpn.getNetwork());
7433         assertTrue(nc.hasTransport(TRANSPORT_VPN));
7434         assertFalse(nc.hasTransport(TRANSPORT_CELLULAR));
7435         assertFalse(nc.hasTransport(TRANSPORT_WIFI));
7436         // For safety reasons a VPN without underlying networks is considered metered.
7437         assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED));
7438         // A VPN without underlying networks is not suspended.
7439         assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
7440         assertVpnTransportInfo(nc, VpnManager.TYPE_VPN_SERVICE);
7441 
7442         final int userId = UserHandle.getUserId(Process.myUid());
7443         assertDefaultNetworkCapabilities(userId /* no networks */);
7444 
7445         // Connect cell and use it as an underlying network.
7446         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
7447         mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_SUSPENDED);
7448         mCellNetworkAgent.connect(true);
7449 
7450         mMockVpn.setUnderlyingNetworks(
7451                 new Network[] { mCellNetworkAgent.getNetwork() });
7452 
7453         vpnNetworkCallback.expectCapabilitiesThat(mMockVpn,
7454                 (caps) -> caps.hasTransport(TRANSPORT_VPN)
7455                 && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
7456                 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED)
7457                 && caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
7458         assertDefaultNetworkCapabilities(userId, mCellNetworkAgent);
7459 
7460         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
7461         mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
7462         mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_SUSPENDED);
7463         mWiFiNetworkAgent.connect(true);
7464 
7465         mMockVpn.setUnderlyingNetworks(
7466                 new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() });
7467 
7468         vpnNetworkCallback.expectCapabilitiesThat(mMockVpn,
7469                 (caps) -> caps.hasTransport(TRANSPORT_VPN)
7470                 && caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
7471                 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED)
7472                 && caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
7473         assertDefaultNetworkCapabilities(userId, mCellNetworkAgent, mWiFiNetworkAgent);
7474 
7475         // Don't disconnect, but note the VPN is not using wifi any more.
7476         mMockVpn.setUnderlyingNetworks(
7477                 new Network[] { mCellNetworkAgent.getNetwork() });
7478 
7479         vpnNetworkCallback.expectCapabilitiesThat(mMockVpn,
7480                 (caps) -> caps.hasTransport(TRANSPORT_VPN)
7481                 && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
7482                 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED)
7483                 && caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
7484         // The return value of getDefaultNetworkCapabilitiesForUser always includes the default
7485         // network (wifi) as well as the underlying networks (cell).
7486         assertDefaultNetworkCapabilities(userId, mCellNetworkAgent, mWiFiNetworkAgent);
7487 
7488         // Remove NOT_SUSPENDED from the only network and observe VPN is now suspended.
7489         mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_SUSPENDED);
7490         vpnNetworkCallback.expectCapabilitiesThat(mMockVpn,
7491                 (caps) -> caps.hasTransport(TRANSPORT_VPN)
7492                 && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
7493                 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED)
7494                 && !caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
7495         vpnNetworkCallback.expectCallback(CallbackEntry.SUSPENDED, mMockVpn);
7496 
7497         // Add NOT_SUSPENDED again and observe VPN is no longer suspended.
7498         mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_SUSPENDED);
7499         vpnNetworkCallback.expectCapabilitiesThat(mMockVpn,
7500                 (caps) -> caps.hasTransport(TRANSPORT_VPN)
7501                 && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
7502                 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED)
7503                 && caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
7504         vpnNetworkCallback.expectCallback(CallbackEntry.RESUMED, mMockVpn);
7505 
7506         // Use Wifi but not cell. Note the VPN is now unmetered and not suspended.
7507         mMockVpn.setUnderlyingNetworks(
7508                 new Network[] { mWiFiNetworkAgent.getNetwork() });
7509 
7510         vpnNetworkCallback.expectCapabilitiesThat(mMockVpn,
7511                 (caps) -> caps.hasTransport(TRANSPORT_VPN)
7512                 && !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
7513                 && caps.hasCapability(NET_CAPABILITY_NOT_METERED)
7514                 && caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
7515         assertDefaultNetworkCapabilities(userId, mWiFiNetworkAgent);
7516 
7517         // Use both again.
7518         mMockVpn.setUnderlyingNetworks(
7519                 new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() });
7520 
7521         vpnNetworkCallback.expectCapabilitiesThat(mMockVpn,
7522                 (caps) -> caps.hasTransport(TRANSPORT_VPN)
7523                 && caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
7524                 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED)
7525                 && caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
7526         assertDefaultNetworkCapabilities(userId, mCellNetworkAgent, mWiFiNetworkAgent);
7527 
7528         // Cell is suspended again. As WiFi is not, this should not cause a callback.
7529         mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_SUSPENDED);
7530         vpnNetworkCallback.assertNoCallback();
7531 
7532         // Stop using WiFi. The VPN is suspended again.
7533         mMockVpn.setUnderlyingNetworks(
7534                 new Network[] { mCellNetworkAgent.getNetwork() });
7535         vpnNetworkCallback.expectCapabilitiesThat(mMockVpn,
7536                 (caps) -> caps.hasTransport(TRANSPORT_VPN)
7537                 && caps.hasTransport(TRANSPORT_CELLULAR)
7538                 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED)
7539                 && !caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
7540         vpnNetworkCallback.expectCallback(CallbackEntry.SUSPENDED, mMockVpn);
7541         assertDefaultNetworkCapabilities(userId, mCellNetworkAgent, mWiFiNetworkAgent);
7542 
7543         // Use both again.
7544         mMockVpn.setUnderlyingNetworks(
7545                 new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() });
7546 
7547         vpnNetworkCallback.expectCapabilitiesThat(mMockVpn,
7548                 (caps) -> caps.hasTransport(TRANSPORT_VPN)
7549                 && caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
7550                 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED)
7551                 && caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
7552         vpnNetworkCallback.expectCallback(CallbackEntry.RESUMED, mMockVpn);
7553         assertDefaultNetworkCapabilities(userId, mCellNetworkAgent, mWiFiNetworkAgent);
7554 
7555         // Disconnect cell. Receive update without even removing the dead network from the
7556         // underlying networks – it's dead anyway. Not metered any more.
7557         mCellNetworkAgent.disconnect();
7558         vpnNetworkCallback.expectCapabilitiesThat(mMockVpn,
7559                 (caps) -> caps.hasTransport(TRANSPORT_VPN)
7560                 && !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
7561                 && caps.hasCapability(NET_CAPABILITY_NOT_METERED));
7562         assertDefaultNetworkCapabilities(userId, mWiFiNetworkAgent);
7563 
7564         // Disconnect wifi too. No underlying networks means this is now metered.
7565         mWiFiNetworkAgent.disconnect();
7566         vpnNetworkCallback.expectCapabilitiesThat(mMockVpn,
7567                 (caps) -> caps.hasTransport(TRANSPORT_VPN)
7568                 && !caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
7569                 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED));
7570         // When a network disconnects, the callbacks are fired before all state is updated, so for a
7571         // short time, synchronous calls will behave as if the network is still connected. Wait for
7572         // things to settle.
7573         waitForIdle();
7574         assertDefaultNetworkCapabilities(userId /* no networks */);
7575 
7576         mMockVpn.disconnect();
7577     }
7578 
7579     @Test
7580     public void testNullUnderlyingNetworks() throws Exception {
7581         final int uid = Process.myUid();
7582 
7583         final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
7584         final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder()
7585                 .removeCapability(NET_CAPABILITY_NOT_VPN)
7586                 .addTransportType(TRANSPORT_VPN)
7587                 .build();
7588         NetworkCapabilities nc;
7589         mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
7590         vpnNetworkCallback.assertNoCallback();
7591 
7592         mMockVpn.establishForMyUid(true /* validated */, false /* hasInternet */,
7593                 false /* isStrictMode */);
7594         assertUidRangesUpdatedForMyUid(true);
7595 
7596         vpnNetworkCallback.expectAvailableThenValidatedCallbacks(mMockVpn);
7597         nc = mCm.getNetworkCapabilities(mMockVpn.getNetwork());
7598         assertTrue(nc.hasTransport(TRANSPORT_VPN));
7599         assertFalse(nc.hasTransport(TRANSPORT_CELLULAR));
7600         assertFalse(nc.hasTransport(TRANSPORT_WIFI));
7601         // By default, VPN is set to track default network (i.e. its underlying networks is null).
7602         // In case of no default network, VPN is considered metered.
7603         assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED));
7604         assertVpnTransportInfo(nc, VpnManager.TYPE_VPN_SERVICE);
7605 
7606         // Connect to Cell; Cell is the default network.
7607         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
7608         mCellNetworkAgent.connect(true);
7609 
7610         vpnNetworkCallback.expectCapabilitiesThat(mMockVpn,
7611                 (caps) -> caps.hasTransport(TRANSPORT_VPN)
7612                 && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
7613                 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED));
7614 
7615         // Connect to WiFi; WiFi is the new default.
7616         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
7617         mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
7618         mWiFiNetworkAgent.connect(true);
7619 
7620         vpnNetworkCallback.expectCapabilitiesThat(mMockVpn,
7621                 (caps) -> caps.hasTransport(TRANSPORT_VPN)
7622                 && !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
7623                 && caps.hasCapability(NET_CAPABILITY_NOT_METERED));
7624 
7625         // Disconnect Cell. The default network did not change, so there shouldn't be any changes in
7626         // the capabilities.
7627         mCellNetworkAgent.disconnect();
7628 
7629         // Disconnect wifi too. Now we have no default network.
7630         mWiFiNetworkAgent.disconnect();
7631 
7632         vpnNetworkCallback.expectCapabilitiesThat(mMockVpn,
7633                 (caps) -> caps.hasTransport(TRANSPORT_VPN)
7634                 && !caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
7635                 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED));
7636 
7637         mMockVpn.disconnect();
7638     }
7639 
7640     @Test
7641     public void testRestrictedProfileAffectsVpnUidRanges() throws Exception {
7642         // NETWORK_SETTINGS is necessary to see the UID ranges in NetworkCapabilities.
7643         mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_GRANTED);
7644 
7645         final NetworkRequest request = new NetworkRequest.Builder()
7646                 .removeCapability(NET_CAPABILITY_NOT_VPN)
7647                 .build();
7648         final TestNetworkCallback callback = new TestNetworkCallback();
7649         mCm.registerNetworkCallback(request, callback);
7650 
7651         // Bring up a VPN
7652         mMockVpn.establishForMyUid();
7653         assertUidRangesUpdatedForMyUid(true);
7654         callback.expectAvailableThenValidatedCallbacks(mMockVpn);
7655         callback.assertNoCallback();
7656 
7657         final int uid = Process.myUid();
7658         NetworkCapabilities nc = mCm.getNetworkCapabilities(mMockVpn.getNetwork());
7659         assertNotNull("nc=" + nc, nc.getUids());
7660         assertEquals(nc.getUids(), UidRange.toIntRanges(uidRangesForUids(uid)));
7661         assertVpnTransportInfo(nc, VpnManager.TYPE_VPN_SERVICE);
7662 
7663         // Set an underlying network and expect to see the VPN transports change.
7664         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
7665         mWiFiNetworkAgent.connect(true);
7666         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
7667         callback.expectCapabilitiesThat(mMockVpn, (caps)
7668                 -> caps.hasTransport(TRANSPORT_VPN)
7669                 && caps.hasTransport(TRANSPORT_WIFI));
7670         callback.expectCapabilitiesThat(mWiFiNetworkAgent, (caps)
7671                 -> caps.hasCapability(NET_CAPABILITY_VALIDATED));
7672 
7673         when(mPackageManager.getPackageUidAsUser(ALWAYS_ON_PACKAGE, RESTRICTED_USER))
7674                 .thenReturn(UserHandle.getUid(RESTRICTED_USER, VPN_UID));
7675 
7676         final Intent addedIntent = new Intent(ACTION_USER_ADDED);
7677         addedIntent.putExtra(Intent.EXTRA_USER, UserHandle.of(RESTRICTED_USER));
7678         addedIntent.putExtra(Intent.EXTRA_USER_HANDLE, RESTRICTED_USER);
7679 
7680         // Send a USER_ADDED broadcast for it.
7681         processBroadcast(addedIntent);
7682 
7683         // Expect that the VPN UID ranges contain both |uid| and the UID range for the newly-added
7684         // restricted user.
7685         final UidRange rRange = UidRange.createForUser(UserHandle.of(RESTRICTED_USER));
7686         final Range<Integer> restrictUidRange = new Range<Integer>(rRange.start, rRange.stop);
7687         final Range<Integer> singleUidRange = new Range<Integer>(uid, uid);
7688         callback.expectCapabilitiesThat(mMockVpn, (caps)
7689                 -> caps.getUids().size() == 2
7690                 && caps.getUids().contains(singleUidRange)
7691                 && caps.getUids().contains(restrictUidRange)
7692                 && caps.hasTransport(TRANSPORT_VPN)
7693                 && caps.hasTransport(TRANSPORT_WIFI));
7694 
7695         // Change the VPN's capabilities somehow (specifically, disconnect wifi).
7696         mWiFiNetworkAgent.disconnect();
7697         callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
7698         callback.expectCapabilitiesThat(mMockVpn, (caps)
7699                 -> caps.getUids().size() == 2
7700                 && caps.getUids().contains(singleUidRange)
7701                 && caps.getUids().contains(restrictUidRange)
7702                 && caps.hasTransport(TRANSPORT_VPN)
7703                 && !caps.hasTransport(TRANSPORT_WIFI));
7704 
7705         // Send a USER_REMOVED broadcast and expect to lose the UID range for the restricted user.
7706         final Intent removedIntent = new Intent(ACTION_USER_REMOVED);
7707         removedIntent.putExtra(Intent.EXTRA_USER, UserHandle.of(RESTRICTED_USER));
7708         removedIntent.putExtra(Intent.EXTRA_USER_HANDLE, RESTRICTED_USER);
7709         processBroadcast(removedIntent);
7710 
7711         // Expect that the VPN gains the UID range for the restricted user, and that the capability
7712         // change made just before that (i.e., loss of TRANSPORT_WIFI) is preserved.
7713         callback.expectCapabilitiesThat(mMockVpn, (caps)
7714                 -> caps.getUids().size() == 1
7715                 && caps.getUids().contains(singleUidRange)
7716                 && caps.hasTransport(TRANSPORT_VPN)
7717                 && !caps.hasTransport(TRANSPORT_WIFI));
7718     }
7719 
7720     @Test
7721     public void testLockdownVpnWithRestrictedProfiles() throws Exception {
7722         // For ConnectivityService#setAlwaysOnVpnPackage.
7723         mServiceContext.setPermission(
7724                 Manifest.permission.CONTROL_ALWAYS_ON_VPN, PERMISSION_GRANTED);
7725         // For call Vpn#setAlwaysOnPackage.
7726         mServiceContext.setPermission(
7727                 Manifest.permission.CONTROL_VPN, PERMISSION_GRANTED);
7728         // Necessary to see the UID ranges in NetworkCapabilities.
7729         mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_GRANTED);
7730 
7731         final NetworkRequest request = new NetworkRequest.Builder()
7732                 .removeCapability(NET_CAPABILITY_NOT_VPN)
7733                 .build();
7734         final TestNetworkCallback callback = new TestNetworkCallback();
7735         mCm.registerNetworkCallback(request, callback);
7736 
7737         final int uid = Process.myUid();
7738 
7739         // Connect wifi and check that UIDs in the main and restricted profiles have network access.
7740         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
7741         mWiFiNetworkAgent.connect(true /* validated */);
7742         final int restrictedUid = UserHandle.getUid(RESTRICTED_USER, 42 /* appId */);
7743         assertNotNull(mCm.getActiveNetworkForUid(uid));
7744         assertNotNull(mCm.getActiveNetworkForUid(restrictedUid));
7745 
7746         // Enable always-on VPN lockdown. The main user loses network access because no VPN is up.
7747         final ArrayList<String> allowList = new ArrayList<>();
7748         mVpnManagerService.setAlwaysOnVpnPackage(PRIMARY_USER, ALWAYS_ON_PACKAGE,
7749                 true /* lockdown */, allowList);
7750         waitForIdle();
7751         assertNull(mCm.getActiveNetworkForUid(uid));
7752         // This is arguably overspecified: a UID that is not running doesn't have an active network.
7753         // But it's useful to check that non-default users do not lose network access, and to prove
7754         // that the loss of connectivity below is indeed due to the restricted profile coming up.
7755         assertNotNull(mCm.getActiveNetworkForUid(restrictedUid));
7756 
7757         // Start the restricted profile, and check that the UID within it loses network access.
7758         when(mPackageManager.getPackageUidAsUser(ALWAYS_ON_PACKAGE, RESTRICTED_USER))
7759                 .thenReturn(UserHandle.getUid(RESTRICTED_USER, VPN_UID));
7760         when(mUserManager.getAliveUsers()).thenReturn(Arrays.asList(PRIMARY_USER_INFO,
7761                 RESTRICTED_USER_INFO));
7762         // TODO: check that VPN app within restricted profile still has access, etc.
7763         final Intent addedIntent = new Intent(ACTION_USER_ADDED);
7764         addedIntent.putExtra(Intent.EXTRA_USER, UserHandle.of(RESTRICTED_USER));
7765         addedIntent.putExtra(Intent.EXTRA_USER_HANDLE, RESTRICTED_USER);
7766         processBroadcast(addedIntent);
7767         assertNull(mCm.getActiveNetworkForUid(uid));
7768         assertNull(mCm.getActiveNetworkForUid(restrictedUid));
7769 
7770         // Stop the restricted profile, and check that the UID within it has network access again.
7771         when(mUserManager.getAliveUsers()).thenReturn(Arrays.asList(PRIMARY_USER_INFO));
7772 
7773         // Send a USER_REMOVED broadcast and expect to lose the UID range for the restricted user.
7774         final Intent removedIntent = new Intent(ACTION_USER_REMOVED);
7775         removedIntent.putExtra(Intent.EXTRA_USER, UserHandle.of(RESTRICTED_USER));
7776         removedIntent.putExtra(Intent.EXTRA_USER_HANDLE, RESTRICTED_USER);
7777         processBroadcast(removedIntent);
7778         assertNull(mCm.getActiveNetworkForUid(uid));
7779         assertNotNull(mCm.getActiveNetworkForUid(restrictedUid));
7780 
7781         mVpnManagerService.setAlwaysOnVpnPackage(PRIMARY_USER, null, false /* lockdown */,
7782                 allowList);
7783         waitForIdle();
7784     }
7785 
7786     @Test
7787     public void testIsActiveNetworkMeteredOverWifi() throws Exception {
7788         // Returns true by default when no network is available.
7789         assertTrue(mCm.isActiveNetworkMetered());
7790         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
7791         mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
7792         mWiFiNetworkAgent.connect(true);
7793         waitForIdle();
7794 
7795         assertFalse(mCm.isActiveNetworkMetered());
7796     }
7797 
7798     @Test
7799     public void testIsActiveNetworkMeteredOverCell() throws Exception {
7800         // Returns true by default when no network is available.
7801         assertTrue(mCm.isActiveNetworkMetered());
7802         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
7803         mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
7804         mCellNetworkAgent.connect(true);
7805         waitForIdle();
7806 
7807         assertTrue(mCm.isActiveNetworkMetered());
7808     }
7809 
7810     @Test
7811     public void testIsActiveNetworkMeteredOverVpnTrackingPlatformDefault() throws Exception {
7812         // Returns true by default when no network is available.
7813         assertTrue(mCm.isActiveNetworkMetered());
7814         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
7815         mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
7816         mCellNetworkAgent.connect(true);
7817         waitForIdle();
7818         assertTrue(mCm.isActiveNetworkMetered());
7819 
7820         // Connect VPN network. By default it is using current default network (Cell).
7821         mMockVpn.establishForMyUid();
7822         assertUidRangesUpdatedForMyUid(true);
7823 
7824         // Ensure VPN is now the active network.
7825         assertEquals(mMockVpn.getNetwork(), mCm.getActiveNetwork());
7826 
7827         // Expect VPN to be metered.
7828         assertTrue(mCm.isActiveNetworkMetered());
7829 
7830         // Connect WiFi.
7831         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
7832         mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
7833         mWiFiNetworkAgent.connect(true);
7834         waitForIdle();
7835         // VPN should still be the active network.
7836         assertEquals(mMockVpn.getNetwork(), mCm.getActiveNetwork());
7837 
7838         // Expect VPN to be unmetered as it should now be using WiFi (new default).
7839         assertFalse(mCm.isActiveNetworkMetered());
7840 
7841         // Disconnecting Cell should not affect VPN's meteredness.
7842         mCellNetworkAgent.disconnect();
7843         waitForIdle();
7844 
7845         assertFalse(mCm.isActiveNetworkMetered());
7846 
7847         // Disconnect WiFi; Now there is no platform default network.
7848         mWiFiNetworkAgent.disconnect();
7849         waitForIdle();
7850 
7851         // VPN without any underlying networks is treated as metered.
7852         assertTrue(mCm.isActiveNetworkMetered());
7853 
7854         mMockVpn.disconnect();
7855     }
7856 
7857    @Test
7858    public void testIsActiveNetworkMeteredOverVpnSpecifyingUnderlyingNetworks() throws Exception {
7859         // Returns true by default when no network is available.
7860         assertTrue(mCm.isActiveNetworkMetered());
7861         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
7862         mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
7863         mCellNetworkAgent.connect(true);
7864         waitForIdle();
7865         assertTrue(mCm.isActiveNetworkMetered());
7866 
7867         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
7868         mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
7869         mWiFiNetworkAgent.connect(true);
7870         waitForIdle();
7871         assertFalse(mCm.isActiveNetworkMetered());
7872 
7873         // Connect VPN network.
7874         mMockVpn.establishForMyUid();
7875         assertUidRangesUpdatedForMyUid(true);
7876 
7877         // Ensure VPN is now the active network.
7878         assertEquals(mMockVpn.getNetwork(), mCm.getActiveNetwork());
7879         // VPN is using Cell
7880         mMockVpn.setUnderlyingNetworks(
7881                 new Network[] { mCellNetworkAgent.getNetwork() });
7882         waitForIdle();
7883 
7884         // Expect VPN to be metered.
7885         assertTrue(mCm.isActiveNetworkMetered());
7886 
7887         // VPN is now using WiFi
7888         mMockVpn.setUnderlyingNetworks(
7889                 new Network[] { mWiFiNetworkAgent.getNetwork() });
7890         waitForIdle();
7891 
7892         // Expect VPN to be unmetered
7893         assertFalse(mCm.isActiveNetworkMetered());
7894 
7895         // VPN is using Cell | WiFi.
7896         mMockVpn.setUnderlyingNetworks(
7897                 new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() });
7898         waitForIdle();
7899 
7900         // Expect VPN to be metered.
7901         assertTrue(mCm.isActiveNetworkMetered());
7902 
7903         // VPN is using WiFi | Cell.
7904         mMockVpn.setUnderlyingNetworks(
7905                 new Network[] { mWiFiNetworkAgent.getNetwork(), mCellNetworkAgent.getNetwork() });
7906         waitForIdle();
7907 
7908         // Order should not matter and VPN should still be metered.
7909         assertTrue(mCm.isActiveNetworkMetered());
7910 
7911         // VPN is not using any underlying networks.
7912         mMockVpn.setUnderlyingNetworks(new Network[0]);
7913         waitForIdle();
7914 
7915         // VPN without underlying networks is treated as metered.
7916         assertTrue(mCm.isActiveNetworkMetered());
7917 
7918         mMockVpn.disconnect();
7919     }
7920 
7921     @Test
7922     public void testIsActiveNetworkMeteredOverAlwaysMeteredVpn() throws Exception {
7923         // Returns true by default when no network is available.
7924         assertTrue(mCm.isActiveNetworkMetered());
7925         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
7926         mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
7927         mWiFiNetworkAgent.connect(true);
7928         waitForIdle();
7929         assertFalse(mCm.isActiveNetworkMetered());
7930 
7931         // Connect VPN network.
7932         mMockVpn.registerAgent(true /* isAlwaysMetered */, uidRangesForUids(Process.myUid()),
7933                 new LinkProperties());
7934         mMockVpn.connect(true);
7935         waitForIdle();
7936         assertEquals(mMockVpn.getNetwork(), mCm.getActiveNetwork());
7937 
7938         // VPN is tracking current platform default (WiFi).
7939         mMockVpn.setUnderlyingNetworks(null);
7940         waitForIdle();
7941 
7942         // Despite VPN using WiFi (which is unmetered), VPN itself is marked as always metered.
7943         assertTrue(mCm.isActiveNetworkMetered());
7944 
7945 
7946         // VPN explicitly declares WiFi as its underlying network.
7947         mMockVpn.setUnderlyingNetworks(
7948                 new Network[] { mWiFiNetworkAgent.getNetwork() });
7949         waitForIdle();
7950 
7951         // Doesn't really matter whether VPN declares its underlying networks explicitly.
7952         assertTrue(mCm.isActiveNetworkMetered());
7953 
7954         // With WiFi lost, VPN is basically without any underlying networks. And in that case it is
7955         // anyways suppose to be metered.
7956         mWiFiNetworkAgent.disconnect();
7957         waitForIdle();
7958 
7959         assertTrue(mCm.isActiveNetworkMetered());
7960 
7961         mMockVpn.disconnect();
7962     }
7963 
7964     private class DetailedBlockedStatusCallback extends TestNetworkCallback {
7965         public void expectAvailableThenValidatedCallbacks(HasNetwork n, int blockedStatus) {
7966             super.expectAvailableThenValidatedCallbacks(n.getNetwork(), blockedStatus, TIMEOUT_MS);
7967         }
7968         public void expectBlockedStatusCallback(HasNetwork n, int blockedStatus) {
7969             // This doesn't work:
7970             // super.expectBlockedStatusCallback(blockedStatus, n.getNetwork());
7971             super.expectBlockedStatusCallback(blockedStatus, n.getNetwork(), TIMEOUT_MS);
7972         }
7973         public void onBlockedStatusChanged(Network network, int blockedReasons) {
7974             getHistory().add(new CallbackEntry.BlockedStatusInt(network, blockedReasons));
7975         }
7976     }
7977 
7978     @Test
7979     public void testNetworkBlockedStatus() throws Exception {
7980         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
7981         final NetworkRequest cellRequest = new NetworkRequest.Builder()
7982                 .addTransportType(TRANSPORT_CELLULAR)
7983                 .build();
7984         mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
7985         final DetailedBlockedStatusCallback detailedCallback = new DetailedBlockedStatusCallback();
7986         mCm.registerNetworkCallback(cellRequest, detailedCallback);
7987 
7988         mockUidNetworkingBlocked();
7989 
7990         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
7991         mCellNetworkAgent.connect(true);
7992         cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
7993         detailedCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent,
7994                 BLOCKED_REASON_NONE);
7995         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
7996         assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
7997         assertNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
7998         assertExtraInfoFromCmPresent(mCellNetworkAgent);
7999 
8000         setBlockedReasonChanged(BLOCKED_REASON_BATTERY_SAVER);
8001         cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
8002         detailedCallback.expectBlockedStatusCallback(mCellNetworkAgent,
8003                 BLOCKED_REASON_BATTERY_SAVER);
8004         assertNull(mCm.getActiveNetwork());
8005         assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
8006         assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
8007         assertExtraInfoFromCmBlocked(mCellNetworkAgent);
8008 
8009         // If blocked state does not change but blocked reason does, the boolean callback is called.
8010         // TODO: investigate de-duplicating.
8011         setBlockedReasonChanged(BLOCKED_METERED_REASON_USER_RESTRICTED);
8012         cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
8013         detailedCallback.expectBlockedStatusCallback(mCellNetworkAgent,
8014                 BLOCKED_METERED_REASON_USER_RESTRICTED);
8015 
8016         setBlockedReasonChanged(BLOCKED_REASON_NONE);
8017         cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
8018         detailedCallback.expectBlockedStatusCallback(mCellNetworkAgent, BLOCKED_REASON_NONE);
8019         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
8020         assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
8021         assertNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
8022         assertExtraInfoFromCmPresent(mCellNetworkAgent);
8023 
8024         setBlockedReasonChanged(BLOCKED_METERED_REASON_DATA_SAVER);
8025         cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
8026         detailedCallback.expectBlockedStatusCallback(mCellNetworkAgent,
8027                 BLOCKED_METERED_REASON_DATA_SAVER);
8028         assertNull(mCm.getActiveNetwork());
8029         assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
8030         assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
8031         assertExtraInfoFromCmBlocked(mCellNetworkAgent);
8032 
8033         // Restrict the network based on UID rule and NOT_METERED capability change.
8034         mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
8035         cellNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_NOT_METERED, mCellNetworkAgent);
8036         cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
8037         detailedCallback.expectCapabilitiesWith(NET_CAPABILITY_NOT_METERED, mCellNetworkAgent);
8038         detailedCallback.expectBlockedStatusCallback(mCellNetworkAgent, BLOCKED_REASON_NONE);
8039         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
8040         assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
8041         assertNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
8042         assertExtraInfoFromCmPresent(mCellNetworkAgent);
8043 
8044         mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
8045         cellNetworkCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_METERED,
8046                 mCellNetworkAgent);
8047         cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
8048         detailedCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_METERED,
8049                 mCellNetworkAgent);
8050         detailedCallback.expectBlockedStatusCallback(mCellNetworkAgent,
8051                 BLOCKED_METERED_REASON_DATA_SAVER);
8052         assertNull(mCm.getActiveNetwork());
8053         assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
8054         assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
8055         assertExtraInfoFromCmBlocked(mCellNetworkAgent);
8056 
8057         setBlockedReasonChanged(BLOCKED_REASON_NONE);
8058         cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
8059         detailedCallback.expectBlockedStatusCallback(mCellNetworkAgent, BLOCKED_REASON_NONE);
8060         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
8061         assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
8062         assertNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
8063         assertExtraInfoFromCmPresent(mCellNetworkAgent);
8064 
8065         setBlockedReasonChanged(BLOCKED_REASON_NONE);
8066         cellNetworkCallback.assertNoCallback();
8067         detailedCallback.assertNoCallback();
8068 
8069         // Restrict background data. Networking is not blocked because the network is unmetered.
8070         setBlockedReasonChanged(BLOCKED_METERED_REASON_DATA_SAVER);
8071         cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
8072         detailedCallback.expectBlockedStatusCallback(mCellNetworkAgent,
8073                 BLOCKED_METERED_REASON_DATA_SAVER);
8074         assertNull(mCm.getActiveNetwork());
8075         assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
8076         assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
8077         assertExtraInfoFromCmBlocked(mCellNetworkAgent);
8078         setBlockedReasonChanged(BLOCKED_METERED_REASON_DATA_SAVER);
8079         cellNetworkCallback.assertNoCallback();
8080 
8081         setBlockedReasonChanged(BLOCKED_REASON_NONE);
8082         cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
8083         detailedCallback.expectBlockedStatusCallback(mCellNetworkAgent, BLOCKED_REASON_NONE);
8084         assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
8085         assertNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
8086         assertExtraInfoFromCmPresent(mCellNetworkAgent);
8087 
8088         setBlockedReasonChanged(BLOCKED_REASON_NONE);
8089         cellNetworkCallback.assertNoCallback();
8090         detailedCallback.assertNoCallback();
8091         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
8092         assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
8093         assertNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
8094         assertExtraInfoFromCmPresent(mCellNetworkAgent);
8095 
8096         mCm.unregisterNetworkCallback(cellNetworkCallback);
8097     }
8098 
8099     @Test
8100     public void testNetworkBlockedStatusBeforeAndAfterConnect() throws Exception {
8101         final TestNetworkCallback defaultCallback = new TestNetworkCallback();
8102         mCm.registerDefaultNetworkCallback(defaultCallback);
8103         mockUidNetworkingBlocked();
8104 
8105         // No Networkcallbacks invoked before any network is active.
8106         setBlockedReasonChanged(BLOCKED_REASON_BATTERY_SAVER);
8107         setBlockedReasonChanged(BLOCKED_REASON_NONE);
8108         setBlockedReasonChanged(BLOCKED_METERED_REASON_DATA_SAVER);
8109         defaultCallback.assertNoCallback();
8110 
8111         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
8112         mCellNetworkAgent.connect(true);
8113         defaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mCellNetworkAgent);
8114         defaultCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mCellNetworkAgent);
8115 
8116         // Allow to use the network after switching to NOT_METERED network.
8117         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
8118         mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
8119         mWiFiNetworkAgent.connect(true);
8120         defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
8121 
8122         // Switch to METERED network. Restrict the use of the network.
8123         mWiFiNetworkAgent.disconnect();
8124         defaultCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
8125         defaultCallback.expectAvailableCallbacksValidatedAndBlocked(mCellNetworkAgent);
8126 
8127         // Network becomes NOT_METERED.
8128         mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
8129         defaultCallback.expectCapabilitiesWith(NET_CAPABILITY_NOT_METERED, mCellNetworkAgent);
8130         defaultCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
8131 
8132         // Verify there's no Networkcallbacks invoked after data saver on/off.
8133         setBlockedReasonChanged(BLOCKED_METERED_REASON_DATA_SAVER);
8134         setBlockedReasonChanged(BLOCKED_REASON_NONE);
8135         defaultCallback.assertNoCallback();
8136 
8137         mCellNetworkAgent.disconnect();
8138         defaultCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
8139         defaultCallback.assertNoCallback();
8140 
8141         mCm.unregisterNetworkCallback(defaultCallback);
8142     }
8143 
8144     private void expectNetworkRejectNonSecureVpn(InOrder inOrder, boolean add,
8145             UidRangeParcel... expected) throws Exception {
8146         inOrder.verify(mMockNetd).networkRejectNonSecureVpn(eq(add), aryEq(expected));
8147     }
8148 
8149     private void checkNetworkInfo(NetworkInfo ni, int type, DetailedState state) {
8150         assertNotNull(ni);
8151         assertEquals(type, ni.getType());
8152         assertEquals(ConnectivityManager.getNetworkTypeName(type), state, ni.getDetailedState());
8153         if (state == DetailedState.CONNECTED || state == DetailedState.SUSPENDED) {
8154             assertNotNull(ni.getExtraInfo());
8155         } else {
8156             // Technically speaking, a network that's in CONNECTING state will generally have a
8157             // non-null extraInfo. This doesn't actually happen in this test because it never calls
8158             // a legacy API while a network is connecting. When a network is in CONNECTING state
8159             // because of legacy lockdown VPN, its extraInfo is always null.
8160             assertNull(ni.getExtraInfo());
8161         }
8162     }
8163 
8164     private void assertActiveNetworkInfo(int type, DetailedState state) {
8165         checkNetworkInfo(mCm.getActiveNetworkInfo(), type, state);
8166     }
8167     private void assertNetworkInfo(int type, DetailedState state) {
8168         checkNetworkInfo(mCm.getNetworkInfo(type), type, state);
8169     }
8170 
8171     private void assertExtraInfoFromCm(TestNetworkAgentWrapper network, boolean present) {
8172         final NetworkInfo niForNetwork = mCm.getNetworkInfo(network.getNetwork());
8173         final NetworkInfo niForType = mCm.getNetworkInfo(network.getLegacyType());
8174         if (present) {
8175             assertEquals(network.getExtraInfo(), niForNetwork.getExtraInfo());
8176             assertEquals(network.getExtraInfo(), niForType.getExtraInfo());
8177         } else {
8178             assertNull(niForNetwork.getExtraInfo());
8179             assertNull(niForType.getExtraInfo());
8180         }
8181     }
8182 
8183     private void assertExtraInfoFromCmBlocked(TestNetworkAgentWrapper network) {
8184         assertExtraInfoFromCm(network, false);
8185     }
8186 
8187     private void assertExtraInfoFromCmPresent(TestNetworkAgentWrapper network) {
8188         assertExtraInfoFromCm(network, true);
8189     }
8190 
8191     // Checks that each of the |agents| receive a blocked status change callback with the specified
8192     // |blocked| value, in any order. This is needed because when an event affects multiple
8193     // networks, ConnectivityService does not guarantee the order in which callbacks are fired.
8194     private void assertBlockedCallbackInAnyOrder(TestNetworkCallback callback, boolean blocked,
8195             TestNetworkAgentWrapper... agents) {
8196         final List<Network> expectedNetworks = Arrays.asList(agents).stream()
8197                 .map((agent) -> agent.getNetwork())
8198                 .collect(Collectors.toList());
8199 
8200         // Expect exactly one blocked callback for each agent.
8201         for (int i = 0; i < agents.length; i++) {
8202             CallbackEntry e = callback.expectCallbackThat(TIMEOUT_MS, (c) ->
8203                     c instanceof CallbackEntry.BlockedStatus
8204                             && ((CallbackEntry.BlockedStatus) c).getBlocked() == blocked);
8205             Network network = e.getNetwork();
8206             assertTrue("Received unexpected blocked callback for network " + network,
8207                     expectedNetworks.remove(network));
8208         }
8209     }
8210 
8211     @Test
8212     public void testNetworkBlockedStatusAlwaysOnVpn() throws Exception {
8213         mServiceContext.setPermission(
8214                 Manifest.permission.CONTROL_ALWAYS_ON_VPN, PERMISSION_GRANTED);
8215         mServiceContext.setPermission(
8216                 Manifest.permission.CONTROL_VPN, PERMISSION_GRANTED);
8217         mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_GRANTED);
8218 
8219         final TestNetworkCallback callback = new TestNetworkCallback();
8220         final NetworkRequest request = new NetworkRequest.Builder()
8221                 .removeCapability(NET_CAPABILITY_NOT_VPN)
8222                 .build();
8223         mCm.registerNetworkCallback(request, callback);
8224 
8225         final TestNetworkCallback defaultCallback = new TestNetworkCallback();
8226         mCm.registerDefaultNetworkCallback(defaultCallback);
8227 
8228         final TestNetworkCallback vpnUidCallback = new TestNetworkCallback();
8229         final NetworkRequest vpnUidRequest = new NetworkRequest.Builder().build();
8230         registerNetworkCallbackAsUid(vpnUidRequest, vpnUidCallback, VPN_UID);
8231 
8232         final TestNetworkCallback vpnUidDefaultCallback = new TestNetworkCallback();
8233         registerDefaultNetworkCallbackAsUid(vpnUidDefaultCallback, VPN_UID);
8234 
8235         final TestNetworkCallback vpnDefaultCallbackAsUid = new TestNetworkCallback();
8236         mCm.registerDefaultNetworkCallbackForUid(VPN_UID, vpnDefaultCallbackAsUid,
8237                 new Handler(ConnectivityThread.getInstanceLooper()));
8238 
8239         final int uid = Process.myUid();
8240         final int userId = UserHandle.getUserId(uid);
8241         final ArrayList<String> allowList = new ArrayList<>();
8242         mVpnManagerService.setAlwaysOnVpnPackage(userId, ALWAYS_ON_PACKAGE, true /* lockdown */,
8243                 allowList);
8244         waitForIdle();
8245 
8246         UidRangeParcel firstHalf = new UidRangeParcel(1, VPN_UID - 1);
8247         UidRangeParcel secondHalf = new UidRangeParcel(VPN_UID + 1, 99999);
8248         InOrder inOrder = inOrder(mMockNetd);
8249         expectNetworkRejectNonSecureVpn(inOrder, true, firstHalf, secondHalf);
8250 
8251         // Connect a network when lockdown is active, expect to see it blocked.
8252         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
8253         mWiFiNetworkAgent.connect(false /* validated */);
8254         callback.expectAvailableCallbacksUnvalidatedAndBlocked(mWiFiNetworkAgent);
8255         defaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mWiFiNetworkAgent);
8256         vpnUidCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
8257         vpnUidDefaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
8258         vpnDefaultCallbackAsUid.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
8259         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
8260         assertNull(mCm.getActiveNetwork());
8261         assertActiveNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED);
8262         // Mobile is BLOCKED even though it's not actually connected.
8263         assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
8264         assertNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED);
8265 
8266         // Disable lockdown, expect to see the network unblocked.
8267         mVpnManagerService.setAlwaysOnVpnPackage(userId, null, false /* lockdown */, allowList);
8268         callback.expectBlockedStatusCallback(false, mWiFiNetworkAgent);
8269         defaultCallback.expectBlockedStatusCallback(false, mWiFiNetworkAgent);
8270         vpnUidCallback.assertNoCallback();
8271         vpnUidDefaultCallback.assertNoCallback();
8272         vpnDefaultCallbackAsUid.assertNoCallback();
8273         expectNetworkRejectNonSecureVpn(inOrder, false, firstHalf, secondHalf);
8274         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
8275         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
8276         assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
8277         assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED);
8278         assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
8279 
8280         // Add our UID to the allowlist and re-enable lockdown, expect network is not blocked.
8281         allowList.add(TEST_PACKAGE_NAME);
8282         mVpnManagerService.setAlwaysOnVpnPackage(userId, ALWAYS_ON_PACKAGE, true /* lockdown */,
8283                 allowList);
8284         callback.assertNoCallback();
8285         defaultCallback.assertNoCallback();
8286         vpnUidCallback.assertNoCallback();
8287         vpnUidDefaultCallback.assertNoCallback();
8288         vpnDefaultCallbackAsUid.assertNoCallback();
8289 
8290         // The following requires that the UID of this test package is greater than VPN_UID. This
8291         // is always true in practice because a plain AOSP build with no apps installed has almost
8292         // 200 packages installed.
8293         final UidRangeParcel piece1 = new UidRangeParcel(1, VPN_UID - 1);
8294         final UidRangeParcel piece2 = new UidRangeParcel(VPN_UID + 1, uid - 1);
8295         final UidRangeParcel piece3 = new UidRangeParcel(uid + 1, 99999);
8296         expectNetworkRejectNonSecureVpn(inOrder, true, piece1, piece2, piece3);
8297         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
8298         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
8299         assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
8300         assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED);
8301         assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
8302 
8303         // Connect a new network, expect it to be unblocked.
8304         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
8305         mCellNetworkAgent.connect(false /* validated */);
8306         callback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
8307         defaultCallback.assertNoCallback();
8308         vpnUidCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
8309         vpnUidDefaultCallback.assertNoCallback();
8310         vpnDefaultCallbackAsUid.assertNoCallback();
8311         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
8312         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
8313         assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
8314         // Cellular is DISCONNECTED because it's not the default and there are no requests for it.
8315         assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED);
8316         assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
8317 
8318         // Disable lockdown, remove our UID from the allowlist, and re-enable lockdown.
8319         // Everything should now be blocked.
8320         mVpnManagerService.setAlwaysOnVpnPackage(userId, null, false /* lockdown */, allowList);
8321         waitForIdle();
8322         expectNetworkRejectNonSecureVpn(inOrder, false, piece1, piece2, piece3);
8323         allowList.clear();
8324         mVpnManagerService.setAlwaysOnVpnPackage(userId, ALWAYS_ON_PACKAGE, true /* lockdown */,
8325                 allowList);
8326         waitForIdle();
8327         expectNetworkRejectNonSecureVpn(inOrder, true, firstHalf, secondHalf);
8328         defaultCallback.expectBlockedStatusCallback(true, mWiFiNetworkAgent);
8329         assertBlockedCallbackInAnyOrder(callback, true, mWiFiNetworkAgent, mCellNetworkAgent);
8330         vpnUidCallback.assertNoCallback();
8331         vpnUidDefaultCallback.assertNoCallback();
8332         vpnDefaultCallbackAsUid.assertNoCallback();
8333         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
8334         assertNull(mCm.getActiveNetwork());
8335         assertActiveNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED);
8336         assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
8337         assertNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED);
8338 
8339         // Disable lockdown. Everything is unblocked.
8340         mVpnManagerService.setAlwaysOnVpnPackage(userId, null, false /* lockdown */, allowList);
8341         defaultCallback.expectBlockedStatusCallback(false, mWiFiNetworkAgent);
8342         assertBlockedCallbackInAnyOrder(callback, false, mWiFiNetworkAgent, mCellNetworkAgent);
8343         vpnUidCallback.assertNoCallback();
8344         vpnUidDefaultCallback.assertNoCallback();
8345         vpnDefaultCallbackAsUid.assertNoCallback();
8346         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
8347         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
8348         assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
8349         assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED);
8350         assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
8351 
8352         // Enable and disable an always-on VPN package without lockdown. Expect no changes.
8353         reset(mMockNetd);
8354         mVpnManagerService.setAlwaysOnVpnPackage(userId, ALWAYS_ON_PACKAGE, false /* lockdown */,
8355                 allowList);
8356         inOrder.verify(mMockNetd, never()).networkRejectNonSecureVpn(anyBoolean(), any());
8357         callback.assertNoCallback();
8358         defaultCallback.assertNoCallback();
8359         vpnUidCallback.assertNoCallback();
8360         vpnUidDefaultCallback.assertNoCallback();
8361         vpnDefaultCallbackAsUid.assertNoCallback();
8362         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
8363         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
8364         assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
8365         assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED);
8366         assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
8367 
8368         mVpnManagerService.setAlwaysOnVpnPackage(userId, null, false /* lockdown */, allowList);
8369         inOrder.verify(mMockNetd, never()).networkRejectNonSecureVpn(anyBoolean(), any());
8370         callback.assertNoCallback();
8371         defaultCallback.assertNoCallback();
8372         vpnUidCallback.assertNoCallback();
8373         vpnUidDefaultCallback.assertNoCallback();
8374         vpnDefaultCallbackAsUid.assertNoCallback();
8375         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
8376         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
8377         assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
8378         assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED);
8379         assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
8380 
8381         // Enable lockdown and connect a VPN. The VPN is not blocked.
8382         mVpnManagerService.setAlwaysOnVpnPackage(userId, ALWAYS_ON_PACKAGE, true /* lockdown */,
8383                 allowList);
8384         defaultCallback.expectBlockedStatusCallback(true, mWiFiNetworkAgent);
8385         assertBlockedCallbackInAnyOrder(callback, true, mWiFiNetworkAgent, mCellNetworkAgent);
8386         vpnUidCallback.assertNoCallback();
8387         vpnUidDefaultCallback.assertNoCallback();
8388         vpnDefaultCallbackAsUid.assertNoCallback();
8389         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
8390         assertNull(mCm.getActiveNetwork());
8391         assertActiveNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED);
8392         assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
8393         assertNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED);
8394 
8395         mMockVpn.establishForMyUid();
8396         assertUidRangesUpdatedForMyUid(true);
8397         defaultCallback.expectAvailableThenValidatedCallbacks(mMockVpn);
8398         vpnUidCallback.assertNoCallback();  // vpnUidCallback has NOT_VPN capability.
8399         vpnUidDefaultCallback.assertNoCallback();  // VPN does not apply to VPN_UID
8400         vpnDefaultCallbackAsUid.assertNoCallback();
8401         assertEquals(mMockVpn.getNetwork(), mCm.getActiveNetwork());
8402         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
8403         assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
8404         assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED);
8405         assertNetworkInfo(TYPE_VPN, DetailedState.CONNECTED);
8406         assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
8407 
8408         mMockVpn.disconnect();
8409         defaultCallback.expectCallback(CallbackEntry.LOST, mMockVpn);
8410         defaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mWiFiNetworkAgent);
8411         vpnUidCallback.assertNoCallback();
8412         vpnUidDefaultCallback.assertNoCallback();
8413         vpnDefaultCallbackAsUid.assertNoCallback();
8414         assertNull(mCm.getActiveNetwork());
8415 
8416         mCm.unregisterNetworkCallback(callback);
8417         mCm.unregisterNetworkCallback(defaultCallback);
8418         mCm.unregisterNetworkCallback(vpnUidCallback);
8419         mCm.unregisterNetworkCallback(vpnUidDefaultCallback);
8420         mCm.unregisterNetworkCallback(vpnDefaultCallbackAsUid);
8421     }
8422 
8423     private void setupLegacyLockdownVpn() {
8424         final String profileName = "testVpnProfile";
8425         final byte[] profileTag = profileName.getBytes(StandardCharsets.UTF_8);
8426         when(mVpnProfileStore.get(Credentials.LOCKDOWN_VPN)).thenReturn(profileTag);
8427 
8428         final VpnProfile profile = new VpnProfile(profileName);
8429         profile.name = "My VPN";
8430         profile.server = "192.0.2.1";
8431         profile.dnsServers = "8.8.8.8";
8432         profile.type = VpnProfile.TYPE_IPSEC_XAUTH_PSK;
8433         final byte[] encodedProfile = profile.encode();
8434         when(mVpnProfileStore.get(Credentials.VPN + profileName)).thenReturn(encodedProfile);
8435     }
8436 
8437     private void establishLegacyLockdownVpn(Network underlying) throws Exception {
8438         // The legacy lockdown VPN only supports userId 0, and must have an underlying network.
8439         assertNotNull(underlying);
8440         mMockVpn.setVpnType(VpnManager.TYPE_VPN_LEGACY);
8441         // The legacy lockdown VPN only supports userId 0.
8442         final Set<UidRange> ranges = Collections.singleton(PRIMARY_UIDRANGE);
8443         mMockVpn.registerAgent(ranges);
8444         mMockVpn.setUnderlyingNetworks(new Network[]{underlying});
8445         mMockVpn.connect(true);
8446     }
8447 
8448     @Test
8449     public void testLegacyLockdownVpn() throws Exception {
8450         mServiceContext.setPermission(
8451                 Manifest.permission.CONTROL_VPN, PERMISSION_GRANTED);
8452         // For LockdownVpnTracker to call registerSystemDefaultNetworkCallback.
8453         mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_GRANTED);
8454 
8455         final NetworkRequest request = new NetworkRequest.Builder().clearCapabilities().build();
8456         final TestNetworkCallback callback = new TestNetworkCallback();
8457         mCm.registerNetworkCallback(request, callback);
8458 
8459         final TestNetworkCallback defaultCallback = new TestNetworkCallback();
8460         mCm.registerDefaultNetworkCallback(defaultCallback);
8461 
8462         final TestNetworkCallback systemDefaultCallback = new TestNetworkCallback();
8463         mCm.registerSystemDefaultNetworkCallback(systemDefaultCallback,
8464                 new Handler(ConnectivityThread.getInstanceLooper()));
8465 
8466         // Pretend lockdown VPN was configured.
8467         setupLegacyLockdownVpn();
8468 
8469         // LockdownVpnTracker disables the Vpn teardown code and enables lockdown.
8470         // Check the VPN's state before it does so.
8471         assertTrue(mMockVpn.getEnableTeardown());
8472         assertFalse(mMockVpn.getLockdown());
8473 
8474         // Send a USER_UNLOCKED broadcast so CS starts LockdownVpnTracker.
8475         final int userId = UserHandle.getUserId(Process.myUid());
8476         final Intent addedIntent = new Intent(ACTION_USER_UNLOCKED);
8477         addedIntent.putExtra(Intent.EXTRA_USER, UserHandle.of(userId));
8478         addedIntent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
8479         processBroadcast(addedIntent);
8480 
8481         // Lockdown VPN disables teardown and enables lockdown.
8482         assertFalse(mMockVpn.getEnableTeardown());
8483         assertTrue(mMockVpn.getLockdown());
8484 
8485         // Bring up a network.
8486         // Expect nothing to happen because the network does not have an IPv4 default route: legacy
8487         // VPN only supports IPv4.
8488         final LinkProperties cellLp = new LinkProperties();
8489         cellLp.setInterfaceName("rmnet0");
8490         cellLp.addLinkAddress(new LinkAddress("2001:db8::1/64"));
8491         cellLp.addRoute(new RouteInfo(new IpPrefix("::/0"), null, "rmnet0"));
8492         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
8493         mCellNetworkAgent.connect(false /* validated */);
8494         callback.expectAvailableCallbacksUnvalidatedAndBlocked(mCellNetworkAgent);
8495         defaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mCellNetworkAgent);
8496         systemDefaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mCellNetworkAgent);
8497         waitForIdle();
8498         assertNull(mMockVpn.getAgent());
8499 
8500         // Add an IPv4 address. Ideally the VPN should start, but it doesn't because nothing calls
8501         // LockdownVpnTracker#handleStateChangedLocked. This is a bug.
8502         // TODO: consider fixing this.
8503         cellLp.addLinkAddress(new LinkAddress("192.0.2.2/25"));
8504         cellLp.addRoute(new RouteInfo(new IpPrefix("0.0.0.0/0"), null, "rmnet0"));
8505         mCellNetworkAgent.sendLinkProperties(cellLp);
8506         callback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
8507         defaultCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
8508         systemDefaultCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED,
8509                 mCellNetworkAgent);
8510         waitForIdle();
8511         assertNull(mMockVpn.getAgent());
8512 
8513         // Disconnect, then try again with a network that supports IPv4 at connection time.
8514         // Expect lockdown VPN to come up.
8515         ExpectedBroadcast b1 = expectConnectivityAction(TYPE_MOBILE, DetailedState.DISCONNECTED);
8516         mCellNetworkAgent.disconnect();
8517         callback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
8518         defaultCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
8519         systemDefaultCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
8520         b1.expectBroadcast();
8521 
8522         // When lockdown VPN is active, the NetworkInfo state in CONNECTIVITY_ACTION is overwritten
8523         // with the state of the VPN network. So expect a CONNECTING broadcast.
8524         b1 = expectConnectivityAction(TYPE_MOBILE, DetailedState.CONNECTING);
8525         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
8526         mCellNetworkAgent.connect(false /* validated */);
8527         callback.expectAvailableCallbacksUnvalidatedAndBlocked(mCellNetworkAgent);
8528         defaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mCellNetworkAgent);
8529         systemDefaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mCellNetworkAgent);
8530         b1.expectBroadcast();
8531         assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
8532         assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
8533         assertNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED);
8534         assertNetworkInfo(TYPE_VPN, DetailedState.BLOCKED);
8535         assertExtraInfoFromCmBlocked(mCellNetworkAgent);
8536 
8537         // TODO: it would be nice if we could simply rely on the production code here, and have
8538         // LockdownVpnTracker start the VPN, have the VPN code register its NetworkAgent with
8539         // ConnectivityService, etc. That would require duplicating a fair bit of code from the
8540         // Vpn tests around how to mock out LegacyVpnRunner. But even if we did that, this does not
8541         // work for at least two reasons:
8542         // 1. In this test, calling registerNetworkAgent does not actually result in an agent being
8543         //    registered. This is because nothing calls onNetworkMonitorCreated, which is what
8544         //    actually ends up causing handleRegisterNetworkAgent to be called. Code in this test
8545         //    that wants to register an agent must use TestNetworkAgentWrapper.
8546         // 2. Even if we exposed Vpn#agentConnect to the test, and made MockVpn#agentConnect call
8547         //    the TestNetworkAgentWrapper code, this would deadlock because the
8548         //    TestNetworkAgentWrapper code cannot be called on the handler thread since it calls
8549         //    waitForIdle().
8550         mMockVpn.expectStartLegacyVpnRunner();
8551         b1 = expectConnectivityAction(TYPE_VPN, DetailedState.CONNECTED);
8552         ExpectedBroadcast b2 = expectConnectivityAction(TYPE_MOBILE, DetailedState.CONNECTED);
8553         establishLegacyLockdownVpn(mCellNetworkAgent.getNetwork());
8554         callback.expectAvailableThenValidatedCallbacks(mMockVpn);
8555         defaultCallback.expectAvailableThenValidatedCallbacks(mMockVpn);
8556         systemDefaultCallback.assertNoCallback();
8557         NetworkCapabilities vpnNc = mCm.getNetworkCapabilities(mMockVpn.getNetwork());
8558         b1.expectBroadcast();
8559         b2.expectBroadcast();
8560         assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
8561         assertNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
8562         assertNetworkInfo(TYPE_WIFI, DetailedState.DISCONNECTED);
8563         assertNetworkInfo(TYPE_VPN, DetailedState.CONNECTED);
8564         assertExtraInfoFromCmPresent(mCellNetworkAgent);
8565         assertTrue(vpnNc.hasTransport(TRANSPORT_VPN));
8566         assertTrue(vpnNc.hasTransport(TRANSPORT_CELLULAR));
8567         assertFalse(vpnNc.hasTransport(TRANSPORT_WIFI));
8568         assertFalse(vpnNc.hasCapability(NET_CAPABILITY_NOT_METERED));
8569         assertVpnTransportInfo(vpnNc, VpnManager.TYPE_VPN_LEGACY);
8570 
8571         // Switch default network from cell to wifi. Expect VPN to disconnect and reconnect.
8572         final LinkProperties wifiLp = new LinkProperties();
8573         wifiLp.setInterfaceName("wlan0");
8574         wifiLp.addLinkAddress(new LinkAddress("192.0.2.163/25"));
8575         wifiLp.addRoute(new RouteInfo(new IpPrefix("0.0.0.0/0"), null, "wlan0"));
8576         final NetworkCapabilities wifiNc = new NetworkCapabilities();
8577         wifiNc.addTransportType(TRANSPORT_WIFI);
8578         wifiNc.addCapability(NET_CAPABILITY_NOT_METERED);
8579         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp, wifiNc);
8580 
8581         b1 = expectConnectivityAction(TYPE_MOBILE, DetailedState.DISCONNECTED);
8582         // Wifi is CONNECTING because the VPN isn't up yet.
8583         b2 = expectConnectivityAction(TYPE_WIFI, DetailedState.CONNECTING);
8584         ExpectedBroadcast b3 = expectConnectivityAction(TYPE_VPN, DetailedState.DISCONNECTED);
8585         mWiFiNetworkAgent.connect(false /* validated */);
8586         b1.expectBroadcast();
8587         b2.expectBroadcast();
8588         b3.expectBroadcast();
8589         mMockVpn.expectStopVpnRunnerPrivileged();
8590         mMockVpn.expectStartLegacyVpnRunner();
8591 
8592         // TODO: why is wifi not blocked? Is it because when this callback is sent, the VPN is still
8593         // connected, so the network is not considered blocked by the lockdown UID ranges? But the
8594         // fact that a VPN is connected should only result in the VPN itself being unblocked, not
8595         // any other network. Bug in isUidBlockedByVpn?
8596         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
8597         callback.expectCallback(CallbackEntry.LOST, mMockVpn);
8598         defaultCallback.expectCallback(CallbackEntry.LOST, mMockVpn);
8599         defaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mWiFiNetworkAgent);
8600         systemDefaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
8601 
8602         // While the VPN is reconnecting on the new network, everything is blocked.
8603         assertActiveNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED);
8604         assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
8605         assertNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED);
8606         assertNetworkInfo(TYPE_VPN, DetailedState.BLOCKED);
8607         assertExtraInfoFromCmBlocked(mWiFiNetworkAgent);
8608 
8609         // The VPN comes up again on wifi.
8610         b1 = expectConnectivityAction(TYPE_VPN, DetailedState.CONNECTED);
8611         b2 = expectConnectivityAction(TYPE_WIFI, DetailedState.CONNECTED);
8612         establishLegacyLockdownVpn(mWiFiNetworkAgent.getNetwork());
8613         callback.expectAvailableThenValidatedCallbacks(mMockVpn);
8614         defaultCallback.expectAvailableThenValidatedCallbacks(mMockVpn);
8615         systemDefaultCallback.assertNoCallback();
8616         b1.expectBroadcast();
8617         b2.expectBroadcast();
8618         assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
8619         assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED);
8620         assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
8621         assertNetworkInfo(TYPE_VPN, DetailedState.CONNECTED);
8622         assertExtraInfoFromCmPresent(mWiFiNetworkAgent);
8623         vpnNc = mCm.getNetworkCapabilities(mMockVpn.getNetwork());
8624         assertTrue(vpnNc.hasTransport(TRANSPORT_VPN));
8625         assertTrue(vpnNc.hasTransport(TRANSPORT_WIFI));
8626         assertFalse(vpnNc.hasTransport(TRANSPORT_CELLULAR));
8627         assertTrue(vpnNc.hasCapability(NET_CAPABILITY_NOT_METERED));
8628 
8629         // Disconnect cell. Nothing much happens since it's not the default network.
8630         mCellNetworkAgent.disconnect();
8631         callback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
8632         defaultCallback.assertNoCallback();
8633         systemDefaultCallback.assertNoCallback();
8634 
8635         assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
8636         assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED);
8637         assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
8638         assertNetworkInfo(TYPE_VPN, DetailedState.CONNECTED);
8639         assertExtraInfoFromCmPresent(mWiFiNetworkAgent);
8640 
8641         b1 = expectConnectivityAction(TYPE_WIFI, DetailedState.DISCONNECTED);
8642         b2 = expectConnectivityAction(TYPE_VPN, DetailedState.DISCONNECTED);
8643         mWiFiNetworkAgent.disconnect();
8644         callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
8645         systemDefaultCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
8646         b1.expectBroadcast();
8647         callback.expectCapabilitiesThat(mMockVpn, nc -> !nc.hasTransport(TRANSPORT_WIFI));
8648         mMockVpn.expectStopVpnRunnerPrivileged();
8649         callback.expectCallback(CallbackEntry.LOST, mMockVpn);
8650         b2.expectBroadcast();
8651     }
8652 
8653     /**
8654      * Test mutable and requestable network capabilities such as
8655      * {@link NetworkCapabilities#NET_CAPABILITY_TRUSTED} and
8656      * {@link NetworkCapabilities#NET_CAPABILITY_NOT_VCN_MANAGED}. Verify that the
8657      * {@code ConnectivityService} re-assign the networks accordingly.
8658      */
8659     @Test
8660     public final void testLoseMutableAndRequestableCaps() throws Exception {
8661         final int[] testCaps = new int [] {
8662                 NET_CAPABILITY_TRUSTED,
8663                 NET_CAPABILITY_NOT_VCN_MANAGED
8664         };
8665         for (final int testCap : testCaps) {
8666             // Create requests with and without the testing capability.
8667             final TestNetworkCallback callbackWithCap = new TestNetworkCallback();
8668             final TestNetworkCallback callbackWithoutCap = new TestNetworkCallback();
8669             mCm.requestNetwork(new NetworkRequest.Builder().addCapability(testCap).build(),
8670                     callbackWithCap);
8671             mCm.requestNetwork(new NetworkRequest.Builder().removeCapability(testCap).build(),
8672                     callbackWithoutCap);
8673 
8674             // Setup networks with testing capability and verify the default network changes.
8675             mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
8676             mCellNetworkAgent.addCapability(testCap);
8677             mCellNetworkAgent.connect(true);
8678             callbackWithCap.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
8679             callbackWithoutCap.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
8680             verify(mMockNetd).networkSetDefault(eq(mCellNetworkAgent.getNetwork().netId));
8681             reset(mMockNetd);
8682 
8683             mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
8684             mWiFiNetworkAgent.addCapability(testCap);
8685             mWiFiNetworkAgent.connect(true);
8686             callbackWithCap.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
8687             callbackWithoutCap.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
8688             verify(mMockNetd).networkSetDefault(eq(mWiFiNetworkAgent.getNetwork().netId));
8689             reset(mMockNetd);
8690 
8691             // Remove the testing capability on wifi, verify the callback and default network
8692             // changes back to cellular.
8693             mWiFiNetworkAgent.removeCapability(testCap);
8694             callbackWithCap.expectAvailableCallbacksValidated(mCellNetworkAgent);
8695             callbackWithoutCap.expectCapabilitiesWithout(testCap, mWiFiNetworkAgent);
8696             verify(mMockNetd).networkSetDefault(eq(mCellNetworkAgent.getNetwork().netId));
8697             reset(mMockNetd);
8698 
8699             mCellNetworkAgent.removeCapability(testCap);
8700             callbackWithCap.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
8701             callbackWithoutCap.assertNoCallback();
8702             verify(mMockNetd).networkClearDefault();
8703 
8704             mCm.unregisterNetworkCallback(callbackWithCap);
8705             mCm.unregisterNetworkCallback(callbackWithoutCap);
8706         }
8707     }
8708 
8709     @Test
8710     public final void testBatteryStatsNetworkType() throws Exception {
8711         final LinkProperties cellLp = new LinkProperties();
8712         cellLp.setInterfaceName("cell0");
8713         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
8714         mCellNetworkAgent.connect(true);
8715         waitForIdle();
8716         verify(mDeps).reportNetworkInterfaceForTransports(mServiceContext,
8717                 cellLp.getInterfaceName(),
8718                 new int[] { TRANSPORT_CELLULAR });
8719 
8720         final LinkProperties wifiLp = new LinkProperties();
8721         wifiLp.setInterfaceName("wifi0");
8722         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp);
8723         mWiFiNetworkAgent.connect(true);
8724         waitForIdle();
8725         verify(mDeps).reportNetworkInterfaceForTransports(mServiceContext,
8726                 wifiLp.getInterfaceName(),
8727                 new int[] { TRANSPORT_WIFI });
8728 
8729         mCellNetworkAgent.disconnect();
8730         mWiFiNetworkAgent.disconnect();
8731 
8732         cellLp.setInterfaceName("wifi0");
8733         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
8734         mCellNetworkAgent.connect(true);
8735         waitForIdle();
8736         verify(mDeps).reportNetworkInterfaceForTransports(mServiceContext,
8737                 cellLp.getInterfaceName(),
8738                 new int[] { TRANSPORT_CELLULAR });
8739         mCellNetworkAgent.disconnect();
8740     }
8741 
8742     /**
8743      * Make simulated InterfaceConfigParcel for Nat464Xlat to query clat lower layer info.
8744      */
8745     private InterfaceConfigurationParcel getClatInterfaceConfigParcel(LinkAddress la) {
8746         final InterfaceConfigurationParcel cfg = new InterfaceConfigurationParcel();
8747         cfg.hwAddr = "11:22:33:44:55:66";
8748         cfg.ipv4Addr = la.getAddress().getHostAddress();
8749         cfg.prefixLength = la.getPrefixLength();
8750         return cfg;
8751     }
8752 
8753     /**
8754      * Make expected stack link properties, copied from Nat464Xlat.
8755      */
8756     private LinkProperties makeClatLinkProperties(LinkAddress la) {
8757         LinkAddress clatAddress = la;
8758         LinkProperties stacked = new LinkProperties();
8759         stacked.setInterfaceName(CLAT_MOBILE_IFNAME);
8760         RouteInfo ipv4Default = new RouteInfo(
8761                 new LinkAddress(Inet4Address.ANY, 0),
8762                 clatAddress.getAddress(), CLAT_MOBILE_IFNAME);
8763         stacked.addRoute(ipv4Default);
8764         stacked.addLinkAddress(clatAddress);
8765         return stacked;
8766     }
8767 
8768     private Nat64PrefixEventParcel makeNat64PrefixEvent(final int netId, final int prefixOperation,
8769             final String prefixAddress, final int prefixLength) {
8770         final Nat64PrefixEventParcel event = new Nat64PrefixEventParcel();
8771         event.netId = netId;
8772         event.prefixOperation = prefixOperation;
8773         event.prefixAddress = prefixAddress;
8774         event.prefixLength = prefixLength;
8775         return event;
8776     }
8777 
8778     @Test
8779     public void testStackedLinkProperties() throws Exception {
8780         final LinkAddress myIpv4 = new LinkAddress("1.2.3.4/24");
8781         final LinkAddress myIpv6 = new LinkAddress("2001:db8:1::1/64");
8782         final String kNat64PrefixString = "2001:db8:64:64:64:64::";
8783         final IpPrefix kNat64Prefix = new IpPrefix(InetAddress.getByName(kNat64PrefixString), 96);
8784         final String kOtherNat64PrefixString = "64:ff9b::";
8785         final IpPrefix kOtherNat64Prefix = new IpPrefix(
8786                 InetAddress.getByName(kOtherNat64PrefixString), 96);
8787         final RouteInfo ipv6Default =
8788                 new RouteInfo((IpPrefix) null, myIpv6.getAddress(), MOBILE_IFNAME);
8789         final RouteInfo ipv6Subnet = new RouteInfo(myIpv6, null, MOBILE_IFNAME);
8790         final RouteInfo ipv4Subnet = new RouteInfo(myIpv4, null, MOBILE_IFNAME);
8791         final RouteInfo stackedDefault =
8792                 new RouteInfo((IpPrefix) null, myIpv4.getAddress(), CLAT_MOBILE_IFNAME);
8793 
8794         final NetworkRequest networkRequest = new NetworkRequest.Builder()
8795                 .addTransportType(TRANSPORT_CELLULAR)
8796                 .addCapability(NET_CAPABILITY_INTERNET)
8797                 .build();
8798         final TestNetworkCallback networkCallback = new TestNetworkCallback();
8799         mCm.registerNetworkCallback(networkRequest, networkCallback);
8800 
8801         // Prepare ipv6 only link properties.
8802         final LinkProperties cellLp = new LinkProperties();
8803         cellLp.setInterfaceName(MOBILE_IFNAME);
8804         cellLp.addLinkAddress(myIpv6);
8805         cellLp.addRoute(ipv6Default);
8806         cellLp.addRoute(ipv6Subnet);
8807         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
8808         reset(mMockDnsResolver);
8809         reset(mMockNetd);
8810 
8811         // Connect with ipv6 link properties. Expect prefix discovery to be started.
8812         mCellNetworkAgent.connect(true);
8813         int cellNetId = mCellNetworkAgent.getNetwork().netId;
8814         waitForIdle();
8815 
8816         verify(mMockNetd, times(1)).networkCreate(nativeNetworkConfigPhysical(cellNetId,
8817                 INetd.PERMISSION_NONE));
8818         assertRoutesAdded(cellNetId, ipv6Subnet, ipv6Default);
8819         verify(mMockDnsResolver, times(1)).createNetworkCache(eq(cellNetId));
8820         verify(mMockNetd, times(1)).networkAddInterface(cellNetId, MOBILE_IFNAME);
8821         verify(mDeps).reportNetworkInterfaceForTransports(mServiceContext,
8822                 cellLp.getInterfaceName(),
8823                 new int[] { TRANSPORT_CELLULAR });
8824 
8825         networkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
8826         verify(mMockDnsResolver, times(1)).startPrefix64Discovery(cellNetId);
8827 
8828         // Switching default network updates TCP buffer sizes.
8829         verifyTcpBufferSizeChange(ConnectivityService.DEFAULT_TCP_BUFFER_SIZES);
8830         // Add an IPv4 address. Expect prefix discovery to be stopped. Netd doesn't tell us that
8831         // the NAT64 prefix was removed because one was never discovered.
8832         cellLp.addLinkAddress(myIpv4);
8833         mCellNetworkAgent.sendLinkProperties(cellLp);
8834         networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
8835         assertRoutesAdded(cellNetId, ipv4Subnet);
8836         verify(mMockDnsResolver, times(1)).stopPrefix64Discovery(cellNetId);
8837         verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(any());
8838 
8839         // Make sure BatteryStats was not told about any v4- interfaces, as none should have
8840         // come online yet.
8841         waitForIdle();
8842         verify(mDeps, never())
8843                 .reportNetworkInterfaceForTransports(eq(mServiceContext), startsWith("v4-"), any());
8844 
8845         verifyNoMoreInteractions(mMockNetd);
8846         verifyNoMoreInteractions(mMockDnsResolver);
8847         reset(mMockNetd);
8848         reset(mMockDnsResolver);
8849         when(mMockNetd.interfaceGetCfg(CLAT_MOBILE_IFNAME))
8850                 .thenReturn(getClatInterfaceConfigParcel(myIpv4));
8851 
8852         // Remove IPv4 address. Expect prefix discovery to be started again.
8853         cellLp.removeLinkAddress(myIpv4);
8854         mCellNetworkAgent.sendLinkProperties(cellLp);
8855         networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
8856         verify(mMockDnsResolver, times(1)).startPrefix64Discovery(cellNetId);
8857         assertRoutesRemoved(cellNetId, ipv4Subnet);
8858 
8859         // When NAT64 prefix discovery succeeds, LinkProperties are updated and clatd is started.
8860         Nat464Xlat clat = getNat464Xlat(mCellNetworkAgent);
8861         assertNull(mCm.getLinkProperties(mCellNetworkAgent.getNetwork()).getNat64Prefix());
8862         mService.mResolverUnsolEventCallback.onNat64PrefixEvent(
8863                 makeNat64PrefixEvent(cellNetId, PREFIX_OPERATION_ADDED, kNat64PrefixString, 96));
8864         LinkProperties lpBeforeClat = networkCallback.expectCallback(
8865                 CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent).getLp();
8866         assertEquals(0, lpBeforeClat.getStackedLinks().size());
8867         assertEquals(kNat64Prefix, lpBeforeClat.getNat64Prefix());
8868         verify(mMockNetd, times(1)).clatdStart(MOBILE_IFNAME, kNat64Prefix.toString());
8869 
8870         // Clat iface comes up. Expect stacked link to be added.
8871         clat.interfaceLinkStateChanged(CLAT_MOBILE_IFNAME, true);
8872         networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
8873         List<LinkProperties> stackedLps = mCm.getLinkProperties(mCellNetworkAgent.getNetwork())
8874                 .getStackedLinks();
8875         assertEquals(makeClatLinkProperties(myIpv4), stackedLps.get(0));
8876         assertRoutesAdded(cellNetId, stackedDefault);
8877         verify(mMockNetd, times(1)).networkAddInterface(cellNetId, CLAT_MOBILE_IFNAME);
8878         // Change trivial linkproperties and see if stacked link is preserved.
8879         cellLp.addDnsServer(InetAddress.getByName("8.8.8.8"));
8880         mCellNetworkAgent.sendLinkProperties(cellLp);
8881         networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
8882 
8883         List<LinkProperties> stackedLpsAfterChange =
8884                 mCm.getLinkProperties(mCellNetworkAgent.getNetwork()).getStackedLinks();
8885         assertNotEquals(stackedLpsAfterChange, Collections.EMPTY_LIST);
8886         assertEquals(makeClatLinkProperties(myIpv4), stackedLpsAfterChange.get(0));
8887 
8888         verify(mMockDnsResolver, times(1)).setResolverConfiguration(
8889                 mResolverParamsParcelCaptor.capture());
8890         ResolverParamsParcel resolvrParams = mResolverParamsParcelCaptor.getValue();
8891         assertEquals(1, resolvrParams.servers.length);
8892         assertTrue(ArrayUtils.contains(resolvrParams.servers, "8.8.8.8"));
8893 
8894         for (final LinkProperties stackedLp : stackedLpsAfterChange) {
8895             verify(mDeps).reportNetworkInterfaceForTransports(
8896                     mServiceContext, stackedLp.getInterfaceName(),
8897                     new int[] { TRANSPORT_CELLULAR });
8898         }
8899         reset(mMockNetd);
8900         when(mMockNetd.interfaceGetCfg(CLAT_MOBILE_IFNAME))
8901                 .thenReturn(getClatInterfaceConfigParcel(myIpv4));
8902         // Change the NAT64 prefix without first removing it.
8903         // Expect clatd to be stopped and started with the new prefix.
8904         mService.mResolverUnsolEventCallback.onNat64PrefixEvent(makeNat64PrefixEvent(
8905                 cellNetId, PREFIX_OPERATION_ADDED, kOtherNat64PrefixString, 96));
8906         networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
8907                 (lp) -> lp.getStackedLinks().size() == 0);
8908         verify(mMockNetd, times(1)).clatdStop(MOBILE_IFNAME);
8909         assertRoutesRemoved(cellNetId, stackedDefault);
8910         verify(mMockNetd, times(1)).networkRemoveInterface(cellNetId, CLAT_MOBILE_IFNAME);
8911 
8912         verify(mMockNetd, times(1)).clatdStart(MOBILE_IFNAME, kOtherNat64Prefix.toString());
8913         networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
8914                 (lp) -> lp.getNat64Prefix().equals(kOtherNat64Prefix));
8915         clat.interfaceLinkStateChanged(CLAT_MOBILE_IFNAME, true);
8916         networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
8917                 (lp) -> lp.getStackedLinks().size() == 1);
8918         assertRoutesAdded(cellNetId, stackedDefault);
8919         verify(mMockNetd, times(1)).networkAddInterface(cellNetId, CLAT_MOBILE_IFNAME);
8920         reset(mMockNetd);
8921 
8922         // Add ipv4 address, expect that clatd and prefix discovery are stopped and stacked
8923         // linkproperties are cleaned up.
8924         cellLp.addLinkAddress(myIpv4);
8925         cellLp.addRoute(ipv4Subnet);
8926         mCellNetworkAgent.sendLinkProperties(cellLp);
8927         networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
8928         assertRoutesAdded(cellNetId, ipv4Subnet);
8929         verify(mMockNetd, times(1)).clatdStop(MOBILE_IFNAME);
8930         verify(mMockDnsResolver, times(1)).stopPrefix64Discovery(cellNetId);
8931 
8932         // As soon as stop is called, the linkproperties lose the stacked interface.
8933         networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
8934         LinkProperties actualLpAfterIpv4 = mCm.getLinkProperties(mCellNetworkAgent.getNetwork());
8935         LinkProperties expected = new LinkProperties(cellLp);
8936         expected.setNat64Prefix(kOtherNat64Prefix);
8937         assertEquals(expected, actualLpAfterIpv4);
8938         assertEquals(0, actualLpAfterIpv4.getStackedLinks().size());
8939         assertRoutesRemoved(cellNetId, stackedDefault);
8940 
8941         // The interface removed callback happens but has no effect after stop is called.
8942         clat.interfaceRemoved(CLAT_MOBILE_IFNAME);
8943         networkCallback.assertNoCallback();
8944         verify(mMockNetd, times(1)).networkRemoveInterface(cellNetId, CLAT_MOBILE_IFNAME);
8945         verifyNoMoreInteractions(mMockNetd);
8946         verifyNoMoreInteractions(mMockDnsResolver);
8947         reset(mMockNetd);
8948         reset(mMockDnsResolver);
8949         when(mMockNetd.interfaceGetCfg(CLAT_MOBILE_IFNAME))
8950                 .thenReturn(getClatInterfaceConfigParcel(myIpv4));
8951 
8952         // Stopping prefix discovery causes netd to tell us that the NAT64 prefix is gone.
8953         mService.mResolverUnsolEventCallback.onNat64PrefixEvent(makeNat64PrefixEvent(
8954                 cellNetId, PREFIX_OPERATION_REMOVED, kOtherNat64PrefixString, 96));
8955         networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
8956                 (lp) -> lp.getNat64Prefix() == null);
8957 
8958         // Remove IPv4 address and expect prefix discovery and clatd to be started again.
8959         cellLp.removeLinkAddress(myIpv4);
8960         cellLp.removeRoute(new RouteInfo(myIpv4, null, MOBILE_IFNAME));
8961         cellLp.removeDnsServer(InetAddress.getByName("8.8.8.8"));
8962         mCellNetworkAgent.sendLinkProperties(cellLp);
8963         networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
8964         assertRoutesRemoved(cellNetId, ipv4Subnet);  // Directly-connected routes auto-added.
8965         verify(mMockDnsResolver, times(1)).startPrefix64Discovery(cellNetId);
8966         mService.mResolverUnsolEventCallback.onNat64PrefixEvent(makeNat64PrefixEvent(
8967                 cellNetId, PREFIX_OPERATION_ADDED, kNat64PrefixString, 96));
8968         networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
8969         verify(mMockNetd, times(1)).clatdStart(MOBILE_IFNAME, kNat64Prefix.toString());
8970 
8971         // Clat iface comes up. Expect stacked link to be added.
8972         clat.interfaceLinkStateChanged(CLAT_MOBILE_IFNAME, true);
8973         networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
8974                 (lp) -> lp.getStackedLinks().size() == 1 && lp.getNat64Prefix() != null);
8975         assertRoutesAdded(cellNetId, stackedDefault);
8976         verify(mMockNetd, times(1)).networkAddInterface(cellNetId, CLAT_MOBILE_IFNAME);
8977 
8978         // NAT64 prefix is removed. Expect that clat is stopped.
8979         mService.mResolverUnsolEventCallback.onNat64PrefixEvent(makeNat64PrefixEvent(
8980                 cellNetId, PREFIX_OPERATION_REMOVED, kNat64PrefixString, 96));
8981         networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
8982                 (lp) -> lp.getStackedLinks().size() == 0 && lp.getNat64Prefix() == null);
8983         assertRoutesRemoved(cellNetId, ipv4Subnet, stackedDefault);
8984 
8985         // Stop has no effect because clat is already stopped.
8986         verify(mMockNetd, times(1)).clatdStop(MOBILE_IFNAME);
8987         networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
8988                 (lp) -> lp.getStackedLinks().size() == 0);
8989         verify(mMockNetd, times(1)).networkRemoveInterface(cellNetId, CLAT_MOBILE_IFNAME);
8990         verify(mMockNetd, times(1)).interfaceGetCfg(CLAT_MOBILE_IFNAME);
8991         // Clean up.
8992         mCellNetworkAgent.disconnect();
8993         networkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
8994         networkCallback.assertNoCallback();
8995         verify(mMockNetd, times(1)).idletimerRemoveInterface(eq(MOBILE_IFNAME), anyInt(),
8996                 eq(Integer.toString(TRANSPORT_CELLULAR)));
8997         verify(mMockNetd).networkDestroy(cellNetId);
8998         verifyNoMoreInteractions(mMockNetd);
8999         reset(mMockNetd);
9000 
9001         // Test disconnecting a network that is running 464xlat.
9002 
9003         // Connect a network with a NAT64 prefix.
9004         when(mMockNetd.interfaceGetCfg(CLAT_MOBILE_IFNAME))
9005                 .thenReturn(getClatInterfaceConfigParcel(myIpv4));
9006         cellLp.setNat64Prefix(kNat64Prefix);
9007         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
9008         mCellNetworkAgent.connect(false /* validated */);
9009         networkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
9010         cellNetId = mCellNetworkAgent.getNetwork().netId;
9011         verify(mMockNetd, times(1)).networkCreate(nativeNetworkConfigPhysical(cellNetId,
9012                 INetd.PERMISSION_NONE));
9013         assertRoutesAdded(cellNetId, ipv6Subnet, ipv6Default);
9014 
9015         // Clatd is started and clat iface comes up. Expect stacked link to be added.
9016         verify(mMockNetd).clatdStart(MOBILE_IFNAME, kNat64Prefix.toString());
9017         clat = getNat464Xlat(mCellNetworkAgent);
9018         clat.interfaceLinkStateChanged(CLAT_MOBILE_IFNAME, true /* up */);
9019         networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
9020                 (lp) -> lp.getStackedLinks().size() == 1
9021                         && lp.getNat64Prefix().equals(kNat64Prefix));
9022         verify(mMockNetd).networkAddInterface(cellNetId, CLAT_MOBILE_IFNAME);
9023         // assertRoutesAdded sees all calls since last mMockNetd reset, so expect IPv6 routes again.
9024         assertRoutesAdded(cellNetId, ipv6Subnet, ipv6Default, stackedDefault);
9025         reset(mMockNetd);
9026 
9027         // Disconnect the network. clat is stopped and the network is destroyed.
9028         mCellNetworkAgent.disconnect();
9029         networkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
9030         networkCallback.assertNoCallback();
9031         verify(mMockNetd).clatdStop(MOBILE_IFNAME);
9032         verify(mMockNetd).idletimerRemoveInterface(eq(MOBILE_IFNAME), anyInt(),
9033                 eq(Integer.toString(TRANSPORT_CELLULAR)));
9034         verify(mMockNetd).networkDestroy(cellNetId);
9035         verifyNoMoreInteractions(mMockNetd);
9036 
9037         mCm.unregisterNetworkCallback(networkCallback);
9038     }
9039 
9040     private void expectNat64PrefixChange(TestableNetworkCallback callback,
9041             TestNetworkAgentWrapper agent, IpPrefix prefix) {
9042         callback.expectLinkPropertiesThat(agent, x -> Objects.equals(x.getNat64Prefix(), prefix));
9043     }
9044 
9045     @Test
9046     public void testNat64PrefixMultipleSources() throws Exception {
9047         final String iface = "wlan0";
9048         final String pref64FromRaStr = "64:ff9b::";
9049         final String pref64FromDnsStr = "2001:db8:64::";
9050         final IpPrefix pref64FromRa = new IpPrefix(InetAddress.getByName(pref64FromRaStr), 96);
9051         final IpPrefix pref64FromDns = new IpPrefix(InetAddress.getByName(pref64FromDnsStr), 96);
9052         final IpPrefix newPref64FromRa = new IpPrefix("2001:db8:64:64:64:64::/96");
9053 
9054         final NetworkRequest request = new NetworkRequest.Builder()
9055                 .addCapability(NET_CAPABILITY_INTERNET)
9056                 .build();
9057         final TestNetworkCallback callback = new TestNetworkCallback();
9058         mCm.registerNetworkCallback(request, callback);
9059 
9060         final LinkProperties baseLp = new LinkProperties();
9061         baseLp.setInterfaceName(iface);
9062         baseLp.addLinkAddress(new LinkAddress("2001:db8:1::1/64"));
9063         baseLp.addDnsServer(InetAddress.getByName("2001:4860:4860::6464"));
9064 
9065         reset(mMockNetd, mMockDnsResolver);
9066         InOrder inOrder = inOrder(mMockNetd, mMockDnsResolver);
9067 
9068         // If a network already has a NAT64 prefix on connect, clatd is started immediately and
9069         // prefix discovery is never started.
9070         LinkProperties lp = new LinkProperties(baseLp);
9071         lp.setNat64Prefix(pref64FromRa);
9072         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, lp);
9073         mWiFiNetworkAgent.connect(false);
9074         final Network network = mWiFiNetworkAgent.getNetwork();
9075         int netId = network.getNetId();
9076         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
9077         inOrder.verify(mMockNetd).clatdStart(iface, pref64FromRa.toString());
9078         inOrder.verify(mMockDnsResolver).setPrefix64(netId, pref64FromRa.toString());
9079         inOrder.verify(mMockDnsResolver, never()).startPrefix64Discovery(netId);
9080         callback.assertNoCallback();
9081         assertEquals(pref64FromRa, mCm.getLinkProperties(network).getNat64Prefix());
9082 
9083         // If the RA prefix is withdrawn, clatd is stopped and prefix discovery is started.
9084         lp.setNat64Prefix(null);
9085         mWiFiNetworkAgent.sendLinkProperties(lp);
9086         expectNat64PrefixChange(callback, mWiFiNetworkAgent, null);
9087         inOrder.verify(mMockNetd).clatdStop(iface);
9088         inOrder.verify(mMockDnsResolver).setPrefix64(netId, "");
9089         inOrder.verify(mMockDnsResolver).startPrefix64Discovery(netId);
9090 
9091         // If the RA prefix appears while DNS discovery is in progress, discovery is stopped and
9092         // clatd is started with the prefix from the RA.
9093         lp.setNat64Prefix(pref64FromRa);
9094         mWiFiNetworkAgent.sendLinkProperties(lp);
9095         expectNat64PrefixChange(callback, mWiFiNetworkAgent, pref64FromRa);
9096         inOrder.verify(mMockNetd).clatdStart(iface, pref64FromRa.toString());
9097         inOrder.verify(mMockDnsResolver).stopPrefix64Discovery(netId);
9098         inOrder.verify(mMockDnsResolver).setPrefix64(netId, pref64FromRa.toString());
9099 
9100         // Withdraw the RA prefix so we can test the case where an RA prefix appears after DNS
9101         // discovery has succeeded.
9102         lp.setNat64Prefix(null);
9103         mWiFiNetworkAgent.sendLinkProperties(lp);
9104         expectNat64PrefixChange(callback, mWiFiNetworkAgent, null);
9105         inOrder.verify(mMockNetd).clatdStop(iface);
9106         inOrder.verify(mMockDnsResolver).setPrefix64(netId, "");
9107         inOrder.verify(mMockDnsResolver).startPrefix64Discovery(netId);
9108 
9109         mService.mResolverUnsolEventCallback.onNat64PrefixEvent(
9110                 makeNat64PrefixEvent(netId, PREFIX_OPERATION_ADDED, pref64FromDnsStr, 96));
9111         expectNat64PrefixChange(callback, mWiFiNetworkAgent, pref64FromDns);
9112         inOrder.verify(mMockNetd).clatdStart(iface, pref64FromDns.toString());
9113 
9114         // If an RA advertises the same prefix that was discovered by DNS, nothing happens: prefix
9115         // discovery is not stopped, and there are no callbacks.
9116         lp.setNat64Prefix(pref64FromDns);
9117         mWiFiNetworkAgent.sendLinkProperties(lp);
9118         callback.assertNoCallback();
9119         inOrder.verify(mMockNetd, never()).clatdStop(iface);
9120         inOrder.verify(mMockNetd, never()).clatdStart(eq(iface), anyString());
9121         inOrder.verify(mMockDnsResolver, never()).stopPrefix64Discovery(netId);
9122         inOrder.verify(mMockDnsResolver, never()).startPrefix64Discovery(netId);
9123         inOrder.verify(mMockDnsResolver, never()).setPrefix64(eq(netId), anyString());
9124 
9125         // If the RA is later withdrawn, nothing happens again.
9126         lp.setNat64Prefix(null);
9127         mWiFiNetworkAgent.sendLinkProperties(lp);
9128         callback.assertNoCallback();
9129         inOrder.verify(mMockNetd, never()).clatdStop(iface);
9130         inOrder.verify(mMockNetd, never()).clatdStart(eq(iface), anyString());
9131         inOrder.verify(mMockDnsResolver, never()).stopPrefix64Discovery(netId);
9132         inOrder.verify(mMockDnsResolver, never()).startPrefix64Discovery(netId);
9133         inOrder.verify(mMockDnsResolver, never()).setPrefix64(eq(netId), anyString());
9134 
9135         // If the RA prefix changes, clatd is restarted and prefix discovery is stopped.
9136         lp.setNat64Prefix(pref64FromRa);
9137         mWiFiNetworkAgent.sendLinkProperties(lp);
9138         expectNat64PrefixChange(callback, mWiFiNetworkAgent, pref64FromRa);
9139         inOrder.verify(mMockNetd).clatdStop(iface);
9140         inOrder.verify(mMockDnsResolver).stopPrefix64Discovery(netId);
9141 
9142         // Stopping prefix discovery results in a prefix removed notification.
9143         mService.mResolverUnsolEventCallback.onNat64PrefixEvent(
9144                 makeNat64PrefixEvent(netId, PREFIX_OPERATION_REMOVED, pref64FromDnsStr, 96));
9145 
9146         inOrder.verify(mMockNetd).clatdStart(iface, pref64FromRa.toString());
9147         inOrder.verify(mMockDnsResolver).setPrefix64(netId, pref64FromRa.toString());
9148         inOrder.verify(mMockDnsResolver, never()).startPrefix64Discovery(netId);
9149 
9150         // If the RA prefix changes, clatd is restarted and prefix discovery is not started.
9151         lp.setNat64Prefix(newPref64FromRa);
9152         mWiFiNetworkAgent.sendLinkProperties(lp);
9153         expectNat64PrefixChange(callback, mWiFiNetworkAgent, newPref64FromRa);
9154         inOrder.verify(mMockNetd).clatdStop(iface);
9155         inOrder.verify(mMockDnsResolver).setPrefix64(netId, "");
9156         inOrder.verify(mMockNetd).clatdStart(iface, newPref64FromRa.toString());
9157         inOrder.verify(mMockDnsResolver).setPrefix64(netId, newPref64FromRa.toString());
9158         inOrder.verify(mMockDnsResolver, never()).stopPrefix64Discovery(netId);
9159         inOrder.verify(mMockDnsResolver, never()).startPrefix64Discovery(netId);
9160 
9161         // If the RA prefix changes to the same value, nothing happens.
9162         lp.setNat64Prefix(newPref64FromRa);
9163         mWiFiNetworkAgent.sendLinkProperties(lp);
9164         callback.assertNoCallback();
9165         assertEquals(newPref64FromRa, mCm.getLinkProperties(network).getNat64Prefix());
9166         inOrder.verify(mMockNetd, never()).clatdStop(iface);
9167         inOrder.verify(mMockNetd, never()).clatdStart(eq(iface), anyString());
9168         inOrder.verify(mMockDnsResolver, never()).stopPrefix64Discovery(netId);
9169         inOrder.verify(mMockDnsResolver, never()).startPrefix64Discovery(netId);
9170         inOrder.verify(mMockDnsResolver, never()).setPrefix64(eq(netId), anyString());
9171 
9172         // The transition between no prefix and DNS prefix is tested in testStackedLinkProperties.
9173 
9174         // If the same prefix is learned first by DNS and then by RA, and clat is later stopped,
9175         // (e.g., because the network disconnects) setPrefix64(netid, "") is never called.
9176         lp.setNat64Prefix(null);
9177         mWiFiNetworkAgent.sendLinkProperties(lp);
9178         expectNat64PrefixChange(callback, mWiFiNetworkAgent, null);
9179         inOrder.verify(mMockNetd).clatdStop(iface);
9180         inOrder.verify(mMockDnsResolver).setPrefix64(netId, "");
9181         inOrder.verify(mMockDnsResolver).startPrefix64Discovery(netId);
9182         mService.mResolverUnsolEventCallback.onNat64PrefixEvent(
9183                 makeNat64PrefixEvent(netId, PREFIX_OPERATION_ADDED, pref64FromDnsStr, 96));
9184         expectNat64PrefixChange(callback, mWiFiNetworkAgent, pref64FromDns);
9185         inOrder.verify(mMockNetd).clatdStart(iface, pref64FromDns.toString());
9186         inOrder.verify(mMockDnsResolver, never()).setPrefix64(eq(netId), any());
9187 
9188         lp.setNat64Prefix(pref64FromDns);
9189         mWiFiNetworkAgent.sendLinkProperties(lp);
9190         callback.assertNoCallback();
9191         inOrder.verify(mMockNetd, never()).clatdStop(iface);
9192         inOrder.verify(mMockNetd, never()).clatdStart(eq(iface), anyString());
9193         inOrder.verify(mMockDnsResolver, never()).stopPrefix64Discovery(netId);
9194         inOrder.verify(mMockDnsResolver, never()).startPrefix64Discovery(netId);
9195         inOrder.verify(mMockDnsResolver, never()).setPrefix64(eq(netId), anyString());
9196 
9197         // When tearing down a network, clat state is only updated after CALLBACK_LOST is fired, but
9198         // before CONNECTIVITY_ACTION is sent. Wait for CONNECTIVITY_ACTION before verifying that
9199         // clat has been stopped, or the test will be flaky.
9200         ExpectedBroadcast b = expectConnectivityAction(TYPE_WIFI, DetailedState.DISCONNECTED);
9201         mWiFiNetworkAgent.disconnect();
9202         callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
9203         b.expectBroadcast();
9204 
9205         inOrder.verify(mMockNetd).clatdStop(iface);
9206         inOrder.verify(mMockDnsResolver).stopPrefix64Discovery(netId);
9207         inOrder.verify(mMockDnsResolver, never()).setPrefix64(eq(netId), anyString());
9208 
9209         mCm.unregisterNetworkCallback(callback);
9210     }
9211 
9212     @Test
9213     public void testWith464XlatDisable() throws Exception {
9214         doReturn(false).when(mDeps).getCellular464XlatEnabled();
9215 
9216         final TestNetworkCallback callback = new TestNetworkCallback();
9217         final TestNetworkCallback defaultCallback = new TestNetworkCallback();
9218         final NetworkRequest networkRequest = new NetworkRequest.Builder()
9219                 .addCapability(NET_CAPABILITY_INTERNET)
9220                 .build();
9221         mCm.registerNetworkCallback(networkRequest, callback);
9222         mCm.registerDefaultNetworkCallback(defaultCallback);
9223 
9224         // Bring up validated cell.
9225         final LinkProperties cellLp = new LinkProperties();
9226         cellLp.setInterfaceName(MOBILE_IFNAME);
9227         cellLp.addLinkAddress(new LinkAddress("2001:db8:1::1/64"));
9228         cellLp.addRoute(new RouteInfo(new IpPrefix("::/0"), null, MOBILE_IFNAME));
9229         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
9230 
9231         mCellNetworkAgent.sendLinkProperties(cellLp);
9232         mCellNetworkAgent.connect(true);
9233         callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
9234         defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
9235         final int cellNetId = mCellNetworkAgent.getNetwork().netId;
9236         waitForIdle();
9237 
9238         verify(mMockDnsResolver, never()).startPrefix64Discovery(cellNetId);
9239         Nat464Xlat clat = getNat464Xlat(mCellNetworkAgent);
9240         assertTrue("Nat464Xlat was not IDLE", !clat.isStarted());
9241 
9242         // This cannot happen because prefix discovery cannot succeed if it is never started.
9243         mService.mResolverUnsolEventCallback.onNat64PrefixEvent(
9244                 makeNat64PrefixEvent(cellNetId, PREFIX_OPERATION_ADDED, "64:ff9b::", 96));
9245 
9246         // ... but still, check that even if it did, clatd would not be started.
9247         verify(mMockNetd, never()).clatdStart(anyString(), anyString());
9248         assertTrue("Nat464Xlat was not IDLE", !clat.isStarted());
9249     }
9250 
9251     @Test
9252     public void testDataActivityTracking() throws Exception {
9253         final TestNetworkCallback networkCallback = new TestNetworkCallback();
9254         final NetworkRequest networkRequest = new NetworkRequest.Builder()
9255                 .addCapability(NET_CAPABILITY_INTERNET)
9256                 .build();
9257         mCm.registerNetworkCallback(networkRequest, networkCallback);
9258 
9259         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
9260         final LinkProperties cellLp = new LinkProperties();
9261         cellLp.setInterfaceName(MOBILE_IFNAME);
9262         mCellNetworkAgent.sendLinkProperties(cellLp);
9263         mCellNetworkAgent.connect(true);
9264         networkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
9265         verify(mMockNetd, times(1)).idletimerAddInterface(eq(MOBILE_IFNAME), anyInt(),
9266                 eq(Integer.toString(TRANSPORT_CELLULAR)));
9267 
9268         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
9269         final LinkProperties wifiLp = new LinkProperties();
9270         wifiLp.setInterfaceName(WIFI_IFNAME);
9271         mWiFiNetworkAgent.sendLinkProperties(wifiLp);
9272 
9273         // Network switch
9274         mWiFiNetworkAgent.connect(true);
9275         networkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
9276         networkCallback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
9277         networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
9278         verify(mMockNetd, times(1)).idletimerAddInterface(eq(WIFI_IFNAME), anyInt(),
9279                 eq(Integer.toString(TRANSPORT_WIFI)));
9280         verify(mMockNetd, times(1)).idletimerRemoveInterface(eq(MOBILE_IFNAME), anyInt(),
9281                 eq(Integer.toString(TRANSPORT_CELLULAR)));
9282 
9283         // Disconnect wifi and switch back to cell
9284         reset(mMockNetd);
9285         mWiFiNetworkAgent.disconnect();
9286         networkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
9287         assertNoCallbacks(networkCallback);
9288         verify(mMockNetd, times(1)).idletimerRemoveInterface(eq(WIFI_IFNAME), anyInt(),
9289                 eq(Integer.toString(TRANSPORT_WIFI)));
9290         verify(mMockNetd, times(1)).idletimerAddInterface(eq(MOBILE_IFNAME), anyInt(),
9291                 eq(Integer.toString(TRANSPORT_CELLULAR)));
9292 
9293         // reconnect wifi
9294         reset(mMockNetd);
9295         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
9296         wifiLp.setInterfaceName(WIFI_IFNAME);
9297         mWiFiNetworkAgent.sendLinkProperties(wifiLp);
9298         mWiFiNetworkAgent.connect(true);
9299         networkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
9300         networkCallback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
9301         networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
9302         verify(mMockNetd, times(1)).idletimerAddInterface(eq(WIFI_IFNAME), anyInt(),
9303                 eq(Integer.toString(TRANSPORT_WIFI)));
9304         verify(mMockNetd, times(1)).idletimerRemoveInterface(eq(MOBILE_IFNAME), anyInt(),
9305                 eq(Integer.toString(TRANSPORT_CELLULAR)));
9306 
9307         // Disconnect cell
9308         reset(mMockNetd);
9309         mCellNetworkAgent.disconnect();
9310         networkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
9311         // LOST callback is triggered earlier than removing idle timer. Broadcast should also be
9312         // sent as network being switched. Ensure rule removal for cell will not be triggered
9313         // unexpectedly before network being removed.
9314         waitForIdle();
9315         verify(mMockNetd, times(0)).idletimerRemoveInterface(eq(MOBILE_IFNAME), anyInt(),
9316                 eq(Integer.toString(TRANSPORT_CELLULAR)));
9317         verify(mMockNetd, times(1)).networkDestroy(eq(mCellNetworkAgent.getNetwork().netId));
9318         verify(mMockDnsResolver, times(1))
9319                 .destroyNetworkCache(eq(mCellNetworkAgent.getNetwork().netId));
9320 
9321         // Disconnect wifi
9322         ExpectedBroadcast b = expectConnectivityAction(TYPE_WIFI, DetailedState.DISCONNECTED);
9323         mWiFiNetworkAgent.disconnect();
9324         b.expectBroadcast();
9325         verify(mMockNetd, times(1)).idletimerRemoveInterface(eq(WIFI_IFNAME), anyInt(),
9326                 eq(Integer.toString(TRANSPORT_WIFI)));
9327 
9328         // Clean up
9329         mCm.unregisterNetworkCallback(networkCallback);
9330     }
9331 
9332     private void verifyTcpBufferSizeChange(String tcpBufferSizes) throws Exception {
9333         String[] values = tcpBufferSizes.split(",");
9334         String rmemValues = String.join(" ", values[0], values[1], values[2]);
9335         String wmemValues = String.join(" ", values[3], values[4], values[5]);
9336         verify(mMockNetd, atLeastOnce()).setTcpRWmemorySize(rmemValues, wmemValues);
9337         reset(mMockNetd);
9338     }
9339 
9340     @Test
9341     public void testTcpBufferReset() throws Exception {
9342         final String testTcpBufferSizes = "1,2,3,4,5,6";
9343         final NetworkRequest networkRequest = new NetworkRequest.Builder()
9344                 .addTransportType(TRANSPORT_CELLULAR)
9345                 .addCapability(NET_CAPABILITY_INTERNET)
9346                 .build();
9347         final TestNetworkCallback networkCallback = new TestNetworkCallback();
9348         mCm.registerNetworkCallback(networkRequest, networkCallback);
9349 
9350         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
9351         reset(mMockNetd);
9352         // Switching default network updates TCP buffer sizes.
9353         mCellNetworkAgent.connect(false);
9354         networkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
9355         verifyTcpBufferSizeChange(ConnectivityService.DEFAULT_TCP_BUFFER_SIZES);
9356         // Change link Properties should have updated tcp buffer size.
9357         LinkProperties lp = new LinkProperties();
9358         lp.setTcpBufferSizes(testTcpBufferSizes);
9359         mCellNetworkAgent.sendLinkProperties(lp);
9360         networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
9361         verifyTcpBufferSizeChange(testTcpBufferSizes);
9362         // Clean up.
9363         mCellNetworkAgent.disconnect();
9364         networkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
9365         networkCallback.assertNoCallback();
9366         mCm.unregisterNetworkCallback(networkCallback);
9367     }
9368 
9369     @Test
9370     public void testGetGlobalProxyForNetwork() throws Exception {
9371         final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
9372         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
9373         final Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
9374         when(mService.mProxyTracker.getGlobalProxy()).thenReturn(testProxyInfo);
9375         assertEquals(testProxyInfo, mService.getProxyForNetwork(wifiNetwork));
9376     }
9377 
9378     @Test
9379     public void testGetProxyForActiveNetwork() throws Exception {
9380         final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
9381         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
9382         mWiFiNetworkAgent.connect(true);
9383         waitForIdle();
9384         assertNull(mService.getProxyForNetwork(null));
9385 
9386         final LinkProperties testLinkProperties = new LinkProperties();
9387         testLinkProperties.setHttpProxy(testProxyInfo);
9388 
9389         mWiFiNetworkAgent.sendLinkProperties(testLinkProperties);
9390         waitForIdle();
9391 
9392         assertEquals(testProxyInfo, mService.getProxyForNetwork(null));
9393     }
9394 
9395     @Test
9396     public void testGetProxyForVPN() throws Exception {
9397         final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
9398 
9399         // Set up a WiFi network with no proxy
9400         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
9401         mWiFiNetworkAgent.connect(true);
9402         waitForIdle();
9403         assertNull(mService.getProxyForNetwork(null));
9404 
9405         // Connect a VPN network with a proxy.
9406         LinkProperties testLinkProperties = new LinkProperties();
9407         testLinkProperties.setHttpProxy(testProxyInfo);
9408         mMockVpn.establishForMyUid(testLinkProperties);
9409         assertUidRangesUpdatedForMyUid(true);
9410 
9411         // Test that the VPN network returns a proxy, and the WiFi does not.
9412         assertEquals(testProxyInfo, mService.getProxyForNetwork(mMockVpn.getNetwork()));
9413         assertEquals(testProxyInfo, mService.getProxyForNetwork(null));
9414         assertNull(mService.getProxyForNetwork(mWiFiNetworkAgent.getNetwork()));
9415 
9416         // Test that the VPN network returns no proxy when it is set to null.
9417         testLinkProperties.setHttpProxy(null);
9418         mMockVpn.sendLinkProperties(testLinkProperties);
9419         waitForIdle();
9420         assertNull(mService.getProxyForNetwork(mMockVpn.getNetwork()));
9421         assertNull(mService.getProxyForNetwork(null));
9422 
9423         // Set WiFi proxy and check that the vpn proxy is still null.
9424         testLinkProperties.setHttpProxy(testProxyInfo);
9425         mWiFiNetworkAgent.sendLinkProperties(testLinkProperties);
9426         waitForIdle();
9427         assertNull(mService.getProxyForNetwork(null));
9428 
9429         // Disconnect from VPN and check that the active network, which is now the WiFi, has the
9430         // correct proxy setting.
9431         mMockVpn.disconnect();
9432         waitForIdle();
9433         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
9434         assertEquals(testProxyInfo, mService.getProxyForNetwork(mWiFiNetworkAgent.getNetwork()));
9435         assertEquals(testProxyInfo, mService.getProxyForNetwork(null));
9436     }
9437 
9438     @Test
9439     public void testFullyRoutedVpnResultsInInterfaceFilteringRules() throws Exception {
9440         LinkProperties lp = new LinkProperties();
9441         lp.setInterfaceName("tun0");
9442         lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
9443         lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), RTN_UNREACHABLE));
9444         // The uid range needs to cover the test app so the network is visible to it.
9445         final Set<UidRange> vpnRange = Collections.singleton(PRIMARY_UIDRANGE);
9446         mMockVpn.establish(lp, VPN_UID, vpnRange);
9447         assertVpnUidRangesUpdated(true, vpnRange, VPN_UID);
9448 
9449         // A connected VPN should have interface rules set up. There are two expected invocations,
9450         // one during the VPN initial connection, one during the VPN LinkProperties update.
9451         ArgumentCaptor<int[]> uidCaptor = ArgumentCaptor.forClass(int[].class);
9452         verify(mMockNetd, times(2)).firewallAddUidInterfaceRules(eq("tun0"), uidCaptor.capture());
9453         assertContainsExactly(uidCaptor.getAllValues().get(0), APP1_UID, APP2_UID);
9454         assertContainsExactly(uidCaptor.getAllValues().get(1), APP1_UID, APP2_UID);
9455         assertTrue(mService.mPermissionMonitor.getVpnUidRanges("tun0").equals(vpnRange));
9456 
9457         mMockVpn.disconnect();
9458         waitForIdle();
9459 
9460         // Disconnected VPN should have interface rules removed
9461         verify(mMockNetd).firewallRemoveUidInterfaceRules(uidCaptor.capture());
9462         assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
9463         assertNull(mService.mPermissionMonitor.getVpnUidRanges("tun0"));
9464     }
9465 
9466     @Test
9467     public void testLegacyVpnDoesNotResultInInterfaceFilteringRule() throws Exception {
9468         LinkProperties lp = new LinkProperties();
9469         lp.setInterfaceName("tun0");
9470         lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
9471         lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
9472         // The uid range needs to cover the test app so the network is visible to it.
9473         final Set<UidRange> vpnRange = Collections.singleton(PRIMARY_UIDRANGE);
9474         mMockVpn.establish(lp, Process.SYSTEM_UID, vpnRange);
9475         assertVpnUidRangesUpdated(true, vpnRange, Process.SYSTEM_UID);
9476 
9477         // Legacy VPN should not have interface rules set up
9478         verify(mMockNetd, never()).firewallAddUidInterfaceRules(any(), any());
9479     }
9480 
9481     @Test
9482     public void testLocalIpv4OnlyVpnDoesNotResultInInterfaceFilteringRule()
9483             throws Exception {
9484         LinkProperties lp = new LinkProperties();
9485         lp.setInterfaceName("tun0");
9486         lp.addRoute(new RouteInfo(new IpPrefix("192.0.2.0/24"), null, "tun0"));
9487         lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), RTN_UNREACHABLE));
9488         // The uid range needs to cover the test app so the network is visible to it.
9489         final Set<UidRange> vpnRange = Collections.singleton(PRIMARY_UIDRANGE);
9490         mMockVpn.establish(lp, Process.SYSTEM_UID, vpnRange);
9491         assertVpnUidRangesUpdated(true, vpnRange, Process.SYSTEM_UID);
9492 
9493         // IPv6 unreachable route should not be misinterpreted as a default route
9494         verify(mMockNetd, never()).firewallAddUidInterfaceRules(any(), any());
9495     }
9496 
9497     @Test
9498     public void testVpnHandoverChangesInterfaceFilteringRule() throws Exception {
9499         LinkProperties lp = new LinkProperties();
9500         lp.setInterfaceName("tun0");
9501         lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
9502         lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
9503         // The uid range needs to cover the test app so the network is visible to it.
9504         final Set<UidRange> vpnRange = Collections.singleton(PRIMARY_UIDRANGE);
9505         mMockVpn.establish(lp, VPN_UID, vpnRange);
9506         assertVpnUidRangesUpdated(true, vpnRange, VPN_UID);
9507 
9508         // Connected VPN should have interface rules set up. There are two expected invocations,
9509         // one during VPN uid update, one during VPN LinkProperties update
9510         ArgumentCaptor<int[]> uidCaptor = ArgumentCaptor.forClass(int[].class);
9511         verify(mMockNetd, times(2)).firewallAddUidInterfaceRules(eq("tun0"), uidCaptor.capture());
9512         assertContainsExactly(uidCaptor.getAllValues().get(0), APP1_UID, APP2_UID);
9513         assertContainsExactly(uidCaptor.getAllValues().get(1), APP1_UID, APP2_UID);
9514 
9515         reset(mMockNetd);
9516         InOrder inOrder = inOrder(mMockNetd);
9517         lp.setInterfaceName("tun1");
9518         mMockVpn.sendLinkProperties(lp);
9519         waitForIdle();
9520         // VPN handover (switch to a new interface) should result in rules being updated (old rules
9521         // removed first, then new rules added)
9522         inOrder.verify(mMockNetd).firewallRemoveUidInterfaceRules(uidCaptor.capture());
9523         assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
9524         inOrder.verify(mMockNetd).firewallAddUidInterfaceRules(eq("tun1"), uidCaptor.capture());
9525         assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
9526 
9527         reset(mMockNetd);
9528         lp = new LinkProperties();
9529         lp.setInterfaceName("tun1");
9530         lp.addRoute(new RouteInfo(new IpPrefix("192.0.2.0/24"), null, "tun1"));
9531         mMockVpn.sendLinkProperties(lp);
9532         waitForIdle();
9533         // VPN not routing everything should no longer have interface filtering rules
9534         verify(mMockNetd).firewallRemoveUidInterfaceRules(uidCaptor.capture());
9535         assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
9536 
9537         reset(mMockNetd);
9538         lp = new LinkProperties();
9539         lp.setInterfaceName("tun1");
9540         lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), RTN_UNREACHABLE));
9541         lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
9542         mMockVpn.sendLinkProperties(lp);
9543         waitForIdle();
9544         // Back to routing all IPv6 traffic should have filtering rules
9545         verify(mMockNetd).firewallAddUidInterfaceRules(eq("tun1"), uidCaptor.capture());
9546         assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
9547     }
9548 
9549     @Test
9550     public void testStartVpnProfileFromDiffPackage() throws Exception {
9551         final String notMyVpnPkg = "com.not.my.vpn";
9552         assertThrows(
9553                 SecurityException.class, () -> mVpnManagerService.startVpnProfile(notMyVpnPkg));
9554     }
9555 
9556     @Test
9557     public void testStopVpnProfileFromDiffPackage() throws Exception {
9558         final String notMyVpnPkg = "com.not.my.vpn";
9559         assertThrows(SecurityException.class, () -> mVpnManagerService.stopVpnProfile(notMyVpnPkg));
9560     }
9561 
9562     @Test
9563     public void testUidUpdateChangesInterfaceFilteringRule() throws Exception {
9564         LinkProperties lp = new LinkProperties();
9565         lp.setInterfaceName("tun0");
9566         lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), RTN_UNREACHABLE));
9567         lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
9568         // The uid range needs to cover the test app so the network is visible to it.
9569         final UidRange vpnRange = PRIMARY_UIDRANGE;
9570         final Set<UidRange> vpnRanges = Collections.singleton(vpnRange);
9571         mMockVpn.establish(lp, VPN_UID, vpnRanges);
9572         assertVpnUidRangesUpdated(true, vpnRanges, VPN_UID);
9573 
9574         reset(mMockNetd);
9575         InOrder inOrder = inOrder(mMockNetd);
9576 
9577         // Update to new range which is old range minus APP1, i.e. only APP2
9578         final Set<UidRange> newRanges = new HashSet<>(Arrays.asList(
9579                 new UidRange(vpnRange.start, APP1_UID - 1),
9580                 new UidRange(APP1_UID + 1, vpnRange.stop)));
9581         mMockVpn.setUids(newRanges);
9582         waitForIdle();
9583 
9584         ArgumentCaptor<int[]> uidCaptor = ArgumentCaptor.forClass(int[].class);
9585         // Verify old rules are removed before new rules are added
9586         inOrder.verify(mMockNetd).firewallRemoveUidInterfaceRules(uidCaptor.capture());
9587         assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
9588         inOrder.verify(mMockNetd).firewallAddUidInterfaceRules(eq("tun0"), uidCaptor.capture());
9589         assertContainsExactly(uidCaptor.getValue(), APP2_UID);
9590     }
9591 
9592     @Test
9593     public void testLinkPropertiesWithWakeOnLanForActiveNetwork() throws Exception {
9594         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
9595 
9596         LinkProperties wifiLp = new LinkProperties();
9597         wifiLp.setInterfaceName(WIFI_WOL_IFNAME);
9598         wifiLp.setWakeOnLanSupported(false);
9599 
9600         // Default network switch should update ifaces.
9601         mWiFiNetworkAgent.connect(false);
9602         mWiFiNetworkAgent.sendLinkProperties(wifiLp);
9603         waitForIdle();
9604 
9605         // ConnectivityService should have changed the WakeOnLanSupported to true
9606         wifiLp.setWakeOnLanSupported(true);
9607         assertEquals(wifiLp, mService.getActiveLinkProperties());
9608     }
9609 
9610     @Test
9611     public void testLegacyExtraInfoSentToNetworkMonitor() throws Exception {
9612         class TestNetworkAgent extends NetworkAgent {
9613             TestNetworkAgent(Context context, Looper looper, NetworkAgentConfig config) {
9614                 super(context, looper, "MockAgent", new NetworkCapabilities(),
9615                         new LinkProperties(), 40 , config, null /* provider */);
9616             }
9617         }
9618         final NetworkAgent naNoExtraInfo = new TestNetworkAgent(
9619                 mServiceContext, mCsHandlerThread.getLooper(), new NetworkAgentConfig());
9620         naNoExtraInfo.register();
9621         verify(mNetworkStack).makeNetworkMonitor(any(), isNull(String.class), any());
9622         naNoExtraInfo.unregister();
9623 
9624         reset(mNetworkStack);
9625         final NetworkAgentConfig config =
9626                 new NetworkAgentConfig.Builder().setLegacyExtraInfo("legacyinfo").build();
9627         final NetworkAgent naExtraInfo = new TestNetworkAgent(
9628                 mServiceContext, mCsHandlerThread.getLooper(), config);
9629         naExtraInfo.register();
9630         verify(mNetworkStack).makeNetworkMonitor(any(), eq("legacyinfo"), any());
9631         naExtraInfo.unregister();
9632     }
9633 
9634     // To avoid granting location permission bypass.
9635     private void denyAllLocationPrivilegedPermissions() {
9636         mServiceContext.setPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
9637                 PERMISSION_DENIED);
9638         mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_DENIED);
9639         mServiceContext.setPermission(NETWORK_STACK, PERMISSION_DENIED);
9640         mServiceContext.setPermission(Manifest.permission.NETWORK_SETUP_WIZARD,
9641                 PERMISSION_DENIED);
9642     }
9643 
9644     private void setupLocationPermissions(
9645             int targetSdk, boolean locationToggle, String op, String perm) throws Exception {
9646         denyAllLocationPrivilegedPermissions();
9647 
9648         final ApplicationInfo applicationInfo = new ApplicationInfo();
9649         applicationInfo.targetSdkVersion = targetSdk;
9650         when(mPackageManager.getApplicationInfoAsUser(anyString(), anyInt(), any()))
9651                 .thenReturn(applicationInfo);
9652         when(mPackageManager.getTargetSdkVersion(any())).thenReturn(targetSdk);
9653 
9654         when(mLocationManager.isLocationEnabledForUser(any())).thenReturn(locationToggle);
9655 
9656         if (op != null) {
9657             when(mAppOpsManager.noteOp(eq(op), eq(Process.myUid()),
9658                     eq(mContext.getPackageName()), eq(getAttributionTag()), anyString()))
9659                 .thenReturn(AppOpsManager.MODE_ALLOWED);
9660         }
9661 
9662         if (perm != null) {
9663             mServiceContext.setPermission(perm, PERMISSION_GRANTED);
9664         }
9665     }
9666 
9667     private int getOwnerUidNetCapsPermission(int ownerUid, int callerUid,
9668             boolean includeLocationSensitiveInfo) {
9669         final NetworkCapabilities netCap = new NetworkCapabilities().setOwnerUid(ownerUid);
9670 
9671         return mService.createWithLocationInfoSanitizedIfNecessaryWhenParceled(
9672                 netCap, includeLocationSensitiveInfo, Process.myUid(), callerUid,
9673                 mContext.getPackageName(), getAttributionTag())
9674                 .getOwnerUid();
9675     }
9676 
9677     private void verifyTransportInfoCopyNetCapsPermission(
9678             int callerUid, boolean includeLocationSensitiveInfo,
9679             boolean shouldMakeCopyWithLocationSensitiveFieldsParcelable) {
9680         final TransportInfo transportInfo = mock(TransportInfo.class);
9681         when(transportInfo.getApplicableRedactions()).thenReturn(REDACT_FOR_ACCESS_FINE_LOCATION);
9682         final NetworkCapabilities netCap =
9683                 new NetworkCapabilities().setTransportInfo(transportInfo);
9684 
9685         mService.createWithLocationInfoSanitizedIfNecessaryWhenParceled(
9686                 netCap, includeLocationSensitiveInfo, Process.myPid(), callerUid,
9687                 mContext.getPackageName(), getAttributionTag());
9688         if (shouldMakeCopyWithLocationSensitiveFieldsParcelable) {
9689             verify(transportInfo).makeCopy(REDACT_NONE);
9690         } else {
9691             verify(transportInfo).makeCopy(REDACT_FOR_ACCESS_FINE_LOCATION);
9692         }
9693     }
9694 
9695     private void verifyOwnerUidAndTransportInfoNetCapsPermission(
9696             boolean shouldInclLocationSensitiveOwnerUidWithoutIncludeFlag,
9697             boolean shouldInclLocationSensitiveOwnerUidWithIncludeFlag,
9698             boolean shouldInclLocationSensitiveTransportInfoWithoutIncludeFlag,
9699             boolean shouldInclLocationSensitiveTransportInfoWithIncludeFlag) {
9700         final int myUid = Process.myUid();
9701 
9702         final int expectedOwnerUidWithoutIncludeFlag =
9703                 shouldInclLocationSensitiveOwnerUidWithoutIncludeFlag
9704                         ? myUid : INVALID_UID;
9705         assertEquals(expectedOwnerUidWithoutIncludeFlag, getOwnerUidNetCapsPermission(
9706                 myUid, myUid, false /* includeLocationSensitiveInfo */));
9707 
9708         final int expectedOwnerUidWithIncludeFlag =
9709                 shouldInclLocationSensitiveOwnerUidWithIncludeFlag ? myUid : INVALID_UID;
9710         assertEquals(expectedOwnerUidWithIncludeFlag, getOwnerUidNetCapsPermission(
9711                 myUid, myUid, true /* includeLocationSensitiveInfo */));
9712 
9713         verifyTransportInfoCopyNetCapsPermission(myUid,
9714                 false, /* includeLocationSensitiveInfo */
9715                 shouldInclLocationSensitiveTransportInfoWithoutIncludeFlag);
9716 
9717         verifyTransportInfoCopyNetCapsPermission(myUid,
9718                 true, /* includeLocationSensitiveInfo */
9719                 shouldInclLocationSensitiveTransportInfoWithIncludeFlag);
9720 
9721     }
9722 
9723     private void verifyOwnerUidAndTransportInfoNetCapsPermissionPreS() {
9724         verifyOwnerUidAndTransportInfoNetCapsPermission(
9725                 // Ensure that owner uid is included even if the request asks to remove it (which is
9726                 // the default) since the app has necessary permissions and targetSdk < S.
9727                 true, /* shouldInclLocationSensitiveOwnerUidWithoutIncludeFlag */
9728                 true, /* shouldInclLocationSensitiveOwnerUidWithIncludeFlag */
9729                 // Ensure that location info is removed if the request asks to remove it even if the
9730                 // app has necessary permissions.
9731                 false, /* shouldInclLocationSensitiveTransportInfoWithoutIncludeFlag */
9732                 true /* shouldInclLocationSensitiveTransportInfoWithIncludeFlag */
9733         );
9734     }
9735 
9736     @Test
9737     public void testCreateWithLocationInfoSanitizedWithFineLocationAfterQPreS()
9738             throws Exception {
9739         setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
9740                 Manifest.permission.ACCESS_FINE_LOCATION);
9741 
9742         verifyOwnerUidAndTransportInfoNetCapsPermissionPreS();
9743     }
9744 
9745     @Test
9746     public void testCreateWithLocationInfoSanitizedWithFineLocationPreSWithAndWithoutCallbackFlag()
9747             throws Exception {
9748         setupLocationPermissions(Build.VERSION_CODES.R, true, AppOpsManager.OPSTR_FINE_LOCATION,
9749                 Manifest.permission.ACCESS_FINE_LOCATION);
9750 
9751         verifyOwnerUidAndTransportInfoNetCapsPermissionPreS();
9752     }
9753 
9754     @Test
9755     public void
9756             testCreateWithLocationInfoSanitizedWithFineLocationAfterSWithAndWithoutCallbackFlag()
9757             throws Exception {
9758         setupLocationPermissions(Build.VERSION_CODES.S, true, AppOpsManager.OPSTR_FINE_LOCATION,
9759                 Manifest.permission.ACCESS_FINE_LOCATION);
9760 
9761         verifyOwnerUidAndTransportInfoNetCapsPermission(
9762                 // Ensure that the owner UID is removed if the request asks us to remove it even
9763                 // if the app has necessary permissions since targetSdk >= S.
9764                 false, /* shouldInclLocationSensitiveOwnerUidWithoutIncludeFlag */
9765                 true, /* shouldInclLocationSensitiveOwnerUidWithIncludeFlag */
9766                 // Ensure that location info is removed if the request asks to remove it even if the
9767                 // app has necessary permissions.
9768                 false, /* shouldInclLocationSensitiveTransportInfoWithoutIncludeFlag */
9769                 true /* shouldInclLocationSensitiveTransportInfoWithIncludeFlag */
9770         );
9771     }
9772 
9773     @Test
9774     public void testCreateWithLocationInfoSanitizedWithCoarseLocationPreQ()
9775             throws Exception {
9776         setupLocationPermissions(Build.VERSION_CODES.P, true, AppOpsManager.OPSTR_COARSE_LOCATION,
9777                 Manifest.permission.ACCESS_COARSE_LOCATION);
9778 
9779         verifyOwnerUidAndTransportInfoNetCapsPermissionPreS();
9780     }
9781 
9782     private void verifyOwnerUidAndTransportInfoNetCapsNotIncluded() {
9783         verifyOwnerUidAndTransportInfoNetCapsPermission(
9784                 false, /* shouldInclLocationSensitiveOwnerUidWithoutIncludeFlag */
9785                 false, /* shouldInclLocationSensitiveOwnerUidWithIncludeFlag */
9786                 false, /* shouldInclLocationSensitiveTransportInfoWithoutIncludeFlag */
9787                 false /* shouldInclLocationSensitiveTransportInfoWithIncludeFlag */
9788         );
9789     }
9790 
9791     @Test
9792     public void testCreateWithLocationInfoSanitizedLocationOff() throws Exception {
9793         // Test that even with fine location permission, and UIDs matching, the UID is sanitized.
9794         setupLocationPermissions(Build.VERSION_CODES.Q, false, AppOpsManager.OPSTR_FINE_LOCATION,
9795                 Manifest.permission.ACCESS_FINE_LOCATION);
9796 
9797         verifyOwnerUidAndTransportInfoNetCapsNotIncluded();
9798     }
9799 
9800     @Test
9801     public void testCreateWithLocationInfoSanitizedWrongUid() throws Exception {
9802         // Test that even with fine location permission, not being the owner leads to sanitization.
9803         setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
9804                 Manifest.permission.ACCESS_FINE_LOCATION);
9805 
9806         final int myUid = Process.myUid();
9807         assertEquals(Process.INVALID_UID,
9808                 getOwnerUidNetCapsPermission(myUid + 1, myUid,
9809                         true /* includeLocationSensitiveInfo */));
9810     }
9811 
9812     @Test
9813     public void testCreateWithLocationInfoSanitizedWithCoarseLocationAfterQ()
9814             throws Exception {
9815         // Test that not having fine location permission leads to sanitization.
9816         setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_COARSE_LOCATION,
9817                 Manifest.permission.ACCESS_COARSE_LOCATION);
9818 
9819         verifyOwnerUidAndTransportInfoNetCapsNotIncluded();
9820     }
9821 
9822     @Test
9823     public void testCreateWithLocationInfoSanitizedWithCoarseLocationAfterS()
9824             throws Exception {
9825         // Test that not having fine location permission leads to sanitization.
9826         setupLocationPermissions(Build.VERSION_CODES.S, true, AppOpsManager.OPSTR_COARSE_LOCATION,
9827                 Manifest.permission.ACCESS_COARSE_LOCATION);
9828 
9829         verifyOwnerUidAndTransportInfoNetCapsNotIncluded();
9830     }
9831 
9832     @Test
9833     public void testCreateForCallerWithLocalMacAddressSanitizedWithLocalMacAddressPermission()
9834             throws Exception {
9835         mServiceContext.setPermission(Manifest.permission.LOCAL_MAC_ADDRESS, PERMISSION_GRANTED);
9836 
9837         final TransportInfo transportInfo = mock(TransportInfo.class);
9838         when(transportInfo.getApplicableRedactions())
9839                 .thenReturn(REDACT_FOR_ACCESS_FINE_LOCATION | REDACT_FOR_LOCAL_MAC_ADDRESS);
9840         final NetworkCapabilities netCap =
9841                 new NetworkCapabilities().setTransportInfo(transportInfo);
9842 
9843         mService.createWithLocationInfoSanitizedIfNecessaryWhenParceled(
9844                 netCap, false /* includeLocationSensitiveInfoInTransportInfo */,
9845                 Process.myPid(), Process.myUid(),
9846                 mContext.getPackageName(), getAttributionTag());
9847         // don't redact MAC_ADDRESS fields, only location sensitive fields.
9848         verify(transportInfo).makeCopy(REDACT_FOR_ACCESS_FINE_LOCATION);
9849     }
9850 
9851     @Test
9852     public void testCreateForCallerWithLocalMacAddressSanitizedWithoutLocalMacAddressPermission()
9853             throws Exception {
9854         mServiceContext.setPermission(Manifest.permission.LOCAL_MAC_ADDRESS, PERMISSION_DENIED);
9855 
9856         final TransportInfo transportInfo = mock(TransportInfo.class);
9857         when(transportInfo.getApplicableRedactions())
9858                 .thenReturn(REDACT_FOR_ACCESS_FINE_LOCATION | REDACT_FOR_LOCAL_MAC_ADDRESS);
9859         final NetworkCapabilities netCap =
9860                 new NetworkCapabilities().setTransportInfo(transportInfo);
9861 
9862         mService.createWithLocationInfoSanitizedIfNecessaryWhenParceled(
9863                 netCap, false /* includeLocationSensitiveInfoInTransportInfo */,
9864                 Process.myPid(), Process.myUid(),
9865                 mContext.getPackageName(), getAttributionTag());
9866         // redact both MAC_ADDRESS & location sensitive fields.
9867         verify(transportInfo).makeCopy(REDACT_FOR_ACCESS_FINE_LOCATION
9868                 | REDACT_FOR_LOCAL_MAC_ADDRESS);
9869     }
9870 
9871     @Test
9872     public void testCreateForCallerWithLocalMacAddressSanitizedWithSettingsPermission()
9873             throws Exception {
9874         mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_GRANTED);
9875 
9876         final TransportInfo transportInfo = mock(TransportInfo.class);
9877         when(transportInfo.getApplicableRedactions())
9878                 .thenReturn(REDACT_FOR_ACCESS_FINE_LOCATION | REDACT_FOR_NETWORK_SETTINGS);
9879         final NetworkCapabilities netCap =
9880                 new NetworkCapabilities().setTransportInfo(transportInfo);
9881 
9882         mService.createWithLocationInfoSanitizedIfNecessaryWhenParceled(
9883                 netCap, false /* includeLocationSensitiveInfoInTransportInfo */,
9884                 Process.myPid(), Process.myUid(),
9885                 mContext.getPackageName(), getAttributionTag());
9886         // don't redact NETWORK_SETTINGS fields, only location sensitive fields.
9887         verify(transportInfo).makeCopy(REDACT_FOR_ACCESS_FINE_LOCATION);
9888     }
9889 
9890     @Test
9891     public void testCreateForCallerWithLocalMacAddressSanitizedWithoutSettingsPermission()
9892             throws Exception {
9893         mServiceContext.setPermission(Manifest.permission.LOCAL_MAC_ADDRESS, PERMISSION_DENIED);
9894 
9895         final TransportInfo transportInfo = mock(TransportInfo.class);
9896         when(transportInfo.getApplicableRedactions())
9897                 .thenReturn(REDACT_FOR_ACCESS_FINE_LOCATION | REDACT_FOR_NETWORK_SETTINGS);
9898         final NetworkCapabilities netCap =
9899                 new NetworkCapabilities().setTransportInfo(transportInfo);
9900 
9901         mService.createWithLocationInfoSanitizedIfNecessaryWhenParceled(
9902                 netCap, false /* includeLocationSensitiveInfoInTransportInfo */,
9903                 Process.myPid(), Process.myUid(),
9904                 mContext.getPackageName(), getAttributionTag());
9905         // redact both NETWORK_SETTINGS & location sensitive fields.
9906         verify(transportInfo).makeCopy(
9907                 REDACT_FOR_ACCESS_FINE_LOCATION | REDACT_FOR_NETWORK_SETTINGS);
9908     }
9909 
9910     /**
9911      * Test TransportInfo to verify redaction mechanism.
9912      */
9913     private static class TestTransportInfo implements TransportInfo {
9914         public final boolean locationRedacted;
9915         public final boolean localMacAddressRedacted;
9916         public final boolean settingsRedacted;
9917 
9918         TestTransportInfo() {
9919             locationRedacted = false;
9920             localMacAddressRedacted = false;
9921             settingsRedacted = false;
9922         }
9923 
9924         TestTransportInfo(boolean locationRedacted, boolean localMacAddressRedacted,
9925                 boolean settingsRedacted) {
9926             this.locationRedacted = locationRedacted;
9927             this.localMacAddressRedacted =
9928                     localMacAddressRedacted;
9929             this.settingsRedacted = settingsRedacted;
9930         }
9931 
9932         @Override
9933         public TransportInfo makeCopy(@NetworkCapabilities.RedactionType long redactions) {
9934             return new TestTransportInfo(
9935                     locationRedacted | (redactions & REDACT_FOR_ACCESS_FINE_LOCATION) != 0,
9936                     localMacAddressRedacted | (redactions & REDACT_FOR_LOCAL_MAC_ADDRESS) != 0,
9937                     settingsRedacted | (redactions & REDACT_FOR_NETWORK_SETTINGS) != 0
9938             );
9939         }
9940 
9941         @Override
9942         public @NetworkCapabilities.RedactionType long getApplicableRedactions() {
9943             return REDACT_FOR_ACCESS_FINE_LOCATION | REDACT_FOR_LOCAL_MAC_ADDRESS
9944                     | REDACT_FOR_NETWORK_SETTINGS;
9945         }
9946 
9947         @Override
9948         public boolean equals(Object other) {
9949             if (!(other instanceof TestTransportInfo)) return false;
9950             TestTransportInfo that = (TestTransportInfo) other;
9951             return that.locationRedacted == this.locationRedacted
9952                     && that.localMacAddressRedacted == this.localMacAddressRedacted
9953                     && that.settingsRedacted == this.settingsRedacted;
9954         }
9955 
9956         @Override
9957         public int hashCode() {
9958             return Objects.hash(locationRedacted, localMacAddressRedacted, settingsRedacted);
9959         }
9960 
9961         @Override
9962         public String toString() {
9963             return String.format(
9964                     "TestTransportInfo{locationRedacted=%s macRedacted=%s settingsRedacted=%s}",
9965                     locationRedacted, localMacAddressRedacted, settingsRedacted);
9966         }
9967     }
9968 
9969     private TestTransportInfo getTestTransportInfo(NetworkCapabilities nc) {
9970         return (TestTransportInfo) nc.getTransportInfo();
9971     }
9972 
9973     private TestTransportInfo getTestTransportInfo(TestNetworkAgentWrapper n) {
9974         final NetworkCapabilities nc = mCm.getNetworkCapabilities(n.getNetwork());
9975         assertNotNull(nc);
9976         return getTestTransportInfo(nc);
9977     }
9978 
9979 
9980     private void verifyNetworkCallbackLocationDataInclusionUsingTransportInfoAndOwnerUidInNetCaps(
9981             @NonNull TestNetworkCallback wifiNetworkCallback, int actualOwnerUid,
9982             @NonNull TransportInfo actualTransportInfo, int expectedOwnerUid,
9983             @NonNull TransportInfo expectedTransportInfo) throws Exception {
9984         when(mPackageManager.getTargetSdkVersion(anyString())).thenReturn(Build.VERSION_CODES.S);
9985         final NetworkCapabilities ncTemplate =
9986                 new NetworkCapabilities()
9987                         .addTransportType(TRANSPORT_WIFI)
9988                         .setOwnerUid(actualOwnerUid);
9989 
9990         final NetworkRequest wifiRequest = new NetworkRequest.Builder()
9991                 .addTransportType(TRANSPORT_WIFI).build();
9992         mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
9993 
9994         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, new LinkProperties(),
9995                 ncTemplate);
9996         mWiFiNetworkAgent.connect(false);
9997 
9998         wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
9999 
10000         // Send network capabilities update with TransportInfo to trigger capabilities changed
10001         // callback.
10002         mWiFiNetworkAgent.setNetworkCapabilities(
10003                 ncTemplate.setTransportInfo(actualTransportInfo), true);
10004 
10005         wifiNetworkCallback.expectCapabilitiesThat(mWiFiNetworkAgent,
10006                 nc -> Objects.equals(expectedOwnerUid, nc.getOwnerUid())
10007                         && Objects.equals(expectedTransportInfo, nc.getTransportInfo()));
10008     }
10009 
10010     @Test
10011     public void testVerifyLocationDataIsNotIncludedWhenInclFlagNotSet() throws Exception {
10012         final TestNetworkCallback wifiNetworkCallack = new TestNetworkCallback();
10013         final int ownerUid = Process.myUid();
10014         final TransportInfo transportInfo = new TestTransportInfo();
10015         // Even though the test uid holds privileged permissions, mask location fields since
10016         // the callback did not explicitly opt-in to get location data.
10017         final TransportInfo sanitizedTransportInfo = new TestTransportInfo(
10018                 true, /* locationRedacted */
10019                 true, /* localMacAddressRedacted */
10020                 true /* settingsRedacted */
10021         );
10022         // Should not expect location data since the callback does not set the flag for including
10023         // location data.
10024         verifyNetworkCallbackLocationDataInclusionUsingTransportInfoAndOwnerUidInNetCaps(
10025                 wifiNetworkCallack, ownerUid, transportInfo, INVALID_UID, sanitizedTransportInfo);
10026     }
10027 
10028     @Test
10029     public void testTransportInfoRedactionInSynchronousCalls() throws Exception {
10030         final NetworkCapabilities ncTemplate = new NetworkCapabilities()
10031                 .addTransportType(TRANSPORT_WIFI)
10032                 .setTransportInfo(new TestTransportInfo());
10033 
10034         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, new LinkProperties(),
10035                 ncTemplate);
10036         mWiFiNetworkAgent.connect(true /* validated; waits for callback */);
10037 
10038         // NETWORK_SETTINGS redaction is controlled by the NETWORK_SETTINGS permission
10039         assertTrue(getTestTransportInfo(mWiFiNetworkAgent).settingsRedacted);
10040         withPermission(NETWORK_SETTINGS, () -> {
10041             assertFalse(getTestTransportInfo(mWiFiNetworkAgent).settingsRedacted);
10042         });
10043         assertTrue(getTestTransportInfo(mWiFiNetworkAgent).settingsRedacted);
10044 
10045         // LOCAL_MAC_ADDRESS redaction is controlled by the LOCAL_MAC_ADDRESS permission
10046         assertTrue(getTestTransportInfo(mWiFiNetworkAgent).localMacAddressRedacted);
10047         withPermission(LOCAL_MAC_ADDRESS, () -> {
10048             assertFalse(getTestTransportInfo(mWiFiNetworkAgent).localMacAddressRedacted);
10049         });
10050         assertTrue(getTestTransportInfo(mWiFiNetworkAgent).localMacAddressRedacted);
10051 
10052         // Synchronous getNetworkCapabilities calls never return unredacted location-sensitive
10053         // information.
10054         assertTrue(getTestTransportInfo(mWiFiNetworkAgent).locationRedacted);
10055         setupLocationPermissions(Build.VERSION_CODES.S, true, AppOpsManager.OPSTR_FINE_LOCATION,
10056                 Manifest.permission.ACCESS_FINE_LOCATION);
10057         assertTrue(getTestTransportInfo(mWiFiNetworkAgent).locationRedacted);
10058         denyAllLocationPrivilegedPermissions();
10059         assertTrue(getTestTransportInfo(mWiFiNetworkAgent).locationRedacted);
10060     }
10061 
10062     private void setupConnectionOwnerUid(int vpnOwnerUid, @VpnManager.VpnType int vpnType)
10063             throws Exception {
10064         final Set<UidRange> vpnRange = Collections.singleton(PRIMARY_UIDRANGE);
10065         mMockVpn.setVpnType(vpnType);
10066         mMockVpn.establish(new LinkProperties(), vpnOwnerUid, vpnRange);
10067         assertVpnUidRangesUpdated(true, vpnRange, vpnOwnerUid);
10068 
10069         final UnderlyingNetworkInfo underlyingNetworkInfo =
10070                 new UnderlyingNetworkInfo(vpnOwnerUid, VPN_IFNAME, new ArrayList<String>());
10071         mMockVpn.setUnderlyingNetworkInfo(underlyingNetworkInfo);
10072         when(mDeps.getConnectionOwnerUid(anyInt(), any(), any())).thenReturn(42);
10073     }
10074 
10075     private void setupConnectionOwnerUidAsVpnApp(int vpnOwnerUid, @VpnManager.VpnType int vpnType)
10076             throws Exception {
10077         setupConnectionOwnerUid(vpnOwnerUid, vpnType);
10078 
10079         // Test as VPN app
10080         mServiceContext.setPermission(NETWORK_STACK, PERMISSION_DENIED);
10081         mServiceContext.setPermission(
10082                 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, PERMISSION_DENIED);
10083     }
10084 
10085     private ConnectionInfo getTestConnectionInfo() throws Exception {
10086         return new ConnectionInfo(
10087                 IPPROTO_TCP,
10088                 new InetSocketAddress(InetAddresses.parseNumericAddress("1.2.3.4"), 1234),
10089                 new InetSocketAddress(InetAddresses.parseNumericAddress("2.3.4.5"), 2345));
10090     }
10091 
10092     @Test
10093     public void testGetConnectionOwnerUidPlatformVpn() throws Exception {
10094         final int myUid = Process.myUid();
10095         setupConnectionOwnerUidAsVpnApp(myUid, VpnManager.TYPE_VPN_PLATFORM);
10096 
10097         assertEquals(INVALID_UID, mService.getConnectionOwnerUid(getTestConnectionInfo()));
10098     }
10099 
10100     @Test
10101     public void testGetConnectionOwnerUidVpnServiceWrongUser() throws Exception {
10102         final int myUid = Process.myUid();
10103         setupConnectionOwnerUidAsVpnApp(myUid + 1, VpnManager.TYPE_VPN_SERVICE);
10104 
10105         assertEquals(INVALID_UID, mService.getConnectionOwnerUid(getTestConnectionInfo()));
10106     }
10107 
10108     @Test
10109     public void testGetConnectionOwnerUidVpnServiceDoesNotThrow() throws Exception {
10110         final int myUid = Process.myUid();
10111         setupConnectionOwnerUidAsVpnApp(myUid, VpnManager.TYPE_VPN_SERVICE);
10112 
10113         assertEquals(42, mService.getConnectionOwnerUid(getTestConnectionInfo()));
10114     }
10115 
10116     @Test
10117     public void testGetConnectionOwnerUidVpnServiceNetworkStackDoesNotThrow() throws Exception {
10118         final int myUid = Process.myUid();
10119         setupConnectionOwnerUid(myUid, VpnManager.TYPE_VPN_SERVICE);
10120         mServiceContext.setPermission(NETWORK_STACK, PERMISSION_GRANTED);
10121 
10122         assertEquals(42, mService.getConnectionOwnerUid(getTestConnectionInfo()));
10123     }
10124 
10125     @Test
10126     public void testGetConnectionOwnerUidVpnServiceMainlineNetworkStackDoesNotThrow()
10127             throws Exception {
10128         final int myUid = Process.myUid();
10129         setupConnectionOwnerUid(myUid, VpnManager.TYPE_VPN_SERVICE);
10130         mServiceContext.setPermission(
10131                 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, PERMISSION_GRANTED);
10132 
10133         assertEquals(42, mService.getConnectionOwnerUid(getTestConnectionInfo()));
10134     }
10135 
10136     private static PackageInfo buildPackageInfo(boolean hasSystemPermission, int uid) {
10137         final PackageInfo packageInfo = new PackageInfo();
10138         if (hasSystemPermission) {
10139             packageInfo.requestedPermissions = new String[] {
10140                     CHANGE_NETWORK_STATE, CONNECTIVITY_USE_RESTRICTED_NETWORKS };
10141             packageInfo.requestedPermissionsFlags = new int[] {
10142                     REQUESTED_PERMISSION_GRANTED, REQUESTED_PERMISSION_GRANTED };
10143         } else {
10144             packageInfo.requestedPermissions = new String[0];
10145         }
10146         packageInfo.applicationInfo = new ApplicationInfo();
10147         packageInfo.applicationInfo.privateFlags = 0;
10148         packageInfo.applicationInfo.uid = UserHandle.getUid(UserHandle.USER_SYSTEM,
10149                 UserHandle.getAppId(uid));
10150         return packageInfo;
10151     }
10152 
10153     @Test
10154     public void testRegisterConnectivityDiagnosticsCallbackInvalidRequest() throws Exception {
10155         final NetworkRequest request =
10156                 new NetworkRequest(
10157                         new NetworkCapabilities(), TYPE_ETHERNET, 0, NetworkRequest.Type.NONE);
10158         try {
10159             mService.registerConnectivityDiagnosticsCallback(
10160                     mConnectivityDiagnosticsCallback, request, mContext.getPackageName());
10161             fail("registerConnectivityDiagnosticsCallback should throw on invalid NetworkRequest");
10162         } catch (IllegalArgumentException expected) {
10163         }
10164     }
10165 
10166     private void assertRouteInfoParcelMatches(RouteInfo route, RouteInfoParcel parcel) {
10167         assertEquals(route.getDestination().toString(), parcel.destination);
10168         assertEquals(route.getInterface(), parcel.ifName);
10169         assertEquals(route.getMtu(), parcel.mtu);
10170 
10171         switch (route.getType()) {
10172             case RouteInfo.RTN_UNICAST:
10173                 if (route.hasGateway()) {
10174                     assertEquals(route.getGateway().getHostAddress(), parcel.nextHop);
10175                 } else {
10176                     assertEquals(INetd.NEXTHOP_NONE, parcel.nextHop);
10177                 }
10178                 break;
10179             case RouteInfo.RTN_UNREACHABLE:
10180                 assertEquals(INetd.NEXTHOP_UNREACHABLE, parcel.nextHop);
10181                 break;
10182             case RouteInfo.RTN_THROW:
10183                 assertEquals(INetd.NEXTHOP_THROW, parcel.nextHop);
10184                 break;
10185             default:
10186                 assertEquals(INetd.NEXTHOP_NONE, parcel.nextHop);
10187                 break;
10188         }
10189     }
10190 
10191     private void assertRoutesAdded(int netId, RouteInfo... routes) throws Exception {
10192         // TODO: add @JavaDerive(equals=true) to RouteInfoParcel, use eq() directly, and delete
10193         // assertRouteInfoParcelMatches above.
10194         ArgumentCaptor<RouteInfoParcel> captor = ArgumentCaptor.forClass(RouteInfoParcel.class);
10195         verify(mMockNetd, times(routes.length)).networkAddRouteParcel(eq(netId), captor.capture());
10196         for (int i = 0; i < routes.length; i++) {
10197             assertRouteInfoParcelMatches(routes[i], captor.getAllValues().get(i));
10198         }
10199     }
10200 
10201     private void assertRoutesRemoved(int netId, RouteInfo... routes) throws Exception {
10202         ArgumentCaptor<RouteInfoParcel> captor = ArgumentCaptor.forClass(RouteInfoParcel.class);
10203         verify(mMockNetd, times(routes.length)).networkRemoveRouteParcel(eq(netId),
10204                 captor.capture());
10205         for (int i = 0; i < routes.length; i++) {
10206             assertRouteInfoParcelMatches(routes[i], captor.getAllValues().get(i));
10207         }
10208     }
10209 
10210     @Test
10211     public void testRegisterUnregisterConnectivityDiagnosticsCallback() throws Exception {
10212         final NetworkRequest wifiRequest =
10213                 new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI).build();
10214         when(mConnectivityDiagnosticsCallback.asBinder()).thenReturn(mIBinder);
10215 
10216         mService.registerConnectivityDiagnosticsCallback(
10217                 mConnectivityDiagnosticsCallback, wifiRequest, mContext.getPackageName());
10218 
10219         // Block until all other events are done processing.
10220         HandlerUtils.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
10221 
10222         verify(mIBinder).linkToDeath(any(ConnectivityDiagnosticsCallbackInfo.class), anyInt());
10223         verify(mConnectivityDiagnosticsCallback).asBinder();
10224         assertTrue(mService.mConnectivityDiagnosticsCallbacks.containsKey(mIBinder));
10225 
10226         mService.unregisterConnectivityDiagnosticsCallback(mConnectivityDiagnosticsCallback);
10227         verify(mIBinder, timeout(TIMEOUT_MS))
10228                 .unlinkToDeath(any(ConnectivityDiagnosticsCallbackInfo.class), anyInt());
10229         assertFalse(mService.mConnectivityDiagnosticsCallbacks.containsKey(mIBinder));
10230         verify(mConnectivityDiagnosticsCallback, atLeastOnce()).asBinder();
10231     }
10232 
10233     @Test
10234     public void testRegisterDuplicateConnectivityDiagnosticsCallback() throws Exception {
10235         final NetworkRequest wifiRequest =
10236                 new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI).build();
10237         when(mConnectivityDiagnosticsCallback.asBinder()).thenReturn(mIBinder);
10238 
10239         mService.registerConnectivityDiagnosticsCallback(
10240                 mConnectivityDiagnosticsCallback, wifiRequest, mContext.getPackageName());
10241 
10242         // Block until all other events are done processing.
10243         HandlerUtils.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
10244 
10245         verify(mIBinder).linkToDeath(any(ConnectivityDiagnosticsCallbackInfo.class), anyInt());
10246         verify(mConnectivityDiagnosticsCallback).asBinder();
10247         assertTrue(mService.mConnectivityDiagnosticsCallbacks.containsKey(mIBinder));
10248 
10249         // Register the same callback again
10250         mService.registerConnectivityDiagnosticsCallback(
10251                 mConnectivityDiagnosticsCallback, wifiRequest, mContext.getPackageName());
10252 
10253         // Block until all other events are done processing.
10254         HandlerUtils.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
10255 
10256         assertTrue(mService.mConnectivityDiagnosticsCallbacks.containsKey(mIBinder));
10257     }
10258 
10259     public NetworkAgentInfo fakeMobileNai(NetworkCapabilities nc) {
10260         final NetworkCapabilities cellNc = new NetworkCapabilities.Builder(nc)
10261                 .addTransportType(TRANSPORT_CELLULAR).build();
10262         final NetworkInfo info = new NetworkInfo(TYPE_MOBILE, TelephonyManager.NETWORK_TYPE_LTE,
10263                 ConnectivityManager.getNetworkTypeName(TYPE_MOBILE),
10264                 TelephonyManager.getNetworkTypeName(TelephonyManager.NETWORK_TYPE_LTE));
10265         return fakeNai(cellNc, info);
10266     }
10267 
10268     private NetworkAgentInfo fakeWifiNai(NetworkCapabilities nc) {
10269         final NetworkCapabilities wifiNc = new NetworkCapabilities.Builder(nc)
10270                 .addTransportType(TRANSPORT_WIFI).build();
10271         final NetworkInfo info = new NetworkInfo(TYPE_WIFI, 0 /* subtype */,
10272                 ConnectivityManager.getNetworkTypeName(TYPE_WIFI), "" /* subtypeName */);
10273         return fakeNai(wifiNc, info);
10274     }
10275 
10276     private NetworkAgentInfo fakeNai(NetworkCapabilities nc, NetworkInfo networkInfo) {
10277         return new NetworkAgentInfo(null, new Network(NET_ID), networkInfo, new LinkProperties(),
10278                 nc, new NetworkScore.Builder().setLegacyInt(0).build(),
10279                 mServiceContext, null, new NetworkAgentConfig(), mService, null, null, 0,
10280                 INVALID_UID, TEST_LINGER_DELAY_MS, mQosCallbackTracker,
10281                 new ConnectivityService.Dependencies());
10282     }
10283 
10284     @Test
10285     public void testCheckConnectivityDiagnosticsPermissionsNetworkStack() throws Exception {
10286         final NetworkAgentInfo naiWithoutUid = fakeMobileNai(new NetworkCapabilities());
10287 
10288         mServiceContext.setPermission(NETWORK_STACK, PERMISSION_GRANTED);
10289         assertTrue(
10290                 "NetworkStack permission not applied",
10291                 mService.checkConnectivityDiagnosticsPermissions(
10292                         Process.myPid(), Process.myUid(), naiWithoutUid,
10293                         mContext.getOpPackageName()));
10294     }
10295 
10296     @Test
10297     public void testCheckConnectivityDiagnosticsPermissionsWrongUidPackageName() throws Exception {
10298         final int wrongUid = Process.myUid() + 1;
10299 
10300         final NetworkCapabilities nc = new NetworkCapabilities();
10301         nc.setAdministratorUids(new int[] {wrongUid});
10302         final NetworkAgentInfo naiWithUid = fakeWifiNai(nc);
10303 
10304         mServiceContext.setPermission(NETWORK_STACK, PERMISSION_DENIED);
10305 
10306         assertFalse(
10307                 "Mismatched uid/package name should not pass the location permission check",
10308                 mService.checkConnectivityDiagnosticsPermissions(
10309                         Process.myPid() + 1, wrongUid, naiWithUid, mContext.getOpPackageName()));
10310     }
10311 
10312     private void verifyConnectivityDiagnosticsPermissionsWithNetworkAgentInfo(
10313             NetworkAgentInfo info, boolean expectPermission) {
10314         mServiceContext.setPermission(NETWORK_STACK, PERMISSION_DENIED);
10315 
10316         assertEquals(
10317                 "Unexpected ConnDiags permission",
10318                 expectPermission,
10319                 mService.checkConnectivityDiagnosticsPermissions(
10320                         Process.myPid(), Process.myUid(), info, mContext.getOpPackageName()));
10321     }
10322 
10323     @Test
10324     public void testCheckConnectivityDiagnosticsPermissionsCellularNoLocationPermission()
10325             throws Exception {
10326         final NetworkCapabilities nc = new NetworkCapabilities();
10327         nc.setAdministratorUids(new int[] {Process.myUid()});
10328         final NetworkAgentInfo naiWithUid = fakeMobileNai(nc);
10329 
10330         verifyConnectivityDiagnosticsPermissionsWithNetworkAgentInfo(naiWithUid,
10331                 true /* expectPermission */);
10332     }
10333 
10334     @Test
10335     public void testCheckConnectivityDiagnosticsPermissionsWifiNoLocationPermission()
10336             throws Exception {
10337         final NetworkCapabilities nc = new NetworkCapabilities();
10338         nc.setAdministratorUids(new int[] {Process.myUid()});
10339         final NetworkAgentInfo naiWithUid = fakeWifiNai(nc);
10340 
10341         verifyConnectivityDiagnosticsPermissionsWithNetworkAgentInfo(naiWithUid,
10342                 false /* expectPermission */);
10343     }
10344 
10345     @Test
10346     public void testCheckConnectivityDiagnosticsPermissionsActiveVpn() throws Exception {
10347         final NetworkAgentInfo naiWithoutUid = fakeMobileNai(new NetworkCapabilities());
10348 
10349         mMockVpn.establishForMyUid();
10350         assertUidRangesUpdatedForMyUid(true);
10351 
10352         // Wait for networks to connect and broadcasts to be sent before removing permissions.
10353         waitForIdle();
10354         setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
10355                 Manifest.permission.ACCESS_FINE_LOCATION);
10356 
10357         assertTrue(mMockVpn.setUnderlyingNetworks(new Network[] {naiWithoutUid.network}));
10358         waitForIdle();
10359         assertTrue(
10360                 "Active VPN permission not applied",
10361                 mService.checkConnectivityDiagnosticsPermissions(
10362                         Process.myPid(), Process.myUid(), naiWithoutUid,
10363                         mContext.getOpPackageName()));
10364 
10365         assertTrue(mMockVpn.setUnderlyingNetworks(null));
10366         waitForIdle();
10367         assertFalse(
10368                 "VPN shouldn't receive callback on non-underlying network",
10369                 mService.checkConnectivityDiagnosticsPermissions(
10370                         Process.myPid(), Process.myUid(), naiWithoutUid,
10371                         mContext.getOpPackageName()));
10372     }
10373 
10374     @Test
10375     public void testCheckConnectivityDiagnosticsPermissionsNetworkAdministrator() throws Exception {
10376         final NetworkCapabilities nc = new NetworkCapabilities();
10377         nc.setAdministratorUids(new int[] {Process.myUid()});
10378         final NetworkAgentInfo naiWithUid = fakeMobileNai(nc);
10379 
10380         setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
10381                 Manifest.permission.ACCESS_FINE_LOCATION);
10382         mServiceContext.setPermission(NETWORK_STACK, PERMISSION_DENIED);
10383 
10384         assertTrue(
10385                 "NetworkCapabilities administrator uid permission not applied",
10386                 mService.checkConnectivityDiagnosticsPermissions(
10387                         Process.myPid(), Process.myUid(), naiWithUid, mContext.getOpPackageName()));
10388     }
10389 
10390     @Test
10391     public void testCheckConnectivityDiagnosticsPermissionsFails() throws Exception {
10392         final NetworkCapabilities nc = new NetworkCapabilities();
10393         nc.setOwnerUid(Process.myUid());
10394         nc.setAdministratorUids(new int[] {Process.myUid()});
10395         final NetworkAgentInfo naiWithUid = fakeMobileNai(nc);
10396 
10397         setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
10398                 Manifest.permission.ACCESS_FINE_LOCATION);
10399         mServiceContext.setPermission(NETWORK_STACK, PERMISSION_DENIED);
10400 
10401         // Use wrong pid and uid
10402         assertFalse(
10403                 "Permissions allowed when they shouldn't be granted",
10404                 mService.checkConnectivityDiagnosticsPermissions(
10405                         Process.myPid() + 1, Process.myUid() + 1, naiWithUid,
10406                         mContext.getOpPackageName()));
10407     }
10408 
10409     @Test
10410     public void testRegisterConnectivityDiagnosticsCallbackCallsOnConnectivityReport()
10411             throws Exception {
10412         // Set up the Network, which leads to a ConnectivityReport being cached for the network.
10413         final TestNetworkCallback callback = new TestNetworkCallback();
10414         mCm.registerDefaultNetworkCallback(callback);
10415         final LinkProperties linkProperties = new LinkProperties();
10416         linkProperties.setInterfaceName(INTERFACE_NAME);
10417         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, linkProperties);
10418         mCellNetworkAgent.connect(true);
10419         callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
10420         callback.assertNoCallback();
10421 
10422         final NetworkRequest request = new NetworkRequest.Builder().build();
10423         when(mConnectivityDiagnosticsCallback.asBinder()).thenReturn(mIBinder);
10424 
10425         mServiceContext.setPermission(NETWORK_STACK, PERMISSION_GRANTED);
10426 
10427         mService.registerConnectivityDiagnosticsCallback(
10428                 mConnectivityDiagnosticsCallback, request, mContext.getPackageName());
10429 
10430         // Block until all other events are done processing.
10431         HandlerUtils.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
10432 
10433         verify(mConnectivityDiagnosticsCallback)
10434                 .onConnectivityReportAvailable(argThat(report -> {
10435                     return INTERFACE_NAME.equals(report.getLinkProperties().getInterfaceName())
10436                             && report.getNetworkCapabilities().hasTransport(TRANSPORT_CELLULAR);
10437                 }));
10438     }
10439 
10440     private void setUpConnectivityDiagnosticsCallback() throws Exception {
10441         final NetworkRequest request = new NetworkRequest.Builder().build();
10442         when(mConnectivityDiagnosticsCallback.asBinder()).thenReturn(mIBinder);
10443 
10444         mServiceContext.setPermission(NETWORK_STACK, PERMISSION_GRANTED);
10445 
10446         mService.registerConnectivityDiagnosticsCallback(
10447                 mConnectivityDiagnosticsCallback, request, mContext.getPackageName());
10448 
10449         // Block until all other events are done processing.
10450         HandlerUtils.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
10451 
10452         // Connect the cell agent verify that it notifies TestNetworkCallback that it is available
10453         final TestNetworkCallback callback = new TestNetworkCallback();
10454         mCm.registerDefaultNetworkCallback(callback);
10455 
10456         final NetworkCapabilities ncTemplate = new NetworkCapabilities()
10457                 .addTransportType(TRANSPORT_CELLULAR)
10458                 .setTransportInfo(new TestTransportInfo());
10459         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, new LinkProperties(),
10460                 ncTemplate);
10461         mCellNetworkAgent.connect(true);
10462         callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
10463         callback.assertNoCallback();
10464     }
10465 
10466     private boolean areConnDiagCapsRedacted(NetworkCapabilities nc) {
10467         TestTransportInfo ti = (TestTransportInfo) nc.getTransportInfo();
10468         return nc.getUids() == null
10469                 && nc.getAdministratorUids().length == 0
10470                 && nc.getOwnerUid() == Process.INVALID_UID
10471                 && getTestTransportInfo(nc).locationRedacted
10472                 && getTestTransportInfo(nc).localMacAddressRedacted
10473                 && getTestTransportInfo(nc).settingsRedacted;
10474     }
10475 
10476     @Test
10477     public void testConnectivityDiagnosticsCallbackOnConnectivityReportAvailable()
10478             throws Exception {
10479         setUpConnectivityDiagnosticsCallback();
10480 
10481         // Block until all other events are done processing.
10482         HandlerUtils.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
10483 
10484         // Verify onConnectivityReport fired
10485         verify(mConnectivityDiagnosticsCallback).onConnectivityReportAvailable(
10486                 argThat(report -> areConnDiagCapsRedacted(report.getNetworkCapabilities())));
10487     }
10488 
10489     @Test
10490     public void testConnectivityDiagnosticsCallbackOnDataStallSuspected() throws Exception {
10491         setUpConnectivityDiagnosticsCallback();
10492 
10493         // Trigger notifyDataStallSuspected() on the INetworkMonitorCallbacks instance in the
10494         // cellular network agent
10495         mCellNetworkAgent.notifyDataStallSuspected();
10496 
10497         // Block until all other events are done processing.
10498         HandlerUtils.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
10499 
10500         // Verify onDataStallSuspected fired
10501         verify(mConnectivityDiagnosticsCallback).onDataStallSuspected(
10502                 argThat(report -> areConnDiagCapsRedacted(report.getNetworkCapabilities())));
10503     }
10504 
10505     @Test
10506     public void testConnectivityDiagnosticsCallbackOnConnectivityReported() throws Exception {
10507         setUpConnectivityDiagnosticsCallback();
10508 
10509         final Network n = mCellNetworkAgent.getNetwork();
10510         final boolean hasConnectivity = true;
10511         mService.reportNetworkConnectivity(n, hasConnectivity);
10512 
10513         // Block until all other events are done processing.
10514         HandlerUtils.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
10515 
10516         // Verify onNetworkConnectivityReported fired
10517         verify(mConnectivityDiagnosticsCallback)
10518                 .onNetworkConnectivityReported(eq(n), eq(hasConnectivity));
10519 
10520         final boolean noConnectivity = false;
10521         mService.reportNetworkConnectivity(n, noConnectivity);
10522 
10523         // Block until all other events are done processing.
10524         HandlerUtils.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
10525 
10526         // Wait for onNetworkConnectivityReported to fire
10527         verify(mConnectivityDiagnosticsCallback)
10528                 .onNetworkConnectivityReported(eq(n), eq(noConnectivity));
10529     }
10530 
10531     @Test
10532     public void testRouteAddDeleteUpdate() throws Exception {
10533         final NetworkRequest request = new NetworkRequest.Builder().build();
10534         final TestNetworkCallback networkCallback = new TestNetworkCallback();
10535         mCm.registerNetworkCallback(request, networkCallback);
10536         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
10537         reset(mMockNetd);
10538         mCellNetworkAgent.connect(false);
10539         networkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
10540         final int netId = mCellNetworkAgent.getNetwork().netId;
10541 
10542         final String iface = "rmnet_data0";
10543         final InetAddress gateway = InetAddress.getByName("fe80::5678");
10544         RouteInfo direct = RouteInfo.makeHostRoute(gateway, iface);
10545         RouteInfo rio1 = new RouteInfo(new IpPrefix("2001:db8:1::/48"), gateway, iface);
10546         RouteInfo rio2 = new RouteInfo(new IpPrefix("2001:db8:2::/48"), gateway, iface);
10547         RouteInfo defaultRoute = new RouteInfo((IpPrefix) null, gateway, iface);
10548         RouteInfo defaultWithMtu = new RouteInfo(null, gateway, iface, RouteInfo.RTN_UNICAST,
10549                                                  1280 /* mtu */);
10550 
10551         // Send LinkProperties and check that we ask netd to add routes.
10552         LinkProperties lp = new LinkProperties();
10553         lp.setInterfaceName(iface);
10554         lp.addRoute(direct);
10555         lp.addRoute(rio1);
10556         lp.addRoute(defaultRoute);
10557         mCellNetworkAgent.sendLinkProperties(lp);
10558         networkCallback.expectLinkPropertiesThat(mCellNetworkAgent, x -> x.getRoutes().size() == 3);
10559 
10560         assertRoutesAdded(netId, direct, rio1, defaultRoute);
10561         reset(mMockNetd);
10562 
10563         // Send updated LinkProperties and check that we ask netd to add, remove, update routes.
10564         assertTrue(lp.getRoutes().contains(defaultRoute));
10565         lp.removeRoute(rio1);
10566         lp.addRoute(rio2);
10567         lp.addRoute(defaultWithMtu);
10568         // Ensure adding the same route with a different MTU replaces the previous route.
10569         assertFalse(lp.getRoutes().contains(defaultRoute));
10570         assertTrue(lp.getRoutes().contains(defaultWithMtu));
10571 
10572         mCellNetworkAgent.sendLinkProperties(lp);
10573         networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
10574                 x -> x.getRoutes().contains(rio2));
10575 
10576         assertRoutesRemoved(netId, rio1);
10577         assertRoutesAdded(netId, rio2);
10578 
10579         ArgumentCaptor<RouteInfoParcel> captor = ArgumentCaptor.forClass(RouteInfoParcel.class);
10580         verify(mMockNetd).networkUpdateRouteParcel(eq(netId), captor.capture());
10581         assertRouteInfoParcelMatches(defaultWithMtu, captor.getValue());
10582 
10583 
10584         mCm.unregisterNetworkCallback(networkCallback);
10585     }
10586 
10587     @Test
10588     public void testDumpDoesNotCrash() {
10589         mServiceContext.setPermission(DUMP, PERMISSION_GRANTED);
10590         // Filing a couple requests prior to testing the dump.
10591         final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback();
10592         final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
10593         final NetworkRequest genericRequest = new NetworkRequest.Builder()
10594                 .clearCapabilities().build();
10595         final NetworkRequest wifiRequest = new NetworkRequest.Builder()
10596                 .addTransportType(TRANSPORT_WIFI).build();
10597         mCm.registerNetworkCallback(genericRequest, genericNetworkCallback);
10598         mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
10599         final StringWriter stringWriter = new StringWriter();
10600 
10601         mService.dump(new FileDescriptor(), new PrintWriter(stringWriter), new String[0]);
10602 
10603         assertFalse(stringWriter.toString().isEmpty());
10604     }
10605 
10606     @Test
10607     public void testRequestsSortedByIdSortsCorrectly() {
10608         final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback();
10609         final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
10610         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
10611         final NetworkRequest genericRequest = new NetworkRequest.Builder()
10612                 .clearCapabilities().build();
10613         final NetworkRequest wifiRequest = new NetworkRequest.Builder()
10614                 .addTransportType(TRANSPORT_WIFI).build();
10615         final NetworkRequest cellRequest = new NetworkRequest.Builder()
10616                 .addTransportType(TRANSPORT_CELLULAR).build();
10617         mCm.registerNetworkCallback(genericRequest, genericNetworkCallback);
10618         mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
10619         mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
10620         waitForIdle();
10621 
10622         final NetworkRequestInfo[] nriOutput = mService.requestsSortedById();
10623 
10624         assertTrue(nriOutput.length > 1);
10625         for (int i = 0; i < nriOutput.length - 1; i++) {
10626             final boolean isRequestIdInOrder =
10627                     nriOutput[i].mRequests.get(0).requestId
10628                             < nriOutput[i + 1].mRequests.get(0).requestId;
10629             assertTrue(isRequestIdInOrder);
10630         }
10631     }
10632 
10633     private void assertUidRangesUpdatedForMyUid(boolean add) throws Exception {
10634         final int uid = Process.myUid();
10635         assertVpnUidRangesUpdated(add, uidRangesForUids(uid), uid);
10636     }
10637 
10638     private void assertVpnUidRangesUpdated(boolean add, Set<UidRange> vpnRanges, int exemptUid)
10639             throws Exception {
10640         InOrder inOrder = inOrder(mMockNetd);
10641         ArgumentCaptor<int[]> exemptUidCaptor = ArgumentCaptor.forClass(int[].class);
10642 
10643         inOrder.verify(mMockNetd, times(1)).socketDestroy(eq(toUidRangeStableParcels(vpnRanges)),
10644                 exemptUidCaptor.capture());
10645         assertContainsExactly(exemptUidCaptor.getValue(), Process.VPN_UID, exemptUid);
10646 
10647         if (add) {
10648             inOrder.verify(mMockNetd, times(1)).networkAddUidRangesParcel(
10649                     new NativeUidRangeConfig(mMockVpn.getNetwork().getNetId(),
10650                             toUidRangeStableParcels(vpnRanges), PREFERENCE_PRIORITY_VPN));
10651         } else {
10652             inOrder.verify(mMockNetd, times(1)).networkRemoveUidRangesParcel(
10653                     new NativeUidRangeConfig(mMockVpn.getNetwork().getNetId(),
10654                             toUidRangeStableParcels(vpnRanges), PREFERENCE_PRIORITY_VPN));
10655         }
10656 
10657         inOrder.verify(mMockNetd, times(1)).socketDestroy(eq(toUidRangeStableParcels(vpnRanges)),
10658                 exemptUidCaptor.capture());
10659         assertContainsExactly(exemptUidCaptor.getValue(), Process.VPN_UID, exemptUid);
10660     }
10661 
10662     @Test
10663     public void testVpnUidRangesUpdate() throws Exception {
10664         // Set up a WiFi network without proxy.
10665         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
10666         mWiFiNetworkAgent.connect(true);
10667         assertNull(mService.getProxyForNetwork(null));
10668         assertNull(mCm.getDefaultProxy());
10669 
10670         final LinkProperties lp = new LinkProperties();
10671         lp.setInterfaceName("tun0");
10672         lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
10673         lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
10674         final UidRange vpnRange = PRIMARY_UIDRANGE;
10675         final Set<UidRange> vpnRanges = Collections.singleton(vpnRange);
10676         mMockVpn.establish(lp, VPN_UID, vpnRanges);
10677         assertVpnUidRangesUpdated(true, vpnRanges, VPN_UID);
10678         // VPN is connected but proxy is not set, so there is no need to send proxy broadcast.
10679         verify(mProxyTracker, never()).sendProxyBroadcast();
10680 
10681         // Update to new range which is old range minus APP1, i.e. only APP2
10682         final Set<UidRange> newRanges = new HashSet<>(Arrays.asList(
10683                 new UidRange(vpnRange.start, APP1_UID - 1),
10684                 new UidRange(APP1_UID + 1, vpnRange.stop)));
10685         mMockVpn.setUids(newRanges);
10686         waitForIdle();
10687 
10688         assertVpnUidRangesUpdated(true, newRanges, VPN_UID);
10689         assertVpnUidRangesUpdated(false, vpnRanges, VPN_UID);
10690 
10691         // Uid has changed but proxy is not set, so there is no need to send proxy broadcast.
10692         verify(mProxyTracker, never()).sendProxyBroadcast();
10693 
10694         final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
10695         lp.setHttpProxy(testProxyInfo);
10696         mMockVpn.sendLinkProperties(lp);
10697         waitForIdle();
10698         // Proxy is set, so send a proxy broadcast.
10699         verify(mProxyTracker, times(1)).sendProxyBroadcast();
10700         reset(mProxyTracker);
10701 
10702         mMockVpn.setUids(vpnRanges);
10703         waitForIdle();
10704         // Uid has changed and proxy is already set, so send a proxy broadcast.
10705         verify(mProxyTracker, times(1)).sendProxyBroadcast();
10706         reset(mProxyTracker);
10707 
10708         // Proxy is removed, send a proxy broadcast.
10709         lp.setHttpProxy(null);
10710         mMockVpn.sendLinkProperties(lp);
10711         waitForIdle();
10712         verify(mProxyTracker, times(1)).sendProxyBroadcast();
10713         reset(mProxyTracker);
10714 
10715         // Proxy is added in WiFi(default network), setDefaultProxy will be called.
10716         final LinkProperties wifiLp = mCm.getLinkProperties(mWiFiNetworkAgent.getNetwork());
10717         assertNotNull(wifiLp);
10718         wifiLp.setHttpProxy(testProxyInfo);
10719         mWiFiNetworkAgent.sendLinkProperties(wifiLp);
10720         waitForIdle();
10721         verify(mProxyTracker, times(1)).setDefaultProxy(eq(testProxyInfo));
10722         reset(mProxyTracker);
10723     }
10724 
10725     @Test
10726     public void testProxyBroadcastWillBeSentWhenVpnHasProxyAndConnects() throws Exception {
10727         // Set up a WiFi network without proxy.
10728         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
10729         mWiFiNetworkAgent.connect(true);
10730         assertNull(mService.getProxyForNetwork(null));
10731         assertNull(mCm.getDefaultProxy());
10732 
10733         final LinkProperties lp = new LinkProperties();
10734         lp.setInterfaceName("tun0");
10735         lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
10736         lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
10737         final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
10738         lp.setHttpProxy(testProxyInfo);
10739         final UidRange vpnRange = PRIMARY_UIDRANGE;
10740         final Set<UidRange> vpnRanges = Collections.singleton(vpnRange);
10741         mMockVpn.setOwnerAndAdminUid(VPN_UID);
10742         mMockVpn.registerAgent(false, vpnRanges, lp);
10743         // In any case, the proxy broadcast won't be sent before VPN goes into CONNECTED state.
10744         // Otherwise, the app that calls ConnectivityManager#getDefaultProxy() when it receives the
10745         // proxy broadcast will get null.
10746         verify(mProxyTracker, never()).sendProxyBroadcast();
10747         mMockVpn.connect(true /* validated */, true /* hasInternet */, false /* isStrictMode */);
10748         waitForIdle();
10749         assertVpnUidRangesUpdated(true, vpnRanges, VPN_UID);
10750         // Vpn is connected with proxy, so the proxy broadcast will be sent to inform the apps to
10751         // update their proxy data.
10752         verify(mProxyTracker, times(1)).sendProxyBroadcast();
10753     }
10754 
10755     @Test
10756     public void testProxyBroadcastWillBeSentWhenTheProxyOfNonDefaultNetworkHasChanged()
10757             throws Exception {
10758         // Set up a CELLULAR network without proxy.
10759         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
10760         mCellNetworkAgent.connect(true);
10761         assertNull(mService.getProxyForNetwork(null));
10762         assertNull(mCm.getDefaultProxy());
10763         // CELLULAR network should be the default network.
10764         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
10765 
10766         // Set up a WiFi network without proxy.
10767         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
10768         mWiFiNetworkAgent.connect(true);
10769         assertNull(mService.getProxyForNetwork(null));
10770         assertNull(mCm.getDefaultProxy());
10771         // WiFi network should be the default network.
10772         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
10773         // CELLULAR network is not the default network.
10774         assertNotEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
10775 
10776         // CELLULAR network is not the system default network, but it might be a per-app default
10777         // network. The proxy broadcast should be sent once its proxy has changed.
10778         final LinkProperties cellularLp = new LinkProperties();
10779         cellularLp.setInterfaceName(MOBILE_IFNAME);
10780         final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
10781         cellularLp.setHttpProxy(testProxyInfo);
10782         mCellNetworkAgent.sendLinkProperties(cellularLp);
10783         waitForIdle();
10784         verify(mProxyTracker, times(1)).sendProxyBroadcast();
10785     }
10786 
10787     @Test
10788     public void testInvalidRequestTypes() {
10789         final int[] invalidReqTypeInts = new int[]{-1, NetworkRequest.Type.NONE.ordinal(),
10790                 NetworkRequest.Type.LISTEN.ordinal(), NetworkRequest.Type.values().length};
10791         final NetworkCapabilities nc = new NetworkCapabilities().addTransportType(TRANSPORT_WIFI);
10792 
10793         for (int reqTypeInt : invalidReqTypeInts) {
10794             assertThrows("Expect throws for invalid request type " + reqTypeInt,
10795                     IllegalArgumentException.class,
10796                     () -> mService.requestNetwork(Process.INVALID_UID, nc, reqTypeInt, null, 0,
10797                             null, ConnectivityManager.TYPE_NONE, NetworkCallback.FLAG_NONE,
10798                             mContext.getPackageName(), getAttributionTag())
10799             );
10800         }
10801     }
10802 
10803     @Test
10804     public void testKeepConnected() throws Exception {
10805         setAlwaysOnNetworks(false);
10806         registerDefaultNetworkCallbacks();
10807         final TestNetworkCallback allNetworksCb = new TestNetworkCallback();
10808         final NetworkRequest allNetworksRequest = new NetworkRequest.Builder().clearCapabilities()
10809                 .build();
10810         mCm.registerNetworkCallback(allNetworksRequest, allNetworksCb);
10811 
10812         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
10813         mCellNetworkAgent.connect(true /* validated */);
10814 
10815         mDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
10816         allNetworksCb.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
10817 
10818         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
10819         mWiFiNetworkAgent.connect(true /* validated */);
10820 
10821         mDefaultNetworkCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
10822         // While the default callback doesn't see the network before it's validated, the listen
10823         // sees the network come up and validate later
10824         allNetworksCb.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
10825         allNetworksCb.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
10826         allNetworksCb.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
10827         allNetworksCb.expectCallback(CallbackEntry.LOST, mCellNetworkAgent,
10828                 TEST_LINGER_DELAY_MS * 2);
10829 
10830         // The cell network has disconnected (see LOST above) because it was outscored and
10831         // had no requests (see setAlwaysOnNetworks(false) above)
10832         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
10833         final NetworkScore score = new NetworkScore.Builder().setLegacyInt(30).build();
10834         mCellNetworkAgent.setScore(score);
10835         mCellNetworkAgent.connect(false /* validated */);
10836 
10837         // The cell network gets torn down right away.
10838         allNetworksCb.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
10839         allNetworksCb.expectCallback(CallbackEntry.LOST, mCellNetworkAgent,
10840                 TEST_NASCENT_DELAY_MS * 2);
10841         allNetworksCb.assertNoCallback();
10842 
10843         // Now create a cell network with KEEP_CONNECTED_FOR_HANDOVER and make sure it's
10844         // not disconnected immediately when outscored.
10845         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
10846         final NetworkScore scoreKeepup = new NetworkScore.Builder().setLegacyInt(30)
10847                 .setKeepConnectedReason(KEEP_CONNECTED_FOR_HANDOVER).build();
10848         mCellNetworkAgent.setScore(scoreKeepup);
10849         mCellNetworkAgent.connect(true /* validated */);
10850 
10851         allNetworksCb.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
10852         mDefaultNetworkCallback.assertNoCallback();
10853 
10854         mWiFiNetworkAgent.disconnect();
10855 
10856         allNetworksCb.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
10857         mDefaultNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
10858         mDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
10859 
10860         // Reconnect a WiFi network and make sure the cell network is still not torn down.
10861         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
10862         mWiFiNetworkAgent.connect(true /* validated */);
10863 
10864         allNetworksCb.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
10865         mDefaultNetworkCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
10866 
10867         // Now remove the reason to keep connected and make sure the network lingers and is
10868         // torn down.
10869         mCellNetworkAgent.setScore(new NetworkScore.Builder().setLegacyInt(30).build());
10870         allNetworksCb.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent,
10871                 TEST_NASCENT_DELAY_MS * 2);
10872         allNetworksCb.expectCallback(CallbackEntry.LOST, mCellNetworkAgent,
10873                 TEST_LINGER_DELAY_MS * 2);
10874         mDefaultNetworkCallback.assertNoCallback();
10875 
10876         mCm.unregisterNetworkCallback(allNetworksCb);
10877         // mDefaultNetworkCallback will be unregistered by tearDown()
10878     }
10879 
10880     private class QosCallbackMockHelper {
10881         @NonNull public final QosFilter mFilter;
10882         @NonNull public final IQosCallback mCallback;
10883         @NonNull public final TestNetworkAgentWrapper mAgentWrapper;
10884         @NonNull private final List<IQosCallback> mCallbacks = new ArrayList();
10885 
10886         QosCallbackMockHelper() throws Exception {
10887             Log.d(TAG, "QosCallbackMockHelper: ");
10888             mFilter = mock(QosFilter.class);
10889 
10890             // Ensure the network is disconnected before anything else occurs
10891             assertNull(mCellNetworkAgent);
10892 
10893             mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
10894             mCellNetworkAgent.connect(true);
10895 
10896             verifyActiveNetwork(TRANSPORT_CELLULAR);
10897             waitForIdle();
10898             final Network network = mCellNetworkAgent.getNetwork();
10899 
10900             final Pair<IQosCallback, IBinder> pair = createQosCallback();
10901             mCallback = pair.first;
10902 
10903             when(mFilter.getNetwork()).thenReturn(network);
10904             when(mFilter.validate()).thenReturn(QosCallbackException.EX_TYPE_FILTER_NONE);
10905             mAgentWrapper = mCellNetworkAgent;
10906         }
10907 
10908         void registerQosCallback(@NonNull final QosFilter filter,
10909                 @NonNull final IQosCallback callback) {
10910             mCallbacks.add(callback);
10911             final NetworkAgentInfo nai =
10912                     mService.getNetworkAgentInfoForNetwork(filter.getNetwork());
10913             mService.registerQosCallbackInternal(filter, callback, nai);
10914         }
10915 
10916         void tearDown() {
10917             for (int i = 0; i < mCallbacks.size(); i++) {
10918                 mService.unregisterQosCallback(mCallbacks.get(i));
10919             }
10920         }
10921     }
10922 
10923     private Pair<IQosCallback, IBinder> createQosCallback() {
10924         final IQosCallback callback = mock(IQosCallback.class);
10925         final IBinder binder = mock(Binder.class);
10926         when(callback.asBinder()).thenReturn(binder);
10927         when(binder.isBinderAlive()).thenReturn(true);
10928         return new Pair<>(callback, binder);
10929     }
10930 
10931 
10932     @Test
10933     public void testQosCallbackRegistration() throws Exception {
10934         mQosCallbackMockHelper = new QosCallbackMockHelper();
10935         final NetworkAgentWrapper wrapper = mQosCallbackMockHelper.mAgentWrapper;
10936 
10937         when(mQosCallbackMockHelper.mFilter.validate())
10938                 .thenReturn(QosCallbackException.EX_TYPE_FILTER_NONE);
10939         mQosCallbackMockHelper.registerQosCallback(
10940                 mQosCallbackMockHelper.mFilter, mQosCallbackMockHelper.mCallback);
10941 
10942         final NetworkAgentWrapper.CallbackType.OnQosCallbackRegister cbRegister1 =
10943                 (NetworkAgentWrapper.CallbackType.OnQosCallbackRegister)
10944                         wrapper.getCallbackHistory().poll(1000, x -> true);
10945         assertNotNull(cbRegister1);
10946 
10947         final int registerCallbackId = cbRegister1.mQosCallbackId;
10948         mService.unregisterQosCallback(mQosCallbackMockHelper.mCallback);
10949         final NetworkAgentWrapper.CallbackType.OnQosCallbackUnregister cbUnregister;
10950         cbUnregister = (NetworkAgentWrapper.CallbackType.OnQosCallbackUnregister)
10951                 wrapper.getCallbackHistory().poll(1000, x -> true);
10952         assertNotNull(cbUnregister);
10953         assertEquals(registerCallbackId, cbUnregister.mQosCallbackId);
10954         assertNull(wrapper.getCallbackHistory().poll(200, x -> true));
10955     }
10956 
10957     @Test
10958     public void testQosCallbackNoRegistrationOnValidationError() throws Exception {
10959         mQosCallbackMockHelper = new QosCallbackMockHelper();
10960 
10961         when(mQosCallbackMockHelper.mFilter.validate())
10962                 .thenReturn(QosCallbackException.EX_TYPE_FILTER_NETWORK_RELEASED);
10963         mQosCallbackMockHelper.registerQosCallback(
10964                 mQosCallbackMockHelper.mFilter, mQosCallbackMockHelper.mCallback);
10965         waitForIdle();
10966         verify(mQosCallbackMockHelper.mCallback)
10967                 .onError(eq(QosCallbackException.EX_TYPE_FILTER_NETWORK_RELEASED));
10968     }
10969 
10970     @Test
10971     public void testQosCallbackAvailableAndLost() throws Exception {
10972         mQosCallbackMockHelper = new QosCallbackMockHelper();
10973         final int sessionId = 10;
10974         final int qosCallbackId = 1;
10975 
10976         when(mQosCallbackMockHelper.mFilter.validate())
10977                 .thenReturn(QosCallbackException.EX_TYPE_FILTER_NONE);
10978         mQosCallbackMockHelper.registerQosCallback(
10979                 mQosCallbackMockHelper.mFilter, mQosCallbackMockHelper.mCallback);
10980         waitForIdle();
10981 
10982         final EpsBearerQosSessionAttributes attributes = new EpsBearerQosSessionAttributes(
10983                 1, 2, 3, 4, 5, new ArrayList<>());
10984         mQosCallbackMockHelper.mAgentWrapper.getNetworkAgent()
10985                 .sendQosSessionAvailable(qosCallbackId, sessionId, attributes);
10986         waitForIdle();
10987 
10988         verify(mQosCallbackMockHelper.mCallback).onQosEpsBearerSessionAvailable(argThat(session ->
10989                 session.getSessionId() == sessionId
10990                         && session.getSessionType() == QosSession.TYPE_EPS_BEARER), eq(attributes));
10991 
10992         mQosCallbackMockHelper.mAgentWrapper.getNetworkAgent()
10993                 .sendQosSessionLost(qosCallbackId, sessionId, QosSession.TYPE_EPS_BEARER);
10994         waitForIdle();
10995         verify(mQosCallbackMockHelper.mCallback).onQosSessionLost(argThat(session ->
10996                 session.getSessionId() == sessionId
10997                         && session.getSessionType() == QosSession.TYPE_EPS_BEARER));
10998     }
10999 
11000     @Test
11001     public void testNrQosCallbackAvailableAndLost() throws Exception {
11002         mQosCallbackMockHelper = new QosCallbackMockHelper();
11003         final int sessionId = 10;
11004         final int qosCallbackId = 1;
11005 
11006         when(mQosCallbackMockHelper.mFilter.validate())
11007                 .thenReturn(QosCallbackException.EX_TYPE_FILTER_NONE);
11008         mQosCallbackMockHelper.registerQosCallback(
11009                 mQosCallbackMockHelper.mFilter, mQosCallbackMockHelper.mCallback);
11010         waitForIdle();
11011 
11012         final NrQosSessionAttributes attributes = new NrQosSessionAttributes(
11013                 1, 2, 3, 4, 5, 6, 7, new ArrayList<>());
11014         mQosCallbackMockHelper.mAgentWrapper.getNetworkAgent()
11015                 .sendQosSessionAvailable(qosCallbackId, sessionId, attributes);
11016         waitForIdle();
11017 
11018         verify(mQosCallbackMockHelper.mCallback).onNrQosSessionAvailable(argThat(session ->
11019                 session.getSessionId() == sessionId
11020                         && session.getSessionType() == QosSession.TYPE_NR_BEARER), eq(attributes));
11021 
11022         mQosCallbackMockHelper.mAgentWrapper.getNetworkAgent()
11023                 .sendQosSessionLost(qosCallbackId, sessionId, QosSession.TYPE_NR_BEARER);
11024         waitForIdle();
11025         verify(mQosCallbackMockHelper.mCallback).onQosSessionLost(argThat(session ->
11026                 session.getSessionId() == sessionId
11027                         && session.getSessionType() == QosSession.TYPE_NR_BEARER));
11028     }
11029 
11030     @Test
11031     public void testQosCallbackTooManyRequests() throws Exception {
11032         mQosCallbackMockHelper = new QosCallbackMockHelper();
11033 
11034         when(mQosCallbackMockHelper.mFilter.validate())
11035                 .thenReturn(QosCallbackException.EX_TYPE_FILTER_NONE);
11036         for (int i = 0; i < 100; i++) {
11037             final Pair<IQosCallback, IBinder> pair = createQosCallback();
11038 
11039             try {
11040                 mQosCallbackMockHelper.registerQosCallback(
11041                         mQosCallbackMockHelper.mFilter, pair.first);
11042             } catch (ServiceSpecificException e) {
11043                 assertEquals(e.errorCode, ConnectivityManager.Errors.TOO_MANY_REQUESTS);
11044                 if (i < 50) {
11045                     fail("TOO_MANY_REQUESTS thrown too early, the count is " + i);
11046                 }
11047 
11048                 // As long as there is at least 50 requests, it is safe to assume it works.
11049                 // Note: The count isn't being tested precisely against 100 because the counter
11050                 // is shared with request network.
11051                 return;
11052             }
11053         }
11054         fail("TOO_MANY_REQUESTS never thrown");
11055     }
11056 
11057     private void mockGetApplicationInfo(@NonNull final String packageName, final int uid) {
11058         mockGetApplicationInfo(packageName, uid, PRIMARY_USER_HANDLE);
11059     }
11060 
11061     private void mockGetApplicationInfo(@NonNull final String packageName, final int uid,
11062             @NonNull final UserHandle user) {
11063         final ApplicationInfo applicationInfo = new ApplicationInfo();
11064         applicationInfo.uid = uid;
11065         try {
11066             when(mPackageManager.getApplicationInfoAsUser(eq(packageName), anyInt(), eq(user)))
11067                     .thenReturn(applicationInfo);
11068         } catch (Exception e) {
11069             fail(e.getMessage());
11070         }
11071     }
11072 
11073     private void mockGetApplicationInfoThrowsNameNotFound(@NonNull final String packageName,
11074             @NonNull final UserHandle user)
11075             throws Exception {
11076         when(mPackageManager.getApplicationInfoAsUser(eq(packageName), anyInt(), eq(user)))
11077                 .thenThrow(new PackageManager.NameNotFoundException(packageName));
11078     }
11079 
11080     private void mockHasSystemFeature(@NonNull final String featureName, final boolean hasFeature) {
11081         when(mPackageManager.hasSystemFeature(eq(featureName)))
11082                 .thenReturn(hasFeature);
11083     }
11084 
11085     private Range<Integer> getNriFirstUidRange(@NonNull final NetworkRequestInfo nri) {
11086         return nri.mRequests.get(0).networkCapabilities.getUids().iterator().next();
11087     }
11088 
11089     private OemNetworkPreferences createDefaultOemNetworkPreferences(
11090             @OemNetworkPreferences.OemNetworkPreference final int preference) {
11091         // Arrange PackageManager mocks
11092         mockGetApplicationInfo(TEST_PACKAGE_NAME, TEST_PACKAGE_UID);
11093 
11094         // Build OemNetworkPreferences object
11095         return new OemNetworkPreferences.Builder()
11096                 .addNetworkPreference(TEST_PACKAGE_NAME, preference)
11097                 .build();
11098     }
11099 
11100     @Test
11101     public void testOemNetworkRequestFactoryPreferenceUninitializedThrowsError() {
11102         @OemNetworkPreferences.OemNetworkPreference final int prefToTest =
11103                 OEM_NETWORK_PREFERENCE_UNINITIALIZED;
11104 
11105         // Act on OemNetworkRequestFactory.createNrisFromOemNetworkPreferences()
11106         assertThrows(IllegalArgumentException.class,
11107                 () -> mService.new OemNetworkRequestFactory()
11108                         .createNrisFromOemNetworkPreferences(
11109                                 createDefaultOemNetworkPreferences(prefToTest)));
11110     }
11111 
11112     @Test
11113     public void testOemNetworkRequestFactoryPreferenceOemPaid()
11114             throws Exception {
11115         // Expectations
11116         final int expectedNumOfNris = 1;
11117         final int expectedNumOfRequests = 3;
11118 
11119         @OemNetworkPreferences.OemNetworkPreference final int prefToTest =
11120                 OEM_NETWORK_PREFERENCE_OEM_PAID;
11121 
11122         // Act on OemNetworkRequestFactory.createNrisFromOemNetworkPreferences()
11123         final ArraySet<NetworkRequestInfo> nris =
11124                 mService.new OemNetworkRequestFactory()
11125                         .createNrisFromOemNetworkPreferences(
11126                                 createDefaultOemNetworkPreferences(prefToTest));
11127         final NetworkRequestInfo nri = nris.iterator().next();
11128         assertEquals(PREFERENCE_PRIORITY_OEM, nri.mPreferencePriority);
11129         final List<NetworkRequest> mRequests = nri.mRequests;
11130         assertEquals(expectedNumOfNris, nris.size());
11131         assertEquals(expectedNumOfRequests, mRequests.size());
11132         assertTrue(mRequests.get(0).isListen());
11133         assertTrue(mRequests.get(0).hasCapability(NET_CAPABILITY_NOT_METERED));
11134         assertTrue(mRequests.get(0).hasCapability(NET_CAPABILITY_VALIDATED));
11135         assertTrue(mRequests.get(1).isRequest());
11136         assertTrue(mRequests.get(1).hasCapability(NET_CAPABILITY_OEM_PAID));
11137         assertEquals(NetworkRequest.Type.TRACK_DEFAULT, mRequests.get(2).type);
11138         assertTrue(mService.getDefaultRequest().networkCapabilities.equalsNetCapabilities(
11139                 mRequests.get(2).networkCapabilities));
11140     }
11141 
11142     @Test
11143     public void testOemNetworkRequestFactoryPreferenceOemPaidNoFallback()
11144             throws Exception {
11145         // Expectations
11146         final int expectedNumOfNris = 1;
11147         final int expectedNumOfRequests = 2;
11148 
11149         @OemNetworkPreferences.OemNetworkPreference final int prefToTest =
11150                 OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK;
11151 
11152         // Act on OemNetworkRequestFactory.createNrisFromOemNetworkPreferences()
11153         final ArraySet<NetworkRequestInfo> nris =
11154                 mService.new OemNetworkRequestFactory()
11155                         .createNrisFromOemNetworkPreferences(
11156                                 createDefaultOemNetworkPreferences(prefToTest));
11157         final NetworkRequestInfo nri = nris.iterator().next();
11158         assertEquals(PREFERENCE_PRIORITY_OEM, nri.mPreferencePriority);
11159         final List<NetworkRequest> mRequests = nri.mRequests;
11160         assertEquals(expectedNumOfNris, nris.size());
11161         assertEquals(expectedNumOfRequests, mRequests.size());
11162         assertTrue(mRequests.get(0).isListen());
11163         assertTrue(mRequests.get(0).hasCapability(NET_CAPABILITY_NOT_METERED));
11164         assertTrue(mRequests.get(0).hasCapability(NET_CAPABILITY_VALIDATED));
11165         assertTrue(mRequests.get(1).isRequest());
11166         assertTrue(mRequests.get(1).hasCapability(NET_CAPABILITY_OEM_PAID));
11167     }
11168 
11169     @Test
11170     public void testOemNetworkRequestFactoryPreferenceOemPaidOnly()
11171             throws Exception {
11172         // Expectations
11173         final int expectedNumOfNris = 1;
11174         final int expectedNumOfRequests = 1;
11175 
11176         @OemNetworkPreferences.OemNetworkPreference final int prefToTest =
11177                 OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY;
11178 
11179         // Act on OemNetworkRequestFactory.createNrisFromOemNetworkPreferences()
11180         final ArraySet<NetworkRequestInfo> nris =
11181                 mService.new OemNetworkRequestFactory()
11182                         .createNrisFromOemNetworkPreferences(
11183                                 createDefaultOemNetworkPreferences(prefToTest));
11184         final NetworkRequestInfo nri = nris.iterator().next();
11185         assertEquals(PREFERENCE_PRIORITY_OEM, nri.mPreferencePriority);
11186         final List<NetworkRequest> mRequests = nri.mRequests;
11187         assertEquals(expectedNumOfNris, nris.size());
11188         assertEquals(expectedNumOfRequests, mRequests.size());
11189         assertTrue(mRequests.get(0).isRequest());
11190         assertTrue(mRequests.get(0).hasCapability(NET_CAPABILITY_OEM_PAID));
11191     }
11192 
11193     @Test
11194     public void testOemNetworkRequestFactoryPreferenceOemPrivateOnly()
11195             throws Exception {
11196         // Expectations
11197         final int expectedNumOfNris = 1;
11198         final int expectedNumOfRequests = 1;
11199 
11200         @OemNetworkPreferences.OemNetworkPreference final int prefToTest =
11201                 OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY;
11202 
11203         // Act on OemNetworkRequestFactory.createNrisFromOemNetworkPreferences()
11204         final ArraySet<NetworkRequestInfo> nris =
11205                 mService.new OemNetworkRequestFactory()
11206                         .createNrisFromOemNetworkPreferences(
11207                                 createDefaultOemNetworkPreferences(prefToTest));
11208         final NetworkRequestInfo nri = nris.iterator().next();
11209         assertEquals(PREFERENCE_PRIORITY_OEM, nri.mPreferencePriority);
11210         final List<NetworkRequest> mRequests = nri.mRequests;
11211         assertEquals(expectedNumOfNris, nris.size());
11212         assertEquals(expectedNumOfRequests, mRequests.size());
11213         assertTrue(mRequests.get(0).isRequest());
11214         assertTrue(mRequests.get(0).hasCapability(NET_CAPABILITY_OEM_PRIVATE));
11215         assertFalse(mRequests.get(0).hasCapability(NET_CAPABILITY_OEM_PAID));
11216     }
11217 
11218     @Test
11219     public void testOemNetworkRequestFactoryCreatesCorrectNumOfNris()
11220             throws Exception {
11221         // Expectations
11222         final int expectedNumOfNris = 2;
11223 
11224         // Arrange PackageManager mocks
11225         final String testPackageName2 = "com.google.apps.dialer";
11226         mockGetApplicationInfo(TEST_PACKAGE_NAME, TEST_PACKAGE_UID);
11227         mockGetApplicationInfo(testPackageName2, TEST_PACKAGE_UID);
11228 
11229         // Build OemNetworkPreferences object
11230         final int testOemPref = OEM_NETWORK_PREFERENCE_OEM_PAID;
11231         final int testOemPref2 = OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK;
11232         final OemNetworkPreferences pref = new OemNetworkPreferences.Builder()
11233                 .addNetworkPreference(TEST_PACKAGE_NAME, testOemPref)
11234                 .addNetworkPreference(testPackageName2, testOemPref2)
11235                 .build();
11236 
11237         // Act on OemNetworkRequestFactory.createNrisFromOemNetworkPreferences()
11238         final ArraySet<NetworkRequestInfo> nris =
11239                 mService.new OemNetworkRequestFactory().createNrisFromOemNetworkPreferences(pref);
11240 
11241         assertNotNull(nris);
11242         assertEquals(expectedNumOfNris, nris.size());
11243     }
11244 
11245     @Test
11246     public void testOemNetworkRequestFactoryMultiplePrefsCorrectlySetsUids()
11247             throws Exception {
11248         // Arrange PackageManager mocks
11249         final String testPackageName2 = "com.google.apps.dialer";
11250         final int testPackageNameUid2 = 456;
11251         mockGetApplicationInfo(TEST_PACKAGE_NAME, TEST_PACKAGE_UID);
11252         mockGetApplicationInfo(testPackageName2, testPackageNameUid2);
11253 
11254         // Build OemNetworkPreferences object
11255         final int testOemPref = OEM_NETWORK_PREFERENCE_OEM_PAID;
11256         final int testOemPref2 = OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK;
11257         final OemNetworkPreferences pref = new OemNetworkPreferences.Builder()
11258                 .addNetworkPreference(TEST_PACKAGE_NAME, testOemPref)
11259                 .addNetworkPreference(testPackageName2, testOemPref2)
11260                 .build();
11261 
11262         // Act on OemNetworkRequestFactory.createNrisFromOemNetworkPreferences()
11263         final List<NetworkRequestInfo> nris =
11264                 new ArrayList<>(
11265                         mService.new OemNetworkRequestFactory().createNrisFromOemNetworkPreferences(
11266                                 pref));
11267 
11268         // Sort by uid to access nris by index
11269         nris.sort(Comparator.comparingInt(nri -> getNriFirstUidRange(nri).getLower()));
11270         assertEquals(TEST_PACKAGE_UID, (int) getNriFirstUidRange(nris.get(0)).getLower());
11271         assertEquals(TEST_PACKAGE_UID, (int) getNriFirstUidRange(nris.get(0)).getUpper());
11272         assertEquals(testPackageNameUid2, (int) getNriFirstUidRange(nris.get(1)).getLower());
11273         assertEquals(testPackageNameUid2, (int) getNriFirstUidRange(nris.get(1)).getUpper());
11274     }
11275 
11276     @Test
11277     public void testOemNetworkRequestFactoryMultipleUsersSetsUids()
11278             throws Exception {
11279         // Arrange users
11280         final int secondUserTestPackageUid = UserHandle.getUid(SECONDARY_USER, TEST_PACKAGE_UID);
11281         final int thirdUserTestPackageUid = UserHandle.getUid(TERTIARY_USER, TEST_PACKAGE_UID);
11282         when(mUserManager.getUserHandles(anyBoolean())).thenReturn(
11283                 Arrays.asList(PRIMARY_USER_HANDLE, SECONDARY_USER_HANDLE, TERTIARY_USER_HANDLE));
11284 
11285         // Arrange PackageManager mocks testing for users who have and don't have a package.
11286         mockGetApplicationInfoThrowsNameNotFound(TEST_PACKAGE_NAME, PRIMARY_USER_HANDLE);
11287         mockGetApplicationInfo(TEST_PACKAGE_NAME, secondUserTestPackageUid, SECONDARY_USER_HANDLE);
11288         mockGetApplicationInfo(TEST_PACKAGE_NAME, thirdUserTestPackageUid, TERTIARY_USER_HANDLE);
11289 
11290         // Build OemNetworkPreferences object
11291         final int testOemPref = OEM_NETWORK_PREFERENCE_OEM_PAID;
11292         final OemNetworkPreferences pref = new OemNetworkPreferences.Builder()
11293                 .addNetworkPreference(TEST_PACKAGE_NAME, testOemPref)
11294                 .build();
11295 
11296         // Act on OemNetworkRequestFactory.createNrisFromOemNetworkPreferences()
11297         final List<NetworkRequestInfo> nris =
11298                 new ArrayList<>(
11299                         mService.new OemNetworkRequestFactory().createNrisFromOemNetworkPreferences(
11300                                 pref));
11301 
11302         // UIDs for users with installed packages should be present.
11303         // Three users exist, but only two have the test package installed.
11304         final int expectedUidSize = 2;
11305         final List<Range<Integer>> uids =
11306                 new ArrayList<>(nris.get(0).mRequests.get(0).networkCapabilities.getUids());
11307         assertEquals(expectedUidSize, uids.size());
11308 
11309         // Sort by uid to access nris by index
11310         uids.sort(Comparator.comparingInt(uid -> uid.getLower()));
11311         assertEquals(secondUserTestPackageUid, (int) uids.get(0).getLower());
11312         assertEquals(secondUserTestPackageUid, (int) uids.get(0).getUpper());
11313         assertEquals(thirdUserTestPackageUid, (int) uids.get(1).getLower());
11314         assertEquals(thirdUserTestPackageUid, (int) uids.get(1).getUpper());
11315     }
11316 
11317     @Test
11318     public void testOemNetworkRequestFactoryAddsPackagesToCorrectPreference()
11319             throws Exception {
11320         // Expectations
11321         final int expectedNumOfNris = 1;
11322         final int expectedNumOfAppUids = 2;
11323 
11324         // Arrange PackageManager mocks
11325         final String testPackageName2 = "com.google.apps.dialer";
11326         final int testPackageNameUid2 = 456;
11327         mockGetApplicationInfo(TEST_PACKAGE_NAME, TEST_PACKAGE_UID);
11328         mockGetApplicationInfo(testPackageName2, testPackageNameUid2);
11329 
11330         // Build OemNetworkPreferences object
11331         final int testOemPref = OEM_NETWORK_PREFERENCE_OEM_PAID;
11332         final OemNetworkPreferences pref = new OemNetworkPreferences.Builder()
11333                 .addNetworkPreference(TEST_PACKAGE_NAME, testOemPref)
11334                 .addNetworkPreference(testPackageName2, testOemPref)
11335                 .build();
11336 
11337         // Act on OemNetworkRequestFactory.createNrisFromOemNetworkPreferences()
11338         final ArraySet<NetworkRequestInfo> nris =
11339                 mService.new OemNetworkRequestFactory().createNrisFromOemNetworkPreferences(pref);
11340 
11341         assertEquals(expectedNumOfNris, nris.size());
11342         assertEquals(expectedNumOfAppUids,
11343                 nris.iterator().next().mRequests.get(0).networkCapabilities.getUids().size());
11344     }
11345 
11346     @Test
11347     public void testSetOemNetworkPreferenceNullListenerAndPrefParamThrowsNpe() {
11348         mockHasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, true);
11349 
11350         // Act on ConnectivityService.setOemNetworkPreference()
11351         assertThrows(NullPointerException.class,
11352                 () -> mService.setOemNetworkPreference(
11353                         null,
11354                         null));
11355     }
11356 
11357     @Test
11358     public void testSetOemNetworkPreferenceFailsForNonAutomotive()
11359             throws Exception {
11360         mockHasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, false);
11361         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
11362                 OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY;
11363 
11364         // Act on ConnectivityService.setOemNetworkPreference()
11365         assertThrows(UnsupportedOperationException.class,
11366                 () -> mService.setOemNetworkPreference(
11367                         createDefaultOemNetworkPreferences(networkPref),
11368                         null));
11369     }
11370 
11371     @Test
11372     public void testSetOemNetworkPreferenceFailsForTestRequestWithoutPermission() {
11373         // Calling setOemNetworkPreference() with a test pref requires the permission
11374         // MANAGE_TEST_NETWORKS.
11375         mockHasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, false);
11376         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
11377                 OEM_NETWORK_PREFERENCE_TEST;
11378 
11379         // Act on ConnectivityService.setOemNetworkPreference()
11380         assertThrows(SecurityException.class,
11381                 () -> mService.setOemNetworkPreference(
11382                         createDefaultOemNetworkPreferences(networkPref),
11383                         null));
11384     }
11385 
11386     @Test
11387     public void testSetOemNetworkPreferenceFailsForInvalidTestRequest() {
11388         assertSetOemNetworkPreferenceFailsForInvalidTestRequest(OEM_NETWORK_PREFERENCE_TEST);
11389     }
11390 
11391     @Test
11392     public void testSetOemNetworkPreferenceFailsForInvalidTestOnlyRequest() {
11393         assertSetOemNetworkPreferenceFailsForInvalidTestRequest(OEM_NETWORK_PREFERENCE_TEST_ONLY);
11394     }
11395 
11396     private void assertSetOemNetworkPreferenceFailsForInvalidTestRequest(
11397             @OemNetworkPreferences.OemNetworkPreference final int oemNetworkPreferenceForTest) {
11398         mockHasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, true);
11399         final String secondPackage = "does.not.matter";
11400 
11401         // A valid test request would only have a single mapping.
11402         final OemNetworkPreferences pref = new OemNetworkPreferences.Builder()
11403                 .addNetworkPreference(TEST_PACKAGE_NAME, oemNetworkPreferenceForTest)
11404                 .addNetworkPreference(secondPackage, oemNetworkPreferenceForTest)
11405                 .build();
11406 
11407         // Act on ConnectivityService.setOemNetworkPreference()
11408         assertThrows(IllegalArgumentException.class,
11409                 () -> mService.setOemNetworkPreference(pref, null));
11410     }
11411 
11412     private void setOemNetworkPreferenceAgentConnected(final int transportType,
11413             final boolean connectAgent) throws Exception {
11414         switch(transportType) {
11415             // Corresponds to a metered cellular network. Will be used for the default network.
11416             case TRANSPORT_CELLULAR:
11417                 if (!connectAgent) {
11418                     mCellNetworkAgent.disconnect();
11419                     break;
11420                 }
11421                 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
11422                 mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
11423                 mCellNetworkAgent.connect(true);
11424                 break;
11425             // Corresponds to a restricted ethernet network with OEM_PAID/OEM_PRIVATE.
11426             case TRANSPORT_ETHERNET:
11427                 if (!connectAgent) {
11428                     stopOemManagedNetwork();
11429                     break;
11430                 }
11431                 startOemManagedNetwork(true);
11432                 break;
11433             // Corresponds to unmetered Wi-Fi.
11434             case TRANSPORT_WIFI:
11435                 if (!connectAgent) {
11436                     mWiFiNetworkAgent.disconnect();
11437                     break;
11438                 }
11439                 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
11440                 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
11441                 mWiFiNetworkAgent.connect(true);
11442                 break;
11443             default:
11444                 throw new AssertionError("Unsupported transport type passed in.");
11445 
11446         }
11447         waitForIdle();
11448     }
11449 
11450     private void startOemManagedNetwork(final boolean isOemPaid) throws Exception {
11451         mEthernetNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
11452         mEthernetNetworkAgent.addCapability(
11453                 isOemPaid ? NET_CAPABILITY_OEM_PAID : NET_CAPABILITY_OEM_PRIVATE);
11454         mEthernetNetworkAgent.removeCapability(NET_CAPABILITY_NOT_RESTRICTED);
11455         mEthernetNetworkAgent.connect(true);
11456     }
11457 
11458     private void stopOemManagedNetwork() {
11459         mEthernetNetworkAgent.disconnect();
11460         waitForIdle();
11461     }
11462 
11463     private void verifyMultipleDefaultNetworksTracksCorrectly(
11464             final int expectedOemRequestsSize,
11465             @NonNull final Network expectedDefaultNetwork,
11466             @NonNull final Network expectedPerAppNetwork) {
11467         // The current test setup assumes two tracked default network requests; one for the default
11468         // network and the other for the OEM network preference being tested. This will be validated
11469         // each time to confirm it doesn't change under test.
11470         final int expectedDefaultNetworkRequestsSize = 2;
11471         assertEquals(expectedDefaultNetworkRequestsSize, mService.mDefaultNetworkRequests.size());
11472         for (final NetworkRequestInfo defaultRequest : mService.mDefaultNetworkRequests) {
11473             final Network defaultNetwork = defaultRequest.getSatisfier() == null
11474                     ? null : defaultRequest.getSatisfier().network();
11475             // If this is the default request.
11476             if (defaultRequest == mService.mDefaultRequest) {
11477                 assertEquals(
11478                         expectedDefaultNetwork,
11479                         defaultNetwork);
11480                 // Make sure this value doesn't change.
11481                 assertEquals(1, defaultRequest.mRequests.size());
11482                 continue;
11483             }
11484             assertEquals(expectedPerAppNetwork, defaultNetwork);
11485             assertEquals(expectedOemRequestsSize, defaultRequest.mRequests.size());
11486         }
11487         verifyMultipleDefaultCallbacks(expectedDefaultNetwork, expectedPerAppNetwork);
11488     }
11489 
11490     /**
11491      * Verify default callbacks for 'available' fire as expected. This will only run if
11492      * registerDefaultNetworkCallbacks() was executed prior and will only be different if the
11493      * setOemNetworkPreference() per-app API was used for the current process.
11494      * @param expectedSystemDefault the expected network for the system default.
11495      * @param expectedPerAppDefault the expected network for the current process's default.
11496      */
11497     private void verifyMultipleDefaultCallbacks(
11498             @NonNull final Network expectedSystemDefault,
11499             @NonNull final Network expectedPerAppDefault) {
11500         if (null != mSystemDefaultNetworkCallback && null != expectedSystemDefault
11501                 && mService.mNoServiceNetwork.network() != expectedSystemDefault) {
11502             // getLastAvailableNetwork() is used as this method can be called successively with
11503             // the same network to validate therefore expectAvailableThenValidatedCallbacks
11504             // can't be used.
11505             assertEquals(mSystemDefaultNetworkCallback.getLastAvailableNetwork(),
11506                     expectedSystemDefault);
11507         }
11508         if (null != mDefaultNetworkCallback && null != expectedPerAppDefault
11509                 && mService.mNoServiceNetwork.network() != expectedPerAppDefault) {
11510             assertEquals(mDefaultNetworkCallback.getLastAvailableNetwork(),
11511                     expectedPerAppDefault);
11512         }
11513     }
11514 
11515     private void registerDefaultNetworkCallbacks() {
11516         if (mSystemDefaultNetworkCallback != null || mDefaultNetworkCallback != null
11517                 || mProfileDefaultNetworkCallback != null
11518                 || mTestPackageDefaultNetworkCallback != null) {
11519             throw new IllegalStateException("Default network callbacks already registered");
11520         }
11521 
11522         // Using Manifest.permission.NETWORK_SETTINGS for registerSystemDefaultNetworkCallback()
11523         mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_GRANTED);
11524         mSystemDefaultNetworkCallback = new TestNetworkCallback();
11525         mDefaultNetworkCallback = new TestNetworkCallback();
11526         mProfileDefaultNetworkCallback = new TestNetworkCallback();
11527         mTestPackageDefaultNetworkCallback = new TestNetworkCallback();
11528         mCm.registerSystemDefaultNetworkCallback(mSystemDefaultNetworkCallback,
11529                 new Handler(ConnectivityThread.getInstanceLooper()));
11530         mCm.registerDefaultNetworkCallback(mDefaultNetworkCallback);
11531         registerDefaultNetworkCallbackAsUid(mProfileDefaultNetworkCallback,
11532                 TEST_WORK_PROFILE_APP_UID);
11533         registerDefaultNetworkCallbackAsUid(mTestPackageDefaultNetworkCallback, TEST_PACKAGE_UID);
11534         // TODO: test using ConnectivityManager#registerDefaultNetworkCallbackAsUid as well.
11535         mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_DENIED);
11536     }
11537 
11538     private void unregisterDefaultNetworkCallbacks() {
11539         if (null != mDefaultNetworkCallback) {
11540             mCm.unregisterNetworkCallback(mDefaultNetworkCallback);
11541         }
11542         if (null != mSystemDefaultNetworkCallback) {
11543             mCm.unregisterNetworkCallback(mSystemDefaultNetworkCallback);
11544         }
11545         if (null != mProfileDefaultNetworkCallback) {
11546             mCm.unregisterNetworkCallback(mProfileDefaultNetworkCallback);
11547         }
11548         if (null != mTestPackageDefaultNetworkCallback) {
11549             mCm.unregisterNetworkCallback(mTestPackageDefaultNetworkCallback);
11550         }
11551     }
11552 
11553     private void setupMultipleDefaultNetworksForOemNetworkPreferenceNotCurrentUidTest(
11554             @OemNetworkPreferences.OemNetworkPreference final int networkPrefToSetup)
11555             throws Exception {
11556         final int testPackageNameUid = TEST_PACKAGE_UID;
11557         final String testPackageName = "per.app.defaults.package";
11558         setupMultipleDefaultNetworksForOemNetworkPreferenceTest(
11559                 networkPrefToSetup, testPackageNameUid, testPackageName);
11560     }
11561 
11562     private void setupMultipleDefaultNetworksForOemNetworkPreferenceCurrentUidTest(
11563             @OemNetworkPreferences.OemNetworkPreference final int networkPrefToSetup)
11564             throws Exception {
11565         final int testPackageNameUid = Process.myUid();
11566         final String testPackageName = "per.app.defaults.package";
11567         setupMultipleDefaultNetworksForOemNetworkPreferenceTest(
11568                 networkPrefToSetup, testPackageNameUid, testPackageName);
11569     }
11570 
11571     private void setupMultipleDefaultNetworksForOemNetworkPreferenceTest(
11572             @OemNetworkPreferences.OemNetworkPreference final int networkPrefToSetup,
11573             final int testPackageUid, @NonNull final String testPackageName) throws Exception {
11574         // Only the default request should be included at start.
11575         assertEquals(1, mService.mDefaultNetworkRequests.size());
11576 
11577         final UidRangeParcel[] uidRanges =
11578                 toUidRangeStableParcels(uidRangesForUids(testPackageUid));
11579         setupSetOemNetworkPreferenceForPreferenceTest(
11580                 networkPrefToSetup, uidRanges, testPackageName);
11581     }
11582 
11583     private void setupSetOemNetworkPreferenceForPreferenceTest(
11584             @OemNetworkPreferences.OemNetworkPreference final int networkPrefToSetup,
11585             @NonNull final UidRangeParcel[] uidRanges,
11586             @NonNull final String testPackageName) throws Exception {
11587         setupSetOemNetworkPreferenceForPreferenceTest(networkPrefToSetup, uidRanges,
11588                 testPackageName, PRIMARY_USER_HANDLE, true /* hasAutomotiveFeature */);
11589     }
11590 
11591     private void setupSetOemNetworkPreferenceForPreferenceTest(
11592             @OemNetworkPreferences.OemNetworkPreference final int networkPrefToSetup,
11593             @NonNull final UidRangeParcel[] uidRanges,
11594             @NonNull final String testPackageName,
11595             @NonNull final UserHandle user) throws Exception {
11596         setupSetOemNetworkPreferenceForPreferenceTest(networkPrefToSetup, uidRanges,
11597                 testPackageName, user, true /* hasAutomotiveFeature */);
11598     }
11599 
11600     private void setupSetOemNetworkPreferenceForPreferenceTest(
11601             @OemNetworkPreferences.OemNetworkPreference final int networkPrefToSetup,
11602             @NonNull final UidRangeParcel[] uidRanges,
11603             @NonNull final String testPackageName,
11604             @NonNull final UserHandle user,
11605             final boolean hasAutomotiveFeature) throws Exception {
11606         mockHasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, hasAutomotiveFeature);
11607 
11608         // These tests work off a single UID therefore using 'start' is valid.
11609         mockGetApplicationInfo(testPackageName, uidRanges[0].start, user);
11610 
11611         setOemNetworkPreference(networkPrefToSetup, testPackageName);
11612     }
11613 
11614     private void setOemNetworkPreference(final int networkPrefToSetup,
11615             @NonNull final String... testPackageNames)
11616             throws Exception {
11617         mockHasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, true);
11618 
11619         // Build OemNetworkPreferences object
11620         final OemNetworkPreferences.Builder builder = new OemNetworkPreferences.Builder();
11621         for (final String packageName : testPackageNames) {
11622             builder.addNetworkPreference(packageName, networkPrefToSetup);
11623         }
11624         final OemNetworkPreferences pref = builder.build();
11625 
11626         // Act on ConnectivityService.setOemNetworkPreference()
11627         final TestOemListenerCallback oemPrefListener = new TestOemListenerCallback();
11628         mService.setOemNetworkPreference(pref, oemPrefListener);
11629 
11630         // Verify call returned successfully
11631         oemPrefListener.expectOnComplete();
11632     }
11633 
11634     private static class TestOemListenerCallback implements IOnCompleteListener {
11635         final CompletableFuture<Object> mDone = new CompletableFuture<>();
11636 
11637         @Override
11638         public void onComplete() {
11639             mDone.complete(new Object());
11640         }
11641 
11642         void expectOnComplete() {
11643             try {
11644                 mDone.get(TIMEOUT_MS, TimeUnit.MILLISECONDS);
11645             } catch (TimeoutException e) {
11646                 fail("Expected onComplete() not received after " + TIMEOUT_MS + " ms");
11647             } catch (Exception e) {
11648                 fail(e.getMessage());
11649             }
11650         }
11651 
11652         @Override
11653         public IBinder asBinder() {
11654             return null;
11655         }
11656     }
11657 
11658     @Test
11659     public void testMultiDefaultGetActiveNetworkIsCorrect() throws Exception {
11660         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
11661                 OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY;
11662         final int expectedOemPrefRequestSize = 1;
11663         registerDefaultNetworkCallbacks();
11664 
11665         // Setup the test process to use networkPref for their default network.
11666         setupMultipleDefaultNetworksForOemNetworkPreferenceCurrentUidTest(networkPref);
11667 
11668         // Bring up ethernet with OEM_PAID. This will satisfy NET_CAPABILITY_OEM_PAID.
11669         // The active network for the default should be null at this point as this is a retricted
11670         // network.
11671         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, true);
11672         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
11673                 null,
11674                 mEthernetNetworkAgent.getNetwork());
11675 
11676         // Verify that the active network is correct
11677         verifyActiveNetwork(TRANSPORT_ETHERNET);
11678         // default NCs will be unregistered in tearDown
11679     }
11680 
11681     @Test
11682     public void testMultiDefaultIsActiveNetworkMeteredIsCorrect() throws Exception {
11683         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
11684                 OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY;
11685         final int expectedOemPrefRequestSize = 1;
11686         registerDefaultNetworkCallbacks();
11687 
11688         // Setup the test process to use networkPref for their default network.
11689         setupMultipleDefaultNetworksForOemNetworkPreferenceCurrentUidTest(networkPref);
11690 
11691         // Returns true by default when no network is available.
11692         assertTrue(mCm.isActiveNetworkMetered());
11693 
11694         // Connect to an unmetered restricted network that will only be available to the OEM pref.
11695         mEthernetNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
11696         mEthernetNetworkAgent.addCapability(NET_CAPABILITY_OEM_PAID);
11697         mEthernetNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
11698         mEthernetNetworkAgent.removeCapability(NET_CAPABILITY_NOT_RESTRICTED);
11699         mEthernetNetworkAgent.connect(true);
11700         waitForIdle();
11701 
11702         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
11703                 null,
11704                 mEthernetNetworkAgent.getNetwork());
11705 
11706         assertFalse(mCm.isActiveNetworkMetered());
11707         // default NCs will be unregistered in tearDown
11708     }
11709 
11710     @Test
11711     public void testPerAppDefaultRegisterDefaultNetworkCallback() throws Exception {
11712         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
11713                 OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY;
11714         final int expectedOemPrefRequestSize = 1;
11715         final TestNetworkCallback defaultNetworkCallback = new TestNetworkCallback();
11716 
11717         // Register the default network callback before the pref is already set. This means that
11718         // the policy will be applied to the callback on setOemNetworkPreference().
11719         mCm.registerDefaultNetworkCallback(defaultNetworkCallback);
11720         defaultNetworkCallback.assertNoCallback();
11721 
11722         final TestNetworkCallback otherUidDefaultCallback = new TestNetworkCallback();
11723         withPermission(NETWORK_SETTINGS, () ->
11724                 mCm.registerDefaultNetworkCallbackForUid(TEST_PACKAGE_UID, otherUidDefaultCallback,
11725                         new Handler(ConnectivityThread.getInstanceLooper())));
11726 
11727         // Setup the test process to use networkPref for their default network.
11728         setupMultipleDefaultNetworksForOemNetworkPreferenceCurrentUidTest(networkPref);
11729 
11730         // Bring up ethernet with OEM_PAID. This will satisfy NET_CAPABILITY_OEM_PAID.
11731         // The active nai for the default is null at this point as this is a restricted network.
11732         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, true);
11733         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
11734                 null,
11735                 mEthernetNetworkAgent.getNetwork());
11736 
11737         // At this point with a restricted network used, the available callback should trigger.
11738         defaultNetworkCallback.expectAvailableThenValidatedCallbacks(mEthernetNetworkAgent);
11739         assertEquals(defaultNetworkCallback.getLastAvailableNetwork(),
11740                 mEthernetNetworkAgent.getNetwork());
11741         otherUidDefaultCallback.assertNoCallback();
11742 
11743         // Now bring down the default network which should trigger a LOST callback.
11744         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, false);
11745 
11746         // At this point, with no network is available, the lost callback should trigger
11747         defaultNetworkCallback.expectCallback(CallbackEntry.LOST, mEthernetNetworkAgent);
11748         otherUidDefaultCallback.assertNoCallback();
11749 
11750         // Confirm we can unregister without issues.
11751         mCm.unregisterNetworkCallback(defaultNetworkCallback);
11752         mCm.unregisterNetworkCallback(otherUidDefaultCallback);
11753     }
11754 
11755     @Test
11756     public void testPerAppDefaultRegisterDefaultNetworkCallbackAfterPrefSet() throws Exception {
11757         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
11758                 OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY;
11759         final int expectedOemPrefRequestSize = 1;
11760         final TestNetworkCallback defaultNetworkCallback = new TestNetworkCallback();
11761 
11762         // Setup the test process to use networkPref for their default network.
11763         setupMultipleDefaultNetworksForOemNetworkPreferenceCurrentUidTest(networkPref);
11764 
11765         // Register the default network callback after the pref is already set. This means that
11766         // the policy will be applied to the callback on requestNetwork().
11767         mCm.registerDefaultNetworkCallback(defaultNetworkCallback);
11768         defaultNetworkCallback.assertNoCallback();
11769 
11770         final TestNetworkCallback otherUidDefaultCallback = new TestNetworkCallback();
11771         withPermission(NETWORK_SETTINGS, () ->
11772                 mCm.registerDefaultNetworkCallbackForUid(TEST_PACKAGE_UID, otherUidDefaultCallback,
11773                         new Handler(ConnectivityThread.getInstanceLooper())));
11774 
11775         // Bring up ethernet with OEM_PAID. This will satisfy NET_CAPABILITY_OEM_PAID.
11776         // The active nai for the default is null at this point as this is a restricted network.
11777         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, true);
11778         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
11779                 null,
11780                 mEthernetNetworkAgent.getNetwork());
11781 
11782         // At this point with a restricted network used, the available callback should trigger
11783         defaultNetworkCallback.expectAvailableThenValidatedCallbacks(mEthernetNetworkAgent);
11784         assertEquals(defaultNetworkCallback.getLastAvailableNetwork(),
11785                 mEthernetNetworkAgent.getNetwork());
11786         otherUidDefaultCallback.assertNoCallback();
11787 
11788         // Now bring down the default network which should trigger a LOST callback.
11789         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, false);
11790         otherUidDefaultCallback.assertNoCallback();
11791 
11792         // At this point, with no network is available, the lost callback should trigger
11793         defaultNetworkCallback.expectCallback(CallbackEntry.LOST, mEthernetNetworkAgent);
11794         otherUidDefaultCallback.assertNoCallback();
11795 
11796         // Confirm we can unregister without issues.
11797         mCm.unregisterNetworkCallback(defaultNetworkCallback);
11798         mCm.unregisterNetworkCallback(otherUidDefaultCallback);
11799     }
11800 
11801     @Test
11802     public void testPerAppDefaultRegisterDefaultNetworkCallbackDoesNotFire() throws Exception {
11803         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
11804                 OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY;
11805         final int expectedOemPrefRequestSize = 1;
11806         final TestNetworkCallback defaultNetworkCallback = new TestNetworkCallback();
11807         final int userId = UserHandle.getUserId(Process.myUid());
11808 
11809         mCm.registerDefaultNetworkCallback(defaultNetworkCallback);
11810         defaultNetworkCallback.assertNoCallback();
11811 
11812         final TestNetworkCallback otherUidDefaultCallback = new TestNetworkCallback();
11813         withPermission(NETWORK_SETTINGS, () ->
11814                 mCm.registerDefaultNetworkCallbackForUid(TEST_PACKAGE_UID, otherUidDefaultCallback,
11815                         new Handler(ConnectivityThread.getInstanceLooper())));
11816 
11817         // Setup a process different than the test process to use the default network. This means
11818         // that the defaultNetworkCallback won't be tracked by the per-app policy.
11819         setupMultipleDefaultNetworksForOemNetworkPreferenceNotCurrentUidTest(networkPref);
11820 
11821         // Bring up ethernet with OEM_PAID. This will satisfy NET_CAPABILITY_OEM_PAID.
11822         // The active nai for the default is null at this point as this is a restricted network.
11823         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, true);
11824         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
11825                 null,
11826                 mEthernetNetworkAgent.getNetwork());
11827 
11828         // As this callback does not have access to the OEM_PAID network, it will not fire.
11829         defaultNetworkCallback.assertNoCallback();
11830         assertDefaultNetworkCapabilities(userId /* no networks */);
11831 
11832         // The other UID does have access, and gets a callback.
11833         otherUidDefaultCallback.expectAvailableThenValidatedCallbacks(mEthernetNetworkAgent);
11834 
11835         // Bring up unrestricted cellular. This should now satisfy the default network.
11836         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true);
11837         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
11838                 mCellNetworkAgent.getNetwork(),
11839                 mEthernetNetworkAgent.getNetwork());
11840 
11841         // At this point with an unrestricted network used, the available callback should trigger
11842         // The other UID is unaffected and remains on the paid network.
11843         defaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
11844         assertEquals(defaultNetworkCallback.getLastAvailableNetwork(),
11845                 mCellNetworkAgent.getNetwork());
11846         assertDefaultNetworkCapabilities(userId, mCellNetworkAgent);
11847         otherUidDefaultCallback.assertNoCallback();
11848 
11849         // Now bring down the per-app network.
11850         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, false);
11851 
11852         // Since the callback didn't use the per-app network, only the other UID gets a callback.
11853         // Because the preference specifies no fallback, it does not switch to cellular.
11854         defaultNetworkCallback.assertNoCallback();
11855         otherUidDefaultCallback.expectCallback(CallbackEntry.LOST, mEthernetNetworkAgent);
11856 
11857         // Now bring down the default network.
11858         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, false);
11859 
11860         // As this callback was tracking the default, this should now trigger.
11861         defaultNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
11862         otherUidDefaultCallback.assertNoCallback();
11863 
11864         // Confirm we can unregister without issues.
11865         mCm.unregisterNetworkCallback(defaultNetworkCallback);
11866         mCm.unregisterNetworkCallback(otherUidDefaultCallback);
11867     }
11868 
11869     /**
11870      * This method assumes that the same uidRanges input will be used to verify that dependencies
11871      * are called as expected.
11872      */
11873     private void verifySetOemNetworkPreferenceForPreference(
11874             @NonNull final UidRangeParcel[] uidRanges,
11875             final int addUidRangesNetId,
11876             final int addUidRangesTimes,
11877             final int removeUidRangesNetId,
11878             final int removeUidRangesTimes,
11879             final boolean shouldDestroyNetwork) throws RemoteException {
11880         verifySetOemNetworkPreferenceForPreference(uidRanges, uidRanges,
11881                 addUidRangesNetId, addUidRangesTimes, removeUidRangesNetId, removeUidRangesTimes,
11882                 shouldDestroyNetwork);
11883     }
11884 
11885     private void verifySetOemNetworkPreferenceForPreference(
11886             @NonNull final UidRangeParcel[] addedUidRanges,
11887             @NonNull final UidRangeParcel[] removedUidRanges,
11888             final int addUidRangesNetId,
11889             final int addUidRangesTimes,
11890             final int removeUidRangesNetId,
11891             final int removeUidRangesTimes,
11892             final boolean shouldDestroyNetwork) throws RemoteException {
11893         final boolean useAnyIdForAdd = OEM_PREF_ANY_NET_ID == addUidRangesNetId;
11894         final boolean useAnyIdForRemove = OEM_PREF_ANY_NET_ID == removeUidRangesNetId;
11895 
11896         // Validate that add/remove uid range (with oem priority) to/from netd.
11897         verify(mMockNetd, times(addUidRangesTimes)).networkAddUidRangesParcel(argThat(config ->
11898                 (useAnyIdForAdd ? true : addUidRangesNetId == config.netId)
11899                         && Arrays.equals(addedUidRanges, config.uidRanges)
11900                         && PREFERENCE_PRIORITY_OEM == config.subPriority));
11901         verify(mMockNetd, times(removeUidRangesTimes)).networkRemoveUidRangesParcel(
11902                 argThat(config -> (useAnyIdForRemove ? true : removeUidRangesNetId == config.netId)
11903                         && Arrays.equals(removedUidRanges, config.uidRanges)
11904                         && PREFERENCE_PRIORITY_OEM == config.subPriority));
11905         if (shouldDestroyNetwork) {
11906             verify(mMockNetd, times(1))
11907                     .networkDestroy((useAnyIdForRemove ? anyInt() : eq(removeUidRangesNetId)));
11908         }
11909         reset(mMockNetd);
11910     }
11911 
11912     /**
11913      * Test the tracked default requests allows test requests without standard setup.
11914      */
11915     @Test
11916     public void testSetOemNetworkPreferenceAllowsValidTestRequestWithoutChecks() throws Exception {
11917         @OemNetworkPreferences.OemNetworkPreference int networkPref =
11918                 OEM_NETWORK_PREFERENCE_TEST;
11919         validateSetOemNetworkPreferenceAllowsValidTestPrefRequest(networkPref);
11920     }
11921 
11922     /**
11923      * Test the tracked default requests allows test only requests without standard setup.
11924      */
11925     @Test
11926     public void testSetOemNetworkPreferenceAllowsValidTestOnlyRequestWithoutChecks()
11927             throws Exception {
11928         @OemNetworkPreferences.OemNetworkPreference int networkPref =
11929                 OEM_NETWORK_PREFERENCE_TEST_ONLY;
11930         validateSetOemNetworkPreferenceAllowsValidTestPrefRequest(networkPref);
11931     }
11932 
11933     private void validateSetOemNetworkPreferenceAllowsValidTestPrefRequest(int networkPref)
11934             throws Exception {
11935         // The caller must have the MANAGE_TEST_NETWORKS permission.
11936         final int testPackageUid = 123;
11937         final String validTestPackageName = "does.not.matter";
11938         final UidRangeParcel[] uidRanges =
11939                 toUidRangeStableParcels(uidRangesForUids(testPackageUid));
11940         mServiceContext.setPermission(
11941                 Manifest.permission.MANAGE_TEST_NETWORKS, PERMISSION_GRANTED);
11942 
11943         // Put the system into a state in which setOemNetworkPreference() would normally fail. This
11944         // will confirm that a valid test request can bypass these checks.
11945         mockHasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, false);
11946         mServiceContext.setPermission(
11947                 Manifest.permission.CONTROL_OEM_PAID_NETWORK_PREFERENCE, PERMISSION_DENIED);
11948 
11949         // Validate the starting requests only includes the system default request.
11950         assertEquals(1, mService.mDefaultNetworkRequests.size());
11951 
11952         // Add an OEM default network request to track.
11953         setupSetOemNetworkPreferenceForPreferenceTest(
11954                 networkPref, uidRanges, validTestPackageName, PRIMARY_USER_HANDLE,
11955                 false /* hasAutomotiveFeature */);
11956 
11957         // Two requests should now exist; the system default and the test request.
11958         assertEquals(2, mService.mDefaultNetworkRequests.size());
11959     }
11960 
11961     /**
11962      * Test the tracked default requests clear previous OEM requests on setOemNetworkPreference().
11963      */
11964     @Test
11965     public void testSetOemNetworkPreferenceClearPreviousOemValues() throws Exception {
11966         @OemNetworkPreferences.OemNetworkPreference int networkPref =
11967                 OEM_NETWORK_PREFERENCE_OEM_PAID;
11968         final int testPackageUid = 123;
11969         final String testPackageName = "com.google.apps.contacts";
11970         final UidRangeParcel[] uidRanges =
11971                 toUidRangeStableParcels(uidRangesForUids(testPackageUid));
11972 
11973         // Validate the starting requests only includes the system default request.
11974         assertEquals(1, mService.mDefaultNetworkRequests.size());
11975 
11976         // Add an OEM default network request to track.
11977         setupSetOemNetworkPreferenceForPreferenceTest(networkPref, uidRanges, testPackageName);
11978 
11979         // Two requests should exist, one for the fallback and one for the pref.
11980         assertEquals(2, mService.mDefaultNetworkRequests.size());
11981 
11982         networkPref = OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY;
11983         setupSetOemNetworkPreferenceForPreferenceTest(networkPref, uidRanges, testPackageName);
11984 
11985         // Two requests should still exist validating the previous per-app request was replaced.
11986         assertEquals(2, mService.mDefaultNetworkRequests.size());
11987     }
11988 
11989     /**
11990      * Test network priority for preference OEM_NETWORK_PREFERENCE_OEM_PAID in the following order:
11991      * NET_CAPABILITY_NOT_METERED -> NET_CAPABILITY_OEM_PAID -> fallback
11992      */
11993     @Test
11994     public void testMultilayerForPreferenceOemPaidEvaluatesCorrectly()
11995             throws Exception {
11996         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
11997                 OEM_NETWORK_PREFERENCE_OEM_PAID;
11998 
11999         // Arrange PackageManager mocks
12000         final UidRangeParcel[] uidRanges =
12001                 toUidRangeStableParcels(uidRangesForUids(TEST_PACKAGE_UID));
12002         setupSetOemNetworkPreferenceForPreferenceTest(networkPref, uidRanges, TEST_PACKAGE_NAME);
12003 
12004         // Verify the starting state. No networks should be connected.
12005         verifySetOemNetworkPreferenceForPreference(uidRanges,
12006                 OEM_PREF_ANY_NET_ID, 0 /* times */,
12007                 OEM_PREF_ANY_NET_ID, 0 /* times */,
12008                 false /* shouldDestroyNetwork */);
12009 
12010         // Test lowest to highest priority requests.
12011         // Bring up metered cellular. This will satisfy the fallback network.
12012         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true);
12013         verifySetOemNetworkPreferenceForPreference(uidRanges,
12014                 mCellNetworkAgent.getNetwork().netId, 1 /* times */,
12015                 OEM_PREF_ANY_NET_ID, 0 /* times */,
12016                 false /* shouldDestroyNetwork */);
12017 
12018         // Bring up ethernet with OEM_PAID. This will satisfy NET_CAPABILITY_OEM_PAID.
12019         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, true);
12020         verifySetOemNetworkPreferenceForPreference(uidRanges,
12021                 mEthernetNetworkAgent.getNetwork().netId, 1 /* times */,
12022                 mCellNetworkAgent.getNetwork().netId, 1 /* times */,
12023                 false /* shouldDestroyNetwork */);
12024 
12025         // Bring up unmetered Wi-Fi. This will satisfy NET_CAPABILITY_NOT_METERED.
12026         setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, true);
12027         verifySetOemNetworkPreferenceForPreference(uidRanges,
12028                 mWiFiNetworkAgent.getNetwork().netId, 1 /* times */,
12029                 mEthernetNetworkAgent.getNetwork().netId, 1 /* times */,
12030                 false /* shouldDestroyNetwork */);
12031 
12032         // Disconnecting OEM_PAID should have no effect as it is lower in priority then unmetered.
12033         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, false);
12034         // netd should not be called as default networks haven't changed.
12035         verifySetOemNetworkPreferenceForPreference(uidRanges,
12036                 OEM_PREF_ANY_NET_ID, 0 /* times */,
12037                 OEM_PREF_ANY_NET_ID, 0 /* times */,
12038                 false /* shouldDestroyNetwork */);
12039 
12040         // Disconnecting unmetered should put PANS on lowest priority fallback request.
12041         setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, false);
12042         verifySetOemNetworkPreferenceForPreference(uidRanges,
12043                 mCellNetworkAgent.getNetwork().netId, 1 /* times */,
12044                 mWiFiNetworkAgent.getNetwork().netId, 0 /* times */,
12045                 true /* shouldDestroyNetwork */);
12046 
12047         // Disconnecting the fallback network should result in no connectivity.
12048         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, false);
12049         verifySetOemNetworkPreferenceForPreference(uidRanges,
12050                 OEM_PREF_ANY_NET_ID, 0 /* times */,
12051                 mCellNetworkAgent.getNetwork().netId, 0 /* times */,
12052                 true /* shouldDestroyNetwork */);
12053     }
12054 
12055     /**
12056      * Test network priority for OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK in the following order:
12057      * NET_CAPABILITY_NOT_METERED -> NET_CAPABILITY_OEM_PAID
12058      */
12059     @Test
12060     public void testMultilayerForPreferenceOemPaidNoFallbackEvaluatesCorrectly()
12061             throws Exception {
12062         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
12063                 OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK;
12064 
12065         // Arrange PackageManager mocks
12066         final UidRangeParcel[] uidRanges =
12067                 toUidRangeStableParcels(uidRangesForUids(TEST_PACKAGE_UID));
12068         setupSetOemNetworkPreferenceForPreferenceTest(networkPref, uidRanges, TEST_PACKAGE_NAME);
12069 
12070         // Verify the starting state. This preference doesn't support using the fallback network
12071         // therefore should be on the disconnected network as it has no networks to connect to.
12072         verifySetOemNetworkPreferenceForPreference(uidRanges,
12073                 mService.mNoServiceNetwork.network.getNetId(), 1 /* times */,
12074                 OEM_PREF_ANY_NET_ID, 0 /* times */,
12075                 false /* shouldDestroyNetwork */);
12076 
12077         // Test lowest to highest priority requests.
12078         // Bring up metered cellular. This will satisfy the fallback network.
12079         // This preference should not use this network as it doesn't support fallback usage.
12080         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true);
12081         verifySetOemNetworkPreferenceForPreference(uidRanges,
12082                 OEM_PREF_ANY_NET_ID, 0 /* times */,
12083                 OEM_PREF_ANY_NET_ID, 0 /* times */,
12084                 false /* shouldDestroyNetwork */);
12085 
12086         // Bring up ethernet with OEM_PAID. This will satisfy NET_CAPABILITY_OEM_PAID.
12087         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, true);
12088         verifySetOemNetworkPreferenceForPreference(uidRanges,
12089                 mEthernetNetworkAgent.getNetwork().netId, 1 /* times */,
12090                 mService.mNoServiceNetwork.network.getNetId(), 1 /* times */,
12091                 false /* shouldDestroyNetwork */);
12092 
12093         // Bring up unmetered Wi-Fi. This will satisfy NET_CAPABILITY_NOT_METERED.
12094         setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, true);
12095         verifySetOemNetworkPreferenceForPreference(uidRanges,
12096                 mWiFiNetworkAgent.getNetwork().netId, 1 /* times */,
12097                 mEthernetNetworkAgent.getNetwork().netId, 1 /* times */,
12098                 false /* shouldDestroyNetwork */);
12099 
12100         // Disconnecting unmetered should put PANS on OEM_PAID.
12101         setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, false);
12102         verifySetOemNetworkPreferenceForPreference(uidRanges,
12103                 mEthernetNetworkAgent.getNetwork().netId, 1 /* times */,
12104                 mWiFiNetworkAgent.getNetwork().netId, 0 /* times */,
12105                 true /* shouldDestroyNetwork */);
12106 
12107         // Disconnecting OEM_PAID should result in no connectivity.
12108         // OEM_PAID_NO_FALLBACK not supporting a fallback now uses the disconnected network.
12109         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, false);
12110         verifySetOemNetworkPreferenceForPreference(uidRanges,
12111                 mService.mNoServiceNetwork.network.getNetId(), 1 /* times */,
12112                 mEthernetNetworkAgent.getNetwork().netId, 0 /* times */,
12113                 true /* shouldDestroyNetwork */);
12114     }
12115 
12116     /**
12117      * Test network priority for OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY in the following order:
12118      * NET_CAPABILITY_OEM_PAID
12119      * This preference should only apply to OEM_PAID networks.
12120      */
12121     @Test
12122     public void testMultilayerForPreferenceOemPaidOnlyEvaluatesCorrectly()
12123             throws Exception {
12124         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
12125                 OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY;
12126 
12127         // Arrange PackageManager mocks
12128         final UidRangeParcel[] uidRanges =
12129                 toUidRangeStableParcels(uidRangesForUids(TEST_PACKAGE_UID));
12130         setupSetOemNetworkPreferenceForPreferenceTest(networkPref, uidRanges, TEST_PACKAGE_NAME);
12131 
12132         // Verify the starting state. This preference doesn't support using the fallback network
12133         // therefore should be on the disconnected network as it has no networks to connect to.
12134         verifySetOemNetworkPreferenceForPreference(uidRanges,
12135                 mService.mNoServiceNetwork.network.getNetId(), 1 /* times */,
12136                 OEM_PREF_ANY_NET_ID, 0 /* times */,
12137                 false /* shouldDestroyNetwork */);
12138 
12139         // Bring up metered cellular. This should not apply to this preference.
12140         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true);
12141         verifySetOemNetworkPreferenceForPreference(uidRanges,
12142                 OEM_PREF_ANY_NET_ID, 0 /* times */,
12143                 OEM_PREF_ANY_NET_ID, 0 /* times */,
12144                 false /* shouldDestroyNetwork */);
12145 
12146         // Bring up unmetered Wi-Fi. This should not apply to this preference.
12147         setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, true);
12148         verifySetOemNetworkPreferenceForPreference(uidRanges,
12149                 OEM_PREF_ANY_NET_ID, 0 /* times */,
12150                 OEM_PREF_ANY_NET_ID, 0 /* times */,
12151                 false /* shouldDestroyNetwork */);
12152 
12153         // Bring up ethernet with OEM_PAID. This will satisfy NET_CAPABILITY_OEM_PAID.
12154         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, true);
12155         verifySetOemNetworkPreferenceForPreference(uidRanges,
12156                 mEthernetNetworkAgent.getNetwork().netId, 1 /* times */,
12157                 mService.mNoServiceNetwork.network.getNetId(), 1 /* times */,
12158                 false /* shouldDestroyNetwork */);
12159 
12160         // Disconnecting OEM_PAID should result in no connectivity.
12161         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, false);
12162         verifySetOemNetworkPreferenceForPreference(uidRanges,
12163                 mService.mNoServiceNetwork.network.getNetId(), 1 /* times */,
12164                 mEthernetNetworkAgent.getNetwork().netId, 0 /* times */,
12165                 true /* shouldDestroyNetwork */);
12166     }
12167 
12168     /**
12169      * Test network priority for OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY in the following order:
12170      * NET_CAPABILITY_OEM_PRIVATE
12171      * This preference should only apply to OEM_PRIVATE networks.
12172      */
12173     @Test
12174     public void testMultilayerForPreferenceOemPrivateOnlyEvaluatesCorrectly()
12175             throws Exception {
12176         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
12177                 OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY;
12178 
12179         // Arrange PackageManager mocks
12180         final UidRangeParcel[] uidRanges =
12181                 toUidRangeStableParcels(uidRangesForUids(TEST_PACKAGE_UID));
12182         setupSetOemNetworkPreferenceForPreferenceTest(networkPref, uidRanges, TEST_PACKAGE_NAME);
12183 
12184         // Verify the starting state. This preference doesn't support using the fallback network
12185         // therefore should be on the disconnected network as it has no networks to connect to.
12186         verifySetOemNetworkPreferenceForPreference(uidRanges,
12187                 mService.mNoServiceNetwork.network.getNetId(), 1 /* times */,
12188                 OEM_PREF_ANY_NET_ID, 0 /* times */,
12189                 false /* shouldDestroyNetwork */);
12190 
12191         // Bring up metered cellular. This should not apply to this preference.
12192         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true);
12193         verifySetOemNetworkPreferenceForPreference(uidRanges,
12194                 OEM_PREF_ANY_NET_ID, 0 /* times */,
12195                 OEM_PREF_ANY_NET_ID, 0 /* times */,
12196                 false /* shouldDestroyNetwork */);
12197 
12198         // Bring up unmetered Wi-Fi. This should not apply to this preference.
12199         setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, true);
12200         verifySetOemNetworkPreferenceForPreference(uidRanges,
12201                 OEM_PREF_ANY_NET_ID, 0 /* times */,
12202                 OEM_PREF_ANY_NET_ID, 0 /* times */,
12203                 false /* shouldDestroyNetwork */);
12204 
12205         // Bring up ethernet with OEM_PRIVATE. This will satisfy NET_CAPABILITY_OEM_PRIVATE.
12206         startOemManagedNetwork(false);
12207         verifySetOemNetworkPreferenceForPreference(uidRanges,
12208                 mEthernetNetworkAgent.getNetwork().netId, 1 /* times */,
12209                 mService.mNoServiceNetwork.network.getNetId(), 1 /* times */,
12210                 false /* shouldDestroyNetwork */);
12211 
12212         // Disconnecting OEM_PRIVATE should result in no connectivity.
12213         stopOemManagedNetwork();
12214         verifySetOemNetworkPreferenceForPreference(uidRanges,
12215                 mService.mNoServiceNetwork.network.getNetId(), 1 /* times */,
12216                 mEthernetNetworkAgent.getNetwork().netId, 0 /* times */,
12217                 true /* shouldDestroyNetwork */);
12218     }
12219 
12220     @Test
12221     public void testMultilayerForMultipleUsersEvaluatesCorrectly()
12222             throws Exception {
12223         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
12224                 OEM_NETWORK_PREFERENCE_OEM_PAID;
12225 
12226         // Arrange users
12227         final int secondUser = 10;
12228         final UserHandle secondUserHandle = new UserHandle(secondUser);
12229         when(mUserManager.getUserHandles(anyBoolean())).thenReturn(
12230                 Arrays.asList(PRIMARY_USER_HANDLE, secondUserHandle));
12231 
12232         // Arrange PackageManager mocks
12233         final int secondUserTestPackageUid = UserHandle.getUid(secondUser, TEST_PACKAGE_UID);
12234         final UidRangeParcel[] uidRanges =
12235                 toUidRangeStableParcels(
12236                         uidRangesForUids(TEST_PACKAGE_UID, secondUserTestPackageUid));
12237         mockGetApplicationInfo(TEST_PACKAGE_NAME, secondUserTestPackageUid, secondUserHandle);
12238         setupSetOemNetworkPreferenceForPreferenceTest(networkPref, uidRanges, TEST_PACKAGE_NAME);
12239 
12240         // Verify the starting state. No networks should be connected.
12241         verifySetOemNetworkPreferenceForPreference(uidRanges,
12242                 OEM_PREF_ANY_NET_ID, 0 /* times */,
12243                 OEM_PREF_ANY_NET_ID, 0 /* times */,
12244                 false /* shouldDestroyNetwork */);
12245 
12246         // Test that we correctly add the expected values for multiple users.
12247         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true);
12248         verifySetOemNetworkPreferenceForPreference(uidRanges,
12249                 mCellNetworkAgent.getNetwork().netId, 1 /* times */,
12250                 OEM_PREF_ANY_NET_ID, 0 /* times */,
12251                 false /* shouldDestroyNetwork */);
12252 
12253         // Test that we correctly remove the expected values for multiple users.
12254         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, false);
12255         verifySetOemNetworkPreferenceForPreference(uidRanges,
12256                 OEM_PREF_ANY_NET_ID, 0 /* times */,
12257                 mCellNetworkAgent.getNetwork().netId, 0 /* times */,
12258                 true /* shouldDestroyNetwork */);
12259     }
12260 
12261     @Test
12262     public void testMultilayerForBroadcastedUsersEvaluatesCorrectly()
12263             throws Exception {
12264         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
12265                 OEM_NETWORK_PREFERENCE_OEM_PAID;
12266 
12267         // Arrange users
12268         final int secondUser = 10;
12269         final UserHandle secondUserHandle = new UserHandle(secondUser);
12270         when(mUserManager.getUserHandles(anyBoolean())).thenReturn(
12271                 Arrays.asList(PRIMARY_USER_HANDLE));
12272 
12273         // Arrange PackageManager mocks
12274         final int secondUserTestPackageUid = UserHandle.getUid(secondUser, TEST_PACKAGE_UID);
12275         final UidRangeParcel[] uidRangesSingleUser =
12276                 toUidRangeStableParcels(uidRangesForUids(TEST_PACKAGE_UID));
12277         final UidRangeParcel[] uidRangesBothUsers =
12278                 toUidRangeStableParcels(
12279                         uidRangesForUids(TEST_PACKAGE_UID, secondUserTestPackageUid));
12280         mockGetApplicationInfo(TEST_PACKAGE_NAME, secondUserTestPackageUid, secondUserHandle);
12281         setupSetOemNetworkPreferenceForPreferenceTest(
12282                 networkPref, uidRangesSingleUser, TEST_PACKAGE_NAME);
12283 
12284         // Verify the starting state. No networks should be connected.
12285         verifySetOemNetworkPreferenceForPreference(uidRangesSingleUser,
12286                 OEM_PREF_ANY_NET_ID, 0 /* times */,
12287                 OEM_PREF_ANY_NET_ID, 0 /* times */,
12288                 false /* shouldDestroyNetwork */);
12289 
12290         // Test that we correctly add the expected values for multiple users.
12291         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true);
12292         verifySetOemNetworkPreferenceForPreference(uidRangesSingleUser,
12293                 mCellNetworkAgent.getNetwork().netId, 1 /* times */,
12294                 OEM_PREF_ANY_NET_ID, 0 /* times */,
12295                 false /* shouldDestroyNetwork */);
12296 
12297         // Send a broadcast indicating a user was added.
12298         when(mUserManager.getUserHandles(anyBoolean())).thenReturn(
12299                 Arrays.asList(PRIMARY_USER_HANDLE, secondUserHandle));
12300         final Intent addedIntent = new Intent(ACTION_USER_ADDED);
12301         addedIntent.putExtra(Intent.EXTRA_USER, UserHandle.of(secondUser));
12302         processBroadcast(addedIntent);
12303 
12304         // Test that we correctly add values for all users and remove for the single user.
12305         verifySetOemNetworkPreferenceForPreference(uidRangesBothUsers, uidRangesSingleUser,
12306                 mCellNetworkAgent.getNetwork().netId, 1 /* times */,
12307                 mCellNetworkAgent.getNetwork().netId, 1 /* times */,
12308                 false /* shouldDestroyNetwork */);
12309 
12310         // Send a broadcast indicating a user was removed.
12311         when(mUserManager.getUserHandles(anyBoolean())).thenReturn(
12312                 Arrays.asList(PRIMARY_USER_HANDLE));
12313         final Intent removedIntent = new Intent(ACTION_USER_REMOVED);
12314         removedIntent.putExtra(Intent.EXTRA_USER, UserHandle.of(secondUser));
12315         processBroadcast(removedIntent);
12316 
12317         // Test that we correctly add values for the single user and remove for the all users.
12318         verifySetOemNetworkPreferenceForPreference(uidRangesSingleUser, uidRangesBothUsers,
12319                 mCellNetworkAgent.getNetwork().netId, 1 /* times */,
12320                 mCellNetworkAgent.getNetwork().netId, 1 /* times */,
12321                 false /* shouldDestroyNetwork */);
12322     }
12323 
12324     @Test
12325     public void testMultilayerForPackageChangesEvaluatesCorrectly()
12326             throws Exception {
12327         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
12328                 OEM_NETWORK_PREFERENCE_OEM_PAID;
12329         final String packageScheme = "package:";
12330 
12331         // Arrange PackageManager mocks
12332         final String packageToInstall = "package.to.install";
12333         final int packageToInstallUid = 81387;
12334         final UidRangeParcel[] uidRangesSinglePackage =
12335                 toUidRangeStableParcels(uidRangesForUids(TEST_PACKAGE_UID));
12336         mockGetApplicationInfo(TEST_PACKAGE_NAME, TEST_PACKAGE_UID);
12337         mockGetApplicationInfoThrowsNameNotFound(packageToInstall, PRIMARY_USER_HANDLE);
12338         setOemNetworkPreference(networkPref, TEST_PACKAGE_NAME, packageToInstall);
12339         grantUsingBackgroundNetworksPermissionForUid(Binder.getCallingUid(), packageToInstall);
12340 
12341         // Verify the starting state. No networks should be connected.
12342         verifySetOemNetworkPreferenceForPreference(uidRangesSinglePackage,
12343                 OEM_PREF_ANY_NET_ID, 0 /* times */,
12344                 OEM_PREF_ANY_NET_ID, 0 /* times */,
12345                 false /* shouldDestroyNetwork */);
12346 
12347         // Test that we correctly add the expected values for installed packages.
12348         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true);
12349         verifySetOemNetworkPreferenceForPreference(uidRangesSinglePackage,
12350                 mCellNetworkAgent.getNetwork().netId, 1 /* times */,
12351                 OEM_PREF_ANY_NET_ID, 0 /* times */,
12352                 false /* shouldDestroyNetwork */);
12353 
12354         // Set the system to recognize the package to be installed
12355         mockGetApplicationInfo(packageToInstall, packageToInstallUid);
12356         final UidRangeParcel[] uidRangesAllPackages =
12357                 toUidRangeStableParcels(uidRangesForUids(TEST_PACKAGE_UID, packageToInstallUid));
12358 
12359         // Send a broadcast indicating a package was installed.
12360         final Intent addedIntent = new Intent(ACTION_PACKAGE_ADDED);
12361         addedIntent.setData(Uri.parse(packageScheme + packageToInstall));
12362         processBroadcast(addedIntent);
12363 
12364         // Test the single package is removed and the combined packages are added.
12365         verifySetOemNetworkPreferenceForPreference(uidRangesAllPackages, uidRangesSinglePackage,
12366                 mCellNetworkAgent.getNetwork().netId, 1 /* times */,
12367                 mCellNetworkAgent.getNetwork().netId, 1 /* times */,
12368                 false /* shouldDestroyNetwork */);
12369 
12370         // Set the system to no longer recognize the package to be installed
12371         mockGetApplicationInfoThrowsNameNotFound(packageToInstall, PRIMARY_USER_HANDLE);
12372 
12373         // Send a broadcast indicating a package was removed.
12374         final Intent removedIntent = new Intent(ACTION_PACKAGE_REMOVED);
12375         removedIntent.setData(Uri.parse(packageScheme + packageToInstall));
12376         processBroadcast(removedIntent);
12377 
12378         // Test the combined packages are removed and the single package is added.
12379         verifySetOemNetworkPreferenceForPreference(uidRangesSinglePackage, uidRangesAllPackages,
12380                 mCellNetworkAgent.getNetwork().netId, 1 /* times */,
12381                 mCellNetworkAgent.getNetwork().netId, 1 /* times */,
12382                 false /* shouldDestroyNetwork */);
12383 
12384         // Set the system to change the installed package's uid
12385         final int replacedTestPackageUid = TEST_PACKAGE_UID + 1;
12386         mockGetApplicationInfo(TEST_PACKAGE_NAME, replacedTestPackageUid);
12387         final UidRangeParcel[] uidRangesReplacedPackage =
12388                 toUidRangeStableParcels(uidRangesForUids(replacedTestPackageUid));
12389 
12390         // Send a broadcast indicating a package was replaced.
12391         final Intent replacedIntent = new Intent(ACTION_PACKAGE_REPLACED);
12392         replacedIntent.setData(Uri.parse(packageScheme + TEST_PACKAGE_NAME));
12393         processBroadcast(replacedIntent);
12394 
12395         // Test the original uid is removed and is replaced with the new uid.
12396         verifySetOemNetworkPreferenceForPreference(uidRangesReplacedPackage, uidRangesSinglePackage,
12397                 mCellNetworkAgent.getNetwork().netId, 1 /* times */,
12398                 mCellNetworkAgent.getNetwork().netId, 1 /* times */,
12399                 false /* shouldDestroyNetwork */);
12400     }
12401 
12402     /**
12403      * Test network priority for preference OEM_NETWORK_PREFERENCE_OEM_PAID in the following order:
12404      * NET_CAPABILITY_NOT_METERED -> NET_CAPABILITY_OEM_PAID -> fallback
12405      */
12406     @Test
12407     public void testMultipleDefaultNetworksTracksOemNetworkPreferenceOemPaidCorrectly()
12408             throws Exception {
12409         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
12410                 OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PAID;
12411         setupMultipleDefaultNetworksForOemNetworkPreferenceCurrentUidTest(networkPref);
12412         final int expectedDefaultRequestSize = 2;
12413         final int expectedOemPrefRequestSize = 3;
12414         registerDefaultNetworkCallbacks();
12415 
12416         // The fallback as well as the OEM preference should now be tracked.
12417         assertEquals(expectedDefaultRequestSize, mService.mDefaultNetworkRequests.size());
12418 
12419         // Test lowest to highest priority requests.
12420         // Bring up metered cellular. This will satisfy the fallback network.
12421         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true);
12422         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
12423                 mCellNetworkAgent.getNetwork(),
12424                 mCellNetworkAgent.getNetwork());
12425 
12426         // Bring up ethernet with OEM_PAID. This will satisfy NET_CAPABILITY_OEM_PAID.
12427         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, true);
12428         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
12429                 mCellNetworkAgent.getNetwork(),
12430                 mEthernetNetworkAgent.getNetwork());
12431 
12432         // Bring up unmetered Wi-Fi. This will satisfy NET_CAPABILITY_NOT_METERED.
12433         setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, true);
12434         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
12435                 mWiFiNetworkAgent.getNetwork(),
12436                 mWiFiNetworkAgent.getNetwork());
12437 
12438         // Disconnecting unmetered Wi-Fi will put the pref on OEM_PAID and fallback on cellular.
12439         setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, false);
12440         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
12441                 mCellNetworkAgent.getNetwork(),
12442                 mEthernetNetworkAgent.getNetwork());
12443 
12444         // Disconnecting cellular should keep OEM network on OEM_PAID and fallback will be null.
12445         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, false);
12446         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
12447                 null,
12448                 mEthernetNetworkAgent.getNetwork());
12449 
12450         // Disconnecting OEM_PAID will put both on null as it is the last network.
12451         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, false);
12452         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
12453                 null,
12454                 null);
12455 
12456         // default callbacks will be unregistered in tearDown
12457     }
12458 
12459     @Test
12460     public void testNetworkFactoryRequestsWithMultilayerRequest()
12461             throws Exception {
12462         // First use OEM_PAID preference to create a multi-layer request : 1. listen for
12463         // unmetered, 2. request network with cap OEM_PAID, 3, request the default network for
12464         // fallback.
12465         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
12466                 OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PAID;
12467         setupMultipleDefaultNetworksForOemNetworkPreferenceCurrentUidTest(networkPref);
12468 
12469         final HandlerThread handlerThread = new HandlerThread("MockFactory");
12470         handlerThread.start();
12471         NetworkCapabilities internetFilter = new NetworkCapabilities()
12472                 .addCapability(NET_CAPABILITY_INTERNET)
12473                 .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED);
12474         final MockNetworkFactory internetFactory = new MockNetworkFactory(handlerThread.getLooper(),
12475                 mServiceContext, "internetFactory", internetFilter, mCsHandlerThread);
12476         internetFactory.setScoreFilter(40);
12477         internetFactory.register();
12478         // Default internet request only. The unmetered request is never sent to factories (it's a
12479         // LISTEN, not requestable). The 3rd (fallback) request in OEM_PAID NRI is TRACK_DEFAULT
12480         // which is also not sent to factories. Finally, the OEM_PAID request doesn't match the
12481         // internetFactory filter.
12482         internetFactory.expectRequestAdds(1);
12483         internetFactory.assertRequestCountEquals(1);
12484 
12485         NetworkCapabilities oemPaidFilter = new NetworkCapabilities()
12486                 .addCapability(NET_CAPABILITY_INTERNET)
12487                 .addCapability(NET_CAPABILITY_OEM_PAID)
12488                 .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
12489                 .removeCapability(NET_CAPABILITY_NOT_RESTRICTED);
12490         final MockNetworkFactory oemPaidFactory = new MockNetworkFactory(handlerThread.getLooper(),
12491                 mServiceContext, "oemPaidFactory", oemPaidFilter, mCsHandlerThread);
12492         oemPaidFactory.setScoreFilter(40);
12493         oemPaidFactory.register();
12494         oemPaidFactory.expectRequestAdd(); // Because nobody satisfies the request
12495 
12496         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
12497         mCellNetworkAgent.connect(true);
12498 
12499         // A network connected that satisfies the default internet request. For the OEM_PAID
12500         // preference, this is not as good as an OEM_PAID network, so even if the score of
12501         // the network is better than the factory announced, it still should try to bring up
12502         // the network.
12503         expectNoRequestChanged(oemPaidFactory);
12504         oemPaidFactory.assertRequestCountEquals(1);
12505         // The internet factory however is outscored, and should lose its requests.
12506         internetFactory.expectRequestRemove();
12507         internetFactory.assertRequestCountEquals(0);
12508 
12509         final NetworkCapabilities oemPaidNc = new NetworkCapabilities();
12510         oemPaidNc.addCapability(NET_CAPABILITY_OEM_PAID);
12511         oemPaidNc.removeCapability(NET_CAPABILITY_NOT_RESTRICTED);
12512         final TestNetworkAgentWrapper oemPaidAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR,
12513                 new LinkProperties(), oemPaidNc);
12514         oemPaidAgent.connect(true);
12515 
12516         // The oemPaidAgent has score 50/cell transport, so it beats what the oemPaidFactory can
12517         // provide, therefore it loses the request.
12518         oemPaidFactory.expectRequestRemove();
12519         oemPaidFactory.assertRequestCountEquals(0);
12520         expectNoRequestChanged(internetFactory);
12521         internetFactory.assertRequestCountEquals(0);
12522 
12523         oemPaidAgent.setScore(new NetworkScore.Builder().setLegacyInt(20).setExiting(true).build());
12524         // Now the that the agent is weak, the oemPaidFactory can beat the existing network for the
12525         // OEM_PAID request. The internet factory however can't beat a network that has OEM_PAID
12526         // for the preference request, so it doesn't see the request.
12527         oemPaidFactory.expectRequestAdd();
12528         oemPaidFactory.assertRequestCountEquals(1);
12529         expectNoRequestChanged(internetFactory);
12530         internetFactory.assertRequestCountEquals(0);
12531 
12532         mCellNetworkAgent.disconnect();
12533         // The network satisfying the default internet request has disconnected, so the
12534         // internetFactory sees the default request again. However there is a network with OEM_PAID
12535         // connected, so the 2nd OEM_PAID req is already satisfied, so the oemPaidFactory doesn't
12536         // care about networks that don't have OEM_PAID.
12537         expectNoRequestChanged(oemPaidFactory);
12538         oemPaidFactory.assertRequestCountEquals(1);
12539         internetFactory.expectRequestAdd();
12540         internetFactory.assertRequestCountEquals(1);
12541 
12542         // Cell connects again, still with score 50. Back to the previous state.
12543         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
12544         mCellNetworkAgent.connect(true);
12545         expectNoRequestChanged(oemPaidFactory);
12546         oemPaidFactory.assertRequestCountEquals(1);
12547         internetFactory.expectRequestRemove();
12548         internetFactory.assertRequestCountEquals(0);
12549 
12550         // Create a request that holds the upcoming wifi network.
12551         final TestNetworkCallback wifiCallback = new TestNetworkCallback();
12552         mCm.requestNetwork(new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI).build(),
12553                 wifiCallback);
12554 
12555         // Now WiFi connects and it's unmetered, but it's weaker than cell.
12556         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
12557         mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
12558         mWiFiNetworkAgent.setScore(new NetworkScore.Builder().setLegacyInt(30).setExiting(true)
12559                 .build()); // Not the best Internet network, but unmetered
12560         mWiFiNetworkAgent.connect(true);
12561 
12562         // The OEM_PAID preference prefers an unmetered network to an OEM_PAID network, so
12563         // the oemPaidFactory can't beat wifi no matter how high its score.
12564         oemPaidFactory.expectRequestRemove();
12565         expectNoRequestChanged(internetFactory);
12566 
12567         mCellNetworkAgent.disconnect();
12568         // Now that the best internet network (cell, with its 50 score compared to 30 for WiFi
12569         // at this point), the default internet request is satisfied by a network worse than
12570         // the internetFactory announced, so it gets the request. However, there is still an
12571         // unmetered network, so the oemPaidNetworkFactory still can't beat this.
12572         expectNoRequestChanged(oemPaidFactory);
12573         internetFactory.expectRequestAdd();
12574         mCm.unregisterNetworkCallback(wifiCallback);
12575     }
12576 
12577     /**
12578      * Test network priority for OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK in the following order:
12579      * NET_CAPABILITY_NOT_METERED -> NET_CAPABILITY_OEM_PAID
12580      */
12581     @Test
12582     public void testMultipleDefaultNetworksTracksOemNetworkPreferenceOemPaidNoFallbackCorrectly()
12583             throws Exception {
12584         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
12585                 OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK;
12586         setupMultipleDefaultNetworksForOemNetworkPreferenceCurrentUidTest(networkPref);
12587         final int expectedDefaultRequestSize = 2;
12588         final int expectedOemPrefRequestSize = 2;
12589         registerDefaultNetworkCallbacks();
12590 
12591         // The fallback as well as the OEM preference should now be tracked.
12592         assertEquals(expectedDefaultRequestSize, mService.mDefaultNetworkRequests.size());
12593 
12594         // Test lowest to highest priority requests.
12595         // Bring up metered cellular. This will satisfy the fallback network but not the pref.
12596         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true);
12597         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
12598                 mCellNetworkAgent.getNetwork(),
12599                 mService.mNoServiceNetwork.network());
12600 
12601         // Bring up ethernet with OEM_PAID. This will satisfy NET_CAPABILITY_OEM_PAID.
12602         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, true);
12603         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
12604                 mCellNetworkAgent.getNetwork(),
12605                 mEthernetNetworkAgent.getNetwork());
12606 
12607         // Bring up unmetered Wi-Fi. This will satisfy NET_CAPABILITY_NOT_METERED.
12608         setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, true);
12609         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
12610                 mWiFiNetworkAgent.getNetwork(),
12611                 mWiFiNetworkAgent.getNetwork());
12612 
12613         // Disconnecting unmetered Wi-Fi will put the OEM pref on OEM_PAID and fallback on cellular.
12614         setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, false);
12615         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
12616                 mCellNetworkAgent.getNetwork(),
12617                 mEthernetNetworkAgent.getNetwork());
12618 
12619         // Disconnecting cellular should keep OEM network on OEM_PAID and fallback will be null.
12620         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, false);
12621         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
12622                 null,
12623                 mEthernetNetworkAgent.getNetwork());
12624 
12625         // Disconnecting OEM_PAID puts the fallback on null and the pref on the disconnected net.
12626         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, false);
12627         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
12628                 null,
12629                 mService.mNoServiceNetwork.network());
12630 
12631         // default callbacks will be unregistered in tearDown
12632     }
12633 
12634     /**
12635      * Test network priority for OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY in the following order:
12636      * NET_CAPABILITY_OEM_PAID
12637      * This preference should only apply to OEM_PAID networks.
12638      */
12639     @Test
12640     public void testMultipleDefaultNetworksTracksOemNetworkPreferenceOemPaidOnlyCorrectly()
12641             throws Exception {
12642         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
12643                 OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY;
12644         setupMultipleDefaultNetworksForOemNetworkPreferenceCurrentUidTest(networkPref);
12645         final int expectedDefaultRequestSize = 2;
12646         final int expectedOemPrefRequestSize = 1;
12647         registerDefaultNetworkCallbacks();
12648 
12649         // The fallback as well as the OEM preference should now be tracked.
12650         assertEquals(expectedDefaultRequestSize, mService.mDefaultNetworkRequests.size());
12651 
12652         // Test lowest to highest priority requests.
12653         // Bring up metered cellular. This will satisfy the fallback network.
12654         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true);
12655         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
12656                 mCellNetworkAgent.getNetwork(),
12657                 mService.mNoServiceNetwork.network());
12658 
12659         // Bring up ethernet with OEM_PAID. This will satisfy NET_CAPABILITY_OEM_PAID.
12660         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, true);
12661         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
12662                 mCellNetworkAgent.getNetwork(),
12663                 mEthernetNetworkAgent.getNetwork());
12664 
12665         // Bring up unmetered Wi-Fi. The OEM network shouldn't change, the fallback will take Wi-Fi.
12666         setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, true);
12667         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
12668                 mWiFiNetworkAgent.getNetwork(),
12669                 mEthernetNetworkAgent.getNetwork());
12670 
12671         // Disconnecting unmetered Wi-Fi shouldn't change the OEM network with fallback on cellular.
12672         setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, false);
12673         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
12674                 mCellNetworkAgent.getNetwork(),
12675                 mEthernetNetworkAgent.getNetwork());
12676 
12677         // Disconnecting OEM_PAID will keep the fallback on cellular and nothing for OEM_PAID.
12678         // OEM_PAID_ONLY not supporting a fallback now uses the disconnected network.
12679         setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, false);
12680         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
12681                 mCellNetworkAgent.getNetwork(),
12682                 mService.mNoServiceNetwork.network());
12683 
12684         // Disconnecting cellular will put the fallback on null and the pref on disconnected.
12685         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, false);
12686         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
12687                 null,
12688                 mService.mNoServiceNetwork.network());
12689 
12690         // default callbacks will be unregistered in tearDown
12691     }
12692 
12693     /**
12694      * Test network priority for OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY in the following order:
12695      * NET_CAPABILITY_OEM_PRIVATE
12696      * This preference should only apply to OEM_PRIVATE networks.
12697      */
12698     @Test
12699     public void testMultipleDefaultNetworksTracksOemNetworkPreferenceOemPrivateOnlyCorrectly()
12700             throws Exception {
12701         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
12702                 OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY;
12703         setupMultipleDefaultNetworksForOemNetworkPreferenceCurrentUidTest(networkPref);
12704         final int expectedDefaultRequestSize = 2;
12705         final int expectedOemPrefRequestSize = 1;
12706         registerDefaultNetworkCallbacks();
12707 
12708         // The fallback as well as the OEM preference should now be tracked.
12709         assertEquals(expectedDefaultRequestSize, mService.mDefaultNetworkRequests.size());
12710 
12711         // Test lowest to highest priority requests.
12712         // Bring up metered cellular. This will satisfy the fallback network.
12713         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true);
12714         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
12715                 mCellNetworkAgent.getNetwork(),
12716                 mService.mNoServiceNetwork.network());
12717 
12718         // Bring up ethernet with OEM_PRIVATE. This will satisfy NET_CAPABILITY_OEM_PRIVATE.
12719         startOemManagedNetwork(false);
12720         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
12721                 mCellNetworkAgent.getNetwork(),
12722                 mEthernetNetworkAgent.getNetwork());
12723 
12724         // Bring up unmetered Wi-Fi. The OEM network shouldn't change, the fallback will take Wi-Fi.
12725         setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, true);
12726         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
12727                 mWiFiNetworkAgent.getNetwork(),
12728                 mEthernetNetworkAgent.getNetwork());
12729 
12730         // Disconnecting unmetered Wi-Fi shouldn't change the OEM network with fallback on cellular.
12731         setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, false);
12732         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
12733                 mCellNetworkAgent.getNetwork(),
12734                 mEthernetNetworkAgent.getNetwork());
12735 
12736         // Disconnecting OEM_PRIVATE will keep the fallback on cellular.
12737         // OEM_PRIVATE_ONLY not supporting a fallback now uses to the disconnected network.
12738         stopOemManagedNetwork();
12739         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
12740                 mCellNetworkAgent.getNetwork(),
12741                 mService.mNoServiceNetwork.network());
12742 
12743         // Disconnecting cellular will put the fallback on null and pref on disconnected.
12744         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, false);
12745         verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
12746                 null,
12747                 mService.mNoServiceNetwork.network());
12748 
12749         // default callbacks will be unregistered in tearDown
12750     }
12751 
12752     @Test
12753     public void testCapabilityWithOemNetworkPreference() throws Exception {
12754         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
12755                 OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY;
12756         setupMultipleDefaultNetworksForOemNetworkPreferenceNotCurrentUidTest(networkPref);
12757         registerDefaultNetworkCallbacks();
12758 
12759         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true);
12760 
12761         mSystemDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
12762         mDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
12763 
12764         mCellNetworkAgent.addCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED);
12765         mSystemDefaultNetworkCallback.expectCapabilitiesThat(mCellNetworkAgent, nc ->
12766                 nc.hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED));
12767         mDefaultNetworkCallback.expectCapabilitiesThat(mCellNetworkAgent, nc ->
12768                 nc.hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED));
12769 
12770         // default callbacks will be unregistered in tearDown
12771     }
12772 
12773     @Test
12774     public void testSetOemNetworkPreferenceLogsRequest() throws Exception {
12775         mServiceContext.setPermission(DUMP, PERMISSION_GRANTED);
12776         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
12777                 OEM_NETWORK_PREFERENCE_OEM_PAID;
12778         final StringWriter stringWriter = new StringWriter();
12779         final String logIdentifier = "UPDATE INITIATED: OemNetworkPreferences";
12780         final Pattern pattern = Pattern.compile(logIdentifier);
12781 
12782         final int expectedNumLogs = 2;
12783         final UidRangeParcel[] uidRanges =
12784                 toUidRangeStableParcels(uidRangesForUids(TEST_PACKAGE_UID));
12785 
12786         // Call twice to generate two logs.
12787         setupSetOemNetworkPreferenceForPreferenceTest(networkPref, uidRanges, TEST_PACKAGE_NAME);
12788         setupSetOemNetworkPreferenceForPreferenceTest(networkPref, uidRanges, TEST_PACKAGE_NAME);
12789         mService.dump(new FileDescriptor(), new PrintWriter(stringWriter), new String[0]);
12790 
12791         final String dumpOutput = stringWriter.toString();
12792         final Matcher matcher = pattern.matcher(dumpOutput);
12793         int count = 0;
12794         while (matcher.find()) {
12795             count++;
12796         }
12797         assertEquals(expectedNumLogs, count);
12798     }
12799 
12800     @Test
12801     public void testGetAllNetworkStateSnapshots() throws Exception {
12802         verifyNoNetwork();
12803 
12804         // Setup test cellular network with specified LinkProperties and NetworkCapabilities,
12805         // verify the content of the snapshot matches.
12806         final LinkProperties cellLp = new LinkProperties();
12807         final LinkAddress myIpv4Addr = new LinkAddress(InetAddress.getByName("192.0.2.129"), 25);
12808         final LinkAddress myIpv6Addr = new LinkAddress(InetAddress.getByName("2001:db8::1"), 64);
12809         cellLp.setInterfaceName("test01");
12810         cellLp.addLinkAddress(myIpv4Addr);
12811         cellLp.addLinkAddress(myIpv6Addr);
12812         cellLp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
12813         cellLp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
12814         cellLp.addRoute(new RouteInfo(myIpv4Addr, null));
12815         cellLp.addRoute(new RouteInfo(myIpv6Addr, null));
12816         final NetworkCapabilities cellNcTemplate = new NetworkCapabilities.Builder()
12817                 .addTransportType(TRANSPORT_CELLULAR).addCapability(NET_CAPABILITY_MMS).build();
12818 
12819         final TestNetworkCallback cellCb = new TestNetworkCallback();
12820         mCm.requestNetwork(new NetworkRequest.Builder().addCapability(NET_CAPABILITY_MMS).build(),
12821                 cellCb);
12822         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp, cellNcTemplate);
12823         mCellNetworkAgent.connect(true);
12824         cellCb.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
12825         List<NetworkStateSnapshot> snapshots = mCm.getAllNetworkStateSnapshots();
12826         assertLength(1, snapshots);
12827 
12828         // Compose the expected cellular snapshot for verification.
12829         final NetworkCapabilities cellNc =
12830                 mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork());
12831         final NetworkStateSnapshot cellSnapshot = new NetworkStateSnapshot(
12832                 mCellNetworkAgent.getNetwork(), cellNc, cellLp,
12833                 null, ConnectivityManager.TYPE_MOBILE);
12834         assertEquals(cellSnapshot, snapshots.get(0));
12835 
12836         // Connect wifi and verify the snapshots.
12837         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
12838         mWiFiNetworkAgent.connect(true);
12839         waitForIdle();
12840         // Compose the expected wifi snapshot for verification.
12841         final NetworkCapabilities wifiNc =
12842                 mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork());
12843         final NetworkStateSnapshot wifiSnapshot = new NetworkStateSnapshot(
12844                 mWiFiNetworkAgent.getNetwork(), wifiNc, new LinkProperties(), null,
12845                 ConnectivityManager.TYPE_WIFI);
12846 
12847         snapshots = mCm.getAllNetworkStateSnapshots();
12848         assertLength(2, snapshots);
12849         assertContainsAll(snapshots, cellSnapshot, wifiSnapshot);
12850 
12851         // Set cellular as suspended, verify the snapshots will not contain suspended networks.
12852         // TODO: Consider include SUSPENDED networks, which should be considered as
12853         //  temporary shortage of connectivity of a connected network.
12854         mCellNetworkAgent.suspend();
12855         waitForIdle();
12856         snapshots = mCm.getAllNetworkStateSnapshots();
12857         assertLength(1, snapshots);
12858         assertEquals(wifiSnapshot, snapshots.get(0));
12859 
12860         // Disconnect wifi, verify the snapshots contain nothing.
12861         mWiFiNetworkAgent.disconnect();
12862         waitForIdle();
12863         snapshots = mCm.getAllNetworkStateSnapshots();
12864         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
12865         assertLength(0, snapshots);
12866 
12867         mCellNetworkAgent.resume();
12868         waitForIdle();
12869         snapshots = mCm.getAllNetworkStateSnapshots();
12870         assertLength(1, snapshots);
12871         assertEquals(cellSnapshot, snapshots.get(0));
12872 
12873         mCellNetworkAgent.disconnect();
12874         waitForIdle();
12875         verifyNoNetwork();
12876         mCm.unregisterNetworkCallback(cellCb);
12877     }
12878 
12879     // Cannot be part of MockNetworkFactory since it requires method of the test.
12880     private void expectNoRequestChanged(@NonNull MockNetworkFactory factory) {
12881         waitForIdle();
12882         factory.assertNoRequestChanged();
12883     }
12884 
12885     @Test
12886     public void testRegisterBestMatchingNetworkCallback_noIssueToFactory() throws Exception {
12887         // Prepare mock mms factory.
12888         final HandlerThread handlerThread = new HandlerThread("MockCellularFactory");
12889         handlerThread.start();
12890         NetworkCapabilities filter = new NetworkCapabilities()
12891                 .addTransportType(TRANSPORT_CELLULAR)
12892                 .addCapability(NET_CAPABILITY_MMS);
12893         final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
12894                 mServiceContext, "testFactory", filter, mCsHandlerThread);
12895         testFactory.setScoreFilter(40);
12896 
12897         try {
12898             // Register the factory. It doesn't see the default request because its filter does
12899             // not include INTERNET.
12900             testFactory.register();
12901             expectNoRequestChanged(testFactory);
12902             testFactory.assertRequestCountEquals(0);
12903             // The factory won't try to start the network since the default request doesn't
12904             // match the filter (no INTERNET capability).
12905             assertFalse(testFactory.getMyStartRequested());
12906 
12907             // Register callback for listening best matching network. Verify that the request won't
12908             // be sent to factory.
12909             final TestNetworkCallback bestMatchingCb = new TestNetworkCallback();
12910             mCm.registerBestMatchingNetworkCallback(
12911                     new NetworkRequest.Builder().addCapability(NET_CAPABILITY_MMS).build(),
12912                     bestMatchingCb, mCsHandlerThread.getThreadHandler());
12913             bestMatchingCb.assertNoCallback();
12914             expectNoRequestChanged(testFactory);
12915             testFactory.assertRequestCountEquals(0);
12916             assertFalse(testFactory.getMyStartRequested());
12917 
12918             // Fire a normal mms request, verify the factory will only see the request.
12919             final TestNetworkCallback mmsNetworkCallback = new TestNetworkCallback();
12920             final NetworkRequest mmsRequest = new NetworkRequest.Builder()
12921                     .addCapability(NET_CAPABILITY_MMS).build();
12922             mCm.requestNetwork(mmsRequest, mmsNetworkCallback);
12923             testFactory.expectRequestAdd();
12924             testFactory.assertRequestCountEquals(1);
12925             assertTrue(testFactory.getMyStartRequested());
12926 
12927             // Unregister best matching callback, verify factory see no change.
12928             mCm.unregisterNetworkCallback(bestMatchingCb);
12929             expectNoRequestChanged(testFactory);
12930             testFactory.assertRequestCountEquals(1);
12931             assertTrue(testFactory.getMyStartRequested());
12932         } finally {
12933             testFactory.terminate();
12934         }
12935     }
12936 
12937     @Test
12938     public void testRegisterBestMatchingNetworkCallback_trackBestNetwork() throws Exception {
12939         final TestNetworkCallback bestMatchingCb = new TestNetworkCallback();
12940         mCm.registerBestMatchingNetworkCallback(
12941                 new NetworkRequest.Builder().addCapability(NET_CAPABILITY_TRUSTED).build(),
12942                 bestMatchingCb, mCsHandlerThread.getThreadHandler());
12943 
12944         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
12945         mCellNetworkAgent.connect(true);
12946         bestMatchingCb.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
12947 
12948         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
12949         mWiFiNetworkAgent.connect(true);
12950         bestMatchingCb.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
12951 
12952         // Change something on cellular to trigger capabilities changed, since the callback
12953         // only cares about the best network, verify it received nothing from cellular.
12954         mCellNetworkAgent.addCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED);
12955         bestMatchingCb.assertNoCallback();
12956 
12957         // Make cellular the best network again, verify the callback now tracks cellular.
12958         mWiFiNetworkAgent.adjustScore(-50);
12959         bestMatchingCb.expectAvailableCallbacksValidated(mCellNetworkAgent);
12960 
12961         // Make cellular temporary non-trusted, which will not satisfying the request.
12962         // Verify the callback switch from/to the other network accordingly.
12963         mCellNetworkAgent.removeCapability(NET_CAPABILITY_TRUSTED);
12964         bestMatchingCb.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
12965         mCellNetworkAgent.addCapability(NET_CAPABILITY_TRUSTED);
12966         bestMatchingCb.expectAvailableDoubleValidatedCallbacks(mCellNetworkAgent);
12967 
12968         // Verify the callback doesn't care about wifi disconnect.
12969         mWiFiNetworkAgent.disconnect();
12970         bestMatchingCb.assertNoCallback();
12971         mCellNetworkAgent.disconnect();
12972         bestMatchingCb.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
12973     }
12974 
12975     private UidRangeParcel[] uidRangeFor(final UserHandle handle) {
12976         UidRange range = UidRange.createForUser(handle);
12977         return new UidRangeParcel[] { new UidRangeParcel(range.start, range.stop) };
12978     }
12979 
12980     private static class TestOnCompleteListener implements Runnable {
12981         final class OnComplete {}
12982         final ArrayTrackRecord<OnComplete>.ReadHead mHistory =
12983                 new ArrayTrackRecord<OnComplete>().newReadHead();
12984 
12985         @Override
12986         public void run() {
12987             mHistory.add(new OnComplete());
12988         }
12989 
12990         public void expectOnComplete() {
12991             assertNotNull(mHistory.poll(TIMEOUT_MS, it -> true));
12992         }
12993     }
12994 
12995     private TestNetworkAgentWrapper makeEnterpriseNetworkAgent() throws Exception {
12996         final NetworkCapabilities workNc = new NetworkCapabilities();
12997         workNc.addCapability(NET_CAPABILITY_ENTERPRISE);
12998         workNc.removeCapability(NET_CAPABILITY_NOT_RESTRICTED);
12999         return new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, new LinkProperties(), workNc);
13000     }
13001 
13002     private TestNetworkCallback mEnterpriseCallback;
13003     private UserHandle setupEnterpriseNetwork() {
13004         final UserHandle userHandle = UserHandle.of(TEST_WORK_PROFILE_USER_ID);
13005         mServiceContext.setWorkProfile(userHandle, true);
13006 
13007         // File a request to avoid the enterprise network being disconnected as soon as the default
13008         // request goes away – it would make impossible to test that networkRemoveUidRanges
13009         // is called, as the network would disconnect first for lack of a request.
13010         mEnterpriseCallback = new TestNetworkCallback();
13011         final NetworkRequest keepUpRequest = new NetworkRequest.Builder()
13012                 .addCapability(NET_CAPABILITY_ENTERPRISE)
13013                 .build();
13014         mCm.requestNetwork(keepUpRequest, mEnterpriseCallback);
13015         return userHandle;
13016     }
13017 
13018     private void maybeTearDownEnterpriseNetwork() {
13019         if (null != mEnterpriseCallback) {
13020             mCm.unregisterNetworkCallback(mEnterpriseCallback);
13021         }
13022     }
13023 
13024     /**
13025      * Make sure per-profile networking preference behaves as expected when the enterprise network
13026      * goes up and down while the preference is active. Make sure they behave as expected whether
13027      * there is a general default network or not.
13028      */
13029     @Test
13030     public void testPreferenceForUserNetworkUpDown() throws Exception {
13031         final InOrder inOrder = inOrder(mMockNetd);
13032         final UserHandle testHandle = setupEnterpriseNetwork();
13033         registerDefaultNetworkCallbacks();
13034 
13035         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
13036         mCellNetworkAgent.connect(true);
13037 
13038         mSystemDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
13039         mDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
13040         mProfileDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
13041         inOrder.verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
13042                 mCellNetworkAgent.getNetwork().netId, INetd.PERMISSION_NONE));
13043 
13044 
13045         final TestOnCompleteListener listener = new TestOnCompleteListener();
13046         mCm.setProfileNetworkPreference(testHandle, PROFILE_NETWORK_PREFERENCE_ENTERPRISE,
13047                 r -> r.run(), listener);
13048         listener.expectOnComplete();
13049 
13050         // Setting a network preference for this user will create a new set of routing rules for
13051         // the UID range that corresponds to this user, so as to define the default network
13052         // for these apps separately. This is true because the multi-layer request relevant to
13053         // this UID range contains a TRACK_DEFAULT, so the range will be moved through UID-specific
13054         // rules to the correct network – in this case the system default network. The case where
13055         // the default network for the profile happens to be the same as the system default
13056         // is not handled specially, the rules are always active as long as a preference is set.
13057         inOrder.verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
13058                 mCellNetworkAgent.getNetwork().netId, uidRangeFor(testHandle),
13059                 PREFERENCE_PRIORITY_PROFILE));
13060 
13061         // The enterprise network is not ready yet.
13062         assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback,
13063                 mProfileDefaultNetworkCallback);
13064 
13065         final TestNetworkAgentWrapper workAgent = makeEnterpriseNetworkAgent();
13066         workAgent.connect(false);
13067 
13068         mProfileDefaultNetworkCallback.expectAvailableCallbacksUnvalidated(workAgent);
13069         mSystemDefaultNetworkCallback.assertNoCallback();
13070         mDefaultNetworkCallback.assertNoCallback();
13071         inOrder.verify(mMockNetd).networkCreate(
13072                 nativeNetworkConfigPhysical(workAgent.getNetwork().netId, INetd.PERMISSION_SYSTEM));
13073         inOrder.verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
13074                 workAgent.getNetwork().netId, uidRangeFor(testHandle),
13075                 PREFERENCE_PRIORITY_PROFILE));
13076         inOrder.verify(mMockNetd).networkRemoveUidRangesParcel(new NativeUidRangeConfig(
13077                 mCellNetworkAgent.getNetwork().netId, uidRangeFor(testHandle),
13078                 PREFERENCE_PRIORITY_PROFILE));
13079 
13080         // Make sure changes to the work agent send callbacks to the app in the work profile, but
13081         // not to the other apps.
13082         workAgent.setNetworkValid(true /* isStrictMode */);
13083         workAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
13084         mProfileDefaultNetworkCallback.expectCapabilitiesThat(workAgent,
13085                 nc -> nc.hasCapability(NET_CAPABILITY_VALIDATED)
13086                         && nc.hasCapability(NET_CAPABILITY_ENTERPRISE));
13087         assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback);
13088 
13089         workAgent.addCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED);
13090         mProfileDefaultNetworkCallback.expectCapabilitiesThat(workAgent, nc ->
13091                 nc.hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED));
13092         assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback);
13093 
13094         // Conversely, change a capability on the system-wide default network and make sure
13095         // that only the apps outside of the work profile receive the callbacks.
13096         mCellNetworkAgent.addCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED);
13097         mSystemDefaultNetworkCallback.expectCapabilitiesThat(mCellNetworkAgent, nc ->
13098                 nc.hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED));
13099         mDefaultNetworkCallback.expectCapabilitiesThat(mCellNetworkAgent, nc ->
13100                 nc.hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED));
13101         mProfileDefaultNetworkCallback.assertNoCallback();
13102 
13103         // Disconnect and reconnect the system-wide default network and make sure that the
13104         // apps on this network see the appropriate callbacks, and the app on the work profile
13105         // doesn't because it continues to use the enterprise network.
13106         mCellNetworkAgent.disconnect();
13107         mSystemDefaultNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
13108         mDefaultNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
13109         mProfileDefaultNetworkCallback.assertNoCallback();
13110         inOrder.verify(mMockNetd).networkDestroy(mCellNetworkAgent.getNetwork().netId);
13111 
13112         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
13113         mCellNetworkAgent.connect(true);
13114         mSystemDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
13115         mDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
13116         mProfileDefaultNetworkCallback.assertNoCallback();
13117         inOrder.verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
13118                 mCellNetworkAgent.getNetwork().netId, INetd.PERMISSION_NONE));
13119 
13120         // When the agent disconnects, test that the app on the work profile falls back to the
13121         // default network.
13122         workAgent.disconnect();
13123         mProfileDefaultNetworkCallback.expectCallback(CallbackEntry.LOST, workAgent);
13124         mProfileDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
13125         assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback);
13126         inOrder.verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
13127                 mCellNetworkAgent.getNetwork().netId, uidRangeFor(testHandle),
13128                 PREFERENCE_PRIORITY_PROFILE));
13129         inOrder.verify(mMockNetd).networkDestroy(workAgent.getNetwork().netId);
13130 
13131         mCellNetworkAgent.disconnect();
13132         mSystemDefaultNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
13133         mDefaultNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
13134         mProfileDefaultNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
13135 
13136         // Waiting for the handler to be idle before checking for networkDestroy is necessary
13137         // here because ConnectivityService calls onLost before the network is fully torn down.
13138         waitForIdle();
13139         inOrder.verify(mMockNetd).networkDestroy(mCellNetworkAgent.getNetwork().netId);
13140 
13141         // If the control comes here, callbacks seem to behave correctly in the presence of
13142         // a default network when the enterprise network goes up and down. Now, make sure they
13143         // also behave correctly in the absence of a system-wide default network.
13144         final TestNetworkAgentWrapper workAgent2 = makeEnterpriseNetworkAgent();
13145         workAgent2.connect(false);
13146 
13147         mProfileDefaultNetworkCallback.expectAvailableCallbacksUnvalidated(workAgent2);
13148         assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback);
13149         inOrder.verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
13150                 workAgent2.getNetwork().netId, INetd.PERMISSION_SYSTEM));
13151         inOrder.verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
13152                 workAgent2.getNetwork().netId, uidRangeFor(testHandle),
13153                 PREFERENCE_PRIORITY_PROFILE));
13154 
13155         workAgent2.setNetworkValid(true /* isStrictMode */);
13156         workAgent2.mNetworkMonitor.forceReevaluation(Process.myUid());
13157         mProfileDefaultNetworkCallback.expectCapabilitiesThat(workAgent2,
13158                 nc -> nc.hasCapability(NET_CAPABILITY_ENTERPRISE)
13159                         && !nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
13160         assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback);
13161         inOrder.verify(mMockNetd, never()).networkAddUidRangesParcel(any());
13162 
13163         // When the agent disconnects, test that the app on the work profile falls back to the
13164         // default network.
13165         workAgent2.disconnect();
13166         mProfileDefaultNetworkCallback.expectCallback(CallbackEntry.LOST, workAgent2);
13167         assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback);
13168         inOrder.verify(mMockNetd).networkDestroy(workAgent2.getNetwork().netId);
13169 
13170         assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback,
13171                 mProfileDefaultNetworkCallback);
13172 
13173         // Callbacks will be unregistered by tearDown()
13174     }
13175 
13176     /**
13177      * Test that, in a given networking context, calling setPreferenceForUser to set per-profile
13178      * defaults on then off works as expected.
13179      */
13180     @Test
13181     public void testSetPreferenceForUserOnOff() throws Exception {
13182         final InOrder inOrder = inOrder(mMockNetd);
13183         final UserHandle testHandle = setupEnterpriseNetwork();
13184 
13185         // Connect both a regular cell agent and an enterprise network first.
13186         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
13187         mCellNetworkAgent.connect(true);
13188 
13189         final TestNetworkAgentWrapper workAgent = makeEnterpriseNetworkAgent();
13190         workAgent.connect(true);
13191 
13192         final TestOnCompleteListener listener = new TestOnCompleteListener();
13193         mCm.setProfileNetworkPreference(testHandle, PROFILE_NETWORK_PREFERENCE_ENTERPRISE,
13194                 r -> r.run(), listener);
13195         listener.expectOnComplete();
13196         inOrder.verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
13197                 mCellNetworkAgent.getNetwork().netId, INetd.PERMISSION_NONE));
13198         inOrder.verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
13199                 workAgent.getNetwork().netId, uidRangeFor(testHandle),
13200                 PREFERENCE_PRIORITY_PROFILE));
13201 
13202         registerDefaultNetworkCallbacks();
13203 
13204         mSystemDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
13205         mDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
13206         mProfileDefaultNetworkCallback.expectAvailableCallbacksValidated(workAgent);
13207 
13208         mCm.setProfileNetworkPreference(testHandle, PROFILE_NETWORK_PREFERENCE_DEFAULT,
13209                 r -> r.run(), listener);
13210         listener.expectOnComplete();
13211 
13212         mProfileDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
13213         assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback);
13214         inOrder.verify(mMockNetd).networkRemoveUidRangesParcel(new NativeUidRangeConfig(
13215                 workAgent.getNetwork().netId, uidRangeFor(testHandle),
13216                 PREFERENCE_PRIORITY_PROFILE));
13217 
13218         workAgent.disconnect();
13219         mCellNetworkAgent.disconnect();
13220 
13221         // Callbacks will be unregistered by tearDown()
13222     }
13223 
13224     /**
13225      * Test per-profile default networks for two different profiles concurrently.
13226      */
13227     @Test
13228     public void testSetPreferenceForTwoProfiles() throws Exception {
13229         final InOrder inOrder = inOrder(mMockNetd);
13230         final UserHandle testHandle2 = setupEnterpriseNetwork();
13231         final UserHandle testHandle4 = UserHandle.of(TEST_WORK_PROFILE_USER_ID + 2);
13232         mServiceContext.setWorkProfile(testHandle4, true);
13233         registerDefaultNetworkCallbacks();
13234 
13235         final TestNetworkCallback app4Cb = new TestNetworkCallback();
13236         final int testWorkProfileAppUid4 =
13237                 UserHandle.getUid(testHandle4.getIdentifier(), TEST_APP_ID);
13238         registerDefaultNetworkCallbackAsUid(app4Cb, testWorkProfileAppUid4);
13239 
13240         // Connect both a regular cell agent and an enterprise network first.
13241         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
13242         mCellNetworkAgent.connect(true);
13243 
13244         final TestNetworkAgentWrapper workAgent = makeEnterpriseNetworkAgent();
13245         workAgent.connect(true);
13246 
13247         mSystemDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
13248         mDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
13249         mProfileDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
13250         app4Cb.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
13251         inOrder.verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
13252                 mCellNetworkAgent.getNetwork().netId, INetd.PERMISSION_NONE));
13253         inOrder.verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
13254                 workAgent.getNetwork().netId, INetd.PERMISSION_SYSTEM));
13255 
13256         final TestOnCompleteListener listener = new TestOnCompleteListener();
13257         mCm.setProfileNetworkPreference(testHandle2, PROFILE_NETWORK_PREFERENCE_ENTERPRISE,
13258                 r -> r.run(), listener);
13259         listener.expectOnComplete();
13260         inOrder.verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
13261                 workAgent.getNetwork().netId, uidRangeFor(testHandle2),
13262                 PREFERENCE_PRIORITY_PROFILE));
13263 
13264         mProfileDefaultNetworkCallback.expectAvailableCallbacksValidated(workAgent);
13265         assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback,
13266                 app4Cb);
13267 
13268         mCm.setProfileNetworkPreference(testHandle4, PROFILE_NETWORK_PREFERENCE_ENTERPRISE,
13269                 r -> r.run(), listener);
13270         listener.expectOnComplete();
13271         inOrder.verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
13272                 workAgent.getNetwork().netId, uidRangeFor(testHandle4),
13273                 PREFERENCE_PRIORITY_PROFILE));
13274 
13275         app4Cb.expectAvailableCallbacksValidated(workAgent);
13276         assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback,
13277                 mProfileDefaultNetworkCallback);
13278 
13279         mCm.setProfileNetworkPreference(testHandle2, PROFILE_NETWORK_PREFERENCE_DEFAULT,
13280                 r -> r.run(), listener);
13281         listener.expectOnComplete();
13282         inOrder.verify(mMockNetd).networkRemoveUidRangesParcel(new NativeUidRangeConfig(
13283                 workAgent.getNetwork().netId, uidRangeFor(testHandle2),
13284                 PREFERENCE_PRIORITY_PROFILE));
13285 
13286         mProfileDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
13287         assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback,
13288                 app4Cb);
13289 
13290         workAgent.disconnect();
13291         mCellNetworkAgent.disconnect();
13292 
13293         mCm.unregisterNetworkCallback(app4Cb);
13294         // Other callbacks will be unregistered by tearDown()
13295     }
13296 
13297     @Test
13298     public void testProfilePreferenceRemovedUponUserRemoved() throws Exception {
13299         final InOrder inOrder = inOrder(mMockNetd);
13300         final UserHandle testHandle = setupEnterpriseNetwork();
13301 
13302         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
13303         mCellNetworkAgent.connect(true);
13304 
13305         final TestOnCompleteListener listener = new TestOnCompleteListener();
13306         mCm.setProfileNetworkPreference(testHandle, PROFILE_NETWORK_PREFERENCE_ENTERPRISE,
13307                 r -> r.run(), listener);
13308         listener.expectOnComplete();
13309         inOrder.verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
13310                 mCellNetworkAgent.getNetwork().netId, INetd.PERMISSION_NONE));
13311         inOrder.verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
13312                 mCellNetworkAgent.getNetwork().netId, uidRangeFor(testHandle),
13313                 PREFERENCE_PRIORITY_PROFILE));
13314 
13315         final Intent removedIntent = new Intent(ACTION_USER_REMOVED);
13316         removedIntent.putExtra(Intent.EXTRA_USER, testHandle);
13317         processBroadcast(removedIntent);
13318 
13319         inOrder.verify(mMockNetd).networkRemoveUidRangesParcel(new NativeUidRangeConfig(
13320                 mCellNetworkAgent.getNetwork().netId, uidRangeFor(testHandle),
13321                 PREFERENCE_PRIORITY_PROFILE));
13322     }
13323 
13324     /**
13325      * Make sure wrong preferences for per-profile default networking are rejected.
13326      */
13327     @Test
13328     public void testProfileNetworkPrefWrongPreference() throws Exception {
13329         final UserHandle testHandle = UserHandle.of(TEST_WORK_PROFILE_USER_ID);
13330         mServiceContext.setWorkProfile(testHandle, true);
13331         assertThrows("Should not be able to set an illegal preference",
13332                 IllegalArgumentException.class,
13333                 () -> mCm.setProfileNetworkPreference(testHandle,
13334                         PROFILE_NETWORK_PREFERENCE_ENTERPRISE + 1, null, null));
13335     }
13336 
13337     /**
13338      * Make sure requests for per-profile default networking for a non-work profile are
13339      * rejected
13340      */
13341     @Test
13342     public void testProfileNetworkPrefWrongProfile() throws Exception {
13343         final UserHandle testHandle = UserHandle.of(TEST_WORK_PROFILE_USER_ID);
13344         mServiceContext.setWorkProfile(testHandle, false);
13345         assertThrows("Should not be able to set a user pref for a non-work profile",
13346                 IllegalArgumentException.class , () ->
13347                         mCm.setProfileNetworkPreference(testHandle,
13348                                 PROFILE_NETWORK_PREFERENCE_ENTERPRISE, null, null));
13349     }
13350 
13351     @Test
13352     public void testSubIdsClearedWithoutNetworkFactoryPermission() throws Exception {
13353         mServiceContext.setPermission(NETWORK_FACTORY, PERMISSION_DENIED);
13354         final NetworkCapabilities nc = new NetworkCapabilities();
13355         nc.setSubscriptionIds(Collections.singleton(Process.myUid()));
13356 
13357         final NetworkCapabilities result =
13358                 mService.networkCapabilitiesRestrictedForCallerPermissions(
13359                         nc, Process.myPid(), Process.myUid());
13360         assertTrue(result.getSubscriptionIds().isEmpty());
13361     }
13362 
13363     @Test
13364     public void testSubIdsExistWithNetworkFactoryPermission() throws Exception {
13365         mServiceContext.setPermission(NETWORK_FACTORY, PERMISSION_GRANTED);
13366 
13367         final Set<Integer> subIds = Collections.singleton(Process.myUid());
13368         final NetworkCapabilities nc = new NetworkCapabilities();
13369         nc.setSubscriptionIds(subIds);
13370 
13371         final NetworkCapabilities result =
13372                 mService.networkCapabilitiesRestrictedForCallerPermissions(
13373                         nc, Process.myPid(), Process.myUid());
13374         assertEquals(subIds, result.getSubscriptionIds());
13375     }
13376 
13377     private NetworkRequest getRequestWithSubIds() {
13378         return new NetworkRequest.Builder()
13379                 .setSubscriptionIds(Collections.singleton(Process.myUid()))
13380                 .build();
13381     }
13382 
13383     @Test
13384     public void testNetworkRequestWithSubIdsWithNetworkFactoryPermission() throws Exception {
13385         mServiceContext.setPermission(NETWORK_FACTORY, PERMISSION_GRANTED);
13386         final PendingIntent pendingIntent = PendingIntent.getBroadcast(
13387                 mContext, 0 /* requestCode */, new Intent("a"), FLAG_IMMUTABLE);
13388         final NetworkCallback networkCallback1 = new NetworkCallback();
13389         final NetworkCallback networkCallback2 = new NetworkCallback();
13390 
13391         mCm.requestNetwork(getRequestWithSubIds(), networkCallback1);
13392         mCm.requestNetwork(getRequestWithSubIds(), pendingIntent);
13393         mCm.registerNetworkCallback(getRequestWithSubIds(), networkCallback2);
13394 
13395         mCm.unregisterNetworkCallback(networkCallback1);
13396         mCm.releaseNetworkRequest(pendingIntent);
13397         mCm.unregisterNetworkCallback(networkCallback2);
13398     }
13399 
13400     @Test
13401     public void testNetworkRequestWithSubIdsWithoutNetworkFactoryPermission() throws Exception {
13402         mServiceContext.setPermission(NETWORK_FACTORY, PERMISSION_DENIED);
13403         final PendingIntent pendingIntent = PendingIntent.getBroadcast(
13404                 mContext, 0 /* requestCode */, new Intent("a"), FLAG_IMMUTABLE);
13405 
13406         final Class<SecurityException> expected = SecurityException.class;
13407         assertThrows(
13408                 expected, () -> mCm.requestNetwork(getRequestWithSubIds(), new NetworkCallback()));
13409         assertThrows(expected, () -> mCm.requestNetwork(getRequestWithSubIds(), pendingIntent));
13410         assertThrows(
13411                 expected,
13412                 () -> mCm.registerNetworkCallback(getRequestWithSubIds(), new NetworkCallback()));
13413     }
13414 
13415     /**
13416      * Validate request counts are counted accurately on setProfileNetworkPreference on set/replace.
13417      */
13418     @Test
13419     public void testProfileNetworkPrefCountsRequestsCorrectlyOnSet() throws Exception {
13420         final UserHandle testHandle = setupEnterpriseNetwork();
13421         final TestOnCompleteListener listener = new TestOnCompleteListener();
13422         // Leave one request available so the profile preference can be set.
13423         testRequestCountLimits(1 /* countToLeaveAvailable */, () -> {
13424             withPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
13425                     Process.myPid(), Process.myUid(), () -> {
13426                         // Set initially to test the limit prior to having existing requests.
13427                         mCm.setProfileNetworkPreference(testHandle,
13428                                 PROFILE_NETWORK_PREFERENCE_ENTERPRISE,
13429                                 Runnable::run, listener);
13430                     });
13431             listener.expectOnComplete();
13432 
13433             // Simulate filing requests as some app on the work profile
13434             final int otherAppUid = UserHandle.getUid(TEST_WORK_PROFILE_USER_ID,
13435                     UserHandle.getAppId(Process.myUid() + 1));
13436             final int remainingCount = ConnectivityService.MAX_NETWORK_REQUESTS_PER_UID
13437                     - mService.mNetworkRequestCounter.mUidToNetworkRequestCount.get(otherAppUid)
13438                     - 1;
13439             final NetworkCallback[] callbacks = new NetworkCallback[remainingCount];
13440             doAsUid(otherAppUid, () -> {
13441                 for (int i = 0; i < remainingCount; ++i) {
13442                     callbacks[i] = new TestableNetworkCallback();
13443                     mCm.registerDefaultNetworkCallback(callbacks[i]);
13444                 }
13445             });
13446 
13447             withPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
13448                     Process.myPid(), Process.myUid(), () -> {
13449                         // re-set so as to test the limit as part of replacing existing requests.
13450                         mCm.setProfileNetworkPreference(testHandle,
13451                                 PROFILE_NETWORK_PREFERENCE_ENTERPRISE, Runnable::run, listener);
13452                     });
13453             listener.expectOnComplete();
13454 
13455             doAsUid(otherAppUid, () -> {
13456                 for (final NetworkCallback callback : callbacks) {
13457                     mCm.unregisterNetworkCallback(callback);
13458                 }
13459             });
13460         });
13461     }
13462 
13463     /**
13464      * Validate request counts are counted accurately on setOemNetworkPreference on set/replace.
13465      */
13466     @Test
13467     public void testSetOemNetworkPreferenceCountsRequestsCorrectlyOnSet() throws Exception {
13468         mockHasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, true);
13469         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
13470                 OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY;
13471         // Leave one request available so the OEM preference can be set.
13472         testRequestCountLimits(1 /* countToLeaveAvailable */, () ->
13473                 withPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, () -> {
13474                     // Set initially to test the limit prior to having existing requests.
13475                     final TestOemListenerCallback listener = new TestOemListenerCallback();
13476                     mService.setOemNetworkPreference(
13477                             createDefaultOemNetworkPreferences(networkPref), listener);
13478                     listener.expectOnComplete();
13479 
13480                     // re-set so as to test the limit as part of replacing existing requests.
13481                     mService.setOemNetworkPreference(
13482                             createDefaultOemNetworkPreferences(networkPref), listener);
13483                     listener.expectOnComplete();
13484                 }));
13485     }
13486 
13487     private void testRequestCountLimits(final int countToLeaveAvailable,
13488             @NonNull final ExceptionalRunnable r) throws Exception {
13489         final ArraySet<TestNetworkCallback> callbacks = new ArraySet<>();
13490         try {
13491             final int requestCount = mService.mSystemNetworkRequestCounter
13492                     .mUidToNetworkRequestCount.get(Process.myUid());
13493             // The limit is hit when total requests = limit - 1, and exceeded with a crash when
13494             // total requests >= limit.
13495             final int countToFile =
13496                     MAX_NETWORK_REQUESTS_PER_SYSTEM_UID - requestCount - countToLeaveAvailable;
13497             // Need permission so registerDefaultNetworkCallback uses mSystemNetworkRequestCounter
13498             withPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, () -> {
13499                 for (int i = 1; i < countToFile; i++) {
13500                     final TestNetworkCallback cb = new TestNetworkCallback();
13501                     mCm.registerDefaultNetworkCallback(cb);
13502                     callbacks.add(cb);
13503                 }
13504                 assertEquals(MAX_NETWORK_REQUESTS_PER_SYSTEM_UID - 1 - countToLeaveAvailable,
13505                         mService.mSystemNetworkRequestCounter
13506                               .mUidToNetworkRequestCount.get(Process.myUid()));
13507             });
13508             // Code to run to check if it triggers a max request count limit error.
13509             r.run();
13510         } finally {
13511             for (final TestNetworkCallback cb : callbacks) {
13512                 mCm.unregisterNetworkCallback(cb);
13513             }
13514         }
13515     }
13516 
13517     private void assertCreateNrisFromMobileDataPreferredUids(Set<Integer> uids) {
13518         final Set<NetworkRequestInfo> nris =
13519                 mService.createNrisFromMobileDataPreferredUids(uids);
13520         final NetworkRequestInfo nri = nris.iterator().next();
13521         // Verify that one NRI is created with multilayer requests. Because one NRI can contain
13522         // multiple uid ranges, so it only need create one NRI here.
13523         assertEquals(1, nris.size());
13524         assertTrue(nri.isMultilayerRequest());
13525         assertEquals(nri.getUids(), uidRangesForUids(uids));
13526         assertEquals(PREFERENCE_PRIORITY_MOBILE_DATA_PREFERERRED, nri.mPreferencePriority);
13527     }
13528 
13529     /**
13530      * Test createNrisFromMobileDataPreferredUids returns correct NetworkRequestInfo.
13531      */
13532     @Test
13533     public void testCreateNrisFromMobileDataPreferredUids() {
13534         // Verify that empty uid set should not create any NRI for it.
13535         final Set<NetworkRequestInfo> nrisNoUid =
13536                 mService.createNrisFromMobileDataPreferredUids(new ArraySet<>());
13537         assertEquals(0, nrisNoUid.size());
13538 
13539         final int uid1 = PRIMARY_USER_HANDLE.getUid(TEST_PACKAGE_UID);
13540         final int uid2 = PRIMARY_USER_HANDLE.getUid(TEST_PACKAGE_UID2);
13541         final int uid3 = SECONDARY_USER_HANDLE.getUid(TEST_PACKAGE_UID);
13542         assertCreateNrisFromMobileDataPreferredUids(Set.of(uid1));
13543         assertCreateNrisFromMobileDataPreferredUids(Set.of(uid1, uid3));
13544         assertCreateNrisFromMobileDataPreferredUids(Set.of(uid1, uid2));
13545     }
13546 
13547     private void setAndUpdateMobileDataPreferredUids(Set<Integer> uids) {
13548         ConnectivitySettingsManager.setMobileDataPreferredUids(mServiceContext, uids);
13549         mService.updateMobileDataPreferredUids();
13550         waitForIdle();
13551     }
13552 
13553     /**
13554      * Test that MOBILE_DATA_PREFERRED_UIDS changes will send correct net id and uid ranges to netd.
13555      */
13556     @Test
13557     public void testMobileDataPreferredUidsChanged() throws Exception {
13558         final InOrder inorder = inOrder(mMockNetd);
13559         registerDefaultNetworkCallbacks();
13560         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
13561         mCellNetworkAgent.connect(true);
13562         mDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
13563         mTestPackageDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
13564 
13565         final int cellNetId = mCellNetworkAgent.getNetwork().netId;
13566         inorder.verify(mMockNetd, times(1)).networkCreate(nativeNetworkConfigPhysical(
13567                 cellNetId, INetd.PERMISSION_NONE));
13568 
13569         // Initial mobile data preferred uids status.
13570         setAndUpdateMobileDataPreferredUids(Set.of());
13571         inorder.verify(mMockNetd, never()).networkAddUidRangesParcel(any());
13572         inorder.verify(mMockNetd, never()).networkRemoveUidRangesParcel(any());
13573 
13574         // Set MOBILE_DATA_PREFERRED_UIDS setting and verify that net id and uid ranges send to netd
13575         final Set<Integer> uids1 = Set.of(PRIMARY_USER_HANDLE.getUid(TEST_PACKAGE_UID));
13576         final UidRangeParcel[] uidRanges1 = toUidRangeStableParcels(uidRangesForUids(uids1));
13577         final NativeUidRangeConfig config1 = new NativeUidRangeConfig(cellNetId, uidRanges1,
13578                 PREFERENCE_PRIORITY_MOBILE_DATA_PREFERERRED);
13579         setAndUpdateMobileDataPreferredUids(uids1);
13580         inorder.verify(mMockNetd, times(1)).networkAddUidRangesParcel(config1);
13581         inorder.verify(mMockNetd, never()).networkRemoveUidRangesParcel(any());
13582 
13583         // Set MOBILE_DATA_PREFERRED_UIDS setting again and verify that old rules are removed and
13584         // new rules are added.
13585         final Set<Integer> uids2 = Set.of(PRIMARY_USER_HANDLE.getUid(TEST_PACKAGE_UID),
13586                 PRIMARY_USER_HANDLE.getUid(TEST_PACKAGE_UID2),
13587                 SECONDARY_USER_HANDLE.getUid(TEST_PACKAGE_UID));
13588         final UidRangeParcel[] uidRanges2 = toUidRangeStableParcels(uidRangesForUids(uids2));
13589         final NativeUidRangeConfig config2 = new NativeUidRangeConfig(cellNetId, uidRanges2,
13590                 PREFERENCE_PRIORITY_MOBILE_DATA_PREFERERRED);
13591         setAndUpdateMobileDataPreferredUids(uids2);
13592         inorder.verify(mMockNetd, times(1)).networkRemoveUidRangesParcel(config1);
13593         inorder.verify(mMockNetd, times(1)).networkAddUidRangesParcel(config2);
13594 
13595         // Clear MOBILE_DATA_PREFERRED_UIDS setting again and verify that old rules are removed and
13596         // new rules are not added.
13597         setAndUpdateMobileDataPreferredUids(Set.of());
13598         inorder.verify(mMockNetd, times(1)).networkRemoveUidRangesParcel(config2);
13599         inorder.verify(mMockNetd, never()).networkAddUidRangesParcel(any());
13600     }
13601 
13602     /**
13603      * Make sure mobile data preferred uids feature behaves as expected when the mobile network
13604      * goes up and down while the uids is set. Make sure they behave as expected whether
13605      * there is a general default network or not.
13606      */
13607     @Test
13608     public void testMobileDataPreferenceForMobileNetworkUpDown() throws Exception {
13609         final InOrder inorder = inOrder(mMockNetd);
13610         // File a request for cell to ensure it doesn't go down.
13611         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
13612         final NetworkRequest cellRequest = new NetworkRequest.Builder()
13613                 .addTransportType(TRANSPORT_CELLULAR).build();
13614         mCm.requestNetwork(cellRequest, cellNetworkCallback);
13615         cellNetworkCallback.assertNoCallback();
13616 
13617         registerDefaultNetworkCallbacks();
13618         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
13619         mWiFiNetworkAgent.connect(true);
13620         mDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
13621         mTestPackageDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
13622         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_PACKAGE_UID));
13623 
13624         final int wifiNetId = mWiFiNetworkAgent.getNetwork().netId;
13625         inorder.verify(mMockNetd, times(1)).networkCreate(nativeNetworkConfigPhysical(
13626                 wifiNetId, INetd.PERMISSION_NONE));
13627 
13628         // Initial mobile data preferred uids status.
13629         setAndUpdateMobileDataPreferredUids(Set.of());
13630         inorder.verify(mMockNetd, never()).networkAddUidRangesParcel(any());
13631         inorder.verify(mMockNetd, never()).networkRemoveUidRangesParcel(any());
13632 
13633         // Set MOBILE_DATA_PREFERRED_UIDS setting and verify that wifi net id and uid ranges send to
13634         // netd.
13635         final Set<Integer> uids = Set.of(PRIMARY_USER_HANDLE.getUid(TEST_PACKAGE_UID));
13636         final UidRangeParcel[] uidRanges = toUidRangeStableParcels(uidRangesForUids(uids));
13637         final NativeUidRangeConfig wifiConfig = new NativeUidRangeConfig(wifiNetId, uidRanges,
13638                 PREFERENCE_PRIORITY_MOBILE_DATA_PREFERERRED);
13639         setAndUpdateMobileDataPreferredUids(uids);
13640         inorder.verify(mMockNetd, times(1)).networkAddUidRangesParcel(wifiConfig);
13641         inorder.verify(mMockNetd, never()).networkRemoveUidRangesParcel(any());
13642 
13643         // Cellular network connected. mTestPackageDefaultNetworkCallback should receive
13644         // callback with cellular network and net id and uid ranges should be updated to netd.
13645         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
13646         mCellNetworkAgent.connect(true);
13647         cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
13648         mDefaultNetworkCallback.assertNoCallback();
13649         mTestPackageDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
13650         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_PACKAGE_UID));
13651 
13652         final int cellNetId = mCellNetworkAgent.getNetwork().netId;
13653         final NativeUidRangeConfig cellConfig = new NativeUidRangeConfig(cellNetId, uidRanges,
13654                 PREFERENCE_PRIORITY_MOBILE_DATA_PREFERERRED);
13655         inorder.verify(mMockNetd, times(1)).networkCreate(nativeNetworkConfigPhysical(
13656                 cellNetId, INetd.PERMISSION_NONE));
13657         inorder.verify(mMockNetd, times(1)).networkAddUidRangesParcel(cellConfig);
13658         inorder.verify(mMockNetd, times(1)).networkRemoveUidRangesParcel(wifiConfig);
13659 
13660         // Cellular network disconnected. mTestPackageDefaultNetworkCallback should receive
13661         // callback with wifi network from fallback request.
13662         mCellNetworkAgent.disconnect();
13663         mDefaultNetworkCallback.assertNoCallback();
13664         cellNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
13665         mTestPackageDefaultNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
13666         mTestPackageDefaultNetworkCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
13667         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_PACKAGE_UID));
13668         inorder.verify(mMockNetd, times(1)).networkAddUidRangesParcel(wifiConfig);
13669         inorder.verify(mMockNetd, never()).networkRemoveUidRangesParcel(any());
13670         inorder.verify(mMockNetd).networkDestroy(cellNetId);
13671 
13672         // Cellular network comes back. mTestPackageDefaultNetworkCallback should receive
13673         // callback with cellular network.
13674         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
13675         mCellNetworkAgent.connect(true);
13676         cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
13677         mDefaultNetworkCallback.assertNoCallback();
13678         mTestPackageDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
13679         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_PACKAGE_UID));
13680 
13681         final int cellNetId2 = mCellNetworkAgent.getNetwork().netId;
13682         final NativeUidRangeConfig cellConfig2 = new NativeUidRangeConfig(cellNetId2, uidRanges,
13683                 PREFERENCE_PRIORITY_MOBILE_DATA_PREFERERRED);
13684         inorder.verify(mMockNetd, times(1)).networkCreate(nativeNetworkConfigPhysical(
13685                 cellNetId2, INetd.PERMISSION_NONE));
13686         inorder.verify(mMockNetd, times(1)).networkAddUidRangesParcel(cellConfig2);
13687         inorder.verify(mMockNetd, times(1)).networkRemoveUidRangesParcel(wifiConfig);
13688 
13689         // Wifi network disconnected. mTestPackageDefaultNetworkCallback should not receive
13690         // any callback.
13691         mWiFiNetworkAgent.disconnect();
13692         mDefaultNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
13693         mDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
13694         mTestPackageDefaultNetworkCallback.assertNoCallback();
13695         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_PACKAGE_UID));
13696         waitForIdle();
13697         inorder.verify(mMockNetd, never()).networkAddUidRangesParcel(any());
13698         inorder.verify(mMockNetd, never()).networkRemoveUidRangesParcel(any());
13699         inorder.verify(mMockNetd).networkDestroy(wifiNetId);
13700 
13701         mCm.unregisterNetworkCallback(cellNetworkCallback);
13702     }
13703 
13704     @Test
13705     public void testMultilayerRequestsOfSetMobileDataPreferredUids() throws Exception {
13706         // First set mobile data preferred uid to create a multi-layer requests: 1. request for
13707         // cellular, 2. track the default network for fallback.
13708         setAndUpdateMobileDataPreferredUids(
13709                 Set.of(PRIMARY_USER_HANDLE.getUid(TEST_PACKAGE_UID)));
13710 
13711         final HandlerThread handlerThread = new HandlerThread("MockFactory");
13712         handlerThread.start();
13713         final NetworkCapabilities cellFilter = new NetworkCapabilities()
13714                 .addTransportType(TRANSPORT_CELLULAR)
13715                 .addCapability(NET_CAPABILITY_INTERNET)
13716                 .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED);
13717         final MockNetworkFactory cellFactory = new MockNetworkFactory(handlerThread.getLooper(),
13718                 mServiceContext, "cellFactory", cellFilter, mCsHandlerThread);
13719         cellFactory.setScoreFilter(40);
13720 
13721         try {
13722             cellFactory.register();
13723             // Default internet request and the mobile data preferred request.
13724             cellFactory.expectRequestAdds(2);
13725             cellFactory.assertRequestCountEquals(2);
13726 
13727             mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
13728             mWiFiNetworkAgent.connect(true);
13729 
13730             // The cellFactory however is outscored, and should lose default internet request.
13731             // But it should still see mobile data preferred request.
13732             cellFactory.expectRequestRemove();
13733             cellFactory.assertRequestCountEquals(1);
13734 
13735             mWiFiNetworkAgent.disconnect();
13736             // The network satisfying the default internet request has disconnected, so the
13737             // cellFactory sees the default internet requests again.
13738             cellFactory.expectRequestAdd();
13739             cellFactory.assertRequestCountEquals(2);
13740         } finally {
13741             cellFactory.terminate();
13742             handlerThread.quitSafely();
13743         }
13744     }
13745 
13746     /**
13747      * Validate request counts are counted accurately on MOBILE_DATA_PREFERRED_UIDS change
13748      * on set/replace.
13749      */
13750     @Test
13751     public void testMobileDataPreferredUidsChangedCountsRequestsCorrectlyOnSet() throws Exception {
13752         ConnectivitySettingsManager.setMobileDataPreferredUids(mServiceContext,
13753                 Set.of(PRIMARY_USER_HANDLE.getUid(TEST_PACKAGE_UID)));
13754         // Leave one request available so MDO preference set up above can be set.
13755         testRequestCountLimits(1 /* countToLeaveAvailable */, () ->
13756                 withPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
13757                         Process.myPid(), Process.myUid(), () -> {
13758                             // Set initially to test the limit prior to having existing requests.
13759                             mService.updateMobileDataPreferredUids();
13760                             waitForIdle();
13761 
13762                             // re-set so as to test the limit as part of replacing existing requests
13763                             mService.updateMobileDataPreferredUids();
13764                             waitForIdle();
13765                         }));
13766     }
13767 
13768     @Test
13769     public void testAllNetworkPreferencesCanCoexist()
13770             throws Exception {
13771         final InOrder inorder = inOrder(mMockNetd);
13772         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
13773                 OEM_NETWORK_PREFERENCE_OEM_PAID;
13774         final UserHandle testHandle = setupEnterpriseNetwork();
13775 
13776         setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true);
13777         final int cellNetId = mCellNetworkAgent.getNetwork().netId;
13778         inorder.verify(mMockNetd, times(1)).networkCreate(nativeNetworkConfigPhysical(
13779                 cellNetId, INetd.PERMISSION_NONE));
13780 
13781         // Set oem network preference
13782         final int[] uids1 = new int[] { PRIMARY_USER_HANDLE.getUid(TEST_PACKAGE_UID) };
13783         final UidRangeParcel[] uidRanges1 = toUidRangeStableParcels(uidRangesForUids(uids1));
13784         final NativeUidRangeConfig config1 = new NativeUidRangeConfig(cellNetId, uidRanges1,
13785                 PREFERENCE_PRIORITY_OEM);
13786         setupSetOemNetworkPreferenceForPreferenceTest(networkPref, uidRanges1, TEST_PACKAGE_NAME);
13787         inorder.verify(mMockNetd, times(1)).networkAddUidRangesParcel(config1);
13788         inorder.verify(mMockNetd, never()).networkRemoveUidRangesParcel(any());
13789 
13790         // Set user profile network preference
13791         final TestNetworkAgentWrapper workAgent = makeEnterpriseNetworkAgent();
13792         workAgent.connect(true);
13793 
13794         final TestOnCompleteListener listener = new TestOnCompleteListener();
13795         mCm.setProfileNetworkPreference(testHandle, PROFILE_NETWORK_PREFERENCE_ENTERPRISE,
13796                 r -> r.run(), listener);
13797         listener.expectOnComplete();
13798         final NativeUidRangeConfig config2 = new NativeUidRangeConfig(workAgent.getNetwork().netId,
13799                 uidRangeFor(testHandle), PREFERENCE_PRIORITY_PROFILE);
13800         inorder.verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
13801                 workAgent.getNetwork().netId, INetd.PERMISSION_SYSTEM));
13802         inorder.verify(mMockNetd, never()).networkRemoveUidRangesParcel(any());
13803         inorder.verify(mMockNetd).networkAddUidRangesParcel(config2);
13804 
13805         // Set MOBILE_DATA_PREFERRED_UIDS setting
13806         final Set<Integer> uids2 = Set.of(PRIMARY_USER_HANDLE.getUid(TEST_PACKAGE_UID2));
13807         final UidRangeParcel[] uidRanges2 = toUidRangeStableParcels(uidRangesForUids(uids2));
13808         final NativeUidRangeConfig config3 = new NativeUidRangeConfig(cellNetId, uidRanges2,
13809                 PREFERENCE_PRIORITY_MOBILE_DATA_PREFERERRED);
13810         setAndUpdateMobileDataPreferredUids(uids2);
13811         inorder.verify(mMockNetd, never()).networkRemoveUidRangesParcel(any());
13812         inorder.verify(mMockNetd, times(1)).networkAddUidRangesParcel(config3);
13813 
13814         // Set oem network preference again with different uid.
13815         final Set<Integer> uids3 = Set.of(PRIMARY_USER_HANDLE.getUid(TEST_PACKAGE_UID3));
13816         final UidRangeParcel[] uidRanges3 = toUidRangeStableParcels(uidRangesForUids(uids3));
13817         final NativeUidRangeConfig config4 = new NativeUidRangeConfig(cellNetId, uidRanges3,
13818                 PREFERENCE_PRIORITY_OEM);
13819         setupSetOemNetworkPreferenceForPreferenceTest(networkPref, uidRanges3, "com.android.test");
13820         inorder.verify(mMockNetd, times(1)).networkRemoveUidRangesParcel(config1);
13821         inorder.verify(mMockNetd, times(1)).networkAddUidRangesParcel(config4);
13822 
13823         // Remove user profile network preference
13824         mCm.setProfileNetworkPreference(testHandle, PROFILE_NETWORK_PREFERENCE_DEFAULT,
13825                 r -> r.run(), listener);
13826         listener.expectOnComplete();
13827         inorder.verify(mMockNetd, times(1)).networkRemoveUidRangesParcel(config2);
13828         inorder.verify(mMockNetd, never()).networkAddUidRangesParcel(any());
13829 
13830         // Set MOBILE_DATA_PREFERRED_UIDS setting again with same uid as oem network preference.
13831         final NativeUidRangeConfig config6 = new NativeUidRangeConfig(cellNetId, uidRanges3,
13832                 PREFERENCE_PRIORITY_MOBILE_DATA_PREFERERRED);
13833         setAndUpdateMobileDataPreferredUids(uids3);
13834         inorder.verify(mMockNetd, times(1)).networkRemoveUidRangesParcel(config3);
13835         inorder.verify(mMockNetd, times(1)).networkAddUidRangesParcel(config6);
13836     }
13837 
13838     @Test
13839     public void testNetworkCallbackAndActiveNetworkForUid_AllNetworkPreferencesEnabled()
13840             throws Exception {
13841         // File a request for cell to ensure it doesn't go down.
13842         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
13843         final NetworkRequest cellRequest = new NetworkRequest.Builder()
13844                 .addTransportType(TRANSPORT_CELLULAR).build();
13845         mCm.requestNetwork(cellRequest, cellNetworkCallback);
13846         cellNetworkCallback.assertNoCallback();
13847 
13848         // Register callbacks and have wifi network as default network.
13849         registerDefaultNetworkCallbacks();
13850         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
13851         mWiFiNetworkAgent.connect(true);
13852         mDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
13853         mProfileDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
13854         mTestPackageDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
13855         assertEquals(mWiFiNetworkAgent.getNetwork(),
13856                 mCm.getActiveNetworkForUid(TEST_WORK_PROFILE_APP_UID));
13857         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_PACKAGE_UID));
13858 
13859         // Set MOBILE_DATA_PREFERRED_UIDS setting with TEST_WORK_PROFILE_APP_UID and
13860         // TEST_PACKAGE_UID. Both mProfileDefaultNetworkCallback and
13861         // mTestPackageDefaultNetworkCallback should receive callback with cell network.
13862         setAndUpdateMobileDataPreferredUids(Set.of(TEST_WORK_PROFILE_APP_UID, TEST_PACKAGE_UID));
13863         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
13864         mCellNetworkAgent.connect(true);
13865         cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
13866         mDefaultNetworkCallback.assertNoCallback();
13867         mProfileDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
13868         mTestPackageDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
13869         assertEquals(mCellNetworkAgent.getNetwork(),
13870                 mCm.getActiveNetworkForUid(TEST_WORK_PROFILE_APP_UID));
13871         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_PACKAGE_UID));
13872 
13873         // Set user profile network preference with test profile. mProfileDefaultNetworkCallback
13874         // should receive callback with higher priority network preference (enterprise network).
13875         // The others should have no callbacks.
13876         final UserHandle testHandle = setupEnterpriseNetwork();
13877         final TestNetworkAgentWrapper workAgent = makeEnterpriseNetworkAgent();
13878         workAgent.connect(true);
13879         final TestOnCompleteListener listener = new TestOnCompleteListener();
13880         mCm.setProfileNetworkPreference(testHandle, PROFILE_NETWORK_PREFERENCE_ENTERPRISE,
13881                 r -> r.run(), listener);
13882         listener.expectOnComplete();
13883         assertNoCallbacks(mDefaultNetworkCallback, mTestPackageDefaultNetworkCallback);
13884         mProfileDefaultNetworkCallback.expectAvailableCallbacksValidated(workAgent);
13885         assertEquals(workAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_WORK_PROFILE_APP_UID));
13886         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_PACKAGE_UID));
13887 
13888         // Set oem network preference with TEST_PACKAGE_UID. mTestPackageDefaultNetworkCallback
13889         // should receive callback with higher priority network preference (current default network)
13890         // and the others should have no callbacks.
13891         @OemNetworkPreferences.OemNetworkPreference final int networkPref =
13892                 OEM_NETWORK_PREFERENCE_OEM_PAID;
13893         final int[] uids1 = new int[] { TEST_PACKAGE_UID };
13894         final UidRangeParcel[] uidRanges1 = toUidRangeStableParcels(uidRangesForUids(uids1));
13895         setupSetOemNetworkPreferenceForPreferenceTest(networkPref, uidRanges1, TEST_PACKAGE_NAME);
13896         assertNoCallbacks(mDefaultNetworkCallback, mProfileDefaultNetworkCallback);
13897         mTestPackageDefaultNetworkCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
13898         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_PACKAGE_UID));
13899         assertEquals(workAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_WORK_PROFILE_APP_UID));
13900 
13901         // Set oem network preference with TEST_WORK_PROFILE_APP_UID. Both
13902         // mProfileDefaultNetworkCallback and mTestPackageDefaultNetworkCallback should receive
13903         // callback.
13904         final int[] uids2 = new int[] { TEST_WORK_PROFILE_APP_UID };
13905         final UidRangeParcel[] uidRanges2 = toUidRangeStableParcels(uidRangesForUids(uids2));
13906         when(mUserManager.getUserHandles(anyBoolean())).thenReturn(Arrays.asList(testHandle));
13907         setupSetOemNetworkPreferenceForPreferenceTest(
13908                 networkPref, uidRanges2, "com.android.test", testHandle);
13909         mDefaultNetworkCallback.assertNoCallback();
13910         mProfileDefaultNetworkCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
13911         mTestPackageDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
13912         assertEquals(mWiFiNetworkAgent.getNetwork(),
13913                 mCm.getActiveNetworkForUid(TEST_WORK_PROFILE_APP_UID));
13914         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_PACKAGE_UID));
13915 
13916         // Remove oem network preference, mProfileDefaultNetworkCallback should receive callback
13917         // with current highest priority network preference (enterprise network) and the others
13918         // should have no callbacks.
13919         final TestOemListenerCallback oemPrefListener = new TestOemListenerCallback();
13920         mService.setOemNetworkPreference(
13921                 new OemNetworkPreferences.Builder().build(), oemPrefListener);
13922         oemPrefListener.expectOnComplete();
13923         assertNoCallbacks(mDefaultNetworkCallback, mTestPackageDefaultNetworkCallback);
13924         mProfileDefaultNetworkCallback.expectAvailableCallbacksValidated(workAgent);
13925         assertEquals(workAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_WORK_PROFILE_APP_UID));
13926         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_PACKAGE_UID));
13927 
13928         // Remove user profile network preference.
13929         mCm.setProfileNetworkPreference(testHandle, PROFILE_NETWORK_PREFERENCE_DEFAULT,
13930                 r -> r.run(), listener);
13931         listener.expectOnComplete();
13932         assertNoCallbacks(mDefaultNetworkCallback, mTestPackageDefaultNetworkCallback);
13933         mProfileDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
13934         assertEquals(mCellNetworkAgent.getNetwork(),
13935                 mCm.getActiveNetworkForUid(TEST_WORK_PROFILE_APP_UID));
13936         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(TEST_PACKAGE_UID));
13937 
13938         // Disconnect wifi
13939         mWiFiNetworkAgent.disconnect();
13940         assertNoCallbacks(mProfileDefaultNetworkCallback, mTestPackageDefaultNetworkCallback);
13941         mDefaultNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
13942         mDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
13943     }
13944 
13945     @Test
13946     public void testRequestRouteToHostAddress_PackageDoesNotBelongToCaller() {
13947         assertThrows(SecurityException.class, () -> mService.requestRouteToHostAddress(
13948                 ConnectivityManager.TYPE_NONE, null /* hostAddress */, "com.not.package.owner",
13949                 null /* callingAttributionTag */));
13950     }
13951 }
13952