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.content.pm.PackageManager.PERMISSION_GRANTED;
21 import static android.net.ConnectivityDiagnosticsManager.ConnectivityReport.KEY_NETWORK_PROBES_ATTEMPTED_BITMASK;
22 import static android.net.ConnectivityDiagnosticsManager.ConnectivityReport.KEY_NETWORK_PROBES_SUCCEEDED_BITMASK;
23 import static android.net.ConnectivityDiagnosticsManager.ConnectivityReport.KEY_NETWORK_VALIDATION_RESULT;
24 import static android.net.ConnectivityDiagnosticsManager.DataStallReport.DETECTION_METHOD_DNS_EVENTS;
25 import static android.net.ConnectivityDiagnosticsManager.DataStallReport.DETECTION_METHOD_TCP_METRICS;
26 import static android.net.ConnectivityDiagnosticsManager.DataStallReport.KEY_DNS_CONSECUTIVE_TIMEOUTS;
27 import static android.net.ConnectivityDiagnosticsManager.DataStallReport.KEY_TCP_METRICS_COLLECTION_PERIOD_MILLIS;
28 import static android.net.ConnectivityDiagnosticsManager.DataStallReport.KEY_TCP_PACKET_FAIL_RATE;
29 import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
30 import static android.net.ConnectivityManager.NETID_UNSET;
31 import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OPPORTUNISTIC;
32 import static android.net.ConnectivityManager.TYPE_ETHERNET;
33 import static android.net.ConnectivityManager.TYPE_NONE;
34 import static android.net.ConnectivityManager.TYPE_VPN;
35 import static android.net.ConnectivityManager.getNetworkTypeName;
36 import static android.net.ConnectivityManager.isNetworkTypeValid;
37 import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_PRIVDNS;
38 import static android.net.INetworkMonitor.NETWORK_VALIDATION_RESULT_PARTIAL;
39 import static android.net.INetworkMonitor.NETWORK_VALIDATION_RESULT_VALID;
40 import static android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL;
41 import static android.net.NetworkCapabilities.NET_CAPABILITY_FOREGROUND;
42 import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
43 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
44 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
45 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING;
46 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED;
47 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN;
48 import static android.net.NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVITY;
49 import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
50 import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
51 import static android.net.NetworkCapabilities.TRANSPORT_TEST;
52 import static android.net.NetworkCapabilities.TRANSPORT_VPN;
53 import static android.net.NetworkPolicyManager.RULE_NONE;
54 import static android.net.NetworkPolicyManager.uidRulesToString;
55 import static android.net.shared.NetworkMonitorUtils.isPrivateDnsValidationRequired;
56 import static android.os.Process.INVALID_UID;
57 import static android.system.OsConstants.IPPROTO_TCP;
58 import static android.system.OsConstants.IPPROTO_UDP;
59 
60 import static java.util.Map.Entry;
61 
62 import android.Manifest;
63 import android.annotation.NonNull;
64 import android.annotation.Nullable;
65 import android.app.AppOpsManager;
66 import android.app.BroadcastOptions;
67 import android.app.NotificationManager;
68 import android.app.PendingIntent;
69 import android.content.BroadcastReceiver;
70 import android.content.ComponentName;
71 import android.content.ContentResolver;
72 import android.content.Context;
73 import android.content.Intent;
74 import android.content.IntentFilter;
75 import android.content.pm.PackageManager;
76 import android.content.res.Configuration;
77 import android.database.ContentObserver;
78 import android.net.CaptivePortal;
79 import android.net.CaptivePortalData;
80 import android.net.ConnectionInfo;
81 import android.net.ConnectivityDiagnosticsManager.ConnectivityReport;
82 import android.net.ConnectivityDiagnosticsManager.DataStallReport;
83 import android.net.ConnectivityManager;
84 import android.net.DataStallReportParcelable;
85 import android.net.ICaptivePortal;
86 import android.net.IConnectivityDiagnosticsCallback;
87 import android.net.IConnectivityManager;
88 import android.net.IDnsResolver;
89 import android.net.IIpConnectivityMetrics;
90 import android.net.INetd;
91 import android.net.INetdEventCallback;
92 import android.net.INetworkManagementEventObserver;
93 import android.net.INetworkMonitor;
94 import android.net.INetworkMonitorCallbacks;
95 import android.net.INetworkPolicyListener;
96 import android.net.INetworkPolicyManager;
97 import android.net.INetworkStatsService;
98 import android.net.ISocketKeepaliveCallback;
99 import android.net.InetAddresses;
100 import android.net.IpMemoryStore;
101 import android.net.IpPrefix;
102 import android.net.LinkProperties;
103 import android.net.MatchAllNetworkSpecifier;
104 import android.net.NattSocketKeepalive;
105 import android.net.Network;
106 import android.net.NetworkAgent;
107 import android.net.NetworkAgentConfig;
108 import android.net.NetworkCapabilities;
109 import android.net.NetworkConfig;
110 import android.net.NetworkInfo;
111 import android.net.NetworkInfo.DetailedState;
112 import android.net.NetworkMonitorManager;
113 import android.net.NetworkPolicyManager;
114 import android.net.NetworkProvider;
115 import android.net.NetworkQuotaInfo;
116 import android.net.NetworkRequest;
117 import android.net.NetworkSpecifier;
118 import android.net.NetworkStack;
119 import android.net.NetworkStackClient;
120 import android.net.NetworkState;
121 import android.net.NetworkTestResultParcelable;
122 import android.net.NetworkUtils;
123 import android.net.NetworkWatchlistManager;
124 import android.net.PrivateDnsConfigParcel;
125 import android.net.ProxyInfo;
126 import android.net.RouteInfo;
127 import android.net.RouteInfoParcel;
128 import android.net.SocketKeepalive;
129 import android.net.TetheringManager;
130 import android.net.UidRange;
131 import android.net.Uri;
132 import android.net.VpnManager;
133 import android.net.VpnService;
134 import android.net.metrics.IpConnectivityLog;
135 import android.net.metrics.NetworkEvent;
136 import android.net.netlink.InetDiagMessage;
137 import android.net.shared.PrivateDnsConfig;
138 import android.net.util.LinkPropertiesUtils.CompareOrUpdateResult;
139 import android.net.util.LinkPropertiesUtils.CompareResult;
140 import android.net.util.MultinetworkPolicyTracker;
141 import android.net.util.NetdService;
142 import android.os.Binder;
143 import android.os.Build;
144 import android.os.Bundle;
145 import android.os.Handler;
146 import android.os.HandlerThread;
147 import android.os.IBinder;
148 import android.os.INetworkManagementService;
149 import android.os.Looper;
150 import android.os.Message;
151 import android.os.Messenger;
152 import android.os.ParcelFileDescriptor;
153 import android.os.Parcelable;
154 import android.os.PersistableBundle;
155 import android.os.PowerManager;
156 import android.os.Process;
157 import android.os.RemoteException;
158 import android.os.ResultReceiver;
159 import android.os.ServiceManager;
160 import android.os.ServiceSpecificException;
161 import android.os.ShellCallback;
162 import android.os.ShellCommand;
163 import android.os.SystemClock;
164 import android.os.SystemProperties;
165 import android.os.UserHandle;
166 import android.os.UserManager;
167 import android.provider.Settings;
168 import android.security.Credentials;
169 import android.security.KeyStore;
170 import android.telephony.TelephonyManager;
171 import android.text.TextUtils;
172 import android.util.ArraySet;
173 import android.util.LocalLog;
174 import android.util.Log;
175 import android.util.Pair;
176 import android.util.Slog;
177 import android.util.SparseArray;
178 import android.util.SparseIntArray;
179 import android.util.Xml;
180 
181 import com.android.internal.R;
182 import com.android.internal.annotations.GuardedBy;
183 import com.android.internal.annotations.VisibleForTesting;
184 import com.android.internal.app.IBatteryStats;
185 import com.android.internal.logging.MetricsLogger;
186 import com.android.internal.net.LegacyVpnInfo;
187 import com.android.internal.net.VpnConfig;
188 import com.android.internal.net.VpnInfo;
189 import com.android.internal.net.VpnProfile;
190 import com.android.internal.util.ArrayUtils;
191 import com.android.internal.util.AsyncChannel;
192 import com.android.internal.util.DumpUtils;
193 import com.android.internal.util.IndentingPrintWriter;
194 import com.android.internal.util.LocationPermissionChecker;
195 import com.android.internal.util.MessageUtils;
196 import com.android.internal.util.XmlUtils;
197 import com.android.server.am.BatteryStatsService;
198 import com.android.server.connectivity.AutodestructReference;
199 import com.android.server.connectivity.DataConnectionStats;
200 import com.android.server.connectivity.DnsManager;
201 import com.android.server.connectivity.DnsManager.PrivateDnsValidationUpdate;
202 import com.android.server.connectivity.IpConnectivityMetrics;
203 import com.android.server.connectivity.KeepaliveTracker;
204 import com.android.server.connectivity.LingerMonitor;
205 import com.android.server.connectivity.MockableSystemProperties;
206 import com.android.server.connectivity.MultipathPolicyTracker;
207 import com.android.server.connectivity.NetworkAgentInfo;
208 import com.android.server.connectivity.NetworkDiagnostics;
209 import com.android.server.connectivity.NetworkNotificationManager;
210 import com.android.server.connectivity.NetworkNotificationManager.NotificationType;
211 import com.android.server.connectivity.NetworkRanker;
212 import com.android.server.connectivity.PermissionMonitor;
213 import com.android.server.connectivity.ProxyTracker;
214 import com.android.server.connectivity.Vpn;
215 import com.android.server.net.BaseNetdEventCallback;
216 import com.android.server.net.BaseNetworkObserver;
217 import com.android.server.net.LockdownVpnTracker;
218 import com.android.server.net.NetworkPolicyManagerInternal;
219 import com.android.server.utils.PriorityDump;
220 
221 import com.google.android.collect.Lists;
222 
223 import org.xmlpull.v1.XmlPullParser;
224 import org.xmlpull.v1.XmlPullParserException;
225 
226 import java.io.File;
227 import java.io.FileDescriptor;
228 import java.io.FileNotFoundException;
229 import java.io.FileReader;
230 import java.io.IOException;
231 import java.io.PrintWriter;
232 import java.net.Inet4Address;
233 import java.net.InetAddress;
234 import java.net.UnknownHostException;
235 import java.util.ArrayList;
236 import java.util.Arrays;
237 import java.util.Collection;
238 import java.util.Collections;
239 import java.util.Comparator;
240 import java.util.ConcurrentModificationException;
241 import java.util.HashMap;
242 import java.util.HashSet;
243 import java.util.List;
244 import java.util.Map;
245 import java.util.Objects;
246 import java.util.Set;
247 import java.util.SortedSet;
248 import java.util.StringJoiner;
249 import java.util.TreeSet;
250 import java.util.concurrent.atomic.AtomicInteger;
251 
252 /**
253  * @hide
254  */
255 public class ConnectivityService extends IConnectivityManager.Stub
256         implements PendingIntent.OnFinished {
257     private static final String TAG = ConnectivityService.class.getSimpleName();
258 
259     private static final String DIAG_ARG = "--diag";
260     public static final String SHORT_ARG = "--short";
261     private static final String NETWORK_ARG = "networks";
262     private static final String REQUEST_ARG = "requests";
263 
264     private static final boolean DBG = true;
265     private static final boolean DDBG = Log.isLoggable(TAG, Log.DEBUG);
266     private static final boolean VDBG = Log.isLoggable(TAG, Log.VERBOSE);
267 
268     private static final boolean LOGD_BLOCKED_NETWORKINFO = true;
269 
270     /**
271      * Default URL to use for {@link #getCaptivePortalServerUrl()}. This should not be changed
272      * by OEMs for configuration purposes, as this value is overridden by
273      * Settings.Global.CAPTIVE_PORTAL_HTTP_URL.
274      * R.string.config_networkCaptivePortalServerUrl should be overridden instead for this purpose
275      * (preferably via runtime resource overlays).
276      */
277     private static final String DEFAULT_CAPTIVE_PORTAL_HTTP_URL =
278             "http://connectivitycheck.gstatic.com/generate_204";
279 
280     // TODO: create better separation between radio types and network types
281 
282     // how long to wait before switching back to a radio's default network
283     private static final int RESTORE_DEFAULT_NETWORK_DELAY = 1 * 60 * 1000;
284     // system property that can override the above value
285     private static final String NETWORK_RESTORE_DELAY_PROP_NAME =
286             "android.telephony.apn-restore";
287 
288     // How long to wait before putting up a "This network doesn't have an Internet connection,
289     // connect anyway?" dialog after the user selects a network that doesn't validate.
290     private static final int PROMPT_UNVALIDATED_DELAY_MS = 8 * 1000;
291 
292     // Default to 30s linger time-out. Modifiable only for testing.
293     private static final String LINGER_DELAY_PROPERTY = "persist.netmon.linger";
294     private static final int DEFAULT_LINGER_DELAY_MS = 30_000;
295     @VisibleForTesting
296     protected int mLingerDelayMs;  // Can't be final, or test subclass constructors can't change it.
297 
298     // How long to delay to removal of a pending intent based request.
299     // See Settings.Secure.CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS
300     private final int mReleasePendingIntentDelayMs;
301 
302     private MockableSystemProperties mSystemProperties;
303 
304     @VisibleForTesting
305     protected final PermissionMonitor mPermissionMonitor;
306 
307     private KeyStore mKeyStore;
308 
309     @VisibleForTesting
310     @GuardedBy("mVpns")
311     protected final SparseArray<Vpn> mVpns = new SparseArray<>();
312 
313     // TODO: investigate if mLockdownEnabled can be removed and replaced everywhere by
314     // a direct call to LockdownVpnTracker.isEnabled().
315     @GuardedBy("mVpns")
316     private boolean mLockdownEnabled;
317     @GuardedBy("mVpns")
318     private LockdownVpnTracker mLockdownTracker;
319 
320     /**
321      * Stale copy of uid rules provided by NPMS. As long as they are accessed only in internal
322      * handler thread, they don't need a lock.
323      */
324     private SparseIntArray mUidRules = new SparseIntArray();
325     /** Flag indicating if background data is restricted. */
326     private boolean mRestrictBackground;
327 
328     private final Context mContext;
329     private final Dependencies mDeps;
330     // 0 is full bad, 100 is full good
331     private int mDefaultInetConditionPublished = 0;
332 
333     private INetworkManagementService mNMS;
334     @VisibleForTesting
335     protected IDnsResolver mDnsResolver;
336     @VisibleForTesting
337     protected INetd mNetd;
338     private INetworkStatsService mStatsService;
339     private INetworkPolicyManager mPolicyManager;
340     private NetworkPolicyManagerInternal mPolicyManagerInternal;
341 
342     /**
343      * TestNetworkService (lazily) created upon first usage. Locked to prevent creation of multiple
344      * instances.
345      */
346     @GuardedBy("mTNSLock")
347     private TestNetworkService mTNS;
348 
349     private final Object mTNSLock = new Object();
350 
351     private String mCurrentTcpBufferSizes;
352 
353     private static final SparseArray<String> sMagicDecoderRing = MessageUtils.findMessageNames(
354             new Class[] { AsyncChannel.class, ConnectivityService.class, NetworkAgent.class,
355                     NetworkAgentInfo.class });
356 
357     private enum ReapUnvalidatedNetworks {
358         // Tear down networks that have no chance (e.g. even if validated) of becoming
359         // the highest scoring network satisfying a NetworkRequest.  This should be passed when
360         // all networks have been rematched against all NetworkRequests.
361         REAP,
362         // Don't reap networks.  This should be passed when some networks have not yet been
363         // rematched against all NetworkRequests.
364         DONT_REAP
365     }
366 
367     private enum UnneededFor {
368         LINGER,    // Determine whether this network is unneeded and should be lingered.
369         TEARDOWN,  // Determine whether this network is unneeded and should be torn down.
370     }
371 
372     /**
373      * used internally to clear a wakelock when transitioning
374      * from one net to another.  Clear happens when we get a new
375      * network - EVENT_EXPIRE_NET_TRANSITION_WAKELOCK happens
376      * after a timeout if no network is found (typically 1 min).
377      */
378     private static final int EVENT_CLEAR_NET_TRANSITION_WAKELOCK = 8;
379 
380     /**
381      * used internally to reload global proxy settings
382      */
383     private static final int EVENT_APPLY_GLOBAL_HTTP_PROXY = 9;
384 
385     /**
386      * PAC manager has received new port.
387      */
388     private static final int EVENT_PROXY_HAS_CHANGED = 16;
389 
390     /**
391      * used internally when registering NetworkProviders
392      * obj = NetworkProviderInfo
393      */
394     private static final int EVENT_REGISTER_NETWORK_PROVIDER = 17;
395 
396     /**
397      * used internally when registering NetworkAgents
398      * obj = Messenger
399      */
400     private static final int EVENT_REGISTER_NETWORK_AGENT = 18;
401 
402     /**
403      * used to add a network request
404      * includes a NetworkRequestInfo
405      */
406     private static final int EVENT_REGISTER_NETWORK_REQUEST = 19;
407 
408     /**
409      * indicates a timeout period is over - check if we had a network yet or not
410      * and if not, call the timeout callback (but leave the request live until they
411      * cancel it.
412      * includes a NetworkRequestInfo
413      */
414     private static final int EVENT_TIMEOUT_NETWORK_REQUEST = 20;
415 
416     /**
417      * used to add a network listener - no request
418      * includes a NetworkRequestInfo
419      */
420     private static final int EVENT_REGISTER_NETWORK_LISTENER = 21;
421 
422     /**
423      * used to remove a network request, either a listener or a real request
424      * arg1 = UID of caller
425      * obj  = NetworkRequest
426      */
427     private static final int EVENT_RELEASE_NETWORK_REQUEST = 22;
428 
429     /**
430      * used internally when registering NetworkProviders
431      * obj = Messenger
432      */
433     private static final int EVENT_UNREGISTER_NETWORK_PROVIDER = 23;
434 
435     /**
436      * used internally to expire a wakelock when transitioning
437      * from one net to another.  Expire happens when we fail to find
438      * a new network (typically after 1 minute) -
439      * EVENT_CLEAR_NET_TRANSITION_WAKELOCK happens if we had found
440      * a replacement network.
441      */
442     private static final int EVENT_EXPIRE_NET_TRANSITION_WAKELOCK = 24;
443 
444     /**
445      * Used internally to indicate the system is ready.
446      */
447     private static final int EVENT_SYSTEM_READY = 25;
448 
449     /**
450      * used to add a network request with a pending intent
451      * obj = NetworkRequestInfo
452      */
453     private static final int EVENT_REGISTER_NETWORK_REQUEST_WITH_INTENT = 26;
454 
455     /**
456      * used to remove a pending intent and its associated network request.
457      * arg1 = UID of caller
458      * obj  = PendingIntent
459      */
460     private static final int EVENT_RELEASE_NETWORK_REQUEST_WITH_INTENT = 27;
461 
462     /**
463      * used to specify whether a network should be used even if unvalidated.
464      * arg1 = whether to accept the network if it's unvalidated (1 or 0)
465      * arg2 = whether to remember this choice in the future (1 or 0)
466      * obj  = network
467      */
468     private static final int EVENT_SET_ACCEPT_UNVALIDATED = 28;
469 
470     /**
471      * used to ask the user to confirm a connection to an unvalidated network.
472      * obj  = network
473      */
474     private static final int EVENT_PROMPT_UNVALIDATED = 29;
475 
476     /**
477      * used internally to (re)configure always-on networks.
478      */
479     private static final int EVENT_CONFIGURE_ALWAYS_ON_NETWORKS = 30;
480 
481     /**
482      * used to add a network listener with a pending intent
483      * obj = NetworkRequestInfo
484      */
485     private static final int EVENT_REGISTER_NETWORK_LISTENER_WITH_INTENT = 31;
486 
487     /**
488      * used to specify whether a network should not be penalized when it becomes unvalidated.
489      */
490     private static final int EVENT_SET_AVOID_UNVALIDATED = 35;
491 
492     /**
493      * used to trigger revalidation of a network.
494      */
495     private static final int EVENT_REVALIDATE_NETWORK = 36;
496 
497     // Handle changes in Private DNS settings.
498     private static final int EVENT_PRIVATE_DNS_SETTINGS_CHANGED = 37;
499 
500     // Handle private DNS validation status updates.
501     private static final int EVENT_PRIVATE_DNS_VALIDATION_UPDATE = 38;
502 
503     /**
504      * Used to handle onUidRulesChanged event from NetworkPolicyManagerService.
505      */
506     private static final int EVENT_UID_RULES_CHANGED = 39;
507 
508     /**
509      * Used to handle onRestrictBackgroundChanged event from NetworkPolicyManagerService.
510      */
511     private static final int EVENT_DATA_SAVER_CHANGED = 40;
512 
513      /**
514       * Event for NetworkMonitor/NetworkAgentInfo to inform ConnectivityService that the network has
515       * been tested.
516       * obj = {@link NetworkTestedResults} representing information sent from NetworkMonitor.
517       * data = PersistableBundle of extras passed from NetworkMonitor. If {@link
518       * NetworkMonitorCallbacks#notifyNetworkTested} is called, this will be null.
519       */
520     private static final int EVENT_NETWORK_TESTED = 41;
521 
522     /**
523      * Event for NetworkMonitor/NetworkAgentInfo to inform ConnectivityService that the private DNS
524      * config was resolved.
525      * obj = PrivateDnsConfig
526      * arg2 = netid
527      */
528     private static final int EVENT_PRIVATE_DNS_CONFIG_RESOLVED = 42;
529 
530     /**
531      * Request ConnectivityService display provisioning notification.
532      * arg1    = Whether to make the notification visible.
533      * arg2    = NetID.
534      * obj     = Intent to be launched when notification selected by user, null if !arg1.
535      */
536     private static final int EVENT_PROVISIONING_NOTIFICATION = 43;
537 
538     /**
539      * Used to specify whether a network should be used even if connectivity is partial.
540      * arg1 = whether to accept the network if its connectivity is partial (1 for true or 0 for
541      * false)
542      * arg2 = whether to remember this choice in the future (1 for true or 0 for false)
543      * obj  = network
544      */
545     private static final int EVENT_SET_ACCEPT_PARTIAL_CONNECTIVITY = 44;
546 
547     /**
548      * Event for NetworkMonitor to inform ConnectivityService that the probe status has changed.
549      * Both of the arguments are bitmasks, and the value of bits come from
550      * INetworkMonitor.NETWORK_VALIDATION_PROBE_*.
551      * arg1 = A bitmask to describe which probes are completed.
552      * arg2 = A bitmask to describe which probes are successful.
553      */
554     public static final int EVENT_PROBE_STATUS_CHANGED = 45;
555 
556     /**
557      * Event for NetworkMonitor to inform ConnectivityService that captive portal data has changed.
558      * arg1 = unused
559      * arg2 = netId
560      * obj = captive portal data
561      */
562     private static final int EVENT_CAPPORT_DATA_CHANGED = 46;
563 
564     /**
565      * Argument for {@link #EVENT_PROVISIONING_NOTIFICATION} to indicate that the notification
566      * should be shown.
567      */
568     private static final int PROVISIONING_NOTIFICATION_SHOW = 1;
569 
570     /**
571      * Argument for {@link #EVENT_PROVISIONING_NOTIFICATION} to indicate that the notification
572      * should be hidden.
573      */
574     private static final int PROVISIONING_NOTIFICATION_HIDE = 0;
575 
eventName(int what)576     private static String eventName(int what) {
577         return sMagicDecoderRing.get(what, Integer.toString(what));
578     }
579 
getDnsResolver()580     private static IDnsResolver getDnsResolver() {
581         return IDnsResolver.Stub
582                 .asInterface(ServiceManager.getService("dnsresolver"));
583     }
584 
585     /** Handler thread used for all of the handlers below. */
586     @VisibleForTesting
587     protected final HandlerThread mHandlerThread;
588     /** Handler used for internal events. */
589     final private InternalHandler mHandler;
590     /** Handler used for incoming {@link NetworkStateTracker} events. */
591     final private NetworkStateTrackerHandler mTrackerHandler;
592     /** Handler used for processing {@link android.net.ConnectivityDiagnosticsManager} events */
593     @VisibleForTesting
594     final ConnectivityDiagnosticsHandler mConnectivityDiagnosticsHandler;
595 
596     private final DnsManager mDnsManager;
597     private final NetworkRanker mNetworkRanker;
598 
599     private boolean mSystemReady;
600     private Intent mInitialBroadcast;
601 
602     private PowerManager.WakeLock mNetTransitionWakeLock;
603     private int mNetTransitionWakeLockTimeout;
604     private final PowerManager.WakeLock mPendingIntentWakeLock;
605 
606     // A helper object to track the current default HTTP proxy. ConnectivityService needs to tell
607     // the world when it changes.
608     @VisibleForTesting
609     protected final ProxyTracker mProxyTracker;
610 
611     final private SettingsObserver mSettingsObserver;
612 
613     private UserManager mUserManager;
614 
615     private NetworkConfig[] mNetConfigs;
616     private int mNetworksDefined;
617 
618     // the set of network types that can only be enabled by system/sig apps
619     private List mProtectedNetworks;
620 
621     private Set<String> mWolSupportedInterfaces;
622 
623     private final TelephonyManager mTelephonyManager;
624     private final AppOpsManager mAppOpsManager;
625 
626     private final LocationPermissionChecker mLocationPermissionChecker;
627 
628     private KeepaliveTracker mKeepaliveTracker;
629     private NetworkNotificationManager mNotifier;
630     private LingerMonitor mLingerMonitor;
631 
632     // sequence number of NetworkRequests
633     private int mNextNetworkRequestId = 1;
634 
635     // Sequence number for NetworkProvider IDs.
636     private final AtomicInteger mNextNetworkProviderId = new AtomicInteger(
637             NetworkProvider.FIRST_PROVIDER_ID);
638 
639     // NetworkRequest activity String log entries.
640     private static final int MAX_NETWORK_REQUEST_LOGS = 20;
641     private final LocalLog mNetworkRequestInfoLogs = new LocalLog(MAX_NETWORK_REQUEST_LOGS);
642 
643     // NetworkInfo blocked and unblocked String log entries
644     private static final int MAX_NETWORK_INFO_LOGS = 40;
645     private final LocalLog mNetworkInfoBlockingLogs = new LocalLog(MAX_NETWORK_INFO_LOGS);
646 
647     private static final int MAX_WAKELOCK_LOGS = 20;
648     private final LocalLog mWakelockLogs = new LocalLog(MAX_WAKELOCK_LOGS);
649     private int mTotalWakelockAcquisitions = 0;
650     private int mTotalWakelockReleases = 0;
651     private long mTotalWakelockDurationMs = 0;
652     private long mMaxWakelockDurationMs = 0;
653     private long mLastWakeLockAcquireTimestamp = 0;
654 
655     private final IpConnectivityLog mMetricsLog;
656 
657     @GuardedBy("mBandwidthRequests")
658     private final SparseArray<Integer> mBandwidthRequests = new SparseArray(10);
659 
660     @VisibleForTesting
661     final MultinetworkPolicyTracker mMultinetworkPolicyTracker;
662 
663     @VisibleForTesting
664     final MultipathPolicyTracker mMultipathPolicyTracker;
665 
666     @VisibleForTesting
667     final Map<IBinder, ConnectivityDiagnosticsCallbackInfo> mConnectivityDiagnosticsCallbacks =
668             new HashMap<>();
669 
670     /**
671      * Implements support for the legacy "one network per network type" model.
672      *
673      * We used to have a static array of NetworkStateTrackers, one for each
674      * network type, but that doesn't work any more now that we can have,
675      * for example, more that one wifi network. This class stores all the
676      * NetworkAgentInfo objects that support a given type, but the legacy
677      * API will only see the first one.
678      *
679      * It serves two main purposes:
680      *
681      * 1. Provide information about "the network for a given type" (since this
682      *    API only supports one).
683      * 2. Send legacy connectivity change broadcasts. Broadcasts are sent if
684      *    the first network for a given type changes, or if the default network
685      *    changes.
686      */
687     @VisibleForTesting
688     static class LegacyTypeTracker {
689 
690         private static final boolean DBG = true;
691         private static final boolean VDBG = false;
692 
693         /**
694          * Array of lists, one per legacy network type (e.g., TYPE_MOBILE_MMS).
695          * Each list holds references to all NetworkAgentInfos that are used to
696          * satisfy requests for that network type.
697          *
698          * This array is built out at startup such that an unsupported network
699          * doesn't get an ArrayList instance, making this a tristate:
700          * unsupported, supported but not active and active.
701          *
702          * The actual lists are populated when we scan the network types that
703          * are supported on this device.
704          *
705          * Threading model:
706          *  - addSupportedType() is only called in the constructor
707          *  - add(), update(), remove() are only called from the ConnectivityService handler thread.
708          *    They are therefore not thread-safe with respect to each other.
709          *  - getNetworkForType() can be called at any time on binder threads. It is synchronized
710          *    on mTypeLists to be thread-safe with respect to a concurrent remove call.
711          *  - dump is thread-safe with respect to concurrent add and remove calls.
712          */
713         private final ArrayList<NetworkAgentInfo> mTypeLists[];
714         @NonNull
715         private final ConnectivityService mService;
716 
LegacyTypeTracker(@onNull ConnectivityService service)717         LegacyTypeTracker(@NonNull ConnectivityService service) {
718             mService = service;
719             mTypeLists = new ArrayList[ConnectivityManager.MAX_NETWORK_TYPE + 1];
720         }
721 
addSupportedType(int type)722         public void addSupportedType(int type) {
723             if (mTypeLists[type] != null) {
724                 throw new IllegalStateException(
725                         "legacy list for type " + type + "already initialized");
726             }
727             mTypeLists[type] = new ArrayList<>();
728         }
729 
isTypeSupported(int type)730         public boolean isTypeSupported(int type) {
731             return isNetworkTypeValid(type) && mTypeLists[type] != null;
732         }
733 
getNetworkForType(int type)734         public NetworkAgentInfo getNetworkForType(int type) {
735             synchronized (mTypeLists) {
736                 if (isTypeSupported(type) && !mTypeLists[type].isEmpty()) {
737                     return mTypeLists[type].get(0);
738                 }
739             }
740             return null;
741         }
742 
maybeLogBroadcast(NetworkAgentInfo nai, DetailedState state, int type, boolean isDefaultNetwork)743         private void maybeLogBroadcast(NetworkAgentInfo nai, DetailedState state, int type,
744                 boolean isDefaultNetwork) {
745             if (DBG) {
746                 log("Sending " + state
747                         + " broadcast for type " + type + " " + nai.toShortString()
748                         + " isDefaultNetwork=" + isDefaultNetwork);
749             }
750         }
751 
752         /** Adds the given network to the specified legacy type list. */
add(int type, NetworkAgentInfo nai)753         public void add(int type, NetworkAgentInfo nai) {
754             if (!isTypeSupported(type)) {
755                 return;  // Invalid network type.
756             }
757             if (VDBG) log("Adding agent " + nai + " for legacy network type " + type);
758 
759             ArrayList<NetworkAgentInfo> list = mTypeLists[type];
760             if (list.contains(nai)) {
761                 return;
762             }
763             synchronized (mTypeLists) {
764                 list.add(nai);
765             }
766 
767             // Send a broadcast if this is the first network of its type or if it's the default.
768             final boolean isDefaultNetwork = mService.isDefaultNetwork(nai);
769             if ((list.size() == 1) || isDefaultNetwork) {
770                 maybeLogBroadcast(nai, DetailedState.CONNECTED, type, isDefaultNetwork);
771                 mService.sendLegacyNetworkBroadcast(nai, DetailedState.CONNECTED, type);
772             }
773         }
774 
775         /** Removes the given network from the specified legacy type list. */
remove(int type, NetworkAgentInfo nai, boolean wasDefault)776         public void remove(int type, NetworkAgentInfo nai, boolean wasDefault) {
777             ArrayList<NetworkAgentInfo> list = mTypeLists[type];
778             if (list == null || list.isEmpty()) {
779                 return;
780             }
781             final boolean wasFirstNetwork = list.get(0).equals(nai);
782 
783             synchronized (mTypeLists) {
784                 if (!list.remove(nai)) {
785                     return;
786                 }
787             }
788 
789             if (wasFirstNetwork || wasDefault) {
790                 maybeLogBroadcast(nai, DetailedState.DISCONNECTED, type, wasDefault);
791                 mService.sendLegacyNetworkBroadcast(nai, DetailedState.DISCONNECTED, type);
792             }
793 
794             if (!list.isEmpty() && wasFirstNetwork) {
795                 if (DBG) log("Other network available for type " + type +
796                               ", sending connected broadcast");
797                 final NetworkAgentInfo replacement = list.get(0);
798                 maybeLogBroadcast(replacement, DetailedState.CONNECTED, type,
799                         mService.isDefaultNetwork(replacement));
800                 mService.sendLegacyNetworkBroadcast(replacement, DetailedState.CONNECTED, type);
801             }
802         }
803 
804         /** Removes the given network from all legacy type lists. */
remove(NetworkAgentInfo nai, boolean wasDefault)805         public void remove(NetworkAgentInfo nai, boolean wasDefault) {
806             if (VDBG) log("Removing agent " + nai + " wasDefault=" + wasDefault);
807             for (int type = 0; type < mTypeLists.length; type++) {
808                 remove(type, nai, wasDefault);
809             }
810         }
811 
812         // send out another legacy broadcast - currently only used for suspend/unsuspend
813         // toggle
update(NetworkAgentInfo nai)814         public void update(NetworkAgentInfo nai) {
815             final boolean isDefault = mService.isDefaultNetwork(nai);
816             final DetailedState state = nai.networkInfo.getDetailedState();
817             for (int type = 0; type < mTypeLists.length; type++) {
818                 final ArrayList<NetworkAgentInfo> list = mTypeLists[type];
819                 final boolean contains = (list != null && list.contains(nai));
820                 final boolean isFirst = contains && (nai == list.get(0));
821                 if (isFirst || contains && isDefault) {
822                     maybeLogBroadcast(nai, state, type, isDefault);
823                     mService.sendLegacyNetworkBroadcast(nai, state, type);
824                 }
825             }
826         }
827 
dump(IndentingPrintWriter pw)828         public void dump(IndentingPrintWriter pw) {
829             pw.println("mLegacyTypeTracker:");
830             pw.increaseIndent();
831             pw.print("Supported types:");
832             for (int type = 0; type < mTypeLists.length; type++) {
833                 if (mTypeLists[type] != null) pw.print(" " + type);
834             }
835             pw.println();
836             pw.println("Current state:");
837             pw.increaseIndent();
838             synchronized (mTypeLists) {
839                 for (int type = 0; type < mTypeLists.length; type++) {
840                     if (mTypeLists[type] == null || mTypeLists[type].isEmpty()) continue;
841                     for (NetworkAgentInfo nai : mTypeLists[type]) {
842                         pw.println(type + " " + nai.toShortString());
843                     }
844                 }
845             }
846             pw.decreaseIndent();
847             pw.decreaseIndent();
848             pw.println();
849         }
850     }
851     private final LegacyTypeTracker mLegacyTypeTracker = new LegacyTypeTracker(this);
852 
853     /**
854      * Helper class which parses out priority arguments and dumps sections according to their
855      * priority. If priority arguments are omitted, function calls the legacy dump command.
856      */
857     private final PriorityDump.PriorityDumper mPriorityDumper = new PriorityDump.PriorityDumper() {
858         @Override
859         public void dumpHigh(FileDescriptor fd, PrintWriter pw, String[] args, boolean asProto) {
860             doDump(fd, pw, new String[] {DIAG_ARG}, asProto);
861             doDump(fd, pw, new String[] {SHORT_ARG}, asProto);
862         }
863 
864         @Override
865         public void dumpNormal(FileDescriptor fd, PrintWriter pw, String[] args, boolean asProto) {
866             doDump(fd, pw, args, asProto);
867         }
868 
869         @Override
870         public void dump(FileDescriptor fd, PrintWriter pw, String[] args, boolean asProto) {
871            doDump(fd, pw, args, asProto);
872         }
873     };
874 
875     /**
876      * Dependencies of ConnectivityService, for injection in tests.
877      */
878     @VisibleForTesting
879     public static class Dependencies {
880         /**
881          * Get system properties to use in ConnectivityService.
882          */
getSystemProperties()883         public MockableSystemProperties getSystemProperties() {
884             return new MockableSystemProperties();
885         }
886 
887         /**
888          * Create a HandlerThread to use in ConnectivityService.
889          */
makeHandlerThread()890         public HandlerThread makeHandlerThread() {
891             return new HandlerThread("ConnectivityServiceThread");
892         }
893 
894         /**
895          * Get a reference to the NetworkStackClient.
896          */
getNetworkStack()897         public NetworkStackClient getNetworkStack() {
898             return NetworkStackClient.getInstance();
899         }
900 
901         /**
902          * @see ProxyTracker
903          */
makeProxyTracker(@onNull Context context, @NonNull Handler connServiceHandler)904         public ProxyTracker makeProxyTracker(@NonNull Context context,
905                 @NonNull Handler connServiceHandler) {
906             return new ProxyTracker(context, connServiceHandler, EVENT_PROXY_HAS_CHANGED);
907         }
908 
909         /**
910          * @see NetIdManager
911          */
makeNetIdManager()912         public NetIdManager makeNetIdManager() {
913             return new NetIdManager();
914         }
915 
916         /**
917          * @see NetworkUtils#queryUserAccess(int, int)
918          */
queryUserAccess(int uid, int netId)919         public boolean queryUserAccess(int uid, int netId) {
920             return NetworkUtils.queryUserAccess(uid, netId);
921         }
922 
923         /**
924          * @see MultinetworkPolicyTracker
925          */
makeMultinetworkPolicyTracker( @onNull Context c, @NonNull Handler h, @NonNull Runnable r)926         public MultinetworkPolicyTracker makeMultinetworkPolicyTracker(
927                 @NonNull Context c, @NonNull Handler h, @NonNull Runnable r) {
928             return new MultinetworkPolicyTracker(c, h, r);
929         }
930 
931         /**
932          * @see ServiceManager#checkService(String)
933          */
hasService(@onNull String name)934         public boolean hasService(@NonNull String name) {
935             return ServiceManager.checkService(name) != null;
936         }
937 
938         /**
939          * @see IpConnectivityMetrics.Logger
940          */
getMetricsLogger()941         public IpConnectivityMetrics.Logger getMetricsLogger() {
942             return Objects.requireNonNull(LocalServices.getService(IpConnectivityMetrics.Logger.class),
943                     "no IpConnectivityMetrics service");
944         }
945 
946         /**
947          * @see IpConnectivityMetrics
948          */
getIpConnectivityMetrics()949         public IIpConnectivityMetrics getIpConnectivityMetrics() {
950             return IIpConnectivityMetrics.Stub.asInterface(
951                     ServiceManager.getService(IpConnectivityLog.SERVICE_NAME));
952         }
953 
getBatteryStatsService()954         public IBatteryStats getBatteryStatsService() {
955             return BatteryStatsService.getService();
956         }
957     }
958 
ConnectivityService(Context context, INetworkManagementService netManager, INetworkStatsService statsService, INetworkPolicyManager policyManager)959     public ConnectivityService(Context context, INetworkManagementService netManager,
960             INetworkStatsService statsService, INetworkPolicyManager policyManager) {
961         this(context, netManager, statsService, policyManager, getDnsResolver(),
962                 new IpConnectivityLog(), NetdService.getInstance(), new Dependencies());
963     }
964 
965     @VisibleForTesting
ConnectivityService(Context context, INetworkManagementService netManager, INetworkStatsService statsService, INetworkPolicyManager policyManager, IDnsResolver dnsresolver, IpConnectivityLog logger, INetd netd, Dependencies deps)966     protected ConnectivityService(Context context, INetworkManagementService netManager,
967             INetworkStatsService statsService, INetworkPolicyManager policyManager,
968             IDnsResolver dnsresolver, IpConnectivityLog logger, INetd netd, Dependencies deps) {
969         if (DBG) log("ConnectivityService starting up");
970 
971         mDeps = Objects.requireNonNull(deps, "missing Dependencies");
972         mSystemProperties = mDeps.getSystemProperties();
973         mNetIdManager = mDeps.makeNetIdManager();
974         mContext = Objects.requireNonNull(context, "missing Context");
975 
976         mMetricsLog = logger;
977         mDefaultRequest = createDefaultInternetRequestForTransport(-1, NetworkRequest.Type.REQUEST);
978         mNetworkRanker = new NetworkRanker();
979         NetworkRequestInfo defaultNRI = new NetworkRequestInfo(null, mDefaultRequest, new Binder());
980         mNetworkRequests.put(mDefaultRequest, defaultNRI);
981         mNetworkRequestInfoLogs.log("REGISTER " + defaultNRI);
982 
983         mDefaultMobileDataRequest = createDefaultInternetRequestForTransport(
984                 NetworkCapabilities.TRANSPORT_CELLULAR, NetworkRequest.Type.BACKGROUND_REQUEST);
985 
986         // The default WiFi request is a background request so that apps using WiFi are
987         // migrated to a better network (typically ethernet) when one comes up, instead
988         // of staying on WiFi forever.
989         mDefaultWifiRequest = createDefaultInternetRequestForTransport(
990                 NetworkCapabilities.TRANSPORT_WIFI, NetworkRequest.Type.BACKGROUND_REQUEST);
991 
992         mHandlerThread = mDeps.makeHandlerThread();
993         mHandlerThread.start();
994         mHandler = new InternalHandler(mHandlerThread.getLooper());
995         mTrackerHandler = new NetworkStateTrackerHandler(mHandlerThread.getLooper());
996         mConnectivityDiagnosticsHandler =
997                 new ConnectivityDiagnosticsHandler(mHandlerThread.getLooper());
998 
999         mReleasePendingIntentDelayMs = Settings.Secure.getInt(context.getContentResolver(),
1000                 Settings.Secure.CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS, 5_000);
1001 
1002         mLingerDelayMs = mSystemProperties.getInt(LINGER_DELAY_PROPERTY, DEFAULT_LINGER_DELAY_MS);
1003 
1004         mNMS = Objects.requireNonNull(netManager, "missing INetworkManagementService");
1005         mStatsService = Objects.requireNonNull(statsService, "missing INetworkStatsService");
1006         mPolicyManager = Objects.requireNonNull(policyManager, "missing INetworkPolicyManager");
1007         mPolicyManagerInternal = Objects.requireNonNull(
1008                 LocalServices.getService(NetworkPolicyManagerInternal.class),
1009                 "missing NetworkPolicyManagerInternal");
1010         mDnsResolver = Objects.requireNonNull(dnsresolver, "missing IDnsResolver");
1011         mProxyTracker = mDeps.makeProxyTracker(mContext, mHandler);
1012 
1013         mNetd = netd;
1014         mKeyStore = KeyStore.getInstance();
1015         mTelephonyManager = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
1016         mAppOpsManager = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
1017         mLocationPermissionChecker = new LocationPermissionChecker(mContext);
1018 
1019         // To ensure uid rules are synchronized with Network Policy, register for
1020         // NetworkPolicyManagerService events must happen prior to NetworkPolicyManagerService
1021         // reading existing policy from disk.
1022         try {
1023             mPolicyManager.registerListener(mPolicyListener);
1024         } catch (RemoteException e) {
1025             // ouch, no rules updates means some processes may never get network
1026             loge("unable to register INetworkPolicyListener" + e);
1027         }
1028 
1029         final PowerManager powerManager = (PowerManager) context.getSystemService(
1030                 Context.POWER_SERVICE);
1031         mNetTransitionWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
1032         mNetTransitionWakeLockTimeout = mContext.getResources().getInteger(
1033                 com.android.internal.R.integer.config_networkTransitionTimeout);
1034         mPendingIntentWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
1035 
1036         mNetConfigs = new NetworkConfig[ConnectivityManager.MAX_NETWORK_TYPE+1];
1037 
1038         // TODO: What is the "correct" way to do determine if this is a wifi only device?
1039         boolean wifiOnly = mSystemProperties.getBoolean("ro.radio.noril", false);
1040         log("wifiOnly=" + wifiOnly);
1041         String[] naStrings = context.getResources().getStringArray(
1042                 com.android.internal.R.array.networkAttributes);
1043         for (String naString : naStrings) {
1044             try {
1045                 NetworkConfig n = new NetworkConfig(naString);
1046                 if (VDBG) log("naString=" + naString + " config=" + n);
1047                 if (n.type > ConnectivityManager.MAX_NETWORK_TYPE) {
1048                     loge("Error in networkAttributes - ignoring attempt to define type " +
1049                             n.type);
1050                     continue;
1051                 }
1052                 if (wifiOnly && ConnectivityManager.isNetworkTypeMobile(n.type)) {
1053                     log("networkAttributes - ignoring mobile as this dev is wifiOnly " +
1054                             n.type);
1055                     continue;
1056                 }
1057                 if (mNetConfigs[n.type] != null) {
1058                     loge("Error in networkAttributes - ignoring attempt to redefine type " +
1059                             n.type);
1060                     continue;
1061                 }
1062                 mLegacyTypeTracker.addSupportedType(n.type);
1063 
1064                 mNetConfigs[n.type] = n;
1065                 mNetworksDefined++;
1066             } catch(Exception e) {
1067                 // ignore it - leave the entry null
1068             }
1069         }
1070 
1071         // Forcibly add TYPE_VPN as a supported type, if it has not already been added via config.
1072         if (mNetConfigs[TYPE_VPN] == null) {
1073             // mNetConfigs is used only for "restore time", which isn't applicable to VPNs, so we
1074             // don't need to add TYPE_VPN to mNetConfigs.
1075             mLegacyTypeTracker.addSupportedType(TYPE_VPN);
1076             mNetworksDefined++;  // used only in the log() statement below.
1077         }
1078 
1079         // Do the same for Ethernet, since it's often not specified in the configs, although many
1080         // devices can use it via USB host adapters.
1081         if (mNetConfigs[TYPE_ETHERNET] == null && mDeps.hasService(Context.ETHERNET_SERVICE)) {
1082             mLegacyTypeTracker.addSupportedType(TYPE_ETHERNET);
1083             mNetworksDefined++;
1084         }
1085 
1086         if (VDBG) log("mNetworksDefined=" + mNetworksDefined);
1087 
1088         mProtectedNetworks = new ArrayList<Integer>();
1089         int[] protectedNetworks = context.getResources().getIntArray(
1090                 com.android.internal.R.array.config_protectedNetworks);
1091         for (int p : protectedNetworks) {
1092             if ((mNetConfigs[p] != null) && (mProtectedNetworks.contains(p) == false)) {
1093                 mProtectedNetworks.add(p);
1094             } else {
1095                 if (DBG) loge("Ignoring protectedNetwork " + p);
1096             }
1097         }
1098 
1099         mWolSupportedInterfaces = new ArraySet(
1100                 mContext.getResources().getStringArray(
1101                         com.android.internal.R.array.config_wakeonlan_supported_interfaces));
1102 
1103         mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
1104 
1105         mPermissionMonitor = new PermissionMonitor(mContext, mNetd);
1106 
1107         // Set up the listener for user state for creating user VPNs.
1108         // Should run on mHandler to avoid any races.
1109         IntentFilter intentFilter = new IntentFilter();
1110         intentFilter.addAction(Intent.ACTION_USER_STARTED);
1111         intentFilter.addAction(Intent.ACTION_USER_STOPPED);
1112         intentFilter.addAction(Intent.ACTION_USER_ADDED);
1113         intentFilter.addAction(Intent.ACTION_USER_REMOVED);
1114         intentFilter.addAction(Intent.ACTION_USER_UNLOCKED);
1115         mContext.registerReceiverAsUser(
1116                 mIntentReceiver,
1117                 UserHandle.ALL,
1118                 intentFilter,
1119                 null /* broadcastPermission */,
1120                 mHandler);
1121         mContext.registerReceiverAsUser(mUserPresentReceiver, UserHandle.SYSTEM,
1122                 new IntentFilter(Intent.ACTION_USER_PRESENT), null, null);
1123 
1124         // Listen to package add and removal events for all users.
1125         intentFilter = new IntentFilter();
1126         intentFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
1127         intentFilter.addAction(Intent.ACTION_PACKAGE_REPLACED);
1128         intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
1129         intentFilter.addDataScheme("package");
1130         mContext.registerReceiverAsUser(
1131                 mIntentReceiver,
1132                 UserHandle.ALL,
1133                 intentFilter,
1134                 null /* broadcastPermission */,
1135                 mHandler);
1136 
1137         try {
1138             mNMS.registerObserver(mDataActivityObserver);
1139         } catch (RemoteException e) {
1140             loge("Error registering observer :" + e);
1141         }
1142 
1143         mSettingsObserver = new SettingsObserver(mContext, mHandler);
1144         registerSettingsCallbacks();
1145 
1146         final DataConnectionStats dataConnectionStats = new DataConnectionStats(mContext, mHandler);
1147         dataConnectionStats.startMonitoring();
1148 
1149         mKeepaliveTracker = new KeepaliveTracker(mContext, mHandler);
1150         mNotifier = new NetworkNotificationManager(mContext, mTelephonyManager,
1151                 mContext.getSystemService(NotificationManager.class));
1152 
1153         final int dailyLimit = Settings.Global.getInt(mContext.getContentResolver(),
1154                 Settings.Global.NETWORK_SWITCH_NOTIFICATION_DAILY_LIMIT,
1155                 LingerMonitor.DEFAULT_NOTIFICATION_DAILY_LIMIT);
1156         final long rateLimit = Settings.Global.getLong(mContext.getContentResolver(),
1157                 Settings.Global.NETWORK_SWITCH_NOTIFICATION_RATE_LIMIT_MILLIS,
1158                 LingerMonitor.DEFAULT_NOTIFICATION_RATE_LIMIT_MILLIS);
1159         mLingerMonitor = new LingerMonitor(mContext, mNotifier, dailyLimit, rateLimit);
1160 
1161         mMultinetworkPolicyTracker = mDeps.makeMultinetworkPolicyTracker(
1162                 mContext, mHandler, () -> rematchForAvoidBadWifiUpdate());
1163         mMultinetworkPolicyTracker.start();
1164 
1165         mMultipathPolicyTracker = new MultipathPolicyTracker(mContext, mHandler);
1166 
1167         mDnsManager = new DnsManager(mContext, mDnsResolver, mSystemProperties);
1168         registerPrivateDnsSettingsCallbacks();
1169     }
1170 
createDefaultNetworkCapabilitiesForUid(int uid)1171     private static NetworkCapabilities createDefaultNetworkCapabilitiesForUid(int uid) {
1172         final NetworkCapabilities netCap = new NetworkCapabilities();
1173         netCap.addCapability(NET_CAPABILITY_INTERNET);
1174         netCap.removeCapability(NET_CAPABILITY_NOT_VPN);
1175         netCap.setSingleUid(uid);
1176         return netCap;
1177     }
1178 
createDefaultInternetRequestForTransport( int transportType, NetworkRequest.Type type)1179     private NetworkRequest createDefaultInternetRequestForTransport(
1180             int transportType, NetworkRequest.Type type) {
1181         final NetworkCapabilities netCap = new NetworkCapabilities();
1182         netCap.addCapability(NET_CAPABILITY_INTERNET);
1183         netCap.setRequestorUidAndPackageName(Process.myUid(), mContext.getPackageName());
1184         if (transportType > -1) {
1185             netCap.addTransportType(transportType);
1186         }
1187         return new NetworkRequest(netCap, TYPE_NONE, nextNetworkRequestId(), type);
1188     }
1189 
1190     // Used only for testing.
1191     // TODO: Delete this and either:
1192     // 1. Give FakeSettingsProvider the ability to send settings change notifications (requires
1193     //    changing ContentResolver to make registerContentObserver non-final).
1194     // 2. Give FakeSettingsProvider an alternative notification mechanism and have the test use it
1195     //    by subclassing SettingsObserver.
1196     @VisibleForTesting
updateAlwaysOnNetworks()1197     void updateAlwaysOnNetworks() {
1198         mHandler.sendEmptyMessage(EVENT_CONFIGURE_ALWAYS_ON_NETWORKS);
1199     }
1200 
1201     // See FakeSettingsProvider comment above.
1202     @VisibleForTesting
updatePrivateDnsSettings()1203     void updatePrivateDnsSettings() {
1204         mHandler.sendEmptyMessage(EVENT_PRIVATE_DNS_SETTINGS_CHANGED);
1205     }
1206 
handleAlwaysOnNetworkRequest( NetworkRequest networkRequest, String settingName, boolean defaultValue)1207     private void handleAlwaysOnNetworkRequest(
1208             NetworkRequest networkRequest, String settingName, boolean defaultValue) {
1209         final boolean enable = toBool(Settings.Global.getInt(
1210                 mContext.getContentResolver(), settingName, encodeBool(defaultValue)));
1211         final boolean isEnabled = (mNetworkRequests.get(networkRequest) != null);
1212         if (enable == isEnabled) {
1213             return;  // Nothing to do.
1214         }
1215 
1216         if (enable) {
1217             handleRegisterNetworkRequest(new NetworkRequestInfo(
1218                     null, networkRequest, new Binder()));
1219         } else {
1220             handleReleaseNetworkRequest(networkRequest, Process.SYSTEM_UID,
1221                     /* callOnUnavailable */ false);
1222         }
1223     }
1224 
handleConfigureAlwaysOnNetworks()1225     private void handleConfigureAlwaysOnNetworks() {
1226         handleAlwaysOnNetworkRequest(
1227                 mDefaultMobileDataRequest,Settings.Global.MOBILE_DATA_ALWAYS_ON, true);
1228         handleAlwaysOnNetworkRequest(mDefaultWifiRequest, Settings.Global.WIFI_ALWAYS_REQUESTED,
1229                 false);
1230     }
1231 
registerSettingsCallbacks()1232     private void registerSettingsCallbacks() {
1233         // Watch for global HTTP proxy changes.
1234         mSettingsObserver.observe(
1235                 Settings.Global.getUriFor(Settings.Global.HTTP_PROXY),
1236                 EVENT_APPLY_GLOBAL_HTTP_PROXY);
1237 
1238         // Watch for whether or not to keep mobile data always on.
1239         mSettingsObserver.observe(
1240                 Settings.Global.getUriFor(Settings.Global.MOBILE_DATA_ALWAYS_ON),
1241                 EVENT_CONFIGURE_ALWAYS_ON_NETWORKS);
1242 
1243         // Watch for whether or not to keep wifi always on.
1244         mSettingsObserver.observe(
1245                 Settings.Global.getUriFor(Settings.Global.WIFI_ALWAYS_REQUESTED),
1246                 EVENT_CONFIGURE_ALWAYS_ON_NETWORKS);
1247     }
1248 
registerPrivateDnsSettingsCallbacks()1249     private void registerPrivateDnsSettingsCallbacks() {
1250         for (Uri uri : DnsManager.getPrivateDnsSettingsUris()) {
1251             mSettingsObserver.observe(uri, EVENT_PRIVATE_DNS_SETTINGS_CHANGED);
1252         }
1253     }
1254 
nextNetworkRequestId()1255     private synchronized int nextNetworkRequestId() {
1256         return mNextNetworkRequestId++;
1257     }
1258 
getFilteredNetworkState(int networkType, int uid)1259     private NetworkState getFilteredNetworkState(int networkType, int uid) {
1260         if (mLegacyTypeTracker.isTypeSupported(networkType)) {
1261             final NetworkAgentInfo nai = mLegacyTypeTracker.getNetworkForType(networkType);
1262             final NetworkState state;
1263             if (nai != null) {
1264                 state = nai.getNetworkState();
1265                 state.networkInfo.setType(networkType);
1266             } else {
1267                 final NetworkInfo info = new NetworkInfo(networkType, 0,
1268                         getNetworkTypeName(networkType), "");
1269                 info.setDetailedState(NetworkInfo.DetailedState.DISCONNECTED, null, null);
1270                 info.setIsAvailable(true);
1271                 final NetworkCapabilities capabilities = new NetworkCapabilities();
1272                 capabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING,
1273                         !info.isRoaming());
1274                 state = new NetworkState(info, new LinkProperties(), capabilities,
1275                         null, null, null);
1276             }
1277             filterNetworkStateForUid(state, uid, false);
1278             return state;
1279         } else {
1280             return NetworkState.EMPTY;
1281         }
1282     }
1283 
1284     @VisibleForTesting
getNetworkAgentInfoForNetwork(Network network)1285     protected NetworkAgentInfo getNetworkAgentInfoForNetwork(Network network) {
1286         if (network == null) {
1287             return null;
1288         }
1289         return getNetworkAgentInfoForNetId(network.netId);
1290     }
1291 
getNetworkAgentInfoForNetId(int netId)1292     private NetworkAgentInfo getNetworkAgentInfoForNetId(int netId) {
1293         synchronized (mNetworkForNetId) {
1294             return mNetworkForNetId.get(netId);
1295         }
1296     }
1297 
getVpnUnderlyingNetworks(int uid)1298     private Network[] getVpnUnderlyingNetworks(int uid) {
1299         synchronized (mVpns) {
1300             if (!mLockdownEnabled) {
1301                 int user = UserHandle.getUserId(uid);
1302                 Vpn vpn = mVpns.get(user);
1303                 if (vpn != null && vpn.appliesToUid(uid)) {
1304                     return vpn.getUnderlyingNetworks();
1305                 }
1306             }
1307         }
1308         return null;
1309     }
1310 
getUnfilteredActiveNetworkState(int uid)1311     private NetworkState getUnfilteredActiveNetworkState(int uid) {
1312         NetworkAgentInfo nai = getDefaultNetwork();
1313 
1314         final Network[] networks = getVpnUnderlyingNetworks(uid);
1315         if (networks != null) {
1316             // getUnderlyingNetworks() returns:
1317             // null => there was no VPN, or the VPN didn't specify anything, so we use the default.
1318             // empty array => the VPN explicitly said "no default network".
1319             // non-empty array => the VPN specified one or more default networks; we use the
1320             //                    first one.
1321             if (networks.length > 0) {
1322                 nai = getNetworkAgentInfoForNetwork(networks[0]);
1323             } else {
1324                 nai = null;
1325             }
1326         }
1327 
1328         if (nai != null) {
1329             return nai.getNetworkState();
1330         } else {
1331             return NetworkState.EMPTY;
1332         }
1333     }
1334 
1335     /**
1336      * Check if UID should be blocked from using the network with the given LinkProperties.
1337      */
isNetworkWithLinkPropertiesBlocked(LinkProperties lp, int uid, boolean ignoreBlocked)1338     private boolean isNetworkWithLinkPropertiesBlocked(LinkProperties lp, int uid,
1339             boolean ignoreBlocked) {
1340         // Networks aren't blocked when ignoring blocked status
1341         if (ignoreBlocked) {
1342             return false;
1343         }
1344         synchronized (mVpns) {
1345             final Vpn vpn = mVpns.get(UserHandle.getUserId(uid));
1346             if (vpn != null && vpn.getLockdown() && vpn.isBlockingUid(uid)) {
1347                 return true;
1348             }
1349         }
1350         final String iface = (lp == null ? "" : lp.getInterfaceName());
1351         return mPolicyManagerInternal.isUidNetworkingBlocked(uid, iface);
1352     }
1353 
maybeLogBlockedNetworkInfo(NetworkInfo ni, int uid)1354     private void maybeLogBlockedNetworkInfo(NetworkInfo ni, int uid) {
1355         if (ni == null || !LOGD_BLOCKED_NETWORKINFO) {
1356             return;
1357         }
1358         final boolean blocked;
1359         synchronized (mBlockedAppUids) {
1360             if (ni.getDetailedState() == DetailedState.BLOCKED && mBlockedAppUids.add(uid)) {
1361                 blocked = true;
1362             } else if (ni.isConnected() && mBlockedAppUids.remove(uid)) {
1363                 blocked = false;
1364             } else {
1365                 return;
1366             }
1367         }
1368         String action = blocked ? "BLOCKED" : "UNBLOCKED";
1369         log(String.format("Returning %s NetworkInfo to uid=%d", action, uid));
1370         mNetworkInfoBlockingLogs.log(action + " " + uid);
1371     }
1372 
maybeLogBlockedStatusChanged(NetworkRequestInfo nri, Network net, boolean blocked)1373     private void maybeLogBlockedStatusChanged(NetworkRequestInfo nri, Network net,
1374             boolean blocked) {
1375         if (nri == null || net == null || !LOGD_BLOCKED_NETWORKINFO) {
1376             return;
1377         }
1378         final String action = blocked ? "BLOCKED" : "UNBLOCKED";
1379         mNetworkInfoBlockingLogs.log(String.format(
1380                 "%s %d(%d) on netId %d", action, nri.mUid, nri.request.requestId, net.netId));
1381     }
1382 
1383     /**
1384      * Apply any relevant filters to {@link NetworkState} for the given UID. For
1385      * example, this may mark the network as {@link DetailedState#BLOCKED} based
1386      * on {@link #isNetworkWithLinkPropertiesBlocked}.
1387      */
filterNetworkStateForUid(NetworkState state, int uid, boolean ignoreBlocked)1388     private void filterNetworkStateForUid(NetworkState state, int uid, boolean ignoreBlocked) {
1389         if (state == null || state.networkInfo == null || state.linkProperties == null) return;
1390 
1391         if (isNetworkWithLinkPropertiesBlocked(state.linkProperties, uid, ignoreBlocked)) {
1392             state.networkInfo.setDetailedState(DetailedState.BLOCKED, null, null);
1393         }
1394         synchronized (mVpns) {
1395             if (mLockdownTracker != null) {
1396                 mLockdownTracker.augmentNetworkInfo(state.networkInfo);
1397             }
1398         }
1399     }
1400 
1401     /**
1402      * Return NetworkInfo for the active (i.e., connected) network interface.
1403      * It is assumed that at most one network is active at a time. If more
1404      * than one is active, it is indeterminate which will be returned.
1405      * @return the info for the active network, or {@code null} if none is
1406      * active
1407      */
1408     @Override
getActiveNetworkInfo()1409     public NetworkInfo getActiveNetworkInfo() {
1410         enforceAccessPermission();
1411         final int uid = Binder.getCallingUid();
1412         final NetworkState state = getUnfilteredActiveNetworkState(uid);
1413         filterNetworkStateForUid(state, uid, false);
1414         maybeLogBlockedNetworkInfo(state.networkInfo, uid);
1415         return state.networkInfo;
1416     }
1417 
1418     @Override
getActiveNetwork()1419     public Network getActiveNetwork() {
1420         enforceAccessPermission();
1421         return getActiveNetworkForUidInternal(Binder.getCallingUid(), false);
1422     }
1423 
1424     @Override
getActiveNetworkForUid(int uid, boolean ignoreBlocked)1425     public Network getActiveNetworkForUid(int uid, boolean ignoreBlocked) {
1426         NetworkStack.checkNetworkStackPermission(mContext);
1427         return getActiveNetworkForUidInternal(uid, ignoreBlocked);
1428     }
1429 
getActiveNetworkForUidInternal(final int uid, boolean ignoreBlocked)1430     private Network getActiveNetworkForUidInternal(final int uid, boolean ignoreBlocked) {
1431         final int user = UserHandle.getUserId(uid);
1432         int vpnNetId = NETID_UNSET;
1433         synchronized (mVpns) {
1434             final Vpn vpn = mVpns.get(user);
1435             // TODO : now that capabilities contain the UID, the appliesToUid test should
1436             // be removed as the satisfying test below should be enough.
1437             if (vpn != null && vpn.appliesToUid(uid)) vpnNetId = vpn.getNetId();
1438         }
1439         NetworkAgentInfo nai;
1440         if (vpnNetId != NETID_UNSET) {
1441             nai = getNetworkAgentInfoForNetId(vpnNetId);
1442             if (nai != null) {
1443                 final NetworkCapabilities requiredCaps =
1444                     createDefaultNetworkCapabilitiesForUid(uid);
1445                 if (requiredCaps.satisfiedByNetworkCapabilities(nai.networkCapabilities)) {
1446                     return nai.network;
1447                 }
1448             }
1449         }
1450         nai = getDefaultNetwork();
1451         if (nai != null
1452                 && isNetworkWithLinkPropertiesBlocked(nai.linkProperties, uid, ignoreBlocked)) {
1453             nai = null;
1454         }
1455         return nai != null ? nai.network : null;
1456     }
1457 
1458     // Public because it's used by mLockdownTracker.
getActiveNetworkInfoUnfiltered()1459     public NetworkInfo getActiveNetworkInfoUnfiltered() {
1460         enforceAccessPermission();
1461         final int uid = Binder.getCallingUid();
1462         NetworkState state = getUnfilteredActiveNetworkState(uid);
1463         return state.networkInfo;
1464     }
1465 
1466     @Override
getActiveNetworkInfoForUid(int uid, boolean ignoreBlocked)1467     public NetworkInfo getActiveNetworkInfoForUid(int uid, boolean ignoreBlocked) {
1468         NetworkStack.checkNetworkStackPermission(mContext);
1469         final NetworkState state = getUnfilteredActiveNetworkState(uid);
1470         filterNetworkStateForUid(state, uid, ignoreBlocked);
1471         return state.networkInfo;
1472     }
1473 
1474     @Override
getNetworkInfo(int networkType)1475     public NetworkInfo getNetworkInfo(int networkType) {
1476         enforceAccessPermission();
1477         final int uid = Binder.getCallingUid();
1478         if (getVpnUnderlyingNetworks(uid) != null) {
1479             // A VPN is active, so we may need to return one of its underlying networks. This
1480             // information is not available in LegacyTypeTracker, so we have to get it from
1481             // getUnfilteredActiveNetworkState.
1482             final NetworkState state = getUnfilteredActiveNetworkState(uid);
1483             if (state.networkInfo != null && state.networkInfo.getType() == networkType) {
1484                 filterNetworkStateForUid(state, uid, false);
1485                 return state.networkInfo;
1486             }
1487         }
1488         final NetworkState state = getFilteredNetworkState(networkType, uid);
1489         return state.networkInfo;
1490     }
1491 
1492     @Override
getNetworkInfoForUid(Network network, int uid, boolean ignoreBlocked)1493     public NetworkInfo getNetworkInfoForUid(Network network, int uid, boolean ignoreBlocked) {
1494         enforceAccessPermission();
1495         final NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
1496         if (nai != null) {
1497             final NetworkState state = nai.getNetworkState();
1498             filterNetworkStateForUid(state, uid, ignoreBlocked);
1499             return state.networkInfo;
1500         } else {
1501             return null;
1502         }
1503     }
1504 
1505     @Override
getAllNetworkInfo()1506     public NetworkInfo[] getAllNetworkInfo() {
1507         enforceAccessPermission();
1508         final ArrayList<NetworkInfo> result = Lists.newArrayList();
1509         for (int networkType = 0; networkType <= ConnectivityManager.MAX_NETWORK_TYPE;
1510                 networkType++) {
1511             NetworkInfo info = getNetworkInfo(networkType);
1512             if (info != null) {
1513                 result.add(info);
1514             }
1515         }
1516         return result.toArray(new NetworkInfo[result.size()]);
1517     }
1518 
1519     @Override
getNetworkForType(int networkType)1520     public Network getNetworkForType(int networkType) {
1521         enforceAccessPermission();
1522         final int uid = Binder.getCallingUid();
1523         NetworkState state = getFilteredNetworkState(networkType, uid);
1524         if (!isNetworkWithLinkPropertiesBlocked(state.linkProperties, uid, false)) {
1525             return state.network;
1526         }
1527         return null;
1528     }
1529 
1530     @Override
getAllNetworks()1531     public Network[] getAllNetworks() {
1532         enforceAccessPermission();
1533         synchronized (mNetworkForNetId) {
1534             final Network[] result = new Network[mNetworkForNetId.size()];
1535             for (int i = 0; i < mNetworkForNetId.size(); i++) {
1536                 result[i] = mNetworkForNetId.valueAt(i).network;
1537             }
1538             return result;
1539         }
1540     }
1541 
1542     @Override
getDefaultNetworkCapabilitiesForUser( int userId, String callingPackageName)1543     public NetworkCapabilities[] getDefaultNetworkCapabilitiesForUser(
1544                 int userId, String callingPackageName) {
1545         // The basic principle is: if an app's traffic could possibly go over a
1546         // network, without the app doing anything multinetwork-specific,
1547         // (hence, by "default"), then include that network's capabilities in
1548         // the array.
1549         //
1550         // In the normal case, app traffic only goes over the system's default
1551         // network connection, so that's the only network returned.
1552         //
1553         // With a VPN in force, some app traffic may go into the VPN, and thus
1554         // over whatever underlying networks the VPN specifies, while other app
1555         // traffic may go over the system default network (e.g.: a split-tunnel
1556         // VPN, or an app disallowed by the VPN), so the set of networks
1557         // returned includes the VPN's underlying networks and the system
1558         // default.
1559         enforceAccessPermission();
1560 
1561         HashMap<Network, NetworkCapabilities> result = new HashMap<>();
1562 
1563         NetworkAgentInfo nai = getDefaultNetwork();
1564         NetworkCapabilities nc = getNetworkCapabilitiesInternal(nai);
1565         if (nc != null) {
1566             result.put(
1567                     nai.network,
1568                     maybeSanitizeLocationInfoForCaller(
1569                             nc, Binder.getCallingUid(), callingPackageName));
1570         }
1571 
1572         synchronized (mVpns) {
1573             if (!mLockdownEnabled) {
1574                 Vpn vpn = mVpns.get(userId);
1575                 if (vpn != null) {
1576                     Network[] networks = vpn.getUnderlyingNetworks();
1577                     if (networks != null) {
1578                         for (Network network : networks) {
1579                             nc = getNetworkCapabilitiesInternal(network);
1580                             if (nc != null) {
1581                                 result.put(
1582                                         network,
1583                                         maybeSanitizeLocationInfoForCaller(
1584                                                 nc, Binder.getCallingUid(), callingPackageName));
1585                             }
1586                         }
1587                     }
1588                 }
1589             }
1590         }
1591 
1592         NetworkCapabilities[] out = new NetworkCapabilities[result.size()];
1593         out = result.values().toArray(out);
1594         return out;
1595     }
1596 
1597     @Override
isNetworkSupported(int networkType)1598     public boolean isNetworkSupported(int networkType) {
1599         enforceAccessPermission();
1600         return mLegacyTypeTracker.isTypeSupported(networkType);
1601     }
1602 
1603     /**
1604      * Return LinkProperties for the active (i.e., connected) default
1605      * network interface.  It is assumed that at most one default network
1606      * is active at a time. If more than one is active, it is indeterminate
1607      * which will be returned.
1608      * @return the ip properties for the active network, or {@code null} if
1609      * none is active
1610      */
1611     @Override
getActiveLinkProperties()1612     public LinkProperties getActiveLinkProperties() {
1613         enforceAccessPermission();
1614         final int uid = Binder.getCallingUid();
1615         NetworkState state = getUnfilteredActiveNetworkState(uid);
1616         if (state.linkProperties == null) return null;
1617         return linkPropertiesRestrictedForCallerPermissions(state.linkProperties,
1618                 Binder.getCallingPid(), uid);
1619     }
1620 
1621     @Override
getLinkPropertiesForType(int networkType)1622     public LinkProperties getLinkPropertiesForType(int networkType) {
1623         enforceAccessPermission();
1624         NetworkAgentInfo nai = mLegacyTypeTracker.getNetworkForType(networkType);
1625         final LinkProperties lp = getLinkProperties(nai);
1626         if (lp == null) return null;
1627         return linkPropertiesRestrictedForCallerPermissions(
1628                 lp, Binder.getCallingPid(), Binder.getCallingUid());
1629     }
1630 
1631     // TODO - this should be ALL networks
1632     @Override
getLinkProperties(Network network)1633     public LinkProperties getLinkProperties(Network network) {
1634         enforceAccessPermission();
1635         final LinkProperties lp = getLinkProperties(getNetworkAgentInfoForNetwork(network));
1636         if (lp == null) return null;
1637         return linkPropertiesRestrictedForCallerPermissions(
1638                 lp, Binder.getCallingPid(), Binder.getCallingUid());
1639     }
1640 
1641     @Nullable
getLinkProperties(@ullable NetworkAgentInfo nai)1642     private LinkProperties getLinkProperties(@Nullable NetworkAgentInfo nai) {
1643         if (nai == null) {
1644             return null;
1645         }
1646         synchronized (nai) {
1647             return nai.linkProperties;
1648         }
1649     }
1650 
getNetworkCapabilitiesInternal(Network network)1651     private NetworkCapabilities getNetworkCapabilitiesInternal(Network network) {
1652         return getNetworkCapabilitiesInternal(getNetworkAgentInfoForNetwork(network));
1653     }
1654 
getNetworkCapabilitiesInternal(NetworkAgentInfo nai)1655     private NetworkCapabilities getNetworkCapabilitiesInternal(NetworkAgentInfo nai) {
1656         if (nai == null) return null;
1657         synchronized (nai) {
1658             if (nai.networkCapabilities == null) return null;
1659             return networkCapabilitiesRestrictedForCallerPermissions(
1660                     nai.networkCapabilities, Binder.getCallingPid(), Binder.getCallingUid());
1661         }
1662     }
1663 
1664     @Override
getNetworkCapabilities(Network network, String callingPackageName)1665     public NetworkCapabilities getNetworkCapabilities(Network network, String callingPackageName) {
1666         mAppOpsManager.checkPackage(Binder.getCallingUid(), callingPackageName);
1667         enforceAccessPermission();
1668         return maybeSanitizeLocationInfoForCaller(
1669                 getNetworkCapabilitiesInternal(network),
1670                 Binder.getCallingUid(), callingPackageName);
1671     }
1672 
1673     @VisibleForTesting
networkCapabilitiesRestrictedForCallerPermissions( NetworkCapabilities nc, int callerPid, int callerUid)1674     NetworkCapabilities networkCapabilitiesRestrictedForCallerPermissions(
1675             NetworkCapabilities nc, int callerPid, int callerUid) {
1676         final NetworkCapabilities newNc = new NetworkCapabilities(nc);
1677         if (!checkSettingsPermission(callerPid, callerUid)) {
1678             newNc.setUids(null);
1679             newNc.setSSID(null);
1680         }
1681         if (newNc.getNetworkSpecifier() != null) {
1682             newNc.setNetworkSpecifier(newNc.getNetworkSpecifier().redact());
1683         }
1684         newNc.setAdministratorUids(new int[0]);
1685 
1686         return newNc;
1687     }
1688 
1689     @VisibleForTesting
1690     @Nullable
maybeSanitizeLocationInfoForCaller( @ullable NetworkCapabilities nc, int callerUid, @NonNull String callerPkgName)1691     NetworkCapabilities maybeSanitizeLocationInfoForCaller(
1692             @Nullable NetworkCapabilities nc, int callerUid, @NonNull String callerPkgName) {
1693         if (nc == null) {
1694             return null;
1695         }
1696         final NetworkCapabilities newNc = new NetworkCapabilities(nc);
1697         if (callerUid != newNc.getOwnerUid()) {
1698             newNc.setOwnerUid(INVALID_UID);
1699             return newNc;
1700         }
1701 
1702         // Allow VPNs to see ownership of their own VPN networks - not location sensitive.
1703         if (nc.hasTransport(TRANSPORT_VPN)) {
1704             // Owner UIDs already checked above. No need to re-check.
1705             return newNc;
1706         }
1707 
1708         Binder.withCleanCallingIdentity(
1709                 () -> {
1710                     if (!mLocationPermissionChecker.checkLocationPermission(
1711                             callerPkgName, null /* featureId */, callerUid, null /* message */)) {
1712                         // Caller does not have the requisite location permissions. Reset the
1713                         // owner's UID in the NetworkCapabilities.
1714                         newNc.setOwnerUid(INVALID_UID);
1715                     }
1716                 }
1717         );
1718 
1719         return newNc;
1720     }
1721 
linkPropertiesRestrictedForCallerPermissions( LinkProperties lp, int callerPid, int callerUid)1722     private LinkProperties linkPropertiesRestrictedForCallerPermissions(
1723             LinkProperties lp, int callerPid, int callerUid) {
1724         if (lp == null) return new LinkProperties();
1725 
1726         // Only do a permission check if sanitization is needed, to avoid unnecessary binder calls.
1727         final boolean needsSanitization =
1728                 (lp.getCaptivePortalApiUrl() != null || lp.getCaptivePortalData() != null);
1729         if (!needsSanitization) {
1730             return new LinkProperties(lp);
1731         }
1732 
1733         if (checkSettingsPermission(callerPid, callerUid)) {
1734             return new LinkProperties(lp, true /* parcelSensitiveFields */);
1735         }
1736 
1737         final LinkProperties newLp = new LinkProperties(lp);
1738         // Sensitive fields would not be parceled anyway, but sanitize for consistency before the
1739         // object gets parceled.
1740         newLp.setCaptivePortalApiUrl(null);
1741         newLp.setCaptivePortalData(null);
1742         return newLp;
1743     }
1744 
restrictRequestUidsForCallerAndSetRequestorInfo(NetworkCapabilities nc, int callerUid, String callerPackageName)1745     private void restrictRequestUidsForCallerAndSetRequestorInfo(NetworkCapabilities nc,
1746             int callerUid, String callerPackageName) {
1747         if (!checkSettingsPermission()) {
1748             nc.setSingleUid(callerUid);
1749         }
1750         nc.setRequestorUidAndPackageName(callerUid, callerPackageName);
1751         nc.setAdministratorUids(new int[0]);
1752 
1753         // Clear owner UID; this can never come from an app.
1754         nc.setOwnerUid(INVALID_UID);
1755     }
1756 
restrictBackgroundRequestForCaller(NetworkCapabilities nc)1757     private void restrictBackgroundRequestForCaller(NetworkCapabilities nc) {
1758         if (!mPermissionMonitor.hasUseBackgroundNetworksPermission(Binder.getCallingUid())) {
1759             nc.addCapability(NET_CAPABILITY_FOREGROUND);
1760         }
1761     }
1762 
1763     @Override
getAllNetworkState()1764     public NetworkState[] getAllNetworkState() {
1765         // This contains IMSI details, so make sure the caller is privileged.
1766         NetworkStack.checkNetworkStackPermission(mContext);
1767 
1768         final ArrayList<NetworkState> result = Lists.newArrayList();
1769         for (Network network : getAllNetworks()) {
1770             final NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
1771             if (nai != null) {
1772                 // TODO (b/73321673) : NetworkState contains a copy of the
1773                 // NetworkCapabilities, which may contain UIDs of apps to which the
1774                 // network applies. Should the UIDs be cleared so as not to leak or
1775                 // interfere ?
1776                 result.add(nai.getNetworkState());
1777             }
1778         }
1779         return result.toArray(new NetworkState[result.size()]);
1780     }
1781 
1782     @Override
1783     @Deprecated
getActiveNetworkQuotaInfo()1784     public NetworkQuotaInfo getActiveNetworkQuotaInfo() {
1785         Log.w(TAG, "Shame on UID " + Binder.getCallingUid()
1786                 + " for calling the hidden API getNetworkQuotaInfo(). Shame!");
1787         return new NetworkQuotaInfo();
1788     }
1789 
1790     @Override
isActiveNetworkMetered()1791     public boolean isActiveNetworkMetered() {
1792         enforceAccessPermission();
1793 
1794         final NetworkCapabilities caps = getNetworkCapabilitiesInternal(getActiveNetwork());
1795         if (caps != null) {
1796             return !caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
1797         } else {
1798             // Always return the most conservative value
1799             return true;
1800         }
1801     }
1802 
1803     private INetworkManagementEventObserver mDataActivityObserver = new BaseNetworkObserver() {
1804         @Override
1805         public void interfaceClassDataActivityChanged(String label, boolean active, long tsNanos) {
1806             int deviceType = Integer.parseInt(label);
1807             sendDataActivityBroadcast(deviceType, active, tsNanos);
1808         }
1809     };
1810 
1811     /**
1812      * Ensures that the system cannot call a particular method.
1813      */
disallowedBecauseSystemCaller()1814     private boolean disallowedBecauseSystemCaller() {
1815         // TODO: start throwing a SecurityException when GnssLocationProvider stops calling
1816         // requestRouteToHost. In Q, GnssLocationProvider is changed to not call requestRouteToHost
1817         // for devices launched with Q and above. However, existing devices upgrading to Q and
1818         // above must continued to be supported for few more releases.
1819         if (isSystem(Binder.getCallingUid()) && SystemProperties.getInt(
1820                 "ro.product.first_api_level", 0) > Build.VERSION_CODES.P) {
1821             log("This method exists only for app backwards compatibility"
1822                     + " and must not be called by system services.");
1823             return true;
1824         }
1825         return false;
1826     }
1827 
1828     /**
1829      * Ensure that a network route exists to deliver traffic to the specified
1830      * host via the specified network interface.
1831      * @param networkType the type of the network over which traffic to the
1832      * specified host is to be routed
1833      * @param hostAddress the IP address of the host to which the route is
1834      * desired
1835      * @return {@code true} on success, {@code false} on failure
1836      */
1837     @Override
requestRouteToHostAddress(int networkType, byte[] hostAddress)1838     public boolean requestRouteToHostAddress(int networkType, byte[] hostAddress) {
1839         if (disallowedBecauseSystemCaller()) {
1840             return false;
1841         }
1842         enforceChangePermission();
1843         if (mProtectedNetworks.contains(networkType)) {
1844             enforceConnectivityRestrictedNetworksPermission();
1845         }
1846 
1847         InetAddress addr;
1848         try {
1849             addr = InetAddress.getByAddress(hostAddress);
1850         } catch (UnknownHostException e) {
1851             if (DBG) log("requestRouteToHostAddress got " + e.toString());
1852             return false;
1853         }
1854 
1855         if (!ConnectivityManager.isNetworkTypeValid(networkType)) {
1856             if (DBG) log("requestRouteToHostAddress on invalid network: " + networkType);
1857             return false;
1858         }
1859 
1860         NetworkAgentInfo nai = mLegacyTypeTracker.getNetworkForType(networkType);
1861         if (nai == null) {
1862             if (mLegacyTypeTracker.isTypeSupported(networkType) == false) {
1863                 if (DBG) log("requestRouteToHostAddress on unsupported network: " + networkType);
1864             } else {
1865                 if (DBG) log("requestRouteToHostAddress on down network: " + networkType);
1866             }
1867             return false;
1868         }
1869 
1870         DetailedState netState;
1871         synchronized (nai) {
1872             netState = nai.networkInfo.getDetailedState();
1873         }
1874 
1875         if (netState != DetailedState.CONNECTED && netState != DetailedState.CAPTIVE_PORTAL_CHECK) {
1876             if (VDBG) {
1877                 log("requestRouteToHostAddress on down network "
1878                         + "(" + networkType + ") - dropped"
1879                         + " netState=" + netState);
1880             }
1881             return false;
1882         }
1883 
1884         final int uid = Binder.getCallingUid();
1885         final long token = Binder.clearCallingIdentity();
1886         try {
1887             LinkProperties lp;
1888             int netId;
1889             synchronized (nai) {
1890                 lp = nai.linkProperties;
1891                 netId = nai.network.netId;
1892             }
1893             boolean ok = addLegacyRouteToHost(lp, addr, netId, uid);
1894             if (DBG) log("requestRouteToHostAddress ok=" + ok);
1895             return ok;
1896         } finally {
1897             Binder.restoreCallingIdentity(token);
1898         }
1899     }
1900 
addLegacyRouteToHost(LinkProperties lp, InetAddress addr, int netId, int uid)1901     private boolean addLegacyRouteToHost(LinkProperties lp, InetAddress addr, int netId, int uid) {
1902         RouteInfo bestRoute = RouteInfo.selectBestRoute(lp.getAllRoutes(), addr);
1903         if (bestRoute == null) {
1904             bestRoute = RouteInfo.makeHostRoute(addr, lp.getInterfaceName());
1905         } else {
1906             String iface = bestRoute.getInterface();
1907             if (bestRoute.getGateway().equals(addr)) {
1908                 // if there is no better route, add the implied hostroute for our gateway
1909                 bestRoute = RouteInfo.makeHostRoute(addr, iface);
1910             } else {
1911                 // if we will connect to this through another route, add a direct route
1912                 // to it's gateway
1913                 bestRoute = RouteInfo.makeHostRoute(addr, bestRoute.getGateway(), iface);
1914             }
1915         }
1916         if (DBG) log("Adding legacy route " + bestRoute +
1917                 " for UID/PID " + uid + "/" + Binder.getCallingPid());
1918         try {
1919             mNMS.addLegacyRouteForNetId(netId, bestRoute, uid);
1920         } catch (Exception e) {
1921             // never crash - catch them all
1922             if (DBG) loge("Exception trying to add a route: " + e);
1923             return false;
1924         }
1925         return true;
1926     }
1927 
1928     @VisibleForTesting
1929     protected final INetdEventCallback mNetdEventCallback = new BaseNetdEventCallback() {
1930         @Override
1931         public void onPrivateDnsValidationEvent(int netId, String ipAddress,
1932                 String hostname, boolean validated) {
1933             try {
1934                 mHandler.sendMessage(mHandler.obtainMessage(
1935                         EVENT_PRIVATE_DNS_VALIDATION_UPDATE,
1936                         new PrivateDnsValidationUpdate(netId,
1937                                 InetAddress.parseNumericAddress(ipAddress),
1938                                 hostname, validated)));
1939             } catch (IllegalArgumentException e) {
1940                 loge("Error parsing ip address in validation event");
1941             }
1942         }
1943 
1944         @Override
1945         public void onDnsEvent(int netId, int eventType, int returnCode, String hostname,
1946                 String[] ipAddresses, int ipAddressesCount, long timestamp, int uid) {
1947             NetworkAgentInfo nai = getNetworkAgentInfoForNetId(netId);
1948             // Netd event only allow registrants from system. Each NetworkMonitor thread is under
1949             // the caller thread of registerNetworkAgent. Thus, it's not allowed to register netd
1950             // event callback for certain nai. e.g. cellular. Register here to pass to
1951             // NetworkMonitor instead.
1952             // TODO: Move the Dns Event to NetworkMonitor. NetdEventListenerService only allow one
1953             // callback from each caller type. Need to re-factor NetdEventListenerService to allow
1954             // multiple NetworkMonitor registrants.
1955             if (nai != null && nai.satisfies(mDefaultRequest)) {
1956                 nai.networkMonitor().notifyDnsResponse(returnCode);
1957             }
1958         }
1959 
1960         @Override
1961         public void onNat64PrefixEvent(int netId, boolean added,
1962                                        String prefixString, int prefixLength) {
1963             mHandler.post(() -> handleNat64PrefixEvent(netId, added, prefixString, prefixLength));
1964         }
1965     };
1966 
registerNetdEventCallback()1967     private void registerNetdEventCallback() {
1968         final IIpConnectivityMetrics ipConnectivityMetrics = mDeps.getIpConnectivityMetrics();
1969         if (ipConnectivityMetrics == null) {
1970             Slog.wtf(TAG, "Missing IIpConnectivityMetrics");
1971             return;
1972         }
1973 
1974         try {
1975             ipConnectivityMetrics.addNetdEventCallback(
1976                     INetdEventCallback.CALLBACK_CALLER_CONNECTIVITY_SERVICE,
1977                     mNetdEventCallback);
1978         } catch (Exception e) {
1979             loge("Error registering netd callback: " + e);
1980         }
1981     }
1982 
1983     private final INetworkPolicyListener mPolicyListener = new NetworkPolicyManager.Listener() {
1984         @Override
1985         public void onUidRulesChanged(int uid, int uidRules) {
1986             mHandler.sendMessage(mHandler.obtainMessage(EVENT_UID_RULES_CHANGED, uid, uidRules));
1987         }
1988         @Override
1989         public void onRestrictBackgroundChanged(boolean restrictBackground) {
1990             // caller is NPMS, since we only register with them
1991             if (LOGD_BLOCKED_NETWORKINFO) {
1992                 log("onRestrictBackgroundChanged(restrictBackground=" + restrictBackground + ")");
1993             }
1994             mHandler.sendMessage(mHandler.obtainMessage(
1995                     EVENT_DATA_SAVER_CHANGED, restrictBackground ? 1 : 0, 0));
1996         }
1997     };
1998 
handleUidRulesChanged(int uid, int newRules)1999     void handleUidRulesChanged(int uid, int newRules) {
2000         // skip update when we've already applied rules
2001         final int oldRules = mUidRules.get(uid, RULE_NONE);
2002         if (oldRules == newRules) return;
2003 
2004         maybeNotifyNetworkBlockedForNewUidRules(uid, newRules);
2005 
2006         if (newRules == RULE_NONE) {
2007             mUidRules.delete(uid);
2008         } else {
2009             mUidRules.put(uid, newRules);
2010         }
2011     }
2012 
handleRestrictBackgroundChanged(boolean restrictBackground)2013     void handleRestrictBackgroundChanged(boolean restrictBackground) {
2014         if (mRestrictBackground == restrictBackground) return;
2015 
2016         for (final NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
2017             final boolean curMetered = nai.networkCapabilities.isMetered();
2018             maybeNotifyNetworkBlocked(nai, curMetered, curMetered, mRestrictBackground,
2019                     restrictBackground);
2020         }
2021 
2022         mRestrictBackground = restrictBackground;
2023     }
2024 
isUidNetworkingWithVpnBlocked(int uid, int uidRules, boolean isNetworkMetered, boolean isBackgroundRestricted)2025     private boolean isUidNetworkingWithVpnBlocked(int uid, int uidRules, boolean isNetworkMetered,
2026             boolean isBackgroundRestricted) {
2027         synchronized (mVpns) {
2028             final Vpn vpn = mVpns.get(UserHandle.getUserId(uid));
2029             // Because the return value of this function depends on the list of UIDs the
2030             // always-on VPN blocks when in lockdown mode, when the always-on VPN changes that
2031             // list all state depending on the return value of this function has to be recomputed.
2032             // TODO: add a trigger when the always-on VPN sets its blocked UIDs to reevaluate and
2033             // send the necessary onBlockedStatusChanged callbacks.
2034             if (vpn != null && vpn.getLockdown() && vpn.isBlockingUid(uid)) {
2035                 return true;
2036             }
2037         }
2038 
2039         return NetworkPolicyManagerInternal.isUidNetworkingBlocked(uid, uidRules,
2040                 isNetworkMetered, isBackgroundRestricted);
2041     }
2042 
2043     /**
2044      * Require that the caller is either in the same user or has appropriate permission to interact
2045      * across users.
2046      *
2047      * @param userId Target user for whatever operation the current IPC is supposed to perform.
2048      */
enforceCrossUserPermission(int userId)2049     private void enforceCrossUserPermission(int userId) {
2050         if (userId == UserHandle.getCallingUserId()) {
2051             // Not a cross-user call.
2052             return;
2053         }
2054         mContext.enforceCallingOrSelfPermission(
2055                 android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
2056                 "ConnectivityService");
2057     }
2058 
checkAnyPermissionOf(String... permissions)2059     private boolean checkAnyPermissionOf(String... permissions) {
2060         for (String permission : permissions) {
2061             if (mContext.checkCallingOrSelfPermission(permission) == PERMISSION_GRANTED) {
2062                 return true;
2063             }
2064         }
2065         return false;
2066     }
2067 
checkAnyPermissionOf(int pid, int uid, String... permissions)2068     private boolean checkAnyPermissionOf(int pid, int uid, String... permissions) {
2069         for (String permission : permissions) {
2070             if (mContext.checkPermission(permission, pid, uid) == PERMISSION_GRANTED) {
2071                 return true;
2072             }
2073         }
2074         return false;
2075     }
2076 
enforceAnyPermissionOf(String... permissions)2077     private void enforceAnyPermissionOf(String... permissions) {
2078         if (!checkAnyPermissionOf(permissions)) {
2079             throw new SecurityException("Requires one of the following permissions: "
2080                     + String.join(", ", permissions) + ".");
2081         }
2082     }
2083 
enforceInternetPermission()2084     private void enforceInternetPermission() {
2085         mContext.enforceCallingOrSelfPermission(
2086                 android.Manifest.permission.INTERNET,
2087                 "ConnectivityService");
2088     }
2089 
enforceAccessPermission()2090     private void enforceAccessPermission() {
2091         mContext.enforceCallingOrSelfPermission(
2092                 android.Manifest.permission.ACCESS_NETWORK_STATE,
2093                 "ConnectivityService");
2094     }
2095 
enforceChangePermission()2096     private void enforceChangePermission() {
2097         ConnectivityManager.enforceChangePermission(mContext);
2098     }
2099 
enforceSettingsPermission()2100     private void enforceSettingsPermission() {
2101         enforceAnyPermissionOf(
2102                 android.Manifest.permission.NETWORK_SETTINGS,
2103                 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK);
2104     }
2105 
enforceNetworkFactoryPermission()2106     private void enforceNetworkFactoryPermission() {
2107         enforceAnyPermissionOf(
2108                 android.Manifest.permission.NETWORK_FACTORY,
2109                 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK);
2110     }
2111 
enforceNetworkFactoryOrSettingsPermission()2112     private void enforceNetworkFactoryOrSettingsPermission() {
2113         enforceAnyPermissionOf(
2114                 android.Manifest.permission.NETWORK_SETTINGS,
2115                 android.Manifest.permission.NETWORK_FACTORY,
2116                 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK);
2117     }
2118 
enforceNetworkFactoryOrTestNetworksPermission()2119     private void enforceNetworkFactoryOrTestNetworksPermission() {
2120         enforceAnyPermissionOf(
2121                 android.Manifest.permission.MANAGE_TEST_NETWORKS,
2122                 android.Manifest.permission.NETWORK_FACTORY,
2123                 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK);
2124     }
2125 
checkSettingsPermission()2126     private boolean checkSettingsPermission() {
2127         return checkAnyPermissionOf(
2128                 android.Manifest.permission.NETWORK_SETTINGS,
2129                 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK);
2130     }
2131 
checkSettingsPermission(int pid, int uid)2132     private boolean checkSettingsPermission(int pid, int uid) {
2133         return PERMISSION_GRANTED == mContext.checkPermission(
2134                 android.Manifest.permission.NETWORK_SETTINGS, pid, uid)
2135                 || PERMISSION_GRANTED == mContext.checkPermission(
2136                 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, pid, uid);
2137     }
2138 
enforceControlAlwaysOnVpnPermission()2139     private void enforceControlAlwaysOnVpnPermission() {
2140         mContext.enforceCallingOrSelfPermission(
2141                 android.Manifest.permission.CONTROL_ALWAYS_ON_VPN,
2142                 "ConnectivityService");
2143     }
2144 
enforceNetworkStackOrSettingsPermission()2145     private void enforceNetworkStackOrSettingsPermission() {
2146         enforceAnyPermissionOf(
2147                 android.Manifest.permission.NETWORK_SETTINGS,
2148                 android.Manifest.permission.NETWORK_STACK,
2149                 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK);
2150     }
2151 
enforceNetworkStackSettingsOrSetup()2152     private void enforceNetworkStackSettingsOrSetup() {
2153         enforceAnyPermissionOf(
2154                 android.Manifest.permission.NETWORK_SETTINGS,
2155                 android.Manifest.permission.NETWORK_SETUP_WIZARD,
2156                 android.Manifest.permission.NETWORK_STACK,
2157                 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK);
2158     }
2159 
enforceAirplaneModePermission()2160     private void enforceAirplaneModePermission() {
2161         enforceAnyPermissionOf(
2162                 android.Manifest.permission.NETWORK_AIRPLANE_MODE,
2163                 android.Manifest.permission.NETWORK_SETTINGS,
2164                 android.Manifest.permission.NETWORK_SETUP_WIZARD,
2165                 android.Manifest.permission.NETWORK_STACK,
2166                 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK);
2167     }
2168 
checkNetworkStackPermission()2169     private boolean checkNetworkStackPermission() {
2170         return checkAnyPermissionOf(
2171                 android.Manifest.permission.NETWORK_STACK,
2172                 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK);
2173     }
2174 
checkNetworkStackPermission(int pid, int uid)2175     private boolean checkNetworkStackPermission(int pid, int uid) {
2176         return checkAnyPermissionOf(pid, uid,
2177                 android.Manifest.permission.NETWORK_STACK,
2178                 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK);
2179     }
2180 
checkNetworkSignalStrengthWakeupPermission(int pid, int uid)2181     private boolean checkNetworkSignalStrengthWakeupPermission(int pid, int uid) {
2182         return checkAnyPermissionOf(pid, uid,
2183                 android.Manifest.permission.NETWORK_SIGNAL_STRENGTH_WAKEUP,
2184                 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
2185                 android.Manifest.permission.NETWORK_SETTINGS);
2186     }
2187 
enforceConnectivityRestrictedNetworksPermission()2188     private void enforceConnectivityRestrictedNetworksPermission() {
2189         try {
2190             mContext.enforceCallingOrSelfPermission(
2191                     android.Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS,
2192                     "ConnectivityService");
2193             return;
2194         } catch (SecurityException e) { /* fallback to ConnectivityInternalPermission */ }
2195         //  TODO: Remove this fallback check after all apps have declared
2196         //   CONNECTIVITY_USE_RESTRICTED_NETWORKS.
2197         mContext.enforceCallingOrSelfPermission(
2198                 android.Manifest.permission.CONNECTIVITY_INTERNAL,
2199                 "ConnectivityService");
2200     }
2201 
enforceKeepalivePermission()2202     private void enforceKeepalivePermission() {
2203         mContext.enforceCallingOrSelfPermission(KeepaliveTracker.PERMISSION, "ConnectivityService");
2204     }
2205 
2206     // Public because it's used by mLockdownTracker.
sendConnectedBroadcast(NetworkInfo info)2207     public void sendConnectedBroadcast(NetworkInfo info) {
2208         NetworkStack.checkNetworkStackPermission(mContext);
2209         sendGeneralBroadcast(info, CONNECTIVITY_ACTION);
2210     }
2211 
sendInetConditionBroadcast(NetworkInfo info)2212     private void sendInetConditionBroadcast(NetworkInfo info) {
2213         sendGeneralBroadcast(info, ConnectivityManager.INET_CONDITION_ACTION);
2214     }
2215 
makeGeneralIntent(NetworkInfo info, String bcastType)2216     private Intent makeGeneralIntent(NetworkInfo info, String bcastType) {
2217         synchronized (mVpns) {
2218             if (mLockdownTracker != null) {
2219                 info = new NetworkInfo(info);
2220                 mLockdownTracker.augmentNetworkInfo(info);
2221             }
2222         }
2223 
2224         Intent intent = new Intent(bcastType);
2225         intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, new NetworkInfo(info));
2226         intent.putExtra(ConnectivityManager.EXTRA_NETWORK_TYPE, info.getType());
2227         if (info.isFailover()) {
2228             intent.putExtra(ConnectivityManager.EXTRA_IS_FAILOVER, true);
2229             info.setFailover(false);
2230         }
2231         if (info.getReason() != null) {
2232             intent.putExtra(ConnectivityManager.EXTRA_REASON, info.getReason());
2233         }
2234         if (info.getExtraInfo() != null) {
2235             intent.putExtra(ConnectivityManager.EXTRA_EXTRA_INFO,
2236                     info.getExtraInfo());
2237         }
2238         intent.putExtra(ConnectivityManager.EXTRA_INET_CONDITION, mDefaultInetConditionPublished);
2239         return intent;
2240     }
2241 
sendGeneralBroadcast(NetworkInfo info, String bcastType)2242     private void sendGeneralBroadcast(NetworkInfo info, String bcastType) {
2243         sendStickyBroadcast(makeGeneralIntent(info, bcastType));
2244     }
2245 
sendDataActivityBroadcast(int deviceType, boolean active, long tsNanos)2246     private void sendDataActivityBroadcast(int deviceType, boolean active, long tsNanos) {
2247         Intent intent = new Intent(ConnectivityManager.ACTION_DATA_ACTIVITY_CHANGE);
2248         intent.putExtra(ConnectivityManager.EXTRA_DEVICE_TYPE, deviceType);
2249         intent.putExtra(ConnectivityManager.EXTRA_IS_ACTIVE, active);
2250         intent.putExtra(ConnectivityManager.EXTRA_REALTIME_NS, tsNanos);
2251         final long ident = Binder.clearCallingIdentity();
2252         try {
2253             mContext.sendOrderedBroadcastAsUser(intent, UserHandle.ALL,
2254                     RECEIVE_DATA_ACTIVITY_CHANGE, null, null, 0, null, null);
2255         } finally {
2256             Binder.restoreCallingIdentity(ident);
2257         }
2258     }
2259 
sendStickyBroadcast(Intent intent)2260     private void sendStickyBroadcast(Intent intent) {
2261         synchronized (this) {
2262             if (!mSystemReady
2263                     && intent.getAction().equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
2264                 mInitialBroadcast = new Intent(intent);
2265             }
2266             intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
2267             if (VDBG) {
2268                 log("sendStickyBroadcast: action=" + intent.getAction());
2269             }
2270 
2271             Bundle options = null;
2272             final long ident = Binder.clearCallingIdentity();
2273             if (ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction())) {
2274                 final NetworkInfo ni = intent.getParcelableExtra(
2275                         ConnectivityManager.EXTRA_NETWORK_INFO);
2276                 final BroadcastOptions opts = BroadcastOptions.makeBasic();
2277                 opts.setMaxManifestReceiverApiLevel(Build.VERSION_CODES.M);
2278                 options = opts.toBundle();
2279                 final IBatteryStats bs = mDeps.getBatteryStatsService();
2280                 try {
2281                     bs.noteConnectivityChanged(intent.getIntExtra(
2282                             ConnectivityManager.EXTRA_NETWORK_TYPE, ConnectivityManager.TYPE_NONE),
2283                             ni.getState().toString());
2284                 } catch (RemoteException e) {
2285                 }
2286                 intent.addFlags(Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS);
2287             }
2288             try {
2289                 mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL, options);
2290             } finally {
2291                 Binder.restoreCallingIdentity(ident);
2292             }
2293         }
2294     }
2295 
2296     /**
2297      * Called when the system is ready and ConnectivityService can initialize remaining components.
2298      */
2299     @VisibleForTesting
systemReady()2300     public void systemReady() {
2301         // Let PermissionMonitor#startMonitoring() running in the beginning of the systemReady
2302         // before MultipathPolicyTracker.start(). Since mApps in PermissionMonitor needs to be
2303         // populated first to ensure that listening network request which is sent by
2304         // MultipathPolicyTracker won't be added NET_CAPABILITY_FOREGROUND capability.
2305         mPermissionMonitor.startMonitoring();
2306         mProxyTracker.loadGlobalProxy();
2307         registerNetdEventCallback();
2308 
2309         synchronized (this) {
2310             mSystemReady = true;
2311             if (mInitialBroadcast != null) {
2312                 mContext.sendStickyBroadcastAsUser(mInitialBroadcast, UserHandle.ALL);
2313                 mInitialBroadcast = null;
2314             }
2315         }
2316 
2317         // Try bringing up tracker, but KeyStore won't be ready yet for secondary users so wait
2318         // for user to unlock device too.
2319         updateLockdownVpn();
2320 
2321         // Create network requests for always-on networks.
2322         mHandler.sendMessage(mHandler.obtainMessage(EVENT_CONFIGURE_ALWAYS_ON_NETWORKS));
2323 
2324         mHandler.sendMessage(mHandler.obtainMessage(EVENT_SYSTEM_READY));
2325     }
2326 
2327     /**
2328      * Setup data activity tracking for the given network.
2329      *
2330      * Every {@code setupDataActivityTracking} should be paired with a
2331      * {@link #removeDataActivityTracking} for cleanup.
2332      */
setupDataActivityTracking(NetworkAgentInfo networkAgent)2333     private void setupDataActivityTracking(NetworkAgentInfo networkAgent) {
2334         final String iface = networkAgent.linkProperties.getInterfaceName();
2335 
2336         final int timeout;
2337         final int type;
2338 
2339         if (networkAgent.networkCapabilities.hasTransport(
2340                 NetworkCapabilities.TRANSPORT_CELLULAR)) {
2341             timeout = Settings.Global.getInt(mContext.getContentResolver(),
2342                                              Settings.Global.DATA_ACTIVITY_TIMEOUT_MOBILE,
2343                                              10);
2344             type = ConnectivityManager.TYPE_MOBILE;
2345         } else if (networkAgent.networkCapabilities.hasTransport(
2346                 NetworkCapabilities.TRANSPORT_WIFI)) {
2347             timeout = Settings.Global.getInt(mContext.getContentResolver(),
2348                                              Settings.Global.DATA_ACTIVITY_TIMEOUT_WIFI,
2349                                              15);
2350             type = ConnectivityManager.TYPE_WIFI;
2351         } else {
2352             return; // do not track any other networks
2353         }
2354 
2355         if (timeout > 0 && iface != null) {
2356             try {
2357                 mNMS.addIdleTimer(iface, timeout, type);
2358             } catch (Exception e) {
2359                 // You shall not crash!
2360                 loge("Exception in setupDataActivityTracking " + e);
2361             }
2362         }
2363     }
2364 
2365     /**
2366      * Remove data activity tracking when network disconnects.
2367      */
removeDataActivityTracking(NetworkAgentInfo networkAgent)2368     private void removeDataActivityTracking(NetworkAgentInfo networkAgent) {
2369         final String iface = networkAgent.linkProperties.getInterfaceName();
2370         final NetworkCapabilities caps = networkAgent.networkCapabilities;
2371 
2372         if (iface != null && (caps.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) ||
2373                               caps.hasTransport(NetworkCapabilities.TRANSPORT_WIFI))) {
2374             try {
2375                 // the call fails silently if no idle timer setup for this interface
2376                 mNMS.removeIdleTimer(iface);
2377             } catch (Exception e) {
2378                 loge("Exception in removeDataActivityTracking " + e);
2379             }
2380         }
2381     }
2382 
2383     /**
2384      * Update data activity tracking when network state is updated.
2385      */
updateDataActivityTracking(NetworkAgentInfo newNetwork, NetworkAgentInfo oldNetwork)2386     private void updateDataActivityTracking(NetworkAgentInfo newNetwork,
2387             NetworkAgentInfo oldNetwork) {
2388         if (newNetwork != null) {
2389             setupDataActivityTracking(newNetwork);
2390         }
2391         if (oldNetwork != null) {
2392             removeDataActivityTracking(oldNetwork);
2393         }
2394     }
2395     /**
2396      * Reads the network specific MTU size from resources.
2397      * and set it on it's iface.
2398      */
updateMtu(LinkProperties newLp, LinkProperties oldLp)2399     private void updateMtu(LinkProperties newLp, LinkProperties oldLp) {
2400         final String iface = newLp.getInterfaceName();
2401         final int mtu = newLp.getMtu();
2402         if (oldLp == null && mtu == 0) {
2403             // Silently ignore unset MTU value.
2404             return;
2405         }
2406         if (oldLp != null && newLp.isIdenticalMtu(oldLp)) {
2407             if (VDBG) log("identical MTU - not setting");
2408             return;
2409         }
2410         if (!LinkProperties.isValidMtu(mtu, newLp.hasGlobalIpv6Address())) {
2411             if (mtu != 0) loge("Unexpected mtu value: " + mtu + ", " + iface);
2412             return;
2413         }
2414 
2415         // Cannot set MTU without interface name
2416         if (TextUtils.isEmpty(iface)) {
2417             loge("Setting MTU size with null iface.");
2418             return;
2419         }
2420 
2421         try {
2422             if (VDBG || DDBG) log("Setting MTU size: " + iface + ", " + mtu);
2423             mNMS.setMtu(iface, mtu);
2424         } catch (Exception e) {
2425             Slog.e(TAG, "exception in setMtu()" + e);
2426         }
2427     }
2428 
2429     @VisibleForTesting
2430     protected static final String DEFAULT_TCP_BUFFER_SIZES = "4096,87380,110208,4096,16384,110208";
2431 
updateTcpBufferSizes(String tcpBufferSizes)2432     private void updateTcpBufferSizes(String tcpBufferSizes) {
2433         String[] values = null;
2434         if (tcpBufferSizes != null) {
2435             values = tcpBufferSizes.split(",");
2436         }
2437 
2438         if (values == null || values.length != 6) {
2439             if (DBG) log("Invalid tcpBufferSizes string: " + tcpBufferSizes +", using defaults");
2440             tcpBufferSizes = DEFAULT_TCP_BUFFER_SIZES;
2441             values = tcpBufferSizes.split(",");
2442         }
2443 
2444         if (tcpBufferSizes.equals(mCurrentTcpBufferSizes)) return;
2445 
2446         try {
2447             if (VDBG || DDBG) Slog.d(TAG, "Setting tx/rx TCP buffers to " + tcpBufferSizes);
2448 
2449             String rmemValues = String.join(" ", values[0], values[1], values[2]);
2450             String wmemValues = String.join(" ", values[3], values[4], values[5]);
2451             mNetd.setTcpRWmemorySize(rmemValues, wmemValues);
2452             mCurrentTcpBufferSizes = tcpBufferSizes;
2453         } catch (RemoteException | ServiceSpecificException e) {
2454             loge("Can't set TCP buffer sizes:" + e);
2455         }
2456 
2457         Integer rwndValue = Settings.Global.getInt(mContext.getContentResolver(),
2458             Settings.Global.TCP_DEFAULT_INIT_RWND,
2459                     mSystemProperties.getInt("net.tcp.default_init_rwnd", 0));
2460         final String sysctlKey = "sys.sysctl.tcp_def_init_rwnd";
2461         if (rwndValue != 0) {
2462             mSystemProperties.set(sysctlKey, rwndValue.toString());
2463         }
2464     }
2465 
2466     @Override
getRestoreDefaultNetworkDelay(int networkType)2467     public int getRestoreDefaultNetworkDelay(int networkType) {
2468         String restoreDefaultNetworkDelayStr = mSystemProperties.get(
2469                 NETWORK_RESTORE_DELAY_PROP_NAME);
2470         if(restoreDefaultNetworkDelayStr != null &&
2471                 restoreDefaultNetworkDelayStr.length() != 0) {
2472             try {
2473                 return Integer.parseInt(restoreDefaultNetworkDelayStr);
2474             } catch (NumberFormatException e) {
2475             }
2476         }
2477         // if the system property isn't set, use the value for the apn type
2478         int ret = RESTORE_DEFAULT_NETWORK_DELAY;
2479 
2480         if ((networkType <= ConnectivityManager.MAX_NETWORK_TYPE) &&
2481                 (mNetConfigs[networkType] != null)) {
2482             ret = mNetConfigs[networkType].restoreTime;
2483         }
2484         return ret;
2485     }
2486 
dumpNetworkDiagnostics(IndentingPrintWriter pw)2487     private void dumpNetworkDiagnostics(IndentingPrintWriter pw) {
2488         final List<NetworkDiagnostics> netDiags = new ArrayList<NetworkDiagnostics>();
2489         final long DIAG_TIME_MS = 5000;
2490         for (NetworkAgentInfo nai : networksSortedById()) {
2491             PrivateDnsConfig privateDnsCfg = mDnsManager.getPrivateDnsConfig(nai.network);
2492             // Start gathering diagnostic information.
2493             netDiags.add(new NetworkDiagnostics(
2494                     nai.network,
2495                     new LinkProperties(nai.linkProperties),  // Must be a copy.
2496                     privateDnsCfg,
2497                     DIAG_TIME_MS));
2498         }
2499 
2500         for (NetworkDiagnostics netDiag : netDiags) {
2501             pw.println();
2502             netDiag.waitForMeasurements();
2503             netDiag.dump(pw);
2504         }
2505     }
2506 
2507     @Override
dump(@onNull FileDescriptor fd, @NonNull PrintWriter writer, @Nullable String[] args)2508     protected void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter writer,
2509             @Nullable String[] args) {
2510         PriorityDump.dump(mPriorityDumper, fd, writer, args);
2511     }
2512 
doDump(FileDescriptor fd, PrintWriter writer, String[] args, boolean asProto)2513     private void doDump(FileDescriptor fd, PrintWriter writer, String[] args, boolean asProto) {
2514         final IndentingPrintWriter pw = new IndentingPrintWriter(writer, "  ");
2515         if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
2516         if (asProto) return;
2517 
2518         if (ArrayUtils.contains(args, DIAG_ARG)) {
2519             dumpNetworkDiagnostics(pw);
2520             return;
2521         } else if (ArrayUtils.contains(args, NETWORK_ARG)) {
2522             dumpNetworks(pw);
2523             return;
2524         } else if (ArrayUtils.contains(args, REQUEST_ARG)) {
2525             dumpNetworkRequests(pw);
2526             return;
2527         }
2528 
2529         pw.print("NetworkProviders for:");
2530         for (NetworkProviderInfo npi : mNetworkProviderInfos.values()) {
2531             pw.print(" " + npi.name);
2532         }
2533         pw.println();
2534         pw.println();
2535 
2536         final NetworkAgentInfo defaultNai = getDefaultNetwork();
2537         pw.print("Active default network: ");
2538         if (defaultNai == null) {
2539             pw.println("none");
2540         } else {
2541             pw.println(defaultNai.network.netId);
2542         }
2543         pw.println();
2544 
2545         pw.println("Current Networks:");
2546         pw.increaseIndent();
2547         dumpNetworks(pw);
2548         pw.decreaseIndent();
2549         pw.println();
2550 
2551         pw.print("Restrict background: ");
2552         pw.println(mRestrictBackground);
2553         pw.println();
2554 
2555         pw.println("Status for known UIDs:");
2556         pw.increaseIndent();
2557         final int size = mUidRules.size();
2558         for (int i = 0; i < size; i++) {
2559             // Don't crash if the array is modified while dumping in bugreports.
2560             try {
2561                 final int uid = mUidRules.keyAt(i);
2562                 final int uidRules = mUidRules.get(uid, RULE_NONE);
2563                 pw.println("UID=" + uid + " rules=" + uidRulesToString(uidRules));
2564             } catch (ArrayIndexOutOfBoundsException e) {
2565                 pw.println("  ArrayIndexOutOfBoundsException");
2566             } catch (ConcurrentModificationException e) {
2567                 pw.println("  ConcurrentModificationException");
2568             }
2569         }
2570         pw.println();
2571         pw.decreaseIndent();
2572 
2573         pw.println("Network Requests:");
2574         pw.increaseIndent();
2575         dumpNetworkRequests(pw);
2576         pw.decreaseIndent();
2577         pw.println();
2578 
2579         mLegacyTypeTracker.dump(pw);
2580 
2581         pw.println();
2582         mKeepaliveTracker.dump(pw);
2583 
2584         pw.println();
2585         dumpAvoidBadWifiSettings(pw);
2586 
2587         pw.println();
2588         mMultipathPolicyTracker.dump(pw);
2589 
2590         if (ArrayUtils.contains(args, SHORT_ARG) == false) {
2591             pw.println();
2592             pw.println("mNetworkRequestInfoLogs (most recent first):");
2593             pw.increaseIndent();
2594             mNetworkRequestInfoLogs.reverseDump(fd, pw, args);
2595             pw.decreaseIndent();
2596 
2597             pw.println();
2598             pw.println("mNetworkInfoBlockingLogs (most recent first):");
2599             pw.increaseIndent();
2600             mNetworkInfoBlockingLogs.reverseDump(fd, pw, args);
2601             pw.decreaseIndent();
2602 
2603             pw.println();
2604             pw.println("NetTransition WakeLock activity (most recent first):");
2605             pw.increaseIndent();
2606             pw.println("total acquisitions: " + mTotalWakelockAcquisitions);
2607             pw.println("total releases: " + mTotalWakelockReleases);
2608             pw.println("cumulative duration: " + (mTotalWakelockDurationMs / 1000) + "s");
2609             pw.println("longest duration: " + (mMaxWakelockDurationMs / 1000) + "s");
2610             if (mTotalWakelockAcquisitions > mTotalWakelockReleases) {
2611                 long duration = SystemClock.elapsedRealtime() - mLastWakeLockAcquireTimestamp;
2612                 pw.println("currently holding WakeLock for: " + (duration / 1000) + "s");
2613             }
2614             mWakelockLogs.reverseDump(fd, pw, args);
2615 
2616             pw.println();
2617             pw.println("bandwidth update requests (by uid):");
2618             pw.increaseIndent();
2619             synchronized (mBandwidthRequests) {
2620                 for (int i = 0; i < mBandwidthRequests.size(); i++) {
2621                     pw.println("[" + mBandwidthRequests.keyAt(i)
2622                             + "]: " + mBandwidthRequests.valueAt(i));
2623                 }
2624             }
2625             pw.decreaseIndent();
2626 
2627             pw.decreaseIndent();
2628         }
2629 
2630         pw.println();
2631         pw.println("NetworkStackClient logs:");
2632         pw.increaseIndent();
2633         NetworkStackClient.getInstance().dump(pw);
2634         pw.decreaseIndent();
2635 
2636         pw.println();
2637         pw.println("Permission Monitor:");
2638         pw.increaseIndent();
2639         mPermissionMonitor.dump(pw);
2640         pw.decreaseIndent();
2641     }
2642 
dumpNetworks(IndentingPrintWriter pw)2643     private void dumpNetworks(IndentingPrintWriter pw) {
2644         for (NetworkAgentInfo nai : networksSortedById()) {
2645             pw.println(nai.toString());
2646             pw.increaseIndent();
2647             pw.println(String.format(
2648                     "Requests: REQUEST:%d LISTEN:%d BACKGROUND_REQUEST:%d total:%d",
2649                     nai.numForegroundNetworkRequests(),
2650                     nai.numNetworkRequests() - nai.numRequestNetworkRequests(),
2651                     nai.numBackgroundNetworkRequests(),
2652                     nai.numNetworkRequests()));
2653             pw.increaseIndent();
2654             for (int i = 0; i < nai.numNetworkRequests(); i++) {
2655                 pw.println(nai.requestAt(i).toString());
2656             }
2657             pw.decreaseIndent();
2658             pw.println("Lingered:");
2659             pw.increaseIndent();
2660             nai.dumpLingerTimers(pw);
2661             pw.decreaseIndent();
2662             pw.decreaseIndent();
2663         }
2664     }
2665 
dumpNetworkRequests(IndentingPrintWriter pw)2666     private void dumpNetworkRequests(IndentingPrintWriter pw) {
2667         for (NetworkRequestInfo nri : requestsSortedById()) {
2668             pw.println(nri.toString());
2669         }
2670     }
2671 
2672     /**
2673      * Return an array of all current NetworkAgentInfos sorted by network id.
2674      */
networksSortedById()2675     private NetworkAgentInfo[] networksSortedById() {
2676         NetworkAgentInfo[] networks = new NetworkAgentInfo[0];
2677         networks = mNetworkAgentInfos.values().toArray(networks);
2678         Arrays.sort(networks, Comparator.comparingInt(nai -> nai.network.netId));
2679         return networks;
2680     }
2681 
2682     /**
2683      * Return an array of all current NetworkRequest sorted by request id.
2684      */
requestsSortedById()2685     private NetworkRequestInfo[] requestsSortedById() {
2686         NetworkRequestInfo[] requests = new NetworkRequestInfo[0];
2687         requests = mNetworkRequests.values().toArray(requests);
2688         Arrays.sort(requests, Comparator.comparingInt(nri -> nri.request.requestId));
2689         return requests;
2690     }
2691 
isLiveNetworkAgent(NetworkAgentInfo nai, int what)2692     private boolean isLiveNetworkAgent(NetworkAgentInfo nai, int what) {
2693         if (nai.network == null) return false;
2694         final NetworkAgentInfo officialNai = getNetworkAgentInfoForNetwork(nai.network);
2695         if (officialNai != null && officialNai.equals(nai)) return true;
2696         if (officialNai != null || VDBG) {
2697             loge(eventName(what) + " - isLiveNetworkAgent found mismatched netId: " + officialNai +
2698                 " - " + nai);
2699         }
2700         return false;
2701     }
2702 
2703     // must be stateless - things change under us.
2704     private class NetworkStateTrackerHandler extends Handler {
NetworkStateTrackerHandler(Looper looper)2705         public NetworkStateTrackerHandler(Looper looper) {
2706             super(looper);
2707         }
2708 
maybeHandleAsyncChannelMessage(Message msg)2709         private boolean maybeHandleAsyncChannelMessage(Message msg) {
2710             switch (msg.what) {
2711                 default:
2712                     return false;
2713                 case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: {
2714                     handleAsyncChannelHalfConnect(msg);
2715                     break;
2716                 }
2717                 case AsyncChannel.CMD_CHANNEL_DISCONNECT: {
2718                     NetworkAgentInfo nai = mNetworkAgentInfos.get(msg.replyTo);
2719                     if (nai != null) nai.asyncChannel.disconnect();
2720                     break;
2721                 }
2722                 case AsyncChannel.CMD_CHANNEL_DISCONNECTED: {
2723                     handleAsyncChannelDisconnected(msg);
2724                     break;
2725                 }
2726             }
2727             return true;
2728         }
2729 
maybeHandleNetworkAgentMessage(Message msg)2730         private void maybeHandleNetworkAgentMessage(Message msg) {
2731             NetworkAgentInfo nai = mNetworkAgentInfos.get(msg.replyTo);
2732             if (nai == null) {
2733                 if (VDBG) {
2734                     log(String.format("%s from unknown NetworkAgent", eventName(msg.what)));
2735                 }
2736                 return;
2737             }
2738 
2739             switch (msg.what) {
2740                 case NetworkAgent.EVENT_NETWORK_CAPABILITIES_CHANGED: {
2741                     NetworkCapabilities networkCapabilities = (NetworkCapabilities) msg.obj;
2742                     if (networkCapabilities.hasConnectivityManagedCapability()) {
2743                         Slog.wtf(TAG, "BUG: " + nai + " has CS-managed capability.");
2744                     }
2745                     if (networkCapabilities.hasTransport(TRANSPORT_TEST)) {
2746                         // Make sure the original object is not mutated. NetworkAgent normally
2747                         // makes a copy of the capabilities when sending the message through
2748                         // the Messenger, but if this ever changes, not making a defensive copy
2749                         // here will give attack vectors to clients using this code path.
2750                         networkCapabilities = new NetworkCapabilities(networkCapabilities);
2751                         networkCapabilities.restrictCapabilitesForTestNetwork(nai.creatorUid);
2752                     }
2753                     updateCapabilities(nai.getCurrentScore(), nai, networkCapabilities);
2754                     break;
2755                 }
2756                 case NetworkAgent.EVENT_NETWORK_PROPERTIES_CHANGED: {
2757                     LinkProperties newLp = (LinkProperties) msg.obj;
2758                     processLinkPropertiesFromAgent(nai, newLp);
2759                     handleUpdateLinkProperties(nai, newLp);
2760                     break;
2761                 }
2762                 case NetworkAgent.EVENT_NETWORK_INFO_CHANGED: {
2763                     NetworkInfo info = (NetworkInfo) msg.obj;
2764                     updateNetworkInfo(nai, info);
2765                     break;
2766                 }
2767                 case NetworkAgent.EVENT_NETWORK_SCORE_CHANGED: {
2768                     updateNetworkScore(nai, msg.arg1);
2769                     break;
2770                 }
2771                 case NetworkAgent.EVENT_SET_EXPLICITLY_SELECTED: {
2772                     if (nai.everConnected) {
2773                         loge("ERROR: cannot call explicitlySelected on already-connected network");
2774                     }
2775                     nai.networkAgentConfig.explicitlySelected = toBool(msg.arg1);
2776                     nai.networkAgentConfig.acceptUnvalidated = toBool(msg.arg1) && toBool(msg.arg2);
2777                     // Mark the network as temporarily accepting partial connectivity so that it
2778                     // will be validated (and possibly become default) even if it only provides
2779                     // partial internet access. Note that if user connects to partial connectivity
2780                     // and choose "don't ask again", then wifi disconnected by some reasons(maybe
2781                     // out of wifi coverage) and if the same wifi is available again, the device
2782                     // will auto connect to this wifi even though the wifi has "no internet".
2783                     // TODO: Evaluate using a separate setting in IpMemoryStore.
2784                     nai.networkAgentConfig.acceptPartialConnectivity = toBool(msg.arg2);
2785                     break;
2786                 }
2787                 case NetworkAgent.EVENT_SOCKET_KEEPALIVE: {
2788                     mKeepaliveTracker.handleEventSocketKeepalive(nai, msg);
2789                     break;
2790                 }
2791             }
2792         }
2793 
maybeHandleNetworkMonitorMessage(Message msg)2794         private boolean maybeHandleNetworkMonitorMessage(Message msg) {
2795             switch (msg.what) {
2796                 default:
2797                     return false;
2798                 case EVENT_PROBE_STATUS_CHANGED: {
2799                     final Integer netId = (Integer) msg.obj;
2800                     final NetworkAgentInfo nai = getNetworkAgentInfoForNetId(netId);
2801                     if (nai == null) {
2802                         break;
2803                     }
2804                     final boolean probePrivateDnsCompleted =
2805                             ((msg.arg1 & NETWORK_VALIDATION_PROBE_PRIVDNS) != 0);
2806                     final boolean privateDnsBroken =
2807                             ((msg.arg2 & NETWORK_VALIDATION_PROBE_PRIVDNS) == 0);
2808                     if (probePrivateDnsCompleted) {
2809                         if (nai.networkCapabilities.isPrivateDnsBroken() != privateDnsBroken) {
2810                             nai.networkCapabilities.setPrivateDnsBroken(privateDnsBroken);
2811                             final int oldScore = nai.getCurrentScore();
2812                             updateCapabilities(oldScore, nai, nai.networkCapabilities);
2813                         }
2814                         // Only show the notification when the private DNS is broken and the
2815                         // PRIVATE_DNS_BROKEN notification hasn't shown since last valid.
2816                         if (privateDnsBroken && !nai.networkAgentConfig.hasShownBroken) {
2817                             showNetworkNotification(nai, NotificationType.PRIVATE_DNS_BROKEN);
2818                         }
2819                         nai.networkAgentConfig.hasShownBroken = privateDnsBroken;
2820                     } else if (nai.networkCapabilities.isPrivateDnsBroken()) {
2821                         // If probePrivateDnsCompleted is false but nai.networkCapabilities says
2822                         // private DNS is broken, it means this network is being reevaluated.
2823                         // Either probing private DNS is not necessary any more or it hasn't been
2824                         // done yet. In either case, the networkCapabilities should be updated to
2825                         // reflect the new status.
2826                         nai.networkCapabilities.setPrivateDnsBroken(false);
2827                         final int oldScore = nai.getCurrentScore();
2828                         updateCapabilities(oldScore, nai, nai.networkCapabilities);
2829                         nai.networkAgentConfig.hasShownBroken = false;
2830                     }
2831                     break;
2832                 }
2833                 case EVENT_NETWORK_TESTED: {
2834                     final NetworkTestedResults results = (NetworkTestedResults) msg.obj;
2835 
2836                     final NetworkAgentInfo nai = getNetworkAgentInfoForNetId(results.mNetId);
2837                     if (nai == null) break;
2838 
2839                     handleNetworkTested(nai, results.mTestResult,
2840                             (results.mRedirectUrl == null) ? "" : results.mRedirectUrl);
2841                     break;
2842                 }
2843                 case EVENT_PROVISIONING_NOTIFICATION: {
2844                     final int netId = msg.arg2;
2845                     final boolean visible = toBool(msg.arg1);
2846                     final NetworkAgentInfo nai = getNetworkAgentInfoForNetId(netId);
2847                     // If captive portal status has changed, update capabilities or disconnect.
2848                     if (nai != null && (visible != nai.lastCaptivePortalDetected)) {
2849                         final int oldScore = nai.getCurrentScore();
2850                         nai.lastCaptivePortalDetected = visible;
2851                         nai.everCaptivePortalDetected |= visible;
2852                         if (nai.lastCaptivePortalDetected &&
2853                             Settings.Global.CAPTIVE_PORTAL_MODE_AVOID == getCaptivePortalMode()) {
2854                             if (DBG) log("Avoiding captive portal network: " + nai.toShortString());
2855                             nai.asyncChannel.sendMessage(
2856                                     NetworkAgent.CMD_PREVENT_AUTOMATIC_RECONNECT);
2857                             teardownUnneededNetwork(nai);
2858                             break;
2859                         }
2860                         updateCapabilities(oldScore, nai, nai.networkCapabilities);
2861                     }
2862                     if (!visible) {
2863                         // Only clear SIGN_IN and NETWORK_SWITCH notifications here, or else other
2864                         // notifications belong to the same network may be cleared unexpectedly.
2865                         mNotifier.clearNotification(netId, NotificationType.SIGN_IN);
2866                         mNotifier.clearNotification(netId, NotificationType.NETWORK_SWITCH);
2867                     } else {
2868                         if (nai == null) {
2869                             loge("EVENT_PROVISIONING_NOTIFICATION from unknown NetworkMonitor");
2870                             break;
2871                         }
2872                         if (!nai.networkAgentConfig.provisioningNotificationDisabled) {
2873                             mNotifier.showNotification(netId, NotificationType.SIGN_IN, nai, null,
2874                                     (PendingIntent) msg.obj,
2875                                     nai.networkAgentConfig.explicitlySelected);
2876                         }
2877                     }
2878                     break;
2879                 }
2880                 case EVENT_PRIVATE_DNS_CONFIG_RESOLVED: {
2881                     final NetworkAgentInfo nai = getNetworkAgentInfoForNetId(msg.arg2);
2882                     if (nai == null) break;
2883 
2884                     updatePrivateDns(nai, (PrivateDnsConfig) msg.obj);
2885                     break;
2886                 }
2887                 case EVENT_CAPPORT_DATA_CHANGED: {
2888                     final NetworkAgentInfo nai = getNetworkAgentInfoForNetId(msg.arg2);
2889                     if (nai == null) break;
2890                     handleCaptivePortalDataUpdate(nai, (CaptivePortalData) msg.obj);
2891                     break;
2892                 }
2893             }
2894             return true;
2895         }
2896 
handleNetworkTested( @onNull NetworkAgentInfo nai, int testResult, @NonNull String redirectUrl)2897         private void handleNetworkTested(
2898                 @NonNull NetworkAgentInfo nai, int testResult, @NonNull String redirectUrl) {
2899             final boolean wasPartial = nai.partialConnectivity;
2900             nai.partialConnectivity = ((testResult & NETWORK_VALIDATION_RESULT_PARTIAL) != 0);
2901             final boolean partialConnectivityChanged =
2902                     (wasPartial != nai.partialConnectivity);
2903 
2904             final boolean valid = ((testResult & NETWORK_VALIDATION_RESULT_VALID) != 0);
2905             final boolean wasValidated = nai.lastValidated;
2906             final boolean wasDefault = isDefaultNetwork(nai);
2907 
2908             if (DBG) {
2909                 final String logMsg = !TextUtils.isEmpty(redirectUrl)
2910                         ? " with redirect to " + redirectUrl
2911                         : "";
2912                 log(nai.toShortString() + " validation " + (valid ? "passed" : "failed") + logMsg);
2913             }
2914             if (valid != nai.lastValidated) {
2915                 if (wasDefault) {
2916                     mDeps.getMetricsLogger()
2917                             .defaultNetworkMetrics().logDefaultNetworkValidity(
2918                             SystemClock.elapsedRealtime(), valid);
2919                 }
2920                 final int oldScore = nai.getCurrentScore();
2921                 nai.lastValidated = valid;
2922                 nai.everValidated |= valid;
2923                 updateCapabilities(oldScore, nai, nai.networkCapabilities);
2924                 // If score has changed, rebroadcast to NetworkProviders. b/17726566
2925                 if (oldScore != nai.getCurrentScore()) sendUpdatedScoreToFactories(nai);
2926                 if (valid) {
2927                     handleFreshlyValidatedNetwork(nai);
2928                     // Clear NO_INTERNET, PRIVATE_DNS_BROKEN, PARTIAL_CONNECTIVITY and
2929                     // LOST_INTERNET notifications if network becomes valid.
2930                     mNotifier.clearNotification(nai.network.netId,
2931                             NotificationType.NO_INTERNET);
2932                     mNotifier.clearNotification(nai.network.netId,
2933                             NotificationType.LOST_INTERNET);
2934                     mNotifier.clearNotification(nai.network.netId,
2935                             NotificationType.PARTIAL_CONNECTIVITY);
2936                     mNotifier.clearNotification(nai.network.netId,
2937                             NotificationType.PRIVATE_DNS_BROKEN);
2938                     // If network becomes valid, the hasShownBroken should be reset for
2939                     // that network so that the notification will be fired when the private
2940                     // DNS is broken again.
2941                     nai.networkAgentConfig.hasShownBroken = false;
2942                 }
2943             } else if (partialConnectivityChanged) {
2944                 updateCapabilities(nai.getCurrentScore(), nai, nai.networkCapabilities);
2945             }
2946             updateInetCondition(nai);
2947             // Let the NetworkAgent know the state of its network
2948             Bundle redirectUrlBundle = new Bundle();
2949             redirectUrlBundle.putString(NetworkAgent.REDIRECT_URL_KEY, redirectUrl);
2950             // TODO: Evaluate to update partial connectivity to status to NetworkAgent.
2951             nai.asyncChannel.sendMessage(
2952                     NetworkAgent.CMD_REPORT_NETWORK_STATUS,
2953                     (valid ? NetworkAgent.VALID_NETWORK : NetworkAgent.INVALID_NETWORK),
2954                     0, redirectUrlBundle);
2955 
2956             // If NetworkMonitor detects partial connectivity before
2957             // EVENT_PROMPT_UNVALIDATED arrives, show the partial connectivity notification
2958             // immediately. Re-notify partial connectivity silently if no internet
2959             // notification already there.
2960             if (!wasPartial && nai.partialConnectivity) {
2961                 // Remove delayed message if there is a pending message.
2962                 mHandler.removeMessages(EVENT_PROMPT_UNVALIDATED, nai.network);
2963                 handlePromptUnvalidated(nai.network);
2964             }
2965 
2966             if (wasValidated && !nai.lastValidated) {
2967                 handleNetworkUnvalidated(nai);
2968             }
2969         }
2970 
getCaptivePortalMode()2971         private int getCaptivePortalMode() {
2972             return Settings.Global.getInt(mContext.getContentResolver(),
2973                     Settings.Global.CAPTIVE_PORTAL_MODE,
2974                     Settings.Global.CAPTIVE_PORTAL_MODE_PROMPT);
2975         }
2976 
maybeHandleNetworkAgentInfoMessage(Message msg)2977         private boolean maybeHandleNetworkAgentInfoMessage(Message msg) {
2978             switch (msg.what) {
2979                 default:
2980                     return false;
2981                 case NetworkAgentInfo.EVENT_NETWORK_LINGER_COMPLETE: {
2982                     NetworkAgentInfo nai = (NetworkAgentInfo) msg.obj;
2983                     if (nai != null && isLiveNetworkAgent(nai, msg.what)) {
2984                         handleLingerComplete(nai);
2985                     }
2986                     break;
2987                 }
2988             }
2989             return true;
2990         }
2991 
2992         @Override
handleMessage(Message msg)2993         public void handleMessage(Message msg) {
2994             if (!maybeHandleAsyncChannelMessage(msg)
2995                     && !maybeHandleNetworkMonitorMessage(msg)
2996                     && !maybeHandleNetworkAgentInfoMessage(msg)) {
2997                 maybeHandleNetworkAgentMessage(msg);
2998             }
2999         }
3000     }
3001 
3002     private class NetworkMonitorCallbacks extends INetworkMonitorCallbacks.Stub {
3003         private final int mNetId;
3004         private final AutodestructReference<NetworkAgentInfo> mNai;
3005 
NetworkMonitorCallbacks(NetworkAgentInfo nai)3006         private NetworkMonitorCallbacks(NetworkAgentInfo nai) {
3007             mNetId = nai.network.netId;
3008             mNai = new AutodestructReference<>(nai);
3009         }
3010 
3011         @Override
onNetworkMonitorCreated(INetworkMonitor networkMonitor)3012         public void onNetworkMonitorCreated(INetworkMonitor networkMonitor) {
3013             mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_AGENT,
3014                     new Pair<>(mNai.getAndDestroy(), networkMonitor)));
3015         }
3016 
3017         @Override
notifyNetworkTested(int testResult, @Nullable String redirectUrl)3018         public void notifyNetworkTested(int testResult, @Nullable String redirectUrl) {
3019             // Legacy version of notifyNetworkTestedWithExtras.
3020             // Would only be called if the system has a NetworkStack module older than the
3021             // framework, which does not happen in practice.
3022             Slog.wtf(TAG, "Deprecated notifyNetworkTested called: no action taken");
3023         }
3024 
3025         @Override
notifyNetworkTestedWithExtras(NetworkTestResultParcelable p)3026         public void notifyNetworkTestedWithExtras(NetworkTestResultParcelable p) {
3027             // Notify mTrackerHandler and mConnectivityDiagnosticsHandler of the event. Both use
3028             // the same looper so messages will be processed in sequence.
3029             final Message msg = mTrackerHandler.obtainMessage(
3030                     EVENT_NETWORK_TESTED,
3031                     new NetworkTestedResults(
3032                             mNetId, p.result, p.timestampMillis, p.redirectUrl));
3033             mTrackerHandler.sendMessage(msg);
3034 
3035             // Invoke ConnectivityReport generation for this Network test event.
3036             final NetworkAgentInfo nai = getNetworkAgentInfoForNetId(mNetId);
3037             if (nai == null) return;
3038             final Message m = mConnectivityDiagnosticsHandler.obtainMessage(
3039                     ConnectivityDiagnosticsHandler.EVENT_NETWORK_TESTED,
3040                     new ConnectivityReportEvent(p.timestampMillis, nai));
3041 
3042             final PersistableBundle extras = new PersistableBundle();
3043             extras.putInt(KEY_NETWORK_VALIDATION_RESULT, p.result);
3044             extras.putInt(KEY_NETWORK_PROBES_SUCCEEDED_BITMASK, p.probesSucceeded);
3045             extras.putInt(KEY_NETWORK_PROBES_ATTEMPTED_BITMASK, p.probesAttempted);
3046 
3047             m.setData(new Bundle(extras));
3048             mConnectivityDiagnosticsHandler.sendMessage(m);
3049         }
3050 
3051         @Override
notifyPrivateDnsConfigResolved(PrivateDnsConfigParcel config)3052         public void notifyPrivateDnsConfigResolved(PrivateDnsConfigParcel config) {
3053             mTrackerHandler.sendMessage(mTrackerHandler.obtainMessage(
3054                     EVENT_PRIVATE_DNS_CONFIG_RESOLVED,
3055                     0, mNetId, PrivateDnsConfig.fromParcel(config)));
3056         }
3057 
3058         @Override
notifyProbeStatusChanged(int probesCompleted, int probesSucceeded)3059         public void notifyProbeStatusChanged(int probesCompleted, int probesSucceeded) {
3060             mTrackerHandler.sendMessage(mTrackerHandler.obtainMessage(
3061                     EVENT_PROBE_STATUS_CHANGED,
3062                     probesCompleted, probesSucceeded, new Integer(mNetId)));
3063         }
3064 
3065         @Override
notifyCaptivePortalDataChanged(CaptivePortalData data)3066         public void notifyCaptivePortalDataChanged(CaptivePortalData data) {
3067             mTrackerHandler.sendMessage(mTrackerHandler.obtainMessage(
3068                     EVENT_CAPPORT_DATA_CHANGED,
3069                     0, mNetId, data));
3070         }
3071 
3072         @Override
showProvisioningNotification(String action, String packageName)3073         public void showProvisioningNotification(String action, String packageName) {
3074             final Intent intent = new Intent(action);
3075             intent.setPackage(packageName);
3076 
3077             final PendingIntent pendingIntent;
3078             // Only the system server can register notifications with package "android"
3079             final long token = Binder.clearCallingIdentity();
3080             try {
3081                 pendingIntent = PendingIntent.getBroadcast(
3082                         mContext,
3083                         0 /* requestCode */,
3084                         intent,
3085                         PendingIntent.FLAG_IMMUTABLE);
3086             } finally {
3087                 Binder.restoreCallingIdentity(token);
3088             }
3089             mTrackerHandler.sendMessage(mTrackerHandler.obtainMessage(
3090                     EVENT_PROVISIONING_NOTIFICATION, PROVISIONING_NOTIFICATION_SHOW,
3091                     mNetId, pendingIntent));
3092         }
3093 
3094         @Override
hideProvisioningNotification()3095         public void hideProvisioningNotification() {
3096             mTrackerHandler.sendMessage(mTrackerHandler.obtainMessage(
3097                     EVENT_PROVISIONING_NOTIFICATION, PROVISIONING_NOTIFICATION_HIDE, mNetId));
3098         }
3099 
3100         @Override
notifyDataStallSuspected(DataStallReportParcelable p)3101         public void notifyDataStallSuspected(DataStallReportParcelable p) {
3102             ConnectivityService.this.notifyDataStallSuspected(p, mNetId);
3103         }
3104 
3105         @Override
getInterfaceVersion()3106         public int getInterfaceVersion() {
3107             return this.VERSION;
3108         }
3109 
3110         @Override
getInterfaceHash()3111         public String getInterfaceHash() {
3112             return this.HASH;
3113         }
3114     }
3115 
notifyDataStallSuspected(DataStallReportParcelable p, int netId)3116     private void notifyDataStallSuspected(DataStallReportParcelable p, int netId) {
3117         log("Data stall detected with methods: " + p.detectionMethod);
3118 
3119         final PersistableBundle extras = new PersistableBundle();
3120         int detectionMethod = 0;
3121         if (hasDataStallDetectionMethod(p, DETECTION_METHOD_DNS_EVENTS)) {
3122             extras.putInt(KEY_DNS_CONSECUTIVE_TIMEOUTS, p.dnsConsecutiveTimeouts);
3123             detectionMethod |= DETECTION_METHOD_DNS_EVENTS;
3124         }
3125         if (hasDataStallDetectionMethod(p, DETECTION_METHOD_TCP_METRICS)) {
3126             extras.putInt(KEY_TCP_PACKET_FAIL_RATE, p.tcpPacketFailRate);
3127             extras.putInt(KEY_TCP_METRICS_COLLECTION_PERIOD_MILLIS,
3128                     p.tcpMetricsCollectionPeriodMillis);
3129             detectionMethod |= DETECTION_METHOD_TCP_METRICS;
3130         }
3131 
3132         final Message msg = mConnectivityDiagnosticsHandler.obtainMessage(
3133                 ConnectivityDiagnosticsHandler.EVENT_DATA_STALL_SUSPECTED, detectionMethod, netId,
3134                 p.timestampMillis);
3135         msg.setData(new Bundle(extras));
3136 
3137         // NetworkStateTrackerHandler currently doesn't take any actions based on data
3138         // stalls so send the message directly to ConnectivityDiagnosticsHandler and avoid
3139         // the cost of going through two handlers.
3140         mConnectivityDiagnosticsHandler.sendMessage(msg);
3141     }
3142 
hasDataStallDetectionMethod(DataStallReportParcelable p, int detectionMethod)3143     private boolean hasDataStallDetectionMethod(DataStallReportParcelable p, int detectionMethod) {
3144         return (p.detectionMethod & detectionMethod) != 0;
3145     }
3146 
networkRequiresPrivateDnsValidation(NetworkAgentInfo nai)3147     private boolean networkRequiresPrivateDnsValidation(NetworkAgentInfo nai) {
3148         return isPrivateDnsValidationRequired(nai.networkCapabilities);
3149     }
3150 
handleFreshlyValidatedNetwork(NetworkAgentInfo nai)3151     private void handleFreshlyValidatedNetwork(NetworkAgentInfo nai) {
3152         if (nai == null) return;
3153         // If the Private DNS mode is opportunistic, reprogram the DNS servers
3154         // in order to restart a validation pass from within netd.
3155         final PrivateDnsConfig cfg = mDnsManager.getPrivateDnsConfig();
3156         if (cfg.useTls && TextUtils.isEmpty(cfg.hostname)) {
3157             updateDnses(nai.linkProperties, null, nai.network.netId);
3158         }
3159     }
3160 
handlePrivateDnsSettingsChanged()3161     private void handlePrivateDnsSettingsChanged() {
3162         final PrivateDnsConfig cfg = mDnsManager.getPrivateDnsConfig();
3163 
3164         for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
3165             handlePerNetworkPrivateDnsConfig(nai, cfg);
3166             if (networkRequiresPrivateDnsValidation(nai)) {
3167                 handleUpdateLinkProperties(nai, new LinkProperties(nai.linkProperties));
3168             }
3169         }
3170     }
3171 
handlePerNetworkPrivateDnsConfig(NetworkAgentInfo nai, PrivateDnsConfig cfg)3172     private void handlePerNetworkPrivateDnsConfig(NetworkAgentInfo nai, PrivateDnsConfig cfg) {
3173         // Private DNS only ever applies to networks that might provide
3174         // Internet access and therefore also require validation.
3175         if (!networkRequiresPrivateDnsValidation(nai)) return;
3176 
3177         // Notify the NetworkAgentInfo/NetworkMonitor in case NetworkMonitor needs to cancel or
3178         // schedule DNS resolutions. If a DNS resolution is required the
3179         // result will be sent back to us.
3180         nai.networkMonitor().notifyPrivateDnsChanged(cfg.toParcel());
3181 
3182         // With Private DNS bypass support, we can proceed to update the
3183         // Private DNS config immediately, even if we're in strict mode
3184         // and have not yet resolved the provider name into a set of IPs.
3185         updatePrivateDns(nai, cfg);
3186     }
3187 
updatePrivateDns(NetworkAgentInfo nai, PrivateDnsConfig newCfg)3188     private void updatePrivateDns(NetworkAgentInfo nai, PrivateDnsConfig newCfg) {
3189         mDnsManager.updatePrivateDns(nai.network, newCfg);
3190         updateDnses(nai.linkProperties, null, nai.network.netId);
3191     }
3192 
handlePrivateDnsValidationUpdate(PrivateDnsValidationUpdate update)3193     private void handlePrivateDnsValidationUpdate(PrivateDnsValidationUpdate update) {
3194         NetworkAgentInfo nai = getNetworkAgentInfoForNetId(update.netId);
3195         if (nai == null) {
3196             return;
3197         }
3198         mDnsManager.updatePrivateDnsValidation(update);
3199         handleUpdateLinkProperties(nai, new LinkProperties(nai.linkProperties));
3200     }
3201 
handleNat64PrefixEvent(int netId, boolean added, String prefixString, int prefixLength)3202     private void handleNat64PrefixEvent(int netId, boolean added, String prefixString,
3203             int prefixLength) {
3204         NetworkAgentInfo nai = mNetworkForNetId.get(netId);
3205         if (nai == null) return;
3206 
3207         log(String.format("NAT64 prefix %s on netId %d: %s/%d",
3208                           (added ? "added" : "removed"), netId, prefixString, prefixLength));
3209 
3210         IpPrefix prefix = null;
3211         if (added) {
3212             try {
3213                 prefix = new IpPrefix(InetAddresses.parseNumericAddress(prefixString),
3214                         prefixLength);
3215             } catch (IllegalArgumentException e) {
3216                 loge("Invalid NAT64 prefix " + prefixString + "/" + prefixLength);
3217                 return;
3218             }
3219         }
3220 
3221         nai.clatd.setNat64PrefixFromDns(prefix);
3222         handleUpdateLinkProperties(nai, new LinkProperties(nai.linkProperties));
3223     }
3224 
handleCaptivePortalDataUpdate(@onNull final NetworkAgentInfo nai, @Nullable final CaptivePortalData data)3225     private void handleCaptivePortalDataUpdate(@NonNull final NetworkAgentInfo nai,
3226             @Nullable final CaptivePortalData data) {
3227         nai.captivePortalData = data;
3228         // CaptivePortalData will be merged into LinkProperties from NetworkAgentInfo
3229         handleUpdateLinkProperties(nai, new LinkProperties(nai.linkProperties));
3230     }
3231 
3232     /**
3233      * Updates the linger state from the network requests inside the NAI.
3234      * @param nai the agent info to update
3235      * @param now the timestamp of the event causing this update
3236      * @return whether the network was lingered as a result of this update
3237      */
updateLingerState(@onNull final NetworkAgentInfo nai, final long now)3238     private boolean updateLingerState(@NonNull final NetworkAgentInfo nai, final long now) {
3239         // 1. Update the linger timer. If it's changed, reschedule or cancel the alarm.
3240         // 2. If the network was lingering and there are now requests, unlinger it.
3241         // 3. If this network is unneeded (which implies it is not lingering), and there is at least
3242         //    one lingered request, start lingering.
3243         nai.updateLingerTimer();
3244         if (nai.isLingering() && nai.numForegroundNetworkRequests() > 0) {
3245             if (DBG) log("Unlingering " + nai.toShortString());
3246             nai.unlinger();
3247             logNetworkEvent(nai, NetworkEvent.NETWORK_UNLINGER);
3248         } else if (unneeded(nai, UnneededFor.LINGER) && nai.getLingerExpiry() > 0) {
3249             if (DBG) {
3250                 final int lingerTime = (int) (nai.getLingerExpiry() - now);
3251                 log("Lingering " + nai.toShortString() + " for " + lingerTime + "ms");
3252             }
3253             nai.linger();
3254             logNetworkEvent(nai, NetworkEvent.NETWORK_LINGER);
3255             return true;
3256         }
3257         return false;
3258     }
3259 
handleAsyncChannelHalfConnect(Message msg)3260     private void handleAsyncChannelHalfConnect(Message msg) {
3261         ensureRunningOnConnectivityServiceThread();
3262         final AsyncChannel ac = (AsyncChannel) msg.obj;
3263         if (mNetworkProviderInfos.containsKey(msg.replyTo)) {
3264             if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
3265                 if (VDBG) log("NetworkFactory connected");
3266                 // Finish setting up the full connection
3267                 NetworkProviderInfo npi = mNetworkProviderInfos.get(msg.replyTo);
3268                 npi.completeConnection();
3269                 sendAllRequestsToProvider(npi);
3270             } else {
3271                 loge("Error connecting NetworkFactory");
3272                 mNetworkProviderInfos.remove(msg.obj);
3273             }
3274         } else if (mNetworkAgentInfos.containsKey(msg.replyTo)) {
3275             if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
3276                 if (VDBG) log("NetworkAgent connected");
3277                 // A network agent has requested a connection.  Establish the connection.
3278                 mNetworkAgentInfos.get(msg.replyTo).asyncChannel.
3279                         sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION);
3280             } else {
3281                 loge("Error connecting NetworkAgent");
3282                 NetworkAgentInfo nai = mNetworkAgentInfos.remove(msg.replyTo);
3283                 if (nai != null) {
3284                     final boolean wasDefault = isDefaultNetwork(nai);
3285                     synchronized (mNetworkForNetId) {
3286                         mNetworkForNetId.remove(nai.network.netId);
3287                     }
3288                     mNetIdManager.releaseNetId(nai.network.netId);
3289                     // Just in case.
3290                     mLegacyTypeTracker.remove(nai, wasDefault);
3291                 }
3292             }
3293         }
3294     }
3295 
3296     // This is a no-op if it's called with a message designating a network that has
3297     // already been destroyed, because its reference will not be found in the relevant
3298     // maps.
handleAsyncChannelDisconnected(Message msg)3299     private void handleAsyncChannelDisconnected(Message msg) {
3300         NetworkAgentInfo nai = mNetworkAgentInfos.get(msg.replyTo);
3301         if (nai != null) {
3302             disconnectAndDestroyNetwork(nai);
3303         } else {
3304             NetworkProviderInfo npi = mNetworkProviderInfos.remove(msg.replyTo);
3305             if (DBG && npi != null) log("unregisterNetworkFactory for " + npi.name);
3306         }
3307     }
3308 
3309     // Destroys a network, remove references to it from the internal state managed by
3310     // ConnectivityService, free its interfaces and clean up.
3311     // Must be called on the Handler thread.
disconnectAndDestroyNetwork(NetworkAgentInfo nai)3312     private void disconnectAndDestroyNetwork(NetworkAgentInfo nai) {
3313         ensureRunningOnConnectivityServiceThread();
3314         if (DBG) {
3315             log(nai.toShortString() + " disconnected, was satisfying " + nai.numNetworkRequests());
3316         }
3317         // Clear all notifications of this network.
3318         mNotifier.clearNotification(nai.network.netId);
3319         // A network agent has disconnected.
3320         // TODO - if we move the logic to the network agent (have them disconnect
3321         // because they lost all their requests or because their score isn't good)
3322         // then they would disconnect organically, report their new state and then
3323         // disconnect the channel.
3324         if (nai.networkInfo.isConnected()) {
3325             nai.networkInfo.setDetailedState(NetworkInfo.DetailedState.DISCONNECTED,
3326                     null, null);
3327         }
3328         final boolean wasDefault = isDefaultNetwork(nai);
3329         if (wasDefault) {
3330             mDefaultInetConditionPublished = 0;
3331             // Log default network disconnection before required book-keeping.
3332             // Let rematchAllNetworksAndRequests() below record a new default network event
3333             // if there is a fallback. Taken together, the two form a X -> 0, 0 -> Y sequence
3334             // whose timestamps tell how long it takes to recover a default network.
3335             long now = SystemClock.elapsedRealtime();
3336             mDeps.getMetricsLogger().defaultNetworkMetrics().logDefaultNetworkEvent(now, null, nai);
3337         }
3338         notifyIfacesChangedForNetworkStats();
3339         // TODO - we shouldn't send CALLBACK_LOST to requests that can be satisfied
3340         // by other networks that are already connected. Perhaps that can be done by
3341         // sending all CALLBACK_LOST messages (for requests, not listens) at the end
3342         // of rematchAllNetworksAndRequests
3343         notifyNetworkCallbacks(nai, ConnectivityManager.CALLBACK_LOST);
3344         mKeepaliveTracker.handleStopAllKeepalives(nai, SocketKeepalive.ERROR_INVALID_NETWORK);
3345         for (String iface : nai.linkProperties.getAllInterfaceNames()) {
3346             // Disable wakeup packet monitoring for each interface.
3347             wakeupModifyInterface(iface, nai.networkCapabilities, false);
3348         }
3349         nai.networkMonitor().notifyNetworkDisconnected();
3350         mNetworkAgentInfos.remove(nai.messenger);
3351         nai.clatd.update();
3352         synchronized (mNetworkForNetId) {
3353             // Remove the NetworkAgent, but don't mark the netId as
3354             // available until we've told netd to delete it below.
3355             mNetworkForNetId.remove(nai.network.netId);
3356         }
3357         // Remove all previously satisfied requests.
3358         for (int i = 0; i < nai.numNetworkRequests(); i++) {
3359             NetworkRequest request = nai.requestAt(i);
3360             final NetworkRequestInfo nri = mNetworkRequests.get(request);
3361             final NetworkAgentInfo currentNetwork = nri.mSatisfier;
3362             if (currentNetwork != null && currentNetwork.network.netId == nai.network.netId) {
3363                 nri.mSatisfier = null;
3364                 sendUpdatedScoreToFactories(request, null);
3365             }
3366         }
3367         nai.clearLingerState();
3368         if (nai.isSatisfyingRequest(mDefaultRequest.requestId)) {
3369             mDefaultNetworkNai = null;
3370             updateDataActivityTracking(null /* newNetwork */, nai);
3371             notifyLockdownVpn(nai);
3372             ensureNetworkTransitionWakelock(nai.toShortString());
3373         }
3374         mLegacyTypeTracker.remove(nai, wasDefault);
3375         if (!nai.networkCapabilities.hasTransport(TRANSPORT_VPN)) {
3376             updateAllVpnsCapabilities();
3377         }
3378         rematchAllNetworksAndRequests();
3379         mLingerMonitor.noteDisconnect(nai);
3380         if (nai.created) {
3381             // Tell netd to clean up the configuration for this network
3382             // (routing rules, DNS, etc).
3383             // This may be slow as it requires a lot of netd shelling out to ip and
3384             // ip[6]tables to flush routes and remove the incoming packet mark rule, so do it
3385             // after we've rematched networks with requests which should make a potential
3386             // fallback network the default or requested a new network from the
3387             // NetworkProviders, so network traffic isn't interrupted for an unnecessarily
3388             // long time.
3389             destroyNativeNetwork(nai);
3390             mDnsManager.removeNetwork(nai.network);
3391         }
3392         mNetIdManager.releaseNetId(nai.network.netId);
3393     }
3394 
createNativeNetwork(@onNull NetworkAgentInfo networkAgent)3395     private boolean createNativeNetwork(@NonNull NetworkAgentInfo networkAgent) {
3396         try {
3397             // This should never fail.  Specifying an already in use NetID will cause failure.
3398             if (networkAgent.isVPN()) {
3399                 mNetd.networkCreateVpn(networkAgent.network.netId,
3400                         (networkAgent.networkAgentConfig == null
3401                                 || !networkAgent.networkAgentConfig.allowBypass));
3402             } else {
3403                 mNetd.networkCreatePhysical(networkAgent.network.netId,
3404                         getNetworkPermission(networkAgent.networkCapabilities));
3405             }
3406             mDnsResolver.createNetworkCache(networkAgent.network.netId);
3407             mDnsManager.updateTransportsForNetwork(networkAgent.network.netId,
3408                     networkAgent.networkCapabilities.getTransportTypes());
3409             return true;
3410         } catch (RemoteException | ServiceSpecificException e) {
3411             loge("Error creating network " + networkAgent.network.netId + ": "
3412                     + e.getMessage());
3413             return false;
3414         }
3415     }
3416 
destroyNativeNetwork(@onNull NetworkAgentInfo networkAgent)3417     private void destroyNativeNetwork(@NonNull NetworkAgentInfo networkAgent) {
3418         try {
3419             mNetd.networkDestroy(networkAgent.network.netId);
3420             mDnsResolver.destroyNetworkCache(networkAgent.network.netId);
3421         } catch (RemoteException | ServiceSpecificException e) {
3422             loge("Exception destroying network: " + e);
3423         }
3424     }
3425 
3426     // If this method proves to be too slow then we can maintain a separate
3427     // pendingIntent => NetworkRequestInfo map.
3428     // This method assumes that every non-null PendingIntent maps to exactly 1 NetworkRequestInfo.
findExistingNetworkRequestInfo(PendingIntent pendingIntent)3429     private NetworkRequestInfo findExistingNetworkRequestInfo(PendingIntent pendingIntent) {
3430         Intent intent = pendingIntent.getIntent();
3431         for (Map.Entry<NetworkRequest, NetworkRequestInfo> entry : mNetworkRequests.entrySet()) {
3432             PendingIntent existingPendingIntent = entry.getValue().mPendingIntent;
3433             if (existingPendingIntent != null &&
3434                     existingPendingIntent.getIntent().filterEquals(intent)) {
3435                 return entry.getValue();
3436             }
3437         }
3438         return null;
3439     }
3440 
handleRegisterNetworkRequestWithIntent(Message msg)3441     private void handleRegisterNetworkRequestWithIntent(Message msg) {
3442         final NetworkRequestInfo nri = (NetworkRequestInfo) (msg.obj);
3443 
3444         NetworkRequestInfo existingRequest = findExistingNetworkRequestInfo(nri.mPendingIntent);
3445         if (existingRequest != null) { // remove the existing request.
3446             if (DBG) log("Replacing " + existingRequest.request + " with "
3447                     + nri.request + " because their intents matched.");
3448             handleReleaseNetworkRequest(existingRequest.request, getCallingUid(),
3449                     /* callOnUnavailable */ false);
3450         }
3451         handleRegisterNetworkRequest(nri);
3452     }
3453 
handleRegisterNetworkRequest(NetworkRequestInfo nri)3454     private void handleRegisterNetworkRequest(NetworkRequestInfo nri) {
3455         ensureRunningOnConnectivityServiceThread();
3456         mNetworkRequests.put(nri.request, nri);
3457         mNetworkRequestInfoLogs.log("REGISTER " + nri);
3458         if (nri.request.isListen()) {
3459             for (NetworkAgentInfo network : mNetworkAgentInfos.values()) {
3460                 if (nri.request.networkCapabilities.hasSignalStrength() &&
3461                         network.satisfiesImmutableCapabilitiesOf(nri.request)) {
3462                     updateSignalStrengthThresholds(network, "REGISTER", nri.request);
3463                 }
3464             }
3465         }
3466         rematchAllNetworksAndRequests();
3467         if (nri.request.isRequest() && nri.mSatisfier == null) {
3468             sendUpdatedScoreToFactories(nri.request, null);
3469         }
3470     }
3471 
handleReleaseNetworkRequestWithIntent(PendingIntent pendingIntent, int callingUid)3472     private void handleReleaseNetworkRequestWithIntent(PendingIntent pendingIntent,
3473             int callingUid) {
3474         NetworkRequestInfo nri = findExistingNetworkRequestInfo(pendingIntent);
3475         if (nri != null) {
3476             handleReleaseNetworkRequest(nri.request, callingUid, /* callOnUnavailable */ false);
3477         }
3478     }
3479 
3480     // Determines whether the network is the best (or could become the best, if it validated), for
3481     // none of a particular type of NetworkRequests. The type of NetworkRequests considered depends
3482     // on the value of reason:
3483     //
3484     // - UnneededFor.TEARDOWN: non-listen NetworkRequests. If a network is unneeded for this reason,
3485     //   then it should be torn down.
3486     // - UnneededFor.LINGER: foreground NetworkRequests. If a network is unneeded for this reason,
3487     //   then it should be lingered.
unneeded(NetworkAgentInfo nai, UnneededFor reason)3488     private boolean unneeded(NetworkAgentInfo nai, UnneededFor reason) {
3489         ensureRunningOnConnectivityServiceThread();
3490         final int numRequests;
3491         switch (reason) {
3492             case TEARDOWN:
3493                 numRequests = nai.numRequestNetworkRequests();
3494                 break;
3495             case LINGER:
3496                 numRequests = nai.numForegroundNetworkRequests();
3497                 break;
3498             default:
3499                 Slog.wtf(TAG, "Invalid reason. Cannot happen.");
3500                 return true;
3501         }
3502 
3503         if (!nai.everConnected || nai.isVPN() || nai.isLingering() || numRequests > 0) {
3504             return false;
3505         }
3506         for (NetworkRequestInfo nri : mNetworkRequests.values()) {
3507             if (reason == UnneededFor.LINGER && nri.request.isBackgroundRequest()) {
3508                 // Background requests don't affect lingering.
3509                 continue;
3510             }
3511 
3512             // If this Network is already the highest scoring Network for a request, or if
3513             // there is hope for it to become one if it validated, then it is needed.
3514             if (nri.request.isRequest() && nai.satisfies(nri.request) &&
3515                     (nai.isSatisfyingRequest(nri.request.requestId) ||
3516                     // Note that this catches two important cases:
3517                     // 1. Unvalidated cellular will not be reaped when unvalidated WiFi
3518                     //    is currently satisfying the request.  This is desirable when
3519                     //    cellular ends up validating but WiFi does not.
3520                     // 2. Unvalidated WiFi will not be reaped when validated cellular
3521                     //    is currently satisfying the request.  This is desirable when
3522                     //    WiFi ends up validating and out scoring cellular.
3523                     nri.mSatisfier.getCurrentScore()
3524                             < nai.getCurrentScoreAsValidated())) {
3525                 return false;
3526             }
3527         }
3528         return true;
3529     }
3530 
getNriForAppRequest( NetworkRequest request, int callingUid, String requestedOperation)3531     private NetworkRequestInfo getNriForAppRequest(
3532             NetworkRequest request, int callingUid, String requestedOperation) {
3533         final NetworkRequestInfo nri = mNetworkRequests.get(request);
3534 
3535         if (nri != null) {
3536             if (Process.SYSTEM_UID != callingUid && Process.NETWORK_STACK_UID != callingUid
3537                     && nri.mUid != callingUid) {
3538                 log(String.format("UID %d attempted to %s for unowned request %s",
3539                         callingUid, requestedOperation, nri));
3540                 return null;
3541             }
3542         }
3543 
3544         return nri;
3545     }
3546 
handleTimedOutNetworkRequest(final NetworkRequestInfo nri)3547     private void handleTimedOutNetworkRequest(final NetworkRequestInfo nri) {
3548         ensureRunningOnConnectivityServiceThread();
3549         if (mNetworkRequests.get(nri.request) == null) {
3550             return;
3551         }
3552         if (nri.mSatisfier != null) {
3553             return;
3554         }
3555         if (VDBG || (DBG && nri.request.isRequest())) {
3556             log("releasing " + nri.request + " (timeout)");
3557         }
3558         handleRemoveNetworkRequest(nri);
3559         callCallbackForRequest(nri, null, ConnectivityManager.CALLBACK_UNAVAIL, 0);
3560     }
3561 
handleReleaseNetworkRequest(NetworkRequest request, int callingUid, boolean callOnUnavailable)3562     private void handleReleaseNetworkRequest(NetworkRequest request, int callingUid,
3563             boolean callOnUnavailable) {
3564         final NetworkRequestInfo nri =
3565                 getNriForAppRequest(request, callingUid, "release NetworkRequest");
3566         if (nri == null) {
3567             return;
3568         }
3569         if (VDBG || (DBG && nri.request.isRequest())) {
3570             log("releasing " + nri.request + " (release request)");
3571         }
3572         handleRemoveNetworkRequest(nri);
3573         if (callOnUnavailable) {
3574             callCallbackForRequest(nri, null, ConnectivityManager.CALLBACK_UNAVAIL, 0);
3575         }
3576     }
3577 
handleRemoveNetworkRequest(final NetworkRequestInfo nri)3578     private void handleRemoveNetworkRequest(final NetworkRequestInfo nri) {
3579         ensureRunningOnConnectivityServiceThread();
3580 
3581         nri.unlinkDeathRecipient();
3582         mNetworkRequests.remove(nri.request);
3583 
3584         decrementNetworkRequestPerUidCount(nri);
3585 
3586         mNetworkRequestInfoLogs.log("RELEASE " + nri);
3587         if (nri.request.isRequest()) {
3588             boolean wasKept = false;
3589             final NetworkAgentInfo nai = nri.mSatisfier;
3590             if (nai != null) {
3591                 boolean wasBackgroundNetwork = nai.isBackgroundNetwork();
3592                 nai.removeRequest(nri.request.requestId);
3593                 if (VDBG || DDBG) {
3594                     log(" Removing from current network " + nai.toShortString()
3595                             + ", leaving " + nai.numNetworkRequests() + " requests.");
3596                 }
3597                 // If there are still lingered requests on this network, don't tear it down,
3598                 // but resume lingering instead.
3599                 final long now = SystemClock.elapsedRealtime();
3600                 if (updateLingerState(nai, now)) {
3601                     notifyNetworkLosing(nai, now);
3602                 }
3603                 if (unneeded(nai, UnneededFor.TEARDOWN)) {
3604                     if (DBG) log("no live requests for " + nai.toShortString() + "; disconnecting");
3605                     teardownUnneededNetwork(nai);
3606                 } else {
3607                     wasKept = true;
3608                 }
3609                 nri.mSatisfier = null;
3610                 if (!wasBackgroundNetwork && nai.isBackgroundNetwork()) {
3611                     // Went from foreground to background.
3612                     updateCapabilities(nai.getCurrentScore(), nai, nai.networkCapabilities);
3613                 }
3614             }
3615 
3616             // Maintain the illusion.  When this request arrived, we might have pretended
3617             // that a network connected to serve it, even though the network was already
3618             // connected.  Now that this request has gone away, we might have to pretend
3619             // that the network disconnected.  LegacyTypeTracker will generate that
3620             // phantom disconnect for this type.
3621             if (nri.request.legacyType != TYPE_NONE && nai != null) {
3622                 boolean doRemove = true;
3623                 if (wasKept) {
3624                     // check if any of the remaining requests for this network are for the
3625                     // same legacy type - if so, don't remove the nai
3626                     for (int i = 0; i < nai.numNetworkRequests(); i++) {
3627                         NetworkRequest otherRequest = nai.requestAt(i);
3628                         if (otherRequest.legacyType == nri.request.legacyType &&
3629                                 otherRequest.isRequest()) {
3630                             if (DBG) log(" still have other legacy request - leaving");
3631                             doRemove = false;
3632                         }
3633                     }
3634                 }
3635 
3636                 if (doRemove) {
3637                     mLegacyTypeTracker.remove(nri.request.legacyType, nai, false);
3638                 }
3639             }
3640 
3641             for (NetworkProviderInfo npi : mNetworkProviderInfos.values()) {
3642                 npi.cancelRequest(nri.request);
3643             }
3644         } else {
3645             // listens don't have a singular affectedNetwork.  Check all networks to see
3646             // if this listen request applies and remove it.
3647             for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
3648                 nai.removeRequest(nri.request.requestId);
3649                 if (nri.request.networkCapabilities.hasSignalStrength() &&
3650                         nai.satisfiesImmutableCapabilitiesOf(nri.request)) {
3651                     updateSignalStrengthThresholds(nai, "RELEASE", nri.request);
3652                 }
3653             }
3654         }
3655     }
3656 
decrementNetworkRequestPerUidCount(final NetworkRequestInfo nri)3657     private void decrementNetworkRequestPerUidCount(final NetworkRequestInfo nri) {
3658         synchronized (mUidToNetworkRequestCount) {
3659             final int requests = mUidToNetworkRequestCount.get(nri.mUid, 0);
3660             if (requests < 1) {
3661                 Slog.wtf(TAG, "BUG: too small request count " + requests + " for UID " + nri.mUid);
3662             } else if (requests == 1) {
3663                 mUidToNetworkRequestCount.removeAt(mUidToNetworkRequestCount.indexOfKey(nri.mUid));
3664             } else {
3665                 mUidToNetworkRequestCount.put(nri.mUid, requests - 1);
3666             }
3667         }
3668     }
3669 
3670     @Override
setAcceptUnvalidated(Network network, boolean accept, boolean always)3671     public void setAcceptUnvalidated(Network network, boolean accept, boolean always) {
3672         enforceNetworkStackSettingsOrSetup();
3673         mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_ACCEPT_UNVALIDATED,
3674                 encodeBool(accept), encodeBool(always), network));
3675     }
3676 
3677     @Override
setAcceptPartialConnectivity(Network network, boolean accept, boolean always)3678     public void setAcceptPartialConnectivity(Network network, boolean accept, boolean always) {
3679         enforceNetworkStackSettingsOrSetup();
3680         mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_ACCEPT_PARTIAL_CONNECTIVITY,
3681                 encodeBool(accept), encodeBool(always), network));
3682     }
3683 
3684     @Override
setAvoidUnvalidated(Network network)3685     public void setAvoidUnvalidated(Network network) {
3686         enforceNetworkStackSettingsOrSetup();
3687         mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_AVOID_UNVALIDATED, network));
3688     }
3689 
handleSetAcceptUnvalidated(Network network, boolean accept, boolean always)3690     private void handleSetAcceptUnvalidated(Network network, boolean accept, boolean always) {
3691         if (DBG) log("handleSetAcceptUnvalidated network=" + network +
3692                 " accept=" + accept + " always=" + always);
3693 
3694         NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
3695         if (nai == null) {
3696             // Nothing to do.
3697             return;
3698         }
3699 
3700         if (nai.everValidated) {
3701             // The network validated while the dialog box was up. Take no action.
3702             return;
3703         }
3704 
3705         if (!nai.networkAgentConfig.explicitlySelected) {
3706             Slog.wtf(TAG, "BUG: setAcceptUnvalidated non non-explicitly selected network");
3707         }
3708 
3709         if (accept != nai.networkAgentConfig.acceptUnvalidated) {
3710             nai.networkAgentConfig.acceptUnvalidated = accept;
3711             // If network becomes partial connectivity and user already accepted to use this
3712             // network, we should respect the user's option and don't need to popup the
3713             // PARTIAL_CONNECTIVITY notification to user again.
3714             nai.networkAgentConfig.acceptPartialConnectivity = accept;
3715             rematchAllNetworksAndRequests();
3716             sendUpdatedScoreToFactories(nai);
3717         }
3718 
3719         if (always) {
3720             nai.asyncChannel.sendMessage(
3721                     NetworkAgent.CMD_SAVE_ACCEPT_UNVALIDATED, encodeBool(accept));
3722         }
3723 
3724         if (!accept) {
3725             // Tell the NetworkAgent to not automatically reconnect to the network.
3726             nai.asyncChannel.sendMessage(NetworkAgent.CMD_PREVENT_AUTOMATIC_RECONNECT);
3727             // Teardown the network.
3728             teardownUnneededNetwork(nai);
3729         }
3730 
3731     }
3732 
handleSetAcceptPartialConnectivity(Network network, boolean accept, boolean always)3733     private void handleSetAcceptPartialConnectivity(Network network, boolean accept,
3734             boolean always) {
3735         if (DBG) {
3736             log("handleSetAcceptPartialConnectivity network=" + network + " accept=" + accept
3737                     + " always=" + always);
3738         }
3739 
3740         final NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
3741         if (nai == null) {
3742             // Nothing to do.
3743             return;
3744         }
3745 
3746         if (nai.lastValidated) {
3747             // The network validated while the dialog box was up. Take no action.
3748             return;
3749         }
3750 
3751         if (accept != nai.networkAgentConfig.acceptPartialConnectivity) {
3752             nai.networkAgentConfig.acceptPartialConnectivity = accept;
3753         }
3754 
3755         // TODO: Use the current design or save the user choice into IpMemoryStore.
3756         if (always) {
3757             nai.asyncChannel.sendMessage(
3758                     NetworkAgent.CMD_SAVE_ACCEPT_UNVALIDATED, encodeBool(accept));
3759         }
3760 
3761         if (!accept) {
3762             // Tell the NetworkAgent to not automatically reconnect to the network.
3763             nai.asyncChannel.sendMessage(NetworkAgent.CMD_PREVENT_AUTOMATIC_RECONNECT);
3764             // Tear down the network.
3765             teardownUnneededNetwork(nai);
3766         } else {
3767             // Inform NetworkMonitor that partial connectivity is acceptable. This will likely
3768             // result in a partial connectivity result which will be processed by
3769             // maybeHandleNetworkMonitorMessage.
3770             //
3771             // TODO: NetworkMonitor does not refer to the "never ask again" bit. The bit is stored
3772             // per network. Therefore, NetworkMonitor may still do https probe.
3773             nai.networkMonitor().setAcceptPartialConnectivity();
3774         }
3775     }
3776 
handleSetAvoidUnvalidated(Network network)3777     private void handleSetAvoidUnvalidated(Network network) {
3778         NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
3779         if (nai == null || nai.lastValidated) {
3780             // Nothing to do. The network either disconnected or revalidated.
3781             return;
3782         }
3783         if (!nai.avoidUnvalidated) {
3784             nai.avoidUnvalidated = true;
3785             rematchAllNetworksAndRequests();
3786             sendUpdatedScoreToFactories(nai);
3787         }
3788     }
3789 
scheduleUnvalidatedPrompt(NetworkAgentInfo nai)3790     private void scheduleUnvalidatedPrompt(NetworkAgentInfo nai) {
3791         if (VDBG) log("scheduleUnvalidatedPrompt " + nai.network);
3792         mHandler.sendMessageDelayed(
3793                 mHandler.obtainMessage(EVENT_PROMPT_UNVALIDATED, nai.network),
3794                 PROMPT_UNVALIDATED_DELAY_MS);
3795     }
3796 
3797     @Override
startCaptivePortalApp(Network network)3798     public void startCaptivePortalApp(Network network) {
3799         enforceNetworkStackOrSettingsPermission();
3800         mHandler.post(() -> {
3801             NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
3802             if (nai == null) return;
3803             if (!nai.networkCapabilities.hasCapability(NET_CAPABILITY_CAPTIVE_PORTAL)) return;
3804             nai.networkMonitor().launchCaptivePortalApp();
3805         });
3806     }
3807 
3808     /**
3809      * NetworkStack endpoint to start the captive portal app. The NetworkStack needs to use this
3810      * endpoint as it does not have INTERACT_ACROSS_USERS_FULL itself.
3811      * @param network Network on which the captive portal was detected.
3812      * @param appExtras Bundle to use as intent extras for the captive portal application.
3813      *                  Must be treated as opaque to avoid preventing the captive portal app to
3814      *                  update its arguments.
3815      */
3816     @Override
startCaptivePortalAppInternal(Network network, Bundle appExtras)3817     public void startCaptivePortalAppInternal(Network network, Bundle appExtras) {
3818         mContext.enforceCallingOrSelfPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
3819                 "ConnectivityService");
3820 
3821         final Intent appIntent = new Intent(ConnectivityManager.ACTION_CAPTIVE_PORTAL_SIGN_IN);
3822         appIntent.putExtras(appExtras);
3823         appIntent.putExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL,
3824                 new CaptivePortal(new CaptivePortalImpl(network).asBinder()));
3825         appIntent.setFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT | Intent.FLAG_ACTIVITY_NEW_TASK);
3826 
3827         Binder.withCleanCallingIdentity(() ->
3828                 mContext.startActivityAsUser(appIntent, UserHandle.CURRENT));
3829     }
3830 
3831     private class CaptivePortalImpl extends ICaptivePortal.Stub {
3832         private final Network mNetwork;
3833 
CaptivePortalImpl(Network network)3834         private CaptivePortalImpl(Network network) {
3835             mNetwork = network;
3836         }
3837 
3838         @Override
appResponse(final int response)3839         public void appResponse(final int response) {
3840             if (response == CaptivePortal.APP_RETURN_WANTED_AS_IS) {
3841                 enforceSettingsPermission();
3842             }
3843 
3844             final NetworkMonitorManager nm = getNetworkMonitorManager(mNetwork);
3845             if (nm == null) return;
3846             nm.notifyCaptivePortalAppFinished(response);
3847         }
3848 
3849         @Override
appRequest(final int request)3850         public void appRequest(final int request) {
3851             final NetworkMonitorManager nm = getNetworkMonitorManager(mNetwork);
3852             if (nm == null) return;
3853 
3854             if (request == CaptivePortal.APP_REQUEST_REEVALUATION_REQUIRED) {
3855                 checkNetworkStackPermission();
3856                 nm.forceReevaluation(Binder.getCallingUid());
3857             }
3858         }
3859 
3860         @Nullable
getNetworkMonitorManager(final Network network)3861         private NetworkMonitorManager getNetworkMonitorManager(final Network network) {
3862             // getNetworkAgentInfoForNetwork is thread-safe
3863             final NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
3864             if (nai == null) return null;
3865 
3866             // nai.networkMonitor() is thread-safe
3867             return nai.networkMonitor();
3868         }
3869 
3870         @Override
logEvent(int eventId, String packageName)3871         public void logEvent(int eventId, String packageName) {
3872             enforceSettingsPermission();
3873 
3874             new MetricsLogger().action(eventId, packageName);
3875         }
3876     }
3877 
avoidBadWifi()3878     public boolean avoidBadWifi() {
3879         return mMultinetworkPolicyTracker.getAvoidBadWifi();
3880     }
3881 
3882     /**
3883      * Return whether the device should maintain continuous, working connectivity by switching away
3884      * from WiFi networks having no connectivity.
3885      * @see MultinetworkPolicyTracker#getAvoidBadWifi()
3886      */
shouldAvoidBadWifi()3887     public boolean shouldAvoidBadWifi() {
3888         if (!checkNetworkStackPermission()) {
3889             throw new SecurityException("avoidBadWifi requires NETWORK_STACK permission");
3890         }
3891         return avoidBadWifi();
3892     }
3893 
3894 
rematchForAvoidBadWifiUpdate()3895     private void rematchForAvoidBadWifiUpdate() {
3896         rematchAllNetworksAndRequests();
3897         for (NetworkAgentInfo nai: mNetworkAgentInfos.values()) {
3898             if (nai.networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
3899                 sendUpdatedScoreToFactories(nai);
3900             }
3901         }
3902     }
3903 
3904     // TODO: Evaluate whether this is of interest to other consumers of
3905     // MultinetworkPolicyTracker and worth moving out of here.
dumpAvoidBadWifiSettings(IndentingPrintWriter pw)3906     private void dumpAvoidBadWifiSettings(IndentingPrintWriter pw) {
3907         final boolean configRestrict = mMultinetworkPolicyTracker.configRestrictsAvoidBadWifi();
3908         if (!configRestrict) {
3909             pw.println("Bad Wi-Fi avoidance: unrestricted");
3910             return;
3911         }
3912 
3913         pw.println("Bad Wi-Fi avoidance: " + avoidBadWifi());
3914         pw.increaseIndent();
3915         pw.println("Config restrict:   " + configRestrict);
3916 
3917         final String value = mMultinetworkPolicyTracker.getAvoidBadWifiSetting();
3918         String description;
3919         // Can't use a switch statement because strings are legal case labels, but null is not.
3920         if ("0".equals(value)) {
3921             description = "get stuck";
3922         } else if (value == null) {
3923             description = "prompt";
3924         } else if ("1".equals(value)) {
3925             description = "avoid";
3926         } else {
3927             description = value + " (?)";
3928         }
3929         pw.println("User setting:      " + description);
3930         pw.println("Network overrides:");
3931         pw.increaseIndent();
3932         for (NetworkAgentInfo nai : networksSortedById()) {
3933             if (nai.avoidUnvalidated) {
3934                 pw.println(nai.toShortString());
3935             }
3936         }
3937         pw.decreaseIndent();
3938         pw.decreaseIndent();
3939     }
3940 
3941     // TODO: This method is copied from TetheringNotificationUpdater. Should have a utility class to
3942     // unify the method.
getSettingsPackageName(@onNull final PackageManager pm)3943     private static @NonNull String getSettingsPackageName(@NonNull final PackageManager pm) {
3944         final Intent settingsIntent = new Intent(Settings.ACTION_SETTINGS);
3945         final ComponentName settingsComponent = settingsIntent.resolveActivity(pm);
3946         return settingsComponent != null
3947                 ? settingsComponent.getPackageName() : "com.android.settings";
3948     }
3949 
showNetworkNotification(NetworkAgentInfo nai, NotificationType type)3950     private void showNetworkNotification(NetworkAgentInfo nai, NotificationType type) {
3951         final String action;
3952         final boolean highPriority;
3953         switch (type) {
3954             case NO_INTERNET:
3955                 action = ConnectivityManager.ACTION_PROMPT_UNVALIDATED;
3956                 // High priority because it is only displayed for explicitly selected networks.
3957                 highPriority = true;
3958                 break;
3959             case PRIVATE_DNS_BROKEN:
3960                 action = Settings.ACTION_WIRELESS_SETTINGS;
3961                 // High priority because we should let user know why there is no internet.
3962                 highPriority = true;
3963                 break;
3964             case LOST_INTERNET:
3965                 action = ConnectivityManager.ACTION_PROMPT_LOST_VALIDATION;
3966                 // High priority because it could help the user avoid unexpected data usage.
3967                 highPriority = true;
3968                 break;
3969             case PARTIAL_CONNECTIVITY:
3970                 action = ConnectivityManager.ACTION_PROMPT_PARTIAL_CONNECTIVITY;
3971                 // Don't bother the user with a high-priority notification if the network was not
3972                 // explicitly selected by the user.
3973                 highPriority = nai.networkAgentConfig.explicitlySelected;
3974                 break;
3975             default:
3976                 Slog.wtf(TAG, "Unknown notification type " + type);
3977                 return;
3978         }
3979 
3980         Intent intent = new Intent(action);
3981         if (type != NotificationType.PRIVATE_DNS_BROKEN) {
3982             intent.setData(Uri.fromParts("netId", Integer.toString(nai.network.netId), null));
3983             intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
3984             // Some OEMs have their own Settings package. Thus, need to get the current using
3985             // Settings package name instead of just use default name "com.android.settings".
3986             final String settingsPkgName = getSettingsPackageName(mContext.getPackageManager());
3987             intent.setClassName(settingsPkgName,
3988                     settingsPkgName + ".wifi.WifiNoInternetDialog");
3989         }
3990 
3991         PendingIntent pendingIntent = PendingIntent.getActivityAsUser(
3992                 mContext,
3993                 0 /* requestCode */,
3994                 intent,
3995                 PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE,
3996                 null /* options */,
3997                 UserHandle.CURRENT);
3998 
3999         mNotifier.showNotification(nai.network.netId, type, nai, null, pendingIntent, highPriority);
4000     }
4001 
shouldPromptUnvalidated(NetworkAgentInfo nai)4002     private boolean shouldPromptUnvalidated(NetworkAgentInfo nai) {
4003         // Don't prompt if the network is validated, and don't prompt on captive portals
4004         // because we're already prompting the user to sign in.
4005         if (nai.everValidated || nai.everCaptivePortalDetected) {
4006             return false;
4007         }
4008 
4009         // If a network has partial connectivity, always prompt unless the user has already accepted
4010         // partial connectivity and selected don't ask again. This ensures that if the device
4011         // automatically connects to a network that has partial Internet access, the user will
4012         // always be able to use it, either because they've already chosen "don't ask again" or
4013         // because we have prompt them.
4014         if (nai.partialConnectivity && !nai.networkAgentConfig.acceptPartialConnectivity) {
4015             return true;
4016         }
4017 
4018         // If a network has no Internet access, only prompt if the network was explicitly selected
4019         // and if the user has not already told us to use the network regardless of whether it
4020         // validated or not.
4021         if (nai.networkAgentConfig.explicitlySelected
4022                 && !nai.networkAgentConfig.acceptUnvalidated) {
4023             return true;
4024         }
4025 
4026         return false;
4027     }
4028 
handlePromptUnvalidated(Network network)4029     private void handlePromptUnvalidated(Network network) {
4030         if (VDBG || DDBG) log("handlePromptUnvalidated " + network);
4031         NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
4032 
4033         if (nai == null || !shouldPromptUnvalidated(nai)) {
4034             return;
4035         }
4036 
4037         // Stop automatically reconnecting to this network in the future. Automatically connecting
4038         // to a network that provides no or limited connectivity is not useful, because the user
4039         // cannot use that network except through the notification shown by this method, and the
4040         // notification is only shown if the network is explicitly selected by the user.
4041         nai.asyncChannel.sendMessage(NetworkAgent.CMD_PREVENT_AUTOMATIC_RECONNECT);
4042 
4043         // TODO: Evaluate if it's needed to wait 8 seconds for triggering notification when
4044         // NetworkMonitor detects the network is partial connectivity. Need to change the design to
4045         // popup the notification immediately when the network is partial connectivity.
4046         if (nai.partialConnectivity) {
4047             showNetworkNotification(nai, NotificationType.PARTIAL_CONNECTIVITY);
4048         } else {
4049             showNetworkNotification(nai, NotificationType.NO_INTERNET);
4050         }
4051     }
4052 
handleNetworkUnvalidated(NetworkAgentInfo nai)4053     private void handleNetworkUnvalidated(NetworkAgentInfo nai) {
4054         NetworkCapabilities nc = nai.networkCapabilities;
4055         if (DBG) log("handleNetworkUnvalidated " + nai.toShortString() + " cap=" + nc);
4056 
4057         if (!nc.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
4058             return;
4059         }
4060 
4061         if (mMultinetworkPolicyTracker.shouldNotifyWifiUnvalidated()) {
4062             showNetworkNotification(nai, NotificationType.LOST_INTERNET);
4063         }
4064     }
4065 
4066     @Override
getMultipathPreference(Network network)4067     public int getMultipathPreference(Network network) {
4068         enforceAccessPermission();
4069 
4070         NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
4071         if (nai != null && nai.networkCapabilities
4072                 .hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED)) {
4073             return ConnectivityManager.MULTIPATH_PREFERENCE_UNMETERED;
4074         }
4075 
4076         Integer networkPreference = mMultipathPolicyTracker.getMultipathPreference(network);
4077         if (networkPreference != null) {
4078             return networkPreference;
4079         }
4080 
4081         return mMultinetworkPolicyTracker.getMeteredMultipathPreference();
4082     }
4083 
4084     @Override
getDefaultRequest()4085     public NetworkRequest getDefaultRequest() {
4086         return mDefaultRequest;
4087     }
4088 
4089     private class InternalHandler extends Handler {
InternalHandler(Looper looper)4090         public InternalHandler(Looper looper) {
4091             super(looper);
4092         }
4093 
4094         @Override
handleMessage(Message msg)4095         public void handleMessage(Message msg) {
4096             switch (msg.what) {
4097                 case EVENT_EXPIRE_NET_TRANSITION_WAKELOCK:
4098                 case EVENT_CLEAR_NET_TRANSITION_WAKELOCK: {
4099                     handleReleaseNetworkTransitionWakelock(msg.what);
4100                     break;
4101                 }
4102                 case EVENT_APPLY_GLOBAL_HTTP_PROXY: {
4103                     mProxyTracker.loadDeprecatedGlobalHttpProxy();
4104                     break;
4105                 }
4106                 case EVENT_PROXY_HAS_CHANGED: {
4107                     handleApplyDefaultProxy((ProxyInfo)msg.obj);
4108                     break;
4109                 }
4110                 case EVENT_REGISTER_NETWORK_PROVIDER: {
4111                     handleRegisterNetworkProvider((NetworkProviderInfo) msg.obj);
4112                     break;
4113                 }
4114                 case EVENT_UNREGISTER_NETWORK_PROVIDER: {
4115                     handleUnregisterNetworkProvider((Messenger) msg.obj);
4116                     break;
4117                 }
4118                 case EVENT_REGISTER_NETWORK_AGENT: {
4119                     final Pair<NetworkAgentInfo, INetworkMonitor> arg =
4120                             (Pair<NetworkAgentInfo, INetworkMonitor>) msg.obj;
4121                     handleRegisterNetworkAgent(arg.first, arg.second);
4122                     break;
4123                 }
4124                 case EVENT_REGISTER_NETWORK_REQUEST:
4125                 case EVENT_REGISTER_NETWORK_LISTENER: {
4126                     handleRegisterNetworkRequest((NetworkRequestInfo) msg.obj);
4127                     break;
4128                 }
4129                 case EVENT_REGISTER_NETWORK_REQUEST_WITH_INTENT:
4130                 case EVENT_REGISTER_NETWORK_LISTENER_WITH_INTENT: {
4131                     handleRegisterNetworkRequestWithIntent(msg);
4132                     break;
4133                 }
4134                 case EVENT_TIMEOUT_NETWORK_REQUEST: {
4135                     NetworkRequestInfo nri = (NetworkRequestInfo) msg.obj;
4136                     handleTimedOutNetworkRequest(nri);
4137                     break;
4138                 }
4139                 case EVENT_RELEASE_NETWORK_REQUEST_WITH_INTENT: {
4140                     handleReleaseNetworkRequestWithIntent((PendingIntent) msg.obj, msg.arg1);
4141                     break;
4142                 }
4143                 case EVENT_RELEASE_NETWORK_REQUEST: {
4144                     handleReleaseNetworkRequest((NetworkRequest) msg.obj, msg.arg1,
4145                             /* callOnUnavailable */ false);
4146                     break;
4147                 }
4148                 case EVENT_SET_ACCEPT_UNVALIDATED: {
4149                     Network network = (Network) msg.obj;
4150                     handleSetAcceptUnvalidated(network, toBool(msg.arg1), toBool(msg.arg2));
4151                     break;
4152                 }
4153                 case EVENT_SET_ACCEPT_PARTIAL_CONNECTIVITY: {
4154                     Network network = (Network) msg.obj;
4155                     handleSetAcceptPartialConnectivity(network, toBool(msg.arg1),
4156                             toBool(msg.arg2));
4157                     break;
4158                 }
4159                 case EVENT_SET_AVOID_UNVALIDATED: {
4160                     handleSetAvoidUnvalidated((Network) msg.obj);
4161                     break;
4162                 }
4163                 case EVENT_PROMPT_UNVALIDATED: {
4164                     handlePromptUnvalidated((Network) msg.obj);
4165                     break;
4166                 }
4167                 case EVENT_CONFIGURE_ALWAYS_ON_NETWORKS: {
4168                     handleConfigureAlwaysOnNetworks();
4169                     break;
4170                 }
4171                 // Sent by KeepaliveTracker to process an app request on the state machine thread.
4172                 case NetworkAgent.CMD_START_SOCKET_KEEPALIVE: {
4173                     mKeepaliveTracker.handleStartKeepalive(msg);
4174                     break;
4175                 }
4176                 // Sent by KeepaliveTracker to process an app request on the state machine thread.
4177                 case NetworkAgent.CMD_STOP_SOCKET_KEEPALIVE: {
4178                     NetworkAgentInfo nai = getNetworkAgentInfoForNetwork((Network) msg.obj);
4179                     int slot = msg.arg1;
4180                     int reason = msg.arg2;
4181                     mKeepaliveTracker.handleStopKeepalive(nai, slot, reason);
4182                     break;
4183                 }
4184                 case EVENT_SYSTEM_READY: {
4185                     mMultipathPolicyTracker.start();
4186                     break;
4187                 }
4188                 case EVENT_REVALIDATE_NETWORK: {
4189                     handleReportNetworkConnectivity((Network) msg.obj, msg.arg1, toBool(msg.arg2));
4190                     break;
4191                 }
4192                 case EVENT_PRIVATE_DNS_SETTINGS_CHANGED:
4193                     handlePrivateDnsSettingsChanged();
4194                     break;
4195                 case EVENT_PRIVATE_DNS_VALIDATION_UPDATE:
4196                     handlePrivateDnsValidationUpdate(
4197                             (PrivateDnsValidationUpdate) msg.obj);
4198                     break;
4199                 case EVENT_UID_RULES_CHANGED:
4200                     handleUidRulesChanged(msg.arg1, msg.arg2);
4201                     break;
4202                 case EVENT_DATA_SAVER_CHANGED:
4203                     handleRestrictBackgroundChanged(toBool(msg.arg1));
4204                     break;
4205             }
4206         }
4207     }
4208 
4209     @Override
4210     @Deprecated
getLastTetherError(String iface)4211     public int getLastTetherError(String iface) {
4212         final TetheringManager tm = (TetheringManager) mContext.getSystemService(
4213                 Context.TETHERING_SERVICE);
4214         return tm.getLastTetherError(iface);
4215     }
4216 
4217     @Override
4218     @Deprecated
getTetherableIfaces()4219     public String[] getTetherableIfaces() {
4220         final TetheringManager tm = (TetheringManager) mContext.getSystemService(
4221                 Context.TETHERING_SERVICE);
4222         return tm.getTetherableIfaces();
4223     }
4224 
4225     @Override
4226     @Deprecated
getTetheredIfaces()4227     public String[] getTetheredIfaces() {
4228         final TetheringManager tm = (TetheringManager) mContext.getSystemService(
4229                 Context.TETHERING_SERVICE);
4230         return tm.getTetheredIfaces();
4231     }
4232 
4233 
4234     @Override
4235     @Deprecated
getTetheringErroredIfaces()4236     public String[] getTetheringErroredIfaces() {
4237         final TetheringManager tm = (TetheringManager) mContext.getSystemService(
4238                 Context.TETHERING_SERVICE);
4239 
4240         return tm.getTetheringErroredIfaces();
4241     }
4242 
4243     @Override
4244     @Deprecated
getTetherableUsbRegexs()4245     public String[] getTetherableUsbRegexs() {
4246         final TetheringManager tm = (TetheringManager) mContext.getSystemService(
4247                 Context.TETHERING_SERVICE);
4248 
4249         return tm.getTetherableUsbRegexs();
4250     }
4251 
4252     @Override
4253     @Deprecated
getTetherableWifiRegexs()4254     public String[] getTetherableWifiRegexs() {
4255         final TetheringManager tm = (TetheringManager) mContext.getSystemService(
4256                 Context.TETHERING_SERVICE);
4257         return tm.getTetherableWifiRegexs();
4258     }
4259 
4260     // Called when we lose the default network and have no replacement yet.
4261     // This will automatically be cleared after X seconds or a new default network
4262     // becomes CONNECTED, whichever happens first.  The timer is started by the
4263     // first caller and not restarted by subsequent callers.
ensureNetworkTransitionWakelock(String forWhom)4264     private void ensureNetworkTransitionWakelock(String forWhom) {
4265         synchronized (this) {
4266             if (mNetTransitionWakeLock.isHeld()) {
4267                 return;
4268             }
4269             mNetTransitionWakeLock.acquire();
4270             mLastWakeLockAcquireTimestamp = SystemClock.elapsedRealtime();
4271             mTotalWakelockAcquisitions++;
4272         }
4273         mWakelockLogs.log("ACQUIRE for " + forWhom);
4274         Message msg = mHandler.obtainMessage(EVENT_EXPIRE_NET_TRANSITION_WAKELOCK);
4275         mHandler.sendMessageDelayed(msg, mNetTransitionWakeLockTimeout);
4276     }
4277 
4278     // Called when we gain a new default network to release the network transition wakelock in a
4279     // second, to allow a grace period for apps to reconnect over the new network. Pending expiry
4280     // message is cancelled.
scheduleReleaseNetworkTransitionWakelock()4281     private void scheduleReleaseNetworkTransitionWakelock() {
4282         synchronized (this) {
4283             if (!mNetTransitionWakeLock.isHeld()) {
4284                 return; // expiry message released the lock first.
4285             }
4286         }
4287         // Cancel self timeout on wakelock hold.
4288         mHandler.removeMessages(EVENT_EXPIRE_NET_TRANSITION_WAKELOCK);
4289         Message msg = mHandler.obtainMessage(EVENT_CLEAR_NET_TRANSITION_WAKELOCK);
4290         mHandler.sendMessageDelayed(msg, 1000);
4291     }
4292 
4293     // Called when either message of ensureNetworkTransitionWakelock or
4294     // scheduleReleaseNetworkTransitionWakelock is processed.
handleReleaseNetworkTransitionWakelock(int eventId)4295     private void handleReleaseNetworkTransitionWakelock(int eventId) {
4296         String event = eventName(eventId);
4297         synchronized (this) {
4298             if (!mNetTransitionWakeLock.isHeld()) {
4299                 mWakelockLogs.log(String.format("RELEASE: already released (%s)", event));
4300                 Slog.w(TAG, "expected Net Transition WakeLock to be held");
4301                 return;
4302             }
4303             mNetTransitionWakeLock.release();
4304             long lockDuration = SystemClock.elapsedRealtime() - mLastWakeLockAcquireTimestamp;
4305             mTotalWakelockDurationMs += lockDuration;
4306             mMaxWakelockDurationMs = Math.max(mMaxWakelockDurationMs, lockDuration);
4307             mTotalWakelockReleases++;
4308         }
4309         mWakelockLogs.log(String.format("RELEASE (%s)", event));
4310     }
4311 
4312     // 100 percent is full good, 0 is full bad.
4313     @Override
reportInetCondition(int networkType, int percentage)4314     public void reportInetCondition(int networkType, int percentage) {
4315         NetworkAgentInfo nai = mLegacyTypeTracker.getNetworkForType(networkType);
4316         if (nai == null) return;
4317         reportNetworkConnectivity(nai.network, percentage > 50);
4318     }
4319 
4320     @Override
reportNetworkConnectivity(Network network, boolean hasConnectivity)4321     public void reportNetworkConnectivity(Network network, boolean hasConnectivity) {
4322         enforceAccessPermission();
4323         enforceInternetPermission();
4324         final int uid = Binder.getCallingUid();
4325         final int connectivityInfo = encodeBool(hasConnectivity);
4326 
4327         // Handle ConnectivityDiagnostics event before attempting to revalidate the network. This
4328         // forces an ordering of ConnectivityDiagnostics events in the case where hasConnectivity
4329         // does not match the known connectivity of the network - this causes NetworkMonitor to
4330         // revalidate the network and generate a ConnectivityDiagnostics ConnectivityReport event.
4331         final NetworkAgentInfo nai;
4332         if (network == null) {
4333             nai = getDefaultNetwork();
4334         } else {
4335             nai = getNetworkAgentInfoForNetwork(network);
4336         }
4337         if (nai != null) {
4338             mConnectivityDiagnosticsHandler.sendMessage(
4339                     mConnectivityDiagnosticsHandler.obtainMessage(
4340                             ConnectivityDiagnosticsHandler.EVENT_NETWORK_CONNECTIVITY_REPORTED,
4341                             connectivityInfo, 0, nai));
4342         }
4343 
4344         mHandler.sendMessage(
4345                 mHandler.obtainMessage(EVENT_REVALIDATE_NETWORK, uid, connectivityInfo, network));
4346     }
4347 
handleReportNetworkConnectivity( Network network, int uid, boolean hasConnectivity)4348     private void handleReportNetworkConnectivity(
4349             Network network, int uid, boolean hasConnectivity) {
4350         final NetworkAgentInfo nai;
4351         if (network == null) {
4352             nai = getDefaultNetwork();
4353         } else {
4354             nai = getNetworkAgentInfoForNetwork(network);
4355         }
4356         if (nai == null || nai.networkInfo.getState() == NetworkInfo.State.DISCONNECTING ||
4357             nai.networkInfo.getState() == NetworkInfo.State.DISCONNECTED) {
4358             return;
4359         }
4360         // Revalidate if the app report does not match our current validated state.
4361         if (hasConnectivity == nai.lastValidated) {
4362             return;
4363         }
4364         if (DBG) {
4365             int netid = nai.network.netId;
4366             log("reportNetworkConnectivity(" + netid + ", " + hasConnectivity + ") by " + uid);
4367         }
4368         // Validating a network that has not yet connected could result in a call to
4369         // rematchNetworkAndRequests() which is not meant to work on such networks.
4370         if (!nai.everConnected) {
4371             return;
4372         }
4373         LinkProperties lp = getLinkProperties(nai);
4374         if (isNetworkWithLinkPropertiesBlocked(lp, uid, false)) {
4375             return;
4376         }
4377         nai.networkMonitor().forceReevaluation(uid);
4378     }
4379 
4380     /**
4381      * Returns information about the proxy a certain network is using. If given a null network, it
4382      * it will return the proxy for the bound network for the caller app or the default proxy if
4383      * none.
4384      *
4385      * @param network the network we want to get the proxy information for.
4386      * @return Proxy information if a network has a proxy configured, or otherwise null.
4387      */
4388     @Override
getProxyForNetwork(Network network)4389     public ProxyInfo getProxyForNetwork(Network network) {
4390         final ProxyInfo globalProxy = mProxyTracker.getGlobalProxy();
4391         if (globalProxy != null) return globalProxy;
4392         if (network == null) {
4393             // Get the network associated with the calling UID.
4394             final Network activeNetwork = getActiveNetworkForUidInternal(Binder.getCallingUid(),
4395                     true);
4396             if (activeNetwork == null) {
4397                 return null;
4398             }
4399             return getLinkPropertiesProxyInfo(activeNetwork);
4400         } else if (mDeps.queryUserAccess(Binder.getCallingUid(), network.netId)) {
4401             // Don't call getLinkProperties() as it requires ACCESS_NETWORK_STATE permission, which
4402             // caller may not have.
4403             return getLinkPropertiesProxyInfo(network);
4404         }
4405         // No proxy info available if the calling UID does not have network access.
4406         return null;
4407     }
4408 
4409 
getLinkPropertiesProxyInfo(Network network)4410     private ProxyInfo getLinkPropertiesProxyInfo(Network network) {
4411         final NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
4412         if (nai == null) return null;
4413         synchronized (nai) {
4414             final ProxyInfo linkHttpProxy = nai.linkProperties.getHttpProxy();
4415             return linkHttpProxy == null ? null : new ProxyInfo(linkHttpProxy);
4416         }
4417     }
4418 
4419     @Override
setGlobalProxy(final ProxyInfo proxyProperties)4420     public void setGlobalProxy(final ProxyInfo proxyProperties) {
4421         NetworkStack.checkNetworkStackPermission(mContext);
4422         mProxyTracker.setGlobalProxy(proxyProperties);
4423     }
4424 
4425     @Override
4426     @Nullable
getGlobalProxy()4427     public ProxyInfo getGlobalProxy() {
4428         return mProxyTracker.getGlobalProxy();
4429     }
4430 
handleApplyDefaultProxy(ProxyInfo proxy)4431     private void handleApplyDefaultProxy(ProxyInfo proxy) {
4432         if (proxy != null && TextUtils.isEmpty(proxy.getHost())
4433                 && Uri.EMPTY.equals(proxy.getPacFileUrl())) {
4434             proxy = null;
4435         }
4436         mProxyTracker.setDefaultProxy(proxy);
4437     }
4438 
4439     // If the proxy has changed from oldLp to newLp, resend proxy broadcast. This method gets called
4440     // when any network changes proxy.
4441     // TODO: Remove usage of broadcast extras as they are deprecated and not applicable in a
4442     // multi-network world where an app might be bound to a non-default network.
updateProxy(LinkProperties newLp, LinkProperties oldLp)4443     private void updateProxy(LinkProperties newLp, LinkProperties oldLp) {
4444         ProxyInfo newProxyInfo = newLp == null ? null : newLp.getHttpProxy();
4445         ProxyInfo oldProxyInfo = oldLp == null ? null : oldLp.getHttpProxy();
4446 
4447         if (!ProxyTracker.proxyInfoEqual(newProxyInfo, oldProxyInfo)) {
4448             mProxyTracker.sendProxyBroadcast();
4449         }
4450     }
4451 
4452     private static class SettingsObserver extends ContentObserver {
4453         final private HashMap<Uri, Integer> mUriEventMap;
4454         final private Context mContext;
4455         final private Handler mHandler;
4456 
SettingsObserver(Context context, Handler handler)4457         SettingsObserver(Context context, Handler handler) {
4458             super(null);
4459             mUriEventMap = new HashMap<>();
4460             mContext = context;
4461             mHandler = handler;
4462         }
4463 
observe(Uri uri, int what)4464         void observe(Uri uri, int what) {
4465             mUriEventMap.put(uri, what);
4466             final ContentResolver resolver = mContext.getContentResolver();
4467             resolver.registerContentObserver(uri, false, this);
4468         }
4469 
4470         @Override
onChange(boolean selfChange)4471         public void onChange(boolean selfChange) {
4472             Slog.wtf(TAG, "Should never be reached.");
4473         }
4474 
4475         @Override
onChange(boolean selfChange, Uri uri)4476         public void onChange(boolean selfChange, Uri uri) {
4477             final Integer what = mUriEventMap.get(uri);
4478             if (what != null) {
4479                 mHandler.obtainMessage(what).sendToTarget();
4480             } else {
4481                 loge("No matching event to send for URI=" + uri);
4482             }
4483         }
4484     }
4485 
log(String s)4486     private static void log(String s) {
4487         Slog.d(TAG, s);
4488     }
4489 
loge(String s)4490     private static void loge(String s) {
4491         Slog.e(TAG, s);
4492     }
4493 
loge(String s, Throwable t)4494     private static void loge(String s, Throwable t) {
4495         Slog.e(TAG, s, t);
4496     }
4497 
4498     /**
4499      * Prepare for a VPN application.
4500      * VPN permissions are checked in the {@link Vpn} class. If the caller is not {@code userId},
4501      * {@link android.Manifest.permission.INTERACT_ACROSS_USERS_FULL} permission is required.
4502      *
4503      * @param oldPackage Package name of the application which currently controls VPN, which will
4504      *                   be replaced. If there is no such application, this should should either be
4505      *                   {@code null} or {@link VpnConfig.LEGACY_VPN}.
4506      * @param newPackage Package name of the application which should gain control of VPN, or
4507      *                   {@code null} to disable.
4508      * @param userId User for whom to prepare the new VPN.
4509      *
4510      * @hide
4511      */
4512     @Override
prepareVpn(@ullable String oldPackage, @Nullable String newPackage, int userId)4513     public boolean prepareVpn(@Nullable String oldPackage, @Nullable String newPackage,
4514             int userId) {
4515         enforceCrossUserPermission(userId);
4516 
4517         synchronized (mVpns) {
4518             throwIfLockdownEnabled();
4519             Vpn vpn = mVpns.get(userId);
4520             if (vpn != null) {
4521                 return vpn.prepare(oldPackage, newPackage, VpnManager.TYPE_VPN_SERVICE);
4522             } else {
4523                 return false;
4524             }
4525         }
4526     }
4527 
4528     /**
4529      * Set whether the VPN package has the ability to launch VPNs without user intervention. This
4530      * method is used by system-privileged apps. VPN permissions are checked in the {@link Vpn}
4531      * class. If the caller is not {@code userId}, {@link
4532      * android.Manifest.permission.INTERACT_ACROSS_USERS_FULL} permission is required.
4533      *
4534      * @param packageName The package for which authorization state should change.
4535      * @param userId User for whom {@code packageName} is installed.
4536      * @param authorized {@code true} if this app should be able to start a VPN connection without
4537      *     explicit user approval, {@code false} if not.
4538      * @param vpnType The {@link VpnManager.VpnType} constant representing what class of VPN
4539      *     permissions should be granted. When unauthorizing an app, {@link
4540      *     VpnManager.TYPE_VPN_NONE} should be used.
4541      * @hide
4542      */
4543     @Override
setVpnPackageAuthorization( String packageName, int userId, @VpnManager.VpnType int vpnType)4544     public void setVpnPackageAuthorization(
4545             String packageName, int userId, @VpnManager.VpnType int vpnType) {
4546         enforceCrossUserPermission(userId);
4547 
4548         synchronized (mVpns) {
4549             Vpn vpn = mVpns.get(userId);
4550             if (vpn != null) {
4551                 vpn.setPackageAuthorization(packageName, vpnType);
4552             }
4553         }
4554     }
4555 
4556     /**
4557      * Configure a TUN interface and return its file descriptor. Parameters
4558      * are encoded and opaque to this class. This method is used by VpnBuilder
4559      * and not available in ConnectivityManager. Permissions are checked in
4560      * Vpn class.
4561      * @hide
4562      */
4563     @Override
establishVpn(VpnConfig config)4564     public ParcelFileDescriptor establishVpn(VpnConfig config) {
4565         int user = UserHandle.getUserId(Binder.getCallingUid());
4566         synchronized (mVpns) {
4567             throwIfLockdownEnabled();
4568             return mVpns.get(user).establish(config);
4569         }
4570     }
4571 
4572     /**
4573      * Stores the given VPN profile based on the provisioning package name.
4574      *
4575      * <p>If there is already a VPN profile stored for the provisioning package, this call will
4576      * overwrite the profile.
4577      *
4578      * <p>This is designed to serve the VpnManager only; settings-based VPN profiles are managed
4579      * exclusively by the Settings app, and passed into the platform at startup time.
4580      *
4581      * @return {@code true} if user consent has already been granted, {@code false} otherwise.
4582      * @hide
4583      */
4584     @Override
provisionVpnProfile(@onNull VpnProfile profile, @NonNull String packageName)4585     public boolean provisionVpnProfile(@NonNull VpnProfile profile, @NonNull String packageName) {
4586         final int user = UserHandle.getUserId(Binder.getCallingUid());
4587         synchronized (mVpns) {
4588             return mVpns.get(user).provisionVpnProfile(packageName, profile, mKeyStore);
4589         }
4590     }
4591 
4592     /**
4593      * Deletes the stored VPN profile for the provisioning package
4594      *
4595      * <p>If there are no profiles for the given package, this method will silently succeed.
4596      *
4597      * <p>This is designed to serve the VpnManager only; settings-based VPN profiles are managed
4598      * exclusively by the Settings app, and passed into the platform at startup time.
4599      *
4600      * @hide
4601      */
4602     @Override
deleteVpnProfile(@onNull String packageName)4603     public void deleteVpnProfile(@NonNull String packageName) {
4604         final int user = UserHandle.getUserId(Binder.getCallingUid());
4605         synchronized (mVpns) {
4606             mVpns.get(user).deleteVpnProfile(packageName, mKeyStore);
4607         }
4608     }
4609 
4610     /**
4611      * Starts the VPN based on the stored profile for the given package
4612      *
4613      * <p>This is designed to serve the VpnManager only; settings-based VPN profiles are managed
4614      * exclusively by the Settings app, and passed into the platform at startup time.
4615      *
4616      * @throws IllegalArgumentException if no profile was found for the given package name.
4617      * @hide
4618      */
4619     @Override
startVpnProfile(@onNull String packageName)4620     public void startVpnProfile(@NonNull String packageName) {
4621         final int user = UserHandle.getUserId(Binder.getCallingUid());
4622         synchronized (mVpns) {
4623             throwIfLockdownEnabled();
4624             mVpns.get(user).startVpnProfile(packageName, mKeyStore);
4625         }
4626     }
4627 
4628     /**
4629      * Stops the Platform VPN if the provided package is running one.
4630      *
4631      * <p>This is designed to serve the VpnManager only; settings-based VPN profiles are managed
4632      * exclusively by the Settings app, and passed into the platform at startup time.
4633      *
4634      * @hide
4635      */
4636     @Override
stopVpnProfile(@onNull String packageName)4637     public void stopVpnProfile(@NonNull String packageName) {
4638         final int user = UserHandle.getUserId(Binder.getCallingUid());
4639         synchronized (mVpns) {
4640             mVpns.get(user).stopVpnProfile(packageName);
4641         }
4642     }
4643 
4644     /**
4645      * Start legacy VPN, controlling native daemons as needed. Creates a
4646      * secondary thread to perform connection work, returning quickly.
4647      */
4648     @Override
startLegacyVpn(VpnProfile profile)4649     public void startLegacyVpn(VpnProfile profile) {
4650         int user = UserHandle.getUserId(Binder.getCallingUid());
4651         final LinkProperties egress = getActiveLinkProperties();
4652         if (egress == null) {
4653             throw new IllegalStateException("Missing active network connection");
4654         }
4655         synchronized (mVpns) {
4656             throwIfLockdownEnabled();
4657             mVpns.get(user).startLegacyVpn(profile, mKeyStore, egress);
4658         }
4659     }
4660 
4661     /**
4662      * Return the information of the ongoing legacy VPN. This method is used
4663      * by VpnSettings and not available in ConnectivityManager. Permissions
4664      * are checked in Vpn class.
4665      */
4666     @Override
getLegacyVpnInfo(int userId)4667     public LegacyVpnInfo getLegacyVpnInfo(int userId) {
4668         enforceCrossUserPermission(userId);
4669 
4670         synchronized (mVpns) {
4671             return mVpns.get(userId).getLegacyVpnInfo();
4672         }
4673     }
4674 
4675     /**
4676      * Return the information of all ongoing VPNs.
4677      *
4678      * <p>This method is used to update NetworkStatsService.
4679      *
4680      * <p>Must be called on the handler thread.
4681      */
getAllVpnInfo()4682     private VpnInfo[] getAllVpnInfo() {
4683         ensureRunningOnConnectivityServiceThread();
4684         synchronized (mVpns) {
4685             if (mLockdownEnabled) {
4686                 return new VpnInfo[0];
4687             }
4688 
4689             List<VpnInfo> infoList = new ArrayList<>();
4690             for (int i = 0; i < mVpns.size(); i++) {
4691                 VpnInfo info = createVpnInfo(mVpns.valueAt(i));
4692                 if (info != null) {
4693                     infoList.add(info);
4694                 }
4695             }
4696             return infoList.toArray(new VpnInfo[infoList.size()]);
4697         }
4698     }
4699 
4700     /**
4701      * @return VPN information for accounting, or null if we can't retrieve all required
4702      *         information, e.g underlying ifaces.
4703      */
4704     @Nullable
createVpnInfo(Vpn vpn)4705     private VpnInfo createVpnInfo(Vpn vpn) {
4706         VpnInfo info = vpn.getVpnInfo();
4707         if (info == null) {
4708             return null;
4709         }
4710         Network[] underlyingNetworks = vpn.getUnderlyingNetworks();
4711         // see VpnService.setUnderlyingNetworks()'s javadoc about how to interpret
4712         // the underlyingNetworks list.
4713         if (underlyingNetworks == null) {
4714             NetworkAgentInfo defaultNai = getDefaultNetwork();
4715             if (defaultNai != null) {
4716                 underlyingNetworks = new Network[] { defaultNai.network };
4717             }
4718         }
4719         if (underlyingNetworks != null && underlyingNetworks.length > 0) {
4720             List<String> interfaces = new ArrayList<>();
4721             for (Network network : underlyingNetworks) {
4722                 LinkProperties lp = getLinkProperties(network);
4723                 if (lp != null) {
4724                     for (String iface : lp.getAllInterfaceNames()) {
4725                         if (!TextUtils.isEmpty(iface)) {
4726                             interfaces.add(iface);
4727                         }
4728                     }
4729                 }
4730             }
4731             if (!interfaces.isEmpty()) {
4732                 info.underlyingIfaces = interfaces.toArray(new String[interfaces.size()]);
4733             }
4734         }
4735         return info.underlyingIfaces == null ? null : info;
4736     }
4737 
4738     /**
4739      * Returns the information of the ongoing VPN for {@code userId}. This method is used by
4740      * VpnDialogs and not available in ConnectivityManager.
4741      * Permissions are checked in Vpn class.
4742      * @hide
4743      */
4744     @Override
getVpnConfig(int userId)4745     public VpnConfig getVpnConfig(int userId) {
4746         enforceCrossUserPermission(userId);
4747         synchronized (mVpns) {
4748             Vpn vpn = mVpns.get(userId);
4749             if (vpn != null) {
4750                 return vpn.getVpnConfig();
4751             } else {
4752                 return null;
4753             }
4754         }
4755     }
4756 
4757     /**
4758      * Ask all VPN objects to recompute and update their capabilities.
4759      *
4760      * When underlying networks change, VPNs may have to update capabilities to reflect things
4761      * like the metered bit, their transports, and so on. This asks the VPN objects to update
4762      * their capabilities, and as this will cause them to send messages to the ConnectivityService
4763      * handler thread through their agent, this is asynchronous. When the capabilities objects
4764      * are computed they will be up-to-date as they are computed synchronously from here and
4765      * this is running on the ConnectivityService thread.
4766      */
updateAllVpnsCapabilities()4767     private void updateAllVpnsCapabilities() {
4768         Network defaultNetwork = getNetwork(getDefaultNetwork());
4769         synchronized (mVpns) {
4770             for (int i = 0; i < mVpns.size(); i++) {
4771                 final Vpn vpn = mVpns.valueAt(i);
4772                 NetworkCapabilities nc = vpn.updateCapabilities(defaultNetwork);
4773                 updateVpnCapabilities(vpn, nc);
4774             }
4775         }
4776     }
4777 
updateVpnCapabilities(Vpn vpn, @Nullable NetworkCapabilities nc)4778     private void updateVpnCapabilities(Vpn vpn, @Nullable NetworkCapabilities nc) {
4779         ensureRunningOnConnectivityServiceThread();
4780         NetworkAgentInfo vpnNai = getNetworkAgentInfoForNetId(vpn.getNetId());
4781         if (vpnNai == null || nc == null) {
4782             return;
4783         }
4784         updateCapabilities(vpnNai.getCurrentScore(), vpnNai, nc);
4785     }
4786 
4787     @Override
updateLockdownVpn()4788     public boolean updateLockdownVpn() {
4789         if (Binder.getCallingUid() != Process.SYSTEM_UID) {
4790             Slog.w(TAG, "Lockdown VPN only available to AID_SYSTEM");
4791             return false;
4792         }
4793 
4794         synchronized (mVpns) {
4795             // Tear down existing lockdown if profile was removed
4796             mLockdownEnabled = LockdownVpnTracker.isEnabled();
4797             if (mLockdownEnabled) {
4798                 byte[] profileTag = mKeyStore.get(Credentials.LOCKDOWN_VPN);
4799                 if (profileTag == null) {
4800                     Slog.e(TAG, "Lockdown VPN configured but cannot be read from keystore");
4801                     return false;
4802                 }
4803                 String profileName = new String(profileTag);
4804                 final VpnProfile profile = VpnProfile.decode(
4805                         profileName, mKeyStore.get(Credentials.VPN + profileName));
4806                 if (profile == null) {
4807                     Slog.e(TAG, "Lockdown VPN configured invalid profile " + profileName);
4808                     setLockdownTracker(null);
4809                     return true;
4810                 }
4811                 int user = UserHandle.getUserId(Binder.getCallingUid());
4812                 Vpn vpn = mVpns.get(user);
4813                 if (vpn == null) {
4814                     Slog.w(TAG, "VPN for user " + user + " not ready yet. Skipping lockdown");
4815                     return false;
4816                 }
4817                 setLockdownTracker(new LockdownVpnTracker(mContext, this, mHandler, vpn, profile));
4818             } else {
4819                 setLockdownTracker(null);
4820             }
4821         }
4822 
4823         return true;
4824     }
4825 
4826     /**
4827      * Internally set new {@link LockdownVpnTracker}, shutting down any existing
4828      * {@link LockdownVpnTracker}. Can be {@code null} to disable lockdown.
4829      */
4830     @GuardedBy("mVpns")
setLockdownTracker(LockdownVpnTracker tracker)4831     private void setLockdownTracker(LockdownVpnTracker tracker) {
4832         // Shutdown any existing tracker
4833         final LockdownVpnTracker existing = mLockdownTracker;
4834         // TODO: Add a trigger when the always-on VPN enable/disable to reevaluate and send the
4835         // necessary onBlockedStatusChanged callbacks.
4836         mLockdownTracker = null;
4837         if (existing != null) {
4838             existing.shutdown();
4839         }
4840 
4841         if (tracker != null) {
4842             mLockdownTracker = tracker;
4843             mLockdownTracker.init();
4844         }
4845     }
4846 
4847     /**
4848      * Throws if there is any currently running, always-on Legacy VPN.
4849      *
4850      * <p>The LockdownVpnTracker and mLockdownEnabled both track whether an always-on Legacy VPN is
4851      * running across the entire system. Tracking for app-based VPNs is done on a per-user,
4852      * per-package basis in Vpn.java
4853      */
4854     @GuardedBy("mVpns")
throwIfLockdownEnabled()4855     private void throwIfLockdownEnabled() {
4856         if (mLockdownEnabled) {
4857             throw new IllegalStateException("Unavailable in lockdown mode");
4858         }
4859     }
4860 
4861     /**
4862      * Starts the always-on VPN {@link VpnService} for user {@param userId}, which should perform
4863      * some setup and then call {@code establish()} to connect.
4864      *
4865      * @return {@code true} if the service was started, the service was already connected, or there
4866      *         was no always-on VPN to start. {@code false} otherwise.
4867      */
startAlwaysOnVpn(int userId)4868     private boolean startAlwaysOnVpn(int userId) {
4869         synchronized (mVpns) {
4870             Vpn vpn = mVpns.get(userId);
4871             if (vpn == null) {
4872                 // Shouldn't happen as all code paths that point here should have checked the Vpn
4873                 // exists already.
4874                 Slog.wtf(TAG, "User " + userId + " has no Vpn configuration");
4875                 return false;
4876             }
4877 
4878             return vpn.startAlwaysOnVpn(mKeyStore);
4879         }
4880     }
4881 
4882     @Override
isAlwaysOnVpnPackageSupported(int userId, String packageName)4883     public boolean isAlwaysOnVpnPackageSupported(int userId, String packageName) {
4884         enforceSettingsPermission();
4885         enforceCrossUserPermission(userId);
4886 
4887         synchronized (mVpns) {
4888             Vpn vpn = mVpns.get(userId);
4889             if (vpn == null) {
4890                 Slog.w(TAG, "User " + userId + " has no Vpn configuration");
4891                 return false;
4892             }
4893             return vpn.isAlwaysOnPackageSupported(packageName, mKeyStore);
4894         }
4895     }
4896 
4897     @Override
setAlwaysOnVpnPackage( int userId, String packageName, boolean lockdown, List<String> lockdownWhitelist)4898     public boolean setAlwaysOnVpnPackage(
4899             int userId, String packageName, boolean lockdown, List<String> lockdownWhitelist) {
4900         enforceControlAlwaysOnVpnPermission();
4901         enforceCrossUserPermission(userId);
4902 
4903         synchronized (mVpns) {
4904             // Can't set always-on VPN if legacy VPN is already in lockdown mode.
4905             if (LockdownVpnTracker.isEnabled()) {
4906                 return false;
4907             }
4908 
4909             Vpn vpn = mVpns.get(userId);
4910             if (vpn == null) {
4911                 Slog.w(TAG, "User " + userId + " has no Vpn configuration");
4912                 return false;
4913             }
4914             if (!vpn.setAlwaysOnPackage(packageName, lockdown, lockdownWhitelist, mKeyStore)) {
4915                 return false;
4916             }
4917             if (!startAlwaysOnVpn(userId)) {
4918                 vpn.setAlwaysOnPackage(null, false, null, mKeyStore);
4919                 return false;
4920             }
4921         }
4922         return true;
4923     }
4924 
4925     @Override
getAlwaysOnVpnPackage(int userId)4926     public String getAlwaysOnVpnPackage(int userId) {
4927         enforceControlAlwaysOnVpnPermission();
4928         enforceCrossUserPermission(userId);
4929 
4930         synchronized (mVpns) {
4931             Vpn vpn = mVpns.get(userId);
4932             if (vpn == null) {
4933                 Slog.w(TAG, "User " + userId + " has no Vpn configuration");
4934                 return null;
4935             }
4936             return vpn.getAlwaysOnPackage();
4937         }
4938     }
4939 
4940     @Override
isVpnLockdownEnabled(int userId)4941     public boolean isVpnLockdownEnabled(int userId) {
4942         enforceControlAlwaysOnVpnPermission();
4943         enforceCrossUserPermission(userId);
4944 
4945         synchronized (mVpns) {
4946             Vpn vpn = mVpns.get(userId);
4947             if (vpn == null) {
4948                 Slog.w(TAG, "User " + userId + " has no Vpn configuration");
4949                 return false;
4950             }
4951             return vpn.getLockdown();
4952         }
4953     }
4954 
4955     @Override
getVpnLockdownWhitelist(int userId)4956     public List<String> getVpnLockdownWhitelist(int userId) {
4957         enforceControlAlwaysOnVpnPermission();
4958         enforceCrossUserPermission(userId);
4959 
4960         synchronized (mVpns) {
4961             Vpn vpn = mVpns.get(userId);
4962             if (vpn == null) {
4963                 Slog.w(TAG, "User " + userId + " has no Vpn configuration");
4964                 return null;
4965             }
4966             return vpn.getLockdownWhitelist();
4967         }
4968     }
4969 
4970     @Override
checkMobileProvisioning(int suggestedTimeOutMs)4971     public int checkMobileProvisioning(int suggestedTimeOutMs) {
4972         // TODO: Remove?  Any reason to trigger a provisioning check?
4973         return -1;
4974     }
4975 
4976     /** Location to an updatable file listing carrier provisioning urls.
4977      *  An example:
4978      *
4979      * <?xml version="1.0" encoding="utf-8"?>
4980      *  <provisioningUrls>
4981      *   <provisioningUrl mcc="310" mnc="4">http://myserver.com/foo?mdn=%3$s&amp;iccid=%1$s&amp;imei=%2$s</provisioningUrl>
4982      *  </provisioningUrls>
4983      */
4984     private static final String PROVISIONING_URL_PATH =
4985             "/data/misc/radio/provisioning_urls.xml";
4986     private final File mProvisioningUrlFile = new File(PROVISIONING_URL_PATH);
4987 
4988     /** XML tag for root element. */
4989     private static final String TAG_PROVISIONING_URLS = "provisioningUrls";
4990     /** XML tag for individual url */
4991     private static final String TAG_PROVISIONING_URL = "provisioningUrl";
4992     /** XML attribute for mcc */
4993     private static final String ATTR_MCC = "mcc";
4994     /** XML attribute for mnc */
4995     private static final String ATTR_MNC = "mnc";
4996 
getProvisioningUrlBaseFromFile()4997     private String getProvisioningUrlBaseFromFile() {
4998         XmlPullParser parser;
4999         Configuration config = mContext.getResources().getConfiguration();
5000 
5001         try (FileReader fileReader = new FileReader(mProvisioningUrlFile)) {
5002             parser = Xml.newPullParser();
5003             parser.setInput(fileReader);
5004             XmlUtils.beginDocument(parser, TAG_PROVISIONING_URLS);
5005 
5006             while (true) {
5007                 XmlUtils.nextElement(parser);
5008 
5009                 String element = parser.getName();
5010                 if (element == null) break;
5011 
5012                 if (element.equals(TAG_PROVISIONING_URL)) {
5013                     String mcc = parser.getAttributeValue(null, ATTR_MCC);
5014                     try {
5015                         if (mcc != null && Integer.parseInt(mcc) == config.mcc) {
5016                             String mnc = parser.getAttributeValue(null, ATTR_MNC);
5017                             if (mnc != null && Integer.parseInt(mnc) == config.mnc) {
5018                                 parser.next();
5019                                 if (parser.getEventType() == XmlPullParser.TEXT) {
5020                                     return parser.getText();
5021                                 }
5022                             }
5023                         }
5024                     } catch (NumberFormatException e) {
5025                         loge("NumberFormatException in getProvisioningUrlBaseFromFile: " + e);
5026                     }
5027                 }
5028             }
5029             return null;
5030         } catch (FileNotFoundException e) {
5031             loge("Carrier Provisioning Urls file not found");
5032         } catch (XmlPullParserException e) {
5033             loge("Xml parser exception reading Carrier Provisioning Urls file: " + e);
5034         } catch (IOException e) {
5035             loge("I/O exception reading Carrier Provisioning Urls file: " + e);
5036         }
5037         return null;
5038     }
5039 
5040     @Override
getMobileProvisioningUrl()5041     public String getMobileProvisioningUrl() {
5042         enforceSettingsPermission();
5043         String url = getProvisioningUrlBaseFromFile();
5044         if (TextUtils.isEmpty(url)) {
5045             url = mContext.getResources().getString(R.string.mobile_provisioning_url);
5046             log("getMobileProvisioningUrl: mobile_provisioining_url from resource =" + url);
5047         } else {
5048             log("getMobileProvisioningUrl: mobile_provisioning_url from File =" + url);
5049         }
5050         // populate the iccid, imei and phone number in the provisioning url.
5051         if (!TextUtils.isEmpty(url)) {
5052             String phoneNumber = mTelephonyManager.getLine1Number();
5053             if (TextUtils.isEmpty(phoneNumber)) {
5054                 phoneNumber = "0000000000";
5055             }
5056             url = String.format(url,
5057                     mTelephonyManager.getSimSerialNumber() /* ICCID */,
5058                     mTelephonyManager.getDeviceId() /* IMEI */,
5059                     phoneNumber /* Phone number */);
5060         }
5061 
5062         return url;
5063     }
5064 
5065     @Override
setProvisioningNotificationVisible(boolean visible, int networkType, String action)5066     public void setProvisioningNotificationVisible(boolean visible, int networkType,
5067             String action) {
5068         enforceSettingsPermission();
5069         if (!ConnectivityManager.isNetworkTypeValid(networkType)) {
5070             return;
5071         }
5072         final long ident = Binder.clearCallingIdentity();
5073         try {
5074             // Concatenate the range of types onto the range of NetIDs.
5075             int id = NetIdManager.MAX_NET_ID + 1 + (networkType - ConnectivityManager.TYPE_NONE);
5076             mNotifier.setProvNotificationVisible(visible, id, action);
5077         } finally {
5078             Binder.restoreCallingIdentity(ident);
5079         }
5080     }
5081 
5082     @Override
setAirplaneMode(boolean enable)5083     public void setAirplaneMode(boolean enable) {
5084         enforceAirplaneModePermission();
5085         final long ident = Binder.clearCallingIdentity();
5086         try {
5087             final ContentResolver cr = mContext.getContentResolver();
5088             Settings.Global.putInt(cr, Settings.Global.AIRPLANE_MODE_ON, encodeBool(enable));
5089             Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
5090             intent.putExtra("state", enable);
5091             mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
5092         } finally {
5093             Binder.restoreCallingIdentity(ident);
5094         }
5095     }
5096 
onUserStart(int userId)5097     private void onUserStart(int userId) {
5098         synchronized (mVpns) {
5099             Vpn userVpn = mVpns.get(userId);
5100             if (userVpn != null) {
5101                 loge("Starting user already has a VPN");
5102                 return;
5103             }
5104             userVpn = new Vpn(mHandler.getLooper(), mContext, mNMS, userId, mKeyStore);
5105             mVpns.put(userId, userVpn);
5106             if (mUserManager.getUserInfo(userId).isPrimary() && LockdownVpnTracker.isEnabled()) {
5107                 updateLockdownVpn();
5108             }
5109         }
5110     }
5111 
onUserStop(int userId)5112     private void onUserStop(int userId) {
5113         synchronized (mVpns) {
5114             Vpn userVpn = mVpns.get(userId);
5115             if (userVpn == null) {
5116                 loge("Stopped user has no VPN");
5117                 return;
5118             }
5119             userVpn.onUserStopped();
5120             mVpns.delete(userId);
5121         }
5122     }
5123 
onUserAdded(int userId)5124     private void onUserAdded(int userId) {
5125         mPermissionMonitor.onUserAdded(userId);
5126         Network defaultNetwork = getNetwork(getDefaultNetwork());
5127         synchronized (mVpns) {
5128             final int vpnsSize = mVpns.size();
5129             for (int i = 0; i < vpnsSize; i++) {
5130                 Vpn vpn = mVpns.valueAt(i);
5131                 vpn.onUserAdded(userId);
5132                 NetworkCapabilities nc = vpn.updateCapabilities(defaultNetwork);
5133                 updateVpnCapabilities(vpn, nc);
5134             }
5135         }
5136     }
5137 
onUserRemoved(int userId)5138     private void onUserRemoved(int userId) {
5139         mPermissionMonitor.onUserRemoved(userId);
5140         Network defaultNetwork = getNetwork(getDefaultNetwork());
5141         synchronized (mVpns) {
5142             final int vpnsSize = mVpns.size();
5143             for (int i = 0; i < vpnsSize; i++) {
5144                 Vpn vpn = mVpns.valueAt(i);
5145                 vpn.onUserRemoved(userId);
5146                 NetworkCapabilities nc = vpn.updateCapabilities(defaultNetwork);
5147                 updateVpnCapabilities(vpn, nc);
5148             }
5149         }
5150     }
5151 
onPackageAdded(String packageName, int uid)5152     private void onPackageAdded(String packageName, int uid) {
5153         if (TextUtils.isEmpty(packageName) || uid < 0) {
5154             Slog.wtf(TAG, "Invalid package in onPackageAdded: " + packageName + " | " + uid);
5155             return;
5156         }
5157         mPermissionMonitor.onPackageAdded(packageName, uid);
5158     }
5159 
onPackageReplaced(String packageName, int uid)5160     private void onPackageReplaced(String packageName, int uid) {
5161         if (TextUtils.isEmpty(packageName) || uid < 0) {
5162             Slog.wtf(TAG, "Invalid package in onPackageReplaced: " + packageName + " | " + uid);
5163             return;
5164         }
5165         final int userId = UserHandle.getUserId(uid);
5166         synchronized (mVpns) {
5167             final Vpn vpn = mVpns.get(userId);
5168             if (vpn == null) {
5169                 return;
5170             }
5171             // Legacy always-on VPN won't be affected since the package name is not set.
5172             if (TextUtils.equals(vpn.getAlwaysOnPackage(), packageName)) {
5173                 Slog.d(TAG, "Restarting always-on VPN package " + packageName + " for user "
5174                         + userId);
5175                 vpn.startAlwaysOnVpn(mKeyStore);
5176             }
5177         }
5178     }
5179 
onPackageRemoved(String packageName, int uid, boolean isReplacing)5180     private void onPackageRemoved(String packageName, int uid, boolean isReplacing) {
5181         if (TextUtils.isEmpty(packageName) || uid < 0) {
5182             Slog.wtf(TAG, "Invalid package in onPackageRemoved: " + packageName + " | " + uid);
5183             return;
5184         }
5185         mPermissionMonitor.onPackageRemoved(uid);
5186 
5187         final int userId = UserHandle.getUserId(uid);
5188         synchronized (mVpns) {
5189             final Vpn vpn = mVpns.get(userId);
5190             if (vpn == null) {
5191                 return;
5192             }
5193             // Legacy always-on VPN won't be affected since the package name is not set.
5194             if (TextUtils.equals(vpn.getAlwaysOnPackage(), packageName) && !isReplacing) {
5195                 Slog.d(TAG, "Removing always-on VPN package " + packageName + " for user "
5196                         + userId);
5197                 vpn.setAlwaysOnPackage(null, false, null, mKeyStore);
5198             }
5199         }
5200     }
5201 
onUserUnlocked(int userId)5202     private void onUserUnlocked(int userId) {
5203         synchronized (mVpns) {
5204             // User present may be sent because of an unlock, which might mean an unlocked keystore.
5205             if (mUserManager.getUserInfo(userId).isPrimary() && LockdownVpnTracker.isEnabled()) {
5206                 updateLockdownVpn();
5207             } else {
5208                 startAlwaysOnVpn(userId);
5209             }
5210         }
5211     }
5212 
5213     private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
5214         @Override
5215         public void onReceive(Context context, Intent intent) {
5216             ensureRunningOnConnectivityServiceThread();
5217             final String action = intent.getAction();
5218             final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
5219             final int uid = intent.getIntExtra(Intent.EXTRA_UID, -1);
5220             final Uri packageData = intent.getData();
5221             final String packageName =
5222                     packageData != null ? packageData.getSchemeSpecificPart() : null;
5223             if (userId == UserHandle.USER_NULL) return;
5224 
5225             if (Intent.ACTION_USER_STARTED.equals(action)) {
5226                 onUserStart(userId);
5227             } else if (Intent.ACTION_USER_STOPPED.equals(action)) {
5228                 onUserStop(userId);
5229             } else if (Intent.ACTION_USER_ADDED.equals(action)) {
5230                 onUserAdded(userId);
5231             } else if (Intent.ACTION_USER_REMOVED.equals(action)) {
5232                 onUserRemoved(userId);
5233             } else if (Intent.ACTION_USER_UNLOCKED.equals(action)) {
5234                 onUserUnlocked(userId);
5235             } else if (Intent.ACTION_PACKAGE_ADDED.equals(action)) {
5236                 onPackageAdded(packageName, uid);
5237             } else if (Intent.ACTION_PACKAGE_REPLACED.equals(action)) {
5238                 onPackageReplaced(packageName, uid);
5239             } else if (Intent.ACTION_PACKAGE_REMOVED.equals(action)) {
5240                 final boolean isReplacing = intent.getBooleanExtra(
5241                         Intent.EXTRA_REPLACING, false);
5242                 onPackageRemoved(packageName, uid, isReplacing);
5243             }
5244         }
5245     };
5246 
5247     private BroadcastReceiver mUserPresentReceiver = new BroadcastReceiver() {
5248         @Override
5249         public void onReceive(Context context, Intent intent) {
5250             // Try creating lockdown tracker, since user present usually means
5251             // unlocked keystore.
5252             updateLockdownVpn();
5253             mContext.unregisterReceiver(this);
5254         }
5255     };
5256 
5257     private final HashMap<Messenger, NetworkProviderInfo> mNetworkProviderInfos = new HashMap<>();
5258     private final HashMap<NetworkRequest, NetworkRequestInfo> mNetworkRequests = new HashMap<>();
5259 
5260     private static final int MAX_NETWORK_REQUESTS_PER_UID = 100;
5261     // Map from UID to number of NetworkRequests that UID has filed.
5262     @GuardedBy("mUidToNetworkRequestCount")
5263     private final SparseIntArray mUidToNetworkRequestCount = new SparseIntArray();
5264 
5265     private static class NetworkProviderInfo {
5266         public final String name;
5267         public final Messenger messenger;
5268         private final AsyncChannel mAsyncChannel;
5269         private final IBinder.DeathRecipient mDeathRecipient;
5270         public final int providerId;
5271 
NetworkProviderInfo(String name, Messenger messenger, AsyncChannel asyncChannel, int providerId, IBinder.DeathRecipient deathRecipient)5272         NetworkProviderInfo(String name, Messenger messenger, AsyncChannel asyncChannel,
5273                 int providerId, IBinder.DeathRecipient deathRecipient) {
5274             this.name = name;
5275             this.messenger = messenger;
5276             this.providerId = providerId;
5277             mAsyncChannel = asyncChannel;
5278             mDeathRecipient = deathRecipient;
5279 
5280             if ((mAsyncChannel == null) == (mDeathRecipient == null)) {
5281                 throw new AssertionError("Must pass exactly one of asyncChannel or deathRecipient");
5282             }
5283         }
5284 
isLegacyNetworkFactory()5285         boolean isLegacyNetworkFactory() {
5286             return mAsyncChannel != null;
5287         }
5288 
sendMessageToNetworkProvider(int what, int arg1, int arg2, Object obj)5289         void sendMessageToNetworkProvider(int what, int arg1, int arg2, Object obj) {
5290             try {
5291                 messenger.send(Message.obtain(null /* handler */, what, arg1, arg2, obj));
5292             } catch (RemoteException e) {
5293                 // Remote process died. Ignore; the death recipient will remove this
5294                 // NetworkProviderInfo from mNetworkProviderInfos.
5295             }
5296         }
5297 
requestNetwork(NetworkRequest request, int score, int servingProviderId)5298         void requestNetwork(NetworkRequest request, int score, int servingProviderId) {
5299             if (isLegacyNetworkFactory()) {
5300                 mAsyncChannel.sendMessage(android.net.NetworkFactory.CMD_REQUEST_NETWORK, score,
5301                         servingProviderId, request);
5302             } else {
5303                 sendMessageToNetworkProvider(NetworkProvider.CMD_REQUEST_NETWORK, score,
5304                             servingProviderId, request);
5305             }
5306         }
5307 
cancelRequest(NetworkRequest request)5308         void cancelRequest(NetworkRequest request) {
5309             if (isLegacyNetworkFactory()) {
5310                 mAsyncChannel.sendMessage(android.net.NetworkFactory.CMD_CANCEL_REQUEST, request);
5311             } else {
5312                 sendMessageToNetworkProvider(NetworkProvider.CMD_CANCEL_REQUEST, 0, 0, request);
5313             }
5314         }
5315 
connect(Context context, Handler handler)5316         void connect(Context context, Handler handler) {
5317             if (isLegacyNetworkFactory()) {
5318                 mAsyncChannel.connect(context, handler, messenger);
5319             } else {
5320                 try {
5321                     messenger.getBinder().linkToDeath(mDeathRecipient, 0);
5322                 } catch (RemoteException e) {
5323                     mDeathRecipient.binderDied();
5324                 }
5325             }
5326         }
5327 
completeConnection()5328         void completeConnection() {
5329             if (isLegacyNetworkFactory()) {
5330                 mAsyncChannel.sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION);
5331             }
5332         }
5333     }
5334 
ensureNetworkRequestHasType(NetworkRequest request)5335     private void ensureNetworkRequestHasType(NetworkRequest request) {
5336         if (request.type == NetworkRequest.Type.NONE) {
5337             throw new IllegalArgumentException(
5338                     "All NetworkRequests in ConnectivityService must have a type");
5339         }
5340     }
5341 
5342     /**
5343      * Tracks info about the requester.
5344      * Also used to notice when the calling process dies so we can self-expire
5345      */
5346     private class NetworkRequestInfo implements IBinder.DeathRecipient {
5347         final NetworkRequest request;
5348         // The network currently satisfying this request, or null if none. Must only be touched
5349         // on the handler thread. This only makes sense for network requests and not for listens,
5350         // as defined by NetworkRequest#isRequest(). For listens, this is always null.
5351         @Nullable
5352         NetworkAgentInfo mSatisfier;
5353         final PendingIntent mPendingIntent;
5354         boolean mPendingIntentSent;
5355         private final IBinder mBinder;
5356         final int mPid;
5357         final int mUid;
5358         final Messenger messenger;
5359 
NetworkRequestInfo(NetworkRequest r, PendingIntent pi)5360         NetworkRequestInfo(NetworkRequest r, PendingIntent pi) {
5361             request = r;
5362             ensureNetworkRequestHasType(request);
5363             mPendingIntent = pi;
5364             messenger = null;
5365             mBinder = null;
5366             mPid = getCallingPid();
5367             mUid = getCallingUid();
5368             enforceRequestCountLimit();
5369         }
5370 
NetworkRequestInfo(Messenger m, NetworkRequest r, IBinder binder)5371         NetworkRequestInfo(Messenger m, NetworkRequest r, IBinder binder) {
5372             super();
5373             messenger = m;
5374             request = r;
5375             ensureNetworkRequestHasType(request);
5376             mBinder = binder;
5377             mPid = getCallingPid();
5378             mUid = getCallingUid();
5379             mPendingIntent = null;
5380             enforceRequestCountLimit();
5381 
5382             try {
5383                 mBinder.linkToDeath(this, 0);
5384             } catch (RemoteException e) {
5385                 binderDied();
5386             }
5387         }
5388 
NetworkRequestInfo(NetworkRequest r)5389         NetworkRequestInfo(NetworkRequest r) {
5390             this(r, null);
5391         }
5392 
enforceRequestCountLimit()5393         private void enforceRequestCountLimit() {
5394             synchronized (mUidToNetworkRequestCount) {
5395                 int networkRequests = mUidToNetworkRequestCount.get(mUid, 0) + 1;
5396                 if (networkRequests >= MAX_NETWORK_REQUESTS_PER_UID) {
5397                     throw new ServiceSpecificException(
5398                             ConnectivityManager.Errors.TOO_MANY_REQUESTS);
5399                 }
5400                 mUidToNetworkRequestCount.put(mUid, networkRequests);
5401             }
5402         }
5403 
unlinkDeathRecipient()5404         void unlinkDeathRecipient() {
5405             if (mBinder != null) {
5406                 mBinder.unlinkToDeath(this, 0);
5407             }
5408         }
5409 
binderDied()5410         public void binderDied() {
5411             log("ConnectivityService NetworkRequestInfo binderDied(" +
5412                     request + ", " + mBinder + ")");
5413             releaseNetworkRequest(request);
5414         }
5415 
toString()5416         public String toString() {
5417             return "uid/pid:" + mUid + "/" + mPid + " " + request
5418                     + (mPendingIntent == null ? "" : " to trigger " + mPendingIntent);
5419         }
5420     }
5421 
ensureRequestableCapabilities(NetworkCapabilities networkCapabilities)5422     private void ensureRequestableCapabilities(NetworkCapabilities networkCapabilities) {
5423         final String badCapability = networkCapabilities.describeFirstNonRequestableCapability();
5424         if (badCapability != null) {
5425             throw new IllegalArgumentException("Cannot request network with " + badCapability);
5426         }
5427     }
5428 
5429     // This checks that the passed capabilities either do not request a
5430     // specific SSID/SignalStrength, or the calling app has permission to do so.
ensureSufficientPermissionsForRequest(NetworkCapabilities nc, int callerPid, int callerUid, String callerPackageName)5431     private void ensureSufficientPermissionsForRequest(NetworkCapabilities nc,
5432             int callerPid, int callerUid, String callerPackageName) {
5433         if (null != nc.getSsid() && !checkSettingsPermission(callerPid, callerUid)) {
5434             throw new SecurityException("Insufficient permissions to request a specific SSID");
5435         }
5436 
5437         if (nc.hasSignalStrength()
5438                 && !checkNetworkSignalStrengthWakeupPermission(callerPid, callerUid)) {
5439             throw new SecurityException(
5440                     "Insufficient permissions to request a specific signal strength");
5441         }
5442         mAppOpsManager.checkPackage(callerUid, callerPackageName);
5443     }
5444 
getSignalStrengthThresholds(NetworkAgentInfo nai)5445     private ArrayList<Integer> getSignalStrengthThresholds(NetworkAgentInfo nai) {
5446         final SortedSet<Integer> thresholds = new TreeSet<>();
5447         synchronized (nai) {
5448             for (NetworkRequestInfo nri : mNetworkRequests.values()) {
5449                 if (nri.request.networkCapabilities.hasSignalStrength() &&
5450                         nai.satisfiesImmutableCapabilitiesOf(nri.request)) {
5451                     thresholds.add(nri.request.networkCapabilities.getSignalStrength());
5452                 }
5453             }
5454         }
5455         return new ArrayList<>(thresholds);
5456     }
5457 
updateSignalStrengthThresholds( NetworkAgentInfo nai, String reason, NetworkRequest request)5458     private void updateSignalStrengthThresholds(
5459             NetworkAgentInfo nai, String reason, NetworkRequest request) {
5460         ArrayList<Integer> thresholdsArray = getSignalStrengthThresholds(nai);
5461         Bundle thresholds = new Bundle();
5462         thresholds.putIntegerArrayList("thresholds", thresholdsArray);
5463 
5464         if (VDBG || (DBG && !"CONNECT".equals(reason))) {
5465             String detail;
5466             if (request != null && request.networkCapabilities.hasSignalStrength()) {
5467                 detail = reason + " " + request.networkCapabilities.getSignalStrength();
5468             } else {
5469                 detail = reason;
5470             }
5471             log(String.format("updateSignalStrengthThresholds: %s, sending %s to %s",
5472                     detail, Arrays.toString(thresholdsArray.toArray()), nai.toShortString()));
5473         }
5474 
5475         nai.asyncChannel.sendMessage(
5476                 android.net.NetworkAgent.CMD_SET_SIGNAL_STRENGTH_THRESHOLDS,
5477                 0, 0, thresholds);
5478     }
5479 
ensureValidNetworkSpecifier(NetworkCapabilities nc)5480     private void ensureValidNetworkSpecifier(NetworkCapabilities nc) {
5481         if (nc == null) {
5482             return;
5483         }
5484         NetworkSpecifier ns = nc.getNetworkSpecifier();
5485         if (ns == null) {
5486             return;
5487         }
5488         MatchAllNetworkSpecifier.checkNotMatchAllNetworkSpecifier(ns);
5489     }
5490 
ensureValid(NetworkCapabilities nc)5491     private void ensureValid(NetworkCapabilities nc) {
5492         ensureValidNetworkSpecifier(nc);
5493         if (nc.isPrivateDnsBroken()) {
5494             throw new IllegalArgumentException("Can't request broken private DNS");
5495         }
5496     }
5497 
checkUnsupportedStartingFrom(int version, String callingPackageName)5498     private boolean checkUnsupportedStartingFrom(int version, String callingPackageName) {
5499         final PackageManager pm = mContext.getPackageManager();
5500         final int userId = UserHandle.getCallingUserId();
5501         try {
5502             final int callingVersion = pm.getApplicationInfoAsUser(
5503                     callingPackageName, 0 /* flags */, userId).targetSdkVersion;
5504             if (callingVersion < version) return false;
5505         } catch (PackageManager.NameNotFoundException e) { }
5506         return true;
5507     }
5508 
5509     @Override
requestNetwork(NetworkCapabilities networkCapabilities, Messenger messenger, int timeoutMs, IBinder binder, int legacyType, @NonNull String callingPackageName)5510     public NetworkRequest requestNetwork(NetworkCapabilities networkCapabilities,
5511             Messenger messenger, int timeoutMs, IBinder binder, int legacyType,
5512             @NonNull String callingPackageName) {
5513         if (legacyType != TYPE_NONE && !checkNetworkStackPermission()) {
5514             if (checkUnsupportedStartingFrom(Build.VERSION_CODES.M, callingPackageName)) {
5515                 throw new SecurityException("Insufficient permissions to specify legacy type");
5516             }
5517         }
5518         final int callingUid = Binder.getCallingUid();
5519         final NetworkRequest.Type type = (networkCapabilities == null)
5520                 ? NetworkRequest.Type.TRACK_DEFAULT
5521                 : NetworkRequest.Type.REQUEST;
5522         // If the requested networkCapabilities is null, take them instead from
5523         // the default network request. This allows callers to keep track of
5524         // the system default network.
5525         if (type == NetworkRequest.Type.TRACK_DEFAULT) {
5526             networkCapabilities = createDefaultNetworkCapabilitiesForUid(callingUid);
5527             enforceAccessPermission();
5528         } else {
5529             networkCapabilities = new NetworkCapabilities(networkCapabilities);
5530             enforceNetworkRequestPermissions(networkCapabilities);
5531             // TODO: this is incorrect. We mark the request as metered or not depending on the state
5532             // of the app when the request is filed, but we never change the request if the app
5533             // changes network state. http://b/29964605
5534             enforceMeteredApnPolicy(networkCapabilities);
5535         }
5536         ensureRequestableCapabilities(networkCapabilities);
5537         ensureSufficientPermissionsForRequest(networkCapabilities,
5538                 Binder.getCallingPid(), callingUid, callingPackageName);
5539         // Set the UID range for this request to the single UID of the requester, or to an empty
5540         // set of UIDs if the caller has the appropriate permission and UIDs have not been set.
5541         // This will overwrite any allowed UIDs in the requested capabilities. Though there
5542         // are no visible methods to set the UIDs, an app could use reflection to try and get
5543         // networks for other apps so it's essential that the UIDs are overwritten.
5544         restrictRequestUidsForCallerAndSetRequestorInfo(networkCapabilities,
5545                 callingUid, callingPackageName);
5546 
5547         if (timeoutMs < 0) {
5548             throw new IllegalArgumentException("Bad timeout specified");
5549         }
5550         ensureValid(networkCapabilities);
5551 
5552         NetworkRequest networkRequest = new NetworkRequest(networkCapabilities, legacyType,
5553                 nextNetworkRequestId(), type);
5554         NetworkRequestInfo nri = new NetworkRequestInfo(messenger, networkRequest, binder);
5555         if (DBG) log("requestNetwork for " + nri);
5556 
5557         mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_REQUEST, nri));
5558         if (timeoutMs > 0) {
5559             mHandler.sendMessageDelayed(mHandler.obtainMessage(EVENT_TIMEOUT_NETWORK_REQUEST,
5560                     nri), timeoutMs);
5561         }
5562         return networkRequest;
5563     }
5564 
enforceNetworkRequestPermissions(NetworkCapabilities networkCapabilities)5565     private void enforceNetworkRequestPermissions(NetworkCapabilities networkCapabilities) {
5566         if (networkCapabilities.hasCapability(NET_CAPABILITY_NOT_RESTRICTED) == false) {
5567             enforceConnectivityRestrictedNetworksPermission();
5568         } else {
5569             enforceChangePermission();
5570         }
5571     }
5572 
5573     @Override
requestBandwidthUpdate(Network network)5574     public boolean requestBandwidthUpdate(Network network) {
5575         enforceAccessPermission();
5576         NetworkAgentInfo nai = null;
5577         if (network == null) {
5578             return false;
5579         }
5580         synchronized (mNetworkForNetId) {
5581             nai = mNetworkForNetId.get(network.netId);
5582         }
5583         if (nai != null) {
5584             nai.asyncChannel.sendMessage(android.net.NetworkAgent.CMD_REQUEST_BANDWIDTH_UPDATE);
5585             synchronized (mBandwidthRequests) {
5586                 final int uid = Binder.getCallingUid();
5587                 Integer uidReqs = mBandwidthRequests.get(uid);
5588                 if (uidReqs == null) {
5589                     uidReqs = 0;
5590                 }
5591                 mBandwidthRequests.put(uid, ++uidReqs);
5592             }
5593             return true;
5594         }
5595         return false;
5596     }
5597 
isSystem(int uid)5598     private boolean isSystem(int uid) {
5599         return uid < Process.FIRST_APPLICATION_UID;
5600     }
5601 
enforceMeteredApnPolicy(NetworkCapabilities networkCapabilities)5602     private void enforceMeteredApnPolicy(NetworkCapabilities networkCapabilities) {
5603         final int uid = Binder.getCallingUid();
5604         if (isSystem(uid)) {
5605             // Exemption for system uid.
5606             return;
5607         }
5608         if (networkCapabilities.hasCapability(NET_CAPABILITY_NOT_METERED)) {
5609             // Policy already enforced.
5610             return;
5611         }
5612         if (mPolicyManagerInternal.isUidRestrictedOnMeteredNetworks(uid)) {
5613             // If UID is restricted, don't allow them to bring up metered APNs.
5614             networkCapabilities.addCapability(NET_CAPABILITY_NOT_METERED);
5615         }
5616     }
5617 
5618     @Override
pendingRequestForNetwork(NetworkCapabilities networkCapabilities, PendingIntent operation, @NonNull String callingPackageName)5619     public NetworkRequest pendingRequestForNetwork(NetworkCapabilities networkCapabilities,
5620             PendingIntent operation, @NonNull String callingPackageName) {
5621         Objects.requireNonNull(operation, "PendingIntent cannot be null.");
5622         final int callingUid = Binder.getCallingUid();
5623         networkCapabilities = new NetworkCapabilities(networkCapabilities);
5624         enforceNetworkRequestPermissions(networkCapabilities);
5625         enforceMeteredApnPolicy(networkCapabilities);
5626         ensureRequestableCapabilities(networkCapabilities);
5627         ensureSufficientPermissionsForRequest(networkCapabilities,
5628                 Binder.getCallingPid(), callingUid, callingPackageName);
5629         ensureValidNetworkSpecifier(networkCapabilities);
5630         restrictRequestUidsForCallerAndSetRequestorInfo(networkCapabilities,
5631                 callingUid, callingPackageName);
5632 
5633         NetworkRequest networkRequest = new NetworkRequest(networkCapabilities, TYPE_NONE,
5634                 nextNetworkRequestId(), NetworkRequest.Type.REQUEST);
5635         NetworkRequestInfo nri = new NetworkRequestInfo(networkRequest, operation);
5636         if (DBG) log("pendingRequest for " + nri);
5637         mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_REQUEST_WITH_INTENT,
5638                 nri));
5639         return networkRequest;
5640     }
5641 
releasePendingNetworkRequestWithDelay(PendingIntent operation)5642     private void releasePendingNetworkRequestWithDelay(PendingIntent operation) {
5643         mHandler.sendMessageDelayed(
5644                 mHandler.obtainMessage(EVENT_RELEASE_NETWORK_REQUEST_WITH_INTENT,
5645                 getCallingUid(), 0, operation), mReleasePendingIntentDelayMs);
5646     }
5647 
5648     @Override
releasePendingNetworkRequest(PendingIntent operation)5649     public void releasePendingNetworkRequest(PendingIntent operation) {
5650         Objects.requireNonNull(operation, "PendingIntent cannot be null.");
5651         mHandler.sendMessage(mHandler.obtainMessage(EVENT_RELEASE_NETWORK_REQUEST_WITH_INTENT,
5652                 getCallingUid(), 0, operation));
5653     }
5654 
5655     // In order to implement the compatibility measure for pre-M apps that call
5656     // WifiManager.enableNetwork(..., true) without also binding to that network explicitly,
5657     // WifiManager registers a network listen for the purpose of calling setProcessDefaultNetwork.
5658     // This ensures it has permission to do so.
hasWifiNetworkListenPermission(NetworkCapabilities nc)5659     private boolean hasWifiNetworkListenPermission(NetworkCapabilities nc) {
5660         if (nc == null) {
5661             return false;
5662         }
5663         int[] transportTypes = nc.getTransportTypes();
5664         if (transportTypes.length != 1 || transportTypes[0] != NetworkCapabilities.TRANSPORT_WIFI) {
5665             return false;
5666         }
5667         try {
5668             mContext.enforceCallingOrSelfPermission(
5669                     android.Manifest.permission.ACCESS_WIFI_STATE,
5670                     "ConnectivityService");
5671         } catch (SecurityException e) {
5672             return false;
5673         }
5674         return true;
5675     }
5676 
5677     @Override
listenForNetwork(NetworkCapabilities networkCapabilities, Messenger messenger, IBinder binder, @NonNull String callingPackageName)5678     public NetworkRequest listenForNetwork(NetworkCapabilities networkCapabilities,
5679             Messenger messenger, IBinder binder, @NonNull String callingPackageName) {
5680         final int callingUid = Binder.getCallingUid();
5681         if (!hasWifiNetworkListenPermission(networkCapabilities)) {
5682             enforceAccessPermission();
5683         }
5684 
5685         NetworkCapabilities nc = new NetworkCapabilities(networkCapabilities);
5686         ensureSufficientPermissionsForRequest(networkCapabilities,
5687                 Binder.getCallingPid(), callingUid, callingPackageName);
5688         restrictRequestUidsForCallerAndSetRequestorInfo(nc, callingUid, callingPackageName);
5689         // Apps without the CHANGE_NETWORK_STATE permission can't use background networks, so
5690         // make all their listens include NET_CAPABILITY_FOREGROUND. That way, they will get
5691         // onLost and onAvailable callbacks when networks move in and out of the background.
5692         // There is no need to do this for requests because an app without CHANGE_NETWORK_STATE
5693         // can't request networks.
5694         restrictBackgroundRequestForCaller(nc);
5695         ensureValid(nc);
5696 
5697         NetworkRequest networkRequest = new NetworkRequest(nc, TYPE_NONE, nextNetworkRequestId(),
5698                 NetworkRequest.Type.LISTEN);
5699         NetworkRequestInfo nri = new NetworkRequestInfo(messenger, networkRequest, binder);
5700         if (VDBG) log("listenForNetwork for " + nri);
5701 
5702         mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_LISTENER, nri));
5703         return networkRequest;
5704     }
5705 
5706     @Override
pendingListenForNetwork(NetworkCapabilities networkCapabilities, PendingIntent operation, @NonNull String callingPackageName)5707     public void pendingListenForNetwork(NetworkCapabilities networkCapabilities,
5708             PendingIntent operation, @NonNull String callingPackageName) {
5709         Objects.requireNonNull(operation, "PendingIntent cannot be null.");
5710         final int callingUid = Binder.getCallingUid();
5711         if (!hasWifiNetworkListenPermission(networkCapabilities)) {
5712             enforceAccessPermission();
5713         }
5714         ensureValid(networkCapabilities);
5715         ensureSufficientPermissionsForRequest(networkCapabilities,
5716                 Binder.getCallingPid(), callingUid, callingPackageName);
5717         final NetworkCapabilities nc = new NetworkCapabilities(networkCapabilities);
5718         restrictRequestUidsForCallerAndSetRequestorInfo(nc, callingUid, callingPackageName);
5719 
5720         NetworkRequest networkRequest = new NetworkRequest(nc, TYPE_NONE, nextNetworkRequestId(),
5721                 NetworkRequest.Type.LISTEN);
5722         NetworkRequestInfo nri = new NetworkRequestInfo(networkRequest, operation);
5723         if (VDBG) log("pendingListenForNetwork for " + nri);
5724 
5725         mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_LISTENER, nri));
5726     }
5727 
5728     /** Returns the next Network provider ID. */
nextNetworkProviderId()5729     public final int nextNetworkProviderId() {
5730         return mNextNetworkProviderId.getAndIncrement();
5731     }
5732 
5733     @Override
releaseNetworkRequest(NetworkRequest networkRequest)5734     public void releaseNetworkRequest(NetworkRequest networkRequest) {
5735         ensureNetworkRequestHasType(networkRequest);
5736         mHandler.sendMessage(mHandler.obtainMessage(
5737                 EVENT_RELEASE_NETWORK_REQUEST, getCallingUid(), 0, networkRequest));
5738     }
5739 
5740     @Override
registerNetworkFactory(Messenger messenger, String name)5741     public int registerNetworkFactory(Messenger messenger, String name) {
5742         enforceNetworkFactoryPermission();
5743         NetworkProviderInfo npi = new NetworkProviderInfo(name, messenger, new AsyncChannel(),
5744                 nextNetworkProviderId(), null /* deathRecipient */);
5745         mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_PROVIDER, npi));
5746         return npi.providerId;
5747     }
5748 
handleRegisterNetworkProvider(NetworkProviderInfo npi)5749     private void handleRegisterNetworkProvider(NetworkProviderInfo npi) {
5750         if (mNetworkProviderInfos.containsKey(npi.messenger)) {
5751             // Avoid creating duplicates. even if an app makes a direct AIDL call.
5752             // This will never happen if an app calls ConnectivityManager#registerNetworkProvider,
5753             // as that will throw if a duplicate provider is registered.
5754             Slog.e(TAG, "Attempt to register existing NetworkProviderInfo "
5755                     + mNetworkProviderInfos.get(npi.messenger).name);
5756             return;
5757         }
5758 
5759         if (DBG) log("Got NetworkProvider Messenger for " + npi.name);
5760         mNetworkProviderInfos.put(npi.messenger, npi);
5761         npi.connect(mContext, mTrackerHandler);
5762         if (!npi.isLegacyNetworkFactory()) {
5763             // Legacy NetworkFactories get their requests when their AsyncChannel connects.
5764             sendAllRequestsToProvider(npi);
5765         }
5766     }
5767 
5768     @Override
registerNetworkProvider(Messenger messenger, String name)5769     public int registerNetworkProvider(Messenger messenger, String name) {
5770         enforceNetworkFactoryOrSettingsPermission();
5771         NetworkProviderInfo npi = new NetworkProviderInfo(name, messenger,
5772                 null /* asyncChannel */, nextNetworkProviderId(),
5773                 () -> unregisterNetworkProvider(messenger));
5774         mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_PROVIDER, npi));
5775         return npi.providerId;
5776     }
5777 
5778     @Override
unregisterNetworkProvider(Messenger messenger)5779     public void unregisterNetworkProvider(Messenger messenger) {
5780         enforceNetworkFactoryOrSettingsPermission();
5781         mHandler.sendMessage(mHandler.obtainMessage(EVENT_UNREGISTER_NETWORK_PROVIDER, messenger));
5782     }
5783 
5784     @Override
unregisterNetworkFactory(Messenger messenger)5785     public void unregisterNetworkFactory(Messenger messenger) {
5786         unregisterNetworkProvider(messenger);
5787     }
5788 
handleUnregisterNetworkProvider(Messenger messenger)5789     private void handleUnregisterNetworkProvider(Messenger messenger) {
5790         NetworkProviderInfo npi = mNetworkProviderInfos.remove(messenger);
5791         if (npi == null) {
5792             loge("Failed to find Messenger in unregisterNetworkProvider");
5793             return;
5794         }
5795         if (DBG) log("unregisterNetworkProvider for " + npi.name);
5796     }
5797 
5798     @Override
declareNetworkRequestUnfulfillable(NetworkRequest request)5799     public void declareNetworkRequestUnfulfillable(NetworkRequest request) {
5800         if (request.hasTransport(TRANSPORT_TEST)) {
5801             enforceNetworkFactoryOrTestNetworksPermission();
5802         } else {
5803             enforceNetworkFactoryPermission();
5804         }
5805         mHandler.post(() -> handleReleaseNetworkRequest(request, Binder.getCallingUid(), true));
5806     }
5807 
5808     // NOTE: Accessed on multiple threads, must be synchronized on itself.
5809     @GuardedBy("mNetworkForNetId")
5810     private final SparseArray<NetworkAgentInfo> mNetworkForNetId = new SparseArray<>();
5811     // NOTE: Accessed on multiple threads, synchronized with mNetworkForNetId.
5812     // An entry is first reserved with NetIdManager, prior to being added to mNetworkForNetId, so
5813     // there may not be a strict 1:1 correlation between the two.
5814     private final NetIdManager mNetIdManager;
5815 
5816     // NetworkAgentInfo keyed off its connecting messenger
5817     // TODO - eval if we can reduce the number of lists/hashmaps/sparsearrays
5818     // NOTE: Only should be accessed on ConnectivityServiceThread, except dump().
5819     private final HashMap<Messenger, NetworkAgentInfo> mNetworkAgentInfos = new HashMap<>();
5820 
5821     @GuardedBy("mBlockedAppUids")
5822     private final HashSet<Integer> mBlockedAppUids = new HashSet<>();
5823 
5824     // Note: if mDefaultRequest is changed, NetworkMonitor needs to be updated.
5825     @NonNull
5826     private final NetworkRequest mDefaultRequest;
5827     // The NetworkAgentInfo currently satisfying the default request, if any.
5828     @Nullable
5829     private volatile NetworkAgentInfo mDefaultNetworkNai = null;
5830 
5831     // Request used to optionally keep mobile data active even when higher
5832     // priority networks like Wi-Fi are active.
5833     private final NetworkRequest mDefaultMobileDataRequest;
5834 
5835     // Request used to optionally keep wifi data active even when higher
5836     // priority networks like ethernet are active.
5837     private final NetworkRequest mDefaultWifiRequest;
5838 
getDefaultNetwork()5839     private NetworkAgentInfo getDefaultNetwork() {
5840         return mDefaultNetworkNai;
5841     }
5842 
5843     @Nullable
getNetwork(@ullable NetworkAgentInfo nai)5844     private Network getNetwork(@Nullable NetworkAgentInfo nai) {
5845         return nai != null ? nai.network : null;
5846     }
5847 
ensureRunningOnConnectivityServiceThread()5848     private void ensureRunningOnConnectivityServiceThread() {
5849         if (mHandler.getLooper().getThread() != Thread.currentThread()) {
5850             throw new IllegalStateException(
5851                     "Not running on ConnectivityService thread: "
5852                             + Thread.currentThread().getName());
5853         }
5854     }
5855 
5856     @VisibleForTesting
isDefaultNetwork(NetworkAgentInfo nai)5857     protected boolean isDefaultNetwork(NetworkAgentInfo nai) {
5858         return nai == getDefaultNetwork();
5859     }
5860 
isDefaultRequest(NetworkRequestInfo nri)5861     private boolean isDefaultRequest(NetworkRequestInfo nri) {
5862         return nri.request.requestId == mDefaultRequest.requestId;
5863     }
5864 
5865     // TODO : remove this method. It's a stopgap measure to help sheperding a number of dependent
5866     // changes that would conflict throughout the automerger graph. Having this method temporarily
5867     // helps with the process of going through with all these dependent changes across the entire
5868     // tree.
5869     /**
5870      * Register a new agent. {@see #registerNetworkAgent} below.
5871      */
registerNetworkAgent(Messenger messenger, NetworkInfo networkInfo, LinkProperties linkProperties, NetworkCapabilities networkCapabilities, int currentScore, NetworkAgentConfig networkAgentConfig)5872     public Network registerNetworkAgent(Messenger messenger, NetworkInfo networkInfo,
5873             LinkProperties linkProperties, NetworkCapabilities networkCapabilities,
5874             int currentScore, NetworkAgentConfig networkAgentConfig) {
5875         return registerNetworkAgent(messenger, networkInfo, linkProperties, networkCapabilities,
5876                 currentScore, networkAgentConfig, NetworkProvider.ID_NONE);
5877     }
5878 
5879     /**
5880      * Register a new agent with ConnectivityService to handle a network.
5881      *
5882      * @param messenger a messenger for ConnectivityService to contact the agent asynchronously.
5883      * @param networkInfo the initial info associated with this network. It can be updated later :
5884      *         see {@link #updateNetworkInfo}.
5885      * @param linkProperties the initial link properties of this network. They can be updated
5886      *         later : see {@link #updateLinkProperties}.
5887      * @param networkCapabilities the initial capabilites of this network. They can be updated
5888      *         later : see {@link #updateCapabilities}.
5889      * @param currentScore the initial score of the network. See
5890      *         {@link NetworkAgentInfo#getCurrentScore}.
5891      * @param networkAgentConfig metadata about the network. This is never updated.
5892      * @param providerId the ID of the provider owning this NetworkAgent.
5893      * @return the network created for this agent.
5894      */
registerNetworkAgent(Messenger messenger, NetworkInfo networkInfo, LinkProperties linkProperties, NetworkCapabilities networkCapabilities, int currentScore, NetworkAgentConfig networkAgentConfig, int providerId)5895     public Network registerNetworkAgent(Messenger messenger, NetworkInfo networkInfo,
5896             LinkProperties linkProperties, NetworkCapabilities networkCapabilities,
5897             int currentScore, NetworkAgentConfig networkAgentConfig, int providerId) {
5898         if (networkCapabilities.hasTransport(TRANSPORT_TEST)) {
5899             enforceAnyPermissionOf(Manifest.permission.MANAGE_TEST_NETWORKS);
5900             // Strictly, sanitizing here is unnecessary as the capabilities will be sanitized in
5901             // the call to mixInCapabilities below anyway, but sanitizing here means the NAI never
5902             // sees capabilities that may be malicious, which might prevent mistakes in the future.
5903             networkCapabilities = new NetworkCapabilities(networkCapabilities);
5904             networkCapabilities.restrictCapabilitesForTestNetwork(Binder.getCallingUid());
5905         } else {
5906             enforceNetworkFactoryPermission();
5907         }
5908 
5909         LinkProperties lp = new LinkProperties(linkProperties);
5910 
5911         // TODO: Instead of passing mDefaultRequest, provide an API to determine whether a Network
5912         // satisfies mDefaultRequest.
5913         final NetworkCapabilities nc = new NetworkCapabilities(networkCapabilities);
5914         final NetworkAgentInfo nai = new NetworkAgentInfo(messenger, new AsyncChannel(),
5915                 new Network(mNetIdManager.reserveNetId()), new NetworkInfo(networkInfo), lp, nc,
5916                 currentScore, mContext, mTrackerHandler, new NetworkAgentConfig(networkAgentConfig),
5917                 this, mNetd, mDnsResolver, mNMS, providerId, Binder.getCallingUid());
5918 
5919         // Make sure the LinkProperties and NetworkCapabilities reflect what the agent info says.
5920         nai.getAndSetNetworkCapabilities(mixInCapabilities(nai, nc));
5921         processLinkPropertiesFromAgent(nai, nai.linkProperties);
5922 
5923         final String extraInfo = networkInfo.getExtraInfo();
5924         final String name = TextUtils.isEmpty(extraInfo)
5925                 ? nai.networkCapabilities.getSsid() : extraInfo;
5926         if (DBG) log("registerNetworkAgent " + nai);
5927         final long token = Binder.clearCallingIdentity();
5928         try {
5929             mDeps.getNetworkStack().makeNetworkMonitor(
5930                     nai.network, name, new NetworkMonitorCallbacks(nai));
5931         } finally {
5932             Binder.restoreCallingIdentity(token);
5933         }
5934         // NetworkAgentInfo registration will finish when the NetworkMonitor is created.
5935         // If the network disconnects or sends any other event before that, messages are deferred by
5936         // NetworkAgent until nai.asyncChannel.connect(), which will be called when finalizing the
5937         // registration.
5938         return nai.network;
5939     }
5940 
handleRegisterNetworkAgent(NetworkAgentInfo nai, INetworkMonitor networkMonitor)5941     private void handleRegisterNetworkAgent(NetworkAgentInfo nai, INetworkMonitor networkMonitor) {
5942         nai.onNetworkMonitorCreated(networkMonitor);
5943         if (VDBG) log("Got NetworkAgent Messenger");
5944         mNetworkAgentInfos.put(nai.messenger, nai);
5945         synchronized (mNetworkForNetId) {
5946             mNetworkForNetId.put(nai.network.netId, nai);
5947         }
5948 
5949         try {
5950             networkMonitor.start();
5951         } catch (RemoteException e) {
5952             e.rethrowAsRuntimeException();
5953         }
5954         nai.asyncChannel.connect(mContext, mTrackerHandler, nai.messenger);
5955         NetworkInfo networkInfo = nai.networkInfo;
5956         updateNetworkInfo(nai, networkInfo);
5957         updateUids(nai, null, nai.networkCapabilities);
5958     }
5959 
processLinkPropertiesFromAgent(NetworkAgentInfo nai, LinkProperties lp)5960     private void processLinkPropertiesFromAgent(NetworkAgentInfo nai, LinkProperties lp) {
5961         lp.ensureDirectlyConnectedRoutes();
5962         nai.clatd.setNat64PrefixFromRa(lp.getNat64Prefix());
5963     }
5964 
updateLinkProperties(NetworkAgentInfo networkAgent, LinkProperties newLp, @NonNull LinkProperties oldLp)5965     private void updateLinkProperties(NetworkAgentInfo networkAgent, LinkProperties newLp,
5966             @NonNull LinkProperties oldLp) {
5967         int netId = networkAgent.network.netId;
5968 
5969         // The NetworkAgent does not know whether clatd is running on its network or not, or whether
5970         // a NAT64 prefix was discovered by the DNS resolver. Before we do anything else, make sure
5971         // the LinkProperties for the network are accurate.
5972         networkAgent.clatd.fixupLinkProperties(oldLp, newLp);
5973 
5974         updateInterfaces(newLp, oldLp, netId, networkAgent.networkCapabilities,
5975                 networkAgent.networkInfo.getType());
5976 
5977         // update filtering rules, need to happen after the interface update so netd knows about the
5978         // new interface (the interface name -> index map becomes initialized)
5979         updateVpnFiltering(newLp, oldLp, networkAgent);
5980 
5981         updateMtu(newLp, oldLp);
5982         // TODO - figure out what to do for clat
5983 //        for (LinkProperties lp : newLp.getStackedLinks()) {
5984 //            updateMtu(lp, null);
5985 //        }
5986         if (isDefaultNetwork(networkAgent)) {
5987             updateTcpBufferSizes(newLp.getTcpBufferSizes());
5988         }
5989 
5990         updateRoutes(newLp, oldLp, netId);
5991         updateDnses(newLp, oldLp, netId);
5992         // Make sure LinkProperties represents the latest private DNS status.
5993         // This does not need to be done before updateDnses because the
5994         // LinkProperties are not the source of the private DNS configuration.
5995         // updateDnses will fetch the private DNS configuration from DnsManager.
5996         mDnsManager.updatePrivateDnsStatus(netId, newLp);
5997 
5998         if (isDefaultNetwork(networkAgent)) {
5999             handleApplyDefaultProxy(newLp.getHttpProxy());
6000         } else {
6001             updateProxy(newLp, oldLp);
6002         }
6003 
6004         updateWakeOnLan(newLp);
6005 
6006         // Captive portal data is obtained from NetworkMonitor and stored in NetworkAgentInfo,
6007         // it is not contained in LinkProperties sent from NetworkAgents so needs to be merged here.
6008         newLp.setCaptivePortalData(networkAgent.captivePortalData);
6009 
6010         // TODO - move this check to cover the whole function
6011         if (!Objects.equals(newLp, oldLp)) {
6012             synchronized (networkAgent) {
6013                 networkAgent.linkProperties = newLp;
6014             }
6015             // Start or stop DNS64 detection and 464xlat according to network state.
6016             networkAgent.clatd.update();
6017             notifyIfacesChangedForNetworkStats();
6018             networkAgent.networkMonitor().notifyLinkPropertiesChanged(
6019                     new LinkProperties(newLp, true /* parcelSensitiveFields */));
6020             if (networkAgent.everConnected) {
6021                 notifyNetworkCallbacks(networkAgent, ConnectivityManager.CALLBACK_IP_CHANGED);
6022             }
6023         }
6024 
6025         mKeepaliveTracker.handleCheckKeepalivesStillValid(networkAgent);
6026     }
6027 
wakeupModifyInterface(String iface, NetworkCapabilities caps, boolean add)6028     private void wakeupModifyInterface(String iface, NetworkCapabilities caps, boolean add) {
6029         // Marks are only available on WiFi interfaces. Checking for
6030         // marks on unsupported interfaces is harmless.
6031         if (!caps.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
6032             return;
6033         }
6034 
6035         int mark = mContext.getResources().getInteger(
6036             com.android.internal.R.integer.config_networkWakeupPacketMark);
6037         int mask = mContext.getResources().getInteger(
6038             com.android.internal.R.integer.config_networkWakeupPacketMask);
6039 
6040         // Mask/mark of zero will not detect anything interesting.
6041         // Don't install rules unless both values are nonzero.
6042         if (mark == 0 || mask == 0) {
6043             return;
6044         }
6045 
6046         final String prefix = "iface:" + iface;
6047         try {
6048             if (add) {
6049                 mNetd.wakeupAddInterface(iface, prefix, mark, mask);
6050             } else {
6051                 mNetd.wakeupDelInterface(iface, prefix, mark, mask);
6052             }
6053         } catch (Exception e) {
6054             loge("Exception modifying wakeup packet monitoring: " + e);
6055         }
6056 
6057     }
6058 
updateInterfaces(final @Nullable LinkProperties newLp, final @Nullable LinkProperties oldLp, final int netId, final @Nullable NetworkCapabilities caps, final int legacyType)6059     private void updateInterfaces(final @Nullable LinkProperties newLp,
6060             final @Nullable LinkProperties oldLp, final int netId,
6061             final @Nullable NetworkCapabilities caps, final int legacyType) {
6062         final CompareResult<String> interfaceDiff = new CompareResult<>(
6063                 oldLp != null ? oldLp.getAllInterfaceNames() : null,
6064                 newLp != null ? newLp.getAllInterfaceNames() : null);
6065         if (!interfaceDiff.added.isEmpty()) {
6066             final IBatteryStats bs = mDeps.getBatteryStatsService();
6067             for (final String iface : interfaceDiff.added) {
6068                 try {
6069                     if (DBG) log("Adding iface " + iface + " to network " + netId);
6070                     mNMS.addInterfaceToNetwork(iface, netId);
6071                     wakeupModifyInterface(iface, caps, true);
6072                     bs.noteNetworkInterfaceType(iface, legacyType);
6073                 } catch (Exception e) {
6074                     loge("Exception adding interface: " + e);
6075                 }
6076             }
6077         }
6078         for (final String iface : interfaceDiff.removed) {
6079             try {
6080                 if (DBG) log("Removing iface " + iface + " from network " + netId);
6081                 wakeupModifyInterface(iface, caps, false);
6082                 mNMS.removeInterfaceFromNetwork(iface, netId);
6083             } catch (Exception e) {
6084                 loge("Exception removing interface: " + e);
6085             }
6086         }
6087     }
6088 
6089     // TODO: move to frameworks/libs/net.
convertRouteInfo(RouteInfo route)6090     private RouteInfoParcel convertRouteInfo(RouteInfo route) {
6091         final String nextHop;
6092 
6093         switch (route.getType()) {
6094             case RouteInfo.RTN_UNICAST:
6095                 if (route.hasGateway()) {
6096                     nextHop = route.getGateway().getHostAddress();
6097                 } else {
6098                     nextHop = INetd.NEXTHOP_NONE;
6099                 }
6100                 break;
6101             case RouteInfo.RTN_UNREACHABLE:
6102                 nextHop = INetd.NEXTHOP_UNREACHABLE;
6103                 break;
6104             case RouteInfo.RTN_THROW:
6105                 nextHop = INetd.NEXTHOP_THROW;
6106                 break;
6107             default:
6108                 nextHop = INetd.NEXTHOP_NONE;
6109                 break;
6110         }
6111 
6112         final RouteInfoParcel rip = new RouteInfoParcel();
6113         rip.ifName = route.getInterface();
6114         rip.destination = route.getDestination().toString();
6115         rip.nextHop = nextHop;
6116         rip.mtu = route.getMtu();
6117 
6118         return rip;
6119     }
6120 
6121     /**
6122      * Have netd update routes from oldLp to newLp.
6123      * @return true if routes changed between oldLp and newLp
6124      */
updateRoutes(LinkProperties newLp, LinkProperties oldLp, int netId)6125     private boolean updateRoutes(LinkProperties newLp, LinkProperties oldLp, int netId) {
6126         // compare the route diff to determine which routes have been updated
6127         final CompareOrUpdateResult<RouteInfo.RouteKey, RouteInfo> routeDiff =
6128                 new CompareOrUpdateResult<>(
6129                         oldLp != null ? oldLp.getAllRoutes() : null,
6130                         newLp != null ? newLp.getAllRoutes() : null,
6131                         (r) -> r.getRouteKey());
6132 
6133         // add routes before removing old in case it helps with continuous connectivity
6134 
6135         // do this twice, adding non-next-hop routes first, then routes they are dependent on
6136         for (RouteInfo route : routeDiff.added) {
6137             if (route.hasGateway()) continue;
6138             if (VDBG || DDBG) log("Adding Route [" + route + "] to network " + netId);
6139             try {
6140                 mNetd.networkAddRouteParcel(netId, convertRouteInfo(route));
6141             } catch (Exception e) {
6142                 if ((route.getDestination().getAddress() instanceof Inet4Address) || VDBG) {
6143                     loge("Exception in networkAddRouteParcel for non-gateway: " + e);
6144                 }
6145             }
6146         }
6147         for (RouteInfo route : routeDiff.added) {
6148             if (!route.hasGateway()) continue;
6149             if (VDBG || DDBG) log("Adding Route [" + route + "] to network " + netId);
6150             try {
6151                 mNetd.networkAddRouteParcel(netId, convertRouteInfo(route));
6152             } catch (Exception e) {
6153                 if ((route.getGateway() instanceof Inet4Address) || VDBG) {
6154                     loge("Exception in networkAddRouteParcel for gateway: " + e);
6155                 }
6156             }
6157         }
6158 
6159         for (RouteInfo route : routeDiff.removed) {
6160             if (VDBG || DDBG) log("Removing Route [" + route + "] from network " + netId);
6161             try {
6162                 mNetd.networkRemoveRouteParcel(netId, convertRouteInfo(route));
6163             } catch (Exception e) {
6164                 loge("Exception in networkRemoveRouteParcel: " + e);
6165             }
6166         }
6167 
6168         for (RouteInfo route : routeDiff.updated) {
6169             if (VDBG || DDBG) log("Updating Route [" + route + "] from network " + netId);
6170             try {
6171                 mNetd.networkUpdateRouteParcel(netId, convertRouteInfo(route));
6172             } catch (Exception e) {
6173                 loge("Exception in networkUpdateRouteParcel: " + e);
6174             }
6175         }
6176         return !routeDiff.added.isEmpty() || !routeDiff.removed.isEmpty()
6177                 || !routeDiff.updated.isEmpty();
6178     }
6179 
updateDnses(LinkProperties newLp, LinkProperties oldLp, int netId)6180     private void updateDnses(LinkProperties newLp, LinkProperties oldLp, int netId) {
6181         if (oldLp != null && newLp.isIdenticalDnses(oldLp)) {
6182             return;  // no updating necessary
6183         }
6184 
6185         final NetworkAgentInfo defaultNai = getDefaultNetwork();
6186         final boolean isDefaultNetwork = (defaultNai != null && defaultNai.network.netId == netId);
6187 
6188         if (DBG) {
6189             final Collection<InetAddress> dnses = newLp.getDnsServers();
6190             log("Setting DNS servers for network " + netId + " to " + dnses);
6191         }
6192         try {
6193             mDnsManager.noteDnsServersForNetwork(netId, newLp);
6194             // TODO: netd should listen on [::1]:53 and proxy queries to the current
6195             // default network, and we should just set net.dns1 to ::1, not least
6196             // because applications attempting to use net.dns resolvers will bypass
6197             // the privacy protections of things like DNS-over-TLS.
6198             if (isDefaultNetwork) mDnsManager.setDefaultDnsSystemProperties(newLp.getDnsServers());
6199             mDnsManager.flushVmDnsCache();
6200         } catch (Exception e) {
6201             loge("Exception in setDnsConfigurationForNetwork: " + e);
6202         }
6203     }
6204 
updateVpnFiltering(LinkProperties newLp, LinkProperties oldLp, NetworkAgentInfo nai)6205     private void updateVpnFiltering(LinkProperties newLp, LinkProperties oldLp,
6206             NetworkAgentInfo nai) {
6207         final String oldIface = oldLp != null ? oldLp.getInterfaceName() : null;
6208         final String newIface = newLp != null ? newLp.getInterfaceName() : null;
6209         final boolean wasFiltering = requiresVpnIsolation(nai, nai.networkCapabilities, oldLp);
6210         final boolean needsFiltering = requiresVpnIsolation(nai, nai.networkCapabilities, newLp);
6211 
6212         if (!wasFiltering && !needsFiltering) {
6213             // Nothing to do.
6214             return;
6215         }
6216 
6217         if (Objects.equals(oldIface, newIface) && (wasFiltering == needsFiltering)) {
6218             // Nothing changed.
6219             return;
6220         }
6221 
6222         final Set<UidRange> ranges = nai.networkCapabilities.getUids();
6223         final int vpnAppUid = nai.networkCapabilities.getOwnerUid();
6224         // TODO: this create a window of opportunity for apps to receive traffic between the time
6225         // when the old rules are removed and the time when new rules are added. To fix this,
6226         // make eBPF support two whitelisted interfaces so here new rules can be added before the
6227         // old rules are being removed.
6228         if (wasFiltering) {
6229             mPermissionMonitor.onVpnUidRangesRemoved(oldIface, ranges, vpnAppUid);
6230         }
6231         if (needsFiltering) {
6232             mPermissionMonitor.onVpnUidRangesAdded(newIface, ranges, vpnAppUid);
6233         }
6234     }
6235 
updateWakeOnLan(@onNull LinkProperties lp)6236     private void updateWakeOnLan(@NonNull LinkProperties lp) {
6237         lp.setWakeOnLanSupported(mWolSupportedInterfaces.contains(lp.getInterfaceName()));
6238     }
6239 
getNetworkPermission(NetworkCapabilities nc)6240     private int getNetworkPermission(NetworkCapabilities nc) {
6241         if (!nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)) {
6242             return INetd.PERMISSION_SYSTEM;
6243         }
6244         if (!nc.hasCapability(NET_CAPABILITY_FOREGROUND)) {
6245             return INetd.PERMISSION_NETWORK;
6246         }
6247         return INetd.PERMISSION_NONE;
6248     }
6249 
updateNetworkPermissions(@onNull final NetworkAgentInfo nai, @NonNull final NetworkCapabilities newNc)6250     private void updateNetworkPermissions(@NonNull final NetworkAgentInfo nai,
6251             @NonNull final NetworkCapabilities newNc) {
6252         final int oldPermission = getNetworkPermission(nai.networkCapabilities);
6253         final int newPermission = getNetworkPermission(newNc);
6254         if (oldPermission != newPermission && nai.created && !nai.isVPN()) {
6255             try {
6256                 mNMS.setNetworkPermission(nai.network.netId, newPermission);
6257             } catch (RemoteException e) {
6258                 loge("Exception in setNetworkPermission: " + e);
6259             }
6260         }
6261     }
6262 
6263     /**
6264      * Augments the NetworkCapabilities passed in by a NetworkAgent with capabilities that are
6265      * maintained here that the NetworkAgent is not aware of (e.g., validated, captive portal,
6266      * and foreground status).
6267      */
mixInCapabilities(NetworkAgentInfo nai, NetworkCapabilities nc)6268     private NetworkCapabilities mixInCapabilities(NetworkAgentInfo nai, NetworkCapabilities nc) {
6269         // Once a NetworkAgent is connected, complain if some immutable capabilities are removed.
6270          // Don't complain for VPNs since they're not driven by requests and there is no risk of
6271          // causing a connect/teardown loop.
6272          // TODO: remove this altogether and make it the responsibility of the NetworkProviders to
6273          // avoid connect/teardown loops.
6274         if (nai.everConnected &&
6275                 !nai.isVPN() &&
6276                 !nai.networkCapabilities.satisfiedByImmutableNetworkCapabilities(nc)) {
6277             // TODO: consider not complaining when a network agent degrades its capabilities if this
6278             // does not cause any request (that is not a listen) currently matching that agent to
6279             // stop being matched by the updated agent.
6280             String diff = nai.networkCapabilities.describeImmutableDifferences(nc);
6281             if (!TextUtils.isEmpty(diff)) {
6282                 Slog.wtf(TAG, "BUG: " + nai + " lost immutable capabilities:" + diff);
6283             }
6284         }
6285 
6286         // Don't modify caller's NetworkCapabilities.
6287         NetworkCapabilities newNc = new NetworkCapabilities(nc);
6288         if (nai.lastValidated) {
6289             newNc.addCapability(NET_CAPABILITY_VALIDATED);
6290         } else {
6291             newNc.removeCapability(NET_CAPABILITY_VALIDATED);
6292         }
6293         if (nai.lastCaptivePortalDetected) {
6294             newNc.addCapability(NET_CAPABILITY_CAPTIVE_PORTAL);
6295         } else {
6296             newNc.removeCapability(NET_CAPABILITY_CAPTIVE_PORTAL);
6297         }
6298         if (nai.isBackgroundNetwork()) {
6299             newNc.removeCapability(NET_CAPABILITY_FOREGROUND);
6300         } else {
6301             newNc.addCapability(NET_CAPABILITY_FOREGROUND);
6302         }
6303         if (nai.partialConnectivity) {
6304             newNc.addCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY);
6305         } else {
6306             newNc.removeCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY);
6307         }
6308         newNc.setPrivateDnsBroken(nai.networkCapabilities.isPrivateDnsBroken());
6309 
6310         // TODO : remove this once all factories are updated to send NOT_SUSPENDED and NOT_ROAMING
6311         if (!newNc.hasTransport(TRANSPORT_CELLULAR)) {
6312             newNc.addCapability(NET_CAPABILITY_NOT_SUSPENDED);
6313             newNc.addCapability(NET_CAPABILITY_NOT_ROAMING);
6314         }
6315 
6316         return newNc;
6317     }
6318 
6319     /**
6320      * Update the NetworkCapabilities for {@code nai} to {@code nc}. Specifically:
6321      *
6322      * 1. Calls mixInCapabilities to merge the passed-in NetworkCapabilities {@code nc} with the
6323      *    capabilities we manage and store in {@code nai}, such as validated status and captive
6324      *    portal status)
6325      * 2. Takes action on the result: changes network permissions, sends CAP_CHANGED callbacks, and
6326      *    potentially triggers rematches.
6327      * 3. Directly informs other network stack components (NetworkStatsService, VPNs, etc. of the
6328      *    change.)
6329      *
6330      * @param oldScore score of the network before any of the changes that prompted us
6331      *                 to call this function.
6332      * @param nai the network having its capabilities updated.
6333      * @param nc the new network capabilities.
6334      */
updateCapabilities(final int oldScore, @NonNull final NetworkAgentInfo nai, @NonNull final NetworkCapabilities nc)6335     private void updateCapabilities(final int oldScore, @NonNull final NetworkAgentInfo nai,
6336             @NonNull final NetworkCapabilities nc) {
6337         NetworkCapabilities newNc = mixInCapabilities(nai, nc);
6338         if (Objects.equals(nai.networkCapabilities, newNc)) return;
6339         updateNetworkPermissions(nai, newNc);
6340         final NetworkCapabilities prevNc = nai.getAndSetNetworkCapabilities(newNc);
6341 
6342         updateUids(nai, prevNc, newNc);
6343 
6344         if (nai.getCurrentScore() == oldScore && newNc.equalRequestableCapabilities(prevNc)) {
6345             // If the requestable capabilities haven't changed, and the score hasn't changed, then
6346             // the change we're processing can't affect any requests, it can only affect the listens
6347             // on this network. We might have been called by rematchNetworkAndRequests when a
6348             // network changed foreground state.
6349             processListenRequests(nai);
6350             final boolean prevSuspended = !prevNc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED);
6351             final boolean suspended = !newNc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED);
6352             final boolean prevRoaming = !prevNc.hasCapability(NET_CAPABILITY_NOT_ROAMING);
6353             final boolean roaming = !newNc.hasCapability(NET_CAPABILITY_NOT_ROAMING);
6354             if (prevSuspended != suspended || prevRoaming != roaming) {
6355                 // TODO (b/73132094) : remove this call once the few users of onSuspended and
6356                 // onResumed have been removed.
6357                 notifyNetworkCallbacks(nai, suspended ? ConnectivityManager.CALLBACK_SUSPENDED
6358                         : ConnectivityManager.CALLBACK_RESUMED);
6359                 // updateNetworkInfo will mix in the suspended info from the capabilities and
6360                 // take appropriate action for the network having possibly changed state.
6361                 updateNetworkInfo(nai, nai.networkInfo);
6362             }
6363         } else {
6364             // If the requestable capabilities have changed or the score changed, we can't have been
6365             // called by rematchNetworkAndRequests, so it's safe to start a rematch.
6366             rematchAllNetworksAndRequests();
6367             notifyNetworkCallbacks(nai, ConnectivityManager.CALLBACK_CAP_CHANGED);
6368         }
6369 
6370         // TODO : static analysis indicates that prevNc can't be null here (getAndSetNetworkCaps
6371         // never returns null), so mark the relevant members and functions in nai as @NonNull and
6372         // remove this test
6373         if (prevNc != null) {
6374             final boolean oldMetered = prevNc.isMetered();
6375             final boolean newMetered = newNc.isMetered();
6376             final boolean meteredChanged = oldMetered != newMetered;
6377 
6378             if (meteredChanged) {
6379                 maybeNotifyNetworkBlocked(nai, oldMetered, newMetered, mRestrictBackground,
6380                         mRestrictBackground);
6381             }
6382 
6383             final boolean roamingChanged = prevNc.hasCapability(NET_CAPABILITY_NOT_ROAMING) !=
6384                     newNc.hasCapability(NET_CAPABILITY_NOT_ROAMING);
6385 
6386             // Report changes that are interesting for network statistics tracking.
6387             if (meteredChanged || roamingChanged) {
6388                 notifyIfacesChangedForNetworkStats();
6389             }
6390         }
6391 
6392         if (!newNc.hasTransport(TRANSPORT_VPN)) {
6393             // Tell VPNs about updated capabilities, since they may need to
6394             // bubble those changes through.
6395             updateAllVpnsCapabilities();
6396         }
6397 
6398         if (!newNc.equalsTransportTypes(prevNc)) {
6399             mDnsManager.updateTransportsForNetwork(nai.network.netId, newNc.getTransportTypes());
6400         }
6401     }
6402 
6403     /**
6404      * Returns whether VPN isolation (ingress interface filtering) should be applied on the given
6405      * network.
6406      *
6407      * Ingress interface filtering enforces that all apps under the given network can only receive
6408      * packets from the network's interface (and loopback). This is important for VPNs because
6409      * apps that cannot bypass a fully-routed VPN shouldn't be able to receive packets from any
6410      * non-VPN interfaces.
6411      *
6412      * As a result, this method should return true iff
6413      *  1. the network is an app VPN (not legacy VPN)
6414      *  2. the VPN does not allow bypass
6415      *  3. the VPN is fully-routed
6416      *  4. the VPN interface is non-null
6417      *
6418      * @see INetd#firewallAddUidInterfaceRules
6419      * @see INetd#firewallRemoveUidInterfaceRules
6420      */
requiresVpnIsolation(@onNull NetworkAgentInfo nai, NetworkCapabilities nc, LinkProperties lp)6421     private boolean requiresVpnIsolation(@NonNull NetworkAgentInfo nai, NetworkCapabilities nc,
6422             LinkProperties lp) {
6423         if (nc == null || lp == null) return false;
6424         return nai.isVPN()
6425                 && !nai.networkAgentConfig.allowBypass
6426                 && nc.getOwnerUid() != Process.SYSTEM_UID
6427                 && lp.getInterfaceName() != null
6428                 && (lp.hasIPv4DefaultRoute() || lp.hasIpv4UnreachableDefaultRoute())
6429                 && (lp.hasIPv6DefaultRoute() || lp.hasIpv6UnreachableDefaultRoute());
6430     }
6431 
updateUids(NetworkAgentInfo nai, NetworkCapabilities prevNc, NetworkCapabilities newNc)6432     private void updateUids(NetworkAgentInfo nai, NetworkCapabilities prevNc,
6433             NetworkCapabilities newNc) {
6434         Set<UidRange> prevRanges = null == prevNc ? null : prevNc.getUids();
6435         Set<UidRange> newRanges = null == newNc ? null : newNc.getUids();
6436         if (null == prevRanges) prevRanges = new ArraySet<>();
6437         if (null == newRanges) newRanges = new ArraySet<>();
6438         final Set<UidRange> prevRangesCopy = new ArraySet<>(prevRanges);
6439 
6440         prevRanges.removeAll(newRanges);
6441         newRanges.removeAll(prevRangesCopy);
6442 
6443         try {
6444             // When updating the VPN uid routing rules, add the new range first then remove the old
6445             // range. If old range were removed first, there would be a window between the old
6446             // range being removed and the new range being added, during which UIDs contained
6447             // in both ranges are not subject to any VPN routing rules. Adding new range before
6448             // removing old range works because, unlike the filtering rules below, it's possible to
6449             // add duplicate UID routing rules.
6450             if (!newRanges.isEmpty()) {
6451                 final UidRange[] addedRangesArray = new UidRange[newRanges.size()];
6452                 newRanges.toArray(addedRangesArray);
6453                 mNMS.addVpnUidRanges(nai.network.netId, addedRangesArray);
6454             }
6455             if (!prevRanges.isEmpty()) {
6456                 final UidRange[] removedRangesArray = new UidRange[prevRanges.size()];
6457                 prevRanges.toArray(removedRangesArray);
6458                 mNMS.removeVpnUidRanges(nai.network.netId, removedRangesArray);
6459             }
6460             final boolean wasFiltering = requiresVpnIsolation(nai, prevNc, nai.linkProperties);
6461             final boolean shouldFilter = requiresVpnIsolation(nai, newNc, nai.linkProperties);
6462             final String iface = nai.linkProperties.getInterfaceName();
6463             // For VPN uid interface filtering, old ranges need to be removed before new ranges can
6464             // be added, due to the range being expanded and stored as individual UIDs. For example
6465             // the UIDs might be updated from [0, 99999] to ([0, 10012], [10014, 99999]) which means
6466             // prevRanges = [0, 99999] while newRanges = [0, 10012], [10014, 99999]. If prevRanges
6467             // were added first and then newRanges got removed later, there would be only one uid
6468             // 10013 left. A consequence of removing old ranges before adding new ranges is that
6469             // there is now a window of opportunity when the UIDs are not subject to any filtering.
6470             // Note that this is in contrast with the (more robust) update of VPN routing rules
6471             // above, where the addition of new ranges happens before the removal of old ranges.
6472             // TODO Fix this window by computing an accurate diff on Set<UidRange>, so the old range
6473             // to be removed will never overlap with the new range to be added.
6474             if (wasFiltering && !prevRanges.isEmpty()) {
6475                 mPermissionMonitor.onVpnUidRangesRemoved(iface, prevRanges, prevNc.getOwnerUid());
6476             }
6477             if (shouldFilter && !newRanges.isEmpty()) {
6478                 mPermissionMonitor.onVpnUidRangesAdded(iface, newRanges, newNc.getOwnerUid());
6479             }
6480         } catch (Exception e) {
6481             // Never crash!
6482             loge("Exception in updateUids: ", e);
6483         }
6484     }
6485 
handleUpdateLinkProperties(NetworkAgentInfo nai, LinkProperties newLp)6486     public void handleUpdateLinkProperties(NetworkAgentInfo nai, LinkProperties newLp) {
6487         ensureRunningOnConnectivityServiceThread();
6488 
6489         if (getNetworkAgentInfoForNetId(nai.network.netId) != nai) {
6490             // Ignore updates for disconnected networks
6491             return;
6492         }
6493         if (VDBG || DDBG) {
6494             log("Update of LinkProperties for " + nai.toShortString()
6495                     + "; created=" + nai.created
6496                     + "; everConnected=" + nai.everConnected);
6497         }
6498         // TODO: eliminate this defensive copy after confirming that updateLinkProperties does not
6499         // modify its oldLp parameter.
6500         updateLinkProperties(nai, newLp, new LinkProperties(nai.linkProperties));
6501     }
6502 
sendUpdatedScoreToFactories(NetworkAgentInfo nai)6503     private void sendUpdatedScoreToFactories(NetworkAgentInfo nai) {
6504         for (int i = 0; i < nai.numNetworkRequests(); i++) {
6505             NetworkRequest nr = nai.requestAt(i);
6506             // Don't send listening requests to factories. b/17393458
6507             if (nr.isListen()) continue;
6508             sendUpdatedScoreToFactories(nr, nai);
6509         }
6510     }
6511 
sendUpdatedScoreToFactories(@onNull NetworkRequest networkRequest, @Nullable NetworkAgentInfo nai)6512     private void sendUpdatedScoreToFactories(@NonNull NetworkRequest networkRequest,
6513             @Nullable NetworkAgentInfo nai) {
6514         final int score;
6515         final int serial;
6516         if (nai != null) {
6517             score = nai.getCurrentScore();
6518             serial = nai.factorySerialNumber;
6519         } else {
6520             score = 0;
6521             serial = 0;
6522         }
6523         if (VDBG || DDBG){
6524             log("sending new Min Network Score(" + score + "): " + networkRequest.toString());
6525         }
6526         for (NetworkProviderInfo npi : mNetworkProviderInfos.values()) {
6527             npi.requestNetwork(networkRequest, score, serial);
6528         }
6529     }
6530 
6531     /** Sends all current NetworkRequests to the specified factory. */
sendAllRequestsToProvider(NetworkProviderInfo npi)6532     private void sendAllRequestsToProvider(NetworkProviderInfo npi) {
6533         ensureRunningOnConnectivityServiceThread();
6534         for (NetworkRequestInfo nri : mNetworkRequests.values()) {
6535             if (nri.request.isListen()) continue;
6536             NetworkAgentInfo nai = nri.mSatisfier;
6537             final int score;
6538             final int serial;
6539             if (nai != null) {
6540                 score = nai.getCurrentScore();
6541                 serial = nai.factorySerialNumber;
6542             } else {
6543                 score = 0;
6544                 serial = NetworkProvider.ID_NONE;
6545             }
6546             npi.requestNetwork(nri.request, score, serial);
6547         }
6548     }
6549 
sendPendingIntentForRequest(NetworkRequestInfo nri, NetworkAgentInfo networkAgent, int notificationType)6550     private void sendPendingIntentForRequest(NetworkRequestInfo nri, NetworkAgentInfo networkAgent,
6551             int notificationType) {
6552         if (notificationType == ConnectivityManager.CALLBACK_AVAILABLE && !nri.mPendingIntentSent) {
6553             Intent intent = new Intent();
6554             intent.putExtra(ConnectivityManager.EXTRA_NETWORK, networkAgent.network);
6555             intent.putExtra(ConnectivityManager.EXTRA_NETWORK_REQUEST, nri.request);
6556             nri.mPendingIntentSent = true;
6557             sendIntent(nri.mPendingIntent, intent);
6558         }
6559         // else not handled
6560     }
6561 
sendIntent(PendingIntent pendingIntent, Intent intent)6562     private void sendIntent(PendingIntent pendingIntent, Intent intent) {
6563         mPendingIntentWakeLock.acquire();
6564         try {
6565             if (DBG) log("Sending " + pendingIntent);
6566             pendingIntent.send(mContext, 0, intent, this /* onFinished */, null /* Handler */);
6567         } catch (PendingIntent.CanceledException e) {
6568             if (DBG) log(pendingIntent + " was not sent, it had been canceled.");
6569             mPendingIntentWakeLock.release();
6570             releasePendingNetworkRequest(pendingIntent);
6571         }
6572         // ...otherwise, mPendingIntentWakeLock.release() gets called by onSendFinished()
6573     }
6574 
6575     @Override
onSendFinished(PendingIntent pendingIntent, Intent intent, int resultCode, String resultData, Bundle resultExtras)6576     public void onSendFinished(PendingIntent pendingIntent, Intent intent, int resultCode,
6577             String resultData, Bundle resultExtras) {
6578         if (DBG) log("Finished sending " + pendingIntent);
6579         mPendingIntentWakeLock.release();
6580         // Release with a delay so the receiving client has an opportunity to put in its
6581         // own request.
6582         releasePendingNetworkRequestWithDelay(pendingIntent);
6583     }
6584 
callCallbackForRequest(NetworkRequestInfo nri, NetworkAgentInfo networkAgent, int notificationType, int arg1)6585     private void callCallbackForRequest(NetworkRequestInfo nri,
6586             NetworkAgentInfo networkAgent, int notificationType, int arg1) {
6587         if (nri.messenger == null) {
6588             // Default request has no msgr. Also prevents callbacks from being invoked for
6589             // NetworkRequestInfos registered with ConnectivityDiagnostics requests. Those callbacks
6590             // are Type.LISTEN, but should not have NetworkCallbacks invoked.
6591             return;
6592         }
6593         Bundle bundle = new Bundle();
6594         // TODO: check if defensive copies of data is needed.
6595         putParcelable(bundle, new NetworkRequest(nri.request));
6596         Message msg = Message.obtain();
6597         if (notificationType != ConnectivityManager.CALLBACK_UNAVAIL) {
6598             putParcelable(bundle, networkAgent.network);
6599         }
6600         switch (notificationType) {
6601             case ConnectivityManager.CALLBACK_AVAILABLE: {
6602                 final NetworkCapabilities nc =
6603                         networkCapabilitiesRestrictedForCallerPermissions(
6604                                 networkAgent.networkCapabilities, nri.mPid, nri.mUid);
6605                 putParcelable(
6606                         bundle,
6607                         maybeSanitizeLocationInfoForCaller(
6608                                 nc, nri.mUid, nri.request.getRequestorPackageName()));
6609                 putParcelable(bundle, linkPropertiesRestrictedForCallerPermissions(
6610                         networkAgent.linkProperties, nri.mPid, nri.mUid));
6611                 // For this notification, arg1 contains the blocked status.
6612                 msg.arg1 = arg1;
6613                 break;
6614             }
6615             case ConnectivityManager.CALLBACK_LOSING: {
6616                 msg.arg1 = arg1;
6617                 break;
6618             }
6619             case ConnectivityManager.CALLBACK_CAP_CHANGED: {
6620                 // networkAgent can't be null as it has been accessed a few lines above.
6621                 final NetworkCapabilities netCap =
6622                         networkCapabilitiesRestrictedForCallerPermissions(
6623                                 networkAgent.networkCapabilities, nri.mPid, nri.mUid);
6624                 putParcelable(
6625                         bundle,
6626                         maybeSanitizeLocationInfoForCaller(
6627                                 netCap, nri.mUid, nri.request.getRequestorPackageName()));
6628                 break;
6629             }
6630             case ConnectivityManager.CALLBACK_IP_CHANGED: {
6631                 putParcelable(bundle, linkPropertiesRestrictedForCallerPermissions(
6632                         networkAgent.linkProperties, nri.mPid, nri.mUid));
6633                 break;
6634             }
6635             case ConnectivityManager.CALLBACK_BLK_CHANGED: {
6636                 maybeLogBlockedStatusChanged(nri, networkAgent.network, arg1 != 0);
6637                 msg.arg1 = arg1;
6638                 break;
6639             }
6640         }
6641         msg.what = notificationType;
6642         msg.setData(bundle);
6643         try {
6644             if (VDBG) {
6645                 String notification = ConnectivityManager.getCallbackName(notificationType);
6646                 log("sending notification " + notification + " for " + nri.request);
6647             }
6648             nri.messenger.send(msg);
6649         } catch (RemoteException e) {
6650             // may occur naturally in the race of binder death.
6651             loge("RemoteException caught trying to send a callback msg for " + nri.request);
6652         }
6653     }
6654 
putParcelable(Bundle bundle, T t)6655     private static <T extends Parcelable> void putParcelable(Bundle bundle, T t) {
6656         bundle.putParcelable(t.getClass().getSimpleName(), t);
6657     }
6658 
teardownUnneededNetwork(NetworkAgentInfo nai)6659     private void teardownUnneededNetwork(NetworkAgentInfo nai) {
6660         if (nai.numRequestNetworkRequests() != 0) {
6661             for (int i = 0; i < nai.numNetworkRequests(); i++) {
6662                 NetworkRequest nr = nai.requestAt(i);
6663                 // Ignore listening requests.
6664                 if (nr.isListen()) continue;
6665                 loge("Dead network still had at least " + nr);
6666                 break;
6667             }
6668         }
6669         nai.asyncChannel.disconnect();
6670     }
6671 
handleLingerComplete(NetworkAgentInfo oldNetwork)6672     private void handleLingerComplete(NetworkAgentInfo oldNetwork) {
6673         if (oldNetwork == null) {
6674             loge("Unknown NetworkAgentInfo in handleLingerComplete");
6675             return;
6676         }
6677         if (DBG) log("handleLingerComplete for " + oldNetwork.toShortString());
6678 
6679         // If we get here it means that the last linger timeout for this network expired. So there
6680         // must be no other active linger timers, and we must stop lingering.
6681         oldNetwork.clearLingerState();
6682 
6683         if (unneeded(oldNetwork, UnneededFor.TEARDOWN)) {
6684             // Tear the network down.
6685             teardownUnneededNetwork(oldNetwork);
6686         } else {
6687             // Put the network in the background.
6688             updateCapabilities(oldNetwork.getCurrentScore(), oldNetwork,
6689                     oldNetwork.networkCapabilities);
6690         }
6691     }
6692 
makeDefault(@ullable final NetworkAgentInfo newNetwork)6693     private void makeDefault(@Nullable final NetworkAgentInfo newNetwork) {
6694         if (DBG) log("Switching to new default network: " + newNetwork);
6695 
6696         mDefaultNetworkNai = newNetwork;
6697 
6698         try {
6699             if (null != newNetwork) {
6700                 mNMS.setDefaultNetId(newNetwork.network.netId);
6701             } else {
6702                 mNMS.clearDefaultNetId();
6703             }
6704         } catch (Exception e) {
6705             loge("Exception setting default network :" + e);
6706         }
6707 
6708         notifyLockdownVpn(newNetwork);
6709         handleApplyDefaultProxy(null != newNetwork
6710                 ? newNetwork.linkProperties.getHttpProxy() : null);
6711         updateTcpBufferSizes(null != newNetwork
6712                 ? newNetwork.linkProperties.getTcpBufferSizes() : null);
6713         mDnsManager.setDefaultDnsSystemProperties(null != newNetwork
6714                 ? newNetwork.linkProperties.getDnsServers() : Collections.EMPTY_LIST);
6715         notifyIfacesChangedForNetworkStats();
6716         // Fix up the NetworkCapabilities of any VPNs that don't specify underlying networks.
6717         updateAllVpnsCapabilities();
6718     }
6719 
processListenRequests(@onNull final NetworkAgentInfo nai)6720     private void processListenRequests(@NonNull final NetworkAgentInfo nai) {
6721         // For consistency with previous behaviour, send onLost callbacks before onAvailable.
6722         processNewlyLostListenRequests(nai);
6723         notifyNetworkCallbacks(nai, ConnectivityManager.CALLBACK_CAP_CHANGED);
6724         processNewlySatisfiedListenRequests(nai);
6725     }
6726 
processNewlyLostListenRequests(@onNull final NetworkAgentInfo nai)6727     private void processNewlyLostListenRequests(@NonNull final NetworkAgentInfo nai) {
6728         for (NetworkRequestInfo nri : mNetworkRequests.values()) {
6729             NetworkRequest nr = nri.request;
6730             if (!nr.isListen()) continue;
6731             if (nai.isSatisfyingRequest(nr.requestId) && !nai.satisfies(nr)) {
6732                 nai.removeRequest(nri.request.requestId);
6733                 callCallbackForRequest(nri, nai, ConnectivityManager.CALLBACK_LOST, 0);
6734             }
6735         }
6736     }
6737 
processNewlySatisfiedListenRequests(@onNull final NetworkAgentInfo nai)6738     private void processNewlySatisfiedListenRequests(@NonNull final NetworkAgentInfo nai) {
6739         for (NetworkRequestInfo nri : mNetworkRequests.values()) {
6740             NetworkRequest nr = nri.request;
6741             if (!nr.isListen()) continue;
6742             if (nai.satisfies(nr) && !nai.isSatisfyingRequest(nr.requestId)) {
6743                 nai.addRequest(nr);
6744                 notifyNetworkAvailable(nai, nri);
6745             }
6746         }
6747     }
6748 
6749     // An accumulator class to gather the list of changes that result from a rematch.
6750     private static class NetworkReassignment {
6751         static class RequestReassignment {
6752             @NonNull public final NetworkRequestInfo mRequest;
6753             @Nullable public final NetworkAgentInfo mOldNetwork;
6754             @Nullable public final NetworkAgentInfo mNewNetwork;
RequestReassignment(@onNull final NetworkRequestInfo request, @Nullable final NetworkAgentInfo oldNetwork, @Nullable final NetworkAgentInfo newNetwork)6755             RequestReassignment(@NonNull final NetworkRequestInfo request,
6756                     @Nullable final NetworkAgentInfo oldNetwork,
6757                     @Nullable final NetworkAgentInfo newNetwork) {
6758                 mRequest = request;
6759                 mOldNetwork = oldNetwork;
6760                 mNewNetwork = newNetwork;
6761             }
6762 
toString()6763             public String toString() {
6764                 return mRequest.request.requestId + " : "
6765                         + (null != mOldNetwork ? mOldNetwork.network.netId : "null")
6766                         + " → " + (null != mNewNetwork ? mNewNetwork.network.netId : "null");
6767             }
6768         }
6769 
6770         @NonNull private final ArrayList<RequestReassignment> mReassignments = new ArrayList<>();
6771 
getRequestReassignments()6772         @NonNull Iterable<RequestReassignment> getRequestReassignments() {
6773             return mReassignments;
6774         }
6775 
addRequestReassignment(@onNull final RequestReassignment reassignment)6776         void addRequestReassignment(@NonNull final RequestReassignment reassignment) {
6777             if (!Build.IS_USER) {
6778                 // The code is never supposed to add two reassignments of the same request. Make
6779                 // sure this stays true, but without imposing this expensive check on all
6780                 // reassignments on all user devices.
6781                 for (final RequestReassignment existing : mReassignments) {
6782                     if (existing.mRequest.equals(reassignment.mRequest)) {
6783                         throw new IllegalStateException("Trying to reassign ["
6784                                 + reassignment + "] but already have ["
6785                                 + existing + "]");
6786                     }
6787                 }
6788             }
6789             mReassignments.add(reassignment);
6790         }
6791 
6792         // Will return null if this reassignment does not change the network assigned to
6793         // the passed request.
6794         @Nullable
getReassignment(@onNull final NetworkRequestInfo nri)6795         private RequestReassignment getReassignment(@NonNull final NetworkRequestInfo nri) {
6796             for (final RequestReassignment event : getRequestReassignments()) {
6797                 if (nri == event.mRequest) return event;
6798             }
6799             return null;
6800         }
6801 
toString()6802         public String toString() {
6803             final StringJoiner sj = new StringJoiner(", " /* delimiter */,
6804                     "NetReassign [" /* prefix */, "]" /* suffix */);
6805             if (mReassignments.isEmpty()) return sj.add("no changes").toString();
6806             for (final RequestReassignment rr : getRequestReassignments()) {
6807                 sj.add(rr.toString());
6808             }
6809             return sj.toString();
6810         }
6811 
debugString()6812         public String debugString() {
6813             final StringBuilder sb = new StringBuilder();
6814             sb.append("NetworkReassignment :");
6815             if (mReassignments.isEmpty()) return sb.append(" no changes").toString();
6816             for (final RequestReassignment rr : getRequestReassignments()) {
6817                 sb.append("\n  ").append(rr);
6818             }
6819             return sb.append("\n").toString();
6820         }
6821     }
6822 
updateSatisfiersForRematchRequest(@onNull final NetworkRequestInfo nri, @Nullable final NetworkAgentInfo previousSatisfier, @Nullable final NetworkAgentInfo newSatisfier, final long now)6823     private void updateSatisfiersForRematchRequest(@NonNull final NetworkRequestInfo nri,
6824             @Nullable final NetworkAgentInfo previousSatisfier,
6825             @Nullable final NetworkAgentInfo newSatisfier,
6826             final long now) {
6827         if (newSatisfier != null) {
6828             if (VDBG) log("rematch for " + newSatisfier.toShortString());
6829             if (previousSatisfier != null) {
6830                 if (VDBG || DDBG) {
6831                     log("   accepting network in place of " + previousSatisfier.toShortString());
6832                 }
6833                 previousSatisfier.removeRequest(nri.request.requestId);
6834                 previousSatisfier.lingerRequest(nri.request, now, mLingerDelayMs);
6835             } else {
6836                 if (VDBG || DDBG) log("   accepting network in place of null");
6837             }
6838             newSatisfier.unlingerRequest(nri.request);
6839             if (!newSatisfier.addRequest(nri.request)) {
6840                 Slog.wtf(TAG, "BUG: " + newSatisfier.toShortString() + " already has "
6841                         + nri.request);
6842             }
6843         } else {
6844             if (DBG) {
6845                 log("Network " + previousSatisfier.toShortString() + " stopped satisfying"
6846                         + " request " + nri.request.requestId);
6847             }
6848             previousSatisfier.removeRequest(nri.request.requestId);
6849         }
6850         nri.mSatisfier = newSatisfier;
6851     }
6852 
6853     @NonNull
computeNetworkReassignment()6854     private NetworkReassignment computeNetworkReassignment() {
6855         ensureRunningOnConnectivityServiceThread();
6856         final NetworkReassignment changes = new NetworkReassignment();
6857 
6858         // Gather the list of all relevant agents and sort them by score.
6859         final ArrayList<NetworkAgentInfo> nais = new ArrayList<>();
6860         for (final NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
6861             if (!nai.everConnected) continue;
6862             nais.add(nai);
6863         }
6864 
6865         for (final NetworkRequestInfo nri : mNetworkRequests.values()) {
6866             if (nri.request.isListen()) continue;
6867             final NetworkAgentInfo bestNetwork = mNetworkRanker.getBestNetwork(nri.request, nais);
6868             if (bestNetwork != nri.mSatisfier) {
6869                 // bestNetwork may be null if no network can satisfy this request.
6870                 changes.addRequestReassignment(new NetworkReassignment.RequestReassignment(
6871                         nri, nri.mSatisfier, bestNetwork));
6872             }
6873         }
6874         return changes;
6875     }
6876 
6877     /**
6878      * Attempt to rematch all Networks with NetworkRequests.  This may result in Networks
6879      * being disconnected.
6880      */
rematchAllNetworksAndRequests()6881     private void rematchAllNetworksAndRequests() {
6882         // TODO: This may be slow, and should be optimized.
6883         final long now = SystemClock.elapsedRealtime();
6884         final NetworkReassignment changes = computeNetworkReassignment();
6885         if (VDBG || DDBG) {
6886             log(changes.debugString());
6887         } else if (DBG) {
6888             log(changes.toString()); // Shorter form, only one line of log
6889         }
6890         applyNetworkReassignment(changes, now);
6891     }
6892 
applyNetworkReassignment(@onNull final NetworkReassignment changes, final long now)6893     private void applyNetworkReassignment(@NonNull final NetworkReassignment changes,
6894             final long now) {
6895         final Collection<NetworkAgentInfo> nais = mNetworkAgentInfos.values();
6896 
6897         // Since most of the time there are only 0 or 1 background networks, it would probably
6898         // be more efficient to just use an ArrayList here. TODO : measure performance
6899         final ArraySet<NetworkAgentInfo> oldBgNetworks = new ArraySet<>();
6900         for (final NetworkAgentInfo nai : nais) {
6901             if (nai.isBackgroundNetwork()) oldBgNetworks.add(nai);
6902         }
6903 
6904         // First, update the lists of satisfied requests in the network agents. This is necessary
6905         // because some code later depends on this state to be correct, most prominently computing
6906         // the linger status.
6907         for (final NetworkReassignment.RequestReassignment event :
6908                 changes.getRequestReassignments()) {
6909             updateSatisfiersForRematchRequest(event.mRequest, event.mOldNetwork,
6910                     event.mNewNetwork, now);
6911         }
6912 
6913         final NetworkAgentInfo oldDefaultNetwork = getDefaultNetwork();
6914         final NetworkRequestInfo defaultRequestInfo = mNetworkRequests.get(mDefaultRequest);
6915         final NetworkReassignment.RequestReassignment reassignment =
6916                 changes.getReassignment(defaultRequestInfo);
6917         final NetworkAgentInfo newDefaultNetwork =
6918                 null != reassignment ? reassignment.mNewNetwork : oldDefaultNetwork;
6919 
6920         if (oldDefaultNetwork != newDefaultNetwork) {
6921             if (oldDefaultNetwork != null) {
6922                 mLingerMonitor.noteLingerDefaultNetwork(oldDefaultNetwork, newDefaultNetwork);
6923             }
6924             updateDataActivityTracking(newDefaultNetwork, oldDefaultNetwork);
6925             // Notify system services of the new default.
6926             makeDefault(newDefaultNetwork);
6927             // Log 0 -> X and Y -> X default network transitions, where X is the new default.
6928             mDeps.getMetricsLogger().defaultNetworkMetrics().logDefaultNetworkEvent(
6929                     now, newDefaultNetwork, oldDefaultNetwork);
6930             // Have a new default network, release the transition wakelock in
6931             scheduleReleaseNetworkTransitionWakelock();
6932         }
6933 
6934         // Notify requested networks are available after the default net is switched, but
6935         // before LegacyTypeTracker sends legacy broadcasts
6936         for (final NetworkReassignment.RequestReassignment event :
6937                 changes.getRequestReassignments()) {
6938             // Tell NetworkProviders about the new score, so they can stop
6939             // trying to connect if they know they cannot match it.
6940             // TODO - this could get expensive if there are a lot of outstanding requests for this
6941             // network. Think of a way to reduce this. Push netid->request mapping to each factory?
6942             sendUpdatedScoreToFactories(event.mRequest.request, event.mNewNetwork);
6943 
6944             if (null != event.mNewNetwork) {
6945                 notifyNetworkAvailable(event.mNewNetwork, event.mRequest);
6946             } else {
6947                 callCallbackForRequest(event.mRequest, event.mOldNetwork,
6948                         ConnectivityManager.CALLBACK_LOST, 0);
6949             }
6950         }
6951 
6952         // Update the linger state before processing listen callbacks, because the background
6953         // computation depends on whether the network is lingering. Don't send the LOSING callbacks
6954         // just yet though, because they have to be sent after the listens are processed to keep
6955         // backward compatibility.
6956         final ArrayList<NetworkAgentInfo> lingeredNetworks = new ArrayList<>();
6957         for (final NetworkAgentInfo nai : nais) {
6958             // Rematching may have altered the linger state of some networks, so update all linger
6959             // timers. updateLingerState reads the state from the network agent and does nothing
6960             // if the state has not changed : the source of truth is controlled with
6961             // NetworkAgentInfo#lingerRequest and NetworkAgentInfo#unlingerRequest, which have been
6962             // called while rematching the individual networks above.
6963             if (updateLingerState(nai, now)) {
6964                 lingeredNetworks.add(nai);
6965             }
6966         }
6967 
6968         for (final NetworkAgentInfo nai : nais) {
6969             if (!nai.everConnected) continue;
6970             final boolean oldBackground = oldBgNetworks.contains(nai);
6971             // Process listen requests and update capabilities if the background state has
6972             // changed for this network. For consistency with previous behavior, send onLost
6973             // callbacks before onAvailable.
6974             processNewlyLostListenRequests(nai);
6975             if (oldBackground != nai.isBackgroundNetwork()) {
6976                 applyBackgroundChangeForRematch(nai);
6977             }
6978             processNewlySatisfiedListenRequests(nai);
6979         }
6980 
6981         for (final NetworkAgentInfo nai : lingeredNetworks) {
6982             notifyNetworkLosing(nai, now);
6983         }
6984 
6985         updateLegacyTypeTrackerAndVpnLockdownForRematch(oldDefaultNetwork, newDefaultNetwork, nais);
6986 
6987         // Tear down all unneeded networks.
6988         for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
6989             if (unneeded(nai, UnneededFor.TEARDOWN)) {
6990                 if (nai.getLingerExpiry() > 0) {
6991                     // This network has active linger timers and no requests, but is not
6992                     // lingering. Linger it.
6993                     //
6994                     // One way (the only way?) this can happen if this network is unvalidated
6995                     // and became unneeded due to another network improving its score to the
6996                     // point where this network will no longer be able to satisfy any requests
6997                     // even if it validates.
6998                     if (updateLingerState(nai, now)) {
6999                         notifyNetworkLosing(nai, now);
7000                     }
7001                 } else {
7002                     if (DBG) log("Reaping " + nai.toShortString());
7003                     teardownUnneededNetwork(nai);
7004                 }
7005             }
7006         }
7007     }
7008 
7009     /**
7010      * Apply a change in background state resulting from rematching networks with requests.
7011      *
7012      * During rematch, a network may change background states by starting to satisfy or stopping
7013      * to satisfy a foreground request. Listens don't count for this. When a network changes
7014      * background states, its capabilities need to be updated and callbacks fired for the
7015      * capability change.
7016      *
7017      * @param nai The network that changed background states
7018      */
applyBackgroundChangeForRematch(@onNull final NetworkAgentInfo nai)7019     private void applyBackgroundChangeForRematch(@NonNull final NetworkAgentInfo nai) {
7020         final NetworkCapabilities newNc = mixInCapabilities(nai, nai.networkCapabilities);
7021         if (Objects.equals(nai.networkCapabilities, newNc)) return;
7022         updateNetworkPermissions(nai, newNc);
7023         nai.getAndSetNetworkCapabilities(newNc);
7024         notifyNetworkCallbacks(nai, ConnectivityManager.CALLBACK_CAP_CHANGED);
7025     }
7026 
updateLegacyTypeTrackerAndVpnLockdownForRematch( @ullable final NetworkAgentInfo oldDefaultNetwork, @Nullable final NetworkAgentInfo newDefaultNetwork, @NonNull final Collection<NetworkAgentInfo> nais)7027     private void updateLegacyTypeTrackerAndVpnLockdownForRematch(
7028             @Nullable final NetworkAgentInfo oldDefaultNetwork,
7029             @Nullable final NetworkAgentInfo newDefaultNetwork,
7030             @NonNull final Collection<NetworkAgentInfo> nais) {
7031         if (oldDefaultNetwork != newDefaultNetwork) {
7032             // Maintain the illusion : since the legacy API only understands one network at a time,
7033             // if the default network changed, apps should see a disconnected broadcast for the
7034             // old default network before they see a connected broadcast for the new one.
7035             if (oldDefaultNetwork != null) {
7036                 mLegacyTypeTracker.remove(oldDefaultNetwork.networkInfo.getType(),
7037                         oldDefaultNetwork, true);
7038             }
7039             if (newDefaultNetwork != null) {
7040                 // The new default network can be newly null if and only if the old default
7041                 // network doesn't satisfy the default request any more because it lost a
7042                 // capability.
7043                 mDefaultInetConditionPublished = newDefaultNetwork.lastValidated ? 100 : 0;
7044                 mLegacyTypeTracker.add(newDefaultNetwork.networkInfo.getType(), newDefaultNetwork);
7045                 // If the legacy VPN is connected, notifyLockdownVpn may end up sending a broadcast
7046                 // to reflect the NetworkInfo of this new network. This broadcast has to be sent
7047                 // after the disconnect broadcasts above, but before the broadcasts sent by the
7048                 // legacy type tracker below.
7049                 // TODO : refactor this, it's too complex
7050                 notifyLockdownVpn(newDefaultNetwork);
7051             }
7052         }
7053 
7054         // Now that all the callbacks have been sent, send the legacy network broadcasts
7055         // as needed. This is necessary so that legacy requests correctly bind dns
7056         // requests to this network. The legacy users are listening for this broadcast
7057         // and will generally do a dns request so they can ensureRouteToHost and if
7058         // they do that before the callbacks happen they'll use the default network.
7059         //
7060         // TODO: Is there still a race here? The legacy broadcast will be sent after sending
7061         // callbacks, but if apps can receive the broadcast before the callback, they still might
7062         // have an inconsistent view of networking.
7063         //
7064         // This *does* introduce a race where if the user uses the new api
7065         // (notification callbacks) and then uses the old api (getNetworkInfo(type))
7066         // they may get old info. Reverse this after the old startUsing api is removed.
7067         // This is on top of the multiple intent sequencing referenced in the todo above.
7068         for (NetworkAgentInfo nai : nais) {
7069             if (nai.everConnected) {
7070                 addNetworkToLegacyTypeTracker(nai);
7071             }
7072         }
7073     }
7074 
addNetworkToLegacyTypeTracker(@onNull final NetworkAgentInfo nai)7075     private void addNetworkToLegacyTypeTracker(@NonNull final NetworkAgentInfo nai) {
7076         for (int i = 0; i < nai.numNetworkRequests(); i++) {
7077             NetworkRequest nr = nai.requestAt(i);
7078             if (nr.legacyType != TYPE_NONE && nr.isRequest()) {
7079                 // legacy type tracker filters out repeat adds
7080                 mLegacyTypeTracker.add(nr.legacyType, nai);
7081             }
7082         }
7083 
7084         // A VPN generally won't get added to the legacy tracker in the "for (nri)" loop above,
7085         // because usually there are no NetworkRequests it satisfies (e.g., mDefaultRequest
7086         // wants the NOT_VPN capability, so it will never be satisfied by a VPN). So, add the
7087         // newNetwork to the tracker explicitly (it's a no-op if it has already been added).
7088         if (nai.isVPN()) {
7089             mLegacyTypeTracker.add(TYPE_VPN, nai);
7090         }
7091     }
7092 
updateInetCondition(NetworkAgentInfo nai)7093     private void updateInetCondition(NetworkAgentInfo nai) {
7094         // Don't bother updating until we've graduated to validated at least once.
7095         if (!nai.everValidated) return;
7096         // For now only update icons for default connection.
7097         // TODO: Update WiFi and cellular icons separately. b/17237507
7098         if (!isDefaultNetwork(nai)) return;
7099 
7100         int newInetCondition = nai.lastValidated ? 100 : 0;
7101         // Don't repeat publish.
7102         if (newInetCondition == mDefaultInetConditionPublished) return;
7103 
7104         mDefaultInetConditionPublished = newInetCondition;
7105         sendInetConditionBroadcast(nai.networkInfo);
7106     }
7107 
notifyLockdownVpn(NetworkAgentInfo nai)7108     private void notifyLockdownVpn(NetworkAgentInfo nai) {
7109         synchronized (mVpns) {
7110             if (mLockdownTracker != null) {
7111                 if (nai != null && nai.isVPN()) {
7112                     mLockdownTracker.onVpnStateChanged(nai.networkInfo);
7113                 } else {
7114                     mLockdownTracker.onNetworkInfoChanged();
7115                 }
7116             }
7117         }
7118     }
7119 
7120     @NonNull
mixInInfo(@onNull final NetworkAgentInfo nai, @NonNull NetworkInfo info)7121     private NetworkInfo mixInInfo(@NonNull final NetworkAgentInfo nai, @NonNull NetworkInfo info) {
7122         final NetworkInfo newInfo = new NetworkInfo(info);
7123         // The suspended and roaming bits are managed in NetworkCapabilities.
7124         final boolean suspended =
7125                 !nai.networkCapabilities.hasCapability(NET_CAPABILITY_NOT_SUSPENDED);
7126         if (suspended && info.getDetailedState() == NetworkInfo.DetailedState.CONNECTED) {
7127             // Only override the state with SUSPENDED if the network is currently in CONNECTED
7128             // state. This is because the network could have been suspended before connecting,
7129             // or it could be disconnecting while being suspended, and in both these cases
7130             // the state should not be overridden. Note that the only detailed state that
7131             // maps to State.CONNECTED is DetailedState.CONNECTED, so there is also no need to
7132             // worry about multiple different substates of CONNECTED.
7133             newInfo.setDetailedState(NetworkInfo.DetailedState.SUSPENDED, info.getReason(),
7134                     info.getExtraInfo());
7135         } else if (!suspended && info.getDetailedState() == NetworkInfo.DetailedState.SUSPENDED) {
7136             // SUSPENDED state is currently only overridden from CONNECTED state. In the case the
7137             // network agent is created, then goes to suspended, then goes out of suspended without
7138             // ever setting connected. Check if network agent is ever connected to update the state.
7139             newInfo.setDetailedState(nai.everConnected
7140                     ? NetworkInfo.DetailedState.CONNECTED
7141                     : NetworkInfo.DetailedState.CONNECTING,
7142                     info.getReason(),
7143                     info.getExtraInfo());
7144         }
7145         newInfo.setRoaming(!nai.networkCapabilities.hasCapability(NET_CAPABILITY_NOT_ROAMING));
7146         return newInfo;
7147     }
7148 
updateNetworkInfo(NetworkAgentInfo networkAgent, NetworkInfo info)7149     private void updateNetworkInfo(NetworkAgentInfo networkAgent, NetworkInfo info) {
7150         final NetworkInfo newInfo = mixInInfo(networkAgent, info);
7151 
7152         final NetworkInfo.State state = newInfo.getState();
7153         NetworkInfo oldInfo = null;
7154         synchronized (networkAgent) {
7155             oldInfo = networkAgent.networkInfo;
7156             networkAgent.networkInfo = newInfo;
7157         }
7158         notifyLockdownVpn(networkAgent);
7159 
7160         if (DBG) {
7161             log(networkAgent.toShortString() + " EVENT_NETWORK_INFO_CHANGED, going from "
7162                     + oldInfo.getState() + " to " + state);
7163         }
7164 
7165         if (!networkAgent.created
7166                 && (state == NetworkInfo.State.CONNECTED
7167                 || (state == NetworkInfo.State.CONNECTING && networkAgent.isVPN()))) {
7168 
7169             // A network that has just connected has zero requests and is thus a foreground network.
7170             networkAgent.networkCapabilities.addCapability(NET_CAPABILITY_FOREGROUND);
7171 
7172             if (!createNativeNetwork(networkAgent)) return;
7173             if (networkAgent.isVPN()) {
7174                 // Initialize the VPN capabilities to their starting values according to the
7175                 // underlying networks. This will avoid a spurious callback to
7176                 // onCapabilitiesUpdated being sent in updateAllVpnCapabilities below as
7177                 // the VPN would switch from its default, blank capabilities to those
7178                 // that reflect the capabilities of its underlying networks.
7179                 updateAllVpnsCapabilities();
7180             }
7181             networkAgent.created = true;
7182         }
7183 
7184         if (!networkAgent.everConnected && state == NetworkInfo.State.CONNECTED) {
7185             networkAgent.everConnected = true;
7186 
7187             if (networkAgent.linkProperties == null) {
7188                 Slog.wtf(TAG, networkAgent.toShortString() + " connected with null LinkProperties");
7189             }
7190 
7191             // NetworkCapabilities need to be set before sending the private DNS config to
7192             // NetworkMonitor, otherwise NetworkMonitor cannot determine if validation is required.
7193             networkAgent.getAndSetNetworkCapabilities(networkAgent.networkCapabilities);
7194 
7195             handlePerNetworkPrivateDnsConfig(networkAgent, mDnsManager.getPrivateDnsConfig());
7196             updateLinkProperties(networkAgent, new LinkProperties(networkAgent.linkProperties),
7197                     null);
7198 
7199             // Until parceled LinkProperties are sent directly to NetworkMonitor, the connect
7200             // command must be sent after updating LinkProperties to maximize chances of
7201             // NetworkMonitor seeing the correct LinkProperties when starting.
7202             // TODO: pass LinkProperties to the NetworkMonitor in the notifyNetworkConnected call.
7203             if (networkAgent.networkAgentConfig.acceptPartialConnectivity) {
7204                 networkAgent.networkMonitor().setAcceptPartialConnectivity();
7205             }
7206             networkAgent.networkMonitor().notifyNetworkConnected(
7207                     new LinkProperties(networkAgent.linkProperties,
7208                             true /* parcelSensitiveFields */),
7209                     networkAgent.networkCapabilities);
7210             scheduleUnvalidatedPrompt(networkAgent);
7211 
7212             // Whether a particular NetworkRequest listen should cause signal strength thresholds to
7213             // be communicated to a particular NetworkAgent depends only on the network's immutable,
7214             // capabilities, so it only needs to be done once on initial connect, not every time the
7215             // network's capabilities change. Note that we do this before rematching the network,
7216             // so we could decide to tear it down immediately afterwards. That's fine though - on
7217             // disconnection NetworkAgents should stop any signal strength monitoring they have been
7218             // doing.
7219             updateSignalStrengthThresholds(networkAgent, "CONNECT", null);
7220 
7221             if (networkAgent.isVPN()) {
7222                 updateAllVpnsCapabilities();
7223             }
7224 
7225             // Consider network even though it is not yet validated.
7226             rematchAllNetworksAndRequests();
7227 
7228             // This has to happen after matching the requests, because callbacks are just requests.
7229             notifyNetworkCallbacks(networkAgent, ConnectivityManager.CALLBACK_PRECHECK);
7230         } else if (state == NetworkInfo.State.DISCONNECTED) {
7231             networkAgent.asyncChannel.disconnect();
7232             if (networkAgent.isVPN()) {
7233                 updateUids(networkAgent, networkAgent.networkCapabilities, null);
7234             }
7235             disconnectAndDestroyNetwork(networkAgent);
7236             if (networkAgent.isVPN()) {
7237                 // As the active or bound network changes for apps, broadcast the default proxy, as
7238                 // apps may need to update their proxy data. This is called after disconnecting from
7239                 // VPN to make sure we do not broadcast the old proxy data.
7240                 // TODO(b/122649188): send the broadcast only to VPN users.
7241                 mProxyTracker.sendProxyBroadcast();
7242             }
7243         } else if (networkAgent.created && (oldInfo.getState() == NetworkInfo.State.SUSPENDED ||
7244                 state == NetworkInfo.State.SUSPENDED)) {
7245             mLegacyTypeTracker.update(networkAgent);
7246         }
7247     }
7248 
updateNetworkScore(@onNull final NetworkAgentInfo nai, final int score)7249     private void updateNetworkScore(@NonNull final NetworkAgentInfo nai, final int score) {
7250         if (VDBG || DDBG) log("updateNetworkScore for " + nai.toShortString() + " to " + score);
7251         nai.setScore(score);
7252         rematchAllNetworksAndRequests();
7253         sendUpdatedScoreToFactories(nai);
7254     }
7255 
7256     // Notify only this one new request of the current state. Transfer all the
7257     // current state by calling NetworkCapabilities and LinkProperties callbacks
7258     // so that callers can be guaranteed to have as close to atomicity in state
7259     // transfer as can be supported by this current API.
notifyNetworkAvailable(NetworkAgentInfo nai, NetworkRequestInfo nri)7260     protected void notifyNetworkAvailable(NetworkAgentInfo nai, NetworkRequestInfo nri) {
7261         mHandler.removeMessages(EVENT_TIMEOUT_NETWORK_REQUEST, nri);
7262         if (nri.mPendingIntent != null) {
7263             sendPendingIntentForRequest(nri, nai, ConnectivityManager.CALLBACK_AVAILABLE);
7264             // Attempt no subsequent state pushes where intents are involved.
7265             return;
7266         }
7267 
7268         final boolean metered = nai.networkCapabilities.isMetered();
7269         final boolean blocked = isUidNetworkingWithVpnBlocked(nri.mUid, mUidRules.get(nri.mUid),
7270                 metered, mRestrictBackground);
7271         callCallbackForRequest(nri, nai, ConnectivityManager.CALLBACK_AVAILABLE, blocked ? 1 : 0);
7272     }
7273 
7274     // Notify the requests on this NAI that the network is now lingered.
notifyNetworkLosing(@onNull final NetworkAgentInfo nai, final long now)7275     private void notifyNetworkLosing(@NonNull final NetworkAgentInfo nai, final long now) {
7276         final int lingerTime = (int) (nai.getLingerExpiry() - now);
7277         notifyNetworkCallbacks(nai, ConnectivityManager.CALLBACK_LOSING, lingerTime);
7278     }
7279 
7280     /**
7281      * Notify of the blocked state apps with a registered callback matching a given NAI.
7282      *
7283      * Unlike other callbacks, blocked status is different between each individual uid. So for
7284      * any given nai, all requests need to be considered according to the uid who filed it.
7285      *
7286      * @param nai The target NetworkAgentInfo.
7287      * @param oldMetered True if the previous network capabilities is metered.
7288      * @param newRestrictBackground True if data saver is enabled.
7289      */
maybeNotifyNetworkBlocked(NetworkAgentInfo nai, boolean oldMetered, boolean newMetered, boolean oldRestrictBackground, boolean newRestrictBackground)7290     private void maybeNotifyNetworkBlocked(NetworkAgentInfo nai, boolean oldMetered,
7291             boolean newMetered, boolean oldRestrictBackground, boolean newRestrictBackground) {
7292 
7293         for (int i = 0; i < nai.numNetworkRequests(); i++) {
7294             NetworkRequest nr = nai.requestAt(i);
7295             NetworkRequestInfo nri = mNetworkRequests.get(nr);
7296             final int uidRules = mUidRules.get(nri.mUid);
7297             final boolean oldBlocked, newBlocked;
7298             // mVpns lock needs to be hold here to ensure that the active VPN cannot be changed
7299             // between these two calls.
7300             synchronized (mVpns) {
7301                 oldBlocked = isUidNetworkingWithVpnBlocked(nri.mUid, uidRules, oldMetered,
7302                         oldRestrictBackground);
7303                 newBlocked = isUidNetworkingWithVpnBlocked(nri.mUid, uidRules, newMetered,
7304                         newRestrictBackground);
7305             }
7306             if (oldBlocked != newBlocked) {
7307                 callCallbackForRequest(nri, nai, ConnectivityManager.CALLBACK_BLK_CHANGED,
7308                         encodeBool(newBlocked));
7309             }
7310         }
7311     }
7312 
7313     /**
7314      * Notify apps with a given UID of the new blocked state according to new uid rules.
7315      * @param uid The uid for which the rules changed.
7316      * @param newRules The new rules to apply.
7317      */
maybeNotifyNetworkBlockedForNewUidRules(int uid, int newRules)7318     private void maybeNotifyNetworkBlockedForNewUidRules(int uid, int newRules) {
7319         for (final NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
7320             final boolean metered = nai.networkCapabilities.isMetered();
7321             final boolean oldBlocked, newBlocked;
7322             // TODO: Consider that doze mode or turn on/off battery saver would deliver lots of uid
7323             // rules changed event. And this function actually loop through all connected nai and
7324             // its requests. It seems that mVpns lock will be grabbed frequently in this case.
7325             // Reduce the number of locking or optimize the use of lock are likely needed in future.
7326             synchronized (mVpns) {
7327                 oldBlocked = isUidNetworkingWithVpnBlocked(
7328                         uid, mUidRules.get(uid), metered, mRestrictBackground);
7329                 newBlocked = isUidNetworkingWithVpnBlocked(
7330                         uid, newRules, metered, mRestrictBackground);
7331             }
7332             if (oldBlocked == newBlocked) {
7333                 continue;
7334             }
7335             final int arg = encodeBool(newBlocked);
7336             for (int i = 0; i < nai.numNetworkRequests(); i++) {
7337                 NetworkRequest nr = nai.requestAt(i);
7338                 NetworkRequestInfo nri = mNetworkRequests.get(nr);
7339                 if (nri != null && nri.mUid == uid) {
7340                     callCallbackForRequest(nri, nai, ConnectivityManager.CALLBACK_BLK_CHANGED, arg);
7341                 }
7342             }
7343         }
7344     }
7345 
7346     @VisibleForTesting
sendLegacyNetworkBroadcast(NetworkAgentInfo nai, DetailedState state, int type)7347     protected void sendLegacyNetworkBroadcast(NetworkAgentInfo nai, DetailedState state, int type) {
7348         // The NetworkInfo we actually send out has no bearing on the real
7349         // state of affairs. For example, if the default connection is mobile,
7350         // and a request for HIPRI has just gone away, we need to pretend that
7351         // HIPRI has just disconnected. So we need to set the type to HIPRI and
7352         // the state to DISCONNECTED, even though the network is of type MOBILE
7353         // and is still connected.
7354         NetworkInfo info = new NetworkInfo(nai.networkInfo);
7355         info.setType(type);
7356         if (state != DetailedState.DISCONNECTED) {
7357             info.setDetailedState(state, null, info.getExtraInfo());
7358             sendConnectedBroadcast(info);
7359         } else {
7360             info.setDetailedState(state, info.getReason(), info.getExtraInfo());
7361             Intent intent = new Intent(ConnectivityManager.CONNECTIVITY_ACTION);
7362             intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, info);
7363             intent.putExtra(ConnectivityManager.EXTRA_NETWORK_TYPE, info.getType());
7364             if (info.isFailover()) {
7365                 intent.putExtra(ConnectivityManager.EXTRA_IS_FAILOVER, true);
7366                 nai.networkInfo.setFailover(false);
7367             }
7368             if (info.getReason() != null) {
7369                 intent.putExtra(ConnectivityManager.EXTRA_REASON, info.getReason());
7370             }
7371             if (info.getExtraInfo() != null) {
7372                 intent.putExtra(ConnectivityManager.EXTRA_EXTRA_INFO, info.getExtraInfo());
7373             }
7374             NetworkAgentInfo newDefaultAgent = null;
7375             if (nai.isSatisfyingRequest(mDefaultRequest.requestId)) {
7376                 newDefaultAgent = getDefaultNetwork();
7377                 if (newDefaultAgent != null) {
7378                     intent.putExtra(ConnectivityManager.EXTRA_OTHER_NETWORK_INFO,
7379                             newDefaultAgent.networkInfo);
7380                 } else {
7381                     intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, true);
7382                 }
7383             }
7384             intent.putExtra(ConnectivityManager.EXTRA_INET_CONDITION,
7385                     mDefaultInetConditionPublished);
7386             sendStickyBroadcast(intent);
7387             if (newDefaultAgent != null) {
7388                 sendConnectedBroadcast(newDefaultAgent.networkInfo);
7389             }
7390         }
7391     }
7392 
notifyNetworkCallbacks(NetworkAgentInfo networkAgent, int notifyType, int arg1)7393     protected void notifyNetworkCallbacks(NetworkAgentInfo networkAgent, int notifyType, int arg1) {
7394         if (VDBG || DDBG) {
7395             String notification = ConnectivityManager.getCallbackName(notifyType);
7396             log("notifyType " + notification + " for " + networkAgent.toShortString());
7397         }
7398         for (int i = 0; i < networkAgent.numNetworkRequests(); i++) {
7399             NetworkRequest nr = networkAgent.requestAt(i);
7400             NetworkRequestInfo nri = mNetworkRequests.get(nr);
7401             if (VDBG) log(" sending notification for " + nr);
7402             if (nri.mPendingIntent == null) {
7403                 callCallbackForRequest(nri, networkAgent, notifyType, arg1);
7404             } else {
7405                 sendPendingIntentForRequest(nri, networkAgent, notifyType);
7406             }
7407         }
7408     }
7409 
notifyNetworkCallbacks(NetworkAgentInfo networkAgent, int notifyType)7410     protected void notifyNetworkCallbacks(NetworkAgentInfo networkAgent, int notifyType) {
7411         notifyNetworkCallbacks(networkAgent, notifyType, 0);
7412     }
7413 
7414     /**
7415      * Returns the list of all interfaces that could be used by network traffic that does not
7416      * explicitly specify a network. This includes the default network, but also all VPNs that are
7417      * currently connected.
7418      *
7419      * Must be called on the handler thread.
7420      */
getDefaultNetworks()7421     private Network[] getDefaultNetworks() {
7422         ensureRunningOnConnectivityServiceThread();
7423         ArrayList<Network> defaultNetworks = new ArrayList<>();
7424         NetworkAgentInfo defaultNetwork = getDefaultNetwork();
7425         for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
7426             if (nai.everConnected && (nai == defaultNetwork || nai.isVPN())) {
7427                 defaultNetworks.add(nai.network);
7428             }
7429         }
7430         return defaultNetworks.toArray(new Network[0]);
7431     }
7432 
7433     /**
7434      * Notify NetworkStatsService that the set of active ifaces has changed, or that one of the
7435      * active iface's tracked properties has changed.
7436      */
notifyIfacesChangedForNetworkStats()7437     private void notifyIfacesChangedForNetworkStats() {
7438         ensureRunningOnConnectivityServiceThread();
7439         String activeIface = null;
7440         LinkProperties activeLinkProperties = getActiveLinkProperties();
7441         if (activeLinkProperties != null) {
7442             activeIface = activeLinkProperties.getInterfaceName();
7443         }
7444 
7445         final VpnInfo[] vpnInfos = getAllVpnInfo();
7446         try {
7447             mStatsService.forceUpdateIfaces(
7448                     getDefaultNetworks(), getAllNetworkState(), activeIface, vpnInfos);
7449         } catch (Exception ignored) {
7450         }
7451     }
7452 
7453     @Override
addVpnAddress(String address, int prefixLength)7454     public boolean addVpnAddress(String address, int prefixLength) {
7455         int user = UserHandle.getUserId(Binder.getCallingUid());
7456         synchronized (mVpns) {
7457             throwIfLockdownEnabled();
7458             return mVpns.get(user).addAddress(address, prefixLength);
7459         }
7460     }
7461 
7462     @Override
removeVpnAddress(String address, int prefixLength)7463     public boolean removeVpnAddress(String address, int prefixLength) {
7464         int user = UserHandle.getUserId(Binder.getCallingUid());
7465         synchronized (mVpns) {
7466             throwIfLockdownEnabled();
7467             return mVpns.get(user).removeAddress(address, prefixLength);
7468         }
7469     }
7470 
7471     @Override
setUnderlyingNetworksForVpn(Network[] networks)7472     public boolean setUnderlyingNetworksForVpn(Network[] networks) {
7473         int user = UserHandle.getUserId(Binder.getCallingUid());
7474         final boolean success;
7475         synchronized (mVpns) {
7476             throwIfLockdownEnabled();
7477             success = mVpns.get(user).setUnderlyingNetworks(networks);
7478         }
7479         if (success) {
7480             mHandler.post(() -> {
7481                 // Update VPN's capabilities based on updated underlying network set.
7482                 updateAllVpnsCapabilities();
7483                 notifyIfacesChangedForNetworkStats();
7484             });
7485         }
7486         return success;
7487     }
7488 
7489     @Override
getCaptivePortalServerUrl()7490     public String getCaptivePortalServerUrl() {
7491         enforceNetworkStackOrSettingsPermission();
7492         String settingUrl = mContext.getResources().getString(
7493                 R.string.config_networkCaptivePortalServerUrl);
7494 
7495         if (!TextUtils.isEmpty(settingUrl)) {
7496             return settingUrl;
7497         }
7498 
7499         settingUrl = Settings.Global.getString(mContext.getContentResolver(),
7500                 Settings.Global.CAPTIVE_PORTAL_HTTP_URL);
7501         if (!TextUtils.isEmpty(settingUrl)) {
7502             return settingUrl;
7503         }
7504 
7505         return DEFAULT_CAPTIVE_PORTAL_HTTP_URL;
7506     }
7507 
7508     @Override
startNattKeepalive(Network network, int intervalSeconds, ISocketKeepaliveCallback cb, String srcAddr, int srcPort, String dstAddr)7509     public void startNattKeepalive(Network network, int intervalSeconds,
7510             ISocketKeepaliveCallback cb, String srcAddr, int srcPort, String dstAddr) {
7511         enforceKeepalivePermission();
7512         mKeepaliveTracker.startNattKeepalive(
7513                 getNetworkAgentInfoForNetwork(network), null /* fd */,
7514                 intervalSeconds, cb,
7515                 srcAddr, srcPort, dstAddr, NattSocketKeepalive.NATT_PORT);
7516     }
7517 
7518     @Override
startNattKeepaliveWithFd(Network network, FileDescriptor fd, int resourceId, int intervalSeconds, ISocketKeepaliveCallback cb, String srcAddr, String dstAddr)7519     public void startNattKeepaliveWithFd(Network network, FileDescriptor fd, int resourceId,
7520             int intervalSeconds, ISocketKeepaliveCallback cb, String srcAddr,
7521             String dstAddr) {
7522         mKeepaliveTracker.startNattKeepalive(
7523                 getNetworkAgentInfoForNetwork(network), fd, resourceId,
7524                 intervalSeconds, cb,
7525                 srcAddr, dstAddr, NattSocketKeepalive.NATT_PORT);
7526     }
7527 
7528     @Override
startTcpKeepalive(Network network, FileDescriptor fd, int intervalSeconds, ISocketKeepaliveCallback cb)7529     public void startTcpKeepalive(Network network, FileDescriptor fd, int intervalSeconds,
7530             ISocketKeepaliveCallback cb) {
7531         enforceKeepalivePermission();
7532         mKeepaliveTracker.startTcpKeepalive(
7533                 getNetworkAgentInfoForNetwork(network), fd, intervalSeconds, cb);
7534     }
7535 
7536     @Override
stopKeepalive(Network network, int slot)7537     public void stopKeepalive(Network network, int slot) {
7538         mHandler.sendMessage(mHandler.obtainMessage(
7539                 NetworkAgent.CMD_STOP_SOCKET_KEEPALIVE, slot, SocketKeepalive.SUCCESS, network));
7540     }
7541 
7542     @Override
factoryReset()7543     public void factoryReset() {
7544         enforceSettingsPermission();
7545 
7546         if (mUserManager.hasUserRestriction(UserManager.DISALLOW_NETWORK_RESET)) {
7547             return;
7548         }
7549 
7550         final int userId = UserHandle.getCallingUserId();
7551 
7552         Binder.withCleanCallingIdentity(() -> {
7553             final IpMemoryStore ipMemoryStore = IpMemoryStore.getMemoryStore(mContext);
7554             ipMemoryStore.factoryReset();
7555         });
7556 
7557         // Turn airplane mode off
7558         setAirplaneMode(false);
7559 
7560         if (!mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_VPN)) {
7561             // Remove always-on package
7562             synchronized (mVpns) {
7563                 final String alwaysOnPackage = getAlwaysOnVpnPackage(userId);
7564                 if (alwaysOnPackage != null) {
7565                     setAlwaysOnVpnPackage(userId, null, false, null);
7566                     setVpnPackageAuthorization(alwaysOnPackage, userId, VpnManager.TYPE_VPN_NONE);
7567                 }
7568 
7569                 // Turn Always-on VPN off
7570                 if (mLockdownEnabled && userId == UserHandle.USER_SYSTEM) {
7571                     final long ident = Binder.clearCallingIdentity();
7572                     try {
7573                         mKeyStore.delete(Credentials.LOCKDOWN_VPN);
7574                         mLockdownEnabled = false;
7575                         setLockdownTracker(null);
7576                     } finally {
7577                         Binder.restoreCallingIdentity(ident);
7578                     }
7579                 }
7580 
7581                 // Turn VPN off
7582                 VpnConfig vpnConfig = getVpnConfig(userId);
7583                 if (vpnConfig != null) {
7584                     if (vpnConfig.legacy) {
7585                         prepareVpn(VpnConfig.LEGACY_VPN, VpnConfig.LEGACY_VPN, userId);
7586                     } else {
7587                         // Prevent this app (packagename = vpnConfig.user) from initiating
7588                         // VPN connections in the future without user intervention.
7589                         setVpnPackageAuthorization(
7590                                 vpnConfig.user, userId, VpnManager.TYPE_VPN_NONE);
7591 
7592                         prepareVpn(null, VpnConfig.LEGACY_VPN, userId);
7593                     }
7594                 }
7595             }
7596         }
7597 
7598         // restore private DNS settings to default mode (opportunistic)
7599         if (!mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_PRIVATE_DNS)) {
7600             Settings.Global.putString(mContext.getContentResolver(),
7601                     Settings.Global.PRIVATE_DNS_MODE, PRIVATE_DNS_MODE_OPPORTUNISTIC);
7602         }
7603 
7604         Settings.Global.putString(mContext.getContentResolver(),
7605                 Settings.Global.NETWORK_AVOID_BAD_WIFI, null);
7606     }
7607 
7608     @Override
getNetworkWatchlistConfigHash()7609     public byte[] getNetworkWatchlistConfigHash() {
7610         NetworkWatchlistManager nwm = mContext.getSystemService(NetworkWatchlistManager.class);
7611         if (nwm == null) {
7612             loge("Unable to get NetworkWatchlistManager");
7613             return null;
7614         }
7615         // Redirect it to network watchlist service to access watchlist file and calculate hash.
7616         return nwm.getWatchlistConfigHash();
7617     }
7618 
logNetworkEvent(NetworkAgentInfo nai, int evtype)7619     private void logNetworkEvent(NetworkAgentInfo nai, int evtype) {
7620         int[] transports = nai.networkCapabilities.getTransportTypes();
7621         mMetricsLog.log(nai.network.netId, transports, new NetworkEvent(evtype));
7622     }
7623 
toBool(int encodedBoolean)7624     private static boolean toBool(int encodedBoolean) {
7625         return encodedBoolean != 0; // Only 0 means false.
7626     }
7627 
encodeBool(boolean b)7628     private static int encodeBool(boolean b) {
7629         return b ? 1 : 0;
7630     }
7631 
7632     @Override
onShellCommand(@onNull FileDescriptor in, @NonNull FileDescriptor out, FileDescriptor err, @NonNull String[] args, ShellCallback callback, @NonNull ResultReceiver resultReceiver)7633     public void onShellCommand(@NonNull FileDescriptor in, @NonNull FileDescriptor out,
7634             FileDescriptor err, @NonNull String[] args, ShellCallback callback,
7635             @NonNull ResultReceiver resultReceiver) {
7636         (new ShellCmd()).exec(this, in, out, err, args, callback, resultReceiver);
7637     }
7638 
7639     private class ShellCmd extends ShellCommand {
7640 
7641         @Override
onCommand(String cmd)7642         public int onCommand(String cmd) {
7643             if (cmd == null) {
7644                 return handleDefaultCommands(cmd);
7645             }
7646             final PrintWriter pw = getOutPrintWriter();
7647             try {
7648                 switch (cmd) {
7649                     case "airplane-mode":
7650                         final String action = getNextArg();
7651                         if ("enable".equals(action)) {
7652                             setAirplaneMode(true);
7653                             return 0;
7654                         } else if ("disable".equals(action)) {
7655                             setAirplaneMode(false);
7656                             return 0;
7657                         } else if (action == null) {
7658                             final ContentResolver cr = mContext.getContentResolver();
7659                             final int enabled = Settings.Global.getInt(cr,
7660                                     Settings.Global.AIRPLANE_MODE_ON);
7661                             pw.println(enabled == 0 ? "disabled" : "enabled");
7662                             return 0;
7663                         } else {
7664                             onHelp();
7665                             return -1;
7666                         }
7667                     default:
7668                         return handleDefaultCommands(cmd);
7669                 }
7670             } catch (Exception e) {
7671                 pw.println(e);
7672             }
7673             return -1;
7674         }
7675 
7676         @Override
onHelp()7677         public void onHelp() {
7678             PrintWriter pw = getOutPrintWriter();
7679             pw.println("Connectivity service commands:");
7680             pw.println("  help");
7681             pw.println("    Print this help text.");
7682             pw.println("  airplane-mode [enable|disable]");
7683             pw.println("    Turn airplane mode on or off.");
7684             pw.println("  airplane-mode");
7685             pw.println("    Get airplane mode.");
7686         }
7687     }
7688 
7689     @GuardedBy("mVpns")
getVpnIfOwner()7690     private Vpn getVpnIfOwner() {
7691         return getVpnIfOwner(Binder.getCallingUid());
7692     }
7693 
7694     @GuardedBy("mVpns")
getVpnIfOwner(int uid)7695     private Vpn getVpnIfOwner(int uid) {
7696         final int user = UserHandle.getUserId(uid);
7697 
7698         final Vpn vpn = mVpns.get(user);
7699         if (vpn == null) {
7700             return null;
7701         } else {
7702             final VpnInfo info = vpn.getVpnInfo();
7703             return (info == null || info.ownerUid != uid) ? null : vpn;
7704         }
7705     }
7706 
7707     /**
7708      * Caller either needs to be an active VPN, or hold the NETWORK_STACK permission
7709      * for testing.
7710      */
enforceActiveVpnOrNetworkStackPermission()7711     private Vpn enforceActiveVpnOrNetworkStackPermission() {
7712         if (checkNetworkStackPermission()) {
7713             return null;
7714         }
7715         synchronized (mVpns) {
7716             Vpn vpn = getVpnIfOwner();
7717             if (vpn != null) {
7718                 return vpn;
7719             }
7720         }
7721         throw new SecurityException("App must either be an active VPN or have the NETWORK_STACK "
7722                 + "permission");
7723     }
7724 
7725     /**
7726      * @param connectionInfo the connection to resolve.
7727      * @return {@code uid} if the connection is found and the app has permission to observe it
7728      * (e.g., if it is associated with the calling VPN app's tunnel) or {@code INVALID_UID} if the
7729      * connection is not found.
7730      */
getConnectionOwnerUid(ConnectionInfo connectionInfo)7731     public int getConnectionOwnerUid(ConnectionInfo connectionInfo) {
7732         final Vpn vpn = enforceActiveVpnOrNetworkStackPermission();
7733 
7734         // Only VpnService based VPNs should be able to get this information.
7735         if (vpn != null && vpn.getActiveAppVpnType() != VpnManager.TYPE_VPN_SERVICE) {
7736             throw new SecurityException(
7737                     "getConnectionOwnerUid() not allowed for non-VpnService VPNs");
7738         }
7739 
7740         if (connectionInfo.protocol != IPPROTO_TCP && connectionInfo.protocol != IPPROTO_UDP) {
7741             throw new IllegalArgumentException("Unsupported protocol " + connectionInfo.protocol);
7742         }
7743 
7744         final int uid = InetDiagMessage.getConnectionOwnerUid(connectionInfo.protocol,
7745                 connectionInfo.local, connectionInfo.remote);
7746 
7747         /* Filter out Uids not associated with the VPN. */
7748         if (vpn != null && !vpn.appliesToUid(uid)) {
7749             return INVALID_UID;
7750         }
7751 
7752         return uid;
7753     }
7754 
7755     @Override
isCallerCurrentAlwaysOnVpnApp()7756     public boolean isCallerCurrentAlwaysOnVpnApp() {
7757         synchronized (mVpns) {
7758             Vpn vpn = getVpnIfOwner();
7759             return vpn != null && vpn.getAlwaysOn();
7760         }
7761     }
7762 
7763     @Override
isCallerCurrentAlwaysOnVpnLockdownApp()7764     public boolean isCallerCurrentAlwaysOnVpnLockdownApp() {
7765         synchronized (mVpns) {
7766             Vpn vpn = getVpnIfOwner();
7767             return vpn != null && vpn.getLockdown();
7768         }
7769     }
7770 
7771     /**
7772      * Returns a IBinder to a TestNetworkService. Will be lazily created as needed.
7773      *
7774      * <p>The TestNetworkService must be run in the system server due to TUN creation.
7775      */
7776     @Override
startOrGetTestNetworkService()7777     public IBinder startOrGetTestNetworkService() {
7778         synchronized (mTNSLock) {
7779             TestNetworkService.enforceTestNetworkPermissions(mContext);
7780 
7781             if (mTNS == null) {
7782                 mTNS = new TestNetworkService(mContext, mNMS);
7783             }
7784 
7785             return mTNS;
7786         }
7787     }
7788 
7789     /**
7790      * Handler used for managing all Connectivity Diagnostics related functions.
7791      *
7792      * @see android.net.ConnectivityDiagnosticsManager
7793      *
7794      * TODO(b/147816404): Explore moving ConnectivityDiagnosticsHandler to a separate file
7795      */
7796     @VisibleForTesting
7797     class ConnectivityDiagnosticsHandler extends Handler {
7798         private final String mTag = ConnectivityDiagnosticsHandler.class.getSimpleName();
7799 
7800         /**
7801          * Used to handle ConnectivityDiagnosticsCallback registration events from {@link
7802          * android.net.ConnectivityDiagnosticsManager}.
7803          * obj = ConnectivityDiagnosticsCallbackInfo with IConnectivityDiagnosticsCallback and
7804          * NetworkRequestInfo to be registered
7805          */
7806         private static final int EVENT_REGISTER_CONNECTIVITY_DIAGNOSTICS_CALLBACK = 1;
7807 
7808         /**
7809          * Used to handle ConnectivityDiagnosticsCallback unregister events from {@link
7810          * android.net.ConnectivityDiagnosticsManager}.
7811          * obj = the IConnectivityDiagnosticsCallback to be unregistered
7812          * arg1 = the uid of the caller
7813          */
7814         private static final int EVENT_UNREGISTER_CONNECTIVITY_DIAGNOSTICS_CALLBACK = 2;
7815 
7816         /**
7817          * Event for {@link NetworkStateTrackerHandler} to trigger ConnectivityReport callbacks
7818          * after processing {@link #EVENT_NETWORK_TESTED} events.
7819          * obj = {@link ConnectivityReportEvent} representing ConnectivityReport info reported from
7820          * NetworkMonitor.
7821          * data = PersistableBundle of extras passed from NetworkMonitor.
7822          *
7823          * <p>See {@link ConnectivityService#EVENT_NETWORK_TESTED}.
7824          */
7825         private static final int EVENT_NETWORK_TESTED = ConnectivityService.EVENT_NETWORK_TESTED;
7826 
7827         /**
7828          * Event for NetworkMonitor to inform ConnectivityService that a potential data stall has
7829          * been detected on the network.
7830          * obj = Long the timestamp (in millis) for when the suspected data stall was detected.
7831          * arg1 = {@link DataStallReport#DetectionMethod} indicating the detection method.
7832          * arg2 = NetID.
7833          * data = PersistableBundle of extras passed from NetworkMonitor.
7834          */
7835         private static final int EVENT_DATA_STALL_SUSPECTED = 4;
7836 
7837         /**
7838          * Event for ConnectivityDiagnosticsHandler to handle network connectivity being reported to
7839          * the platform. This event will invoke {@link
7840          * IConnectivityDiagnosticsCallback#onNetworkConnectivityReported} for permissioned
7841          * callbacks.
7842          * obj = Network that was reported on
7843          * arg1 = boolint for the quality reported
7844          */
7845         private static final int EVENT_NETWORK_CONNECTIVITY_REPORTED = 5;
7846 
ConnectivityDiagnosticsHandler(Looper looper)7847         private ConnectivityDiagnosticsHandler(Looper looper) {
7848             super(looper);
7849         }
7850 
7851         @Override
handleMessage(Message msg)7852         public void handleMessage(Message msg) {
7853             switch (msg.what) {
7854                 case EVENT_REGISTER_CONNECTIVITY_DIAGNOSTICS_CALLBACK: {
7855                     handleRegisterConnectivityDiagnosticsCallback(
7856                             (ConnectivityDiagnosticsCallbackInfo) msg.obj);
7857                     break;
7858                 }
7859                 case EVENT_UNREGISTER_CONNECTIVITY_DIAGNOSTICS_CALLBACK: {
7860                     handleUnregisterConnectivityDiagnosticsCallback(
7861                             (IConnectivityDiagnosticsCallback) msg.obj, msg.arg1);
7862                     break;
7863                 }
7864                 case EVENT_NETWORK_TESTED: {
7865                     final ConnectivityReportEvent reportEvent =
7866                             (ConnectivityReportEvent) msg.obj;
7867 
7868                     // This is safe because {@link
7869                     // NetworkMonitorCallbacks#notifyNetworkTestedWithExtras} receives a
7870                     // PersistableBundle and converts it to the Bundle in the incoming Message. If
7871                     // {@link NetworkMonitorCallbacks#notifyNetworkTested} is called, msg.data will
7872                     // not be set. This is also safe, as msg.getData() will return an empty Bundle.
7873                     final PersistableBundle extras = new PersistableBundle(msg.getData());
7874                     handleNetworkTestedWithExtras(reportEvent, extras);
7875                     break;
7876                 }
7877                 case EVENT_DATA_STALL_SUSPECTED: {
7878                     final NetworkAgentInfo nai = getNetworkAgentInfoForNetId(msg.arg2);
7879                     if (nai == null) break;
7880 
7881                     // This is safe because NetworkMonitorCallbacks#notifyDataStallSuspected
7882                     // receives a PersistableBundle and converts it to the Bundle in the incoming
7883                     // Message.
7884                     final PersistableBundle extras = new PersistableBundle(msg.getData());
7885                     handleDataStallSuspected(nai, (long) msg.obj, msg.arg1, extras);
7886                     break;
7887                 }
7888                 case EVENT_NETWORK_CONNECTIVITY_REPORTED: {
7889                     handleNetworkConnectivityReported((NetworkAgentInfo) msg.obj, toBool(msg.arg1));
7890                     break;
7891                 }
7892                 default: {
7893                     Log.e(mTag, "Unrecognized event in ConnectivityDiagnostics: " + msg.what);
7894                 }
7895             }
7896         }
7897     }
7898 
7899     /** Class used for cleaning up IConnectivityDiagnosticsCallback instances after their death. */
7900     @VisibleForTesting
7901     class ConnectivityDiagnosticsCallbackInfo implements Binder.DeathRecipient {
7902         @NonNull private final IConnectivityDiagnosticsCallback mCb;
7903         @NonNull private final NetworkRequestInfo mRequestInfo;
7904         @NonNull private final String mCallingPackageName;
7905 
7906         @VisibleForTesting
ConnectivityDiagnosticsCallbackInfo( @onNull IConnectivityDiagnosticsCallback cb, @NonNull NetworkRequestInfo nri, @NonNull String callingPackageName)7907         ConnectivityDiagnosticsCallbackInfo(
7908                 @NonNull IConnectivityDiagnosticsCallback cb,
7909                 @NonNull NetworkRequestInfo nri,
7910                 @NonNull String callingPackageName) {
7911             mCb = cb;
7912             mRequestInfo = nri;
7913             mCallingPackageName = callingPackageName;
7914         }
7915 
7916         @Override
binderDied()7917         public void binderDied() {
7918             log("ConnectivityDiagnosticsCallback IBinder died.");
7919             unregisterConnectivityDiagnosticsCallback(mCb);
7920         }
7921     }
7922 
7923     /**
7924      * Class used for sending information from {@link
7925      * NetworkMonitorCallbacks#notifyNetworkTestedWithExtras} to the handler for processing it.
7926      */
7927     private static class NetworkTestedResults {
7928         private final int mNetId;
7929         private final int mTestResult;
7930         private final long mTimestampMillis;
7931         @Nullable private final String mRedirectUrl;
7932 
NetworkTestedResults( int netId, int testResult, long timestampMillis, @Nullable String redirectUrl)7933         private NetworkTestedResults(
7934                 int netId, int testResult, long timestampMillis, @Nullable String redirectUrl) {
7935             mNetId = netId;
7936             mTestResult = testResult;
7937             mTimestampMillis = timestampMillis;
7938             mRedirectUrl = redirectUrl;
7939         }
7940     }
7941 
7942     /**
7943      * Class used for sending information from {@link NetworkStateTrackerHandler} to {@link
7944      * ConnectivityDiagnosticsHandler}.
7945      */
7946     private static class ConnectivityReportEvent {
7947         private final long mTimestampMillis;
7948         @NonNull private final NetworkAgentInfo mNai;
7949 
ConnectivityReportEvent(long timestampMillis, @NonNull NetworkAgentInfo nai)7950         private ConnectivityReportEvent(long timestampMillis, @NonNull NetworkAgentInfo nai) {
7951             mTimestampMillis = timestampMillis;
7952             mNai = nai;
7953         }
7954     }
7955 
handleRegisterConnectivityDiagnosticsCallback( @onNull ConnectivityDiagnosticsCallbackInfo cbInfo)7956     private void handleRegisterConnectivityDiagnosticsCallback(
7957             @NonNull ConnectivityDiagnosticsCallbackInfo cbInfo) {
7958         ensureRunningOnConnectivityServiceThread();
7959 
7960         final IConnectivityDiagnosticsCallback cb = cbInfo.mCb;
7961         final IBinder iCb = cb.asBinder();
7962         final NetworkRequestInfo nri = cbInfo.mRequestInfo;
7963 
7964         // This means that the client registered the same callback multiple times. Do
7965         // not override the previous entry, and exit silently.
7966         if (mConnectivityDiagnosticsCallbacks.containsKey(iCb)) {
7967             if (VDBG) log("Diagnostics callback is already registered");
7968 
7969             // Decrement the reference count for this NetworkRequestInfo. The reference count is
7970             // incremented when the NetworkRequestInfo is created as part of
7971             // enforceRequestCountLimit().
7972             decrementNetworkRequestPerUidCount(nri);
7973             return;
7974         }
7975 
7976         mConnectivityDiagnosticsCallbacks.put(iCb, cbInfo);
7977 
7978         try {
7979             iCb.linkToDeath(cbInfo, 0);
7980         } catch (RemoteException e) {
7981             cbInfo.binderDied();
7982             return;
7983         }
7984 
7985         // Once registered, provide ConnectivityReports for matching Networks
7986         final List<NetworkAgentInfo> matchingNetworks = new ArrayList<>();
7987         synchronized (mNetworkForNetId) {
7988             for (int i = 0; i < mNetworkForNetId.size(); i++) {
7989                 final NetworkAgentInfo nai = mNetworkForNetId.valueAt(i);
7990                 if (nai.satisfies(nri.request)) {
7991                     matchingNetworks.add(nai);
7992                 }
7993             }
7994         }
7995         for (final NetworkAgentInfo nai : matchingNetworks) {
7996             final ConnectivityReport report = nai.getConnectivityReport();
7997             if (report == null) {
7998                 continue;
7999             }
8000             if (!checkConnectivityDiagnosticsPermissions(
8001                     nri.mPid, nri.mUid, nai, cbInfo.mCallingPackageName)) {
8002                 continue;
8003             }
8004 
8005             try {
8006                 cb.onConnectivityReportAvailable(report);
8007             } catch (RemoteException e) {
8008                 // Exception while sending the ConnectivityReport. Move on to the next network.
8009             }
8010         }
8011     }
8012 
handleUnregisterConnectivityDiagnosticsCallback( @onNull IConnectivityDiagnosticsCallback cb, int uid)8013     private void handleUnregisterConnectivityDiagnosticsCallback(
8014             @NonNull IConnectivityDiagnosticsCallback cb, int uid) {
8015         ensureRunningOnConnectivityServiceThread();
8016         final IBinder iCb = cb.asBinder();
8017 
8018         final ConnectivityDiagnosticsCallbackInfo cbInfo =
8019                 mConnectivityDiagnosticsCallbacks.remove(iCb);
8020         if (cbInfo == null) {
8021             if (VDBG) log("Removing diagnostics callback that is not currently registered");
8022             return;
8023         }
8024 
8025         final NetworkRequestInfo nri = cbInfo.mRequestInfo;
8026 
8027         if (uid != nri.mUid) {
8028             if (VDBG) loge("Different uid than registrant attempting to unregister cb");
8029             return;
8030         }
8031 
8032         // Decrement the reference count for this NetworkRequestInfo. The reference count is
8033         // incremented when the NetworkRequestInfo is created as part of
8034         // enforceRequestCountLimit().
8035         decrementNetworkRequestPerUidCount(nri);
8036 
8037         iCb.unlinkToDeath(cbInfo, 0);
8038     }
8039 
handleNetworkTestedWithExtras( @onNull ConnectivityReportEvent reportEvent, @NonNull PersistableBundle extras)8040     private void handleNetworkTestedWithExtras(
8041             @NonNull ConnectivityReportEvent reportEvent, @NonNull PersistableBundle extras) {
8042         final NetworkAgentInfo nai = reportEvent.mNai;
8043         final NetworkCapabilities networkCapabilities =
8044                 getNetworkCapabilitiesWithoutUids(nai.networkCapabilities);
8045         final ConnectivityReport report =
8046                 new ConnectivityReport(
8047                         reportEvent.mNai.network,
8048                         reportEvent.mTimestampMillis,
8049                         nai.linkProperties,
8050                         networkCapabilities,
8051                         extras);
8052         nai.setConnectivityReport(report);
8053         final List<IConnectivityDiagnosticsCallback> results =
8054                 getMatchingPermissionedCallbacks(nai);
8055         for (final IConnectivityDiagnosticsCallback cb : results) {
8056             try {
8057                 cb.onConnectivityReportAvailable(report);
8058             } catch (RemoteException ex) {
8059                 loge("Error invoking onConnectivityReport", ex);
8060             }
8061         }
8062     }
8063 
handleDataStallSuspected( @onNull NetworkAgentInfo nai, long timestampMillis, int detectionMethod, @NonNull PersistableBundle extras)8064     private void handleDataStallSuspected(
8065             @NonNull NetworkAgentInfo nai, long timestampMillis, int detectionMethod,
8066             @NonNull PersistableBundle extras) {
8067         final NetworkCapabilities networkCapabilities =
8068                 getNetworkCapabilitiesWithoutUids(nai.networkCapabilities);
8069         final DataStallReport report =
8070                 new DataStallReport(
8071                         nai.network,
8072                         timestampMillis,
8073                         detectionMethod,
8074                         nai.linkProperties,
8075                         networkCapabilities,
8076                         extras);
8077         final List<IConnectivityDiagnosticsCallback> results =
8078                 getMatchingPermissionedCallbacks(nai);
8079         for (final IConnectivityDiagnosticsCallback cb : results) {
8080             try {
8081                 cb.onDataStallSuspected(report);
8082             } catch (RemoteException ex) {
8083                 loge("Error invoking onDataStallSuspected", ex);
8084             }
8085         }
8086     }
8087 
handleNetworkConnectivityReported( @onNull NetworkAgentInfo nai, boolean connectivity)8088     private void handleNetworkConnectivityReported(
8089             @NonNull NetworkAgentInfo nai, boolean connectivity) {
8090         final List<IConnectivityDiagnosticsCallback> results =
8091                 getMatchingPermissionedCallbacks(nai);
8092         for (final IConnectivityDiagnosticsCallback cb : results) {
8093             try {
8094                 cb.onNetworkConnectivityReported(nai.network, connectivity);
8095             } catch (RemoteException ex) {
8096                 loge("Error invoking onNetworkConnectivityReported", ex);
8097             }
8098         }
8099     }
8100 
getNetworkCapabilitiesWithoutUids(@onNull NetworkCapabilities nc)8101     private NetworkCapabilities getNetworkCapabilitiesWithoutUids(@NonNull NetworkCapabilities nc) {
8102         final NetworkCapabilities sanitized = new NetworkCapabilities(nc);
8103         sanitized.setUids(null);
8104         sanitized.setAdministratorUids(new int[0]);
8105         sanitized.setOwnerUid(Process.INVALID_UID);
8106         return sanitized;
8107     }
8108 
getMatchingPermissionedCallbacks( @onNull NetworkAgentInfo nai)8109     private List<IConnectivityDiagnosticsCallback> getMatchingPermissionedCallbacks(
8110             @NonNull NetworkAgentInfo nai) {
8111         final List<IConnectivityDiagnosticsCallback> results = new ArrayList<>();
8112         for (Entry<IBinder, ConnectivityDiagnosticsCallbackInfo> entry :
8113                 mConnectivityDiagnosticsCallbacks.entrySet()) {
8114             final ConnectivityDiagnosticsCallbackInfo cbInfo = entry.getValue();
8115             final NetworkRequestInfo nri = cbInfo.mRequestInfo;
8116             if (nai.satisfies(nri.request)) {
8117                 if (checkConnectivityDiagnosticsPermissions(
8118                         nri.mPid, nri.mUid, nai, cbInfo.mCallingPackageName)) {
8119                     results.add(entry.getValue().mCb);
8120                 }
8121             }
8122         }
8123         return results;
8124     }
8125 
8126     @VisibleForTesting
checkConnectivityDiagnosticsPermissions( int callbackPid, int callbackUid, NetworkAgentInfo nai, String callbackPackageName)8127     boolean checkConnectivityDiagnosticsPermissions(
8128             int callbackPid, int callbackUid, NetworkAgentInfo nai, String callbackPackageName) {
8129         if (checkNetworkStackPermission(callbackPid, callbackUid)) {
8130             return true;
8131         }
8132 
8133         // LocationPermissionChecker#checkLocationPermission can throw SecurityException if the uid
8134         // and package name don't match. Throwing on the CS thread is not acceptable, so wrap the
8135         // call in a try-catch.
8136         try {
8137             if (!mLocationPermissionChecker.checkLocationPermission(
8138                     callbackPackageName, null /* featureId */, callbackUid, null /* message */)) {
8139                 return false;
8140             }
8141         } catch (SecurityException e) {
8142             return false;
8143         }
8144 
8145         final Network[] underlyingNetworks;
8146         synchronized (mVpns) {
8147             final Vpn vpn = getVpnIfOwner(callbackUid);
8148             underlyingNetworks = (vpn == null) ? null : vpn.getUnderlyingNetworks();
8149         }
8150         if (underlyingNetworks != null) {
8151             if (Arrays.asList(underlyingNetworks).contains(nai.network)) return true;
8152         }
8153 
8154         // Administrator UIDs also contains the Owner UID
8155         final int[] administratorUids = nai.networkCapabilities.getAdministratorUids();
8156         return ArrayUtils.contains(administratorUids, callbackUid);
8157     }
8158 
8159     @Override
registerConnectivityDiagnosticsCallback( @onNull IConnectivityDiagnosticsCallback callback, @NonNull NetworkRequest request, @NonNull String callingPackageName)8160     public void registerConnectivityDiagnosticsCallback(
8161             @NonNull IConnectivityDiagnosticsCallback callback,
8162             @NonNull NetworkRequest request,
8163             @NonNull String callingPackageName) {
8164         if (request.legacyType != TYPE_NONE) {
8165             throw new IllegalArgumentException("ConnectivityManager.TYPE_* are deprecated."
8166                     + " Please use NetworkCapabilities instead.");
8167         }
8168         final int callingUid = Binder.getCallingUid();
8169         mAppOpsManager.checkPackage(callingUid, callingPackageName);
8170 
8171         // This NetworkCapabilities is only used for matching to Networks. Clear out its owner uid
8172         // and administrator uids to be safe.
8173         final NetworkCapabilities nc = new NetworkCapabilities(request.networkCapabilities);
8174         restrictRequestUidsForCallerAndSetRequestorInfo(nc, callingUid, callingPackageName);
8175 
8176         final NetworkRequest requestWithId =
8177                 new NetworkRequest(
8178                         nc, TYPE_NONE, nextNetworkRequestId(), NetworkRequest.Type.LISTEN);
8179 
8180         // NetworkRequestInfos created here count towards MAX_NETWORK_REQUESTS_PER_UID limit.
8181         //
8182         // nri is not bound to the death of callback. Instead, callback.bindToDeath() is set in
8183         // handleRegisterConnectivityDiagnosticsCallback(). nri will be cleaned up as part of the
8184         // callback's binder death.
8185         final NetworkRequestInfo nri = new NetworkRequestInfo(requestWithId);
8186         final ConnectivityDiagnosticsCallbackInfo cbInfo =
8187                 new ConnectivityDiagnosticsCallbackInfo(callback, nri, callingPackageName);
8188 
8189         mConnectivityDiagnosticsHandler.sendMessage(
8190                 mConnectivityDiagnosticsHandler.obtainMessage(
8191                         ConnectivityDiagnosticsHandler
8192                                 .EVENT_REGISTER_CONNECTIVITY_DIAGNOSTICS_CALLBACK,
8193                         cbInfo));
8194     }
8195 
8196     @Override
unregisterConnectivityDiagnosticsCallback( @onNull IConnectivityDiagnosticsCallback callback)8197     public void unregisterConnectivityDiagnosticsCallback(
8198             @NonNull IConnectivityDiagnosticsCallback callback) {
8199         mConnectivityDiagnosticsHandler.sendMessage(
8200                 mConnectivityDiagnosticsHandler.obtainMessage(
8201                         ConnectivityDiagnosticsHandler
8202                                 .EVENT_UNREGISTER_CONNECTIVITY_DIAGNOSTICS_CALLBACK,
8203                         Binder.getCallingUid(),
8204                         0,
8205                         callback));
8206     }
8207 
8208     @Override
simulateDataStall(int detectionMethod, long timestampMillis, @NonNull Network network, @NonNull PersistableBundle extras)8209     public void simulateDataStall(int detectionMethod, long timestampMillis,
8210             @NonNull Network network, @NonNull PersistableBundle extras) {
8211         enforceAnyPermissionOf(android.Manifest.permission.MANAGE_TEST_NETWORKS,
8212                 android.Manifest.permission.NETWORK_STACK);
8213         final NetworkCapabilities nc = getNetworkCapabilitiesInternal(network);
8214         if (!nc.hasTransport(TRANSPORT_TEST)) {
8215             throw new SecurityException("Data Stall simluation is only possible for test networks");
8216         }
8217 
8218         final NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
8219         if (nai == null || nai.creatorUid != Binder.getCallingUid()) {
8220             throw new SecurityException("Data Stall simulation is only possible for network "
8221                 + "creators");
8222         }
8223 
8224         // Instead of passing the data stall directly to the ConnectivityDiagnostics handler, treat
8225         // this as a Data Stall received directly from NetworkMonitor. This requires wrapping the
8226         // Data Stall information as a DataStallReportParcelable and passing to
8227         // #notifyDataStallSuspected. This ensures that unknown Data Stall detection methods are
8228         // still passed to ConnectivityDiagnostics (with new detection methods masked).
8229         final DataStallReportParcelable p = new DataStallReportParcelable();
8230         p.timestampMillis = timestampMillis;
8231         p.detectionMethod = detectionMethod;
8232 
8233         if (hasDataStallDetectionMethod(p, DETECTION_METHOD_DNS_EVENTS)) {
8234             p.dnsConsecutiveTimeouts = extras.getInt(KEY_DNS_CONSECUTIVE_TIMEOUTS);
8235         }
8236         if (hasDataStallDetectionMethod(p, DETECTION_METHOD_TCP_METRICS)) {
8237             p.tcpPacketFailRate = extras.getInt(KEY_TCP_PACKET_FAIL_RATE);
8238             p.tcpMetricsCollectionPeriodMillis = extras.getInt(
8239                     KEY_TCP_METRICS_COLLECTION_PERIOD_MILLIS);
8240         }
8241 
8242         notifyDataStallSuspected(p, network.netId);
8243     }
8244 }
8245