/services/core/java/com/android/server/ConnectivityService.java
https://github.com/android/platform_frameworks_base · Java · 5779 lines · 4315 code · 603 blank · 861 comment · 1045 complexity · 1ef65e9554cdaf17bb6b75fc1136f041 MD5 · raw file
Large files are truncated click here to view the full file
- /*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- package com.android.server;
- import static android.Manifest.permission.RECEIVE_DATA_ACTIVITY_CHANGE;
- import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
- import static android.net.ConnectivityManager.NETID_UNSET;
- import static android.net.ConnectivityManager.TYPE_ETHERNET;
- import static android.net.ConnectivityManager.TYPE_NONE;
- import static android.net.ConnectivityManager.TYPE_VPN;
- import static android.net.ConnectivityManager.getNetworkTypeName;
- import static android.net.ConnectivityManager.isNetworkTypeValid;
- import static android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL;
- import static android.net.NetworkCapabilities.NET_CAPABILITY_FOREGROUND;
- import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
- import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
- import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
- import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING;
- import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED;
- import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN;
- import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
- import static android.net.NetworkCapabilities.TRANSPORT_VPN;
- import static com.android.internal.util.Preconditions.checkNotNull;
- import android.annotation.Nullable;
- import android.app.BroadcastOptions;
- import android.app.NotificationManager;
- import android.app.PendingIntent;
- import android.content.BroadcastReceiver;
- import android.content.ContentResolver;
- import android.content.Context;
- import android.content.Intent;
- import android.content.IntentFilter;
- import android.content.res.Configuration;
- import android.database.ContentObserver;
- import android.net.ConnectivityManager;
- import android.net.ConnectivityManager.PacketKeepalive;
- import android.net.IConnectivityManager;
- import android.net.INetworkManagementEventObserver;
- import android.net.INetworkPolicyListener;
- import android.net.INetworkPolicyManager;
- import android.net.INetworkStatsService;
- import android.net.LinkProperties;
- import android.net.LinkProperties.CompareResult;
- import android.net.MatchAllNetworkSpecifier;
- import android.net.Network;
- import android.net.NetworkAgent;
- import android.net.NetworkCapabilities;
- import android.net.NetworkConfig;
- import android.net.NetworkInfo;
- import android.net.NetworkInfo.DetailedState;
- import android.net.NetworkMisc;
- import android.net.NetworkPolicyManager;
- import android.net.NetworkQuotaInfo;
- import android.net.NetworkRequest;
- import android.net.NetworkSpecifier;
- import android.net.NetworkState;
- import android.net.NetworkUtils;
- import android.net.Proxy;
- import android.net.ProxyInfo;
- import android.net.RouteInfo;
- import android.net.UidRange;
- import android.net.Uri;
- import android.net.VpnService;
- import android.net.metrics.IpConnectivityLog;
- import android.net.metrics.NetworkEvent;
- import android.net.util.MultinetworkPolicyTracker;
- import android.os.Binder;
- import android.os.Build;
- import android.os.Bundle;
- import android.os.FileUtils;
- import android.os.Handler;
- import android.os.HandlerThread;
- import android.os.IBinder;
- import android.os.INetworkManagementService;
- import android.os.Looper;
- import android.os.Message;
- import android.os.Messenger;
- import android.os.ParcelFileDescriptor;
- import android.os.Parcelable;
- import android.os.PowerManager;
- import android.os.Process;
- import android.os.RemoteException;
- import android.os.ResultReceiver;
- import android.os.ServiceManager;
- import android.os.ServiceSpecificException;
- import android.os.SystemClock;
- import android.os.UserHandle;
- import android.os.UserManager;
- import android.provider.Settings;
- import android.security.Credentials;
- import android.security.KeyStore;
- import android.telephony.TelephonyManager;
- import android.text.TextUtils;
- import android.util.ArraySet;
- import android.util.LocalLog;
- import android.util.LocalLog.ReadOnlyLocalLog;
- import android.util.Log;
- import android.util.Slog;
- import android.util.SparseArray;
- import android.util.SparseBooleanArray;
- import android.util.SparseIntArray;
- import android.util.Xml;
- import com.android.internal.R;
- import com.android.internal.annotations.GuardedBy;
- import com.android.internal.annotations.VisibleForTesting;
- import com.android.internal.app.IBatteryStats;
- import com.android.internal.net.LegacyVpnInfo;
- import com.android.internal.net.NetworkStatsFactory;
- import com.android.internal.net.VpnConfig;
- import com.android.internal.net.VpnInfo;
- import com.android.internal.net.VpnProfile;
- import com.android.internal.util.AsyncChannel;
- import com.android.internal.util.DumpUtils;
- import com.android.internal.util.IndentingPrintWriter;
- import com.android.internal.util.MessageUtils;
- import com.android.internal.util.WakeupMessage;
- import com.android.internal.util.XmlUtils;
- import com.android.server.am.BatteryStatsService;
- import com.android.server.connectivity.DataConnectionStats;
- import com.android.server.connectivity.DnsManager;
- import com.android.server.connectivity.DnsManager.PrivateDnsConfig;
- import com.android.server.connectivity.IpConnectivityMetrics;
- import com.android.server.connectivity.KeepaliveTracker;
- import com.android.server.connectivity.LingerMonitor;
- import com.android.server.connectivity.MockableSystemProperties;
- import com.android.server.connectivity.NetworkAgentInfo;
- import com.android.server.connectivity.NetworkDiagnostics;
- import com.android.server.connectivity.NetworkMonitor;
- import com.android.server.connectivity.NetworkNotificationManager;
- import com.android.server.connectivity.NetworkNotificationManager.NotificationType;
- import com.android.server.connectivity.PacManager;
- import com.android.server.connectivity.PermissionMonitor;
- import com.android.server.connectivity.Tethering;
- import com.android.server.connectivity.Vpn;
- import com.android.server.connectivity.tethering.TetheringDependencies;
- import com.android.server.net.BaseNetworkObserver;
- import com.android.server.net.LockdownVpnTracker;
- import com.android.server.net.NetworkPolicyManagerInternal;
- import com.google.android.collect.Lists;
- import org.xmlpull.v1.XmlPullParser;
- import org.xmlpull.v1.XmlPullParserException;
- import java.io.File;
- import java.io.FileDescriptor;
- import java.io.FileNotFoundException;
- import java.io.FileReader;
- import java.io.IOException;
- import java.io.PrintWriter;
- import java.net.Inet4Address;
- import java.net.InetAddress;
- import java.net.UnknownHostException;
- import java.util.ArrayDeque;
- import java.util.ArrayList;
- import java.util.Arrays;
- import java.util.Collection;
- import java.util.HashMap;
- import java.util.HashSet;
- import java.util.List;
- import java.util.Map;
- import java.util.Objects;
- import java.util.Set;
- import java.util.SortedSet;
- import java.util.TreeSet;
- /**
- * @hide
- */
- public class ConnectivityService extends IConnectivityManager.Stub
- implements PendingIntent.OnFinished {
- private static final String TAG = ConnectivityService.class.getSimpleName();
- public static final String DIAG_ARG = "--diag";
- public static final String SHORT_ARG = "--short";
- public static final String TETHERING_ARG = "tethering";
- private static final boolean DBG = true;
- private static final boolean VDBG = false;
- private static final boolean LOGD_RULES = false;
- private static final boolean LOGD_BLOCKED_NETWORKINFO = true;
- // TODO: create better separation between radio types and network types
- // how long to wait before switching back to a radio's default network
- private static final int RESTORE_DEFAULT_NETWORK_DELAY = 1 * 60 * 1000;
- // system property that can override the above value
- private static final String NETWORK_RESTORE_DELAY_PROP_NAME =
- "android.telephony.apn-restore";
- // How long to wait before putting up a "This network doesn't have an Internet connection,
- // connect anyway?" dialog after the user selects a network that doesn't validate.
- private static final int PROMPT_UNVALIDATED_DELAY_MS = 8 * 1000;
- // Default to 30s linger time-out. Modifiable only for testing.
- private static final String LINGER_DELAY_PROPERTY = "persist.netmon.linger";
- private static final int DEFAULT_LINGER_DELAY_MS = 30_000;
- @VisibleForTesting
- protected int mLingerDelayMs; // Can't be final, or test subclass constructors can't change it.
- // How long to delay to removal of a pending intent based request.
- // See Settings.Secure.CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS
- private final int mReleasePendingIntentDelayMs;
- private MockableSystemProperties mSystemProperties;
- private Tethering mTethering;
- private final PermissionMonitor mPermissionMonitor;
- private KeyStore mKeyStore;
- @GuardedBy("mVpns")
- private final SparseArray<Vpn> mVpns = new SparseArray<Vpn>();
- // TODO: investigate if mLockdownEnabled can be removed and replaced everywhere by
- // a direct call to LockdownVpnTracker.isEnabled().
- @GuardedBy("mVpns")
- private boolean mLockdownEnabled;
- @GuardedBy("mVpns")
- private LockdownVpnTracker mLockdownTracker;
- final private Context mContext;
- private int mNetworkPreference;
- // 0 is full bad, 100 is full good
- private int mDefaultInetConditionPublished = 0;
- private boolean mTestMode;
- private static ConnectivityService sServiceInstance;
- private INetworkManagementService mNetd;
- private INetworkStatsService mStatsService;
- private INetworkPolicyManager mPolicyManager;
- private NetworkPolicyManagerInternal mPolicyManagerInternal;
- private String mCurrentTcpBufferSizes;
- private static final int ENABLED = 1;
- private static final int DISABLED = 0;
- private static final SparseArray<String> sMagicDecoderRing = MessageUtils.findMessageNames(
- new Class[] { AsyncChannel.class, ConnectivityService.class, NetworkAgent.class,
- NetworkAgentInfo.class });
- private enum ReapUnvalidatedNetworks {
- // Tear down networks that have no chance (e.g. even if validated) of becoming
- // the highest scoring network satisfying a NetworkRequest. This should be passed when
- // all networks have been rematched against all NetworkRequests.
- REAP,
- // Don't reap networks. This should be passed when some networks have not yet been
- // rematched against all NetworkRequests.
- DONT_REAP
- };
- private enum UnneededFor {
- LINGER, // Determine whether this network is unneeded and should be lingered.
- TEARDOWN, // Determine whether this network is unneeded and should be torn down.
- }
- /**
- * used internally to change our mobile data enabled flag
- */
- private static final int EVENT_CHANGE_MOBILE_DATA_ENABLED = 2;
- /**
- * used internally to clear a wakelock when transitioning
- * from one net to another. Clear happens when we get a new
- * network - EVENT_EXPIRE_NET_TRANSITION_WAKELOCK happens
- * after a timeout if no network is found (typically 1 min).
- */
- private static final int EVENT_CLEAR_NET_TRANSITION_WAKELOCK = 8;
- /**
- * used internally to reload global proxy settings
- */
- private static final int EVENT_APPLY_GLOBAL_HTTP_PROXY = 9;
- /**
- * PAC manager has received new port.
- */
- private static final int EVENT_PROXY_HAS_CHANGED = 16;
- /**
- * used internally when registering NetworkFactories
- * obj = NetworkFactoryInfo
- */
- private static final int EVENT_REGISTER_NETWORK_FACTORY = 17;
- /**
- * used internally when registering NetworkAgents
- * obj = Messenger
- */
- private static final int EVENT_REGISTER_NETWORK_AGENT = 18;
- /**
- * used to add a network request
- * includes a NetworkRequestInfo
- */
- private static final int EVENT_REGISTER_NETWORK_REQUEST = 19;
- /**
- * indicates a timeout period is over - check if we had a network yet or not
- * and if not, call the timeout callback (but leave the request live until they
- * cancel it.
- * includes a NetworkRequestInfo
- */
- private static final int EVENT_TIMEOUT_NETWORK_REQUEST = 20;
- /**
- * used to add a network listener - no request
- * includes a NetworkRequestInfo
- */
- private static final int EVENT_REGISTER_NETWORK_LISTENER = 21;
- /**
- * used to remove a network request, either a listener or a real request
- * arg1 = UID of caller
- * obj = NetworkRequest
- */
- private static final int EVENT_RELEASE_NETWORK_REQUEST = 22;
- /**
- * used internally when registering NetworkFactories
- * obj = Messenger
- */
- private static final int EVENT_UNREGISTER_NETWORK_FACTORY = 23;
- /**
- * used internally to expire a wakelock when transitioning
- * from one net to another. Expire happens when we fail to find
- * a new network (typically after 1 minute) -
- * EVENT_CLEAR_NET_TRANSITION_WAKELOCK happens if we had found
- * a replacement network.
- */
- private static final int EVENT_EXPIRE_NET_TRANSITION_WAKELOCK = 24;
- /**
- * Used internally to indicate the system is ready.
- */
- private static final int EVENT_SYSTEM_READY = 25;
- /**
- * used to add a network request with a pending intent
- * obj = NetworkRequestInfo
- */
- private static final int EVENT_REGISTER_NETWORK_REQUEST_WITH_INTENT = 26;
- /**
- * used to remove a pending intent and its associated network request.
- * arg1 = UID of caller
- * obj = PendingIntent
- */
- private static final int EVENT_RELEASE_NETWORK_REQUEST_WITH_INTENT = 27;
- /**
- * used to specify whether a network should be used even if unvalidated.
- * arg1 = whether to accept the network if it's unvalidated (1 or 0)
- * arg2 = whether to remember this choice in the future (1 or 0)
- * obj = network
- */
- private static final int EVENT_SET_ACCEPT_UNVALIDATED = 28;
- /**
- * used to ask the user to confirm a connection to an unvalidated network.
- * obj = network
- */
- private static final int EVENT_PROMPT_UNVALIDATED = 29;
- /**
- * used internally to (re)configure mobile data always-on settings.
- */
- private static final int EVENT_CONFIGURE_MOBILE_DATA_ALWAYS_ON = 30;
- /**
- * used to add a network listener with a pending intent
- * obj = NetworkRequestInfo
- */
- private static final int EVENT_REGISTER_NETWORK_LISTENER_WITH_INTENT = 31;
- /**
- * used to specify whether a network should not be penalized when it becomes unvalidated.
- */
- private static final int EVENT_SET_AVOID_UNVALIDATED = 35;
- /**
- * used to trigger revalidation of a network.
- */
- private static final int EVENT_REVALIDATE_NETWORK = 36;
- // Handle changes in Private DNS settings.
- private static final int EVENT_PRIVATE_DNS_SETTINGS_CHANGED = 37;
- private static String eventName(int what) {
- return sMagicDecoderRing.get(what, Integer.toString(what));
- }
- /** Handler thread used for both of the handlers below. */
- @VisibleForTesting
- protected final HandlerThread mHandlerThread;
- /** Handler used for internal events. */
- final private InternalHandler mHandler;
- /** Handler used for incoming {@link NetworkStateTracker} events. */
- final private NetworkStateTrackerHandler mTrackerHandler;
- private final DnsManager mDnsManager;
- private boolean mSystemReady;
- private Intent mInitialBroadcast;
- private PowerManager.WakeLock mNetTransitionWakeLock;
- private int mNetTransitionWakeLockTimeout;
- private final PowerManager.WakeLock mPendingIntentWakeLock;
- // track the current default http proxy - tell the world if we get a new one (real change)
- private volatile ProxyInfo mDefaultProxy = null;
- private Object mProxyLock = new Object();
- private boolean mDefaultProxyDisabled = false;
- // track the global proxy.
- private ProxyInfo mGlobalProxy = null;
- private PacManager mPacManager = null;
- final private SettingsObserver mSettingsObserver;
- private UserManager mUserManager;
- NetworkConfig[] mNetConfigs;
- int mNetworksDefined;
- // the set of network types that can only be enabled by system/sig apps
- List mProtectedNetworks;
- private DataConnectionStats mDataConnectionStats;
- TelephonyManager mTelephonyManager;
- private KeepaliveTracker mKeepaliveTracker;
- private NetworkNotificationManager mNotifier;
- private LingerMonitor mLingerMonitor;
- // sequence number for Networks; keep in sync with system/netd/NetworkController.cpp
- private static final int MIN_NET_ID = 100; // some reserved marks
- private static final int MAX_NET_ID = 65535 - 0x0400; // Top 1024 bits reserved by IpSecService
- private int mNextNetId = MIN_NET_ID;
- // sequence number of NetworkRequests
- private int mNextNetworkRequestId = 1;
- // NetworkRequest activity String log entries.
- private static final int MAX_NETWORK_REQUEST_LOGS = 20;
- private final LocalLog mNetworkRequestInfoLogs = new LocalLog(MAX_NETWORK_REQUEST_LOGS);
- // NetworkInfo blocked and unblocked String log entries
- private static final int MAX_NETWORK_INFO_LOGS = 40;
- private final LocalLog mNetworkInfoBlockingLogs = new LocalLog(MAX_NETWORK_INFO_LOGS);
- private static final int MAX_WAKELOCK_LOGS = 20;
- private final LocalLog mWakelockLogs = new LocalLog(MAX_WAKELOCK_LOGS);
- private int mTotalWakelockAcquisitions = 0;
- private int mTotalWakelockReleases = 0;
- private long mTotalWakelockDurationMs = 0;
- private long mMaxWakelockDurationMs = 0;
- private long mLastWakeLockAcquireTimestamp = 0;
- // Array of <Network,ReadOnlyLocalLogs> tracking network validation and results
- private static final int MAX_VALIDATION_LOGS = 10;
- private static class ValidationLog {
- final Network mNetwork;
- final String mNetworkExtraInfo;
- final ReadOnlyLocalLog mLog;
- ValidationLog(Network network, String networkExtraInfo, ReadOnlyLocalLog log) {
- mNetwork = network;
- mNetworkExtraInfo = networkExtraInfo;
- mLog = log;
- }
- }
- private final ArrayDeque<ValidationLog> mValidationLogs =
- new ArrayDeque<ValidationLog>(MAX_VALIDATION_LOGS);
- private void addValidationLogs(ReadOnlyLocalLog log, Network network, String networkExtraInfo) {
- synchronized (mValidationLogs) {
- while (mValidationLogs.size() >= MAX_VALIDATION_LOGS) {
- mValidationLogs.removeLast();
- }
- mValidationLogs.addFirst(new ValidationLog(network, networkExtraInfo, log));
- }
- }
- private final IpConnectivityLog mMetricsLog;
- @VisibleForTesting
- final MultinetworkPolicyTracker mMultinetworkPolicyTracker;
- /**
- * Implements support for the legacy "one network per network type" model.
- *
- * We used to have a static array of NetworkStateTrackers, one for each
- * network type, but that doesn't work any more now that we can have,
- * for example, more that one wifi network. This class stores all the
- * NetworkAgentInfo objects that support a given type, but the legacy
- * API will only see the first one.
- *
- * It serves two main purposes:
- *
- * 1. Provide information about "the network for a given type" (since this
- * API only supports one).
- * 2. Send legacy connectivity change broadcasts. Broadcasts are sent if
- * the first network for a given type changes, or if the default network
- * changes.
- */
- private class LegacyTypeTracker {
- private static final boolean DBG = true;
- private static final boolean VDBG = false;
- /**
- * Array of lists, one per legacy network type (e.g., TYPE_MOBILE_MMS).
- * Each list holds references to all NetworkAgentInfos that are used to
- * satisfy requests for that network type.
- *
- * This array is built out at startup such that an unsupported network
- * doesn't get an ArrayList instance, making this a tristate:
- * unsupported, supported but not active and active.
- *
- * The actual lists are populated when we scan the network types that
- * are supported on this device.
- *
- * Threading model:
- * - addSupportedType() is only called in the constructor
- * - add(), update(), remove() are only called from the ConnectivityService handler thread.
- * They are therefore not thread-safe with respect to each other.
- * - getNetworkForType() can be called at any time on binder threads. It is synchronized
- * on mTypeLists to be thread-safe with respect to a concurrent remove call.
- * - dump is thread-safe with respect to concurrent add and remove calls.
- */
- private final ArrayList<NetworkAgentInfo> mTypeLists[];
- public LegacyTypeTracker() {
- mTypeLists = (ArrayList<NetworkAgentInfo>[])
- new ArrayList[ConnectivityManager.MAX_NETWORK_TYPE + 1];
- }
- public void addSupportedType(int type) {
- if (mTypeLists[type] != null) {
- throw new IllegalStateException(
- "legacy list for type " + type + "already initialized");
- }
- mTypeLists[type] = new ArrayList<NetworkAgentInfo>();
- }
- public boolean isTypeSupported(int type) {
- return isNetworkTypeValid(type) && mTypeLists[type] != null;
- }
- public NetworkAgentInfo getNetworkForType(int type) {
- synchronized (mTypeLists) {
- if (isTypeSupported(type) && !mTypeLists[type].isEmpty()) {
- return mTypeLists[type].get(0);
- }
- }
- return null;
- }
- private void maybeLogBroadcast(NetworkAgentInfo nai, DetailedState state, int type,
- boolean isDefaultNetwork) {
- if (DBG) {
- log("Sending " + state +
- " broadcast for type " + type + " " + nai.name() +
- " isDefaultNetwork=" + isDefaultNetwork);
- }
- }
- /** Adds the given network to the specified legacy type list. */
- public void add(int type, NetworkAgentInfo nai) {
- if (!isTypeSupported(type)) {
- return; // Invalid network type.
- }
- if (VDBG) log("Adding agent " + nai + " for legacy network type " + type);
- ArrayList<NetworkAgentInfo> list = mTypeLists[type];
- if (list.contains(nai)) {
- return;
- }
- synchronized (mTypeLists) {
- list.add(nai);
- }
- // Send a broadcast if this is the first network of its type or if it's the default.
- final boolean isDefaultNetwork = isDefaultNetwork(nai);
- if ((list.size() == 1) || isDefaultNetwork) {
- maybeLogBroadcast(nai, DetailedState.CONNECTED, type, isDefaultNetwork);
- sendLegacyNetworkBroadcast(nai, DetailedState.CONNECTED, type);
- }
- }
- /** Removes the given network from the specified legacy type list. */
- public void remove(int type, NetworkAgentInfo nai, boolean wasDefault) {
- ArrayList<NetworkAgentInfo> list = mTypeLists[type];
- if (list == null || list.isEmpty()) {
- return;
- }
- final boolean wasFirstNetwork = list.get(0).equals(nai);
- synchronized (mTypeLists) {
- if (!list.remove(nai)) {
- return;
- }
- }
- final DetailedState state = DetailedState.DISCONNECTED;
- if (wasFirstNetwork || wasDefault) {
- maybeLogBroadcast(nai, state, type, wasDefault);
- sendLegacyNetworkBroadcast(nai, state, type);
- }
- if (!list.isEmpty() && wasFirstNetwork) {
- if (DBG) log("Other network available for type " + type +
- ", sending connected broadcast");
- final NetworkAgentInfo replacement = list.get(0);
- maybeLogBroadcast(replacement, state, type, isDefaultNetwork(replacement));
- sendLegacyNetworkBroadcast(replacement, state, type);
- }
- }
- /** Removes the given network from all legacy type lists. */
- public void remove(NetworkAgentInfo nai, boolean wasDefault) {
- if (VDBG) log("Removing agent " + nai + " wasDefault=" + wasDefault);
- for (int type = 0; type < mTypeLists.length; type++) {
- remove(type, nai, wasDefault);
- }
- }
- // send out another legacy broadcast - currently only used for suspend/unsuspend
- // toggle
- public void update(NetworkAgentInfo nai) {
- final boolean isDefault = isDefaultNetwork(nai);
- final DetailedState state = nai.networkInfo.getDetailedState();
- for (int type = 0; type < mTypeLists.length; type++) {
- final ArrayList<NetworkAgentInfo> list = mTypeLists[type];
- final boolean contains = (list != null && list.contains(nai));
- final boolean isFirst = contains && (nai == list.get(0));
- if (isFirst || contains && isDefault) {
- maybeLogBroadcast(nai, state, type, isDefault);
- sendLegacyNetworkBroadcast(nai, state, type);
- }
- }
- }
- private String naiToString(NetworkAgentInfo nai) {
- String name = (nai != null) ? nai.name() : "null";
- String state = (nai.networkInfo != null) ?
- nai.networkInfo.getState() + "/" + nai.networkInfo.getDetailedState() :
- "???/???";
- return name + " " + state;
- }
- public void dump(IndentingPrintWriter pw) {
- pw.println("mLegacyTypeTracker:");
- pw.increaseIndent();
- pw.print("Supported types:");
- for (int type = 0; type < mTypeLists.length; type++) {
- if (mTypeLists[type] != null) pw.print(" " + type);
- }
- pw.println();
- pw.println("Current state:");
- pw.increaseIndent();
- synchronized (mTypeLists) {
- for (int type = 0; type < mTypeLists.length; type++) {
- if (mTypeLists[type] == null || mTypeLists[type].isEmpty()) continue;
- for (NetworkAgentInfo nai : mTypeLists[type]) {
- pw.println(type + " " + naiToString(nai));
- }
- }
- }
- pw.decreaseIndent();
- pw.decreaseIndent();
- pw.println();
- }
- }
- private LegacyTypeTracker mLegacyTypeTracker = new LegacyTypeTracker();
- public ConnectivityService(Context context, INetworkManagementService netManager,
- INetworkStatsService statsService, INetworkPolicyManager policyManager) {
- this(context, netManager, statsService, policyManager, new IpConnectivityLog());
- }
- @VisibleForTesting
- protected ConnectivityService(Context context, INetworkManagementService netManager,
- INetworkStatsService statsService, INetworkPolicyManager policyManager,
- IpConnectivityLog logger) {
- if (DBG) log("ConnectivityService starting up");
- mSystemProperties = getSystemProperties();
- mMetricsLog = logger;
- mDefaultRequest = createDefaultInternetRequestForTransport(-1, NetworkRequest.Type.REQUEST);
- NetworkRequestInfo defaultNRI = new NetworkRequestInfo(null, mDefaultRequest, new Binder());
- mNetworkRequests.put(mDefaultRequest, defaultNRI);
- mNetworkRequestInfoLogs.log("REGISTER " + defaultNRI);
- mDefaultMobileDataRequest = createDefaultInternetRequestForTransport(
- NetworkCapabilities.TRANSPORT_CELLULAR, NetworkRequest.Type.BACKGROUND_REQUEST);
- mHandlerThread = new HandlerThread("ConnectivityServiceThread");
- mHandlerThread.start();
- mHandler = new InternalHandler(mHandlerThread.getLooper());
- mTrackerHandler = new NetworkStateTrackerHandler(mHandlerThread.getLooper());
- mReleasePendingIntentDelayMs = Settings.Secure.getInt(context.getContentResolver(),
- Settings.Secure.CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS, 5_000);
- mLingerDelayMs = mSystemProperties.getInt(LINGER_DELAY_PROPERTY, DEFAULT_LINGER_DELAY_MS);
- mContext = checkNotNull(context, "missing Context");
- mNetd = checkNotNull(netManager, "missing INetworkManagementService");
- mStatsService = checkNotNull(statsService, "missing INetworkStatsService");
- mPolicyManager = checkNotNull(policyManager, "missing INetworkPolicyManager");
- mPolicyManagerInternal = checkNotNull(
- LocalServices.getService(NetworkPolicyManagerInternal.class),
- "missing NetworkPolicyManagerInternal");
- mKeyStore = KeyStore.getInstance();
- mTelephonyManager = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
- try {
- mPolicyManager.registerListener(mPolicyListener);
- } catch (RemoteException e) {
- // ouch, no rules updates means some processes may never get network
- loge("unable to register INetworkPolicyListener" + e);
- }
- final PowerManager powerManager = (PowerManager) context.getSystemService(
- Context.POWER_SERVICE);
- mNetTransitionWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
- mNetTransitionWakeLockTimeout = mContext.getResources().getInteger(
- com.android.internal.R.integer.config_networkTransitionTimeout);
- mPendingIntentWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
- mNetConfigs = new NetworkConfig[ConnectivityManager.MAX_NETWORK_TYPE+1];
- // TODO: What is the "correct" way to do determine if this is a wifi only device?
- boolean wifiOnly = mSystemProperties.getBoolean("ro.radio.noril", false);
- log("wifiOnly=" + wifiOnly);
- String[] naStrings = context.getResources().getStringArray(
- com.android.internal.R.array.networkAttributes);
- for (String naString : naStrings) {
- try {
- NetworkConfig n = new NetworkConfig(naString);
- if (VDBG) log("naString=" + naString + " config=" + n);
- if (n.type > ConnectivityManager.MAX_NETWORK_TYPE) {
- loge("Error in networkAttributes - ignoring attempt to define type " +
- n.type);
- continue;
- }
- if (wifiOnly && ConnectivityManager.isNetworkTypeMobile(n.type)) {
- log("networkAttributes - ignoring mobile as this dev is wifiOnly " +
- n.type);
- continue;
- }
- if (mNetConfigs[n.type] != null) {
- loge("Error in networkAttributes - ignoring attempt to redefine type " +
- n.type);
- continue;
- }
- mLegacyTypeTracker.addSupportedType(n.type);
- mNetConfigs[n.type] = n;
- mNetworksDefined++;
- } catch(Exception e) {
- // ignore it - leave the entry null
- }
- }
- // Forcibly add TYPE_VPN as a supported type, if it has not already been added via config.
- if (mNetConfigs[TYPE_VPN] == null) {
- // mNetConfigs is used only for "restore time", which isn't applicable to VPNs, so we
- // don't need to add TYPE_VPN to mNetConfigs.
- mLegacyTypeTracker.addSupportedType(TYPE_VPN);
- mNetworksDefined++; // used only in the log() statement below.
- }
- // Do the same for Ethernet, since it's often not specified in the configs, although many
- // devices can use it via USB host adapters.
- if (mNetConfigs[TYPE_ETHERNET] == null && hasService(Context.ETHERNET_SERVICE)) {
- mLegacyTypeTracker.addSupportedType(TYPE_ETHERNET);
- mNetworksDefined++;
- }
- if (VDBG) log("mNetworksDefined=" + mNetworksDefined);
- mProtectedNetworks = new ArrayList<Integer>();
- int[] protectedNetworks = context.getResources().getIntArray(
- com.android.internal.R.array.config_protectedNetworks);
- for (int p : protectedNetworks) {
- if ((mNetConfigs[p] != null) && (mProtectedNetworks.contains(p) == false)) {
- mProtectedNetworks.add(p);
- } else {
- if (DBG) loge("Ignoring protectedNetwork " + p);
- }
- }
- mTestMode = mSystemProperties.get("cm.test.mode").equals("true")
- && mSystemProperties.get("ro.build.type").equals("eng");
- mTethering = makeTethering();
- mPermissionMonitor = new PermissionMonitor(mContext, mNetd);
- //set up the listener for user state for creating user VPNs
- IntentFilter intentFilter = new IntentFilter();
- intentFilter.addAction(Intent.ACTION_USER_STARTED);
- intentFilter.addAction(Intent.ACTION_USER_STOPPED);
- intentFilter.addAction(Intent.ACTION_USER_ADDED);
- intentFilter.addAction(Intent.ACTION_USER_REMOVED);
- intentFilter.addAction(Intent.ACTION_USER_UNLOCKED);
- mContext.registerReceiverAsUser(
- mUserIntentReceiver, UserHandle.ALL, intentFilter, null, null);
- mContext.registerReceiverAsUser(mUserPresentReceiver, UserHandle.SYSTEM,
- new IntentFilter(Intent.ACTION_USER_PRESENT), null, null);
- try {
- mNetd.registerObserver(mTethering);
- mNetd.registerObserver(mDataActivityObserver);
- } catch (RemoteException e) {
- loge("Error registering observer :" + e);
- }
- mSettingsObserver = new SettingsObserver(mContext, mHandler);
- registerSettingsCallbacks();
- mDataConnectionStats = new DataConnectionStats(mContext);
- mDataConnectionStats.startMonitoring();
- mPacManager = new PacManager(mContext, mHandler, EVENT_PROXY_HAS_CHANGED);
- mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
- mKeepaliveTracker = new KeepaliveTracker(mHandler);
- mNotifier = new NetworkNotificationManager(mContext, mTelephonyManager,
- mContext.getSystemService(NotificationManager.class));
- final int dailyLimit = Settings.Global.getInt(mContext.getContentResolver(),
- Settings.Global.NETWORK_SWITCH_NOTIFICATION_DAILY_LIMIT,
- LingerMonitor.DEFAULT_NOTIFICATION_DAILY_LIMIT);
- final long rateLimit = Settings.Global.getLong(mContext.getContentResolver(),
- Settings.Global.NETWORK_SWITCH_NOTIFICATION_RATE_LIMIT_MILLIS,
- LingerMonitor.DEFAULT_NOTIFICATION_RATE_LIMIT_MILLIS);
- mLingerMonitor = new LingerMonitor(mContext, mNotifier, dailyLimit, rateLimit);
- mMultinetworkPolicyTracker = createMultinetworkPolicyTracker(
- mContext, mHandler, () -> rematchForAvoidBadWifiUpdate());
- mMultinetworkPolicyTracker.start();
- mDnsManager = new DnsManager(mContext, mNetd, mSystemProperties);
- registerPrivateDnsSettingsCallbacks();
- }
- private Tethering makeTethering() {
- // TODO: Move other elements into @Overridden getters.
- final TetheringDependencies deps = new TetheringDependencies();
- return new Tethering(mContext, mNetd, mStatsService, mPolicyManager,
- IoThread.get().getLooper(), new MockableSystemProperties(),
- deps);
- }
- private NetworkRequest createDefaultInternetRequestForTransport(
- int transportType, NetworkRequest.Type type) {
- NetworkCapabilities netCap = new NetworkCapabilities();
- netCap.addCapability(NET_CAPABILITY_INTERNET);
- netCap.addCapability(NET_CAPABILITY_NOT_RESTRICTED);
- if (transportType > -1) {
- netCap.addTransportType(transportType);
- }
- return new NetworkRequest(netCap, TYPE_NONE, nextNetworkRequestId(), type);
- }
- // Used only for testing.
- // TODO: Delete this and either:
- // 1. Give Fake SettingsProvider the ability to send settings change notifications (requires
- // changing ContentResolver to make registerContentObserver non-final).
- // 2. Give FakeSettingsProvider an alternative notification mechanism and have the test use it
- // by subclassing SettingsObserver.
- @VisibleForTesting
- void updateMobileDataAlwaysOn() {
- mHandler.sendEmptyMessage(EVENT_CONFIGURE_MOBILE_DATA_ALWAYS_ON);
- }
- private void handleMobileDataAlwaysOn() {
- final boolean enable = toBool(Settings.Global.getInt(
- mContext.getContentResolver(), Settings.Global.MOBILE_DATA_ALWAYS_ON, 1));
- final boolean isEnabled = (mNetworkRequests.get(mDefaultMobileDataRequest) != null);
- if (enable == isEnabled) {
- return; // Nothing to do.
- }
- if (enable) {
- handleRegisterNetworkRequest(new NetworkRequestInfo(
- null, mDefaultMobileDataRequest, new Binder()));
- } else {
- handleReleaseNetworkRequest(mDefaultMobileDataRequest, Process.SYSTEM_UID);
- }
- }
- private void registerSettingsCallbacks() {
- // Watch for global HTTP proxy changes.
- mSettingsObserver.observe(
- Settings.Global.getUriFor(Settings.Global.HTTP_PROXY),
- EVENT_APPLY_GLOBAL_HTTP_PROXY);
- // Watch for whether or not to keep mobile data always on.
- mSettingsObserver.observe(
- Settings.Global.getUriFor(Settings.Global.MOBILE_DATA_ALWAYS_ON),
- EVENT_CONFIGURE_MOBILE_DATA_ALWAYS_ON);
- }
- private void registerPrivateDnsSettingsCallbacks() {
- for (Uri u : DnsManager.getPrivateDnsSettingsUris()) {
- mSettingsObserver.observe(u, EVENT_PRIVATE_DNS_SETTINGS_CHANGED);
- }
- }
- private synchronized int nextNetworkRequestId() {
- return mNextNetworkRequestId++;
- }
- @VisibleForTesting
- protected int reserveNetId() {
- synchronized (mNetworkForNetId) {
- for (int i = MIN_NET_ID; i <= MAX_NET_ID; i++) {
- int netId = mNextNetId;
- if (++mNextNetId > MAX_NET_ID) mNextNetId = MIN_NET_ID;
- // Make sure NetID unused. http://b/16815182
- if (!mNetIdInUse.get(netId)) {
- mNetIdInUse.put(netId, true);
- return netId;
- }
- }
- }
- throw new IllegalStateException("No free netIds");
- }
- private NetworkState getFilteredNetworkState(int networkType, int uid, boolean ignoreBlocked) {
- if (mLegacyTypeTracker.isTypeSupported(networkType)) {
- final NetworkAgentInfo nai = mLegacyTypeTracker.getNetworkForType(networkType);
- final NetworkState state;
- if (nai != null) {
- state = nai.getNetworkState();
- state.networkInfo.setType(networkType);
- } else {
- final NetworkInfo info = new NetworkInfo(networkType, 0,
- getNetworkTypeName(networkType), "");
- info.setDetailedState(NetworkInfo.DetailedState.DISCONNECTED, null, null);
- info.setIsAvailable(true);
- final NetworkCapabilities capabilities = new NetworkCapabilities();
- capabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING,
- !info.isRoaming());
- state = new NetworkState(info, new LinkProperties(), capabilities,
- null, null, null);
- }
- filterNetworkStateForUid(state, uid, ignoreBlocked);
- return state;
- } else {
- return NetworkState.EMPTY;
- }
- }
- private NetworkAgentInfo getNetworkAgentInfoForNetwork(Network network) {
- if (network == null) {
- return null;
- }
- synchronized (mNetworkForNetId) {
- return mNetworkForNetId.get(network.netId);
- }
- }
- private Network[] getVpnUnderlyingNetworks(int uid) {
- synchronized (mVpns) {
- if (!mLockdownEnabled) {
- int user = UserHandle.getUserId(uid);
- Vpn vpn = mVpns.get(user);
- if (vpn != null && vpn.appliesToUid(uid)) {
- return vpn.getUnderlyingNetworks();
- }
- }
- }
- return null;
- }
- private NetworkState getUnfilteredActiveNetworkState(int uid) {
- NetworkAgentInfo nai = getDefaultNetwork();
- final Network[] networks = getVpnUnderlyingNetworks(uid);
- if (networks != null) {
- // getUnderlyingNetworks() returns:
- // null => there was no VPN, or the VPN didn't specify anything, so we use the default.
- // empty array => the VPN explicitly said "no default network".
- // non-empty array => the VPN specified one or more default networks; we use the
- // first one.
- if (networks.length > 0) {
- nai = getNetworkAgentInfoForNetwork(networks[0]);
- } else {
- nai = null;
- }
- }
- if (nai != null) {
- return nai.getNetworkState();
- } else {
- return NetworkState.EMPTY;
- }
- }
- /**
- * Check if UID should be blocked from using the network with the given LinkProperties.
- */
- private boolean isNetworkWithLinkPropertiesBlocked(LinkProperties lp, int uid,
- boolean ignoreBlocked) {
- // Networks aren't blocked when ignoring blocked status
- if (ignoreBlocked) {
- return false;
- }
- // Networks are never blocked for system services
- // TODO: consider moving this check to NetworkPolicyManagerInternal.isUidNetworkingBlocked.
- if (isSystem(uid)) {
- return false;
- }
- synchronized (mVpns) {
- final Vpn vpn = mVpns.get(UserHandle.getUserId(uid));
- if (vpn != null && vpn.isBlockingUid(uid)) {
- return true;
- }
- }
- final String iface = (lp == null ? "" : lp.getInterfaceName());
- return mPolicyManagerInternal.isUidNetworkingBlocked(uid, iface);
- }
- private void maybeLogBlockedNetworkInfo(NetworkInfo ni, int uid) {
- if (ni == null || !LOGD_BLOCKED_NETWORKINFO) {
- return;
- }
- final boolean blocked;
- synchronized (mBlockedAppUids) {
- if (ni.getDetailedState() == DetailedState.BLOCKED && mBlockedAppUids.add(uid)) {
- blocked = true;
- } else if (ni.isConnected() && mBlockedAppUids.remove(uid)) {
- blocked = false;
- } else {
- return;
- }
- }
- String action = blocked ? "BLOCKED" : "UNBLOCKED";
- log(String.format("Returning %s NetworkInfo to uid=%d", action, uid));
- mNetworkInfoBlockingLogs.log(action + " " + uid);
- }
- /**
- * Apply any relevant filters to {@link NetworkState} for the given UID. For
- * example, this may mark the network as {@link DetailedState#BLOCKED} based
- * on {@link #isNetworkWithLinkPropertiesBlocked}.
- */
- private void filterNetworkStateForUid(NetworkState state, int uid, boolean ignoreBlocked) {
- if (state == null || state.networkInfo == null || state.linkProperties == null) return;
- if (isNetworkWithLinkPropertiesBlocked(state.linkProperties, uid, ignoreBlocked)) {
- state.networkInfo.setDetailedState(DetailedState.BLOCKED, null, null);
- }
- synchronized (mVpns) {
- if (mLockdownTracker != null) {
- mLockdownTracker.augmentNetworkInfo(state.networkInfo);
- }
- }
- }
- /**
- * Return NetworkInfo for the active (i.e., connected) network interface.
- * It is assumed that at most one network is active at a time. If more
- * than one is active, it is indeterminate which will be returned.
- * @return the info for the active network, or {@code null} if none is
- * active
- */
- @Override
- public NetworkInfo getActiveNetworkInfo() {
- enforceAccessPermission();
- final int uid = Binder.getCallingUid();
- final NetworkState state = getUnfilteredActiveNetworkState(uid);
- filterNetworkStateForUid(state, uid, false);
- maybeLogBlockedNetworkInfo(state.networkInfo, uid);
- return state.networkInfo;
- }
- @Override
- public Network getActiveNetwork() {
- enforceAccessPermission();
- return getActiveNetworkForUidInternal(Binder.getCallingUid(), false);
- }
- @Override
- public Network getActiveNetworkForUid(int uid, boolean ignoreBlocked) {
- enforceConnectivityInternalPermission();
- return getActiveNetworkForUidInternal(uid, ignoreBlocked);
- }
- private Network getActiveNetworkForUidInternal(final int uid, boolean ignoreBlocked) {
- final int user = UserHandle.getUserId(uid);
- int vpnNetId = NETID_UNSET;
- synchronized (mVpns) {
- final Vpn vpn = mVpns.get(user);
- if (vpn != null && vpn.appliesToUid(uid)) vpnNetId = vpn.getNetId();
- }
- NetworkAgentInfo nai;
- if (vpnNetId != NETID_UNSET) {
- synchronized (mNetworkForNetId) {
- nai = mNetworkForNetId.get(vpnNetId);
- }
- if (nai != null) return nai.network;
- }
- nai = getDefaultNetwork();
- if (nai != null
- && isNetworkWithLinkPropertiesBlocked(nai.linkProperties, uid, ignoreBlocked)) {
- nai = null;
- }
- return nai != null ? nai.network : null;
- }
- // Public because it's used by mLockdownTracker.
- public NetworkInfo getActiveNetworkInfoUnfiltered() {
- enforceAccessPermission();
- final int uid = Binder.getCallingUid();
- NetworkState state = getUnfilteredActiveNetworkState(uid);
- return state.networkInfo;
- }
- @Override
- public NetworkInfo getActiveNetworkInfoForUid(int uid, boolean ignoreBlocked) {
- enforceConnectivityInternalPermission();
- final NetworkState state = getUnfilteredActiveNetworkState(uid);
- filterNetworkStateForUid(state, uid, ignoreBlocked);
- return state.networkInfo;
- }
- @Override
- public NetworkInfo getNetworkInfo(int networkType) {
- enforceAccessPermission();
- final int uid = Binder.getCallingUid();
- if (getVpnUnderlyingNetworks(uid) != null) {
- // A VPN is active, so we may need to return one of its underlying networks. This
- // information is not available in LegacyTypeTracker, so we have to get it from
- // getUnfilteredActiveNetworkState.
- final NetworkState state = getUnfilteredActiveNetworkState(uid);
- if (state.networkInfo != null && state.networkInfo.getType() == networkType) {
- filterNetworkStateForUid(state, uid, false);
- return state.networkInfo;
- }
- }
- final NetworkState state = getFilteredNetworkState(networkType, uid, false);
- return state.networkInfo;
- }
- @Override
- public NetworkInfo getNetworkInfoForUid(Network network, int uid, boolean ignoreBlocked) {
- enforceAccessPermission();
- final NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
- if (nai != null) {
- final NetworkState state = nai.getNetworkState();
- filterNetworkStateForUid(state, uid, ignoreBlocked);
- return state.networkInfo;
- } else {
- return null;
- }
- }
- @Override
- public NetworkInfo[] getAllNetworkInfo() {
- enforceAccessPermission();
- final ArrayList<NetworkInfo> result = Lists.newArrayList();
- for (int networkType = 0; networkType <= ConnectivityManager.MAX_NETWORK_TYPE;
- networkType++) {
- NetworkInfo info = getNetworkInfo(networkType);
- if (info != null) {
- result.add(info);
- }
- }
- return result.toArray(new NetworkInfo[result.size()]);
- }
- @Override
- public Network getNetworkForType(int networkType) {
- enforceAccessPermission();
- final int uid = Binder.getCallingUid();
- NetworkState state = getFilteredNetworkState(networkType, uid, false);
- if (!isNetworkWithLinkPropertiesBlocked(state.linkProperties, uid, false)) {
- return state.network;
- }
- return null;
- }
- @Override
- public Network[] getAllNetworks() {
- enforceAccessPermission();
- synchronized (mNetworkForNetId) {
- final Network[] result = new Network[mNetworkForNetId.size()];
- for (int i = 0; i < mNetworkForNetId.size(); i++) {
- result[i] = mN…