1 /*
2  * Copyright (C) 2008 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.RECEIVE_DATA_ACTIVITY_CHANGE;
20 import static android.app.ActivityManager.UidFrozenStateChangedCallback.UID_FROZEN_STATE_FROZEN;
21 import static android.content.pm.PackageManager.FEATURE_BLUETOOTH;
22 import static android.content.pm.PackageManager.FEATURE_LEANBACK;
23 import static android.content.pm.PackageManager.FEATURE_WATCH;
24 import static android.content.pm.PackageManager.FEATURE_WIFI;
25 import static android.content.pm.PackageManager.FEATURE_WIFI_DIRECT;
26 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
27 import static android.net.BpfNetMapsConstants.METERED_ALLOW_CHAINS;
28 import static android.net.BpfNetMapsConstants.METERED_DENY_CHAINS;
29 import static android.net.ConnectivityDiagnosticsManager.ConnectivityReport.KEY_NETWORK_PROBES_ATTEMPTED_BITMASK;
30 import static android.net.ConnectivityDiagnosticsManager.ConnectivityReport.KEY_NETWORK_PROBES_SUCCEEDED_BITMASK;
31 import static android.net.ConnectivityDiagnosticsManager.ConnectivityReport.KEY_NETWORK_VALIDATION_RESULT;
32 import static android.net.ConnectivityDiagnosticsManager.DataStallReport.DETECTION_METHOD_DNS_EVENTS;
33 import static android.net.ConnectivityDiagnosticsManager.DataStallReport.DETECTION_METHOD_TCP_METRICS;
34 import static android.net.ConnectivityDiagnosticsManager.DataStallReport.KEY_DNS_CONSECUTIVE_TIMEOUTS;
35 import static android.net.ConnectivityDiagnosticsManager.DataStallReport.KEY_TCP_METRICS_COLLECTION_PERIOD_MILLIS;
36 import static android.net.ConnectivityDiagnosticsManager.DataStallReport.KEY_TCP_PACKET_FAIL_RATE;
37 import static android.net.ConnectivityManager.ACTION_RESTRICT_BACKGROUND_CHANGED;
38 import static android.net.ConnectivityManager.BLOCKED_METERED_REASON_MASK;
39 import static android.net.ConnectivityManager.BLOCKED_REASON_APP_BACKGROUND;
40 import static android.net.ConnectivityManager.BLOCKED_REASON_LOCKDOWN_VPN;
41 import static android.net.ConnectivityManager.BLOCKED_REASON_NONE;
42 import static android.net.ConnectivityManager.BLOCKED_REASON_NETWORK_RESTRICTED;
43 import static android.net.ConnectivityManager.CALLBACK_IP_CHANGED;
44 import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
45 import static android.net.ConnectivityManager.FIREWALL_CHAIN_BACKGROUND;
46 import static android.net.ConnectivityManager.FIREWALL_RULE_ALLOW;
47 import static android.net.ConnectivityManager.FIREWALL_RULE_DEFAULT;
48 import static android.net.ConnectivityManager.FIREWALL_RULE_DENY;
49 import static android.net.ConnectivityManager.TYPE_BLUETOOTH;
50 import static android.net.ConnectivityManager.TYPE_ETHERNET;
51 import static android.net.ConnectivityManager.TYPE_MOBILE;
52 import static android.net.ConnectivityManager.TYPE_MOBILE_CBS;
53 import static android.net.ConnectivityManager.TYPE_MOBILE_DUN;
54 import static android.net.ConnectivityManager.TYPE_MOBILE_EMERGENCY;
55 import static android.net.ConnectivityManager.TYPE_MOBILE_FOTA;
56 import static android.net.ConnectivityManager.TYPE_MOBILE_HIPRI;
57 import static android.net.ConnectivityManager.TYPE_MOBILE_IA;
58 import static android.net.ConnectivityManager.TYPE_MOBILE_IMS;
59 import static android.net.ConnectivityManager.TYPE_MOBILE_MMS;
60 import static android.net.ConnectivityManager.TYPE_MOBILE_SUPL;
61 import static android.net.ConnectivityManager.TYPE_NONE;
62 import static android.net.ConnectivityManager.TYPE_PROXY;
63 import static android.net.ConnectivityManager.TYPE_VPN;
64 import static android.net.ConnectivityManager.TYPE_WIFI;
65 import static android.net.ConnectivityManager.TYPE_WIFI_P2P;
66 import static android.net.ConnectivityManager.getNetworkTypeName;
67 import static android.net.ConnectivityManager.isNetworkTypeValid;
68 import static android.net.ConnectivitySettingsManager.PRIVATE_DNS_MODE_OPPORTUNISTIC;
69 import static android.net.INetd.PERMISSION_INTERNET;
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_SKIPPED;
73 import static android.net.INetworkMonitor.NETWORK_VALIDATION_RESULT_VALID;
74 import static android.net.MulticastRoutingConfig.FORWARD_NONE;
75 import static android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL;
76 import static android.net.NetworkCapabilities.NET_CAPABILITY_ENTERPRISE;
77 import static android.net.NetworkCapabilities.NET_CAPABILITY_FOREGROUND;
78 import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
79 import static android.net.NetworkCapabilities.NET_CAPABILITY_LOCAL_NETWORK;
80 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_BANDWIDTH_CONSTRAINED;
81 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED;
82 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
83 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
84 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING;
85 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED;
86 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED;
87 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN;
88 import static android.net.NetworkCapabilities.NET_CAPABILITY_OEM_PAID;
89 import static android.net.NetworkCapabilities.NET_CAPABILITY_OEM_PRIVATE;
90 import static android.net.NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVITY;
91 import static android.net.NetworkCapabilities.NET_CAPABILITY_TEMPORARILY_NOT_METERED;
92 import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
93 import static android.net.NetworkCapabilities.NET_ENTERPRISE_ID_1;
94 import static android.net.NetworkCapabilities.NET_ENTERPRISE_ID_5;
95 import static android.net.NetworkCapabilities.REDACT_FOR_ACCESS_FINE_LOCATION;
96 import static android.net.NetworkCapabilities.REDACT_FOR_LOCAL_MAC_ADDRESS;
97 import static android.net.NetworkCapabilities.REDACT_FOR_NETWORK_SETTINGS;
98 import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
99 import static android.net.NetworkCapabilities.TRANSPORT_TEST;
100 import static android.net.NetworkCapabilities.TRANSPORT_VPN;
101 import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
102 import static android.net.NetworkRequest.Type.LISTEN_FOR_BEST;
103 import static android.net.NetworkScore.POLICY_TRANSPORT_PRIMARY;
104 import static android.net.OemNetworkPreferences.OEM_NETWORK_PREFERENCE_TEST;
105 import static android.net.OemNetworkPreferences.OEM_NETWORK_PREFERENCE_TEST_ONLY;
106 import static android.net.connectivity.ConnectivityCompatChanges.ENABLE_MATCH_LOCAL_NETWORK;
107 import static android.net.connectivity.ConnectivityCompatChanges.ENABLE_SELF_CERTIFIED_CAPABILITIES_DECLARATION;
108 import static android.net.connectivity.ConnectivityCompatChanges.NETWORK_BLOCKED_WITHOUT_INTERNET_PERMISSION;
109 import static android.os.Process.INVALID_UID;
110 import static android.os.Process.VPN_UID;
111 import static android.system.OsConstants.ETH_P_ALL;
112 import static android.system.OsConstants.F_OK;
113 import static android.system.OsConstants.IPPROTO_TCP;
114 import static android.system.OsConstants.IPPROTO_UDP;
115 
116 import static com.android.net.module.util.BpfUtils.BPF_CGROUP_GETSOCKOPT;
117 import static com.android.net.module.util.BpfUtils.BPF_CGROUP_INET4_BIND;
118 import static com.android.net.module.util.BpfUtils.BPF_CGROUP_INET4_CONNECT;
119 import static com.android.net.module.util.BpfUtils.BPF_CGROUP_INET6_BIND;
120 import static com.android.net.module.util.BpfUtils.BPF_CGROUP_INET6_CONNECT;
121 import static com.android.net.module.util.BpfUtils.BPF_CGROUP_INET_EGRESS;
122 import static com.android.net.module.util.BpfUtils.BPF_CGROUP_INET_INGRESS;
123 import static com.android.net.module.util.BpfUtils.BPF_CGROUP_INET_SOCK_CREATE;
124 import static com.android.net.module.util.BpfUtils.BPF_CGROUP_INET_SOCK_RELEASE;
125 import static com.android.net.module.util.BpfUtils.BPF_CGROUP_SETSOCKOPT;
126 import static com.android.net.module.util.BpfUtils.BPF_CGROUP_UDP4_RECVMSG;
127 import static com.android.net.module.util.BpfUtils.BPF_CGROUP_UDP4_SENDMSG;
128 import static com.android.net.module.util.BpfUtils.BPF_CGROUP_UDP6_RECVMSG;
129 import static com.android.net.module.util.BpfUtils.BPF_CGROUP_UDP6_SENDMSG;
130 import static com.android.net.module.util.NetworkMonitorUtils.isPrivateDnsValidationRequired;
131 import static com.android.net.module.util.PermissionUtils.enforceAnyPermissionOf;
132 import static com.android.net.module.util.PermissionUtils.enforceNetworkStackPermission;
133 import static com.android.net.module.util.PermissionUtils.enforceNetworkStackPermissionOr;
134 import static com.android.net.module.util.PermissionUtils.hasAnyPermissionOf;
135 import static com.android.server.ConnectivityStatsLog.CONNECTIVITY_STATE_SAMPLE;
136 import static com.android.server.connectivity.ConnectivityFlags.DELAY_DESTROY_SOCKETS;
137 import static com.android.server.connectivity.ConnectivityFlags.REQUEST_RESTRICTED_WIFI;
138 import static com.android.server.connectivity.ConnectivityFlags.INGRESS_TO_VPN_ADDRESS_FILTERING;
139 
140 import static java.util.Map.Entry;
141 
142 import android.Manifest;
143 import android.annotation.CheckResult;
144 import android.annotation.NonNull;
145 import android.annotation.Nullable;
146 import android.annotation.RequiresApi;
147 import android.annotation.SuppressLint;
148 import android.annotation.TargetApi;
149 import android.app.ActivityManager;
150 import android.app.ActivityManager.UidFrozenStateChangedCallback;
151 import android.app.AppOpsManager;
152 import android.app.BroadcastOptions;
153 import android.app.PendingIntent;
154 import android.app.admin.DevicePolicyManager;
155 import android.app.compat.CompatChanges;
156 import android.app.usage.NetworkStatsManager;
157 import android.content.BroadcastReceiver;
158 import android.content.ComponentName;
159 import android.content.ContentResolver;
160 import android.content.Context;
161 import android.content.Intent;
162 import android.content.IntentFilter;
163 import android.content.pm.PackageManager;
164 import android.content.res.XmlResourceParser;
165 import android.database.ContentObserver;
166 import android.net.BpfNetMapsUtils;
167 import android.net.CaptivePortal;
168 import android.net.CaptivePortalData;
169 import android.net.ConnectionInfo;
170 import android.net.ConnectivityDiagnosticsManager.ConnectivityReport;
171 import android.net.ConnectivityDiagnosticsManager.DataStallReport;
172 import android.net.ConnectivityManager;
173 import android.net.ConnectivityManager.BlockedReason;
174 import android.net.ConnectivityManager.NetworkCallback;
175 import android.net.ConnectivityManager.RestrictBackgroundStatus;
176 import android.net.ConnectivitySettingsManager;
177 import android.net.DataStallReportParcelable;
178 import android.net.DnsResolverServiceManager;
179 import android.net.DscpPolicy;
180 import android.net.ICaptivePortal;
181 import android.net.IConnectivityDiagnosticsCallback;
182 import android.net.IConnectivityManager;
183 import android.net.IDnsResolver;
184 import android.net.INetd;
185 import android.net.INetworkActivityListener;
186 import android.net.INetworkAgent;
187 import android.net.INetworkMonitor;
188 import android.net.INetworkMonitorCallbacks;
189 import android.net.INetworkOfferCallback;
190 import android.net.IOnCompleteListener;
191 import android.net.IQosCallback;
192 import android.net.ISocketKeepaliveCallback;
193 import android.net.InetAddresses;
194 import android.net.IpMemoryStore;
195 import android.net.IpPrefix;
196 import android.net.LinkProperties;
197 import android.net.LocalNetworkConfig;
198 import android.net.LocalNetworkInfo;
199 import android.net.MatchAllNetworkSpecifier;
200 import android.net.MulticastRoutingConfig;
201 import android.net.NativeNetworkConfig;
202 import android.net.NativeNetworkType;
203 import android.net.NattSocketKeepalive;
204 import android.net.Network;
205 import android.net.NetworkAgent;
206 import android.net.NetworkAgentConfig;
207 import android.net.NetworkCapabilities;
208 import android.net.NetworkInfo;
209 import android.net.NetworkInfo.DetailedState;
210 import android.net.NetworkMonitorManager;
211 import android.net.NetworkPolicyManager;
212 import android.net.NetworkPolicyManager.NetworkPolicyCallback;
213 import android.net.NetworkProvider;
214 import android.net.NetworkRequest;
215 import android.net.NetworkScore;
216 import android.net.NetworkSpecifier;
217 import android.net.NetworkStack;
218 import android.net.NetworkState;
219 import android.net.NetworkStateSnapshot;
220 import android.net.NetworkTestResultParcelable;
221 import android.net.NetworkUtils;
222 import android.net.NetworkWatchlistManager;
223 import android.net.OemNetworkPreferences;
224 import android.net.PrivateDnsConfigParcel;
225 import android.net.ProfileNetworkPreference;
226 import android.net.ProxyInfo;
227 import android.net.QosCallbackException;
228 import android.net.QosFilter;
229 import android.net.QosSocketFilter;
230 import android.net.QosSocketInfo;
231 import android.net.RouteInfo;
232 import android.net.SocketKeepalive;
233 import android.net.TetheringManager;
234 import android.net.TransportInfo;
235 import android.net.UidRange;
236 import android.net.UidRangeParcel;
237 import android.net.UnderlyingNetworkInfo;
238 import android.net.Uri;
239 import android.net.VpnManager;
240 import android.net.VpnTransportInfo;
241 import android.net.metrics.IpConnectivityLog;
242 import android.net.metrics.NetworkEvent;
243 import android.net.netd.aidl.NativeUidRangeConfig;
244 import android.net.networkstack.ModuleNetworkStackClient;
245 import android.net.networkstack.NetworkStackClientBase;
246 import android.net.networkstack.aidl.NetworkMonitorParameters;
247 import android.net.resolv.aidl.DnsHealthEventParcel;
248 import android.net.resolv.aidl.IDnsResolverUnsolicitedEventListener;
249 import android.net.resolv.aidl.Nat64PrefixEventParcel;
250 import android.net.resolv.aidl.PrivateDnsValidationEventParcel;
251 import android.net.shared.PrivateDnsConfig;
252 import android.net.wifi.WifiInfo;
253 import android.os.BatteryStatsManager;
254 import android.os.Binder;
255 import android.os.Build;
256 import android.os.Bundle;
257 import android.os.ConditionVariable;
258 import android.os.Handler;
259 import android.os.HandlerThread;
260 import android.os.IBinder;
261 import android.os.Looper;
262 import android.os.Message;
263 import android.os.Messenger;
264 import android.os.ParcelFileDescriptor;
265 import android.os.Parcelable;
266 import android.os.PersistableBundle;
267 import android.os.PowerManager;
268 import android.os.Process;
269 import android.os.RemoteCallbackList;
270 import android.os.RemoteException;
271 import android.os.ServiceSpecificException;
272 import android.os.SystemClock;
273 import android.os.SystemProperties;
274 import android.os.UserHandle;
275 import android.os.UserManager;
276 import android.provider.Settings;
277 import android.stats.connectivity.MeteredState;
278 import android.stats.connectivity.RequestType;
279 import android.stats.connectivity.ValidatedState;
280 import android.sysprop.NetworkProperties;
281 import android.system.ErrnoException;
282 import android.system.Os;
283 import android.telephony.SubscriptionManager;
284 import android.telephony.TelephonyManager;
285 import android.text.TextUtils;
286 import android.util.ArrayMap;
287 import android.util.ArraySet;
288 import android.util.LocalLog;
289 import android.util.Log;
290 import android.util.Pair;
291 import android.util.Range;
292 import android.util.SparseArray;
293 import android.util.SparseIntArray;
294 import android.util.StatsEvent;
295 
296 import com.android.connectivity.resources.R;
297 import com.android.internal.annotations.GuardedBy;
298 import com.android.internal.annotations.VisibleForTesting;
299 import com.android.internal.util.IndentingPrintWriter;
300 import com.android.internal.util.MessageUtils;
301 import com.android.metrics.ConnectionDurationForTransports;
302 import com.android.metrics.ConnectionDurationPerTransports;
303 import com.android.metrics.ConnectivitySampleMetricsHelper;
304 import com.android.metrics.ConnectivityStateSample;
305 import com.android.metrics.NetworkCountForTransports;
306 import com.android.metrics.NetworkCountPerTransports;
307 import com.android.metrics.NetworkDescription;
308 import com.android.metrics.NetworkList;
309 import com.android.metrics.NetworkRequestCount;
310 import com.android.metrics.RequestCountForType;
311 import com.android.modules.utils.BasicShellCommandHandler;
312 import com.android.modules.utils.build.SdkLevel;
313 import com.android.net.module.util.BaseNetdUnsolicitedEventListener;
314 import com.android.net.module.util.BinderUtils;
315 import com.android.net.module.util.BitUtils;
316 import com.android.net.module.util.BpfUtils;
317 import com.android.net.module.util.CollectionUtils;
318 import com.android.net.module.util.DeviceConfigUtils;
319 import com.android.net.module.util.HandlerUtils;
320 import com.android.net.module.util.InterfaceParams;
321 import com.android.net.module.util.LinkPropertiesUtils.CompareOrUpdateResult;
322 import com.android.net.module.util.LinkPropertiesUtils.CompareResult;
323 import com.android.net.module.util.LocationPermissionChecker;
324 import com.android.net.module.util.PerUidCounter;
325 import com.android.net.module.util.PermissionUtils;
326 import com.android.net.module.util.TcUtils;
327 import com.android.net.module.util.netlink.InetDiagMessage;
328 import com.android.networkstack.apishim.BroadcastOptionsShimImpl;
329 import com.android.networkstack.apishim.ConstantsShim;
330 import com.android.networkstack.apishim.common.BroadcastOptionsShim;
331 import com.android.networkstack.apishim.common.UnsupportedApiLevelException;
332 import com.android.server.connectivity.ApplicationSelfCertifiedNetworkCapabilities;
333 import com.android.server.connectivity.AutodestructReference;
334 import com.android.server.connectivity.AutomaticOnOffKeepaliveTracker;
335 import com.android.server.connectivity.AutomaticOnOffKeepaliveTracker.AutomaticOnOffKeepalive;
336 import com.android.server.connectivity.CarrierPrivilegeAuthenticator;
337 import com.android.server.connectivity.ClatCoordinator;
338 import com.android.server.connectivity.ConnectivityFlags;
339 import com.android.server.connectivity.ConnectivityResources;
340 import com.android.server.connectivity.DnsManager;
341 import com.android.server.connectivity.DnsManager.PrivateDnsValidationUpdate;
342 import com.android.server.connectivity.DscpPolicyTracker;
343 import com.android.server.connectivity.FullScore;
344 import com.android.server.connectivity.InvalidTagException;
345 import com.android.server.connectivity.KeepaliveResourceUtil;
346 import com.android.server.connectivity.KeepaliveTracker;
347 import com.android.server.connectivity.LingerMonitor;
348 import com.android.server.connectivity.MockableSystemProperties;
349 import com.android.server.connectivity.MulticastRoutingCoordinatorService;
350 import com.android.server.connectivity.MultinetworkPolicyTracker;
351 import com.android.server.connectivity.NetworkAgentInfo;
352 import com.android.server.connectivity.NetworkDiagnostics;
353 import com.android.server.connectivity.NetworkNotificationManager;
354 import com.android.server.connectivity.NetworkNotificationManager.NotificationType;
355 import com.android.server.connectivity.NetworkOffer;
356 import com.android.server.connectivity.NetworkPreferenceList;
357 import com.android.server.connectivity.NetworkRanker;
358 import com.android.server.connectivity.NetworkRequestStateStatsMetrics;
359 import com.android.server.connectivity.PermissionMonitor;
360 import com.android.server.connectivity.ProfileNetworkPreferenceInfo;
361 import com.android.server.connectivity.ProxyTracker;
362 import com.android.server.connectivity.QosCallbackTracker;
363 import com.android.server.connectivity.RoutingCoordinatorService;
364 import com.android.server.connectivity.SatelliteAccessController;
365 import com.android.server.connectivity.UidRangeUtils;
366 import com.android.server.connectivity.VpnNetworkPreferenceInfo;
367 import com.android.server.connectivity.wear.CompanionDeviceManagerProxyService;
368 
369 import libcore.io.IoUtils;
370 
371 import org.xmlpull.v1.XmlPullParserException;
372 
373 import java.io.FileDescriptor;
374 import java.io.IOException;
375 import java.io.InterruptedIOException;
376 import java.io.PrintWriter;
377 import java.io.Writer;
378 import java.net.Inet4Address;
379 import java.net.InetAddress;
380 import java.net.InetSocketAddress;
381 import java.net.SocketException;
382 import java.net.UnknownHostException;
383 import java.util.ArrayList;
384 import java.util.Arrays;
385 import java.util.Collection;
386 import java.util.Collections;
387 import java.util.Comparator;
388 import java.util.ConcurrentModificationException;
389 import java.util.HashMap;
390 import java.util.HashSet;
391 import java.util.List;
392 import java.util.Map;
393 import java.util.Map.Entry;
394 import java.util.NoSuchElementException;
395 import java.util.Objects;
396 import java.util.Random;
397 import java.util.Set;
398 import java.util.SortedSet;
399 import java.util.StringJoiner;
400 import java.util.TreeSet;
401 import java.util.concurrent.TimeUnit;
402 import java.util.concurrent.atomic.AtomicInteger;
403 import java.util.function.BiConsumer;
404 import java.util.function.Consumer;
405 
406 /**
407  * @hide
408  */
409 public class ConnectivityService extends IConnectivityManager.Stub
410         implements PendingIntent.OnFinished {
411     private static final String TAG = ConnectivityService.class.getSimpleName();
412 
413     private static final String DIAG_ARG = "--diag";
414     public static final String SHORT_ARG = "--short";
415     private static final String NETWORK_ARG = "networks";
416     private static final String REQUEST_ARG = "requests";
417     private static final String TRAFFICCONTROLLER_ARG = "trafficcontroller";
418     public static final String CLATEGRESS4RAWBPFMAP_ARG = "clatEgress4RawBpfMap";
419     public static final String CLATINGRESS6RAWBPFMAP_ARG = "clatIngress6RawBpfMap";
420 
421     private static final boolean DBG = true;
422     private static final boolean DDBG = Log.isLoggable(TAG, Log.DEBUG);
423     private static final boolean VDBG = Log.isLoggable(TAG, Log.VERBOSE);
424 
425     private static final boolean LOGD_BLOCKED_NETWORKINFO = true;
426 
427     /**
428      * Default URL to use for {@link #getCaptivePortalServerUrl()}. This should not be changed
429      * by OEMs for configuration purposes, as this value is overridden by
430      * ConnectivitySettingsManager.CAPTIVE_PORTAL_HTTP_URL.
431      * R.string.config_networkCaptivePortalServerUrl should be overridden instead for this purpose
432      * (preferably via runtime resource overlays).
433      */
434     private static final String DEFAULT_CAPTIVE_PORTAL_HTTP_URL =
435             "http://connectivitycheck.gstatic.com/generate_204";
436 
437     // TODO: create better separation between radio types and network types
438 
439     // how long to wait before switching back to a radio's default network
440     private static final int RESTORE_DEFAULT_NETWORK_DELAY = 1 * 60 * 1000;
441     // system property that can override the above value
442     private static final String NETWORK_RESTORE_DELAY_PROP_NAME =
443             "android.telephony.apn-restore";
444 
445     // How long to wait before putting up a "This network doesn't have an Internet connection,
446     // connect anyway?" dialog after the user selects a network that doesn't validate.
447     private static final int PROMPT_UNVALIDATED_DELAY_MS = 8 * 1000;
448 
449     // How long to wait before considering that a network is bad in the absence of any form
450     // of connectivity (valid, partial, captive portal). If none has been detected after this
451     // delay, the stack considers this network bad, which may affect how it's handled in ranking
452     // according to config_networkAvoidBadWifi.
453     // Timeout in case the "actively prefer bad wifi" feature is on
454     private static final int ACTIVELY_PREFER_BAD_WIFI_INITIAL_TIMEOUT_MS = 20 * 1000;
455     // Timeout in case the "actively prefer bad wifi" feature is off
456     private static final int DEFAULT_EVALUATION_TIMEOUT_MS = 8 * 1000;
457 
458     // Default to 30s linger time-out, and 5s for nascent network. Modifiable only for testing.
459     private static final String LINGER_DELAY_PROPERTY = "persist.netmon.linger";
460     private static final int DEFAULT_LINGER_DELAY_MS = 30_000;
461     private static final int DEFAULT_NASCENT_DELAY_MS = 5_000;
462 
463     // Delimiter used when creating the broadcast delivery group for sending
464     // CONNECTIVITY_ACTION broadcast.
465     private static final char DELIVERY_GROUP_KEY_DELIMITER = ';';
466 
467     // The maximum value for the blocking validation result, in milliseconds.
468     public static final int MAX_VALIDATION_IGNORE_AFTER_ROAM_TIME_MS = 10000;
469 
470     // The maximum number of network request allowed per uid before an exception is thrown.
471     @VisibleForTesting
472     static final int MAX_NETWORK_REQUESTS_PER_UID = 100;
473 
474     // The maximum number of network request allowed for system UIDs before an exception is thrown.
475     @VisibleForTesting
476     static final int MAX_NETWORK_REQUESTS_PER_SYSTEM_UID = 250;
477 
478     @VisibleForTesting
479     protected int mLingerDelayMs;  // Can't be final, or test subclass constructors can't change it.
480     @VisibleForTesting
481     protected int mNascentDelayMs;
482     // True if the cell radio of the device is capable of time-sharing.
483     @VisibleForTesting
484     protected boolean mCellularRadioTimesharingCapable = true;
485 
486     // How long to delay to removal of a pending intent based request.
487     // See ConnectivitySettingsManager.CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS
488     private final int mReleasePendingIntentDelayMs;
489 
490     private final MockableSystemProperties mSystemProperties;
491 
492     private final PermissionMonitor mPermissionMonitor;
493 
494     @VisibleForTesting
495     final RequestInfoPerUidCounter mNetworkRequestCounter;
496     @VisibleForTesting
497     final RequestInfoPerUidCounter mSystemNetworkRequestCounter;
498 
499     private volatile boolean mLockdownEnabled;
500 
501     private final boolean mRequestRestrictedWifiEnabled;
502     private final boolean mBackgroundFirewallChainEnabled;
503 
504     private final boolean mUseDeclaredMethodsForCallbacksEnabled;
505 
506     /**
507      * Uids ConnectivityService tracks blocked status of to send blocked status callbacks.
508      * Key is uid based on mAsUid of registered networkRequestInfo
509      * Value is count of registered networkRequestInfo
510      *
511      * This is necessary because when a firewall chain is enabled or disabled, that affects all UIDs
512      * on the system, not just UIDs on that firewall chain. For example, entering doze mode affects
513      * all UIDs that are not on the dozable chain. ConnectivityService doesn't know which UIDs are
514      * running. But it only needs to send onBlockedStatusChanged to UIDs that have at least one
515      * NetworkCallback registered.
516      *
517      * UIDs are added to this list on the binder thread when processing requestNetwork and similar
518      * IPCs. They are removed from this list on the handler thread, when the callback unregistration
519      * is fully processed. They cannot be unregistered when the unregister IPC is processed because
520      * sometimes requests are unregistered on the handler thread.
521      */
522     @GuardedBy("mBlockedStatusTrackingUids")
523     private final SparseIntArray mBlockedStatusTrackingUids = new SparseIntArray();
524 
525     /**
526      * Stale copy of UID blocked reasons. This is used to send onBlockedStatusChanged
527      * callbacks. This is only used on the handler thread, so it does not require a lock.
528      * On U-, the blocked reasons come from NPMS.
529      * On V+, the blocked reasons come from the BPF map contents and only maintains blocked reasons
530      * of uids that register network callbacks.
531      */
532     private final SparseIntArray mUidBlockedReasons = new SparseIntArray();
533 
534     private final Context mContext;
535     private final ConnectivityResources mResources;
536     private final int mWakeUpMark;
537     private final int mWakeUpMask;
538     // The Context is created for UserHandle.ALL.
539     private final Context mUserAllContext;
540     private final Dependencies mDeps;
541     private final ConnectivityFlags mFlags;
542     // 0 is full bad, 100 is full good
543     private int mDefaultInetConditionPublished = 0;
544 
545     @VisibleForTesting
546     protected IDnsResolver mDnsResolver;
547     @VisibleForTesting
548     protected INetd mNetd;
549     private DscpPolicyTracker mDscpPolicyTracker = null;
550     private final NetworkStatsManager mStatsManager;
551     private final NetworkPolicyManager mPolicyManager;
552     private final BpfNetMaps mBpfNetMaps;
553 
554     /**
555      * TestNetworkService (lazily) created upon first usage. Locked to prevent creation of multiple
556      * instances.
557      */
558     @GuardedBy("mTNSLock")
559     private TestNetworkService mTNS;
560     private final CompanionDeviceManagerProxyService mCdmps;
561     private final MulticastRoutingCoordinatorService mMulticastRoutingCoordinatorService;
562     private final RoutingCoordinatorService mRoutingCoordinatorService;
563 
564     private final Object mTNSLock = new Object();
565 
566     private String mCurrentTcpBufferSizes;
567 
568     private static final SparseArray<String> sMagicDecoderRing = MessageUtils.findMessageNames(
569             new Class[] {
570                     ConnectivityService.class,
571                     NetworkAgent.class,
572                     NetworkAgentInfo.class,
573                     AutomaticOnOffKeepaliveTracker.class });
574 
575     private enum ReapUnvalidatedNetworks {
576         // Tear down networks that have no chance (e.g. even if validated) of becoming
577         // the highest scoring network satisfying a NetworkRequest.  This should be passed when
578         // all networks have been rematched against all NetworkRequests.
579         REAP,
580         // Don't reap networks.  This should be passed when some networks have not yet been
581         // rematched against all NetworkRequests.
582         DONT_REAP
583     }
584 
585     private enum UnneededFor {
586         LINGER,    // Determine whether this network is unneeded and should be lingered.
587         TEARDOWN,  // Determine whether this network is unneeded and should be torn down.
588     }
589 
590     /**
591      * For per-app preferences, requests contain an int to signify which request
592      * should have priority. The order is passed to netd which will use it together
593      * with UID ranges to generate the corresponding IP rule. This serves to
594      * direct device-originated data traffic of the specific UIDs to the correct
595      * default network for each app.
596      * Order ints passed to netd must be in the 0~999 range. Larger values code for
597      * a lower priority, see {@link NativeUidRangeConfig}.
598      * Note that only the highest priority preference is applied if the uid is the target of
599      * multiple preferences.
600      *
601      * Requests that don't code for a per-app preference use PREFERENCE_ORDER_INVALID.
602      * The default request uses PREFERENCE_ORDER_DEFAULT.
603      */
604     // Used when sending to netd to code for "no order".
605     static final int PREFERENCE_ORDER_NONE = 0;
606     // Order for requests that don't code for a per-app preference. As it is
607     // out of the valid range, the corresponding order should be
608     // PREFERENCE_ORDER_NONE when sending to netd.
609     @VisibleForTesting
610     static final int PREFERENCE_ORDER_INVALID = Integer.MAX_VALUE;
611     // As a security feature, VPNs have the top priority.
612     static final int PREFERENCE_ORDER_VPN = 0; // Netd supports only 0 for VPN.
613     // Order of per-app OEM preference. See {@link #setOemNetworkPreference}.
614     @VisibleForTesting
615     static final int PREFERENCE_ORDER_OEM = 10;
616     // Order of per-profile preference, such as used by enterprise networks.
617     // See {@link #setProfileNetworkPreference}.
618     @VisibleForTesting
619     static final int PREFERENCE_ORDER_PROFILE = 20;
620     // Order of user setting to prefer mobile data even when networks with
621     // better scores are connected.
622     // See {@link ConnectivitySettingsManager#setMobileDataPreferredUids}
623     @VisibleForTesting
624     static final int PREFERENCE_ORDER_MOBILE_DATA_PREFERERRED = 30;
625     // Order of setting satellite network preference fallback when default message application
626     // with role_sms role and android.permission.SATELLITE_COMMUNICATION permission detected
627     @VisibleForTesting
628     static final int PREFERENCE_ORDER_SATELLITE_FALLBACK = 40;
629     // Preference order that signifies the network shouldn't be set as a default network for
630     // the UIDs, only give them access to it. TODO : replace this with a boolean
631     // in NativeUidRangeConfig
632     @VisibleForTesting
633     static final int PREFERENCE_ORDER_IRRELEVANT_BECAUSE_NOT_DEFAULT = 999;
634     // Bound for the lowest valid preference order.
635     static final int PREFERENCE_ORDER_LOWEST = 999;
636 
637     /**
638      * used internally to clear a wakelock when transitioning
639      * from one net to another.  Clear happens when we get a new
640      * network - EVENT_EXPIRE_NET_TRANSITION_WAKELOCK happens
641      * after a timeout if no network is found (typically 1 min).
642      */
643     private static final int EVENT_CLEAR_NET_TRANSITION_WAKELOCK = 8;
644 
645     /**
646      * used internally to reload global proxy settings
647      */
648     private static final int EVENT_APPLY_GLOBAL_HTTP_PROXY = 9;
649 
650     /**
651      * PAC manager has received new port.
652      */
653     private static final int EVENT_PAC_PROXY_HAS_CHANGED = 16;
654 
655     /**
656      * used internally when registering NetworkProviders
657      * obj = NetworkProviderInfo
658      */
659     private static final int EVENT_REGISTER_NETWORK_PROVIDER = 17;
660 
661     /**
662      * used internally when registering NetworkAgents
663      * obj = Messenger
664      */
665     private static final int EVENT_REGISTER_NETWORK_AGENT = 18;
666 
667     /**
668      * used to add a network request
669      * includes a NetworkRequestInfo
670      */
671     private static final int EVENT_REGISTER_NETWORK_REQUEST = 19;
672 
673     /**
674      * indicates a timeout period is over - check if we had a network yet or not
675      * and if not, call the timeout callback (but leave the request live until they
676      * cancel it.
677      * includes a NetworkRequestInfo
678      */
679     private static final int EVENT_TIMEOUT_NETWORK_REQUEST = 20;
680 
681     /**
682      * used to add a network listener - no request
683      * includes a NetworkRequestInfo
684      */
685     private static final int EVENT_REGISTER_NETWORK_LISTENER = 21;
686 
687     /**
688      * used to remove a network request, either a listener or a real request
689      * arg1 = UID of caller
690      * obj  = NetworkRequest
691      */
692     private static final int EVENT_RELEASE_NETWORK_REQUEST = 22;
693 
694     /**
695      * used internally when registering NetworkProviders
696      * obj = Messenger
697      */
698     private static final int EVENT_UNREGISTER_NETWORK_PROVIDER = 23;
699 
700     /**
701      * used internally to expire a wakelock when transitioning
702      * from one net to another.  Expire happens when we fail to find
703      * a new network (typically after 1 minute) -
704      * EVENT_CLEAR_NET_TRANSITION_WAKELOCK happens if we had found
705      * a replacement network.
706      */
707     private static final int EVENT_EXPIRE_NET_TRANSITION_WAKELOCK = 24;
708 
709     /**
710      * used to add a network request with a pending intent
711      * obj = NetworkRequestInfo
712      */
713     private static final int EVENT_REGISTER_NETWORK_REQUEST_WITH_INTENT = 26;
714 
715     /**
716      * used to remove a pending intent and its associated network request.
717      * arg1 = UID of caller
718      * obj  = PendingIntent
719      */
720     private static final int EVENT_RELEASE_NETWORK_REQUEST_WITH_INTENT = 27;
721 
722     /**
723      * used to specify whether a network should be used even if unvalidated.
724      * arg1 = whether to accept the network if it's unvalidated (1 or 0)
725      * arg2 = whether to remember this choice in the future (1 or 0)
726      * obj  = network
727      */
728     private static final int EVENT_SET_ACCEPT_UNVALIDATED = 28;
729 
730     /**
731      * used internally to (re)configure always-on networks.
732      */
733     private static final int EVENT_CONFIGURE_ALWAYS_ON_NETWORKS = 30;
734 
735     /**
736      * used to add a network listener with a pending intent
737      * obj = NetworkRequestInfo
738      */
739     private static final int EVENT_REGISTER_NETWORK_LISTENER_WITH_INTENT = 31;
740 
741     /**
742      * used to specify whether a network should not be penalized when it becomes unvalidated.
743      */
744     private static final int EVENT_SET_AVOID_UNVALIDATED = 35;
745 
746     /**
747      * used to handle reported network connectivity. May trigger revalidation of a network.
748      */
749     private static final int EVENT_REPORT_NETWORK_CONNECTIVITY = 36;
750 
751     // Handle changes in Private DNS settings.
752     private static final int EVENT_PRIVATE_DNS_SETTINGS_CHANGED = 37;
753 
754     // Handle private DNS validation status updates.
755     private static final int EVENT_PRIVATE_DNS_VALIDATION_UPDATE = 38;
756 
757      /**
758       * Event for NetworkMonitor/NetworkAgentInfo to inform ConnectivityService that the network has
759       * been tested.
760       * obj = {@link NetworkTestedResults} representing information sent from NetworkMonitor.
761       * data = PersistableBundle of extras passed from NetworkMonitor. If {@link
762       * NetworkMonitorCallbacks#notifyNetworkTested} is called, this will be null.
763       */
764     private static final int EVENT_NETWORK_TESTED = 41;
765 
766     /**
767      * Event for NetworkMonitor/NetworkAgentInfo to inform ConnectivityService that the private DNS
768      * config was resolved.
769      * obj = PrivateDnsConfig
770      * arg2 = netid
771      */
772     private static final int EVENT_PRIVATE_DNS_CONFIG_RESOLVED = 42;
773 
774     /**
775      * Request ConnectivityService display provisioning notification.
776      * arg1    = Whether to make the notification visible.
777      * arg2    = NetID.
778      * obj     = Intent to be launched when notification selected by user, null if !arg1.
779      */
780     private static final int EVENT_PROVISIONING_NOTIFICATION = 43;
781 
782     /**
783      * Used to specify whether a network should be used even if connectivity is partial.
784      * arg1 = whether to accept the network if its connectivity is partial (1 for true or 0 for
785      * false)
786      * arg2 = whether to remember this choice in the future (1 for true or 0 for false)
787      * obj  = network
788      */
789     private static final int EVENT_SET_ACCEPT_PARTIAL_CONNECTIVITY = 44;
790 
791     /**
792      * Event for NetworkMonitor to inform ConnectivityService that the probe status has changed.
793      * Both of the arguments are bitmasks, and the value of bits come from
794      * INetworkMonitor.NETWORK_VALIDATION_PROBE_*.
795      * arg1 = unused
796      * arg2 = netId
797      * obj = A Pair of integers: the bitmasks of, respectively, completed and successful probes.
798      */
799     public static final int EVENT_PROBE_STATUS_CHANGED = 45;
800 
801     /**
802      * Event for NetworkMonitor to inform ConnectivityService that captive portal data has changed.
803      * arg1 = unused
804      * arg2 = netId
805      * obj = captive portal data
806      */
807     private static final int EVENT_CAPPORT_DATA_CHANGED = 46;
808 
809     /**
810      * Used by setRequireVpnForUids.
811      * arg1 = whether the specified UID ranges are required to use a VPN.
812      * obj  = Array of UidRange objects.
813      */
814     private static final int EVENT_SET_REQUIRE_VPN_FOR_UIDS = 47;
815 
816     /**
817      * Used internally when setting the default networks for OemNetworkPreferences.
818      * obj = Pair<OemNetworkPreferences, listener>
819      */
820     private static final int EVENT_SET_OEM_NETWORK_PREFERENCE = 48;
821 
822     /**
823      * Used to indicate the system default network becomes active.
824      */
825     private static final int EVENT_REPORT_NETWORK_ACTIVITY = 49;
826 
827     /**
828      * Used internally when setting a network preference for a user profile.
829      * obj = Pair<ProfileNetworkPreference, Listener>
830      */
831     private static final int EVENT_SET_PROFILE_NETWORK_PREFERENCE = 50;
832 
833     /**
834      * Event to update blocked reasons for uids.
835      * obj = List of Pair(uid, blockedReasons)
836      */
837     private static final int EVENT_BLOCKED_REASONS_CHANGED = 51;
838 
839     /**
840      * Event to register a new network offer
841      * obj = NetworkOffer
842      */
843     private static final int EVENT_REGISTER_NETWORK_OFFER = 52;
844 
845     /**
846      * Event to unregister an existing network offer
847      * obj = INetworkOfferCallback
848      */
849     private static final int EVENT_UNREGISTER_NETWORK_OFFER = 53;
850 
851     /**
852      * Used internally when MOBILE_DATA_PREFERRED_UIDS setting changed.
853      */
854     private static final int EVENT_MOBILE_DATA_PREFERRED_UIDS_CHANGED = 54;
855 
856     /**
857      * Event to set temporary allow bad wifi within a limited time to override
858      * {@code config_networkAvoidBadWifi}.
859      */
860     private static final int EVENT_SET_TEST_ALLOW_BAD_WIFI_UNTIL = 55;
861 
862     /**
863      * Used internally when INGRESS_RATE_LIMIT_BYTES_PER_SECOND setting changes.
864      */
865     private static final int EVENT_INGRESS_RATE_LIMIT_CHANGED = 56;
866 
867     /**
868      * The initial evaluation period is over for this network.
869      *
870      * If no form of connectivity has been found on this network (valid, partial, captive portal)
871      * then the stack will now consider it to have been determined bad.
872      */
873     private static final int EVENT_INITIAL_EVALUATION_TIMEOUT = 57;
874 
875     /**
876      * Used internally when the user does not want the network from captive portal app.
877      * obj = Network
878      */
879     private static final int EVENT_USER_DOES_NOT_WANT = 58;
880 
881     /**
882      * Event to set VPN as preferred network for specific apps.
883      * obj = VpnNetworkPreferenceInfo
884      */
885     private static final int EVENT_SET_VPN_NETWORK_PREFERENCE = 59;
886 
887     /**
888      * Event to use low TCP polling timer used in automatic on/off keepalive temporarily.
889      */
890     private static final int EVENT_SET_LOW_TCP_POLLING_UNTIL = 60;
891 
892     /**
893      * Event to inform the ConnectivityService handler when a uid has been frozen or unfrozen.
894      */
895     private static final int EVENT_UID_FROZEN_STATE_CHANGED = 61;
896 
897     /**
898      * Event to update firewall socket destroy reasons for uids.
899      * obj = List of Pair(uid, socketDestroyReasons)
900      */
901     private static final int EVENT_UPDATE_FIREWALL_DESTROY_SOCKET_REASONS = 62;
902 
903     /**
904      * Event to clear firewall socket destroy reasons for all uids.
905      * arg1 = socketDestroyReason
906      */
907     private static final int EVENT_CLEAR_FIREWALL_DESTROY_SOCKET_REASONS = 63;
908 
909     /**
910      * Argument for {@link #EVENT_PROVISIONING_NOTIFICATION} to indicate that the notification
911      * should be shown.
912      */
913     private static final int PROVISIONING_NOTIFICATION_SHOW = 1;
914 
915     /**
916      * Argument for {@link #EVENT_PROVISIONING_NOTIFICATION} to indicate that the notification
917      * should be hidden.
918      */
919     private static final int PROVISIONING_NOTIFICATION_HIDE = 0;
920 
921     /**
922      * The maximum alive time to allow bad wifi configuration for testing.
923      */
924     private static final long MAX_TEST_ALLOW_BAD_WIFI_UNTIL_MS = 5 * 60 * 1000L;
925 
926     /**
927      * The maximum alive time to decrease TCP polling timer in automatic on/off keepalive for
928      * testing.
929      */
930     private static final long MAX_TEST_LOW_TCP_POLLING_UNTIL_MS = 5 * 60 * 1000L;
931 
932     /**
933      * The priority of the tc police rate limiter -- smaller value is higher priority.
934      * This value needs to be coordinated with PRIO_CLAT, PRIO_TETHER4, and PRIO_TETHER6.
935      */
936     private static final short TC_PRIO_POLICE = 1;
937 
938     /**
939      * The BPF program attached to the tc-police hook to account for to-be-dropped traffic.
940      */
941     private static final String TC_POLICE_BPF_PROG_PATH =
942             "/sys/fs/bpf/netd_shared/prog_netd_schedact_ingress_account";
943 
eventName(int what)944     private static String eventName(int what) {
945         return sMagicDecoderRing.get(what, Integer.toString(what));
946     }
947 
getDnsResolver(Context context)948     private static IDnsResolver getDnsResolver(Context context) {
949         final DnsResolverServiceManager dsm = context.getSystemService(
950                 DnsResolverServiceManager.class);
951         return IDnsResolver.Stub.asInterface(dsm.getService());
952     }
953 
954     /** Handler thread used for all of the handlers below. */
955     @VisibleForTesting
956     protected final HandlerThread mHandlerThread;
957     /** Handler used for internal events. */
958     final private InternalHandler mHandler;
959     /** Handler used for incoming {@link NetworkStateTracker} events. */
960     final private NetworkStateTrackerHandler mTrackerHandler;
961     /** Handler used for processing {@link android.net.ConnectivityDiagnosticsManager} events */
962     @VisibleForTesting
963     final ConnectivityDiagnosticsHandler mConnectivityDiagnosticsHandler;
964 
965     private final DnsManager mDnsManager;
966     @VisibleForTesting
967     final NetworkRanker mNetworkRanker;
968 
969     private boolean mSystemReady;
970     private Intent mInitialBroadcast;
971 
972     private final PowerManager.WakeLock mNetTransitionWakeLock;
973     private final PowerManager.WakeLock mPendingIntentWakeLock;
974 
975     // A helper object to track the current default HTTP proxy. ConnectivityService needs to tell
976     // the world when it changes.
977     private final ProxyTracker mProxyTracker;
978 
979     final private SettingsObserver mSettingsObserver;
980 
981     private final UserManager mUserManager;
982 
983     // the set of network types that can only be enabled by system/sig apps
984     private final List<Integer> mProtectedNetworks;
985 
986     private Set<String> mWolSupportedInterfaces;
987 
988     private final TelephonyManager mTelephonyManager;
989     private final CarrierPrivilegeAuthenticator mCarrierPrivilegeAuthenticator;
990     private final AppOpsManager mAppOpsManager;
991 
992     private final LocationPermissionChecker mLocationPermissionChecker;
993 
994     private final AutomaticOnOffKeepaliveTracker mKeepaliveTracker;
995     private final QosCallbackTracker mQosCallbackTracker;
996     private final NetworkNotificationManager mNotifier;
997     private final LingerMonitor mLingerMonitor;
998     private final SatelliteAccessController mSatelliteAccessController;
999 
1000     // sequence number of NetworkRequests
1001     private int mNextNetworkRequestId = NetworkRequest.FIRST_REQUEST_ID;
1002 
1003     // Sequence number for NetworkProvider IDs.
1004     private final AtomicInteger mNextNetworkProviderId = new AtomicInteger(
1005             NetworkProvider.FIRST_PROVIDER_ID);
1006 
1007     // NetworkRequest activity String log entries.
1008     private static final int MAX_NETWORK_REQUEST_LOGS = 20;
1009     private final LocalLog mNetworkRequestInfoLogs = new LocalLog(MAX_NETWORK_REQUEST_LOGS);
1010 
1011     // NetworkInfo blocked and unblocked String log entries
1012     private static final int MAX_NETWORK_INFO_LOGS = 40;
1013     private final LocalLog mNetworkInfoBlockingLogs = new LocalLog(MAX_NETWORK_INFO_LOGS);
1014 
1015     private static final int MAX_WAKELOCK_LOGS = 20;
1016     private final LocalLog mWakelockLogs = new LocalLog(MAX_WAKELOCK_LOGS);
1017     private int mTotalWakelockAcquisitions = 0;
1018     private int mTotalWakelockReleases = 0;
1019     private long mTotalWakelockDurationMs = 0;
1020     private long mMaxWakelockDurationMs = 0;
1021     private long mLastWakeLockAcquireTimestamp = 0;
1022 
1023     private final IpConnectivityLog mMetricsLog;
1024 
1025     @Nullable private final NetworkRequestStateStatsMetrics mNetworkRequestStateStatsMetrics;
1026 
1027     @GuardedBy("mBandwidthRequests")
1028     private final SparseArray<Integer> mBandwidthRequests = new SparseArray<>(10);
1029 
1030     @VisibleForTesting
1031     final MultinetworkPolicyTracker mMultinetworkPolicyTracker;
1032 
1033     @VisibleForTesting
1034     final Map<IBinder, ConnectivityDiagnosticsCallbackInfo> mConnectivityDiagnosticsCallbacks =
1035             new HashMap<>();
1036 
1037     // Rate limit applicable to all internet capable networks (-1 = disabled). This value is
1038     // configured via {@link
1039     // ConnectivitySettingsManager#INGRESS_RATE_LIMIT_BYTES_PER_SECOND}
1040     // Only the handler thread is allowed to access this field.
1041     private long mIngressRateLimit = -1;
1042 
1043     // This is the cache for the packageName -> ApplicationSelfCertifiedNetworkCapabilities. This
1044     // value can be accessed from both handler thread and any random binder thread. Therefore,
1045     // accessing this value requires holding a lock. The cache is the same across all the users.
1046     @GuardedBy("mSelfCertifiedCapabilityCache")
1047     private final Map<String, ApplicationSelfCertifiedNetworkCapabilities>
1048             mSelfCertifiedCapabilityCache = new HashMap<>();
1049 
1050     // Flag to enable the feature of closing frozen app sockets.
1051     private final boolean mDestroyFrozenSockets;
1052 
1053     // Flag to optimize closing app sockets by waiting for the cellular modem to wake up.
1054     private final boolean mDelayDestroySockets;
1055 
1056     // Flag to allow SysUI to receive connectivity reports for wifi picker UI.
1057     private final boolean mAllowSysUiConnectivityReports;
1058 
1059     // Uids that ConnectivityService is pending to close sockets of.
1060     // Key is uid and value is reasons of socket destroy
1061     private final SparseIntArray mDestroySocketPendingUids = new SparseIntArray();
1062 
1063     private static final int DESTROY_SOCKET_REASON_NONE = 0;
1064     private static final int DESTROY_SOCKET_REASON_FROZEN = 1 << 0;
1065     private static final int DESTROY_SOCKET_REASON_FIREWALL_BACKGROUND = 1 << 1;
1066 
1067     // Flag to drop packets to VPN addresses ingressing via non-VPN interfaces.
1068     private final boolean mIngressToVpnAddressFiltering;
1069 
1070     /**
1071      * Implements support for the legacy "one network per network type" model.
1072      *
1073      * We used to have a static array of NetworkStateTrackers, one for each
1074      * network type, but that doesn't work any more now that we can have,
1075      * for example, more that one wifi network. This class stores all the
1076      * NetworkAgentInfo objects that support a given type, but the legacy
1077      * API will only see the first one.
1078      *
1079      * It serves two main purposes:
1080      *
1081      * 1. Provide information about "the network for a given type" (since this
1082      *    API only supports one).
1083      * 2. Send legacy connectivity change broadcasts. Broadcasts are sent if
1084      *    the first network for a given type changes, or if the default network
1085      *    changes.
1086      */
1087     @VisibleForTesting
1088     static class LegacyTypeTracker {
1089 
1090         private static final boolean DBG = true;
1091         private static final boolean VDBG = false;
1092 
1093         /**
1094          * Array of lists, one per legacy network type (e.g., TYPE_MOBILE_MMS).
1095          * Each list holds references to all NetworkAgentInfos that are used to
1096          * satisfy requests for that network type.
1097          *
1098          * This array is built out at startup such that an unsupported network
1099          * doesn't get an ArrayList instance, making this a tristate:
1100          * unsupported, supported but not active and active.
1101          *
1102          * The actual lists are populated when we scan the network types that
1103          * are supported on this device.
1104          *
1105          * Threading model:
1106          *  - addSupportedType() is only called in the constructor
1107          *  - add(), update(), remove() are only called from the ConnectivityService handler thread.
1108          *    They are therefore not thread-safe with respect to each other.
1109          *  - getNetworkForType() can be called at any time on binder threads. It is synchronized
1110          *    on mTypeLists to be thread-safe with respect to a concurrent remove call.
1111          *  - getRestoreTimerForType(type) is also synchronized on mTypeLists.
1112          *  - dump is thread-safe with respect to concurrent add and remove calls.
1113          */
1114         private final ArrayList<NetworkAgentInfo>[] mTypeLists;
1115         @NonNull
1116         private final ConnectivityService mService;
1117 
1118         // Restore timers for requestNetworkForFeature (network type -> timer in ms). Types without
1119         // an entry have no timer (equivalent to -1). Lazily loaded.
1120         @NonNull
1121         private ArrayMap<Integer, Integer> mRestoreTimers = new ArrayMap<>();
1122 
LegacyTypeTracker(@onNull ConnectivityService service)1123         LegacyTypeTracker(@NonNull ConnectivityService service) {
1124             mService = service;
1125             mTypeLists = new ArrayList[ConnectivityManager.MAX_NETWORK_TYPE + 1];
1126         }
1127 
1128         // TODO: Set the mini sdk to 31 and remove @TargetApi annotation when b/205923322 is
1129         //  addressed.
1130         @TargetApi(Build.VERSION_CODES.S)
loadSupportedTypes(@onNull Context ctx, @NonNull TelephonyManager tm)1131         public void loadSupportedTypes(@NonNull Context ctx, @NonNull TelephonyManager tm) {
1132             final PackageManager pm = ctx.getPackageManager();
1133             if (pm.hasSystemFeature(FEATURE_WIFI)) {
1134                 addSupportedType(TYPE_WIFI);
1135             }
1136             if (pm.hasSystemFeature(FEATURE_WIFI_DIRECT)) {
1137                 addSupportedType(TYPE_WIFI_P2P);
1138             }
1139             if (tm.isDataCapable()) {
1140                 // Telephony does not have granular support for these types: they are either all
1141                 // supported, or none is supported
1142                 addSupportedType(TYPE_MOBILE);
1143                 addSupportedType(TYPE_MOBILE_MMS);
1144                 addSupportedType(TYPE_MOBILE_SUPL);
1145                 addSupportedType(TYPE_MOBILE_DUN);
1146                 addSupportedType(TYPE_MOBILE_HIPRI);
1147                 addSupportedType(TYPE_MOBILE_FOTA);
1148                 addSupportedType(TYPE_MOBILE_IMS);
1149                 addSupportedType(TYPE_MOBILE_CBS);
1150                 addSupportedType(TYPE_MOBILE_IA);
1151                 addSupportedType(TYPE_MOBILE_EMERGENCY);
1152             }
1153             if (pm.hasSystemFeature(FEATURE_BLUETOOTH)) {
1154                 addSupportedType(TYPE_BLUETOOTH);
1155             }
1156             if (pm.hasSystemFeature(FEATURE_WATCH)) {
1157                 // TYPE_PROXY is only used on Wear
1158                 addSupportedType(TYPE_PROXY);
1159             }
1160             // Ethernet is often not specified in the configs, although many devices can use it via
1161             // USB host adapters. Add it as long as the ethernet service is here.
1162             if (deviceSupportsEthernet(ctx)) {
1163                 addSupportedType(TYPE_ETHERNET);
1164             }
1165 
1166             // Always add TYPE_VPN as a supported type
1167             addSupportedType(TYPE_VPN);
1168         }
1169 
addSupportedType(int type)1170         private void addSupportedType(int type) {
1171             if (mTypeLists[type] != null) {
1172                 throw new IllegalStateException(
1173                         "legacy list for type " + type + "already initialized");
1174             }
1175             mTypeLists[type] = new ArrayList<>();
1176         }
1177 
isTypeSupported(int type)1178         public boolean isTypeSupported(int type) {
1179             return isNetworkTypeValid(type) && mTypeLists[type] != null;
1180         }
1181 
getNetworkForType(int type)1182         public NetworkAgentInfo getNetworkForType(int type) {
1183             synchronized (mTypeLists) {
1184                 if (isTypeSupported(type) && !mTypeLists[type].isEmpty()) {
1185                     return mTypeLists[type].get(0);
1186                 }
1187             }
1188             return null;
1189         }
1190 
getRestoreTimerForType(int type)1191         public int getRestoreTimerForType(int type) {
1192             synchronized (mTypeLists) {
1193                 if (mRestoreTimers == null) {
1194                     mRestoreTimers = loadRestoreTimers();
1195                 }
1196                 return mRestoreTimers.getOrDefault(type, -1);
1197             }
1198         }
1199 
loadRestoreTimers()1200         private ArrayMap<Integer, Integer> loadRestoreTimers() {
1201             final String[] configs = mService.mResources.get().getStringArray(
1202                     R.array.config_legacy_networktype_restore_timers);
1203             final ArrayMap<Integer, Integer> ret = new ArrayMap<>(configs.length);
1204             for (final String config : configs) {
1205                 final String[] splits = TextUtils.split(config, ",");
1206                 if (splits.length != 2) {
1207                     logwtf("Invalid restore timer token count: " + config);
1208                     continue;
1209                 }
1210                 try {
1211                     ret.put(Integer.parseInt(splits[0]), Integer.parseInt(splits[1]));
1212                 } catch (NumberFormatException e) {
1213                     logwtf("Invalid restore timer number format: " + config, e);
1214                 }
1215             }
1216             return ret;
1217         }
1218 
maybeLogBroadcast(NetworkAgentInfo nai, DetailedState state, int type, boolean isDefaultNetwork)1219         private void maybeLogBroadcast(NetworkAgentInfo nai, DetailedState state, int type,
1220                 boolean isDefaultNetwork) {
1221             if (DBG) {
1222                 log("Sending " + state
1223                         + " broadcast for type " + type + " " + nai.toShortString()
1224                         + " isDefaultNetwork=" + isDefaultNetwork);
1225             }
1226         }
1227 
1228         // When a lockdown VPN connects, send another CONNECTED broadcast for the underlying
1229         // network type, to preserve previous behaviour.
maybeSendLegacyLockdownBroadcast(@onNull NetworkAgentInfo vpnNai)1230         private void maybeSendLegacyLockdownBroadcast(@NonNull NetworkAgentInfo vpnNai) {
1231             if (vpnNai != mService.getLegacyLockdownNai()) return;
1232 
1233             if (vpnNai.declaredUnderlyingNetworks == null
1234                     || vpnNai.declaredUnderlyingNetworks.length != 1) {
1235                 Log.wtf(TAG, "Legacy lockdown VPN must have exactly one underlying network: "
1236                         + Arrays.toString(vpnNai.declaredUnderlyingNetworks));
1237                 return;
1238             }
1239             final NetworkAgentInfo underlyingNai = mService.getNetworkAgentInfoForNetwork(
1240                     vpnNai.declaredUnderlyingNetworks[0]);
1241             if (underlyingNai == null) return;
1242 
1243             final int type = underlyingNai.networkInfo.getType();
1244             final DetailedState state = DetailedState.CONNECTED;
1245             maybeLogBroadcast(underlyingNai, state, type, true /* isDefaultNetwork */);
1246             mService.sendLegacyNetworkBroadcast(underlyingNai, state, type);
1247         }
1248 
1249         /** Adds the given network to the specified legacy type list. */
add(int type, NetworkAgentInfo nai)1250         public void add(int type, NetworkAgentInfo nai) {
1251             if (!isTypeSupported(type)) {
1252                 return;  // Invalid network type.
1253             }
1254             if (VDBG) log("Adding agent " + nai + " for legacy network type " + type);
1255 
1256             ArrayList<NetworkAgentInfo> list = mTypeLists[type];
1257             if (list.contains(nai)) {
1258                 return;
1259             }
1260             synchronized (mTypeLists) {
1261                 list.add(nai);
1262             }
1263 
1264             // Send a broadcast if this is the first network of its type or if it's the default.
1265             final boolean isDefaultNetwork = mService.isDefaultNetwork(nai);
1266 
1267             // If a legacy lockdown VPN is active, override the NetworkInfo state in all broadcasts
1268             // to preserve previous behaviour.
1269             final DetailedState state = mService.getLegacyLockdownState(DetailedState.CONNECTED);
1270             if ((list.size() == 1) || isDefaultNetwork) {
1271                 maybeLogBroadcast(nai, state, type, isDefaultNetwork);
1272                 mService.sendLegacyNetworkBroadcast(nai, state, type);
1273             }
1274 
1275             if (type == TYPE_VPN && state == DetailedState.CONNECTED) {
1276                 maybeSendLegacyLockdownBroadcast(nai);
1277             }
1278         }
1279 
1280         /** Removes the given network from the specified legacy type list. */
remove(int type, NetworkAgentInfo nai, boolean wasDefault)1281         public void remove(int type, NetworkAgentInfo nai, boolean wasDefault) {
1282             ArrayList<NetworkAgentInfo> list = mTypeLists[type];
1283             if (list == null || list.isEmpty()) {
1284                 return;
1285             }
1286             final boolean wasFirstNetwork = list.get(0).equals(nai);
1287 
1288             synchronized (mTypeLists) {
1289                 if (!list.remove(nai)) {
1290                     return;
1291                 }
1292             }
1293 
1294             if (wasFirstNetwork || wasDefault) {
1295                 maybeLogBroadcast(nai, DetailedState.DISCONNECTED, type, wasDefault);
1296                 mService.sendLegacyNetworkBroadcast(nai, DetailedState.DISCONNECTED, type);
1297             }
1298 
1299             if (!list.isEmpty() && wasFirstNetwork) {
1300                 if (DBG) log("Other network available for type " + type +
1301                               ", sending connected broadcast");
1302                 final NetworkAgentInfo replacement = list.get(0);
1303                 maybeLogBroadcast(replacement, DetailedState.CONNECTED, type,
1304                         mService.isDefaultNetwork(replacement));
1305                 mService.sendLegacyNetworkBroadcast(replacement, DetailedState.CONNECTED, type);
1306             }
1307         }
1308 
1309         /** Removes the given network from all legacy type lists. */
remove(NetworkAgentInfo nai, boolean wasDefault)1310         public void remove(NetworkAgentInfo nai, boolean wasDefault) {
1311             if (VDBG) log("Removing agent " + nai + " wasDefault=" + wasDefault);
1312             for (int type = 0; type < mTypeLists.length; type++) {
1313                 remove(type, nai, wasDefault);
1314             }
1315         }
1316 
1317         // send out another legacy broadcast - currently only used for suspend/unsuspend toggle
update(NetworkAgentInfo nai)1318         public void update(NetworkAgentInfo nai) {
1319             final boolean isDefault = mService.isDefaultNetwork(nai);
1320             final DetailedState state = nai.networkInfo.getDetailedState();
1321             for (int type = 0; type < mTypeLists.length; type++) {
1322                 final ArrayList<NetworkAgentInfo> list = mTypeLists[type];
1323                 final boolean contains = (list != null && list.contains(nai));
1324                 final boolean isFirst = contains && (nai == list.get(0));
1325                 if (isFirst || contains && isDefault) {
1326                     maybeLogBroadcast(nai, state, type, isDefault);
1327                     mService.sendLegacyNetworkBroadcast(nai, state, type);
1328                 }
1329             }
1330         }
1331 
dump(IndentingPrintWriter pw)1332         public void dump(IndentingPrintWriter pw) {
1333             pw.println("mLegacyTypeTracker:");
1334             pw.increaseIndent();
1335             pw.print("Supported types:");
1336             for (int type = 0; type < mTypeLists.length; type++) {
1337                 if (mTypeLists[type] != null) pw.print(" " + type);
1338             }
1339             pw.println();
1340             pw.println("Current state:");
1341             pw.increaseIndent();
1342             synchronized (mTypeLists) {
1343                 for (int type = 0; type < mTypeLists.length; type++) {
1344                     if (mTypeLists[type] == null || mTypeLists[type].isEmpty()) continue;
1345                     for (NetworkAgentInfo nai : mTypeLists[type]) {
1346                         pw.println(type + " " + nai.toShortString());
1347                     }
1348                 }
1349             }
1350             pw.decreaseIndent();
1351             pw.decreaseIndent();
1352             pw.println();
1353         }
1354     }
1355     private final LegacyTypeTracker mLegacyTypeTracker = new LegacyTypeTracker(this);
1356 
1357     final LocalPriorityDump mPriorityDumper = new LocalPriorityDump();
1358     /**
1359      * Helper class which parses out priority arguments and dumps sections according to their
1360      * priority. If priority arguments are omitted, function calls the legacy dump command.
1361      */
1362     private class LocalPriorityDump {
1363         private static final String PRIORITY_ARG = "--dump-priority";
1364         private static final String PRIORITY_ARG_HIGH = "HIGH";
1365         private static final String PRIORITY_ARG_NORMAL = "NORMAL";
1366         private static final int DUMPSYS_DEFAULT_TIMEOUT_MS = 10_000;
1367 
LocalPriorityDump()1368         LocalPriorityDump() {}
1369 
dumpHigh(FileDescriptor fd, PrintWriter pw)1370         private void dumpHigh(FileDescriptor fd, PrintWriter pw) {
1371             if (!HandlerUtils.runWithScissorsForDump(mHandler, () -> {
1372                 doDump(fd, pw, new String[]{DIAG_ARG});
1373                 doDump(fd, pw, new String[]{SHORT_ARG});
1374             }, DUMPSYS_DEFAULT_TIMEOUT_MS)) {
1375                 pw.println("dumpHigh timeout");
1376             }
1377         }
1378 
dumpNormal(FileDescriptor fd, PrintWriter pw, String[] args)1379         private void dumpNormal(FileDescriptor fd, PrintWriter pw, String[] args) {
1380             if (!HandlerUtils.runWithScissorsForDump(mHandler, () -> doDump(fd, pw, args),
1381                     DUMPSYS_DEFAULT_TIMEOUT_MS)) {
1382                 pw.println("dumpNormal timeout");
1383             }
1384         }
1385 
dump(FileDescriptor fd, PrintWriter pw, String[] args)1386         public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1387             if (args == null) {
1388                 dumpNormal(fd, pw, args);
1389                 return;
1390             }
1391 
1392             String priority = null;
1393             for (int argIndex = 0; argIndex < args.length; argIndex++) {
1394                 if (args[argIndex].equals(PRIORITY_ARG) && argIndex + 1 < args.length) {
1395                     argIndex++;
1396                     priority = args[argIndex];
1397                 }
1398             }
1399 
1400             if (PRIORITY_ARG_HIGH.equals(priority)) {
1401                 dumpHigh(fd, pw);
1402             } else if (PRIORITY_ARG_NORMAL.equals(priority)) {
1403                 dumpNormal(fd, pw, args);
1404             } else {
1405                 // ConnectivityService publishes binder service using publishBinderService() with
1406                 // no priority assigned will be treated as NORMAL priority. Dumpsys does not send
1407                 // "--dump-priority" arguments to the service. Thus, dump NORMAL only to align the
1408                 // legacy output for dumpsys connectivity.
1409                 // TODO: Integrate into signal dump.
1410                 dumpNormal(fd, pw, args);
1411             }
1412         }
1413     }
1414 
1415     /**
1416      * Dependencies of ConnectivityService, for injection in tests.
1417      */
1418     @VisibleForTesting
1419     public static class Dependencies {
getCallingUid()1420         public int getCallingUid() {
1421             return Binder.getCallingUid();
1422         }
1423 
isAtLeastS()1424         public boolean isAtLeastS() {
1425             return SdkLevel.isAtLeastS();
1426         }
1427 
isAtLeastT()1428         public boolean isAtLeastT() {
1429             return SdkLevel.isAtLeastT();
1430         }
1431 
isAtLeastU()1432         public boolean isAtLeastU() {
1433             return SdkLevel.isAtLeastU();
1434         }
1435 
isAtLeastV()1436         public boolean isAtLeastV() {
1437             return SdkLevel.isAtLeastV();
1438         }
1439 
1440         /**
1441          * Get system properties to use in ConnectivityService.
1442          */
getSystemProperties()1443         public MockableSystemProperties getSystemProperties() {
1444             return new MockableSystemProperties();
1445         }
1446 
1447         /**
1448          * Get the {@link ConnectivityResources} to use in ConnectivityService.
1449          */
getResources(@onNull Context ctx)1450         public ConnectivityResources getResources(@NonNull Context ctx) {
1451             return new ConnectivityResources(ctx);
1452         }
1453 
1454         /**
1455          * Create a HandlerThread to use in ConnectivityService.
1456          */
makeHandlerThread(@onNull final String tag)1457         public HandlerThread makeHandlerThread(@NonNull final String tag) {
1458             return new HandlerThread(tag);
1459         }
1460 
1461         /**
1462          * Get a reference to the ModuleNetworkStackClient.
1463          */
getNetworkStack()1464         public NetworkStackClientBase getNetworkStack() {
1465             return ModuleNetworkStackClient.getInstance(null);
1466         }
1467 
1468         /**
1469          * @see ProxyTracker
1470          */
makeProxyTracker(@onNull Context context, @NonNull Handler connServiceHandler)1471         public ProxyTracker makeProxyTracker(@NonNull Context context,
1472                 @NonNull Handler connServiceHandler) {
1473             return new ProxyTracker(context, connServiceHandler, EVENT_PAC_PROXY_HAS_CHANGED);
1474         }
1475 
1476         /**
1477          * @see NetIdManager
1478          */
makeNetIdManager()1479         public NetIdManager makeNetIdManager() {
1480             return new NetIdManager();
1481         }
1482 
1483         /**
1484          * @see NetworkUtils#queryUserAccess(int, int)
1485          */
queryUserAccess(int uid, Network network, ConnectivityService cs)1486         public boolean queryUserAccess(int uid, Network network, ConnectivityService cs) {
1487             return cs.queryUserAccess(uid, network);
1488         }
1489 
1490         /**
1491          * Gets the UID that owns a socket connection. Needed because opening SOCK_DIAG sockets
1492          * requires CAP_NET_ADMIN, which the unit tests do not have.
1493          */
getConnectionOwnerUid(int protocol, InetSocketAddress local, InetSocketAddress remote)1494         public int getConnectionOwnerUid(int protocol, InetSocketAddress local,
1495                 InetSocketAddress remote) {
1496             return InetDiagMessage.getConnectionOwnerUid(protocol, local, remote);
1497         }
1498 
1499         /**
1500          * @see MultinetworkPolicyTracker
1501          */
makeMultinetworkPolicyTracker( @onNull Context c, @NonNull Handler h, @NonNull Runnable r)1502         public MultinetworkPolicyTracker makeMultinetworkPolicyTracker(
1503                 @NonNull Context c, @NonNull Handler h, @NonNull Runnable r) {
1504             return new MultinetworkPolicyTracker(c, h, r);
1505         }
1506 
1507         /**
1508          * @see AutomaticOnOffKeepaliveTracker
1509          */
makeAutomaticOnOffKeepaliveTracker( @onNull Context c, @NonNull Handler h)1510         public AutomaticOnOffKeepaliveTracker makeAutomaticOnOffKeepaliveTracker(
1511                 @NonNull Context c, @NonNull Handler h) {
1512             return new AutomaticOnOffKeepaliveTracker(c, h);
1513         }
1514 
makeMulticastRoutingCoordinatorService( @onNull Handler h)1515         public MulticastRoutingCoordinatorService makeMulticastRoutingCoordinatorService(
1516                     @NonNull Handler h) {
1517             try {
1518                 return new MulticastRoutingCoordinatorService(h);
1519             } catch (UnsupportedOperationException e) {
1520                 // Multicast routing is not supported by the kernel
1521                 Log.i(TAG, "Skipping unsupported MulticastRoutingCoordinatorService");
1522                 return null;
1523             }
1524         }
1525 
1526         /**
1527          * @see NetworkRequestStateStatsMetrics
1528          */
makeNetworkRequestStateStatsMetrics( Context context)1529         public NetworkRequestStateStatsMetrics makeNetworkRequestStateStatsMetrics(
1530                 Context context) {
1531             // We currently have network requests metric for Watch devices only
1532             if (context.getPackageManager().hasSystemFeature(FEATURE_WATCH)) {
1533                 return new NetworkRequestStateStatsMetrics();
1534             } else {
1535                 return null;
1536             }
1537         }
1538 
1539         /**
1540          * @see BatteryStatsManager
1541          */
reportNetworkInterfaceForTransports(Context context, String iface, int[] transportTypes)1542         public void reportNetworkInterfaceForTransports(Context context, String iface,
1543                 int[] transportTypes) {
1544             final BatteryStatsManager batteryStats =
1545                     context.getSystemService(BatteryStatsManager.class);
1546             batteryStats.reportNetworkInterfaceForTransports(iface, transportTypes);
1547         }
1548 
getCellular464XlatEnabled()1549         public boolean getCellular464XlatEnabled() {
1550             return NetworkProperties.isCellular464XlatEnabled().orElse(true);
1551         }
1552 
1553         /**
1554          * @see PendingIntent#intentFilterEquals
1555          */
intentFilterEquals(PendingIntent a, PendingIntent b)1556         public boolean intentFilterEquals(PendingIntent a, PendingIntent b) {
1557             return a.intentFilterEquals(b);
1558         }
1559 
1560         /**
1561          * @see LocationPermissionChecker
1562          */
makeLocationPermissionChecker(Context context)1563         public LocationPermissionChecker makeLocationPermissionChecker(Context context) {
1564             return new LocationPermissionChecker(context);
1565         }
1566 
1567         /**
1568          * @see CarrierPrivilegeAuthenticator
1569          *
1570          * This method returns null in versions before T, where carrier privilege
1571          * authentication is not supported.
1572          */
1573         @Nullable
makeCarrierPrivilegeAuthenticator( @onNull final Context context, @NonNull final TelephonyManager tm, boolean requestRestrictedWifiEnabled, @NonNull BiConsumer<Integer, Integer> listener, @NonNull final Handler connectivityServiceHandler)1574         public CarrierPrivilegeAuthenticator makeCarrierPrivilegeAuthenticator(
1575                 @NonNull final Context context,
1576                 @NonNull final TelephonyManager tm,
1577                 boolean requestRestrictedWifiEnabled,
1578                 @NonNull BiConsumer<Integer, Integer> listener,
1579                 @NonNull final Handler connectivityServiceHandler) {
1580             if (isAtLeastT()) {
1581                 return new CarrierPrivilegeAuthenticator(context, tm, requestRestrictedWifiEnabled,
1582                         listener, connectivityServiceHandler);
1583             } else {
1584                 return null;
1585             }
1586         }
1587 
1588         /**
1589          * @see SatelliteAccessController
1590          */
1591         @Nullable
makeSatelliteAccessController( @onNull final Context context, Consumer<Set<Integer>> updateSatelliteNetworkFallbackUidCallback, @NonNull final Handler connectivityServiceInternalHandler)1592         public SatelliteAccessController makeSatelliteAccessController(
1593                 @NonNull final Context context,
1594                 Consumer<Set<Integer>> updateSatelliteNetworkFallbackUidCallback,
1595                 @NonNull final Handler connectivityServiceInternalHandler) {
1596             return new SatelliteAccessController(context, updateSatelliteNetworkFallbackUidCallback,
1597                     connectivityServiceInternalHandler);
1598         }
1599 
1600         /**
1601          * @see DeviceConfigUtils#isTetheringFeatureEnabled
1602          */
isFeatureEnabled(Context context, String name)1603         public boolean isFeatureEnabled(Context context, String name) {
1604             return DeviceConfigUtils.isTetheringFeatureEnabled(context, name);
1605         }
1606 
1607         /**
1608          * @see DeviceConfigUtils#isTetheringFeatureNotChickenedOut
1609          */
isFeatureNotChickenedOut(Context context, String name)1610         public boolean isFeatureNotChickenedOut(Context context, String name) {
1611             return DeviceConfigUtils.isTetheringFeatureNotChickenedOut(context, name);
1612         }
1613 
1614         /**
1615          * Get the BpfNetMaps implementation to use in ConnectivityService.
1616          * @param netd a netd binder
1617          * @return BpfNetMaps implementation.
1618          */
getBpfNetMaps(Context context, INetd netd)1619         public BpfNetMaps getBpfNetMaps(Context context, INetd netd) {
1620             return new BpfNetMaps(context, netd);
1621         }
1622 
1623         /**
1624          * @see ClatCoordinator
1625          */
1626         @RequiresApi(Build.VERSION_CODES.TIRAMISU)
getClatCoordinator(INetd netd)1627         public ClatCoordinator getClatCoordinator(INetd netd) {
1628             return new ClatCoordinator(
1629                 new ClatCoordinator.Dependencies() {
1630                     @NonNull
1631                     public INetd getNetd() {
1632                         return netd;
1633                     }
1634                 });
1635         }
1636 
1637         /**
1638          * Wraps {@link TcUtils#tcFilterAddDevIngressPolice}
1639          */
enableIngressRateLimit(String iface, long rateInBytesPerSecond)1640         public void enableIngressRateLimit(String iface, long rateInBytesPerSecond) {
1641             final InterfaceParams params = InterfaceParams.getByName(iface);
1642             if (params == null) {
1643                 // the interface might have disappeared.
1644                 logw("Failed to get interface params for interface " + iface);
1645                 return;
1646             }
1647             try {
1648                 // converting rateInBytesPerSecond from long to int is safe here because the
1649                 // setting's range is limited to INT_MAX.
1650                 // TODO: add long/uint64 support to tcFilterAddDevIngressPolice.
1651                 Log.i(TAG,
1652                         "enableIngressRateLimit on " + iface + ": " + rateInBytesPerSecond + "B/s");
1653                 TcUtils.tcFilterAddDevIngressPolice(params.index, TC_PRIO_POLICE, (short) ETH_P_ALL,
1654                         (int) rateInBytesPerSecond, TC_POLICE_BPF_PROG_PATH);
1655             } catch (IOException e) {
1656                 loge("TcUtils.tcFilterAddDevIngressPolice(ifaceIndex=" + params.index
1657                         + ", PRIO_POLICE, ETH_P_ALL, rateInBytesPerSecond="
1658                         + rateInBytesPerSecond + ", bpfProgPath=" + TC_POLICE_BPF_PROG_PATH
1659                         + ") failure: ", e);
1660             }
1661         }
1662 
1663         /**
1664          * Wraps {@link TcUtils#tcFilterDelDev}
1665          */
disableIngressRateLimit(String iface)1666         public void disableIngressRateLimit(String iface) {
1667             final InterfaceParams params = InterfaceParams.getByName(iface);
1668             if (params == null) {
1669                 // the interface might have disappeared.
1670                 logw("Failed to get interface params for interface " + iface);
1671                 return;
1672             }
1673             try {
1674                 Log.i(TAG,
1675                         "disableIngressRateLimit on " + iface);
1676                 TcUtils.tcFilterDelDev(params.index, true, TC_PRIO_POLICE, (short) ETH_P_ALL);
1677             } catch (IOException e) {
1678                 loge("TcUtils.tcFilterDelDev(ifaceIndex=" + params.index
1679                         + ", ingress=true, PRIO_POLICE, ETH_P_ALL) failure: ", e);
1680             }
1681         }
1682 
1683         /**
1684          * Get BPF program Id from CGROUP. See {@link BpfUtils#getProgramId}.
1685          */
getBpfProgramId(final int attachType)1686         public int getBpfProgramId(final int attachType)
1687                 throws IOException {
1688             return BpfUtils.getProgramId(attachType);
1689         }
1690 
1691         /**
1692          * Wraps {@link BroadcastOptionsShimImpl#newInstance(BroadcastOptions)}
1693          */
1694         // TODO: when available in all active branches:
1695         //  @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
1696         @RequiresApi(Build.VERSION_CODES.CUR_DEVELOPMENT)
makeBroadcastOptionsShim(BroadcastOptions options)1697         public BroadcastOptionsShim makeBroadcastOptionsShim(BroadcastOptions options) {
1698             return BroadcastOptionsShimImpl.newInstance(options);
1699         }
1700 
1701         /**
1702          * Wrapper method for
1703          * {@link android.app.compat.CompatChanges#isChangeEnabled(long, String, UserHandle)}.
1704          *
1705          * @param changeId    The ID of the compatibility change in question.
1706          * @param packageName The package name of the app in question.
1707          * @param user        The user that the operation is done for.
1708          * @return {@code true} if the change is enabled for the specified package.
1709          */
isChangeEnabled(long changeId, @NonNull final String packageName, @NonNull final UserHandle user)1710         public boolean isChangeEnabled(long changeId, @NonNull final String packageName,
1711                 @NonNull final UserHandle user) {
1712             return CompatChanges.isChangeEnabled(changeId, packageName, user);
1713         }
1714 
1715         /**
1716          * As above but with a UID.
1717          * @see CompatChanges#isChangeEnabled(long, int)
1718          */
isChangeEnabled(final long changeId, final int uid)1719         public boolean isChangeEnabled(final long changeId, final int uid) {
1720             return CompatChanges.isChangeEnabled(changeId, uid);
1721         }
1722 
1723         /**
1724          * Call {@link InetDiagMessage#destroyLiveTcpSockets(Set, Set)}
1725          *
1726          * @param ranges target uid ranges
1727          * @param exemptUids uids to skip close socket
1728          */
destroyLiveTcpSockets(@onNull final Set<Range<Integer>> ranges, @NonNull final Set<Integer> exemptUids)1729         public void destroyLiveTcpSockets(@NonNull final Set<Range<Integer>> ranges,
1730                 @NonNull final Set<Integer> exemptUids)
1731                 throws SocketException, InterruptedIOException, ErrnoException {
1732             InetDiagMessage.destroyLiveTcpSockets(ranges, exemptUids);
1733         }
1734 
1735         /**
1736          * Call {@link InetDiagMessage#destroyLiveTcpSocketsByOwnerUids(Set)}
1737          *
1738          * @param ownerUids target uids to close sockets
1739          */
destroyLiveTcpSocketsByOwnerUids(final Set<Integer> ownerUids)1740         public void destroyLiveTcpSocketsByOwnerUids(final Set<Integer> ownerUids)
1741                 throws SocketException, InterruptedIOException, ErrnoException {
1742             InetDiagMessage.destroyLiveTcpSocketsByOwnerUids(ownerUids);
1743         }
1744 
1745         /**
1746          * Schedule the evaluation timeout.
1747          *
1748          * When a network connects, it's "not evaluated" yet. Detection events cause the network
1749          * to be "evaluated" (typically, validation or detection of a captive portal). If none
1750          * of these events happen, this time will run out, after which the network is considered
1751          * "evaluated" even if nothing happened to it. Notionally that means the system gave up
1752          * on this network and considers it won't provide connectivity. In particular, that means
1753          * it's when the system prefers it to cell if it's wifi and configuration says it should
1754          * prefer bad wifi to cell.
1755          */
scheduleEvaluationTimeout(@onNull Handler handler, @NonNull final Network network, final long delayMs)1756         public void scheduleEvaluationTimeout(@NonNull Handler handler,
1757                 @NonNull final Network network, final long delayMs) {
1758             handler.sendMessageDelayed(
1759                     handler.obtainMessage(EVENT_INITIAL_EVALUATION_TIMEOUT, network), delayMs);
1760         }
1761     }
1762 
1763     public ConnectivityService(Context context) {
1764         this(context, getDnsResolver(context), new IpConnectivityLog(),
1765                 INetd.Stub.asInterface((IBinder) context.getSystemService(Context.NETD_SERVICE)),
1766                 new Dependencies());
1767     }
1768 
1769     @VisibleForTesting
1770     protected ConnectivityService(Context context, IDnsResolver dnsresolver,
1771             IpConnectivityLog logger, INetd netd, Dependencies deps) {
1772         if (DBG) log("ConnectivityService starting up");
1773 
1774         mDeps = Objects.requireNonNull(deps, "missing Dependencies");
1775         mFlags = new ConnectivityFlags();
1776         mSystemProperties = mDeps.getSystemProperties();
1777         mNetIdManager = mDeps.makeNetIdManager();
1778         mContext = Objects.requireNonNull(context, "missing Context");
1779         mResources = deps.getResources(mContext);
1780         // The legacy PerUidCounter is buggy and throwing exception at count == limit.
1781         // Pass limit - 1 to maintain backward compatibility.
1782         // TODO: Remove the workaround.
1783         mNetworkRequestCounter =
1784                 new RequestInfoPerUidCounter(MAX_NETWORK_REQUESTS_PER_UID - 1);
1785         mSystemNetworkRequestCounter =
1786                 new RequestInfoPerUidCounter(MAX_NETWORK_REQUESTS_PER_SYSTEM_UID - 1);
1787 
1788         mMetricsLog = logger;
1789         mNetworkRequestStateStatsMetrics = mDeps.makeNetworkRequestStateStatsMetrics(mContext);
1790         final NetworkRequest defaultInternetRequest = createDefaultRequest();
1791         mDefaultRequest = new NetworkRequestInfo(
1792                 Process.myUid(), defaultInternetRequest, null,
1793                 null /* binder */, NetworkCallback.FLAG_INCLUDE_LOCATION_INFO,
1794                 null /* attributionTags */);
1795         mNetworkRequests.put(defaultInternetRequest, mDefaultRequest);
1796         mDefaultNetworkRequests.add(mDefaultRequest);
1797         mNetworkRequestInfoLogs.log("REGISTER " + mDefaultRequest);
1798 
1799         mDefaultMobileDataRequest = createDefaultInternetRequestForTransport(
1800                 NetworkCapabilities.TRANSPORT_CELLULAR, NetworkRequest.Type.BACKGROUND_REQUEST);
1801 
1802         // The default WiFi request is a background request so that apps using WiFi are
1803         // migrated to a better network (typically ethernet) when one comes up, instead
1804         // of staying on WiFi forever.
1805         mDefaultWifiRequest = createDefaultInternetRequestForTransport(
1806                 NetworkCapabilities.TRANSPORT_WIFI, NetworkRequest.Type.BACKGROUND_REQUEST);
1807 
1808         mDefaultVehicleRequest = createAlwaysOnRequestForCapability(
1809                 NetworkCapabilities.NET_CAPABILITY_VEHICLE_INTERNAL,
1810                 NetworkRequest.Type.BACKGROUND_REQUEST);
1811 
1812         mLingerDelayMs = mSystemProperties.getInt(LINGER_DELAY_PROPERTY, DEFAULT_LINGER_DELAY_MS);
1813         // TODO: Consider making the timer customizable.
1814         mNascentDelayMs = DEFAULT_NASCENT_DELAY_MS;
1815         mCellularRadioTimesharingCapable =
1816                 mResources.get().getBoolean(R.bool.config_cellular_radio_timesharing_capable);
1817 
1818         int mark = mResources.get().getInteger(R.integer.config_networkWakeupPacketMark);
1819         int mask = mResources.get().getInteger(R.integer.config_networkWakeupPacketMask);
1820 
1821         if (SdkLevel.isAtLeastU()) {
1822             // U+ default value of both mark & mask, this is the top bit of the skb->mark,
1823             // see //system/netd/include/FwMark.h union Fwmark, field ingress_cpu_wakeup
1824             final int defaultUMarkMask = 0x80000000;  // u32
1825 
1826             if ((mark == 0) || (mask == 0)) {
1827                 // simply treat unset/disabled as the default U value
1828                 mark = defaultUMarkMask;
1829                 mask = defaultUMarkMask;
1830             }
1831             if ((mark != defaultUMarkMask) || (mask != defaultUMarkMask)) {
1832                 // invalid device overlay settings
1833                 throw new IllegalArgumentException(
1834                         "Bad config_networkWakeupPacketMark/Mask " + mark + "/" + mask);
1835             }
1836         }
1837 
1838         mWakeUpMark = mark;
1839         mWakeUpMask = mask;
1840 
1841         mNetd = netd;
1842         mBpfNetMaps = mDeps.getBpfNetMaps(mContext, netd);
1843         mHandlerThread = mDeps.makeHandlerThread("ConnectivityServiceThread");
1844         mPermissionMonitor =
1845                 new PermissionMonitor(mContext, mNetd, mBpfNetMaps, mHandlerThread);
1846         mHandlerThread.start();
1847         mHandler = new InternalHandler(mHandlerThread.getLooper());
1848         // Temporary hack to report netbpfload result.
1849         // TODO: remove in 2024-09 when netbpfload starts loading mainline bpf programs.
1850         if (!mDeps.isAtLeastV()) {
1851             mHandler.postDelayed(() -> {
1852                 // Test Log.wtf reporting pipeline. Ignore this Log.wtf if it shows up in the logs.
1853                 final Random r = new Random();
1854                 if (Build.TYPE.equals("user") && r.nextInt(1000) == 0) {
1855                     Log.wtf(TAG, "NOT A FAILURE, PLEASE IGNORE! Ensure netbpfload result reported");
1856                 }
1857                 // Did netbpfload create the map?
1858                 try {
1859                     Os.access("/sys/fs/bpf/net_shared/map_gentle_test", F_OK);
1860                 } catch (ErrnoException e) {
1861                     Log.wtf(TAG, "netbpfload did not create map", e);
1862                 }
1863                 // Did netbpfload create the program?
1864                 try {
1865                     Os.access("/sys/fs/bpf/net_shared/prog_gentle_skfilter_accept", F_OK);
1866                 } catch (ErrnoException e) {
1867                     Log.wtf(TAG, "netbpfload did not create program", e);
1868                 }
1869                 // Did netbpfload run to completion?
1870                 try {
1871                     Os.access("/sys/fs/bpf/netd_shared/mainline_done", F_OK);
1872                 } catch (ErrnoException e) {
1873                     Log.wtf(TAG, "netbpfload did not run to completion", e);
1874                 }
1875             }, 30_000 /* delayMillis */);
1876         }
1877         mTrackerHandler = new NetworkStateTrackerHandler(mHandlerThread.getLooper());
1878         mConnectivityDiagnosticsHandler =
1879                 new ConnectivityDiagnosticsHandler(mHandlerThread.getLooper());
1880 
1881         mReleasePendingIntentDelayMs = Settings.Secure.getInt(context.getContentResolver(),
1882                 ConnectivitySettingsManager.CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS, 5_000);
1883 
1884         mStatsManager = mContext.getSystemService(NetworkStatsManager.class);
1885         mPolicyManager = mContext.getSystemService(NetworkPolicyManager.class);
1886         mDnsResolver = Objects.requireNonNull(dnsresolver, "missing IDnsResolver");
1887         mProxyTracker = mDeps.makeProxyTracker(mContext, mHandler);
1888 
1889         mTelephonyManager = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
1890         mAppOpsManager = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
1891         mLocationPermissionChecker = mDeps.makeLocationPermissionChecker(mContext);
1892         mRequestRestrictedWifiEnabled = mDeps.isAtLeastU()
1893                 && mDeps.isFeatureEnabled(context, REQUEST_RESTRICTED_WIFI);
1894         mBackgroundFirewallChainEnabled = mDeps.isAtLeastV() && mDeps.isFeatureNotChickenedOut(
1895                 context, ConnectivityFlags.BACKGROUND_FIREWALL_CHAIN);
1896         mUseDeclaredMethodsForCallbacksEnabled = mDeps.isFeatureEnabled(context,
1897                 ConnectivityFlags.USE_DECLARED_METHODS_FOR_CALLBACKS);
1898         mCarrierPrivilegeAuthenticator = mDeps.makeCarrierPrivilegeAuthenticator(
1899                 mContext, mTelephonyManager, mRequestRestrictedWifiEnabled,
1900                 this::handleUidCarrierPrivilegesLost, mHandler);
1901 
1902         if (mDeps.isAtLeastU()
1903                 && mDeps
1904                 .isFeatureNotChickenedOut(mContext, ALLOW_SATALLITE_NETWORK_FALLBACK)) {
1905             mSatelliteAccessController = mDeps.makeSatelliteAccessController(
1906                     mContext, this::updateSatelliteNetworkPreferenceUids, mHandler);
1907         } else {
1908             mSatelliteAccessController = null;
1909         }
1910 
1911         // To ensure uid state is synchronized with Network Policy, register for
1912         // NetworkPolicyManagerService events must happen prior to NetworkPolicyManagerService
1913         // reading existing policy from disk.
1914         // If shouldTrackUidsForBlockedStatusCallbacks() is true (On V+), ConnectivityService
1915         // updates blocked reasons when firewall chain and data saver status is updated based on
1916         // bpf map contents instead of receiving callbacks from NPMS
1917         if (!shouldTrackUidsForBlockedStatusCallbacks()) {
1918             mPolicyManager.registerNetworkPolicyCallback(null, mPolicyCallback);
1919         }
1920 
1921         final PowerManager powerManager = (PowerManager) context.getSystemService(
1922                 Context.POWER_SERVICE);
1923         mNetTransitionWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
1924         mPendingIntentWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
1925 
1926         mLegacyTypeTracker.loadSupportedTypes(mContext, mTelephonyManager);
1927         mProtectedNetworks = new ArrayList<>();
1928         int[] protectedNetworks = mResources.get().getIntArray(R.array.config_protectedNetworks);
1929         for (int p : protectedNetworks) {
1930             if (mLegacyTypeTracker.isTypeSupported(p) && !mProtectedNetworks.contains(p)) {
1931                 mProtectedNetworks.add(p);
1932             } else {
1933                 if (DBG) loge("Ignoring protectedNetwork " + p);
1934             }
1935         }
1936 
1937         mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
1938 
1939         mUserAllContext = mContext.createContextAsUser(UserHandle.ALL, 0 /* flags */);
1940         // Listen for user add/removes to inform PermissionMonitor.
1941         // Should run on mHandler to avoid any races.
1942         final IntentFilter userIntentFilter = new IntentFilter();
1943         userIntentFilter.addAction(Intent.ACTION_USER_ADDED);
1944         userIntentFilter.addAction(Intent.ACTION_USER_REMOVED);
1945         mUserAllContext.registerReceiver(mUserIntentReceiver, userIntentFilter,
1946                 null /* broadcastPermission */, mHandler);
1947 
1948         // Listen to package add/removes for netd
1949         final IntentFilter packageIntentFilter = new IntentFilter();
1950         packageIntentFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
1951         packageIntentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
1952         packageIntentFilter.addAction(Intent.ACTION_PACKAGE_REPLACED);
1953         packageIntentFilter.addDataScheme("package");
1954         mUserAllContext.registerReceiver(mPackageIntentReceiver, packageIntentFilter,
1955                 null /* broadcastPermission */, mHandler);
1956 
1957         // This is needed for pre-V devices to propagate the data saver status
1958         // to the BPF map. This isn't supported before Android T because BPF maps are
1959         // unsupported, and it's also unnecessary on Android V and later versions,
1960         // as the platform code handles data saver bit updates. Additionally, checking
1961         // the initial data saver status here is superfluous because the intent won't
1962         // be sent until the system is ready.
1963         if (mDeps.isAtLeastT() && !mDeps.isAtLeastV()) {
1964             final IntentFilter dataSaverIntentFilter =
1965                     new IntentFilter(ACTION_RESTRICT_BACKGROUND_CHANGED);
1966             mUserAllContext.registerReceiver(mDataSaverReceiver, dataSaverIntentFilter,
1967                     null /* broadcastPermission */, mHandler);
1968         }
1969 
1970         // TrackMultiNetworkActivities feature should be enabled by trunk stable flag.
1971         // But reading the trunk stable flags from mainline modules is not supported yet.
1972         // So enabling this feature on V+ release.
1973         mTrackMultiNetworkActivities = mDeps.isAtLeastV();
1974         mNetworkActivityTracker = new LegacyNetworkActivityTracker(mContext, mNetd, mHandler,
1975                 mTrackMultiNetworkActivities);
1976 
1977         final NetdCallback netdCallback = new NetdCallback();
1978         try {
1979             mNetd.registerUnsolicitedEventListener(netdCallback);
1980         } catch (RemoteException | ServiceSpecificException e) {
1981             loge("Error registering event listener :" + e);
1982         }
1983 
1984         mSettingsObserver = new SettingsObserver(mContext, mHandler);
1985         registerSettingsCallbacks();
1986 
1987         mKeepaliveTracker = mDeps.makeAutomaticOnOffKeepaliveTracker(mContext, mHandler);
1988         mNotifier = new NetworkNotificationManager(mContext, mTelephonyManager);
1989         mQosCallbackTracker = new QosCallbackTracker(mHandler, mNetworkRequestCounter);
1990 
1991         final int dailyLimit = Settings.Global.getInt(mContext.getContentResolver(),
1992                 ConnectivitySettingsManager.NETWORK_SWITCH_NOTIFICATION_DAILY_LIMIT,
1993                 LingerMonitor.DEFAULT_NOTIFICATION_DAILY_LIMIT);
1994         final long rateLimit = Settings.Global.getLong(mContext.getContentResolver(),
1995                 ConnectivitySettingsManager.NETWORK_SWITCH_NOTIFICATION_RATE_LIMIT_MILLIS,
1996                 LingerMonitor.DEFAULT_NOTIFICATION_RATE_LIMIT_MILLIS);
1997         mLingerMonitor = new LingerMonitor(mContext, mNotifier, dailyLimit, rateLimit);
1998 
1999         mMultinetworkPolicyTracker = mDeps.makeMultinetworkPolicyTracker(
2000                 mContext, mHandler, () -> updateAvoidBadWifi());
2001         mNetworkRanker =
2002                 new NetworkRanker(new NetworkRanker.Configuration(activelyPreferBadWifi()));
2003 
2004         mMultinetworkPolicyTracker.start();
2005 
2006         mDnsManager = new DnsManager(mContext, mDnsResolver);
2007         registerPrivateDnsSettingsCallbacks();
2008 
2009         // This NAI is a sentinel used to offer no service to apps that are on a multi-layer
2010         // request that doesn't allow fallback to the default network. It should never be visible
2011         // to apps. As such, it's not in the list of NAIs and doesn't need many of the normal
2012         // arguments like the handler or the DnsResolver.
2013         // TODO : remove this ; it is probably better handled with a sentinel request.
2014         mNoServiceNetwork = new NetworkAgentInfo(null,
2015                 new Network(INetd.UNREACHABLE_NET_ID),
2016                 new NetworkInfo(TYPE_NONE, 0, "", ""),
2017                 new LinkProperties(), new NetworkCapabilities(), null /* localNetworkConfig */,
2018                 new NetworkScore.Builder().setLegacyInt(0).build(), mContext, null,
2019                 new NetworkAgentConfig(), this, null, null, 0, INVALID_UID,
2020                 mLingerDelayMs, mQosCallbackTracker, mDeps);
2021 
2022         try {
2023             // DscpPolicyTracker cannot run on S because on S the tethering module can only load
2024             // BPF programs/maps into /sys/fs/tethering/bpf, which the system server cannot access.
2025             // Even if it could, running on S would at least require mocking out the BPF map,
2026             // otherwise the unit tests will fail on pre-T devices where the seccomp filter blocks
2027             // the bpf syscall. http://aosp/1907693
2028             if (mDeps.isAtLeastT()) {
2029                 mDscpPolicyTracker = new DscpPolicyTracker();
2030             }
2031         } catch (ErrnoException e) {
2032             loge("Unable to create DscpPolicyTracker");
2033         }
2034 
2035         mIngressRateLimit = ConnectivitySettingsManager.getIngressRateLimitInBytesPerSecond(
2036                 mContext);
2037 
2038         if (mDeps.isAtLeastT()) {
2039             mCdmps = new CompanionDeviceManagerProxyService(context);
2040         } else {
2041             mCdmps = null;
2042         }
2043 
2044         mRoutingCoordinatorService = new RoutingCoordinatorService(netd);
2045         mMulticastRoutingCoordinatorService =
2046                 mDeps.makeMulticastRoutingCoordinatorService(mHandler);
2047 
2048         mDestroyFrozenSockets = mDeps.isAtLeastV() || (mDeps.isAtLeastU()
2049                 && mDeps.isFeatureEnabled(context, KEY_DESTROY_FROZEN_SOCKETS_VERSION));
2050         mDelayDestroySockets = mDeps.isFeatureNotChickenedOut(context, DELAY_DESTROY_SOCKETS);
2051         mAllowSysUiConnectivityReports = mDeps.isFeatureNotChickenedOut(
2052                 mContext, ALLOW_SYSUI_CONNECTIVITY_REPORTS);
2053         if (mDestroyFrozenSockets) {
2054             final UidFrozenStateChangedCallback frozenStateChangedCallback =
2055                     new UidFrozenStateChangedCallback() {
2056                 @Override
2057                 public void onUidFrozenStateChanged(int[] uids, int[] frozenStates) {
2058                     if (uids.length != frozenStates.length) {
2059                         Log.wtf(TAG, "uids has length " + uids.length
2060                                 + " but frozenStates has length " + frozenStates.length);
2061                         return;
2062                     }
2063 
2064                     final UidFrozenStateChangedArgs args =
2065                             new UidFrozenStateChangedArgs(uids, frozenStates);
2066 
2067                     mHandler.sendMessage(
2068                             mHandler.obtainMessage(EVENT_UID_FROZEN_STATE_CHANGED, args));
2069                 }
2070             };
2071 
2072             final ActivityManager activityManager =
2073                     mContext.getSystemService(ActivityManager.class);
2074             activityManager.registerUidFrozenStateChangedCallback(
2075                     (Runnable r) -> r.run(), frozenStateChangedCallback);
2076         }
2077         mIngressToVpnAddressFiltering = mDeps.isAtLeastT()
2078                 && mDeps.isFeatureNotChickenedOut(mContext, INGRESS_TO_VPN_ADDRESS_FILTERING);
2079     }
2080 
2081     /**
2082      * Check whether or not the device supports Ethernet transport.
2083      */
2084     public static boolean deviceSupportsEthernet(final Context context) {
2085         final PackageManager pm = context.getPackageManager();
2086         return pm.hasSystemFeature(PackageManager.FEATURE_ETHERNET)
2087                 || pm.hasSystemFeature(PackageManager.FEATURE_USB_HOST);
2088     }
2089 
2090     private static NetworkCapabilities createDefaultNetworkCapabilitiesForUid(int uid) {
2091         return createDefaultNetworkCapabilitiesForUidRangeSet(Collections.singleton(
2092                 new UidRange(uid, uid)));
2093     }
2094 
2095     private static NetworkCapabilities createDefaultNetworkCapabilitiesForUidRangeSet(
2096             @NonNull final Set<UidRange> uidRangeSet) {
2097         final NetworkCapabilities netCap = new NetworkCapabilities();
2098         netCap.addCapability(NET_CAPABILITY_INTERNET);
2099         netCap.addCapability(NET_CAPABILITY_NOT_VCN_MANAGED);
2100         netCap.removeCapability(NET_CAPABILITY_NOT_VPN);
2101         netCap.setUids(UidRange.toIntRanges(uidRangeSet));
2102         return netCap;
2103     }
2104 
2105     private NetworkRequest createDefaultRequest() {
2106         return createDefaultInternetRequestForTransport(
2107                 TYPE_NONE, NetworkRequest.Type.REQUEST);
2108     }
2109 
2110     private NetworkRequest createVpnRequest() {
2111         final NetworkCapabilities netCap = new NetworkCapabilities.Builder()
2112                 .withoutDefaultCapabilities()
2113                 .addTransportType(TRANSPORT_VPN)
2114                 .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
2115                 .addCapability(NET_CAPABILITY_NOT_RESTRICTED)
2116                 .build();
2117         netCap.setRequestorUidAndPackageName(Process.myUid(), mContext.getPackageName());
2118         return createNetworkRequest(NetworkRequest.Type.REQUEST, netCap);
2119     }
2120 
2121     private NetworkRequest createDefaultInternetRequestForTransport(
2122             int transportType, NetworkRequest.Type type) {
2123         final NetworkCapabilities netCap = new NetworkCapabilities();
2124         netCap.addCapability(NET_CAPABILITY_INTERNET);
2125         netCap.addCapability(NET_CAPABILITY_NOT_VCN_MANAGED);
2126         netCap.setRequestorUidAndPackageName(Process.myUid(), mContext.getPackageName());
2127         if (transportType > TYPE_NONE) {
2128             netCap.addTransportType(transportType);
2129         }
2130         return createNetworkRequest(type, netCap);
2131     }
2132 
2133     private NetworkRequest createNetworkRequest(
2134             NetworkRequest.Type type, NetworkCapabilities netCap) {
2135         return new NetworkRequest(netCap, TYPE_NONE, nextNetworkRequestId(), type);
2136     }
2137 
2138     private NetworkRequest createAlwaysOnRequestForCapability(int capability,
2139             NetworkRequest.Type type) {
2140         final NetworkCapabilities netCap = new NetworkCapabilities();
2141         netCap.clearAll();
2142         netCap.addCapability(capability);
2143         netCap.setRequestorUidAndPackageName(Process.myUid(), mContext.getPackageName());
2144         return new NetworkRequest(netCap, TYPE_NONE, nextNetworkRequestId(), type);
2145     }
2146 
2147     // Used only for testing.
2148     // TODO: Delete this and either:
2149     // 1. Give FakeSettingsProvider the ability to send settings change notifications (requires
2150     //    changing ContentResolver to make registerContentObserver non-final).
2151     // 2. Give FakeSettingsProvider an alternative notification mechanism and have the test use it
2152     //    by subclassing SettingsObserver.
2153     @VisibleForTesting
2154     void updateAlwaysOnNetworks() {
2155         mHandler.sendEmptyMessage(EVENT_CONFIGURE_ALWAYS_ON_NETWORKS);
2156     }
2157 
2158     // See FakeSettingsProvider comment above.
2159     @VisibleForTesting
2160     void updatePrivateDnsSettings() {
2161         mHandler.sendEmptyMessage(EVENT_PRIVATE_DNS_SETTINGS_CHANGED);
2162     }
2163 
2164     @VisibleForTesting
2165     void updateMobileDataPreferredUids() {
2166         mHandler.sendEmptyMessage(EVENT_MOBILE_DATA_PREFERRED_UIDS_CHANGED);
2167     }
2168 
2169     @VisibleForTesting
2170     void updateIngressRateLimit() {
2171         mHandler.sendEmptyMessage(EVENT_INGRESS_RATE_LIMIT_CHANGED);
2172     }
2173 
2174     @VisibleForTesting
2175     void simulateUpdateProxyInfo(@Nullable final Network network,
2176             @NonNull final ProxyInfo proxyInfo) {
2177         Message.obtain(mHandler, EVENT_PAC_PROXY_HAS_CHANGED,
2178                 new Pair<>(network, proxyInfo)).sendToTarget();
2179     }
2180 
2181     /**
2182      * Called when satellite network fallback uids at {@link SatelliteAccessController}
2183      * cache was updated based on {@link
2184      * android.app.role.OnRoleHoldersChangedListener#onRoleHoldersChanged(String, UserHandle)},
2185      * to create multilayer request with preference order
2186      * {@link #PREFERENCE_ORDER_SATELLITE_FALLBACK} there on.
2187      *
2188      */
2189     private void updateSatelliteNetworkPreferenceUids(Set<Integer> satelliteNetworkFallbackUids) {
2190         handleSetSatelliteNetworkPreference(satelliteNetworkFallbackUids);
2191     }
2192 
2193     private void handleAlwaysOnNetworkRequest(
2194             NetworkRequest networkRequest, String settingName, boolean defaultValue) {
2195         final boolean enable = toBool(Settings.Global.getInt(
2196                 mContext.getContentResolver(), settingName, encodeBool(defaultValue)));
2197         handleAlwaysOnNetworkRequest(networkRequest, enable);
2198     }
2199 
2200     private void handleAlwaysOnNetworkRequest(NetworkRequest networkRequest, boolean enable) {
2201         final boolean isEnabled = (mNetworkRequests.get(networkRequest) != null);
2202         if (enable == isEnabled) {
2203             return;  // Nothing to do.
2204         }
2205 
2206         if (enable) {
2207             handleRegisterNetworkRequest(new NetworkRequestInfo(
2208                     Process.myUid(), networkRequest, null /* messenger */, null /* binder */,
2209                     NetworkCallback.FLAG_INCLUDE_LOCATION_INFO,
2210                     null /* attributionTags */));
2211         } else {
2212             handleReleaseNetworkRequest(networkRequest, Process.SYSTEM_UID,
2213                     /* callOnUnavailable */ false);
2214         }
2215     }
2216 
2217     private void handleConfigureAlwaysOnNetworks() {
2218         handleAlwaysOnNetworkRequest(mDefaultMobileDataRequest,
2219                 ConnectivitySettingsManager.MOBILE_DATA_ALWAYS_ON, true /* defaultValue */);
2220         handleAlwaysOnNetworkRequest(mDefaultWifiRequest,
2221                 ConnectivitySettingsManager.WIFI_ALWAYS_REQUESTED, false /* defaultValue */);
2222         final boolean vehicleAlwaysRequested = mResources.get().getBoolean(
2223                 R.bool.config_vehicleInternalNetworkAlwaysRequested);
2224         handleAlwaysOnNetworkRequest(mDefaultVehicleRequest, vehicleAlwaysRequested);
2225     }
2226 
2227     // Note that registering observer for setting do not get initial callback when registering,
2228     // callers must fetch the initial value of the setting themselves if needed.
2229     private void registerSettingsCallbacks() {
2230         // Watch for global HTTP proxy changes.
2231         mSettingsObserver.observe(
2232                 Settings.Global.getUriFor(Settings.Global.HTTP_PROXY),
2233                 EVENT_APPLY_GLOBAL_HTTP_PROXY);
2234 
2235         // Watch for whether to keep mobile data always on.
2236         mSettingsObserver.observe(
2237                 Settings.Global.getUriFor(ConnectivitySettingsManager.MOBILE_DATA_ALWAYS_ON),
2238                 EVENT_CONFIGURE_ALWAYS_ON_NETWORKS);
2239 
2240         // Watch for whether to keep wifi always on.
2241         mSettingsObserver.observe(
2242                 Settings.Global.getUriFor(ConnectivitySettingsManager.WIFI_ALWAYS_REQUESTED),
2243                 EVENT_CONFIGURE_ALWAYS_ON_NETWORKS);
2244 
2245         // Watch for mobile data preferred uids changes.
2246         mSettingsObserver.observe(
2247                 Settings.Secure.getUriFor(ConnectivitySettingsManager.MOBILE_DATA_PREFERRED_UIDS),
2248                 EVENT_MOBILE_DATA_PREFERRED_UIDS_CHANGED);
2249 
2250         // Watch for ingress rate limit changes.
2251         mSettingsObserver.observe(
2252                 Settings.Global.getUriFor(
2253                         ConnectivitySettingsManager.INGRESS_RATE_LIMIT_BYTES_PER_SECOND),
2254                 EVENT_INGRESS_RATE_LIMIT_CHANGED);
2255     }
2256 
2257     private void registerPrivateDnsSettingsCallbacks() {
2258         for (Uri uri : DnsManager.getPrivateDnsSettingsUris()) {
2259             mSettingsObserver.observe(uri, EVENT_PRIVATE_DNS_SETTINGS_CHANGED);
2260         }
2261     }
2262 
2263     private synchronized int nextNetworkRequestId() {
2264         // TODO: Consider handle wrapping and exclude {@link NetworkRequest#REQUEST_ID_NONE} if
2265         //  doing that.
2266         return mNextNetworkRequestId++;
2267     }
2268 
2269     @VisibleForTesting
2270     @Nullable
2271     protected NetworkAgentInfo getNetworkAgentInfoForNetwork(Network network) {
2272         if (network == null) {
2273             return null;
2274         }
2275         return getNetworkAgentInfoForNetId(network.getNetId());
2276     }
2277 
2278     private NetworkAgentInfo getNetworkAgentInfoForNetId(int netId) {
2279         synchronized (mNetworkForNetId) {
2280             return mNetworkForNetId.get(netId);
2281         }
2282     }
2283 
2284     // TODO: determine what to do when more than one VPN applies to |uid|.
2285     @Nullable
2286     private NetworkAgentInfo getVpnForUid(int uid) {
2287         synchronized (mNetworkForNetId) {
2288             for (int i = 0; i < mNetworkForNetId.size(); i++) {
2289                 final NetworkAgentInfo nai = mNetworkForNetId.valueAt(i);
2290                 if (nai.isVPN() && nai.everConnected()
2291                         && nai.networkCapabilities.appliesToUid(uid)) {
2292                     return nai;
2293                 }
2294             }
2295         }
2296         return null;
2297     }
2298 
2299     @Nullable
2300     private Network[] getVpnUnderlyingNetworks(int uid) {
2301         if (mLockdownEnabled) return null;
2302         final NetworkAgentInfo nai = getVpnForUid(uid);
2303         if (nai != null) return nai.declaredUnderlyingNetworks;
2304         return null;
2305     }
2306 
2307     private NetworkAgentInfo getNetworkAgentInfoForUid(int uid) {
2308         NetworkAgentInfo nai = getDefaultNetworkForUid(uid);
2309 
2310         final Network[] networks = getVpnUnderlyingNetworks(uid);
2311         if (networks != null) {
2312             // getUnderlyingNetworks() returns:
2313             // null => there was no VPN, or the VPN didn't specify anything, so we use the default.
2314             // empty array => the VPN explicitly said "no default network".
2315             // non-empty array => the VPN specified one or more default networks; we use the
2316             //                    first one.
2317             if (networks.length > 0) {
2318                 nai = getNetworkAgentInfoForNetwork(networks[0]);
2319             } else {
2320                 nai = null;
2321             }
2322         }
2323         return nai;
2324     }
2325 
2326     @RequiresApi(Build.VERSION_CODES.TIRAMISU)
2327     private boolean hasInternetPermission(final int uid) {
2328         return (mBpfNetMaps.getNetPermForUid(uid) & PERMISSION_INTERNET) != 0;
2329     }
2330 
2331     /**
2332      * Check if UID should be blocked from using the specified network.
2333      */
2334     private boolean isNetworkWithCapabilitiesBlocked(@Nullable final NetworkCapabilities nc,
2335             final int uid, final boolean ignoreBlocked) {
2336         // Networks aren't blocked when ignoring blocked status
2337         if (ignoreBlocked) {
2338             return false;
2339         }
2340         if (isUidBlockedByVpn(uid, mVpnBlockedUidRanges)) return true;
2341         final long ident = Binder.clearCallingIdentity();
2342         try {
2343             final boolean metered = nc == null ? true : nc.isMetered();
2344             if (mDeps.isAtLeastV()) {
2345                 final boolean hasInternetPermission = hasInternetPermission(uid);
2346                 final boolean blockedByUidRules = mBpfNetMaps.isUidNetworkingBlocked(uid, metered);
2347                 if (mDeps.isChangeEnabled(NETWORK_BLOCKED_WITHOUT_INTERNET_PERMISSION, uid)) {
2348                     return blockedByUidRules || !hasInternetPermission;
2349                 } else {
2350                     return hasInternetPermission && blockedByUidRules;
2351                 }
2352             } else {
2353                 return mPolicyManager.isUidNetworkingBlocked(uid, metered);
2354             }
2355         } finally {
2356             Binder.restoreCallingIdentity(ident);
2357         }
2358     }
2359 
2360     private void maybeLogBlockedNetworkInfo(NetworkInfo ni, int uid) {
2361         if (ni == null || !LOGD_BLOCKED_NETWORKINFO) {
2362             return;
2363         }
2364         final boolean blocked;
2365         synchronized (mBlockedAppUids) {
2366             if (ni.getDetailedState() == DetailedState.BLOCKED && mBlockedAppUids.add(uid)) {
2367                 blocked = true;
2368             } else if (ni.isConnected() && mBlockedAppUids.remove(uid)) {
2369                 blocked = false;
2370             } else {
2371                 return;
2372             }
2373         }
2374         String action = blocked ? "BLOCKED" : "UNBLOCKED";
2375         log(String.format("Returning %s NetworkInfo to uid=%d", action, uid));
2376         mNetworkInfoBlockingLogs.log(action + " " + uid);
2377     }
2378 
2379     private void maybeLogBlockedStatusChanged(NetworkRequestInfo nri, Network net, int blocked) {
2380         if (nri == null || net == null || !LOGD_BLOCKED_NETWORKINFO) {
2381             return;
2382         }
2383         final String action = (blocked != 0) ? "BLOCKED" : "UNBLOCKED";
2384         final int requestId = nri.getActiveRequest() != null
2385                 ? nri.getActiveRequest().requestId : nri.mRequests.get(0).requestId;
2386         mNetworkInfoBlockingLogs.log(String.format(
2387                 "%s %d(%d) on netId %d: %s", action, nri.mAsUid, requestId, net.getNetId(),
2388                 Integer.toHexString(blocked)));
2389     }
2390 
2391     /**
2392      * Apply any relevant filters to the specified {@link NetworkInfo} for the given UID. For
2393      * example, this may mark the network as {@link DetailedState#BLOCKED} based
2394      * on {@link #isNetworkWithCapabilitiesBlocked}.
2395      */
2396     @NonNull
2397     private NetworkInfo filterNetworkInfo(@NonNull NetworkInfo networkInfo, int type,
2398             @NonNull NetworkCapabilities nc, int uid, boolean ignoreBlocked) {
2399         final NetworkInfo filtered = new NetworkInfo(networkInfo);
2400         // Many legacy types (e.g,. TYPE_MOBILE_HIPRI) are not actually a property of the network
2401         // but only exists if an app asks about them or requests them. Ensure the requesting app
2402         // gets the type it asks for.
2403         filtered.setType(type);
2404         if (isNetworkWithCapabilitiesBlocked(nc, uid, ignoreBlocked)) {
2405             filtered.setDetailedState(DetailedState.BLOCKED, null /* reason */,
2406                     null /* extraInfo */);
2407         }
2408         filterForLegacyLockdown(filtered);
2409         return filtered;
2410     }
2411 
2412     private NetworkInfo getFilteredNetworkInfo(NetworkAgentInfo nai, int uid,
2413             boolean ignoreBlocked) {
2414         return filterNetworkInfo(nai.networkInfo, nai.networkInfo.getType(),
2415                 nai.networkCapabilities, uid, ignoreBlocked);
2416     }
2417 
2418     /**
2419      * Return NetworkInfo for the active (i.e., connected) network interface.
2420      * It is assumed that at most one network is active at a time. If more
2421      * than one is active, it is indeterminate which will be returned.
2422      * @return the info for the active network, or {@code null} if none is
2423      * active
2424      */
2425     @Override
2426     @Nullable
2427     public NetworkInfo getActiveNetworkInfo() {
2428         enforceAccessPermission();
2429         final int uid = mDeps.getCallingUid();
2430         final NetworkAgentInfo nai = getNetworkAgentInfoForUid(uid);
2431         if (nai == null) return null;
2432         final NetworkInfo networkInfo = getFilteredNetworkInfo(nai, uid, false /* ignoreBlocked */);
2433         maybeLogBlockedNetworkInfo(networkInfo, uid);
2434         return networkInfo;
2435     }
2436 
2437     @Override
2438     @Nullable
2439     public Network getActiveNetwork() {
2440         enforceAccessPermission();
2441         return getActiveNetworkForUidInternal(mDeps.getCallingUid(), false);
2442     }
2443 
2444     @Override
2445     @Nullable
2446     public Network getActiveNetworkForUid(int uid, boolean ignoreBlocked) {
2447         enforceNetworkStackPermission(mContext);
2448         return getActiveNetworkForUidInternal(uid, ignoreBlocked);
2449     }
2450 
2451     @Nullable
2452     private Network getActiveNetworkForUidInternal(final int uid, boolean ignoreBlocked) {
2453         final NetworkAgentInfo vpnNai = getVpnForUid(uid);
2454         if (vpnNai != null) {
2455             final NetworkCapabilities requiredCaps = createDefaultNetworkCapabilitiesForUid(uid);
2456             if (requiredCaps.satisfiedByNetworkCapabilities(vpnNai.networkCapabilities)) {
2457                 return vpnNai.network;
2458             }
2459         }
2460 
2461         NetworkAgentInfo nai = getDefaultNetworkForUid(uid);
2462         if (nai == null || isNetworkWithCapabilitiesBlocked(nai.networkCapabilities, uid,
2463                 ignoreBlocked)) {
2464             return null;
2465         }
2466         return nai.network;
2467     }
2468 
2469     @Override
2470     @Nullable
2471     public NetworkInfo getActiveNetworkInfoForUid(int uid, boolean ignoreBlocked) {
2472         enforceNetworkStackPermission(mContext);
2473         final NetworkAgentInfo nai = getNetworkAgentInfoForUid(uid);
2474         if (nai == null) return null;
2475         return getFilteredNetworkInfo(nai, uid, ignoreBlocked);
2476     }
2477 
2478     /** Returns a NetworkInfo object for a network that doesn't exist. */
2479     private NetworkInfo makeFakeNetworkInfo(int networkType, int uid) {
2480         final NetworkInfo info = new NetworkInfo(networkType, 0 /* subtype */,
2481                 getNetworkTypeName(networkType), "" /* subtypeName */);
2482         info.setIsAvailable(true);
2483         // For compatibility with legacy code, return BLOCKED instead of DISCONNECTED when
2484         // background data is restricted.
2485         final NetworkCapabilities nc = new NetworkCapabilities();  // Metered.
2486         final DetailedState state = isNetworkWithCapabilitiesBlocked(nc, uid, false)
2487                 ? DetailedState.BLOCKED
2488                 : DetailedState.DISCONNECTED;
2489         info.setDetailedState(state, null /* reason */, null /* extraInfo */);
2490         filterForLegacyLockdown(info);
2491         return info;
2492     }
2493 
2494     private NetworkInfo getFilteredNetworkInfoForType(int networkType, int uid) {
2495         if (!mLegacyTypeTracker.isTypeSupported(networkType)) {
2496             return null;
2497         }
2498         final NetworkAgentInfo nai = mLegacyTypeTracker.getNetworkForType(networkType);
2499         if (nai == null) {
2500             return makeFakeNetworkInfo(networkType, uid);
2501         }
2502         return filterNetworkInfo(nai.networkInfo, networkType, nai.networkCapabilities, uid,
2503                 false);
2504     }
2505 
2506     @Override
2507     @Nullable
2508     public NetworkInfo getNetworkInfo(int networkType) {
2509         enforceAccessPermission();
2510         final int uid = mDeps.getCallingUid();
2511         if (getVpnUnderlyingNetworks(uid) != null) {
2512             // A VPN is active, so we may need to return one of its underlying networks. This
2513             // information is not available in LegacyTypeTracker, so we have to get it from
2514             // getNetworkAgentInfoForUid.
2515             final NetworkAgentInfo nai = getNetworkAgentInfoForUid(uid);
2516             if (nai == null) return null;
2517             final NetworkInfo networkInfo = getFilteredNetworkInfo(nai, uid, false);
2518             if (networkInfo.getType() == networkType) {
2519                 return networkInfo;
2520             }
2521         }
2522         return getFilteredNetworkInfoForType(networkType, uid);
2523     }
2524 
2525     @Override
2526     @Nullable
2527     public NetworkInfo getNetworkInfoForUid(Network network, int uid, boolean ignoreBlocked) {
2528         enforceAccessPermission();
2529         final NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
2530         if (nai == null) return null;
2531         return getFilteredNetworkInfo(nai, uid, ignoreBlocked);
2532     }
2533 
2534     @Override
2535     public NetworkInfo[] getAllNetworkInfo() {
2536         enforceAccessPermission();
2537         final ArrayList<NetworkInfo> result = new ArrayList<>();
2538         for (int networkType = 0; networkType <= ConnectivityManager.MAX_NETWORK_TYPE;
2539                 networkType++) {
2540             NetworkInfo info = getNetworkInfo(networkType);
2541             if (info != null) {
2542                 result.add(info);
2543             }
2544         }
2545         return result.toArray(new NetworkInfo[result.size()]);
2546     }
2547 
2548     @Override
2549     @Nullable
2550     public Network getNetworkForType(int networkType) {
2551         enforceAccessPermission();
2552         if (!mLegacyTypeTracker.isTypeSupported(networkType)) {
2553             return null;
2554         }
2555         final NetworkAgentInfo nai = mLegacyTypeTracker.getNetworkForType(networkType);
2556         if (nai == null) {
2557             return null;
2558         }
2559         final int uid = mDeps.getCallingUid();
2560         if (isNetworkWithCapabilitiesBlocked(nai.networkCapabilities, uid, false)) {
2561             return null;
2562         }
2563         return nai.network;
2564     }
2565 
2566     @Override
2567     @NonNull
2568     public Network[] getAllNetworks() {
2569         enforceAccessPermission();
2570         synchronized (mNetworkForNetId) {
2571             final Network[] result = new Network[mNetworkForNetId.size()];
2572             for (int i = 0; i < mNetworkForNetId.size(); i++) {
2573                 result[i] = mNetworkForNetId.valueAt(i).network;
2574             }
2575             return result;
2576         }
2577     }
2578 
2579     @Override
2580     public NetworkCapabilities[] getDefaultNetworkCapabilitiesForUser(
2581                 int userId, String callingPackageName, @Nullable String callingAttributionTag) {
2582         // The basic principle is: if an app's traffic could possibly go over a
2583         // network, without the app doing anything multinetwork-specific,
2584         // (hence, by "default"), then include that network's capabilities in
2585         // the array.
2586         //
2587         // In the normal case, app traffic only goes over the system's default
2588         // network connection, so that's the only network returned.
2589         //
2590         // With a VPN in force, some app traffic may go into the VPN, and thus
2591         // over whatever underlying networks the VPN specifies, while other app
2592         // traffic may go over the system default network (e.g.: a split-tunnel
2593         // VPN, or an app disallowed by the VPN), so the set of networks
2594         // returned includes the VPN's underlying networks and the system
2595         // default.
2596         enforceAccessPermission();
2597 
2598         HashMap<Network, NetworkCapabilities> result = new HashMap<>();
2599 
2600         for (final NetworkRequestInfo nri : mDefaultNetworkRequests) {
2601             if (!nri.isBeingSatisfied()) {
2602                 continue;
2603             }
2604             final NetworkAgentInfo nai = nri.getSatisfier();
2605             final NetworkCapabilities nc = getNetworkCapabilitiesInternal(nai);
2606             if (null != nc
2607                     && nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)
2608                     && !result.containsKey(nai.network)) {
2609                 result.put(
2610                         nai.network,
2611                         createWithLocationInfoSanitizedIfNecessaryWhenParceled(
2612                                 nc, false /* includeLocationSensitiveInfo */,
2613                                 getCallingPid(), mDeps.getCallingUid(), callingPackageName,
2614                                 callingAttributionTag));
2615             }
2616         }
2617 
2618         // No need to check mLockdownEnabled. If it's true, getVpnUnderlyingNetworks returns null.
2619         final Network[] networks = getVpnUnderlyingNetworks(mDeps.getCallingUid());
2620         if (null != networks) {
2621             for (final Network network : networks) {
2622                 final NetworkCapabilities nc = getNetworkCapabilitiesInternal(network);
2623                 if (null != nc) {
2624                     result.put(
2625                             network,
2626                             createWithLocationInfoSanitizedIfNecessaryWhenParceled(
2627                                     nc,
2628                                     false /* includeLocationSensitiveInfo */,
2629                                     getCallingPid(), mDeps.getCallingUid(), callingPackageName,
2630                                     callingAttributionTag));
2631                 }
2632             }
2633         }
2634 
2635         NetworkCapabilities[] out = new NetworkCapabilities[result.size()];
2636         out = result.values().toArray(out);
2637         return out;
2638     }
2639 
2640     // Because StatsEvent is not usable in tests (everything inside it is hidden), this
2641     // method is used to convert a ConnectivityStateSample into a StatsEvent, so that tests
2642     // can call sampleConnectivityState and make the checks on it.
2643     @NonNull
2644     private StatsEvent sampleConnectivityStateToStatsEvent() {
2645         final ConnectivityStateSample sample = sampleConnectivityState();
2646         return ConnectivityStatsLog.buildStatsEvent(
2647                 ConnectivityStatsLog.CONNECTIVITY_STATE_SAMPLE,
2648                 sample.getNetworkCountPerTransports().toByteArray(),
2649                 sample.getConnectionDurationPerTransports().toByteArray(),
2650                 sample.getNetworkRequestCount().toByteArray(),
2651                 sample.getNetworks().toByteArray());
2652     }
2653 
2654     /**
2655      * Gather and return a snapshot of the current connectivity state, to be used as a sample.
2656      *
2657      * This is used for metrics. These snapshots will be sampled and constitute a base for
2658      * statistics about connectivity state of devices.
2659      */
2660     @VisibleForTesting
2661     @NonNull
2662     public ConnectivityStateSample sampleConnectivityState() {
2663         ensureRunningOnConnectivityServiceThread();
2664         final ConnectivityStateSample.Builder builder = ConnectivityStateSample.newBuilder();
2665         builder.setNetworkCountPerTransports(sampleNetworkCount(mNetworkAgentInfos));
2666         builder.setConnectionDurationPerTransports(sampleConnectionDuration(mNetworkAgentInfos));
2667         builder.setNetworkRequestCount(sampleNetworkRequestCount(mNetworkRequests.values()));
2668         builder.setNetworks(sampleNetworks(mNetworkAgentInfos));
2669         return builder.build();
2670     }
2671 
2672     private static NetworkCountPerTransports sampleNetworkCount(
2673             @NonNull final ArraySet<NetworkAgentInfo> nais) {
2674         final SparseIntArray countPerTransports = new SparseIntArray();
2675         for (final NetworkAgentInfo nai : nais) {
2676             int transports = (int) nai.networkCapabilities.getTransportTypesInternal();
2677             countPerTransports.put(transports, 1 + countPerTransports.get(transports, 0));
2678         }
2679         final NetworkCountPerTransports.Builder builder = NetworkCountPerTransports.newBuilder();
2680         for (int i = countPerTransports.size() - 1; i >= 0; --i) {
2681             final NetworkCountForTransports.Builder c = NetworkCountForTransports.newBuilder();
2682             c.setTransportTypes(countPerTransports.keyAt(i));
2683             c.setNetworkCount(countPerTransports.valueAt(i));
2684             builder.addNetworkCountForTransports(c);
2685         }
2686         return builder.build();
2687     }
2688 
2689     private static ConnectionDurationPerTransports sampleConnectionDuration(
2690             @NonNull final ArraySet<NetworkAgentInfo> nais) {
2691         final ConnectionDurationPerTransports.Builder builder =
2692                 ConnectionDurationPerTransports.newBuilder();
2693         for (final NetworkAgentInfo nai : nais) {
2694             final ConnectionDurationForTransports.Builder c =
2695                     ConnectionDurationForTransports.newBuilder();
2696             c.setTransportTypes((int) nai.networkCapabilities.getTransportTypesInternal());
2697             final long durationMillis = SystemClock.elapsedRealtime() - nai.getConnectedTime();
2698             final long millisPerSecond = TimeUnit.SECONDS.toMillis(1);
2699             // Add millisPerSecond/2 to round up or down to the nearest value
2700             c.setDurationSec((int) ((durationMillis + millisPerSecond / 2) / millisPerSecond));
2701             builder.addConnectionDurationForTransports(c);
2702         }
2703         return builder.build();
2704     }
2705 
2706     private static NetworkRequestCount sampleNetworkRequestCount(
2707             @NonNull final Collection<NetworkRequestInfo> nris) {
2708         final NetworkRequestCount.Builder builder = NetworkRequestCount.newBuilder();
2709         final SparseIntArray countPerType = new SparseIntArray();
2710         for (final NetworkRequestInfo nri : nris) {
2711             final int type;
2712             if (Process.SYSTEM_UID == nri.mAsUid) {
2713                 // The request is filed "as" the system, so it's the system on its own behalf.
2714                 type = RequestType.RT_SYSTEM.getNumber();
2715             } else if (Process.SYSTEM_UID == nri.mUid) {
2716                 // The request is filed by the system as some other app, so it's the system on
2717                 // behalf of an app.
2718                 type = RequestType.RT_SYSTEM_ON_BEHALF_OF_APP.getNumber();
2719             } else {
2720                 // Not the system, so it's an app requesting on its own behalf.
2721                 type = RequestType.RT_APP.getNumber();
2722             }
2723             countPerType.put(type, countPerType.get(type, 0) + 1);
2724         }
2725         for (int i = countPerType.size() - 1; i >= 0; --i) {
2726             final RequestCountForType.Builder r = RequestCountForType.newBuilder();
2727             r.setRequestType(RequestType.forNumber(countPerType.keyAt(i)));
2728             r.setRequestCount(countPerType.valueAt(i));
2729             builder.addRequestCountForType(r);
2730         }
2731         return builder.build();
2732     }
2733 
2734     private static NetworkList sampleNetworks(@NonNull final ArraySet<NetworkAgentInfo> nais) {
2735         final NetworkList.Builder builder = NetworkList.newBuilder();
2736         for (final NetworkAgentInfo nai : nais) {
2737             final NetworkCapabilities nc = nai.networkCapabilities;
2738             final NetworkDescription.Builder d = NetworkDescription.newBuilder();
2739             d.setTransportTypes((int) nc.getTransportTypesInternal());
2740             final MeteredState meteredState;
2741             if (nc.hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED)) {
2742                 meteredState = MeteredState.METERED_TEMPORARILY_UNMETERED;
2743             } else if (nc.hasCapability(NET_CAPABILITY_NOT_METERED)) {
2744                 meteredState = MeteredState.METERED_NO;
2745             } else {
2746                 meteredState = MeteredState.METERED_YES;
2747             }
2748             d.setMeteredState(meteredState);
2749             final ValidatedState validatedState;
2750             if (nc.hasCapability(NET_CAPABILITY_CAPTIVE_PORTAL)) {
2751                 validatedState = ValidatedState.VS_PORTAL;
2752             } else if (nc.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY)) {
2753                 validatedState = ValidatedState.VS_PARTIAL;
2754             } else if (nc.hasCapability(NET_CAPABILITY_VALIDATED)) {
2755                 validatedState = ValidatedState.VS_VALID;
2756             } else {
2757                 validatedState = ValidatedState.VS_INVALID;
2758             }
2759             d.setValidatedState(validatedState);
2760             d.setScorePolicies(nai.getScore().getPoliciesInternal());
2761             d.setCapabilities(nc.getCapabilitiesInternal());
2762             d.setEnterpriseId(nc.getEnterpriseIdsInternal());
2763             builder.addNetworkDescription(d);
2764         }
2765         return builder.build();
2766     }
2767 
2768     @Override
2769     public boolean isNetworkSupported(int networkType) {
2770         enforceAccessPermission();
2771         return mLegacyTypeTracker.isTypeSupported(networkType);
2772     }
2773 
2774     /**
2775      * Return LinkProperties for the active (i.e., connected) default
2776      * network interface for the calling uid.
2777      * @return the ip properties for the active network, or {@code null} if
2778      * none is active
2779      */
2780     @Override
2781     public LinkProperties getActiveLinkProperties() {
2782         enforceAccessPermission();
2783         final int uid = mDeps.getCallingUid();
2784         NetworkAgentInfo nai = getNetworkAgentInfoForUid(uid);
2785         if (nai == null) return null;
2786         return linkPropertiesRestrictedForCallerPermissions(nai.linkProperties,
2787                 Binder.getCallingPid(), uid);
2788     }
2789 
2790     @Override
2791     public LinkProperties getLinkPropertiesForType(int networkType) {
2792         enforceAccessPermission();
2793         NetworkAgentInfo nai = mLegacyTypeTracker.getNetworkForType(networkType);
2794         final LinkProperties lp = getLinkProperties(nai);
2795         if (lp == null) return null;
2796         return linkPropertiesRestrictedForCallerPermissions(
2797                 lp, Binder.getCallingPid(), mDeps.getCallingUid());
2798     }
2799 
2800     // TODO - this should be ALL networks
2801     @Override
2802     public LinkProperties getLinkProperties(Network network) {
2803         enforceAccessPermission();
2804         final LinkProperties lp = getLinkProperties(getNetworkAgentInfoForNetwork(network));
2805         if (lp == null) return null;
2806         return linkPropertiesRestrictedForCallerPermissions(
2807                 lp, Binder.getCallingPid(), mDeps.getCallingUid());
2808     }
2809 
2810     @Nullable
2811     private LinkProperties getLinkProperties(@Nullable NetworkAgentInfo nai) {
2812         if (nai == null) {
2813             return null;
2814         }
2815         synchronized (nai) {
2816             return nai.linkProperties;
2817         }
2818     }
2819 
2820     @Override
2821     @Nullable
2822     public LinkProperties getRedactedLinkPropertiesForPackage(@NonNull LinkProperties lp, int uid,
2823             @NonNull String packageName, @Nullable String callingAttributionTag) {
2824         Objects.requireNonNull(packageName);
2825         Objects.requireNonNull(lp);
2826         enforceNetworkStackOrSettingsPermission();
2827         if (!hasAccessPermission(-1 /* pid */, uid)) {
2828             return null;
2829         }
2830         return linkPropertiesRestrictedForCallerPermissions(lp, -1 /* callerPid */, uid);
2831     }
2832 
2833     private NetworkCapabilities getNetworkCapabilitiesInternal(Network network) {
2834         return getNetworkCapabilitiesInternal(getNetworkAgentInfoForNetwork(network));
2835     }
2836 
2837     private NetworkCapabilities getNetworkCapabilitiesInternal(NetworkAgentInfo nai) {
2838         if (nai == null) return null;
2839         synchronized (nai) {
2840             return networkCapabilitiesRestrictedForCallerPermissions(
2841                     nai.networkCapabilities, Binder.getCallingPid(), mDeps.getCallingUid());
2842         }
2843     }
2844 
2845     @Override
2846     public NetworkCapabilities getNetworkCapabilities(Network network, String callingPackageName,
2847             @Nullable String callingAttributionTag) {
2848         mAppOpsManager.checkPackage(mDeps.getCallingUid(), callingPackageName);
2849         enforceAccessPermission();
2850         return createWithLocationInfoSanitizedIfNecessaryWhenParceled(
2851                 getNetworkCapabilitiesInternal(network),
2852                 false /* includeLocationSensitiveInfo */,
2853                 getCallingPid(), mDeps.getCallingUid(), callingPackageName, callingAttributionTag);
2854     }
2855 
2856     @Override
2857     public NetworkCapabilities getRedactedNetworkCapabilitiesForPackage(
2858             @NonNull NetworkCapabilities nc, int uid, @NonNull String packageName,
2859             @Nullable String callingAttributionTag) {
2860         Objects.requireNonNull(nc);
2861         Objects.requireNonNull(packageName);
2862         enforceNetworkStackOrSettingsPermission();
2863         if (!hasAccessPermission(-1 /* pid */, uid)) {
2864             return null;
2865         }
2866         return createWithLocationInfoSanitizedIfNecessaryWhenParceled(
2867                 networkCapabilitiesRestrictedForCallerPermissions(nc, -1 /* callerPid */, uid),
2868                 true /* includeLocationSensitiveInfo */, -1 /* callingPid */, uid, packageName,
2869                 callingAttributionTag);
2870     }
2871 
2872     private void redactUnderlyingNetworksForCapabilities(NetworkCapabilities nc, int pid, int uid) {
2873         if (nc.getUnderlyingNetworks() != null
2874                 && !hasNetworkFactoryOrSettingsPermission(pid, uid)) {
2875             nc.setUnderlyingNetworks(null);
2876         }
2877     }
2878 
2879     private boolean canSeeAllowedUids(final int pid, final int uid, final int netOwnerUid) {
2880         return Process.SYSTEM_UID == uid
2881                 || netOwnerUid == uid
2882                 || hasAnyPermissionOf(mContext, pid, uid,
2883                         android.Manifest.permission.NETWORK_FACTORY);
2884     }
2885 
2886     @VisibleForTesting
2887     NetworkCapabilities networkCapabilitiesRestrictedForCallerPermissions(
2888             NetworkCapabilities nc, int callerPid, int callerUid) {
2889         // Note : here it would be nice to check ACCESS_NETWORK_STATE and return null, but
2890         // this would be expensive (one more permission check every time any NC callback is
2891         // sent) and possibly dangerous : apps normally can't lose ACCESS_NETWORK_STATE, if
2892         // it happens for some reason (e.g. the package is uninstalled while CS is trying to
2893         // send the callback) it would crash the system server with NPE.
2894         final NetworkCapabilities newNc = new NetworkCapabilities(nc);
2895         if (!hasSettingsPermission(callerPid, callerUid)) {
2896             newNc.setUids(null);
2897             newNc.setSSID(null);
2898         }
2899         if (newNc.getNetworkSpecifier() != null) {
2900             newNc.setNetworkSpecifier(newNc.getNetworkSpecifier().redact());
2901         }
2902         if (!hasAnyPermissionOf(mContext, callerPid, callerUid,
2903                 android.Manifest.permission.NETWORK_STACK,
2904                 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK)) {
2905             newNc.setAdministratorUids(new int[0]);
2906         }
2907         if (!canSeeAllowedUids(callerPid, callerUid, newNc.getOwnerUid())) {
2908             newNc.setAllowedUids(new ArraySet<>());
2909         }
2910         redactUnderlyingNetworksForCapabilities(newNc, callerPid, callerUid);
2911 
2912         return newNc;
2913     }
2914 
2915     /**
2916      * Wrapper used to cache the permission check results performed for the corresponding
2917      * app. This avoids performing multiple permission checks for different fields in
2918      * NetworkCapabilities.
2919      * Note: This wrapper does not support any sort of invalidation and thus must not be
2920      * persistent or long-lived. It may only be used for the time necessary to
2921      * compute the redactions required by one particular NetworkCallback or
2922      * synchronous call.
2923      */
2924     private class RedactionPermissionChecker {
2925         private final int mCallingPid;
2926         private final int mCallingUid;
2927         @NonNull private final String mCallingPackageName;
2928         @Nullable private final String mCallingAttributionTag;
2929 
2930         private Boolean mHasLocationPermission = null;
2931         private Boolean mHasLocalMacAddressPermission = null;
2932         private Boolean mHasSettingsPermission = null;
2933 
2934         RedactionPermissionChecker(int callingPid, int callingUid,
2935                 @NonNull String callingPackageName, @Nullable String callingAttributionTag) {
2936             mCallingPid = callingPid;
2937             mCallingUid = callingUid;
2938             mCallingPackageName = callingPackageName;
2939             mCallingAttributionTag = callingAttributionTag;
2940         }
2941 
2942         private boolean hasLocationPermissionInternal() {
2943             final long token = Binder.clearCallingIdentity();
2944             try {
2945                 return mLocationPermissionChecker.checkLocationPermission(
2946                         mCallingPackageName, mCallingAttributionTag, mCallingUid,
2947                         null /* message */);
2948             } finally {
2949                 Binder.restoreCallingIdentity(token);
2950             }
2951         }
2952 
2953         /**
2954          * Returns whether the app holds location permission or not (might return cached result
2955          * if the permission was already checked before).
2956          */
2957         public boolean hasLocationPermission() {
2958             if (mHasLocationPermission == null) {
2959                 // If there is no cached result, perform the check now.
2960                 mHasLocationPermission = hasLocationPermissionInternal();
2961             }
2962             return mHasLocationPermission;
2963         }
2964 
2965         /**
2966          * Returns whether the app holds local mac address permission or not (might return cached
2967          * result if the permission was already checked before).
2968          */
2969         @CheckResult
2970         public boolean hasLocalMacAddressPermission() {
2971             if (mHasLocalMacAddressPermission == null) {
2972                 // If there is no cached result, perform the check now.
2973                 mHasLocalMacAddressPermission = ConnectivityService.this
2974                         .hasLocalMacAddressPermission(mCallingPid, mCallingUid);
2975             }
2976             return mHasLocalMacAddressPermission;
2977         }
2978 
2979         /**
2980          * Returns whether the app holds settings permission or not (might return cached
2981          * result if the permission was already checked before).
2982          */
2983         @CheckResult
2984         public boolean hasSettingsPermission() {
2985             if (mHasSettingsPermission == null) {
2986                 // If there is no cached result, perform the check now.
2987                 mHasSettingsPermission =
2988                         ConnectivityService.this.hasSettingsPermission(mCallingPid, mCallingUid);
2989             }
2990             return mHasSettingsPermission;
2991         }
2992     }
2993 
2994     private static boolean shouldRedact(@NetworkCapabilities.RedactionType long redactions,
2995             @NetworkCapabilities.NetCapability long redaction) {
2996         return (redactions & redaction) != 0;
2997     }
2998 
2999     /**
3000      * Use the provided |applicableRedactions| to check the receiving app's
3001      * permissions and clear/set the corresponding bit in the returned bitmask. The bitmask
3002      * returned will be used to ensure the necessary redactions are performed by NetworkCapabilities
3003      * before being sent to the corresponding app.
3004      */
3005     private @NetworkCapabilities.RedactionType long retrieveRequiredRedactions(
3006             @NetworkCapabilities.RedactionType long applicableRedactions,
3007             @NonNull RedactionPermissionChecker redactionPermissionChecker,
3008             boolean includeLocationSensitiveInfo) {
3009         long redactions = applicableRedactions;
3010         if (shouldRedact(redactions, REDACT_FOR_ACCESS_FINE_LOCATION)) {
3011             if (includeLocationSensitiveInfo
3012                     && redactionPermissionChecker.hasLocationPermission()) {
3013                 redactions &= ~REDACT_FOR_ACCESS_FINE_LOCATION;
3014             }
3015         }
3016         if (shouldRedact(redactions, REDACT_FOR_LOCAL_MAC_ADDRESS)) {
3017             if (redactionPermissionChecker.hasLocalMacAddressPermission()) {
3018                 redactions &= ~REDACT_FOR_LOCAL_MAC_ADDRESS;
3019             }
3020         }
3021         if (shouldRedact(redactions, REDACT_FOR_NETWORK_SETTINGS)) {
3022             if (redactionPermissionChecker.hasSettingsPermission()) {
3023                 redactions &= ~REDACT_FOR_NETWORK_SETTINGS;
3024             }
3025         }
3026         return redactions;
3027     }
3028 
3029     @VisibleForTesting
3030     @Nullable
3031     NetworkCapabilities createWithLocationInfoSanitizedIfNecessaryWhenParceled(
3032             @Nullable NetworkCapabilities nc, boolean includeLocationSensitiveInfo,
3033             int callingPid, int callingUid, @NonNull String callingPkgName,
3034             @Nullable String callingAttributionTag) {
3035         if (nc == null) {
3036             return null;
3037         }
3038         // Avoid doing location permission check if the transport info has no location sensitive
3039         // data.
3040         final RedactionPermissionChecker redactionPermissionChecker =
3041                 new RedactionPermissionChecker(callingPid, callingUid, callingPkgName,
3042                         callingAttributionTag);
3043         final long redactions = retrieveRequiredRedactions(
3044                 nc.getApplicableRedactions(), redactionPermissionChecker,
3045                 includeLocationSensitiveInfo);
3046         final NetworkCapabilities newNc = new NetworkCapabilities(nc, redactions);
3047         // Reset owner uid if not destined for the owner app.
3048         // TODO : calling UID is redacted because apps should generally not know what UID is
3049         // bringing up the VPN, but this should not apply to some very privileged apps like settings
3050         if (callingUid != nc.getOwnerUid()) {
3051             newNc.setOwnerUid(INVALID_UID);
3052             return newNc;
3053         }
3054         // Allow VPNs to see ownership of their own VPN networks - not location sensitive.
3055         if (nc.hasTransport(TRANSPORT_VPN)) {
3056             // Owner UIDs already checked above. No need to re-check.
3057             return newNc;
3058         }
3059         // If the calling does not want location sensitive data & target SDK >= S, then mask info.
3060         // Else include the owner UID iff the calling has location permission to provide backwards
3061         // compatibility for older apps.
3062         if (!includeLocationSensitiveInfo
3063                 && isTargetSdkAtleast(
3064                         Build.VERSION_CODES.S, callingUid, callingPkgName)) {
3065             newNc.setOwnerUid(INVALID_UID);
3066             return newNc;
3067         }
3068         // Reset owner uid if the app has no location permission.
3069         if (!redactionPermissionChecker.hasLocationPermission()) {
3070             newNc.setOwnerUid(INVALID_UID);
3071         }
3072         return newNc;
3073     }
3074 
3075     @NonNull
3076     private LinkProperties linkPropertiesRestrictedForCallerPermissions(
3077             LinkProperties lp, int callerPid, int callerUid) {
3078         if (lp == null) return new LinkProperties();
3079         // Note : here it would be nice to check ACCESS_NETWORK_STATE and return null, but
3080         // this would be expensive (one more permission check every time any LP callback is
3081         // sent) and possibly dangerous : apps normally can't lose ACCESS_NETWORK_STATE, if
3082         // it happens for some reason (e.g. the package is uninstalled while CS is trying to
3083         // send the callback) it would crash the system server with NPE.
3084 
3085         // Only do a permission check if sanitization is needed, to avoid unnecessary binder calls.
3086         final boolean needsSanitization =
3087                 (lp.getCaptivePortalApiUrl() != null || lp.getCaptivePortalData() != null);
3088         if (!needsSanitization) {
3089             return new LinkProperties(lp);
3090         }
3091 
3092         if (hasSettingsPermission(callerPid, callerUid)) {
3093             return new LinkProperties(lp, true /* parcelSensitiveFields */);
3094         }
3095 
3096         final LinkProperties newLp = new LinkProperties(lp);
3097         // Sensitive fields would not be parceled anyway, but sanitize for consistency before the
3098         // object gets parceled.
3099         newLp.setCaptivePortalApiUrl(null);
3100         newLp.setCaptivePortalData(null);
3101         return newLp;
3102     }
3103 
3104     private void restrictRequestUidsForCallerAndSetRequestorInfo(NetworkCapabilities nc,
3105             int callerUid, String callerPackageName) {
3106         // There is no need to track the effective UID of the request here. If the caller
3107         // lacks the settings permission, the effective UID is the same as the calling ID.
3108         if (!hasSettingsPermission()) {
3109             // Unprivileged apps can only pass in null or their own UID.
3110             if (nc.getUids() == null) {
3111                 // If the caller passes in null, the callback will also match networks that do not
3112                 // apply to its UID, similarly to what it would see if it called getAllNetworks.
3113                 // In this case, redact everything in the request immediately. This ensures that the
3114                 // app is not able to get any redacted information by filing an unredacted request
3115                 // and observing whether the request matches something.
3116                 if (nc.getNetworkSpecifier() != null) {
3117                     nc.setNetworkSpecifier(nc.getNetworkSpecifier().redact());
3118                 }
3119             } else {
3120                 nc.setSingleUid(callerUid);
3121             }
3122         }
3123         nc.setRequestorUidAndPackageName(callerUid, callerPackageName);
3124         nc.setAdministratorUids(new int[0]);
3125 
3126         // Clear owner UID; this can never come from an app.
3127         nc.setOwnerUid(INVALID_UID);
3128     }
3129 
3130     private void restrictBackgroundRequestForCaller(NetworkCapabilities nc) {
3131         if (!mPermissionMonitor.hasUseBackgroundNetworksPermission(mDeps.getCallingUid())) {
3132             nc.addCapability(NET_CAPABILITY_FOREGROUND);
3133         }
3134     }
3135 
3136     private void maybeDisableLocalNetworkMatching(NetworkCapabilities nc, int callingUid) {
3137         if (mDeps.isChangeEnabled(ENABLE_MATCH_LOCAL_NETWORK, callingUid)) {
3138             return;
3139         }
3140         // If NET_CAPABILITY_LOCAL_NETWORK is not added to capability, request should not be
3141         // satisfied by local networks.
3142         if (!nc.hasCapability(NET_CAPABILITY_LOCAL_NETWORK)) {
3143             nc.addForbiddenCapability(NET_CAPABILITY_LOCAL_NETWORK);
3144         }
3145     }
3146 
3147     private void restrictRequestNetworkCapabilitiesForCaller(NetworkCapabilities nc,
3148             int callingUid, String callerPackageName) {
3149         restrictRequestUidsForCallerAndSetRequestorInfo(nc, callingUid, callerPackageName);
3150         maybeDisableLocalNetworkMatching(nc, callingUid);
3151     }
3152 
3153     @Override
3154     public @RestrictBackgroundStatus int getRestrictBackgroundStatusByCaller() {
3155         enforceAccessPermission();
3156         final int callerUid = Binder.getCallingUid();
3157         final long token = Binder.clearCallingIdentity();
3158         try {
3159             return mPolicyManager.getRestrictBackgroundStatus(callerUid);
3160         } finally {
3161             Binder.restoreCallingIdentity(token);
3162         }
3163     }
3164 
3165     // TODO: Consider delete this function or turn it into a no-op method.
3166     @Override
3167     public NetworkState[] getAllNetworkState() {
3168         // This contains IMSI details, so make sure the caller is privileged.
3169         enforceNetworkStackPermission(mContext);
3170 
3171         final ArrayList<NetworkState> result = new ArrayList<>();
3172         for (NetworkStateSnapshot snapshot : getAllNetworkStateSnapshots()) {
3173             // NetworkStateSnapshot doesn't contain NetworkInfo, so need to fetch it from the
3174             // NetworkAgentInfo.
3175             final NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(snapshot.getNetwork());
3176             if (nai != null && nai.networkInfo.isConnected()) {
3177                 result.add(new NetworkState(new NetworkInfo(nai.networkInfo),
3178                         snapshot.getLinkProperties(), snapshot.getNetworkCapabilities(),
3179                         snapshot.getNetwork(), snapshot.getSubscriberId()));
3180             }
3181         }
3182         return result.toArray(new NetworkState[0]);
3183     }
3184 
3185     @Override
3186     @NonNull
3187     public List<NetworkStateSnapshot> getAllNetworkStateSnapshots() {
3188         // This contains IMSI details, so make sure the caller is privileged.
3189         enforceNetworkStackOrSettingsPermission();
3190 
3191         final ArrayList<NetworkStateSnapshot> result = new ArrayList<>();
3192         for (Network network : getAllNetworks()) {
3193             final NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
3194             final boolean includeNetwork = (nai != null) && nai.isCreated();
3195             if (includeNetwork) {
3196                 // TODO (b/73321673) : NetworkStateSnapshot contains a copy of the
3197                 // NetworkCapabilities, which may contain UIDs of apps to which the
3198                 // network applies. Should the UIDs be cleared so as not to leak or
3199                 // interfere ?
3200                 result.add(nai.getNetworkStateSnapshot());
3201             }
3202         }
3203         return result;
3204     }
3205 
3206     @Override
3207     public boolean isActiveNetworkMetered() {
3208         enforceAccessPermission();
3209 
3210         final NetworkCapabilities caps = getNetworkCapabilitiesInternal(getActiveNetwork());
3211         if (caps != null) {
3212             return !caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
3213         } else {
3214             // Always return the most conservative value
3215             return true;
3216         }
3217     }
3218 
3219     /**
3220      * Ensures that the system cannot call a particular method.
3221      */
3222     private boolean disallowedBecauseSystemCaller() {
3223         // TODO: start throwing a SecurityException when GnssLocationProvider stops calling
3224         // requestRouteToHost. In Q, GnssLocationProvider is changed to not call requestRouteToHost
3225         // for devices launched with Q and above. However, existing devices upgrading to Q and
3226         // above must continued to be supported for few more releases.
3227         if (isSystem(mDeps.getCallingUid()) && SystemProperties.getInt(
3228                 "ro.product.first_api_level", 0) > Build.VERSION_CODES.P) {
3229             log("This method exists only for app backwards compatibility"
3230                     + " and must not be called by system services.");
3231             return true;
3232         }
3233         return false;
3234     }
3235 
3236     /**
3237      * Ensure that a network route exists to deliver traffic to the specified
3238      * host via the specified network interface.
3239      * @param networkType the type of the network over which traffic to the
3240      * specified host is to be routed
3241      * @param hostAddress the IP address of the host to which the route is
3242      * desired
3243      * @return {@code true} on success, {@code false} on failure
3244      */
3245     @Override
3246     public boolean requestRouteToHostAddress(int networkType, byte[] hostAddress,
3247             String callingPackageName, String callingAttributionTag) {
3248         if (disallowedBecauseSystemCaller()) {
3249             return false;
3250         }
3251         PermissionUtils.enforcePackageNameMatchesUid(
3252                 mContext, mDeps.getCallingUid(), callingPackageName);
3253         enforceChangePermission(callingPackageName, callingAttributionTag);
3254         if (mProtectedNetworks.contains(networkType)) {
3255             enforceConnectivityRestrictedNetworksPermission(true /* checkUidsAllowedList */);
3256         }
3257 
3258         InetAddress addr;
3259         try {
3260             addr = InetAddress.getByAddress(hostAddress);
3261         } catch (UnknownHostException e) {
3262             if (DBG) log("requestRouteToHostAddress got " + e);
3263             return false;
3264         }
3265 
3266         if (!ConnectivityManager.isNetworkTypeValid(networkType)) {
3267             if (DBG) log("requestRouteToHostAddress on invalid network: " + networkType);
3268             return false;
3269         }
3270 
3271         NetworkAgentInfo nai = mLegacyTypeTracker.getNetworkForType(networkType);
3272         if (nai == null) {
3273             if (!mLegacyTypeTracker.isTypeSupported(networkType)) {
3274                 if (DBG) log("requestRouteToHostAddress on unsupported network: " + networkType);
3275             } else {
3276                 if (DBG) log("requestRouteToHostAddress on down network: " + networkType);
3277             }
3278             return false;
3279         }
3280 
3281         DetailedState netState;
3282         synchronized (nai) {
3283             netState = nai.networkInfo.getDetailedState();
3284         }
3285 
3286         if (netState != DetailedState.CONNECTED && netState != DetailedState.CAPTIVE_PORTAL_CHECK) {
3287             if (VDBG) {
3288                 log("requestRouteToHostAddress on down network "
3289                         + "(" + networkType + ") - dropped"
3290                         + " netState=" + netState);
3291             }
3292             return false;
3293         }
3294 
3295         final int uid = mDeps.getCallingUid();
3296         final long token = Binder.clearCallingIdentity();
3297         try {
3298             LinkProperties lp;
3299             int netId;
3300             synchronized (nai) {
3301                 lp = nai.linkProperties;
3302                 netId = nai.network.getNetId();
3303             }
3304             boolean ok = addLegacyRouteToHost(lp, addr, netId, uid);
3305             if (DBG) {
3306                 log("requestRouteToHostAddress " + addr + nai.toShortString() + " ok=" + ok);
3307             }
3308             return ok;
3309         } finally {
3310             Binder.restoreCallingIdentity(token);
3311         }
3312     }
3313 
3314     private boolean addLegacyRouteToHost(LinkProperties lp, InetAddress addr, int netId, int uid) {
3315         RouteInfo bestRoute = RouteInfo.selectBestRoute(lp.getAllRoutes(), addr);
3316         if (bestRoute == null) {
3317             bestRoute = RouteInfo.makeHostRoute(addr, lp.getInterfaceName());
3318         } else {
3319             String iface = bestRoute.getInterface();
3320             if (bestRoute.getGateway().equals(addr)) {
3321                 // if there is no better route, add the implied hostroute for our gateway
3322                 bestRoute = RouteInfo.makeHostRoute(addr, iface);
3323             } else {
3324                 // if we will connect to this through another route, add a direct route
3325                 // to it's gateway
3326                 bestRoute = RouteInfo.makeHostRoute(addr, bestRoute.getGateway(), iface);
3327             }
3328         }
3329         if (DBG) log("Adding legacy route " + bestRoute +
3330                 " for UID/PID " + uid + "/" + Binder.getCallingPid());
3331 
3332         final String dst = bestRoute.getDestinationLinkAddress().toString();
3333         final String nextHop = bestRoute.hasGateway()
3334                 ? bestRoute.getGateway().getHostAddress() : "";
3335         try {
3336             mNetd.networkAddLegacyRoute(netId, bestRoute.getInterface(), dst, nextHop , uid);
3337         } catch (RemoteException | ServiceSpecificException e) {
3338             if (DBG) loge("Exception trying to add a route: " + e);
3339             return false;
3340         }
3341         return true;
3342     }
3343 
3344     class DnsResolverUnsolicitedEventCallback extends
3345             IDnsResolverUnsolicitedEventListener.Stub {
3346         @Override
3347         public void onPrivateDnsValidationEvent(final PrivateDnsValidationEventParcel event) {
3348             try {
3349                 mHandler.sendMessage(mHandler.obtainMessage(
3350                         EVENT_PRIVATE_DNS_VALIDATION_UPDATE,
3351                         new PrivateDnsValidationUpdate(event.netId,
3352                                 InetAddresses.parseNumericAddress(event.ipAddress),
3353                                 event.hostname, event.validation)));
3354             } catch (IllegalArgumentException e) {
3355                 loge("Error parsing ip address in validation event");
3356             }
3357         }
3358 
3359         @Override
3360         public void onDnsHealthEvent(final DnsHealthEventParcel event) {
3361             NetworkAgentInfo nai = getNetworkAgentInfoForNetId(event.netId);
3362             // Netd event only allow registrants from system. Each NetworkMonitor thread is under
3363             // the caller thread of registerNetworkAgent. Thus, it's not allowed to register netd
3364             // event callback for certain nai. e.g. cellular. Register here to pass to
3365             // NetworkMonitor instead.
3366             // TODO: Move the Dns Event to NetworkMonitor. NetdEventListenerService only allows one
3367             // callback from each caller type. Need to re-factor NetdEventListenerService to allow
3368             // multiple NetworkMonitor registrants.
3369             if (nai != null && nai.satisfies(mDefaultRequest.mRequests.get(0))) {
3370                 nai.networkMonitor().notifyDnsResponse(event.healthResult);
3371             }
3372         }
3373 
3374         @Override
3375         public void onNat64PrefixEvent(final Nat64PrefixEventParcel event) {
3376             mHandler.post(() -> handleNat64PrefixEvent(event.netId, event.prefixOperation,
3377                     event.prefixAddress, event.prefixLength));
3378         }
3379 
3380         @Override
3381         public int getInterfaceVersion() {
3382             return this.VERSION;
3383         }
3384 
3385         @Override
3386         public String getInterfaceHash() {
3387             return this.HASH;
3388         }
3389     }
3390 
3391     @VisibleForTesting
3392     protected final DnsResolverUnsolicitedEventCallback mResolverUnsolEventCallback =
3393             new DnsResolverUnsolicitedEventCallback();
3394 
3395     private void registerDnsResolverUnsolicitedEventListener() {
3396         try {
3397             mDnsResolver.registerUnsolicitedEventListener(mResolverUnsolEventCallback);
3398         } catch (Exception e) {
3399             loge("Error registering DnsResolver unsolicited event callback: " + e);
3400         }
3401     }
3402 
3403     private final NetworkPolicyCallback mPolicyCallback = new NetworkPolicyCallback() {
3404         @Override
3405         public void onUidBlockedReasonChanged(int uid, @BlockedReason int blockedReasons) {
3406             if (shouldTrackUidsForBlockedStatusCallbacks()) {
3407                 Log.wtf(TAG, "Received unexpected NetworkPolicy callback");
3408                 return;
3409             }
3410             mHandler.sendMessage(mHandler.obtainMessage(
3411                     EVENT_BLOCKED_REASONS_CHANGED,
3412                     List.of(new Pair<>(uid, blockedReasons))));
3413         }
3414     };
3415 
3416     private boolean shouldTrackUidsForBlockedStatusCallbacks() {
3417         return mDeps.isAtLeastV();
3418     }
3419 
3420     @VisibleForTesting
3421     void handleBlockedReasonsChanged(List<Pair<Integer, Integer>> reasonsList) {
3422         for (Pair<Integer, Integer> reasons: reasonsList) {
3423             final int uid = reasons.first;
3424             final int blockedReasons = reasons.second;
3425             if (shouldTrackUidsForBlockedStatusCallbacks()) {
3426                 synchronized (mBlockedStatusTrackingUids) {
3427                     if (mBlockedStatusTrackingUids.get(uid) == 0) {
3428                         // This uid is not tracked anymore.
3429                         // This can happen if the network request is unregistered while
3430                         // EVENT_BLOCKED_REASONS_CHANGED is posted but not processed yet.
3431                         continue;
3432                     }
3433                 }
3434             }
3435             maybeNotifyNetworkBlockedForNewState(uid, blockedReasons);
3436             setUidBlockedReasons(uid, blockedReasons);
3437         }
3438     }
3439 
3440     static final class UidFrozenStateChangedArgs {
3441         final int[] mUids;
3442         final int[] mFrozenStates;
3443 
3444         UidFrozenStateChangedArgs(int[] uids, int[] frozenStates) {
3445             mUids = uids;
3446             mFrozenStates = frozenStates;
3447         }
3448     }
3449 
3450     /**
3451      * Check if the cell network is idle.
3452      * @return true if the cell network state is idle
3453      *         false if the cell network state is active or unknown
3454      */
3455     private boolean isCellNetworkIdle() {
3456         final NetworkAgentInfo defaultNai = getDefaultNetwork();
3457         if (defaultNai == null
3458                 || !defaultNai.networkCapabilities.hasTransport(TRANSPORT_CELLULAR)) {
3459             // mNetworkActivityTracker only tracks the activity of the default network. So if the
3460             // cell network is not the default network, cell network state is unknown.
3461             // TODO(b/279380356): Track cell network state when the cell is not the default network
3462             return false;
3463         }
3464 
3465         return !mNetworkActivityTracker.isDefaultNetworkActive();
3466     }
3467 
3468     private boolean shouldTrackFirewallDestroySocketReasons() {
3469         return mDeps.isAtLeastV();
3470     }
3471 
3472     private void updateDestroySocketReasons(final int uid, final int reason,
3473             final boolean addReason) {
3474         final int destroyReasons = mDestroySocketPendingUids.get(uid, DESTROY_SOCKET_REASON_NONE);
3475         if (addReason) {
3476             mDestroySocketPendingUids.put(uid, destroyReasons | reason);
3477         } else {
3478             final int newDestroyReasons = destroyReasons & ~reason;
3479             if (newDestroyReasons == DESTROY_SOCKET_REASON_NONE) {
3480                 mDestroySocketPendingUids.delete(uid);
3481             } else {
3482                 mDestroySocketPendingUids.put(uid, newDestroyReasons);
3483             }
3484         }
3485     }
3486 
3487     private void handleFrozenUids(int[] uids, int[] frozenStates) {
3488         ensureRunningOnConnectivityServiceThread();
3489         for (int i = 0; i < uids.length; i++) {
3490             final int uid = uids[i];
3491             final boolean addReason = frozenStates[i] == UID_FROZEN_STATE_FROZEN;
3492             updateDestroySocketReasons(uid, DESTROY_SOCKET_REASON_FROZEN, addReason);
3493         }
3494 
3495         if (!mDelayDestroySockets || !isCellNetworkIdle()) {
3496             destroyPendingSockets();
3497         }
3498     }
3499 
3500     private void handleUpdateFirewallDestroySocketReasons(
3501             List<Pair<Integer, Integer>> reasonsList) {
3502         if (!shouldTrackFirewallDestroySocketReasons()) {
3503             Log.wtf(TAG, "handleUpdateFirewallDestroySocketReasons is called unexpectedly");
3504             return;
3505         }
3506         ensureRunningOnConnectivityServiceThread();
3507 
3508         for (Pair<Integer, Integer> uidSocketDestroyReasons: reasonsList) {
3509             final int uid = uidSocketDestroyReasons.first;
3510             final int reasons = uidSocketDestroyReasons.second;
3511             final boolean destroyByFirewallBackground =
3512                     (reasons & DESTROY_SOCKET_REASON_FIREWALL_BACKGROUND)
3513                             != DESTROY_SOCKET_REASON_NONE;
3514             updateDestroySocketReasons(uid, DESTROY_SOCKET_REASON_FIREWALL_BACKGROUND,
3515                     destroyByFirewallBackground);
3516         }
3517 
3518         if (!mDelayDestroySockets || !isCellNetworkIdle()) {
3519             destroyPendingSockets();
3520         }
3521     }
3522 
3523     private void handleClearFirewallDestroySocketReasons(final int reason) {
3524         if (!shouldTrackFirewallDestroySocketReasons()) {
3525             Log.wtf(TAG, "handleClearFirewallDestroySocketReasons is called uexpectedly");
3526             return;
3527         }
3528         ensureRunningOnConnectivityServiceThread();
3529 
3530         // Unset reason from all pending uids
3531         for (int i = mDestroySocketPendingUids.size() - 1; i >= 0; i--) {
3532             final int uid = mDestroySocketPendingUids.keyAt(i);
3533             updateDestroySocketReasons(uid, reason, false /* addReason */);
3534         }
3535     }
3536 
3537     private void destroyPendingSockets() {
3538         ensureRunningOnConnectivityServiceThread();
3539         if (mDestroySocketPendingUids.size() == 0) {
3540             return;
3541         }
3542 
3543         Set<Integer> uids = new ArraySet<>();
3544         for (int i = 0; i < mDestroySocketPendingUids.size(); i++) {
3545             uids.add(mDestroySocketPendingUids.keyAt(i));
3546         }
3547 
3548         try {
3549             mDeps.destroyLiveTcpSocketsByOwnerUids(uids);
3550         } catch (SocketException | InterruptedIOException | ErrnoException e) {
3551             loge("Failed to destroy sockets: " + e);
3552         }
3553         mDestroySocketPendingUids.clear();
3554     }
3555 
3556     private void handleReportNetworkActivity(final NetworkActivityParams params) {
3557         mNetworkActivityTracker.handleReportNetworkActivity(params);
3558 
3559         final boolean isCellNetworkActivity;
3560         if (mTrackMultiNetworkActivities) {
3561             final NetworkAgentInfo nai = getNetworkAgentInfoForNetId(params.label);
3562             // nai could be null if netd receives a netlink message and calls the network
3563             // activity change callback after the network is unregistered from ConnectivityService.
3564             isCellNetworkActivity = nai != null
3565                     && nai.networkCapabilities.hasTransport(TRANSPORT_CELLULAR);
3566         } else {
3567             isCellNetworkActivity = params.label == TRANSPORT_CELLULAR;
3568         }
3569 
3570         if (mDelayDestroySockets && params.isActive && isCellNetworkActivity) {
3571             destroyPendingSockets();
3572         }
3573     }
3574 
3575     /**
3576      * If the cellular network is no longer the default network, destroy pending sockets.
3577      *
3578      * @param newNetwork new default network
3579      * @param oldNetwork old default network
3580      */
3581     private void maybeDestroyPendingSockets(NetworkAgentInfo newNetwork,
3582             NetworkAgentInfo oldNetwork) {
3583         final boolean isOldNetworkCellular = oldNetwork != null
3584                 && oldNetwork.networkCapabilities.hasTransport(TRANSPORT_CELLULAR);
3585         final boolean isNewNetworkCellular = newNetwork != null
3586                 && newNetwork.networkCapabilities.hasTransport(TRANSPORT_CELLULAR);
3587 
3588         if (isOldNetworkCellular && !isNewNetworkCellular) {
3589             destroyPendingSockets();
3590         }
3591     }
3592 
3593     private void dumpDestroySockets(IndentingPrintWriter pw) {
3594         pw.println("DestroySockets:");
3595         pw.increaseIndent();
3596         pw.print("mDestroyFrozenSockets="); pw.println(mDestroyFrozenSockets);
3597         pw.print("mDelayDestroySockets="); pw.println(mDelayDestroySockets);
3598         pw.print("mDestroySocketPendingUids:");
3599         pw.increaseIndent();
3600         for (int i = 0; i < mDestroySocketPendingUids.size(); i++) {
3601             final int uid = mDestroySocketPendingUids.keyAt(i);
3602             final int reasons = mDestroySocketPendingUids.valueAt(i);
3603             pw.print(uid + ": reasons=" + reasons);
3604         }
3605         pw.decreaseIndent();
3606         pw.decreaseIndent();
3607     }
3608 
3609     @RequiresApi(Build.VERSION_CODES.TIRAMISU)
3610     private void dumpBpfProgramStatus(IndentingPrintWriter pw) {
3611         pw.println("Bpf Program Status:");
3612         pw.increaseIndent();
3613         try {
3614             pw.print("CGROUP_INET_INGRESS: ");
3615             pw.println(mDeps.getBpfProgramId(BPF_CGROUP_INET_INGRESS));
3616             pw.print("CGROUP_INET_EGRESS: ");
3617             pw.println(mDeps.getBpfProgramId(BPF_CGROUP_INET_EGRESS));
3618 
3619             pw.print("CGROUP_INET_SOCK_CREATE: ");
3620             pw.println(mDeps.getBpfProgramId(BPF_CGROUP_INET_SOCK_CREATE));
3621 
3622             pw.print("CGROUP_INET4_BIND: ");
3623             pw.println(mDeps.getBpfProgramId(BPF_CGROUP_INET4_BIND));
3624             pw.print("CGROUP_INET6_BIND: ");
3625             pw.println(mDeps.getBpfProgramId(BPF_CGROUP_INET6_BIND));
3626 
3627             pw.print("CGROUP_INET4_CONNECT: ");
3628             pw.println(mDeps.getBpfProgramId(BPF_CGROUP_INET4_CONNECT));
3629             pw.print("CGROUP_INET6_CONNECT: ");
3630             pw.println(mDeps.getBpfProgramId(BPF_CGROUP_INET6_CONNECT));
3631 
3632             pw.print("CGROUP_UDP4_SENDMSG: ");
3633             pw.println(mDeps.getBpfProgramId(BPF_CGROUP_UDP4_SENDMSG));
3634             pw.print("CGROUP_UDP6_SENDMSG: ");
3635             pw.println(mDeps.getBpfProgramId(BPF_CGROUP_UDP6_SENDMSG));
3636 
3637             pw.print("CGROUP_UDP4_RECVMSG: ");
3638             pw.println(mDeps.getBpfProgramId(BPF_CGROUP_UDP4_RECVMSG));
3639             pw.print("CGROUP_UDP6_RECVMSG: ");
3640             pw.println(mDeps.getBpfProgramId(BPF_CGROUP_UDP6_RECVMSG));
3641 
3642             pw.print("CGROUP_GETSOCKOPT: ");
3643             pw.println(mDeps.getBpfProgramId(BPF_CGROUP_GETSOCKOPT));
3644             pw.print("CGROUP_SETSOCKOPT: ");
3645             pw.println(mDeps.getBpfProgramId(BPF_CGROUP_SETSOCKOPT));
3646 
3647             pw.print("CGROUP_INET_SOCK_RELEASE: ");
3648             pw.println(mDeps.getBpfProgramId(BPF_CGROUP_INET_SOCK_RELEASE));
3649         } catch (IOException e) {
3650             pw.println("  IOException");
3651         }
3652         pw.decreaseIndent();
3653     }
3654 
3655     @VisibleForTesting
3656     static final String KEY_DESTROY_FROZEN_SOCKETS_VERSION = "destroy_frozen_sockets_version";
3657 
3658     @VisibleForTesting
3659     public static final String ALLOW_SYSUI_CONNECTIVITY_REPORTS =
3660             "allow_sysui_connectivity_reports";
3661 
3662     public static final String ALLOW_SATALLITE_NETWORK_FALLBACK =
3663             "allow_satallite_network_fallback";
3664 
3665     private void enforceInternetPermission() {
3666         mContext.enforceCallingOrSelfPermission(
3667                 android.Manifest.permission.INTERNET,
3668                 "ConnectivityService");
3669     }
3670 
3671     private void enforceAccessPermission() {
3672         mContext.enforceCallingOrSelfPermission(
3673                 android.Manifest.permission.ACCESS_NETWORK_STATE,
3674                 "ConnectivityService");
3675     }
3676 
3677     @CheckResult
3678     private boolean hasAccessPermission(int pid, int uid) {
3679         return mContext.checkPermission(android.Manifest.permission.ACCESS_NETWORK_STATE, pid, uid)
3680                 == PERMISSION_GRANTED;
3681     }
3682 
3683     /**
3684      * Performs a strict and comprehensive check of whether a calling package is allowed to
3685      * change the state of network, as the condition differs for pre-M, M+, and
3686      * privileged/preinstalled apps. The caller is expected to have either the
3687      * CHANGE_NETWORK_STATE or the WRITE_SETTINGS permission declared. Either of these
3688      * permissions allow changing network state; WRITE_SETTINGS is a runtime permission and
3689      * can be revoked, but (except in M, excluding M MRs), CHANGE_NETWORK_STATE is a normal
3690      * permission and cannot be revoked. See http://b/23597341
3691      *
3692      * Note: if the check succeeds because the application holds WRITE_SETTINGS, the operation
3693      * of this app will be updated to the current time.
3694      */
3695     private void enforceChangePermission(String callingPkg, String callingAttributionTag) {
3696         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.CHANGE_NETWORK_STATE)
3697                 == PackageManager.PERMISSION_GRANTED) {
3698             return;
3699         }
3700 
3701         if (callingPkg == null) {
3702             throw new SecurityException("Calling package name is null.");
3703         }
3704 
3705         final AppOpsManager appOpsMgr = mContext.getSystemService(AppOpsManager.class);
3706         final int uid = mDeps.getCallingUid();
3707         final int mode = appOpsMgr.noteOpNoThrow(AppOpsManager.OPSTR_WRITE_SETTINGS, uid,
3708                 callingPkg, callingAttributionTag, null /* message */);
3709 
3710         if (mode == AppOpsManager.MODE_ALLOWED) {
3711             return;
3712         }
3713 
3714         if ((mode == AppOpsManager.MODE_DEFAULT) && (mContext.checkCallingOrSelfPermission(
3715                 android.Manifest.permission.WRITE_SETTINGS) == PackageManager.PERMISSION_GRANTED)) {
3716             return;
3717         }
3718 
3719         throw new SecurityException(callingPkg + " was not granted either of these permissions:"
3720                 + android.Manifest.permission.CHANGE_NETWORK_STATE + ","
3721                 + android.Manifest.permission.WRITE_SETTINGS + ".");
3722     }
3723 
3724     private void enforceSettingsPermission() {
3725         enforceAnyPermissionOf(mContext,
3726                 android.Manifest.permission.NETWORK_SETTINGS,
3727                 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK);
3728     }
3729 
3730     private void enforceSettingsOrSetupWizardOrUseRestrictedNetworksPermission() {
3731         enforceAnyPermissionOf(mContext,
3732                 android.Manifest.permission.NETWORK_SETTINGS,
3733                 android.Manifest.permission.NETWORK_SETUP_WIZARD,
3734                 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
3735                 Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS);
3736     }
3737 
3738     private void enforceNetworkFactoryPermission() {
3739         // TODO: Check for the BLUETOOTH_STACK permission once that is in the API surface.
3740         if (UserHandle.getAppId(getCallingUid()) == Process.BLUETOOTH_UID) return;
3741         enforceAnyPermissionOf(mContext,
3742                 android.Manifest.permission.NETWORK_FACTORY,
3743                 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK);
3744     }
3745 
3746     private void enforceNetworkFactoryOrSettingsPermission() {
3747         // TODO: Check for the BLUETOOTH_STACK permission once that is in the API surface.
3748         if (UserHandle.getAppId(getCallingUid()) == Process.BLUETOOTH_UID) return;
3749         enforceAnyPermissionOf(mContext,
3750                 android.Manifest.permission.NETWORK_SETTINGS,
3751                 android.Manifest.permission.NETWORK_FACTORY,
3752                 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK);
3753     }
3754 
3755     private void enforceNetworkFactoryOrTestNetworksPermission() {
3756         // TODO: Check for the BLUETOOTH_STACK permission once that is in the API surface.
3757         if (UserHandle.getAppId(getCallingUid()) == Process.BLUETOOTH_UID) return;
3758         enforceAnyPermissionOf(mContext,
3759                 android.Manifest.permission.MANAGE_TEST_NETWORKS,
3760                 android.Manifest.permission.NETWORK_FACTORY,
3761                 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK);
3762     }
3763 
3764     @CheckResult
3765     private boolean hasNetworkFactoryOrSettingsPermission(int pid, int uid) {
3766         return PERMISSION_GRANTED == mContext.checkPermission(
3767                 android.Manifest.permission.NETWORK_FACTORY, pid, uid)
3768                 || PERMISSION_GRANTED == mContext.checkPermission(
3769                 android.Manifest.permission.NETWORK_SETTINGS, pid, uid)
3770                 || PERMISSION_GRANTED == mContext.checkPermission(
3771                 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, pid, uid)
3772                 || UserHandle.getAppId(uid) == Process.BLUETOOTH_UID;
3773     }
3774 
3775     @CheckResult
3776     private boolean hasSettingsPermission() {
3777         return hasAnyPermissionOf(mContext, android.Manifest.permission.NETWORK_SETTINGS,
3778                 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK);
3779     }
3780 
3781     @CheckResult
3782     private boolean hasSettingsPermission(int pid, int uid) {
3783         return PERMISSION_GRANTED == mContext.checkPermission(
3784                 android.Manifest.permission.NETWORK_SETTINGS, pid, uid)
3785                 || PERMISSION_GRANTED == mContext.checkPermission(
3786                 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, pid, uid);
3787     }
3788 
3789     private void enforceNetworkStackOrSettingsPermission() {
3790         enforceNetworkStackPermissionOr(mContext,
3791                 android.Manifest.permission.NETWORK_SETTINGS);
3792     }
3793 
3794     private void enforceNetworkStackSettingsOrSetup() {
3795         enforceNetworkStackPermissionOr(mContext,
3796                 android.Manifest.permission.NETWORK_SETTINGS,
3797                 android.Manifest.permission.NETWORK_SETUP_WIZARD);
3798     }
3799 
3800     private void enforceAirplaneModePermission() {
3801         enforceNetworkStackPermissionOr(mContext,
3802                 android.Manifest.permission.NETWORK_AIRPLANE_MODE,
3803                 android.Manifest.permission.NETWORK_SETTINGS,
3804                 android.Manifest.permission.NETWORK_SETUP_WIZARD);
3805     }
3806 
3807     private void enforceOemNetworkPreferencesPermission() {
3808         mContext.enforceCallingOrSelfPermission(
3809                 android.Manifest.permission.CONTROL_OEM_PAID_NETWORK_PREFERENCE,
3810                 "ConnectivityService");
3811     }
3812 
3813     private void enforceManageTestNetworksPermission() {
3814         mContext.enforceCallingOrSelfPermission(
3815                 android.Manifest.permission.MANAGE_TEST_NETWORKS,
3816                 "ConnectivityService");
3817     }
3818 
3819     @CheckResult
3820     private boolean hasNetworkStackPermission() {
3821         return hasAnyPermissionOf(mContext, android.Manifest.permission.NETWORK_STACK,
3822                 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK);
3823     }
3824 
3825     @CheckResult
3826     private boolean hasNetworkStackPermission(int pid, int uid) {
3827         return hasAnyPermissionOf(mContext, pid, uid, android.Manifest.permission.NETWORK_STACK,
3828                 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK);
3829     }
3830 
3831     @CheckResult
3832     private boolean hasSystemBarServicePermission(int pid, int uid) {
3833         return hasAnyPermissionOf(mContext, pid, uid,
3834                 android.Manifest.permission.STATUS_BAR_SERVICE);
3835     }
3836 
3837     @CheckResult
3838     private boolean hasNetworkSignalStrengthWakeupPermission(int pid, int uid) {
3839         return hasAnyPermissionOf(mContext, pid, uid,
3840                 android.Manifest.permission.NETWORK_SIGNAL_STRENGTH_WAKEUP,
3841                 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
3842                 android.Manifest.permission.NETWORK_SETTINGS);
3843     }
3844 
3845     @CheckResult
3846     private boolean hasConnectivityRestrictedNetworksPermission(int callingUid,
3847             boolean checkUidsAllowedList) {
3848         if (hasAnyPermissionOf(mContext,
3849                 android.Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS)) {
3850             return true;
3851         }
3852 
3853         // fallback to ConnectivityInternalPermission
3854         // TODO: Remove this fallback check after all apps have declared
3855         //  CONNECTIVITY_USE_RESTRICTED_NETWORKS.
3856         if (hasAnyPermissionOf(mContext, android.Manifest.permission.CONNECTIVITY_INTERNAL)) {
3857             return true;
3858         }
3859 
3860         // Check whether uid is in allowed on restricted networks list.
3861         if (checkUidsAllowedList
3862                 && mPermissionMonitor.isUidAllowedOnRestrictedNetworks(callingUid)) {
3863             return true;
3864         }
3865         return false;
3866     }
3867 
3868     private void enforceConnectivityRestrictedNetworksPermission(boolean checkUidsAllowedList) {
3869         final int callingUid = mDeps.getCallingUid();
3870         if (!hasConnectivityRestrictedNetworksPermission(callingUid, checkUidsAllowedList)) {
3871             throw new SecurityException("ConnectivityService: user " + callingUid
3872                     + " has no permission to access restricted network.");
3873         }
3874     }
3875 
3876     private void enforceKeepalivePermission() {
3877         mContext.enforceCallingOrSelfPermission(KeepaliveTracker.PERMISSION, "ConnectivityService");
3878     }
3879 
3880     @CheckResult
3881     private boolean hasLocalMacAddressPermission(int pid, int uid) {
3882         return PERMISSION_GRANTED == mContext.checkPermission(
3883                 Manifest.permission.LOCAL_MAC_ADDRESS, pid, uid);
3884     }
3885 
3886     private void sendConnectedBroadcast(NetworkInfo info) {
3887         sendGeneralBroadcast(info, CONNECTIVITY_ACTION);
3888     }
3889 
3890     private void sendInetConditionBroadcast(NetworkInfo info) {
3891         sendGeneralBroadcast(info, ConnectivityManager.INET_CONDITION_ACTION);
3892     }
3893 
3894     private Intent makeGeneralIntent(NetworkInfo info, String bcastType) {
3895         Intent intent = new Intent(bcastType);
3896         intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, new NetworkInfo(info));
3897         intent.putExtra(ConnectivityManager.EXTRA_NETWORK_TYPE, info.getType());
3898         if (info.isFailover()) {
3899             intent.putExtra(ConnectivityManager.EXTRA_IS_FAILOVER, true);
3900             info.setFailover(false);
3901         }
3902         if (info.getReason() != null) {
3903             intent.putExtra(ConnectivityManager.EXTRA_REASON, info.getReason());
3904         }
3905         if (info.getExtraInfo() != null) {
3906             intent.putExtra(ConnectivityManager.EXTRA_EXTRA_INFO,
3907                     info.getExtraInfo());
3908         }
3909         intent.putExtra(ConnectivityManager.EXTRA_INET_CONDITION, mDefaultInetConditionPublished);
3910         return intent;
3911     }
3912 
3913     private void sendGeneralBroadcast(NetworkInfo info, String bcastType) {
3914         sendStickyBroadcast(makeGeneralIntent(info, bcastType));
3915     }
3916 
3917     // TODO(b/193460475): Remove when tooling supports SystemApi to public API.
3918     @SuppressLint("NewApi")
3919     // TODO: Set the mini sdk to 31 and remove @TargetApi annotation when b/205923322 is addressed.
3920     @TargetApi(Build.VERSION_CODES.S)
3921     private void sendStickyBroadcast(Intent intent) {
3922         synchronized (this) {
3923             if (!mSystemReady
3924                     && intent.getAction().equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
3925                 mInitialBroadcast = new Intent(intent);
3926             }
3927             intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
3928             if (VDBG) {
3929                 log("sendStickyBroadcast: action=" + intent.getAction());
3930             }
3931 
3932             Bundle options = null;
3933             final long ident = Binder.clearCallingIdentity();
3934             if (ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction())) {
3935                 final NetworkInfo ni = intent.getParcelableExtra(
3936                         ConnectivityManager.EXTRA_NETWORK_INFO);
3937                 final BroadcastOptions opts = BroadcastOptions.makeBasic();
3938                 opts.setMaxManifestReceiverApiLevel(Build.VERSION_CODES.M);
3939                 applyMostRecentPolicyForConnectivityAction(opts, ni);
3940                 options = opts.toBundle();
3941                 intent.addFlags(Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS);
3942             }
3943             try {
3944                 mUserAllContext.sendStickyBroadcast(intent, options);
3945             } finally {
3946                 Binder.restoreCallingIdentity(ident);
3947             }
3948         }
3949     }
3950 
3951     private void applyMostRecentPolicyForConnectivityAction(BroadcastOptions options,
3952             NetworkInfo info) {
3953         // Delivery group policy APIs are only available on U+.
3954         if (!mDeps.isAtLeastU()) return;
3955 
3956         final BroadcastOptionsShim optsShim = mDeps.makeBroadcastOptionsShim(options);
3957         try {
3958             // This allows us to discard older broadcasts still waiting to be delivered
3959             // which have the same namespace and key.
3960             optsShim.setDeliveryGroupPolicy(ConstantsShim.DELIVERY_GROUP_POLICY_MOST_RECENT);
3961             optsShim.setDeliveryGroupMatchingKey(ConnectivityManager.CONNECTIVITY_ACTION,
3962                     createDeliveryGroupKeyForConnectivityAction(info));
3963             optsShim.setDeferralPolicy(ConstantsShim.DEFERRAL_POLICY_UNTIL_ACTIVE);
3964         } catch (UnsupportedApiLevelException e) {
3965             Log.wtf(TAG, "Using unsupported API" + e);
3966         }
3967     }
3968 
3969     @VisibleForTesting
3970     static String createDeliveryGroupKeyForConnectivityAction(NetworkInfo info) {
3971         final StringBuilder sb = new StringBuilder();
3972         sb.append(info.getType()).append(DELIVERY_GROUP_KEY_DELIMITER);
3973         sb.append(info.getSubtype()).append(DELIVERY_GROUP_KEY_DELIMITER);
3974         sb.append(info.getExtraInfo());
3975         return sb.toString();
3976     }
3977 
3978     /**
3979      * Called by SystemServer through ConnectivityManager when the system is ready.
3980      */
3981     @Override
3982     public void systemReady() {
3983         if (mDeps.getCallingUid() != Process.SYSTEM_UID) {
3984             throw new SecurityException("Calling Uid is not system uid.");
3985         }
3986         systemReadyInternal();
3987     }
3988 
3989     /**
3990      * Called when ConnectivityService can initialize remaining components.
3991      */
3992     @VisibleForTesting
3993     public void systemReadyInternal() {
3994         // Load flags after PackageManager is ready to query module version
3995         mFlags.loadFlags(mDeps, mContext);
3996 
3997         // Since mApps in PermissionMonitor needs to be populated first to ensure that
3998         // listening network request which is sent by MultipathPolicyTracker won't be added
3999         // NET_CAPABILITY_FOREGROUND capability. Thus, MultipathPolicyTracker.start() must
4000         // be called after PermissionMonitor#startMonitoring().
4001         // Calling PermissionMonitor#startMonitoring() in systemReadyInternal() and the
4002         // MultipathPolicyTracker.start() is called in NetworkPolicyManagerService#systemReady()
4003         // to ensure the tracking will be initialized correctly.
4004         final ConditionVariable startMonitoringDone = new ConditionVariable();
4005         mHandler.post(() -> {
4006             mPermissionMonitor.startMonitoring();
4007             startMonitoringDone.open();
4008         });
4009         mProxyTracker.loadGlobalProxy();
4010         registerDnsResolverUnsolicitedEventListener();
4011 
4012         synchronized (this) {
4013             mSystemReady = true;
4014             if (mInitialBroadcast != null) {
4015                 mContext.sendStickyBroadcastAsUser(mInitialBroadcast, UserHandle.ALL);
4016                 mInitialBroadcast = null;
4017             }
4018         }
4019 
4020         // Create network requests for always-on networks.
4021         mHandler.sendMessage(mHandler.obtainMessage(EVENT_CONFIGURE_ALWAYS_ON_NETWORKS));
4022 
4023         // Update mobile data preference if necessary.
4024         // Note that updating can be skipped here if the list is empty only because no uid
4025         // rules are applied before system ready. Normally, the empty uid list means to clear
4026         // the uids rules on netd.
4027         if (!ConnectivitySettingsManager.getMobileDataPreferredUids(mContext).isEmpty()) {
4028             updateMobileDataPreferredUids();
4029         }
4030 
4031         if (mSatelliteAccessController != null) {
4032             mSatelliteAccessController.start();
4033         }
4034 
4035         if (mCarrierPrivilegeAuthenticator != null) {
4036             mCarrierPrivilegeAuthenticator.start();
4037         }
4038 
4039         // On T+ devices, register callback for statsd to pull NETWORK_BPF_MAP_INFO atom
4040         if (mDeps.isAtLeastT()) {
4041             mBpfNetMaps.setPullAtomCallback(mContext);
4042         }
4043         ConnectivitySampleMetricsHelper.start(mContext, mHandler,
4044                 CONNECTIVITY_STATE_SAMPLE, this::sampleConnectivityStateToStatsEvent);
4045         // Wait PermissionMonitor to finish the permission update. Then MultipathPolicyTracker won't
4046         // have permission problem. While CV#block() is unbounded in time and can in principle block
4047         // forever, this replaces a synchronous call to PermissionMonitor#startMonitoring, which
4048         // could have blocked forever too.
4049         startMonitoringDone.block();
4050     }
4051 
4052     /**
4053      * Start listening for default data network activity state changes.
4054      */
4055     @Override
4056     public void registerNetworkActivityListener(@NonNull INetworkActivityListener l) {
4057         mNetworkActivityTracker.registerNetworkActivityListener(l);
4058     }
4059 
4060     /**
4061      * Stop listening for default data network activity state changes.
4062      */
4063     @Override
4064     public void unregisterNetworkActivityListener(@NonNull INetworkActivityListener l) {
4065         mNetworkActivityTracker.unregisterNetworkActivityListener(l);
4066     }
4067 
4068     /**
4069      * Check whether the default network radio is currently active.
4070      */
4071     @Override
4072     public boolean isDefaultNetworkActive() {
4073         return mNetworkActivityTracker.isDefaultNetworkActive();
4074     }
4075 
4076     /**
4077      * Reads the network specific MTU size from resources.
4078      * and set it on it's iface.
4079      */
4080     private void updateMtu(@NonNull LinkProperties newLp, @Nullable LinkProperties oldLp) {
4081         final String iface = newLp.getInterfaceName();
4082         final int mtu = newLp.getMtu();
4083         if (mtu == 0) {
4084             // Silently ignore unset MTU value.
4085             return;
4086         }
4087         if (oldLp != null && newLp.isIdenticalMtu(oldLp)
4088                 && TextUtils.equals(oldLp.getInterfaceName(), iface)) {
4089             if (VDBG) log("identical MTU and iface - not setting");
4090             return;
4091         }
4092         // Cannot set MTU without interface name
4093         if (TextUtils.isEmpty(iface)) {
4094             if (VDBG) log("Setting MTU size with null iface.");
4095             return;
4096         }
4097 
4098         if (!LinkProperties.isValidMtu(mtu, newLp.hasGlobalIpv6Address())) {
4099             loge("Unexpected mtu value: " + mtu + ", " + iface);
4100             return;
4101         }
4102 
4103         try {
4104             if (VDBG || DDBG) log("Setting MTU size: " + iface + ", " + mtu);
4105             mNetd.interfaceSetMtu(iface, mtu);
4106         } catch (RemoteException | ServiceSpecificException e) {
4107             loge("exception in interfaceSetMtu()" + e);
4108         }
4109     }
4110 
4111     @VisibleForTesting
4112     protected static final String DEFAULT_TCP_BUFFER_SIZES = "4096,87380,110208,4096,16384,110208";
4113 
4114     private void updateTcpBufferSizes(@Nullable String tcpBufferSizes) {
4115         String[] values = null;
4116         if (tcpBufferSizes != null) {
4117             values = tcpBufferSizes.split(",");
4118         }
4119 
4120         if (values == null || values.length != 6) {
4121             if (DBG) log("Invalid tcpBufferSizes string: " + tcpBufferSizes +", using defaults");
4122             tcpBufferSizes = DEFAULT_TCP_BUFFER_SIZES;
4123             values = tcpBufferSizes.split(",");
4124         }
4125 
4126         if (tcpBufferSizes.equals(mCurrentTcpBufferSizes)) return;
4127 
4128         try {
4129             if (VDBG || DDBG) log("Setting tx/rx TCP buffers to " + tcpBufferSizes);
4130 
4131             String rmemValues = String.join(" ", values[0], values[1], values[2]);
4132             String wmemValues = String.join(" ", values[3], values[4], values[5]);
4133             mNetd.setTcpRWmemorySize(rmemValues, wmemValues);
4134             mCurrentTcpBufferSizes = tcpBufferSizes;
4135         } catch (RemoteException | ServiceSpecificException e) {
4136             loge("Can't set TCP buffer sizes:" + e);
4137         }
4138     }
4139 
4140     @Override
4141     public int getRestoreDefaultNetworkDelay(int networkType) {
4142         String restoreDefaultNetworkDelayStr = mSystemProperties.get(
4143                 NETWORK_RESTORE_DELAY_PROP_NAME);
4144         if(restoreDefaultNetworkDelayStr != null &&
4145                 restoreDefaultNetworkDelayStr.length() != 0) {
4146             try {
4147                 return Integer.parseInt(restoreDefaultNetworkDelayStr);
4148             } catch (NumberFormatException e) {
4149             }
4150         }
4151         // if the system property isn't set, use the value for the apn type
4152         int ret = RESTORE_DEFAULT_NETWORK_DELAY;
4153 
4154         if (mLegacyTypeTracker.isTypeSupported(networkType)) {
4155             ret = mLegacyTypeTracker.getRestoreTimerForType(networkType);
4156         }
4157         return ret;
4158     }
4159 
4160     private void dumpNetworkDiagnostics(IndentingPrintWriter pw) {
4161         final List<NetworkDiagnostics> netDiags = new ArrayList<>();
4162         final long DIAG_TIME_MS = 5000;
4163         for (NetworkAgentInfo nai : networksSortedById()) {
4164             PrivateDnsConfig privateDnsCfg = mDnsManager.getPrivateDnsConfig(nai.network);
4165             // Start gathering diagnostic information.
4166             netDiags.add(new NetworkDiagnostics(
4167                     nai.network,
4168                     new LinkProperties(nai.linkProperties),  // Must be a copy.
4169                     privateDnsCfg,
4170                     DIAG_TIME_MS));
4171         }
4172 
4173         for (NetworkDiagnostics netDiag : netDiags) {
4174             pw.println();
4175             netDiag.waitForMeasurements();
4176             netDiag.dump(pw);
4177         }
4178     }
4179 
4180     @Override
4181     protected void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter writer,
4182             @Nullable String[] args) {
4183         if (!hasDumpPermission(mContext, TAG, writer)) return;
4184 
4185         mPriorityDumper.dump(fd, writer, args);
4186     }
4187 
4188     @CheckResult
4189     private boolean hasDumpPermission(Context context, String tag, PrintWriter pw) {
4190         if (context.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
4191                 != PackageManager.PERMISSION_GRANTED) {
4192             pw.println("Permission Denial: can't dump " + tag + " from from pid="
4193                     + Binder.getCallingPid() + ", uid=" + mDeps.getCallingUid()
4194                     + " due to missing android.permission.DUMP permission");
4195             return false;
4196         } else {
4197             return true;
4198         }
4199     }
4200 
4201     private void doDump(FileDescriptor fd, PrintWriter writer, String[] args) {
4202         final IndentingPrintWriter pw = new IndentingPrintWriter(writer, "  ");
4203 
4204         if (CollectionUtils.contains(args, DIAG_ARG)) {
4205             dumpNetworkDiagnostics(pw);
4206             return;
4207         } else if (CollectionUtils.contains(args, NETWORK_ARG)) {
4208             dumpNetworks(pw);
4209             return;
4210         } else if (CollectionUtils.contains(args, REQUEST_ARG)) {
4211             dumpNetworkRequests(pw);
4212             return;
4213         } else if (CollectionUtils.contains(args, TRAFFICCONTROLLER_ARG)) {
4214             boolean verbose = !CollectionUtils.contains(args, SHORT_ARG);
4215             dumpTrafficController(pw, fd, verbose);
4216             return;
4217         } else if (CollectionUtils.contains(args, CLATEGRESS4RAWBPFMAP_ARG)) {
4218             dumpClatBpfRawMap(pw, true /* isEgress4Map */);
4219             return;
4220         } else if (CollectionUtils.contains(args, CLATINGRESS6RAWBPFMAP_ARG)) {
4221             dumpClatBpfRawMap(pw, false /* isEgress4Map */);
4222             return;
4223         }
4224 
4225         pw.println("NetworkProviders for:");
4226         pw.increaseIndent();
4227         for (NetworkProviderInfo npi : mNetworkProviderInfos.values()) {
4228             pw.println(npi.providerId + ": " + npi.name);
4229         }
4230         pw.decreaseIndent();
4231         pw.println();
4232 
4233         final NetworkAgentInfo defaultNai = getDefaultNetwork();
4234         pw.print("Active default network: ");
4235         if (defaultNai == null) {
4236             pw.println("none");
4237         } else {
4238             pw.println(defaultNai.network.getNetId());
4239         }
4240         pw.println();
4241 
4242         pw.println("Current network preferences: ");
4243         pw.increaseIndent();
4244         dumpNetworkPreferences(pw);
4245         pw.decreaseIndent();
4246         pw.println();
4247 
4248         pw.println("Current Networks:");
4249         pw.increaseIndent();
4250         dumpNetworks(pw);
4251         pw.decreaseIndent();
4252         pw.println();
4253 
4254         pw.println("Status for known UIDs:");
4255         pw.increaseIndent();
4256         final int size = mUidBlockedReasons.size();
4257         for (int i = 0; i < size; i++) {
4258             // Don't crash if the array is modified while dumping in bugreports.
4259             try {
4260                 final int uid = mUidBlockedReasons.keyAt(i);
4261                 final int blockedReasons = mUidBlockedReasons.valueAt(i);
4262                 pw.println("UID=" + uid + " blockedReasons="
4263                         + Integer.toHexString(blockedReasons));
4264             } catch (ArrayIndexOutOfBoundsException e) {
4265                 pw.println("  ArrayIndexOutOfBoundsException");
4266             } catch (ConcurrentModificationException e) {
4267                 pw.println("  ConcurrentModificationException");
4268             }
4269         }
4270         pw.println();
4271         pw.decreaseIndent();
4272 
4273         pw.println("Network Requests:");
4274         pw.increaseIndent();
4275         dumpNetworkRequests(pw);
4276         pw.decreaseIndent();
4277         pw.println();
4278 
4279         pw.println("Network Offers:");
4280         pw.increaseIndent();
4281         for (final NetworkOfferInfo offerInfo : mNetworkOffers) {
4282             pw.println(offerInfo.offer);
4283         }
4284         pw.decreaseIndent();
4285         pw.println();
4286 
4287         mLegacyTypeTracker.dump(pw);
4288 
4289         pw.println();
4290         mKeepaliveTracker.dump(pw);
4291 
4292         pw.println();
4293         dumpAvoidBadWifiSettings(pw);
4294 
4295         pw.println();
4296         dumpDestroySockets(pw);
4297 
4298         if (mDeps.isAtLeastT()) {
4299             // R: https://android.googlesource.com/platform/system/core/+/refs/heads/android11-release/rootdir/init.rc
4300             //   shows /dev/cg2_bpf
4301             // S: https://android.googlesource.com/platform/system/core/+/refs/heads/android12-release/rootdir/init.rc
4302             //   does not
4303             // Thus cgroups are mounted at /dev/cg2_bpf on R and not on /sys/fs/cgroup
4304             // so the following won't work (on R) anyway.
4305             // The /sys/fs/cgroup path is only actually enforced/required starting with U,
4306             // but it is very likely to already be the case (though not guaranteed) on T.
4307             // I'm not at all sure about S - let's just skip it to get rid of lint warnings.
4308             pw.println();
4309             dumpBpfProgramStatus(pw);
4310         }
4311 
4312         if (null != mCarrierPrivilegeAuthenticator) {
4313             pw.println();
4314             mCarrierPrivilegeAuthenticator.dump(pw);
4315         }
4316 
4317         pw.println();
4318 
4319         if (!CollectionUtils.contains(args, SHORT_ARG)) {
4320             pw.println();
4321             pw.println("mNetworkRequestInfoLogs (most recent first):");
4322             pw.increaseIndent();
4323             mNetworkRequestInfoLogs.reverseDump(pw);
4324             pw.decreaseIndent();
4325 
4326             pw.println();
4327             pw.println("mNetworkInfoBlockingLogs (most recent first):");
4328             pw.increaseIndent();
4329             mNetworkInfoBlockingLogs.reverseDump(pw);
4330             pw.decreaseIndent();
4331 
4332             pw.println();
4333             pw.println("NetTransition WakeLock activity (most recent first):");
4334             pw.increaseIndent();
4335             pw.println("total acquisitions: " + mTotalWakelockAcquisitions);
4336             pw.println("total releases: " + mTotalWakelockReleases);
4337             pw.println("cumulative duration: " + (mTotalWakelockDurationMs / 1000) + "s");
4338             pw.println("longest duration: " + (mMaxWakelockDurationMs / 1000) + "s");
4339             if (mTotalWakelockAcquisitions > mTotalWakelockReleases) {
4340                 long duration = SystemClock.elapsedRealtime() - mLastWakeLockAcquireTimestamp;
4341                 pw.println("currently holding WakeLock for: " + (duration / 1000) + "s");
4342             }
4343             mWakelockLogs.reverseDump(pw);
4344 
4345             pw.println();
4346             pw.println("bandwidth update requests (by uid):");
4347             pw.increaseIndent();
4348             synchronized (mBandwidthRequests) {
4349                 for (int i = 0; i < mBandwidthRequests.size(); i++) {
4350                     pw.println("[" + mBandwidthRequests.keyAt(i)
4351                             + "]: " + mBandwidthRequests.valueAt(i));
4352                 }
4353             }
4354             pw.decreaseIndent();
4355             pw.decreaseIndent();
4356 
4357             pw.println();
4358             pw.println("mOemNetworkPreferencesLogs (most recent first):");
4359             pw.increaseIndent();
4360             mOemNetworkPreferencesLogs.reverseDump(pw);
4361             pw.decreaseIndent();
4362         }
4363 
4364         pw.println();
4365 
4366         pw.println();
4367         pw.println("Permission Monitor:");
4368         pw.increaseIndent();
4369         mPermissionMonitor.dump(pw);
4370         pw.decreaseIndent();
4371 
4372         pw.println();
4373         pw.println("Legacy network activity:");
4374         pw.increaseIndent();
4375         mNetworkActivityTracker.dump(pw);
4376         pw.decreaseIndent();
4377 
4378         pw.println();
4379         pw.println("Multicast routing supported: " +
4380                 (mMulticastRoutingCoordinatorService != null));
4381 
4382         pw.println();
4383         pw.println("Background firewall chain enabled: " + mBackgroundFirewallChainEnabled);
4384     }
4385 
4386     private void dumpNetworks(IndentingPrintWriter pw) {
4387         for (NetworkAgentInfo nai : networksSortedById()) {
4388             pw.println(nai.toString());
4389             pw.increaseIndent();
4390             pw.println("Nat464Xlat:");
4391             pw.increaseIndent();
4392             nai.dumpNat464Xlat(pw);
4393             pw.decreaseIndent();
4394             pw.println(String.format(
4395                     "Requests: REQUEST:%d LISTEN:%d BACKGROUND_REQUEST:%d total:%d",
4396                     nai.numForegroundNetworkRequests(),
4397                     nai.numNetworkRequests() - nai.numRequestNetworkRequests(),
4398                     nai.numBackgroundNetworkRequests(),
4399                     nai.numNetworkRequests()));
4400             pw.increaseIndent();
4401             for (int i = 0; i < nai.numNetworkRequests(); i++) {
4402                 pw.println(nai.requestAt(i).toString());
4403             }
4404             pw.decreaseIndent();
4405             pw.println("Inactivity Timers:");
4406             pw.increaseIndent();
4407             nai.dumpInactivityTimers(pw);
4408             pw.decreaseIndent();
4409             pw.decreaseIndent();
4410         }
4411     }
4412 
4413     private void dumpNetworkPreferences(IndentingPrintWriter pw) {
4414         if (!mProfileNetworkPreferences.isEmpty()) {
4415             pw.println("Profile preferences:");
4416             pw.increaseIndent();
4417             pw.println(mProfileNetworkPreferences);
4418             pw.decreaseIndent();
4419         }
4420         if (!mOemNetworkPreferences.isEmpty()) {
4421             pw.println("OEM preferences:");
4422             pw.increaseIndent();
4423             pw.println(mOemNetworkPreferences);
4424             pw.decreaseIndent();
4425         }
4426         if (!mMobileDataPreferredUids.isEmpty()) {
4427             pw.println("Mobile data preferred UIDs:");
4428             pw.increaseIndent();
4429             pw.println(mMobileDataPreferredUids);
4430             pw.decreaseIndent();
4431         }
4432 
4433         pw.println("Default requests:");
4434         pw.increaseIndent();
4435         dumpPerAppDefaultRequests(pw);
4436         pw.decreaseIndent();
4437     }
4438 
4439     private void dumpPerAppDefaultRequests(IndentingPrintWriter pw) {
4440         for (final NetworkRequestInfo defaultRequest : mDefaultNetworkRequests) {
4441             if (mDefaultRequest == defaultRequest) {
4442                 continue;
4443             }
4444 
4445             final NetworkAgentInfo satisfier = defaultRequest.getSatisfier();
4446             final String networkOutput;
4447             if (null == satisfier) {
4448                 networkOutput = "null";
4449             } else if (mNoServiceNetwork.equals(satisfier)) {
4450                 networkOutput = "no service network";
4451             } else {
4452                 networkOutput = String.valueOf(satisfier.network.netId);
4453             }
4454             final String asUidString = (defaultRequest.mAsUid == defaultRequest.mUid)
4455                     ? "" : " asUid: " + defaultRequest.mAsUid;
4456             final String requestInfo = "Request: [uid/pid:" + defaultRequest.mUid + "/"
4457                     + defaultRequest.mPid + asUidString + "]";
4458             final String satisfierOutput = "Satisfier: [" + networkOutput + "]"
4459                     + " Preference order: " + defaultRequest.mPreferenceOrder
4460                     + " Tracked UIDs: " + defaultRequest.getUids();
4461             pw.println(requestInfo + " - " + satisfierOutput);
4462         }
4463     }
4464 
4465     private void dumpNetworkRequests(IndentingPrintWriter pw) {
4466         NetworkRequestInfo[] infos = null;
4467         while (infos == null) {
4468             try {
4469                 infos = requestsSortedById();
4470             } catch (ConcurrentModificationException e) {
4471                 // mNetworkRequests should only be accessed from handler thread, except dump().
4472                 // As dump() is never called in normal usage, it would be needlessly expensive
4473                 // to lock the collection only for its benefit. Instead, retry getting the
4474                 // requests if ConcurrentModificationException is thrown during dump().
4475             }
4476         }
4477         for (NetworkRequestInfo nri : infos) {
4478             pw.println(nri.toString());
4479         }
4480     }
4481 
4482     private void dumpTrafficController(IndentingPrintWriter pw, final FileDescriptor fd,
4483             boolean verbose) {
4484         try {
4485             mBpfNetMaps.dump(pw, fd, verbose);
4486         } catch (ServiceSpecificException e) {
4487             pw.println(e.getMessage());
4488         } catch (IOException e) {
4489             loge("Dump BPF maps failed, " + e);
4490         }
4491     }
4492 
4493     private void dumpClatBpfRawMap(IndentingPrintWriter pw, boolean isEgress4Map) {
4494         for (NetworkAgentInfo nai : networksSortedById()) {
4495             if (nai.clatd != null) {
4496                 nai.clatd.dumpRawBpfMap(pw, isEgress4Map);
4497                 break;
4498             }
4499         }
4500     }
4501 
4502     private void dumpAllRequestInfoLogsToLogcat() {
4503         try (PrintWriter logPw = new PrintWriter(new Writer() {
4504             @Override
4505             public void write(final char[] cbuf, final int off, final int len) {
4506                 // This method is called with 0-length and 1-length arrays for empty strings
4507                 // or strings containing only the DEL character.
4508                 if (len <= 1) return;
4509                 Log.e(TAG, new String(cbuf, off, len));
4510             }
4511             @Override public void flush() {}
4512             @Override public void close() {}
4513         })) {
4514             mNetworkRequestInfoLogs.dump(logPw);
4515         }
4516     }
4517 
4518     /**
4519      * Return an array of all current NetworkAgentInfos sorted by network id.
4520      */
4521     private NetworkAgentInfo[] networksSortedById() {
4522         NetworkAgentInfo[] networks = new NetworkAgentInfo[0];
4523         networks = mNetworkAgentInfos.toArray(networks);
4524         Arrays.sort(networks, Comparator.comparingInt(nai -> nai.network.getNetId()));
4525         return networks;
4526     }
4527 
4528     /**
4529      * Return an array of all current NetworkRequest sorted by request id.
4530      */
4531     @VisibleForTesting
4532     NetworkRequestInfo[] requestsSortedById() {
4533         NetworkRequestInfo[] requests = new NetworkRequestInfo[0];
4534         requests = getNrisFromGlobalRequests().toArray(requests);
4535         // Sort the array based off the NRI containing the min requestId in its requests.
4536         Arrays.sort(requests,
4537                 Comparator.comparingInt(nri -> Collections.min(nri.mRequests,
4538                         Comparator.comparingInt(req -> req.requestId)).requestId
4539                 )
4540         );
4541         return requests;
4542     }
4543 
4544     private boolean isLiveNetworkAgent(NetworkAgentInfo nai, int what) {
4545         final NetworkAgentInfo officialNai = getNetworkAgentInfoForNetwork(nai.network);
4546         if (officialNai != null && officialNai.equals(nai)) return true;
4547         if (officialNai != null || VDBG) {
4548             loge(eventName(what) + " - isLiveNetworkAgent found mismatched netId: " + officialNai +
4549                 " - " + nai);
4550         }
4551         return false;
4552     }
4553 
4554     private boolean isDisconnectRequest(Message msg) {
4555         if (msg.what != NetworkAgent.EVENT_NETWORK_INFO_CHANGED) return false;
4556         final NetworkInfo info = (NetworkInfo) ((Pair) msg.obj).second;
4557         return info.getState() == NetworkInfo.State.DISCONNECTED;
4558     }
4559 
4560     // must be stateless - things change under us.
4561     private class NetworkStateTrackerHandler extends Handler {
4562         public NetworkStateTrackerHandler(Looper looper) {
4563             super(looper);
4564         }
4565 
4566         private void maybeHandleNetworkAgentMessage(Message msg) {
4567             final Pair<NetworkAgentInfo, Object> arg = (Pair<NetworkAgentInfo, Object>) msg.obj;
4568             final NetworkAgentInfo nai = arg.first;
4569             if (!mNetworkAgentInfos.contains(nai)) {
4570                 if (VDBG) {
4571                     log(String.format("%s from unknown NetworkAgent", eventName(msg.what)));
4572                 }
4573                 return;
4574             }
4575 
4576             // If the network has been destroyed, the only thing that it can do is disconnect.
4577             if (nai.isDestroyed() && !isDisconnectRequest(msg)) {
4578                 return;
4579             }
4580 
4581             switch (msg.what) {
4582                 case NetworkAgent.EVENT_NETWORK_CAPABILITIES_CHANGED: {
4583                     final NetworkCapabilities proposed = (NetworkCapabilities) arg.second;
4584                     if (!nai.respectsNcStructuralConstraints(proposed)) {
4585                         Log.wtf(TAG, "Agent " + nai + " violates nc structural constraints : "
4586                                 + nai.networkCapabilities + " -> " + proposed);
4587                         disconnectAndDestroyNetwork(nai);
4588                         return;
4589                     }
4590                     nai.setDeclaredCapabilities(proposed);
4591                     final NetworkCapabilities sanitized =
4592                             nai.getDeclaredCapabilitiesSanitized(mCarrierPrivilegeAuthenticator);
4593                     maybeUpdateWifiRoamTimestamp(nai, sanitized);
4594                     updateCapabilities(nai.getScore(), nai, sanitized);
4595                     break;
4596                 }
4597                 case NetworkAgent.EVENT_NETWORK_PROPERTIES_CHANGED: {
4598                     LinkProperties newLp = (LinkProperties) arg.second;
4599                     processLinkPropertiesFromAgent(nai, newLp);
4600                     handleUpdateLinkProperties(nai, newLp);
4601                     break;
4602                 }
4603                 case NetworkAgent.EVENT_NETWORK_INFO_CHANGED: {
4604                     NetworkInfo info = (NetworkInfo) arg.second;
4605                     updateNetworkInfo(nai, info);
4606                     break;
4607                 }
4608                 case NetworkAgent.EVENT_LOCAL_NETWORK_CONFIG_CHANGED: {
4609                     final LocalNetworkConfig config = (LocalNetworkConfig) arg.second;
4610                     handleUpdateLocalNetworkConfig(nai, nai.localNetworkConfig, config);
4611                     break;
4612                 }
4613                 case NetworkAgent.EVENT_NETWORK_SCORE_CHANGED: {
4614                     updateNetworkScore(nai, (NetworkScore) arg.second);
4615                     break;
4616                 }
4617                 case NetworkAgent.EVENT_SET_EXPLICITLY_SELECTED: {
4618                     if (nai.everConnected()) {
4619                         loge("ERROR: cannot call explicitlySelected on already-connected network");
4620                         // Note that if the NAI had been connected, this would affect the
4621                         // score, and therefore would require re-mixing the score and performing
4622                         // a rematch.
4623                     }
4624                     nai.networkAgentConfig.explicitlySelected = toBool(msg.arg1);
4625                     nai.networkAgentConfig.acceptUnvalidated = toBool(msg.arg1) && toBool(msg.arg2);
4626                     // Mark the network as temporarily accepting partial connectivity so that it
4627                     // will be validated (and possibly become default) even if it only provides
4628                     // partial internet access. Note that if user connects to partial connectivity
4629                     // and choose "don't ask again", then wifi disconnected by some reasons(maybe
4630                     // out of wifi coverage) and if the same wifi is available again, the device
4631                     // will auto connect to this wifi even though the wifi has "no internet".
4632                     // TODO: Evaluate using a separate setting in IpMemoryStore.
4633                     nai.networkAgentConfig.acceptPartialConnectivity = toBool(msg.arg2);
4634                     break;
4635                 }
4636                 case NetworkAgent.EVENT_SOCKET_KEEPALIVE: {
4637                     mKeepaliveTracker.handleEventSocketKeepalive(nai, msg.arg1, msg.arg2);
4638                     break;
4639                 }
4640                 case NetworkAgent.EVENT_UNDERLYING_NETWORKS_CHANGED: {
4641                     // TODO: prevent loops, e.g., if a network declares itself as underlying.
4642                     final List<Network> underlying = (List<Network>) arg.second;
4643 
4644                     if (isLegacyLockdownNai(nai)
4645                             && (underlying == null || underlying.size() != 1)) {
4646                         Log.wtf(TAG, "Legacy lockdown VPN " + nai.toShortString()
4647                                 + " must have exactly one underlying network: " + underlying);
4648                     }
4649 
4650                     final Network[] oldUnderlying = nai.declaredUnderlyingNetworks;
4651                     nai.declaredUnderlyingNetworks = (underlying != null)
4652                             ? underlying.toArray(new Network[0]) : null;
4653 
4654                     if (!Arrays.equals(oldUnderlying, nai.declaredUnderlyingNetworks)) {
4655                         if (DBG) {
4656                             log(nai.toShortString() + " changed underlying networks to "
4657                                     + Arrays.toString(nai.declaredUnderlyingNetworks));
4658                         }
4659                         updateCapabilitiesForNetwork(nai);
4660                         notifyIfacesChangedForNetworkStats();
4661                     }
4662                     break;
4663                 }
4664                 case NetworkAgent.EVENT_TEARDOWN_DELAY_CHANGED: {
4665                     if (msg.arg1 >= 0 && msg.arg1 <= NetworkAgent.MAX_TEARDOWN_DELAY_MS) {
4666                         nai.teardownDelayMs = msg.arg1;
4667                     } else {
4668                         logwtf(nai.toShortString() + " set invalid teardown delay " + msg.arg1);
4669                     }
4670                     break;
4671                 }
4672                 case NetworkAgent.EVENT_LINGER_DURATION_CHANGED: {
4673                     nai.setLingerDuration((int) arg.second);
4674                     break;
4675                 }
4676                 case NetworkAgent.EVENT_ADD_DSCP_POLICY: {
4677                     DscpPolicy policy = (DscpPolicy) arg.second;
4678                     if (mDscpPolicyTracker != null) {
4679                         mDscpPolicyTracker.addDscpPolicy(nai, policy);
4680                     }
4681                     break;
4682                 }
4683                 case NetworkAgent.EVENT_REMOVE_DSCP_POLICY: {
4684                     if (mDscpPolicyTracker != null) {
4685                         mDscpPolicyTracker.removeDscpPolicy(nai, (int) arg.second);
4686                     }
4687                     break;
4688                 }
4689                 case NetworkAgent.EVENT_REMOVE_ALL_DSCP_POLICIES: {
4690                     if (mDscpPolicyTracker != null) {
4691                         mDscpPolicyTracker.removeAllDscpPolicies(nai, true);
4692                     }
4693                     break;
4694                 }
4695                 case NetworkAgent.EVENT_UNREGISTER_AFTER_REPLACEMENT: {
4696                     if (!nai.everConnected()) {
4697                         Log.d(TAG, "unregisterAfterReplacement on never-connected "
4698                                 + nai.toShortString() + ", tearing down instead");
4699                         teardownUnneededNetwork(nai);
4700                         break;
4701                     }
4702 
4703                     if (nai.isDestroyed()) {
4704                         Log.d(TAG, "unregisterAfterReplacement on destroyed " + nai.toShortString()
4705                                 + ", ignoring");
4706                         break;
4707                     }
4708 
4709                     final int timeoutMs = (int) arg.second;
4710                     if (timeoutMs < 0 || timeoutMs > NetworkAgent.MAX_TEARDOWN_DELAY_MS) {
4711                         Log.e(TAG, "Invalid network replacement timer " + timeoutMs
4712                                 + ", must be between 0 and " + NetworkAgent.MAX_TEARDOWN_DELAY_MS);
4713                     }
4714 
4715                     // Marking a network awaiting replacement is used to ensure that any requests
4716                     // satisfied by the network do not switch to another network until a
4717                     // replacement is available or the wait for a replacement times out.
4718                     // If the network is inactive (i.e., nascent or lingering), then there are no
4719                     // such requests, and there is no point keeping it. Just tear it down.
4720                     // Note that setLingerDuration(0) cannot be used to do this because the network
4721                     // could be nascent.
4722                     nai.clearInactivityState();
4723                     if (unneeded(nai, UnneededFor.TEARDOWN)) {
4724                         Log.d(TAG, nai.toShortString()
4725                                 + " marked awaiting replacement is unneeded, tearing down instead");
4726                         teardownUnneededNetwork(nai);
4727                         break;
4728                     }
4729 
4730                     Log.d(TAG, "Marking " + nai.toShortString()
4731                             + " destroyed, awaiting replacement within " + timeoutMs + "ms");
4732                     destroyNativeNetwork(nai);
4733 
4734                     // TODO: deduplicate this call with the one in disconnectAndDestroyNetwork.
4735                     // This is not trivial because KeepaliveTracker#handleStartKeepalive does not
4736                     // consider the fact that the network could already have disconnected or been
4737                     // destroyed. Fix the code to send ERROR_INVALID_NETWORK when this happens
4738                     // (taking care to ensure no dup'd FD leaks), then remove the code duplication
4739                     // and move this code to a sensible location (destroyNativeNetwork perhaps?).
4740                     mKeepaliveTracker.handleStopAllKeepalives(nai,
4741                             SocketKeepalive.ERROR_INVALID_NETWORK);
4742 
4743                     nai.updateScoreForNetworkAgentUpdate();
4744                     // This rematch is almost certainly not going to result in any changes, because
4745                     // the destroyed flag is only just above the "current satisfier wins"
4746                     // tie-breaker. But technically anything that affects scoring should rematch.
4747                     rematchAllNetworksAndRequests();
4748                     mHandler.postDelayed(() -> nai.disconnect(), timeoutMs);
4749                     break;
4750                 }
4751             }
4752         }
4753 
4754         private boolean maybeHandleNetworkMonitorMessage(Message msg) {
4755             final int netId = msg.arg2;
4756             final NetworkAgentInfo nai = getNetworkAgentInfoForNetId(netId);
4757             // If a network has already been destroyed, all NetworkMonitor updates are ignored.
4758             if (nai != null && nai.isDestroyed()) return true;
4759             switch (msg.what) {
4760                 default:
4761                     return false;
4762                 case EVENT_PROBE_STATUS_CHANGED: {
4763                     if (nai == null) {
4764                         break;
4765                     }
4766                     final int probesCompleted = ((Pair<Integer, Integer>) msg.obj).first;
4767                     final int probesSucceeded = ((Pair<Integer, Integer>) msg.obj).second;
4768                     final boolean probePrivateDnsCompleted =
4769                             ((probesCompleted & NETWORK_VALIDATION_PROBE_PRIVDNS) != 0);
4770                     final boolean privateDnsBroken =
4771                             ((probesSucceeded & NETWORK_VALIDATION_PROBE_PRIVDNS) == 0);
4772                     if (probePrivateDnsCompleted) {
4773                         if (nai.networkCapabilities.isPrivateDnsBroken() != privateDnsBroken) {
4774                             nai.networkCapabilities.setPrivateDnsBroken(privateDnsBroken);
4775                             updateCapabilitiesForNetwork(nai);
4776                         }
4777                         // Only show the notification when the private DNS is broken and the
4778                         // PRIVATE_DNS_BROKEN notification hasn't shown since last valid.
4779                         if (privateDnsBroken && !nai.networkAgentConfig.hasShownBroken) {
4780                             showNetworkNotification(nai, NotificationType.PRIVATE_DNS_BROKEN);
4781                         }
4782                         nai.networkAgentConfig.hasShownBroken = privateDnsBroken;
4783                     } else if (nai.networkCapabilities.isPrivateDnsBroken()) {
4784                         // If probePrivateDnsCompleted is false but nai.networkCapabilities says
4785                         // private DNS is broken, it means this network is being reevaluated.
4786                         // Either probing private DNS is not necessary any more or it hasn't been
4787                         // done yet. In either case, the networkCapabilities should be updated to
4788                         // reflect the new status.
4789                         nai.networkCapabilities.setPrivateDnsBroken(false);
4790                         updateCapabilitiesForNetwork(nai);
4791                         nai.networkAgentConfig.hasShownBroken = false;
4792                     }
4793                     break;
4794                 }
4795                 case EVENT_NETWORK_TESTED: {
4796                     final NetworkTestedResults results = (NetworkTestedResults) msg.obj;
4797 
4798                     if (nai == null) break;
4799 
4800                     handleNetworkTested(nai, results.mTestResult,
4801                             (results.mRedirectUrl == null) ? "" : results.mRedirectUrl);
4802                     break;
4803                 }
4804                 case EVENT_PROVISIONING_NOTIFICATION: {
4805                     final boolean visible = toBool(msg.arg1);
4806                     // If captive portal status has changed, update capabilities or disconnect.
4807                     if (!visible) {
4808                         // Only clear SIGN_IN and NETWORK_SWITCH notifications here, or else other
4809                         // notifications belong to the same network may be cleared unexpectedly.
4810                         mNotifier.clearNotification(netId, NotificationType.SIGN_IN);
4811                         mNotifier.clearNotification(netId, NotificationType.NETWORK_SWITCH);
4812                     } else {
4813                         if (nai == null) {
4814                             loge("EVENT_PROVISIONING_NOTIFICATION from unknown NetworkMonitor");
4815                             break;
4816                         }
4817                         if (!nai.networkAgentConfig.provisioningNotificationDisabled) {
4818                             mNotifier.showNotification(netId, NotificationType.SIGN_IN, nai, null,
4819                                     (PendingIntent) msg.obj,
4820                                     nai.networkAgentConfig.explicitlySelected);
4821                         }
4822                     }
4823                     break;
4824                 }
4825                 case EVENT_PRIVATE_DNS_CONFIG_RESOLVED: {
4826                     if (nai == null) break;
4827 
4828                     updatePrivateDns(nai, (PrivateDnsConfig) msg.obj);
4829                     break;
4830                 }
4831                 case EVENT_CAPPORT_DATA_CHANGED: {
4832                     if (nai == null) break;
4833                     handleCapportApiDataUpdate(nai, (CaptivePortalData) msg.obj);
4834                     break;
4835                 }
4836             }
4837             return true;
4838         }
4839 
4840         private void handleNetworkTested(
4841                 @NonNull NetworkAgentInfo nai, int testResult, @NonNull String redirectUrl) {
4842             final boolean valid = (testResult & NETWORK_VALIDATION_RESULT_VALID) != 0;
4843             final boolean partial = (testResult & NETWORK_VALIDATION_RESULT_PARTIAL) != 0;
4844             final boolean portal = !TextUtils.isEmpty(redirectUrl);
4845 
4846             // If there is any kind of working networking, then the NAI has been evaluated
4847             // once. {@see NetworkAgentInfo#setEvaluated}, which returns whether this is
4848             // the first time this ever happened.
4849             final boolean someConnectivity = (valid || partial || portal);
4850             final boolean becameEvaluated = someConnectivity && nai.setEvaluated();
4851             // Because of b/245893397, if the score is updated when updateCapabilities is called,
4852             // any callback that receives onAvailable for that rematch receives an extra caps
4853             // callback. To prevent that, update the score in the agent so the updates below won't
4854             // see an update to both caps and score at the same time.
4855             // TODO : fix b/245893397 and remove this.
4856             if (becameEvaluated) nai.updateScoreForNetworkAgentUpdate();
4857 
4858             if (!valid && shouldIgnoreValidationFailureAfterRoam(nai)) {
4859                 // Assume the validation failure is due to a temporary failure after roaming
4860                 // and ignore it. NetworkMonitor will continue to retry validation. If it
4861                 // continues to fail after the block timeout expires, the network will be
4862                 // marked unvalidated. If it succeeds, then validation state will not change.
4863                 return;
4864             }
4865 
4866             final boolean wasValidated = nai.isValidated();
4867             final boolean wasPartial = nai.partialConnectivity();
4868             final boolean wasPortal = nai.captivePortalDetected();
4869             nai.setPartialConnectivity(partial);
4870             nai.setCaptivePortalDetected(portal);
4871             nai.updateScoreForNetworkAgentUpdate();
4872             final boolean partialConnectivityChanged = (wasPartial != partial);
4873             final boolean portalChanged = (wasPortal != portal);
4874 
4875             if (DBG) {
4876                 final String logMsg = !TextUtils.isEmpty(redirectUrl)
4877                         ? " with redirect to " + redirectUrl
4878                         : "";
4879                 final String statusMsg;
4880                 if (valid) {
4881                     statusMsg = "passed";
4882                 } else if (!TextUtils.isEmpty(redirectUrl)) {
4883                     statusMsg = "detected a portal";
4884                 } else {
4885                     statusMsg = "failed";
4886                 }
4887                 log(nai.toShortString() + " validation " + statusMsg + logMsg);
4888             }
4889             if (valid != wasValidated) {
4890                 final FullScore oldScore = nai.getScore();
4891                 nai.setValidated(valid);
4892                 updateCapabilities(oldScore, nai, nai.networkCapabilities);
4893                 if (valid) {
4894                     handleFreshlyValidatedNetwork(nai);
4895                     // Clear NO_INTERNET, PRIVATE_DNS_BROKEN, PARTIAL_CONNECTIVITY and
4896                     // LOST_INTERNET notifications if network becomes valid.
4897                     mNotifier.clearNotification(nai.network.getNetId(),
4898                             NotificationType.NO_INTERNET);
4899                     mNotifier.clearNotification(nai.network.getNetId(),
4900                             NotificationType.LOST_INTERNET);
4901                     mNotifier.clearNotification(nai.network.getNetId(),
4902                             NotificationType.PARTIAL_CONNECTIVITY);
4903                     mNotifier.clearNotification(nai.network.getNetId(),
4904                             NotificationType.PRIVATE_DNS_BROKEN);
4905                     // If network becomes valid, the hasShownBroken should be reset for
4906                     // that network so that the notification will be fired when the private
4907                     // DNS is broken again.
4908                     nai.networkAgentConfig.hasShownBroken = false;
4909                 }
4910             } else if (partialConnectivityChanged) {
4911                 updateCapabilitiesForNetwork(nai);
4912             } else if (portalChanged) {
4913                 if (portal && ConnectivitySettingsManager.CAPTIVE_PORTAL_MODE_AVOID
4914                         == getCaptivePortalMode(nai)) {
4915                     if (DBG) log("Avoiding captive portal network: " + nai.toShortString());
4916                     nai.onPreventAutomaticReconnect();
4917                     teardownUnneededNetwork(nai);
4918                     return;
4919                 } else {
4920                     updateCapabilitiesForNetwork(nai);
4921                 }
4922             } else if (becameEvaluated) {
4923                 // If valid or partial connectivity changed, updateCapabilities* has
4924                 // done the rematch.
4925                 rematchAllNetworksAndRequests();
4926             }
4927             updateInetCondition(nai);
4928 
4929             // Let the NetworkAgent know the state of its network
4930             // TODO: Evaluate to update partial connectivity to status to NetworkAgent.
4931             nai.onValidationStatusChanged(
4932                     valid ? NetworkAgent.VALID_NETWORK : NetworkAgent.INVALID_NETWORK,
4933                     redirectUrl);
4934 
4935             // If NetworkMonitor detects partial connectivity before
4936             // EVENT_INITIAL_EVALUATION_TIMEOUT arrives, show the partial connectivity notification
4937             // immediately. Re-notify partial connectivity silently if no internet
4938             // notification already there.
4939             if (!wasPartial && nai.partialConnectivity()) {
4940                 // Remove delayed message if there is a pending message.
4941                 mHandler.removeMessages(EVENT_INITIAL_EVALUATION_TIMEOUT, nai.network);
4942                 handleInitialEvaluationTimeout(nai.network);
4943             }
4944 
4945             if (wasValidated && !nai.isValidated()) {
4946                 handleNetworkUnvalidated(nai);
4947             }
4948         }
4949 
4950         private int getCaptivePortalMode(@NonNull NetworkAgentInfo nai) {
4951             if (nai.networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_BLUETOOTH) &&
4952                     mContext.getPackageManager().hasSystemFeature(FEATURE_WATCH)) {
4953                 // Do not avoid captive portal when network is wear proxy.
4954                 return ConnectivitySettingsManager.CAPTIVE_PORTAL_MODE_PROMPT;
4955             }
4956 
4957             return Settings.Global.getInt(mContext.getContentResolver(),
4958                     ConnectivitySettingsManager.CAPTIVE_PORTAL_MODE,
4959                     ConnectivitySettingsManager.CAPTIVE_PORTAL_MODE_PROMPT);
4960         }
4961 
4962         private boolean maybeHandleNetworkAgentInfoMessage(Message msg) {
4963             switch (msg.what) {
4964                 default:
4965                     return false;
4966                 case NetworkAgentInfo.EVENT_NETWORK_LINGER_COMPLETE: {
4967                     NetworkAgentInfo nai = (NetworkAgentInfo) msg.obj;
4968                     if (nai != null && isLiveNetworkAgent(nai, msg.what)) {
4969                         handleLingerComplete(nai);
4970                     }
4971                     break;
4972                 }
4973                 case NetworkAgentInfo.EVENT_AGENT_REGISTERED: {
4974                     handleNetworkAgentRegistered(msg);
4975                     break;
4976                 }
4977                 case NetworkAgentInfo.EVENT_AGENT_DISCONNECTED: {
4978                     handleNetworkAgentDisconnected(msg);
4979                     break;
4980                 }
4981             }
4982             return true;
4983         }
4984 
4985         @Override
4986         public void handleMessage(@NonNull Message msg) {
4987             if (!maybeHandleNetworkMonitorMessage(msg)
4988                     && !maybeHandleNetworkAgentInfoMessage(msg)) {
4989                 maybeHandleNetworkAgentMessage(msg);
4990             }
4991         }
4992     }
4993 
4994     private class NetworkMonitorCallbacks extends INetworkMonitorCallbacks.Stub {
4995         private final int mNetId;
4996         private final AutodestructReference<NetworkAgentInfo> mNai;
4997 
4998         private NetworkMonitorCallbacks(NetworkAgentInfo nai) {
4999             mNetId = nai.network.getNetId();
5000             mNai = new AutodestructReference<>(nai);
5001         }
5002 
5003         @Override
5004         public void onNetworkMonitorCreated(INetworkMonitor networkMonitor) {
5005             mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_AGENT,
5006                     new Pair<>(mNai.getAndDestroy(), networkMonitor)));
5007         }
5008 
5009         @Override
5010         public void notifyNetworkTested(int testResult, @Nullable String redirectUrl) {
5011             // Legacy version of notifyNetworkTestedWithExtras.
5012             // Would only be called if the system has a NetworkStack module older than the
5013             // framework, which does not happen in practice.
5014             Log.wtf(TAG, "Deprecated notifyNetworkTested called: no action taken");
5015         }
5016 
5017         @Override
5018         public void notifyNetworkTestedWithExtras(NetworkTestResultParcelable p) {
5019             // Notify mTrackerHandler and mConnectivityDiagnosticsHandler of the event. Both use
5020             // the same looper so messages will be processed in sequence.
5021             final Message msg = mTrackerHandler.obtainMessage(
5022                     EVENT_NETWORK_TESTED,
5023                     0, mNetId,
5024                     new NetworkTestedResults(
5025                             mNetId, p.result, p.timestampMillis, p.redirectUrl));
5026             mTrackerHandler.sendMessage(msg);
5027 
5028             // Invoke ConnectivityReport generation for this Network test event.
5029             final NetworkAgentInfo nai = getNetworkAgentInfoForNetId(mNetId);
5030             if (nai == null) return;
5031 
5032             // NetworkMonitor reports the network validation result as a bitmask while
5033             // ConnectivityDiagnostics treats this value as an int. Convert the result to a single
5034             // logical value for ConnectivityDiagnostics.
5035             final int validationResult = networkMonitorValidationResultToConnDiagsValidationResult(
5036                     p.result);
5037 
5038             final PersistableBundle extras = new PersistableBundle();
5039             extras.putInt(KEY_NETWORK_VALIDATION_RESULT, validationResult);
5040             extras.putInt(KEY_NETWORK_PROBES_SUCCEEDED_BITMASK, p.probesSucceeded);
5041             extras.putInt(KEY_NETWORK_PROBES_ATTEMPTED_BITMASK, p.probesAttempted);
5042 
5043             ConnectivityReportEvent reportEvent =
5044                     new ConnectivityReportEvent(p.timestampMillis, nai, extras);
5045             final Message m = mConnectivityDiagnosticsHandler.obtainMessage(
5046                     ConnectivityDiagnosticsHandler.CMD_SEND_CONNECTIVITY_REPORT, reportEvent);
5047             mConnectivityDiagnosticsHandler.sendMessage(m);
5048         }
5049 
5050         @Override
5051         public void notifyPrivateDnsConfigResolved(PrivateDnsConfigParcel config) {
5052             mTrackerHandler.sendMessage(mTrackerHandler.obtainMessage(
5053                     EVENT_PRIVATE_DNS_CONFIG_RESOLVED,
5054                     0, mNetId, PrivateDnsConfig.fromParcel(config)));
5055         }
5056 
5057         @Override
5058         public void notifyProbeStatusChanged(int probesCompleted, int probesSucceeded) {
5059             mTrackerHandler.sendMessage(mTrackerHandler.obtainMessage(
5060                     EVENT_PROBE_STATUS_CHANGED,
5061                     0, mNetId, new Pair<>(probesCompleted, probesSucceeded)));
5062         }
5063 
5064         @Override
5065         public void notifyCaptivePortalDataChanged(CaptivePortalData data) {
5066             mTrackerHandler.sendMessage(mTrackerHandler.obtainMessage(
5067                     EVENT_CAPPORT_DATA_CHANGED,
5068                     0, mNetId, data));
5069         }
5070 
5071         @Override
5072         public void showProvisioningNotification(String action, String packageName) {
5073             final Intent intent = new Intent(action);
5074             intent.setPackage(packageName);
5075 
5076             final PendingIntent pendingIntent;
5077             // Only the system server can register notifications with package "android"
5078             final long token = Binder.clearCallingIdentity();
5079             try {
5080                 pendingIntent = PendingIntent.getBroadcast(
5081                         mContext,
5082                         0 /* requestCode */,
5083                         intent,
5084                         PendingIntent.FLAG_IMMUTABLE);
5085             } finally {
5086                 Binder.restoreCallingIdentity(token);
5087             }
5088             mTrackerHandler.sendMessage(mTrackerHandler.obtainMessage(
5089                     EVENT_PROVISIONING_NOTIFICATION, PROVISIONING_NOTIFICATION_SHOW,
5090                     mNetId, pendingIntent));
5091         }
5092 
5093         @Override
5094         public void hideProvisioningNotification() {
5095             mTrackerHandler.sendMessage(mTrackerHandler.obtainMessage(
5096                     EVENT_PROVISIONING_NOTIFICATION, PROVISIONING_NOTIFICATION_HIDE, mNetId));
5097         }
5098 
5099         @Override
5100         public void notifyDataStallSuspected(DataStallReportParcelable p) {
5101             ConnectivityService.this.notifyDataStallSuspected(p, mNetId);
5102         }
5103 
5104         @Override
5105         public int getInterfaceVersion() {
5106             return this.VERSION;
5107         }
5108 
5109         @Override
5110         public String getInterfaceHash() {
5111             return this.HASH;
5112         }
5113     }
5114 
5115     /**
5116      * Converts the given NetworkMonitor-specific validation result bitmask to a
5117      * ConnectivityDiagnostics-specific validation result int.
5118      */
5119     private int networkMonitorValidationResultToConnDiagsValidationResult(int validationResult) {
5120         if ((validationResult & NETWORK_VALIDATION_RESULT_SKIPPED) != 0) {
5121             return ConnectivityReport.NETWORK_VALIDATION_RESULT_SKIPPED;
5122         }
5123         if ((validationResult & NETWORK_VALIDATION_RESULT_VALID) == 0) {
5124             return ConnectivityReport.NETWORK_VALIDATION_RESULT_INVALID;
5125         }
5126         return (validationResult & NETWORK_VALIDATION_RESULT_PARTIAL) != 0
5127                 ? ConnectivityReport.NETWORK_VALIDATION_RESULT_PARTIALLY_VALID
5128                 : ConnectivityReport.NETWORK_VALIDATION_RESULT_VALID;
5129     }
5130 
5131     private void notifyDataStallSuspected(DataStallReportParcelable p, int netId) {
5132         log("Data stall detected with methods: " + p.detectionMethod);
5133 
5134         final PersistableBundle extras = new PersistableBundle();
5135         int detectionMethod = 0;
5136         if (hasDataStallDetectionMethod(p, DETECTION_METHOD_DNS_EVENTS)) {
5137             extras.putInt(KEY_DNS_CONSECUTIVE_TIMEOUTS, p.dnsConsecutiveTimeouts);
5138             detectionMethod |= DETECTION_METHOD_DNS_EVENTS;
5139         }
5140         if (hasDataStallDetectionMethod(p, DETECTION_METHOD_TCP_METRICS)) {
5141             extras.putInt(KEY_TCP_PACKET_FAIL_RATE, p.tcpPacketFailRate);
5142             extras.putInt(KEY_TCP_METRICS_COLLECTION_PERIOD_MILLIS,
5143                     p.tcpMetricsCollectionPeriodMillis);
5144             detectionMethod |= DETECTION_METHOD_TCP_METRICS;
5145         }
5146 
5147         final Message msg = mConnectivityDiagnosticsHandler.obtainMessage(
5148                 ConnectivityDiagnosticsHandler.EVENT_DATA_STALL_SUSPECTED, detectionMethod, netId,
5149                 new Pair<>(p.timestampMillis, extras));
5150 
5151         // NetworkStateTrackerHandler currently doesn't take any actions based on data
5152         // stalls so send the message directly to ConnectivityDiagnosticsHandler and avoid
5153         // the cost of going through two handlers.
5154         mConnectivityDiagnosticsHandler.sendMessage(msg);
5155     }
5156 
5157     private boolean hasDataStallDetectionMethod(DataStallReportParcelable p, int detectionMethod) {
5158         return (p.detectionMethod & detectionMethod) != 0;
5159     }
5160 
5161     private boolean networkRequiresPrivateDnsValidation(NetworkAgentInfo nai) {
5162         return isPrivateDnsValidationRequired(nai.networkCapabilities);
5163     }
5164 
5165     private void handleFreshlyValidatedNetwork(NetworkAgentInfo nai) {
5166         if (nai == null) return;
5167         // If the Private DNS mode is opportunistic, reprogram the DNS servers
5168         // in order to restart a validation pass from within netd.
5169         final PrivateDnsConfig cfg = mDnsManager.getPrivateDnsConfig();
5170         if (cfg.inOpportunisticMode()) {
5171             updateDnses(nai.linkProperties, null, nai.network.getNetId());
5172         }
5173     }
5174 
5175     private void handlePrivateDnsSettingsChanged() {
5176         final PrivateDnsConfig cfg = mDnsManager.getPrivateDnsConfig();
5177 
5178         for (NetworkAgentInfo nai : mNetworkAgentInfos) {
5179             handlePerNetworkPrivateDnsConfig(nai, cfg);
5180             if (networkRequiresPrivateDnsValidation(nai)) {
5181                 handleUpdateLinkProperties(nai, new LinkProperties(nai.linkProperties));
5182             }
5183         }
5184     }
5185 
5186     private void handlePerNetworkPrivateDnsConfig(NetworkAgentInfo nai, PrivateDnsConfig cfg) {
5187         // Private DNS only ever applies to networks that might provide
5188         // Internet access and therefore also require validation.
5189         if (!networkRequiresPrivateDnsValidation(nai)) return;
5190 
5191         // Notify the NetworkAgentInfo/NetworkMonitor in case NetworkMonitor needs to cancel or
5192         // schedule DNS resolutions. If a DNS resolution is required the
5193         // result will be sent back to us.
5194         nai.networkMonitor().notifyPrivateDnsChanged(cfg.toParcel());
5195 
5196         // With Private DNS bypass support, we can proceed to update the
5197         // Private DNS config immediately, even if we're in strict mode
5198         // and have not yet resolved the provider name into a set of IPs.
5199         updatePrivateDns(nai, cfg);
5200     }
5201 
5202     private void updatePrivateDns(NetworkAgentInfo nai, PrivateDnsConfig newCfg) {
5203         mDnsManager.updatePrivateDns(nai.network, newCfg);
5204         updateDnses(nai.linkProperties, null, nai.network.getNetId());
5205     }
5206 
5207     private void handlePrivateDnsValidationUpdate(PrivateDnsValidationUpdate update) {
5208         NetworkAgentInfo nai = getNetworkAgentInfoForNetId(update.netId);
5209         if (nai == null) {
5210             return;
5211         }
5212         mDnsManager.updatePrivateDnsValidation(update);
5213         handleUpdateLinkProperties(nai, new LinkProperties(nai.linkProperties));
5214     }
5215 
5216     private void handleNat64PrefixEvent(int netId, int operation, String prefixAddress,
5217             int prefixLength) {
5218         NetworkAgentInfo nai = mNetworkForNetId.get(netId);
5219         if (nai == null) return;
5220 
5221         log(String.format("NAT64 prefix changed on netId %d: operation=%d, %s/%d",
5222                 netId, operation, prefixAddress, prefixLength));
5223 
5224         IpPrefix prefix = null;
5225         if (operation == IDnsResolverUnsolicitedEventListener.PREFIX_OPERATION_ADDED) {
5226             try {
5227                 prefix = new IpPrefix(InetAddresses.parseNumericAddress(prefixAddress),
5228                         prefixLength);
5229             } catch (IllegalArgumentException e) {
5230                 loge("Invalid NAT64 prefix " + prefixAddress + "/" + prefixLength);
5231                 return;
5232             }
5233         }
5234 
5235         nai.clatd.setNat64PrefixFromDns(prefix);
5236         handleUpdateLinkProperties(nai, new LinkProperties(nai.linkProperties));
5237     }
5238 
5239     private void handleCapportApiDataUpdate(@NonNull final NetworkAgentInfo nai,
5240             @Nullable final CaptivePortalData data) {
5241         nai.capportApiData = data;
5242         // CaptivePortalData will be merged into LinkProperties from NetworkAgentInfo
5243         handleUpdateLinkProperties(nai, new LinkProperties(nai.linkProperties));
5244     }
5245 
5246     /**
5247      * Updates the inactivity state from the network requests inside the NAI.
5248      * @param nai the agent info to update
5249      * @param now the timestamp of the event causing this update
5250      * @return whether the network was inactive as a result of this update
5251      */
5252     private boolean updateInactivityState(@NonNull final NetworkAgentInfo nai, final long now) {
5253         // 1. Update the inactivity timer. If it's changed, reschedule or cancel the alarm.
5254         // 2. If the network was inactive and there are now requests, unset inactive.
5255         // 3. If this network is unneeded (which implies it is not lingering), and there is at least
5256         //    one lingered request, set inactive.
5257         nai.updateInactivityTimer();
5258         if (nai.isInactive() && nai.numForegroundNetworkRequests() > 0) {
5259             if (DBG) log("Unsetting inactive " + nai.toShortString());
5260             nai.unsetInactive();
5261             logNetworkEvent(nai, NetworkEvent.NETWORK_UNLINGER);
5262         } else if (unneeded(nai, UnneededFor.LINGER) && nai.getInactivityExpiry() > 0) {
5263             if (DBG) {
5264                 final int lingerTime = (int) (nai.getInactivityExpiry() - now);
5265                 log("Setting inactive " + nai.toShortString() + " for " + lingerTime + "ms");
5266             }
5267             nai.setInactive();
5268             logNetworkEvent(nai, NetworkEvent.NETWORK_LINGER);
5269             return true;
5270         }
5271         return false;
5272     }
5273 
5274     private void handleNetworkAgentRegistered(Message msg) {
5275         final NetworkAgentInfo nai = (NetworkAgentInfo) msg.obj;
5276         if (!mNetworkAgentInfos.contains(nai)) {
5277             return;
5278         }
5279 
5280         if (msg.arg1 == NetworkAgentInfo.ARG_AGENT_SUCCESS) {
5281             if (VDBG) log("NetworkAgent registered");
5282         } else {
5283             loge("Error connecting NetworkAgent");
5284             mNetworkAgentInfos.remove(nai);
5285             if (nai != null) {
5286                 final boolean wasDefault = isDefaultNetwork(nai);
5287                 synchronized (mNetworkForNetId) {
5288                     mNetworkForNetId.remove(nai.network.getNetId());
5289                 }
5290                 mNetIdManager.releaseNetId(nai.network.getNetId());
5291                 // Just in case.
5292                 mLegacyTypeTracker.remove(nai, wasDefault);
5293             }
5294         }
5295     }
5296 
5297     @VisibleForTesting
5298     protected static boolean shouldCreateNetworksImmediately() {
5299         // The feature of creating the networks immediately was slated for U, but race conditions
5300         // detected late required this was flagged off.
5301         // TODO : enable this in a Mainline update or in V, and re-enable the test for this
5302         // in NetworkAgentTest.
5303         return false;
5304     }
5305 
5306     private static boolean shouldCreateNativeNetwork(@NonNull NetworkAgentInfo nai,
5307             @NonNull NetworkInfo.State state) {
5308         if (nai.isCreated()) return false;
5309         if (state == NetworkInfo.State.CONNECTED) return true;
5310         if (state != NetworkInfo.State.CONNECTING) {
5311             // TODO: throw if no WTFs are observed in the field.
5312             if (shouldCreateNetworksImmediately()) {
5313                 Log.wtf(TAG, "Uncreated network in invalid state: " + state);
5314             }
5315             return false;
5316         }
5317         return nai.isVPN() || shouldCreateNetworksImmediately();
5318     }
5319 
5320     private static boolean shouldDestroyNativeNetwork(@NonNull NetworkAgentInfo nai) {
5321         return nai.isCreated() && !nai.isDestroyed();
5322     }
5323 
5324     @VisibleForTesting
5325     boolean shouldIgnoreValidationFailureAfterRoam(NetworkAgentInfo nai) {
5326         // T+ devices should use unregisterAfterReplacement.
5327         if (mDeps.isAtLeastT()) return false;
5328 
5329         // If the network never roamed, return false. The check below is not sufficient if time
5330         // since boot is less than blockTimeOut, though that's extremely unlikely to happen.
5331         if (nai.lastRoamTime == 0) return false;
5332 
5333         final long blockTimeOut = Long.valueOf(mResources.get().getInteger(
5334                 R.integer.config_validationFailureAfterRoamIgnoreTimeMillis));
5335         if (blockTimeOut <= MAX_VALIDATION_IGNORE_AFTER_ROAM_TIME_MS
5336                 && blockTimeOut >= 0) {
5337             final long currentTimeMs = SystemClock.elapsedRealtime();
5338             long timeSinceLastRoam = currentTimeMs - nai.lastRoamTime;
5339             if (timeSinceLastRoam <= blockTimeOut) {
5340                 log ("blocked because only " + timeSinceLastRoam + "ms after roam");
5341                 return true;
5342             }
5343         }
5344         return false;
5345     }
5346 
5347     private void handleNetworkAgentDisconnected(Message msg) {
5348         NetworkAgentInfo nai = (NetworkAgentInfo) msg.obj;
5349         disconnectAndDestroyNetwork(nai);
5350     }
5351 
5352     // Destroys a network, remove references to it from the internal state managed by
5353     // ConnectivityService, free its interfaces and clean up.
5354     // Must be called on the Handler thread.
5355     private void disconnectAndDestroyNetwork(NetworkAgentInfo nai) {
5356         ensureRunningOnConnectivityServiceThread();
5357 
5358         if (!mNetworkAgentInfos.contains(nai)) return;
5359 
5360         if (DBG) {
5361             log(nai.toShortString() + " disconnected, was satisfying " + nai.numNetworkRequests());
5362         }
5363         // Clear all notifications of this network.
5364         mNotifier.clearNotification(nai.network.getNetId());
5365         // A network agent has disconnected.
5366         // TODO - if we move the logic to the network agent (have them disconnect
5367         // because they lost all their requests or because their score isn't good)
5368         // then they would disconnect organically, report their new state and then
5369         // disconnect the channel.
5370         if (nai.networkInfo.isConnected() || nai.networkInfo.isSuspended()) {
5371             nai.networkInfo.setDetailedState(NetworkInfo.DetailedState.DISCONNECTED,
5372                     null, null);
5373         }
5374         final boolean wasDefault = isDefaultNetwork(nai);
5375         if (wasDefault) {
5376             mDefaultInetConditionPublished = 0;
5377         }
5378         if (mTrackMultiNetworkActivities) {
5379             // If trackMultiNetworkActivities is disabled, ActivityTracker removes idleTimer when
5380             // the network becomes no longer the default network.
5381             mNetworkActivityTracker.removeDataActivityTracking(nai);
5382         }
5383         notifyIfacesChangedForNetworkStats();
5384         // If this was a local network forwarded to some upstream, or if some local network was
5385         // forwarded to this nai, then disable forwarding rules now.
5386         maybeDisableForwardRulesForDisconnectingNai(nai, true /* sendCallbacks */);
5387         // If this is a local network with an upstream selector, remove the associated network
5388         // request.
5389         if (nai.isLocalNetwork()) {
5390             final NetworkRequest selector = nai.localNetworkConfig.getUpstreamSelector();
5391             if (null != selector) {
5392                 handleRemoveNetworkRequest(mNetworkRequests.get(selector));
5393             }
5394         }
5395         // TODO - we shouldn't send CALLBACK_LOST to requests that can be satisfied
5396         // by other networks that are already connected. Perhaps that can be done by
5397         // sending all CALLBACK_LOST messages (for requests, not listens) at the end
5398         // of rematchAllNetworksAndRequests
5399         notifyNetworkCallbacks(nai, ConnectivityManager.CALLBACK_LOST);
5400         mKeepaliveTracker.handleStopAllKeepalives(nai, SocketKeepalive.ERROR_INVALID_NETWORK);
5401 
5402         mQosCallbackTracker.handleNetworkReleased(nai.network);
5403         for (String iface : nai.linkProperties.getAllInterfaceNames()) {
5404             // Disable wakeup packet monitoring for each interface.
5405             wakeupModifyInterface(iface, nai, false);
5406         }
5407         nai.networkMonitor().notifyNetworkDisconnected();
5408         mNetworkAgentInfos.remove(nai);
5409         nai.clatd.update();
5410         synchronized (mNetworkForNetId) {
5411             // Remove the NetworkAgent, but don't mark the netId as
5412             // available until we've told netd to delete it below.
5413             mNetworkForNetId.remove(nai.network.getNetId());
5414         }
5415         propagateUnderlyingNetworkCapabilities(nai.network);
5416         // Update allowed network lists in netd. This should be called after removing nai
5417         // from mNetworkAgentInfos.
5418         updateProfileAllowedNetworks();
5419         // Remove all previously satisfied requests.
5420         for (int i = 0; i < nai.numNetworkRequests(); i++) {
5421             final NetworkRequest request = nai.requestAt(i);
5422             final NetworkRequestInfo nri = mNetworkRequests.get(request);
5423             final NetworkAgentInfo currentNetwork = nri.getSatisfier();
5424             if (currentNetwork != null
5425                     && currentNetwork.network.getNetId() == nai.network.getNetId()) {
5426                 // uid rules for this network will be removed in destroyNativeNetwork(nai).
5427                 // TODO : setting the satisfier is in fact the job of the rematch. Teach the
5428                 // rematch not to keep disconnected agents instead of setting it here ; this
5429                 // will also allow removing updating the offers below.
5430                 nri.setSatisfier(null, null);
5431                 for (final NetworkOfferInfo noi : mNetworkOffers) {
5432                     informOffer(nri, noi.offer, mNetworkRanker);
5433                 }
5434 
5435                 if (mDefaultRequest == nri) {
5436                     mNetworkActivityTracker.updateDefaultNetwork(null /* newNetwork */, nai);
5437                     maybeDestroyPendingSockets(null /* newNetwork */, nai);
5438                     ensureNetworkTransitionWakelock(nai.toShortString());
5439                 }
5440             }
5441         }
5442         nai.clearInactivityState();
5443         // TODO: mLegacyTypeTracker.remove seems redundant given there's a full rematch right after.
5444         //  Currently, deleting it breaks tests that check for the default network disconnecting.
5445         //  Find out why, fix the rematch code, and delete this.
5446         mLegacyTypeTracker.remove(nai, wasDefault);
5447         rematchAllNetworksAndRequests();
5448         mLingerMonitor.noteDisconnect(nai);
5449 
5450         if (null == getDefaultNetwork() && nai.linkProperties.getHttpProxy() != null) {
5451             // The obvious place to do this would be in makeDefault(), however makeDefault() is
5452             // not called by the rematch in this case. This is because the code above unset
5453             // this network from the default request's satisfier, and that is what the rematch
5454             // is using as its source data to know what the old satisfier was. So as far as the
5455             // rematch above is concerned, the old default network was null.
5456             // Therefore if there is no new default, the default network was null and is still
5457             // null, thus there was no change so makeDefault() is not called. So if the old
5458             // network had a proxy and there is no new default, the proxy tracker should be told
5459             // that there is no longer a default proxy.
5460             // Strictly speaking this is not essential because having a proxy setting when
5461             // there is no network is harmless, but it's still counter-intuitive so reset to null.
5462             mProxyTracker.setDefaultProxy(null);
5463         }
5464 
5465         // Immediate teardown.
5466         if (nai.teardownDelayMs == 0) {
5467             destroyNetwork(nai);
5468             return;
5469         }
5470 
5471         // Delayed teardown.
5472         if (nai.isCreated()) {
5473             try {
5474                 mNetd.networkSetPermissionForNetwork(nai.network.netId, INetd.PERMISSION_SYSTEM);
5475             } catch (RemoteException e) {
5476                 Log.d(TAG, "Error marking network restricted during teardown: ", e);
5477             }
5478         }
5479         mHandler.postDelayed(() -> destroyNetwork(nai), nai.teardownDelayMs);
5480     }
5481 
5482     private void destroyNetwork(NetworkAgentInfo nai) {
5483         if (shouldDestroyNativeNetwork(nai)) {
5484             // Tell netd to clean up the configuration for this network
5485             // (routing rules, DNS, etc).
5486             // This may be slow as it requires a lot of netd shelling out to ip and
5487             // ip[6]tables to flush routes and remove the incoming packet mark rule, so do it
5488             // after we've rematched networks with requests (which might change the default
5489             // network or service a new request from an app), so network traffic isn't interrupted
5490             // for an unnecessarily long time.
5491             destroyNativeNetwork(nai);
5492         }
5493         if (!nai.isCreated() && !mDeps.isAtLeastT()) {
5494             // Backwards compatibility: send onNetworkDestroyed even if network was never created.
5495             // This can never run if the code above runs because shouldDestroyNativeNetwork is
5496             // false if the network was never created.
5497             // TODO: delete when S is no longer supported.
5498             nai.onNetworkDestroyed();
5499         }
5500         mNetIdManager.releaseNetId(nai.network.getNetId());
5501     }
5502 
5503     private void maybeDisableForwardRulesForDisconnectingNai(
5504             @NonNull final NetworkAgentInfo disconnecting, final boolean sendCallbacks) {
5505         // Step 1 : maybe this network was the upstream for one or more local networks.
5506         for (final NetworkAgentInfo local : mNetworkAgentInfos) {
5507             if (!local.isLocalNetwork()) continue;
5508             final NetworkRequest selector = local.localNetworkConfig.getUpstreamSelector();
5509             if (null == selector) continue;
5510             final NetworkRequestInfo nri = mNetworkRequests.get(selector);
5511             // null == nri can happen while disconnecting a network, because destroyNetwork() is
5512             // called after removing all associated NRIs from mNetworkRequests.
5513             if (null == nri) continue;
5514             final NetworkAgentInfo satisfier = nri.getSatisfier();
5515             if (disconnecting != satisfier) continue;
5516             removeLocalNetworkUpstream(local, disconnecting);
5517             // Set the satisfier to null immediately so that the LOCAL_NETWORK_CHANGED callback
5518             // correctly contains null as an upstream.
5519             if (sendCallbacks) {
5520                 nri.setSatisfier(null, null);
5521                 notifyNetworkCallbacks(local,
5522                         ConnectivityManager.CALLBACK_LOCAL_NETWORK_INFO_CHANGED);
5523             }
5524         }
5525 
5526         // Step 2 : maybe this is a local network that had an upstream.
5527         if (!disconnecting.isLocalNetwork()) return;
5528         final NetworkRequest selector = disconnecting.localNetworkConfig.getUpstreamSelector();
5529         if (null == selector) return;
5530         final NetworkRequestInfo nri = mNetworkRequests.get(selector);
5531         // As above null == nri can happen while disconnecting a network, because destroyNetwork()
5532         // is called after removing all associated NRIs from mNetworkRequests.
5533         if (null == nri) return;
5534         final NetworkAgentInfo satisfier = nri.getSatisfier();
5535         if (null == satisfier) return;
5536         removeLocalNetworkUpstream(disconnecting, satisfier);
5537     }
5538 
5539     private void removeLocalNetworkUpstream(@NonNull final NetworkAgentInfo localAgent,
5540             @NonNull final NetworkAgentInfo upstream) {
5541         try {
5542             final String localNetworkInterfaceName = localAgent.linkProperties.getInterfaceName();
5543             final String upstreamNetworkInterfaceName = upstream.linkProperties.getInterfaceName();
5544             mRoutingCoordinatorService.removeInterfaceForward(
5545                     localNetworkInterfaceName,
5546                     upstreamNetworkInterfaceName);
5547             disableMulticastRouting(localNetworkInterfaceName, upstreamNetworkInterfaceName);
5548         } catch (RemoteException e) {
5549             loge("Couldn't remove interface forward for "
5550                     + localAgent.linkProperties.getInterfaceName() + " to "
5551                     + upstream.linkProperties.getInterfaceName() + " while disconnecting");
5552         }
5553     }
5554 
5555     private boolean createNativeNetwork(@NonNull NetworkAgentInfo nai) {
5556         try {
5557             // This should never fail.  Specifying an already in use NetID will cause failure.
5558             final NativeNetworkConfig config;
5559             if (nai.isVPN()) {
5560                 if (getVpnType(nai) == VpnManager.TYPE_VPN_NONE) {
5561                     Log.wtf(TAG, "Unable to get VPN type from network " + nai.toShortString());
5562                     return false;
5563                 }
5564                 config = new NativeNetworkConfig(nai.network.getNetId(), NativeNetworkType.VIRTUAL,
5565                         INetd.PERMISSION_NONE,
5566                         !nai.networkAgentConfig.allowBypass /* secure */,
5567                         getVpnType(nai), nai.networkAgentConfig.excludeLocalRouteVpn);
5568             } else {
5569                 config = new NativeNetworkConfig(nai.network.getNetId(),
5570                         nai.isLocalNetwork() ? NativeNetworkType.PHYSICAL_LOCAL
5571                                 : NativeNetworkType.PHYSICAL,
5572                         getNetworkPermission(nai.networkCapabilities),
5573                         false /* secure */,
5574                         VpnManager.TYPE_VPN_NONE,
5575                         false /* excludeLocalRoutes */);
5576             }
5577             mNetd.networkCreate(config);
5578             mDnsResolver.createNetworkCache(nai.network.getNetId());
5579             mDnsManager.updateCapabilitiesForNetwork(nai.network.getNetId(),
5580                     nai.networkCapabilities);
5581             return true;
5582         } catch (RemoteException | ServiceSpecificException e) {
5583             loge("Error creating network " + nai.toShortString() + ": " + e.getMessage());
5584             return false;
5585         }
5586     }
5587 
5588     private void destroyNativeNetwork(@NonNull NetworkAgentInfo nai) {
5589         if (mDscpPolicyTracker != null) {
5590             mDscpPolicyTracker.removeAllDscpPolicies(nai, false);
5591         }
5592         // Remove any forwarding rules to and from the interface for this network, since
5593         // the interface is going to go away. Don't send the callbacks however ; if the network
5594         // was is being disconnected the callbacks have already been sent, and if it is being
5595         // destroyed pending replacement they will be sent when it is disconnected.
5596         maybeDisableForwardRulesForDisconnectingNai(nai, false /* sendCallbacks */);
5597         updateIngressToVpnAddressFiltering(null, nai.linkProperties, nai);
5598         try {
5599             mNetd.networkDestroy(nai.network.getNetId());
5600         } catch (RemoteException | ServiceSpecificException e) {
5601             loge("Exception destroying network(networkDestroy): " + e);
5602         }
5603         try {
5604             mDnsResolver.destroyNetworkCache(nai.network.getNetId());
5605         } catch (RemoteException | ServiceSpecificException e) {
5606             loge("Exception destroying network: " + e);
5607         }
5608         // TODO: defer calling this until the network is removed from mNetworkAgentInfos.
5609         // Otherwise, a private DNS configuration update for a destroyed network, or one that never
5610         // gets created, could add data to DnsManager data structures that will never get deleted.
5611         mDnsManager.removeNetwork(nai.network);
5612 
5613         // clean up tc police filters on interface.
5614         if (nai.everConnected() && canNetworkBeRateLimited(nai) && mIngressRateLimit >= 0) {
5615             mDeps.disableIngressRateLimit(nai.linkProperties.getInterfaceName());
5616         }
5617 
5618         nai.setDestroyed();
5619         nai.onNetworkDestroyed();
5620     }
5621 
5622     // If this method proves to be too slow then we can maintain a separate
5623     // pendingIntent => NetworkRequestInfo map.
5624     // This method assumes that every non-null PendingIntent maps to exactly 1 NetworkRequestInfo.
5625     private NetworkRequestInfo findExistingNetworkRequestInfo(PendingIntent pendingIntent) {
5626         for (Map.Entry<NetworkRequest, NetworkRequestInfo> entry : mNetworkRequests.entrySet()) {
5627             PendingIntent existingPendingIntent = entry.getValue().mPendingIntent;
5628             if (existingPendingIntent != null &&
5629                     mDeps.intentFilterEquals(existingPendingIntent, pendingIntent)) {
5630                 return entry.getValue();
5631             }
5632         }
5633         return null;
5634     }
5635 
5636     private void checkNrisConsistency(final NetworkRequestInfo nri) {
5637         if (mDeps.isAtLeastT()) {
5638             for (final NetworkRequestInfo n : mNetworkRequests.values()) {
5639                 if (n.mBinder != null && n.mBinder == nri.mBinder) {
5640                     // Temporary help to debug b/194394697 ; TODO : remove this function when the
5641                     // bug is fixed.
5642                     dumpAllRequestInfoLogsToLogcat();
5643                     throw new IllegalStateException("This NRI is already registered. New : " + nri
5644                             + ", existing : " + n);
5645                 }
5646             }
5647         }
5648     }
5649 
5650     private boolean hasCarrierPrivilegeForNetworkCaps(final int callingUid,
5651             @NonNull final NetworkCapabilities caps) {
5652         if (mCarrierPrivilegeAuthenticator != null) {
5653             return mCarrierPrivilegeAuthenticator.isCarrierServiceUidForNetworkCapabilities(
5654                     callingUid, caps);
5655         }
5656         return false;
5657     }
5658 
5659     private int getSubscriptionIdFromNetworkCaps(@NonNull final NetworkCapabilities caps) {
5660         if (mCarrierPrivilegeAuthenticator != null) {
5661             return mCarrierPrivilegeAuthenticator.getSubIdFromNetworkCapabilities(caps);
5662         }
5663         return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
5664     }
5665 
5666     private void handleRegisterNetworkRequestWithIntent(@NonNull final Message msg) {
5667         final NetworkRequestInfo nri = (NetworkRequestInfo) (msg.obj);
5668         // handleRegisterNetworkRequestWithIntent() doesn't apply to multilayer requests.
5669         ensureNotMultilayerRequest(nri, "handleRegisterNetworkRequestWithIntent");
5670         final NetworkRequestInfo existingRequest =
5671                 findExistingNetworkRequestInfo(nri.mPendingIntent);
5672         if (existingRequest != null) { // remove the existing request.
5673             if (DBG) {
5674                 log("Replacing " + existingRequest.mRequests.get(0) + " with "
5675                         + nri.mRequests.get(0) + " because their intents matched.");
5676             }
5677             handleReleaseNetworkRequest(existingRequest.mRequests.get(0), mDeps.getCallingUid(),
5678                     /* callOnUnavailable */ false);
5679         }
5680         handleRegisterNetworkRequest(nri);
5681     }
5682 
5683     private void handleRegisterNetworkRequest(@NonNull final NetworkRequestInfo nri) {
5684         handleRegisterNetworkRequests(Collections.singleton(nri));
5685     }
5686 
5687     private void handleRegisterNetworkRequests(@NonNull final Set<NetworkRequestInfo> nris) {
5688         ensureRunningOnConnectivityServiceThread();
5689         for (final NetworkRequestInfo nri : nris) {
5690             mNetworkRequestInfoLogs.log("REGISTER " + nri);
5691             checkNrisConsistency(nri);
5692             for (final NetworkRequest req : nri.mRequests) {
5693                 mNetworkRequests.put(req, nri);
5694                 // TODO: Consider update signal strength for other types.
5695                 if (req.isListen()) {
5696                     for (final NetworkAgentInfo network : mNetworkAgentInfos) {
5697                         if (req.networkCapabilities.hasSignalStrength()
5698                                 && network.satisfiesImmutableCapabilitiesOf(req)) {
5699                             updateSignalStrengthThresholds(network, "REGISTER", req);
5700                         }
5701                     }
5702                 } else if (req.isRequest() && mNetworkRequestStateStatsMetrics != null) {
5703                     mNetworkRequestStateStatsMetrics.onNetworkRequestReceived(req);
5704                 }
5705             }
5706 
5707             // If this NRI has a satisfier already, it is replacing an older request that
5708             // has been removed. Track it.
5709             final NetworkRequest activeRequest = nri.getActiveRequest();
5710             if (null != activeRequest) {
5711                 // If there is an active request, then for sure there is a satisfier.
5712                 nri.getSatisfier().addRequest(activeRequest);
5713             }
5714 
5715             if (shouldTrackUidsForBlockedStatusCallbacks()
5716                     && isAppRequest(nri)
5717                     && !nri.mUidTrackedForBlockedStatus) {
5718                 Log.wtf(TAG, "Registered nri is not tracked for sending blocked status: " + nri);
5719             }
5720         }
5721 
5722         if (mFlags.noRematchAllRequestsOnRegister()) {
5723             rematchNetworksAndRequests(nris);
5724         } else {
5725             rematchAllNetworksAndRequests();
5726         }
5727 
5728         // Requests that have not been matched to a network will not have been sent to the
5729         // providers, because the old satisfier and the new satisfier are the same (null in this
5730         // case). Send these requests to the providers.
5731         for (final NetworkRequestInfo nri : nris) {
5732             for (final NetworkOfferInfo noi : mNetworkOffers) {
5733                 informOffer(nri, noi.offer, mNetworkRanker);
5734             }
5735         }
5736     }
5737 
5738     private void handleReleaseNetworkRequestWithIntent(@NonNull final PendingIntent pendingIntent,
5739             final int callingUid) {
5740         final NetworkRequestInfo nri = findExistingNetworkRequestInfo(pendingIntent);
5741         if (nri != null) {
5742             // handleReleaseNetworkRequestWithIntent() paths don't apply to multilayer requests.
5743             ensureNotMultilayerRequest(nri, "handleReleaseNetworkRequestWithIntent");
5744             handleReleaseNetworkRequest(
5745                     nri.mRequests.get(0),
5746                     callingUid,
5747                     /* callOnUnavailable */ false);
5748         }
5749     }
5750 
5751     // Determines whether the network is the best (or could become the best, if it validated), for
5752     // none of a particular type of NetworkRequests. The type of NetworkRequests considered depends
5753     // on the value of reason:
5754     //
5755     // - UnneededFor.TEARDOWN: non-listen NetworkRequests. If a network is unneeded for this reason,
5756     //   then it should be torn down.
5757     // - UnneededFor.LINGER: foreground NetworkRequests. If a network is unneeded for this reason,
5758     //   then it should be lingered.
5759     private boolean unneeded(NetworkAgentInfo nai, UnneededFor reason) {
5760         ensureRunningOnConnectivityServiceThread();
5761 
5762         if (!nai.everConnected() || nai.isVPN() || nai.isInactive()
5763                 || nai.getScore().getKeepConnectedReason() != NetworkScore.KEEP_CONNECTED_NONE) {
5764             return false;
5765         }
5766 
5767         final int numRequests;
5768         switch (reason) {
5769             case TEARDOWN:
5770                 numRequests = nai.numRequestNetworkRequests();
5771                 break;
5772             case LINGER:
5773                 numRequests = nai.numForegroundNetworkRequests();
5774                 break;
5775             default:
5776                 Log.wtf(TAG, "Invalid reason. Cannot happen.");
5777                 return true;
5778         }
5779 
5780         if (numRequests > 0) return false;
5781 
5782         for (NetworkRequestInfo nri : mNetworkRequests.values()) {
5783             if (reason == UnneededFor.LINGER
5784                     && !nri.isMultilayerRequest()
5785                     && nri.mRequests.get(0).isBackgroundRequest()) {
5786                 // Background requests don't affect lingering.
5787                 continue;
5788             }
5789 
5790             if (isNetworkPotentialSatisfier(nai, nri)) {
5791                 return false;
5792             }
5793         }
5794         return true;
5795     }
5796 
5797     private boolean isNetworkPotentialSatisfier(
5798             @NonNull final NetworkAgentInfo candidate, @NonNull final NetworkRequestInfo nri) {
5799         // While destroyed network sometimes satisfy requests (including occasionally newly
5800         // satisfying requests), *potential* satisfiers are networks that might beat a current
5801         // champion if they validate. As such, a destroyed network is never a potential satisfier,
5802         // because it's never a good idea to keep a destroyed network in case it validates.
5803         // For example, declaring it a potential satisfier would keep an unvalidated destroyed
5804         // candidate after it's been replaced by another unvalidated network.
5805         if (candidate.isDestroyed()) return false;
5806         // Listen requests won't keep up a network satisfying it. If this is not a multilayer
5807         // request, return immediately. For multilayer requests, check to see if any of the
5808         // multilayer requests may have a potential satisfier.
5809         if (!nri.isMultilayerRequest() && (nri.mRequests.get(0).isListen()
5810                 || nri.mRequests.get(0).isListenForBest())) {
5811             return false;
5812         }
5813         for (final NetworkRequest req : nri.mRequests) {
5814             // This multilayer listen request is satisfied therefore no further requests need to be
5815             // evaluated deeming this network not a potential satisfier.
5816             if ((req.isListen() || req.isListenForBest()) && nri.getActiveRequest() == req) {
5817                 return false;
5818             }
5819             // As non-multilayer listen requests have already returned, the below would only happen
5820             // for a multilayer request therefore continue to the next request if available.
5821             if (req.isListen() || req.isListenForBest()) {
5822                 continue;
5823             }
5824             // If there is hope for this network might validate and subsequently become the best
5825             // network for that request, then it is needed. Note that this network can't already
5826             // be the best for this request, or it would be the current satisfier, and therefore
5827             // there would be no need to call this method to find out if it is a *potential*
5828             // satisfier ("unneeded", the only caller, only calls this if this network currently
5829             // satisfies no request).
5830             if (candidate.satisfies(req)) {
5831                 // As soon as a network is found that satisfies a request, return. Specifically for
5832                 // multilayer requests, returning as soon as a NetworkAgentInfo satisfies a request
5833                 // is important so as to not evaluate lower priority requests further in
5834                 // nri.mRequests.
5835                 final NetworkAgentInfo champion = req.equals(nri.getActiveRequest())
5836                         ? nri.getSatisfier() : null;
5837                 // Note that this catches two important cases:
5838                 // 1. Unvalidated cellular will not be reaped when unvalidated WiFi
5839                 //    is currently satisfying the request.  This is desirable when
5840                 //    cellular ends up validating but WiFi does not.
5841                 // 2. Unvalidated WiFi will not be reaped when validated cellular
5842                 //    is currently satisfying the request.  This is desirable when
5843                 //    WiFi ends up validating and out scoring cellular.
5844                 return mNetworkRanker.mightBeat(req, champion, candidate.getValidatedScoreable());
5845             }
5846         }
5847 
5848         return false;
5849     }
5850 
5851     private NetworkRequestInfo getNriForAppRequest(
5852             NetworkRequest request, int callingUid, String requestedOperation) {
5853         // Looking up the app passed param request in mRequests isn't possible since it may return
5854         // null for a request managed by a per-app default. Therefore use getNriForAppRequest() to
5855         // do the lookup since that will also find per-app default managed requests.
5856         // Additionally, this lookup needs to be relatively fast (hence the lookup optimization)
5857         // to avoid potential race conditions when validating a package->uid mapping when sending
5858         // the callback on the very low-chance that an application shuts down prior to the callback
5859         // being sent.
5860         final NetworkRequestInfo nri = mNetworkRequests.get(request) != null
5861                 ? mNetworkRequests.get(request) : getNriForAppRequest(request);
5862 
5863         if (nri != null) {
5864             if (Process.SYSTEM_UID != callingUid && nri.mUid != callingUid) {
5865                 log(String.format("UID %d attempted to %s for unowned request %s",
5866                         callingUid, requestedOperation, nri));
5867                 return null;
5868             }
5869         }
5870 
5871         return nri;
5872     }
5873 
5874     private void ensureNotMultilayerRequest(@NonNull final NetworkRequestInfo nri,
5875             final String callingMethod) {
5876         if (nri.isMultilayerRequest()) {
5877             throw new IllegalStateException(
5878                     callingMethod + " does not support multilayer requests.");
5879         }
5880     }
5881 
5882     private void handleTimedOutNetworkRequest(@NonNull final NetworkRequestInfo nri) {
5883         ensureRunningOnConnectivityServiceThread();
5884         // handleTimedOutNetworkRequest() is part of the requestNetwork() flow which works off of a
5885         // single NetworkRequest and thus does not apply to multilayer requests.
5886         ensureNotMultilayerRequest(nri, "handleTimedOutNetworkRequest");
5887         if (mNetworkRequests.get(nri.mRequests.get(0)) == null) {
5888             return;
5889         }
5890         if (nri.isBeingSatisfied()) {
5891             return;
5892         }
5893         if (VDBG || (DBG && nri.mRequests.get(0).isRequest())) {
5894             log("releasing " + nri.mRequests.get(0) + " (timeout)");
5895         }
5896         handleRemoveNetworkRequest(nri);
5897         callCallbackForRequest(
5898                 nri, null, ConnectivityManager.CALLBACK_UNAVAIL, 0);
5899     }
5900 
5901     private void handleReleaseNetworkRequest(@NonNull final NetworkRequest request,
5902             final int callingUid,
5903             final boolean callOnUnavailable) {
5904         final NetworkRequestInfo nri =
5905                 getNriForAppRequest(request, callingUid, "release NetworkRequest");
5906         if (nri == null) {
5907             return;
5908         }
5909         if (VDBG || (DBG && request.isRequest())) {
5910             log("releasing " + request + " (release request)");
5911         }
5912         handleRemoveNetworkRequest(nri);
5913         if (callOnUnavailable) {
5914             callCallbackForRequest(nri, null, ConnectivityManager.CALLBACK_UNAVAIL, 0);
5915         }
5916     }
5917 
5918     private void handleRemoveNetworkRequest(@NonNull final NetworkRequestInfo nri) {
5919         handleRemoveNetworkRequest(nri, true /* untrackUids */);
5920     }
5921 
5922     private void handleRemoveNetworkRequest(@NonNull final NetworkRequestInfo nri,
5923             final boolean untrackUids) {
5924         ensureRunningOnConnectivityServiceThread();
5925         for (final NetworkRequest req : nri.mRequests) {
5926             if (null == mNetworkRequests.remove(req)) {
5927                 logw("Attempted removal of untracked request " + req + " for nri " + nri);
5928                 continue;
5929             }
5930             if (req.isListen()) {
5931                 removeListenRequestFromNetworks(req);
5932             } else if (req.isRequest() && mNetworkRequestStateStatsMetrics != null) {
5933                 mNetworkRequestStateStatsMetrics.onNetworkRequestRemoved(req);
5934             }
5935         }
5936         nri.unlinkDeathRecipient();
5937         if (mDefaultNetworkRequests.remove(nri)) {
5938             // If this request was one of the defaults, then the UID rules need to be updated
5939             // WARNING : if the app(s) for which this network request is the default are doing
5940             // traffic, this will kill their connected sockets, even if an equivalent request
5941             // is going to be reinstated right away ; unconnected traffic will go on the default
5942             // until the new default is set, which will happen very soon.
5943             // TODO : The only way out of this is to diff old defaults and new defaults, and only
5944             // remove ranges for those requests that won't have a replacement
5945             final NetworkAgentInfo satisfier = nri.getSatisfier();
5946             if (null != satisfier) {
5947                 try {
5948                     mNetd.networkRemoveUidRangesParcel(new NativeUidRangeConfig(
5949                             satisfier.network.getNetId(),
5950                             toUidRangeStableParcels(nri.getUids()),
5951                             nri.getPreferenceOrderForNetd()));
5952                 } catch (RemoteException e) {
5953                     loge("Exception setting network preference default network", e);
5954                 }
5955             }
5956         }
5957 
5958         if (untrackUids) {
5959             maybeUntrackUidAndClearBlockedReasons(nri);
5960         }
5961         mNetworkRequestInfoLogs.log("RELEASE " + nri);
5962         checkNrisConsistency(nri);
5963 
5964         if (null != nri.getActiveRequest()) {
5965             if (!nri.getActiveRequest().isListen()) {
5966                 removeSatisfiedNetworkRequestFromNetwork(nri);
5967             }
5968         }
5969 
5970         // For all outstanding offers, cancel any of the layers of this NRI that used to be
5971         // needed for this offer.
5972         for (final NetworkOfferInfo noi : mNetworkOffers) {
5973             for (final NetworkRequest req : nri.mRequests) {
5974                 if (req.isRequest() && noi.offer.neededFor(req)) {
5975                     noi.offer.onNetworkUnneeded(req);
5976                 }
5977             }
5978         }
5979     }
5980 
5981     private void handleRemoveNetworkRequests(@NonNull final Set<NetworkRequestInfo> nris) {
5982         handleRemoveNetworkRequests(nris, true /* untrackUids */);
5983     }
5984 
5985     private void handleRemoveNetworkRequests(@NonNull final Set<NetworkRequestInfo> nris,
5986             final boolean untrackUids) {
5987         for (final NetworkRequestInfo nri : nris) {
5988             if (mDefaultRequest == nri) {
5989                 // Make sure we never remove the default request.
5990                 continue;
5991             }
5992             handleRemoveNetworkRequest(nri, untrackUids);
5993         }
5994     }
5995 
5996     private void removeListenRequestFromNetworks(@NonNull final NetworkRequest req) {
5997         // listens don't have a singular affected Network. Check all networks to see
5998         // if this listen request applies and remove it.
5999         for (final NetworkAgentInfo nai : mNetworkAgentInfos) {
6000             nai.removeRequest(req.requestId);
6001             if (req.networkCapabilities.hasSignalStrength()
6002                     && nai.satisfiesImmutableCapabilitiesOf(req)) {
6003                 updateSignalStrengthThresholds(nai, "RELEASE", req);
6004             }
6005         }
6006     }
6007 
6008     /**
6009      * Remove a NetworkRequestInfo's satisfied request from its 'satisfier' (NetworkAgentInfo) and
6010      * manage the necessary upkeep (linger, teardown networks, etc.) when doing so.
6011      * @param nri the NetworkRequestInfo to disassociate from its current NetworkAgentInfo
6012      */
6013     private void removeSatisfiedNetworkRequestFromNetwork(@NonNull final NetworkRequestInfo nri) {
6014         boolean wasKept = false;
6015         final NetworkAgentInfo nai = nri.getSatisfier();
6016         if (nai != null) {
6017             final int requestLegacyType = nri.getActiveRequest().legacyType;
6018             final boolean wasBackgroundNetwork = nai.isBackgroundNetwork();
6019             nai.removeRequest(nri.getActiveRequest().requestId);
6020             if (VDBG || DDBG) {
6021                 log(" Removing from current network " + nai.toShortString()
6022                         + ", leaving " + nai.numNetworkRequests() + " requests.");
6023             }
6024             // If there are still lingered requests on this network, don't tear it down,
6025             // but resume lingering instead.
6026             final long now = SystemClock.elapsedRealtime();
6027             if (updateInactivityState(nai, now)) {
6028                 notifyNetworkLosing(nai, now);
6029             }
6030             if (unneeded(nai, UnneededFor.TEARDOWN)) {
6031                 if (DBG) log("no live requests for " + nai.toShortString() + "; disconnecting");
6032                 teardownUnneededNetwork(nai);
6033             } else {
6034                 wasKept = true;
6035             }
6036             if (!wasBackgroundNetwork && nai.isBackgroundNetwork()) {
6037                 // Went from foreground to background.
6038                 updateCapabilitiesForNetwork(nai);
6039             }
6040 
6041             // Maintain the illusion.  When this request arrived, we might have pretended
6042             // that a network connected to serve it, even though the network was already
6043             // connected.  Now that this request has gone away, we might have to pretend
6044             // that the network disconnected.  LegacyTypeTracker will generate that
6045             // phantom disconnect for this type.
6046             if (requestLegacyType != TYPE_NONE) {
6047                 boolean doRemove = true;
6048                 if (wasKept) {
6049                     // check if any of the remaining requests for this network are for the
6050                     // same legacy type - if so, don't remove the nai
6051                     for (int i = 0; i < nai.numNetworkRequests(); i++) {
6052                         NetworkRequest otherRequest = nai.requestAt(i);
6053                         if (otherRequest.legacyType == requestLegacyType
6054                                 && otherRequest.isRequest()) {
6055                             if (DBG) log(" still have other legacy request - leaving");
6056                             doRemove = false;
6057                         }
6058                     }
6059                 }
6060 
6061                 if (doRemove) {
6062                     mLegacyTypeTracker.remove(requestLegacyType, nai, false);
6063                 }
6064             }
6065         }
6066     }
6067 
6068     private RequestInfoPerUidCounter getRequestCounter(NetworkRequestInfo nri) {
6069         return hasAnyPermissionOf(mContext,
6070                 nri.mPid, nri.mUid, NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK)
6071                 ? mSystemNetworkRequestCounter : mNetworkRequestCounter;
6072     }
6073 
6074     @Override
6075     public void setAcceptUnvalidated(Network network, boolean accept, boolean always) {
6076         enforceNetworkStackSettingsOrSetup();
6077         mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_ACCEPT_UNVALIDATED,
6078                 encodeBool(accept), encodeBool(always), network));
6079     }
6080 
6081     @Override
6082     public void setAcceptPartialConnectivity(Network network, boolean accept, boolean always) {
6083         enforceNetworkStackSettingsOrSetup();
6084         mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_ACCEPT_PARTIAL_CONNECTIVITY,
6085                 encodeBool(accept), encodeBool(always), network));
6086     }
6087 
6088     @Override
6089     public void setAvoidUnvalidated(Network network) {
6090         enforceNetworkStackSettingsOrSetup();
6091         mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_AVOID_UNVALIDATED, network));
6092     }
6093 
6094     @Override
6095     public void setTestAllowBadWifiUntil(long timeMs) {
6096         enforceSettingsPermission();
6097         if (!Build.isDebuggable()) {
6098             throw new IllegalStateException("Does not support in non-debuggable build");
6099         }
6100 
6101         if (timeMs > System.currentTimeMillis() + MAX_TEST_ALLOW_BAD_WIFI_UNTIL_MS) {
6102             throw new IllegalArgumentException("It should not exceed "
6103                     + MAX_TEST_ALLOW_BAD_WIFI_UNTIL_MS + "ms from now");
6104         }
6105 
6106         mHandler.sendMessage(
6107                 mHandler.obtainMessage(EVENT_SET_TEST_ALLOW_BAD_WIFI_UNTIL, timeMs));
6108     }
6109 
6110     @Override
6111     public void setTestLowTcpPollingTimerForKeepalive(long timeMs) {
6112         enforceSettingsPermission();
6113 
6114         if (timeMs > System.currentTimeMillis() + MAX_TEST_LOW_TCP_POLLING_UNTIL_MS) {
6115             throw new IllegalArgumentException("Argument should not exceed "
6116                     + MAX_TEST_LOW_TCP_POLLING_UNTIL_MS + "ms from now");
6117         }
6118 
6119         mHandler.sendMessage(
6120                 mHandler.obtainMessage(EVENT_SET_LOW_TCP_POLLING_UNTIL, timeMs));
6121     }
6122 
6123     private void handleSetAcceptUnvalidated(Network network, boolean accept, boolean always) {
6124         if (DBG) log("handleSetAcceptUnvalidated network=" + network +
6125                 " accept=" + accept + " always=" + always);
6126 
6127         NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
6128         if (nai == null) {
6129             // Nothing to do.
6130             return;
6131         }
6132 
6133         if (nai.everValidated()) {
6134             // The network validated while the dialog box was up. Take no action.
6135             return;
6136         }
6137 
6138         if (!nai.networkAgentConfig.explicitlySelected) {
6139             Log.wtf(TAG, "BUG: setAcceptUnvalidated non non-explicitly selected network");
6140         }
6141 
6142         if (accept != nai.networkAgentConfig.acceptUnvalidated) {
6143             nai.networkAgentConfig.acceptUnvalidated = accept;
6144             // If network becomes partial connectivity and user already accepted to use this
6145             // network, we should respect the user's option and don't need to popup the
6146             // PARTIAL_CONNECTIVITY notification to user again.
6147             nai.networkAgentConfig.acceptPartialConnectivity = accept;
6148             nai.updateScoreForNetworkAgentUpdate();
6149             rematchAllNetworksAndRequests();
6150         }
6151 
6152         if (always) {
6153             nai.onSaveAcceptUnvalidated(accept);
6154         }
6155 
6156         if (!accept) {
6157             // Tell the NetworkAgent to not automatically reconnect to the network.
6158             nai.onPreventAutomaticReconnect();
6159             // Teardown the network.
6160             teardownUnneededNetwork(nai);
6161         }
6162 
6163     }
6164 
6165     private void handleSetAcceptPartialConnectivity(Network network, boolean accept,
6166             boolean always) {
6167         if (DBG) {
6168             log("handleSetAcceptPartialConnectivity network=" + network + " accept=" + accept
6169                     + " always=" + always);
6170         }
6171 
6172         final NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
6173         if (nai == null) {
6174             // Nothing to do.
6175             return;
6176         }
6177 
6178         if (nai.isValidated()) {
6179             // The network validated while the dialog box was up. Take no action.
6180             return;
6181         }
6182 
6183         if (accept != nai.networkAgentConfig.acceptPartialConnectivity) {
6184             nai.networkAgentConfig.acceptPartialConnectivity = accept;
6185         }
6186 
6187         // TODO: Use the current design or save the user choice into IpMemoryStore.
6188         if (always) {
6189             nai.onSaveAcceptUnvalidated(accept);
6190         }
6191 
6192         if (!accept) {
6193             // Tell the NetworkAgent to not automatically reconnect to the network.
6194             nai.onPreventAutomaticReconnect();
6195             // Tear down the network.
6196             teardownUnneededNetwork(nai);
6197         } else {
6198             // Inform NetworkMonitor that partial connectivity is acceptable. This will likely
6199             // result in a partial connectivity result which will be processed by
6200             // maybeHandleNetworkMonitorMessage.
6201             //
6202             // TODO: NetworkMonitor does not refer to the "never ask again" bit. The bit is stored
6203             // per network. Therefore, NetworkMonitor may still do https probe.
6204             nai.networkMonitor().setAcceptPartialConnectivity();
6205         }
6206     }
6207 
6208     private void handleSetAvoidUnvalidated(Network network) {
6209         NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
6210         if (nai == null || nai.isValidated()) {
6211             // Nothing to do. The network either disconnected or revalidated.
6212             return;
6213         }
6214         if (0L == nai.getAvoidUnvalidated()) {
6215             nai.setAvoidUnvalidated();
6216             nai.updateScoreForNetworkAgentUpdate();
6217             rematchAllNetworksAndRequests();
6218         }
6219     }
6220 
6221     /** Schedule evaluation timeout */
6222     @VisibleForTesting
6223     public void scheduleEvaluationTimeout(@NonNull final Network network, final long delayMs) {
6224         mDeps.scheduleEvaluationTimeout(mHandler, network, delayMs);
6225     }
6226 
6227     @Override
6228     public void startCaptivePortalApp(Network network) {
6229         enforceNetworkStackOrSettingsPermission();
6230         mHandler.post(() -> {
6231             NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
6232             if (nai == null) return;
6233             if (!nai.networkCapabilities.hasCapability(NET_CAPABILITY_CAPTIVE_PORTAL)) return;
6234             nai.networkMonitor().launchCaptivePortalApp();
6235         });
6236     }
6237 
6238     /**
6239      * NetworkStack endpoint to start the captive portal app. The NetworkStack needs to use this
6240      * endpoint as it does not have INTERACT_ACROSS_USERS_FULL itself.
6241      * @param network Network on which the captive portal was detected.
6242      * @param appExtras Bundle to use as intent extras for the captive portal application.
6243      *                  Must be treated as opaque to avoid preventing the captive portal app to
6244      *                  update its arguments.
6245      */
6246     @Override
6247     public void startCaptivePortalAppInternal(Network network, Bundle appExtras) {
6248         mContext.enforceCallingOrSelfPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
6249                 "ConnectivityService");
6250 
6251         final Intent appIntent = new Intent(ConnectivityManager.ACTION_CAPTIVE_PORTAL_SIGN_IN);
6252         appIntent.putExtras(appExtras);
6253         appIntent.putExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL,
6254                 new CaptivePortal(new CaptivePortalImpl(network).asBinder()));
6255         appIntent.setFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT | Intent.FLAG_ACTIVITY_NEW_TASK);
6256 
6257         final long token = Binder.clearCallingIdentity();
6258         try {
6259             mContext.startActivityAsUser(appIntent, UserHandle.CURRENT);
6260         } finally {
6261             Binder.restoreCallingIdentity(token);
6262         }
6263     }
6264 
6265     private class CaptivePortalImpl extends ICaptivePortal.Stub {
6266         private final Network mNetwork;
6267 
6268         private CaptivePortalImpl(Network network) {
6269             mNetwork = network;
6270         }
6271 
6272         @Override
6273         public void appResponse(final int response) {
6274             if (response == CaptivePortal.APP_RETURN_WANTED_AS_IS) {
6275                 enforceSettingsPermission();
6276             } else if (response == CaptivePortal.APP_RETURN_UNWANTED) {
6277                 mHandler.sendMessage(mHandler.obtainMessage(EVENT_USER_DOES_NOT_WANT, mNetwork));
6278                 // Since the network will be disconnected, skip notifying NetworkMonitor
6279                 return;
6280             }
6281 
6282             final NetworkMonitorManager nm = getNetworkMonitorManager(mNetwork);
6283             if (nm == null) return;
6284             nm.notifyCaptivePortalAppFinished(response);
6285         }
6286 
6287         @Override
6288         public void appRequest(final int request) {
6289             final NetworkMonitorManager nm = getNetworkMonitorManager(mNetwork);
6290             if (nm == null) return;
6291 
6292             if (request == CaptivePortal.APP_REQUEST_REEVALUATION_REQUIRED) {
6293                 // This enforceNetworkStackPermission() should be adopted to check
6294                 // the required permission but this may be break OEM captive portal
6295                 // apps. Simply ignore the request if the caller does not have
6296                 // permission.
6297                 if (!hasNetworkStackPermission()) {
6298                     Log.e(TAG, "Calling appRequest() without proper permission. Skip");
6299                     return;
6300                 }
6301 
6302                 nm.forceReevaluation(mDeps.getCallingUid());
6303             }
6304         }
6305 
6306         @Nullable
6307         private NetworkMonitorManager getNetworkMonitorManager(final Network network) {
6308             // getNetworkAgentInfoForNetwork is thread-safe
6309             final NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
6310             if (nai == null) return null;
6311 
6312             // nai.networkMonitor() is thread-safe
6313             return nai.networkMonitor();
6314         }
6315     }
6316 
6317     public boolean avoidBadWifi() {
6318         return mMultinetworkPolicyTracker.getAvoidBadWifi();
6319     }
6320 
6321     private boolean activelyPreferBadWifi() {
6322         return mMultinetworkPolicyTracker.getActivelyPreferBadWifi();
6323     }
6324 
6325     /**
6326      * Return whether the device should maintain continuous, working connectivity by switching away
6327      * from WiFi networks having no connectivity.
6328      * @see MultinetworkPolicyTracker#getAvoidBadWifi()
6329      */
6330     public boolean shouldAvoidBadWifi() {
6331         if (!hasNetworkStackPermission()) {
6332             throw new SecurityException("avoidBadWifi requires NETWORK_STACK permission");
6333         }
6334         return avoidBadWifi();
6335     }
6336 
6337     private void updateAvoidBadWifi() {
6338         ensureRunningOnConnectivityServiceThread();
6339         // Agent info scores and offer scores depend on whether cells yields to bad wifi.
6340         final boolean avoidBadWifi = avoidBadWifi();
6341         for (final NetworkAgentInfo nai : mNetworkAgentInfos) {
6342             nai.updateScoreForNetworkAgentUpdate();
6343             if (avoidBadWifi) {
6344                 // If the device is now avoiding bad wifi, remove notifications that might have
6345                 // been put up when the device didn't.
6346                 mNotifier.clearNotification(nai.network.getNetId(), NotificationType.LOST_INTERNET);
6347             }
6348         }
6349         // UpdateOfferScore will update mNetworkOffers inline, so make a copy first.
6350         final ArrayList<NetworkOfferInfo> offersToUpdate = new ArrayList<>(mNetworkOffers);
6351         for (final NetworkOfferInfo noi : offersToUpdate) {
6352             updateOfferScore(noi.offer);
6353         }
6354         mNetworkRanker.setConfiguration(new NetworkRanker.Configuration(activelyPreferBadWifi()));
6355         rematchAllNetworksAndRequests();
6356     }
6357 
6358     // TODO: Evaluate whether this is of interest to other consumers of
6359     // MultinetworkPolicyTracker and worth moving out of here.
6360     private void dumpAvoidBadWifiSettings(IndentingPrintWriter pw) {
6361         final boolean configRestrict = mMultinetworkPolicyTracker.configRestrictsAvoidBadWifi();
6362         if (!configRestrict) {
6363             pw.println("Bad Wi-Fi avoidance: unrestricted");
6364             return;
6365         }
6366 
6367         pw.println("Bad Wi-Fi avoidance: " + avoidBadWifi());
6368         pw.increaseIndent();
6369         pw.println("Config restrict:               " + configRestrict);
6370         pw.println("Actively prefer bad wifi:      " + activelyPreferBadWifi());
6371 
6372         final String settingValue = mMultinetworkPolicyTracker.getAvoidBadWifiSetting();
6373         String description;
6374         // Can't use a switch statement because strings are legal case labels, but null is not.
6375         if ("0".equals(settingValue)) {
6376             description = "get stuck";
6377         } else if (settingValue == null) {
6378             description = "prompt";
6379         } else if ("1".equals(settingValue)) {
6380             description = "avoid";
6381         } else {
6382             description = settingValue + " (?)";
6383         }
6384         pw.println("Avoid bad wifi setting:        " + description);
6385 
6386         final Boolean configValue = BinderUtils.withCleanCallingIdentity(
6387                 () -> mMultinetworkPolicyTracker.deviceConfigActivelyPreferBadWifi());
6388         if (null == configValue) {
6389             description = "unset";
6390         } else if (configValue) {
6391             description = "force true";
6392         } else {
6393             description = "force false";
6394         }
6395         pw.println("Actively prefer bad wifi conf: " + description);
6396         pw.println();
6397         pw.println("Network overrides:");
6398         pw.increaseIndent();
6399         for (NetworkAgentInfo nai : networksSortedById()) {
6400             if (0L != nai.getAvoidUnvalidated()) {
6401                 pw.println(nai.toShortString());
6402             }
6403         }
6404         pw.decreaseIndent();
6405         pw.decreaseIndent();
6406     }
6407 
6408     // TODO: This method is copied from TetheringNotificationUpdater. Should have a utility class to
6409     // unify the method.
6410     private static @NonNull String getSettingsPackageName(@NonNull final PackageManager pm) {
6411         final Intent settingsIntent = new Intent(Settings.ACTION_SETTINGS);
6412         final ComponentName settingsComponent = settingsIntent.resolveActivity(pm);
6413         return settingsComponent != null
6414                 ? settingsComponent.getPackageName() : "com.android.settings";
6415     }
6416 
6417     private void showNetworkNotification(NetworkAgentInfo nai, NotificationType type) {
6418         final String action;
6419         final boolean highPriority;
6420         switch (type) {
6421             case NO_INTERNET:
6422                 action = ConnectivityManager.ACTION_PROMPT_UNVALIDATED;
6423                 // High priority because it is only displayed for explicitly selected networks.
6424                 highPriority = true;
6425                 break;
6426             case PRIVATE_DNS_BROKEN:
6427                 action = Settings.ACTION_WIRELESS_SETTINGS;
6428                 // High priority because we should let user know why there is no internet.
6429                 highPriority = true;
6430                 break;
6431             case LOST_INTERNET:
6432                 action = ConnectivityManager.ACTION_PROMPT_LOST_VALIDATION;
6433                 // High priority because it could help the user avoid unexpected data usage.
6434                 highPriority = true;
6435                 break;
6436             case PARTIAL_CONNECTIVITY:
6437                 action = ConnectivityManager.ACTION_PROMPT_PARTIAL_CONNECTIVITY;
6438                 // Don't bother the user with a high-priority notification if the network was not
6439                 // explicitly selected by the user.
6440                 highPriority = nai.networkAgentConfig.explicitlySelected;
6441                 break;
6442             default:
6443                 Log.wtf(TAG, "Unknown notification type " + type);
6444                 return;
6445         }
6446 
6447         Intent intent = new Intent(action);
6448         if (type != NotificationType.PRIVATE_DNS_BROKEN) {
6449             intent.putExtra(ConnectivityManager.EXTRA_NETWORK, nai.network);
6450             intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
6451             // Some OEMs have their own Settings package. Thus, need to get the current using
6452             // Settings package name instead of just use default name "com.android.settings".
6453             final String settingsPkgName = getSettingsPackageName(mContext.getPackageManager());
6454             intent.setClassName(settingsPkgName,
6455                     settingsPkgName + ".wifi.WifiNoInternetDialog");
6456         }
6457 
6458         PendingIntent pendingIntent = PendingIntent.getActivity(
6459                 mContext.createContextAsUser(UserHandle.CURRENT, 0 /* flags */),
6460                 0 /* requestCode */,
6461                 intent,
6462                 PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE);
6463 
6464         mNotifier.showNotification(
6465                 nai.network.getNetId(), type, nai, null, pendingIntent, highPriority);
6466     }
6467 
6468     private boolean shouldPromptUnvalidated(NetworkAgentInfo nai) {
6469         // Don't prompt if the network is validated, and don't prompt on captive portals
6470         // because we're already prompting the user to sign in.
6471         if (nai.everValidated() || nai.everCaptivePortalDetected()) {
6472             return false;
6473         }
6474 
6475         // If a network has partial connectivity, always prompt unless the user has already accepted
6476         // partial connectivity and selected don't ask again. This ensures that if the device
6477         // automatically connects to a network that has partial Internet access, the user will
6478         // always be able to use it, either because they've already chosen "don't ask again" or
6479         // because we have prompted them.
6480         if (nai.partialConnectivity() && !nai.networkAgentConfig.acceptPartialConnectivity) {
6481             return true;
6482         }
6483 
6484         // If a network has no Internet access, only prompt if the network was explicitly selected
6485         // and if the user has not already told us to use the network regardless of whether it
6486         // validated or not.
6487         if (nai.networkAgentConfig.explicitlySelected
6488                 && !nai.networkAgentConfig.acceptUnvalidated) {
6489             return true;
6490         }
6491 
6492         return false;
6493     }
6494 
6495     private void handleInitialEvaluationTimeout(@NonNull final Network network) {
6496         if (VDBG || DDBG) log("handleInitialEvaluationTimeout " + network);
6497 
6498         NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
6499         if (null == nai) return;
6500 
6501         if (nai.setEvaluated()) {
6502             // If setEvaluated() returned true, the network never had any form of connectivity.
6503             // This may have an impact on request matching if bad WiFi avoidance is off and the
6504             // network was found not to have Internet access.
6505             nai.updateScoreForNetworkAgentUpdate();
6506             rematchAllNetworksAndRequests();
6507 
6508             // Also, if this is WiFi and it should be preferred actively, now is the time to
6509             // prompt the user that they walked past and connected to a bad WiFi.
6510             if (nai.networkCapabilities.hasTransport(TRANSPORT_WIFI)
6511                     && !avoidBadWifi()
6512                     && activelyPreferBadWifi()) {
6513                 // The notification will be removed if the network validates or disconnects.
6514                 showNetworkNotification(nai, NotificationType.LOST_INTERNET);
6515                 return;
6516             }
6517         }
6518 
6519         if (!shouldPromptUnvalidated(nai)) return;
6520 
6521         // Stop automatically reconnecting to this network in the future. Automatically connecting
6522         // to a network that provides no or limited connectivity is not useful, because the user
6523         // cannot use that network except through the notification shown by this method, and the
6524         // notification is only shown if the network is explicitly selected by the user.
6525         nai.onPreventAutomaticReconnect();
6526 
6527         if (nai.partialConnectivity()) {
6528             showNetworkNotification(nai, NotificationType.PARTIAL_CONNECTIVITY);
6529         } else {
6530             showNetworkNotification(nai, NotificationType.NO_INTERNET);
6531         }
6532     }
6533 
6534     private void handleNetworkUnvalidated(NetworkAgentInfo nai) {
6535         NetworkCapabilities nc = nai.networkCapabilities;
6536         if (DBG) log("handleNetworkUnvalidated " + nai.toShortString() + " cap=" + nc);
6537 
6538         if (!nc.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
6539             return;
6540         }
6541 
6542         if (mMultinetworkPolicyTracker.shouldNotifyWifiUnvalidated()) {
6543             showNetworkNotification(nai, NotificationType.LOST_INTERNET);
6544         }
6545     }
6546 
6547     @Override
6548     public int getMultipathPreference(Network network) {
6549         enforceAccessPermission();
6550 
6551         NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
6552         if (nai != null && nai.networkCapabilities
6553                 .hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED)) {
6554             return ConnectivityManager.MULTIPATH_PREFERENCE_UNMETERED;
6555         }
6556 
6557         final NetworkPolicyManager netPolicyManager =
6558                  mContext.getSystemService(NetworkPolicyManager.class);
6559 
6560         final long token = Binder.clearCallingIdentity();
6561         final int networkPreference;
6562         try {
6563             networkPreference = netPolicyManager.getMultipathPreference(network);
6564         } finally {
6565             Binder.restoreCallingIdentity(token);
6566         }
6567         if (networkPreference != 0) {
6568             return networkPreference;
6569         }
6570         return mMultinetworkPolicyTracker.getMeteredMultipathPreference();
6571     }
6572 
6573     @Override
6574     public NetworkRequest getDefaultRequest() {
6575         return mDefaultRequest.mRequests.get(0);
6576     }
6577 
6578     private class InternalHandler extends Handler {
6579         public InternalHandler(Looper looper) {
6580             super(looper);
6581         }
6582 
6583         @Override
6584         public void handleMessage(Message msg) {
6585             switch (msg.what) {
6586                 case EVENT_EXPIRE_NET_TRANSITION_WAKELOCK:
6587                 case EVENT_CLEAR_NET_TRANSITION_WAKELOCK: {
6588                     handleReleaseNetworkTransitionWakelock(msg.what);
6589                     break;
6590                 }
6591                 case EVENT_APPLY_GLOBAL_HTTP_PROXY: {
6592                     mProxyTracker.loadDeprecatedGlobalHttpProxy();
6593                     break;
6594                 }
6595                 case EVENT_PAC_PROXY_HAS_CHANGED: {
6596                     final Pair<Network, ProxyInfo> arg = (Pair<Network, ProxyInfo>) msg.obj;
6597                     handlePacProxyServiceStarted(arg.first, arg.second);
6598                     break;
6599                 }
6600                 case EVENT_REGISTER_NETWORK_PROVIDER: {
6601                     handleRegisterNetworkProvider((NetworkProviderInfo) msg.obj);
6602                     break;
6603                 }
6604                 case EVENT_UNREGISTER_NETWORK_PROVIDER: {
6605                     handleUnregisterNetworkProvider((Messenger) msg.obj);
6606                     break;
6607                 }
6608                 case EVENT_REGISTER_NETWORK_OFFER: {
6609                     handleRegisterNetworkOffer((NetworkOffer) msg.obj);
6610                     break;
6611                 }
6612                 case EVENT_UNREGISTER_NETWORK_OFFER: {
6613                     final NetworkOfferInfo offer =
6614                             findNetworkOfferInfoByCallback((INetworkOfferCallback) msg.obj);
6615                     if (null != offer) {
6616                         handleUnregisterNetworkOffer(offer);
6617                     }
6618                     break;
6619                 }
6620                 case EVENT_REGISTER_NETWORK_AGENT: {
6621                     final Pair<NetworkAgentInfo, INetworkMonitor> arg =
6622                             (Pair<NetworkAgentInfo, INetworkMonitor>) msg.obj;
6623                     handleRegisterNetworkAgent(arg.first, arg.second);
6624                     break;
6625                 }
6626                 case EVENT_REGISTER_NETWORK_REQUEST:
6627                 case EVENT_REGISTER_NETWORK_LISTENER: {
6628                     handleRegisterNetworkRequest((NetworkRequestInfo) msg.obj);
6629                     break;
6630                 }
6631                 case EVENT_REGISTER_NETWORK_REQUEST_WITH_INTENT:
6632                 case EVENT_REGISTER_NETWORK_LISTENER_WITH_INTENT: {
6633                     handleRegisterNetworkRequestWithIntent(msg);
6634                     break;
6635                 }
6636                 case EVENT_TIMEOUT_NETWORK_REQUEST: {
6637                     NetworkRequestInfo nri = (NetworkRequestInfo) msg.obj;
6638                     handleTimedOutNetworkRequest(nri);
6639                     break;
6640                 }
6641                 case EVENT_RELEASE_NETWORK_REQUEST_WITH_INTENT: {
6642                     handleReleaseNetworkRequestWithIntent((PendingIntent) msg.obj, msg.arg1);
6643                     break;
6644                 }
6645                 case EVENT_RELEASE_NETWORK_REQUEST: {
6646                     handleReleaseNetworkRequest((NetworkRequest) msg.obj, msg.arg1,
6647                             /* callOnUnavailable */ false);
6648                     break;
6649                 }
6650                 case EVENT_SET_ACCEPT_UNVALIDATED: {
6651                     Network network = (Network) msg.obj;
6652                     handleSetAcceptUnvalidated(network, toBool(msg.arg1), toBool(msg.arg2));
6653                     break;
6654                 }
6655                 case EVENT_SET_ACCEPT_PARTIAL_CONNECTIVITY: {
6656                     Network network = (Network) msg.obj;
6657                     handleSetAcceptPartialConnectivity(network, toBool(msg.arg1),
6658                             toBool(msg.arg2));
6659                     break;
6660                 }
6661                 case EVENT_SET_AVOID_UNVALIDATED: {
6662                     handleSetAvoidUnvalidated((Network) msg.obj);
6663                     break;
6664                 }
6665                 case EVENT_INITIAL_EVALUATION_TIMEOUT: {
6666                     handleInitialEvaluationTimeout((Network) msg.obj);
6667                     break;
6668                 }
6669                 case EVENT_CONFIGURE_ALWAYS_ON_NETWORKS: {
6670                     handleConfigureAlwaysOnNetworks();
6671                     break;
6672                 }
6673                 // Sent by AutomaticOnOffKeepaliveTracker to process an app request on the
6674                 // handler thread.
6675                 case AutomaticOnOffKeepaliveTracker.CMD_REQUEST_START_KEEPALIVE: {
6676                     mKeepaliveTracker.handleStartKeepalive(msg);
6677                     break;
6678                 }
6679                 case AutomaticOnOffKeepaliveTracker.CMD_MONITOR_AUTOMATIC_KEEPALIVE: {
6680                     final AutomaticOnOffKeepalive ki =
6681                             mKeepaliveTracker.getKeepaliveForBinder((IBinder) msg.obj);
6682                     if (null == ki) return; // The callback was unregistered before the alarm fired
6683 
6684                     final Network underpinnedNetwork = ki.getUnderpinnedNetwork();
6685                     final Network network = ki.getNetwork();
6686                     boolean networkFound = false;
6687                     boolean underpinnedNetworkFound = false;
6688                     for (NetworkAgentInfo n : mNetworkAgentInfos) {
6689                         if (n.network.equals(network)) networkFound = true;
6690                         if (n.everConnected() && n.network.equals(underpinnedNetwork)) {
6691                             underpinnedNetworkFound = true;
6692                         }
6693                     }
6694 
6695                     // If the network no longer exists, then the keepalive should have been
6696                     // cleaned up already. There is no point trying to resume keepalives.
6697                     if (!networkFound) return;
6698 
6699                     if (underpinnedNetworkFound) {
6700                         mKeepaliveTracker.handleMonitorAutomaticKeepalive(ki,
6701                                 underpinnedNetwork.netId);
6702                     } else {
6703                         // If no underpinned network, then make sure the keepalive is running.
6704                         mKeepaliveTracker.handleMaybeResumeKeepalive(ki);
6705                     }
6706                     break;
6707                 }
6708                 // Sent by KeepaliveTracker to process an app request on the state machine thread.
6709                 case NetworkAgent.CMD_STOP_SOCKET_KEEPALIVE: {
6710                     final AutomaticOnOffKeepalive ki = mKeepaliveTracker.getKeepaliveForBinder(
6711                             (IBinder) msg.obj);
6712                     if (ki == null) {
6713                         Log.e(TAG, "Attempt to stop an already stopped keepalive");
6714                         return;
6715                     }
6716                     final int reason = msg.arg2;
6717                     mKeepaliveTracker.handleStopKeepalive(ki, reason);
6718                     break;
6719                 }
6720                 case EVENT_REPORT_NETWORK_CONNECTIVITY: {
6721                     handleReportNetworkConnectivity((NetworkAgentInfo) msg.obj, msg.arg1,
6722                             toBool(msg.arg2));
6723                     break;
6724                 }
6725                 case EVENT_PRIVATE_DNS_SETTINGS_CHANGED:
6726                     handlePrivateDnsSettingsChanged();
6727                     break;
6728                 case EVENT_PRIVATE_DNS_VALIDATION_UPDATE:
6729                     handlePrivateDnsValidationUpdate(
6730                             (PrivateDnsValidationUpdate) msg.obj);
6731                     break;
6732                 case EVENT_BLOCKED_REASONS_CHANGED:
6733                     handleBlockedReasonsChanged((List) msg.obj);
6734                     break;
6735                 case EVENT_SET_REQUIRE_VPN_FOR_UIDS:
6736                     handleSetRequireVpnForUids(toBool(msg.arg1), (UidRange[]) msg.obj);
6737                     break;
6738                 case EVENT_SET_OEM_NETWORK_PREFERENCE: {
6739                     final Pair<OemNetworkPreferences, IOnCompleteListener> arg =
6740                             (Pair<OemNetworkPreferences, IOnCompleteListener>) msg.obj;
6741                     handleSetOemNetworkPreference(arg.first, arg.second);
6742                     break;
6743                 }
6744                 case EVENT_SET_PROFILE_NETWORK_PREFERENCE: {
6745                     final Pair<List<ProfileNetworkPreferenceInfo>, IOnCompleteListener> arg =
6746                             (Pair<List<ProfileNetworkPreferenceInfo>, IOnCompleteListener>) msg.obj;
6747                     handleSetProfileNetworkPreference(arg.first, arg.second);
6748                     break;
6749                 }
6750                 case EVENT_REPORT_NETWORK_ACTIVITY:
6751                     final NetworkActivityParams arg = (NetworkActivityParams) msg.obj;
6752                     handleReportNetworkActivity(arg);
6753                     break;
6754                 case EVENT_MOBILE_DATA_PREFERRED_UIDS_CHANGED:
6755                     handleMobileDataPreferredUidsChanged();
6756                     break;
6757                 case EVENT_SET_TEST_ALLOW_BAD_WIFI_UNTIL:
6758                     final long timeMs = ((Long) msg.obj).longValue();
6759                     mMultinetworkPolicyTracker.setTestAllowBadWifiUntil(timeMs);
6760                     break;
6761                 case EVENT_INGRESS_RATE_LIMIT_CHANGED:
6762                     handleIngressRateLimitChanged();
6763                     break;
6764                 case EVENT_USER_DOES_NOT_WANT:
6765                     final NetworkAgentInfo nai = getNetworkAgentInfoForNetwork((Network) msg.obj);
6766                     if (nai == null) break;
6767                     nai.onPreventAutomaticReconnect();
6768                     nai.disconnect();
6769                     break;
6770                 case EVENT_SET_VPN_NETWORK_PREFERENCE:
6771                     handleSetVpnNetworkPreference((VpnNetworkPreferenceInfo) msg.obj);
6772                     break;
6773                 case EVENT_SET_LOW_TCP_POLLING_UNTIL: {
6774                     final long time = ((Long) msg.obj).longValue();
6775                     mKeepaliveTracker.handleSetTestLowTcpPollingTimer(time);
6776                     break;
6777                 }
6778                 case EVENT_UID_FROZEN_STATE_CHANGED:
6779                     UidFrozenStateChangedArgs args = (UidFrozenStateChangedArgs) msg.obj;
6780                     handleFrozenUids(args.mUids, args.mFrozenStates);
6781                     break;
6782                 case EVENT_UPDATE_FIREWALL_DESTROY_SOCKET_REASONS:
6783                     handleUpdateFirewallDestroySocketReasons((List) msg.obj);
6784                     break;
6785                 case EVENT_CLEAR_FIREWALL_DESTROY_SOCKET_REASONS:
6786                     handleClearFirewallDestroySocketReasons(msg.arg1);
6787                     break;
6788             }
6789         }
6790     }
6791 
6792     @Override
6793     @Deprecated
6794     public int getLastTetherError(String iface) {
6795         enforceAccessPermission();
6796         final TetheringManager tm = (TetheringManager) mContext.getSystemService(
6797                 Context.TETHERING_SERVICE);
6798         return tm.getLastTetherError(iface);
6799     }
6800 
6801     @Override
6802     @Deprecated
6803     public String[] getTetherableIfaces() {
6804         enforceAccessPermission();
6805         final TetheringManager tm = (TetheringManager) mContext.getSystemService(
6806                 Context.TETHERING_SERVICE);
6807         return tm.getTetherableIfaces();
6808     }
6809 
6810     @Override
6811     @Deprecated
6812     public String[] getTetheredIfaces() {
6813         enforceAccessPermission();
6814         final TetheringManager tm = (TetheringManager) mContext.getSystemService(
6815                 Context.TETHERING_SERVICE);
6816         return tm.getTetheredIfaces();
6817     }
6818 
6819 
6820     @Override
6821     @Deprecated
6822     public String[] getTetheringErroredIfaces() {
6823         enforceAccessPermission();
6824         final TetheringManager tm = (TetheringManager) mContext.getSystemService(
6825                 Context.TETHERING_SERVICE);
6826 
6827         return tm.getTetheringErroredIfaces();
6828     }
6829 
6830     @Override
6831     @Deprecated
6832     public String[] getTetherableUsbRegexs() {
6833         enforceAccessPermission();
6834         final TetheringManager tm = (TetheringManager) mContext.getSystemService(
6835                 Context.TETHERING_SERVICE);
6836 
6837         return tm.getTetherableUsbRegexs();
6838     }
6839 
6840     @Override
6841     @Deprecated
6842     public String[] getTetherableWifiRegexs() {
6843         enforceAccessPermission();
6844         final TetheringManager tm = (TetheringManager) mContext.getSystemService(
6845                 Context.TETHERING_SERVICE);
6846         return tm.getTetherableWifiRegexs();
6847     }
6848 
6849     // Called when we lose the default network and have no replacement yet.
6850     // This will automatically be cleared after X seconds or a new default network
6851     // becomes CONNECTED, whichever happens first.  The timer is started by the
6852     // first caller and not restarted by subsequent callers.
6853     private void ensureNetworkTransitionWakelock(String forWhom) {
6854         synchronized (this) {
6855             if (mNetTransitionWakeLock.isHeld()) {
6856                 return;
6857             }
6858             mNetTransitionWakeLock.acquire();
6859             mLastWakeLockAcquireTimestamp = SystemClock.elapsedRealtime();
6860             mTotalWakelockAcquisitions++;
6861         }
6862         mWakelockLogs.log("ACQUIRE for " + forWhom);
6863         Message msg = mHandler.obtainMessage(EVENT_EXPIRE_NET_TRANSITION_WAKELOCK);
6864         final int lockTimeout = mResources.get().getInteger(
6865                 R.integer.config_networkTransitionTimeout);
6866         mHandler.sendMessageDelayed(msg, lockTimeout);
6867     }
6868 
6869     // Called when we gain a new default network to release the network transition wakelock in a
6870     // second, to allow a grace period for apps to reconnect over the new network. Pending expiry
6871     // message is cancelled.
6872     private void scheduleReleaseNetworkTransitionWakelock() {
6873         synchronized (this) {
6874             if (!mNetTransitionWakeLock.isHeld()) {
6875                 return; // expiry message released the lock first.
6876             }
6877         }
6878         // Cancel self timeout on wakelock hold.
6879         mHandler.removeMessages(EVENT_EXPIRE_NET_TRANSITION_WAKELOCK);
6880         Message msg = mHandler.obtainMessage(EVENT_CLEAR_NET_TRANSITION_WAKELOCK);
6881         mHandler.sendMessageDelayed(msg, 1000);
6882     }
6883 
6884     // Called when either message of ensureNetworkTransitionWakelock or
6885     // scheduleReleaseNetworkTransitionWakelock is processed.
6886     private void handleReleaseNetworkTransitionWakelock(int eventId) {
6887         String event = eventName(eventId);
6888         synchronized (this) {
6889             if (!mNetTransitionWakeLock.isHeld()) {
6890                 mWakelockLogs.log(String.format("RELEASE: already released (%s)", event));
6891                 Log.w(TAG, "expected Net Transition WakeLock to be held");
6892                 return;
6893             }
6894             mNetTransitionWakeLock.release();
6895             long lockDuration = SystemClock.elapsedRealtime() - mLastWakeLockAcquireTimestamp;
6896             mTotalWakelockDurationMs += lockDuration;
6897             mMaxWakelockDurationMs = Math.max(mMaxWakelockDurationMs, lockDuration);
6898             mTotalWakelockReleases++;
6899         }
6900         mWakelockLogs.log(String.format("RELEASE (%s)", event));
6901     }
6902 
6903     // 100 percent is full good, 0 is full bad.
6904     @Override
6905     public void reportInetCondition(int networkType, int percentage) {
6906         NetworkAgentInfo nai = mLegacyTypeTracker.getNetworkForType(networkType);
6907         if (nai == null) return;
6908         reportNetworkConnectivity(nai.network, percentage > 50);
6909     }
6910 
6911     @Override
6912     public void reportNetworkConnectivity(Network network, boolean hasConnectivity) {
6913         enforceAccessPermission();
6914         enforceInternetPermission();
6915         final int uid = mDeps.getCallingUid();
6916         final int connectivityInfo = encodeBool(hasConnectivity);
6917 
6918         final NetworkAgentInfo nai;
6919         if (network == null) {
6920             nai = getDefaultNetwork();
6921         } else {
6922             nai = getNetworkAgentInfoForNetwork(network);
6923         }
6924 
6925         mHandler.sendMessage(
6926                 mHandler.obtainMessage(
6927                         EVENT_REPORT_NETWORK_CONNECTIVITY, uid, connectivityInfo, nai));
6928     }
6929 
6930     private void handleReportNetworkConnectivity(
6931             @Nullable NetworkAgentInfo nai, int uid, boolean hasConnectivity) {
6932         if (nai == null
6933                 || nai != getNetworkAgentInfoForNetwork(nai.network)
6934                 || nai.networkInfo.getState() == NetworkInfo.State.DISCONNECTED) {
6935             return;
6936         }
6937         // Revalidate if the app report does not match our current validated state.
6938         if (hasConnectivity == nai.isValidated()) {
6939             mConnectivityDiagnosticsHandler.sendMessage(
6940                     mConnectivityDiagnosticsHandler.obtainMessage(
6941                             ConnectivityDiagnosticsHandler.EVENT_NETWORK_CONNECTIVITY_REPORTED,
6942                             new ReportedNetworkConnectivityInfo(
6943                                     hasConnectivity, false /* isNetworkRevalidating */, uid, nai)));
6944             return;
6945         }
6946         if (DBG) {
6947             int netid = nai.network.getNetId();
6948             log("reportNetworkConnectivity(" + netid + ", " + hasConnectivity + ") by " + uid);
6949         }
6950         // Validating a network that has not yet connected could result in a call to
6951         // rematchNetworkAndRequests() which is not meant to work on such networks.
6952         if (!nai.everConnected()) {
6953             return;
6954         }
6955         final NetworkCapabilities nc = getNetworkCapabilitiesInternal(nai);
6956         if (isNetworkWithCapabilitiesBlocked(nc, uid, false)) {
6957             return;
6958         }
6959 
6960         // Send CONNECTIVITY_REPORTED event before re-validating the Network to force an ordering of
6961         // ConnDiags events. This ensures that #onNetworkConnectivityReported() will be called
6962         // before #onConnectivityReportAvailable(), which is called once Network evaluation is
6963         // completed.
6964         mConnectivityDiagnosticsHandler.sendMessage(
6965                 mConnectivityDiagnosticsHandler.obtainMessage(
6966                         ConnectivityDiagnosticsHandler.EVENT_NETWORK_CONNECTIVITY_REPORTED,
6967                         new ReportedNetworkConnectivityInfo(
6968                                 hasConnectivity, true /* isNetworkRevalidating */, uid, nai)));
6969         nai.networkMonitor().forceReevaluation(uid);
6970     }
6971 
6972     // TODO: call into netd.
6973     private boolean queryUserAccess(int uid, Network network) {
6974         final NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
6975         if (nai == null) return false;
6976 
6977         // Any UID can use its default network.
6978         if (nai == getDefaultNetworkForUid(uid)) return true;
6979 
6980         // Privileged apps can use any network.
6981         if (mPermissionMonitor.hasRestrictedNetworksPermission(uid)) {
6982             return true;
6983         }
6984 
6985         // An unprivileged UID can use a VPN iff the VPN applies to it.
6986         if (nai.isVPN()) {
6987             return nai.networkCapabilities.appliesToUid(uid);
6988         }
6989 
6990         // An unprivileged UID can bypass the VPN that applies to it only if it can protect its
6991         // sockets, i.e., if it is the owner.
6992         final NetworkAgentInfo vpn = getVpnForUid(uid);
6993         if (vpn != null && !vpn.networkAgentConfig.allowBypass
6994                 && uid != vpn.networkCapabilities.getOwnerUid()) {
6995             return false;
6996         }
6997 
6998         // The UID's permission must be at least sufficient for the network. Since the restricted
6999         // permission was already checked above, that just leaves background networks.
7000         if (!nai.networkCapabilities.hasCapability(NET_CAPABILITY_FOREGROUND)) {
7001             return mPermissionMonitor.hasUseBackgroundNetworksPermission(uid);
7002         }
7003 
7004         // Unrestricted network. Anyone gets to use it.
7005         return true;
7006     }
7007 
7008     /**
7009      * Returns information about the proxy a certain network is using. If given a null network, it
7010      * it will return the proxy for the bound network for the caller app or the default proxy if
7011      * none.
7012      *
7013      * @param network the network we want to get the proxy information for.
7014      * @return Proxy information if a network has a proxy configured, or otherwise null.
7015      */
7016     @Override
7017     public ProxyInfo getProxyForNetwork(Network network) {
7018         final ProxyInfo globalProxy = mProxyTracker.getGlobalProxy();
7019         if (globalProxy != null) return globalProxy;
7020         if (network == null) {
7021             // Get the network associated with the calling UID.
7022             final Network activeNetwork = getActiveNetworkForUidInternal(mDeps.getCallingUid(),
7023                     true);
7024             if (activeNetwork == null) {
7025                 return null;
7026             }
7027             return getLinkPropertiesProxyInfo(activeNetwork);
7028         } else if (mDeps.queryUserAccess(mDeps.getCallingUid(), network, this)) {
7029             // Don't call getLinkProperties() as it requires ACCESS_NETWORK_STATE permission, which
7030             // caller may not have.
7031             return getLinkPropertiesProxyInfo(network);
7032         }
7033         // No proxy info available if the calling UID does not have network access.
7034         return null;
7035     }
7036 
7037 
7038     private ProxyInfo getLinkPropertiesProxyInfo(Network network) {
7039         final NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
7040         if (nai == null) return null;
7041         synchronized (nai) {
7042             final ProxyInfo linkHttpProxy = nai.linkProperties.getHttpProxy();
7043             return linkHttpProxy == null ? null : new ProxyInfo(linkHttpProxy);
7044         }
7045     }
7046 
7047     @Override
7048     public void setGlobalProxy(@Nullable final ProxyInfo proxyProperties) {
7049         enforceNetworkStackPermission(mContext);
7050         mProxyTracker.setGlobalProxy(proxyProperties);
7051     }
7052 
7053     @Override
7054     @Nullable
7055     public ProxyInfo getGlobalProxy() {
7056         return mProxyTracker.getGlobalProxy();
7057     }
7058 
7059     private void handlePacProxyServiceStarted(@Nullable Network net, @Nullable ProxyInfo proxy) {
7060         mProxyTracker.setDefaultProxy(proxy);
7061         final NetworkAgentInfo nai = getDefaultNetwork();
7062         // TODO : this method should check that net == nai.network, unfortunately at this point
7063         // 'net' is always null in practice (see PacProxyService#sendPacBroadcast). PAC proxy
7064         // is only ever installed on the default network so in practice this is okay.
7065         if (null == nai) return;
7066         // PAC proxies only work on the default network. Therefore, only the default network
7067         // should have its link properties fixed up for PAC proxies.
7068         mProxyTracker.updateDefaultNetworkProxyPortForPAC(nai.linkProperties, nai.network);
7069         if (nai.everConnected()) {
7070             notifyNetworkCallbacks(nai, ConnectivityManager.CALLBACK_IP_CHANGED);
7071         }
7072     }
7073 
7074     // If the proxy has changed from oldLp to newLp, resend proxy broadcast. This method gets called
7075     // when any network changes proxy.
7076     // TODO: Remove usage of broadcast extras as they are deprecated and not applicable in a
7077     // multi-network world where an app might be bound to a non-default network.
7078     private void updateProxy(@NonNull LinkProperties newLp, @Nullable LinkProperties oldLp) {
7079         ProxyInfo newProxyInfo = newLp.getHttpProxy();
7080         ProxyInfo oldProxyInfo = oldLp == null ? null : oldLp.getHttpProxy();
7081 
7082         if (!ProxyTracker.proxyInfoEqual(newProxyInfo, oldProxyInfo)) {
7083             mProxyTracker.sendProxyBroadcast();
7084         }
7085     }
7086 
7087     private static class SettingsObserver extends ContentObserver {
7088         final private HashMap<Uri, Integer> mUriEventMap;
7089         final private Context mContext;
7090         final private Handler mHandler;
7091 
7092         SettingsObserver(Context context, Handler handler) {
7093             super(null);
7094             mUriEventMap = new HashMap<>();
7095             mContext = context;
7096             mHandler = handler;
7097         }
7098 
7099         void observe(Uri uri, int what) {
7100             mUriEventMap.put(uri, what);
7101             final ContentResolver resolver = mContext.getContentResolver();
7102             resolver.registerContentObserver(uri, false, this);
7103         }
7104 
7105         @Override
7106         public void onChange(boolean selfChange) {
7107             Log.wtf(TAG, "Should never be reached.");
7108         }
7109 
7110         @Override
7111         public void onChange(boolean selfChange, Uri uri) {
7112             final Integer what = mUriEventMap.get(uri);
7113             if (what != null) {
7114                 mHandler.obtainMessage(what).sendToTarget();
7115             } else {
7116                 loge("No matching event to send for URI=" + uri);
7117             }
7118         }
7119     }
7120 
7121     private static void log(String s) {
7122         Log.d(TAG, s);
7123     }
7124 
7125     private static void logw(String s) {
7126         Log.w(TAG, s);
7127     }
7128 
7129     private static void logwtf(String s) {
7130         Log.wtf(TAG, s);
7131     }
7132 
7133     private static void logwtf(String s, Throwable t) {
7134         Log.wtf(TAG, s, t);
7135     }
7136 
7137     private static void loge(String s) {
7138         Log.e(TAG, s);
7139     }
7140 
7141     private static void loge(String s, Throwable t) {
7142         Log.e(TAG, s, t);
7143     }
7144 
7145     /**
7146      * Return the information of all ongoing VPNs.
7147      *
7148      * <p>This method is used to update NetworkStatsService.
7149      *
7150      * <p>Must be called on the handler thread.
7151      */
7152     private UnderlyingNetworkInfo[] getAllVpnInfo() {
7153         ensureRunningOnConnectivityServiceThread();
7154         if (mLockdownEnabled) {
7155             return new UnderlyingNetworkInfo[0];
7156         }
7157         List<UnderlyingNetworkInfo> infoList = new ArrayList<>();
7158         for (NetworkAgentInfo nai : mNetworkAgentInfos) {
7159             UnderlyingNetworkInfo info = createVpnInfo(nai);
7160             if (info != null) {
7161                 infoList.add(info);
7162             }
7163         }
7164         return infoList.toArray(new UnderlyingNetworkInfo[infoList.size()]);
7165     }
7166 
7167     /**
7168      * @return VPN information for accounting, or null if we can't retrieve all required
7169      *         information, e.g underlying ifaces.
7170      */
7171     private UnderlyingNetworkInfo createVpnInfo(NetworkAgentInfo nai) {
7172         Network[] underlyingNetworks = nai.declaredUnderlyingNetworks;
7173         // see VpnService.setUnderlyingNetworks()'s javadoc about how to interpret
7174         // the underlyingNetworks list.
7175         // TODO: stop using propagateUnderlyingCapabilities here, for example, by always
7176         // initializing NetworkAgentInfo#declaredUnderlyingNetworks to an empty array.
7177         if (underlyingNetworks == null && nai.propagateUnderlyingCapabilities()) {
7178             final NetworkAgentInfo defaultNai = getDefaultNetworkForUid(
7179                     nai.networkCapabilities.getOwnerUid());
7180             if (defaultNai != null) {
7181                 underlyingNetworks = new Network[] { defaultNai.network };
7182             }
7183         }
7184 
7185         if (CollectionUtils.isEmpty(underlyingNetworks)) return null;
7186 
7187         List<String> interfaces = new ArrayList<>();
7188         for (Network network : underlyingNetworks) {
7189             NetworkAgentInfo underlyingNai = getNetworkAgentInfoForNetwork(network);
7190             if (underlyingNai == null) continue;
7191             LinkProperties lp = underlyingNai.linkProperties;
7192             for (String iface : lp.getAllInterfaceNames()) {
7193                 if (!TextUtils.isEmpty(iface)) {
7194                     interfaces.add(iface);
7195                 }
7196             }
7197         }
7198 
7199         if (interfaces.isEmpty()) return null;
7200 
7201         // Must be non-null or NetworkStatsService will crash.
7202         // Cannot happen in production code because Vpn only registers the NetworkAgent after the
7203         // tun or ipsec interface is created.
7204         // TODO: Remove this check.
7205         if (nai.linkProperties.getInterfaceName() == null) return null;
7206 
7207         return new UnderlyingNetworkInfo(nai.networkCapabilities.getOwnerUid(),
7208                 nai.linkProperties.getInterfaceName(), interfaces);
7209     }
7210 
7211     // TODO This needs to be the default network that applies to the NAI.
7212     private Network[] underlyingNetworksOrDefault(final int ownerUid,
7213             Network[] underlyingNetworks) {
7214         final Network defaultNetwork = getNetwork(getDefaultNetworkForUid(ownerUid));
7215         if (underlyingNetworks == null && defaultNetwork != null) {
7216             // null underlying networks means to track the default.
7217             underlyingNetworks = new Network[] { defaultNetwork };
7218         }
7219         return underlyingNetworks;
7220     }
7221 
7222     // Returns true iff |network| is an underlying network of |nai|.
7223     private boolean hasUnderlyingNetwork(NetworkAgentInfo nai, Network network) {
7224         // TODO: support more than one level of underlying networks, either via a fixed-depth search
7225         // (e.g., 2 levels of underlying networks), or via loop detection, or....
7226         if (!nai.propagateUnderlyingCapabilities()) return false;
7227         final Network[] underlying = underlyingNetworksOrDefault(
7228                 nai.networkCapabilities.getOwnerUid(), nai.declaredUnderlyingNetworks);
7229         return CollectionUtils.contains(underlying, network);
7230     }
7231 
7232     /**
7233      * Recompute the capabilities for any networks that had a specific network as underlying.
7234      *
7235      * When underlying networks change, such networks may have to update capabilities to reflect
7236      * things like the metered bit, their transports, and so on. The capabilities are calculated
7237      * immediately. This method runs on the ConnectivityService thread.
7238      */
7239     private void propagateUnderlyingNetworkCapabilities(Network updatedNetwork) {
7240         ensureRunningOnConnectivityServiceThread();
7241         for (NetworkAgentInfo nai : mNetworkAgentInfos) {
7242             if (updatedNetwork == null || hasUnderlyingNetwork(nai, updatedNetwork)) {
7243                 updateCapabilitiesForNetwork(nai);
7244             }
7245         }
7246     }
7247 
7248     private boolean isUidBlockedByVpn(int uid, List<UidRange> blockedUidRanges) {
7249         // Determine whether this UID is blocked because of always-on VPN lockdown. If a VPN applies
7250         // to the UID, then the UID is not blocked because always-on VPN lockdown applies only when
7251         // a VPN is not up.
7252         final NetworkAgentInfo vpnNai = getVpnForUid(uid);
7253         if (vpnNai != null && !vpnNai.networkAgentConfig.allowBypass) return false;
7254         for (UidRange range : blockedUidRanges) {
7255             if (range.contains(uid)) return true;
7256         }
7257         return false;
7258     }
7259 
7260     @Override
7261     public void setRequireVpnForUids(boolean requireVpn, UidRange[] ranges) {
7262         enforceNetworkStackOrSettingsPermission();
7263         mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_REQUIRE_VPN_FOR_UIDS,
7264                 encodeBool(requireVpn), 0 /* arg2 */, ranges));
7265     }
7266 
7267     private void handleSetRequireVpnForUids(boolean requireVpn, UidRange[] ranges) {
7268         if (DBG) {
7269             Log.d(TAG, "Setting VPN " + (requireVpn ? "" : "not ") + "required for UIDs: "
7270                     + Arrays.toString(ranges));
7271         }
7272         // Cannot use a Set since the list of UID ranges might contain duplicates.
7273         final List<UidRange> newVpnBlockedUidRanges = new ArrayList(mVpnBlockedUidRanges);
7274         for (int i = 0; i < ranges.length; i++) {
7275             if (requireVpn) {
7276                 newVpnBlockedUidRanges.add(ranges[i]);
7277             } else {
7278                 newVpnBlockedUidRanges.remove(ranges[i]);
7279             }
7280         }
7281 
7282         try {
7283             mNetd.networkRejectNonSecureVpn(requireVpn, toUidRangeStableParcels(ranges));
7284         } catch (RemoteException | ServiceSpecificException e) {
7285             Log.e(TAG, "setRequireVpnForUids(" + requireVpn + ", "
7286                     + Arrays.toString(ranges) + "): netd command failed: " + e);
7287         }
7288 
7289         if (mDeps.isAtLeastT()) {
7290             mPermissionMonitor.updateVpnLockdownUidRanges(requireVpn, ranges);
7291         }
7292 
7293         for (final NetworkAgentInfo nai : mNetworkAgentInfos) {
7294             final boolean curMetered = nai.networkCapabilities.isMetered();
7295             maybeNotifyNetworkBlocked(nai, curMetered, curMetered,
7296                     mVpnBlockedUidRanges, newVpnBlockedUidRanges);
7297         }
7298 
7299         mVpnBlockedUidRanges = newVpnBlockedUidRanges;
7300     }
7301 
7302     @Override
7303     public void setLegacyLockdownVpnEnabled(boolean enabled) {
7304         enforceNetworkStackOrSettingsPermission();
7305         mHandler.post(() -> mLockdownEnabled = enabled);
7306     }
7307 
7308     private boolean isLegacyLockdownNai(NetworkAgentInfo nai) {
7309         return mLockdownEnabled
7310                 && getVpnType(nai) == VpnManager.TYPE_VPN_LEGACY
7311                 && nai.networkCapabilities.appliesToUid(Process.FIRST_APPLICATION_UID);
7312     }
7313 
7314     private NetworkAgentInfo getLegacyLockdownNai() {
7315         if (!mLockdownEnabled) {
7316             return null;
7317         }
7318         // The legacy lockdown VPN always only applies to userId 0.
7319         final NetworkAgentInfo nai = getVpnForUid(Process.FIRST_APPLICATION_UID);
7320         if (nai == null || !isLegacyLockdownNai(nai)) return null;
7321 
7322         // The legacy lockdown VPN must always have exactly one underlying network.
7323         // This code may run on any thread and declaredUnderlyingNetworks may change, so store it in
7324         // a local variable. There is no need to make a copy because its contents cannot change.
7325         final Network[] underlying = nai.declaredUnderlyingNetworks;
7326         if (underlying == null ||  underlying.length != 1) {
7327             return null;
7328         }
7329 
7330         // The legacy lockdown VPN always uses the default network.
7331         // If the VPN's underlying network is no longer the current default network, it means that
7332         // the default network has just switched, and the VPN is about to disconnect.
7333         // Report that the VPN is not connected, so the state of NetworkInfo objects overwritten
7334         // by filterForLegacyLockdown will be set to CONNECTING and not CONNECTED.
7335         final NetworkAgentInfo defaultNetwork = getDefaultNetwork();
7336         if (defaultNetwork == null || !defaultNetwork.network.equals(underlying[0])) {
7337             return null;
7338         }
7339 
7340         return nai;
7341     };
7342 
7343     // TODO: move all callers to filterForLegacyLockdown and delete this method.
7344     // This likely requires making sendLegacyNetworkBroadcast take a NetworkInfo object instead of
7345     // just a DetailedState object.
7346     private DetailedState getLegacyLockdownState(DetailedState origState) {
7347         if (origState != DetailedState.CONNECTED) {
7348             return origState;
7349         }
7350         return (mLockdownEnabled && getLegacyLockdownNai() == null)
7351                 ? DetailedState.CONNECTING
7352                 : DetailedState.CONNECTED;
7353     }
7354 
7355     private void filterForLegacyLockdown(NetworkInfo ni) {
7356         if (!mLockdownEnabled || !ni.isConnected()) return;
7357         // The legacy lockdown VPN replaces the state of every network in CONNECTED state with the
7358         // state of its VPN. This is to ensure that when an underlying network connects, apps will
7359         // not see a CONNECTIVITY_ACTION broadcast for a network in state CONNECTED until the VPN
7360         // comes up, at which point there is a new CONNECTIVITY_ACTION broadcast for the underlying
7361         // network, this time with a state of CONNECTED.
7362         //
7363         // Now that the legacy lockdown code lives in ConnectivityService, and no longer has access
7364         // to the internal state of the Vpn object, always replace the state with CONNECTING. This
7365         // is not too far off the truth, since an always-on VPN, when not connected, is always
7366         // trying to reconnect.
7367         if (getLegacyLockdownNai() == null) {
7368             ni.setDetailedState(DetailedState.CONNECTING, "", null);
7369         }
7370     }
7371 
7372     @Override
7373     public void setProvisioningNotificationVisible(boolean visible, int networkType,
7374             String action) {
7375         enforceSettingsPermission();
7376         if (!ConnectivityManager.isNetworkTypeValid(networkType)) {
7377             return;
7378         }
7379         final long ident = Binder.clearCallingIdentity();
7380         try {
7381             // Concatenate the range of types onto the range of NetIDs.
7382             int id = NetIdManager.MAX_NET_ID + 1 + (networkType - ConnectivityManager.TYPE_NONE);
7383             mNotifier.setProvNotificationVisible(visible, id, action);
7384         } finally {
7385             Binder.restoreCallingIdentity(ident);
7386         }
7387     }
7388 
7389     @Override
7390     public void setAirplaneMode(boolean enable) {
7391         enforceAirplaneModePermission();
7392         final long ident = Binder.clearCallingIdentity();
7393         try {
7394             final ContentResolver cr = mContext.getContentResolver();
7395             Settings.Global.putInt(cr, Settings.Global.AIRPLANE_MODE_ON, encodeBool(enable));
7396             Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
7397             intent.putExtra("state", enable);
7398             mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
7399         } finally {
7400             Binder.restoreCallingIdentity(ident);
7401         }
7402     }
7403 
7404     private void onUserAdded(@NonNull final UserHandle user) {
7405         if (mOemNetworkPreferences.getNetworkPreferences().size() > 0) {
7406             handleSetOemNetworkPreference(mOemNetworkPreferences, null);
7407         }
7408         updateProfileAllowedNetworks();
7409     }
7410 
7411     private void onUserRemoved(@NonNull final UserHandle user) {
7412         // If there was a network preference for this user, remove it.
7413         handleSetProfileNetworkPreference(
7414                 List.of(new ProfileNetworkPreferenceInfo(user, null, true,
7415                         false /* blockingNonEnterprise */)),
7416                 null /* listener */);
7417         if (mOemNetworkPreferences.getNetworkPreferences().size() > 0) {
7418             handleSetOemNetworkPreference(mOemNetworkPreferences, null);
7419         }
7420     }
7421 
7422     private void onPackageChanged(@NonNull final String packageName) {
7423         // This is necessary in case a package is added or removed, but also when it's replaced to
7424         // run as a new UID by its manifest rules. Also, if a separate package shares the same UID
7425         // as one in the preferences, then it should follow the same routing as that other package,
7426         // which means updating the rules is never to be needed in this case (whether it joins or
7427         // leaves a UID with a preference).
7428         if (isMappedInOemNetworkPreference(packageName)) {
7429             handleSetOemNetworkPreference(mOemNetworkPreferences, null);
7430         }
7431 
7432         // Invalidates cache entry when the package is updated.
7433         synchronized (mSelfCertifiedCapabilityCache) {
7434             mSelfCertifiedCapabilityCache.remove(packageName);
7435         }
7436     }
7437 
7438     private final BroadcastReceiver mUserIntentReceiver = new BroadcastReceiver() {
7439         @Override
7440         public void onReceive(Context context, Intent intent) {
7441             ensureRunningOnConnectivityServiceThread();
7442             final String action = intent.getAction();
7443             final UserHandle user = intent.getParcelableExtra(Intent.EXTRA_USER);
7444 
7445             // User should be filled for below intents, check the existence.
7446             if (user == null) {
7447                 Log.wtf(TAG, intent.getAction() + " broadcast without EXTRA_USER");
7448                 return;
7449             }
7450 
7451             if (Intent.ACTION_USER_ADDED.equals(action)) {
7452                 onUserAdded(user);
7453             } else if (Intent.ACTION_USER_REMOVED.equals(action)) {
7454                 onUserRemoved(user);
7455             }  else {
7456                 Log.wtf(TAG, "received unexpected intent: " + action);
7457             }
7458         }
7459     };
7460 
7461     private final BroadcastReceiver mPackageIntentReceiver = new BroadcastReceiver() {
7462         @Override
7463         public void onReceive(Context context, Intent intent) {
7464             ensureRunningOnConnectivityServiceThread();
7465             switch (intent.getAction()) {
7466                 case Intent.ACTION_PACKAGE_ADDED:
7467                 case Intent.ACTION_PACKAGE_REMOVED:
7468                 case Intent.ACTION_PACKAGE_REPLACED:
7469                     onPackageChanged(intent.getData().getSchemeSpecificPart());
7470                     break;
7471                 default:
7472                     Log.wtf(TAG, "received unexpected intent: " + intent.getAction());
7473             }
7474         }
7475     };
7476 
7477     @RequiresApi(Build.VERSION_CODES.TIRAMISU)
7478     private final BroadcastReceiver mDataSaverReceiver = new BroadcastReceiver() {
7479         @Override
7480         public void onReceive(Context context, Intent intent) {
7481             if (mDeps.isAtLeastV()) {
7482                 throw new IllegalStateException(
7483                         "data saver status should be updated from platform");
7484             }
7485             ensureRunningOnConnectivityServiceThread();
7486             switch (intent.getAction()) {
7487                 case ACTION_RESTRICT_BACKGROUND_CHANGED:
7488                     // If the uid is present in the deny list, the API will consistently
7489                     // return ENABLED. To retrieve the global switch status, the system
7490                     // uid is chosen because it will never be included in the deny list.
7491                     final int dataSaverForSystemUid =
7492                             mPolicyManager.getRestrictBackgroundStatus(Process.SYSTEM_UID);
7493                     final boolean isDataSaverEnabled = (dataSaverForSystemUid
7494                             != ConnectivityManager.RESTRICT_BACKGROUND_STATUS_DISABLED);
7495                     mBpfNetMaps.setDataSaverEnabled(isDataSaverEnabled);
7496                     break;
7497                 default:
7498                     Log.wtf(TAG, "received unexpected intent: " + intent.getAction());
7499             }
7500         }
7501     };
7502 
7503     private final HashMap<Messenger, NetworkProviderInfo> mNetworkProviderInfos = new HashMap<>();
7504     private final HashMap<NetworkRequest, NetworkRequestInfo> mNetworkRequests = new HashMap<>();
7505 
7506     private static class NetworkProviderInfo {
7507         public final String name;
7508         public final Messenger messenger;
7509         private final IBinder.DeathRecipient mDeathRecipient;
7510         public final int providerId;
7511 
7512         NetworkProviderInfo(String name, Messenger messenger, int providerId,
7513                 @NonNull IBinder.DeathRecipient deathRecipient) {
7514             this.name = name;
7515             this.messenger = messenger;
7516             this.providerId = providerId;
7517             mDeathRecipient = deathRecipient;
7518 
7519             if (mDeathRecipient == null) {
7520                 throw new AssertionError("Must pass a deathRecipient");
7521             }
7522         }
7523 
7524         void connect(Context context, Handler handler) {
7525             try {
7526                 messenger.getBinder().linkToDeath(mDeathRecipient, 0);
7527             } catch (RemoteException e) {
7528                 mDeathRecipient.binderDied();
7529             }
7530         }
7531     }
7532 
7533     private void ensureAllNetworkRequestsHaveType(List<NetworkRequest> requests) {
7534         for (int i = 0; i < requests.size(); i++) {
7535             ensureNetworkRequestHasType(requests.get(i));
7536         }
7537     }
7538 
7539     private void ensureNetworkRequestHasType(NetworkRequest request) {
7540         if (request.type == NetworkRequest.Type.NONE) {
7541             throw new IllegalArgumentException(
7542                     "All NetworkRequests in ConnectivityService must have a type");
7543         }
7544     }
7545 
7546     /**
7547      * Tracks info about the requester.
7548      * Also used to notice when the calling process dies so as to self-expire
7549      */
7550     @VisibleForTesting
7551     protected class NetworkRequestInfo implements IBinder.DeathRecipient {
7552         // The requests to be satisfied in priority order. Non-multilayer requests will only have a
7553         // single NetworkRequest in mRequests.
7554         final List<NetworkRequest> mRequests;
7555 
7556         // mSatisfier and mActiveRequest rely on one another therefore set them together.
7557         void setSatisfier(
7558                 @Nullable final NetworkAgentInfo satisfier,
7559                 @Nullable final NetworkRequest activeRequest) {
7560             mSatisfier = satisfier;
7561             mActiveRequest = activeRequest;
7562         }
7563 
7564         // The network currently satisfying this NRI. Only one request in an NRI can have a
7565         // satisfier. For non-multilayer requests, only non-listen requests can have a satisfier.
7566         @Nullable
7567         private NetworkAgentInfo mSatisfier;
7568         NetworkAgentInfo getSatisfier() {
7569             return mSatisfier;
7570         }
7571 
7572         // The request in mRequests assigned to a network agent. This is null if none of the
7573         // requests in mRequests can be satisfied. This member has the constraint of only being
7574         // accessible on the handler thread.
7575         @Nullable
7576         private NetworkRequest mActiveRequest;
7577         NetworkRequest getActiveRequest() {
7578             return mActiveRequest;
7579         }
7580 
7581         final PendingIntent mPendingIntent;
7582         boolean mPendingIntentSent;
7583         @Nullable
7584         final Messenger mMessenger;
7585 
7586         // Information about the caller that caused this object to be created.
7587         @Nullable
7588         private final IBinder mBinder;
7589         final int mPid;
7590         final int mUid;
7591         final @NetworkCallback.Flag int mCallbackFlags;
7592         @Nullable
7593         final String mCallingAttributionTag;
7594 
7595         // Counter keeping track of this NRI.
7596         final RequestInfoPerUidCounter mPerUidCounter;
7597 
7598         // Effective UID of this request. This is different from mUid when a privileged process
7599         // files a request on behalf of another UID. This UID is used to determine blocked status,
7600         // UID matching, and so on. mUid above is used for permission checks and to enforce the
7601         // maximum limit of registered callbacks per UID.
7602         final int mAsUid;
7603 
7604         // Flag to indicate that uid of this nri is tracked for sending blocked status callbacks.
7605         // It is always true on V+ if mMessenger != null. As such, it's not strictly necessary.
7606         // it's used only as a safeguard to avoid double counting or leaking.
7607         boolean mUidTrackedForBlockedStatus;
7608 
7609         // Preference order of this request.
7610         final int mPreferenceOrder;
7611 
7612         // In order to preserve the mapping of NetworkRequest-to-callback when apps register
7613         // callbacks using a returned NetworkRequest, the original NetworkRequest needs to be
7614         // maintained for keying off of. This is only a concern when the original nri
7615         // mNetworkRequests changes which happens currently for apps that register callbacks to
7616         // track the default network. In those cases, the nri is updated to have mNetworkRequests
7617         // that match the per-app default nri that currently tracks the calling app's uid so that
7618         // callbacks are fired at the appropriate time. When the callbacks fire,
7619         // mNetworkRequestForCallback will be used so as to preserve the caller's mapping. When
7620         // callbacks are updated to key off of an nri vs NetworkRequest, this stops being an issue.
7621         // TODO b/177608132: make sure callbacks are indexed by NRIs and not NetworkRequest objects.
7622         @NonNull
7623         private final NetworkRequest mNetworkRequestForCallback;
7624         NetworkRequest getNetworkRequestForCallback() {
7625             return mNetworkRequestForCallback;
7626         }
7627 
7628         /**
7629          * Get the list of UIDs this nri applies to.
7630          */
7631         @NonNull
7632         Set<UidRange> getUids() {
7633             // networkCapabilities.getUids() returns a defensive copy.
7634             // multilayer requests will all have the same uids so return the first one.
7635             final Set<UidRange> uids = mRequests.get(0).networkCapabilities.getUidRanges();
7636             return (null == uids) ? new ArraySet<>() : uids;
7637         }
7638 
7639         NetworkRequestInfo(int asUid, @NonNull final NetworkRequest r,
7640                 @Nullable final PendingIntent pi, @Nullable String callingAttributionTag) {
7641             this(asUid, Collections.singletonList(r), r, pi, callingAttributionTag,
7642                     PREFERENCE_ORDER_INVALID);
7643         }
7644 
7645         NetworkRequestInfo(int asUid, @NonNull final List<NetworkRequest> r,
7646                 @NonNull final NetworkRequest requestForCallback, @Nullable final PendingIntent pi,
7647                 @Nullable String callingAttributionTag, final int preferenceOrder) {
7648             ensureAllNetworkRequestsHaveType(r);
7649             mRequests = initializeRequests(r);
7650             mNetworkRequestForCallback = requestForCallback;
7651             mPendingIntent = pi;
7652             mMessenger = null;
7653             mBinder = null;
7654             mPid = getCallingPid();
7655             mUid = mDeps.getCallingUid();
7656             mAsUid = asUid;
7657             mPerUidCounter = getRequestCounter(this);
7658             /**
7659              * Location sensitive data not included in pending intent. Only included in
7660              * {@link NetworkCallback}.
7661              */
7662             mCallbackFlags = NetworkCallback.FLAG_NONE;
7663             mCallingAttributionTag = callingAttributionTag;
7664             mPreferenceOrder = preferenceOrder;
7665         }
7666 
7667         NetworkRequestInfo(int asUid, @NonNull final NetworkRequest r, @Nullable final Messenger m,
7668                 @Nullable final IBinder binder,
7669                 @NetworkCallback.Flag int callbackFlags,
7670                 @Nullable String callingAttributionTag) {
7671             this(asUid, Collections.singletonList(r), r, m, binder, callbackFlags,
7672                     callingAttributionTag);
7673         }
7674 
7675         NetworkRequestInfo(int asUid, @NonNull final List<NetworkRequest> r,
7676                 @NonNull final NetworkRequest requestForCallback, @Nullable final Messenger m,
7677                 @Nullable final IBinder binder,
7678                 @NetworkCallback.Flag int callbackFlags,
7679                 @Nullable String callingAttributionTag) {
7680             super();
7681             ensureAllNetworkRequestsHaveType(r);
7682             mRequests = initializeRequests(r);
7683             mNetworkRequestForCallback = requestForCallback;
7684             mMessenger = m;
7685             mBinder = binder;
7686             mPid = getCallingPid();
7687             mUid = mDeps.getCallingUid();
7688             mAsUid = asUid;
7689             mPendingIntent = null;
7690             mPerUidCounter = getRequestCounter(this);
7691             mCallbackFlags = callbackFlags;
7692             mCallingAttributionTag = callingAttributionTag;
7693             mPreferenceOrder = PREFERENCE_ORDER_INVALID;
7694             linkDeathRecipient();
7695         }
7696 
7697         NetworkRequestInfo(@NonNull final NetworkRequestInfo nri,
7698                 @NonNull final List<NetworkRequest> r) {
7699             super();
7700             ensureAllNetworkRequestsHaveType(r);
7701             mRequests = initializeRequests(r);
7702             mNetworkRequestForCallback = nri.getNetworkRequestForCallback();
7703             final NetworkAgentInfo satisfier = nri.getSatisfier();
7704             if (null != satisfier) {
7705                 // If the old NRI was satisfied by an NAI, then it may have had an active request.
7706                 // The active request is necessary to figure out what callbacks to send, in
7707                 // particular when a network updates its capabilities.
7708                 // As this code creates a new NRI with a new set of requests, figure out which of
7709                 // the list of requests should be the active request. It is always the first
7710                 // request of the list that can be satisfied by the satisfier since the order of
7711                 // requests is a priority order.
7712                 // Note even in the presence of a satisfier there may not be an active request,
7713                 // when the satisfier is the no-service network.
7714                 NetworkRequest activeRequest = null;
7715                 for (final NetworkRequest candidate : r) {
7716                     if (candidate.canBeSatisfiedBy(satisfier.networkCapabilities)) {
7717                         activeRequest = candidate;
7718                         break;
7719                     }
7720                 }
7721                 setSatisfier(satisfier, activeRequest);
7722             }
7723             mMessenger = nri.mMessenger;
7724             mBinder = nri.mBinder;
7725             mPid = nri.mPid;
7726             mUid = nri.mUid;
7727             mAsUid = nri.mAsUid;
7728             mPendingIntent = nri.mPendingIntent;
7729             mPerUidCounter = nri.mPerUidCounter;
7730             mCallbackFlags = nri.mCallbackFlags;
7731             mCallingAttributionTag = nri.mCallingAttributionTag;
7732             mUidTrackedForBlockedStatus = nri.mUidTrackedForBlockedStatus;
7733             mPreferenceOrder = PREFERENCE_ORDER_INVALID;
7734             linkDeathRecipient();
7735         }
7736 
7737         NetworkRequestInfo(int asUid, @NonNull final NetworkRequest r) {
7738             this(asUid, Collections.singletonList(r), PREFERENCE_ORDER_INVALID);
7739         }
7740 
7741         NetworkRequestInfo(int asUid, @NonNull final List<NetworkRequest> r,
7742                 final int preferenceOrder) {
7743             this(asUid, r, r.get(0), null /* pi */, null /* callingAttributionTag */,
7744                     preferenceOrder);
7745         }
7746 
7747         // True if this NRI is being satisfied. It also accounts for if the nri has its satisifer
7748         // set to the mNoServiceNetwork in which case mActiveRequest will be null thus returning
7749         // false.
7750         boolean isBeingSatisfied() {
7751             return (null != mSatisfier && null != mActiveRequest);
7752         }
7753 
7754         boolean isMultilayerRequest() {
7755             return mRequests.size() > 1;
7756         }
7757 
7758         private List<NetworkRequest> initializeRequests(List<NetworkRequest> r) {
7759             // Creating a defensive copy to prevent the sender from modifying the list being
7760             // reflected in the return value of this method.
7761             final List<NetworkRequest> tempRequests = new ArrayList<>(r);
7762             return Collections.unmodifiableList(tempRequests);
7763         }
7764 
7765         void linkDeathRecipient() {
7766             if (null != mBinder) {
7767                 try {
7768                     mBinder.linkToDeath(this, 0);
7769                 } catch (RemoteException e) {
7770                     binderDied();
7771                 }
7772             }
7773         }
7774 
7775         void unlinkDeathRecipient() {
7776             if (null != mBinder) {
7777                 try {
7778                     mBinder.unlinkToDeath(this, 0);
7779                 } catch (NoSuchElementException e) {
7780                     // Temporary workaround for b/194394697 pending analysis of additional logs
7781                     Log.wtf(TAG, "unlinkToDeath for already unlinked NRI " + this);
7782                 }
7783             }
7784         }
7785 
7786         boolean hasHigherOrderThan(@NonNull final NetworkRequestInfo target) {
7787             // Compare two preference orders.
7788             return mPreferenceOrder < target.mPreferenceOrder;
7789         }
7790 
7791         int getPreferenceOrderForNetd() {
7792             if (mPreferenceOrder >= PREFERENCE_ORDER_NONE
7793                     && mPreferenceOrder <= PREFERENCE_ORDER_LOWEST) {
7794                 return mPreferenceOrder;
7795             }
7796             return PREFERENCE_ORDER_NONE;
7797         }
7798 
7799         @Override
7800         public void binderDied() {
7801             // As an immutable collection, mRequests cannot change by the time the
7802             // lambda is evaluated on the handler thread so calling .get() from a binder thread
7803             // is acceptable. Use handleReleaseNetworkRequest and not directly
7804             // handleRemoveNetworkRequest so as to force a lookup in the requests map, in case
7805             // the app already unregistered the request.
7806             mHandler.post(() -> handleReleaseNetworkRequest(mRequests.get(0),
7807                     mUid, false /* callOnUnavailable */));
7808         }
7809 
7810         @Override
7811         public String toString() {
7812             final String asUidString = (mAsUid == mUid) ? "" : " asUid: " + mAsUid;
7813             return "uid/pid:" + mUid + "/" + mPid + asUidString + " activeRequest: "
7814                     + (mActiveRequest == null ? null : mActiveRequest.requestId)
7815                     + " callbackRequest: "
7816                     + mNetworkRequestForCallback.requestId
7817                     + " " + mRequests
7818                     + (mPendingIntent == null ? "" : " to trigger " + mPendingIntent)
7819                     + " callback flags: " + mCallbackFlags
7820                     + " order: " + mPreferenceOrder
7821                     + " isUidTracked: " + mUidTrackedForBlockedStatus;
7822         }
7823     }
7824 
7825     // Keep backward compatibility since the ServiceSpecificException is used by
7826     // the API surface, see {@link ConnectivityManager#convertServiceException}.
7827     public static class RequestInfoPerUidCounter extends PerUidCounter {
7828         RequestInfoPerUidCounter(int maxCountPerUid) {
7829             super(maxCountPerUid);
7830         }
7831 
7832         @Override
7833         public synchronized void incrementCountOrThrow(int uid) {
7834             try {
7835                 super.incrementCountOrThrow(uid);
7836             } catch (IllegalStateException e) {
7837                 throw new ServiceSpecificException(
7838                         ConnectivityManager.Errors.TOO_MANY_REQUESTS,
7839                         "Uid " + uid + " exceeded its allotted requests limit");
7840             }
7841         }
7842 
7843         @Override
7844         public synchronized void decrementCountOrThrow(int uid) {
7845             throw new UnsupportedOperationException("Use decrementCount instead.");
7846         }
7847 
7848         public synchronized void decrementCount(int uid) {
7849             try {
7850                 super.decrementCountOrThrow(uid);
7851             } catch (IllegalStateException e) {
7852                 logwtf("Exception when decrement per uid request count: ", e);
7853             }
7854         }
7855     }
7856 
7857     // This checks that the passed capabilities either do not request a
7858     // specific SSID/SignalStrength, or the calling app has permission to do so.
7859     private void ensureSufficientPermissionsForRequest(NetworkCapabilities nc,
7860             int callerPid, int callerUid, String callerPackageName) {
7861         if (null != nc.getSsid() && !hasSettingsPermission(callerPid, callerUid)) {
7862             throw new SecurityException("Insufficient permissions to request a specific SSID");
7863         }
7864 
7865         if (nc.hasSignalStrength()
7866                 && !hasNetworkSignalStrengthWakeupPermission(callerPid, callerUid)) {
7867             throw new SecurityException(
7868                     "Insufficient permissions to request a specific signal strength");
7869         }
7870         mAppOpsManager.checkPackage(callerUid, callerPackageName);
7871     }
7872 
7873     private int[] getSignalStrengthThresholds(@NonNull final NetworkAgentInfo nai) {
7874         final SortedSet<Integer> thresholds = new TreeSet<>();
7875         synchronized (nai) {
7876             // mNetworkRequests may contain the same value multiple times in case of
7877             // multilayer requests. It won't matter in this case because the thresholds
7878             // will then be the same and be deduplicated as they enter the `thresholds` set.
7879             // TODO : have mNetworkRequests be a Set<NetworkRequestInfo> or the like.
7880             for (final NetworkRequestInfo nri : mNetworkRequests.values()) {
7881                 for (final NetworkRequest req : nri.mRequests) {
7882                     if (req.networkCapabilities.hasSignalStrength()
7883                             && nai.satisfiesImmutableCapabilitiesOf(req)) {
7884                         thresholds.add(req.networkCapabilities.getSignalStrength());
7885                     }
7886                 }
7887             }
7888         }
7889         return CollectionUtils.toIntArray(new ArrayList<>(thresholds));
7890     }
7891 
7892     private void updateSignalStrengthThresholds(
7893             NetworkAgentInfo nai, String reason, NetworkRequest request) {
7894         final int[] thresholdsArray = getSignalStrengthThresholds(nai);
7895 
7896         if (VDBG || (DBG && !"CONNECT".equals(reason))) {
7897             String detail;
7898             if (request != null && request.networkCapabilities.hasSignalStrength()) {
7899                 detail = reason + " " + request.networkCapabilities.getSignalStrength();
7900             } else {
7901                 detail = reason;
7902             }
7903             log(String.format("updateSignalStrengthThresholds: %s, sending %s to %s",
7904                     detail, Arrays.toString(thresholdsArray), nai.toShortString()));
7905         }
7906 
7907         nai.onSignalStrengthThresholdsUpdated(thresholdsArray);
7908     }
7909 
7910     private static void ensureValidNetworkSpecifier(NetworkCapabilities nc) {
7911         if (nc == null) {
7912             return;
7913         }
7914         NetworkSpecifier ns = nc.getNetworkSpecifier();
7915         if (ns == null) {
7916             return;
7917         }
7918         if (ns instanceof MatchAllNetworkSpecifier) {
7919             throw new IllegalArgumentException("A MatchAllNetworkSpecifier is not permitted");
7920         }
7921     }
7922 
7923     private static void ensureListenableCapabilities(@NonNull final NetworkCapabilities nc) {
7924         ensureValidNetworkSpecifier(nc);
7925         if (nc.isPrivateDnsBroken()) {
7926             throw new IllegalArgumentException("Can't request broken private DNS");
7927         }
7928         if (nc.hasAllowedUids()) {
7929             throw new IllegalArgumentException("Can't request access UIDs");
7930         }
7931     }
7932 
7933     private void ensureRequestableCapabilities(@NonNull final NetworkCapabilities nc) {
7934         ensureListenableCapabilities(nc);
7935         final String badCapability = nc.describeFirstNonRequestableCapability();
7936         if (badCapability != null) {
7937             throw new IllegalArgumentException("Cannot request network with " + badCapability);
7938         }
7939     }
7940 
7941     // TODO: Set the mini sdk to 31 and remove @TargetApi annotation when b/205923322 is addressed.
7942     @TargetApi(Build.VERSION_CODES.S)
7943     private boolean isTargetSdkAtleast(int version, int callingUid,
7944             @NonNull String callingPackageName) {
7945         final UserHandle user = UserHandle.getUserHandleForUid(callingUid);
7946         final PackageManager pm =
7947                 mContext.createContextAsUser(user, 0 /* flags */).getPackageManager();
7948         try {
7949             final int callingVersion = pm.getTargetSdkVersion(callingPackageName);
7950             if (callingVersion < version) return false;
7951         } catch (PackageManager.NameNotFoundException e) { }
7952         return true;
7953     }
7954 
7955     @Override
7956     public NetworkRequest requestNetwork(int asUid, NetworkCapabilities networkCapabilities,
7957             int reqTypeInt, Messenger messenger, int timeoutMs, final IBinder binder,
7958             int legacyType, int callbackFlags, @NonNull String callingPackageName,
7959             @Nullable String callingAttributionTag) {
7960         if (legacyType != TYPE_NONE && !hasNetworkStackPermission()) {
7961             if (isTargetSdkAtleast(Build.VERSION_CODES.M, mDeps.getCallingUid(),
7962                     callingPackageName)) {
7963                 throw new SecurityException("Insufficient permissions to specify legacy type");
7964             }
7965         }
7966         final NetworkCapabilities defaultNc = mDefaultRequest.mRequests.get(0).networkCapabilities;
7967         final int callingUid = mDeps.getCallingUid();
7968         // Privileged callers can track the default network of another UID by passing in a UID.
7969         if (asUid != Process.INVALID_UID) {
7970             enforceSettingsPermission();
7971         } else {
7972             asUid = callingUid;
7973         }
7974         final NetworkRequest.Type reqType;
7975         try {
7976             reqType = NetworkRequest.Type.values()[reqTypeInt];
7977         } catch (ArrayIndexOutOfBoundsException e) {
7978             throw new IllegalArgumentException("Unsupported request type " + reqTypeInt);
7979         }
7980         switch (reqType) {
7981             case TRACK_DEFAULT:
7982                 // If the request type is TRACK_DEFAULT, the passed {@code networkCapabilities}
7983                 // is unused and will be replaced by ones appropriate for the UID (usually, the
7984                 // calling app). This allows callers to keep track of the default network.
7985                 networkCapabilities = copyDefaultNetworkCapabilitiesForUid(
7986                         defaultNc, asUid, callingUid, callingPackageName);
7987                 enforceAccessPermission();
7988                 break;
7989             case TRACK_SYSTEM_DEFAULT:
7990                 enforceSettingsOrSetupWizardOrUseRestrictedNetworksPermission();
7991                 networkCapabilities = new NetworkCapabilities(defaultNc);
7992                 break;
7993             case BACKGROUND_REQUEST:
7994                 enforceNetworkStackOrSettingsPermission();
7995                 // Fall-through since other checks are the same with normal requests.
7996             case REQUEST:
7997                 networkCapabilities = new NetworkCapabilities(networkCapabilities);
7998                 enforceNetworkRequestPermissions(networkCapabilities, callingPackageName,
7999                         callingAttributionTag, callingUid);
8000                 // TODO: this is incorrect. We mark the request as metered or not depending on
8001                 //  the state of the app when the request is filed, but we never change the
8002                 //  request if the app changes network state. http://b/29964605
8003                 enforceMeteredApnPolicy(networkCapabilities);
8004                 maybeDisableLocalNetworkMatching(networkCapabilities, callingUid);
8005                 break;
8006             case LISTEN_FOR_BEST:
8007                 enforceAccessPermission();
8008                 networkCapabilities = new NetworkCapabilities(networkCapabilities);
8009                 maybeDisableLocalNetworkMatching(networkCapabilities, callingUid);
8010                 break;
8011             default:
8012                 throw new IllegalArgumentException("Unsupported request type " + reqType);
8013         }
8014         ensureRequestableCapabilities(networkCapabilities);
8015         ensureSufficientPermissionsForRequest(networkCapabilities,
8016                 Binder.getCallingPid(), callingUid, callingPackageName);
8017 
8018         // Enforce FOREGROUND if the caller does not have permission to use background network.
8019         if (reqType == LISTEN_FOR_BEST) {
8020             restrictBackgroundRequestForCaller(networkCapabilities);
8021         }
8022 
8023         // Set the UID range for this request to the single UID of the requester, unless the
8024         // requester has the permission to specify other UIDs.
8025         // This will overwrite any allowed UIDs in the requested capabilities. Though there
8026         // are no visible methods to set the UIDs, an app could use reflection to try and get
8027         // networks for other apps so it's essential that the UIDs are overwritten.
8028         // Also set the requester UID and package name in the request.
8029         restrictRequestUidsForCallerAndSetRequestorInfo(networkCapabilities,
8030                 callingUid, callingPackageName);
8031 
8032         if (timeoutMs < 0) {
8033             throw new IllegalArgumentException("Bad timeout specified");
8034         }
8035 
8036         // For TRACK_SYSTEM_DEFAULT callbacks, the capabilities have been modified since they were
8037         // copied from the default request above. (This is necessary to ensure, for example, that
8038         // the callback does not leak sensitive information to unprivileged apps.) Check that the
8039         // changes don't alter request matching.
8040         if (reqType == NetworkRequest.Type.TRACK_SYSTEM_DEFAULT &&
8041                 (!networkCapabilities.equalRequestableCapabilities(defaultNc))) {
8042             throw new IllegalStateException(
8043                     "TRACK_SYSTEM_DEFAULT capabilities don't match default request: "
8044                     + networkCapabilities + " vs. " + defaultNc);
8045         }
8046 
8047         final NetworkRequest networkRequest = new NetworkRequest(networkCapabilities, legacyType,
8048                 nextNetworkRequestId(), reqType);
8049         final NetworkRequestInfo nri = getNriToRegister(
8050                 asUid, networkRequest, messenger, binder, callbackFlags,
8051                 callingAttributionTag);
8052         if (DBG) log("requestNetwork for " + nri);
8053         trackUidAndRegisterNetworkRequest(EVENT_REGISTER_NETWORK_REQUEST, nri);
8054         if (timeoutMs > 0) {
8055             mHandler.sendMessageDelayed(mHandler.obtainMessage(EVENT_TIMEOUT_NETWORK_REQUEST,
8056                     nri), timeoutMs);
8057         }
8058         return networkRequest;
8059     }
8060 
8061     /**
8062      * Return the nri to be used when registering a network request. Specifically, this is used with
8063      * requests registered to track the default request. If there is currently a per-app default
8064      * tracking the app requestor, then we need to create a version of this nri that mirrors that of
8065      * the tracking per-app default so that callbacks are sent to the app requestor appropriately.
8066      * @param asUid the uid on behalf of which to file the request. Different from requestorUid
8067      *              when a privileged caller is tracking the default network for another uid.
8068      * @param nr the network request for the nri.
8069      * @param msgr the messenger for the nri.
8070      * @param binder the binder for the nri.
8071      * @param callingAttributionTag the calling attribution tag for the nri.
8072      * @return the nri to register.
8073      */
8074     private NetworkRequestInfo getNriToRegister(final int asUid, @NonNull final NetworkRequest nr,
8075             @Nullable final Messenger msgr, @Nullable final IBinder binder,
8076             @NetworkCallback.Flag int callbackFlags,
8077             @Nullable String callingAttributionTag) {
8078         final List<NetworkRequest> requests;
8079         if (NetworkRequest.Type.TRACK_DEFAULT == nr.type) {
8080             requests = copyDefaultNetworkRequestsForUid(
8081                     asUid, nr.getRequestorUid(), nr.getRequestorPackageName());
8082         } else {
8083             requests = Collections.singletonList(nr);
8084         }
8085         return new NetworkRequestInfo(
8086                 asUid, requests, nr, msgr, binder, callbackFlags, callingAttributionTag);
8087     }
8088 
8089     private boolean shouldCheckCapabilitiesDeclaration(
8090             @NonNull final NetworkCapabilities networkCapabilities, final int callingUid,
8091             @NonNull final String callingPackageName) {
8092         final UserHandle user = UserHandle.getUserHandleForUid(callingUid);
8093         // Only run the check if the change is enabled.
8094         if (!mDeps.isChangeEnabled(
8095                 ENABLE_SELF_CERTIFIED_CAPABILITIES_DECLARATION,
8096                 callingPackageName, user)) {
8097             return false;
8098         }
8099 
8100         return networkCapabilities.hasCapability(
8101                 NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_BANDWIDTH)
8102                 || networkCapabilities.hasCapability(
8103                 NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_LATENCY);
8104     }
8105 
8106     private void enforceRequestCapabilitiesDeclaration(@NonNull final String callerPackageName,
8107             @NonNull final NetworkCapabilities networkCapabilities, int callingUid) {
8108         // This check is added to fix the linter error for "current min is 30", which is not going
8109         // to happen because Connectivity service always run in S+.
8110         if (!mDeps.isAtLeastS()) {
8111             Log.wtf(TAG, "Connectivity service should always run in at least SDK S");
8112             return;
8113         }
8114         ApplicationSelfCertifiedNetworkCapabilities applicationNetworkCapabilities;
8115         final long ident = Binder.clearCallingIdentity();
8116         try {
8117             synchronized (mSelfCertifiedCapabilityCache) {
8118                 applicationNetworkCapabilities = mSelfCertifiedCapabilityCache.get(
8119                         callerPackageName);
8120                 if (applicationNetworkCapabilities == null) {
8121                     final PackageManager packageManager =
8122                             mContext.createContextAsUser(UserHandle.getUserHandleForUid(
8123                                     callingUid), 0 /* flags */).getPackageManager();
8124                     final PackageManager.Property networkSliceProperty = packageManager.getProperty(
8125                             ConstantsShim.PROPERTY_SELF_CERTIFIED_NETWORK_CAPABILITIES,
8126                             callerPackageName
8127                     );
8128                     final XmlResourceParser parser = packageManager
8129                             .getResourcesForApplication(callerPackageName)
8130                             .getXml(networkSliceProperty.getResourceId());
8131                     applicationNetworkCapabilities =
8132                             ApplicationSelfCertifiedNetworkCapabilities.createFromXml(parser);
8133                     mSelfCertifiedCapabilityCache.put(callerPackageName,
8134                             applicationNetworkCapabilities);
8135                 }
8136 
8137             }
8138         } catch (PackageManager.NameNotFoundException ne) {
8139             throw new SecurityException(
8140                     "Cannot find " + ConstantsShim.PROPERTY_SELF_CERTIFIED_NETWORK_CAPABILITIES
8141                             + " property");
8142         } catch (XmlPullParserException | IOException | InvalidTagException e) {
8143             throw new SecurityException(e.getMessage());
8144         } finally {
8145             Binder.restoreCallingIdentity(ident);
8146         }
8147 
8148         applicationNetworkCapabilities.enforceSelfCertifiedNetworkCapabilitiesDeclared(
8149                 networkCapabilities);
8150     }
8151 
8152     private boolean canRequestRestrictedNetworkDueToCarrierPrivileges(
8153             NetworkCapabilities networkCapabilities, int callingUid) {
8154         if (mRequestRestrictedWifiEnabled) {
8155             // For U+ devices, callers with carrier privilege could request restricted networks
8156             // with CBS capabilities, or any restricted WiFi networks.
8157             return ((networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_CBS)
8158                 || networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI))
8159                 && hasCarrierPrivilegeForNetworkCaps(callingUid, networkCapabilities));
8160         } else {
8161             // For T+ devices, callers with carrier privilege could request with CBS
8162             // capabilities.
8163             return (networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_CBS)
8164                 && hasCarrierPrivilegeForNetworkCaps(callingUid, networkCapabilities));
8165         }
8166     }
8167     private void enforceNetworkRequestPermissions(NetworkCapabilities networkCapabilities,
8168             String callingPackageName, String callingAttributionTag, final int callingUid) {
8169         if (shouldCheckCapabilitiesDeclaration(networkCapabilities, callingUid,
8170                 callingPackageName)) {
8171             enforceRequestCapabilitiesDeclaration(callingPackageName, networkCapabilities,
8172                     callingUid);
8173         }
8174         if (!networkCapabilities.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)) {
8175             if (!canRequestRestrictedNetworkDueToCarrierPrivileges(
8176                     networkCapabilities, callingUid)) {
8177                 enforceConnectivityRestrictedNetworksPermission(true /* checkUidsAllowedList */);
8178             }
8179         } else {
8180             enforceChangePermission(callingPackageName, callingAttributionTag);
8181         }
8182     }
8183 
8184     @Override
8185     public boolean requestBandwidthUpdate(Network network) {
8186         enforceAccessPermission();
8187         NetworkAgentInfo nai = null;
8188         if (network == null) {
8189             return false;
8190         }
8191         synchronized (mNetworkForNetId) {
8192             nai = mNetworkForNetId.get(network.getNetId());
8193         }
8194         if (nai != null) {
8195             nai.onBandwidthUpdateRequested();
8196             synchronized (mBandwidthRequests) {
8197                 final int uid = mDeps.getCallingUid();
8198                 Integer uidReqs = mBandwidthRequests.get(uid);
8199                 if (uidReqs == null) {
8200                     uidReqs = 0;
8201                 }
8202                 mBandwidthRequests.put(uid, ++uidReqs);
8203             }
8204             return true;
8205         }
8206         return false;
8207     }
8208 
8209     private boolean isSystem(int uid) {
8210         return uid < Process.FIRST_APPLICATION_UID;
8211     }
8212 
8213     private void enforceMeteredApnPolicy(NetworkCapabilities networkCapabilities) {
8214         final int uid = mDeps.getCallingUid();
8215         if (isSystem(uid)) {
8216             // Exemption for system uid.
8217             return;
8218         }
8219         if (networkCapabilities.hasCapability(NET_CAPABILITY_NOT_METERED)) {
8220             // Policy already enforced.
8221             return;
8222         }
8223         if (mDeps.isAtLeastV()) {
8224             if (mBpfNetMaps.isUidRestrictedOnMeteredNetworks(uid)) {
8225                 // If UID is restricted, don't allow them to bring up metered APNs.
8226                 networkCapabilities.addCapability(NET_CAPABILITY_NOT_METERED);
8227             }
8228             return;
8229         }
8230         final long ident = Binder.clearCallingIdentity();
8231         try {
8232             if (mPolicyManager.isUidRestrictedOnMeteredNetworks(uid)) {
8233                 // If UID is restricted, don't allow them to bring up metered APNs.
8234                 networkCapabilities.addCapability(NET_CAPABILITY_NOT_METERED);
8235             }
8236         } finally {
8237             Binder.restoreCallingIdentity(ident);
8238         }
8239     }
8240 
8241     @Override
8242     public NetworkRequest pendingRequestForNetwork(NetworkCapabilities networkCapabilities,
8243             PendingIntent operation, @NonNull String callingPackageName,
8244             @Nullable String callingAttributionTag) {
8245         Objects.requireNonNull(operation, "PendingIntent cannot be null.");
8246         final int callingUid = mDeps.getCallingUid();
8247         networkCapabilities = new NetworkCapabilities(networkCapabilities);
8248         enforceNetworkRequestPermissions(networkCapabilities, callingPackageName,
8249                 callingAttributionTag, callingUid);
8250         enforceMeteredApnPolicy(networkCapabilities);
8251         ensureRequestableCapabilities(networkCapabilities);
8252         ensureSufficientPermissionsForRequest(networkCapabilities,
8253                 Binder.getCallingPid(), callingUid, callingPackageName);
8254         restrictRequestNetworkCapabilitiesForCaller(
8255                 networkCapabilities, callingUid, callingPackageName);
8256 
8257         NetworkRequest networkRequest = new NetworkRequest(networkCapabilities, TYPE_NONE,
8258                 nextNetworkRequestId(), NetworkRequest.Type.REQUEST);
8259         NetworkRequestInfo nri = new NetworkRequestInfo(callingUid, networkRequest, operation,
8260                 callingAttributionTag);
8261         if (DBG) log("pendingRequest for " + nri);
8262         trackUidAndRegisterNetworkRequest(EVENT_REGISTER_NETWORK_REQUEST_WITH_INTENT, nri);
8263         return networkRequest;
8264     }
8265 
8266     private void releasePendingNetworkRequestWithDelay(PendingIntent operation) {
8267         mHandler.sendMessageDelayed(
8268                 mHandler.obtainMessage(EVENT_RELEASE_NETWORK_REQUEST_WITH_INTENT,
8269                 mDeps.getCallingUid(), 0, operation), mReleasePendingIntentDelayMs);
8270     }
8271 
8272     @Override
8273     public void releasePendingNetworkRequest(PendingIntent operation) {
8274         Objects.requireNonNull(operation, "PendingIntent cannot be null.");
8275         mHandler.sendMessage(mHandler.obtainMessage(EVENT_RELEASE_NETWORK_REQUEST_WITH_INTENT,
8276                 mDeps.getCallingUid(), 0, operation));
8277     }
8278 
8279     // In order to implement the compatibility measure for pre-M apps that call
8280     // WifiManager.enableNetwork(..., true) without also binding to that network explicitly,
8281     // WifiManager registers a network listen for the purpose of calling setProcessDefaultNetwork.
8282     // This ensures it has permission to do so.
8283     private boolean hasWifiNetworkListenPermission(NetworkCapabilities nc) {
8284         if (nc == null) {
8285             return false;
8286         }
8287         int[] transportTypes = nc.getTransportTypes();
8288         if (transportTypes.length != 1 || transportTypes[0] != NetworkCapabilities.TRANSPORT_WIFI) {
8289             return false;
8290         }
8291         try {
8292             mContext.enforceCallingOrSelfPermission(
8293                     android.Manifest.permission.ACCESS_WIFI_STATE,
8294                     "ConnectivityService");
8295         } catch (SecurityException e) {
8296             return false;
8297         }
8298         return true;
8299     }
8300 
8301     private boolean isAppRequest(NetworkRequestInfo nri) {
8302         return nri.mMessenger != null || nri.mPendingIntent != null;
8303     }
8304 
8305     private void trackUidAndMaybePostCurrentBlockedReason(final NetworkRequestInfo nri) {
8306         if (!isAppRequest(nri)) {
8307             Log.wtf(TAG, "trackUidAndMaybePostCurrentBlockedReason is called for non app"
8308                     + "request: " + nri);
8309             return;
8310         }
8311         nri.mPerUidCounter.incrementCountOrThrow(nri.mUid);
8312 
8313         // If nri.mMessenger is null, this nri does not have NetworkCallback so ConnectivityService
8314         // does not need to send onBlockedStatusChanged callback for this uid and does not need to
8315         // track the uid in mBlockedStatusTrackingUids
8316         if (!shouldTrackUidsForBlockedStatusCallbacks() || nri.mMessenger == null) {
8317             return;
8318         }
8319         if (nri.mUidTrackedForBlockedStatus) {
8320             Log.wtf(TAG, "Nri is already tracked for sending blocked status: " + nri);
8321             return;
8322         }
8323         nri.mUidTrackedForBlockedStatus = true;
8324         synchronized (mBlockedStatusTrackingUids) {
8325             final int uid = nri.mAsUid;
8326             final int count = mBlockedStatusTrackingUids.get(uid, 0);
8327             if (count == 0) {
8328                 mHandler.sendMessage(mHandler.obtainMessage(EVENT_BLOCKED_REASONS_CHANGED,
8329                         List.of(new Pair<>(uid, mBpfNetMaps.getUidNetworkingBlockedReasons(uid)))));
8330             }
8331             mBlockedStatusTrackingUids.put(uid, count + 1);
8332         }
8333     }
8334 
8335     private void trackUidAndRegisterNetworkRequest(final int event, NetworkRequestInfo nri) {
8336         // Post the update of the UID's blocked reasons before posting the message that registers
8337         // the callback. This is necessary because if the callback immediately matches a request,
8338         // the onBlockedStatusChanged must be called with the correct blocked reasons.
8339         // Also, once trackUidAndMaybePostCurrentBlockedReason is called, the register network
8340         // request event must be posted, because otherwise the counter for uid will never be
8341         // decremented.
8342         trackUidAndMaybePostCurrentBlockedReason(nri);
8343         mHandler.sendMessage(mHandler.obtainMessage(event, nri));
8344     }
8345 
8346     private void maybeUntrackUidAndClearBlockedReasons(final NetworkRequestInfo nri) {
8347         if (!isAppRequest(nri)) {
8348             // Not an app request.
8349             return;
8350         }
8351         nri.mPerUidCounter.decrementCount(nri.mUid);
8352 
8353         if (!shouldTrackUidsForBlockedStatusCallbacks() || nri.mMessenger == null) {
8354             return;
8355         }
8356         if (!nri.mUidTrackedForBlockedStatus) {
8357             Log.wtf(TAG, "Nri is not tracked for sending blocked status: " + nri);
8358             return;
8359         }
8360         nri.mUidTrackedForBlockedStatus = false;
8361         synchronized (mBlockedStatusTrackingUids) {
8362             final int count = mBlockedStatusTrackingUids.get(nri.mAsUid);
8363             if (count > 1) {
8364                 mBlockedStatusTrackingUids.put(nri.mAsUid, count - 1);
8365             } else {
8366                 mBlockedStatusTrackingUids.delete(nri.mAsUid);
8367                 mUidBlockedReasons.delete(nri.mAsUid);
8368             }
8369         }
8370     }
8371 
8372     @Override
8373     public NetworkRequest listenForNetwork(NetworkCapabilities networkCapabilities,
8374             Messenger messenger, IBinder binder,
8375             @NetworkCallback.Flag int callbackFlags,
8376             @NonNull String callingPackageName, @NonNull String callingAttributionTag) {
8377         final int callingUid = mDeps.getCallingUid();
8378         if (!hasWifiNetworkListenPermission(networkCapabilities)) {
8379             enforceAccessPermission();
8380         }
8381 
8382         NetworkCapabilities nc = new NetworkCapabilities(networkCapabilities);
8383         ensureSufficientPermissionsForRequest(networkCapabilities,
8384                 Binder.getCallingPid(), callingUid, callingPackageName);
8385         restrictRequestNetworkCapabilitiesForCaller(nc, callingUid, callingPackageName);
8386         // Apps without the CHANGE_NETWORK_STATE permission can't use background networks, so
8387         // make all their listens include NET_CAPABILITY_FOREGROUND. That way, they will get
8388         // onLost and onAvailable callbacks when networks move in and out of the background.
8389         // There is no need to do this for requests because an app without CHANGE_NETWORK_STATE
8390         // can't request networks.
8391         restrictBackgroundRequestForCaller(nc);
8392         ensureListenableCapabilities(nc);
8393 
8394         NetworkRequest networkRequest = new NetworkRequest(nc, TYPE_NONE, nextNetworkRequestId(),
8395                 NetworkRequest.Type.LISTEN);
8396         NetworkRequestInfo nri =
8397                 new NetworkRequestInfo(callingUid, networkRequest, messenger, binder, callbackFlags,
8398                         callingAttributionTag);
8399         if (VDBG) log("listenForNetwork for " + nri);
8400 
8401         trackUidAndRegisterNetworkRequest(EVENT_REGISTER_NETWORK_LISTENER, nri);
8402         return networkRequest;
8403     }
8404 
8405     @Override
8406     public void pendingListenForNetwork(NetworkCapabilities networkCapabilities,
8407             PendingIntent operation, @NonNull String callingPackageName,
8408             @Nullable String callingAttributionTag) {
8409         Objects.requireNonNull(operation, "PendingIntent cannot be null.");
8410         final int callingUid = mDeps.getCallingUid();
8411         if (!hasWifiNetworkListenPermission(networkCapabilities)) {
8412             enforceAccessPermission();
8413         }
8414         ensureListenableCapabilities(networkCapabilities);
8415         ensureSufficientPermissionsForRequest(networkCapabilities,
8416                 Binder.getCallingPid(), callingUid, callingPackageName);
8417         final NetworkCapabilities nc = new NetworkCapabilities(networkCapabilities);
8418         restrictRequestNetworkCapabilitiesForCaller(nc, callingUid, callingPackageName);
8419 
8420         NetworkRequest networkRequest = new NetworkRequest(nc, TYPE_NONE, nextNetworkRequestId(),
8421                 NetworkRequest.Type.LISTEN);
8422         NetworkRequestInfo nri = new NetworkRequestInfo(callingUid, networkRequest, operation,
8423                 callingAttributionTag);
8424         if (VDBG) log("pendingListenForNetwork for " + nri);
8425 
8426         trackUidAndRegisterNetworkRequest(EVENT_REGISTER_NETWORK_LISTENER_WITH_INTENT, nri);
8427     }
8428 
8429     /** Returns the next Network provider ID. */
8430     public final int nextNetworkProviderId() {
8431         return mNextNetworkProviderId.getAndIncrement();
8432     }
8433 
8434     @Override
8435     public void releaseNetworkRequest(NetworkRequest networkRequest) {
8436         ensureNetworkRequestHasType(networkRequest);
8437         mHandler.sendMessage(mHandler.obtainMessage(
8438                 EVENT_RELEASE_NETWORK_REQUEST, mDeps.getCallingUid(), 0, networkRequest));
8439     }
8440 
8441     private void handleRegisterNetworkProvider(NetworkProviderInfo npi) {
8442         if (mNetworkProviderInfos.containsKey(npi.messenger)) {
8443             // Avoid creating duplicates. even if an app makes a direct AIDL call.
8444             // This will never happen if an app calls ConnectivityManager#registerNetworkProvider,
8445             // as that will throw if a duplicate provider is registered.
8446             loge("Attempt to register existing NetworkProviderInfo "
8447                     + mNetworkProviderInfos.get(npi.messenger).name);
8448             return;
8449         }
8450 
8451         if (DBG) log("Got NetworkProvider Messenger for " + npi.name);
8452         mNetworkProviderInfos.put(npi.messenger, npi);
8453         npi.connect(mContext, mTrackerHandler);
8454     }
8455 
8456     @Override
8457     public int registerNetworkProvider(Messenger messenger, String name) {
8458         enforceNetworkFactoryOrSettingsPermission();
8459         Objects.requireNonNull(messenger, "messenger must be non-null");
8460         NetworkProviderInfo npi = new NetworkProviderInfo(name, messenger,
8461                 nextNetworkProviderId(), () -> unregisterNetworkProvider(messenger));
8462         mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_PROVIDER, npi));
8463         return npi.providerId;
8464     }
8465 
8466     @Override
8467     public void unregisterNetworkProvider(Messenger messenger) {
8468         enforceNetworkFactoryOrSettingsPermission();
8469         mHandler.sendMessage(mHandler.obtainMessage(EVENT_UNREGISTER_NETWORK_PROVIDER, messenger));
8470     }
8471 
8472     @Override
8473     public void offerNetwork(final int providerId,
8474             @NonNull final NetworkScore score, @NonNull final NetworkCapabilities caps,
8475             @NonNull final INetworkOfferCallback callback) {
8476         Objects.requireNonNull(score);
8477         Objects.requireNonNull(caps);
8478         Objects.requireNonNull(callback);
8479         final boolean yieldToBadWiFi = caps.hasTransport(TRANSPORT_CELLULAR) && !avoidBadWifi();
8480         final NetworkOffer offer = new NetworkOffer(
8481                 FullScore.makeProspectiveScore(score, caps, yieldToBadWiFi),
8482                 caps, callback, providerId);
8483         mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_OFFER, offer));
8484     }
8485 
8486     private void updateOfferScore(final NetworkOffer offer) {
8487         final boolean yieldToBadWiFi =
8488                 offer.caps.hasTransport(TRANSPORT_CELLULAR) && !avoidBadWifi();
8489         final NetworkOffer newOffer = new NetworkOffer(
8490                 offer.score.withYieldToBadWiFi(yieldToBadWiFi),
8491                         offer.caps, offer.callback, offer.providerId);
8492         if (offer.equals(newOffer)) return;
8493         handleRegisterNetworkOffer(newOffer);
8494     }
8495 
8496     @Override
8497     public void unofferNetwork(@NonNull final INetworkOfferCallback callback) {
8498         Objects.requireNonNull(callback);
8499         mHandler.sendMessage(mHandler.obtainMessage(EVENT_UNREGISTER_NETWORK_OFFER, callback));
8500     }
8501 
8502     private void handleUnregisterNetworkProvider(Messenger messenger) {
8503         NetworkProviderInfo npi = mNetworkProviderInfos.remove(messenger);
8504         if (npi == null) {
8505             loge("Failed to find Messenger in unregisterNetworkProvider");
8506             return;
8507         }
8508         // Unregister all the offers from this provider
8509         final ArrayList<NetworkOfferInfo> toRemove = new ArrayList<>();
8510         for (final NetworkOfferInfo noi : mNetworkOffers) {
8511             if (noi.offer.providerId == npi.providerId) {
8512                 // Can't call handleUnregisterNetworkOffer here because iteration is in progress
8513                 toRemove.add(noi);
8514             }
8515         }
8516         for (final NetworkOfferInfo noi : toRemove) {
8517             handleUnregisterNetworkOffer(noi);
8518         }
8519         if (DBG) log("unregisterNetworkProvider for " + npi.name);
8520     }
8521 
8522     @Override
8523     public void declareNetworkRequestUnfulfillable(@NonNull final NetworkRequest request) {
8524         if (request.hasTransport(TRANSPORT_TEST)) {
8525             enforceNetworkFactoryOrTestNetworksPermission();
8526         } else {
8527             enforceNetworkFactoryPermission();
8528         }
8529         final NetworkRequestInfo nri = mNetworkRequests.get(request);
8530         if (nri != null) {
8531             // declareNetworkRequestUnfulfillable() paths don't apply to multilayer requests.
8532             ensureNotMultilayerRequest(nri, "declareNetworkRequestUnfulfillable");
8533             mHandler.post(() -> handleReleaseNetworkRequest(
8534                     nri.mRequests.get(0), mDeps.getCallingUid(), true));
8535         }
8536     }
8537 
8538     // NOTE: Accessed on multiple threads, must be synchronized on itself.
8539     @GuardedBy("mNetworkForNetId")
8540     private final SparseArray<NetworkAgentInfo> mNetworkForNetId = new SparseArray<>();
8541     // NOTE: Accessed on multiple threads, synchronized with mNetworkForNetId.
8542     // An entry is first reserved with NetIdManager, prior to being added to mNetworkForNetId, so
8543     // there may not be a strict 1:1 correlation between the two.
8544     private final NetIdManager mNetIdManager;
8545 
8546     // Tracks all NetworkAgents that are currently registered.
8547     // NOTE: Only should be accessed on ConnectivityServiceThread, except dump().
8548     private final ArraySet<NetworkAgentInfo> mNetworkAgentInfos = new ArraySet<>();
8549 
8550     // UID ranges for users that are currently blocked by VPNs.
8551     // This array is accessed and iterated on multiple threads without holding locks, so its
8552     // contents must never be mutated. When the ranges change, the array is replaced with a new one
8553     // (on the handler thread).
8554     private volatile List<UidRange> mVpnBlockedUidRanges = new ArrayList<>();
8555 
8556     // Must only be accessed on the handler thread
8557     @NonNull
8558     private final ArrayList<NetworkOfferInfo> mNetworkOffers = new ArrayList<>();
8559 
8560     @GuardedBy("mBlockedAppUids")
8561     private final HashSet<Integer> mBlockedAppUids = new HashSet<>();
8562 
8563     // Current OEM network preferences. This object must only be written to on the handler thread.
8564     // Since it is immutable and always non-null, other threads may read it if they only care
8565     // about seeing a consistent object but not that it is current.
8566     @NonNull
8567     private OemNetworkPreferences mOemNetworkPreferences =
8568             new OemNetworkPreferences.Builder().build();
8569     // Current per-profile network preferences. This object follows the same threading rules as
8570     // the OEM network preferences above.
8571     @NonNull
8572     private NetworkPreferenceList<UserHandle, ProfileNetworkPreferenceInfo>
8573             mProfileNetworkPreferences = new NetworkPreferenceList<>();
8574 
8575     // Current VPN network preferences. This object follows the same threading rules as the OEM
8576     // network preferences above.
8577     @NonNull
8578     private NetworkPreferenceList<String, VpnNetworkPreferenceInfo>
8579             mVpnNetworkPreferences = new NetworkPreferenceList<>();
8580 
8581     // A set of UIDs that should use mobile data preferentially if available. This object follows
8582     // the same threading rules as the OEM network preferences above.
8583     @NonNull
8584     private Set<Integer> mMobileDataPreferredUids = new ArraySet<>();
8585 
8586     // OemNetworkPreferences activity String log entries.
8587     private static final int MAX_OEM_NETWORK_PREFERENCE_LOGS = 20;
8588     @NonNull
8589     private final LocalLog mOemNetworkPreferencesLogs =
8590             new LocalLog(MAX_OEM_NETWORK_PREFERENCE_LOGS);
8591 
8592     /**
8593      * Determine whether a given package has a mapping in the current OemNetworkPreferences.
8594      * @param packageName the package name to check existence of a mapping for.
8595      * @return true if a mapping exists, false otherwise
8596      */
8597     private boolean isMappedInOemNetworkPreference(@NonNull final String packageName) {
8598         return mOemNetworkPreferences.getNetworkPreferences().containsKey(packageName);
8599     }
8600 
8601     // The always-on request for an Internet-capable network that apps without a specific default
8602     // fall back to.
8603     @VisibleForTesting
8604     @NonNull
8605     final NetworkRequestInfo mDefaultRequest;
8606     // Collection of NetworkRequestInfo's used for default networks.
8607     @VisibleForTesting
8608     @NonNull
8609     final ArraySet<NetworkRequestInfo> mDefaultNetworkRequests = new ArraySet<>();
8610 
8611     private boolean isPerAppDefaultRequest(@NonNull final NetworkRequestInfo nri) {
8612         return (mDefaultNetworkRequests.contains(nri) && mDefaultRequest != nri);
8613     }
8614 
8615     /**
8616      * Return the default network request currently tracking the given uid.
8617      * @param uid the uid to check.
8618      * @return the NetworkRequestInfo tracking the given uid.
8619      */
8620     @NonNull
8621     private NetworkRequestInfo getDefaultRequestTrackingUid(final int uid) {
8622         NetworkRequestInfo highestPriorityNri = mDefaultRequest;
8623         for (final NetworkRequestInfo nri : mDefaultNetworkRequests) {
8624             // Checking the first request is sufficient as only multilayer requests will have more
8625             // than one request and for multilayer, all requests will track the same uids.
8626             if (nri.mRequests.get(0).networkCapabilities.appliesToUid(uid)) {
8627                 // Find out the highest priority request.
8628                 if (nri.hasHigherOrderThan(highestPriorityNri)) {
8629                     highestPriorityNri = nri;
8630                 }
8631             }
8632         }
8633         return highestPriorityNri;
8634     }
8635 
8636     /**
8637      * Get a copy of the network requests of the default request that is currently tracking the
8638      * given uid.
8639      * @param asUid the uid on behalf of which to file the request. Different from requestorUid
8640      *              when a privileged caller is tracking the default network for another uid.
8641      * @param requestorUid the uid to check the default for.
8642      * @param requestorPackageName the requestor's package name.
8643      * @return a copy of the default's NetworkRequest that is tracking the given uid.
8644      */
8645     @NonNull
8646     private List<NetworkRequest> copyDefaultNetworkRequestsForUid(
8647             final int asUid, final int requestorUid, @NonNull final String requestorPackageName) {
8648         return copyNetworkRequestsForUid(
8649                 getDefaultRequestTrackingUid(asUid).mRequests,
8650                 asUid, requestorUid, requestorPackageName);
8651     }
8652 
8653     /**
8654      * Copy the given nri's NetworkRequest collection.
8655      * @param requestsToCopy the NetworkRequest collection to be copied.
8656      * @param asUid the uid on behalf of which to file the request. Different from requestorUid
8657      *              when a privileged caller is tracking the default network for another uid.
8658      * @param requestorUid the uid to set on the copied collection.
8659      * @param requestorPackageName the package name to set on the copied collection.
8660      * @return the copied NetworkRequest collection.
8661      */
8662     @NonNull
8663     private List<NetworkRequest> copyNetworkRequestsForUid(
8664             @NonNull final List<NetworkRequest> requestsToCopy, final int asUid,
8665             final int requestorUid, @NonNull final String requestorPackageName) {
8666         final List<NetworkRequest> requests = new ArrayList<>();
8667         for (final NetworkRequest nr : requestsToCopy) {
8668             requests.add(new NetworkRequest(copyDefaultNetworkCapabilitiesForUid(
8669                             nr.networkCapabilities, asUid, requestorUid, requestorPackageName),
8670                     nr.legacyType, nextNetworkRequestId(), nr.type));
8671         }
8672         return requests;
8673     }
8674 
8675     @NonNull
8676     private NetworkCapabilities copyDefaultNetworkCapabilitiesForUid(
8677             @NonNull final NetworkCapabilities netCapToCopy, final int asUid,
8678             final int requestorUid, @NonNull final String requestorPackageName) {
8679         // These capabilities are for a TRACK_DEFAULT callback, so:
8680         // 1. Remove NET_CAPABILITY_VPN, because it's (currently!) the only difference between
8681         //    mDefaultRequest and a per-UID default request.
8682         //    TODO: stop depending on the fact that these two unrelated things happen to be the same
8683         // 2. Always set the UIDs to asUid. restrictRequestUidsForCallerAndSetRequestorInfo will
8684         //    not do this in the case of a privileged application.
8685         final NetworkCapabilities netCap = new NetworkCapabilities(netCapToCopy);
8686         netCap.removeCapability(NET_CAPABILITY_NOT_VPN);
8687         netCap.setSingleUid(asUid);
8688         restrictRequestUidsForCallerAndSetRequestorInfo(
8689                 netCap, requestorUid, requestorPackageName);
8690         return netCap;
8691     }
8692 
8693     /**
8694      * Get the nri that is currently being tracked for callbacks by per-app defaults.
8695      * @param nr the network request to check for equality against.
8696      * @return the nri if one exists, null otherwise.
8697      */
8698     @Nullable
8699     private NetworkRequestInfo getNriForAppRequest(@NonNull final NetworkRequest nr) {
8700         for (final NetworkRequestInfo nri : mNetworkRequests.values()) {
8701             if (nri.getNetworkRequestForCallback().equals(nr)) {
8702                 return nri;
8703             }
8704         }
8705         return null;
8706     }
8707 
8708     /**
8709      * Check if an nri is currently being managed by per-app default networking.
8710      * @param nri the nri to check.
8711      * @return true if this nri is currently being managed by per-app default networking.
8712      */
8713     private boolean isPerAppTrackedNri(@NonNull final NetworkRequestInfo nri) {
8714         // nri.mRequests.get(0) is only different from the original request filed in
8715         // nri.getNetworkRequestForCallback() if nri.mRequests was changed by per-app default
8716         // functionality therefore if these two don't match, it means this particular nri is
8717         // currently being managed by a per-app default.
8718         return nri.getNetworkRequestForCallback() != nri.mRequests.get(0);
8719     }
8720 
8721     /**
8722      * Determine if an nri is a managed default request that disallows default networking.
8723      * @param nri the request to evaluate
8724      * @return true if device-default networking is disallowed
8725      */
8726     private boolean isDefaultBlocked(@NonNull final NetworkRequestInfo nri) {
8727         // Check if this nri is a managed default that supports the default network at its
8728         // lowest priority request.
8729         final NetworkRequest defaultNetworkRequest = mDefaultRequest.mRequests.get(0);
8730         final NetworkCapabilities lowestPriorityNetCap =
8731                 nri.mRequests.get(nri.mRequests.size() - 1).networkCapabilities;
8732         return isPerAppDefaultRequest(nri)
8733                 && !(defaultNetworkRequest.networkCapabilities.equalRequestableCapabilities(
8734                         lowestPriorityNetCap));
8735     }
8736 
8737     // Request used to optionally keep mobile data active even when higher
8738     // priority networks like Wi-Fi are active.
8739     private final NetworkRequest mDefaultMobileDataRequest;
8740 
8741     // Request used to optionally keep wifi data active even when higher
8742     // priority networks like ethernet are active.
8743     private final NetworkRequest mDefaultWifiRequest;
8744 
8745     // Request used to optionally keep vehicle internal network always active
8746     private final NetworkRequest mDefaultVehicleRequest;
8747 
8748     // Sentinel NAI used to direct apps with default networks that should have no connectivity to a
8749     // network with no service. This NAI should never be matched against, nor should any public API
8750     // ever return the associated network. For this reason, this NAI is not in the list of available
8751     // NAIs. It is used in computeNetworkReassignment() to be set as the satisfier for non-device
8752     // default requests that don't support using the device default network which will ultimately
8753     // allow ConnectivityService to use this no-service network when calling makeDefaultForApps().
8754     @VisibleForTesting
8755     final NetworkAgentInfo mNoServiceNetwork;
8756 
8757     // The NetworkAgentInfo currently satisfying the default request, if any.
8758     private NetworkAgentInfo getDefaultNetwork() {
8759         return mDefaultRequest.mSatisfier;
8760     }
8761 
8762     private NetworkAgentInfo getDefaultNetworkForUid(final int uid) {
8763         NetworkRequestInfo highestPriorityNri = mDefaultRequest;
8764         for (final NetworkRequestInfo nri : mDefaultNetworkRequests) {
8765             // Currently, all network requests will have the same uids therefore checking the first
8766             // one is sufficient. If/when uids are tracked at the nri level, this can change.
8767             final Set<UidRange> uids = nri.mRequests.get(0).networkCapabilities.getUidRanges();
8768             if (null == uids) {
8769                 continue;
8770             }
8771             for (final UidRange range : uids) {
8772                 if (range.contains(uid)) {
8773                     if (nri.hasHigherOrderThan(highestPriorityNri)) {
8774                         highestPriorityNri = nri;
8775                     }
8776                 }
8777             }
8778         }
8779         if (!highestPriorityNri.isBeingSatisfied()) return null;
8780         return highestPriorityNri.getSatisfier();
8781     }
8782 
8783     @Nullable
8784     private Network getNetwork(@Nullable NetworkAgentInfo nai) {
8785         return nai != null ? nai.network : null;
8786     }
8787 
8788     private void ensureRunningOnConnectivityServiceThread() {
8789         if (mHandler.getLooper().getThread() != Thread.currentThread()) {
8790             throw new IllegalStateException(
8791                     "Not running on ConnectivityService thread: "
8792                             + Thread.currentThread().getName());
8793         }
8794     }
8795 
8796     @VisibleForTesting
8797     protected boolean isDefaultNetwork(NetworkAgentInfo nai) {
8798         return nai == getDefaultNetwork();
8799     }
8800 
8801     /**
8802      * Returns whether local agents are supported on this device.
8803      *
8804      * Local agents are supported from U on TVs, and from V on all devices.
8805      */
8806     @VisibleForTesting
8807     public boolean areLocalAgentsSupported() {
8808         final PackageManager pm = mContext.getPackageManager();
8809         // Local agents are supported starting on U on TVs and on V on everything else.
8810         return mDeps.isAtLeastV() || (mDeps.isAtLeastU() && pm.hasSystemFeature(FEATURE_LEANBACK));
8811     }
8812 
8813     /**
8814      * Register a new agent with ConnectivityService to handle a network.
8815      *
8816      * @param na a reference for ConnectivityService to contact the agent asynchronously.
8817      * @param networkInfo the initial info associated with this network. It can be updated later :
8818      *         see {@link #updateNetworkInfo}.
8819      * @param linkProperties the initial link properties of this network. They can be updated
8820      *         later : see {@link #updateLinkProperties}.
8821      * @param networkCapabilities the initial capabilites of this network. They can be updated
8822      *         later : see {@link #updateCapabilities}.
8823      * @param initialScore the initial score of the network. See {@link NetworkAgentInfo#getScore}.
8824      * @param localNetworkConfig config about this local network, or null if not a local network
8825      * @param networkAgentConfig metadata about the network. This is never updated.
8826      * @param providerId the ID of the provider owning this NetworkAgent.
8827      * @return the network created for this agent.
8828      */
8829     public Network registerNetworkAgent(INetworkAgent na,
8830             NetworkInfo networkInfo,
8831             LinkProperties linkProperties,
8832             NetworkCapabilities networkCapabilities,
8833             @NonNull NetworkScore initialScore,
8834             @Nullable LocalNetworkConfig localNetworkConfig,
8835             NetworkAgentConfig networkAgentConfig,
8836             int providerId) {
8837         Objects.requireNonNull(networkInfo, "networkInfo must not be null");
8838         Objects.requireNonNull(linkProperties, "linkProperties must not be null");
8839         Objects.requireNonNull(networkCapabilities, "networkCapabilities must not be null");
8840         Objects.requireNonNull(initialScore, "initialScore must not be null");
8841         Objects.requireNonNull(networkAgentConfig, "networkAgentConfig must not be null");
8842         if (networkCapabilities.hasTransport(TRANSPORT_TEST)) {
8843             enforceAnyPermissionOf(mContext, Manifest.permission.MANAGE_TEST_NETWORKS);
8844         } else {
8845             enforceNetworkFactoryPermission();
8846         }
8847         final boolean hasLocalCap =
8848                 networkCapabilities.hasCapability(NET_CAPABILITY_LOCAL_NETWORK);
8849         if (hasLocalCap && !areLocalAgentsSupported()) {
8850             // Before U, netd doesn't support PHYSICAL_LOCAL networks so this can't work.
8851             throw new IllegalArgumentException("Local agents are not supported in this version");
8852         }
8853         final boolean hasLocalNetworkConfig = null != localNetworkConfig;
8854         if (hasLocalCap != hasLocalNetworkConfig) {
8855             throw new IllegalArgumentException(null != localNetworkConfig
8856                     ? "Only local network agents can have a LocalNetworkConfig"
8857                     : "Local network agents must have a LocalNetworkConfig"
8858             );
8859         }
8860 
8861         final int uid = mDeps.getCallingUid();
8862         final long token = Binder.clearCallingIdentity();
8863         try {
8864             return registerNetworkAgentInternal(na, networkInfo, linkProperties,
8865                     networkCapabilities, initialScore, networkAgentConfig, localNetworkConfig,
8866                     providerId, uid);
8867         } finally {
8868             Binder.restoreCallingIdentity(token);
8869         }
8870     }
8871 
8872     private Network registerNetworkAgentInternal(INetworkAgent na, NetworkInfo networkInfo,
8873             LinkProperties linkProperties, NetworkCapabilities networkCapabilities,
8874             NetworkScore currentScore, NetworkAgentConfig networkAgentConfig,
8875             @Nullable LocalNetworkConfig localNetworkConfig, int providerId,
8876             int uid) {
8877 
8878         // Make a copy of the passed NI, LP, NC as the caller may hold a reference to them
8879         // and mutate them at any time.
8880         final NetworkInfo niCopy = new NetworkInfo(networkInfo);
8881         final NetworkCapabilities ncCopy = new NetworkCapabilities(networkCapabilities);
8882         final LinkProperties lpCopy = new LinkProperties(linkProperties);
8883         // No need to copy |localNetworkConfiguration| as it is immutable.
8884 
8885         // At this point the capabilities/properties are untrusted and unverified, e.g. checks that
8886         // the capabilities' access UIDs comply with security limitations. They will be sanitized
8887         // as the NAI registration finishes, in handleRegisterNetworkAgent(). This is
8888         // because some of the checks must happen on the handler thread.
8889         final NetworkAgentInfo nai = new NetworkAgentInfo(na,
8890                 new Network(mNetIdManager.reserveNetId()), niCopy, lpCopy, ncCopy,
8891                 localNetworkConfig, currentScore, mContext, mTrackerHandler,
8892                 new NetworkAgentConfig(networkAgentConfig), this, mNetd, mDnsResolver, providerId,
8893                 uid, mLingerDelayMs, mQosCallbackTracker, mDeps);
8894 
8895         final String extraInfo = niCopy.getExtraInfo();
8896         final String name = TextUtils.isEmpty(extraInfo)
8897                 ? nai.networkCapabilities.getSsid() : extraInfo;
8898         if (DBG) log("registerNetworkAgent " + nai);
8899         mDeps.getNetworkStack().makeNetworkMonitor(
8900                 nai.network, name, new NetworkMonitorCallbacks(nai));
8901         // NetworkAgentInfo registration will finish when the NetworkMonitor is created.
8902         // If the network disconnects or sends any other event before that, messages are deferred by
8903         // NetworkAgent until nai.connect(), which will be called when finalizing the
8904         // registration.
8905         return nai.network;
8906     }
8907 
8908     private void handleRegisterNetworkAgent(NetworkAgentInfo nai, INetworkMonitor networkMonitor) {
8909         if (VDBG) log("Network Monitor created for " +  nai);
8910         // Store a copy of the declared capabilities.
8911         nai.setDeclaredCapabilities(nai.networkCapabilities);
8912         // Make sure the LinkProperties and NetworkCapabilities reflect what the agent info said.
8913         nai.getAndSetNetworkCapabilities(mixInCapabilities(nai,
8914                 nai.getDeclaredCapabilitiesSanitized(mCarrierPrivilegeAuthenticator)));
8915         processLinkPropertiesFromAgent(nai, nai.linkProperties);
8916 
8917         nai.onNetworkMonitorCreated(networkMonitor);
8918 
8919         mNetworkAgentInfos.add(nai);
8920         synchronized (mNetworkForNetId) {
8921             mNetworkForNetId.put(nai.network.getNetId(), nai);
8922         }
8923 
8924         try {
8925             networkMonitor.start();
8926         } catch (RemoteException e) {
8927             e.rethrowAsRuntimeException();
8928         }
8929 
8930         if (nai.isLocalNetwork()) {
8931             handleUpdateLocalNetworkConfig(nai, null /* oldConfig */, nai.localNetworkConfig);
8932         }
8933         nai.notifyRegistered();
8934         NetworkInfo networkInfo = nai.networkInfo;
8935         updateNetworkInfo(nai, networkInfo);
8936         updateVpnUids(nai, null, nai.networkCapabilities);
8937     }
8938 
8939     private class NetworkOfferInfo implements IBinder.DeathRecipient {
8940         @NonNull public final NetworkOffer offer;
8941 
8942         NetworkOfferInfo(@NonNull final NetworkOffer offer) {
8943             this.offer = offer;
8944         }
8945 
8946         @Override
8947         public void binderDied() {
8948             mHandler.post(() -> handleUnregisterNetworkOffer(this));
8949         }
8950     }
8951 
8952     private boolean isNetworkProviderWithIdRegistered(final int providerId) {
8953         for (final NetworkProviderInfo npi : mNetworkProviderInfos.values()) {
8954             if (npi.providerId == providerId) return true;
8955         }
8956         return false;
8957     }
8958 
8959     /**
8960      * Register or update a network offer.
8961      * @param newOffer The new offer. If the callback member is the same as an existing
8962      *                 offer, it is an update of that offer.
8963      */
8964     // TODO : rename this to handleRegisterOrUpdateNetworkOffer
8965     private void handleRegisterNetworkOffer(@NonNull final NetworkOffer newOffer) {
8966         ensureRunningOnConnectivityServiceThread();
8967         if (!isNetworkProviderWithIdRegistered(newOffer.providerId)) {
8968             // This may actually happen if a provider updates its score or registers and then
8969             // immediately unregisters. The offer would still be in the handler queue, but the
8970             // provider would have been removed.
8971             if (DBG) log("Received offer from an unregistered provider");
8972             return;
8973         }
8974         final NetworkOfferInfo existingOffer = findNetworkOfferInfoByCallback(newOffer.callback);
8975         if (null != existingOffer) {
8976             handleUnregisterNetworkOffer(existingOffer);
8977             newOffer.migrateFrom(existingOffer.offer);
8978             if (DBG) {
8979                 // handleUnregisterNetworkOffer has already logged the old offer
8980                 log("update offer from providerId " + newOffer.providerId + " new : " + newOffer);
8981             }
8982         } else {
8983             if (DBG) {
8984                 log("register offer from providerId " + newOffer.providerId + " : " + newOffer);
8985             }
8986         }
8987         final NetworkOfferInfo noi = new NetworkOfferInfo(newOffer);
8988         try {
8989             noi.offer.callback.asBinder().linkToDeath(noi, 0 /* flags */);
8990         } catch (RemoteException e) {
8991             noi.binderDied();
8992             return;
8993         }
8994         mNetworkOffers.add(noi);
8995         issueNetworkNeeds(noi);
8996     }
8997 
8998     private void handleUnregisterNetworkOffer(@NonNull final NetworkOfferInfo noi) {
8999         ensureRunningOnConnectivityServiceThread();
9000         if (DBG) {
9001             log("unregister offer from providerId " + noi.offer.providerId + " : " + noi.offer);
9002         }
9003 
9004         // If the provider removes the offer and dies immediately afterwards this
9005         // function may be called twice in a row, but the array will no longer contain
9006         // the offer.
9007         if (!mNetworkOffers.remove(noi)) return;
9008         noi.offer.callback.asBinder().unlinkToDeath(noi, 0 /* flags */);
9009     }
9010 
9011     @Nullable private NetworkOfferInfo findNetworkOfferInfoByCallback(
9012             @NonNull final INetworkOfferCallback callback) {
9013         ensureRunningOnConnectivityServiceThread();
9014         for (final NetworkOfferInfo noi : mNetworkOffers) {
9015             if (noi.offer.callback.asBinder().equals(callback.asBinder())) return noi;
9016         }
9017         return null;
9018     }
9019 
9020     /**
9021      * Called when receiving LinkProperties directly from a NetworkAgent.
9022      * Stores into |nai| any data coming from the agent that might also be written to the network's
9023      * LinkProperties by ConnectivityService itself. This ensures that the data provided by the
9024      * agent is not lost when updateLinkProperties is called.
9025      * This method should never alter the agent's LinkProperties, only store data in |nai|.
9026      */
9027     private void processLinkPropertiesFromAgent(NetworkAgentInfo nai, LinkProperties lp) {
9028         lp.ensureDirectlyConnectedRoutes();
9029         nai.clatd.setNat64PrefixFromRa(lp.getNat64Prefix());
9030         nai.networkAgentPortalData = lp.getCaptivePortalData();
9031     }
9032 
9033     private void updateLinkProperties(NetworkAgentInfo networkAgent, @NonNull LinkProperties newLp,
9034             @Nullable LinkProperties oldLp) {
9035         int netId = networkAgent.network.getNetId();
9036 
9037         // The NetworkAgent does not know whether clatd is running on its network or not, or whether
9038         // a NAT64 prefix was discovered by the DNS resolver. Before we do anything else, make sure
9039         // the LinkProperties for the network are accurate.
9040         networkAgent.clatd.fixupLinkProperties(oldLp, newLp);
9041 
9042         updateInterfaces(newLp, oldLp, netId, networkAgent);
9043 
9044         // update filtering rules, need to happen after the interface update so netd knows about the
9045         // new interface (the interface name -> index map becomes initialized)
9046         updateVpnFiltering(newLp, oldLp, networkAgent);
9047 
9048         updateIngressToVpnAddressFiltering(newLp, oldLp, networkAgent);
9049 
9050         updateMtu(newLp, oldLp);
9051         // TODO - figure out what to do for clat
9052 //        for (LinkProperties lp : newLp.getStackedLinks()) {
9053 //            updateMtu(lp, null);
9054 //        }
9055         if (isDefaultNetwork(networkAgent)) {
9056             mProxyTracker.updateDefaultNetworkProxyPortForPAC(newLp, null);
9057             updateTcpBufferSizes(newLp.getTcpBufferSizes());
9058         }
9059 
9060         updateRoutes(newLp, oldLp, netId);
9061         updateDnses(newLp, oldLp, netId);
9062         // Make sure LinkProperties represents the latest private DNS status.
9063         // This does not need to be done before updateDnses because the
9064         // LinkProperties are not the source of the private DNS configuration.
9065         // updateDnses will fetch the private DNS configuration from DnsManager.
9066         mDnsManager.updatePrivateDnsStatus(netId, newLp);
9067 
9068         if (isDefaultNetwork(networkAgent)) {
9069             mProxyTracker.setDefaultProxy(newLp.getHttpProxy());
9070         } else if (networkAgent.everConnected()) {
9071             updateProxy(newLp, oldLp);
9072         }
9073 
9074         updateWakeOnLan(newLp);
9075 
9076         // Captive portal data is obtained from NetworkMonitor and stored in NetworkAgentInfo.
9077         // It is not always contained in the LinkProperties sent from NetworkAgents, and if it
9078         // does, it needs to be merged here.
9079         newLp.setCaptivePortalData(mergeCaptivePortalData(networkAgent.networkAgentPortalData,
9080                 networkAgent.capportApiData));
9081 
9082         // TODO - move this check to cover the whole function
9083         if (!Objects.equals(newLp, oldLp)) {
9084             synchronized (networkAgent) {
9085                 networkAgent.linkProperties = newLp;
9086             }
9087             // Start or stop DNS64 detection and 464xlat according to network state.
9088             networkAgent.clatd.update();
9089             // Notify NSS when relevant events happened. Currently, NSS only cares about
9090             // interface changed to update clat interfaces accounting.
9091             final boolean interfacesChanged = oldLp == null
9092                     || !Objects.equals(newLp.getAllInterfaceNames(), oldLp.getAllInterfaceNames());
9093             if (interfacesChanged) {
9094                 notifyIfacesChangedForNetworkStats();
9095             }
9096             networkAgent.networkMonitor().notifyLinkPropertiesChanged(
9097                     new LinkProperties(newLp, true /* parcelSensitiveFields */));
9098             notifyNetworkCallbacks(networkAgent, ConnectivityManager.CALLBACK_IP_CHANGED);
9099         }
9100 
9101         mKeepaliveTracker.handleCheckKeepalivesStillValid(networkAgent);
9102     }
9103 
9104     private void applyInitialLinkProperties(@NonNull NetworkAgentInfo nai) {
9105         updateLinkProperties(nai, new LinkProperties(nai.linkProperties), null);
9106     }
9107 
9108     /**
9109      * @param naData captive portal data from NetworkAgent
9110      * @param apiData captive portal data from capport API
9111      */
9112     @Nullable
9113     private CaptivePortalData mergeCaptivePortalData(CaptivePortalData naData,
9114             CaptivePortalData apiData) {
9115         if (naData == null || apiData == null) {
9116             return naData == null ? apiData : naData;
9117         }
9118         final CaptivePortalData.Builder captivePortalBuilder =
9119                 new CaptivePortalData.Builder(naData);
9120 
9121         if (apiData.isCaptive()) {
9122             captivePortalBuilder.setCaptive(true);
9123         }
9124         if (apiData.isSessionExtendable()) {
9125             captivePortalBuilder.setSessionExtendable(true);
9126         }
9127         if (apiData.getExpiryTimeMillis() >= 0 || apiData.getByteLimit() >= 0) {
9128             // Expiry time, bytes remaining, refresh time all need to come from the same source,
9129             // otherwise data would be inconsistent. Prefer the capport API info if present,
9130             // as it can generally be refreshed more often.
9131             captivePortalBuilder.setExpiryTime(apiData.getExpiryTimeMillis());
9132             captivePortalBuilder.setBytesRemaining(apiData.getByteLimit());
9133             captivePortalBuilder.setRefreshTime(apiData.getRefreshTimeMillis());
9134         } else if (naData.getExpiryTimeMillis() < 0 && naData.getByteLimit() < 0) {
9135             // No source has time / bytes remaining information: surface the newest refresh time
9136             // for other fields
9137             captivePortalBuilder.setRefreshTime(
9138                     Math.max(naData.getRefreshTimeMillis(), apiData.getRefreshTimeMillis()));
9139         }
9140 
9141         // Prioritize the user portal URL from the network agent if the source is authenticated.
9142         if (apiData.getUserPortalUrl() != null && naData.getUserPortalUrlSource()
9143                 != CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_PASSPOINT) {
9144             captivePortalBuilder.setUserPortalUrl(apiData.getUserPortalUrl(),
9145                     apiData.getUserPortalUrlSource());
9146         }
9147         // Prioritize the venue information URL from the network agent if the source is
9148         // authenticated.
9149         if (apiData.getVenueInfoUrl() != null && naData.getVenueInfoUrlSource()
9150                 != CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_PASSPOINT) {
9151             captivePortalBuilder.setVenueInfoUrl(apiData.getVenueInfoUrl(),
9152                     apiData.getVenueInfoUrlSource());
9153         }
9154         return captivePortalBuilder.build();
9155     }
9156 
9157     @VisibleForTesting
9158     static String makeNflogPrefix(String iface, long networkHandle) {
9159         // This needs to be kept in sync and backwards compatible with the decoding logic in
9160         // NetdEventListenerService, which is non-mainline code.
9161         return SdkLevel.isAtLeastU() ? (networkHandle + ":" + iface) : ("iface:" + iface);
9162     }
9163 
9164     private static boolean isWakeupMarkingSupported(NetworkCapabilities capabilities) {
9165         if (capabilities.hasTransport(TRANSPORT_WIFI)) {
9166             return true;
9167         }
9168         if (SdkLevel.isAtLeastU() && capabilities.hasTransport(TRANSPORT_CELLULAR)) {
9169             return true;
9170         }
9171         return false;
9172     }
9173 
9174     private void wakeupModifyInterface(String iface, NetworkAgentInfo nai, boolean add) {
9175         // Marks are only available on WiFi interfaces. Checking for
9176         // marks on unsupported interfaces is harmless.
9177         if (!isWakeupMarkingSupported(nai.networkCapabilities)) {
9178             return;
9179         }
9180 
9181         // Mask/mark of zero will not detect anything interesting.
9182         // Don't install rules unless both values are nonzero.
9183         if (mWakeUpMark == 0 || mWakeUpMask == 0) {
9184             return;
9185         }
9186 
9187         final String prefix = makeNflogPrefix(iface, nai.network.getNetworkHandle());
9188         try {
9189             if (add) {
9190                 mNetd.wakeupAddInterface(iface, prefix, mWakeUpMark, mWakeUpMask);
9191             } else {
9192                 mNetd.wakeupDelInterface(iface, prefix, mWakeUpMark, mWakeUpMask);
9193             }
9194         } catch (Exception e) {
9195             loge("Exception modifying wakeup packet monitoring: " + e);
9196         }
9197     }
9198 
9199     private void updateInterfaces(final @NonNull LinkProperties newLp,
9200             final @Nullable LinkProperties oldLp, final int netId,
9201             final @NonNull NetworkAgentInfo nai) {
9202         final CompareResult<String> interfaceDiff = new CompareResult<>(
9203                 oldLp != null ? oldLp.getAllInterfaceNames() : null, newLp.getAllInterfaceNames());
9204         if (!interfaceDiff.added.isEmpty()) {
9205             for (final String iface : interfaceDiff.added) {
9206                 try {
9207                     if (DBG) log("Adding iface " + iface + " to network " + netId);
9208                     mRoutingCoordinatorService.addInterfaceToNetwork(netId, iface);
9209                     wakeupModifyInterface(iface, nai, true);
9210                     mDeps.reportNetworkInterfaceForTransports(mContext, iface,
9211                             nai.networkCapabilities.getTransportTypes());
9212                 } catch (Exception e) {
9213                     logw("Exception adding interface: " + e);
9214                 }
9215             }
9216         }
9217         for (final String iface : interfaceDiff.removed) {
9218             try {
9219                 if (DBG) log("Removing iface " + iface + " from network " + netId);
9220                 wakeupModifyInterface(iface, nai, false);
9221                 mRoutingCoordinatorService.removeInterfaceFromNetwork(netId, iface);
9222             } catch (Exception e) {
9223                 loge("Exception removing interface: " + e);
9224             }
9225         }
9226     }
9227 
9228     /**
9229      * Have netd update routes from oldLp to newLp.
9230      * @return true if routes changed between oldLp and newLp
9231      */
9232     private boolean updateRoutes(@NonNull LinkProperties newLp, @Nullable LinkProperties oldLp,
9233             int netId) {
9234         // compare the route diff to determine which routes have been updated
9235         final CompareOrUpdateResult<RouteInfo.RouteKey, RouteInfo> routeDiff =
9236                 new CompareOrUpdateResult<>(
9237                         oldLp != null ? oldLp.getAllRoutes() : null,
9238                         newLp.getAllRoutes(),
9239                         (r) -> r.getRouteKey());
9240 
9241         // add routes before removing old in case it helps with continuous connectivity
9242 
9243         // do this twice, adding non-next-hop routes first, then routes they are dependent on
9244         for (RouteInfo route : routeDiff.added) {
9245             if (route.hasGateway()) continue;
9246             if (VDBG || DDBG) log("Adding Route [" + route + "] to network " + netId);
9247             try {
9248                 mRoutingCoordinatorService.addRoute(netId, route);
9249             } catch (Exception e) {
9250                 if ((route.getDestination().getAddress() instanceof Inet4Address) || VDBG) {
9251                     loge("Exception in addRoute for non-gateway: " + e);
9252                 }
9253             }
9254         }
9255         for (RouteInfo route : routeDiff.added) {
9256             if (!route.hasGateway()) continue;
9257             if (VDBG || DDBG) log("Adding Route [" + route + "] to network " + netId);
9258             try {
9259                 mRoutingCoordinatorService.addRoute(netId, route);
9260             } catch (Exception e) {
9261                 if ((route.getGateway() instanceof Inet4Address) || VDBG) {
9262                     loge("Exception in addRoute for gateway: " + e);
9263                 }
9264             }
9265         }
9266 
9267         for (RouteInfo route : routeDiff.removed) {
9268             if (VDBG || DDBG) log("Removing Route [" + route + "] from network " + netId);
9269             try {
9270                 mRoutingCoordinatorService.removeRoute(netId, route);
9271             } catch (Exception e) {
9272                 loge("Exception in removeRoute: " + e);
9273             }
9274         }
9275 
9276         for (RouteInfo route : routeDiff.updated) {
9277             if (VDBG || DDBG) log("Updating Route [" + route + "] from network " + netId);
9278             try {
9279                 mRoutingCoordinatorService.updateRoute(netId, route);
9280             } catch (Exception e) {
9281                 loge("Exception in updateRoute: " + e);
9282             }
9283         }
9284         return !routeDiff.added.isEmpty() || !routeDiff.removed.isEmpty()
9285                 || !routeDiff.updated.isEmpty();
9286     }
9287 
9288     private void updateDnses(@NonNull LinkProperties newLp, @Nullable LinkProperties oldLp,
9289             int netId) {
9290         if (oldLp != null && newLp.isIdenticalDnses(oldLp)) {
9291             return;  // no updating necessary
9292         }
9293 
9294         if (DBG) {
9295             final Collection<InetAddress> dnses = newLp.getDnsServers();
9296             log("Setting DNS servers for network " + netId + " to " + dnses);
9297         }
9298         try {
9299             mDnsManager.noteDnsServersForNetwork(netId, newLp);
9300             mDnsManager.flushVmDnsCache();
9301         } catch (Exception e) {
9302             loge("Exception in setDnsConfigurationForNetwork: " + e);
9303         }
9304     }
9305 
9306     private void updateVpnFiltering(@NonNull LinkProperties newLp, @Nullable LinkProperties oldLp,
9307             @NonNull NetworkAgentInfo nai) {
9308         final String oldIface = getVpnIsolationInterface(nai, nai.networkCapabilities, oldLp);
9309         final String newIface = getVpnIsolationInterface(nai, nai.networkCapabilities, newLp);
9310         final boolean wasFiltering = requiresVpnAllowRule(nai, oldLp, oldIface);
9311         final boolean needsFiltering = requiresVpnAllowRule(nai, newLp, newIface);
9312 
9313         if (!wasFiltering && !needsFiltering) {
9314             // Nothing to do.
9315             return;
9316         }
9317 
9318         if (Objects.equals(oldIface, newIface) && (wasFiltering == needsFiltering)) {
9319             // Nothing changed.
9320             return;
9321         }
9322 
9323         final Set<UidRange> ranges = nai.networkCapabilities.getUidRanges();
9324         if (ranges == null || ranges.isEmpty()) {
9325             return;
9326         }
9327 
9328         final int vpnAppUid = nai.networkCapabilities.getOwnerUid();
9329         // TODO: this create a window of opportunity for apps to receive traffic between the time
9330         // when the old rules are removed and the time when new rules are added. To fix this,
9331         // make eBPF support two allowlisted interfaces so here new rules can be added before the
9332         // old rules are being removed.
9333         if (wasFiltering) {
9334             mPermissionMonitor.onVpnUidRangesRemoved(oldIface, ranges, vpnAppUid);
9335         }
9336         if (needsFiltering) {
9337             mPermissionMonitor.onVpnUidRangesAdded(newIface, ranges, vpnAppUid);
9338         }
9339     }
9340 
9341     /**
9342      * Returns ingress discard rules to drop packets to VPN addresses ingressing via non-VPN
9343      * interfaces.
9344      * Ingress discard rule is added to the address iff
9345      *   1. The address is not a link local address
9346      *   2. The address is used by a single VPN interface and not used by any other
9347      *      interfaces even non-VPN ones
9348      * This method can be called during network disconnects, when nai has already been removed from
9349      * mNetworkAgentInfos.
9350      *
9351      * @param nai This method generates rules assuming lp of this nai is the lp at the second
9352      *            argument.
9353      * @param lp  This method generates rules assuming lp of nai at the first argument is this lp.
9354      *            Caller passes old lp to generate old rules and new lp to generate new rules.
9355      * @return    ingress discard rules. Set of pairs of addresses and interface names
9356      */
9357     private Set<Pair<InetAddress, String>> generateIngressDiscardRules(
9358             @NonNull final NetworkAgentInfo nai, @Nullable final LinkProperties lp) {
9359         Set<NetworkAgentInfo> nais = new ArraySet<>(mNetworkAgentInfos);
9360         nais.add(nai);
9361         // Determine how many networks each IP address is currently configured on.
9362         // Ingress rules are added only for IP addresses that are configured on single interface.
9363         final Map<InetAddress, Integer> addressOwnerCounts = new ArrayMap<>();
9364         for (final NetworkAgentInfo agent : nais) {
9365             if (agent.isDestroyed()) {
9366                 continue;
9367             }
9368             final LinkProperties agentLp = (nai == agent) ? lp : agent.linkProperties;
9369             if (agentLp == null) {
9370                 continue;
9371             }
9372             for (final InetAddress addr: agentLp.getAllAddresses()) {
9373                 addressOwnerCounts.put(addr, addressOwnerCounts.getOrDefault(addr, 0) + 1);
9374             }
9375         }
9376 
9377         // Iterates all networks instead of only generating rule for nai that was passed in since
9378         // lp of the nai change could cause/resolve address collision and result in affecting rule
9379         // for different network.
9380         final Set<Pair<InetAddress, String>> ingressDiscardRules = new ArraySet<>();
9381         for (final NetworkAgentInfo agent : nais) {
9382             if (!agent.isVPN() || agent.isDestroyed()) {
9383                 continue;
9384             }
9385             final LinkProperties agentLp = (nai == agent) ? lp : agent.linkProperties;
9386             if (agentLp == null || agentLp.getInterfaceName() == null) {
9387                 continue;
9388             }
9389 
9390             for (final InetAddress addr: agentLp.getAllAddresses()) {
9391                 if (addressOwnerCounts.get(addr) == 1 && !addr.isLinkLocalAddress()) {
9392                     ingressDiscardRules.add(new Pair<>(addr, agentLp.getInterfaceName()));
9393                 }
9394             }
9395         }
9396         return ingressDiscardRules;
9397     }
9398 
9399     private void updateIngressToVpnAddressFiltering(@Nullable LinkProperties newLp,
9400             @Nullable LinkProperties oldLp, @NonNull NetworkAgentInfo nai) {
9401         // Having isAtleastT to avoid NewApi linter error (b/303382209)
9402         if (!mIngressToVpnAddressFiltering || !mDeps.isAtLeastT()) {
9403             return;
9404         }
9405         final CompareOrUpdateResult<InetAddress, Pair<InetAddress, String>> ruleDiff =
9406                 new CompareOrUpdateResult<>(
9407                         generateIngressDiscardRules(nai, oldLp),
9408                         generateIngressDiscardRules(nai, newLp),
9409                         (rule) -> rule.first);
9410         for (Pair<InetAddress, String> rule: ruleDiff.removed) {
9411             mBpfNetMaps.removeIngressDiscardRule(rule.first);
9412         }
9413         for (Pair<InetAddress, String> rule: ruleDiff.added) {
9414             mBpfNetMaps.setIngressDiscardRule(rule.first, rule.second);
9415         }
9416         // setIngressDiscardRule overrides the existing rule
9417         for (Pair<InetAddress, String> rule: ruleDiff.updated) {
9418             mBpfNetMaps.setIngressDiscardRule(rule.first, rule.second);
9419         }
9420     }
9421 
9422     private void updateWakeOnLan(@NonNull LinkProperties lp) {
9423         if (mWolSupportedInterfaces == null) {
9424             mWolSupportedInterfaces = new ArraySet<>(mResources.get().getStringArray(
9425                     R.array.config_wakeonlan_supported_interfaces));
9426         }
9427         lp.setWakeOnLanSupported(mWolSupportedInterfaces.contains(lp.getInterfaceName()));
9428     }
9429 
9430     private int getNetworkPermission(NetworkCapabilities nc) {
9431         if (!nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)) {
9432             return INetd.PERMISSION_SYSTEM;
9433         }
9434         if (!nc.hasCapability(NET_CAPABILITY_FOREGROUND)) {
9435             return INetd.PERMISSION_NETWORK;
9436         }
9437         return INetd.PERMISSION_NONE;
9438     }
9439 
9440     private void updateNetworkPermissions(@NonNull final NetworkAgentInfo nai,
9441             @NonNull final NetworkCapabilities newNc) {
9442         final int oldPermission = getNetworkPermission(nai.networkCapabilities);
9443         final int newPermission = getNetworkPermission(newNc);
9444         if (oldPermission != newPermission && nai.isCreated() && !nai.isVPN()) {
9445             try {
9446                 mNetd.networkSetPermissionForNetwork(nai.network.getNetId(), newPermission);
9447             } catch (RemoteException | ServiceSpecificException e) {
9448                 loge("Exception in networkSetPermissionForNetwork: " + e);
9449             }
9450         }
9451     }
9452 
9453     /** Modifies |newNc| based on the capabilities of |underlyingNetworks| and |agentCaps|. */
9454     @VisibleForTesting
9455     void applyUnderlyingCapabilities(@Nullable Network[] underlyingNetworks,
9456             @NonNull NetworkCapabilities agentCaps, @NonNull NetworkCapabilities newNc) {
9457         underlyingNetworks = underlyingNetworksOrDefault(
9458                 agentCaps.getOwnerUid(), underlyingNetworks);
9459         long transportTypes = BitUtils.packBits(agentCaps.getTransportTypes());
9460         int downKbps = NetworkCapabilities.LINK_BANDWIDTH_UNSPECIFIED;
9461         int upKbps = NetworkCapabilities.LINK_BANDWIDTH_UNSPECIFIED;
9462         // metered if any underlying is metered, or originally declared metered by the agent.
9463         boolean metered = !agentCaps.hasCapability(NET_CAPABILITY_NOT_METERED);
9464         boolean roaming = false; // roaming if any underlying is roaming
9465         boolean congested = false; // congested if any underlying is congested
9466         boolean suspended = true; // suspended if all underlying are suspended
9467 
9468         boolean hadUnderlyingNetworks = false;
9469         ArrayList<Network> newUnderlyingNetworks = null;
9470         if (null != underlyingNetworks) {
9471             newUnderlyingNetworks = new ArrayList<>();
9472             for (Network underlyingNetwork : underlyingNetworks) {
9473                 final NetworkAgentInfo underlying =
9474                         getNetworkAgentInfoForNetwork(underlyingNetwork);
9475                 if (underlying == null) continue;
9476 
9477                 final NetworkCapabilities underlyingCaps = underlying.networkCapabilities;
9478                 hadUnderlyingNetworks = true;
9479                 for (int underlyingType : underlyingCaps.getTransportTypes()) {
9480                     transportTypes |= 1L << underlyingType;
9481                 }
9482 
9483                 // Merge capabilities of this underlying network. For bandwidth, assume the
9484                 // worst case.
9485                 downKbps = NetworkCapabilities.minBandwidth(downKbps,
9486                         underlyingCaps.getLinkDownstreamBandwidthKbps());
9487                 upKbps = NetworkCapabilities.minBandwidth(upKbps,
9488                         underlyingCaps.getLinkUpstreamBandwidthKbps());
9489                 // If this underlying network is metered, the VPN is metered (it may cost money
9490                 // to send packets on this network).
9491                 metered |= !underlyingCaps.hasCapability(NET_CAPABILITY_NOT_METERED);
9492                 // If this underlying network is roaming, the VPN is roaming (the billing structure
9493                 // is different than the usual, local one).
9494                 roaming |= !underlyingCaps.hasCapability(NET_CAPABILITY_NOT_ROAMING);
9495                 // If this underlying network is congested, the VPN is congested (the current
9496                 // condition of the network affects the performance of this network).
9497                 congested |= !underlyingCaps.hasCapability(NET_CAPABILITY_NOT_CONGESTED);
9498                 // If this network is not suspended, the VPN is not suspended (the VPN
9499                 // is able to transfer some data).
9500                 suspended &= !underlyingCaps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED);
9501                 newUnderlyingNetworks.add(underlyingNetwork);
9502             }
9503         }
9504         if (!hadUnderlyingNetworks) {
9505             // No idea what the underlying networks are; assume reasonable defaults
9506             metered = true;
9507             roaming = false;
9508             congested = false;
9509             suspended = false;
9510         }
9511 
9512         newNc.setTransportTypes(BitUtils.unpackBits(transportTypes));
9513         newNc.setLinkDownstreamBandwidthKbps(downKbps);
9514         newNc.setLinkUpstreamBandwidthKbps(upKbps);
9515         newNc.setCapability(NET_CAPABILITY_NOT_METERED, !metered);
9516         newNc.setCapability(NET_CAPABILITY_NOT_ROAMING, !roaming);
9517         newNc.setCapability(NET_CAPABILITY_NOT_CONGESTED, !congested);
9518         newNc.setCapability(NET_CAPABILITY_NOT_SUSPENDED, !suspended);
9519         newNc.setUnderlyingNetworks(newUnderlyingNetworks);
9520     }
9521 
9522     /**
9523      * Augments the NetworkCapabilities passed in by a NetworkAgent with capabilities that are
9524      * maintained here that the NetworkAgent is not aware of (e.g., validated, captive portal,
9525      * and foreground status).
9526      */
9527     @NonNull
9528     private NetworkCapabilities mixInCapabilities(NetworkAgentInfo nai, NetworkCapabilities nc) {
9529         // Once a NetworkAgent is connected, complain if some immutable capabilities are removed.
9530          // Don't complain for VPNs since they're not driven by requests and there is no risk of
9531          // causing a connect/teardown loop.
9532          // TODO: remove this altogether and make it the responsibility of the NetworkProviders to
9533          // avoid connect/teardown loops.
9534         if (nai.everConnected()
9535                 && !nai.isVPN()
9536                 && !nai.networkCapabilities.satisfiedByImmutableNetworkCapabilities(nc)) {
9537             // TODO: consider not complaining when a network agent degrades its capabilities if this
9538             // does not cause any request (that is not a listen) currently matching that agent to
9539             // stop being matched by the updated agent.
9540             String diff = nai.networkCapabilities.describeImmutableDifferences(nc);
9541             if (!TextUtils.isEmpty(diff)) {
9542                 Log.wtf(TAG, "BUG: " + nai + " lost immutable capabilities:" + diff);
9543             }
9544         }
9545 
9546         // Don't modify caller's NetworkCapabilities.
9547         final NetworkCapabilities newNc = new NetworkCapabilities(nc);
9548         if (nai.isValidated()) {
9549             newNc.addCapability(NET_CAPABILITY_VALIDATED);
9550         } else {
9551             newNc.removeCapability(NET_CAPABILITY_VALIDATED);
9552         }
9553         if (nai.captivePortalDetected()) {
9554             newNc.addCapability(NET_CAPABILITY_CAPTIVE_PORTAL);
9555         } else {
9556             newNc.removeCapability(NET_CAPABILITY_CAPTIVE_PORTAL);
9557         }
9558         if (nai.isBackgroundNetwork()) {
9559             newNc.removeCapability(NET_CAPABILITY_FOREGROUND);
9560         } else {
9561             newNc.addCapability(NET_CAPABILITY_FOREGROUND);
9562         }
9563         if (nai.partialConnectivity()) {
9564             newNc.addCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY);
9565         } else {
9566             newNc.removeCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY);
9567         }
9568         newNc.setPrivateDnsBroken(nai.networkCapabilities.isPrivateDnsBroken());
9569 
9570         // TODO : remove this once all factories are updated to send NOT_SUSPENDED and NOT_ROAMING
9571         if (!newNc.hasTransport(TRANSPORT_CELLULAR)) {
9572             newNc.addCapability(NET_CAPABILITY_NOT_SUSPENDED);
9573             newNc.addCapability(NET_CAPABILITY_NOT_ROAMING);
9574         }
9575 
9576         if (nai.propagateUnderlyingCapabilities()) {
9577             applyUnderlyingCapabilities(nai.declaredUnderlyingNetworks,
9578                     nai.getDeclaredCapabilitiesSanitized(mCarrierPrivilegeAuthenticator),
9579                     newNc);
9580         }
9581 
9582         return newNc;
9583     }
9584 
9585     private void updateNetworkInfoForRoamingAndSuspended(NetworkAgentInfo nai,
9586             NetworkCapabilities prevNc, NetworkCapabilities newNc) {
9587         final boolean prevSuspended = !prevNc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED);
9588         final boolean suspended = !newNc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED);
9589         final boolean prevRoaming = !prevNc.hasCapability(NET_CAPABILITY_NOT_ROAMING);
9590         final boolean roaming = !newNc.hasCapability(NET_CAPABILITY_NOT_ROAMING);
9591         if (prevSuspended != suspended) {
9592             // TODO (b/73132094) : remove this call once the few users of onSuspended and
9593             // onResumed have been removed.
9594             notifyNetworkCallbacks(nai, suspended ? ConnectivityManager.CALLBACK_SUSPENDED
9595                     : ConnectivityManager.CALLBACK_RESUMED);
9596         }
9597         if (prevSuspended != suspended || prevRoaming != roaming) {
9598             // updateNetworkInfo will mix in the suspended info from the capabilities and
9599             // take appropriate action for the network having possibly changed state.
9600             updateNetworkInfo(nai, nai.networkInfo);
9601         }
9602     }
9603 
9604     private void handleUidCarrierPrivilegesLost(int uid, int subId) {
9605         if (!mRequestRestrictedWifiEnabled) {
9606             return;
9607         }
9608         ensureRunningOnConnectivityServiceThread();
9609         // A NetworkRequest needs to be revoked when all the conditions are met
9610         //   1. It requests restricted network
9611         //   2. The requestor uid matches the uid with the callback
9612         //   3. The app doesn't have Carrier Privileges
9613         //   4. The app doesn't have permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS
9614         for (final NetworkRequest nr : mNetworkRequests.keySet()) {
9615             if (nr.isRequest()
9616                     && !nr.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)
9617                     && nr.getRequestorUid() == uid
9618                     && getSubscriptionIdFromNetworkCaps(nr.networkCapabilities) == subId
9619                     && !hasConnectivityRestrictedNetworksPermission(uid, true)) {
9620                 declareNetworkRequestUnfulfillable(nr);
9621             }
9622         }
9623 
9624         // A NetworkAgent's allowedUids may need to be updated if the app has lost
9625         // carrier config
9626         for (final NetworkAgentInfo nai : mNetworkAgentInfos) {
9627             if (nai.networkCapabilities.getAllowedUidsNoCopy().contains(uid)
9628                     && getSubscriptionIdFromNetworkCaps(nai.networkCapabilities) == subId) {
9629                 final NetworkCapabilities nc = new NetworkCapabilities(nai.networkCapabilities);
9630                 NetworkAgentInfo.restrictCapabilitiesFromNetworkAgent(
9631                         nc,
9632                         uid,
9633                         false /* hasAutomotiveFeature (irrelevant) */,
9634                         mDeps,
9635                         mCarrierPrivilegeAuthenticator);
9636                 updateCapabilities(nai.getScore(), nai, nc);
9637             }
9638         }
9639     }
9640 
9641     /**
9642      * Update the NetworkCapabilities for {@code nai} to {@code nc}. Specifically:
9643      *
9644      * 1. Calls mixInCapabilities to merge the passed-in NetworkCapabilities {@code nc} with the
9645      *    capabilities we manage and store in {@code nai}, such as validated status and captive
9646      *    portal status)
9647      * 2. Takes action on the result: changes network permissions, sends CAP_CHANGED callbacks, and
9648      *    potentially triggers rematches.
9649      * 3. Directly informs other network stack components (NetworkStatsService, VPNs, etc. of the
9650      *    change.)
9651      *
9652      * @param oldScore score of the network before any of the changes that prompted us
9653      *                 to call this function.
9654      * @param nai the network having its capabilities updated.
9655      * @param nc the new network capabilities.
9656      */
9657     private void updateCapabilities(final FullScore oldScore, @NonNull final NetworkAgentInfo nai,
9658             @NonNull final NetworkCapabilities nc) {
9659         NetworkCapabilities newNc = mixInCapabilities(nai, nc);
9660         if (Objects.equals(nai.networkCapabilities, newNc)) return;
9661         final String differences = newNc.describeCapsDifferencesFrom(nai.networkCapabilities);
9662         if (null != differences) {
9663             Log.i(TAG, "Update capabilities for net " + nai.network + " : " + differences);
9664         }
9665         updateNetworkPermissions(nai, newNc);
9666         final NetworkCapabilities prevNc = nai.getAndSetNetworkCapabilities(newNc);
9667 
9668         updateVpnUids(nai, prevNc, newNc);
9669         updateAllowedUids(nai, prevNc, newNc);
9670         nai.updateScoreForNetworkAgentUpdate();
9671 
9672         if (nai.getScore().equals(oldScore) && newNc.equalRequestableCapabilities(prevNc)) {
9673             // If the requestable capabilities haven't changed, and the score hasn't changed, then
9674             // the change we're processing can't affect any requests, it can only affect the listens
9675             // on this network. We might have been called by rematchNetworkAndRequests when a
9676             // network changed foreground state.
9677             processListenRequests(nai);
9678         } else {
9679             // If the requestable capabilities have changed or the score changed, we can't have been
9680             // called by rematchNetworkAndRequests, so it's safe to start a rematch.
9681             rematchAllNetworksAndRequests();
9682             notifyNetworkCallbacks(nai, ConnectivityManager.CALLBACK_CAP_CHANGED);
9683         }
9684         updateNetworkInfoForRoamingAndSuspended(nai, prevNc, newNc);
9685 
9686         final boolean oldMetered = prevNc.isMetered();
9687         final boolean newMetered = newNc.isMetered();
9688         final boolean meteredChanged = oldMetered != newMetered;
9689 
9690         if (meteredChanged) {
9691             maybeNotifyNetworkBlocked(nai, oldMetered, newMetered,
9692                     mVpnBlockedUidRanges, mVpnBlockedUidRanges);
9693         }
9694 
9695         final boolean roamingChanged = prevNc.hasCapability(NET_CAPABILITY_NOT_ROAMING)
9696                 != newNc.hasCapability(NET_CAPABILITY_NOT_ROAMING);
9697 
9698         // Report changes that are interesting for network statistics tracking.
9699         if (meteredChanged || roamingChanged) {
9700             notifyIfacesChangedForNetworkStats();
9701         }
9702 
9703         // This network might have been underlying another network. Propagate its capabilities.
9704         propagateUnderlyingNetworkCapabilities(nai.network);
9705 
9706         if (meteredChanged || !newNc.equalsTransportTypes(prevNc)) {
9707             mDnsManager.updateCapabilitiesForNetwork(nai.network.getNetId(), newNc);
9708         }
9709 
9710         maybeSendProxyBroadcast(nai, prevNc, newNc);
9711     }
9712 
9713     /** Convenience method to update the capabilities for a given network. */
9714     private void updateCapabilitiesForNetwork(NetworkAgentInfo nai) {
9715         updateCapabilities(nai.getScore(), nai, nai.networkCapabilities);
9716     }
9717 
9718     private void maybeApplyMulticastRoutingConfig(@NonNull final NetworkAgentInfo nai,
9719             final LocalNetworkConfig oldConfig,
9720             final LocalNetworkConfig newConfig) {
9721         final MulticastRoutingConfig oldUpstreamConfig =
9722                 oldConfig == null ? MulticastRoutingConfig.CONFIG_FORWARD_NONE :
9723                         oldConfig.getUpstreamMulticastRoutingConfig();
9724         final MulticastRoutingConfig oldDownstreamConfig =
9725                 oldConfig == null ? MulticastRoutingConfig.CONFIG_FORWARD_NONE :
9726                         oldConfig.getDownstreamMulticastRoutingConfig();
9727         final MulticastRoutingConfig newUpstreamConfig =
9728                 newConfig == null ? MulticastRoutingConfig.CONFIG_FORWARD_NONE :
9729                         newConfig.getUpstreamMulticastRoutingConfig();
9730         final MulticastRoutingConfig newDownstreamConfig =
9731                 newConfig == null ? MulticastRoutingConfig.CONFIG_FORWARD_NONE :
9732                         newConfig.getDownstreamMulticastRoutingConfig();
9733 
9734         if (oldUpstreamConfig.equals(newUpstreamConfig) &&
9735             oldDownstreamConfig.equals(newDownstreamConfig)) {
9736             return;
9737         }
9738 
9739         final String downstreamNetworkName = nai.linkProperties.getInterfaceName();
9740         final LocalNetworkInfo lni = localNetworkInfoForNai(nai);
9741         final Network upstreamNetwork = lni.getUpstreamNetwork();
9742 
9743         if (upstreamNetwork != null) {
9744             final String upstreamNetworkName =
9745                     getLinkProperties(upstreamNetwork).getInterfaceName();
9746             applyMulticastRoutingConfig(downstreamNetworkName, upstreamNetworkName, newConfig);
9747         }
9748     }
9749 
9750     private void applyMulticastRoutingConfig(@NonNull String localNetworkInterfaceName,
9751             @NonNull String upstreamNetworkInterfaceName,
9752             @NonNull final LocalNetworkConfig config) {
9753         if (mMulticastRoutingCoordinatorService == null) {
9754             if (config.getDownstreamMulticastRoutingConfig().getForwardingMode() != FORWARD_NONE ||
9755                 config.getUpstreamMulticastRoutingConfig().getForwardingMode() != FORWARD_NONE) {
9756                 loge("Multicast routing is not supported, failed to configure " + config
9757                         + " for " + localNetworkInterfaceName + " to "
9758                         +  upstreamNetworkInterfaceName);
9759             }
9760             return;
9761         }
9762 
9763         mMulticastRoutingCoordinatorService.applyMulticastRoutingConfig(localNetworkInterfaceName,
9764                 upstreamNetworkInterfaceName, config.getUpstreamMulticastRoutingConfig());
9765         mMulticastRoutingCoordinatorService.applyMulticastRoutingConfig
9766                 (upstreamNetworkInterfaceName, localNetworkInterfaceName,
9767                         config.getDownstreamMulticastRoutingConfig());
9768     }
9769 
9770     private void disableMulticastRouting(@NonNull String localNetworkInterfaceName,
9771             @NonNull String upstreamNetworkInterfaceName) {
9772         if (mMulticastRoutingCoordinatorService == null) {
9773             return;
9774         }
9775 
9776         mMulticastRoutingCoordinatorService.applyMulticastRoutingConfig(localNetworkInterfaceName,
9777                 upstreamNetworkInterfaceName, MulticastRoutingConfig.CONFIG_FORWARD_NONE);
9778         mMulticastRoutingCoordinatorService.applyMulticastRoutingConfig
9779                 (upstreamNetworkInterfaceName, localNetworkInterfaceName,
9780                         MulticastRoutingConfig.CONFIG_FORWARD_NONE);
9781     }
9782 
9783     // oldConfig is null iff this is the original registration of the local network config
9784     private void handleUpdateLocalNetworkConfig(@NonNull final NetworkAgentInfo nai,
9785             @Nullable final LocalNetworkConfig oldConfig,
9786             @NonNull final LocalNetworkConfig newConfig) {
9787         if (!nai.isLocalNetwork()) {
9788             Log.wtf(TAG, "Ignoring update of a local network info on non-local network " + nai);
9789             return;
9790         }
9791 
9792         if (VDBG) {
9793             Log.v(TAG, "Update local network config " + nai.network.netId + " : " + newConfig);
9794         }
9795         final LocalNetworkConfig.Builder configBuilder = new LocalNetworkConfig.Builder();
9796         configBuilder.setUpstreamMulticastRoutingConfig(
9797                 newConfig.getUpstreamMulticastRoutingConfig());
9798         configBuilder.setDownstreamMulticastRoutingConfig(
9799                 newConfig.getDownstreamMulticastRoutingConfig());
9800 
9801         final NetworkRequest oldRequest =
9802                 (null == oldConfig) ? null : oldConfig.getUpstreamSelector();
9803         final NetworkCapabilities oldCaps =
9804                 (null == oldRequest) ? null : oldRequest.networkCapabilities;
9805         final NetworkRequestInfo oldNri =
9806                 null == oldRequest ? null : mNetworkRequests.get(oldRequest);
9807         final NetworkAgentInfo oldSatisfier =
9808                 null == oldNri ? null : oldNri.getSatisfier();
9809         final NetworkRequest newRequest = newConfig.getUpstreamSelector();
9810         final NetworkCapabilities newCaps =
9811                 (null == newRequest) ? null : newRequest.networkCapabilities;
9812         final boolean requestUpdated = !Objects.equals(newCaps, oldCaps);
9813         if (null != oldRequest && requestUpdated) {
9814             handleRemoveNetworkRequest(mNetworkRequests.get(oldRequest));
9815             if (null == newRequest && null != oldSatisfier) {
9816                 // If there is an old satisfier, but no new request, then remove the old upstream.
9817                 removeLocalNetworkUpstream(nai, oldSatisfier);
9818                 nai.localNetworkConfig = configBuilder.build();
9819                 // When there is a new request, the rematch sees the new request and sends the
9820                 // LOCAL_NETWORK_INFO_CHANGED callbacks accordingly.
9821                 // But here there is no new request, so the rematch won't see anything. Send
9822                 // callbacks to apps now to tell them about the loss of upstream.
9823                 notifyNetworkCallbacks(nai,
9824                         ConnectivityManager.CALLBACK_LOCAL_NETWORK_INFO_CHANGED);
9825                 return;
9826             }
9827         }
9828         if (null != newRequest && requestUpdated) {
9829             // File the new request if :
9830             //  - it has changed (requestUpdated), or
9831             //  - it's the first time this local info (null == oldConfig)
9832             // is updated and the request has not been filed yet.
9833             // Requests for local info are always LISTEN_FOR_BEST, because they have at most one
9834             // upstream (the best) but never request it to be brought up.
9835             final NetworkRequest nr = new NetworkRequest(newCaps, ConnectivityManager.TYPE_NONE,
9836                     nextNetworkRequestId(), LISTEN_FOR_BEST);
9837             configBuilder.setUpstreamSelector(nr);
9838             final NetworkRequestInfo nri = new NetworkRequestInfo(
9839                     nai.creatorUid, nr, null /* messenger */, null /* binder */,
9840                     0 /* callbackFlags */, null /* attributionTag */);
9841             if (null != oldSatisfier) {
9842                 // Set the old satisfier in the new NRI so that the rematch will see any changes
9843                 nri.setSatisfier(oldSatisfier, nr);
9844             }
9845             nai.localNetworkConfig = configBuilder.build();
9846             // handleRegisterNetworkRequest causes a rematch. The rematch must happen after
9847             // nai.localNetworkConfig is set, since it will base its callbacks on the old
9848             // satisfier and the new request.
9849             handleRegisterNetworkRequest(nri);
9850         } else {
9851             configBuilder.setUpstreamSelector(oldRequest);
9852             nai.localNetworkConfig = configBuilder.build();
9853         }
9854         maybeApplyMulticastRoutingConfig(nai, oldConfig, newConfig);
9855     }
9856 
9857     /**
9858      * Returns the interface which requires VPN isolation (ingress interface filtering).
9859      *
9860      * Ingress interface filtering enforces that all apps under the given network can only receive
9861      * packets from the network's interface (and loopback). This is important for VPNs because
9862      * apps that cannot bypass a fully-routed VPN shouldn't be able to receive packets from any
9863      * non-VPN interfaces.
9864      *
9865      * As a result, this method should return Non-null interface iff
9866      *  1. the network is an app VPN (not legacy VPN)
9867      *  2. the VPN does not allow bypass
9868      *  3. the VPN is fully-routed
9869      *  4. the VPN interface is non-null
9870      *
9871      * @see INetd#firewallAddUidInterfaceRules
9872      * @see INetd#firewallRemoveUidInterfaceRules
9873      */
9874     @Nullable
9875     private String getVpnIsolationInterface(@NonNull NetworkAgentInfo nai, NetworkCapabilities nc,
9876             LinkProperties lp) {
9877         if (nc == null || lp == null) return null;
9878         if (nai.isVPN()
9879                 && !nai.networkAgentConfig.allowBypass
9880                 && nc.getOwnerUid() != Process.SYSTEM_UID
9881                 && lp.getInterfaceName() != null
9882                 && (lp.hasIpv4DefaultRoute() || lp.hasIpv4UnreachableDefaultRoute())
9883                 && (lp.hasIpv6DefaultRoute() || lp.hasIpv6UnreachableDefaultRoute())
9884                 && !lp.hasExcludeRoute()) {
9885             return lp.getInterfaceName();
9886         }
9887         return null;
9888     }
9889 
9890     /**
9891      * Returns whether we need to set interface filtering rule or not
9892      */
9893     private boolean requiresVpnAllowRule(NetworkAgentInfo nai, LinkProperties lp,
9894             String isolationIface) {
9895         // Allow rules are always needed if VPN isolation is enabled.
9896         if (isolationIface != null) return true;
9897 
9898         // On T and above, allow rules are needed for all VPNs. Allow rule with null iface is a
9899         // wildcard to allow apps to receive packets on all interfaces. This is required to accept
9900         // incoming traffic in Lockdown mode by overriding the Lockdown blocking rule.
9901         return mDeps.isAtLeastT() && nai.isVPN() && lp != null && lp.getInterfaceName() != null;
9902     }
9903 
9904     private static UidRangeParcel[] toUidRangeStableParcels(final @NonNull Set<UidRange> ranges) {
9905         final UidRangeParcel[] stableRanges = new UidRangeParcel[ranges.size()];
9906         int index = 0;
9907         for (UidRange range : ranges) {
9908             stableRanges[index] = new UidRangeParcel(range.start, range.stop);
9909             index++;
9910         }
9911         return stableRanges;
9912     }
9913 
9914     private static UidRangeParcel[] intsToUidRangeStableParcels(
9915             final @NonNull ArraySet<Integer> uids) {
9916         final UidRangeParcel[] stableRanges = new UidRangeParcel[uids.size()];
9917         int index = 0;
9918         for (int uid : uids) {
9919             stableRanges[index] = new UidRangeParcel(uid, uid);
9920             index++;
9921         }
9922         return stableRanges;
9923     }
9924 
9925     private static UidRangeParcel[] toUidRangeStableParcels(UidRange[] ranges) {
9926         final UidRangeParcel[] stableRanges = new UidRangeParcel[ranges.length];
9927         for (int i = 0; i < ranges.length; i++) {
9928             stableRanges[i] = new UidRangeParcel(ranges[i].start, ranges[i].stop);
9929         }
9930         return stableRanges;
9931     }
9932 
9933     private void maybeCloseSockets(NetworkAgentInfo nai, Set<UidRange> ranges,
9934             UidRangeParcel[] uidRangeParcels, int[] exemptUids) {
9935         if (nai.isVPN() && !nai.networkAgentConfig.allowBypass) {
9936             try {
9937                 if (mDeps.isAtLeastU()) {
9938                     final Set<Integer> exemptUidSet = new ArraySet<>();
9939                     for (final int uid: exemptUids) {
9940                         exemptUidSet.add(uid);
9941                     }
9942                     mDeps.destroyLiveTcpSockets(UidRange.toIntRanges(ranges), exemptUidSet);
9943                 } else {
9944                     mNetd.socketDestroy(uidRangeParcels, exemptUids);
9945                 }
9946             } catch (Exception e) {
9947                 loge("Exception in socket destroy: ", e);
9948             }
9949         }
9950     }
9951 
9952     private void updateVpnUidRanges(boolean add, NetworkAgentInfo nai, Set<UidRange> uidRanges) {
9953         int[] exemptUids = new int[2];
9954         // TODO: Excluding VPN_UID is necessary in order to not to kill the TCP connection used
9955         // by PPTP. Fix this by making Vpn set the owner UID to VPN_UID instead of system when
9956         // starting a legacy VPN, and remove VPN_UID here. (b/176542831)
9957         exemptUids[0] = VPN_UID;
9958         exemptUids[1] = nai.networkCapabilities.getOwnerUid();
9959         UidRangeParcel[] ranges = toUidRangeStableParcels(uidRanges);
9960 
9961         // Close sockets before modifying uid ranges so that RST packets can reach to the server.
9962         maybeCloseSockets(nai, uidRanges, ranges, exemptUids);
9963         try {
9964             if (add) {
9965                 mNetd.networkAddUidRangesParcel(new NativeUidRangeConfig(
9966                         nai.network.netId, ranges, PREFERENCE_ORDER_VPN));
9967             } else {
9968                 mNetd.networkRemoveUidRangesParcel(new NativeUidRangeConfig(
9969                         nai.network.netId, ranges, PREFERENCE_ORDER_VPN));
9970             }
9971         } catch (Exception e) {
9972             loge("Exception while " + (add ? "adding" : "removing") + " uid ranges " + uidRanges +
9973                     " on netId " + nai.network.netId + ". " + e);
9974         }
9975         // Close sockets that established connection while requesting netd.
9976         maybeCloseSockets(nai, uidRanges, ranges, exemptUids);
9977     }
9978 
9979     private boolean isProxySetOnAnyDefaultNetwork() {
9980         ensureRunningOnConnectivityServiceThread();
9981         for (final NetworkRequestInfo nri : mDefaultNetworkRequests) {
9982             final NetworkAgentInfo nai = nri.getSatisfier();
9983             if (nai != null && nai.linkProperties.getHttpProxy() != null) {
9984                 return true;
9985             }
9986         }
9987         return false;
9988     }
9989 
9990     private void maybeSendProxyBroadcast(NetworkAgentInfo nai, NetworkCapabilities prevNc,
9991             NetworkCapabilities newNc) {
9992         // When the apps moved from/to a VPN, a proxy broadcast is needed to inform the apps that
9993         // the proxy might be changed since the default network satisfied by the apps might also
9994         // changed.
9995         // TODO: Try to track the default network that apps use and only send a proxy broadcast when
9996         //  that happens to prevent false alarms.
9997         final Set<UidRange> prevUids = prevNc == null ? null : prevNc.getUidRanges();
9998         final Set<UidRange> newUids = newNc == null ? null : newNc.getUidRanges();
9999         if (nai.isVPN() && nai.everConnected() && !UidRange.hasSameUids(prevUids, newUids)
10000                 && (nai.linkProperties.getHttpProxy() != null || isProxySetOnAnyDefaultNetwork())) {
10001             mProxyTracker.sendProxyBroadcast();
10002         }
10003     }
10004 
10005     private void updateVpnUids(@NonNull NetworkAgentInfo nai, @Nullable NetworkCapabilities prevNc,
10006             @Nullable NetworkCapabilities newNc) {
10007         Set<UidRange> prevRanges = null == prevNc ? null : prevNc.getUidRanges();
10008         Set<UidRange> newRanges = null == newNc ? null : newNc.getUidRanges();
10009         if (null == prevRanges) prevRanges = new ArraySet<>();
10010         if (null == newRanges) newRanges = new ArraySet<>();
10011         final Set<UidRange> prevRangesCopy = new ArraySet<>(prevRanges);
10012 
10013         prevRanges.removeAll(newRanges);
10014         newRanges.removeAll(prevRangesCopy);
10015 
10016         try {
10017             // When updating the VPN uid routing rules, add the new range first then remove the old
10018             // range. If old range were removed first, there would be a window between the old
10019             // range being removed and the new range being added, during which UIDs contained
10020             // in both ranges are not subject to any VPN routing rules. Adding new range before
10021             // removing old range works because, unlike the filtering rules below, it's possible to
10022             // add duplicate UID routing rules.
10023             // TODO: calculate the intersection of add & remove. Imagining that we are trying to
10024             // remove uid 3 from a set containing 1-5. Intersection of the prev and new sets is:
10025             //   [1-5] & [1-2],[4-5] == [3]
10026             // Then we can do:
10027             //   maybeCloseSockets([3])
10028             //   mNetd.networkAddUidRanges([1-2],[4-5])
10029             //   mNetd.networkRemoveUidRanges([1-5])
10030             //   maybeCloseSockets([3])
10031             // This can prevent the sockets of uid 1-2, 4-5 from being closed. It also reduce the
10032             // number of binder calls from 6 to 4.
10033             if (!newRanges.isEmpty()) {
10034                 updateVpnUidRanges(true, nai, newRanges);
10035             }
10036             if (!prevRanges.isEmpty()) {
10037                 updateVpnUidRanges(false, nai, prevRanges);
10038             }
10039             final String oldIface = getVpnIsolationInterface(nai, prevNc, nai.linkProperties);
10040             final String newIface = getVpnIsolationInterface(nai, newNc, nai.linkProperties);
10041             final boolean wasFiltering = requiresVpnAllowRule(nai, nai.linkProperties, oldIface);
10042             final boolean shouldFilter = requiresVpnAllowRule(nai, nai.linkProperties, newIface);
10043             // For VPN uid interface filtering, old ranges need to be removed before new ranges can
10044             // be added, due to the range being expanded and stored as individual UIDs. For example
10045             // the UIDs might be updated from [0, 99999] to ([0, 10012], [10014, 99999]) which means
10046             // prevRanges = [0, 99999] while newRanges = [0, 10012], [10014, 99999]. If prevRanges
10047             // were added first and then newRanges got removed later, there would be only one uid
10048             // 10013 left. A consequence of removing old ranges before adding new ranges is that
10049             // there is now a window of opportunity when the UIDs are not subject to any filtering.
10050             // Note that this is in contrast with the (more robust) update of VPN routing rules
10051             // above, where the addition of new ranges happens before the removal of old ranges.
10052             // TODO Fix this window by computing an accurate diff on Set<UidRange>, so the old range
10053             // to be removed will never overlap with the new range to be added.
10054             if (wasFiltering && !prevRanges.isEmpty()) {
10055                 mPermissionMonitor.onVpnUidRangesRemoved(oldIface, prevRanges,
10056                         prevNc.getOwnerUid());
10057             }
10058             if (shouldFilter && !newRanges.isEmpty()) {
10059                 mPermissionMonitor.onVpnUidRangesAdded(newIface, newRanges, newNc.getOwnerUid());
10060             }
10061         } catch (Exception e) {
10062             // Never crash!
10063             loge("Exception in updateVpnUids: ", e);
10064         }
10065     }
10066 
10067     private void updateAllowedUids(@NonNull NetworkAgentInfo nai,
10068             @Nullable NetworkCapabilities prevNc, @Nullable NetworkCapabilities newNc) {
10069         // In almost all cases both NC code for empty access UIDs. return as fast as possible.
10070         final boolean prevEmpty = null == prevNc || prevNc.getAllowedUidsNoCopy().isEmpty();
10071         final boolean newEmpty = null == newNc || newNc.getAllowedUidsNoCopy().isEmpty();
10072         if (prevEmpty && newEmpty) return;
10073 
10074         final ArraySet<Integer> prevUids =
10075                 null == prevNc ? new ArraySet<>() : prevNc.getAllowedUidsNoCopy();
10076         final ArraySet<Integer> newUids =
10077                 null == newNc ? new ArraySet<>() : newNc.getAllowedUidsNoCopy();
10078 
10079         if (prevUids.equals(newUids)) return;
10080 
10081         // This implementation is very simple and vastly faster for sets of Integers than
10082         // CompareOrUpdateResult, which is tuned for sets that need to be compared based on
10083         // a key computed from the value and has storage for that.
10084         final ArraySet<Integer> toRemove = new ArraySet<>(prevUids);
10085         final ArraySet<Integer> toAdd = new ArraySet<>(newUids);
10086         toRemove.removeAll(newUids);
10087         toAdd.removeAll(prevUids);
10088         try {
10089             if (!toAdd.isEmpty()) {
10090                 mNetd.networkAddUidRangesParcel(new NativeUidRangeConfig(
10091                         nai.network.netId,
10092                         intsToUidRangeStableParcels(toAdd),
10093                         PREFERENCE_ORDER_IRRELEVANT_BECAUSE_NOT_DEFAULT));
10094             }
10095             if (!toRemove.isEmpty()) {
10096                 mNetd.networkRemoveUidRangesParcel(new NativeUidRangeConfig(
10097                         nai.network.netId,
10098                         intsToUidRangeStableParcels(toRemove),
10099                         PREFERENCE_ORDER_IRRELEVANT_BECAUSE_NOT_DEFAULT));
10100             }
10101         } catch (ServiceSpecificException e) {
10102             // Has the interface disappeared since the network was built ?
10103             Log.i(TAG, "Can't set access UIDs for network " + nai.network, e);
10104         } catch (RemoteException e) {
10105             // Netd died. This usually causes a runtime restart anyway.
10106         }
10107     }
10108 
10109     public void handleUpdateLinkProperties(@NonNull NetworkAgentInfo nai,
10110             @NonNull LinkProperties newLp) {
10111         ensureRunningOnConnectivityServiceThread();
10112 
10113         if (!mNetworkAgentInfos.contains(nai)) {
10114             // Ignore updates for disconnected networks
10115             return;
10116         }
10117         if (VDBG || DDBG) {
10118             log("Update of LinkProperties for " + nai.toShortString()
10119                     + "; created=" + nai.getCreatedTime()
10120                     + "; firstConnected=" + nai.getConnectedTime());
10121         }
10122         // TODO: eliminate this defensive copy after confirming that updateLinkProperties does not
10123         // modify its oldLp parameter.
10124         updateLinkProperties(nai, newLp, new LinkProperties(nai.linkProperties));
10125     }
10126 
10127     private void sendPendingIntentForRequest(NetworkRequestInfo nri, NetworkAgentInfo networkAgent,
10128             int notificationType) {
10129         if (notificationType == ConnectivityManager.CALLBACK_AVAILABLE && !nri.mPendingIntentSent) {
10130             Intent intent = new Intent();
10131             intent.putExtra(ConnectivityManager.EXTRA_NETWORK, networkAgent.network);
10132             // If apps could file multi-layer requests with PendingIntents, they'd need to know
10133             // which of the layer is satisfied alongside with some ID for the request. Hence, if
10134             // such an API is ever implemented, there is no doubt the right request to send in
10135             // EXTRA_NETWORK_REQUEST is the active request, and whatever ID would be added would
10136             // need to be sent as a separate extra.
10137             final NetworkRequest req = nri.isMultilayerRequest()
10138                     ? nri.getActiveRequest()
10139                     // Non-multilayer listen requests do not have an active request
10140                     : nri.mRequests.get(0);
10141             if (req == null) {
10142                 Log.wtf(TAG, "No request in NRI " + nri);
10143             }
10144             intent.putExtra(ConnectivityManager.EXTRA_NETWORK_REQUEST, req);
10145             nri.mPendingIntentSent = true;
10146             sendIntent(nri.mPendingIntent, intent);
10147         }
10148         // else not handled
10149     }
10150 
10151     // TODO(b/193460475): Remove when tooling supports SystemApi to public API.
10152     @SuppressLint("NewApi")
10153     private void sendIntent(PendingIntent pendingIntent, Intent intent) {
10154         mPendingIntentWakeLock.acquire();
10155         try {
10156             if (DBG) log("Sending " + pendingIntent);
10157             final BroadcastOptions options = BroadcastOptions.makeBasic();
10158             if (mDeps.isAtLeastT()) {
10159                 // Explicitly disallow the receiver from starting activities, to prevent apps from
10160                 // utilizing the PendingIntent as a backdoor to do this.
10161                 options.setPendingIntentBackgroundActivityLaunchAllowed(false);
10162             }
10163             pendingIntent.send(mContext, 0, intent, this /* onFinished */, null /* Handler */,
10164                     null /* requiredPermission */,
10165                     mDeps.isAtLeastT() ? options.toBundle() : null);
10166         } catch (PendingIntent.CanceledException e) {
10167             if (DBG) log(pendingIntent + " was not sent, it had been canceled.");
10168             mPendingIntentWakeLock.release();
10169             releasePendingNetworkRequest(pendingIntent);
10170         }
10171         // ...otherwise, mPendingIntentWakeLock.release() gets called by onSendFinished()
10172     }
10173 
10174     @Override
10175     public void onSendFinished(PendingIntent pendingIntent, Intent intent, int resultCode,
10176             String resultData, Bundle resultExtras) {
10177         if (DBG) log("Finished sending " + pendingIntent);
10178         mPendingIntentWakeLock.release();
10179         // Release with a delay so the receiving client has an opportunity to put in its
10180         // own request.
10181         releasePendingNetworkRequestWithDelay(pendingIntent);
10182     }
10183 
10184     @Nullable
10185     private LocalNetworkInfo localNetworkInfoForNai(@NonNull final NetworkAgentInfo nai) {
10186         if (!nai.isLocalNetwork()) return null;
10187         final Network upstream;
10188         final NetworkRequest selector = nai.localNetworkConfig.getUpstreamSelector();
10189         if (null == selector) {
10190             upstream = null;
10191         } else {
10192             final NetworkRequestInfo upstreamNri = mNetworkRequests.get(selector);
10193             final NetworkAgentInfo satisfier = upstreamNri.getSatisfier();
10194             upstream = (null == satisfier) ? null : satisfier.network;
10195         }
10196         return new LocalNetworkInfo.Builder().setUpstreamNetwork(upstream).build();
10197     }
10198 
10199     // networkAgent is only allowed to be null if notificationType is
10200     // CALLBACK_UNAVAIL. This is because UNAVAIL is about no network being
10201     // available, while all other cases are about some particular network.
10202     private void callCallbackForRequest(@NonNull final NetworkRequestInfo nri,
10203             @Nullable final NetworkAgentInfo networkAgent, final int notificationType,
10204             final int arg1) {
10205         if (nri.mMessenger == null) {
10206             // Default request has no msgr. Also prevents callbacks from being invoked for
10207             // NetworkRequestInfos registered with ConnectivityDiagnostics requests. Those callbacks
10208             // are Type.LISTEN, but should not have NetworkCallbacks invoked.
10209             return;
10210         }
10211         final Bundle bundle = new Bundle();
10212         // TODO b/177608132: make sure callbacks are indexed by NRIs and not NetworkRequest objects.
10213         // TODO: check if defensive copies of data is needed.
10214         final NetworkRequest nrForCallback = nri.getNetworkRequestForCallback();
10215         putParcelable(bundle, nrForCallback);
10216         Message msg = Message.obtain();
10217         if (notificationType != ConnectivityManager.CALLBACK_UNAVAIL) {
10218             putParcelable(bundle, networkAgent.network);
10219         }
10220         final boolean includeLocationSensitiveInfo =
10221                 (nri.mCallbackFlags & NetworkCallback.FLAG_INCLUDE_LOCATION_INFO) != 0;
10222         switch (notificationType) {
10223             case ConnectivityManager.CALLBACK_AVAILABLE: {
10224                 final NetworkCapabilities nc =
10225                         createWithLocationInfoSanitizedIfNecessaryWhenParceled(
10226                                 networkCapabilitiesRestrictedForCallerPermissions(
10227                                         networkAgent.networkCapabilities, nri.mPid, nri.mUid),
10228                                 includeLocationSensitiveInfo, nri.mPid, nri.mUid,
10229                                 nrForCallback.getRequestorPackageName(),
10230                                 nri.mCallingAttributionTag);
10231                 putParcelable(bundle, nc);
10232                 putParcelable(bundle, linkPropertiesRestrictedForCallerPermissions(
10233                         networkAgent.linkProperties, nri.mPid, nri.mUid));
10234                 // The local network info is often null, so can't use the static putParcelable
10235                 // method here.
10236                 bundle.putParcelable(LocalNetworkInfo.class.getSimpleName(),
10237                         localNetworkInfoForNai(networkAgent));
10238                 // For this notification, arg1 contains the blocked status.
10239                 msg.arg1 = arg1;
10240                 break;
10241             }
10242             case ConnectivityManager.CALLBACK_LOSING: {
10243                 msg.arg1 = arg1;
10244                 break;
10245             }
10246             case ConnectivityManager.CALLBACK_CAP_CHANGED: {
10247                 // networkAgent can't be null as it has been accessed a few lines above.
10248                 final NetworkCapabilities netCap =
10249                         networkCapabilitiesRestrictedForCallerPermissions(
10250                                 networkAgent.networkCapabilities, nri.mPid, nri.mUid);
10251                 putParcelable(
10252                         bundle,
10253                         createWithLocationInfoSanitizedIfNecessaryWhenParceled(
10254                                 netCap, includeLocationSensitiveInfo, nri.mPid, nri.mUid,
10255                                 nrForCallback.getRequestorPackageName(),
10256                                 nri.mCallingAttributionTag));
10257                 break;
10258             }
10259             case ConnectivityManager.CALLBACK_IP_CHANGED: {
10260                 putParcelable(bundle, linkPropertiesRestrictedForCallerPermissions(
10261                         networkAgent.linkProperties, nri.mPid, nri.mUid));
10262                 break;
10263             }
10264             case ConnectivityManager.CALLBACK_BLK_CHANGED: {
10265                 maybeLogBlockedStatusChanged(nri, networkAgent.network, arg1);
10266                 msg.arg1 = arg1;
10267                 break;
10268             }
10269             case ConnectivityManager.CALLBACK_LOCAL_NETWORK_INFO_CHANGED: {
10270                 if (!networkAgent.isLocalNetwork()) {
10271                     Log.wtf(TAG, "Callback for local info for a non-local network");
10272                     return;
10273                 }
10274                 putParcelable(bundle, localNetworkInfoForNai(networkAgent));
10275                 break;
10276             }
10277         }
10278         msg.what = notificationType;
10279         msg.setData(bundle);
10280         try {
10281             if (VDBG) {
10282                 String notification = ConnectivityManager.getCallbackName(notificationType);
10283                 log("sending notification " + notification + " for " + nrForCallback);
10284             }
10285             nri.mMessenger.send(msg);
10286         } catch (RemoteException e) {
10287             // may occur naturally in the race of binder death.
10288             loge("RemoteException caught trying to send a callback msg for " + nrForCallback);
10289         }
10290     }
10291 
10292     private static <T extends Parcelable> void putParcelable(Bundle bundle, T t) {
10293         bundle.putParcelable(t.getClass().getSimpleName(), t);
10294     }
10295 
10296     /**
10297      * Returns whether reassigning a request from an NAI to another can be done gracefully.
10298      *
10299      * When a request should be assigned to a new network, it is normally lingered to give
10300      * time for apps to gracefully migrate their connections. When both networks are on the same
10301      * radio, but that radio can't do time-sharing efficiently, this may end up being
10302      * counter-productive because any traffic on the old network may drastically reduce the
10303      * performance of the new network.
10304      * The stack supports a configuration to let modem vendors state that their radio can't
10305      * do time-sharing efficiently. If this configuration is set, the stack assumes moving
10306      * from one cell network to another can't be done gracefully.
10307      *
10308      * @param oldNai the old network serving the request
10309      * @param newNai the new network serving the request
10310      * @return whether the switch can be graceful
10311      */
10312     private boolean canSupportGracefulNetworkSwitch(@NonNull final NetworkAgentInfo oldSatisfier,
10313             @NonNull final NetworkAgentInfo newSatisfier) {
10314         if (mCellularRadioTimesharingCapable) return true;
10315         return !oldSatisfier.networkCapabilities.hasSingleTransport(TRANSPORT_CELLULAR)
10316                 || !newSatisfier.networkCapabilities.hasSingleTransport(TRANSPORT_CELLULAR)
10317                 || !newSatisfier.getScore().hasPolicy(POLICY_TRANSPORT_PRIMARY);
10318     }
10319 
10320     private void teardownUnneededNetwork(NetworkAgentInfo nai) {
10321         if (nai.numRequestNetworkRequests() != 0) {
10322             for (int i = 0; i < nai.numNetworkRequests(); i++) {
10323                 NetworkRequest nr = nai.requestAt(i);
10324                 // Ignore listening and track default requests.
10325                 if (!nr.isRequest()) continue;
10326                 loge("Dead network still had at least " + nr);
10327                 break;
10328             }
10329         }
10330         nai.disconnect();
10331     }
10332 
10333     private void handleLingerComplete(NetworkAgentInfo oldNetwork) {
10334         if (oldNetwork == null) {
10335             loge("Unknown NetworkAgentInfo in handleLingerComplete");
10336             return;
10337         }
10338         if (DBG) log("handleLingerComplete for " + oldNetwork.toShortString());
10339 
10340         // If we get here it means that the last linger timeout for this network expired. So there
10341         // must be no other active linger timers, and we must stop lingering.
10342         oldNetwork.clearInactivityState();
10343 
10344         if (unneeded(oldNetwork, UnneededFor.TEARDOWN)) {
10345             // Tear the network down.
10346             teardownUnneededNetwork(oldNetwork);
10347         } else {
10348             // Put the network in the background if it doesn't satisfy any foreground request.
10349             updateCapabilitiesForNetwork(oldNetwork);
10350         }
10351     }
10352 
10353     private void processDefaultNetworkChanges(@NonNull final NetworkReassignment changes) {
10354         boolean isDefaultChanged = false;
10355         for (final NetworkRequestInfo defaultRequestInfo : mDefaultNetworkRequests) {
10356             final NetworkReassignment.RequestReassignment reassignment =
10357                     changes.getReassignment(defaultRequestInfo);
10358             if (null == reassignment) {
10359                 continue;
10360             }
10361             // reassignment only contains those instances where the satisfying network changed.
10362             isDefaultChanged = true;
10363             // Notify system services of the new default.
10364             makeDefault(defaultRequestInfo, reassignment.mOldNetwork, reassignment.mNewNetwork);
10365         }
10366 
10367         if (isDefaultChanged) {
10368             // Hold a wakelock for a short time to help apps in migrating to a new default.
10369             scheduleReleaseNetworkTransitionWakelock();
10370         }
10371     }
10372 
10373     private void resetHttpProxyForNonDefaultNetwork(NetworkAgentInfo oldDefaultNetwork) {
10374         if (null == oldDefaultNetwork) return;
10375         // The network stopped being the default. If it was using a PAC proxy, then the
10376         // proxy needs to be reset, otherwise HTTP requests on this network may be sent
10377         // to the local proxy server, which would forward them over the newly default network.
10378         final ProxyInfo proxyInfo = oldDefaultNetwork.linkProperties.getHttpProxy();
10379         if (null == proxyInfo || !proxyInfo.isPacProxy()) return;
10380         oldDefaultNetwork.linkProperties.setHttpProxy(new ProxyInfo(proxyInfo.getPacFileUrl()));
10381         notifyNetworkCallbacks(oldDefaultNetwork, CALLBACK_IP_CHANGED);
10382     }
10383 
10384     private void makeDefault(@NonNull final NetworkRequestInfo nri,
10385             @Nullable final NetworkAgentInfo oldDefaultNetwork,
10386             @Nullable final NetworkAgentInfo newDefaultNetwork) {
10387         if (DBG) {
10388             log("Switching to new default network for: " + nri + " using " + newDefaultNetwork);
10389         }
10390 
10391         // Fix up the NetworkCapabilities of any networks that have this network as underlying.
10392         if (newDefaultNetwork != null) {
10393             propagateUnderlyingNetworkCapabilities(newDefaultNetwork.network);
10394         }
10395 
10396         // Set an app level managed default and return since further processing only applies to the
10397         // default network.
10398         if (mDefaultRequest != nri) {
10399             makeDefaultForApps(nri, oldDefaultNetwork, newDefaultNetwork);
10400             return;
10401         }
10402 
10403         makeDefaultNetwork(newDefaultNetwork);
10404 
10405         if (oldDefaultNetwork != null) {
10406             mLingerMonitor.noteLingerDefaultNetwork(oldDefaultNetwork, newDefaultNetwork);
10407         }
10408         mNetworkActivityTracker.updateDefaultNetwork(newDefaultNetwork, oldDefaultNetwork);
10409         maybeDestroyPendingSockets(newDefaultNetwork, oldDefaultNetwork);
10410         mProxyTracker.setDefaultProxy(null != newDefaultNetwork
10411                 ? newDefaultNetwork.linkProperties.getHttpProxy() : null);
10412         resetHttpProxyForNonDefaultNetwork(oldDefaultNetwork);
10413         updateTcpBufferSizes(null != newDefaultNetwork
10414                 ? newDefaultNetwork.linkProperties.getTcpBufferSizes() : null);
10415         notifyIfacesChangedForNetworkStats();
10416     }
10417 
10418     private void makeDefaultForApps(@NonNull final NetworkRequestInfo nri,
10419             @Nullable final NetworkAgentInfo oldDefaultNetwork,
10420             @Nullable final NetworkAgentInfo newDefaultNetwork) {
10421         try {
10422             if (VDBG) {
10423                 log("Setting default network for " + nri
10424                         + " using UIDs " + nri.getUids()
10425                         + " with old network " + (oldDefaultNetwork != null
10426                         ? oldDefaultNetwork.network().getNetId() : "null")
10427                         + " and new network " + (newDefaultNetwork != null
10428                         ? newDefaultNetwork.network().getNetId() : "null"));
10429             }
10430             if (nri.getUids().isEmpty()) {
10431                 throw new IllegalStateException("makeDefaultForApps called without specifying"
10432                         + " any applications to set as the default." + nri);
10433             }
10434             if (null != newDefaultNetwork) {
10435                 mNetd.networkAddUidRangesParcel(new NativeUidRangeConfig(
10436                         newDefaultNetwork.network.getNetId(),
10437                         toUidRangeStableParcels(nri.getUids()),
10438                         nri.getPreferenceOrderForNetd()));
10439             }
10440             if (null != oldDefaultNetwork) {
10441                 mNetd.networkRemoveUidRangesParcel(new NativeUidRangeConfig(
10442                         oldDefaultNetwork.network.getNetId(),
10443                         toUidRangeStableParcels(nri.getUids()),
10444                         nri.getPreferenceOrderForNetd()));
10445             }
10446         } catch (RemoteException | ServiceSpecificException e) {
10447             loge("Exception setting app default network", e);
10448         }
10449     }
10450 
10451     /**
10452      * Collect restricted uid ranges for the given network and UserHandle, these uids
10453      * are not restricted for matched enterprise networks but being restricted for non-matched
10454      * enterprise networks and non-enterprise networks.
10455      */
10456     @NonNull
10457     private ArraySet<UidRange> getRestrictedUidRangesForEnterpriseBlocking(
10458             @NonNull NetworkAgentInfo nai, @NonNull UserHandle user) {
10459         final ArraySet<UidRange> restrictedUidRanges = new ArraySet<>();
10460         for (final ProfileNetworkPreferenceInfo pref : mProfileNetworkPreferences) {
10461             if (!pref.user.equals(user) || !pref.blockingNonEnterprise) continue;
10462 
10463             if (nai.networkCapabilities.hasCapability(NET_CAPABILITY_ENTERPRISE)) {
10464                 // The NC is built from a `ProfileNetworkPreference` which has only one
10465                 // enterprise ID, so it's guaranteed to have exactly one.
10466                 final int prefId = pref.capabilities.getEnterpriseIds()[0];
10467                 if (nai.networkCapabilities.hasEnterpriseId(prefId)) {
10468                     continue;
10469                 }
10470             }
10471 
10472             if (UidRangeUtils.doesRangeSetOverlap(restrictedUidRanges,
10473                     pref.capabilities.getUidRanges())) {
10474                 throw new IllegalArgumentException(
10475                         "Overlapping uid range in preference: " + pref);
10476             }
10477             restrictedUidRanges.addAll(pref.capabilities.getUidRanges());
10478         }
10479         return restrictedUidRanges;
10480     }
10481 
10482     private void updateProfileAllowedNetworks() {
10483         // Netd command is not implemented before U.
10484         if (!mDeps.isAtLeastU()) return;
10485 
10486         ensureRunningOnConnectivityServiceThread();
10487         final ArrayList<NativeUidRangeConfig> configs = new ArrayList<>();
10488         final List<UserHandle> users = mContext.getSystemService(UserManager.class)
10489                         .getUserHandles(true /* excludeDying */);
10490         if (users.isEmpty()) {
10491             throw new IllegalStateException("No user is available");
10492         }
10493 
10494         for (final NetworkAgentInfo nai : mNetworkAgentInfos) {
10495             ArraySet<UidRange> allowedUidRanges = new ArraySet<>();
10496             for (final UserHandle user : users) {
10497                 final ArraySet<UidRange> restrictedUidRanges =
10498                         getRestrictedUidRangesForEnterpriseBlocking(nai, user);
10499                 allowedUidRanges.addAll(UidRangeUtils.removeRangeSetFromUidRange(
10500                         UidRange.createForUser(user), restrictedUidRanges));
10501             }
10502 
10503             final UidRangeParcel[] rangesParcel = toUidRangeStableParcels(allowedUidRanges);
10504             configs.add(new NativeUidRangeConfig(
10505                     nai.network.netId, rangesParcel, 0 /* subPriority */));
10506         }
10507 
10508         // The netd API replaces the previous configs with the current configs.
10509         // Thus, for network disconnection or preference removal, no need to
10510         // unset previous config. Instead, collecting all currently needed
10511         // configs and issue to netd.
10512         try {
10513             mNetd.setNetworkAllowlist(configs.toArray(new NativeUidRangeConfig[0]));
10514         } catch (ServiceSpecificException e) {
10515             // Has the interface disappeared since the network was built?
10516             Log.wtf(TAG, "Unexpected ServiceSpecificException", e);
10517         } catch (RemoteException e) {
10518             // Netd died. This will cause a runtime restart anyway.
10519             Log.wtf(TAG, "Unexpected RemoteException", e);
10520         }
10521     }
10522 
10523     private void makeDefaultNetwork(@Nullable final NetworkAgentInfo newDefaultNetwork) {
10524         try {
10525             if (null != newDefaultNetwork) {
10526                 mNetd.networkSetDefault(newDefaultNetwork.network.getNetId());
10527             } else {
10528                 mNetd.networkClearDefault();
10529             }
10530         } catch (RemoteException | ServiceSpecificException e) {
10531             loge("Exception setting default network :" + e);
10532         }
10533     }
10534 
10535     private void processListenRequests(@NonNull final NetworkAgentInfo nai) {
10536         // For consistency with previous behaviour, send onLost callbacks before onAvailable.
10537         processNewlyLostListenRequests(nai);
10538         notifyNetworkCallbacks(nai, ConnectivityManager.CALLBACK_CAP_CHANGED);
10539         processNewlySatisfiedListenRequests(nai);
10540     }
10541 
10542     private void processNewlyLostListenRequests(@NonNull final NetworkAgentInfo nai) {
10543         for (final NetworkRequestInfo nri : mNetworkRequests.values()) {
10544             if (nri.isMultilayerRequest()) {
10545                 continue;
10546             }
10547             final NetworkRequest nr = nri.mRequests.get(0);
10548             if (!nr.isListen()) continue;
10549             if (nai.isSatisfyingRequest(nr.requestId) && !nai.satisfies(nr)) {
10550                 nai.removeRequest(nr.requestId);
10551                 callCallbackForRequest(nri, nai, ConnectivityManager.CALLBACK_LOST, 0);
10552             }
10553         }
10554     }
10555 
10556     private void processNewlySatisfiedListenRequests(@NonNull final NetworkAgentInfo nai) {
10557         for (final NetworkRequestInfo nri : mNetworkRequests.values()) {
10558             if (nri.isMultilayerRequest()) {
10559                 continue;
10560             }
10561             final NetworkRequest nr = nri.mRequests.get(0);
10562             if (!nr.isListen()) continue;
10563             if (nai.satisfies(nr) && !nai.isSatisfyingRequest(nr.requestId)) {
10564                 nai.addRequest(nr);
10565                 notifyNetworkAvailable(nai, nri);
10566             }
10567         }
10568     }
10569 
10570     // An accumulator class to gather the list of changes that result from a rematch.
10571     private static class NetworkReassignment {
10572         static class RequestReassignment {
10573             @NonNull public final NetworkRequestInfo mNetworkRequestInfo;
10574             @Nullable public final NetworkRequest mOldNetworkRequest;
10575             @Nullable public final NetworkRequest mNewNetworkRequest;
10576             @Nullable public final NetworkAgentInfo mOldNetwork;
10577             @Nullable public final NetworkAgentInfo mNewNetwork;
10578             RequestReassignment(@NonNull final NetworkRequestInfo networkRequestInfo,
10579                     @Nullable final NetworkRequest oldNetworkRequest,
10580                     @Nullable final NetworkRequest newNetworkRequest,
10581                     @Nullable final NetworkAgentInfo oldNetwork,
10582                     @Nullable final NetworkAgentInfo newNetwork) {
10583                 mNetworkRequestInfo = networkRequestInfo;
10584                 mOldNetworkRequest = oldNetworkRequest;
10585                 mNewNetworkRequest = newNetworkRequest;
10586                 mOldNetwork = oldNetwork;
10587                 mNewNetwork = newNetwork;
10588             }
10589 
10590             public String toString() {
10591                 final NetworkRequest requestToShow = null != mNewNetworkRequest
10592                         ? mNewNetworkRequest : mNetworkRequestInfo.mRequests.get(0);
10593                 return requestToShow.requestId + " : "
10594                         + (null != mOldNetwork ? mOldNetwork.network.getNetId() : "null")
10595                         + " → " + (null != mNewNetwork ? mNewNetwork.network.getNetId() : "null");
10596             }
10597         }
10598 
10599         @NonNull private final ArrayList<RequestReassignment> mReassignments = new ArrayList<>();
10600 
10601         @NonNull Iterable<RequestReassignment> getRequestReassignments() {
10602             return mReassignments;
10603         }
10604 
10605         void addRequestReassignment(@NonNull final RequestReassignment reassignment) {
10606             if (Build.isDebuggable()) {
10607                 // The code is never supposed to add two reassignments of the same request. Make
10608                 // sure this stays true, but without imposing this expensive check on all
10609                 // reassignments on all user devices.
10610                 for (final RequestReassignment existing : mReassignments) {
10611                     if (existing.mNetworkRequestInfo.equals(reassignment.mNetworkRequestInfo)) {
10612                         throw new IllegalStateException("Trying to reassign ["
10613                                 + reassignment + "] but already have ["
10614                                 + existing + "]");
10615                     }
10616                 }
10617             }
10618             mReassignments.add(reassignment);
10619         }
10620 
10621         // Will return null if this reassignment does not change the network assigned to
10622         // the passed request.
10623         @Nullable
10624         private RequestReassignment getReassignment(@NonNull final NetworkRequestInfo nri) {
10625             for (final RequestReassignment event : getRequestReassignments()) {
10626                 if (nri == event.mNetworkRequestInfo) return event;
10627             }
10628             return null;
10629         }
10630 
10631         public String toString() {
10632             final StringJoiner sj = new StringJoiner(", " /* delimiter */,
10633                     "NetReassign [" /* prefix */, "]" /* suffix */);
10634             if (mReassignments.isEmpty()) return sj.add("no changes").toString();
10635             for (final RequestReassignment rr : getRequestReassignments()) {
10636                 sj.add(rr.toString());
10637             }
10638             return sj.toString();
10639         }
10640 
10641         public String debugString() {
10642             final StringBuilder sb = new StringBuilder();
10643             sb.append("NetworkReassignment :");
10644             if (mReassignments.isEmpty()) return sb.append(" no changes").toString();
10645             for (final RequestReassignment rr : getRequestReassignments()) {
10646                 sb.append("\n  ").append(rr);
10647             }
10648             return sb.append("\n").toString();
10649         }
10650     }
10651 
10652     private void updateSatisfiersForRematchRequest(@NonNull final NetworkRequestInfo nri,
10653             @Nullable final NetworkRequest previousRequest,
10654             @Nullable final NetworkRequest newRequest,
10655             @Nullable final NetworkAgentInfo previousSatisfier,
10656             @Nullable final NetworkAgentInfo newSatisfier,
10657             final long now) {
10658         if (null != newSatisfier && mNoServiceNetwork != newSatisfier) {
10659             if (VDBG) log("rematch for " + newSatisfier.toShortString());
10660             if (null != previousRequest && null != previousSatisfier) {
10661                 if (VDBG || DDBG) {
10662                     log("   accepting network in place of " + previousSatisfier.toShortString()
10663                             + " for " + newRequest);
10664                 }
10665                 previousSatisfier.removeRequest(previousRequest.requestId);
10666                 if (canSupportGracefulNetworkSwitch(previousSatisfier, newSatisfier)
10667                         && !previousSatisfier.isDestroyed()) {
10668                     // If this network switch can't be supported gracefully, the request is not
10669                     // lingered. This allows letting go of the network sooner to reclaim some
10670                     // performance on the new network, since the radio can't do both at the same
10671                     // time while preserving good performance.
10672                     //
10673                     // Also don't linger the request if the old network has been destroyed.
10674                     // A destroyed network does not provide actual network connectivity, so
10675                     // lingering it is not useful. In particular this ensures that a destroyed
10676                     // network is outscored by its replacement,
10677                     // then it is torn down immediately instead of being lingered, and any apps that
10678                     // were using it immediately get onLost and can connect using the new network.
10679                     previousSatisfier.lingerRequest(previousRequest.requestId, now);
10680                 }
10681             } else {
10682                 if (VDBG || DDBG) log("   accepting network in place of null for " + newRequest);
10683             }
10684 
10685             // To prevent constantly CPU wake up for nascent timer, if a network comes up
10686             // and immediately satisfies a request then remove the timer. This will happen for
10687             // all networks except in the case of an underlying network for a VCN.
10688             if (newSatisfier.isNascent()) {
10689                 newSatisfier.unlingerRequest(NetworkRequest.REQUEST_ID_NONE);
10690                 newSatisfier.unsetInactive();
10691             }
10692 
10693             // if newSatisfier is not null, then newRequest may not be null.
10694             newSatisfier.unlingerRequest(newRequest.requestId);
10695             if (!newSatisfier.addRequest(newRequest)) {
10696                 Log.wtf(TAG, "BUG: " + newSatisfier.toShortString() + " already has "
10697                         + newRequest);
10698             }
10699         } else if (null != previousRequest && null != previousSatisfier) {
10700             if (DBG) {
10701                 log("Network " + previousSatisfier.toShortString() + " stopped satisfying"
10702                         + " request " + previousRequest.requestId);
10703             }
10704             previousSatisfier.removeRequest(previousRequest.requestId);
10705         }
10706         nri.setSatisfier(newSatisfier, newRequest);
10707     }
10708 
10709     /**
10710      * This function is triggered when something can affect what network should satisfy what
10711      * request, and it computes the network reassignment from the passed collection of requests to
10712      * network match to the one that the system should now have. That data is encoded in an
10713      * object that is a list of changes, each of them having an NRI, and old satisfier, and a new
10714      * satisfier.
10715      *
10716      * After the reassignment is computed, it is applied to the state objects.
10717      *
10718      * @param networkRequests the nri objects to evaluate for possible network reassignment
10719      * @return NetworkReassignment listing of proposed network assignment changes
10720      */
10721     @NonNull
10722     private NetworkReassignment computeNetworkReassignment(
10723             @NonNull final Collection<NetworkRequestInfo> networkRequests) {
10724         final NetworkReassignment changes = new NetworkReassignment();
10725 
10726         // Gather the list of all relevant agents.
10727         final ArrayList<NetworkAgentInfo> nais = new ArrayList<>();
10728         for (final NetworkAgentInfo nai : mNetworkAgentInfos) {
10729             nais.add(nai);
10730         }
10731 
10732         for (final NetworkRequestInfo nri : networkRequests) {
10733             // Non-multilayer listen requests can be ignored.
10734             if (!nri.isMultilayerRequest() && nri.mRequests.get(0).isListen()) {
10735                 continue;
10736             }
10737             NetworkAgentInfo bestNetwork = null;
10738             NetworkRequest bestRequest = null;
10739             for (final NetworkRequest req : nri.mRequests) {
10740                 bestNetwork = mNetworkRanker.getBestNetwork(req, nais, nri.getSatisfier());
10741                 // Stop evaluating as the highest possible priority request is satisfied.
10742                 if (null != bestNetwork) {
10743                     bestRequest = req;
10744                     break;
10745                 }
10746             }
10747             if (null == bestNetwork && isDefaultBlocked(nri)) {
10748                 // Remove default networking if disallowed for managed default requests.
10749                 bestNetwork = mNoServiceNetwork;
10750             }
10751             if (nri.getSatisfier() != bestNetwork) {
10752                 // bestNetwork may be null if no network can satisfy this request.
10753                 changes.addRequestReassignment(new NetworkReassignment.RequestReassignment(
10754                         nri, nri.mActiveRequest, bestRequest, nri.getSatisfier(), bestNetwork));
10755             }
10756         }
10757         return changes;
10758     }
10759 
10760     private Set<NetworkRequestInfo> getNrisFromGlobalRequests() {
10761         return new HashSet<>(mNetworkRequests.values());
10762     }
10763 
10764     /**
10765      * Attempt to rematch all Networks with all NetworkRequests.  This may result in Networks
10766      * being disconnected.
10767      */
10768     private void rematchAllNetworksAndRequests() {
10769         rematchNetworksAndRequests(getNrisFromGlobalRequests());
10770     }
10771 
10772     /**
10773      * Attempt to rematch all Networks with given NetworkRequests.  This may result in Networks
10774      * being disconnected.
10775      */
10776     private void rematchNetworksAndRequests(
10777             @NonNull final Set<NetworkRequestInfo> networkRequests) {
10778         ensureRunningOnConnectivityServiceThread();
10779         // TODO: This may be slow, and should be optimized.
10780         final long start = SystemClock.elapsedRealtime();
10781         final NetworkReassignment changes = computeNetworkReassignment(networkRequests);
10782         final long computed = SystemClock.elapsedRealtime();
10783         applyNetworkReassignment(changes, start);
10784         final long applied = SystemClock.elapsedRealtime();
10785         issueNetworkNeeds();
10786         final long end = SystemClock.elapsedRealtime();
10787         if (VDBG || DDBG) {
10788             log(String.format("Rematched networks [computed %dms] [applied %dms] [issued %d]",
10789                     computed - start, applied - computed, end - applied));
10790             log(changes.debugString());
10791         } else if (DBG) {
10792             // Shorter form, only one line of log
10793             log(String.format("%s [c %d] [a %d] [i %d]", changes.toString(),
10794                     computed - start, applied - computed, end - applied));
10795         }
10796     }
10797 
10798     private boolean hasSameInterfaceName(@Nullable final NetworkAgentInfo nai1,
10799             @Nullable final NetworkAgentInfo nai2) {
10800         if (null == nai1) return null == nai2;
10801         if (null == nai2) return false;
10802         return nai1.linkProperties.getInterfaceName()
10803                 .equals(nai2.linkProperties.getInterfaceName());
10804     }
10805 
10806     private void applyNetworkReassignment(@NonNull final NetworkReassignment changes,
10807             final long now) {
10808         final Collection<NetworkAgentInfo> nais = mNetworkAgentInfos;
10809 
10810         // Since most of the time there are only 0 or 1 background networks, it would probably
10811         // be more efficient to just use an ArrayList here. TODO : measure performance
10812         final ArraySet<NetworkAgentInfo> oldBgNetworks = new ArraySet<>();
10813         for (final NetworkAgentInfo nai : nais) {
10814             if (nai.isBackgroundNetwork()) oldBgNetworks.add(nai);
10815         }
10816 
10817         // First, update the lists of satisfied requests in the network agents. This is necessary
10818         // because some code later depends on this state to be correct, most prominently computing
10819         // the linger status.
10820         for (final NetworkReassignment.RequestReassignment event :
10821                 changes.getRequestReassignments()) {
10822             updateSatisfiersForRematchRequest(event.mNetworkRequestInfo,
10823                     event.mOldNetworkRequest, event.mNewNetworkRequest,
10824                     event.mOldNetwork, event.mNewNetwork,
10825                     now);
10826         }
10827 
10828         // Process default network changes if applicable.
10829         processDefaultNetworkChanges(changes);
10830 
10831         // Update forwarding rules for the upstreams of local networks. Do this before sending
10832         // onAvailable so that by the time onAvailable is sent the forwarding rules are set up.
10833         // Don't send CALLBACK_LOCAL_NETWORK_INFO_CHANGED yet though : they should be sent after
10834         // onAvailable so clients know what network the change is about. Store such changes in
10835         // an array that's only allocated if necessary (because it's almost never necessary).
10836         ArrayList<NetworkAgentInfo> localInfoChangedAgents = null;
10837         for (final NetworkAgentInfo nai : mNetworkAgentInfos) {
10838             if (!nai.isLocalNetwork()) continue;
10839             final NetworkRequest nr = nai.localNetworkConfig.getUpstreamSelector();
10840             if (null == nr) continue; // No upstream for this local network
10841             final NetworkRequestInfo nri = mNetworkRequests.get(nr);
10842             final NetworkReassignment.RequestReassignment change = changes.getReassignment(nri);
10843             if (null == change) continue; // No change in upstreams for this network
10844             final String fromIface = nai.linkProperties.getInterfaceName();
10845             if (!hasSameInterfaceName(change.mOldNetwork, change.mNewNetwork)
10846                     || change.mOldNetwork.isDestroyed()) {
10847                 // There can be a change with the same interface name if the new network is the
10848                 // replacement for the old network that was unregisteredAfterReplacement.
10849                 try {
10850                     if (null != change.mOldNetwork) {
10851                         mRoutingCoordinatorService.removeInterfaceForward(fromIface,
10852                                 change.mOldNetwork.linkProperties.getInterfaceName());
10853                         disableMulticastRouting(fromIface,
10854                                 change.mOldNetwork.linkProperties.getInterfaceName());
10855                     }
10856                     // If the new upstream is already destroyed, there is no point in setting up
10857                     // a forward (in fact, it might forward to the interface for some new network !)
10858                     // Later when the upstream disconnects CS will try to remove the forward, which
10859                     // is ignored with a benign log by RoutingCoordinatorService.
10860                     if (null != change.mNewNetwork && !change.mNewNetwork.isDestroyed()) {
10861                         mRoutingCoordinatorService.addInterfaceForward(fromIface,
10862                                 change.mNewNetwork.linkProperties.getInterfaceName());
10863                         applyMulticastRoutingConfig(fromIface,
10864                                 change.mNewNetwork.linkProperties.getInterfaceName(),
10865                                 nai.localNetworkConfig);
10866                     }
10867                 } catch (final RemoteException e) {
10868                     loge("Can't update forwarding rules", e);
10869                 }
10870             }
10871             if (null == localInfoChangedAgents) localInfoChangedAgents = new ArrayList<>();
10872             localInfoChangedAgents.add(nai);
10873         }
10874 
10875         // Notify requested networks are available after the default net is switched, but
10876         // before LegacyTypeTracker sends legacy broadcasts
10877         for (final NetworkReassignment.RequestReassignment event :
10878                 changes.getRequestReassignments()) {
10879             if (null != event.mNewNetwork) {
10880                 notifyNetworkAvailable(event.mNewNetwork, event.mNetworkRequestInfo);
10881             } else {
10882                 callCallbackForRequest(event.mNetworkRequestInfo, event.mOldNetwork,
10883                         ConnectivityManager.CALLBACK_LOST, 0);
10884             }
10885         }
10886 
10887         // Update the inactivity state before processing listen callbacks, because the background
10888         // computation depends on whether the network is inactive. Don't send the LOSING callbacks
10889         // just yet though, because they have to be sent after the listens are processed to keep
10890         // backward compatibility.
10891         final ArrayList<NetworkAgentInfo> inactiveNetworks = new ArrayList<>();
10892         for (final NetworkAgentInfo nai : nais) {
10893             // Rematching may have altered the inactivity state of some networks, so update all
10894             // inactivity timers. updateInactivityState reads the state from the network agent
10895             // and does nothing if the state has not changed : the source of truth is controlled
10896             // with NetworkAgentInfo#lingerRequest and NetworkAgentInfo#unlingerRequest, which
10897             // have been called while rematching the individual networks above.
10898             if (updateInactivityState(nai, now)) {
10899                 inactiveNetworks.add(nai);
10900             }
10901         }
10902 
10903         for (final NetworkAgentInfo nai : nais) {
10904             final boolean oldBackground = oldBgNetworks.contains(nai);
10905             // Process listen requests and update capabilities if the background state has
10906             // changed for this network. For consistency with previous behavior, send onLost
10907             // callbacks before onAvailable.
10908             processNewlyLostListenRequests(nai);
10909             if (oldBackground != nai.isBackgroundNetwork()) {
10910                 applyBackgroundChangeForRematch(nai);
10911             }
10912             processNewlySatisfiedListenRequests(nai);
10913         }
10914 
10915         for (final NetworkAgentInfo nai : inactiveNetworks) {
10916             // For nascent networks, if connecting with no foreground request, skip broadcasting
10917             // LOSING for backward compatibility. This is typical when mobile data connected while
10918             // wifi connected with mobile data always-on enabled.
10919             if (nai.isNascent()) continue;
10920             notifyNetworkLosing(nai, now);
10921         }
10922 
10923         // Send LOCAL_NETWORK_INFO_CHANGED callbacks now that onAvailable and onLost have been sent.
10924         if (null != localInfoChangedAgents) {
10925             for (final NetworkAgentInfo nai : localInfoChangedAgents) {
10926                 notifyNetworkCallbacks(nai,
10927                         ConnectivityManager.CALLBACK_LOCAL_NETWORK_INFO_CHANGED);
10928             }
10929         }
10930 
10931         updateLegacyTypeTrackerAndVpnLockdownForRematch(changes, nais);
10932 
10933         // Tear down all unneeded networks.
10934         for (NetworkAgentInfo nai : mNetworkAgentInfos) {
10935             if (unneeded(nai, UnneededFor.TEARDOWN)) {
10936                 if (nai.getInactivityExpiry() > 0) {
10937                     // This network has active linger timers and no requests, but is not
10938                     // lingering. Linger it.
10939                     //
10940                     // One way (the only way?) this can happen if this network is unvalidated
10941                     // and became unneeded due to another network improving its score to the
10942                     // point where this network will no longer be able to satisfy any requests
10943                     // even if it validates.
10944                     if (updateInactivityState(nai, now)) {
10945                         notifyNetworkLosing(nai, now);
10946                     }
10947                 } else {
10948                     if (DBG) log("Reaping " + nai.toShortString());
10949                     teardownUnneededNetwork(nai);
10950                 }
10951             }
10952         }
10953     }
10954 
10955     /**
10956      * Apply a change in background state resulting from rematching networks with requests.
10957      *
10958      * During rematch, a network may change background states by starting to satisfy or stopping
10959      * to satisfy a foreground request. Listens don't count for this. When a network changes
10960      * background states, its capabilities need to be updated and callbacks fired for the
10961      * capability change.
10962      *
10963      * @param nai The network that changed background states
10964      */
10965     private void applyBackgroundChangeForRematch(@NonNull final NetworkAgentInfo nai) {
10966         final NetworkCapabilities newNc = mixInCapabilities(nai, nai.networkCapabilities);
10967         if (Objects.equals(nai.networkCapabilities, newNc)) return;
10968         updateNetworkPermissions(nai, newNc);
10969         nai.getAndSetNetworkCapabilities(newNc);
10970         notifyNetworkCallbacks(nai, ConnectivityManager.CALLBACK_CAP_CHANGED);
10971     }
10972 
10973     private void updateLegacyTypeTrackerAndVpnLockdownForRematch(
10974             @NonNull final NetworkReassignment changes,
10975             @NonNull final Collection<NetworkAgentInfo> nais) {
10976         final NetworkReassignment.RequestReassignment reassignmentOfDefault =
10977                 changes.getReassignment(mDefaultRequest);
10978         final NetworkAgentInfo oldDefaultNetwork =
10979                 null != reassignmentOfDefault ? reassignmentOfDefault.mOldNetwork : null;
10980         final NetworkAgentInfo newDefaultNetwork =
10981                 null != reassignmentOfDefault ? reassignmentOfDefault.mNewNetwork : null;
10982 
10983         if (oldDefaultNetwork != newDefaultNetwork) {
10984             // Maintain the illusion : since the legacy API only understands one network at a time,
10985             // if the default network changed, apps should see a disconnected broadcast for the
10986             // old default network before they see a connected broadcast for the new one.
10987             if (oldDefaultNetwork != null) {
10988                 mLegacyTypeTracker.remove(oldDefaultNetwork.networkInfo.getType(),
10989                         oldDefaultNetwork, true);
10990             }
10991             if (newDefaultNetwork != null) {
10992                 // The new default network can be newly null if and only if the old default
10993                 // network doesn't satisfy the default request any more because it lost a
10994                 // capability.
10995                 mDefaultInetConditionPublished = newDefaultNetwork.isValidated() ? 100 : 0;
10996                 mLegacyTypeTracker.add(
10997                         newDefaultNetwork.networkInfo.getType(), newDefaultNetwork);
10998             }
10999         }
11000 
11001         // Now that all the callbacks have been sent, send the legacy network broadcasts
11002         // as needed. This is necessary so that legacy requests correctly bind dns
11003         // requests to this network. The legacy users are listening for this broadcast
11004         // and will generally do a dns request so they can ensureRouteToHost and if
11005         // they do that before the callbacks happen they'll use the default network.
11006         //
11007         // TODO: Is there still a race here? The legacy broadcast will be sent after sending
11008         // callbacks, but if apps can receive the broadcast before the callback, they still might
11009         // have an inconsistent view of networking.
11010         //
11011         // This *does* introduce a race where if the user uses the new api
11012         // (notification callbacks) and then uses the old api (getNetworkInfo(type))
11013         // they may get old info. Reverse this after the old startUsing api is removed.
11014         // This is on top of the multiple intent sequencing referenced in the todo above.
11015         for (NetworkAgentInfo nai : nais) {
11016             if (nai.everConnected()) {
11017                 addNetworkToLegacyTypeTracker(nai);
11018             }
11019         }
11020     }
11021 
11022     private void issueNetworkNeeds() {
11023         ensureRunningOnConnectivityServiceThread();
11024         for (final NetworkOfferInfo noi : mNetworkOffers) {
11025             issueNetworkNeeds(noi);
11026         }
11027     }
11028 
11029     private void issueNetworkNeeds(@NonNull final NetworkOfferInfo noi) {
11030         ensureRunningOnConnectivityServiceThread();
11031         for (final NetworkRequestInfo nri : mNetworkRequests.values()) {
11032             informOffer(nri, noi.offer, mNetworkRanker);
11033         }
11034     }
11035 
11036     /**
11037      * Inform a NetworkOffer about any new situation of a request.
11038      *
11039      * This function handles updates to offers. A number of events may happen that require
11040      * updating the registrant for this offer about the situation :
11041      * • The offer itself was updated. This may lead the offer to no longer being able
11042      *     to satisfy a request or beat a satisfier (and therefore be no longer needed),
11043      *     or conversely being strengthened enough to beat the satisfier (and therefore
11044      *     start being needed)
11045      * • The network satisfying a request changed (including cases where the request
11046      *     starts or stops being satisfied). The new network may be a stronger or weaker
11047      *     match than the old one, possibly affecting whether the offer is needed.
11048      * • The network satisfying a request updated their score. This may lead the offer
11049      *     to no longer be able to beat it if the current satisfier got better, or
11050      *     conversely start being a good choice if the current satisfier got weaker.
11051      *
11052      * @param nri The request
11053      * @param offer The offer. This may be an updated offer.
11054      */
11055     private static void informOffer(@NonNull NetworkRequestInfo nri,
11056             @NonNull final NetworkOffer offer, @NonNull final NetworkRanker networkRanker) {
11057         final NetworkRequest activeRequest = nri.isBeingSatisfied() ? nri.getActiveRequest() : null;
11058         final NetworkAgentInfo satisfier = null != activeRequest ? nri.getSatisfier() : null;
11059 
11060         // Multi-layer requests have a currently active request, the one being satisfied.
11061         // Since the system will try to bring up a better network than is currently satisfying
11062         // the request, NetworkProviders need to be told the offers matching the requests *above*
11063         // the currently satisfied one are needed, that the ones *below* the satisfied one are
11064         // not needed, and the offer is needed for the active request iff the offer can beat
11065         // the satisfier.
11066         // For non-multilayer requests, the logic above gracefully degenerates to only the
11067         // last case.
11068         // To achieve this, the loop below will proceed in three steps. In a first phase, inform
11069         // providers that the offer is needed for this request, until the active request is found.
11070         // In a second phase, deal with the currently active request. In a third phase, inform
11071         // the providers that offer is unneeded for the remaining requests.
11072 
11073         // First phase : inform providers of all requests above the active request.
11074         int i;
11075         for (i = 0; nri.mRequests.size() > i; ++i) {
11076             final NetworkRequest request = nri.mRequests.get(i);
11077             if (activeRequest == request) break; // Found the active request : go to phase 2
11078             if (!request.isRequest()) continue; // Listens/track defaults are never sent to offers
11079             // Since this request is higher-priority than the one currently satisfied, if the
11080             // offer can satisfy it, the provider should try and bring up the network for sure ;
11081             // no need to even ask the ranker – an offer that can satisfy is always better than
11082             // no network. Hence tell the provider so unless it already knew.
11083             if (request.canBeSatisfiedBy(offer.caps) && !offer.neededFor(request)) {
11084                 offer.onNetworkNeeded(request);
11085             }
11086         }
11087 
11088         // Second phase : deal with the active request (if any)
11089         if (null != activeRequest && activeRequest.isRequest()) {
11090             final boolean oldNeeded = offer.neededFor(activeRequest);
11091             // If an offer can satisfy the request, it is considered needed if it is currently
11092             // served by this provider or if this offer can beat the current satisfier.
11093             final boolean currentlyServing = satisfier != null
11094                     && satisfier.factorySerialNumber == offer.providerId
11095                     && activeRequest.canBeSatisfiedBy(offer.caps);
11096             final boolean newNeeded = currentlyServing
11097                     || networkRanker.mightBeat(activeRequest, satisfier, offer);
11098             if (newNeeded != oldNeeded) {
11099                 if (newNeeded) {
11100                     offer.onNetworkNeeded(activeRequest);
11101                 } else {
11102                     // The offer used to be able to beat the satisfier. Now it can't.
11103                     offer.onNetworkUnneeded(activeRequest);
11104                 }
11105             }
11106         }
11107 
11108         // Third phase : inform the providers that the offer isn't needed for any request
11109         // below the active one.
11110         for (++i /* skip the active request */; nri.mRequests.size() > i; ++i) {
11111             final NetworkRequest request = nri.mRequests.get(i);
11112             if (!request.isRequest()) continue; // Listens/track defaults are never sent to offers
11113             // Since this request is lower-priority than the one currently satisfied, if the
11114             // offer can satisfy it, the provider should not try and bring up the network.
11115             // Hence tell the provider so unless it already knew.
11116             if (offer.neededFor(request)) {
11117                 offer.onNetworkUnneeded(request);
11118             }
11119         }
11120     }
11121 
11122     private void addNetworkToLegacyTypeTracker(@NonNull final NetworkAgentInfo nai) {
11123         for (int i = 0; i < nai.numNetworkRequests(); i++) {
11124             NetworkRequest nr = nai.requestAt(i);
11125             if (nr.legacyType != TYPE_NONE && nr.isRequest()) {
11126                 // legacy type tracker filters out repeat adds
11127                 mLegacyTypeTracker.add(nr.legacyType, nai);
11128             }
11129         }
11130 
11131         // A VPN generally won't get added to the legacy tracker in the "for (nri)" loop above,
11132         // because usually there are no NetworkRequests it satisfies (e.g., mDefaultRequest
11133         // wants the NOT_VPN capability, so it will never be satisfied by a VPN). So, add the
11134         // newNetwork to the tracker explicitly (it's a no-op if it has already been added).
11135         if (nai.isVPN()) {
11136             mLegacyTypeTracker.add(TYPE_VPN, nai);
11137         }
11138     }
11139 
11140     private void updateInetCondition(NetworkAgentInfo nai) {
11141         // Don't bother updating until we've graduated to validated at least once.
11142         if (!nai.everValidated()) return;
11143         // For now only update icons for the default connection.
11144         // TODO: Update WiFi and cellular icons separately. b/17237507
11145         if (!isDefaultNetwork(nai)) return;
11146 
11147         int newInetCondition = nai.isValidated() ? 100 : 0;
11148         // Don't repeat publish.
11149         if (newInetCondition == mDefaultInetConditionPublished) return;
11150 
11151         mDefaultInetConditionPublished = newInetCondition;
11152         sendInetConditionBroadcast(nai.networkInfo);
11153     }
11154 
11155     @NonNull
11156     private NetworkInfo mixInInfo(@NonNull final NetworkAgentInfo nai, @NonNull NetworkInfo info) {
11157         final NetworkInfo newInfo = new NetworkInfo(info);
11158         // The suspended and roaming bits are managed in NetworkCapabilities.
11159         final boolean suspended =
11160                 !nai.networkCapabilities.hasCapability(NET_CAPABILITY_NOT_SUSPENDED);
11161         if (suspended && info.getDetailedState() == NetworkInfo.DetailedState.CONNECTED) {
11162             // Only override the state with SUSPENDED if the network is currently in CONNECTED
11163             // state. This is because the network could have been suspended before connecting,
11164             // or it could be disconnecting while being suspended, and in both these cases
11165             // the state should not be overridden. Note that the only detailed state that
11166             // maps to State.CONNECTED is DetailedState.CONNECTED, so there is also no need to
11167             // worry about multiple different substates of CONNECTED.
11168             newInfo.setDetailedState(NetworkInfo.DetailedState.SUSPENDED, info.getReason(),
11169                     info.getExtraInfo());
11170         } else if (!suspended && info.getDetailedState() == NetworkInfo.DetailedState.SUSPENDED) {
11171             // SUSPENDED state is currently only overridden from CONNECTED state. In the case the
11172             // network agent is created, then goes to suspended, then goes out of suspended without
11173             // ever setting connected. Check if network agent is ever connected to update the state.
11174             newInfo.setDetailedState(nai.everConnected()
11175                     ? NetworkInfo.DetailedState.CONNECTED
11176                     : NetworkInfo.DetailedState.CONNECTING,
11177                     info.getReason(),
11178                     info.getExtraInfo());
11179         }
11180         newInfo.setRoaming(!nai.networkCapabilities.hasCapability(NET_CAPABILITY_NOT_ROAMING));
11181         return newInfo;
11182     }
11183 
11184     private void updateNetworkInfo(NetworkAgentInfo networkAgent, NetworkInfo info) {
11185         final NetworkInfo newInfo = mixInInfo(networkAgent, info);
11186 
11187         final NetworkInfo.State state = newInfo.getState();
11188         NetworkInfo oldInfo = null;
11189         synchronized (networkAgent) {
11190             oldInfo = networkAgent.networkInfo;
11191             networkAgent.networkInfo = newInfo;
11192         }
11193 
11194         if (DBG) {
11195             log(networkAgent.toShortString() + " EVENT_NETWORK_INFO_CHANGED, going from "
11196                     + oldInfo.getState() + " to " + state);
11197         }
11198 
11199         if (shouldCreateNativeNetwork(networkAgent, state)) {
11200             // A network that has just connected has zero requests and is thus a foreground network.
11201             networkAgent.networkCapabilities.addCapability(NET_CAPABILITY_FOREGROUND);
11202 
11203             if (!createNativeNetwork(networkAgent)) return;
11204 
11205             networkAgent.setCreated();
11206 
11207             // If the network is created immediately on register, then apply the LinkProperties now.
11208             // Otherwise, this is done further down when the network goes into connected state.
11209             // Applying the LinkProperties means that the network is ready to carry traffic -
11210             // interfaces and routing rules have been added, DNS servers programmed, etc.
11211             // For VPNs, this must be done before the capabilities are updated, because as soon as
11212             // that happens, UIDs are routed to the network.
11213             if (shouldCreateNetworksImmediately()) {
11214                 applyInitialLinkProperties(networkAgent);
11215             }
11216 
11217             // TODO: should this move earlier? It doesn't seem to have anything to do with whether
11218             // a network is created or not.
11219             if (networkAgent.propagateUnderlyingCapabilities()) {
11220                 // Initialize the network's capabilities to their starting values according to the
11221                 // underlying networks. This ensures that the capabilities are correct before
11222                 // anything happens to the network.
11223                 updateCapabilitiesForNetwork(networkAgent);
11224             }
11225             networkAgent.onNetworkCreated();
11226             updateAllowedUids(networkAgent, null, networkAgent.networkCapabilities);
11227             updateProfileAllowedNetworks();
11228         }
11229 
11230         if (!networkAgent.everConnected() && state == NetworkInfo.State.CONNECTED) {
11231             networkAgent.setConnected();
11232 
11233             // NetworkCapabilities need to be set before sending the private DNS config to
11234             // NetworkMonitor, otherwise NetworkMonitor cannot determine if validation is required.
11235             networkAgent.getAndSetNetworkCapabilities(networkAgent.networkCapabilities);
11236 
11237             handlePerNetworkPrivateDnsConfig(networkAgent, mDnsManager.getPrivateDnsConfig());
11238             if (!shouldCreateNetworksImmediately()) {
11239                 applyInitialLinkProperties(networkAgent);
11240             } else {
11241                 // The network was created when the agent registered, and the LinkProperties are
11242                 // already up-to-date. However, updateLinkProperties also makes some changes only
11243                 // when the network connects. Apply those changes here. On T and below these are
11244                 // handled by the applyInitialLinkProperties call just above.
11245                 // TODO: stop relying on updateLinkProperties(..., null) to do this.
11246                 // If something depends on both LinkProperties and connected state, it should be in
11247                 // this method as well.
11248                 networkAgent.clatd.update();
11249                 updateProxy(networkAgent.linkProperties, null);
11250             }
11251 
11252             // If a rate limit has been configured and is applicable to this network (network
11253             // provides internet connectivity), apply it. The tc police filter cannot be attached
11254             // before the clsact qdisc is added which happens as part of updateLinkProperties ->
11255             // updateInterfaces -> RoutingCoordinatorManager#addInterfaceToNetwork
11256             // Note: in case of a system server crash, the NetworkController constructor in netd
11257             // (called when netd starts up) deletes the clsact qdisc of all interfaces.
11258             if (canNetworkBeRateLimited(networkAgent) && mIngressRateLimit >= 0) {
11259                 mDeps.enableIngressRateLimit(networkAgent.linkProperties.getInterfaceName(),
11260                         mIngressRateLimit);
11261             }
11262 
11263             // Until parceled LinkProperties are sent directly to NetworkMonitor, the connect
11264             // command must be sent after updating LinkProperties to maximize chances of
11265             // NetworkMonitor seeing the correct LinkProperties when starting.
11266             // TODO: pass LinkProperties to the NetworkMonitor in the notifyNetworkConnected call.
11267             if (networkAgent.networkAgentConfig.acceptPartialConnectivity) {
11268                 networkAgent.networkMonitor().setAcceptPartialConnectivity();
11269             }
11270             final NetworkMonitorParameters params = new NetworkMonitorParameters();
11271             params.networkAgentConfig = networkAgent.networkAgentConfig;
11272             params.networkCapabilities = networkAgent.networkCapabilities;
11273             params.linkProperties = new LinkProperties(networkAgent.linkProperties,
11274                     true /* parcelSensitiveFields */);
11275             // isAtLeastT() is conservative here, as recent versions of NetworkStack support the
11276             // newer callback even before T. However getInterfaceVersion is a synchronized binder
11277             // call that would cause a Log.wtf to be emitted from the system_server process, and
11278             // in the absence of a satisfactory, scalable solution which follows an easy/standard
11279             // process to check the interface version, just use an SDK check. NetworkStack will
11280             // always be new enough when running on T+.
11281             if (mDeps.isAtLeastT()) {
11282                 networkAgent.networkMonitor().notifyNetworkConnected(params);
11283             } else {
11284                 networkAgent.networkMonitor().notifyNetworkConnected(params.linkProperties,
11285                         params.networkCapabilities);
11286             }
11287             final long evaluationDelay;
11288             if (!networkAgent.networkCapabilities.hasSingleTransport(TRANSPORT_WIFI)) {
11289                 // If the network is anything other than pure wifi, use the default timeout.
11290                 evaluationDelay = DEFAULT_EVALUATION_TIMEOUT_MS;
11291             } else if (networkAgent.networkAgentConfig.isExplicitlySelected()) {
11292                 // If the network is explicitly selected, use the default timeout because it's
11293                 // shorter and the user is likely staring at the screen expecting it to validate
11294                 // right away.
11295                 evaluationDelay = DEFAULT_EVALUATION_TIMEOUT_MS;
11296             } else if (avoidBadWifi() || !activelyPreferBadWifi()) {
11297                 // If avoiding bad wifi, or if not avoiding but also not preferring bad wifi
11298                 evaluationDelay = DEFAULT_EVALUATION_TIMEOUT_MS;
11299             } else {
11300                 // It's wifi, automatically connected, and bad wifi is preferred : use the
11301                 // longer timeout to avoid the device switching to captive portals with bad
11302                 // signal or very slow response.
11303                 evaluationDelay = ACTIVELY_PREFER_BAD_WIFI_INITIAL_TIMEOUT_MS;
11304             }
11305             scheduleEvaluationTimeout(networkAgent.network, evaluationDelay);
11306 
11307             // Whether a particular NetworkRequest listen should cause signal strength thresholds to
11308             // be communicated to a particular NetworkAgent depends only on the network's immutable,
11309             // capabilities, so it only needs to be done once on initial connect, not every time the
11310             // network's capabilities change. Note that we do this before rematching the network,
11311             // so we could decide to tear it down immediately afterwards. That's fine though - on
11312             // disconnection NetworkAgents should stop any signal strength monitoring they have been
11313             // doing.
11314             updateSignalStrengthThresholds(networkAgent, "CONNECT", null);
11315 
11316             // Before first rematching networks, put an inactivity timer without any request, this
11317             // allows {@code updateInactivityState} to update the state accordingly and prevent
11318             // tearing down for any {@code unneeded} evaluation in this period.
11319             // Note that the timer will not be rescheduled since the expiry time is
11320             // fixed after connection regardless of the network satisfying other requests or not.
11321             // But it will be removed as soon as the network satisfies a request for the first time.
11322             networkAgent.lingerRequest(NetworkRequest.REQUEST_ID_NONE,
11323                     SystemClock.elapsedRealtime(), mNascentDelayMs);
11324             networkAgent.setInactive();
11325 
11326             if (mTrackMultiNetworkActivities) {
11327                 // Start tracking activity of this network.
11328                 // This must be called before rematchAllNetworksAndRequests since the network
11329                 // should be tracked when the network becomes the default network.
11330                 // This method does not trigger any callbacks or broadcasts. Callbacks or broadcasts
11331                 // can be triggered later if this network becomes the default network.
11332                 mNetworkActivityTracker.setupDataActivityTracking(networkAgent);
11333             }
11334 
11335             // Consider network even though it is not yet validated.
11336             rematchAllNetworksAndRequests();
11337 
11338             // This has to happen after matching the requests, because callbacks are just requests.
11339             notifyNetworkCallbacks(networkAgent, ConnectivityManager.CALLBACK_PRECHECK);
11340         } else if (state == NetworkInfo.State.DISCONNECTED) {
11341             networkAgent.disconnect();
11342             if (networkAgent.isVPN()) {
11343                 updateVpnUids(networkAgent, networkAgent.networkCapabilities, null);
11344             }
11345             disconnectAndDestroyNetwork(networkAgent);
11346             if (networkAgent.isVPN()) {
11347                 // As the active or bound network changes for apps, broadcast the default proxy, as
11348                 // apps may need to update their proxy data. This is called after disconnecting from
11349                 // VPN to make sure we do not broadcast the old proxy data.
11350                 // TODO(b/122649188): send the broadcast only to VPN users.
11351                 mProxyTracker.sendProxyBroadcast();
11352             }
11353         } else if (networkAgent.isCreated() && (oldInfo.getState() == NetworkInfo.State.SUSPENDED
11354                 || state == NetworkInfo.State.SUSPENDED)) {
11355             mLegacyTypeTracker.update(networkAgent);
11356         }
11357     }
11358 
11359     private void updateNetworkScore(@NonNull final NetworkAgentInfo nai, final NetworkScore score) {
11360         if (VDBG || DDBG) log("updateNetworkScore for " + nai.toShortString() + " to " + score);
11361         nai.setScore(score);
11362         rematchAllNetworksAndRequests();
11363     }
11364 
11365     // Notify only this one new request of the current state. Transfer all the
11366     // current state by calling NetworkCapabilities and LinkProperties callbacks
11367     // so that callers can be guaranteed to have as close to atomicity in state
11368     // transfer as can be supported by this current API.
11369     protected void notifyNetworkAvailable(NetworkAgentInfo nai, NetworkRequestInfo nri) {
11370         mHandler.removeMessages(EVENT_TIMEOUT_NETWORK_REQUEST, nri);
11371         if (nri.mPendingIntent != null) {
11372             sendPendingIntentForRequest(nri, nai, ConnectivityManager.CALLBACK_AVAILABLE);
11373             // Attempt no subsequent state pushes where intents are involved.
11374             return;
11375         }
11376 
11377         final int blockedReasons = mUidBlockedReasons.get(nri.mAsUid, BLOCKED_REASON_NONE);
11378         final boolean metered = nai.networkCapabilities.isMetered();
11379         final boolean vpnBlocked = isUidBlockedByVpn(nri.mAsUid, mVpnBlockedUidRanges);
11380         callCallbackForRequest(nri, nai, ConnectivityManager.CALLBACK_AVAILABLE,
11381                 getBlockedState(nri.mAsUid, blockedReasons, metered, vpnBlocked));
11382     }
11383 
11384     // Notify the requests on this NAI that the network is now lingered.
11385     private void notifyNetworkLosing(@NonNull final NetworkAgentInfo nai, final long now) {
11386         final int lingerTime = (int) (nai.getInactivityExpiry() - now);
11387         notifyNetworkCallbacks(nai, ConnectivityManager.CALLBACK_LOSING, lingerTime);
11388     }
11389 
11390     private int getPermissionBlockedState(final int uid, final int reasons) {
11391         // Before V, the blocked reasons come from NPMS, and that code already behaves as if the
11392         // change was disabled: apps without the internet permission will never be told they are
11393         // blocked.
11394         if (!mDeps.isAtLeastV()) return reasons;
11395 
11396         if (hasInternetPermission(uid)) return reasons;
11397 
11398         return mDeps.isChangeEnabled(NETWORK_BLOCKED_WITHOUT_INTERNET_PERMISSION, uid)
11399                 ? reasons | BLOCKED_REASON_NETWORK_RESTRICTED
11400                 : BLOCKED_REASON_NONE;
11401     }
11402 
11403     private int getBlockedState(int uid, int reasons, boolean metered, boolean vpnBlocked) {
11404         reasons = getPermissionBlockedState(uid, reasons);
11405         if (!metered) reasons &= ~BLOCKED_METERED_REASON_MASK;
11406         return vpnBlocked
11407                 ? reasons | BLOCKED_REASON_LOCKDOWN_VPN
11408                 : reasons & ~BLOCKED_REASON_LOCKDOWN_VPN;
11409     }
11410 
11411     private void setUidBlockedReasons(int uid, @BlockedReason int blockedReasons) {
11412         if (blockedReasons == BLOCKED_REASON_NONE) {
11413             mUidBlockedReasons.delete(uid);
11414         } else {
11415             mUidBlockedReasons.put(uid, blockedReasons);
11416         }
11417     }
11418 
11419     /**
11420      * Notify of the blocked state apps with a registered callback matching a given NAI.
11421      *
11422      * Unlike other callbacks, blocked status is different between each individual uid. So for
11423      * any given nai, all requests need to be considered according to the uid who filed it.
11424      *
11425      * @param nai The target NetworkAgentInfo.
11426      * @param oldMetered True if the previous network capabilities were metered.
11427      * @param newMetered True if the current network capabilities are metered.
11428      * @param oldBlockedUidRanges list of UID ranges previously blocked by lockdown VPN.
11429      * @param newBlockedUidRanges list of UID ranges blocked by lockdown VPN.
11430      */
11431     private void maybeNotifyNetworkBlocked(NetworkAgentInfo nai, boolean oldMetered,
11432             boolean newMetered, List<UidRange> oldBlockedUidRanges,
11433             List<UidRange> newBlockedUidRanges) {
11434 
11435         for (int i = 0; i < nai.numNetworkRequests(); i++) {
11436             NetworkRequest nr = nai.requestAt(i);
11437             NetworkRequestInfo nri = mNetworkRequests.get(nr);
11438 
11439             final int blockedReasons = mUidBlockedReasons.get(nri.mAsUid, BLOCKED_REASON_NONE);
11440             final boolean oldVpnBlocked = isUidBlockedByVpn(nri.mAsUid, oldBlockedUidRanges);
11441             final boolean newVpnBlocked = (oldBlockedUidRanges != newBlockedUidRanges)
11442                     ? isUidBlockedByVpn(nri.mAsUid, newBlockedUidRanges)
11443                     : oldVpnBlocked;
11444 
11445             final int oldBlockedState = getBlockedState(
11446                     nri.mAsUid, blockedReasons, oldMetered, oldVpnBlocked);
11447             final int newBlockedState = getBlockedState(
11448                     nri.mAsUid, blockedReasons, newMetered, newVpnBlocked);
11449             if (oldBlockedState != newBlockedState) {
11450                 callCallbackForRequest(nri, nai, ConnectivityManager.CALLBACK_BLK_CHANGED,
11451                         newBlockedState);
11452             }
11453         }
11454     }
11455 
11456     /**
11457      * Notify apps with a given UID of the new blocked state according to new uid state.
11458      * @param uid The uid for which the rules changed.
11459      * @param blockedReasons The reasons for why an uid is blocked.
11460      */
11461     private void maybeNotifyNetworkBlockedForNewState(int uid, @BlockedReason int blockedReasons) {
11462         for (final NetworkAgentInfo nai : mNetworkAgentInfos) {
11463             final boolean metered = nai.networkCapabilities.isMetered();
11464             final boolean vpnBlocked = isUidBlockedByVpn(uid, mVpnBlockedUidRanges);
11465 
11466             final int oldBlockedState = getBlockedState(
11467                     uid, mUidBlockedReasons.get(uid, BLOCKED_REASON_NONE), metered, vpnBlocked);
11468             final int newBlockedState =
11469                     getBlockedState(uid, blockedReasons, metered, vpnBlocked);
11470             if (oldBlockedState == newBlockedState) {
11471                 continue;
11472             }
11473             for (int i = 0; i < nai.numNetworkRequests(); i++) {
11474                 NetworkRequest nr = nai.requestAt(i);
11475                 NetworkRequestInfo nri = mNetworkRequests.get(nr);
11476                 if (nri != null && nri.mAsUid == uid) {
11477                     callCallbackForRequest(nri, nai, ConnectivityManager.CALLBACK_BLK_CHANGED,
11478                             newBlockedState);
11479                 }
11480             }
11481         }
11482     }
11483 
11484     @VisibleForTesting
11485     protected void sendLegacyNetworkBroadcast(NetworkAgentInfo nai, DetailedState state, int type) {
11486         // The NetworkInfo we actually send out has no bearing on the real
11487         // state of affairs. For example, if the default connection is mobile,
11488         // and a request for HIPRI has just gone away, we need to pretend that
11489         // HIPRI has just disconnected. So we need to set the type to HIPRI and
11490         // the state to DISCONNECTED, even though the network is of type MOBILE
11491         // and is still connected.
11492         NetworkInfo info = new NetworkInfo(nai.networkInfo);
11493         info.setType(type);
11494         filterForLegacyLockdown(info);
11495         if (state != DetailedState.DISCONNECTED) {
11496             info.setDetailedState(state, null, info.getExtraInfo());
11497             sendConnectedBroadcast(info);
11498         } else {
11499             info.setDetailedState(state, info.getReason(), info.getExtraInfo());
11500             Intent intent = new Intent(ConnectivityManager.CONNECTIVITY_ACTION);
11501             intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, info);
11502             intent.putExtra(ConnectivityManager.EXTRA_NETWORK_TYPE, info.getType());
11503             if (info.isFailover()) {
11504                 intent.putExtra(ConnectivityManager.EXTRA_IS_FAILOVER, true);
11505                 nai.networkInfo.setFailover(false);
11506             }
11507             if (info.getReason() != null) {
11508                 intent.putExtra(ConnectivityManager.EXTRA_REASON, info.getReason());
11509             }
11510             if (info.getExtraInfo() != null) {
11511                 intent.putExtra(ConnectivityManager.EXTRA_EXTRA_INFO, info.getExtraInfo());
11512             }
11513             NetworkAgentInfo newDefaultAgent = null;
11514             if (nai.isSatisfyingRequest(mDefaultRequest.mRequests.get(0).requestId)) {
11515                 newDefaultAgent = mDefaultRequest.getSatisfier();
11516                 if (newDefaultAgent != null) {
11517                     intent.putExtra(ConnectivityManager.EXTRA_OTHER_NETWORK_INFO,
11518                             newDefaultAgent.networkInfo);
11519                 } else {
11520                     intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, true);
11521                 }
11522             }
11523             intent.putExtra(ConnectivityManager.EXTRA_INET_CONDITION,
11524                     mDefaultInetConditionPublished);
11525             sendStickyBroadcast(intent);
11526             if (newDefaultAgent != null) {
11527                 sendConnectedBroadcast(newDefaultAgent.networkInfo);
11528             }
11529         }
11530     }
11531 
11532     protected void notifyNetworkCallbacks(NetworkAgentInfo networkAgent, int notifyType, int arg1) {
11533         if (VDBG || DDBG) {
11534             String notification = ConnectivityManager.getCallbackName(notifyType);
11535             log("notifyType " + notification + " for " + networkAgent.toShortString());
11536         }
11537         for (int i = 0; i < networkAgent.numNetworkRequests(); i++) {
11538             NetworkRequest nr = networkAgent.requestAt(i);
11539             NetworkRequestInfo nri = mNetworkRequests.get(nr);
11540             if (VDBG) log(" sending notification for " + nr);
11541             if (nri.mPendingIntent == null) {
11542                 callCallbackForRequest(nri, networkAgent, notifyType, arg1);
11543             } else {
11544                 sendPendingIntentForRequest(nri, networkAgent, notifyType);
11545             }
11546         }
11547     }
11548 
11549     protected void notifyNetworkCallbacks(NetworkAgentInfo networkAgent, int notifyType) {
11550         notifyNetworkCallbacks(networkAgent, notifyType, 0);
11551     }
11552 
11553     /**
11554      * Returns the list of all interfaces that could be used by network traffic that does not
11555      * explicitly specify a network. This includes the default network, but also all VPNs that are
11556      * currently connected.
11557      *
11558      * Must be called on the handler thread.
11559      */
11560     @NonNull
11561     private ArrayList<Network> getDefaultNetworks() {
11562         ensureRunningOnConnectivityServiceThread();
11563         final ArrayList<Network> defaultNetworks = new ArrayList<>();
11564         final Set<Integer> activeNetIds = new ArraySet<>();
11565         for (final NetworkRequestInfo nri : mDefaultNetworkRequests) {
11566             if (nri.isBeingSatisfied()) {
11567                 activeNetIds.add(nri.getSatisfier().network().netId);
11568             }
11569         }
11570         for (NetworkAgentInfo nai : mNetworkAgentInfos) {
11571             if (activeNetIds.contains(nai.network().netId) || nai.isVPN()) {
11572                 defaultNetworks.add(nai.network);
11573             }
11574         }
11575         return defaultNetworks;
11576     }
11577 
11578     /**
11579      * Notify NetworkStatsService that the set of active ifaces has changed, or that one of the
11580      * active iface's tracked properties has changed.
11581      */
11582     private void notifyIfacesChangedForNetworkStats() {
11583         ensureRunningOnConnectivityServiceThread();
11584         String activeIface = null;
11585         LinkProperties activeLinkProperties = getActiveLinkProperties();
11586         if (activeLinkProperties != null) {
11587             activeIface = activeLinkProperties.getInterfaceName();
11588         }
11589 
11590         final UnderlyingNetworkInfo[] underlyingNetworkInfos = getAllVpnInfo();
11591         try {
11592             final ArrayList<NetworkStateSnapshot> snapshots = new ArrayList<>();
11593             snapshots.addAll(getAllNetworkStateSnapshots());
11594             mStatsManager.notifyNetworkStatus(getDefaultNetworks(),
11595                     snapshots, activeIface, Arrays.asList(underlyingNetworkInfos));
11596         } catch (Exception ignored) {
11597         }
11598     }
11599 
11600     @Override
11601     public String getCaptivePortalServerUrl() {
11602         enforceNetworkStackOrSettingsPermission();
11603         String settingUrl = mResources.get().getString(
11604                 R.string.config_networkCaptivePortalServerUrl);
11605 
11606         if (!TextUtils.isEmpty(settingUrl)) {
11607             return settingUrl;
11608         }
11609 
11610         settingUrl = Settings.Global.getString(mContext.getContentResolver(),
11611                 ConnectivitySettingsManager.CAPTIVE_PORTAL_HTTP_URL);
11612         if (!TextUtils.isEmpty(settingUrl)) {
11613             return settingUrl;
11614         }
11615 
11616         return DEFAULT_CAPTIVE_PORTAL_HTTP_URL;
11617     }
11618 
11619     @Override
11620     public void startNattKeepalive(Network network, int intervalSeconds,
11621             ISocketKeepaliveCallback cb, String srcAddr, int srcPort, String dstAddr) {
11622         enforceKeepalivePermission();
11623         mKeepaliveTracker.startNattKeepalive(
11624                 getNetworkAgentInfoForNetwork(network), null /* fd */,
11625                 intervalSeconds, cb, srcAddr, srcPort, dstAddr, NattSocketKeepalive.NATT_PORT,
11626                 // Keep behavior of the deprecated method as it is. Set automaticOnOffKeepalives to
11627                 // false and set the underpinned network to null because there is no way and no
11628                 // plan to configure automaticOnOffKeepalives or underpinnedNetwork in this
11629                 // deprecated method.
11630                 false /* automaticOnOffKeepalives */, null /* underpinnedNetwork */);
11631     }
11632 
11633     @Override
11634     public void startNattKeepaliveWithFd(Network network, ParcelFileDescriptor pfd, int resourceId,
11635             int intervalSeconds, ISocketKeepaliveCallback cb, String srcAddr,
11636             String dstAddr, boolean automaticOnOffKeepalives, Network underpinnedNetwork) {
11637         try {
11638             final FileDescriptor fd = pfd.getFileDescriptor();
11639             mKeepaliveTracker.startNattKeepalive(
11640                     getNetworkAgentInfoForNetwork(network), fd, resourceId,
11641                     intervalSeconds, cb, srcAddr, dstAddr, NattSocketKeepalive.NATT_PORT,
11642                     automaticOnOffKeepalives, underpinnedNetwork);
11643         } finally {
11644             // FileDescriptors coming from AIDL calls must be manually closed to prevent leaks.
11645             // startNattKeepalive calls Os.dup(fd) before returning, so we can close immediately.
11646             if (pfd != null && Binder.getCallingPid() != Process.myPid()) {
11647                 IoUtils.closeQuietly(pfd);
11648             }
11649         }
11650     }
11651 
11652     @Override
11653     public void startTcpKeepalive(Network network, ParcelFileDescriptor pfd, int intervalSeconds,
11654             ISocketKeepaliveCallback cb) {
11655         try {
11656             enforceKeepalivePermission();
11657             final FileDescriptor fd = pfd.getFileDescriptor();
11658             mKeepaliveTracker.startTcpKeepalive(
11659                     getNetworkAgentInfoForNetwork(network), fd, intervalSeconds, cb);
11660         } finally {
11661             // FileDescriptors coming from AIDL calls must be manually closed to prevent leaks.
11662             // startTcpKeepalive calls Os.dup(fd) before returning, so we can close immediately.
11663             if (pfd != null && Binder.getCallingPid() != Process.myPid()) {
11664                 IoUtils.closeQuietly(pfd);
11665             }
11666         }
11667     }
11668 
11669     @Override
11670     public void stopKeepalive(@NonNull final ISocketKeepaliveCallback cb) {
11671         mHandler.sendMessage(mHandler.obtainMessage(
11672                 NetworkAgent.CMD_STOP_SOCKET_KEEPALIVE, 0, SocketKeepalive.SUCCESS,
11673                 Objects.requireNonNull(cb).asBinder()));
11674     }
11675 
11676     @Override
11677     public int[] getSupportedKeepalives() {
11678         enforceAnyPermissionOf(mContext, android.Manifest.permission.NETWORK_SETTINGS,
11679                 // Backwards compatibility with CTS 13
11680                 android.Manifest.permission.QUERY_ALL_PACKAGES);
11681 
11682         return BinderUtils.withCleanCallingIdentity(() ->
11683                 KeepaliveResourceUtil.getSupportedKeepalives(mContext));
11684     }
11685 
11686     @Override
11687     public void factoryReset() {
11688         enforceSettingsPermission();
11689 
11690         final int uid = mDeps.getCallingUid();
11691         final long token = Binder.clearCallingIdentity();
11692         try {
11693             if (mUserManager.hasUserRestrictionForUser(UserManager.DISALLOW_NETWORK_RESET,
11694                     UserHandle.getUserHandleForUid(uid))) {
11695                 return;
11696             }
11697 
11698             final IpMemoryStore ipMemoryStore = IpMemoryStore.getMemoryStore(mContext);
11699             ipMemoryStore.factoryReset();
11700 
11701             // Turn airplane mode off
11702             setAirplaneMode(false);
11703 
11704             // restore private DNS settings to default mode (opportunistic)
11705             if (!mUserManager.hasUserRestrictionForUser(UserManager.DISALLOW_CONFIG_PRIVATE_DNS,
11706                     UserHandle.getUserHandleForUid(uid))) {
11707                 ConnectivitySettingsManager.setPrivateDnsMode(mContext,
11708                         PRIVATE_DNS_MODE_OPPORTUNISTIC);
11709             }
11710 
11711             Settings.Global.putString(mContext.getContentResolver(),
11712                     ConnectivitySettingsManager.NETWORK_AVOID_BAD_WIFI, null);
11713         } finally {
11714             Binder.restoreCallingIdentity(token);
11715         }
11716     }
11717 
11718     @Override
11719     public byte[] getNetworkWatchlistConfigHash() {
11720         NetworkWatchlistManager nwm = mContext.getSystemService(NetworkWatchlistManager.class);
11721         if (nwm == null) {
11722             loge("Unable to get NetworkWatchlistManager");
11723             return null;
11724         }
11725         // Redirect it to network watchlist service to access watchlist file and calculate hash.
11726         return nwm.getWatchlistConfigHash();
11727     }
11728 
11729     private void logNetworkEvent(NetworkAgentInfo nai, int evtype) {
11730         int[] transports = nai.networkCapabilities.getTransportTypes();
11731         mMetricsLog.log(nai.network.getNetId(), transports, new NetworkEvent(evtype));
11732     }
11733 
11734     private static boolean toBool(int encodedBoolean) {
11735         return encodedBoolean != 0; // Only 0 means false.
11736     }
11737 
11738     private static int encodeBool(boolean b) {
11739         return b ? 1 : 0;
11740     }
11741 
11742     @Override
11743     public int handleShellCommand(@NonNull ParcelFileDescriptor in,
11744             @NonNull ParcelFileDescriptor out, @NonNull ParcelFileDescriptor err,
11745             @NonNull String[] args) {
11746         return new ShellCmd().exec(this, in.getFileDescriptor(), out.getFileDescriptor(),
11747                 err.getFileDescriptor(), args);
11748     }
11749 
11750     private class ShellCmd extends BasicShellCommandHandler {
11751 
11752         private Boolean parseBooleanArgument(final String arg) {
11753             if ("true".equals(arg)) {
11754                 return true;
11755             } else if ("false".equals(arg)) {
11756                 return false;
11757             } else {
11758                 getOutPrintWriter().println("Invalid boolean argument: " + arg);
11759                 return null;
11760             }
11761         }
11762 
11763         private Integer parseIntegerArgument(final String arg) {
11764             try {
11765                 return Integer.valueOf(arg);
11766             } catch (NumberFormatException ne) {
11767                 getOutPrintWriter().println("Invalid integer argument: " + arg);
11768                 return null;
11769             }
11770         }
11771 
11772         @Override
11773         public int onCommand(String cmd) {
11774             if (cmd == null) {
11775                 return handleDefaultCommands(cmd);
11776             }
11777             final PrintWriter pw = getOutPrintWriter();
11778             try {
11779                 switch (cmd) {
11780                     case "airplane-mode":
11781                         // Usage : adb shell cmd connectivity airplane-mode [enable|disable]
11782                         // If no argument, get and display the current status
11783                         final String action = getNextArg();
11784                         if ("enable".equals(action)) {
11785                             setAirplaneMode(true);
11786                             return 0;
11787                         } else if ("disable".equals(action)) {
11788                             setAirplaneMode(false);
11789                             return 0;
11790                         } else if (action == null) {
11791                             final ContentResolver cr = mContext.getContentResolver();
11792                             final int enabled = Settings.Global.getInt(cr,
11793                                     Settings.Global.AIRPLANE_MODE_ON);
11794                             pw.println(enabled == 0 ? "disabled" : "enabled");
11795                             return 0;
11796                         } else {
11797                             onHelp();
11798                             return -1;
11799                         }
11800                     case "set-chain3-enabled": {
11801                         final Boolean enabled = parseBooleanArgument(getNextArg());
11802                         if (null == enabled) {
11803                             onHelp();
11804                             return -1;
11805                         }
11806                         Log.i(TAG, (enabled ? "En" : "Dis") + "abled FIREWALL_CHAIN_OEM_DENY_3");
11807                         setFirewallChainEnabled(ConnectivityManager.FIREWALL_CHAIN_OEM_DENY_3,
11808                                 enabled);
11809                         return 0;
11810                     }
11811                     case "get-chain3-enabled": {
11812                         final boolean chainEnabled = getFirewallChainEnabled(
11813                                 ConnectivityManager.FIREWALL_CHAIN_OEM_DENY_3);
11814                         pw.println("chain:" + (chainEnabled ? "enabled" : "disabled"));
11815                         return 0;
11816                     }
11817                     case "set-package-networking-enabled": {
11818                         final Boolean enabled = parseBooleanArgument(getNextArg());
11819                         final String packageName = getNextArg();
11820                         if (null == enabled || null == packageName) {
11821                             onHelp();
11822                             return -1;
11823                         }
11824                         // Throws NameNotFound if the package doesn't exist.
11825                         final int appId = setPackageFirewallRule(
11826                                 ConnectivityManager.FIREWALL_CHAIN_OEM_DENY_3,
11827                                 packageName, enabled ? FIREWALL_RULE_DEFAULT : FIREWALL_RULE_DENY);
11828                         final String msg = (enabled ? "Enabled" : "Disabled")
11829                                 + " networking for " + packageName + ", appId " + appId;
11830                         Log.i(TAG, msg);
11831                         pw.println(msg);
11832                         return 0;
11833                     }
11834                     case "get-package-networking-enabled": {
11835                         final String packageName = getNextArg();
11836                         final int rule = getPackageFirewallRule(
11837                                 ConnectivityManager.FIREWALL_CHAIN_OEM_DENY_3, packageName);
11838                         if (FIREWALL_RULE_ALLOW == rule || FIREWALL_RULE_DEFAULT == rule) {
11839                             pw.println(packageName + ":" + "allow");
11840                         } else if (FIREWALL_RULE_DENY == rule) {
11841                             pw.println(packageName + ":" + "deny");
11842                         } else {
11843                             throw new IllegalStateException("Unknown rule " + rule + " for package "
11844                                     + packageName);
11845                         }
11846                         return 0;
11847                     }
11848                     case "set-background-networking-enabled-for-uid": {
11849                         final Integer uid = parseIntegerArgument(getNextArg());
11850                         final Boolean enabled = parseBooleanArgument(getNextArg());
11851                         if (null == enabled || null == uid) {
11852                             onHelp();
11853                             return -1;
11854                         }
11855                         final int rule = enabled ? FIREWALL_RULE_ALLOW : FIREWALL_RULE_DEFAULT;
11856                         setUidFirewallRule(FIREWALL_CHAIN_BACKGROUND, uid, rule);
11857                         final String msg = (enabled ? "Enabled" : "Disabled")
11858                                 + " background networking for  uid " + uid;
11859                         Log.i(TAG, msg);
11860                         pw.println(msg);
11861                         return 0;
11862                     }
11863                     case "get-background-networking-enabled-for-uid": {
11864                         final Integer uid = parseIntegerArgument(getNextArg());
11865                         if (null == uid) {
11866                             onHelp();
11867                             return -1;
11868                         }
11869                         final int rule = getUidFirewallRule(FIREWALL_CHAIN_BACKGROUND, uid);
11870                         if (FIREWALL_RULE_ALLOW == rule) {
11871                             pw.println(uid + ": allow");
11872                         } else if (FIREWALL_RULE_DENY == rule  || FIREWALL_RULE_DEFAULT == rule) {
11873                             pw.println(uid + ": deny");
11874                         } else {
11875                             throw new IllegalStateException(
11876                                     "Unknown rule " + rule + " for uid " + uid);
11877                         }
11878                         return 0;
11879                     }
11880                     case "reevaluate":
11881                         // Usage : adb shell cmd connectivity reevaluate <netId>
11882                         // If netId is omitted, then reevaluate the default network
11883                         final String netId = getNextArg();
11884                         final NetworkAgentInfo nai;
11885                         if (null == netId) {
11886                             // Note that the command is running on the wrong thread to call this,
11887                             // so this could in principle return stale data. But it can't crash.
11888                             nai = getDefaultNetwork();
11889                         } else {
11890                             // If netId can't be parsed, this throws NumberFormatException, which
11891                             // is passed back to adb who prints it.
11892                             nai = getNetworkAgentInfoForNetId(Integer.parseInt(netId));
11893                         }
11894                         if (null == nai) {
11895                             pw.println("Unknown network (net ID not found or no default network)");
11896                             return 0;
11897                         }
11898                         Log.d(TAG, "Reevaluating network " + nai.network);
11899                         reportNetworkConnectivity(nai.network, !nai.isValidated());
11900                         return 0;
11901                     case "bpf-get-cgroup-program-id": {
11902                         // Usage : adb shell cmd connectivity bpf-get-cgroup-program-id <type>
11903                         // Get cgroup bpf program Id for the given type. See BpfUtils#getProgramId
11904                         // for more detail.
11905                         // If type can't be parsed, this throws NumberFormatException, which
11906                         // is passed back to adb who prints it.
11907                         final int type = Integer.parseInt(getNextArg());
11908                         final int ret = BpfUtils.getProgramId(type);
11909                         pw.println(ret);
11910                         return 0;
11911                     }
11912                     default:
11913                         return handleDefaultCommands(cmd);
11914                 }
11915             } catch (Exception e) {
11916                 pw.println(e);
11917             }
11918             return -1;
11919         }
11920 
11921         @Override
11922         public void onHelp() {
11923             PrintWriter pw = getOutPrintWriter();
11924             pw.println("Connectivity service commands:");
11925             pw.println("  help");
11926             pw.println("    Print this help text.");
11927             pw.println("  airplane-mode [enable|disable]");
11928             pw.println("    Turn airplane mode on or off.");
11929             pw.println("  airplane-mode");
11930             pw.println("    Get airplane mode.");
11931             pw.println("  set-chain3-enabled [true|false]");
11932             pw.println("    Enable or disable FIREWALL_CHAIN_OEM_DENY_3 for debugging.");
11933             pw.println("  get-chain3-enabled");
11934             pw.println("    Returns whether FIREWALL_CHAIN_OEM_DENY_3 is enabled.");
11935             pw.println("  set-package-networking-enabled [true|false] [package name]");
11936             pw.println("    Set the deny bit in FIREWALL_CHAIN_OEM_DENY_3 to package. This has\n"
11937                     + "    no effect if the chain is disabled.");
11938             pw.println("  get-package-networking-enabled [package name]");
11939             pw.println("    Get the deny bit in FIREWALL_CHAIN_OEM_DENY_3 for package.");
11940             pw.println("  set-background-networking-enabled-for-uid [uid] [true|false]");
11941             pw.println("    Set the allow bit in FIREWALL_CHAIN_BACKGROUND for the given uid.");
11942             pw.println("  get-background-networking-enabled-for-uid [uid]");
11943             pw.println("    Get the allow bit in FIREWALL_CHAIN_BACKGROUND for the given uid.");
11944         }
11945     }
11946 
11947     private int getVpnType(@Nullable NetworkAgentInfo vpn) {
11948         if (vpn == null) return VpnManager.TYPE_VPN_NONE;
11949         final TransportInfo ti = vpn.networkCapabilities.getTransportInfo();
11950         if (!(ti instanceof VpnTransportInfo)) return VpnManager.TYPE_VPN_NONE;
11951         return ((VpnTransportInfo) ti).getType();
11952     }
11953 
11954     private void maybeUpdateWifiRoamTimestamp(@NonNull NetworkAgentInfo nai,
11955             @NonNull NetworkCapabilities nc) {
11956         final TransportInfo prevInfo = nai.networkCapabilities.getTransportInfo();
11957         final TransportInfo newInfo = nc.getTransportInfo();
11958         if (!(prevInfo instanceof WifiInfo) || !(newInfo instanceof WifiInfo)) {
11959             return;
11960         }
11961         if (!TextUtils.equals(((WifiInfo)prevInfo).getBSSID(), ((WifiInfo)newInfo).getBSSID())) {
11962             nai.lastRoamTime = SystemClock.elapsedRealtime();
11963         }
11964     }
11965 
11966     /**
11967      * @param connectionInfo the connection to resolve.
11968      * @return {@code uid} if the connection is found and the app has permission to observe it
11969      * (e.g., if it is associated with the calling VPN app's tunnel) or {@code INVALID_UID} if the
11970      * connection is not found.
11971      */
11972     public int getConnectionOwnerUid(ConnectionInfo connectionInfo) {
11973         if (connectionInfo.protocol != IPPROTO_TCP && connectionInfo.protocol != IPPROTO_UDP) {
11974             throw new IllegalArgumentException("Unsupported protocol " + connectionInfo.protocol);
11975         }
11976 
11977         final int uid = mDeps.getConnectionOwnerUid(connectionInfo.protocol,
11978                 connectionInfo.local, connectionInfo.remote);
11979 
11980         if (uid == INVALID_UID) return uid;  // Not found.
11981 
11982         // Connection owner UIDs are visible only to the network stack and to the VpnService-based
11983         // VPN, if any, that applies to the UID that owns the connection.
11984         if (hasNetworkStackPermission()) return uid;
11985 
11986         final NetworkAgentInfo vpn = getVpnForUid(uid);
11987         if (vpn == null || getVpnType(vpn) != VpnManager.TYPE_VPN_SERVICE
11988                 || vpn.networkCapabilities.getOwnerUid() != mDeps.getCallingUid()) {
11989             return INVALID_UID;
11990         }
11991 
11992         return uid;
11993     }
11994 
11995     /**
11996      * Returns a IBinder to a TestNetworkService. Will be lazily created as needed.
11997      *
11998      * <p>The TestNetworkService must be run in the system server due to TUN creation.
11999      */
12000     @Override
12001     public IBinder startOrGetTestNetworkService() {
12002         synchronized (mTNSLock) {
12003             TestNetworkService.enforceTestNetworkPermissions(mContext);
12004 
12005             if (mTNS == null) {
12006                 mTNS = new TestNetworkService(mContext);
12007             }
12008 
12009             return mTNS;
12010         }
12011     }
12012 
12013     /**
12014      * Handler used for managing all Connectivity Diagnostics related functions.
12015      *
12016      * @see android.net.ConnectivityDiagnosticsManager
12017      *
12018      * TODO(b/147816404): Explore moving ConnectivityDiagnosticsHandler to a separate file
12019      */
12020     @VisibleForTesting
12021     class ConnectivityDiagnosticsHandler extends Handler {
12022         private final String mTag = ConnectivityDiagnosticsHandler.class.getSimpleName();
12023 
12024         /**
12025          * Used to handle ConnectivityDiagnosticsCallback registration events from {@link
12026          * android.net.ConnectivityDiagnosticsManager}.
12027          * obj = ConnectivityDiagnosticsCallbackInfo with IConnectivityDiagnosticsCallback and
12028          * NetworkRequestInfo to be registered
12029          */
12030         private static final int EVENT_REGISTER_CONNECTIVITY_DIAGNOSTICS_CALLBACK = 1;
12031 
12032         /**
12033          * Used to handle ConnectivityDiagnosticsCallback unregister events from {@link
12034          * android.net.ConnectivityDiagnosticsManager}.
12035          * obj = the IConnectivityDiagnosticsCallback to be unregistered
12036          * arg1 = the uid of the caller
12037          */
12038         private static final int EVENT_UNREGISTER_CONNECTIVITY_DIAGNOSTICS_CALLBACK = 2;
12039 
12040         /**
12041          * Event for {@link NetworkStateTrackerHandler} to trigger ConnectivityReport callbacks
12042          * after processing {@link #CMD_SEND_CONNECTIVITY_REPORT} events.
12043          * obj = {@link ConnectivityReportEvent} representing ConnectivityReport info reported from
12044          * NetworkMonitor.
12045          * data = PersistableBundle of extras passed from NetworkMonitor.
12046          */
12047         private static final int CMD_SEND_CONNECTIVITY_REPORT = 3;
12048 
12049         /**
12050          * Event for NetworkMonitor to inform ConnectivityService that a potential data stall has
12051          * been detected on the network.
12052          * obj = Long the timestamp (in millis) for when the suspected data stall was detected.
12053          * arg1 = {@link DataStallReport#DetectionMethod} indicating the detection method.
12054          * arg2 = NetID.
12055          * data = PersistableBundle of extras passed from NetworkMonitor.
12056          */
12057         private static final int EVENT_DATA_STALL_SUSPECTED = 4;
12058 
12059         /**
12060          * Event for ConnectivityDiagnosticsHandler to handle network connectivity being reported to
12061          * the platform. This event will invoke {@link
12062          * IConnectivityDiagnosticsCallback#onNetworkConnectivityReported} for permissioned
12063          * callbacks.
12064          * obj = ReportedNetworkConnectivityInfo with info on reported Network connectivity.
12065          */
12066         private static final int EVENT_NETWORK_CONNECTIVITY_REPORTED = 5;
12067 
12068         private ConnectivityDiagnosticsHandler(Looper looper) {
12069             super(looper);
12070         }
12071 
12072         @Override
12073         public void handleMessage(Message msg) {
12074             switch (msg.what) {
12075                 case EVENT_REGISTER_CONNECTIVITY_DIAGNOSTICS_CALLBACK: {
12076                     handleRegisterConnectivityDiagnosticsCallback(
12077                             (ConnectivityDiagnosticsCallbackInfo) msg.obj);
12078                     break;
12079                 }
12080                 case EVENT_UNREGISTER_CONNECTIVITY_DIAGNOSTICS_CALLBACK: {
12081                     handleUnregisterConnectivityDiagnosticsCallback(
12082                             (IConnectivityDiagnosticsCallback) msg.obj, msg.arg1);
12083                     break;
12084                 }
12085                 case CMD_SEND_CONNECTIVITY_REPORT: {
12086                     final ConnectivityReportEvent reportEvent =
12087                             (ConnectivityReportEvent) msg.obj;
12088 
12089                     handleNetworkTestedWithExtras(reportEvent, reportEvent.mExtras);
12090                     break;
12091                 }
12092                 case EVENT_DATA_STALL_SUSPECTED: {
12093                     final NetworkAgentInfo nai = getNetworkAgentInfoForNetId(msg.arg2);
12094                     final Pair<Long, PersistableBundle> arg =
12095                             (Pair<Long, PersistableBundle>) msg.obj;
12096                     if (nai == null) break;
12097 
12098                     handleDataStallSuspected(nai, arg.first, msg.arg1, arg.second);
12099                     break;
12100                 }
12101                 case EVENT_NETWORK_CONNECTIVITY_REPORTED: {
12102                     handleNetworkConnectivityReported((ReportedNetworkConnectivityInfo) msg.obj);
12103                     break;
12104                 }
12105                 default: {
12106                     Log.e(mTag, "Unrecognized event in ConnectivityDiagnostics: " + msg.what);
12107                 }
12108             }
12109         }
12110     }
12111 
12112     /** Class used for cleaning up IConnectivityDiagnosticsCallback instances after their death. */
12113     @VisibleForTesting
12114     class ConnectivityDiagnosticsCallbackInfo implements Binder.DeathRecipient {
12115         @NonNull private final IConnectivityDiagnosticsCallback mCb;
12116         @NonNull private final NetworkRequestInfo mRequestInfo;
12117         @NonNull private final String mCallingPackageName;
12118 
12119         @VisibleForTesting
12120         ConnectivityDiagnosticsCallbackInfo(
12121                 @NonNull IConnectivityDiagnosticsCallback cb,
12122                 @NonNull NetworkRequestInfo nri,
12123                 @NonNull String callingPackageName) {
12124             mCb = cb;
12125             mRequestInfo = nri;
12126             mCallingPackageName = callingPackageName;
12127         }
12128 
12129         @Override
12130         public void binderDied() {
12131             log("ConnectivityDiagnosticsCallback IBinder died.");
12132             unregisterConnectivityDiagnosticsCallback(mCb);
12133         }
12134     }
12135 
12136     /**
12137      * Class used for sending information from {@link
12138      * NetworkMonitorCallbacks#notifyNetworkTestedWithExtras} to the handler for processing it.
12139      */
12140     private static class NetworkTestedResults {
12141         private final int mNetId;
12142         private final int mTestResult;
12143         @Nullable private final String mRedirectUrl;
12144 
12145         private NetworkTestedResults(
12146                 int netId, int testResult, long timestampMillis, @Nullable String redirectUrl) {
12147             mNetId = netId;
12148             mTestResult = testResult;
12149             mRedirectUrl = redirectUrl;
12150         }
12151     }
12152 
12153     /**
12154      * Class used for sending information from {@link NetworkStateTrackerHandler} to {@link
12155      * ConnectivityDiagnosticsHandler}.
12156      */
12157     private static class ConnectivityReportEvent {
12158         private final long mTimestampMillis;
12159         @NonNull private final NetworkAgentInfo mNai;
12160         private final PersistableBundle mExtras;
12161 
12162         private ConnectivityReportEvent(long timestampMillis, @NonNull NetworkAgentInfo nai,
12163                 PersistableBundle p) {
12164             mTimestampMillis = timestampMillis;
12165             mNai = nai;
12166             mExtras = p;
12167         }
12168     }
12169 
12170     /**
12171      * Class used for sending info for a call to {@link #reportNetworkConnectivity()} to {@link
12172      * ConnectivityDiagnosticsHandler}.
12173      */
12174     private static class ReportedNetworkConnectivityInfo {
12175         public final boolean hasConnectivity;
12176         public final boolean isNetworkRevalidating;
12177         public final int reporterUid;
12178         @NonNull public final NetworkAgentInfo nai;
12179 
12180         private ReportedNetworkConnectivityInfo(
12181                 boolean hasConnectivity,
12182                 boolean isNetworkRevalidating,
12183                 int reporterUid,
12184                 @NonNull NetworkAgentInfo nai) {
12185             this.hasConnectivity = hasConnectivity;
12186             this.isNetworkRevalidating = isNetworkRevalidating;
12187             this.reporterUid = reporterUid;
12188             this.nai = nai;
12189         }
12190     }
12191 
12192     private void handleRegisterConnectivityDiagnosticsCallback(
12193             @NonNull ConnectivityDiagnosticsCallbackInfo cbInfo) {
12194         ensureRunningOnConnectivityServiceThread();
12195 
12196         final IConnectivityDiagnosticsCallback cb = cbInfo.mCb;
12197         final IBinder iCb = cb.asBinder();
12198         final NetworkRequestInfo nri = cbInfo.mRequestInfo;
12199 
12200         // Connectivity Diagnostics are meant to be used with a single network request. It would be
12201         // confusing for these networks to change when an NRI is satisfied in another layer.
12202         if (nri.isMultilayerRequest()) {
12203             throw new IllegalArgumentException("Connectivity Diagnostics do not support multilayer "
12204                 + "network requests.");
12205         }
12206 
12207         // This means that the client registered the same callback multiple times. Do
12208         // not override the previous entry, and exit silently.
12209         if (mConnectivityDiagnosticsCallbacks.containsKey(iCb)) {
12210             if (VDBG) log("Diagnostics callback is already registered");
12211 
12212             // Decrement the reference count for this NetworkRequestInfo. The reference count is
12213             // incremented when the NetworkRequestInfo is created as part of
12214             // enforceRequestCountLimit().
12215             nri.mPerUidCounter.decrementCount(nri.mUid);
12216             return;
12217         }
12218 
12219         mConnectivityDiagnosticsCallbacks.put(iCb, cbInfo);
12220 
12221         try {
12222             iCb.linkToDeath(cbInfo, 0);
12223         } catch (RemoteException e) {
12224             cbInfo.binderDied();
12225             return;
12226         }
12227 
12228         // Once registered, provide ConnectivityReports for matching Networks
12229         final List<NetworkAgentInfo> matchingNetworks = new ArrayList<>();
12230         synchronized (mNetworkForNetId) {
12231             for (int i = 0; i < mNetworkForNetId.size(); i++) {
12232                 final NetworkAgentInfo nai = mNetworkForNetId.valueAt(i);
12233                 // Connectivity Diagnostics rejects multilayer requests at registration hence get(0)
12234                 if (nai.satisfies(nri.mRequests.get(0))) {
12235                     matchingNetworks.add(nai);
12236                 }
12237             }
12238         }
12239         for (final NetworkAgentInfo nai : matchingNetworks) {
12240             final ConnectivityReport report = nai.getConnectivityReport();
12241             if (report == null) {
12242                 continue;
12243             }
12244             if (!hasConnectivityDiagnosticsPermissions(
12245                     nri.mPid, nri.mUid, nai, cbInfo.mCallingPackageName)) {
12246                 continue;
12247             }
12248 
12249             try {
12250                 cb.onConnectivityReportAvailable(report);
12251             } catch (RemoteException e) {
12252                 // Exception while sending the ConnectivityReport. Move on to the next network.
12253             }
12254         }
12255     }
12256 
12257     private void handleUnregisterConnectivityDiagnosticsCallback(
12258             @NonNull IConnectivityDiagnosticsCallback cb, int uid) {
12259         ensureRunningOnConnectivityServiceThread();
12260         final IBinder iCb = cb.asBinder();
12261 
12262         final ConnectivityDiagnosticsCallbackInfo cbInfo =
12263                 mConnectivityDiagnosticsCallbacks.remove(iCb);
12264         if (cbInfo == null) {
12265             if (VDBG) log("Removing diagnostics callback that is not currently registered");
12266             return;
12267         }
12268 
12269         final NetworkRequestInfo nri = cbInfo.mRequestInfo;
12270 
12271         // Caller's UID must either be the registrants (if they are unregistering) or the System's
12272         // (if the Binder died)
12273         if (uid != nri.mUid && uid != Process.SYSTEM_UID) {
12274             if (DBG) loge("Uid(" + uid + ") not registrant's (" + nri.mUid + ") or System's");
12275             return;
12276         }
12277 
12278         // Decrement the reference count for this NetworkRequestInfo. The reference count is
12279         // incremented when the NetworkRequestInfo is created as part of
12280         // enforceRequestCountLimit().
12281         nri.mPerUidCounter.decrementCount(nri.mUid);
12282 
12283         iCb.unlinkToDeath(cbInfo, 0);
12284     }
12285 
12286     private void handleNetworkTestedWithExtras(
12287             @NonNull ConnectivityReportEvent reportEvent, @NonNull PersistableBundle extras) {
12288         final NetworkAgentInfo nai = reportEvent.mNai;
12289         final NetworkCapabilities networkCapabilities =
12290                 getNetworkCapabilitiesWithoutUids(nai.networkCapabilities);
12291         final ConnectivityReport report =
12292                 new ConnectivityReport(
12293                         reportEvent.mNai.network,
12294                         reportEvent.mTimestampMillis,
12295                         nai.linkProperties,
12296                         networkCapabilities,
12297                         extras);
12298         nai.setConnectivityReport(report);
12299 
12300         final List<IConnectivityDiagnosticsCallback> results =
12301                 getMatchingPermissionedCallbacks(nai, Process.INVALID_UID);
12302         for (final IConnectivityDiagnosticsCallback cb : results) {
12303             try {
12304                 cb.onConnectivityReportAvailable(report);
12305             } catch (RemoteException ex) {
12306                 loge("Error invoking onConnectivityReportAvailable", ex);
12307             }
12308         }
12309     }
12310 
12311     private void handleDataStallSuspected(
12312             @NonNull NetworkAgentInfo nai, long timestampMillis, int detectionMethod,
12313             @NonNull PersistableBundle extras) {
12314         final NetworkCapabilities networkCapabilities =
12315                 getNetworkCapabilitiesWithoutUids(nai.networkCapabilities);
12316         final DataStallReport report =
12317                 new DataStallReport(
12318                         nai.network,
12319                         timestampMillis,
12320                         detectionMethod,
12321                         nai.linkProperties,
12322                         networkCapabilities,
12323                         extras);
12324         final List<IConnectivityDiagnosticsCallback> results =
12325                 getMatchingPermissionedCallbacks(nai, Process.INVALID_UID);
12326         for (final IConnectivityDiagnosticsCallback cb : results) {
12327             try {
12328                 cb.onDataStallSuspected(report);
12329             } catch (RemoteException ex) {
12330                 loge("Error invoking onDataStallSuspected", ex);
12331             }
12332         }
12333     }
12334 
12335     private void handleNetworkConnectivityReported(
12336             @NonNull ReportedNetworkConnectivityInfo reportedNetworkConnectivityInfo) {
12337         final NetworkAgentInfo nai = reportedNetworkConnectivityInfo.nai;
12338         final ConnectivityReport cachedReport = nai.getConnectivityReport();
12339 
12340         // If the Network is being re-validated as a result of this call to
12341         // reportNetworkConnectivity(), notify all permissioned callbacks. Otherwise, only notify
12342         // permissioned callbacks registered by the reporter.
12343         final List<IConnectivityDiagnosticsCallback> results =
12344                 getMatchingPermissionedCallbacks(
12345                         nai,
12346                         reportedNetworkConnectivityInfo.isNetworkRevalidating
12347                                 ? Process.INVALID_UID
12348                                 : reportedNetworkConnectivityInfo.reporterUid);
12349 
12350         for (final IConnectivityDiagnosticsCallback cb : results) {
12351             try {
12352                 cb.onNetworkConnectivityReported(
12353                         nai.network, reportedNetworkConnectivityInfo.hasConnectivity);
12354             } catch (RemoteException ex) {
12355                 loge("Error invoking onNetworkConnectivityReported", ex);
12356             }
12357 
12358             // If the Network isn't re-validating, also provide the cached report. If there is no
12359             // cached report, the Network is still being validated and a report will be sent once
12360             // validation is complete. Note that networks which never undergo validation will still
12361             // have a cached ConnectivityReport with RESULT_SKIPPED.
12362             if (!reportedNetworkConnectivityInfo.isNetworkRevalidating && cachedReport != null) {
12363                 try {
12364                     cb.onConnectivityReportAvailable(cachedReport);
12365                 } catch (RemoteException ex) {
12366                     loge("Error invoking onConnectivityReportAvailable", ex);
12367                 }
12368             }
12369         }
12370     }
12371 
12372     private NetworkCapabilities getNetworkCapabilitiesWithoutUids(@NonNull NetworkCapabilities nc) {
12373         final NetworkCapabilities sanitized = new NetworkCapabilities(nc,
12374                 NetworkCapabilities.REDACT_ALL);
12375         sanitized.setUids(null);
12376         sanitized.setAdministratorUids(new int[0]);
12377         sanitized.setOwnerUid(Process.INVALID_UID);
12378         return sanitized;
12379     }
12380 
12381     /**
12382      * Gets a list of ConnectivityDiagnostics callbacks that match the specified Network and uid.
12383      *
12384      * <p>If Process.INVALID_UID is specified, all matching callbacks will be returned.
12385      */
12386     private List<IConnectivityDiagnosticsCallback> getMatchingPermissionedCallbacks(
12387             @NonNull NetworkAgentInfo nai, int uid) {
12388         final List<IConnectivityDiagnosticsCallback> results = new ArrayList<>();
12389         for (Entry<IBinder, ConnectivityDiagnosticsCallbackInfo> entry :
12390                 mConnectivityDiagnosticsCallbacks.entrySet()) {
12391             final ConnectivityDiagnosticsCallbackInfo cbInfo = entry.getValue();
12392             final NetworkRequestInfo nri = cbInfo.mRequestInfo;
12393 
12394             // Connectivity Diagnostics rejects multilayer requests at registration hence get(0).
12395             if (!nai.satisfies(nri.mRequests.get(0))) {
12396                 continue;
12397             }
12398 
12399             // UID for this callback must either be:
12400             //  - INVALID_UID (which sends callbacks to all UIDs), or
12401             //  - The callback's owner (the owner called reportNetworkConnectivity() and is being
12402             //    notified as a result)
12403             if (uid != Process.INVALID_UID && uid != nri.mUid) {
12404                 continue;
12405             }
12406 
12407             if (!hasConnectivityDiagnosticsPermissions(
12408                     nri.mPid, nri.mUid, nai, cbInfo.mCallingPackageName)) {
12409                 continue;
12410             }
12411 
12412             results.add(entry.getValue().mCb);
12413         }
12414         return results;
12415     }
12416 
12417     private boolean isLocationPermissionRequiredForConnectivityDiagnostics(
12418             @NonNull NetworkAgentInfo nai) {
12419         // TODO(b/188483916): replace with a transport-agnostic location-aware check
12420         return nai.networkCapabilities.hasTransport(TRANSPORT_WIFI);
12421     }
12422 
12423     private boolean hasLocationPermission(String packageName, int uid) {
12424         // LocationPermissionChecker#checkLocationPermission can throw SecurityException if the uid
12425         // and package name don't match. Throwing on the CS thread is not acceptable, so wrap the
12426         // call in a try-catch.
12427         try {
12428             if (!mLocationPermissionChecker.checkLocationPermission(
12429                         packageName, null /* featureId */, uid, null /* message */)) {
12430                 return false;
12431             }
12432         } catch (SecurityException e) {
12433             return false;
12434         }
12435 
12436         return true;
12437     }
12438 
12439     private boolean ownsVpnRunningOverNetwork(int uid, Network network) {
12440         for (NetworkAgentInfo virtual : mNetworkAgentInfos) {
12441             if (virtual.propagateUnderlyingCapabilities()
12442                     && virtual.networkCapabilities.getOwnerUid() == uid
12443                     && CollectionUtils.contains(virtual.declaredUnderlyingNetworks, network)) {
12444                 return true;
12445             }
12446         }
12447 
12448         return false;
12449     }
12450 
12451     @CheckResult
12452     @VisibleForTesting
12453     boolean hasConnectivityDiagnosticsPermissions(
12454             int callbackPid, int callbackUid, NetworkAgentInfo nai, String callbackPackageName) {
12455         if (hasNetworkStackPermission(callbackPid, callbackUid)) {
12456             return true;
12457         }
12458         if (mAllowSysUiConnectivityReports
12459                 && hasSystemBarServicePermission(callbackPid, callbackUid)) {
12460             return true;
12461         }
12462 
12463         // Administrator UIDs also contains the Owner UID
12464         final int[] administratorUids = nai.networkCapabilities.getAdministratorUids();
12465         if (!CollectionUtils.contains(administratorUids, callbackUid)
12466                 && !ownsVpnRunningOverNetwork(callbackUid, nai.network)) {
12467             return false;
12468         }
12469 
12470         return !isLocationPermissionRequiredForConnectivityDiagnostics(nai)
12471                 || hasLocationPermission(callbackPackageName, callbackUid);
12472     }
12473 
12474     @Override
12475     public void registerConnectivityDiagnosticsCallback(
12476             @NonNull IConnectivityDiagnosticsCallback callback,
12477             @NonNull NetworkRequest request,
12478             @NonNull String callingPackageName) {
12479         Objects.requireNonNull(callback, "callback must not be null");
12480         Objects.requireNonNull(request, "request must not be null");
12481         Objects.requireNonNull(callingPackageName, "callingPackageName must not be null");
12482 
12483         if (request.legacyType != TYPE_NONE) {
12484             throw new IllegalArgumentException("ConnectivityManager.TYPE_* are deprecated."
12485                     + " Please use NetworkCapabilities instead.");
12486         }
12487         final int callingUid = mDeps.getCallingUid();
12488         mAppOpsManager.checkPackage(callingUid, callingPackageName);
12489 
12490         // This NetworkCapabilities is only used for matching to Networks. Clear out its owner uid
12491         // and administrator uids to be safe.
12492         final NetworkCapabilities nc = new NetworkCapabilities(request.networkCapabilities);
12493         restrictRequestNetworkCapabilitiesForCaller(nc, callingUid, callingPackageName);
12494 
12495         final NetworkRequest requestWithId =
12496                 new NetworkRequest(
12497                         nc, TYPE_NONE, nextNetworkRequestId(), NetworkRequest.Type.LISTEN);
12498 
12499         // NetworkRequestInfos created here count towards MAX_NETWORK_REQUESTS_PER_UID limit.
12500         //
12501         // nri is not bound to the death of callback. Instead, callback.bindToDeath() is set in
12502         // handleRegisterConnectivityDiagnosticsCallback(). nri will be cleaned up as part of the
12503         // callback's binder death.
12504         final NetworkRequestInfo nri = new NetworkRequestInfo(callingUid, requestWithId);
12505         nri.mPerUidCounter.incrementCountOrThrow(nri.mUid);
12506         final ConnectivityDiagnosticsCallbackInfo cbInfo =
12507                 new ConnectivityDiagnosticsCallbackInfo(callback, nri, callingPackageName);
12508 
12509         mConnectivityDiagnosticsHandler.sendMessage(
12510                 mConnectivityDiagnosticsHandler.obtainMessage(
12511                         ConnectivityDiagnosticsHandler
12512                                 .EVENT_REGISTER_CONNECTIVITY_DIAGNOSTICS_CALLBACK,
12513                         cbInfo));
12514     }
12515 
12516     @Override
12517     public void unregisterConnectivityDiagnosticsCallback(
12518             @NonNull IConnectivityDiagnosticsCallback callback) {
12519         Objects.requireNonNull(callback, "callback must be non-null");
12520         mConnectivityDiagnosticsHandler.sendMessage(
12521                 mConnectivityDiagnosticsHandler.obtainMessage(
12522                         ConnectivityDiagnosticsHandler
12523                                 .EVENT_UNREGISTER_CONNECTIVITY_DIAGNOSTICS_CALLBACK,
12524                         mDeps.getCallingUid(),
12525                         0,
12526                         callback));
12527     }
12528 
12529     private boolean hasUnderlyingTestNetworks(NetworkCapabilities nc) {
12530         final List<Network> underlyingNetworks = nc.getUnderlyingNetworks();
12531         if (underlyingNetworks == null) return false;
12532 
12533         for (Network network : underlyingNetworks) {
12534             if (getNetworkCapabilitiesInternal(network).hasTransport(TRANSPORT_TEST)) {
12535                 return true;
12536             }
12537         }
12538         return false;
12539     }
12540 
12541     @Override
12542     public void simulateDataStall(int detectionMethod, long timestampMillis,
12543             @NonNull Network network, @NonNull PersistableBundle extras) {
12544         Objects.requireNonNull(network, "network must not be null");
12545         Objects.requireNonNull(extras, "extras must not be null");
12546 
12547         enforceAnyPermissionOf(mContext,
12548                 android.Manifest.permission.MANAGE_TEST_NETWORKS,
12549                 android.Manifest.permission.NETWORK_STACK);
12550         final NetworkCapabilities nc = getNetworkCapabilitiesInternal(network);
12551         if (!nc.hasTransport(TRANSPORT_TEST) && !hasUnderlyingTestNetworks(nc)) {
12552             throw new SecurityException(
12553                     "Data Stall simulation is only possible for test networks or networks built on"
12554                             + " top of test networks");
12555         }
12556 
12557         final NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
12558         if (nai == null
12559                 || (nai.creatorUid != mDeps.getCallingUid()
12560                         && nai.creatorUid != Process.SYSTEM_UID)) {
12561             throw new SecurityException(
12562                     "Data Stall simulation is only possible for network " + "creators");
12563         }
12564 
12565         // Instead of passing the data stall directly to the ConnectivityDiagnostics handler, treat
12566         // this as a Data Stall received directly from NetworkMonitor. This requires wrapping the
12567         // Data Stall information as a DataStallReportParcelable and passing to
12568         // #notifyDataStallSuspected. This ensures that unknown Data Stall detection methods are
12569         // still passed to ConnectivityDiagnostics (with new detection methods masked).
12570         final DataStallReportParcelable p = new DataStallReportParcelable();
12571         p.timestampMillis = timestampMillis;
12572         p.detectionMethod = detectionMethod;
12573 
12574         if (hasDataStallDetectionMethod(p, DETECTION_METHOD_DNS_EVENTS)) {
12575             p.dnsConsecutiveTimeouts = extras.getInt(KEY_DNS_CONSECUTIVE_TIMEOUTS);
12576         }
12577         if (hasDataStallDetectionMethod(p, DETECTION_METHOD_TCP_METRICS)) {
12578             p.tcpPacketFailRate = extras.getInt(KEY_TCP_PACKET_FAIL_RATE);
12579             p.tcpMetricsCollectionPeriodMillis = extras.getInt(
12580                     KEY_TCP_METRICS_COLLECTION_PERIOD_MILLIS);
12581         }
12582 
12583         notifyDataStallSuspected(p, network.getNetId());
12584     }
12585 
12586     /**
12587      * Class to hold the information for network activity change event from idle timers
12588      * {@link NetdCallback#onInterfaceClassActivityChanged(boolean, int, long, int)}
12589      */
12590     private static final class NetworkActivityParams {
12591         public final boolean isActive;
12592         // If TrackMultiNetworkActivities is enabled, idleTimer label is netid.
12593         // If TrackMultiNetworkActivities is disabled, idleTimer label is transport type.
12594         public final int label;
12595         public final long timestampNs;
12596         // Uid represents the uid that was responsible for waking the radio.
12597         // -1 for no uid and uid is -1 if isActive is false.
12598         public final int uid;
12599 
12600         NetworkActivityParams(boolean isActive, int label, long timestampNs, int uid) {
12601             this.isActive = isActive;
12602             this.label = label;
12603             this.timestampNs = timestampNs;
12604             this.uid = uid;
12605         }
12606     }
12607 
12608     private class NetdCallback extends BaseNetdUnsolicitedEventListener {
12609         @Override
12610         public void onInterfaceClassActivityChanged(boolean isActive, int label,
12611                 long timestampNs, int uid) {
12612             mHandler.sendMessage(mHandler.obtainMessage(EVENT_REPORT_NETWORK_ACTIVITY,
12613                     new NetworkActivityParams(isActive, label, timestampNs, uid)));
12614         }
12615 
12616         @Override
12617         public void onInterfaceLinkStateChanged(@NonNull String iface, boolean up) {
12618             mHandler.post(() -> {
12619                 for (NetworkAgentInfo nai : mNetworkAgentInfos) {
12620                     nai.clatd.handleInterfaceLinkStateChanged(iface, up);
12621                 }
12622             });
12623         }
12624 
12625         @Override
12626         public void onInterfaceRemoved(@NonNull String iface) {
12627             mHandler.post(() -> {
12628                 for (NetworkAgentInfo nai : mNetworkAgentInfos) {
12629                     nai.clatd.handleInterfaceRemoved(iface);
12630                 }
12631             });
12632         }
12633     }
12634 
12635     private final boolean mTrackMultiNetworkActivities;
12636     private final LegacyNetworkActivityTracker mNetworkActivityTracker;
12637 
12638     /**
12639      * Class used for updating network activity tracking with netd and notify network activity
12640      * changes.
12641      */
12642     @VisibleForTesting
12643     public static final class LegacyNetworkActivityTracker {
12644         private static final int NO_UID = -1;
12645         private final Context mContext;
12646         private final INetd mNetd;
12647         private final Handler mHandler;
12648         private final RemoteCallbackList<INetworkActivityListener> mNetworkActivityListeners =
12649                 new RemoteCallbackList<>();
12650         // Indicate the current system default network activity is active or not.
12651         // This needs to be volatile to allow non handler threads to read this value without lock.
12652         // If there is no default network, default network is considered active to keep the existing
12653         // behavior. Initial value is used until first connect to the default network.
12654         private volatile boolean mIsDefaultNetworkActive = true;
12655         private Network mDefaultNetwork;
12656         // Key is netId. Value is configured idle timer information.
12657         private final SparseArray<IdleTimerParams> mActiveIdleTimers = new SparseArray<>();
12658         private final boolean mTrackMultiNetworkActivities;
12659         // Store netIds of Wi-Fi networks whose idletimers report that they are active
12660         private final Set<Integer> mActiveWifiNetworks = new ArraySet<>();
12661         // Store netIds of cellular networks whose idletimers report that they are active
12662         private final Set<Integer> mActiveCellularNetworks = new ArraySet<>();
12663 
12664         private static class IdleTimerParams {
12665             public final int timeout;
12666             public final int transportType;
12667 
12668             IdleTimerParams(int timeout, int transport) {
12669                 this.timeout = timeout;
12670                 this.transportType = transport;
12671             }
12672         }
12673 
12674         LegacyNetworkActivityTracker(@NonNull Context context, @NonNull INetd netd,
12675                 @NonNull Handler handler, boolean trackMultiNetworkActivities) {
12676             mContext = context;
12677             mNetd = netd;
12678             mHandler = handler;
12679             mTrackMultiNetworkActivities = trackMultiNetworkActivities;
12680         }
12681 
12682         private void ensureRunningOnConnectivityServiceThread() {
12683             if (mHandler.getLooper().getThread() != Thread.currentThread()) {
12684                 throw new IllegalStateException("Not running on ConnectivityService thread: "
12685                                 + Thread.currentThread().getName());
12686             }
12687         }
12688 
12689         /**
12690          * Update network activity and call BatteryStats to update radio power state if the
12691          * mobile or Wi-Fi activity is changed.
12692          * LegacyNetworkActivityTracker considers the mobile network is active if at least one
12693          * mobile network is active since BatteryStatsService only maintains a single power state
12694          * for the mobile network.
12695          * The Wi-Fi network is also the same.
12696          *
12697          * {@link #setupDataActivityTracking} and {@link #removeDataActivityTracking} use
12698          * TRANSPORT_CELLULAR as the transportType argument if the network has both cell and Wi-Fi
12699          * transports.
12700          */
12701         private void maybeUpdateRadioPowerState(final int netId, final int transportType,
12702                 final boolean isActive, final int uid) {
12703             if (transportType != TRANSPORT_WIFI && transportType != TRANSPORT_CELLULAR) {
12704                 Log.e(TAG, "Unexpected transportType in maybeUpdateRadioPowerState: "
12705                         + transportType);
12706                 return;
12707             }
12708             final Set<Integer> activeNetworks = transportType == TRANSPORT_WIFI
12709                     ? mActiveWifiNetworks : mActiveCellularNetworks;
12710 
12711             final boolean wasEmpty = activeNetworks.isEmpty();
12712             if (isActive) {
12713                 activeNetworks.add(netId);
12714             } else {
12715                 activeNetworks.remove(netId);
12716             }
12717 
12718             if (wasEmpty != activeNetworks.isEmpty()) {
12719                 updateRadioPowerState(isActive, transportType, uid);
12720             }
12721         }
12722 
12723         private void handleDefaultNetworkActivity(final int transportType,
12724                 final boolean isActive, final long timestampNs) {
12725             mIsDefaultNetworkActive = isActive;
12726             sendDataActivityBroadcast(transportTypeToLegacyType(transportType),
12727                     isActive, timestampNs);
12728             if (isActive) {
12729                 reportNetworkActive();
12730             }
12731         }
12732 
12733         private void handleReportNetworkActivityWithNetIdLabel(
12734                 NetworkActivityParams activityParams) {
12735             final int netId = activityParams.label;
12736             final IdleTimerParams idleTimerParams = mActiveIdleTimers.get(netId);
12737             if (idleTimerParams == null) {
12738                 // This network activity change is not tracked anymore
12739                 // This can happen if netd callback post activity change event message but idle
12740                 // timer is removed before processing this message.
12741                 return;
12742             }
12743             // TODO: if a network changes transports, storing the transport type in the
12744             // IdleTimerParams is not correct. Consider getting it from the network's
12745             // NetworkCapabilities instead.
12746             final int transportType = idleTimerParams.transportType;
12747             maybeUpdateRadioPowerState(netId, transportType,
12748                     activityParams.isActive, activityParams.uid);
12749 
12750             if (mDefaultNetwork == null || mDefaultNetwork.netId != netId) {
12751                 // This activity change is not for the default network.
12752                 return;
12753             }
12754 
12755             handleDefaultNetworkActivity(transportType, activityParams.isActive,
12756                     activityParams.timestampNs);
12757         }
12758 
12759         private void handleReportNetworkActivityWithTransportTypeLabel(
12760                 NetworkActivityParams activityParams) {
12761             if (mActiveIdleTimers.size() == 0) {
12762                 // This activity change is not for the current default network.
12763                 // This can happen if netd callback post activity change event message but
12764                 // the default network is lost before processing this message.
12765                 return;
12766             }
12767             handleDefaultNetworkActivity(activityParams.label, activityParams.isActive,
12768                     activityParams.timestampNs);
12769         }
12770 
12771         /**
12772          * Handle network activity change
12773          */
12774         public void handleReportNetworkActivity(NetworkActivityParams activityParams) {
12775             ensureRunningOnConnectivityServiceThread();
12776             if (mTrackMultiNetworkActivities) {
12777                 handleReportNetworkActivityWithNetIdLabel(activityParams);
12778             } else {
12779                 handleReportNetworkActivityWithTransportTypeLabel(activityParams);
12780             }
12781         }
12782 
12783         private void reportNetworkActive() {
12784             final int length = mNetworkActivityListeners.beginBroadcast();
12785             if (DDBG) log("reportNetworkActive, notify " + length + " listeners");
12786             try {
12787                 for (int i = 0; i < length; i++) {
12788                     try {
12789                         mNetworkActivityListeners.getBroadcastItem(i).onNetworkActive();
12790                     } catch (RemoteException | RuntimeException e) {
12791                         loge("Fail to send network activity to listener " + e);
12792                     }
12793                 }
12794             } finally {
12795                 mNetworkActivityListeners.finishBroadcast();
12796             }
12797         }
12798 
12799         // This is deprecated and only to support legacy use cases.
12800         private int transportTypeToLegacyType(int type) {
12801             switch (type) {
12802                 case NetworkCapabilities.TRANSPORT_CELLULAR:
12803                     return TYPE_MOBILE;
12804                 case NetworkCapabilities.TRANSPORT_WIFI:
12805                     return TYPE_WIFI;
12806                 case NetworkCapabilities.TRANSPORT_BLUETOOTH:
12807                     return TYPE_BLUETOOTH;
12808                 case NetworkCapabilities.TRANSPORT_ETHERNET:
12809                     return TYPE_ETHERNET;
12810                 default:
12811                     loge("Unexpected transport in transportTypeToLegacyType: " + type);
12812             }
12813             return ConnectivityManager.TYPE_NONE;
12814         }
12815 
12816         public void sendDataActivityBroadcast(int deviceType, boolean active, long tsNanos) {
12817             final Intent intent = new Intent(ConnectivityManager.ACTION_DATA_ACTIVITY_CHANGE);
12818             intent.putExtra(ConnectivityManager.EXTRA_DEVICE_TYPE, deviceType);
12819             intent.putExtra(ConnectivityManager.EXTRA_IS_ACTIVE, active);
12820             intent.putExtra(ConnectivityManager.EXTRA_REALTIME_NS, tsNanos);
12821             final long ident = Binder.clearCallingIdentity();
12822             try {
12823                 mContext.sendOrderedBroadcastAsUser(intent, UserHandle.ALL,
12824                         RECEIVE_DATA_ACTIVITY_CHANGE,
12825                         null /* resultReceiver */,
12826                         null /* scheduler */,
12827                         0 /* initialCode */,
12828                         null /* initialData */,
12829                         null /* initialExtra */);
12830             } finally {
12831                 Binder.restoreCallingIdentity(ident);
12832             }
12833         }
12834 
12835         /**
12836          * Get idle timer label
12837          */
12838         @VisibleForTesting
12839         public static int getIdleTimerLabel(final boolean trackMultiNetworkActivities,
12840                 final int netId, final int transportType) {
12841             return trackMultiNetworkActivities ? netId : transportType;
12842         }
12843 
12844         private boolean maybeCreateIdleTimer(
12845                 String iface, int netId, int timeout, int transportType) {
12846             if (timeout <= 0 || iface == null) return false;
12847             try {
12848                 final String label = Integer.toString(getIdleTimerLabel(
12849                         mTrackMultiNetworkActivities, netId, transportType));
12850                 mNetd.idletimerAddInterface(iface, timeout, label);
12851                 mActiveIdleTimers.put(netId, new IdleTimerParams(timeout, transportType));
12852                 return true;
12853             } catch (Exception e) {
12854                 loge("Exception in createIdleTimer", e);
12855                 return false;
12856             }
12857         }
12858 
12859         /**
12860          * Setup data activity tracking for the given network.
12861          *
12862          * Every {@code setupDataActivityTracking} should be paired with a
12863          * {@link #removeDataActivityTracking} for cleanup.
12864          *
12865          * @return true if the idleTimer is added to the network, false otherwise
12866          */
12867         private boolean setupDataActivityTracking(NetworkAgentInfo networkAgent) {
12868             ensureRunningOnConnectivityServiceThread();
12869             final String iface = networkAgent.linkProperties.getInterfaceName();
12870             final int netId = networkAgent.network().netId;
12871 
12872             final int timeout;
12873             final int type;
12874 
12875             if (!networkAgent.networkCapabilities.hasCapability(NET_CAPABILITY_NOT_VPN)) {
12876                 // Do not track VPN network.
12877                 return false;
12878             } else if (networkAgent.networkCapabilities.hasTransport(
12879                     NetworkCapabilities.TRANSPORT_CELLULAR)) {
12880                 timeout = Settings.Global.getInt(mContext.getContentResolver(),
12881                         ConnectivitySettingsManager.DATA_ACTIVITY_TIMEOUT_MOBILE,
12882                         10);
12883                 type = NetworkCapabilities.TRANSPORT_CELLULAR;
12884             } else if (networkAgent.networkCapabilities.hasTransport(
12885                     NetworkCapabilities.TRANSPORT_WIFI)) {
12886                 timeout = Settings.Global.getInt(mContext.getContentResolver(),
12887                         ConnectivitySettingsManager.DATA_ACTIVITY_TIMEOUT_WIFI,
12888                         15);
12889                 type = NetworkCapabilities.TRANSPORT_WIFI;
12890             } else {
12891                 return false; // do not track any other networks
12892             }
12893 
12894             final boolean hasIdleTimer = maybeCreateIdleTimer(iface, netId, timeout, type);
12895             if (hasIdleTimer || !mTrackMultiNetworkActivities) {
12896                 // If trackMultiNetwork is disabled, NetworkActivityTracker updates radio power
12897                 // state in all cases. If trackMultiNetwork is enabled, it updates radio power
12898                 // state only about a network that has an idletimer.
12899                 maybeUpdateRadioPowerState(netId, type, true /* isActive */, NO_UID);
12900             }
12901             return hasIdleTimer;
12902         }
12903 
12904         /**
12905          * Remove data activity tracking when network disconnects.
12906          */
12907         public void removeDataActivityTracking(NetworkAgentInfo networkAgent) {
12908             ensureRunningOnConnectivityServiceThread();
12909             final String iface = networkAgent.linkProperties.getInterfaceName();
12910             final int netId = networkAgent.network().netId;
12911             final NetworkCapabilities caps = networkAgent.networkCapabilities;
12912 
12913             if (iface == null) return;
12914 
12915             final int type;
12916             if (!networkAgent.networkCapabilities.hasCapability(NET_CAPABILITY_NOT_VPN)) {
12917                 // Do not track VPN network.
12918                 return;
12919             } else if (caps.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
12920                 type = NetworkCapabilities.TRANSPORT_CELLULAR;
12921             } else if (caps.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
12922                 type = NetworkCapabilities.TRANSPORT_WIFI;
12923             } else {
12924                 return; // do not track any other networks
12925             }
12926 
12927             try {
12928                 maybeUpdateRadioPowerState(netId, type, false /* isActive */, NO_UID);
12929                 final IdleTimerParams params = mActiveIdleTimers.get(netId);
12930                 if (params == null) {
12931                     // IdleTimer is not added if the configured timeout is 0 or negative value
12932                     return;
12933                 }
12934                 mActiveIdleTimers.remove(netId);
12935                 final String label = Integer.toString(getIdleTimerLabel(
12936                         mTrackMultiNetworkActivities, netId, params.transportType));
12937                         // The call fails silently if no idle timer setup for this interface
12938                 mNetd.idletimerRemoveInterface(iface, params.timeout, label);
12939             } catch (Exception e) {
12940                 // You shall not crash!
12941                 loge("Exception in removeDataActivityTracking " + e);
12942             }
12943         }
12944 
12945         private void updateDefaultNetworkActivity(NetworkAgentInfo defaultNetwork,
12946                 boolean hasIdleTimer) {
12947             if (defaultNetwork != null) {
12948                 mDefaultNetwork = defaultNetwork.network();
12949                 mIsDefaultNetworkActive = true;
12950                 // If only the default network is tracked, callbacks are called only when the
12951                 // network has the idle timer.
12952                 if (mTrackMultiNetworkActivities || hasIdleTimer) {
12953                     reportNetworkActive();
12954                 }
12955             } else {
12956                 mDefaultNetwork = null;
12957                 // If there is no default network, default network is considered active to keep the
12958                 // existing behavior.
12959                 mIsDefaultNetworkActive = true;
12960             }
12961         }
12962 
12963         /**
12964          * Update the default network this class tracks the activity of.
12965          */
12966         public void updateDefaultNetwork(NetworkAgentInfo newNetwork,
12967                 NetworkAgentInfo oldNetwork) {
12968             ensureRunningOnConnectivityServiceThread();
12969             // If TrackMultiNetworkActivities is enabled, devices add idleTimer when the network is
12970             // first connected and remove when the network is disconnected.
12971             // If TrackMultiNetworkActivities is disabled, devices add idleTimer when the network
12972             // becomes the default network and remove when the network becomes no longer the default
12973             // network.
12974             boolean hasIdleTimer = false;
12975             if (!mTrackMultiNetworkActivities && newNetwork != null) {
12976                 hasIdleTimer = setupDataActivityTracking(newNetwork);
12977             }
12978             updateDefaultNetworkActivity(newNetwork, hasIdleTimer);
12979             if (!mTrackMultiNetworkActivities && oldNetwork != null) {
12980                 removeDataActivityTracking(oldNetwork);
12981             }
12982         }
12983 
12984         private void updateRadioPowerState(boolean isActive, int transportType, int uid) {
12985             final BatteryStatsManager bs = mContext.getSystemService(BatteryStatsManager.class);
12986             switch (transportType) {
12987                 case NetworkCapabilities.TRANSPORT_CELLULAR:
12988                     bs.reportMobileRadioPowerState(isActive, uid);
12989                     break;
12990                 case NetworkCapabilities.TRANSPORT_WIFI:
12991                     bs.reportWifiRadioPowerState(isActive, uid);
12992                     break;
12993                 default:
12994                     logw("Untracked transport type:" + transportType);
12995             }
12996         }
12997 
12998         public boolean isDefaultNetworkActive() {
12999             return mIsDefaultNetworkActive;
13000         }
13001 
13002         public void registerNetworkActivityListener(@NonNull INetworkActivityListener l) {
13003             mNetworkActivityListeners.register(l);
13004         }
13005 
13006         public void unregisterNetworkActivityListener(@NonNull INetworkActivityListener l) {
13007             mNetworkActivityListeners.unregister(l);
13008         }
13009 
13010         public void dump(IndentingPrintWriter pw) {
13011             pw.print("mTrackMultiNetworkActivities="); pw.println(mTrackMultiNetworkActivities);
13012             pw.print("mIsDefaultNetworkActive="); pw.println(mIsDefaultNetworkActive);
13013             pw.print("mDefaultNetwork="); pw.println(mDefaultNetwork);
13014             pw.println("Idle timers:");
13015             try {
13016                 for (int i = 0; i < mActiveIdleTimers.size(); i++) {
13017                     pw.print("  "); pw.print(mActiveIdleTimers.keyAt(i)); pw.println(":");
13018                     final IdleTimerParams params = mActiveIdleTimers.valueAt(i);
13019                     pw.print("    timeout="); pw.print(params.timeout);
13020                     pw.print(" type="); pw.println(params.transportType);
13021                 }
13022                 pw.println("WiFi active networks: " + mActiveWifiNetworks);
13023                 pw.println("Cellular active networks: " + mActiveCellularNetworks);
13024             } catch (Exception e) {
13025                 // mActiveIdleTimers, mActiveWifiNetworks, and mActiveCellularNetworks should only
13026                 // be accessed from handler thread, except dump(). As dump() is never called in
13027                 // normal usage, it would be needlessly expensive to lock the collection only for
13028                 // its benefit. Also, they are not expected to be updated frequently.
13029                 // So catching the exception and logging.
13030                 pw.println("Failed to dump NetworkActivityTracker: " + e);
13031             }
13032         }
13033     }
13034 
13035     /**
13036      * Registers {@link QosSocketFilter} with {@link IQosCallback}.
13037      *
13038      * @param socketInfo the socket information
13039      * @param callback the callback to register
13040      */
13041     @Override
13042     public void registerQosSocketCallback(@NonNull final QosSocketInfo socketInfo,
13043             @NonNull final IQosCallback callback) {
13044         final NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(socketInfo.getNetwork());
13045         if (nai == null || nai.networkCapabilities == null) {
13046             try {
13047                 callback.onError(QosCallbackException.EX_TYPE_FILTER_NETWORK_RELEASED);
13048             } catch (final RemoteException ex) {
13049                 loge("registerQosCallbackInternal: RemoteException", ex);
13050             }
13051             return;
13052         }
13053         registerQosCallbackInternal(new QosSocketFilter(socketInfo), callback, nai);
13054     }
13055 
13056     /**
13057      * Register a {@link IQosCallback} with base {@link QosFilter}.
13058      *
13059      * @param filter the filter to register
13060      * @param callback the callback to register
13061      * @param nai the agent information related to the filter's network
13062      */
13063     @VisibleForTesting
13064     public void registerQosCallbackInternal(@NonNull final QosFilter filter,
13065             @NonNull final IQosCallback callback, @NonNull final NetworkAgentInfo nai) {
13066         Objects.requireNonNull(filter, "filter must be non-null");
13067         Objects.requireNonNull(callback, "callback must be non-null");
13068 
13069         if (!nai.networkCapabilities.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)) {
13070             // TODO: Check allowed list here and ensure that either a) any QoS callback registered
13071             //  on this network is unregistered when the app loses permission or b) no QoS
13072             //  callbacks are sent for restricted networks unless the app currently has permission
13073             //  to access restricted networks.
13074             enforceConnectivityRestrictedNetworksPermission(false /* checkUidsAllowedList */);
13075         }
13076         mQosCallbackTracker.registerCallback(callback, filter, nai);
13077     }
13078 
13079     /**
13080      * Unregisters the given callback.
13081      *
13082      * @param callback the callback to unregister
13083      */
13084     @Override
13085     public void unregisterQosCallback(@NonNull final IQosCallback callback) {
13086         Objects.requireNonNull(callback, "callback must be non-null");
13087         mQosCallbackTracker.unregisterCallback(callback);
13088     }
13089 
13090     private boolean isNetworkPreferenceAllowedForProfile(@NonNull UserHandle profile) {
13091         // UserManager.isManagedProfile returns true for all apps in managed user profiles.
13092         // Enterprise device can be fully managed like device owner and such use case
13093         // also should be supported. Calling app check for work profile and fully managed device
13094         // is already done in DevicePolicyManager.
13095         // This check is an extra caution to be sure device is fully managed or not.
13096         final UserManager um = mContext.getSystemService(UserManager.class);
13097         final DevicePolicyManager dpm = mContext.getSystemService(DevicePolicyManager.class);
13098         if (um.isManagedProfile(profile.getIdentifier())) {
13099             return true;
13100         }
13101 
13102         return mDeps.isAtLeastT() && dpm.getDeviceOwnerComponentOnAnyUser() != null;
13103     }
13104 
13105     /**
13106      * Set a list of default network selection policies for a user profile or device owner.
13107      *
13108      * See the documentation for the individual preferences for a description of the supported
13109      * behaviors.
13110      *
13111      * @param profile If the device owner is set, any profile is allowed.
13112               Otherwise, the given profile can only be managed profile.
13113      * @param preferences the list of profile network preferences for the
13114      *        provided profile.
13115      * @param listener an optional listener to listen for completion of the operation.
13116      */
13117     @Override
13118     public void setProfileNetworkPreferences(
13119             @NonNull final UserHandle profile,
13120             @NonNull List<ProfileNetworkPreference> preferences,
13121             @Nullable final IOnCompleteListener listener) {
13122         Objects.requireNonNull(preferences);
13123         Objects.requireNonNull(profile);
13124 
13125         if (preferences.size() == 0) {
13126             final ProfileNetworkPreference pref = new ProfileNetworkPreference.Builder()
13127                     .setPreference(ConnectivityManager.PROFILE_NETWORK_PREFERENCE_DEFAULT)
13128                     .build();
13129             preferences.add(pref);
13130         }
13131 
13132         enforceNetworkStackPermission(mContext);
13133         if (DBG) {
13134             log("setProfileNetworkPreferences " + profile + " to " + preferences);
13135         }
13136         if (profile.getIdentifier() < 0) {
13137             throw new IllegalArgumentException("Must explicitly specify a user handle ("
13138                     + "UserHandle.CURRENT not supported)");
13139         }
13140         if (!isNetworkPreferenceAllowedForProfile(profile)) {
13141             throw new IllegalArgumentException("Profile must be a managed profile "
13142                     + "or the device owner must be set. ");
13143         }
13144 
13145         final List<ProfileNetworkPreferenceInfo> preferenceList = new ArrayList<>();
13146         boolean hasDefaultPreference = false;
13147         for (final ProfileNetworkPreference preference : preferences) {
13148             final NetworkCapabilities nc;
13149             boolean allowFallback = true;
13150             boolean blockingNonEnterprise = false;
13151             switch (preference.getPreference()) {
13152                 case ConnectivityManager.PROFILE_NETWORK_PREFERENCE_DEFAULT:
13153                     nc = null;
13154                     hasDefaultPreference = true;
13155                     if (preference.getPreferenceEnterpriseId() != 0) {
13156                         throw new IllegalArgumentException(
13157                                 "Invalid enterprise identifier in setProfileNetworkPreferences");
13158                     }
13159                     break;
13160                 case ConnectivityManager.PROFILE_NETWORK_PREFERENCE_ENTERPRISE_BLOCKING:
13161                     blockingNonEnterprise = true;
13162                     // continue to process the enterprise preference.
13163                 case ConnectivityManager.PROFILE_NETWORK_PREFERENCE_ENTERPRISE_NO_FALLBACK:
13164                     allowFallback = false;
13165                     // continue to process the enterprise preference.
13166                 case ConnectivityManager.PROFILE_NETWORK_PREFERENCE_ENTERPRISE:
13167                     // This code is needed even though there is a check later on,
13168                     // because isRangeAlreadyInPreferenceList assumes that every preference
13169                     // has a UID list.
13170                     if (hasDefaultPreference) {
13171                         throw new IllegalArgumentException(
13172                                 "Default profile preference should not be set along with other "
13173                                         + "preference");
13174                     }
13175                     if (!isEnterpriseIdentifierValid(preference.getPreferenceEnterpriseId())) {
13176                         throw new IllegalArgumentException(
13177                                 "Invalid enterprise identifier in setProfileNetworkPreferences");
13178                     }
13179                     final Set<UidRange> uidRangeSet =
13180                             getUidListToBeAppliedForNetworkPreference(profile, preference);
13181                     if (!isRangeAlreadyInPreferenceList(preferenceList, uidRangeSet)) {
13182                         nc = createDefaultNetworkCapabilitiesForUidRangeSet(uidRangeSet);
13183                     } else {
13184                         throw new IllegalArgumentException(
13185                                 "Overlapping uid range in setProfileNetworkPreferences");
13186                     }
13187                     nc.addCapability(NET_CAPABILITY_ENTERPRISE);
13188                     nc.addEnterpriseId(
13189                             preference.getPreferenceEnterpriseId());
13190                     nc.removeCapability(NET_CAPABILITY_NOT_RESTRICTED);
13191                     break;
13192                 default:
13193                     throw new IllegalArgumentException(
13194                             "Invalid preference in setProfileNetworkPreferences");
13195             }
13196             preferenceList.add(new ProfileNetworkPreferenceInfo(
13197                     profile, nc, allowFallback, blockingNonEnterprise));
13198             if (hasDefaultPreference && preferenceList.size() > 1) {
13199                 throw new IllegalArgumentException(
13200                         "Default profile preference should not be set along with other preference");
13201             }
13202         }
13203         mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_PROFILE_NETWORK_PREFERENCE,
13204                 new Pair<>(preferenceList, listener)));
13205     }
13206 
13207     private Set<UidRange> getUidListToBeAppliedForNetworkPreference(
13208             @NonNull final UserHandle profile,
13209             @NonNull final ProfileNetworkPreference profileNetworkPreference) {
13210         final UidRange profileUids = UidRange.createForUser(profile);
13211         Set<UidRange> uidRangeSet = UidRangeUtils.convertArrayToUidRange(
13212                         profileNetworkPreference.getIncludedUids());
13213 
13214         if (uidRangeSet.size() > 0) {
13215             if (!UidRangeUtils.isRangeSetInUidRange(profileUids, uidRangeSet)) {
13216                 throw new IllegalArgumentException(
13217                         "Allow uid range is outside the uid range of profile.");
13218             }
13219         } else {
13220             ArraySet<UidRange> disallowUidRangeSet = UidRangeUtils.convertArrayToUidRange(
13221                     profileNetworkPreference.getExcludedUids());
13222             if (disallowUidRangeSet.size() > 0) {
13223                 if (!UidRangeUtils.isRangeSetInUidRange(profileUids, disallowUidRangeSet)) {
13224                     throw new IllegalArgumentException(
13225                             "disallow uid range is outside the uid range of profile.");
13226                 }
13227                 uidRangeSet = UidRangeUtils.removeRangeSetFromUidRange(profileUids,
13228                         disallowUidRangeSet);
13229             } else {
13230                 uidRangeSet = new ArraySet<>();
13231                 uidRangeSet.add(profileUids);
13232             }
13233         }
13234         return uidRangeSet;
13235     }
13236 
13237     private boolean isEnterpriseIdentifierValid(
13238             @NetworkCapabilities.EnterpriseId int identifier) {
13239         if ((identifier >= NET_ENTERPRISE_ID_1) && (identifier <= NET_ENTERPRISE_ID_5)) {
13240             return true;
13241         }
13242         return false;
13243     }
13244 
13245     private ArraySet<NetworkRequestInfo> createNrisFromProfileNetworkPreferences(
13246             @NonNull final NetworkPreferenceList<UserHandle, ProfileNetworkPreferenceInfo> prefs) {
13247         final ArraySet<NetworkRequestInfo> result = new ArraySet<>();
13248         for (final ProfileNetworkPreferenceInfo pref : prefs) {
13249             // The NRI for a user should contain the request for capabilities.
13250             // If fallback to default network is needed then NRI should include
13251             // the request for the default network. Create an image of it to
13252             // have the correct UIDs in it (also a request can only be part of one NRI, because
13253             // of lookups in 1:1 associations like mNetworkRequests).
13254             final ArrayList<NetworkRequest> nrs = new ArrayList<>();
13255             nrs.add(createNetworkRequest(NetworkRequest.Type.REQUEST, pref.capabilities));
13256             if (pref.allowFallback) {
13257                 nrs.add(createDefaultInternetRequestForTransport(
13258                         TYPE_NONE, NetworkRequest.Type.TRACK_DEFAULT));
13259             }
13260             if (VDBG) {
13261                 loge("pref.capabilities.getUids():" + UidRange.fromIntRanges(
13262                         pref.capabilities.getUids()));
13263             }
13264 
13265             setNetworkRequestUids(nrs, UidRange.fromIntRanges(pref.capabilities.getUids()));
13266             final NetworkRequestInfo nri = new NetworkRequestInfo(Process.myUid(), nrs,
13267                     PREFERENCE_ORDER_PROFILE);
13268             result.add(nri);
13269         }
13270         return result;
13271     }
13272 
13273     /**
13274      * Compare if the given UID range sets have the same UIDs.
13275      *
13276      */
13277     private boolean isRangeAlreadyInPreferenceList(
13278             @NonNull List<ProfileNetworkPreferenceInfo> preferenceList,
13279             @NonNull Set<UidRange> uidRangeSet) {
13280         if (uidRangeSet.size() == 0 || preferenceList.size() == 0) {
13281             return false;
13282         }
13283         for (ProfileNetworkPreferenceInfo pref : preferenceList) {
13284             if (UidRangeUtils.doesRangeSetOverlap(
13285                     UidRange.fromIntRanges(pref.capabilities.getUids()), uidRangeSet)) {
13286                 return true;
13287             }
13288         }
13289         return false;
13290     }
13291 
13292     private void handleSetProfileNetworkPreference(
13293             @NonNull final List<ProfileNetworkPreferenceInfo> preferenceList,
13294             @Nullable final IOnCompleteListener listener) {
13295         /*
13296          * handleSetProfileNetworkPreference is always called for single user.
13297          * preferenceList only contains preferences for different uids within the same user
13298          * (enforced by getUidListToBeAppliedForNetworkPreference).
13299          * Clear all the existing preferences for the user before applying new preferences.
13300          *
13301          */
13302         mProfileNetworkPreferences = mProfileNetworkPreferences.minus(preferenceList.get(0).user);
13303         for (final ProfileNetworkPreferenceInfo preference : preferenceList) {
13304             mProfileNetworkPreferences = mProfileNetworkPreferences.plus(preference);
13305         }
13306 
13307         removeDefaultNetworkRequestsForPreference(PREFERENCE_ORDER_PROFILE);
13308         addPerAppDefaultNetworkRequests(
13309                 createNrisFromProfileNetworkPreferences(mProfileNetworkPreferences));
13310         updateProfileAllowedNetworks();
13311 
13312         // Finally, rematch.
13313         rematchAllNetworksAndRequests();
13314 
13315         if (null != listener) {
13316             try {
13317                 listener.onComplete();
13318             } catch (RemoteException e) {
13319                 loge("Listener for setProfileNetworkPreference has died");
13320             }
13321         }
13322     }
13323 
13324     @VisibleForTesting
13325     @NonNull
13326     ArraySet<NetworkRequestInfo> createNrisForPreferenceOrder(@NonNull final Set<Integer> uids,
13327             @NonNull final List<NetworkRequest> requests,
13328             final int preferenceOrder) {
13329         final ArraySet<NetworkRequestInfo> nris = new ArraySet<>();
13330         if (uids.size() == 0) {
13331             // Should not create NetworkRequestInfo if no preferences. Without uid range in
13332             // NetworkRequestInfo, makeDefaultForApps() would treat it as a illegal NRI.
13333             return nris;
13334         }
13335 
13336         final Set<UidRange> ranges = new ArraySet<>();
13337         for (final int uid : uids) {
13338             ranges.add(new UidRange(uid, uid));
13339         }
13340         setNetworkRequestUids(requests, ranges);
13341         nris.add(new NetworkRequestInfo(Process.myUid(), requests, preferenceOrder));
13342         return nris;
13343     }
13344 
13345     ArraySet<NetworkRequestInfo> createNrisFromMobileDataPreferredUids(
13346             @NonNull final Set<Integer> uids) {
13347         final List<NetworkRequest> requests = new ArrayList<>();
13348         // The NRI should be comprised of two layers:
13349         // - The request for the mobile network preferred.
13350         // - The request for the default network, for fallback.
13351         requests.add(createDefaultInternetRequestForTransport(
13352                 TRANSPORT_CELLULAR, NetworkRequest.Type.REQUEST));
13353         requests.add(createDefaultInternetRequestForTransport(
13354                 TYPE_NONE, NetworkRequest.Type.TRACK_DEFAULT));
13355         return createNrisForPreferenceOrder(uids, requests, PREFERENCE_ORDER_MOBILE_DATA_PREFERERRED
13356         );
13357     }
13358 
13359     ArraySet<NetworkRequestInfo> createMultiLayerNrisFromSatelliteNetworkFallbackUids(
13360             @NonNull final Set<Integer> uids) {
13361         final List<NetworkRequest> requests = new ArrayList<>();
13362 
13363         // request: track default(unrestricted internet network)
13364         requests.add(createDefaultInternetRequestForTransport(
13365                 TYPE_NONE, NetworkRequest.Type.TRACK_DEFAULT));
13366 
13367         // request: Satellite internet, satellite network could be restricted or constrained
13368         final NetworkCapabilities cap = new NetworkCapabilities.Builder()
13369                 .addCapability(NET_CAPABILITY_INTERNET)
13370                 .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
13371                 .removeCapability(NET_CAPABILITY_NOT_RESTRICTED)
13372                 .removeCapability(NET_CAPABILITY_NOT_BANDWIDTH_CONSTRAINED)
13373                 .addTransportType(NetworkCapabilities.TRANSPORT_SATELLITE)
13374                 .build();
13375         requests.add(createNetworkRequest(NetworkRequest.Type.REQUEST, cap));
13376 
13377         return createNrisForPreferenceOrder(uids, requests, PREFERENCE_ORDER_SATELLITE_FALLBACK);
13378     }
13379 
13380     private void handleMobileDataPreferredUidsChanged() {
13381         mMobileDataPreferredUids = ConnectivitySettingsManager.getMobileDataPreferredUids(mContext);
13382         removeDefaultNetworkRequestsForPreference(PREFERENCE_ORDER_MOBILE_DATA_PREFERERRED);
13383         addPerAppDefaultNetworkRequests(
13384                 createNrisFromMobileDataPreferredUids(mMobileDataPreferredUids));
13385         // Finally, rematch.
13386         rematchAllNetworksAndRequests();
13387     }
13388 
13389     private void handleSetSatelliteNetworkPreference(
13390             @NonNull final Set<Integer> satelliteNetworkPreferredUids) {
13391         removeDefaultNetworkRequestsForPreference(PREFERENCE_ORDER_SATELLITE_FALLBACK);
13392         addPerAppDefaultNetworkRequests(
13393                 createMultiLayerNrisFromSatelliteNetworkFallbackUids(satelliteNetworkPreferredUids)
13394         );
13395         // Finally, rematch.
13396         rematchAllNetworksAndRequests();
13397     }
13398 
13399     private void handleIngressRateLimitChanged() {
13400         final long oldIngressRateLimit = mIngressRateLimit;
13401         mIngressRateLimit = ConnectivitySettingsManager.getIngressRateLimitInBytesPerSecond(
13402                 mContext);
13403         for (final NetworkAgentInfo networkAgent : mNetworkAgentInfos) {
13404             if (canNetworkBeRateLimited(networkAgent)) {
13405                 // If rate limit has previously been enabled, remove the old limit first.
13406                 if (oldIngressRateLimit >= 0) {
13407                     mDeps.disableIngressRateLimit(networkAgent.linkProperties.getInterfaceName());
13408                 }
13409                 if (mIngressRateLimit >= 0) {
13410                     mDeps.enableIngressRateLimit(networkAgent.linkProperties.getInterfaceName(),
13411                             mIngressRateLimit);
13412                 }
13413             }
13414         }
13415     }
13416 
13417     private boolean canNetworkBeRateLimited(@NonNull final NetworkAgentInfo networkAgent) {
13418         // Rate-limiting cannot run correctly before T because the BPF program is not loaded.
13419         if (!mDeps.isAtLeastT()) return false;
13420 
13421         final NetworkCapabilities agentCaps = networkAgent.networkCapabilities;
13422         // Only test networks (they cannot hold NET_CAPABILITY_INTERNET) and networks that provide
13423         // internet connectivity can be rate limited.
13424         if (!agentCaps.hasCapability(NET_CAPABILITY_INTERNET) && !agentCaps.hasTransport(
13425                 TRANSPORT_TEST)) {
13426             return false;
13427         }
13428 
13429         final String iface = networkAgent.linkProperties.getInterfaceName();
13430         if (iface == null) {
13431             // This may happen in tests, but if there is no interface then there is nothing that
13432             // can be rate limited.
13433             loge("canNetworkBeRateLimited: LinkProperties#getInterfaceName returns null");
13434             return false;
13435         }
13436         return true;
13437     }
13438 
13439     private void enforceAutomotiveDevice() {
13440         PermissionUtils.enforceSystemFeature(mContext, PackageManager.FEATURE_AUTOMOTIVE,
13441                 "setOemNetworkPreference() is only available on automotive devices.");
13442     }
13443 
13444     /**
13445      * Used by automotive devices to set the network preferences used to direct traffic at an
13446      * application level as per the given OemNetworkPreferences. An example use-case would be an
13447      * automotive OEM wanting to provide connectivity for applications critical to the usage of a
13448      * vehicle via a particular network.
13449      *
13450      * Calling this will overwrite the existing preference.
13451      *
13452      * @param preference {@link OemNetworkPreferences} The application network preference to be set.
13453      * @param listener {@link ConnectivityManager.OnCompleteListener} Listener used
13454      * to communicate completion of setOemNetworkPreference();
13455      */
13456     @Override
13457     public void setOemNetworkPreference(
13458             @NonNull final OemNetworkPreferences preference,
13459             @Nullable final IOnCompleteListener listener) {
13460 
13461         Objects.requireNonNull(preference, "OemNetworkPreferences must be non-null");
13462         // Only bypass the permission/device checks if this is a valid test request.
13463         if (isValidTestOemNetworkPreference(preference)) {
13464             enforceManageTestNetworksPermission();
13465         } else {
13466             enforceAutomotiveDevice();
13467             enforceOemNetworkPreferencesPermission();
13468             validateOemNetworkPreferences(preference);
13469         }
13470 
13471         mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_OEM_NETWORK_PREFERENCE,
13472                 new Pair<>(preference, listener)));
13473     }
13474 
13475     /**
13476      * Sets the specified UIDs to get/receive the VPN as the only default network.
13477      *
13478      * Calling this will overwrite the existing network preference for this session, and the
13479      * specified UIDs won't get any default network when no VPN is connected.
13480      *
13481      * @param session The VPN session which manages the passed UIDs.
13482      * @param ranges The uid ranges which will treat VPN as the only preferred network. Clear the
13483      *               setting for this session if the array is empty. Null is not allowed, the
13484      *               method will use {@link Objects#requireNonNull(Object)} to check this variable.
13485      * @hide
13486      */
13487     @Override
13488     public void setVpnNetworkPreference(String session, UidRange[] ranges) {
13489         Objects.requireNonNull(ranges);
13490         enforceNetworkStackOrSettingsPermission();
13491         final UidRange[] sortedRanges = UidRangeUtils.sortRangesByStartUid(ranges);
13492         if (UidRangeUtils.sortedRangesContainOverlap(sortedRanges)) {
13493             throw new IllegalArgumentException(
13494                     "setVpnNetworkPreference: Passed UID ranges overlap");
13495         }
13496 
13497         mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_VPN_NETWORK_PREFERENCE,
13498                 new VpnNetworkPreferenceInfo(session,
13499                         new ArraySet<UidRange>(Arrays.asList(ranges)))));
13500     }
13501 
13502     private void handleSetVpnNetworkPreference(VpnNetworkPreferenceInfo preferenceInfo) {
13503         Log.d(TAG, "handleSetVpnNetworkPreference: preferenceInfo = " + preferenceInfo);
13504 
13505         mVpnNetworkPreferences = mVpnNetworkPreferences.minus(preferenceInfo.getKey());
13506         mVpnNetworkPreferences = mVpnNetworkPreferences.plus(preferenceInfo);
13507 
13508         removeDefaultNetworkRequestsForPreference(PREFERENCE_ORDER_VPN);
13509         addPerAppDefaultNetworkRequests(createNrisForVpnNetworkPreference(mVpnNetworkPreferences));
13510         // Finally, rematch.
13511         rematchAllNetworksAndRequests();
13512     }
13513 
13514     private ArraySet<NetworkRequestInfo> createNrisForVpnNetworkPreference(
13515             @NonNull NetworkPreferenceList<String, VpnNetworkPreferenceInfo> preferenceList) {
13516         final ArraySet<NetworkRequestInfo> nris = new ArraySet<>();
13517         for (VpnNetworkPreferenceInfo preferenceInfo : preferenceList) {
13518             final List<NetworkRequest> requests = new ArrayList<>();
13519             // Request VPN only, so other networks won't be the fallback options when VPN is not
13520             // connected temporarily.
13521             requests.add(createVpnRequest());
13522             final Set<UidRange> uidRanges = new ArraySet(preferenceInfo.getUidRangesNoCopy());
13523             setNetworkRequestUids(requests, uidRanges);
13524             nris.add(new NetworkRequestInfo(Process.myUid(), requests, PREFERENCE_ORDER_VPN));
13525         }
13526         return nris;
13527     }
13528 
13529     /**
13530      * Check the validity of an OEM network preference to be used for testing purposes.
13531      * @param preference the preference to validate
13532      * @return true if this is a valid OEM network preference test request.
13533      */
13534     private boolean isValidTestOemNetworkPreference(
13535             @NonNull final OemNetworkPreferences preference) {
13536         // Allow for clearing of an existing OemNetworkPreference used for testing.
13537         // This isn't called on the handler thread so it is possible that mOemNetworkPreferences
13538         // changes after this check is complete. This is an unlikely scenario as calling of this API
13539         // is controlled by the OEM therefore the added complexity is not worth adding given those
13540         // circumstances. That said, it is an edge case to be aware of hence this comment.
13541         final boolean isValidTestClearPref = preference.getNetworkPreferences().size() == 0
13542                 && isTestOemNetworkPreference(mOemNetworkPreferences);
13543         return isTestOemNetworkPreference(preference) || isValidTestClearPref;
13544     }
13545 
13546     private boolean isTestOemNetworkPreference(@NonNull final OemNetworkPreferences preference) {
13547         final Map<String, Integer> prefMap = preference.getNetworkPreferences();
13548         return prefMap.size() == 1
13549                 && (prefMap.containsValue(OEM_NETWORK_PREFERENCE_TEST)
13550                 || prefMap.containsValue(OEM_NETWORK_PREFERENCE_TEST_ONLY));
13551     }
13552 
13553     private void validateOemNetworkPreferences(@NonNull OemNetworkPreferences preference) {
13554         for (@OemNetworkPreferences.OemNetworkPreference final int pref
13555                 : preference.getNetworkPreferences().values()) {
13556             if (pref <= 0 || OemNetworkPreferences.OEM_NETWORK_PREFERENCE_MAX < pref) {
13557                 throw new IllegalArgumentException(
13558                         OemNetworkPreferences.oemNetworkPreferenceToString(pref)
13559                                 + " is an invalid value.");
13560             }
13561         }
13562     }
13563 
13564     private void handleSetOemNetworkPreference(
13565             @NonNull final OemNetworkPreferences preference,
13566             @Nullable final IOnCompleteListener listener) {
13567         Objects.requireNonNull(preference, "OemNetworkPreferences must be non-null");
13568         if (DBG) {
13569             log("set OEM network preferences :" + preference.toString());
13570         }
13571 
13572         mOemNetworkPreferencesLogs.log("UPDATE INITIATED: " + preference);
13573         removeDefaultNetworkRequestsForPreference(PREFERENCE_ORDER_OEM);
13574         addPerAppDefaultNetworkRequests(new OemNetworkRequestFactory()
13575                 .createNrisFromOemNetworkPreferences(preference));
13576         mOemNetworkPreferences = preference;
13577 
13578         if (null != listener) {
13579             try {
13580                 listener.onComplete();
13581             } catch (RemoteException e) {
13582                 loge("Can't send onComplete in handleSetOemNetworkPreference", e);
13583             }
13584         }
13585     }
13586 
13587     private void removeDefaultNetworkRequestsForPreference(final int preferenceOrder) {
13588         // Skip the requests which are set by other network preference. Because the uid range rules
13589         // should stay in netd.
13590         final Set<NetworkRequestInfo> requests = new ArraySet<>(mDefaultNetworkRequests);
13591         requests.removeIf(request -> request.mPreferenceOrder != preferenceOrder);
13592         handleRemoveNetworkRequests(requests);
13593     }
13594 
13595     private void addPerAppDefaultNetworkRequests(@NonNull final Set<NetworkRequestInfo> nris) {
13596         ensureRunningOnConnectivityServiceThread();
13597         mDefaultNetworkRequests.addAll(nris);
13598         final ArraySet<NetworkRequestInfo> perAppCallbackRequestsToUpdate =
13599                 getPerAppCallbackRequestsToUpdate();
13600         final ArraySet<NetworkRequestInfo> nrisToRegister = new ArraySet<>(nris);
13601         // This method does not need to modify perUidCounter and mBlockedStatusTrackingUids because:
13602         // - |nris| only contains per-app network requests created by ConnectivityService which
13603         //    are internal requests and have no messenger and are not associated with any callbacks,
13604         //    and so do not need to be tracked in perUidCounter and mBlockedStatusTrackingUids.
13605         // - The requests in perAppCallbackRequestsToUpdate are removed, modified, and re-added,
13606         //   but the same number of requests is removed and re-added, and none of the requests
13607         //   changes mUid and mAsUid, so the perUidCounter and mBlockedStatusTrackingUids before
13608         //   and after this method remains the same. Re-adding the requests does not modify
13609         //   perUidCounter and mBlockedStatusTrackingUids (that is done when the app registers the
13610         //   request), so removing them must not modify perUidCounter and mBlockedStatusTrackingUids
13611         //   either.
13612         // TODO(b/341228979): Modify nris in place instead of removing them and re-adding them
13613         handleRemoveNetworkRequests(perAppCallbackRequestsToUpdate,
13614                 false /* untrackUids */);
13615         nrisToRegister.addAll(
13616                 createPerAppCallbackRequestsToRegister(perAppCallbackRequestsToUpdate));
13617         handleRegisterNetworkRequests(nrisToRegister);
13618     }
13619 
13620     /**
13621      * All current requests that are tracking the default network need to be assessed as to whether
13622      * or not the current set of per-application default requests will be changing their default
13623      * network. If so, those requests will need to be updated so that they will send callbacks for
13624      * default network changes at the appropriate time. Additionally, those requests tracking the
13625      * default that were previously updated by this flow will need to be reassessed.
13626      * @return the nris which will need to be updated.
13627      */
13628     private ArraySet<NetworkRequestInfo> getPerAppCallbackRequestsToUpdate() {
13629         final ArraySet<NetworkRequestInfo> defaultCallbackRequests = new ArraySet<>();
13630         // Get the distinct nris to check since for multilayer requests, it is possible to have the
13631         // same nri in the map's values for each of its NetworkRequest objects.
13632         final ArraySet<NetworkRequestInfo> nris = new ArraySet<>(mNetworkRequests.values());
13633         for (final NetworkRequestInfo nri : nris) {
13634             // Include this nri if it is currently being tracked.
13635             if (isPerAppTrackedNri(nri)) {
13636                 defaultCallbackRequests.add(nri);
13637                 continue;
13638             }
13639             // We only track callbacks for requests tracking the default.
13640             if (NetworkRequest.Type.TRACK_DEFAULT != nri.mRequests.get(0).type) {
13641                 continue;
13642             }
13643             // Include this nri if it will be tracked by the new per-app default requests.
13644             final boolean isNriGoingToBeTracked =
13645                     getDefaultRequestTrackingUid(nri.mAsUid) != mDefaultRequest;
13646             if (isNriGoingToBeTracked) {
13647                 defaultCallbackRequests.add(nri);
13648             }
13649         }
13650         return defaultCallbackRequests;
13651     }
13652 
13653     /**
13654      * Create nris for those network requests that are currently tracking the default network that
13655      * are being controlled by a per-application default.
13656      * @param perAppCallbackRequestsForUpdate the baseline network requests to be used as the
13657      * foundation when creating the nri. Important items include the calling uid's original
13658      * NetworkRequest to be used when mapping callbacks as well as the caller's uid and name. These
13659      * requests are assumed to have already been validated as needing to be updated.
13660      * @return the Set of nris to use when registering network requests.
13661      */
13662     private ArraySet<NetworkRequestInfo> createPerAppCallbackRequestsToRegister(
13663             @NonNull final ArraySet<NetworkRequestInfo> perAppCallbackRequestsForUpdate) {
13664         final ArraySet<NetworkRequestInfo> callbackRequestsToRegister = new ArraySet<>();
13665         for (final NetworkRequestInfo callbackRequest : perAppCallbackRequestsForUpdate) {
13666             final NetworkRequestInfo trackingNri =
13667                     getDefaultRequestTrackingUid(callbackRequest.mAsUid);
13668 
13669             // If this nri is not being tracked, then change it back to an untracked nri.
13670             if (trackingNri == mDefaultRequest) {
13671                 callbackRequestsToRegister.add(new NetworkRequestInfo(
13672                         callbackRequest,
13673                         Collections.singletonList(callbackRequest.getNetworkRequestForCallback())));
13674                 continue;
13675             }
13676 
13677             final NetworkRequest request = callbackRequest.mRequests.get(0);
13678             callbackRequestsToRegister.add(new NetworkRequestInfo(
13679                     callbackRequest,
13680                     copyNetworkRequestsForUid(
13681                             trackingNri.mRequests, callbackRequest.mAsUid,
13682                             callbackRequest.mUid, request.getRequestorPackageName())));
13683         }
13684         return callbackRequestsToRegister;
13685     }
13686 
13687     private static void setNetworkRequestUids(@NonNull final List<NetworkRequest> requests,
13688             @NonNull final Set<UidRange> uids) {
13689         for (final NetworkRequest req : requests) {
13690             req.networkCapabilities.setUids(UidRange.toIntRanges(uids));
13691         }
13692     }
13693 
13694     /**
13695      * Class used to generate {@link NetworkRequestInfo} based off of {@link OemNetworkPreferences}.
13696      */
13697     @VisibleForTesting
13698     final class OemNetworkRequestFactory {
13699         ArraySet<NetworkRequestInfo> createNrisFromOemNetworkPreferences(
13700                 @NonNull final OemNetworkPreferences preference) {
13701             final ArraySet<NetworkRequestInfo> nris = new ArraySet<>();
13702             final SparseArray<Set<Integer>> uids =
13703                     createUidsFromOemNetworkPreferences(preference);
13704             for (int i = 0; i < uids.size(); i++) {
13705                 final int key = uids.keyAt(i);
13706                 final Set<Integer> value = uids.valueAt(i);
13707                 final NetworkRequestInfo nri = createNriFromOemNetworkPreferences(key, value);
13708                 // No need to add an nri without any requests.
13709                 if (0 == nri.mRequests.size()) {
13710                     continue;
13711                 }
13712                 nris.add(nri);
13713             }
13714 
13715             return nris;
13716         }
13717 
13718         private SparseArray<Set<Integer>> createUidsFromOemNetworkPreferences(
13719                 @NonNull final OemNetworkPreferences preference) {
13720             final SparseArray<Set<Integer>> prefToUids = new SparseArray<>();
13721             final PackageManager pm = mContext.getPackageManager();
13722             final List<UserHandle> users =
13723                     mContext.getSystemService(UserManager.class).getUserHandles(true);
13724             if (null == users || users.size() == 0) {
13725                 if (VDBG || DDBG) {
13726                     log("No users currently available for setting the OEM network preference.");
13727                 }
13728                 return prefToUids;
13729             }
13730             for (final Map.Entry<String, Integer> entry :
13731                     preference.getNetworkPreferences().entrySet()) {
13732                 @OemNetworkPreferences.OemNetworkPreference final int pref = entry.getValue();
13733                 // Add the rules for all users as this policy is device wide.
13734                 for (final UserHandle user : users) {
13735                     try {
13736                         final int uid = pm.getApplicationInfoAsUser(entry.getKey(), 0, user).uid;
13737                         if (!prefToUids.contains(pref)) {
13738                             prefToUids.put(pref, new ArraySet<>());
13739                         }
13740                         prefToUids.get(pref).add(uid);
13741                     } catch (PackageManager.NameNotFoundException e) {
13742                         // Although this may seem like an error scenario, it is ok that uninstalled
13743                         // packages are sent on a network preference as the system will watch for
13744                         // package installations associated with this network preference and update
13745                         // accordingly. This is done to minimize race conditions on app install.
13746                         continue;
13747                     }
13748                 }
13749             }
13750             return prefToUids;
13751         }
13752 
13753         private NetworkRequestInfo createNriFromOemNetworkPreferences(
13754                 @OemNetworkPreferences.OemNetworkPreference final int preference,
13755                 @NonNull final Set<Integer> uids) {
13756             final List<NetworkRequest> requests = new ArrayList<>();
13757             // Requests will ultimately be evaluated by order of insertion therefore it matters.
13758             switch (preference) {
13759                 case OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PAID:
13760                     requests.add(createUnmeteredNetworkRequest());
13761                     requests.add(createOemPaidNetworkRequest());
13762                     requests.add(createDefaultInternetRequestForTransport(
13763                             TYPE_NONE, NetworkRequest.Type.TRACK_DEFAULT));
13764                     break;
13765                 case OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK:
13766                     requests.add(createUnmeteredNetworkRequest());
13767                     requests.add(createOemPaidNetworkRequest());
13768                     break;
13769                 case OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY:
13770                     requests.add(createOemPaidNetworkRequest());
13771                     break;
13772                 case OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY:
13773                     requests.add(createOemPrivateNetworkRequest());
13774                     break;
13775                 case OEM_NETWORK_PREFERENCE_TEST:
13776                     requests.add(createUnmeteredNetworkRequest());
13777                     requests.add(createTestNetworkRequest());
13778                     requests.add(createDefaultRequest());
13779                     break;
13780                 case OEM_NETWORK_PREFERENCE_TEST_ONLY:
13781                     requests.add(createTestNetworkRequest());
13782                     break;
13783                 default:
13784                     // This should never happen.
13785                     throw new IllegalArgumentException("createNriFromOemNetworkPreferences()"
13786                             + " called with invalid preference of " + preference);
13787             }
13788 
13789             final ArraySet<UidRange> ranges = new ArraySet<>();
13790             for (final int uid : uids) {
13791                 ranges.add(new UidRange(uid, uid));
13792             }
13793             setNetworkRequestUids(requests, ranges);
13794             return new NetworkRequestInfo(Process.myUid(), requests, PREFERENCE_ORDER_OEM);
13795         }
13796 
13797         private NetworkRequest createUnmeteredNetworkRequest() {
13798             final NetworkCapabilities netcap = createDefaultPerAppNetCap()
13799                     .addCapability(NET_CAPABILITY_NOT_METERED)
13800                     .addCapability(NET_CAPABILITY_VALIDATED);
13801             return createNetworkRequest(NetworkRequest.Type.LISTEN, netcap);
13802         }
13803 
13804         private NetworkRequest createOemPaidNetworkRequest() {
13805             // NET_CAPABILITY_OEM_PAID is a restricted capability.
13806             final NetworkCapabilities netcap = createDefaultPerAppNetCap()
13807                     .addCapability(NET_CAPABILITY_OEM_PAID)
13808                     .removeCapability(NET_CAPABILITY_NOT_RESTRICTED);
13809             return createNetworkRequest(NetworkRequest.Type.REQUEST, netcap);
13810         }
13811 
13812         private NetworkRequest createOemPrivateNetworkRequest() {
13813             // NET_CAPABILITY_OEM_PRIVATE is a restricted capability.
13814             final NetworkCapabilities netcap = createDefaultPerAppNetCap()
13815                     .addCapability(NET_CAPABILITY_OEM_PRIVATE)
13816                     .removeCapability(NET_CAPABILITY_NOT_RESTRICTED);
13817             return createNetworkRequest(NetworkRequest.Type.REQUEST, netcap);
13818         }
13819 
13820         private NetworkCapabilities createDefaultPerAppNetCap() {
13821             final NetworkCapabilities netcap = new NetworkCapabilities();
13822             netcap.addCapability(NET_CAPABILITY_INTERNET);
13823             netcap.setRequestorUidAndPackageName(Process.myUid(), mContext.getPackageName());
13824             return netcap;
13825         }
13826 
13827         private NetworkRequest createTestNetworkRequest() {
13828             final NetworkCapabilities netcap = new NetworkCapabilities();
13829             netcap.clearAll();
13830             netcap.addTransportType(TRANSPORT_TEST);
13831             return createNetworkRequest(NetworkRequest.Type.REQUEST, netcap);
13832         }
13833     }
13834 
13835     @RequiresApi(Build.VERSION_CODES.TIRAMISU)
13836     @Override
13837     public void setDataSaverEnabled(final boolean enable) {
13838         enforceNetworkStackOrSettingsPermission();
13839         try {
13840             final boolean ret = mNetd.bandwidthEnableDataSaver(enable);
13841             if (!ret) {
13842                 throw new IllegalStateException("Error when changing iptables: " + enable);
13843             }
13844         } catch (RemoteException e) {
13845             // Lack of permission or binder errors.
13846             throw new IllegalStateException(e);
13847         }
13848 
13849         synchronized (mBlockedStatusTrackingUids) {
13850             try {
13851                 mBpfNetMaps.setDataSaverEnabled(enable);
13852             } catch (ServiceSpecificException | UnsupportedOperationException e) {
13853                 Log.e(TAG, "Failed to set data saver " + enable + " : " + e);
13854                 return;
13855             }
13856 
13857             if (shouldTrackUidsForBlockedStatusCallbacks()) {
13858                 updateTrackingUidsBlockedReasons();
13859             }
13860         }
13861     }
13862 
13863     private int setPackageFirewallRule(final int chain, final String packageName, final int rule)
13864             throws PackageManager.NameNotFoundException {
13865         final PackageManager pm = mContext.getPackageManager();
13866         final int appId = UserHandle.getAppId(pm.getPackageUid(packageName, 0 /* flags */));
13867         if (appId < Process.FIRST_APPLICATION_UID) {
13868             throw new RuntimeException("Can't set package firewall rule for system app "
13869                     + packageName + " with appId " + appId);
13870         }
13871         for (final UserHandle uh : mUserManager.getUserHandles(false /* excludeDying */)) {
13872             final int uid = uh.getUid(appId);
13873             setUidFirewallRule(chain, uid, rule);
13874         }
13875         return appId;
13876     }
13877 
13878     @Override
13879     public void setUidFirewallRule(final int chain, final int uid, final int rule) {
13880         enforceNetworkStackOrSettingsPermission();
13881 
13882         if (chain == FIREWALL_CHAIN_BACKGROUND && !mBackgroundFirewallChainEnabled) {
13883             Log.i(TAG, "Ignoring operation setUidFirewallRule on the background chain because the"
13884                     + " feature is disabled.");
13885             return;
13886         }
13887 
13888         // There are only two type of firewall rule: FIREWALL_RULE_ALLOW or FIREWALL_RULE_DENY
13889         int firewallRule = getFirewallRuleType(chain, rule);
13890 
13891         if (firewallRule != FIREWALL_RULE_ALLOW && firewallRule != FIREWALL_RULE_DENY) {
13892             throw new IllegalArgumentException("setUidFirewallRule with invalid rule: " + rule);
13893         }
13894 
13895         synchronized (mBlockedStatusTrackingUids) {
13896             try {
13897                 mBpfNetMaps.setUidRule(chain, uid, firewallRule);
13898             } catch (ServiceSpecificException e) {
13899                 throw new IllegalStateException(e);
13900             }
13901             if (shouldTrackUidsForBlockedStatusCallbacks()
13902                     && mBlockedStatusTrackingUids.get(uid, 0) != 0) {
13903                 mHandler.sendMessage(mHandler.obtainMessage(EVENT_BLOCKED_REASONS_CHANGED,
13904                         List.of(new Pair<>(uid, mBpfNetMaps.getUidNetworkingBlockedReasons(uid)))));
13905             }
13906             if (shouldTrackFirewallDestroySocketReasons()) {
13907                 maybePostFirewallDestroySocketReasons(chain, Set.of(uid));
13908             }
13909         }
13910     }
13911 
13912     private int getPackageFirewallRule(final int chain, final String packageName)
13913             throws PackageManager.NameNotFoundException {
13914         final PackageManager pm = mContext.getPackageManager();
13915         final int appId = UserHandle.getAppId(pm.getPackageUid(packageName, 0 /* flags */));
13916         return getUidFirewallRule(chain, appId);
13917     }
13918 
13919     @Override
13920     public int getUidFirewallRule(final int chain, final int uid) {
13921         enforceNetworkStackOrSettingsPermission();
13922         return mBpfNetMaps.getUidRule(chain, uid);
13923     }
13924 
13925     private int getFirewallRuleType(int chain, int rule) {
13926         final int defaultRule;
13927         switch (chain) {
13928             case ConnectivityManager.FIREWALL_CHAIN_STANDBY:
13929             case ConnectivityManager.FIREWALL_CHAIN_OEM_DENY_1:
13930             case ConnectivityManager.FIREWALL_CHAIN_OEM_DENY_2:
13931             case ConnectivityManager.FIREWALL_CHAIN_OEM_DENY_3:
13932             case ConnectivityManager.FIREWALL_CHAIN_METERED_DENY_USER:
13933             case ConnectivityManager.FIREWALL_CHAIN_METERED_DENY_ADMIN:
13934                 defaultRule = FIREWALL_RULE_ALLOW;
13935                 break;
13936             case ConnectivityManager.FIREWALL_CHAIN_DOZABLE:
13937             case ConnectivityManager.FIREWALL_CHAIN_POWERSAVE:
13938             case ConnectivityManager.FIREWALL_CHAIN_RESTRICTED:
13939             case ConnectivityManager.FIREWALL_CHAIN_LOW_POWER_STANDBY:
13940             case ConnectivityManager.FIREWALL_CHAIN_BACKGROUND:
13941             case ConnectivityManager.FIREWALL_CHAIN_METERED_ALLOW:
13942                 defaultRule = FIREWALL_RULE_DENY;
13943                 break;
13944             default:
13945                 throw new IllegalArgumentException("Unsupported firewall chain: " + chain);
13946         }
13947         if (rule == FIREWALL_RULE_DEFAULT) rule = defaultRule;
13948 
13949         return rule;
13950     }
13951 
13952     @RequiresApi(Build.VERSION_CODES.TIRAMISU)
13953     private Set<Integer> getUidsOnFirewallChain(final int chain) throws ErrnoException {
13954         if (BpfNetMapsUtils.isFirewallAllowList(chain)) {
13955             return mBpfNetMaps.getUidsWithAllowRuleOnAllowListChain(chain);
13956         } else {
13957             return mBpfNetMaps.getUidsWithDenyRuleOnDenyListChain(chain);
13958         }
13959     }
13960 
13961     @RequiresApi(Build.VERSION_CODES.TIRAMISU)
13962     private void closeSocketsForFirewallChainLocked(final int chain)
13963             throws ErrnoException, SocketException, InterruptedIOException {
13964         final Set<Integer> uidsOnChain = getUidsOnFirewallChain(chain);
13965         if (BpfNetMapsUtils.isFirewallAllowList(chain)) {
13966             // Allowlist means the firewall denies all by default, uids must be explicitly allowed
13967             // So, close all non-system socket owned by uids that are not explicitly allowed
13968             Set<Range<Integer>> ranges = new ArraySet<>();
13969             ranges.add(new Range<>(Process.FIRST_APPLICATION_UID, Integer.MAX_VALUE));
13970             mDeps.destroyLiveTcpSockets(ranges, uidsOnChain /* exemptUids */);
13971         } else {
13972             // Denylist means the firewall allows all by default, uids must be explicitly denied
13973             // So, close socket owned by uids that are explicitly denied
13974             mDeps.destroyLiveTcpSocketsByOwnerUids(uidsOnChain /* ownerUids */);
13975         }
13976     }
13977 
13978     private void maybePostClearFirewallDestroySocketReasons(int chain) {
13979         if (chain != FIREWALL_CHAIN_BACKGROUND) {
13980             // TODO (b/300681644): Support other firewall chains
13981             return;
13982         }
13983         mHandler.sendMessage(mHandler.obtainMessage(EVENT_CLEAR_FIREWALL_DESTROY_SOCKET_REASONS,
13984                 DESTROY_SOCKET_REASON_FIREWALL_BACKGROUND, 0 /* arg2 */));
13985     }
13986 
13987     @Override
13988     public void setFirewallChainEnabled(final int chain, final boolean enable) {
13989         enforceNetworkStackOrSettingsPermission();
13990 
13991         if (chain == FIREWALL_CHAIN_BACKGROUND && !mBackgroundFirewallChainEnabled) {
13992             Log.i(TAG, "Ignoring operation setFirewallChainEnabled on the background chain because"
13993                     + " the feature is disabled.");
13994             return;
13995         }
13996         if (METERED_ALLOW_CHAINS.contains(chain) || METERED_DENY_CHAINS.contains(chain)) {
13997             // Metered chains are used from a separate bpf program that is triggered by iptables
13998             // and can not be controlled by setFirewallChainEnabled.
13999             throw new UnsupportedOperationException(
14000                     "Chain (" + chain + ") can not be controlled by setFirewallChainEnabled");
14001         }
14002 
14003         synchronized (mBlockedStatusTrackingUids) {
14004             try {
14005                 mBpfNetMaps.setChildChain(chain, enable);
14006             } catch (ServiceSpecificException e) {
14007                 throw new IllegalStateException(e);
14008             }
14009             if (shouldTrackUidsForBlockedStatusCallbacks()) {
14010                 updateTrackingUidsBlockedReasons();
14011             }
14012             if (shouldTrackFirewallDestroySocketReasons() && !enable) {
14013                 // Clear destroy socket reasons so that CS does not destroy sockets of apps that
14014                 // have network access.
14015                 maybePostClearFirewallDestroySocketReasons(chain);
14016             }
14017         }
14018 
14019         if (mDeps.isAtLeastU() && enable) {
14020             try {
14021                 closeSocketsForFirewallChainLocked(chain);
14022             } catch (ErrnoException | SocketException | InterruptedIOException e) {
14023                 Log.e(TAG, "Failed to close sockets after enabling chain (" + chain + "): " + e);
14024             }
14025         }
14026     }
14027 
14028     @RequiresApi(Build.VERSION_CODES.TIRAMISU)
14029     @GuardedBy("mBlockedStatusTrackingUids")
14030     private void updateTrackingUidsBlockedReasons() {
14031         if (mBlockedStatusTrackingUids.size() == 0) {
14032             return;
14033         }
14034         final ArrayList<Pair<Integer, Integer>> uidBlockedReasonsList = new ArrayList<>();
14035         for (int i = 0; i < mBlockedStatusTrackingUids.size(); i++) {
14036             final int uid = mBlockedStatusTrackingUids.keyAt(i);
14037             uidBlockedReasonsList.add(
14038                     new Pair<>(uid, mBpfNetMaps.getUidNetworkingBlockedReasons(uid)));
14039         }
14040         mHandler.sendMessage(mHandler.obtainMessage(EVENT_BLOCKED_REASONS_CHANGED,
14041                 uidBlockedReasonsList));
14042     }
14043 
14044     private int getFirewallDestroySocketReasons(final int blockedReasons) {
14045         int destroySocketReasons = DESTROY_SOCKET_REASON_NONE;
14046         if ((blockedReasons & BLOCKED_REASON_APP_BACKGROUND) != BLOCKED_REASON_NONE) {
14047             destroySocketReasons |= DESTROY_SOCKET_REASON_FIREWALL_BACKGROUND;
14048         }
14049         return destroySocketReasons;
14050     }
14051 
14052     @RequiresApi(Build.VERSION_CODES.TIRAMISU)
14053     @GuardedBy("mBlockedStatusTrackingUids")
14054     private void maybePostFirewallDestroySocketReasons(int chain, Set<Integer> uids) {
14055         if (chain != FIREWALL_CHAIN_BACKGROUND) {
14056             // TODO (b/300681644): Support other firewall chains
14057             return;
14058         }
14059         final ArrayList<Pair<Integer, Integer>> reasonsList = new ArrayList<>();
14060         for (int uid: uids) {
14061             final int blockedReasons = mBpfNetMaps.getUidNetworkingBlockedReasons(uid);
14062             final int destroySocketReaons = getFirewallDestroySocketReasons(blockedReasons);
14063             reasonsList.add(new Pair<>(uid, destroySocketReaons));
14064         }
14065         mHandler.sendMessage(mHandler.obtainMessage(EVENT_UPDATE_FIREWALL_DESTROY_SOCKET_REASONS,
14066                 reasonsList));
14067     }
14068 
14069     @Override
14070     public boolean getFirewallChainEnabled(final int chain) {
14071         enforceNetworkStackOrSettingsPermission();
14072 
14073         if (METERED_ALLOW_CHAINS.contains(chain) || METERED_DENY_CHAINS.contains(chain)) {
14074             // Metered chains are used from a separate bpf program that is triggered by iptables
14075             // and can not be controlled by setFirewallChainEnabled.
14076             throw new UnsupportedOperationException(
14077                     "getFirewallChainEnabled can not return status of chain (" + chain + ")");
14078         }
14079 
14080         return mBpfNetMaps.isChainEnabled(chain);
14081     }
14082 
14083     @Override
14084     public void replaceFirewallChain(final int chain, final int[] uids) {
14085         enforceNetworkStackOrSettingsPermission();
14086 
14087         if (chain == FIREWALL_CHAIN_BACKGROUND && !mBackgroundFirewallChainEnabled) {
14088             Log.i(TAG, "Ignoring operation replaceFirewallChain on the background chain because"
14089                     + " the feature is disabled.");
14090             return;
14091         }
14092 
14093         synchronized (mBlockedStatusTrackingUids) {
14094             // replaceFirewallChain removes uids that are currently on the chain and put |uids| on
14095             // the chain.
14096             // So this method could change blocked reasons of uids that are currently on chain +
14097             // |uids|.
14098             final Set<Integer> affectedUids = new ArraySet<>();
14099             if (shouldTrackFirewallDestroySocketReasons()) {
14100                 try {
14101                     affectedUids.addAll(getUidsOnFirewallChain(chain));
14102                 } catch (ErrnoException e) {
14103                     Log.e(TAG, "Failed to get uids on chain(" + chain + "): " + e);
14104                 }
14105                 for (final int uid: uids) {
14106                     affectedUids.add(uid);
14107                 }
14108             }
14109 
14110             mBpfNetMaps.replaceUidChain(chain, uids);
14111             if (shouldTrackUidsForBlockedStatusCallbacks()) {
14112                 updateTrackingUidsBlockedReasons();
14113             }
14114             if (shouldTrackFirewallDestroySocketReasons()) {
14115                 maybePostFirewallDestroySocketReasons(chain, affectedUids);
14116             }
14117         }
14118     }
14119 
14120     @Override
14121     public IBinder getCompanionDeviceManagerProxyService() {
14122         enforceNetworkStackPermission(mContext);
14123         return mCdmps;
14124     }
14125 
14126     @Override
14127     public IBinder getRoutingCoordinatorService() {
14128         enforceNetworkStackPermission(mContext);
14129         return mRoutingCoordinatorService;
14130     }
14131 
14132     @Override
14133     public long getEnabledConnectivityManagerFeatures() {
14134         long features = 0;
14135         // The bitmask must be built based on final properties initialized in the constructor, to
14136         // ensure that it does not change over time and is always consistent between
14137         // ConnectivityManager and ConnectivityService.
14138         if (mUseDeclaredMethodsForCallbacksEnabled) {
14139             features |= ConnectivityManager.FEATURE_USE_DECLARED_METHODS_FOR_CALLBACKS;
14140         }
14141         return features;
14142     }
14143 }
14144