2 * Copyright (C) 2008 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package com.android.server;
19 import static android.Manifest.permission.RECEIVE_DATA_ACTIVITY_CHANGE;
20 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
21 import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
22 import static android.net.ConnectivityManager.NETID_UNSET;
23 import static android.net.ConnectivityManager.TYPE_ETHERNET;
24 import static android.net.ConnectivityManager.TYPE_NONE;
25 import static android.net.ConnectivityManager.TYPE_VPN;
26 import static android.net.ConnectivityManager.getNetworkTypeName;
27 import static android.net.ConnectivityManager.isNetworkTypeValid;
28 import static android.net.INetworkMonitor.NETWORK_TEST_RESULT_PARTIAL_CONNECTIVITY;
29 import static android.net.INetworkMonitor.NETWORK_TEST_RESULT_VALID;
30 import static android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL;
31 import static android.net.NetworkCapabilities.NET_CAPABILITY_FOREGROUND;
32 import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
33 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
34 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
35 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING;
36 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED;
37 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN;
38 import static android.net.NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVITY;
39 import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
40 import static android.net.NetworkCapabilities.TRANSPORT_VPN;
41 import static android.net.NetworkPolicyManager.RULE_NONE;
42 import static android.net.NetworkPolicyManager.uidRulesToString;
43 import static android.net.shared.NetworkMonitorUtils.isPrivateDnsValidationRequired;
44 import static android.os.Process.INVALID_UID;
45 import static android.system.OsConstants.IPPROTO_TCP;
46 import static android.system.OsConstants.IPPROTO_UDP;
48 import static com.android.internal.util.Preconditions.checkNotNull;
50 import android.annotation.NonNull;
51 import android.annotation.Nullable;
52 import android.app.BroadcastOptions;
53 import android.app.NotificationManager;
54 import android.app.PendingIntent;
55 import android.content.BroadcastReceiver;
56 import android.content.ContentResolver;
57 import android.content.Context;
58 import android.content.Intent;
59 import android.content.IntentFilter;
60 import android.content.res.Configuration;
61 import android.database.ContentObserver;
62 import android.net.CaptivePortal;
63 import android.net.ConnectionInfo;
64 import android.net.ConnectivityManager;
65 import android.net.ICaptivePortal;
66 import android.net.IConnectivityManager;
67 import android.net.IDnsResolver;
68 import android.net.IIpConnectivityMetrics;
69 import android.net.INetd;
70 import android.net.INetdEventCallback;
71 import android.net.INetworkManagementEventObserver;
72 import android.net.INetworkMonitor;
73 import android.net.INetworkMonitorCallbacks;
74 import android.net.INetworkPolicyListener;
75 import android.net.INetworkPolicyManager;
76 import android.net.INetworkStatsService;
77 import android.net.ISocketKeepaliveCallback;
78 import android.net.ITetheringEventCallback;
79 import android.net.InetAddresses;
80 import android.net.IpPrefix;
81 import android.net.LinkProperties;
82 import android.net.LinkProperties.CompareResult;
83 import android.net.MatchAllNetworkSpecifier;
84 import android.net.NattSocketKeepalive;
85 import android.net.Network;
86 import android.net.NetworkAgent;
87 import android.net.NetworkCapabilities;
88 import android.net.NetworkConfig;
89 import android.net.NetworkFactory;
90 import android.net.NetworkInfo;
91 import android.net.NetworkInfo.DetailedState;
92 import android.net.NetworkMisc;
93 import android.net.NetworkPolicyManager;
94 import android.net.NetworkQuotaInfo;
95 import android.net.NetworkRequest;
96 import android.net.NetworkSpecifier;
97 import android.net.NetworkStack;
98 import android.net.NetworkStackClient;
99 import android.net.NetworkState;
100 import android.net.NetworkUtils;
101 import android.net.NetworkWatchlistManager;
102 import android.net.PrivateDnsConfigParcel;
103 import android.net.ProxyInfo;
104 import android.net.RouteInfo;
105 import android.net.SocketKeepalive;
106 import android.net.UidRange;
107 import android.net.Uri;
108 import android.net.VpnService;
109 import android.net.metrics.IpConnectivityLog;
110 import android.net.metrics.NetworkEvent;
111 import android.net.netlink.InetDiagMessage;
112 import android.net.shared.PrivateDnsConfig;
113 import android.net.util.MultinetworkPolicyTracker;
114 import android.net.util.NetdService;
115 import android.os.Binder;
116 import android.os.Build;
117 import android.os.Bundle;
118 import android.os.Handler;
119 import android.os.HandlerThread;
120 import android.os.IBinder;
121 import android.os.INetworkManagementService;
122 import android.os.Looper;
123 import android.os.Message;
124 import android.os.Messenger;
125 import android.os.ParcelFileDescriptor;
126 import android.os.Parcelable;
127 import android.os.PowerManager;
128 import android.os.Process;
129 import android.os.RemoteException;
130 import android.os.ResultReceiver;
131 import android.os.ServiceManager;
132 import android.os.ServiceSpecificException;
133 import android.os.ShellCallback;
134 import android.os.ShellCommand;
135 import android.os.SystemClock;
136 import android.os.SystemProperties;
137 import android.os.UserHandle;
138 import android.os.UserManager;
139 import android.provider.Settings;
140 import android.security.Credentials;
141 import android.security.KeyStore;
142 import android.telephony.TelephonyManager;
143 import android.text.TextUtils;
144 import android.util.ArraySet;
145 import android.util.LocalLog;
146 import android.util.Log;
147 import android.util.Pair;
148 import android.util.Slog;
149 import android.util.SparseArray;
150 import android.util.SparseBooleanArray;
151 import android.util.SparseIntArray;
152 import android.util.Xml;
154 import com.android.internal.R;
155 import com.android.internal.annotations.GuardedBy;
156 import com.android.internal.annotations.VisibleForTesting;
157 import com.android.internal.app.IBatteryStats;
158 import com.android.internal.logging.MetricsLogger;
159 import com.android.internal.net.LegacyVpnInfo;
160 import com.android.internal.net.VpnConfig;
161 import com.android.internal.net.VpnInfo;
162 import com.android.internal.net.VpnProfile;
163 import com.android.internal.util.ArrayUtils;
164 import com.android.internal.util.AsyncChannel;
165 import com.android.internal.util.DumpUtils;
166 import com.android.internal.util.IndentingPrintWriter;
167 import com.android.internal.util.MessageUtils;
168 import com.android.internal.util.WakeupMessage;
169 import com.android.internal.util.XmlUtils;
170 import com.android.server.am.BatteryStatsService;
171 import com.android.server.connectivity.DataConnectionStats;
172 import com.android.server.connectivity.DnsManager;
173 import com.android.server.connectivity.DnsManager.PrivateDnsValidationUpdate;
174 import com.android.server.connectivity.IpConnectivityMetrics;
175 import com.android.server.connectivity.KeepaliveTracker;
176 import com.android.server.connectivity.LingerMonitor;
177 import com.android.server.connectivity.MockableSystemProperties;
178 import com.android.server.connectivity.MultipathPolicyTracker;
179 import com.android.server.connectivity.NetworkAgentInfo;
180 import com.android.server.connectivity.NetworkDiagnostics;
181 import com.android.server.connectivity.NetworkNotificationManager;
182 import com.android.server.connectivity.NetworkNotificationManager.NotificationType;
183 import com.android.server.connectivity.PermissionMonitor;
184 import com.android.server.connectivity.ProxyTracker;
185 import com.android.server.connectivity.Tethering;
186 import com.android.server.connectivity.Vpn;
187 import com.android.server.connectivity.tethering.TetheringDependencies;
188 import com.android.server.net.BaseNetdEventCallback;
189 import com.android.server.net.BaseNetworkObserver;
190 import com.android.server.net.LockdownVpnTracker;
191 import com.android.server.net.NetworkPolicyManagerInternal;
192 import com.android.server.utils.PriorityDump;
194 import com.google.android.collect.Lists;
196 import org.xmlpull.v1.XmlPullParser;
197 import org.xmlpull.v1.XmlPullParserException;
200 import java.io.FileDescriptor;
201 import java.io.FileNotFoundException;
202 import java.io.FileReader;
203 import java.io.IOException;
204 import java.io.PrintWriter;
205 import java.net.Inet4Address;
206 import java.net.InetAddress;
207 import java.net.UnknownHostException;
208 import java.util.ArrayList;
209 import java.util.Arrays;
210 import java.util.Collection;
211 import java.util.Comparator;
212 import java.util.ConcurrentModificationException;
213 import java.util.HashMap;
214 import java.util.HashSet;
215 import java.util.List;
216 import java.util.Map;
217 import java.util.Objects;
218 import java.util.Set;
219 import java.util.SortedSet;
220 import java.util.TreeSet;
225 public class ConnectivityService extends IConnectivityManager.Stub
226 implements PendingIntent.OnFinished {
227 private static final String TAG = ConnectivityService.class.getSimpleName();
229 private static final String DIAG_ARG = "--diag";
230 public static final String SHORT_ARG = "--short";
231 private static final String TETHERING_ARG = "tethering";
232 private static final String NETWORK_ARG = "networks";
233 private static final String REQUEST_ARG = "requests";
235 private static final boolean DBG = true;
236 private static final boolean DDBG = Log.isLoggable(TAG, Log.DEBUG);
237 private static final boolean VDBG = Log.isLoggable(TAG, Log.VERBOSE);
239 private static final boolean LOGD_BLOCKED_NETWORKINFO = true;
242 * Default URL to use for {@link #getCaptivePortalServerUrl()}. This should not be changed
243 * by OEMs for configuration purposes, as this value is overridden by
244 * Settings.Global.CAPTIVE_PORTAL_HTTP_URL.
245 * R.string.config_networkCaptivePortalServerUrl should be overridden instead for this purpose
246 * (preferably via runtime resource overlays).
248 private static final String DEFAULT_CAPTIVE_PORTAL_HTTP_URL =
249 "http://connectivitycheck.gstatic.com/generate_204";
251 // TODO: create better separation between radio types and network types
253 // how long to wait before switching back to a radio's default network
254 private static final int RESTORE_DEFAULT_NETWORK_DELAY = 1 * 60 * 1000;
255 // system property that can override the above value
256 private static final String NETWORK_RESTORE_DELAY_PROP_NAME =
257 "android.telephony.apn-restore";
259 // How long to wait before putting up a "This network doesn't have an Internet connection,
260 // connect anyway?" dialog after the user selects a network that doesn't validate.
261 private static final int PROMPT_UNVALIDATED_DELAY_MS = 8 * 1000;
263 // How long to dismiss network notification.
264 private static final int TIMEOUT_NOTIFICATION_DELAY_MS = 20 * 1000;
266 // Default to 30s linger time-out. Modifiable only for testing.
267 private static final String LINGER_DELAY_PROPERTY = "persist.netmon.linger";
268 private static final int DEFAULT_LINGER_DELAY_MS = 30_000;
270 protected int mLingerDelayMs; // Can't be final, or test subclass constructors can't change it.
272 // How long to delay to removal of a pending intent based request.
273 // See Settings.Secure.CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS
274 private final int mReleasePendingIntentDelayMs;
276 private MockableSystemProperties mSystemProperties;
278 private Tethering mTethering;
281 protected final PermissionMonitor mPermissionMonitor;
283 private KeyStore mKeyStore;
287 protected final SparseArray<Vpn> mVpns = new SparseArray<>();
289 // TODO: investigate if mLockdownEnabled can be removed and replaced everywhere by
290 // a direct call to LockdownVpnTracker.isEnabled().
292 private boolean mLockdownEnabled;
294 private LockdownVpnTracker mLockdownTracker;
297 * Stale copy of uid rules provided by NPMS. As long as they are accessed only in internal
298 * handler thread, they don't need a lock.
300 private SparseIntArray mUidRules = new SparseIntArray();
301 /** Flag indicating if background data is restricted. */
302 private boolean mRestrictBackground;
304 final private Context mContext;
305 // 0 is full bad, 100 is full good
306 private int mDefaultInetConditionPublished = 0;
308 private INetworkManagementService mNMS;
310 protected IDnsResolver mDnsResolver;
312 protected INetd mNetd;
313 private INetworkStatsService mStatsService;
314 private INetworkPolicyManager mPolicyManager;
315 private NetworkPolicyManagerInternal mPolicyManagerInternal;
318 * TestNetworkService (lazily) created upon first usage. Locked to prevent creation of multiple
321 @GuardedBy("mTNSLock")
322 private TestNetworkService mTNS;
324 private final Object mTNSLock = new Object();
326 private String mCurrentTcpBufferSizes;
328 private static final SparseArray<String> sMagicDecoderRing = MessageUtils.findMessageNames(
329 new Class[] { AsyncChannel.class, ConnectivityService.class, NetworkAgent.class,
330 NetworkAgentInfo.class });
332 private enum ReapUnvalidatedNetworks {
333 // Tear down networks that have no chance (e.g. even if validated) of becoming
334 // the highest scoring network satisfying a NetworkRequest. This should be passed when
335 // all networks have been rematched against all NetworkRequests.
337 // Don't reap networks. This should be passed when some networks have not yet been
338 // rematched against all NetworkRequests.
342 private enum UnneededFor {
343 LINGER, // Determine whether this network is unneeded and should be lingered.
344 TEARDOWN, // Determine whether this network is unneeded and should be torn down.
348 * used internally to clear a wakelock when transitioning
349 * from one net to another. Clear happens when we get a new
350 * network - EVENT_EXPIRE_NET_TRANSITION_WAKELOCK happens
351 * after a timeout if no network is found (typically 1 min).
353 private static final int EVENT_CLEAR_NET_TRANSITION_WAKELOCK = 8;
356 * used internally to reload global proxy settings
358 private static final int EVENT_APPLY_GLOBAL_HTTP_PROXY = 9;
361 * PAC manager has received new port.
363 private static final int EVENT_PROXY_HAS_CHANGED = 16;
366 * used internally when registering NetworkFactories
367 * obj = NetworkFactoryInfo
369 private static final int EVENT_REGISTER_NETWORK_FACTORY = 17;
372 * used internally when registering NetworkAgents
375 private static final int EVENT_REGISTER_NETWORK_AGENT = 18;
378 * used to add a network request
379 * includes a NetworkRequestInfo
381 private static final int EVENT_REGISTER_NETWORK_REQUEST = 19;
384 * indicates a timeout period is over - check if we had a network yet or not
385 * and if not, call the timeout callback (but leave the request live until they
387 * includes a NetworkRequestInfo
389 private static final int EVENT_TIMEOUT_NETWORK_REQUEST = 20;
392 * used to add a network listener - no request
393 * includes a NetworkRequestInfo
395 private static final int EVENT_REGISTER_NETWORK_LISTENER = 21;
398 * used to remove a network request, either a listener or a real request
399 * arg1 = UID of caller
400 * obj = NetworkRequest
402 private static final int EVENT_RELEASE_NETWORK_REQUEST = 22;
405 * used internally when registering NetworkFactories
408 private static final int EVENT_UNREGISTER_NETWORK_FACTORY = 23;
411 * used internally to expire a wakelock when transitioning
412 * from one net to another. Expire happens when we fail to find
413 * a new network (typically after 1 minute) -
414 * EVENT_CLEAR_NET_TRANSITION_WAKELOCK happens if we had found
415 * a replacement network.
417 private static final int EVENT_EXPIRE_NET_TRANSITION_WAKELOCK = 24;
420 * Used internally to indicate the system is ready.
422 private static final int EVENT_SYSTEM_READY = 25;
425 * used to add a network request with a pending intent
426 * obj = NetworkRequestInfo
428 private static final int EVENT_REGISTER_NETWORK_REQUEST_WITH_INTENT = 26;
431 * used to remove a pending intent and its associated network request.
432 * arg1 = UID of caller
433 * obj = PendingIntent
435 private static final int EVENT_RELEASE_NETWORK_REQUEST_WITH_INTENT = 27;
438 * used to specify whether a network should be used even if unvalidated.
439 * arg1 = whether to accept the network if it's unvalidated (1 or 0)
440 * arg2 = whether to remember this choice in the future (1 or 0)
443 private static final int EVENT_SET_ACCEPT_UNVALIDATED = 28;
446 * used to ask the user to confirm a connection to an unvalidated network.
449 private static final int EVENT_PROMPT_UNVALIDATED = 29;
452 * used internally to (re)configure always-on networks.
454 private static final int EVENT_CONFIGURE_ALWAYS_ON_NETWORKS = 30;
457 * used to add a network listener with a pending intent
458 * obj = NetworkRequestInfo
460 private static final int EVENT_REGISTER_NETWORK_LISTENER_WITH_INTENT = 31;
463 * used to specify whether a network should not be penalized when it becomes unvalidated.
465 private static final int EVENT_SET_AVOID_UNVALIDATED = 35;
468 * used to trigger revalidation of a network.
470 private static final int EVENT_REVALIDATE_NETWORK = 36;
472 // Handle changes in Private DNS settings.
473 private static final int EVENT_PRIVATE_DNS_SETTINGS_CHANGED = 37;
475 // Handle private DNS validation status updates.
476 private static final int EVENT_PRIVATE_DNS_VALIDATION_UPDATE = 38;
479 * Used to handle onUidRulesChanged event from NetworkPolicyManagerService.
481 private static final int EVENT_UID_RULES_CHANGED = 39;
484 * Used to handle onRestrictBackgroundChanged event from NetworkPolicyManagerService.
486 private static final int EVENT_DATA_SAVER_CHANGED = 40;
489 * Event for NetworkMonitor/NetworkAgentInfo to inform ConnectivityService that the network has
491 * obj = String representing URL that Internet probe was redirect to, if it was redirected.
492 * arg1 = One of the NETWORK_TESTED_RESULT_* constants.
495 public static final int EVENT_NETWORK_TESTED = 41;
498 * Event for NetworkMonitor/NetworkAgentInfo to inform ConnectivityService that the private DNS
499 * config was resolved.
500 * obj = PrivateDnsConfig
503 public static final int EVENT_PRIVATE_DNS_CONFIG_RESOLVED = 42;
506 * Request ConnectivityService display provisioning notification.
507 * arg1 = Whether to make the notification visible.
509 * obj = Intent to be launched when notification selected by user, null if !arg1.
511 public static final int EVENT_PROVISIONING_NOTIFICATION = 43;
514 * This event can handle dismissing notification by given network id.
516 public static final int EVENT_TIMEOUT_NOTIFICATION = 44;
519 * Used to specify whether a network should be used even if connectivity is partial.
520 * arg1 = whether to accept the network if its connectivity is partial (1 for true or 0 for
522 * arg2 = whether to remember this choice in the future (1 for true or 0 for false)
525 private static final int EVENT_SET_ACCEPT_PARTIAL_CONNECTIVITY = 45;
528 * Argument for {@link #EVENT_PROVISIONING_NOTIFICATION} to indicate that the notification
531 public static final int PROVISIONING_NOTIFICATION_SHOW = 1;
534 * Argument for {@link #EVENT_PROVISIONING_NOTIFICATION} to indicate that the notification
537 public static final int PROVISIONING_NOTIFICATION_HIDE = 0;
539 private static String eventName(int what) {
540 return sMagicDecoderRing.get(what, Integer.toString(what));
543 private static IDnsResolver getDnsResolver() {
544 return IDnsResolver.Stub
545 .asInterface(ServiceManager.getService("dnsresolver"));
548 /** Handler thread used for both of the handlers below. */
550 protected final HandlerThread mHandlerThread;
551 /** Handler used for internal events. */
552 final private InternalHandler mHandler;
553 /** Handler used for incoming {@link NetworkStateTracker} events. */
554 final private NetworkStateTrackerHandler mTrackerHandler;
555 private final DnsManager mDnsManager;
557 private boolean mSystemReady;
558 private Intent mInitialBroadcast;
560 private PowerManager.WakeLock mNetTransitionWakeLock;
561 private int mNetTransitionWakeLockTimeout;
562 private final PowerManager.WakeLock mPendingIntentWakeLock;
564 // A helper object to track the current default HTTP proxy. ConnectivityService needs to tell
565 // the world when it changes.
567 protected final ProxyTracker mProxyTracker;
569 final private SettingsObserver mSettingsObserver;
571 private UserManager mUserManager;
573 private NetworkConfig[] mNetConfigs;
574 private int mNetworksDefined;
576 // the set of network types that can only be enabled by system/sig apps
577 private List mProtectedNetworks;
579 private TelephonyManager mTelephonyManager;
581 private KeepaliveTracker mKeepaliveTracker;
582 private NetworkNotificationManager mNotifier;
583 private LingerMonitor mLingerMonitor;
585 // sequence number for Networks; keep in sync with system/netd/NetworkController.cpp
586 private static final int MIN_NET_ID = 100; // some reserved marks
587 private static final int MAX_NET_ID = 65535 - 0x0400; // Top 1024 bits reserved by IpSecService
588 private int mNextNetId = MIN_NET_ID;
590 // sequence number of NetworkRequests
591 private int mNextNetworkRequestId = 1;
593 // NetworkRequest activity String log entries.
594 private static final int MAX_NETWORK_REQUEST_LOGS = 20;
595 private final LocalLog mNetworkRequestInfoLogs = new LocalLog(MAX_NETWORK_REQUEST_LOGS);
597 // NetworkInfo blocked and unblocked String log entries
598 private static final int MAX_NETWORK_INFO_LOGS = 40;
599 private final LocalLog mNetworkInfoBlockingLogs = new LocalLog(MAX_NETWORK_INFO_LOGS);
601 private static final int MAX_WAKELOCK_LOGS = 20;
602 private final LocalLog mWakelockLogs = new LocalLog(MAX_WAKELOCK_LOGS);
603 private int mTotalWakelockAcquisitions = 0;
604 private int mTotalWakelockReleases = 0;
605 private long mTotalWakelockDurationMs = 0;
606 private long mMaxWakelockDurationMs = 0;
607 private long mLastWakeLockAcquireTimestamp = 0;
609 private final IpConnectivityLog mMetricsLog;
611 @GuardedBy("mBandwidthRequests")
612 private final SparseArray<Integer> mBandwidthRequests = new SparseArray(10);
615 final MultinetworkPolicyTracker mMultinetworkPolicyTracker;
618 final MultipathPolicyTracker mMultipathPolicyTracker;
621 * Implements support for the legacy "one network per network type" model.
623 * We used to have a static array of NetworkStateTrackers, one for each
624 * network type, but that doesn't work any more now that we can have,
625 * for example, more that one wifi network. This class stores all the
626 * NetworkAgentInfo objects that support a given type, but the legacy
627 * API will only see the first one.
629 * It serves two main purposes:
631 * 1. Provide information about "the network for a given type" (since this
632 * API only supports one).
633 * 2. Send legacy connectivity change broadcasts. Broadcasts are sent if
634 * the first network for a given type changes, or if the default network
638 static class LegacyTypeTracker {
640 private static final boolean DBG = true;
641 private static final boolean VDBG = false;
644 * Array of lists, one per legacy network type (e.g., TYPE_MOBILE_MMS).
645 * Each list holds references to all NetworkAgentInfos that are used to
646 * satisfy requests for that network type.
648 * This array is built out at startup such that an unsupported network
649 * doesn't get an ArrayList instance, making this a tristate:
650 * unsupported, supported but not active and active.
652 * The actual lists are populated when we scan the network types that
653 * are supported on this device.
656 * - addSupportedType() is only called in the constructor
657 * - add(), update(), remove() are only called from the ConnectivityService handler thread.
658 * They are therefore not thread-safe with respect to each other.
659 * - getNetworkForType() can be called at any time on binder threads. It is synchronized
660 * on mTypeLists to be thread-safe with respect to a concurrent remove call.
661 * - dump is thread-safe with respect to concurrent add and remove calls.
663 private final ArrayList<NetworkAgentInfo> mTypeLists[];
665 private final ConnectivityService mService;
667 LegacyTypeTracker(@NonNull ConnectivityService service) {
669 mTypeLists = new ArrayList[ConnectivityManager.MAX_NETWORK_TYPE + 1];
672 public void addSupportedType(int type) {
673 if (mTypeLists[type] != null) {
674 throw new IllegalStateException(
675 "legacy list for type " + type + "already initialized");
677 mTypeLists[type] = new ArrayList<>();
680 public boolean isTypeSupported(int type) {
681 return isNetworkTypeValid(type) && mTypeLists[type] != null;
684 public NetworkAgentInfo getNetworkForType(int type) {
685 synchronized (mTypeLists) {
686 if (isTypeSupported(type) && !mTypeLists[type].isEmpty()) {
687 return mTypeLists[type].get(0);
693 private void maybeLogBroadcast(NetworkAgentInfo nai, DetailedState state, int type,
694 boolean isDefaultNetwork) {
696 log("Sending " + state +
697 " broadcast for type " + type + " " + nai.name() +
698 " isDefaultNetwork=" + isDefaultNetwork);
702 /** Adds the given network to the specified legacy type list. */
703 public void add(int type, NetworkAgentInfo nai) {
704 if (!isTypeSupported(type)) {
705 return; // Invalid network type.
707 if (VDBG) log("Adding agent " + nai + " for legacy network type " + type);
709 ArrayList<NetworkAgentInfo> list = mTypeLists[type];
710 if (list.contains(nai)) {
713 synchronized (mTypeLists) {
717 // Send a broadcast if this is the first network of its type or if it's the default.
718 final boolean isDefaultNetwork = mService.isDefaultNetwork(nai);
719 if ((list.size() == 1) || isDefaultNetwork) {
720 maybeLogBroadcast(nai, DetailedState.CONNECTED, type, isDefaultNetwork);
721 mService.sendLegacyNetworkBroadcast(nai, DetailedState.CONNECTED, type);
725 /** Removes the given network from the specified legacy type list. */
726 public void remove(int type, NetworkAgentInfo nai, boolean wasDefault) {
727 ArrayList<NetworkAgentInfo> list = mTypeLists[type];
728 if (list == null || list.isEmpty()) {
731 final boolean wasFirstNetwork = list.get(0).equals(nai);
733 synchronized (mTypeLists) {
734 if (!list.remove(nai)) {
739 if (wasFirstNetwork || wasDefault) {
740 maybeLogBroadcast(nai, DetailedState.DISCONNECTED, type, wasDefault);
741 mService.sendLegacyNetworkBroadcast(nai, DetailedState.DISCONNECTED, type);
744 if (!list.isEmpty() && wasFirstNetwork) {
745 if (DBG) log("Other network available for type " + type +
746 ", sending connected broadcast");
747 final NetworkAgentInfo replacement = list.get(0);
748 maybeLogBroadcast(replacement, DetailedState.CONNECTED, type,
749 mService.isDefaultNetwork(replacement));
750 mService.sendLegacyNetworkBroadcast(replacement, DetailedState.CONNECTED, type);
754 /** Removes the given network from all legacy type lists. */
755 public void remove(NetworkAgentInfo nai, boolean wasDefault) {
756 if (VDBG) log("Removing agent " + nai + " wasDefault=" + wasDefault);
757 for (int type = 0; type < mTypeLists.length; type++) {
758 remove(type, nai, wasDefault);
762 // send out another legacy broadcast - currently only used for suspend/unsuspend
764 public void update(NetworkAgentInfo nai) {
765 final boolean isDefault = mService.isDefaultNetwork(nai);
766 final DetailedState state = nai.networkInfo.getDetailedState();
767 for (int type = 0; type < mTypeLists.length; type++) {
768 final ArrayList<NetworkAgentInfo> list = mTypeLists[type];
769 final boolean contains = (list != null && list.contains(nai));
770 final boolean isFirst = contains && (nai == list.get(0));
771 if (isFirst || contains && isDefault) {
772 maybeLogBroadcast(nai, state, type, isDefault);
773 mService.sendLegacyNetworkBroadcast(nai, state, type);
778 private String naiToString(NetworkAgentInfo nai) {
779 String name = nai.name();
780 String state = (nai.networkInfo != null) ?
781 nai.networkInfo.getState() + "/" + nai.networkInfo.getDetailedState() :
783 return name + " " + state;
786 public void dump(IndentingPrintWriter pw) {
787 pw.println("mLegacyTypeTracker:");
789 pw.print("Supported types:");
790 for (int type = 0; type < mTypeLists.length; type++) {
791 if (mTypeLists[type] != null) pw.print(" " + type);
794 pw.println("Current state:");
796 synchronized (mTypeLists) {
797 for (int type = 0; type < mTypeLists.length; type++) {
798 if (mTypeLists[type] == null || mTypeLists[type].isEmpty()) continue;
799 for (NetworkAgentInfo nai : mTypeLists[type]) {
800 pw.println(type + " " + naiToString(nai));
809 private final LegacyTypeTracker mLegacyTypeTracker = new LegacyTypeTracker(this);
812 * Helper class which parses out priority arguments and dumps sections according to their
813 * priority. If priority arguments are omitted, function calls the legacy dump command.
815 private final PriorityDump.PriorityDumper mPriorityDumper = new PriorityDump.PriorityDumper() {
817 public void dumpHigh(FileDescriptor fd, PrintWriter pw, String[] args, boolean asProto) {
818 doDump(fd, pw, new String[] {DIAG_ARG}, asProto);
819 doDump(fd, pw, new String[] {SHORT_ARG}, asProto);
823 public void dumpNormal(FileDescriptor fd, PrintWriter pw, String[] args, boolean asProto) {
824 doDump(fd, pw, args, asProto);
828 public void dump(FileDescriptor fd, PrintWriter pw, String[] args, boolean asProto) {
829 doDump(fd, pw, args, asProto);
833 public ConnectivityService(Context context, INetworkManagementService netManager,
834 INetworkStatsService statsService, INetworkPolicyManager policyManager) {
835 this(context, netManager, statsService, policyManager,
836 getDnsResolver(), new IpConnectivityLog(), NetdService.getInstance());
840 protected ConnectivityService(Context context, INetworkManagementService netManager,
841 INetworkStatsService statsService, INetworkPolicyManager policyManager,
842 IDnsResolver dnsresolver, IpConnectivityLog logger, INetd netd) {
843 if (DBG) log("ConnectivityService starting up");
845 mSystemProperties = getSystemProperties();
847 mMetricsLog = logger;
848 mDefaultRequest = createDefaultInternetRequestForTransport(-1, NetworkRequest.Type.REQUEST);
849 NetworkRequestInfo defaultNRI = new NetworkRequestInfo(null, mDefaultRequest, new Binder());
850 mNetworkRequests.put(mDefaultRequest, defaultNRI);
851 mNetworkRequestInfoLogs.log("REGISTER " + defaultNRI);
853 mDefaultMobileDataRequest = createDefaultInternetRequestForTransport(
854 NetworkCapabilities.TRANSPORT_CELLULAR, NetworkRequest.Type.BACKGROUND_REQUEST);
856 // The default WiFi request is a background request so that apps using WiFi are
857 // migrated to a better network (typically ethernet) when one comes up, instead
858 // of staying on WiFi forever.
859 mDefaultWifiRequest = createDefaultInternetRequestForTransport(
860 NetworkCapabilities.TRANSPORT_WIFI, NetworkRequest.Type.BACKGROUND_REQUEST);
862 mHandlerThread = new HandlerThread("ConnectivityServiceThread");
863 mHandlerThread.start();
864 mHandler = new InternalHandler(mHandlerThread.getLooper());
865 mTrackerHandler = new NetworkStateTrackerHandler(mHandlerThread.getLooper());
867 mReleasePendingIntentDelayMs = Settings.Secure.getInt(context.getContentResolver(),
868 Settings.Secure.CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS, 5_000);
870 mLingerDelayMs = mSystemProperties.getInt(LINGER_DELAY_PROPERTY, DEFAULT_LINGER_DELAY_MS);
872 mContext = checkNotNull(context, "missing Context");
873 mNMS = checkNotNull(netManager, "missing INetworkManagementService");
874 mStatsService = checkNotNull(statsService, "missing INetworkStatsService");
875 mPolicyManager = checkNotNull(policyManager, "missing INetworkPolicyManager");
876 mPolicyManagerInternal = checkNotNull(
877 LocalServices.getService(NetworkPolicyManagerInternal.class),
878 "missing NetworkPolicyManagerInternal");
879 mDnsResolver = checkNotNull(dnsresolver, "missing IDnsResolver");
880 mProxyTracker = makeProxyTracker();
883 mKeyStore = KeyStore.getInstance();
884 mTelephonyManager = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
886 // To ensure uid rules are synchronized with Network Policy, register for
887 // NetworkPolicyManagerService events must happen prior to NetworkPolicyManagerService
888 // reading existing policy from disk.
890 mPolicyManager.registerListener(mPolicyListener);
891 } catch (RemoteException e) {
892 // ouch, no rules updates means some processes may never get network
893 loge("unable to register INetworkPolicyListener" + e);
896 final PowerManager powerManager = (PowerManager) context.getSystemService(
897 Context.POWER_SERVICE);
898 mNetTransitionWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
899 mNetTransitionWakeLockTimeout = mContext.getResources().getInteger(
900 com.android.internal.R.integer.config_networkTransitionTimeout);
901 mPendingIntentWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
903 mNetConfigs = new NetworkConfig[ConnectivityManager.MAX_NETWORK_TYPE+1];
905 // TODO: What is the "correct" way to do determine if this is a wifi only device?
906 boolean wifiOnly = mSystemProperties.getBoolean("ro.radio.noril", false);
907 log("wifiOnly=" + wifiOnly);
908 String[] naStrings = context.getResources().getStringArray(
909 com.android.internal.R.array.networkAttributes);
910 for (String naString : naStrings) {
912 NetworkConfig n = new NetworkConfig(naString);
913 if (VDBG) log("naString=" + naString + " config=" + n);
914 if (n.type > ConnectivityManager.MAX_NETWORK_TYPE) {
915 loge("Error in networkAttributes - ignoring attempt to define type " +
919 if (wifiOnly && ConnectivityManager.isNetworkTypeMobile(n.type)) {
920 log("networkAttributes - ignoring mobile as this dev is wifiOnly " +
924 if (mNetConfigs[n.type] != null) {
925 loge("Error in networkAttributes - ignoring attempt to redefine type " +
929 mLegacyTypeTracker.addSupportedType(n.type);
931 mNetConfigs[n.type] = n;
933 } catch(Exception e) {
934 // ignore it - leave the entry null
938 // Forcibly add TYPE_VPN as a supported type, if it has not already been added via config.
939 if (mNetConfigs[TYPE_VPN] == null) {
940 // mNetConfigs is used only for "restore time", which isn't applicable to VPNs, so we
941 // don't need to add TYPE_VPN to mNetConfigs.
942 mLegacyTypeTracker.addSupportedType(TYPE_VPN);
943 mNetworksDefined++; // used only in the log() statement below.
946 // Do the same for Ethernet, since it's often not specified in the configs, although many
947 // devices can use it via USB host adapters.
948 if (mNetConfigs[TYPE_ETHERNET] == null && hasService(Context.ETHERNET_SERVICE)) {
949 mLegacyTypeTracker.addSupportedType(TYPE_ETHERNET);
953 if (VDBG) log("mNetworksDefined=" + mNetworksDefined);
955 mProtectedNetworks = new ArrayList<Integer>();
956 int[] protectedNetworks = context.getResources().getIntArray(
957 com.android.internal.R.array.config_protectedNetworks);
958 for (int p : protectedNetworks) {
959 if ((mNetConfigs[p] != null) && (mProtectedNetworks.contains(p) == false)) {
960 mProtectedNetworks.add(p);
962 if (DBG) loge("Ignoring protectedNetwork " + p);
966 mTethering = makeTethering();
968 mPermissionMonitor = new PermissionMonitor(mContext, mNetd);
970 // Set up the listener for user state for creating user VPNs.
971 // Should run on mHandler to avoid any races.
972 IntentFilter intentFilter = new IntentFilter();
973 intentFilter.addAction(Intent.ACTION_USER_STARTED);
974 intentFilter.addAction(Intent.ACTION_USER_STOPPED);
975 intentFilter.addAction(Intent.ACTION_USER_ADDED);
976 intentFilter.addAction(Intent.ACTION_USER_REMOVED);
977 intentFilter.addAction(Intent.ACTION_USER_UNLOCKED);
978 mContext.registerReceiverAsUser(
982 null /* broadcastPermission */,
984 mContext.registerReceiverAsUser(mUserPresentReceiver, UserHandle.SYSTEM,
985 new IntentFilter(Intent.ACTION_USER_PRESENT), null, null);
987 // Listen to package add and removal events for all users.
988 intentFilter = new IntentFilter();
989 intentFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
990 intentFilter.addAction(Intent.ACTION_PACKAGE_REPLACED);
991 intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
992 intentFilter.addDataScheme("package");
993 mContext.registerReceiverAsUser(
997 null /* broadcastPermission */,
1001 mNMS.registerObserver(mTethering);
1002 mNMS.registerObserver(mDataActivityObserver);
1003 } catch (RemoteException e) {
1004 loge("Error registering observer :" + e);
1007 mSettingsObserver = new SettingsObserver(mContext, mHandler);
1008 registerSettingsCallbacks();
1010 final DataConnectionStats dataConnectionStats = new DataConnectionStats(mContext);
1011 dataConnectionStats.startMonitoring();
1013 mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
1015 mKeepaliveTracker = new KeepaliveTracker(mContext, mHandler);
1016 mNotifier = new NetworkNotificationManager(mContext, mTelephonyManager,
1017 mContext.getSystemService(NotificationManager.class));
1019 final int dailyLimit = Settings.Global.getInt(mContext.getContentResolver(),
1020 Settings.Global.NETWORK_SWITCH_NOTIFICATION_DAILY_LIMIT,
1021 LingerMonitor.DEFAULT_NOTIFICATION_DAILY_LIMIT);
1022 final long rateLimit = Settings.Global.getLong(mContext.getContentResolver(),
1023 Settings.Global.NETWORK_SWITCH_NOTIFICATION_RATE_LIMIT_MILLIS,
1024 LingerMonitor.DEFAULT_NOTIFICATION_RATE_LIMIT_MILLIS);
1025 mLingerMonitor = new LingerMonitor(mContext, mNotifier, dailyLimit, rateLimit);
1027 mMultinetworkPolicyTracker = createMultinetworkPolicyTracker(
1028 mContext, mHandler, () -> rematchForAvoidBadWifiUpdate());
1029 mMultinetworkPolicyTracker.start();
1031 mMultipathPolicyTracker = new MultipathPolicyTracker(mContext, mHandler);
1033 mDnsManager = new DnsManager(mContext, mDnsResolver, mSystemProperties);
1034 registerPrivateDnsSettingsCallbacks();
1038 protected Tethering makeTethering() {
1039 // TODO: Move other elements into @Overridden getters.
1040 final TetheringDependencies deps = new TetheringDependencies() {
1042 public boolean isTetheringSupported() {
1043 return ConnectivityService.this.isTetheringSupported();
1046 public NetworkRequest getDefaultNetworkRequest() {
1047 return mDefaultRequest;
1050 return new Tethering(mContext, mNMS, mStatsService, mPolicyManager,
1051 IoThread.get().getLooper(), new MockableSystemProperties(),
1056 protected ProxyTracker makeProxyTracker() {
1057 return new ProxyTracker(mContext, mHandler, EVENT_PROXY_HAS_CHANGED);
1060 private static NetworkCapabilities createDefaultNetworkCapabilitiesForUid(int uid) {
1061 final NetworkCapabilities netCap = new NetworkCapabilities();
1062 netCap.addCapability(NET_CAPABILITY_INTERNET);
1063 netCap.addCapability(NET_CAPABILITY_NOT_RESTRICTED);
1064 netCap.removeCapability(NET_CAPABILITY_NOT_VPN);
1065 netCap.setSingleUid(uid);
1069 private NetworkRequest createDefaultInternetRequestForTransport(
1070 int transportType, NetworkRequest.Type type) {
1071 final NetworkCapabilities netCap = new NetworkCapabilities();
1072 netCap.addCapability(NET_CAPABILITY_INTERNET);
1073 netCap.addCapability(NET_CAPABILITY_NOT_RESTRICTED);
1074 if (transportType > -1) {
1075 netCap.addTransportType(transportType);
1077 return new NetworkRequest(netCap, TYPE_NONE, nextNetworkRequestId(), type);
1080 // Used only for testing.
1081 // TODO: Delete this and either:
1082 // 1. Give FakeSettingsProvider the ability to send settings change notifications (requires
1083 // changing ContentResolver to make registerContentObserver non-final).
1084 // 2. Give FakeSettingsProvider an alternative notification mechanism and have the test use it
1085 // by subclassing SettingsObserver.
1087 void updateAlwaysOnNetworks() {
1088 mHandler.sendEmptyMessage(EVENT_CONFIGURE_ALWAYS_ON_NETWORKS);
1091 // See FakeSettingsProvider comment above.
1093 void updatePrivateDnsSettings() {
1094 mHandler.sendEmptyMessage(EVENT_PRIVATE_DNS_SETTINGS_CHANGED);
1097 private void handleAlwaysOnNetworkRequest(
1098 NetworkRequest networkRequest, String settingName, boolean defaultValue) {
1099 final boolean enable = toBool(Settings.Global.getInt(
1100 mContext.getContentResolver(), settingName, encodeBool(defaultValue)));
1101 final boolean isEnabled = (mNetworkRequests.get(networkRequest) != null);
1102 if (enable == isEnabled) {
1103 return; // Nothing to do.
1107 handleRegisterNetworkRequest(new NetworkRequestInfo(
1108 null, networkRequest, new Binder()));
1110 handleReleaseNetworkRequest(networkRequest, Process.SYSTEM_UID,
1111 /* callOnUnavailable */ false);
1115 private void handleConfigureAlwaysOnNetworks() {
1116 handleAlwaysOnNetworkRequest(
1117 mDefaultMobileDataRequest,Settings.Global.MOBILE_DATA_ALWAYS_ON, true);
1118 handleAlwaysOnNetworkRequest(mDefaultWifiRequest, Settings.Global.WIFI_ALWAYS_REQUESTED,
1122 private void registerSettingsCallbacks() {
1123 // Watch for global HTTP proxy changes.
1124 mSettingsObserver.observe(
1125 Settings.Global.getUriFor(Settings.Global.HTTP_PROXY),
1126 EVENT_APPLY_GLOBAL_HTTP_PROXY);
1128 // Watch for whether or not to keep mobile data always on.
1129 mSettingsObserver.observe(
1130 Settings.Global.getUriFor(Settings.Global.MOBILE_DATA_ALWAYS_ON),
1131 EVENT_CONFIGURE_ALWAYS_ON_NETWORKS);
1133 // Watch for whether or not to keep wifi always on.
1134 mSettingsObserver.observe(
1135 Settings.Global.getUriFor(Settings.Global.WIFI_ALWAYS_REQUESTED),
1136 EVENT_CONFIGURE_ALWAYS_ON_NETWORKS);
1139 private void registerPrivateDnsSettingsCallbacks() {
1140 for (Uri uri : DnsManager.getPrivateDnsSettingsUris()) {
1141 mSettingsObserver.observe(uri, EVENT_PRIVATE_DNS_SETTINGS_CHANGED);
1145 private synchronized int nextNetworkRequestId() {
1146 return mNextNetworkRequestId++;
1150 protected int reserveNetId() {
1151 synchronized (mNetworkForNetId) {
1152 for (int i = MIN_NET_ID; i <= MAX_NET_ID; i++) {
1153 int netId = mNextNetId;
1154 if (++mNextNetId > MAX_NET_ID) mNextNetId = MIN_NET_ID;
1155 // Make sure NetID unused. http://b/16815182
1156 if (!mNetIdInUse.get(netId)) {
1157 mNetIdInUse.put(netId, true);
1162 throw new IllegalStateException("No free netIds");
1165 private NetworkState getFilteredNetworkState(int networkType, int uid) {
1166 if (mLegacyTypeTracker.isTypeSupported(networkType)) {
1167 final NetworkAgentInfo nai = mLegacyTypeTracker.getNetworkForType(networkType);
1168 final NetworkState state;
1170 state = nai.getNetworkState();
1171 state.networkInfo.setType(networkType);
1173 final NetworkInfo info = new NetworkInfo(networkType, 0,
1174 getNetworkTypeName(networkType), "");
1175 info.setDetailedState(NetworkInfo.DetailedState.DISCONNECTED, null, null);
1176 info.setIsAvailable(true);
1177 final NetworkCapabilities capabilities = new NetworkCapabilities();
1178 capabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING,
1180 state = new NetworkState(info, new LinkProperties(), capabilities,
1183 filterNetworkStateForUid(state, uid, false);
1186 return NetworkState.EMPTY;
1191 protected NetworkAgentInfo getNetworkAgentInfoForNetwork(Network network) {
1192 if (network == null) {
1195 return getNetworkAgentInfoForNetId(network.netId);
1198 private NetworkAgentInfo getNetworkAgentInfoForNetId(int netId) {
1199 synchronized (mNetworkForNetId) {
1200 return mNetworkForNetId.get(netId);
1204 private Network[] getVpnUnderlyingNetworks(int uid) {
1205 synchronized (mVpns) {
1206 if (!mLockdownEnabled) {
1207 int user = UserHandle.getUserId(uid);
1208 Vpn vpn = mVpns.get(user);
1209 if (vpn != null && vpn.appliesToUid(uid)) {
1210 return vpn.getUnderlyingNetworks();
1217 private NetworkState getUnfilteredActiveNetworkState(int uid) {
1218 NetworkAgentInfo nai = getDefaultNetwork();
1220 final Network[] networks = getVpnUnderlyingNetworks(uid);
1221 if (networks != null) {
1222 // getUnderlyingNetworks() returns:
1223 // null => there was no VPN, or the VPN didn't specify anything, so we use the default.
1224 // empty array => the VPN explicitly said "no default network".
1225 // non-empty array => the VPN specified one or more default networks; we use the
1227 if (networks.length > 0) {
1228 nai = getNetworkAgentInfoForNetwork(networks[0]);
1235 return nai.getNetworkState();
1237 return NetworkState.EMPTY;
1242 * Check if UID should be blocked from using the network with the given LinkProperties.
1244 private boolean isNetworkWithLinkPropertiesBlocked(LinkProperties lp, int uid,
1245 boolean ignoreBlocked) {
1246 // Networks aren't blocked when ignoring blocked status
1247 if (ignoreBlocked) {
1250 synchronized (mVpns) {
1251 final Vpn vpn = mVpns.get(UserHandle.getUserId(uid));
1252 if (vpn != null && vpn.getLockdown() && vpn.isBlockingUid(uid)) {
1256 final String iface = (lp == null ? "" : lp.getInterfaceName());
1257 return mPolicyManagerInternal.isUidNetworkingBlocked(uid, iface);
1260 private void maybeLogBlockedNetworkInfo(NetworkInfo ni, int uid) {
1261 if (ni == null || !LOGD_BLOCKED_NETWORKINFO) {
1264 final boolean blocked;
1265 synchronized (mBlockedAppUids) {
1266 if (ni.getDetailedState() == DetailedState.BLOCKED && mBlockedAppUids.add(uid)) {
1268 } else if (ni.isConnected() && mBlockedAppUids.remove(uid)) {
1274 String action = blocked ? "BLOCKED" : "UNBLOCKED";
1275 log(String.format("Returning %s NetworkInfo to uid=%d", action, uid));
1276 mNetworkInfoBlockingLogs.log(action + " " + uid);
1279 private void maybeLogBlockedStatusChanged(NetworkRequestInfo nri, Network net,
1281 if (nri == null || net == null || !LOGD_BLOCKED_NETWORKINFO) {
1284 String action = blocked ? "BLOCKED" : "UNBLOCKED";
1285 log(String.format("Blocked status changed to %s for %d(%d) on netId %d", blocked,
1286 nri.mUid, nri.request.requestId, net.netId));
1287 mNetworkInfoBlockingLogs.log(action + " " + nri.mUid);
1291 * Apply any relevant filters to {@link NetworkState} for the given UID. For
1292 * example, this may mark the network as {@link DetailedState#BLOCKED} based
1293 * on {@link #isNetworkWithLinkPropertiesBlocked}.
1295 private void filterNetworkStateForUid(NetworkState state, int uid, boolean ignoreBlocked) {
1296 if (state == null || state.networkInfo == null || state.linkProperties == null) return;
1298 if (isNetworkWithLinkPropertiesBlocked(state.linkProperties, uid, ignoreBlocked)) {
1299 state.networkInfo.setDetailedState(DetailedState.BLOCKED, null, null);
1301 synchronized (mVpns) {
1302 if (mLockdownTracker != null) {
1303 mLockdownTracker.augmentNetworkInfo(state.networkInfo);
1309 * Return NetworkInfo for the active (i.e., connected) network interface.
1310 * It is assumed that at most one network is active at a time. If more
1311 * than one is active, it is indeterminate which will be returned.
1312 * @return the info for the active network, or {@code null} if none is
1316 public NetworkInfo getActiveNetworkInfo() {
1317 enforceAccessPermission();
1318 final int uid = Binder.getCallingUid();
1319 final NetworkState state = getUnfilteredActiveNetworkState(uid);
1320 filterNetworkStateForUid(state, uid, false);
1321 maybeLogBlockedNetworkInfo(state.networkInfo, uid);
1322 return state.networkInfo;
1326 public Network getActiveNetwork() {
1327 enforceAccessPermission();
1328 return getActiveNetworkForUidInternal(Binder.getCallingUid(), false);
1332 public Network getActiveNetworkForUid(int uid, boolean ignoreBlocked) {
1333 enforceConnectivityInternalPermission();
1334 return getActiveNetworkForUidInternal(uid, ignoreBlocked);
1337 private Network getActiveNetworkForUidInternal(final int uid, boolean ignoreBlocked) {
1338 final int user = UserHandle.getUserId(uid);
1339 int vpnNetId = NETID_UNSET;
1340 synchronized (mVpns) {
1341 final Vpn vpn = mVpns.get(user);
1342 // TODO : now that capabilities contain the UID, the appliesToUid test should
1343 // be removed as the satisfying test below should be enough.
1344 if (vpn != null && vpn.appliesToUid(uid)) vpnNetId = vpn.getNetId();
1346 NetworkAgentInfo nai;
1347 if (vpnNetId != NETID_UNSET) {
1348 nai = getNetworkAgentInfoForNetId(vpnNetId);
1350 final NetworkCapabilities requiredCaps =
1351 createDefaultNetworkCapabilitiesForUid(uid);
1352 if (requiredCaps.satisfiedByNetworkCapabilities(nai.networkCapabilities)) {
1357 nai = getDefaultNetwork();
1359 && isNetworkWithLinkPropertiesBlocked(nai.linkProperties, uid, ignoreBlocked)) {
1362 return nai != null ? nai.network : null;
1365 // Public because it's used by mLockdownTracker.
1366 public NetworkInfo getActiveNetworkInfoUnfiltered() {
1367 enforceAccessPermission();
1368 final int uid = Binder.getCallingUid();
1369 NetworkState state = getUnfilteredActiveNetworkState(uid);
1370 return state.networkInfo;
1374 public NetworkInfo getActiveNetworkInfoForUid(int uid, boolean ignoreBlocked) {
1375 enforceConnectivityInternalPermission();
1376 final NetworkState state = getUnfilteredActiveNetworkState(uid);
1377 filterNetworkStateForUid(state, uid, ignoreBlocked);
1378 return state.networkInfo;
1382 public NetworkInfo getNetworkInfo(int networkType) {
1383 enforceAccessPermission();
1384 final int uid = Binder.getCallingUid();
1385 if (getVpnUnderlyingNetworks(uid) != null) {
1386 // A VPN is active, so we may need to return one of its underlying networks. This
1387 // information is not available in LegacyTypeTracker, so we have to get it from
1388 // getUnfilteredActiveNetworkState.
1389 final NetworkState state = getUnfilteredActiveNetworkState(uid);
1390 if (state.networkInfo != null && state.networkInfo.getType() == networkType) {
1391 filterNetworkStateForUid(state, uid, false);
1392 return state.networkInfo;
1395 final NetworkState state = getFilteredNetworkState(networkType, uid);
1396 return state.networkInfo;
1400 public NetworkInfo getNetworkInfoForUid(Network network, int uid, boolean ignoreBlocked) {
1401 enforceAccessPermission();
1402 final NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
1404 final NetworkState state = nai.getNetworkState();
1405 filterNetworkStateForUid(state, uid, ignoreBlocked);
1406 return state.networkInfo;
1413 public NetworkInfo[] getAllNetworkInfo() {
1414 enforceAccessPermission();
1415 final ArrayList<NetworkInfo> result = Lists.newArrayList();
1416 for (int networkType = 0; networkType <= ConnectivityManager.MAX_NETWORK_TYPE;
1418 NetworkInfo info = getNetworkInfo(networkType);
1423 return result.toArray(new NetworkInfo[result.size()]);
1427 public Network getNetworkForType(int networkType) {
1428 enforceAccessPermission();
1429 final int uid = Binder.getCallingUid();
1430 NetworkState state = getFilteredNetworkState(networkType, uid);
1431 if (!isNetworkWithLinkPropertiesBlocked(state.linkProperties, uid, false)) {
1432 return state.network;
1438 public Network[] getAllNetworks() {
1439 enforceAccessPermission();
1440 synchronized (mNetworkForNetId) {
1441 final Network[] result = new Network[mNetworkForNetId.size()];
1442 for (int i = 0; i < mNetworkForNetId.size(); i++) {
1443 result[i] = mNetworkForNetId.valueAt(i).network;
1450 public NetworkCapabilities[] getDefaultNetworkCapabilitiesForUser(int userId) {
1451 // The basic principle is: if an app's traffic could possibly go over a
1452 // network, without the app doing anything multinetwork-specific,
1453 // (hence, by "default"), then include that network's capabilities in
1456 // In the normal case, app traffic only goes over the system's default
1457 // network connection, so that's the only network returned.
1459 // With a VPN in force, some app traffic may go into the VPN, and thus
1460 // over whatever underlying networks the VPN specifies, while other app
1461 // traffic may go over the system default network (e.g.: a split-tunnel
1462 // VPN, or an app disallowed by the VPN), so the set of networks
1463 // returned includes the VPN's underlying networks and the system
1465 enforceAccessPermission();
1467 HashMap<Network, NetworkCapabilities> result = new HashMap<>();
1469 NetworkAgentInfo nai = getDefaultNetwork();
1470 NetworkCapabilities nc = getNetworkCapabilitiesInternal(nai);
1472 result.put(nai.network, nc);
1475 synchronized (mVpns) {
1476 if (!mLockdownEnabled) {
1477 Vpn vpn = mVpns.get(userId);
1479 Network[] networks = vpn.getUnderlyingNetworks();
1480 if (networks != null) {
1481 for (Network network : networks) {
1482 nai = getNetworkAgentInfoForNetwork(network);
1483 nc = getNetworkCapabilitiesInternal(nai);
1485 result.put(network, nc);
1493 NetworkCapabilities[] out = new NetworkCapabilities[result.size()];
1494 out = result.values().toArray(out);
1499 public boolean isNetworkSupported(int networkType) {
1500 enforceAccessPermission();
1501 return mLegacyTypeTracker.isTypeSupported(networkType);
1505 * Return LinkProperties for the active (i.e., connected) default
1506 * network interface. It is assumed that at most one default network
1507 * is active at a time. If more than one is active, it is indeterminate
1508 * which will be returned.
1509 * @return the ip properties for the active network, or {@code null} if
1513 public LinkProperties getActiveLinkProperties() {
1514 enforceAccessPermission();
1515 final int uid = Binder.getCallingUid();
1516 NetworkState state = getUnfilteredActiveNetworkState(uid);
1517 return state.linkProperties;
1521 public LinkProperties getLinkPropertiesForType(int networkType) {
1522 enforceAccessPermission();
1523 NetworkAgentInfo nai = mLegacyTypeTracker.getNetworkForType(networkType);
1525 synchronized (nai) {
1526 return new LinkProperties(nai.linkProperties);
1532 // TODO - this should be ALL networks
1534 public LinkProperties getLinkProperties(Network network) {
1535 enforceAccessPermission();
1536 return getLinkProperties(getNetworkAgentInfoForNetwork(network));
1539 private LinkProperties getLinkProperties(NetworkAgentInfo nai) {
1543 synchronized (nai) {
1544 return new LinkProperties(nai.linkProperties);
1548 private NetworkCapabilities getNetworkCapabilitiesInternal(NetworkAgentInfo nai) {
1550 synchronized (nai) {
1551 if (nai.networkCapabilities != null) {
1552 return networkCapabilitiesRestrictedForCallerPermissions(
1553 nai.networkCapabilities,
1554 Binder.getCallingPid(), Binder.getCallingUid());
1562 public NetworkCapabilities getNetworkCapabilities(Network network) {
1563 enforceAccessPermission();
1564 return getNetworkCapabilitiesInternal(getNetworkAgentInfoForNetwork(network));
1567 private NetworkCapabilities networkCapabilitiesRestrictedForCallerPermissions(
1568 NetworkCapabilities nc, int callerPid, int callerUid) {
1569 final NetworkCapabilities newNc = new NetworkCapabilities(nc);
1570 if (!checkSettingsPermission(callerPid, callerUid)) {
1571 newNc.setUids(null);
1572 newNc.setSSID(null);
1574 if (newNc.getNetworkSpecifier() != null) {
1575 newNc.setNetworkSpecifier(newNc.getNetworkSpecifier().redact());
1580 private void restrictRequestUidsForCaller(NetworkCapabilities nc) {
1581 if (!checkSettingsPermission()) {
1582 nc.setSingleUid(Binder.getCallingUid());
1586 private void restrictBackgroundRequestForCaller(NetworkCapabilities nc) {
1587 if (!mPermissionMonitor.hasUseBackgroundNetworksPermission(Binder.getCallingUid())) {
1588 nc.addCapability(NET_CAPABILITY_FOREGROUND);
1593 public NetworkState[] getAllNetworkState() {
1594 // Require internal since we're handing out IMSI details
1595 enforceConnectivityInternalPermission();
1597 final ArrayList<NetworkState> result = Lists.newArrayList();
1598 for (Network network : getAllNetworks()) {
1599 final NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
1601 // TODO (b/73321673) : NetworkState contains a copy of the
1602 // NetworkCapabilities, which may contain UIDs of apps to which the
1603 // network applies. Should the UIDs be cleared so as not to leak or
1605 result.add(nai.getNetworkState());
1608 return result.toArray(new NetworkState[result.size()]);
1613 public NetworkQuotaInfo getActiveNetworkQuotaInfo() {
1614 Log.w(TAG, "Shame on UID " + Binder.getCallingUid()
1615 + " for calling the hidden API getNetworkQuotaInfo(). Shame!");
1616 return new NetworkQuotaInfo();
1620 public boolean isActiveNetworkMetered() {
1621 enforceAccessPermission();
1623 final NetworkCapabilities caps = getNetworkCapabilities(getActiveNetwork());
1625 return !caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
1627 // Always return the most conservative value
1632 private INetworkManagementEventObserver mDataActivityObserver = new BaseNetworkObserver() {
1634 public void interfaceClassDataActivityChanged(String label, boolean active, long tsNanos) {
1635 int deviceType = Integer.parseInt(label);
1636 sendDataActivityBroadcast(deviceType, active, tsNanos);
1641 * Ensures that the system cannot call a particular method.
1643 private boolean disallowedBecauseSystemCaller() {
1644 // TODO: start throwing a SecurityException when GnssLocationProvider stops calling
1645 // requestRouteToHost. In Q, GnssLocationProvider is changed to not call requestRouteToHost
1646 // for devices launched with Q and above. However, existing devices upgrading to Q and
1647 // above must continued to be supported for few more releases.
1648 if (isSystem(Binder.getCallingUid()) && SystemProperties.getInt(
1649 "ro.product.first_api_level", 0) > Build.VERSION_CODES.P) {
1650 log("This method exists only for app backwards compatibility"
1651 + " and must not be called by system services.");
1658 * Ensure that a network route exists to deliver traffic to the specified
1659 * host via the specified network interface.
1660 * @param networkType the type of the network over which traffic to the
1661 * specified host is to be routed
1662 * @param hostAddress the IP address of the host to which the route is
1664 * @return {@code true} on success, {@code false} on failure
1667 public boolean requestRouteToHostAddress(int networkType, byte[] hostAddress) {
1668 if (disallowedBecauseSystemCaller()) {
1671 enforceChangePermission();
1672 if (mProtectedNetworks.contains(networkType)) {
1673 enforceConnectivityInternalPermission();
1678 addr = InetAddress.getByAddress(hostAddress);
1679 } catch (UnknownHostException e) {
1680 if (DBG) log("requestRouteToHostAddress got " + e.toString());
1684 if (!ConnectivityManager.isNetworkTypeValid(networkType)) {
1685 if (DBG) log("requestRouteToHostAddress on invalid network: " + networkType);
1689 NetworkAgentInfo nai = mLegacyTypeTracker.getNetworkForType(networkType);
1691 if (mLegacyTypeTracker.isTypeSupported(networkType) == false) {
1692 if (DBG) log("requestRouteToHostAddress on unsupported network: " + networkType);
1694 if (DBG) log("requestRouteToHostAddress on down network: " + networkType);
1699 DetailedState netState;
1700 synchronized (nai) {
1701 netState = nai.networkInfo.getDetailedState();
1704 if (netState != DetailedState.CONNECTED && netState != DetailedState.CAPTIVE_PORTAL_CHECK) {
1706 log("requestRouteToHostAddress on down network "
1707 + "(" + networkType + ") - dropped"
1708 + " netState=" + netState);
1713 final int uid = Binder.getCallingUid();
1714 final long token = Binder.clearCallingIdentity();
1718 synchronized (nai) {
1719 lp = nai.linkProperties;
1720 netId = nai.network.netId;
1722 boolean ok = addLegacyRouteToHost(lp, addr, netId, uid);
1723 if (DBG) log("requestRouteToHostAddress ok=" + ok);
1726 Binder.restoreCallingIdentity(token);
1730 private boolean addLegacyRouteToHost(LinkProperties lp, InetAddress addr, int netId, int uid) {
1731 RouteInfo bestRoute = RouteInfo.selectBestRoute(lp.getAllRoutes(), addr);
1732 if (bestRoute == null) {
1733 bestRoute = RouteInfo.makeHostRoute(addr, lp.getInterfaceName());
1735 String iface = bestRoute.getInterface();
1736 if (bestRoute.getGateway().equals(addr)) {
1737 // if there is no better route, add the implied hostroute for our gateway
1738 bestRoute = RouteInfo.makeHostRoute(addr, iface);
1740 // if we will connect to this through another route, add a direct route
1742 bestRoute = RouteInfo.makeHostRoute(addr, bestRoute.getGateway(), iface);
1745 if (DBG) log("Adding legacy route " + bestRoute +
1746 " for UID/PID " + uid + "/" + Binder.getCallingPid());
1748 mNMS.addLegacyRouteForNetId(netId, bestRoute, uid);
1749 } catch (Exception e) {
1750 // never crash - catch them all
1751 if (DBG) loge("Exception trying to add a route: " + e);
1758 protected final INetdEventCallback mNetdEventCallback = new BaseNetdEventCallback() {
1760 public void onPrivateDnsValidationEvent(int netId, String ipAddress,
1761 String hostname, boolean validated) {
1763 mHandler.sendMessage(mHandler.obtainMessage(
1764 EVENT_PRIVATE_DNS_VALIDATION_UPDATE,
1765 new PrivateDnsValidationUpdate(netId,
1766 InetAddress.parseNumericAddress(ipAddress),
1767 hostname, validated)));
1768 } catch (IllegalArgumentException e) {
1769 loge("Error parsing ip address in validation event");
1774 public void onDnsEvent(int netId, int eventType, int returnCode, String hostname,
1775 String[] ipAddresses, int ipAddressesCount, long timestamp, int uid) {
1776 NetworkAgentInfo nai = getNetworkAgentInfoForNetId(netId);
1777 // Netd event only allow registrants from system. Each NetworkMonitor thread is under
1778 // the caller thread of registerNetworkAgent. Thus, it's not allowed to register netd
1779 // event callback for certain nai. e.g. cellular. Register here to pass to
1780 // NetworkMonitor instead.
1781 // TODO: Move the Dns Event to NetworkMonitor. NetdEventListenerService only allow one
1782 // callback from each caller type. Need to re-factor NetdEventListenerService to allow
1783 // multiple NetworkMonitor registrants.
1784 if (nai != null && nai.satisfies(mDefaultRequest)) {
1785 Binder.withCleanCallingIdentity(() ->
1786 nai.networkMonitor().notifyDnsResponse(returnCode));
1791 public void onNat64PrefixEvent(int netId, boolean added,
1792 String prefixString, int prefixLength) {
1793 mHandler.post(() -> handleNat64PrefixEvent(netId, added, prefixString, prefixLength));
1798 protected void registerNetdEventCallback() {
1799 final IIpConnectivityMetrics ipConnectivityMetrics =
1800 IIpConnectivityMetrics.Stub.asInterface(
1801 ServiceManager.getService(IpConnectivityLog.SERVICE_NAME));
1802 if (ipConnectivityMetrics == null) {
1803 Slog.wtf(TAG, "Missing IIpConnectivityMetrics");
1808 ipConnectivityMetrics.addNetdEventCallback(
1809 INetdEventCallback.CALLBACK_CALLER_CONNECTIVITY_SERVICE,
1810 mNetdEventCallback);
1811 } catch (Exception e) {
1812 loge("Error registering netd callback: " + e);
1816 private final INetworkPolicyListener mPolicyListener = new NetworkPolicyManager.Listener() {
1818 public void onUidRulesChanged(int uid, int uidRules) {
1819 mHandler.sendMessage(mHandler.obtainMessage(EVENT_UID_RULES_CHANGED, uid, uidRules));
1822 public void onRestrictBackgroundChanged(boolean restrictBackground) {
1823 // caller is NPMS, since we only register with them
1824 if (LOGD_BLOCKED_NETWORKINFO) {
1825 log("onRestrictBackgroundChanged(restrictBackground=" + restrictBackground + ")");
1827 mHandler.sendMessage(mHandler.obtainMessage(
1828 EVENT_DATA_SAVER_CHANGED, restrictBackground ? 1 : 0, 0));
1830 // TODO: relocate this specific callback in Tethering.
1831 if (restrictBackground) {
1832 log("onRestrictBackgroundChanged(true): disabling tethering");
1833 mTethering.untetherAll();
1838 void handleUidRulesChanged(int uid, int newRules) {
1839 // skip update when we've already applied rules
1840 final int oldRules = mUidRules.get(uid, RULE_NONE);
1841 if (oldRules == newRules) return;
1843 maybeNotifyNetworkBlockedForNewUidRules(uid, newRules);
1845 if (newRules == RULE_NONE) {
1846 mUidRules.delete(uid);
1848 mUidRules.put(uid, newRules);
1852 void handleRestrictBackgroundChanged(boolean restrictBackground) {
1853 if (mRestrictBackground == restrictBackground) return;
1855 for (final NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
1856 final boolean curMetered = nai.networkCapabilities.isMetered();
1857 maybeNotifyNetworkBlocked(nai, curMetered, curMetered, mRestrictBackground,
1858 restrictBackground);
1861 mRestrictBackground = restrictBackground;
1864 private boolean isUidNetworkingWithVpnBlocked(int uid, int uidRules, boolean isNetworkMetered,
1865 boolean isBackgroundRestricted) {
1866 synchronized (mVpns) {
1867 final Vpn vpn = mVpns.get(UserHandle.getUserId(uid));
1868 // Because the return value of this function depends on the list of UIDs the
1869 // always-on VPN blocks when in lockdown mode, when the always-on VPN changes that
1870 // list all state depending on the return value of this function has to be recomputed.
1871 // TODO: add a trigger when the always-on VPN sets its blocked UIDs to reevaluate and
1872 // send the necessary onBlockedStatusChanged callbacks.
1873 if (vpn != null && vpn.getLockdown() && vpn.isBlockingUid(uid)) {
1878 return mPolicyManagerInternal.isUidNetworkingBlocked(uid, uidRules,
1879 isNetworkMetered, isBackgroundRestricted);
1883 * Require that the caller is either in the same user or has appropriate permission to interact
1886 * @param userId Target user for whatever operation the current IPC is supposed to perform.
1888 private void enforceCrossUserPermission(int userId) {
1889 if (userId == UserHandle.getCallingUserId()) {
1890 // Not a cross-user call.
1893 mContext.enforceCallingOrSelfPermission(
1894 android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
1895 "ConnectivityService");
1898 private boolean checkAnyPermissionOf(String... permissions) {
1899 for (String permission : permissions) {
1900 if (mContext.checkCallingOrSelfPermission(permission) == PERMISSION_GRANTED) {
1907 private boolean checkAnyPermissionOf(int pid, int uid, String... permissions) {
1908 for (String permission : permissions) {
1909 if (mContext.checkPermission(permission, pid, uid) == PERMISSION_GRANTED) {
1916 private void enforceAnyPermissionOf(String... permissions) {
1917 if (!checkAnyPermissionOf(permissions)) {
1918 throw new SecurityException("Requires one of the following permissions: "
1919 + String.join(", ", permissions) + ".");
1923 private void enforceInternetPermission() {
1924 mContext.enforceCallingOrSelfPermission(
1925 android.Manifest.permission.INTERNET,
1926 "ConnectivityService");
1929 private void enforceAccessPermission() {
1930 mContext.enforceCallingOrSelfPermission(
1931 android.Manifest.permission.ACCESS_NETWORK_STATE,
1932 "ConnectivityService");
1935 private void enforceChangePermission() {
1936 ConnectivityManager.enforceChangePermission(mContext);
1939 private void enforceSettingsPermission() {
1940 enforceAnyPermissionOf(
1941 android.Manifest.permission.NETWORK_SETTINGS,
1942 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK);
1945 private boolean checkSettingsPermission() {
1946 return checkAnyPermissionOf(
1947 android.Manifest.permission.NETWORK_SETTINGS,
1948 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK);
1951 private boolean checkSettingsPermission(int pid, int uid) {
1952 return PERMISSION_GRANTED == mContext.checkPermission(
1953 android.Manifest.permission.NETWORK_SETTINGS, pid, uid)
1954 || PERMISSION_GRANTED == mContext.checkPermission(
1955 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, pid, uid);
1958 private void enforceTetherAccessPermission() {
1959 mContext.enforceCallingOrSelfPermission(
1960 android.Manifest.permission.ACCESS_NETWORK_STATE,
1961 "ConnectivityService");
1964 private void enforceConnectivityInternalPermission() {
1965 enforceAnyPermissionOf(
1966 android.Manifest.permission.CONNECTIVITY_INTERNAL,
1967 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK);
1970 private void enforceControlAlwaysOnVpnPermission() {
1971 mContext.enforceCallingOrSelfPermission(
1972 android.Manifest.permission.CONTROL_ALWAYS_ON_VPN,
1973 "ConnectivityService");
1976 private void enforceNetworkStackSettingsOrSetup() {
1977 enforceAnyPermissionOf(
1978 android.Manifest.permission.NETWORK_SETTINGS,
1979 android.Manifest.permission.NETWORK_SETUP_WIZARD,
1980 android.Manifest.permission.NETWORK_STACK,
1981 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK);
1984 private boolean checkNetworkStackPermission() {
1985 return checkAnyPermissionOf(
1986 android.Manifest.permission.NETWORK_STACK,
1987 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK);
1990 private boolean checkNetworkSignalStrengthWakeupPermission(int pid, int uid) {
1991 return checkAnyPermissionOf(pid, uid,
1992 android.Manifest.permission.NETWORK_SIGNAL_STRENGTH_WAKEUP,
1993 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK);
1996 private void enforceConnectivityRestrictedNetworksPermission() {
1998 mContext.enforceCallingOrSelfPermission(
1999 android.Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS,
2000 "ConnectivityService");
2002 } catch (SecurityException e) { /* fallback to ConnectivityInternalPermission */ }
2003 enforceConnectivityInternalPermission();
2006 private void enforceKeepalivePermission() {
2007 mContext.enforceCallingOrSelfPermission(KeepaliveTracker.PERMISSION, "ConnectivityService");
2010 // Public because it's used by mLockdownTracker.
2011 public void sendConnectedBroadcast(NetworkInfo info) {
2012 enforceConnectivityInternalPermission();
2013 sendGeneralBroadcast(info, CONNECTIVITY_ACTION);
2016 private void sendInetConditionBroadcast(NetworkInfo info) {
2017 sendGeneralBroadcast(info, ConnectivityManager.INET_CONDITION_ACTION);
2020 private Intent makeGeneralIntent(NetworkInfo info, String bcastType) {
2021 synchronized (mVpns) {
2022 if (mLockdownTracker != null) {
2023 info = new NetworkInfo(info);
2024 mLockdownTracker.augmentNetworkInfo(info);
2028 Intent intent = new Intent(bcastType);
2029 intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, new NetworkInfo(info));
2030 intent.putExtra(ConnectivityManager.EXTRA_NETWORK_TYPE, info.getType());
2031 if (info.isFailover()) {
2032 intent.putExtra(ConnectivityManager.EXTRA_IS_FAILOVER, true);
2033 info.setFailover(false);
2035 if (info.getReason() != null) {
2036 intent.putExtra(ConnectivityManager.EXTRA_REASON, info.getReason());
2038 if (info.getExtraInfo() != null) {
2039 intent.putExtra(ConnectivityManager.EXTRA_EXTRA_INFO,
2040 info.getExtraInfo());
2042 intent.putExtra(ConnectivityManager.EXTRA_INET_CONDITION, mDefaultInetConditionPublished);
2046 private void sendGeneralBroadcast(NetworkInfo info, String bcastType) {
2047 sendStickyBroadcast(makeGeneralIntent(info, bcastType));
2050 private void sendDataActivityBroadcast(int deviceType, boolean active, long tsNanos) {
2051 Intent intent = new Intent(ConnectivityManager.ACTION_DATA_ACTIVITY_CHANGE);
2052 intent.putExtra(ConnectivityManager.EXTRA_DEVICE_TYPE, deviceType);
2053 intent.putExtra(ConnectivityManager.EXTRA_IS_ACTIVE, active);
2054 intent.putExtra(ConnectivityManager.EXTRA_REALTIME_NS, tsNanos);
2055 final long ident = Binder.clearCallingIdentity();
2057 mContext.sendOrderedBroadcastAsUser(intent, UserHandle.ALL,
2058 RECEIVE_DATA_ACTIVITY_CHANGE, null, null, 0, null, null);
2060 Binder.restoreCallingIdentity(ident);
2064 private void sendStickyBroadcast(Intent intent) {
2065 synchronized (this) {
2067 && intent.getAction().equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
2068 mInitialBroadcast = new Intent(intent);
2070 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
2072 log("sendStickyBroadcast: action=" + intent.getAction());
2075 Bundle options = null;
2076 final long ident = Binder.clearCallingIdentity();
2077 if (ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction())) {
2078 final NetworkInfo ni = intent.getParcelableExtra(
2079 ConnectivityManager.EXTRA_NETWORK_INFO);
2080 if (ni.getType() == ConnectivityManager.TYPE_MOBILE_SUPL) {
2081 intent.setAction(ConnectivityManager.CONNECTIVITY_ACTION_SUPL);
2082 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
2084 BroadcastOptions opts = BroadcastOptions.makeBasic();
2085 opts.setMaxManifestReceiverApiLevel(Build.VERSION_CODES.M);
2086 options = opts.toBundle();
2088 final IBatteryStats bs = BatteryStatsService.getService();
2090 bs.noteConnectivityChanged(intent.getIntExtra(
2091 ConnectivityManager.EXTRA_NETWORK_TYPE, ConnectivityManager.TYPE_NONE),
2092 ni.getState().toString());
2093 } catch (RemoteException e) {
2095 intent.addFlags(Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS);
2098 mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL, options);
2100 Binder.restoreCallingIdentity(ident);
2105 void systemReady() {
2106 mProxyTracker.loadGlobalProxy();
2107 registerNetdEventCallback();
2108 mTethering.systemReady();
2110 synchronized (this) {
2111 mSystemReady = true;
2112 if (mInitialBroadcast != null) {
2113 mContext.sendStickyBroadcastAsUser(mInitialBroadcast, UserHandle.ALL);
2114 mInitialBroadcast = null;
2118 // Try bringing up tracker, but KeyStore won't be ready yet for secondary users so wait
2119 // for user to unlock device too.
2120 updateLockdownVpn();
2122 // Create network requests for always-on networks.
2123 mHandler.sendMessage(mHandler.obtainMessage(EVENT_CONFIGURE_ALWAYS_ON_NETWORKS));
2125 mHandler.sendMessage(mHandler.obtainMessage(EVENT_SYSTEM_READY));
2127 mPermissionMonitor.startMonitoring();
2131 * Setup data activity tracking for the given network.
2133 * Every {@code setupDataActivityTracking} should be paired with a
2134 * {@link #removeDataActivityTracking} for cleanup.
2136 private void setupDataActivityTracking(NetworkAgentInfo networkAgent) {
2137 final String iface = networkAgent.linkProperties.getInterfaceName();
2140 int type = ConnectivityManager.TYPE_NONE;
2142 if (networkAgent.networkCapabilities.hasTransport(
2143 NetworkCapabilities.TRANSPORT_CELLULAR)) {
2144 timeout = Settings.Global.getInt(mContext.getContentResolver(),
2145 Settings.Global.DATA_ACTIVITY_TIMEOUT_MOBILE,
2147 type = ConnectivityManager.TYPE_MOBILE;
2148 } else if (networkAgent.networkCapabilities.hasTransport(
2149 NetworkCapabilities.TRANSPORT_WIFI)) {
2150 timeout = Settings.Global.getInt(mContext.getContentResolver(),
2151 Settings.Global.DATA_ACTIVITY_TIMEOUT_WIFI,
2153 type = ConnectivityManager.TYPE_WIFI;
2155 // do not track any other networks
2159 if (timeout > 0 && iface != null && type != ConnectivityManager.TYPE_NONE) {
2161 mNMS.addIdleTimer(iface, timeout, type);
2162 } catch (Exception e) {
2163 // You shall not crash!
2164 loge("Exception in setupDataActivityTracking " + e);
2170 * Remove data activity tracking when network disconnects.
2172 private void removeDataActivityTracking(NetworkAgentInfo networkAgent) {
2173 final String iface = networkAgent.linkProperties.getInterfaceName();
2174 final NetworkCapabilities caps = networkAgent.networkCapabilities;
2176 if (iface != null && (caps.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) ||
2177 caps.hasTransport(NetworkCapabilities.TRANSPORT_WIFI))) {
2179 // the call fails silently if no idle timer setup for this interface
2180 mNMS.removeIdleTimer(iface);
2181 } catch (Exception e) {
2182 loge("Exception in removeDataActivityTracking " + e);
2188 * Update data activity tracking when network state is updated.
2190 private void updateDataActivityTracking(NetworkAgentInfo newNetwork,
2191 NetworkAgentInfo oldNetwork) {
2192 if (newNetwork != null) {
2193 setupDataActivityTracking(newNetwork);
2195 if (oldNetwork != null) {
2196 removeDataActivityTracking(oldNetwork);
2200 * Reads the network specific MTU size from resources.
2201 * and set it on it's iface.
2203 private void updateMtu(LinkProperties newLp, LinkProperties oldLp) {
2204 final String iface = newLp.getInterfaceName();
2205 final int mtu = newLp.getMtu();
2206 if (oldLp == null && mtu == 0) {
2207 // Silently ignore unset MTU value.
2210 if (oldLp != null && newLp.isIdenticalMtu(oldLp)) {
2211 if (VDBG) log("identical MTU - not setting");
2214 if (!LinkProperties.isValidMtu(mtu, newLp.hasGlobalIpv6Address())) {
2215 if (mtu != 0) loge("Unexpected mtu value: " + mtu + ", " + iface);
2219 // Cannot set MTU without interface name
2220 if (TextUtils.isEmpty(iface)) {
2221 loge("Setting MTU size with null iface.");
2226 if (VDBG || DDBG) log("Setting MTU size: " + iface + ", " + mtu);
2227 mNMS.setMtu(iface, mtu);
2228 } catch (Exception e) {
2229 Slog.e(TAG, "exception in setMtu()" + e);
2234 protected static final String DEFAULT_TCP_BUFFER_SIZES = "4096,87380,110208,4096,16384,110208";
2235 private static final String DEFAULT_TCP_RWND_KEY = "net.tcp.default_init_rwnd";
2237 // Overridden for testing purposes to avoid writing to SystemProperties.
2239 protected MockableSystemProperties getSystemProperties() {
2240 return new MockableSystemProperties();
2243 private void updateTcpBufferSizes(String tcpBufferSizes) {
2244 String[] values = null;
2245 if (tcpBufferSizes != null) {
2246 values = tcpBufferSizes.split(",");
2249 if (values == null || values.length != 6) {
2250 if (DBG) log("Invalid tcpBufferSizes string: " + tcpBufferSizes +", using defaults");
2251 tcpBufferSizes = DEFAULT_TCP_BUFFER_SIZES;
2252 values = tcpBufferSizes.split(",");
2255 if (tcpBufferSizes.equals(mCurrentTcpBufferSizes)) return;
2258 if (VDBG || DDBG) Slog.d(TAG, "Setting tx/rx TCP buffers to " + tcpBufferSizes);
2260 String rmemValues = String.join(" ", values[0], values[1], values[2]);
2261 String wmemValues = String.join(" ", values[3], values[4], values[5]);
2262 mNetd.setTcpRWmemorySize(rmemValues, wmemValues);
2263 mCurrentTcpBufferSizes = tcpBufferSizes;
2264 } catch (RemoteException | ServiceSpecificException e) {
2265 loge("Can't set TCP buffer sizes:" + e);
2268 Integer rwndValue = Settings.Global.getInt(mContext.getContentResolver(),
2269 Settings.Global.TCP_DEFAULT_INIT_RWND,
2270 mSystemProperties.getInt("net.tcp.default_init_rwnd", 0));
2271 final String sysctlKey = "sys.sysctl.tcp_def_init_rwnd";
2272 if (rwndValue != 0) {
2273 mSystemProperties.set(sysctlKey, rwndValue.toString());
2278 public int getRestoreDefaultNetworkDelay(int networkType) {
2279 String restoreDefaultNetworkDelayStr = mSystemProperties.get(
2280 NETWORK_RESTORE_DELAY_PROP_NAME);
2281 if(restoreDefaultNetworkDelayStr != null &&
2282 restoreDefaultNetworkDelayStr.length() != 0) {
2284 return Integer.parseInt(restoreDefaultNetworkDelayStr);
2285 } catch (NumberFormatException e) {
2288 // if the system property isn't set, use the value for the apn type
2289 int ret = RESTORE_DEFAULT_NETWORK_DELAY;
2291 if ((networkType <= ConnectivityManager.MAX_NETWORK_TYPE) &&
2292 (mNetConfigs[networkType] != null)) {
2293 ret = mNetConfigs[networkType].restoreTime;
2298 private void dumpNetworkDiagnostics(IndentingPrintWriter pw) {
2299 final List<NetworkDiagnostics> netDiags = new ArrayList<NetworkDiagnostics>();
2300 final long DIAG_TIME_MS = 5000;
2301 for (NetworkAgentInfo nai : networksSortedById()) {
2302 // Start gathering diagnostic information.
2303 netDiags.add(new NetworkDiagnostics(
2305 new LinkProperties(nai.linkProperties), // Must be a copy.
2309 for (NetworkDiagnostics netDiag : netDiags) {
2311 netDiag.waitForMeasurements();
2317 protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
2318 PriorityDump.dump(mPriorityDumper, fd, writer, args);
2321 private void doDump(FileDescriptor fd, PrintWriter writer, String[] args, boolean asProto) {
2322 final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " ");
2323 if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
2324 if (asProto) return;
2326 if (ArrayUtils.contains(args, DIAG_ARG)) {
2327 dumpNetworkDiagnostics(pw);
2329 } else if (ArrayUtils.contains(args, TETHERING_ARG)) {
2330 mTethering.dump(fd, pw, args);
2332 } else if (ArrayUtils.contains(args, NETWORK_ARG)) {
2335 } else if (ArrayUtils.contains(args, REQUEST_ARG)) {
2336 dumpNetworkRequests(pw);
2340 pw.print("NetworkFactories for:");
2341 for (NetworkFactoryInfo nfi : mNetworkFactoryInfos.values()) {
2342 pw.print(" " + nfi.name);
2347 final NetworkAgentInfo defaultNai = getDefaultNetwork();
2348 pw.print("Active default network: ");
2349 if (defaultNai == null) {
2352 pw.println(defaultNai.network.netId);
2356 pw.println("Current Networks:");
2357 pw.increaseIndent();
2359 pw.decreaseIndent();
2362 pw.print("Restrict background: ");
2363 pw.println(mRestrictBackground);
2366 pw.println("Status for known UIDs:");
2367 pw.increaseIndent();
2368 final int size = mUidRules.size();
2369 for (int i = 0; i < size; i++) {
2370 // Don't crash if the array is modified while dumping in bugreports.
2372 final int uid = mUidRules.keyAt(i);
2373 final int uidRules = mUidRules.get(uid, RULE_NONE);
2374 pw.println("UID=" + uid + " rules=" + uidRulesToString(uidRules));
2375 } catch (ArrayIndexOutOfBoundsException e) {
2376 pw.println(" ArrayIndexOutOfBoundsException");
2377 } catch (ConcurrentModificationException e) {
2378 pw.println(" ConcurrentModificationException");
2382 pw.decreaseIndent();
2384 pw.println("Network Requests:");
2385 pw.increaseIndent();
2386 dumpNetworkRequests(pw);
2387 pw.decreaseIndent();
2390 mLegacyTypeTracker.dump(pw);
2393 mTethering.dump(fd, pw, args);
2396 mKeepaliveTracker.dump(pw);
2399 dumpAvoidBadWifiSettings(pw);
2402 mMultipathPolicyTracker.dump(pw);
2404 if (ArrayUtils.contains(args, SHORT_ARG) == false) {
2406 pw.println("mNetworkRequestInfoLogs (most recent first):");
2407 pw.increaseIndent();
2408 mNetworkRequestInfoLogs.reverseDump(fd, pw, args);
2409 pw.decreaseIndent();
2412 pw.println("mNetworkInfoBlockingLogs (most recent first):");
2413 pw.increaseIndent();
2414 mNetworkInfoBlockingLogs.reverseDump(fd, pw, args);
2415 pw.decreaseIndent();
2418 pw.println("NetTransition WakeLock activity (most recent first):");
2419 pw.increaseIndent();
2420 pw.println("total acquisitions: " + mTotalWakelockAcquisitions);
2421 pw.println("total releases: " + mTotalWakelockReleases);
2422 pw.println("cumulative duration: " + (mTotalWakelockDurationMs / 1000) + "s");
2423 pw.println("longest duration: " + (mMaxWakelockDurationMs / 1000) + "s");
2424 if (mTotalWakelockAcquisitions > mTotalWakelockReleases) {
2425 long duration = SystemClock.elapsedRealtime() - mLastWakeLockAcquireTimestamp;
2426 pw.println("currently holding WakeLock for: " + (duration / 1000) + "s");
2428 mWakelockLogs.reverseDump(fd, pw, args);
2431 pw.println("bandwidth update requests (by uid):");
2432 pw.increaseIndent();
2433 synchronized (mBandwidthRequests) {
2434 for (int i = 0; i < mBandwidthRequests.size(); i++) {
2435 pw.println("[" + mBandwidthRequests.keyAt(i)
2436 + "]: " + mBandwidthRequests.valueAt(i));
2439 pw.decreaseIndent();
2441 pw.decreaseIndent();
2445 pw.println("NetworkStackClient logs:");
2446 pw.increaseIndent();
2447 NetworkStackClient.getInstance().dump(pw);
2448 pw.decreaseIndent();
2451 pw.println("Permission Monitor:");
2452 pw.increaseIndent();
2453 mPermissionMonitor.dump(pw);
2454 pw.decreaseIndent();
2457 private void dumpNetworks(IndentingPrintWriter pw) {
2458 for (NetworkAgentInfo nai : networksSortedById()) {
2459 pw.println(nai.toString());
2460 pw.increaseIndent();
2461 pw.println(String.format(
2462 "Requests: REQUEST:%d LISTEN:%d BACKGROUND_REQUEST:%d total:%d",
2463 nai.numForegroundNetworkRequests(),
2464 nai.numNetworkRequests() - nai.numRequestNetworkRequests(),
2465 nai.numBackgroundNetworkRequests(),
2466 nai.numNetworkRequests()));
2467 pw.increaseIndent();
2468 for (int i = 0; i < nai.numNetworkRequests(); i++) {
2469 pw.println(nai.requestAt(i).toString());
2471 pw.decreaseIndent();
2472 pw.println("Lingered:");
2473 pw.increaseIndent();
2474 nai.dumpLingerTimers(pw);
2475 pw.decreaseIndent();
2476 pw.decreaseIndent();
2480 private void dumpNetworkRequests(IndentingPrintWriter pw) {
2481 for (NetworkRequestInfo nri : requestsSortedById()) {
2482 pw.println(nri.toString());
2487 * Return an array of all current NetworkAgentInfos sorted by network id.
2489 private NetworkAgentInfo[] networksSortedById() {
2490 NetworkAgentInfo[] networks = new NetworkAgentInfo[0];
2491 networks = mNetworkAgentInfos.values().toArray(networks);
2492 Arrays.sort(networks, Comparator.comparingInt(nai -> nai.network.netId));
2497 * Return an array of all current NetworkRequest sorted by request id.
2499 private NetworkRequestInfo[] requestsSortedById() {
2500 NetworkRequestInfo[] requests = new NetworkRequestInfo[0];
2501 requests = mNetworkRequests.values().toArray(requests);
2502 Arrays.sort(requests, Comparator.comparingInt(nri -> nri.request.requestId));
2506 private boolean isLiveNetworkAgent(NetworkAgentInfo nai, int what) {
2507 if (nai.network == null) return false;
2508 final NetworkAgentInfo officialNai = getNetworkAgentInfoForNetwork(nai.network);
2509 if (officialNai != null && officialNai.equals(nai)) return true;
2510 if (officialNai != null || VDBG) {
2511 loge(eventName(what) + " - isLiveNetworkAgent found mismatched netId: " + officialNai +
2517 // must be stateless - things change under us.
2518 private class NetworkStateTrackerHandler extends Handler {
2519 public NetworkStateTrackerHandler(Looper looper) {
2523 private boolean maybeHandleAsyncChannelMessage(Message msg) {
2527 case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: {
2528 handleAsyncChannelHalfConnect(msg);
2531 case AsyncChannel.CMD_CHANNEL_DISCONNECT: {
2532 NetworkAgentInfo nai = mNetworkAgentInfos.get(msg.replyTo);
2533 if (nai != null) nai.asyncChannel.disconnect();
2536 case AsyncChannel.CMD_CHANNEL_DISCONNECTED: {
2537 handleAsyncChannelDisconnected(msg);
2544 private void maybeHandleNetworkAgentMessage(Message msg) {
2545 NetworkAgentInfo nai = mNetworkAgentInfos.get(msg.replyTo);
2548 log(String.format("%s from unknown NetworkAgent", eventName(msg.what)));
2554 case NetworkAgent.EVENT_NETWORK_CAPABILITIES_CHANGED: {
2555 final NetworkCapabilities networkCapabilities = (NetworkCapabilities) msg.obj;
2556 if (networkCapabilities.hasConnectivityManagedCapability()) {
2557 Slog.wtf(TAG, "BUG: " + nai + " has CS-managed capability.");
2559 updateCapabilities(nai.getCurrentScore(), nai, networkCapabilities);
2562 case NetworkAgent.EVENT_NETWORK_PROPERTIES_CHANGED: {
2563 handleUpdateLinkProperties(nai, (LinkProperties) msg.obj);
2566 case NetworkAgent.EVENT_NETWORK_INFO_CHANGED: {
2567 NetworkInfo info = (NetworkInfo) msg.obj;
2568 updateNetworkInfo(nai, info);
2571 case NetworkAgent.EVENT_NETWORK_SCORE_CHANGED: {
2572 updateNetworkScore(nai, msg.arg1);
2575 case NetworkAgent.EVENT_SET_EXPLICITLY_SELECTED: {
2576 if (nai.everConnected && !nai.networkMisc.explicitlySelected) {
2577 loge("ERROR: already-connected network explicitly selected.");
2579 nai.networkMisc.explicitlySelected = true;
2580 nai.networkMisc.acceptUnvalidated = msg.arg1 == 1;
2581 // Mark the network as temporarily accepting partial connectivity so that it
2582 // will be validated (and possibly become default) even if it only provides
2583 // partial internet access. Note that if user connects to partial connectivity
2584 // and choose "don't ask again", then wifi disconnected by some reasons(maybe
2585 // out of wifi coverage) and if the same wifi is available again, the device
2586 // will auto connect to this wifi even though the wifi has "no internet".
2587 // TODO: Evaluate using a separate setting in IpMemoryStore.
2588 nai.networkMisc.acceptPartialConnectivity = msg.arg1 == 1;
2591 case NetworkAgent.EVENT_SOCKET_KEEPALIVE: {
2592 mKeepaliveTracker.handleEventSocketKeepalive(nai, msg);
2598 private boolean maybeHandleNetworkMonitorMessage(Message msg) {
2602 case EVENT_NETWORK_TESTED: {
2603 final NetworkAgentInfo nai = getNetworkAgentInfoForNetId(msg.arg2);
2604 if (nai == null) break;
2606 final boolean partialConnectivity =
2607 (msg.arg1 == NETWORK_TEST_RESULT_PARTIAL_CONNECTIVITY)
2608 || (nai.networkMisc.acceptPartialConnectivity
2609 && nai.partialConnectivity);
2610 // Once a network is determined to have partial connectivity, it cannot
2611 // go back to full connectivity without a disconnect. This is because
2612 // NetworkMonitor can only communicate either PARTIAL_CONNECTIVITY or VALID,
2614 // TODO: Provide multi-testResult to improve the communication between
2615 // ConnectivityService and NetworkMonitor, so that ConnectivityService could
2616 // know the real status of network.
2617 final boolean partialConnectivityChanged =
2618 (partialConnectivity && !nai.partialConnectivity);
2620 final boolean valid = (msg.arg1 == NETWORK_TEST_RESULT_VALID);
2621 final boolean wasValidated = nai.lastValidated;
2622 final boolean wasDefault = isDefaultNetwork(nai);
2623 if (nai.everCaptivePortalDetected && !nai.captivePortalLoginNotified
2625 nai.captivePortalLoginNotified = true;
2626 showNetworkNotification(nai, NotificationType.LOGGED_IN);
2629 final String redirectUrl = (msg.obj instanceof String) ? (String) msg.obj : "";
2632 final String logMsg = !TextUtils.isEmpty(redirectUrl)
2633 ? " with redirect to " + redirectUrl
2635 log(nai.name() + " validation " + (valid ? "passed" : "failed") + logMsg);
2637 if (valid != nai.lastValidated) {
2639 metricsLogger().defaultNetworkMetrics().logDefaultNetworkValidity(
2640 SystemClock.elapsedRealtime(), valid);
2642 final int oldScore = nai.getCurrentScore();
2643 nai.lastValidated = valid;
2644 nai.everValidated |= valid;
2645 updateCapabilities(oldScore, nai, nai.networkCapabilities);
2646 // If score has changed, rebroadcast to NetworkFactories. b/17726566
2647 if (oldScore != nai.getCurrentScore()) sendUpdatedScoreToFactories(nai);
2649 handleFreshlyValidatedNetwork(nai);
2650 // Clear NO_INTERNET and LOST_INTERNET notifications if network becomes
2652 mNotifier.clearNotification(nai.network.netId,
2653 NotificationType.NO_INTERNET);
2654 mNotifier.clearNotification(nai.network.netId,
2655 NotificationType.LOST_INTERNET);
2657 } else if (partialConnectivityChanged) {
2658 nai.partialConnectivity = partialConnectivity;
2659 updateCapabilities(nai.getCurrentScore(), nai, nai.networkCapabilities);
2661 updateInetCondition(nai);
2662 // Let the NetworkAgent know the state of its network
2663 Bundle redirectUrlBundle = new Bundle();
2664 redirectUrlBundle.putString(NetworkAgent.REDIRECT_URL_KEY, redirectUrl);
2665 nai.asyncChannel.sendMessage(
2666 NetworkAgent.CMD_REPORT_NETWORK_STATUS,
2667 (valid ? NetworkAgent.VALID_NETWORK : NetworkAgent.INVALID_NETWORK),
2668 0, redirectUrlBundle);
2669 if (wasValidated && !nai.lastValidated) {
2670 handleNetworkUnvalidated(nai);
2674 case EVENT_PROVISIONING_NOTIFICATION: {
2675 final int netId = msg.arg2;
2676 final boolean visible = toBool(msg.arg1);
2677 final NetworkAgentInfo nai = getNetworkAgentInfoForNetId(netId);
2678 // If captive portal status has changed, update capabilities or disconnect.
2679 if (nai != null && (visible != nai.lastCaptivePortalDetected)) {
2680 final int oldScore = nai.getCurrentScore();
2681 nai.lastCaptivePortalDetected = visible;
2682 nai.everCaptivePortalDetected |= visible;
2684 nai.captivePortalLoginNotified = false;
2686 if (nai.lastCaptivePortalDetected &&
2687 Settings.Global.CAPTIVE_PORTAL_MODE_AVOID == getCaptivePortalMode()) {
2688 if (DBG) log("Avoiding captive portal network: " + nai.name());
2689 nai.asyncChannel.sendMessage(
2690 NetworkAgent.CMD_PREVENT_AUTOMATIC_RECONNECT);
2691 teardownUnneededNetwork(nai);
2694 updateCapabilities(oldScore, nai, nai.networkCapabilities);
2697 // Only clear SIGN_IN and NETWORK_SWITCH notifications here, or else other
2698 // notifications belong to the same network may be cleared unexpectedly.
2699 mNotifier.clearNotification(netId, NotificationType.SIGN_IN);
2700 mNotifier.clearNotification(netId, NotificationType.NETWORK_SWITCH);
2703 loge("EVENT_PROVISIONING_NOTIFICATION from unknown NetworkMonitor");
2706 if (!nai.networkMisc.provisioningNotificationDisabled) {
2707 mNotifier.showNotification(netId, NotificationType.SIGN_IN, nai, null,
2708 (PendingIntent) msg.obj, nai.networkMisc.explicitlySelected);
2713 case EVENT_PRIVATE_DNS_CONFIG_RESOLVED: {
2714 final NetworkAgentInfo nai = getNetworkAgentInfoForNetId(msg.arg2);
2715 if (nai == null) break;
2717 updatePrivateDns(nai, (PrivateDnsConfig) msg.obj);
2724 private int getCaptivePortalMode() {
2725 return Settings.Global.getInt(mContext.getContentResolver(),
2726 Settings.Global.CAPTIVE_PORTAL_MODE,
2727 Settings.Global.CAPTIVE_PORTAL_MODE_PROMPT);
2730 private boolean maybeHandleNetworkAgentInfoMessage(Message msg) {
2734 case NetworkAgentInfo.EVENT_NETWORK_LINGER_COMPLETE: {
2735 NetworkAgentInfo nai = (NetworkAgentInfo) msg.obj;
2736 if (nai != null && isLiveNetworkAgent(nai, msg.what)) {
2737 handleLingerComplete(nai);
2745 private boolean maybeHandleNetworkFactoryMessage(Message msg) {
2749 case android.net.NetworkFactory.EVENT_UNFULFILLABLE_REQUEST: {
2750 handleReleaseNetworkRequest((NetworkRequest) msg.obj, msg.sendingUid,
2751 /* callOnUnavailable */ true);
2759 public void handleMessage(Message msg) {
2760 if (!maybeHandleAsyncChannelMessage(msg)
2761 && !maybeHandleNetworkMonitorMessage(msg)
2762 && !maybeHandleNetworkAgentInfoMessage(msg)
2763 && !maybeHandleNetworkFactoryMessage(msg)) {
2764 maybeHandleNetworkAgentMessage(msg);
2769 private class NetworkMonitorCallbacks extends INetworkMonitorCallbacks.Stub {
2770 private final NetworkAgentInfo mNai;
2772 private NetworkMonitorCallbacks(NetworkAgentInfo nai) {
2777 public void onNetworkMonitorCreated(INetworkMonitor networkMonitor) {
2778 mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_AGENT,
2779 new Pair<>(mNai, networkMonitor)));
2783 public void notifyNetworkTested(int testResult, @Nullable String redirectUrl) {
2784 mTrackerHandler.sendMessage(mTrackerHandler.obtainMessage(EVENT_NETWORK_TESTED,
2785 testResult, mNai.network.netId, redirectUrl));
2789 public void notifyPrivateDnsConfigResolved(PrivateDnsConfigParcel config) {
2790 mTrackerHandler.sendMessage(mTrackerHandler.obtainMessage(
2791 EVENT_PRIVATE_DNS_CONFIG_RESOLVED,
2792 0, mNai.network.netId, PrivateDnsConfig.fromParcel(config)));
2796 public void showProvisioningNotification(String action, String packageName) {
2797 final Intent intent = new Intent(action);
2798 intent.setPackage(packageName);
2800 final PendingIntent pendingIntent;
2801 // Only the system server can register notifications with package "android"
2802 final long token = Binder.clearCallingIdentity();
2804 pendingIntent = PendingIntent.getBroadcast(mContext, 0, intent, 0);
2806 Binder.restoreCallingIdentity(token);
2808 mTrackerHandler.sendMessage(mTrackerHandler.obtainMessage(
2809 EVENT_PROVISIONING_NOTIFICATION, PROVISIONING_NOTIFICATION_SHOW,
2815 public void hideProvisioningNotification() {
2816 mTrackerHandler.sendMessage(mTrackerHandler.obtainMessage(
2817 EVENT_PROVISIONING_NOTIFICATION, PROVISIONING_NOTIFICATION_HIDE,
2818 mNai.network.netId));
2822 public int getInterfaceVersion() {
2823 return this.VERSION;
2827 private boolean networkRequiresPrivateDnsValidation(NetworkAgentInfo nai) {
2828 return isPrivateDnsValidationRequired(nai.networkCapabilities);
2831 private void handleFreshlyValidatedNetwork(NetworkAgentInfo nai) {
2832 if (nai == null) return;
2833 // If the Private DNS mode is opportunistic, reprogram the DNS servers
2834 // in order to restart a validation pass from within netd.
2835 final PrivateDnsConfig cfg = mDnsManager.getPrivateDnsConfig();
2836 if (cfg.useTls && TextUtils.isEmpty(cfg.hostname)) {
2837 updateDnses(nai.linkProperties, null, nai.network.netId);
2841 private void handlePrivateDnsSettingsChanged() {
2842 final PrivateDnsConfig cfg = mDnsManager.getPrivateDnsConfig();
2844 for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
2845 handlePerNetworkPrivateDnsConfig(nai, cfg);
2846 if (networkRequiresPrivateDnsValidation(nai)) {
2847 handleUpdateLinkProperties(nai, new LinkProperties(nai.linkProperties));
2852 private void handlePerNetworkPrivateDnsConfig(NetworkAgentInfo nai, PrivateDnsConfig cfg) {
2853 // Private DNS only ever applies to networks that might provide
2854 // Internet access and therefore also require validation.
2855 if (!networkRequiresPrivateDnsValidation(nai)) return;
2857 // Notify the NetworkAgentInfo/NetworkMonitor in case NetworkMonitor needs to cancel or
2858 // schedule DNS resolutions. If a DNS resolution is required the
2859 // result will be sent back to us.
2861 nai.networkMonitor().notifyPrivateDnsChanged(cfg.toParcel());
2862 } catch (RemoteException e) {
2863 e.rethrowAsRuntimeException();
2866 // With Private DNS bypass support, we can proceed to update the
2867 // Private DNS config immediately, even if we're in strict mode
2868 // and have not yet resolved the provider name into a set of IPs.
2869 updatePrivateDns(nai, cfg);
2872 private void updatePrivateDns(NetworkAgentInfo nai, PrivateDnsConfig newCfg) {
2873 mDnsManager.updatePrivateDns(nai.network, newCfg);
2874 updateDnses(nai.linkProperties, null, nai.network.netId);
2877 private void handlePrivateDnsValidationUpdate(PrivateDnsValidationUpdate update) {
2878 NetworkAgentInfo nai = getNetworkAgentInfoForNetId(update.netId);
2882 mDnsManager.updatePrivateDnsValidation(update);
2883 handleUpdateLinkProperties(nai, new LinkProperties(nai.linkProperties));
2886 private void handleNat64PrefixEvent(int netId, boolean added, String prefixString,
2888 NetworkAgentInfo nai = mNetworkForNetId.get(netId);
2889 if (nai == null) return;
2891 log(String.format("NAT64 prefix %s on netId %d: %s/%d",
2892 (added ? "added" : "removed"), netId, prefixString, prefixLength));
2894 IpPrefix prefix = null;
2897 prefix = new IpPrefix(InetAddresses.parseNumericAddress(prefixString),
2899 } catch (IllegalArgumentException e) {
2900 loge("Invalid NAT64 prefix " + prefixString + "/" + prefixLength);
2905 nai.clatd.setNat64Prefix(prefix);
2906 handleUpdateLinkProperties(nai, new LinkProperties(nai.linkProperties));
2909 private void updateLingerState(NetworkAgentInfo nai, long now) {
2910 // 1. Update the linger timer. If it's changed, reschedule or cancel the alarm.
2911 // 2. If the network was lingering and there are now requests, unlinger it.
2912 // 3. If this network is unneeded (which implies it is not lingering), and there is at least
2913 // one lingered request, start lingering.
2914 nai.updateLingerTimer();
2915 if (nai.isLingering() && nai.numForegroundNetworkRequests() > 0) {
2916 if (DBG) log("Unlingering " + nai.name());
2918 logNetworkEvent(nai, NetworkEvent.NETWORK_UNLINGER);
2919 } else if (unneeded(nai, UnneededFor.LINGER) && nai.getLingerExpiry() > 0) {
2920 int lingerTime = (int) (nai.getLingerExpiry() - now);
2921 if (DBG) log("Lingering " + nai.name() + " for " + lingerTime + "ms");
2923 logNetworkEvent(nai, NetworkEvent.NETWORK_LINGER);
2924 notifyNetworkCallbacks(nai, ConnectivityManager.CALLBACK_LOSING, lingerTime);
2928 private void handleAsyncChannelHalfConnect(Message msg) {
2929 AsyncChannel ac = (AsyncChannel) msg.obj;
2930 if (mNetworkFactoryInfos.containsKey(msg.replyTo)) {
2931 if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
2932 if (VDBG) log("NetworkFactory connected");
2933 // Finish setting up the full connection
2934 mNetworkFactoryInfos.get(msg.replyTo).asyncChannel.sendMessage(
2935 AsyncChannel.CMD_CHANNEL_FULL_CONNECTION);
2936 // A network factory has connected. Send it all current NetworkRequests.
2937 for (NetworkRequestInfo nri : mNetworkRequests.values()) {
2938 if (nri.request.isListen()) continue;
2939 NetworkAgentInfo nai = getNetworkForRequest(nri.request.requestId);
2943 score = nai.getCurrentScore();
2944 serial = nai.factorySerialNumber;
2947 serial = NetworkFactory.SerialNumber.NONE;
2949 ac.sendMessage(android.net.NetworkFactory.CMD_REQUEST_NETWORK, score, serial,
2953 loge("Error connecting NetworkFactory");
2954 mNetworkFactoryInfos.remove(msg.obj);
2956 } else if (mNetworkAgentInfos.containsKey(msg.replyTo)) {
2957 if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
2958 if (VDBG) log("NetworkAgent connected");
2959 // A network agent has requested a connection. Establish the connection.
2960 mNetworkAgentInfos.get(msg.replyTo).asyncChannel.
2961 sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION);
2963 loge("Error connecting NetworkAgent");
2964 NetworkAgentInfo nai = mNetworkAgentInfos.remove(msg.replyTo);
2966 final boolean wasDefault = isDefaultNetwork(nai);
2967 synchronized (mNetworkForNetId) {
2968 mNetworkForNetId.remove(nai.network.netId);
2969 mNetIdInUse.delete(nai.network.netId);
2972 mLegacyTypeTracker.remove(nai, wasDefault);
2978 // This is a no-op if it's called with a message designating a network that has
2979 // already been destroyed, because its reference will not be found in the relevant
2981 private void handleAsyncChannelDisconnected(Message msg) {
2982 NetworkAgentInfo nai = mNetworkAgentInfos.get(msg.replyTo);
2984 disconnectAndDestroyNetwork(nai);
2986 NetworkFactoryInfo nfi = mNetworkFactoryInfos.remove(msg.replyTo);
2987 if (DBG && nfi != null) log("unregisterNetworkFactory for " + nfi.name);
2991 // Destroys a network, remove references to it from the internal state managed by
2992 // ConnectivityService, free its interfaces and clean up.
2993 // Must be called on the Handler thread.
2994 private void disconnectAndDestroyNetwork(NetworkAgentInfo nai) {
2996 log(nai.name() + " got DISCONNECTED, was satisfying " + nai.numNetworkRequests());
2998 // Clear all notifications of this network.
2999 mNotifier.clearNotification(nai.network.netId);
3000 // A network agent has disconnected.
3001 // TODO - if we move the logic to the network agent (have them disconnect
3002 // because they lost all their requests or because their score isn't good)
3003 // then they would disconnect organically, report their new state and then
3004 // disconnect the channel.
3005 if (nai.networkInfo.isConnected()) {
3006 nai.networkInfo.setDetailedState(NetworkInfo.DetailedState.DISCONNECTED,
3009 final boolean wasDefault = isDefaultNetwork(nai);
3011 mDefaultInetConditionPublished = 0;
3012 // Log default network disconnection before required book-keeping.
3013 // Let rematchAllNetworksAndRequests() below record a new default network event
3014 // if there is a fallback. Taken together, the two form a X -> 0, 0 -> Y sequence
3015 // whose timestamps tell how long it takes to recover a default network.
3016 long now = SystemClock.elapsedRealtime();
3017 metricsLogger().defaultNetworkMetrics().logDefaultNetworkEvent(now, null, nai);
3019 notifyIfacesChangedForNetworkStats();
3020 // TODO - we shouldn't send CALLBACK_LOST to requests that can be satisfied
3021 // by other networks that are already connected. Perhaps that can be done by
3022 // sending all CALLBACK_LOST messages (for requests, not listens) at the end
3023 // of rematchAllNetworksAndRequests
3024 notifyNetworkCallbacks(nai, ConnectivityManager.CALLBACK_LOST);
3025 mKeepaliveTracker.handleStopAllKeepalives(nai, SocketKeepalive.ERROR_INVALID_NETWORK);
3026 for (String iface : nai.linkProperties.getAllInterfaceNames()) {
3027 // Disable wakeup packet monitoring for each interface.
3028 wakeupModifyInterface(iface, nai.networkCapabilities, false);
3031 nai.networkMonitor().notifyNetworkDisconnected();
3032 } catch (RemoteException e) {
3033 e.rethrowAsRuntimeException();
3035 mNetworkAgentInfos.remove(nai.messenger);
3037 synchronized (mNetworkForNetId) {
3038 // Remove the NetworkAgent, but don't mark the netId as
3039 // available until we've told netd to delete it below.
3040 mNetworkForNetId.remove(nai.network.netId);
3042 // Remove all previously satisfied requests.
3043 for (int i = 0; i < nai.numNetworkRequests(); i++) {
3044 NetworkRequest request = nai.requestAt(i);
3045 NetworkAgentInfo currentNetwork = getNetworkForRequest(request.requestId);
3046 if (currentNetwork != null && currentNetwork.network.netId == nai.network.netId) {
3047 clearNetworkForRequest(request.requestId);
3048 sendUpdatedScoreToFactories(request, null);
3051 nai.clearLingerState();
3052 if (nai.isSatisfyingRequest(mDefaultRequest.requestId)) {
3053 updateDataActivityTracking(null /* newNetwork */, nai);
3054 notifyLockdownVpn(nai);
3055 ensureNetworkTransitionWakelock(nai.name());
3057 mLegacyTypeTracker.remove(nai, wasDefault);
3058 if (!nai.networkCapabilities.hasTransport(TRANSPORT_VPN)) {
3059 updateAllVpnsCapabilities();
3061 rematchAllNetworksAndRequests(null, 0);
3062 mLingerMonitor.noteDisconnect(nai);
3064 // Tell netd to clean up the configuration for this network
3065 // (routing rules, DNS, etc).
3066 // This may be slow as it requires a lot of netd shelling out to ip and
3067 // ip[6]tables to flush routes and remove the incoming packet mark rule, so do it
3068 // after we've rematched networks with requests which should make a potential
3069 // fallback network the default or requested a new network from the
3070 // NetworkFactories, so network traffic isn't interrupted for an unnecessarily
3072 destroyNativeNetwork(nai);
3073 mDnsManager.removeNetwork(nai.network);
3075 synchronized (mNetworkForNetId) {
3076 mNetIdInUse.delete(nai.network.netId);
3080 private boolean createNativeNetwork(@NonNull NetworkAgentInfo networkAgent) {
3082 // This should never fail. Specifying an already in use NetID will cause failure.
3083 if (networkAgent.isVPN()) {
3084 mNetd.networkCreateVpn(networkAgent.network.netId,
3085 (networkAgent.networkMisc == null
3086 || !networkAgent.networkMisc.allowBypass));
3088 mNetd.networkCreatePhysical(networkAgent.network.netId,
3089 getNetworkPermission(networkAgent.networkCapabilities));
3091 mDnsResolver.createNetworkCache(networkAgent.network.netId);
3093 } catch (RemoteException | ServiceSpecificException e) {
3094 loge("Error creating network " + networkAgent.network.netId + ": "
3100 private void destroyNativeNetwork(@NonNull NetworkAgentInfo networkAgent) {
3102 mNetd.networkDestroy(networkAgent.network.netId);
3103 mDnsResolver.destroyNetworkCache(networkAgent.network.netId);
3104 } catch (RemoteException | ServiceSpecificException e) {
3105 loge("Exception destroying network: " + e);
3109 // If this method proves to be too slow then we can maintain a separate
3110 // pendingIntent => NetworkRequestInfo map.
3111 // This method assumes that every non-null PendingIntent maps to exactly 1 NetworkRequestInfo.
3112 private NetworkRequestInfo findExistingNetworkRequestInfo(PendingIntent pendingIntent) {
3113 Intent intent = pendingIntent.getIntent();
3114 for (Map.Entry<NetworkRequest, NetworkRequestInfo> entry : mNetworkRequests.entrySet()) {
3115 PendingIntent existingPendingIntent = entry.getValue().mPendingIntent;
3116 if (existingPendingIntent != null &&
3117 existingPendingIntent.getIntent().filterEquals(intent)) {
3118 return entry.getValue();
3124 private void handleRegisterNetworkRequestWithIntent(Message msg) {
3125 final NetworkRequestInfo nri = (NetworkRequestInfo) (msg.obj);
3127 NetworkRequestInfo existingRequest = findExistingNetworkRequestInfo(nri.mPendingIntent);
3128 if (existingRequest != null) { // remove the existing request.
3129 if (DBG) log("Replacing " + existingRequest.request + " with "
3130 + nri.request + " because their intents matched.");
3131 handleReleaseNetworkRequest(existingRequest.request, getCallingUid(),
3132 /* callOnUnavailable */ false);
3134 handleRegisterNetworkRequest(nri);
3137 private void handleRegisterNetworkRequest(NetworkRequestInfo nri) {
3138 mNetworkRequests.put(nri.request, nri);
3139 mNetworkRequestInfoLogs.log("REGISTER " + nri);
3140 if (nri.request.isListen()) {
3141 for (NetworkAgentInfo network : mNetworkAgentInfos.values()) {
3142 if (nri.request.networkCapabilities.hasSignalStrength() &&
3143 network.satisfiesImmutableCapabilitiesOf(nri.request)) {
3144 updateSignalStrengthThresholds(network, "REGISTER", nri.request);
3148 rematchAllNetworksAndRequests(null, 0);
3149 if (nri.request.isRequest() && getNetworkForRequest(nri.request.requestId) == null) {
3150 sendUpdatedScoreToFactories(nri.request, null);
3154 private void handleReleaseNetworkRequestWithIntent(PendingIntent pendingIntent,
3156 NetworkRequestInfo nri = findExistingNetworkRequestInfo(pendingIntent);
3158 handleReleaseNetworkRequest(nri.request, callingUid, /* callOnUnavailable */ false);
3162 // Determines whether the network is the best (or could become the best, if it validated), for
3163 // none of a particular type of NetworkRequests. The type of NetworkRequests considered depends
3164 // on the value of reason:
3166 // - UnneededFor.TEARDOWN: non-listen NetworkRequests. If a network is unneeded for this reason,
3167 // then it should be torn down.
3168 // - UnneededFor.LINGER: foreground NetworkRequests. If a network is unneeded for this reason,
3169 // then it should be lingered.
3170 private boolean unneeded(NetworkAgentInfo nai, UnneededFor reason) {
3171 final int numRequests;
3174 numRequests = nai.numRequestNetworkRequests();
3177 numRequests = nai.numForegroundNetworkRequests();
3180 Slog.wtf(TAG, "Invalid reason. Cannot happen.");
3184 if (!nai.everConnected || nai.isVPN() || nai.isLingering() || numRequests > 0) {
3187 for (NetworkRequestInfo nri : mNetworkRequests.values()) {
3188 if (reason == UnneededFor.LINGER && nri.request.isBackgroundRequest()) {
3189 // Background requests don't affect lingering.
3193 // If this Network is already the highest scoring Network for a request, or if
3194 // there is hope for it to become one if it validated, then it is needed.
3195 if (nri.request.isRequest() && nai.satisfies(nri.request) &&
3196 (nai.isSatisfyingRequest(nri.request.requestId) ||
3197 // Note that this catches two important cases:
3198 // 1. Unvalidated cellular will not be reaped when unvalidated WiFi
3199 // is currently satisfying the request. This is desirable when
3200 // cellular ends up validating but WiFi does not.
3201 // 2. Unvalidated WiFi will not be reaped when validated cellular
3202 // is currently satisfying the request. This is desirable when
3203 // WiFi ends up validating and out scoring cellular.
3204 getNetworkForRequest(nri.request.requestId).getCurrentScore() <
3205 nai.getCurrentScoreAsValidated())) {
3212 private NetworkRequestInfo getNriForAppRequest(
3213 NetworkRequest request, int callingUid, String requestedOperation) {
3214 final NetworkRequestInfo nri = mNetworkRequests.get(request);
3217 if (Process.SYSTEM_UID != callingUid && nri.mUid != callingUid) {
3218 log(String.format("UID %d attempted to %s for unowned request %s",
3219 callingUid, requestedOperation, nri));
3227 private void handleTimedOutNetworkRequest(final NetworkRequestInfo nri) {
3228 if (mNetworkRequests.get(nri.request) == null) {
3231 if (getNetworkForRequest(nri.request.requestId) != null) {
3234 if (VDBG || (DBG && nri.request.isRequest())) {
3235 log("releasing " + nri.request + " (timeout)");
3237 handleRemoveNetworkRequest(nri);
3238 callCallbackForRequest(nri, null, ConnectivityManager.CALLBACK_UNAVAIL, 0);
3241 private void handleReleaseNetworkRequest(NetworkRequest request, int callingUid,
3242 boolean callOnUnavailable) {
3243 final NetworkRequestInfo nri =
3244 getNriForAppRequest(request, callingUid, "release NetworkRequest");
3248 if (VDBG || (DBG && nri.request.isRequest())) {
3249 log("releasing " + nri.request + " (release request)");
3251 handleRemoveNetworkRequest(nri);
3252 if (callOnUnavailable) {
3253 callCallbackForRequest(nri, null, ConnectivityManager.CALLBACK_UNAVAIL, 0);
3257 private void handleRemoveNetworkRequest(final NetworkRequestInfo nri) {
3258 nri.unlinkDeathRecipient();
3259 mNetworkRequests.remove(nri.request);
3261 synchronized (mUidToNetworkRequestCount) {
3262 int requests = mUidToNetworkRequestCount.get(nri.mUid, 0);
3264 Slog.wtf(TAG, "BUG: too small request count " + requests + " for UID " +
3266 } else if (requests == 1) {
3267 mUidToNetworkRequestCount.removeAt(
3268 mUidToNetworkRequestCount.indexOfKey(nri.mUid));
3270 mUidToNetworkRequestCount.put(nri.mUid, requests - 1);
3274 mNetworkRequestInfoLogs.log("RELEASE " + nri);
3275 if (nri.request.isRequest()) {
3276 boolean wasKept = false;
3277 NetworkAgentInfo nai = getNetworkForRequest(nri.request.requestId);
3279 boolean wasBackgroundNetwork = nai.isBackgroundNetwork();
3280 nai.removeRequest(nri.request.requestId);
3282 log(" Removing from current network " + nai.name() +
3283 ", leaving " + nai.numNetworkRequests() + " requests.");
3285 // If there are still lingered requests on this network, don't tear it down,
3286 // but resume lingering instead.
3287 updateLingerState(nai, SystemClock.elapsedRealtime());
3288 if (unneeded(nai, UnneededFor.TEARDOWN)) {
3289 if (DBG) log("no live requests for " + nai.name() + "; disconnecting");
3290 teardownUnneededNetwork(nai);
3294 clearNetworkForRequest(nri.request.requestId);
3295 if (!wasBackgroundNetwork && nai.isBackgroundNetwork()) {
3296 // Went from foreground to background.
3297 updateCapabilities(nai.getCurrentScore(), nai, nai.networkCapabilities);
3301 // Maintain the illusion. When this request arrived, we might have pretended
3302 // that a network connected to serve it, even though the network was already
3303 // connected. Now that this request has gone away, we might have to pretend
3304 // that the network disconnected. LegacyTypeTracker will generate that
3305 // phantom disconnect for this type.
3306 if (nri.request.legacyType != TYPE_NONE && nai != null) {
3307 boolean doRemove = true;
3309 // check if any of the remaining requests for this network are for the
3310 // same legacy type - if so, don't remove the nai
3311 for (int i = 0; i < nai.numNetworkRequests(); i++) {
3312 NetworkRequest otherRequest = nai.requestAt(i);
3313 if (otherRequest.legacyType == nri.request.legacyType &&
3314 otherRequest.isRequest()) {
3315 if (DBG) log(" still have other legacy request - leaving");
3322 mLegacyTypeTracker.remove(nri.request.legacyType, nai, false);
3326 for (NetworkFactoryInfo nfi : mNetworkFactoryInfos.values()) {
3327 nfi.asyncChannel.sendMessage(android.net.NetworkFactory.CMD_CANCEL_REQUEST,
3331 // listens don't have a singular affectedNetwork. Check all networks to see
3332 // if this listen request applies and remove it.
3333 for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
3334 nai.removeRequest(nri.request.requestId);
3335 if (nri.request.networkCapabilities.hasSignalStrength() &&
3336 nai.satisfiesImmutableCapabilitiesOf(nri.request)) {
3337 updateSignalStrengthThresholds(nai, "RELEASE", nri.request);
3344 public void setAcceptUnvalidated(Network network, boolean accept, boolean always) {
3345 enforceNetworkStackSettingsOrSetup();
3346 mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_ACCEPT_UNVALIDATED,
3347 encodeBool(accept), encodeBool(always), network));
3351 public void setAcceptPartialConnectivity(Network network, boolean accept, boolean always) {
3352 enforceNetworkStackSettingsOrSetup();
3353 mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_ACCEPT_PARTIAL_CONNECTIVITY,
3354 encodeBool(accept), encodeBool(always), network));
3358 public void setAvoidUnvalidated(Network network) {
3359 enforceNetworkStackSettingsOrSetup();
3360 mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_AVOID_UNVALIDATED, network));
3363 private void handleSetAcceptUnvalidated(Network network, boolean accept, boolean always) {
3364 if (DBG) log("handleSetAcceptUnvalidated network=" + network +
3365 " accept=" + accept + " always=" + always);
3367 NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
3373 if (nai.everValidated) {
3374 // The network validated while the dialog box was up. Take no action.
3378 if (!nai.networkMisc.explicitlySelected) {
3379 Slog.wtf(TAG, "BUG: setAcceptUnvalidated non non-explicitly selected network");
3382 if (accept != nai.networkMisc.acceptUnvalidated) {
3383 int oldScore = nai.getCurrentScore();
3384 nai.networkMisc.acceptUnvalidated = accept;
3385 // If network becomes partial connectivity and user already accepted to use this
3386 // network, we should respect the user's option and don't need to popup the
3387 // PARTIAL_CONNECTIVITY notification to user again.
3388 nai.networkMisc.acceptPartialConnectivity = accept;
3389 rematchAllNetworksAndRequests(nai, oldScore);
3390 sendUpdatedScoreToFactories(nai);
3394 nai.asyncChannel.sendMessage(
3395 NetworkAgent.CMD_SAVE_ACCEPT_UNVALIDATED, encodeBool(accept));
3399 // Tell the NetworkAgent to not automatically reconnect to the network.
3400 nai.asyncChannel.sendMessage(NetworkAgent.CMD_PREVENT_AUTOMATIC_RECONNECT);
3401 // Teardown the network.
3402 teardownUnneededNetwork(nai);
3407 private void handleSetAcceptPartialConnectivity(Network network, boolean accept,
3410 log("handleSetAcceptPartialConnectivity network=" + network + " accept=" + accept
3411 + " always=" + always);
3414 final NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
3420 if (nai.lastValidated) {
3421 // The network validated while the dialog box was up. Take no action.
3425 if (accept != nai.networkMisc.acceptPartialConnectivity) {
3426 nai.networkMisc.acceptPartialConnectivity = accept;
3429 // TODO: Use the current design or save the user choice into IpMemoryStore.
3431 nai.asyncChannel.sendMessage(
3432 NetworkAgent.CMD_SAVE_ACCEPT_UNVALIDATED, encodeBool(accept));
3436 // Tell the NetworkAgent to not automatically reconnect to the network.
3437 nai.asyncChannel.sendMessage(NetworkAgent.CMD_PREVENT_AUTOMATIC_RECONNECT);
3438 // Tear down the network.
3439 teardownUnneededNetwork(nai);
3441 // Inform NetworkMonitor that partial connectivity is acceptable. This will likely
3442 // result in a partial connectivity result which will be processed by
3443 // maybeHandleNetworkMonitorMessage.
3445 nai.networkMonitor().setAcceptPartialConnectivity();
3446 } catch (RemoteException e) {
3447 e.rethrowAsRuntimeException();
3452 private void handleSetAvoidUnvalidated(Network network) {
3453 NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
3454 if (nai == null || nai.lastValidated) {
3455 // Nothing to do. The network either disconnected or revalidated.
3458 if (!nai.avoidUnvalidated) {
3459 int oldScore = nai.getCurrentScore();
3460 nai.avoidUnvalidated = true;
3461 rematchAllNetworksAndRequests(nai, oldScore);
3462 sendUpdatedScoreToFactories(nai);
3466 private void scheduleUnvalidatedPrompt(NetworkAgentInfo nai) {
3467 if (VDBG) log("scheduleUnvalidatedPrompt " + nai.network);
3468 mHandler.sendMessageDelayed(
3469 mHandler.obtainMessage(EVENT_PROMPT_UNVALIDATED, nai.network),
3470 PROMPT_UNVALIDATED_DELAY_MS);
3474 public void startCaptivePortalApp(Network network) {
3475 enforceConnectivityInternalPermission();
3476 mHandler.post(() -> {
3477 NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
3478 if (nai == null) return;
3479 if (!nai.networkCapabilities.hasCapability(NET_CAPABILITY_CAPTIVE_PORTAL)) return;
3481 nai.networkMonitor().launchCaptivePortalApp();
3482 } catch (RemoteException e) {
3483 e.rethrowAsRuntimeException();
3489 * NetworkStack endpoint to start the captive portal app. The NetworkStack needs to use this
3490 * endpoint as it does not have INTERACT_ACROSS_USERS_FULL itself.
3491 * @param network Network on which the captive portal was detected.
3492 * @param appExtras Bundle to use as intent extras for the captive portal application.
3493 * Must be treated as opaque to avoid preventing the captive portal app to
3494 * update its arguments.
3497 public void startCaptivePortalAppInternal(Network network, Bundle appExtras) {
3498 mContext.checkCallingOrSelfPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK);
3500 final Intent appIntent = new Intent(ConnectivityManager.ACTION_CAPTIVE_PORTAL_SIGN_IN);
3501 appIntent.putExtras(appExtras);
3502 appIntent.putExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL,
3503 new CaptivePortal(new CaptivePortalImpl(network).asBinder()));
3504 appIntent.setFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT | Intent.FLAG_ACTIVITY_NEW_TASK);
3506 Binder.withCleanCallingIdentity(() ->
3507 mContext.startActivityAsUser(appIntent, UserHandle.CURRENT));
3510 private class CaptivePortalImpl extends ICaptivePortal.Stub {
3511 private final Network mNetwork;
3513 private CaptivePortalImpl(Network network) {
3518 public void appResponse(final int response) throws RemoteException {
3519 if (response == CaptivePortal.APP_RETURN_WANTED_AS_IS) {
3520 enforceSettingsPermission();
3523 // getNetworkAgentInfoForNetwork is thread-safe
3524 final NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(mNetwork);
3525 if (nai == null) return;
3527 // nai.networkMonitor() is thread-safe
3528 final INetworkMonitor nm = nai.networkMonitor();
3529 if (nm == null) return;
3531 final long token = Binder.clearCallingIdentity();
3533 nm.notifyCaptivePortalAppFinished(response);
3535 // Not using Binder.withCleanCallingIdentity() to keep the checked RemoteException
3536 Binder.restoreCallingIdentity(token);
3541 public void logEvent(int eventId, String packageName) {
3542 enforceSettingsPermission();
3544 new MetricsLogger().action(eventId, packageName);
3548 public boolean avoidBadWifi() {
3549 return mMultinetworkPolicyTracker.getAvoidBadWifi();
3553 * Return whether the device should maintain continuous, working connectivity by switching away
3554 * from WiFi networks having no connectivity.
3555 * @see MultinetworkPolicyTracker#getAvoidBadWifi()
3557 public boolean shouldAvoidBadWifi() {
3558 if (!checkNetworkStackPermission()) {
3559 throw new SecurityException("avoidBadWifi requires NETWORK_STACK permission");
3561 return avoidBadWifi();
3565 private void rematchForAvoidBadWifiUpdate() {
3566 rematchAllNetworksAndRequests(null, 0);
3567 for (NetworkAgentInfo nai: mNetworkAgentInfos.values()) {
3568 if (nai.networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
3569 sendUpdatedScoreToFactories(nai);
3574 // TODO: Evaluate whether this is of interest to other consumers of
3575 // MultinetworkPolicyTracker and worth moving out of here.
3576 private void dumpAvoidBadWifiSettings(IndentingPrintWriter pw) {
3577 final boolean configRestrict = mMultinetworkPolicyTracker.configRestrictsAvoidBadWifi();
3578 if (!configRestrict) {
3579 pw.println("Bad Wi-Fi avoidance: unrestricted");
3583 pw.println("Bad Wi-Fi avoidance: " + avoidBadWifi());
3584 pw.increaseIndent();
3585 pw.println("Config restrict: " + configRestrict);
3587 final String value = mMultinetworkPolicyTracker.getAvoidBadWifiSetting();
3589 // Can't use a switch statement because strings are legal case labels, but null is not.
3590 if ("0".equals(value)) {
3591 description = "get stuck";
3592 } else if (value == null) {
3593 description = "prompt";
3594 } else if ("1".equals(value)) {
3595 description = "avoid";
3597 description = value + " (?)";
3599 pw.println("User setting: " + description);
3600 pw.println("Network overrides:");
3601 pw.increaseIndent();
3602 for (NetworkAgentInfo nai : networksSortedById()) {
3603 if (nai.avoidUnvalidated) {
3604 pw.println(nai.name());
3607 pw.decreaseIndent();
3608 pw.decreaseIndent();
3611 private void showNetworkNotification(NetworkAgentInfo nai, NotificationType type) {
3612 final String action;
3615 action = Settings.ACTION_WIFI_SETTINGS;
3616 mHandler.removeMessages(EVENT_TIMEOUT_NOTIFICATION);
3617 mHandler.sendMessageDelayed(mHandler.obtainMessage(EVENT_TIMEOUT_NOTIFICATION,
3618 nai.network.netId, 0), TIMEOUT_NOTIFICATION_DELAY_MS);
3621 action = ConnectivityManager.ACTION_PROMPT_UNVALIDATED;
3624 action = ConnectivityManager.ACTION_PROMPT_LOST_VALIDATION;
3626 case PARTIAL_CONNECTIVITY:
3627 action = ConnectivityManager.ACTION_PROMPT_PARTIAL_CONNECTIVITY;
3630 Slog.wtf(TAG, "Unknown notification type " + type);
3634 Intent intent = new Intent(action);
3635 if (type != NotificationType.LOGGED_IN) {
3636 intent.setData(Uri.fromParts("netId", Integer.toString(nai.network.netId), null));
3637 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
3638 intent.setClassName("com.android.settings",
3639 "com.android.settings.wifi.WifiNoInternetDialog");
3642 PendingIntent pendingIntent = PendingIntent.getActivityAsUser(
3643 mContext, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT, null, UserHandle.CURRENT);
3644 mNotifier.showNotification(nai.network.netId, type, nai, null, pendingIntent, true);
3647 private void handlePromptUnvalidated(Network network) {
3648 if (VDBG || DDBG) log("handlePromptUnvalidated " + network);
3649 NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
3651 // Only prompt if the network is unvalidated or network has partial internet connectivity
3652 // and was explicitly selected by the user, and if we haven't already been told to switch
3653 // to it regardless of whether it validated or not. Also don't prompt on captive portals
3654 // because we're already prompting the user to sign in.
3655 if (nai == null || nai.everValidated || nai.everCaptivePortalDetected
3656 || !nai.networkMisc.explicitlySelected || nai.networkMisc.acceptUnvalidated
3657 // TODO: Once the value of acceptPartialConnectivity is moved to IpMemoryStore,
3658 // we should reevaluate how to handle acceptPartialConnectivity when network just
3660 || nai.networkMisc.acceptPartialConnectivity) {
3663 // TODO: Evaluate if it's needed to wait 8 seconds for triggering notification when
3664 // NetworkMonitor detects the network is partial connectivity. Need to change the design to
3665 // popup the notification immediately when the network is partial connectivity.
3666 if (nai.partialConnectivity) {
3667 showNetworkNotification(nai, NotificationType.PARTIAL_CONNECTIVITY);
3669 showNetworkNotification(nai, NotificationType.NO_INTERNET);
3673 private void handleNetworkUnvalidated(NetworkAgentInfo nai) {
3674 NetworkCapabilities nc = nai.networkCapabilities;
3675 if (DBG) log("handleNetworkUnvalidated " + nai.name() + " cap=" + nc);
3677 if (!nc.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
3681 if (mMultinetworkPolicyTracker.shouldNotifyWifiUnvalidated()) {
3682 showNetworkNotification(nai, NotificationType.LOST_INTERNET);
3687 public int getMultipathPreference(Network network) {
3688 enforceAccessPermission();
3690 NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
3691 if (nai != null && nai.networkCapabilities
3692 .hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED)) {
3693 return ConnectivityManager.MULTIPATH_PREFERENCE_UNMETERED;
3696 Integer networkPreference = mMultipathPolicyTracker.getMultipathPreference(network);
3697 if (networkPreference != null) {
3698 return networkPreference;
3701 return mMultinetworkPolicyTracker.getMeteredMultipathPreference();
3705 public NetworkRequest getDefaultRequest() {
3706 return mDefaultRequest;
3709 private class InternalHandler extends Handler {
3710 public InternalHandler(Looper looper) {
3715 public void handleMessage(Message msg) {
3717 case EVENT_EXPIRE_NET_TRANSITION_WAKELOCK:
3718 case EVENT_CLEAR_NET_TRANSITION_WAKELOCK: {
3719 handleReleaseNetworkTransitionWakelock(msg.what);
3722 case EVENT_APPLY_GLOBAL_HTTP_PROXY: {
3723 mProxyTracker.loadDeprecatedGlobalHttpProxy();
3726 case EVENT_PROXY_HAS_CHANGED: {
3727 handleApplyDefaultProxy((ProxyInfo)msg.obj);
3730 case EVENT_REGISTER_NETWORK_FACTORY: {
3731 handleRegisterNetworkFactory((NetworkFactoryInfo)msg.obj);
3734 case EVENT_UNREGISTER_NETWORK_FACTORY: {
3735 handleUnregisterNetworkFactory((Messenger)msg.obj);
3738 case EVENT_REGISTER_NETWORK_AGENT: {
3739 final Pair<NetworkAgentInfo, INetworkMonitor> arg =
3740 (Pair<NetworkAgentInfo, INetworkMonitor>) msg.obj;
3741 handleRegisterNetworkAgent(arg.first, arg.second);
3744 case EVENT_REGISTER_NETWORK_REQUEST:
3745 case EVENT_REGISTER_NETWORK_LISTENER: {
3746 handleRegisterNetworkRequest((NetworkRequestInfo) msg.obj);
3749 case EVENT_REGISTER_NETWORK_REQUEST_WITH_INTENT:
3750 case EVENT_REGISTER_NETWORK_LISTENER_WITH_INTENT: {
3751 handleRegisterNetworkRequestWithIntent(msg);
3754 case EVENT_TIMEOUT_NETWORK_REQUEST: {
3755 NetworkRequestInfo nri = (NetworkRequestInfo) msg.obj;
3756 handleTimedOutNetworkRequest(nri);
3759 case EVENT_RELEASE_NETWORK_REQUEST_WITH_INTENT: {
3760 handleReleaseNetworkRequestWithIntent((PendingIntent) msg.obj, msg.arg1);
3763 case EVENT_RELEASE_NETWORK_REQUEST: {
3764 handleReleaseNetworkRequest((NetworkRequest) msg.obj, msg.arg1,
3765 /* callOnUnavailable */ false);
3768 case EVENT_SET_ACCEPT_UNVALIDATED: {
3769 Network network = (Network) msg.obj;
3770 handleSetAcceptUnvalidated(network, toBool(msg.arg1), toBool(msg.arg2));
3773 case EVENT_SET_ACCEPT_PARTIAL_CONNECTIVITY: {
3774 Network network = (Network) msg.obj;
3775 handleSetAcceptPartialConnectivity(network, toBool(msg.arg1),
3779 case EVENT_SET_AVOID_UNVALIDATED: {
3780 handleSetAvoidUnvalidated((Network) msg.obj);
3783 case EVENT_PROMPT_UNVALIDATED: {
3784 handlePromptUnvalidated((Network) msg.obj);
3787 case EVENT_CONFIGURE_ALWAYS_ON_NETWORKS: {
3788 handleConfigureAlwaysOnNetworks();
3791 // Sent by KeepaliveTracker to process an app request on the state machine thread.
3792 case NetworkAgent.CMD_START_SOCKET_KEEPALIVE: {
3793 mKeepaliveTracker.handleStartKeepalive(msg);
3796 // Sent by KeepaliveTracker to process an app request on the state machine thread.
3797 case NetworkAgent.CMD_STOP_SOCKET_KEEPALIVE: {
3798 NetworkAgentInfo nai = getNetworkAgentInfoForNetwork((Network) msg.obj);
3799 int slot = msg.arg1;
3800 int reason = msg.arg2;
3801 mKeepaliveTracker.handleStopKeepalive(nai, slot, reason);
3804 case EVENT_SYSTEM_READY: {
3805 mMultipathPolicyTracker.start();
3808 case EVENT_REVALIDATE_NETWORK: {
3809 handleReportNetworkConnectivity((Network) msg.obj, msg.arg1, toBool(msg.arg2));
3812 case EVENT_PRIVATE_DNS_SETTINGS_CHANGED:
3813 handlePrivateDnsSettingsChanged();
3815 case EVENT_PRIVATE_DNS_VALIDATION_UPDATE:
3816 handlePrivateDnsValidationUpdate(
3817 (PrivateDnsValidationUpdate) msg.obj);
3819 case EVENT_UID_RULES_CHANGED:
3820 handleUidRulesChanged(msg.arg1, msg.arg2);
3822 case EVENT_DATA_SAVER_CHANGED:
3823 handleRestrictBackgroundChanged(toBool(msg.arg1));
3825 case EVENT_TIMEOUT_NOTIFICATION:
3826 mNotifier.clearNotification(msg.arg1, NotificationType.LOGGED_IN);
3832 // javadoc from interface
3834 public int tether(String iface, String callerPkg) {
3835 ConnectivityManager.enforceTetherChangePermission(mContext, callerPkg);
3836 if (isTetheringSupported()) {
3837 return mTethering.tether(iface);
3839 return ConnectivityManager.TETHER_ERROR_UNSUPPORTED;
3843 // javadoc from interface
3845 public int untether(String iface, String callerPkg) {
3846 ConnectivityManager.enforceTetherChangePermission(mContext, callerPkg);
3848 if (isTetheringSupported()) {
3849 return mTethering.untether(iface);
3851 return ConnectivityManager.TETHER_ERROR_UNSUPPORTED;
3855 // javadoc from interface
3857 public int getLastTetherError(String iface) {
3858 enforceTetherAccessPermission();
3860 if (isTetheringSupported()) {
3861 return mTethering.getLastTetherError(iface);
3863 return ConnectivityManager.TETHER_ERROR_UNSUPPORTED;
3867 // TODO - proper iface API for selection by property, inspection, etc
3869 public String[] getTetherableUsbRegexs() {
3870 enforceTetherAccessPermission();
3871 if (isTetheringSupported()) {
3872 return mTethering.getTetherableUsbRegexs();
3874 return new String[0];
3879 public String[] getTetherableWifiRegexs() {
3880 enforceTetherAccessPermission();
3881 if (isTetheringSupported()) {
3882 return mTethering.getTetherableWifiRegexs();
3884 return new String[0];
3889 public String[] getTetherableBluetoothRegexs() {
3890 enforceTetherAccessPermission();
3891 if (isTetheringSupported()) {
3892 return mTethering.getTetherableBluetoothRegexs();
3894 return new String[0];
3899 public int setUsbTethering(boolean enable, String callerPkg) {
3900 ConnectivityManager.enforceTetherChangePermission(mContext, callerPkg);
3901 if (isTetheringSupported()) {
3902 return mTethering.setUsbTethering(enable);
3904 return ConnectivityManager.TETHER_ERROR_UNSUPPORTED;
3908 // TODO - move iface listing, queries, etc to new module
3909 // javadoc from interface
3911 public String[] getTetherableIfaces() {
3912 enforceTetherAccessPermission();
3913 return mTethering.getTetherableIfaces();
3917 public String[] getTetheredIfaces() {
3918 enforceTetherAccessPermission();
3919 return mTethering.getTetheredIfaces();
3923 public String[] getTetheringErroredIfaces() {
3924 enforceTetherAccessPermission();
3925 return mTethering.getErroredIfaces();
3929 public String[] getTetheredDhcpRanges() {
3930 enforceConnectivityInternalPermission();
3931 return mTethering.getTetheredDhcpRanges();
3935 public boolean isTetheringSupported(String callerPkg) {
3936 ConnectivityManager.enforceTetherChangePermission(mContext, callerPkg);
3937 return isTetheringSupported();
3940 // if ro.tether.denied = true we default to no tethering
3941 // gservices could set the secure setting to 1 though to enable it on a build where it
3942 // had previously been turned off.
3943 private boolean isTetheringSupported() {
3944 int defaultVal = encodeBool(!mSystemProperties.get("ro.tether.denied").equals("true"));
3945 boolean tetherSupported = toBool(Settings.Global.getInt(mContext.getContentResolver(),
3946 Settings.Global.TETHER_SUPPORTED, defaultVal));
3947 boolean tetherEnabledInSettings = tetherSupported
3948 && !mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_TETHERING);
3950 // Elevate to system UID to avoid caller requiring MANAGE_USERS permission.
3951 boolean adminUser = false;
3952 final long token = Binder.clearCallingIdentity();
3954 adminUser = mUserManager.isAdminUser();
3956 Binder.restoreCallingIdentity(token);
3959 return tetherEnabledInSettings && adminUser && mTethering.hasTetherableConfiguration();
3963 public void startTethering(int type, ResultReceiver receiver, boolean showProvisioningUi,
3965 ConnectivityManager.enforceTetherChangePermission(mContext, callerPkg);
3966 if (!isTetheringSupported()) {
3967 receiver.send(ConnectivityManager.TETHER_ERROR_UNSUPPORTED, null);
3970 mTethering.startTethering(type, receiver, showProvisioningUi);
3974 public void stopTethering(int type, String callerPkg) {
3975 ConnectivityManager.enforceTetherChangePermission(mContext, callerPkg);
3976 mTethering.stopTethering(type);
3980 * Get the latest value of the tethering entitlement check.
3982 * Note: Allow privileged apps who have TETHER_PRIVILEGED permission to access. If it turns
3983 * out some such apps are observed to abuse this API, change to per-UID limits on this API
3984 * if it's really needed.
3987 public void getLatestTetheringEntitlementResult(int type, ResultReceiver receiver,
3988 boolean showEntitlementUi, String callerPkg) {
3989 ConnectivityManager.enforceTetherChangePermission(mContext, callerPkg);
3990 mTethering.getLatestTetheringEntitlementResult(type, receiver, showEntitlementUi);
3993 /** Register tethering event callback. */
3995 public void registerTetheringEventCallback(ITetheringEventCallback callback,
3997 ConnectivityManager.enforceTetherChangePermission(mContext, callerPkg);
3998 mTethering.registerTetheringEventCallback(callback);
4001 /** Unregister tethering event callback. */
4003 public void unregisterTetheringEventCallback(ITetheringEventCallback callback,
4005 ConnectivityManager.enforceTetherChangePermission(mContext, callerPkg);
4006 mTethering.unregisterTetheringEventCallback(callback);
4009 // Called when we lose the default network and have no replacement yet.
4010 // This will automatically be cleared after X seconds or a new default network
4011 // becomes CONNECTED, whichever happens first. The timer is started by the
4012 // first caller and not restarted by subsequent callers.
4013 private void ensureNetworkTransitionWakelock(String forWhom) {
4014 synchronized (this) {
4015 if (mNetTransitionWakeLock.isHeld()) {
4018 mNetTransitionWakeLock.acquire();
4019 mLastWakeLockAcquireTimestamp = SystemClock.elapsedRealtime();
4020 mTotalWakelockAcquisitions++;
4022 mWakelockLogs.log("ACQUIRE for " + forWhom);
4023 Message msg = mHandler.obtainMessage(EVENT_EXPIRE_NET_TRANSITION_WAKELOCK);
4024 mHandler.sendMessageDelayed(msg, mNetTransitionWakeLockTimeout);
4027 // Called when we gain a new default network to release the network transition wakelock in a
4028 // second, to allow a grace period for apps to reconnect over the new network. Pending expiry
4029 // message is cancelled.
4030 private void scheduleReleaseNetworkTransitionWakelock() {
4031 synchronized (this) {
4032 if (!mNetTransitionWakeLock.isHeld()) {
4033 return; // expiry message released the lock first.
4036 // Cancel self timeout on wakelock hold.
4037 mHandler.removeMessages(EVENT_EXPIRE_NET_TRANSITION_WAKELOCK);
4038 Message msg = mHandler.obtainMessage(EVENT_CLEAR_NET_TRANSITION_WAKELOCK);
4039 mHandler.sendMessageDelayed(msg, 1000);
4042 // Called when either message of ensureNetworkTransitionWakelock or
4043 // scheduleReleaseNetworkTransitionWakelock is processed.
4044 private void handleReleaseNetworkTransitionWakelock(int eventId) {
4045 String event = eventName(eventId);
4046 synchronized (this) {
4047 if (!mNetTransitionWakeLock.isHeld()) {
4048 mWakelockLogs.log(String.format("RELEASE: already released (%s)", event));
4049 Slog.w(TAG, "expected Net Transition WakeLock to be held");
4052 mNetTransitionWakeLock.release();
4053 long lockDuration = SystemClock.elapsedRealtime() - mLastWakeLockAcquireTimestamp;
4054 mTotalWakelockDurationMs += lockDuration;
4055 mMaxWakelockDurationMs = Math.max(mMaxWakelockDurationMs, lockDuration);
4056 mTotalWakelockReleases++;
4058 mWakelockLogs.log(String.format("RELEASE (%s)", event));
4061 // 100 percent is full good, 0 is full bad.
4063 public void reportInetCondition(int networkType, int percentage) {
4064 NetworkAgentInfo nai = mLegacyTypeTracker.getNetworkForType(networkType);
4065 if (nai == null) return;
4066 reportNetworkConnectivity(nai.network, percentage > 50);
4070 public void reportNetworkConnectivity(Network network, boolean hasConnectivity) {
4071 enforceAccessPermission();
4072 enforceInternetPermission();
4073 final int uid = Binder.getCallingUid();
4074 final int connectivityInfo = encodeBool(hasConnectivity);
4075 mHandler.sendMessage(
4076 mHandler.obtainMessage(EVENT_REVALIDATE_NETWORK, uid, connectivityInfo, network));
4079 private void handleReportNetworkConnectivity(
4080 Network network, int uid, boolean hasConnectivity) {
4081 final NetworkAgentInfo nai;
4082 if (network == null) {
4083 nai = getDefaultNetwork();
4085 nai = getNetworkAgentInfoForNetwork(network);
4087 if (nai == null || nai.networkInfo.getState() == NetworkInfo.State.DISCONNECTING ||
4088 nai.networkInfo.getState() == NetworkInfo.State.DISCONNECTED) {
4091 // Revalidate if the app report does not match our current validated state.
4092 if (hasConnectivity == nai.lastValidated) {
4096 int netid = nai.network.netId;
4097 log("reportNetworkConnectivity(" + netid + ", " + hasConnectivity + ") by " + uid);
4099 // Validating a network that has not yet connected could result in a call to
4100 // rematchNetworkAndRequests() which is not meant to work on such networks.
4101 if (!nai.everConnected) {
4104 LinkProperties lp = getLinkProperties(nai);
4105 if (isNetworkWithLinkPropertiesBlocked(lp, uid, false)) {
4109 nai.networkMonitor().forceReevaluation(uid);
4110 } catch (RemoteException e) {
4111 e.rethrowAsRuntimeException();
4116 * Returns information about the proxy a certain network is using. If given a null network, it
4117 * it will return the proxy for the bound network for the caller app or the default proxy if
4120 * @param network the network we want to get the proxy information for.
4121 * @return Proxy information if a network has a proxy configured, or otherwise null.
4124 public ProxyInfo getProxyForNetwork(Network network) {
4125 final ProxyInfo globalProxy = mProxyTracker.getGlobalProxy();
4126 if (globalProxy != null) return globalProxy;
4127 if (network == null) {
4128 // Get the network associated with the calling UID.
4129 final Network activeNetwork = getActiveNetworkForUidInternal(Binder.getCallingUid(),
4131 if (activeNetwork == null) {
4134 return getLinkPropertiesProxyInfo(activeNetwork);
4135 } else if (queryUserAccess(Binder.getCallingUid(), network.netId)) {
4136 // Don't call getLinkProperties() as it requires ACCESS_NETWORK_STATE permission, which
4137 // caller may not have.
4138 return getLinkPropertiesProxyInfo(network);
4140 // No proxy info available if the calling UID does not have network access.
4145 protected boolean queryUserAccess(int uid, int netId) {
4146 return NetworkUtils.queryUserAccess(uid, netId);
4149 private ProxyInfo getLinkPropertiesProxyInfo(Network network) {
4150 final NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
4151 if (nai == null) return null;
4152 synchronized (nai) {
4153 final ProxyInfo linkHttpProxy = nai.linkProperties.getHttpProxy();
4154 return linkHttpProxy == null ? null : new ProxyInfo(linkHttpProxy);
4159 public void setGlobalProxy(final ProxyInfo proxyProperties) {
4160 enforceConnectivityInternalPermission();
4161 mProxyTracker.setGlobalProxy(proxyProperties);
4166 public ProxyInfo getGlobalProxy() {
4167 return mProxyTracker.getGlobalProxy();
4170 private void handleApplyDefaultProxy(ProxyInfo proxy) {
4171 if (proxy != null && TextUtils.isEmpty(proxy.getHost())
4172 && Uri.EMPTY.equals(proxy.getPacFileUrl())) {
4175 mProxyTracker.setDefaultProxy(proxy);
4178 // If the proxy has changed from oldLp to newLp, resend proxy broadcast. This method gets called
4179 // when any network changes proxy.
4180 // TODO: Remove usage of broadcast extras as they are deprecated and not applicable in a
4181 // multi-network world where an app might be bound to a non-default network.
4182 private void updateProxy(LinkProperties newLp, LinkProperties oldLp) {
4183 ProxyInfo newProxyInfo = newLp == null ? null : newLp.getHttpProxy();
4184 ProxyInfo oldProxyInfo = oldLp == null ? null : oldLp.getHttpProxy();
4186 if (!ProxyTracker.proxyInfoEqual(newProxyInfo, oldProxyInfo)) {
4187 mProxyTracker.sendProxyBroadcast();
4191 private static class SettingsObserver extends ContentObserver {
4192 final private HashMap<Uri, Integer> mUriEventMap;
4193 final private Context mContext;
4194 final private Handler mHandler;
4196 SettingsObserver(Context context, Handler handler) {
4198 mUriEventMap = new HashMap<>();
4203 void observe(Uri uri, int what) {
4204 mUriEventMap.put(uri, what);
4205 final ContentResolver resolver = mContext.getContentResolver();
4206 resolver.registerContentObserver(uri, false, this);
4210 public void onChange(boolean selfChange) {
4211 Slog.wtf(TAG, "Should never be reached.");
4215 public void onChange(boolean selfChange, Uri uri) {
4216 final Integer what = mUriEventMap.get(uri);
4218 mHandler.obtainMessage(what.intValue()).sendToTarget();
4220 loge("No matching event to send for URI=" + uri);
4225 private static void log(String s) {
4229 private static void loge(String s) {
4233 private static void loge(String s, Throwable t) {
4238 * Prepare for a VPN application.
4239 * VPN permissions are checked in the {@link Vpn} class. If the caller is not {@code userId},
4240 * {@link android.Manifest.permission.INTERACT_ACROSS_USERS_FULL} permission is required.
4242 * @param oldPackage Package name of the application which currently controls VPN, which will
4243 * be replaced. If there is no such application, this should should either be
4244 * {@code null} or {@link VpnConfig.LEGACY_VPN}.
4245 * @param newPackage Package name of the application which should gain control of VPN, or
4246 * {@code null} to disable.
4247 * @param userId User for whom to prepare the new VPN.
4252 public boolean prepareVpn(@Nullable String oldPackage, @Nullable String newPackage,
4254 enforceCrossUserPermission(userId);
4256 synchronized (mVpns) {
4257 throwIfLockdownEnabled();
4258 Vpn vpn = mVpns.get(userId);
4260 return vpn.prepare(oldPackage, newPackage);
4268 * Set whether the VPN package has the ability to launch VPNs without user intervention.
4269 * This method is used by system-privileged apps.
4270 * VPN permissions are checked in the {@link Vpn} class. If the caller is not {@code userId},
4271 * {@link android.Manifest.permission.INTERACT_ACROSS_USERS_FULL} permission is required.
4273 * @param packageName The package for which authorization state should change.
4274 * @param userId User for whom {@code packageName} is installed.
4275 * @param authorized {@code true} if this app should be able to start a VPN connection without
4276 * explicit user approval, {@code false} if not.
4281 public void setVpnPackageAuthorization(String packageName, int userId, boolean authorized) {
4282 enforceCrossUserPermission(userId);
4284 synchronized (mVpns) {
4285 Vpn vpn = mVpns.get(userId);
4287 vpn.setPackageAuthorization(packageName, authorized);
4293 * Configure a TUN interface and return its file descriptor. Parameters
4294 * are encoded and opaque to this class. This method is used by VpnBuilder
4295 * and not available in ConnectivityManager. Permissions are checked in
4300 public ParcelFileDescriptor establishVpn(VpnConfig config) {
4301 int user = UserHandle.getUserId(Binder.getCallingUid());
4302 synchronized (mVpns) {
4303 throwIfLockdownEnabled();
4304 return mVpns.get(user).establish(config);
4309 * Start legacy VPN, controlling native daemons as needed. Creates a
4310 * secondary thread to perform connection work, returning quickly.
4313 public void startLegacyVpn(VpnProfile profile) {
4314 int user = UserHandle.getUserId(Binder.getCallingUid());
4315 final LinkProperties egress = getActiveLinkProperties();
4316 if (egress == null) {
4317 throw new IllegalStateException("Missing active network connection");
4319 synchronized (mVpns) {
4320 throwIfLockdownEnabled();
4321 mVpns.get(user).startLegacyVpn(profile, mKeyStore, egress);
4326 * Return the information of the ongoing legacy VPN. This method is used
4327 * by VpnSettings and not available in ConnectivityManager. Permissions
4328 * are checked in Vpn class.
4331 public LegacyVpnInfo getLegacyVpnInfo(int userId) {
4332 enforceCrossUserPermission(userId);
4334 synchronized (mVpns) {
4335 return mVpns.get(userId).getLegacyVpnInfo();
4340 * Return the information of all ongoing VPNs.
4342 * <p>This method is used to update NetworkStatsService.
4344 * <p>Must be called on the handler thread.
4346 private VpnInfo[] getAllVpnInfo() {
4347 ensureRunningOnConnectivityServiceThread();
4348 synchronized (mVpns) {
4349 if (mLockdownEnabled) {
4350 return new VpnInfo[0];
4353 List<VpnInfo> infoList = new ArrayList<>();
4354 for (int i = 0; i < mVpns.size(); i++) {
4355 VpnInfo info = createVpnInfo(mVpns.valueAt(i));
4360 return infoList.toArray(new VpnInfo[infoList.size()]);
4365 * @return VPN information for accounting, or null if we can't retrieve all required
4366 * information, e.g underlying ifaces.
4369 private VpnInfo createVpnInfo(Vpn vpn) {
4370 VpnInfo info = vpn.getVpnInfo();
4374 Network[] underlyingNetworks = vpn.getUnderlyingNetworks();
4375 // see VpnService.setUnderlyingNetworks()'s javadoc about how to interpret
4376 // the underlyingNetworks list.
4377 if (underlyingNetworks == null) {
4378 NetworkAgentInfo defaultNai = getDefaultNetwork();
4379 if (defaultNai != null && defaultNai.linkProperties != null) {
4380 underlyingNetworks = new Network[] { defaultNai.network };
4383 if (underlyingNetworks != null && underlyingNetworks.length > 0) {
4384 List<String> interfaces = new ArrayList<>();
4385 for (Network network : underlyingNetworks) {
4386 LinkProperties lp = getLinkProperties(network);
4388 interfaces.add(lp.getInterfaceName());
4391 if (!interfaces.isEmpty()) {
4392 info.underlyingIfaces = interfaces.toArray(new String[interfaces.size()]);
4395 return info.underlyingIfaces == null ? null : info;
4399 * Returns the information of the ongoing VPN for {@code userId}. This method is used by
4400 * VpnDialogs and not available in ConnectivityManager.
4401 * Permissions are checked in Vpn class.
4405 public VpnConfig getVpnConfig(int userId) {
4406 enforceCrossUserPermission(userId);
4407 synchronized (mVpns) {
4408 Vpn vpn = mVpns.get(userId);
4410 return vpn.getVpnConfig();
4418 * Ask all VPN objects to recompute and update their capabilities.
4420 * When underlying networks change, VPNs may have to update capabilities to reflect things
4421 * like the metered bit, their transports, and so on. This asks the VPN objects to update
4422 * their capabilities, and as this will cause them to send messages to the ConnectivityService
4423 * handler thread through their agent, this is asynchronous. When the capabilities objects
4424 * are computed they will be up-to-date as they are computed synchronously from here and
4425 * this is running on the ConnectivityService thread.
4427 private void updateAllVpnsCapabilities() {
4428 Network defaultNetwork = getNetwork(getDefaultNetwork());
4429 synchronized (mVpns) {
4430 for (int i = 0; i < mVpns.size(); i++) {
4431 final Vpn vpn = mVpns.valueAt(i);
4432 NetworkCapabilities nc = vpn.updateCapabilities(defaultNetwork);
4433 updateVpnCapabilities(vpn, nc);
4438 private void updateVpnCapabilities(Vpn vpn, @Nullable NetworkCapabilities nc) {
4439 ensureRunningOnConnectivityServiceThread();
4440 NetworkAgentInfo vpnNai = getNetworkAgentInfoForNetId(vpn.getNetId());
4441 if (vpnNai == null || nc == null) {
4444 updateCapabilities(vpnNai.getCurrentScore(), vpnNai, nc);
4448 public boolean updateLockdownVpn() {
4449 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
4450 Slog.w(TAG, "Lockdown VPN only available to AID_SYSTEM");
4454 synchronized (mVpns) {
4455 // Tear down existing lockdown if profile was removed
4456 mLockdownEnabled = LockdownVpnTracker.isEnabled();
4457 if (mLockdownEnabled) {
4458 byte[] profileTag = mKeyStore.get(Credentials.LOCKDOWN_VPN);
4459 if (profileTag == null) {
4460 Slog.e(TAG, "Lockdown VPN configured but cannot be read from keystore");
4463 String profileName = new String(profileTag);
4464 final VpnProfile profile = VpnProfile.decode(
4465 profileName, mKeyStore.get(Credentials.VPN + profileName));
4466 if (profile == null) {
4467 Slog.e(TAG, "Lockdown VPN configured invalid profile " + profileName);
4468 setLockdownTracker(null);
4471 int user = UserHandle.getUserId(Binder.getCallingUid());
4472 Vpn vpn = mVpns.get(user);
4474 Slog.w(TAG, "VPN for user " + user + " not ready yet. Skipping lockdown");
4477 setLockdownTracker(new LockdownVpnTracker(mContext, mNMS, this, vpn, profile));
4479 setLockdownTracker(null);
4487 * Internally set new {@link LockdownVpnTracker}, shutting down any existing
4488 * {@link LockdownVpnTracker}. Can be {@code null} to disable lockdown.
4491 private void setLockdownTracker(LockdownVpnTracker tracker) {
4492 // Shutdown any existing tracker
4493 final LockdownVpnTracker existing = mLockdownTracker;
4494 // TODO: Add a trigger when the always-on VPN enable/disable to reevaluate and send the
4495 // necessary onBlockedStatusChanged callbacks.
4496 mLockdownTracker = null;
4497 if (existing != null) {
4498 existing.shutdown();
4501 if (tracker != null) {
4502 mLockdownTracker = tracker;
4503 mLockdownTracker.init();
4508 private void throwIfLockdownEnabled() {
4509 if (mLockdownEnabled) {
4510 throw new IllegalStateException("Unavailable in lockdown mode");
4515 * Starts the always-on VPN {@link VpnService} for user {@param userId}, which should perform
4516 * some setup and then call {@code establish()} to connect.
4518 * @return {@code true} if the service was started, the service was already connected, or there
4519 * was no always-on VPN to start. {@code false} otherwise.
4521 private boolean startAlwaysOnVpn(int userId) {
4522 synchronized (mVpns) {
4523 Vpn vpn = mVpns.get(userId);
4525 // Shouldn't happen as all code paths that point here should have checked the Vpn
4527 Slog.wtf(TAG, "User " + userId + " has no Vpn configuration");
4531 return vpn.startAlwaysOnVpn();
4536 public boolean isAlwaysOnVpnPackageSupported(int userId, String packageName) {
4537 enforceSettingsPermission();
4538 enforceCrossUserPermission(userId);
4540 synchronized (mVpns) {
4541 Vpn vpn = mVpns.get(userId);
4543 Slog.w(TAG, "User " + userId + " has no Vpn configuration");
4546 return vpn.isAlwaysOnPackageSupported(packageName);
4551 public boolean setAlwaysOnVpnPackage(
4552 int userId, String packageName, boolean lockdown, List<String> lockdownWhitelist) {
4553 enforceControlAlwaysOnVpnPermission();
4554 enforceCrossUserPermission(userId);
4556 synchronized (mVpns) {
4557 // Can't set always-on VPN if legacy VPN is already in lockdown mode.
4558 if (LockdownVpnTracker.isEnabled()) {
4562 Vpn vpn = mVpns.get(userId);
4564 Slog.w(TAG, "User " + userId + " has no Vpn configuration");
4567 if (!vpn.setAlwaysOnPackage(packageName, lockdown, lockdownWhitelist)) {
4570 if (!startAlwaysOnVpn(userId)) {
4571 vpn.setAlwaysOnPackage(null, false, null);
4579 public String getAlwaysOnVpnPackage(int userId) {
4580 enforceControlAlwaysOnVpnPermission();
4581 enforceCrossUserPermission(userId);
4583 synchronized (mVpns) {
4584 Vpn vpn = mVpns.get(userId);
4586 Slog.w(TAG, "User " + userId + " has no Vpn configuration");
4589 return vpn.getAlwaysOnPackage();
4594 public boolean isVpnLockdownEnabled(int userId) {
4595 enforceControlAlwaysOnVpnPermission();
4596 enforceCrossUserPermission(userId);
4598 synchronized (mVpns) {
4599 Vpn vpn = mVpns.get(userId);
4601 Slog.w(TAG, "User " + userId + " has no Vpn configuration");
4604 return vpn.getLockdown();
4609 public List<String> getVpnLockdownWhitelist(int userId) {
4610 enforceControlAlwaysOnVpnPermission();
4611 enforceCrossUserPermission(userId);
4613 synchronized (mVpns) {
4614 Vpn vpn = mVpns.get(userId);
4616 Slog.w(TAG, "User " + userId + " has no Vpn configuration");
4619 return vpn.getLockdownWhitelist();
4624 public int checkMobileProvisioning(int suggestedTimeOutMs) {
4625 // TODO: Remove? Any reason to trigger a provisioning check?
4629 /** Location to an updatable file listing carrier provisioning urls.
4632 * <?xml version="1.0" encoding="utf-8"?>
4633 * <provisioningUrls>
4634 * <provisioningUrl mcc="310" mnc="4">http://myserver.com/foo?mdn=%3$s&iccid=%1$s&imei=%2$s</provisioningUrl>
4635 * </provisioningUrls>
4637 private static final String PROVISIONING_URL_PATH =
4638 "/data/misc/radio/provisioning_urls.xml";
4639 private final File mProvisioningUrlFile = new File(PROVISIONING_URL_PATH);
4641 /** XML tag for root element. */
4642 private static final String TAG_PROVISIONING_URLS = "provisioningUrls";
4643 /** XML tag for individual url */
4644 private static final String TAG_PROVISIONING_URL = "provisioningUrl";
4645 /** XML attribute for mcc */
4646 private static final String ATTR_MCC = "mcc";
4647 /** XML attribute for mnc */
4648 private static final String ATTR_MNC = "mnc";
4650 private String getProvisioningUrlBaseFromFile() {
4651 FileReader fileReader = null;
4652 XmlPullParser parser = null;
4653 Configuration config = mContext.getResources().getConfiguration();
4656 fileReader = new FileReader(mProvisioningUrlFile);
4657 parser = Xml.newPullParser();
4658 parser.setInput(fileReader);
4659 XmlUtils.beginDocument(parser, TAG_PROVISIONING_URLS);
4662 XmlUtils.nextElement(parser);
4664 String element = parser.getName();
4665 if (element == null) break;
4667 if (element.equals(TAG_PROVISIONING_URL)) {
4668 String mcc = parser.getAttributeValue(null, ATTR_MCC);
4670 if (mcc != null && Integer.parseInt(mcc) == config.mcc) {
4671 String mnc = parser.getAttributeValue(null, ATTR_MNC);
4672 if (mnc != null && Integer.parseInt(mnc) == config.mnc) {
4674 if (parser.getEventType() == XmlPullParser.TEXT) {
4675 return parser.getText();
4679 } catch (NumberFormatException e) {
4680 loge("NumberFormatException in getProvisioningUrlBaseFromFile: " + e);
4685 } catch (FileNotFoundException e) {
4686 loge("Carrier Provisioning Urls file not found");
4687 } catch (XmlPullParserException e) {
4688 loge("Xml parser exception reading Carrier Provisioning Urls file: " + e);
4689 } catch (IOException e) {
4690 loge("I/O exception reading Carrier Provisioning Urls file: " + e);
4692 if (fileReader != null) {
4695 } catch (IOException e) {}
4702 public String getMobileProvisioningUrl() {
4703 enforceConnectivityInternalPermission();
4704 String url = getProvisioningUrlBaseFromFile();
4705 if (TextUtils.isEmpty(url)) {
4706 url = mContext.getResources().getString(R.string.mobile_provisioning_url);
4707 log("getMobileProvisioningUrl: mobile_provisioining_url from resource =" + url);
4709 log("getMobileProvisioningUrl: mobile_provisioning_url from File =" + url);
4711 // populate the iccid, imei and phone number in the provisioning url.
4712 if (!TextUtils.isEmpty(url)) {
4713 String phoneNumber = mTelephonyManager.getLine1Number();
4714 if (TextUtils.isEmpty(phoneNumber)) {
4715 phoneNumber = "0000000000";
4717 url = String.format(url,
4718 mTelephonyManager.getSimSerialNumber() /* ICCID */,
4719 mTelephonyManager.getDeviceId() /* IMEI */,
4720 phoneNumber /* Phone number */);
4727 public void setProvisioningNotificationVisible(boolean visible, int networkType,
4729 enforceConnectivityInternalPermission();
4730 if (!ConnectivityManager.isNetworkTypeValid(networkType)) {
4733 final long ident = Binder.clearCallingIdentity();
4735 // Concatenate the range of types onto the range of NetIDs.
4736 int id = MAX_NET_ID + 1 + (networkType - ConnectivityManager.TYPE_NONE);
4737 mNotifier.setProvNotificationVisible(visible, id, action);
4739 Binder.restoreCallingIdentity(ident);
4744 public void setAirplaneMode(boolean enable) {
4745 enforceNetworkStackSettingsOrSetup();
4746 final long ident = Binder.clearCallingIdentity();
4748 final ContentResolver cr = mContext.getContentResolver();
4749 Settings.Global.putInt(cr, Settings.Global.AIRPLANE_MODE_ON, encodeBool(enable));
4750 Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
4751 intent.putExtra("state", enable);
4752 mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
4754 Binder.restoreCallingIdentity(ident);
4758 private void onUserStart(int userId) {
4759 synchronized (mVpns) {
4760 Vpn userVpn = mVpns.get(userId);
4761 if (userVpn != null) {
4762 loge("Starting user already has a VPN");
4765 userVpn = new Vpn(mHandler.getLooper(), mContext, mNMS, userId);
4766 mVpns.put(userId, userVpn);
4767 if (mUserManager.getUserInfo(userId).isPrimary() && LockdownVpnTracker.isEnabled()) {
4768 updateLockdownVpn();
4773 private void onUserStop(int userId) {
4774 synchronized (mVpns) {
4775 Vpn userVpn = mVpns.get(userId);
4776 if (userVpn == null) {
4777 loge("Stopped user has no VPN");
4780 userVpn.onUserStopped();
4781 mVpns.delete(userId);
4785 private void onUserAdded(int userId) {
4786 mPermissionMonitor.onUserAdded(userId);
4787 Network defaultNetwork = getNetwork(getDefaultNetwork());
4788 synchronized (mVpns) {
4789 final int vpnsSize = mVpns.size();
4790 for (int i = 0; i < vpnsSize; i++) {
4791 Vpn vpn = mVpns.valueAt(i);
4792 vpn.onUserAdded(userId);
4793 NetworkCapabilities nc = vpn.updateCapabilities(defaultNetwork);
4794 updateVpnCapabilities(vpn, nc);
4799 private void onUserRemoved(int userId) {
4800 mPermissionMonitor.onUserRemoved(userId);
4801 Network defaultNetwork = getNetwork(getDefaultNetwork());
4802 synchronized (mVpns) {
4803 final int vpnsSize = mVpns.size();
4804 for (int i = 0; i < vpnsSize; i++) {
4805 Vpn vpn = mVpns.valueAt(i);
4806 vpn.onUserRemoved(userId);
4807 NetworkCapabilities nc = vpn.updateCapabilities(defaultNetwork);
4808 updateVpnCapabilities(vpn, nc);
4813 private void onPackageAdded(String packageName, int uid) {
4814 if (TextUtils.isEmpty(packageName) || uid < 0) {
4815 Slog.wtf(TAG, "Invalid package in onPackageAdded: " + packageName + " | " + uid);
4818 mPermissionMonitor.onPackageAdded(packageName, uid);
4821 private void onPackageReplaced(String packageName, int uid) {
4822 if (TextUtils.isEmpty(packageName) || uid < 0) {
4823 Slog.wtf(TAG, "Invalid package in onPackageReplaced: " + packageName + " | " + uid);
4826 final int userId = UserHandle.getUserId(uid);
4827 synchronized (mVpns) {
4828 final Vpn vpn = mVpns.get(userId);
4832 // Legacy always-on VPN won't be affected since the package name is not set.
4833 if (TextUtils.equals(vpn.getAlwaysOnPackage(), packageName)) {
4834 Slog.d(TAG, "Restarting always-on VPN package " + packageName + " for user "
4836 vpn.startAlwaysOnVpn();
4841 private void onPackageRemoved(String packageName, int uid, boolean isReplacing) {
4842 if (TextUtils.isEmpty(packageName) || uid < 0) {
4843 Slog.wtf(TAG, "Invalid package in onPackageRemoved: " + packageName + " | " + uid);
4846 mPermissionMonitor.onPackageRemoved(uid);
4848 final int userId = UserHandle.getUserId(uid);
4849 synchronized (mVpns) {
4850 final Vpn vpn = mVpns.get(userId);
4854 // Legacy always-on VPN won't be affected since the package name is not set.
4855 if (TextUtils.equals(vpn.getAlwaysOnPackage(), packageName) && !isReplacing) {
4856 Slog.d(TAG, "Removing always-on VPN package " + packageName + " for user "
4858 vpn.setAlwaysOnPackage(null, false, null);
4863 private void onUserUnlocked(int userId) {
4864 synchronized (mVpns) {
4865 // User present may be sent because of an unlock, which might mean an unlocked keystore.
4866 if (mUserManager.getUserInfo(userId).isPrimary() && LockdownVpnTracker.isEnabled()) {
4867 updateLockdownVpn();
4869 startAlwaysOnVpn(userId);
4874 private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
4876 public void onReceive(Context context, Intent intent) {
4877 ensureRunningOnConnectivityServiceThread();
4878 final String action = intent.getAction();
4879 final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
4880 final int uid = intent.getIntExtra(Intent.EXTRA_UID, -1);
4881 final Uri packageData = intent.getData();
4882 final String packageName =
4883 packageData != null ? packageData.getSchemeSpecificPart() : null;
4884 if (userId == UserHandle.USER_NULL) return;
4886 if (Intent.ACTION_USER_STARTED.equals(action)) {
4887 onUserStart(userId);
4888 } else if (Intent.ACTION_USER_STOPPED.equals(action)) {
4890 } else if (Intent.ACTION_USER_ADDED.equals(action)) {
4891 onUserAdded(userId);
4892 } else if (Intent.ACTION_USER_REMOVED.equals(action)) {
4893 onUserRemoved(userId);
4894 } else if (Intent.ACTION_USER_UNLOCKED.equals(action)) {
4895 onUserUnlocked(userId);
4896 } else if (Intent.ACTION_PACKAGE_ADDED.equals(action)) {
4897 onPackageAdded(packageName, uid);
4898 } else if (Intent.ACTION_PACKAGE_REPLACED.equals(action)) {
4899 onPackageReplaced(packageName, uid);
4900 } else if (Intent.ACTION_PACKAGE_REMOVED.equals(action)) {
4901 final boolean isReplacing = intent.getBooleanExtra(
4902 Intent.EXTRA_REPLACING, false);
4903 onPackageRemoved(packageName, uid, isReplacing);
4908 private BroadcastReceiver mUserPresentReceiver = new BroadcastReceiver() {
4910 public void onReceive(Context context, Intent intent) {
4911 // Try creating lockdown tracker, since user present usually means
4912 // unlocked keystore.
4913 updateLockdownVpn();
4914 mContext.unregisterReceiver(this);
4918 private final HashMap<Messenger, NetworkFactoryInfo> mNetworkFactoryInfos = new HashMap<>();
4919 private final HashMap<NetworkRequest, NetworkRequestInfo> mNetworkRequests = new HashMap<>();
4921 private static final int MAX_NETWORK_REQUESTS_PER_UID = 100;
4922 // Map from UID to number of NetworkRequests that UID has filed.
4923 @GuardedBy("mUidToNetworkRequestCount")
4924 private final SparseIntArray mUidToNetworkRequestCount = new SparseIntArray();
4926 private static class NetworkFactoryInfo {
4927 public final String name;
4928 public final Messenger messenger;
4929 public final AsyncChannel asyncChannel;
4930 public final int factorySerialNumber;
4932 NetworkFactoryInfo(String name, Messenger messenger, AsyncChannel asyncChannel,
4933 int factorySerialNumber) {
4935 this.messenger = messenger;
4936 this.asyncChannel = asyncChannel;
4937 this.factorySerialNumber = factorySerialNumber;
4941 private void ensureNetworkRequestHasType(NetworkRequest request) {
4942 if (request.type == NetworkRequest.Type.NONE) {
4943 throw new IllegalArgumentException(
4944 "All NetworkRequests in ConnectivityService must have a type");
4949 * Tracks info about the requester.
4950 * Also used to notice when the calling process dies so we can self-expire
4952 private class NetworkRequestInfo implements IBinder.DeathRecipient {
4953 final NetworkRequest request;
4954 final PendingIntent mPendingIntent;
4955 boolean mPendingIntentSent;
4956 private final IBinder mBinder;
4959 final Messenger messenger;
4961 NetworkRequestInfo(NetworkRequest r, PendingIntent pi) {
4963 ensureNetworkRequestHasType(request);
4964 mPendingIntent = pi;
4967 mPid = getCallingPid();
4968 mUid = getCallingUid();
4969 enforceRequestCountLimit();
4972 NetworkRequestInfo(Messenger m, NetworkRequest r, IBinder binder) {
4976 ensureNetworkRequestHasType(request);
4978 mPid = getCallingPid();
4979 mUid = getCallingUid();
4980 mPendingIntent = null;
4981 enforceRequestCountLimit();
4984 mBinder.linkToDeath(this, 0);
4985 } catch (RemoteException e) {
4990 private void enforceRequestCountLimit() {
4991 synchronized (mUidToNetworkRequestCount) {
4992 int networkRequests = mUidToNetworkRequestCount.get(mUid, 0) + 1;
4993 if (networkRequests >= MAX_NETWORK_REQUESTS_PER_UID) {
4994 throw new ServiceSpecificException(
4995 ConnectivityManager.Errors.TOO_MANY_REQUESTS);
4997 mUidToNetworkRequestCount.put(mUid, networkRequests);
5001 void unlinkDeathRecipient() {
5002 if (mBinder != null) {
5003 mBinder.unlinkToDeath(this, 0);
5007 public void binderDied() {
5008 log("ConnectivityService NetworkRequestInfo binderDied(" +
5009 request + ", " + mBinder + ")");
5010 releaseNetworkRequest(request);
5013 public String toString() {
5014 return "uid/pid:" + mUid + "/" + mPid + " " + request +
5015 (mPendingIntent == null ? "" : " to trigger " + mPendingIntent);
5019 private void ensureRequestableCapabilities(NetworkCapabilities networkCapabilities) {
5020 final String badCapability = networkCapabilities.describeFirstNonRequestableCapability();
5021 if (badCapability != null) {
5022 throw new IllegalArgumentException("Cannot request network with " + badCapability);
5026 // This checks that the passed capabilities either do not request a specific SSID/SignalStrength
5027 // , or the calling app has permission to do so.
5028 private void ensureSufficientPermissionsForRequest(NetworkCapabilities nc,
5029 int callerPid, int callerUid) {
5030 if (null != nc.getSSID() && !checkSettingsPermission(callerPid, callerUid)) {
5031 throw new SecurityException("Insufficient permissions to request a specific SSID");
5034 if (nc.hasSignalStrength()
5035 && !checkNetworkSignalStrengthWakeupPermission(callerPid, callerUid)) {
5036 throw new SecurityException(
5037 "Insufficient permissions to request a specific signal strength");
5041 private ArrayList<Integer> getSignalStrengthThresholds(NetworkAgentInfo nai) {
5042 final SortedSet<Integer> thresholds = new TreeSet<>();
5043 synchronized (nai) {
5044 for (NetworkRequestInfo nri : mNetworkRequests.values()) {
5045 if (nri.request.networkCapabilities.hasSignalStrength() &&
5046 nai.satisfiesImmutableCapabilitiesOf(nri.request)) {
5047 thresholds.add(nri.request.networkCapabilities.getSignalStrength());
5051 return new ArrayList<>(thresholds);
5054 private void updateSignalStrengthThresholds(
5055 NetworkAgentInfo nai, String reason, NetworkRequest request) {
5056 ArrayList<Integer> thresholdsArray = getSignalStrengthThresholds(nai);
5057 Bundle thresholds = new Bundle();
5058 thresholds.putIntegerArrayList("thresholds", thresholdsArray);
5060 if (VDBG || (DBG && !"CONNECT".equals(reason))) {
5062 if (request != null && request.networkCapabilities.hasSignalStrength()) {
5063 detail = reason + " " + request.networkCapabilities.getSignalStrength();
5067 log(String.format("updateSignalStrengthThresholds: %s, sending %s to %s",
5068 detail, Arrays.toString(thresholdsArray.toArray()), nai.name()));
5071 nai.asyncChannel.sendMessage(
5072 android.net.NetworkAgent.CMD_SET_SIGNAL_STRENGTH_THRESHOLDS,
5076 private void ensureValidNetworkSpecifier(NetworkCapabilities nc) {
5080 NetworkSpecifier ns = nc.getNetworkSpecifier();
5084 MatchAllNetworkSpecifier.checkNotMatchAllNetworkSpecifier(ns);
5085 ns.assertValidFromUid(Binder.getCallingUid());
5089 public NetworkRequest requestNetwork(NetworkCapabilities networkCapabilities,
5090 Messenger messenger, int timeoutMs, IBinder binder, int legacyType) {
5091 final NetworkRequest.Type type = (networkCapabilities == null)
5092 ? NetworkRequest.Type.TRACK_DEFAULT
5093 : NetworkRequest.Type.REQUEST;
5094 // If the requested networkCapabilities is null, take them instead from
5095 // the default network request. This allows callers to keep track of
5096 // the system default network.
5097 if (type == NetworkRequest.Type.TRACK_DEFAULT) {
5098 networkCapabilities = createDefaultNetworkCapabilitiesForUid(Binder.getCallingUid());
5099 enforceAccessPermission();
5101 networkCapabilities = new NetworkCapabilities(networkCapabilities);
5102 enforceNetworkRequestPermissions(networkCapabilities);
5103 // TODO: this is incorrect. We mark the request as metered or not depending on the state
5104 // of the app when the request is filed, but we never change the request if the app
5105 // changes network state. http://b/29964605
5106 enforceMeteredApnPolicy(networkCapabilities);
5108 ensureRequestableCapabilities(networkCapabilities);
5109 ensureSufficientPermissionsForRequest(networkCapabilities,
5110 Binder.getCallingPid(), Binder.getCallingUid());
5111 // Set the UID range for this request to the single UID of the requester, or to an empty
5112 // set of UIDs if the caller has the appropriate permission and UIDs have not been set.
5113 // This will overwrite any allowed UIDs in the requested capabilities. Though there
5114 // are no visible methods to set the UIDs, an app could use reflection to try and get
5115 // networks for other apps so it's essential that the UIDs are overwritten.
5116 restrictRequestUidsForCaller(networkCapabilities);
5118 if (timeoutMs < 0) {
5119 throw new IllegalArgumentException("Bad timeout specified");
5121 ensureValidNetworkSpecifier(networkCapabilities);
5123 NetworkRequest networkRequest = new NetworkRequest(networkCapabilities, legacyType,
5124 nextNetworkRequestId(), type);
5125 NetworkRequestInfo nri = new NetworkRequestInfo(messenger, networkRequest, binder);
5126 if (DBG) log("requestNetwork for " + nri);
5128 mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_REQUEST, nri));
5129 if (timeoutMs > 0) {
5130 mHandler.sendMessageDelayed(mHandler.obtainMessage(EVENT_TIMEOUT_NETWORK_REQUEST,
5133 return networkRequest;
5136 private void enforceNetworkRequestPermissions(NetworkCapabilities networkCapabilities) {
5137 if (networkCapabilities.hasCapability(NET_CAPABILITY_NOT_RESTRICTED) == false) {
5138 enforceConnectivityRestrictedNetworksPermission();
5140 enforceChangePermission();
5145 public boolean requestBandwidthUpdate(Network network) {
5146 enforceAccessPermission();
5147 NetworkAgentInfo nai = null;
5148 if (network == null) {
5151 synchronized (mNetworkForNetId) {
5152 nai = mNetworkForNetId.get(network.netId);
5155 nai.asyncChannel.sendMessage(android.net.NetworkAgent.CMD_REQUEST_BANDWIDTH_UPDATE);
5156 synchronized (mBandwidthRequests) {
5157 final int uid = Binder.getCallingUid();
5158 Integer uidReqs = mBandwidthRequests.get(uid);
5159 if (uidReqs == null) {
5160 uidReqs = new Integer(0);
5162 mBandwidthRequests.put(uid, ++uidReqs);
5169 private boolean isSystem(int uid) {
5170 return uid < Process.FIRST_APPLICATION_UID;
5173 private void enforceMeteredApnPolicy(NetworkCapabilities networkCapabilities) {
5174 final int uid = Binder.getCallingUid();
5175 if (isSystem(uid)) {
5176 // Exemption for system uid.
5179 if (networkCapabilities.hasCapability(NET_CAPABILITY_NOT_METERED)) {
5180 // Policy already enforced.
5183 if (mPolicyManagerInternal.isUidRestrictedOnMeteredNetworks(uid)) {
5184 // If UID is restricted, don't allow them to bring up metered APNs.
5185 networkCapabilities.addCapability(NET_CAPABILITY_NOT_METERED);
5190 public NetworkRequest pendingRequestForNetwork(NetworkCapabilities networkCapabilities,
5191 PendingIntent operation) {
5192 checkNotNull(operation, "PendingIntent cannot be null.");
5193 networkCapabilities = new NetworkCapabilities(networkCapabilities);
5194 enforceNetworkRequestPermissions(networkCapabilities);
5195 enforceMeteredApnPolicy(networkCapabilities);
5196 ensureRequestableCapabilities(networkCapabilities);
5197 ensureSufficientPermissionsForRequest(networkCapabilities,
5198 Binder.getCallingPid(), Binder.getCallingUid());
5199 ensureValidNetworkSpecifier(networkCapabilities);
5200 restrictRequestUidsForCaller(networkCapabilities);
5202 NetworkRequest networkRequest = new NetworkRequest(networkCapabilities, TYPE_NONE,
5203 nextNetworkRequestId(), NetworkRequest.Type.REQUEST);
5204 NetworkRequestInfo nri = new NetworkRequestInfo(networkRequest, operation);
5205 if (DBG) log("pendingRequest for " + nri);
5206 mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_REQUEST_WITH_INTENT,
5208 return networkRequest;
5211 private void releasePendingNetworkRequestWithDelay(PendingIntent operation) {
5212 mHandler.sendMessageDelayed(
5213 mHandler.obtainMessage(EVENT_RELEASE_NETWORK_REQUEST_WITH_INTENT,
5214 getCallingUid(), 0, operation), mReleasePendingIntentDelayMs);
5218 public void releasePendingNetworkRequest(PendingIntent operation) {
5219 checkNotNull(operation, "PendingIntent cannot be null.");
5220 mHandler.sendMessage(mHandler.obtainMessage(EVENT_RELEASE_NETWORK_REQUEST_WITH_INTENT,
5221 getCallingUid(), 0, operation));
5224 // In order to implement the compatibility measure for pre-M apps that call
5225 // WifiManager.enableNetwork(..., true) without also binding to that network explicitly,
5226 // WifiManager registers a network listen for the purpose of calling setProcessDefaultNetwork.
5227 // This ensures it has permission to do so.
5228 private boolean hasWifiNetworkListenPermission(NetworkCapabilities nc) {
5232 int[] transportTypes = nc.getTransportTypes();
5233 if (transportTypes.length != 1 || transportTypes[0] != NetworkCapabilities.TRANSPORT_WIFI) {
5237 mContext.enforceCallingOrSelfPermission(
5238 android.Manifest.permission.ACCESS_WIFI_STATE,
5239 "ConnectivityService");
5240 } catch (SecurityException e) {
5247 public NetworkRequest listenForNetwork(NetworkCapabilities networkCapabilities,
5248 Messenger messenger, IBinder binder) {
5249 if (!hasWifiNetworkListenPermission(networkCapabilities)) {
5250 enforceAccessPermission();
5253 NetworkCapabilities nc = new NetworkCapabilities(networkCapabilities);
5254 ensureSufficientPermissionsForRequest(networkCapabilities,
5255 Binder.getCallingPid(), Binder.getCallingUid());
5256 restrictRequestUidsForCaller(nc);
5257 // Apps without the CHANGE_NETWORK_STATE permission can't use background networks, so
5258 // make all their listens include NET_CAPABILITY_FOREGROUND. That way, they will get
5259 // onLost and onAvailable callbacks when networks move in and out of the background.
5260 // There is no need to do this for requests because an app without CHANGE_NETWORK_STATE
5261 // can't request networks.
5262 restrictBackgroundRequestForCaller(nc);
5263 ensureValidNetworkSpecifier(nc);
5265 NetworkRequest networkRequest = new NetworkRequest(nc, TYPE_NONE, nextNetworkRequestId(),
5266 NetworkRequest.Type.LISTEN);
5267 NetworkRequestInfo nri = new NetworkRequestInfo(messenger, networkRequest, binder);
5268 if (VDBG) log("listenForNetwork for " + nri);
5270 mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_LISTENER, nri));
5271 return networkRequest;
5275 public void pendingListenForNetwork(NetworkCapabilities networkCapabilities,
5276 PendingIntent operation) {
5277 checkNotNull(operation, "PendingIntent cannot be null.");
5278 if (!hasWifiNetworkListenPermission(networkCapabilities)) {
5279 enforceAccessPermission();
5281 ensureValidNetworkSpecifier(networkCapabilities);
5282 ensureSufficientPermissionsForRequest(networkCapabilities,
5283 Binder.getCallingPid(), Binder.getCallingUid());
5285 final NetworkCapabilities nc = new NetworkCapabilities(networkCapabilities);
5286 restrictRequestUidsForCaller(nc);
5288 NetworkRequest networkRequest = new NetworkRequest(nc, TYPE_NONE, nextNetworkRequestId(),
5289 NetworkRequest.Type.LISTEN);
5290 NetworkRequestInfo nri = new NetworkRequestInfo(networkRequest, operation);
5291 if (VDBG) log("pendingListenForNetwork for " + nri);
5293 mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_LISTENER, nri));
5297 public void releaseNetworkRequest(NetworkRequest networkRequest) {
5298 ensureNetworkRequestHasType(networkRequest);
5299 mHandler.sendMessage(mHandler.obtainMessage(
5300 EVENT_RELEASE_NETWORK_REQUEST, getCallingUid(), 0, networkRequest));
5304 public int registerNetworkFactory(Messenger messenger, String name) {
5305 enforceConnectivityInternalPermission();
5306 NetworkFactoryInfo nfi = new NetworkFactoryInfo(name, messenger, new AsyncChannel(),
5307 NetworkFactory.SerialNumber.nextSerialNumber());
5308 mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_FACTORY, nfi));
5309 return nfi.factorySerialNumber;
5312 private void handleRegisterNetworkFactory(NetworkFactoryInfo nfi) {
5313 if (DBG) log("Got NetworkFactory Messenger for " + nfi.name);
5314 mNetworkFactoryInfos.put(nfi.messenger, nfi);
5315 nfi.asyncChannel.connect(mContext, mTrackerHandler, nfi.messenger);
5319 public void unregisterNetworkFactory(Messenger messenger) {
5320 enforceConnectivityInternalPermission();
5321 mHandler.sendMessage(mHandler.obtainMessage(EVENT_UNREGISTER_NETWORK_FACTORY, messenger));
5324 private void handleUnregisterNetworkFactory(Messenger messenger) {
5325 NetworkFactoryInfo nfi = mNetworkFactoryInfos.remove(messenger);
5327 loge("Failed to find Messenger in unregisterNetworkFactory");
5330 if (DBG) log("unregisterNetworkFactory for " + nfi.name);
5334 * NetworkAgentInfo supporting a request by requestId.
5335 * These have already been vetted (their Capabilities satisfy the request)
5336 * and the are the highest scored network available.
5337 * the are keyed off the Requests requestId.
5339 // NOTE: Accessed on multiple threads, must be synchronized on itself.
5340 @GuardedBy("mNetworkForRequestId")
5341 private final SparseArray<NetworkAgentInfo> mNetworkForRequestId = new SparseArray<>();
5343 // NOTE: Accessed on multiple threads, must be synchronized on itself.
5344 @GuardedBy("mNetworkForNetId")
5345 private final SparseArray<NetworkAgentInfo> mNetworkForNetId = new SparseArray<>();
5346 // NOTE: Accessed on multiple threads, synchronized with mNetworkForNetId.
5347 // An entry is first added to mNetIdInUse, prior to mNetworkForNetId, so
5348 // there may not be a strict 1:1 correlation between the two.
5349 @GuardedBy("mNetworkForNetId")
5350 private final SparseBooleanArray mNetIdInUse = new SparseBooleanArray();
5352 // NetworkAgentInfo keyed off its connecting messenger
5353 // TODO - eval if we can reduce the number of lists/hashmaps/sparsearrays
5354 // NOTE: Only should be accessed on ConnectivityServiceThread, except dump().
5355 private final HashMap<Messenger, NetworkAgentInfo> mNetworkAgentInfos = new HashMap<>();
5357 @GuardedBy("mBlockedAppUids")
5358 private final HashSet<Integer> mBlockedAppUids = new HashSet<>();
5360 // Note: if mDefaultRequest is changed, NetworkMonitor needs to be updated.
5361 private final NetworkRequest mDefaultRequest;
5363 // Request used to optionally keep mobile data active even when higher
5364 // priority networks like Wi-Fi are active.
5365 private final NetworkRequest mDefaultMobileDataRequest;
5367 // Request used to optionally keep wifi data active even when higher
5368 // priority networks like ethernet are active.
5369 private final NetworkRequest mDefaultWifiRequest;
5371 private NetworkAgentInfo getNetworkForRequest(int requestId) {
5372 synchronized (mNetworkForRequestId) {
5373 return mNetworkForRequestId.get(requestId);
5377 private void clearNetworkForRequest(int requestId) {
5378 synchronized (mNetworkForRequestId) {
5379 mNetworkForRequestId.remove(requestId);
5383 private void setNetworkForRequest(int requestId, NetworkAgentInfo nai) {
5384 synchronized (mNetworkForRequestId) {
5385 mNetworkForRequestId.put(requestId, nai);
5389 private NetworkAgentInfo getDefaultNetwork() {
5390 return getNetworkForRequest(mDefaultRequest.requestId);
5394 private Network getNetwork(@Nullable NetworkAgentInfo nai) {
5395 return nai != null ? nai.network : null;
5398 private void ensureRunningOnConnectivityServiceThread() {
5399 if (mHandler.getLooper().getThread() != Thread.currentThread()) {
5400 throw new IllegalStateException(
5401 "Not running on ConnectivityService thread: "
5402 + Thread.currentThread().getName());
5407 protected boolean isDefaultNetwork(NetworkAgentInfo nai) {
5408 return nai == getDefaultNetwork();
5411 private boolean isDefaultRequest(NetworkRequestInfo nri) {
5412 return nri.request.requestId == mDefaultRequest.requestId;
5415 // TODO : remove this method. It's a stopgap measure to help sheperding a number of dependent
5416 // changes that would conflict throughout the automerger graph. Having this method temporarily
5417 // helps with the process of going through with all these dependent changes across the entire
5419 public int registerNetworkAgent(Messenger messenger, NetworkInfo networkInfo,
5420 LinkProperties linkProperties, NetworkCapabilities networkCapabilities,
5421 int currentScore, NetworkMisc networkMisc) {
5422 return registerNetworkAgent(messenger, networkInfo, linkProperties, networkCapabilities,
5423 currentScore, networkMisc, NetworkFactory.SerialNumber.NONE);
5427 * Register a new agent with ConnectivityService to handle a network.
5429 * @param messenger a messenger for ConnectivityService to contact the agent asynchronously.
5430 * @param networkInfo the initial info associated with this network. It can be updated later :
5431 * see {@link #updateNetworkInfo}.
5432 * @param linkProperties the initial link properties of this network. They can be updated
5433 * later : see {@link #updateLinkProperties}.
5434 * @param networkCapabilities the initial capabilites of this network. They can be updated
5435 * later : see {@link #updateNetworkCapabilities}.
5436 * @param currentScore the initial score of the network. See
5437 * {@link NetworkAgentInfo#getCurrentScore}.
5438 * @param networkMisc metadata about the network. This is never updated.
5439 * @param factorySerialNumber the serial number of the factory owning this NetworkAgent.
5441 public int registerNetworkAgent(Messenger messenger, NetworkInfo networkInfo,
5442 LinkProperties linkProperties, NetworkCapabilities networkCapabilities,
5443 int currentScore, NetworkMisc networkMisc, int factorySerialNumber) {
5444 enforceConnectivityInternalPermission();
5446 LinkProperties lp = new LinkProperties(linkProperties);
5447 lp.ensureDirectlyConnectedRoutes();
5448 // TODO: Instead of passing mDefaultRequest, provide an API to determine whether a Network
5449 // satisfies mDefaultRequest.
5450 final NetworkCapabilities nc = new NetworkCapabilities(networkCapabilities);
5451 final NetworkAgentInfo nai = new NetworkAgentInfo(messenger, new AsyncChannel(),
5452 new Network(reserveNetId()), new NetworkInfo(networkInfo), lp, nc, currentScore,
5453 mContext, mTrackerHandler, new NetworkMisc(networkMisc), this, mNetd, mDnsResolver,
5454 mNMS, factorySerialNumber);
5455 // Make sure the network capabilities reflect what the agent info says.
5456 nai.setNetworkCapabilities(mixInCapabilities(nai, nc));
5457 final String extraInfo = networkInfo.getExtraInfo();
5458 final String name = TextUtils.isEmpty(extraInfo)
5459 ? nai.networkCapabilities.getSSID() : extraInfo;
5460 if (DBG) log("registerNetworkAgent " + nai);
5461 final long token = Binder.clearCallingIdentity();
5463 getNetworkStack().makeNetworkMonitor(
5464 nai.network, name, new NetworkMonitorCallbacks(nai));
5466 Binder.restoreCallingIdentity(token);
5468 // NetworkAgentInfo registration will finish when the NetworkMonitor is created.
5469 // If the network disconnects or sends any other event before that, messages are deferred by
5470 // NetworkAgent until nai.asyncChannel.connect(), which will be called when finalizing the
5472 return nai.network.netId;
5476 protected NetworkStackClient getNetworkStack() {
5477 return NetworkStackClient.getInstance();
5480 private void handleRegisterNetworkAgent(NetworkAgentInfo nai, INetworkMonitor networkMonitor) {
5481 nai.onNetworkMonitorCreated(networkMonitor);
5482 if (VDBG) log("Got NetworkAgent Messenger");
5483 mNetworkAgentInfos.put(nai.messenger, nai);
5484 synchronized (mNetworkForNetId) {
5485 mNetworkForNetId.put(nai.network.netId, nai);
5489 networkMonitor.start();
5490 } catch (RemoteException e) {
5491 e.rethrowAsRuntimeException();
5493 nai.asyncChannel.connect(mContext, mTrackerHandler, nai.messenger);
5494 NetworkInfo networkInfo = nai.networkInfo;
5495 nai.networkInfo = null;
5496 updateNetworkInfo(nai, networkInfo);
5497 updateUids(nai, null, nai.networkCapabilities);
5500 private void updateLinkProperties(NetworkAgentInfo networkAgent, LinkProperties newLp,
5501 LinkProperties oldLp) {
5502 int netId = networkAgent.network.netId;
5504 // The NetworkAgentInfo does not know whether clatd is running on its network or not, or
5505 // whether there is a NAT64 prefix. Before we do anything else, make sure its LinkProperties
5507 networkAgent.clatd.fixupLinkProperties(oldLp, newLp);
5509 updateInterfaces(newLp, oldLp, netId, networkAgent.networkCapabilities);
5511 // update filtering rules, need to happen after the interface update so netd knows about the
5512 // new interface (the interface name -> index map becomes initialized)
5513 updateVpnFiltering(newLp, oldLp, networkAgent);
5515 updateMtu(newLp, oldLp);
5516 // TODO - figure out what to do for clat
5517 // for (LinkProperties lp : newLp.getStackedLinks()) {
5518 // updateMtu(lp, null);
5520 if (isDefaultNetwork(networkAgent)) {
5521 updateTcpBufferSizes(newLp.getTcpBufferSizes());
5524 updateRoutes(newLp, oldLp, netId);
5525 updateDnses(newLp, oldLp, netId);
5526 // Make sure LinkProperties represents the latest private DNS status.
5527 // This does not need to be done before updateDnses because the
5528 // LinkProperties are not the source of the private DNS configuration.
5529 // updateDnses will fetch the private DNS configuration from DnsManager.
5530 mDnsManager.updatePrivateDnsStatus(netId, newLp);
5532 if (isDefaultNetwork(networkAgent)) {
5533 handleApplyDefaultProxy(newLp.getHttpProxy());
5535 updateProxy(newLp, oldLp);
5537 // TODO - move this check to cover the whole function
5538 if (!Objects.equals(newLp, oldLp)) {
5539 synchronized (networkAgent) {
5540 networkAgent.linkProperties = newLp;
5542 // Start or stop DNS64 detection and 464xlat according to network state.
5543 networkAgent.clatd.update();
5544 notifyIfacesChangedForNetworkStats();
5546 networkAgent.networkMonitor().notifyLinkPropertiesChanged(newLp);
5547 } catch (RemoteException e) {
5548 e.rethrowAsRuntimeException();
5550 if (networkAgent.everConnected) {
5551 notifyNetworkCallbacks(networkAgent, ConnectivityManager.CALLBACK_IP_CHANGED);
5555 mKeepaliveTracker.handleCheckKeepalivesStillValid(networkAgent);
5558 private void wakeupModifyInterface(String iface, NetworkCapabilities caps, boolean add) {
5559 // Marks are only available on WiFi interfaces. Checking for
5560 // marks on unsupported interfaces is harmless.
5561 if (!caps.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
5565 int mark = mContext.getResources().getInteger(
5566 com.android.internal.R.integer.config_networkWakeupPacketMark);
5567 int mask = mContext.getResources().getInteger(
5568 com.android.internal.R.integer.config_networkWakeupPacketMask);
5570 // Mask/mark of zero will not detect anything interesting.
5571 // Don't install rules unless both values are nonzero.
5572 if (mark == 0 || mask == 0) {
5576 final String prefix = "iface:" + iface;
5579 mNetd.wakeupAddInterface(iface, prefix, mark, mask);
5581 mNetd.wakeupDelInterface(iface, prefix, mark, mask);
5583 } catch (Exception e) {
5584 loge("Exception modifying wakeup packet monitoring: " + e);
5589 private void updateInterfaces(LinkProperties newLp, LinkProperties oldLp, int netId,
5590 NetworkCapabilities caps) {
5591 CompareResult<String> interfaceDiff = new CompareResult<>(
5592 oldLp != null ? oldLp.getAllInterfaceNames() : null,
5593 newLp != null ? newLp.getAllInterfaceNames() : null);
5594 for (String iface : interfaceDiff.added) {
5596 if (DBG) log("Adding iface " + iface + " to network " + netId);
5597 mNMS.addInterfaceToNetwork(iface, netId);
5598 wakeupModifyInterface(iface, caps, true);
5599 } catch (Exception e) {
5600 loge("Exception adding interface: " + e);
5603 for (String iface : interfaceDiff.removed) {
5605 if (DBG) log("Removing iface " + iface + " from network " + netId);
5606 wakeupModifyInterface(iface, caps, false);
5607 mNMS.removeInterfaceFromNetwork(iface, netId);
5608 } catch (Exception e) {
5609 loge("Exception removing interface: " + e);
5615 * Have netd update routes from oldLp to newLp.
5616 * @return true if routes changed between oldLp and newLp
5618 private boolean updateRoutes(LinkProperties newLp, LinkProperties oldLp, int netId) {
5619 // Compare the route diff to determine which routes should be added and removed.
5620 CompareResult<RouteInfo> routeDiff = new CompareResult<RouteInfo>(
5621 oldLp != null ? oldLp.getAllRoutes() : null,
5622 newLp != null ? newLp.getAllRoutes() : null);
5624 // add routes before removing old in case it helps with continuous connectivity
5626 // do this twice, adding non-next-hop routes first, then routes they are dependent on
5627 for (RouteInfo route : routeDiff.added) {
5628 if (route.hasGateway()) continue;
5629 if (VDBG || DDBG) log("Adding Route [" + route + "] to network " + netId);
5631 mNMS.addRoute(netId, route);
5632 } catch (Exception e) {
5633 if ((route.getDestination().getAddress() instanceof Inet4Address) || VDBG) {
5634 loge("Exception in addRoute for non-gateway: " + e);
5638 for (RouteInfo route : routeDiff.added) {
5639 if (route.hasGateway() == false) continue;
5640 if (VDBG || DDBG) log("Adding Route [" + route + "] to network " + netId);
5642 mNMS.addRoute(netId, route);
5643 } catch (Exception e) {
5644 if ((route.getGateway() instanceof Inet4Address) || VDBG) {
5645 loge("Exception in addRoute for gateway: " + e);
5650 for (RouteInfo route : routeDiff.removed) {
5651 if (VDBG || DDBG) log("Removing Route [" + route + "] from network " + netId);
5653 mNMS.removeRoute(netId, route);
5654 } catch (Exception e) {
5655 loge("Exception in removeRoute: " + e);
5658 return !routeDiff.added.isEmpty() || !routeDiff.removed.isEmpty();
5661 private void updateDnses(LinkProperties newLp, LinkProperties oldLp, int netId) {
5662 if (oldLp != null && newLp.isIdenticalDnses(oldLp)) {
5663 return; // no updating necessary
5666 final NetworkAgentInfo defaultNai = getDefaultNetwork();
5667 final boolean isDefaultNetwork = (defaultNai != null && defaultNai.network.netId == netId);
5670 final Collection<InetAddress> dnses = newLp.getDnsServers();
5671 log("Setting DNS servers for network " + netId + " to " + dnses);
5674 mDnsManager.setDnsConfigurationForNetwork(netId, newLp, isDefaultNetwork);
5675 } catch (Exception e) {
5676 loge("Exception in setDnsConfigurationForNetwork: " + e);
5680 private void updateVpnFiltering(LinkProperties newLp, LinkProperties oldLp,
5681 NetworkAgentInfo nai) {
5682 final String oldIface = oldLp != null ? oldLp.getInterfaceName() : null;
5683 final String newIface = newLp != null ? newLp.getInterfaceName() : null;
5684 final boolean wasFiltering = requiresVpnIsolation(nai, nai.networkCapabilities, oldLp);
5685 final boolean needsFiltering = requiresVpnIsolation(nai, nai.networkCapabilities, newLp);
5687 if (!wasFiltering && !needsFiltering) {
5692 if (Objects.equals(oldIface, newIface) && (wasFiltering == needsFiltering)) {
5697 final Set<UidRange> ranges = nai.networkCapabilities.getUids();
5698 final int vpnAppUid = nai.networkCapabilities.getEstablishingVpnAppUid();
5699 // TODO: this create a window of opportunity for apps to receive traffic between the time
5700 // when the old rules are removed and the time when new rules are added. To fix this,
5701 // make eBPF support two whitelisted interfaces so here new rules can be added before the
5702 // old rules are being removed.
5704 mPermissionMonitor.onVpnUidRangesRemoved(oldIface, ranges, vpnAppUid);
5706 if (needsFiltering) {
5707 mPermissionMonitor.onVpnUidRangesAdded(newIface, ranges, vpnAppUid);
5711 private int getNetworkPermission(NetworkCapabilities nc) {
5712 if (!nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)) {
5713 return INetd.PERMISSION_SYSTEM;
5715 if (!nc.hasCapability(NET_CAPABILITY_FOREGROUND)) {
5716 return INetd.PERMISSION_NETWORK;
5718 return INetd.PERMISSION_NONE;
5722 * Augments the NetworkCapabilities passed in by a NetworkAgent with capabilities that are
5723 * maintained here that the NetworkAgent is not aware of (e.g., validated, captive portal,
5724 * and foreground status).
5726 private NetworkCapabilities mixInCapabilities(NetworkAgentInfo nai, NetworkCapabilities nc) {
5727 // Once a NetworkAgent is connected, complain if some immutable capabilities are removed.
5728 // Don't complain for VPNs since they're not driven by requests and there is no risk of
5729 // causing a connect/teardown loop.
5730 // TODO: remove this altogether and make it the responsibility of the NetworkFactories to
5731 // avoid connect/teardown loops.
5732 if (nai.everConnected &&
5734 !nai.networkCapabilities.satisfiedByImmutableNetworkCapabilities(nc)) {
5735 // TODO: consider not complaining when a network agent degrades its capabilities if this
5736 // does not cause any request (that is not a listen) currently matching that agent to
5737 // stop being matched by the updated agent.
5738 String diff = nai.networkCapabilities.describeImmutableDifferences(nc);
5739 if (!TextUtils.isEmpty(diff)) {
5740 Slog.wtf(TAG, "BUG: " + nai + " lost immutable capabilities:" + diff);
5744 // Don't modify caller's NetworkCapabilities.
5745 NetworkCapabilities newNc = new NetworkCapabilities(nc);
5746 if (nai.lastValidated) {
5747 newNc.addCapability(NET_CAPABILITY_VALIDATED);
5749 newNc.removeCapability(NET_CAPABILITY_VALIDATED);
5751 if (nai.lastCaptivePortalDetected) {
5752 newNc.addCapability(NET_CAPABILITY_CAPTIVE_PORTAL);
5754 newNc.removeCapability(NET_CAPABILITY_CAPTIVE_PORTAL);
5756 if (nai.isBackgroundNetwork()) {
5757 newNc.removeCapability(NET_CAPABILITY_FOREGROUND);
5759 newNc.addCapability(NET_CAPABILITY_FOREGROUND);
5761 if (nai.isSuspended()) {
5762 newNc.removeCapability(NET_CAPABILITY_NOT_SUSPENDED);
5764 newNc.addCapability(NET_CAPABILITY_NOT_SUSPENDED);
5766 if (nai.partialConnectivity) {
5767 newNc.addCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY);
5769 newNc.removeCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY);
5776 * Update the NetworkCapabilities for {@code nai} to {@code nc}. Specifically:
5778 * 1. Calls mixInCapabilities to merge the passed-in NetworkCapabilities {@code nc} with the
5779 * capabilities we manage and store in {@code nai}, such as validated status and captive
5781 * 2. Takes action on the result: changes network permissions, sends CAP_CHANGED callbacks, and
5782 * potentially triggers rematches.
5783 * 3. Directly informs other network stack components (NetworkStatsService, VPNs, etc. of the
5786 * @param oldScore score of the network before any of the changes that prompted us
5787 * to call this function.
5788 * @param nai the network having its capabilities updated.
5789 * @param nc the new network capabilities.
5791 private void updateCapabilities(int oldScore, NetworkAgentInfo nai, NetworkCapabilities nc) {
5792 NetworkCapabilities newNc = mixInCapabilities(nai, nc);
5794 if (Objects.equals(nai.networkCapabilities, newNc)) return;
5796 final int oldPermission = getNetworkPermission(nai.networkCapabilities);
5797 final int newPermission = getNetworkPermission(newNc);
5798 if (oldPermission != newPermission && nai.created && !nai.isVPN()) {
5800 mNMS.setNetworkPermission(nai.network.netId, newPermission);
5801 } catch (RemoteException e) {
5802 loge("Exception in setNetworkPermission: " + e);
5806 final NetworkCapabilities prevNc;
5807 synchronized (nai) {
5808 prevNc = nai.networkCapabilities;
5809 nai.setNetworkCapabilities(newNc);
5812 updateUids(nai, prevNc, newNc);
5814 if (nai.getCurrentScore() == oldScore && newNc.equalRequestableCapabilities(prevNc)) {
5815 // If the requestable capabilities haven't changed, and the score hasn't changed, then
5816 // the change we're processing can't affect any requests, it can only affect the listens
5817 // on this network. We might have been called by rematchNetworkAndRequests when a
5818 // network changed foreground state.
5819 processListenRequests(nai, true);
5821 // If the requestable capabilities have changed or the score changed, we can't have been
5822 // called by rematchNetworkAndRequests, so it's safe to start a rematch.
5823 rematchAllNetworksAndRequests(nai, oldScore);
5824 notifyNetworkCallbacks(nai, ConnectivityManager.CALLBACK_CAP_CHANGED);
5827 if (prevNc != null) {
5828 final boolean oldMetered = prevNc.isMetered();
5829 final boolean newMetered = newNc.isMetered();
5830 final boolean meteredChanged = oldMetered != newMetered;
5832 if (meteredChanged) {
5833 maybeNotifyNetworkBlocked(nai, oldMetered, newMetered, mRestrictBackground,
5834 mRestrictBackground);
5837 final boolean roamingChanged = prevNc.hasCapability(NET_CAPABILITY_NOT_ROAMING) !=
5838 newNc.hasCapability(NET_CAPABILITY_NOT_ROAMING);
5840 // Report changes that are interesting for network statistics tracking.
5841 if (meteredChanged || roamingChanged) {
5842 notifyIfacesChangedForNetworkStats();
5846 if (!newNc.hasTransport(TRANSPORT_VPN)) {
5847 // Tell VPNs about updated capabilities, since they may need to
5848 // bubble those changes through.
5849 updateAllVpnsCapabilities();
5854 * Returns whether VPN isolation (ingress interface filtering) should be applied on the given
5857 * Ingress interface filtering enforces that all apps under the given network can only receive
5858 * packets from the network's interface (and loopback). This is important for VPNs because
5859 * apps that cannot bypass a fully-routed VPN shouldn't be able to receive packets from any
5860 * non-VPN interfaces.
5862 * As a result, this method should return true iff
5863 * 1. the network is an app VPN (not legacy VPN)
5864 * 2. the VPN does not allow bypass
5865 * 3. the VPN is fully-routed
5866 * 4. the VPN interface is non-null
5868 * @See INetd#firewallAddUidInterfaceRules
5869 * @See INetd#firewallRemoveUidInterfaceRules
5871 private boolean requiresVpnIsolation(@NonNull NetworkAgentInfo nai, NetworkCapabilities nc,
5872 LinkProperties lp) {
5873 if (nc == null || lp == null) return false;
5875 && !nai.networkMisc.allowBypass
5876 && nc.getEstablishingVpnAppUid() != Process.SYSTEM_UID
5877 && lp.getInterfaceName() != null
5878 && (lp.hasIPv4DefaultRoute() || lp.hasIPv6DefaultRoute());
5881 private void updateUids(NetworkAgentInfo nai, NetworkCapabilities prevNc,
5882 NetworkCapabilities newNc) {
5883 Set<UidRange> prevRanges = null == prevNc ? null : prevNc.getUids();
5884 Set<UidRange> newRanges = null == newNc ? null : newNc.getUids();
5885 if (null == prevRanges) prevRanges = new ArraySet<>();
5886 if (null == newRanges) newRanges = new ArraySet<>();
5887 final Set<UidRange> prevRangesCopy = new ArraySet<>(prevRanges);
5889 prevRanges.removeAll(newRanges);
5890 newRanges.removeAll(prevRangesCopy);
5893 // When updating the VPN uid routing rules, add the new range first then remove the old
5894 // range. If old range were removed first, there would be a window between the old
5895 // range being removed and the new range being added, during which UIDs contained
5896 // in both ranges are not subject to any VPN routing rules. Adding new range before
5897 // removing old range works because, unlike the filtering rules below, it's possible to
5898 // add duplicate UID routing rules.
5899 if (!newRanges.isEmpty()) {
5900 final UidRange[] addedRangesArray = new UidRange[newRanges.size()];
5901 newRanges.toArray(addedRangesArray);
5902 mNMS.addVpnUidRanges(nai.network.netId, addedRangesArray);
5904 if (!prevRanges.isEmpty()) {
5905 final UidRange[] removedRangesArray = new UidRange[prevRanges.size()];
5906 prevRanges.toArray(removedRangesArray);
5907 mNMS.removeVpnUidRanges(nai.network.netId, removedRangesArray);
5909 final boolean wasFiltering = requiresVpnIsolation(nai, prevNc, nai.linkProperties);
5910 final boolean shouldFilter = requiresVpnIsolation(nai, newNc, nai.linkProperties);
5911 final String iface = nai.linkProperties.getInterfaceName();
5912 // For VPN uid interface filtering, old ranges need to be removed before new ranges can
5913 // be added, due to the range being expanded and stored as invidiual UIDs. For example
5914 // the UIDs might be updated from [0, 99999] to ([0, 10012], [10014, 99999]) which means
5915 // prevRanges = [0, 99999] while newRanges = [0, 10012], [10014, 99999]. If prevRanges
5916 // were added first and then newRanges got removed later, there would be only one uid
5917 // 10013 left. A consequence of removing old ranges before adding new ranges is that
5918 // there is now a window of opportunity when the UIDs are not subject to any filtering.
5919 // Note that this is in contrast with the (more robust) update of VPN routing rules
5920 // above, where the addition of new ranges happens before the removal of old ranges.
5921 // TODO Fix this window by computing an accurate diff on Set<UidRange>, so the old range
5922 // to be removed will never overlap with the new range to be added.
5923 if (wasFiltering && !prevRanges.isEmpty()) {
5924 mPermissionMonitor.onVpnUidRangesRemoved(iface, prevRanges,
5925 prevNc.getEstablishingVpnAppUid());
5927 if (shouldFilter && !newRanges.isEmpty()) {
5928 mPermissionMonitor.onVpnUidRangesAdded(iface, newRanges,
5929 newNc.getEstablishingVpnAppUid());
5931 } catch (Exception e) {
5933 loge("Exception in updateUids: ", e);
5937 public void handleUpdateLinkProperties(NetworkAgentInfo nai, LinkProperties newLp) {
5938 ensureRunningOnConnectivityServiceThread();
5940 if (getNetworkAgentInfoForNetId(nai.network.netId) != nai) {
5941 // Ignore updates for disconnected networks
5944 // newLp is already a defensive copy.
5945 newLp.ensureDirectlyConnectedRoutes();
5947 log("Update of LinkProperties for " + nai.name() +
5948 "; created=" + nai.created +
5949 "; everConnected=" + nai.everConnected);
5951 updateLinkProperties(nai, newLp, new LinkProperties(nai.linkProperties));
5954 private void sendUpdatedScoreToFactories(NetworkAgentInfo nai) {
5955 for (int i = 0; i < nai.numNetworkRequests(); i++) {
5956 NetworkRequest nr = nai.requestAt(i);
5957 // Don't send listening requests to factories. b/17393458
5958 if (nr.isListen()) continue;
5959 sendUpdatedScoreToFactories(nr, nai);
5963 private void sendUpdatedScoreToFactories(NetworkRequest networkRequest, NetworkAgentInfo nai) {
5967 score = nai.getCurrentScore();
5968 serial = nai.factorySerialNumber;
5971 log("sending new Min Network Score(" + score + "): " + networkRequest.toString());
5973 for (NetworkFactoryInfo nfi : mNetworkFactoryInfos.values()) {
5974 nfi.asyncChannel.sendMessage(android.net.NetworkFactory.CMD_REQUEST_NETWORK, score,
5975 serial, networkRequest);
5979 private void sendPendingIntentForRequest(NetworkRequestInfo nri, NetworkAgentInfo networkAgent,
5980 int notificationType) {
5981 if (notificationType == ConnectivityManager.CALLBACK_AVAILABLE && !nri.mPendingIntentSent) {
5982 Intent intent = new Intent();
5983 intent.putExtra(ConnectivityManager.EXTRA_NETWORK, networkAgent.network);
5984 intent.putExtra(ConnectivityManager.EXTRA_NETWORK_REQUEST, nri.request);
5985 nri.mPendingIntentSent = true;
5986 sendIntent(nri.mPendingIntent, intent);
5991 private void sendIntent(PendingIntent pendingIntent, Intent intent) {
5992 mPendingIntentWakeLock.acquire();
5994 if (DBG) log("Sending " + pendingIntent);
5995 pendingIntent.send(mContext, 0, intent, this /* onFinished */, null /* Handler */);
5996 } catch (PendingIntent.CanceledException e) {
5997 if (DBG) log(pendingIntent + " was not sent, it had been canceled.");
5998 mPendingIntentWakeLock.release();
5999 releasePendingNetworkRequest(pendingIntent);
6001 // ...otherwise, mPendingIntentWakeLock.release() gets called by onSendFinished()
6005 public void onSendFinished(PendingIntent pendingIntent, Intent intent, int resultCode,
6006 String resultData, Bundle resultExtras) {
6007 if (DBG) log("Finished sending " + pendingIntent);
6008 mPendingIntentWakeLock.release();
6009 // Release with a delay so the receiving client has an opportunity to put in its
6011 releasePendingNetworkRequestWithDelay(pendingIntent);
6014 private void callCallbackForRequest(NetworkRequestInfo nri,
6015 NetworkAgentInfo networkAgent, int notificationType, int arg1) {
6016 if (nri.messenger == null) {
6017 return; // Default request has no msgr
6019 Bundle bundle = new Bundle();
6020 // TODO: check if defensive copies of data is needed.
6021 putParcelable(bundle, new NetworkRequest(nri.request));
6022 Message msg = Message.obtain();
6023 if (notificationType != ConnectivityManager.CALLBACK_UNAVAIL) {
6024 putParcelable(bundle, networkAgent.network);
6026 switch (notificationType) {
6027 case ConnectivityManager.CALLBACK_AVAILABLE: {
6028 putParcelable(bundle, networkCapabilitiesRestrictedForCallerPermissions(
6029 networkAgent.networkCapabilities, nri.mPid, nri.mUid));
6030 putParcelable(bundle, new LinkProperties(networkAgent.linkProperties));
6031 // For this notification, arg1 contains the blocked status.
6035 case ConnectivityManager.CALLBACK_LOSING: {
6039 case ConnectivityManager.CALLBACK_CAP_CHANGED: {
6040 // networkAgent can't be null as it has been accessed a few lines above.
6041 final NetworkCapabilities nc = networkCapabilitiesRestrictedForCallerPermissions(
6042 networkAgent.networkCapabilities, nri.mPid, nri.mUid);
6043 putParcelable(bundle, nc);
6046 case ConnectivityManager.CALLBACK_IP_CHANGED: {
6047 putParcelable(bundle, new LinkProperties(networkAgent.linkProperties));
6050 case ConnectivityManager.CALLBACK_BLK_CHANGED: {
6051 maybeLogBlockedStatusChanged(nri, networkAgent.network, arg1 != 0);
6056 msg.what = notificationType;
6057 msg.setData(bundle);
6060 String notification = ConnectivityManager.getCallbackName(notificationType);
6061 log("sending notification " + notification + " for " + nri.request);
6063 nri.messenger.send(msg);
6064 } catch (RemoteException e) {
6065 // may occur naturally in the race of binder death.
6066 loge("RemoteException caught trying to send a callback msg for " + nri.request);
6070 private static <T extends Parcelable> void putParcelable(Bundle bundle, T t) {
6071 bundle.putParcelable(t.getClass().getSimpleName(), t);
6074 private void teardownUnneededNetwork(NetworkAgentInfo nai) {
6075 if (nai.numRequestNetworkRequests() != 0) {
6076 for (int i = 0; i < nai.numNetworkRequests(); i++) {
6077 NetworkRequest nr = nai.requestAt(i);
6078 // Ignore listening requests.
6079 if (nr.isListen()) continue;
6080 loge("Dead network still had at least " + nr);
6084 nai.asyncChannel.disconnect();
6087 private void handleLingerComplete(NetworkAgentInfo oldNetwork) {
6088 if (oldNetwork == null) {
6089 loge("Unknown NetworkAgentInfo in handleLingerComplete");
6092 if (DBG) log("handleLingerComplete for " + oldNetwork.name());
6094 // If we get here it means that the last linger timeout for this network expired. So there
6095 // must be no other active linger timers, and we must stop lingering.
6096 oldNetwork.clearLingerState();
6098 if (unneeded(oldNetwork, UnneededFor.TEARDOWN)) {
6099 // Tear the network down.
6100 teardownUnneededNetwork(oldNetwork);
6102 // Put the network in the background.
6103 updateCapabilities(oldNetwork.getCurrentScore(), oldNetwork,
6104 oldNetwork.networkCapabilities);
6108 private void makeDefault(NetworkAgentInfo newNetwork) {
6109 if (DBG) log("Switching to new default network: " + newNetwork);
6112 mNMS.setDefaultNetId(newNetwork.network.netId);
6113 } catch (Exception e) {
6114 loge("Exception setting default network :" + e);
6117 notifyLockdownVpn(newNetwork);
6118 handleApplyDefaultProxy(newNetwork.linkProperties.getHttpProxy());
6119 updateTcpBufferSizes(newNetwork.linkProperties.getTcpBufferSizes());
6120 mDnsManager.setDefaultDnsSystemProperties(newNetwork.linkProperties.getDnsServers());
6121 notifyIfacesChangedForNetworkStats();
6122 // Fix up the NetworkCapabilities of any VPNs that don't specify underlying networks.
6123 updateAllVpnsCapabilities();
6126 private void processListenRequests(NetworkAgentInfo nai, boolean capabilitiesChanged) {
6127 // For consistency with previous behaviour, send onLost callbacks before onAvailable.
6128 for (NetworkRequestInfo nri : mNetworkRequests.values()) {
6129 NetworkRequest nr = nri.request;
6130 if (!nr.isListen()) continue;
6131 if (nai.isSatisfyingRequest(nr.requestId) && !nai.satisfies(nr)) {
6132 nai.removeRequest(nri.request.requestId);
6133 callCallbackForRequest(nri, nai, ConnectivityManager.CALLBACK_LOST, 0);
6137 if (capabilitiesChanged) {
6138 notifyNetworkCallbacks(nai, ConnectivityManager.CALLBACK_CAP_CHANGED);
6141 for (NetworkRequestInfo nri : mNetworkRequests.values()) {
6142 NetworkRequest nr = nri.request;
6143 if (!nr.isListen()) continue;
6144 if (nai.satisfies(nr) && !nai.isSatisfyingRequest(nr.requestId)) {
6146 notifyNetworkAvailable(nai, nri);
6151 // Handles a network appearing or improving its score.
6153 // - Evaluates all current NetworkRequests that can be
6154 // satisfied by newNetwork, and reassigns to newNetwork
6155 // any such requests for which newNetwork is the best.
6157 // - Lingers any validated Networks that as a result are no longer
6158 // needed. A network is needed if it is the best network for
6159 // one or more NetworkRequests, or if it is a VPN.
6161 // - Tears down newNetwork if it just became validated
6162 // but turns out to be unneeded.
6164 // - If reapUnvalidatedNetworks==REAP, tears down unvalidated
6165 // networks that have no chance (i.e. even if validated)
6166 // of becoming the highest scoring network.
6168 // NOTE: This function only adds NetworkRequests that "newNetwork" could satisfy,
6169 // it does not remove NetworkRequests that other Networks could better satisfy.
6170 // If you need to handle decreases in score, use {@link rematchAllNetworksAndRequests}.
6171 // This function should be used when possible instead of {@code rematchAllNetworksAndRequests}
6172 // as it performs better by a factor of the number of Networks.
6174 // @param newNetwork is the network to be matched against NetworkRequests.
6175 // @param reapUnvalidatedNetworks indicates if an additional pass over all networks should be
6176 // performed to tear down unvalidated networks that have no chance (i.e. even if
6177 // validated) of becoming the highest scoring network.
6178 private void rematchNetworkAndRequests(NetworkAgentInfo newNetwork,
6179 ReapUnvalidatedNetworks reapUnvalidatedNetworks, long now) {
6180 if (!newNetwork.everConnected) return;
6181 boolean keep = newNetwork.isVPN();
6182 boolean isNewDefault = false;
6183 NetworkAgentInfo oldDefaultNetwork = null;
6185 final boolean wasBackgroundNetwork = newNetwork.isBackgroundNetwork();
6186 final int score = newNetwork.getCurrentScore();
6188 if (VDBG || DDBG) log("rematching " + newNetwork.name());
6190 // Find and migrate to this Network any NetworkRequests for
6191 // which this network is now the best.
6192 ArrayList<NetworkAgentInfo> affectedNetworks = new ArrayList<>();
6193 ArrayList<NetworkRequestInfo> addedRequests = new ArrayList<>();
6194 NetworkCapabilities nc = newNetwork.networkCapabilities;
6195 if (VDBG) log(" network has: " + nc);
6196 for (NetworkRequestInfo nri : mNetworkRequests.values()) {
6197 // Process requests in the first pass and listens in the second pass. This allows us to
6198 // change a network's capabilities depending on which requests it has. This is only
6199 // correct if the change in capabilities doesn't affect whether the network satisfies
6200 // requests or not, and doesn't affect the network's score.
6201 if (nri.request.isListen()) continue;
6203 final NetworkAgentInfo currentNetwork = getNetworkForRequest(nri.request.requestId);
6204 final boolean satisfies = newNetwork.satisfies(nri.request);
6205 if (newNetwork == currentNetwork && satisfies) {
6207 log("Network " + newNetwork.name() + " was already satisfying" +
6208 " request " + nri.request.requestId + ". No change.");
6214 // check if it satisfies the NetworkCapabilities
6215 if (VDBG) log(" checking if request is satisfied: " + nri.request);
6217 // next check if it's better than any current network we're using for
6220 log("currentScore = " +
6221 (currentNetwork != null ? currentNetwork.getCurrentScore() : 0) +
6222 ", newScore = " + score);
6224 if (currentNetwork == null || currentNetwork.getCurrentScore() < score) {
6225 if (VDBG) log("rematch for " + newNetwork.name());
6226 if (currentNetwork != null) {
6228 log(" accepting network in place of " + currentNetwork.name());
6230 currentNetwork.removeRequest(nri.request.requestId);
6231 currentNetwork.lingerRequest(nri.request, now, mLingerDelayMs);
6232 affectedNetworks.add(currentNetwork);
6234 if (VDBG || DDBG) log(" accepting network in place of null");
6236 newNetwork.unlingerRequest(nri.request);
6237 setNetworkForRequest(nri.request.requestId, newNetwork);
6238 if (!newNetwork.addRequest(nri.request)) {
6239 Slog.wtf(TAG, "BUG: " + newNetwork.name() + " already has " + nri.request);
6241 addedRequests.add(nri);
6243 // Tell NetworkFactories about the new score, so they can stop
6244 // trying to connect if they know they cannot match it.
6245 // TODO - this could get expensive if we have a lot of requests for this
6246 // network. Think about if there is a way to reduce this. Push
6247 // netid->request mapping to each factory?
6248 sendUpdatedScoreToFactories(nri.request, newNetwork);
6249 if (isDefaultRequest(nri)) {
6250 isNewDefault = true;
6251 oldDefaultNetwork = currentNetwork;
6252 if (currentNetwork != null) {
6253 mLingerMonitor.noteLingerDefaultNetwork(currentNetwork, newNetwork);
6257 } else if (newNetwork.isSatisfyingRequest(nri.request.requestId)) {
6258 // If "newNetwork" is listed as satisfying "nri" but no longer satisfies "nri",
6259 // mark it as no longer satisfying "nri". Because networks are processed by
6260 // rematchAllNetworksAndRequests() in descending score order, "currentNetwork" will
6261 // match "newNetwork" before this loop will encounter a "currentNetwork" with higher
6262 // score than "newNetwork" and where "currentNetwork" no longer satisfies "nri".
6263 // This means this code doesn't have to handle the case where "currentNetwork" no
6264 // longer satisfies "nri" when "currentNetwork" does not equal "newNetwork".
6266 log("Network " + newNetwork.name() + " stopped satisfying" +
6267 " request " + nri.request.requestId);
6269 newNetwork.removeRequest(nri.request.requestId);
6270 if (currentNetwork == newNetwork) {
6271 clearNetworkForRequest(nri.request.requestId);
6272 sendUpdatedScoreToFactories(nri.request, null);
6274 Slog.wtf(TAG, "BUG: Removing request " + nri.request.requestId + " from " +
6276 " without updating mNetworkForRequestId or factories!");
6278 // TODO: Technically, sending CALLBACK_LOST here is
6279 // incorrect if there is a replacement network currently
6280 // connected that can satisfy nri, which is a request
6281 // (not a listen). However, the only capability that can both
6282 // a) be requested and b) change is NET_CAPABILITY_TRUSTED,
6283 // so this code is only incorrect for a network that loses
6284 // the TRUSTED capability, which is a rare case.
6285 callCallbackForRequest(nri, newNetwork, ConnectivityManager.CALLBACK_LOST, 0);
6289 updateDataActivityTracking(newNetwork, oldDefaultNetwork);
6290 // Notify system services that this network is up.
6291 makeDefault(newNetwork);
6292 // Log 0 -> X and Y -> X default network transitions, where X is the new default.
6293 metricsLogger().defaultNetworkMetrics().logDefaultNetworkEvent(
6294 now, newNetwork, oldDefaultNetwork);
6295 // Have a new default network, release the transition wakelock in
6296 scheduleReleaseNetworkTransitionWakelock();
6299 if (!newNetwork.networkCapabilities.equalRequestableCapabilities(nc)) {
6300 Slog.wtf(TAG, String.format(
6301 "BUG: %s changed requestable capabilities during rematch: %s -> %s",
6302 newNetwork.name(), nc, newNetwork.networkCapabilities));
6304 if (newNetwork.getCurrentScore() != score) {
6305 Slog.wtf(TAG, String.format(
6306 "BUG: %s changed score during rematch: %d -> %d",
6307 newNetwork.name(), score, newNetwork.getCurrentScore()));
6310 // Second pass: process all listens.
6311 if (wasBackgroundNetwork != newNetwork.isBackgroundNetwork()) {
6312 // If the network went from background to foreground or vice versa, we need to update
6313 // its foreground state. It is safe to do this after rematching the requests because
6314 // NET_CAPABILITY_FOREGROUND does not affect requests, as is not a requestable
6315 // capability and does not affect the network's score (see the Slog.wtf call above).
6316 updateCapabilities(score, newNetwork, newNetwork.networkCapabilities);
6318 processListenRequests(newNetwork, false);
6321 // do this after the default net is switched, but
6322 // before LegacyTypeTracker sends legacy broadcasts
6323 for (NetworkRequestInfo nri : addedRequests) notifyNetworkAvailable(newNetwork, nri);
6325 // Linger any networks that are no longer needed. This should be done after sending the
6326 // available callback for newNetwork.
6327 for (NetworkAgentInfo nai : affectedNetworks) {
6328 updateLingerState(nai, now);
6330 // Possibly unlinger newNetwork. Unlingering a network does not send any callbacks so it
6331 // does not need to be done in any particular order.
6332 updateLingerState(newNetwork, now);
6335 // Maintain the illusion: since the legacy API only
6336 // understands one network at a time, we must pretend
6337 // that the current default network disconnected before
6338 // the new one connected.
6339 if (oldDefaultNetwork != null) {
6340 mLegacyTypeTracker.remove(oldDefaultNetwork.networkInfo.getType(),
6341 oldDefaultNetwork, true);
6343 mDefaultInetConditionPublished = newNetwork.lastValidated ? 100 : 0;
6344 mLegacyTypeTracker.add(newNetwork.networkInfo.getType(), newNetwork);
6345 notifyLockdownVpn(newNetwork);
6349 // Notify battery stats service about this network, both the normal
6350 // interface and any stacked links.
6351 // TODO: Avoid redoing this; this must only be done once when a network comes online.
6353 final IBatteryStats bs = BatteryStatsService.getService();
6354 final int type = newNetwork.networkInfo.getType();
6356 final String baseIface = newNetwork.linkProperties.getInterfaceName();
6357 bs.noteNetworkInterfaceType(baseIface, type);
6358 for (LinkProperties stacked : newNetwork.linkProperties.getStackedLinks()) {
6359 final String stackedIface = stacked.getInterfaceName();
6360 bs.noteNetworkInterfaceType(stackedIface, type);
6362 } catch (RemoteException ignored) {
6365 // This has to happen after the notifyNetworkCallbacks as that tickles each
6366 // ConnectivityManager instance so that legacy requests correctly bind dns
6367 // requests to this network. The legacy users are listening for this broadcast
6368 // and will generally do a dns request so they can ensureRouteToHost and if
6369 // they do that before the callbacks happen they'll use the default network.
6371 // TODO: Is there still a race here? We send the broadcast
6372 // after sending the callback, but if the app can receive the
6373 // broadcast before the callback, it might still break.
6375 // This *does* introduce a race where if the user uses the new api
6376 // (notification callbacks) and then uses the old api (getNetworkInfo(type))
6377 // they may get old info. Reverse this after the old startUsing api is removed.
6378 // This is on top of the multiple intent sequencing referenced in the todo above.
6379 for (int i = 0; i < newNetwork.numNetworkRequests(); i++) {
6380 NetworkRequest nr = newNetwork.requestAt(i);
6381 if (nr.legacyType != TYPE_NONE && nr.isRequest()) {
6382 // legacy type tracker filters out repeat adds
6383 mLegacyTypeTracker.add(nr.legacyType, newNetwork);
6387 // A VPN generally won't get added to the legacy tracker in the "for (nri)" loop above,
6388 // because usually there are no NetworkRequests it satisfies (e.g., mDefaultRequest
6389 // wants the NOT_VPN capability, so it will never be satisfied by a VPN). So, add the
6390 // newNetwork to the tracker explicitly (it's a no-op if it has already been added).
6391 if (newNetwork.isVPN()) {
6392 mLegacyTypeTracker.add(TYPE_VPN, newNetwork);
6395 if (reapUnvalidatedNetworks == ReapUnvalidatedNetworks.REAP) {
6396 for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
6397 if (unneeded(nai, UnneededFor.TEARDOWN)) {
6398 if (nai.getLingerExpiry() > 0) {
6399 // This network has active linger timers and no requests, but is not
6400 // lingering. Linger it.
6402 // One way (the only way?) this can happen if this network is unvalidated
6403 // and became unneeded due to another network improving its score to the
6404 // point where this network will no longer be able to satisfy any requests
6405 // even if it validates.
6406 updateLingerState(nai, now);
6408 if (DBG) log("Reaping " + nai.name());
6409 teardownUnneededNetwork(nai);
6417 * Attempt to rematch all Networks with NetworkRequests. This may result in Networks
6418 * being disconnected.
6419 * @param changed If only one Network's score or capabilities have been modified since the last
6420 * time this function was called, pass this Network in this argument, otherwise pass
6422 * @param oldScore If only one Network has been changed but its NetworkCapabilities have not
6423 * changed, pass in the Network's score (from getCurrentScore()) prior to the change via
6424 * this argument, otherwise pass {@code changed.getCurrentScore()} or 0 if
6425 * {@code changed} is {@code null}. This is because NetworkCapabilities influence a
6428 private void rematchAllNetworksAndRequests(NetworkAgentInfo changed, int oldScore) {
6429 // TODO: This may get slow. The "changed" parameter is provided for future optimization
6430 // to avoid the slowness. It is not simply enough to process just "changed", for
6431 // example in the case where "changed"'s score decreases and another network should begin
6432 // satisfying a NetworkRequest that "changed" currently satisfies.
6434 // Optimization: Only reprocess "changed" if its score improved. This is safe because it
6435 // can only add more NetworkRequests satisfied by "changed", and this is exactly what
6436 // rematchNetworkAndRequests() handles.
6437 final long now = SystemClock.elapsedRealtime();
6438 if (changed != null && oldScore < changed.getCurrentScore()) {
6439 rematchNetworkAndRequests(changed, ReapUnvalidatedNetworks.REAP, now);
6441 final NetworkAgentInfo[] nais = mNetworkAgentInfos.values().toArray(
6442 new NetworkAgentInfo[mNetworkAgentInfos.size()]);
6443 // Rematch higher scoring networks first to prevent requests first matching a lower
6444 // scoring network and then a higher scoring network, which could produce multiple
6445 // callbacks and inadvertently unlinger networks.
6447 for (NetworkAgentInfo nai : nais) {
6448 rematchNetworkAndRequests(nai,
6449 // Only reap the last time through the loop. Reaping before all rematching
6450 // is complete could incorrectly teardown a network that hasn't yet been
6452 (nai != nais[nais.length-1]) ? ReapUnvalidatedNetworks.DONT_REAP
6453 : ReapUnvalidatedNetworks.REAP,
6459 private void updateInetCondition(NetworkAgentInfo nai) {
6460 // Don't bother updating until we've graduated to validated at least once.
6461 if (!nai.everValidated) return;
6462 // For now only update icons for default connection.
6463 // TODO: Update WiFi and cellular icons separately. b/17237507
6464 if (!isDefaultNetwork(nai)) return;
6466 int newInetCondition = nai.lastValidated ? 100 : 0;
6467 // Don't repeat publish.
6468 if (newInetCondition == mDefaultInetConditionPublished) return;
6470 mDefaultInetConditionPublished = newInetCondition;
6471 sendInetConditionBroadcast(nai.networkInfo);
6474 private void notifyLockdownVpn(NetworkAgentInfo nai) {
6475 synchronized (mVpns) {
6476 if (mLockdownTracker != null) {
6477 if (nai != null && nai.isVPN()) {
6478 mLockdownTracker.onVpnStateChanged(nai.networkInfo);
6480 mLockdownTracker.onNetworkInfoChanged();
6486 private void updateNetworkInfo(NetworkAgentInfo networkAgent, NetworkInfo newInfo) {
6487 final NetworkInfo.State state = newInfo.getState();
6488 NetworkInfo oldInfo = null;
6489 final int oldScore = networkAgent.getCurrentScore();
6490 synchronized (networkAgent) {
6491 oldInfo = networkAgent.networkInfo;
6492 networkAgent.networkInfo = newInfo;
6494 notifyLockdownVpn(networkAgent);
6497 log(networkAgent.name() + " EVENT_NETWORK_INFO_CHANGED, going from " +
6498 (oldInfo == null ? "null" : oldInfo.getState()) +
6502 if (!networkAgent.created
6503 && (state == NetworkInfo.State.CONNECTED
6504 || (state == NetworkInfo.State.CONNECTING && networkAgent.isVPN()))) {
6506 // A network that has just connected has zero requests and is thus a foreground network.
6507 networkAgent.networkCapabilities.addCapability(NET_CAPABILITY_FOREGROUND);
6509 if (!createNativeNetwork(networkAgent)) return;
6510 networkAgent.created = true;
6513 if (!networkAgent.everConnected && state == NetworkInfo.State.CONNECTED) {
6514 networkAgent.everConnected = true;
6516 if (networkAgent.linkProperties == null) {
6517 Slog.wtf(TAG, networkAgent.name() + " connected with null LinkProperties");
6520 // NetworkCapabilities need to be set before sending the private DNS config to
6521 // NetworkMonitor, otherwise NetworkMonitor cannot determine if validation is required.
6522 synchronized (networkAgent) {
6523 networkAgent.setNetworkCapabilities(networkAgent.networkCapabilities);
6525 handlePerNetworkPrivateDnsConfig(networkAgent, mDnsManager.getPrivateDnsConfig());
6526 updateLinkProperties(networkAgent, new LinkProperties(networkAgent.linkProperties),
6529 // Until parceled LinkProperties are sent directly to NetworkMonitor, the connect
6530 // command must be sent after updating LinkProperties to maximize chances of
6531 // NetworkMonitor seeing the correct LinkProperties when starting.
6532 // TODO: pass LinkProperties to the NetworkMonitor in the notifyNetworkConnected call.
6534 if (networkAgent.networkMisc.acceptPartialConnectivity) {
6535 networkAgent.networkMonitor().setAcceptPartialConnectivity();
6537 networkAgent.networkMonitor().notifyNetworkConnected(
6538 networkAgent.linkProperties, networkAgent.networkCapabilities);
6539 } catch (RemoteException e) {
6540 e.rethrowAsRuntimeException();
6542 scheduleUnvalidatedPrompt(networkAgent);
6544 // Whether a particular NetworkRequest listen should cause signal strength thresholds to
6545 // be communicated to a particular NetworkAgent depends only on the network's immutable,
6546 // capabilities, so it only needs to be done once on initial connect, not every time the
6547 // network's capabilities change. Note that we do this before rematching the network,
6548 // so we could decide to tear it down immediately afterwards. That's fine though - on
6549 // disconnection NetworkAgents should stop any signal strength monitoring they have been
6551 updateSignalStrengthThresholds(networkAgent, "CONNECT", null);
6553 if (networkAgent.isVPN()) {
6554 updateAllVpnsCapabilities();
6557 // Consider network even though it is not yet validated.
6558 final long now = SystemClock.elapsedRealtime();
6559 rematchNetworkAndRequests(networkAgent, ReapUnvalidatedNetworks.REAP, now);
6561 // This has to happen after matching the requests, because callbacks are just requests.
6562 notifyNetworkCallbacks(networkAgent, ConnectivityManager.CALLBACK_PRECHECK);
6563 } else if (state == NetworkInfo.State.DISCONNECTED) {
6564 networkAgent.asyncChannel.disconnect();
6565 if (networkAgent.isVPN()) {
6566 updateUids(networkAgent, networkAgent.networkCapabilities, null);
6568 disconnectAndDestroyNetwork(networkAgent);
6569 if (networkAgent.isVPN()) {
6570 // As the active or bound network changes for apps, broadcast the default proxy, as
6571 // apps may need to update their proxy data. This is called after disconnecting from
6572 // VPN to make sure we do not broadcast the old proxy data.
6573 // TODO(b/122649188): send the broadcast only to VPN users.
6574 mProxyTracker.sendProxyBroadcast();
6576 } else if ((oldInfo != null && oldInfo.getState() == NetworkInfo.State.SUSPENDED) ||
6577 state == NetworkInfo.State.SUSPENDED) {
6578 // going into or coming out of SUSPEND: re-score and notify
6579 if (networkAgent.getCurrentScore() != oldScore) {
6580 rematchAllNetworksAndRequests(networkAgent, oldScore);
6582 updateCapabilities(networkAgent.getCurrentScore(), networkAgent,
6583 networkAgent.networkCapabilities);
6584 // TODO (b/73132094) : remove this call once the few users of onSuspended and
6585 // onResumed have been removed.
6586 notifyNetworkCallbacks(networkAgent, (state == NetworkInfo.State.SUSPENDED ?
6587 ConnectivityManager.CALLBACK_SUSPENDED :
6588 ConnectivityManager.CALLBACK_RESUMED));
6589 mLegacyTypeTracker.update(networkAgent);
6593 private void updateNetworkScore(NetworkAgentInfo nai, int score) {
6594 if (VDBG || DDBG) log("updateNetworkScore for " + nai.name() + " to " + score);
6596 loge("updateNetworkScore for " + nai.name() + " got a negative score (" + score +
6597 "). Bumping score to min of 0");
6601 final int oldScore = nai.getCurrentScore();
6602 nai.setCurrentScore(score);
6604 rematchAllNetworksAndRequests(nai, oldScore);
6606 sendUpdatedScoreToFactories(nai);
6609 // Notify only this one new request of the current state. Transfer all the
6610 // current state by calling NetworkCapabilities and LinkProperties callbacks
6611 // so that callers can be guaranteed to have as close to atomicity in state
6612 // transfer as can be supported by this current API.
6613 protected void notifyNetworkAvailable(NetworkAgentInfo nai, NetworkRequestInfo nri) {
6614 mHandler.removeMessages(EVENT_TIMEOUT_NETWORK_REQUEST, nri);
6615 if (nri.mPendingIntent != null) {
6616 sendPendingIntentForRequest(nri, nai, ConnectivityManager.CALLBACK_AVAILABLE);
6617 // Attempt no subsequent state pushes where intents are involved.
6621 final boolean metered = nai.networkCapabilities.isMetered();
6622 final boolean blocked = isUidNetworkingWithVpnBlocked(nri.mUid, mUidRules.get(nri.mUid),
6623 metered, mRestrictBackground);
6624 callCallbackForRequest(nri, nai, ConnectivityManager.CALLBACK_AVAILABLE, blocked ? 1 : 0);
6628 * Notify of the blocked state apps with a registered callback matching a given NAI.
6630 * Unlike other callbacks, blocked status is different between each individual uid. So for
6631 * any given nai, all requests need to be considered according to the uid who filed it.
6633 * @param nai The target NetworkAgentInfo.
6634 * @param oldMetered True if the previous network capabilities is metered.
6635 * @param newRestrictBackground True if data saver is enabled.
6637 private void maybeNotifyNetworkBlocked(NetworkAgentInfo nai, boolean oldMetered,
6638 boolean newMetered, boolean oldRestrictBackground, boolean newRestrictBackground) {
6640 for (int i = 0; i < nai.numNetworkRequests(); i++) {
6641 NetworkRequest nr = nai.requestAt(i);
6642 NetworkRequestInfo nri = mNetworkRequests.get(nr);
6643 final int uidRules = mUidRules.get(nri.mUid);
6644 final boolean oldBlocked, newBlocked;
6645 // mVpns lock needs to be hold here to ensure that the active VPN cannot be changed
6646 // between these two calls.
6647 synchronized (mVpns) {
6648 oldBlocked = isUidNetworkingWithVpnBlocked(nri.mUid, uidRules, oldMetered,
6649 oldRestrictBackground);
6650 newBlocked = isUidNetworkingWithVpnBlocked(nri.mUid, uidRules, newMetered,
6651 newRestrictBackground);
6653 if (oldBlocked != newBlocked) {
6654 callCallbackForRequest(nri, nai, ConnectivityManager.CALLBACK_BLK_CHANGED,
6655 encodeBool(newBlocked));
6661 * Notify apps with a given UID of the new blocked state according to new uid rules.
6662 * @param uid The uid for which the rules changed.
6663 * @param newRules The new rules to apply.
6665 private void maybeNotifyNetworkBlockedForNewUidRules(int uid, int newRules) {
6666 for (final NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
6667 final boolean metered = nai.networkCapabilities.isMetered();
6668 final boolean oldBlocked, newBlocked;
6669 // TODO: Consider that doze mode or turn on/off battery saver would deliver lots of uid
6670 // rules changed event. And this function actually loop through all connected nai and
6671 // its requests. It seems that mVpns lock will be grabbed frequently in this case.
6672 // Reduce the number of locking or optimize the use of lock are likely needed in future.
6673 synchronized (mVpns) {
6674 oldBlocked = isUidNetworkingWithVpnBlocked(
6675 uid, mUidRules.get(uid), metered, mRestrictBackground);
6676 newBlocked = isUidNetworkingWithVpnBlocked(
6677 uid, newRules, metered, mRestrictBackground);
6679 if (oldBlocked == newBlocked) {
6682 final int arg = encodeBool(newBlocked);
6683 for (int i = 0; i < nai.numNetworkRequests(); i++) {
6684 NetworkRequest nr = nai.requestAt(i);
6685 NetworkRequestInfo nri = mNetworkRequests.get(nr);
6686 if (nri != null && nri.mUid == uid) {
6687 callCallbackForRequest(nri, nai, ConnectivityManager.CALLBACK_BLK_CHANGED, arg);
6694 protected void sendLegacyNetworkBroadcast(NetworkAgentInfo nai, DetailedState state, int type) {
6695 // The NetworkInfo we actually send out has no bearing on the real
6696 // state of affairs. For example, if the default connection is mobile,
6697 // and a request for HIPRI has just gone away, we need to pretend that
6698 // HIPRI has just disconnected. So we need to set the type to HIPRI and
6699 // the state to DISCONNECTED, even though the network is of type MOBILE
6700 // and is still connected.
6701 NetworkInfo info = new NetworkInfo(nai.networkInfo);
6703 if (state != DetailedState.DISCONNECTED) {
6704 info.setDetailedState(state, null, info.getExtraInfo());
6705 sendConnectedBroadcast(info);
6707 info.setDetailedState(state, info.getReason(), info.getExtraInfo());
6708 Intent intent = new Intent(ConnectivityManager.CONNECTIVITY_ACTION);
6709 intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, info);
6710 intent.putExtra(ConnectivityManager.EXTRA_NETWORK_TYPE, info.getType());
6711 if (info.isFailover()) {
6712 intent.putExtra(ConnectivityManager.EXTRA_IS_FAILOVER, true);
6713 nai.networkInfo.setFailover(false);
6715 if (info.getReason() != null) {
6716 intent.putExtra(ConnectivityManager.EXTRA_REASON, info.getReason());
6718 if (info.getExtraInfo() != null) {
6719 intent.putExtra(ConnectivityManager.EXTRA_EXTRA_INFO, info.getExtraInfo());
6721 NetworkAgentInfo newDefaultAgent = null;
6722 if (nai.isSatisfyingRequest(mDefaultRequest.requestId)) {
6723 newDefaultAgent = getDefaultNetwork();
6724 if (newDefaultAgent != null) {
6725 intent.putExtra(ConnectivityManager.EXTRA_OTHER_NETWORK_INFO,
6726 newDefaultAgent.networkInfo);
6728 intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, true);
6731 intent.putExtra(ConnectivityManager.EXTRA_INET_CONDITION,
6732 mDefaultInetConditionPublished);
6733 sendStickyBroadcast(intent);
6734 if (newDefaultAgent != null) {
6735 sendConnectedBroadcast(newDefaultAgent.networkInfo);
6740 protected void notifyNetworkCallbacks(NetworkAgentInfo networkAgent, int notifyType, int arg1) {
6742 String notification = ConnectivityManager.getCallbackName(notifyType);
6743 log("notifyType " + notification + " for " + networkAgent.name());
6745 for (int i = 0; i < networkAgent.numNetworkRequests(); i++) {
6746 NetworkRequest nr = networkAgent.requestAt(i);
6747 NetworkRequestInfo nri = mNetworkRequests.get(nr);
6748 if (VDBG) log(" sending notification for " + nr);
6749 // TODO: if we're in the middle of a rematch, can we send a CAP_CHANGED callback for
6750 // a network that no longer satisfies the listen?
6751 if (nri.mPendingIntent == null) {
6752 callCallbackForRequest(nri, networkAgent, notifyType, arg1);
6754 sendPendingIntentForRequest(nri, networkAgent, notifyType);
6759 protected void notifyNetworkCallbacks(NetworkAgentInfo networkAgent, int notifyType) {
6760 notifyNetworkCallbacks(networkAgent, notifyType, 0);
6764 * Returns the list of all interfaces that could be used by network traffic that does not
6765 * explicitly specify a network. This includes the default network, but also all VPNs that are
6766 * currently connected.
6768 * Must be called on the handler thread.
6770 private Network[] getDefaultNetworks() {
6771 ensureRunningOnConnectivityServiceThread();
6772 ArrayList<Network> defaultNetworks = new ArrayList<>();
6773 NetworkAgentInfo defaultNetwork = getDefaultNetwork();
6774 for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
6775 if (nai.everConnected && (nai == defaultNetwork || nai.isVPN())) {
6776 defaultNetworks.add(nai.network);
6779 return defaultNetworks.toArray(new Network[0]);
6783 * Notify NetworkStatsService that the set of active ifaces has changed, or that one of the
6784 * properties tracked by NetworkStatsService on an active iface has changed.
6786 private void notifyIfacesChangedForNetworkStats() {
6787 ensureRunningOnConnectivityServiceThread();
6788 String activeIface = null;
6789 LinkProperties activeLinkProperties = getActiveLinkProperties();
6790 if (activeLinkProperties != null) {
6791 activeIface = activeLinkProperties.getInterfaceName();
6794 mStatsService.forceUpdateIfaces(
6795 getDefaultNetworks(), getAllVpnInfo(), getAllNetworkState(), activeIface);
6796 } catch (Exception ignored) {
6801 public boolean addVpnAddress(String address, int prefixLength) {
6802 int user = UserHandle.getUserId(Binder.getCallingUid());
6803 synchronized (mVpns) {
6804 throwIfLockdownEnabled();
6805 return mVpns.get(user).addAddress(address, prefixLength);
6810 public boolean removeVpnAddress(String address, int prefixLength) {
6811 int user = UserHandle.getUserId(Binder.getCallingUid());
6812 synchronized (mVpns) {
6813 throwIfLockdownEnabled();
6814 return mVpns.get(user).removeAddress(address, prefixLength);
6819 public boolean setUnderlyingNetworksForVpn(Network[] networks) {
6820 int user = UserHandle.getUserId(Binder.getCallingUid());
6821 final boolean success;
6822 synchronized (mVpns) {
6823 throwIfLockdownEnabled();
6824 success = mVpns.get(user).setUnderlyingNetworks(networks);
6827 mHandler.post(() -> {
6828 // Update VPN's capabilities based on updated underlying network set.
6829 updateAllVpnsCapabilities();
6830 notifyIfacesChangedForNetworkStats();
6837 public String getCaptivePortalServerUrl() {
6838 enforceConnectivityInternalPermission();
6839 String settingUrl = mContext.getResources().getString(
6840 R.string.config_networkCaptivePortalServerUrl);
6842 if (!TextUtils.isEmpty(settingUrl)) {
6846 settingUrl = Settings.Global.getString(mContext.getContentResolver(),
6847 Settings.Global.CAPTIVE_PORTAL_HTTP_URL);
6848 if (!TextUtils.isEmpty(settingUrl)) {
6852 return DEFAULT_CAPTIVE_PORTAL_HTTP_URL;
6856 public void startNattKeepalive(Network network, int intervalSeconds,
6857 ISocketKeepaliveCallback cb, String srcAddr, int srcPort, String dstAddr) {
6858 enforceKeepalivePermission();
6859 mKeepaliveTracker.startNattKeepalive(
6860 getNetworkAgentInfoForNetwork(network), null /* fd */,
6861 intervalSeconds, cb,
6862 srcAddr, srcPort, dstAddr, NattSocketKeepalive.NATT_PORT);
6866 public void startNattKeepaliveWithFd(Network network, FileDescriptor fd, int resourceId,
6867 int intervalSeconds, ISocketKeepaliveCallback cb, String srcAddr,
6869 mKeepaliveTracker.startNattKeepalive(
6870 getNetworkAgentInfoForNetwork(network), fd, resourceId,
6871 intervalSeconds, cb,
6872 srcAddr, dstAddr, NattSocketKeepalive.NATT_PORT);
6876 public void startTcpKeepalive(Network network, FileDescriptor fd, int intervalSeconds,
6877 ISocketKeepaliveCallback cb) {
6878 enforceKeepalivePermission();
6879 mKeepaliveTracker.startTcpKeepalive(
6880 getNetworkAgentInfoForNetwork(network), fd, intervalSeconds, cb);
6884 public void stopKeepalive(Network network, int slot) {
6885 mHandler.sendMessage(mHandler.obtainMessage(
6886 NetworkAgent.CMD_STOP_SOCKET_KEEPALIVE, slot, SocketKeepalive.SUCCESS, network));
6890 public void factoryReset() {
6891 enforceConnectivityInternalPermission();
6893 if (mUserManager.hasUserRestriction(UserManager.DISALLOW_NETWORK_RESET)) {
6897 final int userId = UserHandle.getCallingUserId();
6899 // Turn airplane mode off
6900 setAirplaneMode(false);
6902 if (!mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_TETHERING)) {
6904 String pkgName = mContext.getOpPackageName();
6905 for (String tether : getTetheredIfaces()) {
6906 untether(tether, pkgName);
6910 if (!mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_VPN)) {
6911 // Remove always-on package
6912 synchronized (mVpns) {
6913 final String alwaysOnPackage = getAlwaysOnVpnPackage(userId);
6914 if (alwaysOnPackage != null) {
6915 setAlwaysOnVpnPackage(userId, null, false, null);
6916 setVpnPackageAuthorization(alwaysOnPackage, userId, false);
6919 // Turn Always-on VPN off
6920 if (mLockdownEnabled && userId == UserHandle.USER_SYSTEM) {
6921 final long ident = Binder.clearCallingIdentity();
6923 mKeyStore.delete(Credentials.LOCKDOWN_VPN);
6924 mLockdownEnabled = false;
6925 setLockdownTracker(null);
6927 Binder.restoreCallingIdentity(ident);
6932 VpnConfig vpnConfig = getVpnConfig(userId);
6933 if (vpnConfig != null) {
6934 if (vpnConfig.legacy) {
6935 prepareVpn(VpnConfig.LEGACY_VPN, VpnConfig.LEGACY_VPN, userId);
6937 // Prevent this app (packagename = vpnConfig.user) from initiating
6938 // VPN connections in the future without user intervention.
6939 setVpnPackageAuthorization(vpnConfig.user, userId, false);
6941 prepareVpn(null, VpnConfig.LEGACY_VPN, userId);
6947 Settings.Global.putString(mContext.getContentResolver(),
6948 Settings.Global.NETWORK_AVOID_BAD_WIFI, null);
6952 public byte[] getNetworkWatchlistConfigHash() {
6953 NetworkWatchlistManager nwm = mContext.getSystemService(NetworkWatchlistManager.class);
6955 loge("Unable to get NetworkWatchlistManager");
6958 // Redirect it to network watchlist service to access watchlist file and calculate hash.
6959 return nwm.getWatchlistConfigHash();
6963 MultinetworkPolicyTracker createMultinetworkPolicyTracker(Context c, Handler h, Runnable r) {
6964 return new MultinetworkPolicyTracker(c, h, r);
6968 public WakeupMessage makeWakeupMessage(Context c, Handler h, String s, int cmd, Object obj) {
6969 return new WakeupMessage(c, h, s, cmd, 0, 0, obj);
6973 public boolean hasService(String name) {
6974 return ServiceManager.checkService(name) != null;
6978 protected IpConnectivityMetrics.Logger metricsLogger() {
6979 return checkNotNull(LocalServices.getService(IpConnectivityMetrics.Logger.class),
6980 "no IpConnectivityMetrics service");
6983 private void logNetworkEvent(NetworkAgentInfo nai, int evtype) {
6984 int[] transports = nai.networkCapabilities.getTransportTypes();
6985 mMetricsLog.log(nai.network.netId, transports, new NetworkEvent(evtype));
6988 private static boolean toBool(int encodedBoolean) {
6989 return encodedBoolean != 0; // Only 0 means false.
6992 private static int encodeBool(boolean b) {
6997 public void onShellCommand(FileDescriptor in, FileDescriptor out,
6998 FileDescriptor err, String[] args, ShellCallback callback,
6999 ResultReceiver resultReceiver) {
7000 (new ShellCmd()).exec(this, in, out, err, args, callback, resultReceiver);
7003 private class ShellCmd extends ShellCommand {
7006 public int onCommand(String cmd) {
7008 return handleDefaultCommands(cmd);
7010 final PrintWriter pw = getOutPrintWriter();
7013 case "airplane-mode":
7014 final String action = getNextArg();
7015 if ("enable".equals(action)) {
7016 setAirplaneMode(true);
7018 } else if ("disable".equals(action)) {
7019 setAirplaneMode(false);
7021 } else if (action == null) {
7022 final ContentResolver cr = mContext.getContentResolver();
7023 final int enabled = Settings.Global.getInt(cr,
7024 Settings.Global.AIRPLANE_MODE_ON);
7025 pw.println(enabled == 0 ? "disabled" : "enabled");
7032 return handleDefaultCommands(cmd);
7034 } catch (Exception e) {
7041 public void onHelp() {
7042 PrintWriter pw = getOutPrintWriter();
7043 pw.println("Connectivity service commands:");
7044 pw.println(" help");
7045 pw.println(" Print this help text.");
7046 pw.println(" airplane-mode [enable|disable]");
7047 pw.println(" Turn airplane mode on or off.");
7048 pw.println(" airplane-mode");
7049 pw.println(" Get airplane mode.");
7054 private Vpn getVpnIfOwner() {
7055 final int uid = Binder.getCallingUid();
7056 final int user = UserHandle.getUserId(uid);
7058 final Vpn vpn = mVpns.get(user);
7062 final VpnInfo info = vpn.getVpnInfo();
7063 return (info == null || info.ownerUid != uid) ? null : vpn;
7068 * Caller either needs to be an active VPN, or hold the NETWORK_STACK permission
7071 private Vpn enforceActiveVpnOrNetworkStackPermission() {
7072 if (checkNetworkStackPermission()) {
7075 synchronized (mVpns) {
7076 Vpn vpn = getVpnIfOwner();
7081 throw new SecurityException("App must either be an active VPN or have the NETWORK_STACK "
7086 * @param connectionInfo the connection to resolve.
7087 * @return {@code uid} if the connection is found and the app has permission to observe it
7088 * (e.g., if it is associated with the calling VPN app's tunnel) or {@code INVALID_UID} if the
7089 * connection is not found.
7091 public int getConnectionOwnerUid(ConnectionInfo connectionInfo) {
7092 final Vpn vpn = enforceActiveVpnOrNetworkStackPermission();
7093 if (connectionInfo.protocol != IPPROTO_TCP && connectionInfo.protocol != IPPROTO_UDP) {
7094 throw new IllegalArgumentException("Unsupported protocol " + connectionInfo.protocol);
7097 final int uid = InetDiagMessage.getConnectionOwnerUid(connectionInfo.protocol,
7098 connectionInfo.local, connectionInfo.remote);
7100 /* Filter out Uids not associated with the VPN. */
7101 if (vpn != null && !vpn.appliesToUid(uid)) {
7109 public boolean isCallerCurrentAlwaysOnVpnApp() {
7110 synchronized (mVpns) {
7111 Vpn vpn = getVpnIfOwner();
7112 return vpn != null && vpn.getAlwaysOn();
7117 public boolean isCallerCurrentAlwaysOnVpnLockdownApp() {
7118 synchronized (mVpns) {
7119 Vpn vpn = getVpnIfOwner();
7120 return vpn != null && vpn.getLockdown();
7125 * Returns a IBinder to a TestNetworkService. Will be lazily created as needed.
7127 * <p>The TestNetworkService must be run in the system server due to TUN creation.
7130 public IBinder startOrGetTestNetworkService() {
7131 synchronized (mTNSLock) {
7132 TestNetworkService.enforceTestNetworkPermissions(mContext);
7135 mTNS = new TestNetworkService(mContext, mNMS);