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