Home | History | Annotate | Download | only in server
      1 /*
      2  * Copyright (C) 2008 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.server;
     18 
     19 import static android.Manifest.permission.RECEIVE_DATA_ACTIVITY_CHANGE;
     20 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
     21 import static android.net.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.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL;
     29 import static android.net.NetworkCapabilities.NET_CAPABILITY_FOREGROUND;
     30 import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
     31 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
     32 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
     33 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING;
     34 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED;
     35 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN;
     36 import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
     37 import static android.net.NetworkCapabilities.TRANSPORT_VPN;
     38 
     39 import static com.android.internal.util.Preconditions.checkNotNull;
     40 
     41 import android.annotation.Nullable;
     42 import android.app.BroadcastOptions;
     43 import android.app.NotificationManager;
     44 import android.app.PendingIntent;
     45 import android.content.BroadcastReceiver;
     46 import android.content.ContentResolver;
     47 import android.content.Context;
     48 import android.content.Intent;
     49 import android.content.IntentFilter;
     50 import android.content.res.Configuration;
     51 import android.database.ContentObserver;
     52 import android.net.ConnectivityManager;
     53 import android.net.ConnectivityManager.PacketKeepalive;
     54 import android.net.IConnectivityManager;
     55 import android.net.IIpConnectivityMetrics;
     56 import android.net.INetdEventCallback;
     57 import android.net.INetworkManagementEventObserver;
     58 import android.net.INetworkPolicyListener;
     59 import android.net.INetworkPolicyManager;
     60 import android.net.INetworkStatsService;
     61 import android.net.LinkProperties;
     62 import android.net.LinkProperties.CompareResult;
     63 import android.net.MatchAllNetworkSpecifier;
     64 import android.net.Network;
     65 import android.net.NetworkAgent;
     66 import android.net.NetworkCapabilities;
     67 import android.net.NetworkConfig;
     68 import android.net.NetworkInfo;
     69 import android.net.NetworkInfo.DetailedState;
     70 import android.net.NetworkMisc;
     71 import android.net.NetworkPolicyManager;
     72 import android.net.NetworkQuotaInfo;
     73 import android.net.NetworkRequest;
     74 import android.net.NetworkSpecifier;
     75 import android.net.NetworkState;
     76 import android.net.NetworkUtils;
     77 import android.net.NetworkWatchlistManager;
     78 import android.net.Proxy;
     79 import android.net.ProxyInfo;
     80 import android.net.RouteInfo;
     81 import android.net.UidRange;
     82 import android.net.Uri;
     83 import android.net.VpnService;
     84 import android.net.metrics.IpConnectivityLog;
     85 import android.net.metrics.NetworkEvent;
     86 import android.net.util.MultinetworkPolicyTracker;
     87 import android.os.Binder;
     88 import android.os.Build;
     89 import android.os.Bundle;
     90 import android.os.FileUtils;
     91 import android.os.Handler;
     92 import android.os.HandlerThread;
     93 import android.os.IBinder;
     94 import android.os.INetworkManagementService;
     95 import android.os.Looper;
     96 import android.os.Message;
     97 import android.os.Messenger;
     98 import android.os.ParcelFileDescriptor;
     99 import android.os.Parcelable;
    100 import android.os.PowerManager;
    101 import android.os.Process;
    102 import android.os.RemoteException;
    103 import android.os.ResultReceiver;
    104 import android.os.ServiceManager;
    105 import android.os.ServiceSpecificException;
    106 import android.os.ShellCallback;
    107 import android.os.ShellCommand;
    108 import android.os.SystemClock;
    109 import android.os.UserHandle;
    110 import android.os.UserManager;
    111 import android.provider.Settings;
    112 import android.security.Credentials;
    113 import android.security.KeyStore;
    114 import android.telephony.TelephonyManager;
    115 import android.text.TextUtils;
    116 import android.util.ArraySet;
    117 import android.util.LocalLog;
    118 import android.util.LocalLog.ReadOnlyLocalLog;
    119 import android.util.Log;
    120 import android.util.Slog;
    121 import android.util.SparseArray;
    122 import android.util.SparseBooleanArray;
    123 import android.util.SparseIntArray;
    124 import android.util.Xml;
    125 
    126 import com.android.internal.R;
    127 import com.android.internal.annotations.GuardedBy;
    128 import com.android.internal.annotations.VisibleForTesting;
    129 import com.android.internal.app.IBatteryStats;
    130 import com.android.internal.net.LegacyVpnInfo;
    131 import com.android.internal.net.NetworkStatsFactory;
    132 import com.android.internal.net.VpnConfig;
    133 import com.android.internal.net.VpnInfo;
    134 import com.android.internal.net.VpnProfile;
    135 import com.android.internal.util.ArrayUtils;
    136 import com.android.internal.util.AsyncChannel;
    137 import com.android.internal.util.DumpUtils;
    138 import com.android.internal.util.IndentingPrintWriter;
    139 import com.android.internal.util.MessageUtils;
    140 import com.android.internal.util.WakeupMessage;
    141 import com.android.internal.util.XmlUtils;
    142 import com.android.server.am.BatteryStatsService;
    143 import com.android.server.connectivity.DataConnectionStats;
    144 import com.android.server.connectivity.DnsManager;
    145 import com.android.server.connectivity.DnsManager.PrivateDnsConfig;
    146 import com.android.server.connectivity.DnsManager.PrivateDnsValidationUpdate;
    147 import com.android.server.connectivity.IpConnectivityMetrics;
    148 import com.android.server.connectivity.KeepaliveTracker;
    149 import com.android.server.connectivity.LingerMonitor;
    150 import com.android.server.connectivity.MockableSystemProperties;
    151 import com.android.server.connectivity.MultipathPolicyTracker;
    152 import com.android.server.connectivity.NetworkAgentInfo;
    153 import com.android.server.connectivity.NetworkDiagnostics;
    154 import com.android.server.connectivity.NetworkMonitor;
    155 import com.android.server.connectivity.NetworkNotificationManager;
    156 import com.android.server.connectivity.NetworkNotificationManager.NotificationType;
    157 import com.android.server.connectivity.PacManager;
    158 import com.android.server.connectivity.PermissionMonitor;
    159 import com.android.server.connectivity.Tethering;
    160 import com.android.server.connectivity.Vpn;
    161 import com.android.server.connectivity.tethering.TetheringDependencies;
    162 import com.android.server.net.BaseNetdEventCallback;
    163 import com.android.server.net.BaseNetworkObserver;
    164 import com.android.server.net.LockdownVpnTracker;
    165 import com.android.server.net.NetworkPolicyManagerInternal;
    166 import com.android.server.utils.PriorityDump;
    167 
    168 import com.google.android.collect.Lists;
    169 
    170 import org.xmlpull.v1.XmlPullParser;
    171 import org.xmlpull.v1.XmlPullParserException;
    172 
    173 import java.io.File;
    174 import java.io.FileDescriptor;
    175 import java.io.FileNotFoundException;
    176 import java.io.FileReader;
    177 import java.io.IOException;
    178 import java.io.PrintWriter;
    179 import java.net.Inet4Address;
    180 import java.net.InetAddress;
    181 import java.net.UnknownHostException;
    182 import java.util.ArrayDeque;
    183 import java.util.ArrayList;
    184 import java.util.Arrays;
    185 import java.util.Collection;
    186 import java.util.HashMap;
    187 import java.util.HashSet;
    188 import java.util.List;
    189 import java.util.Map;
    190 import java.util.Objects;
    191 import java.util.Set;
    192 import java.util.SortedSet;
    193 import java.util.TreeSet;
    194 
    195 /**
    196  * @hide
    197  */
    198 public class ConnectivityService extends IConnectivityManager.Stub
    199         implements PendingIntent.OnFinished {
    200     private static final String TAG = ConnectivityService.class.getSimpleName();
    201 
    202     public static final String DIAG_ARG = "--diag";
    203     public static final String SHORT_ARG = "--short";
    204     public static final String TETHERING_ARG = "tethering";
    205 
    206     private static final boolean DBG = true;
    207     private static final boolean VDBG = false;
    208 
    209     private static final boolean LOGD_RULES = false;
    210     private static final boolean LOGD_BLOCKED_NETWORKINFO = true;
    211 
    212     // TODO: create better separation between radio types and network types
    213 
    214     // how long to wait before switching back to a radio's default network
    215     private static final int RESTORE_DEFAULT_NETWORK_DELAY = 1 * 60 * 1000;
    216     // system property that can override the above value
    217     private static final String NETWORK_RESTORE_DELAY_PROP_NAME =
    218             "android.telephony.apn-restore";
    219 
    220     // How long to wait before putting up a "This network doesn't have an Internet connection,
    221     // connect anyway?" dialog after the user selects a network that doesn't validate.
    222     private static final int PROMPT_UNVALIDATED_DELAY_MS = 8 * 1000;
    223 
    224     // Default to 30s linger time-out. Modifiable only for testing.
    225     private static final String LINGER_DELAY_PROPERTY = "persist.netmon.linger";
    226     private static final int DEFAULT_LINGER_DELAY_MS = 30_000;
    227     @VisibleForTesting
    228     protected int mLingerDelayMs;  // Can't be final, or test subclass constructors can't change it.
    229 
    230     // How long to delay to removal of a pending intent based request.
    231     // See Settings.Secure.CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS
    232     private final int mReleasePendingIntentDelayMs;
    233 
    234     private MockableSystemProperties mSystemProperties;
    235 
    236     private Tethering mTethering;
    237 
    238     private final PermissionMonitor mPermissionMonitor;
    239 
    240     private KeyStore mKeyStore;
    241 
    242     @VisibleForTesting
    243     @GuardedBy("mVpns")
    244     protected final SparseArray<Vpn> mVpns = new SparseArray<Vpn>();
    245 
    246     // TODO: investigate if mLockdownEnabled can be removed and replaced everywhere by
    247     // a direct call to LockdownVpnTracker.isEnabled().
    248     @GuardedBy("mVpns")
    249     private boolean mLockdownEnabled;
    250     @GuardedBy("mVpns")
    251     private LockdownVpnTracker mLockdownTracker;
    252 
    253     final private Context mContext;
    254     private int mNetworkPreference;
    255     // 0 is full bad, 100 is full good
    256     private int mDefaultInetConditionPublished = 0;
    257 
    258     private boolean mTestMode;
    259     private static ConnectivityService sServiceInstance;
    260 
    261     private INetworkManagementService mNetd;
    262     private INetworkStatsService mStatsService;
    263     private INetworkPolicyManager mPolicyManager;
    264     private NetworkPolicyManagerInternal mPolicyManagerInternal;
    265     private IIpConnectivityMetrics mIpConnectivityMetrics;
    266 
    267     private String mCurrentTcpBufferSizes;
    268 
    269     private static final int ENABLED  = 1;
    270     private static final int DISABLED = 0;
    271 
    272     private static final SparseArray<String> sMagicDecoderRing = MessageUtils.findMessageNames(
    273             new Class[] { AsyncChannel.class, ConnectivityService.class, NetworkAgent.class,
    274                     NetworkAgentInfo.class });
    275 
    276     private enum ReapUnvalidatedNetworks {
    277         // Tear down networks that have no chance (e.g. even if validated) of becoming
    278         // the highest scoring network satisfying a NetworkRequest.  This should be passed when
    279         // all networks have been rematched against all NetworkRequests.
    280         REAP,
    281         // Don't reap networks.  This should be passed when some networks have not yet been
    282         // rematched against all NetworkRequests.
    283         DONT_REAP
    284     };
    285 
    286     private enum UnneededFor {
    287         LINGER,    // Determine whether this network is unneeded and should be lingered.
    288         TEARDOWN,  // Determine whether this network is unneeded and should be torn down.
    289     }
    290 
    291     /**
    292      * used internally to change our mobile data enabled flag
    293      */
    294     private static final int EVENT_CHANGE_MOBILE_DATA_ENABLED = 2;
    295 
    296     /**
    297      * used internally to clear a wakelock when transitioning
    298      * from one net to another.  Clear happens when we get a new
    299      * network - EVENT_EXPIRE_NET_TRANSITION_WAKELOCK happens
    300      * after a timeout if no network is found (typically 1 min).
    301      */
    302     private static final int EVENT_CLEAR_NET_TRANSITION_WAKELOCK = 8;
    303 
    304     /**
    305      * used internally to reload global proxy settings
    306      */
    307     private static final int EVENT_APPLY_GLOBAL_HTTP_PROXY = 9;
    308 
    309     /**
    310      * PAC manager has received new port.
    311      */
    312     private static final int EVENT_PROXY_HAS_CHANGED = 16;
    313 
    314     /**
    315      * used internally when registering NetworkFactories
    316      * obj = NetworkFactoryInfo
    317      */
    318     private static final int EVENT_REGISTER_NETWORK_FACTORY = 17;
    319 
    320     /**
    321      * used internally when registering NetworkAgents
    322      * obj = Messenger
    323      */
    324     private static final int EVENT_REGISTER_NETWORK_AGENT = 18;
    325 
    326     /**
    327      * used to add a network request
    328      * includes a NetworkRequestInfo
    329      */
    330     private static final int EVENT_REGISTER_NETWORK_REQUEST = 19;
    331 
    332     /**
    333      * indicates a timeout period is over - check if we had a network yet or not
    334      * and if not, call the timeout callback (but leave the request live until they
    335      * cancel it.
    336      * includes a NetworkRequestInfo
    337      */
    338     private static final int EVENT_TIMEOUT_NETWORK_REQUEST = 20;
    339 
    340     /**
    341      * used to add a network listener - no request
    342      * includes a NetworkRequestInfo
    343      */
    344     private static final int EVENT_REGISTER_NETWORK_LISTENER = 21;
    345 
    346     /**
    347      * used to remove a network request, either a listener or a real request
    348      * arg1 = UID of caller
    349      * obj  = NetworkRequest
    350      */
    351     private static final int EVENT_RELEASE_NETWORK_REQUEST = 22;
    352 
    353     /**
    354      * used internally when registering NetworkFactories
    355      * obj = Messenger
    356      */
    357     private static final int EVENT_UNREGISTER_NETWORK_FACTORY = 23;
    358 
    359     /**
    360      * used internally to expire a wakelock when transitioning
    361      * from one net to another.  Expire happens when we fail to find
    362      * a new network (typically after 1 minute) -
    363      * EVENT_CLEAR_NET_TRANSITION_WAKELOCK happens if we had found
    364      * a replacement network.
    365      */
    366     private static final int EVENT_EXPIRE_NET_TRANSITION_WAKELOCK = 24;
    367 
    368     /**
    369      * Used internally to indicate the system is ready.
    370      */
    371     private static final int EVENT_SYSTEM_READY = 25;
    372 
    373     /**
    374      * used to add a network request with a pending intent
    375      * obj = NetworkRequestInfo
    376      */
    377     private static final int EVENT_REGISTER_NETWORK_REQUEST_WITH_INTENT = 26;
    378 
    379     /**
    380      * used to remove a pending intent and its associated network request.
    381      * arg1 = UID of caller
    382      * obj  = PendingIntent
    383      */
    384     private static final int EVENT_RELEASE_NETWORK_REQUEST_WITH_INTENT = 27;
    385 
    386     /**
    387      * used to specify whether a network should be used even if unvalidated.
    388      * arg1 = whether to accept the network if it's unvalidated (1 or 0)
    389      * arg2 = whether to remember this choice in the future (1 or 0)
    390      * obj  = network
    391      */
    392     private static final int EVENT_SET_ACCEPT_UNVALIDATED = 28;
    393 
    394     /**
    395      * used to ask the user to confirm a connection to an unvalidated network.
    396      * obj  = network
    397      */
    398     private static final int EVENT_PROMPT_UNVALIDATED = 29;
    399 
    400     /**
    401      * used internally to (re)configure mobile data always-on settings.
    402      */
    403     private static final int EVENT_CONFIGURE_MOBILE_DATA_ALWAYS_ON = 30;
    404 
    405     /**
    406      * used to add a network listener with a pending intent
    407      * obj = NetworkRequestInfo
    408      */
    409     private static final int EVENT_REGISTER_NETWORK_LISTENER_WITH_INTENT = 31;
    410 
    411     /**
    412      * used to specify whether a network should not be penalized when it becomes unvalidated.
    413      */
    414     private static final int EVENT_SET_AVOID_UNVALIDATED = 35;
    415 
    416     /**
    417      * used to trigger revalidation of a network.
    418      */
    419     private static final int EVENT_REVALIDATE_NETWORK = 36;
    420 
    421     // Handle changes in Private DNS settings.
    422     private static final int EVENT_PRIVATE_DNS_SETTINGS_CHANGED = 37;
    423 
    424     // Handle private DNS validation status updates.
    425     private static final int EVENT_PRIVATE_DNS_VALIDATION_UPDATE = 38;
    426 
    427     private static String eventName(int what) {
    428         return sMagicDecoderRing.get(what, Integer.toString(what));
    429     }
    430 
    431     /** Handler thread used for both of the handlers below. */
    432     @VisibleForTesting
    433     protected final HandlerThread mHandlerThread;
    434     /** Handler used for internal events. */
    435     final private InternalHandler mHandler;
    436     /** Handler used for incoming {@link NetworkStateTracker} events. */
    437     final private NetworkStateTrackerHandler mTrackerHandler;
    438     private final DnsManager mDnsManager;
    439 
    440     private boolean mSystemReady;
    441     private Intent mInitialBroadcast;
    442 
    443     private PowerManager.WakeLock mNetTransitionWakeLock;
    444     private int mNetTransitionWakeLockTimeout;
    445     private final PowerManager.WakeLock mPendingIntentWakeLock;
    446 
    447     // track the current default http proxy - tell the world if we get a new one (real change)
    448     private volatile ProxyInfo mDefaultProxy = null;
    449     private Object mProxyLock = new Object();
    450     private boolean mDefaultProxyDisabled = false;
    451 
    452     // track the global proxy.
    453     private ProxyInfo mGlobalProxy = null;
    454 
    455     private PacManager mPacManager = null;
    456 
    457     final private SettingsObserver mSettingsObserver;
    458 
    459     private UserManager mUserManager;
    460 
    461     NetworkConfig[] mNetConfigs;
    462     int mNetworksDefined;
    463 
    464     // the set of network types that can only be enabled by system/sig apps
    465     List mProtectedNetworks;
    466 
    467     private DataConnectionStats mDataConnectionStats;
    468 
    469     TelephonyManager mTelephonyManager;
    470 
    471     private KeepaliveTracker mKeepaliveTracker;
    472     private NetworkNotificationManager mNotifier;
    473     private LingerMonitor mLingerMonitor;
    474 
    475     // sequence number for Networks; keep in sync with system/netd/NetworkController.cpp
    476     private static final int MIN_NET_ID = 100; // some reserved marks
    477     private static final int MAX_NET_ID = 65535 - 0x0400; // Top 1024 bits reserved by IpSecService
    478     private int mNextNetId = MIN_NET_ID;
    479 
    480     // sequence number of NetworkRequests
    481     private int mNextNetworkRequestId = 1;
    482 
    483     // NetworkRequest activity String log entries.
    484     private static final int MAX_NETWORK_REQUEST_LOGS = 20;
    485     private final LocalLog mNetworkRequestInfoLogs = new LocalLog(MAX_NETWORK_REQUEST_LOGS);
    486 
    487     // NetworkInfo blocked and unblocked String log entries
    488     private static final int MAX_NETWORK_INFO_LOGS = 40;
    489     private final LocalLog mNetworkInfoBlockingLogs = new LocalLog(MAX_NETWORK_INFO_LOGS);
    490 
    491     private static final int MAX_WAKELOCK_LOGS = 20;
    492     private final LocalLog mWakelockLogs = new LocalLog(MAX_WAKELOCK_LOGS);
    493     private int mTotalWakelockAcquisitions = 0;
    494     private int mTotalWakelockReleases = 0;
    495     private long mTotalWakelockDurationMs = 0;
    496     private long mMaxWakelockDurationMs = 0;
    497     private long mLastWakeLockAcquireTimestamp = 0;
    498 
    499     // Array of <Network,ReadOnlyLocalLogs> tracking network validation and results
    500     private static final int MAX_VALIDATION_LOGS = 10;
    501     private static class ValidationLog {
    502         final Network mNetwork;
    503         final String mName;
    504         final ReadOnlyLocalLog mLog;
    505 
    506         ValidationLog(Network network, String name, ReadOnlyLocalLog log) {
    507             mNetwork = network;
    508             mName = name;
    509             mLog = log;
    510         }
    511     }
    512     private final ArrayDeque<ValidationLog> mValidationLogs =
    513             new ArrayDeque<ValidationLog>(MAX_VALIDATION_LOGS);
    514 
    515     private void addValidationLogs(ReadOnlyLocalLog log, Network network, String name) {
    516         synchronized (mValidationLogs) {
    517             while (mValidationLogs.size() >= MAX_VALIDATION_LOGS) {
    518                 mValidationLogs.removeLast();
    519             }
    520             mValidationLogs.addFirst(new ValidationLog(network, name, log));
    521         }
    522     }
    523 
    524     private final IpConnectivityLog mMetricsLog;
    525 
    526     @VisibleForTesting
    527     final MultinetworkPolicyTracker mMultinetworkPolicyTracker;
    528 
    529     @VisibleForTesting
    530     final MultipathPolicyTracker mMultipathPolicyTracker;
    531 
    532     /**
    533      * Implements support for the legacy "one network per network type" model.
    534      *
    535      * We used to have a static array of NetworkStateTrackers, one for each
    536      * network type, but that doesn't work any more now that we can have,
    537      * for example, more that one wifi network. This class stores all the
    538      * NetworkAgentInfo objects that support a given type, but the legacy
    539      * API will only see the first one.
    540      *
    541      * It serves two main purposes:
    542      *
    543      * 1. Provide information about "the network for a given type" (since this
    544      *    API only supports one).
    545      * 2. Send legacy connectivity change broadcasts. Broadcasts are sent if
    546      *    the first network for a given type changes, or if the default network
    547      *    changes.
    548      */
    549     private class LegacyTypeTracker {
    550 
    551         private static final boolean DBG = true;
    552         private static final boolean VDBG = false;
    553 
    554         /**
    555          * Array of lists, one per legacy network type (e.g., TYPE_MOBILE_MMS).
    556          * Each list holds references to all NetworkAgentInfos that are used to
    557          * satisfy requests for that network type.
    558          *
    559          * This array is built out at startup such that an unsupported network
    560          * doesn't get an ArrayList instance, making this a tristate:
    561          * unsupported, supported but not active and active.
    562          *
    563          * The actual lists are populated when we scan the network types that
    564          * are supported on this device.
    565          *
    566          * Threading model:
    567          *  - addSupportedType() is only called in the constructor
    568          *  - add(), update(), remove() are only called from the ConnectivityService handler thread.
    569          *    They are therefore not thread-safe with respect to each other.
    570          *  - getNetworkForType() can be called at any time on binder threads. It is synchronized
    571          *    on mTypeLists to be thread-safe with respect to a concurrent remove call.
    572          *  - dump is thread-safe with respect to concurrent add and remove calls.
    573          */
    574         private final ArrayList<NetworkAgentInfo> mTypeLists[];
    575 
    576         public LegacyTypeTracker() {
    577             mTypeLists = (ArrayList<NetworkAgentInfo>[])
    578                     new ArrayList[ConnectivityManager.MAX_NETWORK_TYPE + 1];
    579         }
    580 
    581         public void addSupportedType(int type) {
    582             if (mTypeLists[type] != null) {
    583                 throw new IllegalStateException(
    584                         "legacy list for type " + type + "already initialized");
    585             }
    586             mTypeLists[type] = new ArrayList<NetworkAgentInfo>();
    587         }
    588 
    589         public boolean isTypeSupported(int type) {
    590             return isNetworkTypeValid(type) && mTypeLists[type] != null;
    591         }
    592 
    593         public NetworkAgentInfo getNetworkForType(int type) {
    594             synchronized (mTypeLists) {
    595                 if (isTypeSupported(type) && !mTypeLists[type].isEmpty()) {
    596                     return mTypeLists[type].get(0);
    597                 }
    598             }
    599             return null;
    600         }
    601 
    602         private void maybeLogBroadcast(NetworkAgentInfo nai, DetailedState state, int type,
    603                 boolean isDefaultNetwork) {
    604             if (DBG) {
    605                 log("Sending " + state +
    606                         " broadcast for type " + type + " " + nai.name() +
    607                         " isDefaultNetwork=" + isDefaultNetwork);
    608             }
    609         }
    610 
    611         /** Adds the given network to the specified legacy type list. */
    612         public void add(int type, NetworkAgentInfo nai) {
    613             if (!isTypeSupported(type)) {
    614                 return;  // Invalid network type.
    615             }
    616             if (VDBG) log("Adding agent " + nai + " for legacy network type " + type);
    617 
    618             ArrayList<NetworkAgentInfo> list = mTypeLists[type];
    619             if (list.contains(nai)) {
    620                 return;
    621             }
    622             synchronized (mTypeLists) {
    623                 list.add(nai);
    624             }
    625 
    626             // Send a broadcast if this is the first network of its type or if it's the default.
    627             final boolean isDefaultNetwork = isDefaultNetwork(nai);
    628             if ((list.size() == 1) || isDefaultNetwork) {
    629                 maybeLogBroadcast(nai, DetailedState.CONNECTED, type, isDefaultNetwork);
    630                 sendLegacyNetworkBroadcast(nai, DetailedState.CONNECTED, type);
    631             }
    632         }
    633 
    634         /** Removes the given network from the specified legacy type list. */
    635         public void remove(int type, NetworkAgentInfo nai, boolean wasDefault) {
    636             ArrayList<NetworkAgentInfo> list = mTypeLists[type];
    637             if (list == null || list.isEmpty()) {
    638                 return;
    639             }
    640             final boolean wasFirstNetwork = list.get(0).equals(nai);
    641 
    642             synchronized (mTypeLists) {
    643                 if (!list.remove(nai)) {
    644                     return;
    645                 }
    646             }
    647 
    648             final DetailedState state = DetailedState.DISCONNECTED;
    649 
    650             if (wasFirstNetwork || wasDefault) {
    651                 maybeLogBroadcast(nai, state, type, wasDefault);
    652                 sendLegacyNetworkBroadcast(nai, state, type);
    653             }
    654 
    655             if (!list.isEmpty() && wasFirstNetwork) {
    656                 if (DBG) log("Other network available for type " + type +
    657                               ", sending connected broadcast");
    658                 final NetworkAgentInfo replacement = list.get(0);
    659                 maybeLogBroadcast(replacement, state, type, isDefaultNetwork(replacement));
    660                 sendLegacyNetworkBroadcast(replacement, state, type);
    661             }
    662         }
    663 
    664         /** Removes the given network from all legacy type lists. */
    665         public void remove(NetworkAgentInfo nai, boolean wasDefault) {
    666             if (VDBG) log("Removing agent " + nai + " wasDefault=" + wasDefault);
    667             for (int type = 0; type < mTypeLists.length; type++) {
    668                 remove(type, nai, wasDefault);
    669             }
    670         }
    671 
    672         // send out another legacy broadcast - currently only used for suspend/unsuspend
    673         // toggle
    674         public void update(NetworkAgentInfo nai) {
    675             final boolean isDefault = isDefaultNetwork(nai);
    676             final DetailedState state = nai.networkInfo.getDetailedState();
    677             for (int type = 0; type < mTypeLists.length; type++) {
    678                 final ArrayList<NetworkAgentInfo> list = mTypeLists[type];
    679                 final boolean contains = (list != null && list.contains(nai));
    680                 final boolean isFirst = contains && (nai == list.get(0));
    681                 if (isFirst || contains && isDefault) {
    682                     maybeLogBroadcast(nai, state, type, isDefault);
    683                     sendLegacyNetworkBroadcast(nai, state, type);
    684                 }
    685             }
    686         }
    687 
    688         private String naiToString(NetworkAgentInfo nai) {
    689             String name = (nai != null) ? nai.name() : "null";
    690             String state = (nai.networkInfo != null) ?
    691                     nai.networkInfo.getState() + "/" + nai.networkInfo.getDetailedState() :
    692                     "???/???";
    693             return name + " " + state;
    694         }
    695 
    696         public void dump(IndentingPrintWriter pw) {
    697             pw.println("mLegacyTypeTracker:");
    698             pw.increaseIndent();
    699             pw.print("Supported types:");
    700             for (int type = 0; type < mTypeLists.length; type++) {
    701                 if (mTypeLists[type] != null) pw.print(" " + type);
    702             }
    703             pw.println();
    704             pw.println("Current state:");
    705             pw.increaseIndent();
    706             synchronized (mTypeLists) {
    707                 for (int type = 0; type < mTypeLists.length; type++) {
    708                     if (mTypeLists[type] == null || mTypeLists[type].isEmpty()) continue;
    709                     for (NetworkAgentInfo nai : mTypeLists[type]) {
    710                         pw.println(type + " " + naiToString(nai));
    711                     }
    712                 }
    713             }
    714             pw.decreaseIndent();
    715             pw.decreaseIndent();
    716             pw.println();
    717         }
    718     }
    719     private LegacyTypeTracker mLegacyTypeTracker = new LegacyTypeTracker();
    720 
    721     /**
    722      * Helper class which parses out priority arguments and dumps sections according to their
    723      * priority. If priority arguments are omitted, function calls the legacy dump command.
    724      */
    725     private final PriorityDump.PriorityDumper mPriorityDumper = new PriorityDump.PriorityDumper() {
    726         @Override
    727         public void dumpHigh(FileDescriptor fd, PrintWriter pw, String[] args, boolean asProto) {
    728             doDump(fd, pw, new String[] {DIAG_ARG}, asProto);
    729             doDump(fd, pw, new String[] {SHORT_ARG}, asProto);
    730         }
    731 
    732         @Override
    733         public void dumpNormal(FileDescriptor fd, PrintWriter pw, String[] args, boolean asProto) {
    734             doDump(fd, pw, args, asProto);
    735         }
    736 
    737         @Override
    738         public void dump(FileDescriptor fd, PrintWriter pw, String[] args, boolean asProto) {
    739            doDump(fd, pw, args, asProto);
    740         }
    741     };
    742 
    743     public ConnectivityService(Context context, INetworkManagementService netManager,
    744             INetworkStatsService statsService, INetworkPolicyManager policyManager) {
    745         this(context, netManager, statsService, policyManager, new IpConnectivityLog());
    746     }
    747 
    748     @VisibleForTesting
    749     protected ConnectivityService(Context context, INetworkManagementService netManager,
    750             INetworkStatsService statsService, INetworkPolicyManager policyManager,
    751             IpConnectivityLog logger) {
    752         if (DBG) log("ConnectivityService starting up");
    753 
    754         mSystemProperties = getSystemProperties();
    755 
    756         mMetricsLog = logger;
    757         mDefaultRequest = createDefaultInternetRequestForTransport(-1, NetworkRequest.Type.REQUEST);
    758         NetworkRequestInfo defaultNRI = new NetworkRequestInfo(null, mDefaultRequest, new Binder());
    759         mNetworkRequests.put(mDefaultRequest, defaultNRI);
    760         mNetworkRequestInfoLogs.log("REGISTER " + defaultNRI);
    761 
    762         mDefaultMobileDataRequest = createDefaultInternetRequestForTransport(
    763                 NetworkCapabilities.TRANSPORT_CELLULAR, NetworkRequest.Type.BACKGROUND_REQUEST);
    764 
    765         mHandlerThread = new HandlerThread("ConnectivityServiceThread");
    766         mHandlerThread.start();
    767         mHandler = new InternalHandler(mHandlerThread.getLooper());
    768         mTrackerHandler = new NetworkStateTrackerHandler(mHandlerThread.getLooper());
    769 
    770         mReleasePendingIntentDelayMs = Settings.Secure.getInt(context.getContentResolver(),
    771                 Settings.Secure.CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS, 5_000);
    772 
    773         mLingerDelayMs = mSystemProperties.getInt(LINGER_DELAY_PROPERTY, DEFAULT_LINGER_DELAY_MS);
    774 
    775         mContext = checkNotNull(context, "missing Context");
    776         mNetd = checkNotNull(netManager, "missing INetworkManagementService");
    777         mStatsService = checkNotNull(statsService, "missing INetworkStatsService");
    778         mPolicyManager = checkNotNull(policyManager, "missing INetworkPolicyManager");
    779         mPolicyManagerInternal = checkNotNull(
    780                 LocalServices.getService(NetworkPolicyManagerInternal.class),
    781                 "missing NetworkPolicyManagerInternal");
    782 
    783         mKeyStore = KeyStore.getInstance();
    784         mTelephonyManager = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
    785 
    786         try {
    787             mPolicyManager.registerListener(mPolicyListener);
    788         } catch (RemoteException e) {
    789             // ouch, no rules updates means some processes may never get network
    790             loge("unable to register INetworkPolicyListener" + e);
    791         }
    792 
    793         final PowerManager powerManager = (PowerManager) context.getSystemService(
    794                 Context.POWER_SERVICE);
    795         mNetTransitionWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
    796         mNetTransitionWakeLockTimeout = mContext.getResources().getInteger(
    797                 com.android.internal.R.integer.config_networkTransitionTimeout);
    798         mPendingIntentWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
    799 
    800         mNetConfigs = new NetworkConfig[ConnectivityManager.MAX_NETWORK_TYPE+1];
    801 
    802         // TODO: What is the "correct" way to do determine if this is a wifi only device?
    803         boolean wifiOnly = mSystemProperties.getBoolean("ro.radio.noril", false);
    804         log("wifiOnly=" + wifiOnly);
    805         String[] naStrings = context.getResources().getStringArray(
    806                 com.android.internal.R.array.networkAttributes);
    807         for (String naString : naStrings) {
    808             try {
    809                 NetworkConfig n = new NetworkConfig(naString);
    810                 if (VDBG) log("naString=" + naString + " config=" + n);
    811                 if (n.type > ConnectivityManager.MAX_NETWORK_TYPE) {
    812                     loge("Error in networkAttributes - ignoring attempt to define type " +
    813                             n.type);
    814                     continue;
    815                 }
    816                 if (wifiOnly && ConnectivityManager.isNetworkTypeMobile(n.type)) {
    817                     log("networkAttributes - ignoring mobile as this dev is wifiOnly " +
    818                             n.type);
    819                     continue;
    820                 }
    821                 if (mNetConfigs[n.type] != null) {
    822                     loge("Error in networkAttributes - ignoring attempt to redefine type " +
    823                             n.type);
    824                     continue;
    825                 }
    826                 mLegacyTypeTracker.addSupportedType(n.type);
    827 
    828                 mNetConfigs[n.type] = n;
    829                 mNetworksDefined++;
    830             } catch(Exception e) {
    831                 // ignore it - leave the entry null
    832             }
    833         }
    834 
    835         // Forcibly add TYPE_VPN as a supported type, if it has not already been added via config.
    836         if (mNetConfigs[TYPE_VPN] == null) {
    837             // mNetConfigs is used only for "restore time", which isn't applicable to VPNs, so we
    838             // don't need to add TYPE_VPN to mNetConfigs.
    839             mLegacyTypeTracker.addSupportedType(TYPE_VPN);
    840             mNetworksDefined++;  // used only in the log() statement below.
    841         }
    842 
    843         // Do the same for Ethernet, since it's often not specified in the configs, although many
    844         // devices can use it via USB host adapters.
    845         if (mNetConfigs[TYPE_ETHERNET] == null && hasService(Context.ETHERNET_SERVICE)) {
    846             mLegacyTypeTracker.addSupportedType(TYPE_ETHERNET);
    847             mNetworksDefined++;
    848         }
    849 
    850         if (VDBG) log("mNetworksDefined=" + mNetworksDefined);
    851 
    852         mProtectedNetworks = new ArrayList<Integer>();
    853         int[] protectedNetworks = context.getResources().getIntArray(
    854                 com.android.internal.R.array.config_protectedNetworks);
    855         for (int p : protectedNetworks) {
    856             if ((mNetConfigs[p] != null) && (mProtectedNetworks.contains(p) == false)) {
    857                 mProtectedNetworks.add(p);
    858             } else {
    859                 if (DBG) loge("Ignoring protectedNetwork " + p);
    860             }
    861         }
    862 
    863         mTestMode = mSystemProperties.get("cm.test.mode").equals("true")
    864                 && mSystemProperties.get("ro.build.type").equals("eng");
    865 
    866         mTethering = makeTethering();
    867 
    868         mPermissionMonitor = new PermissionMonitor(mContext, mNetd);
    869 
    870         //set up the listener for user state for creating user VPNs
    871         IntentFilter intentFilter = new IntentFilter();
    872         intentFilter.addAction(Intent.ACTION_USER_STARTED);
    873         intentFilter.addAction(Intent.ACTION_USER_STOPPED);
    874         intentFilter.addAction(Intent.ACTION_USER_ADDED);
    875         intentFilter.addAction(Intent.ACTION_USER_REMOVED);
    876         intentFilter.addAction(Intent.ACTION_USER_UNLOCKED);
    877         mContext.registerReceiverAsUser(
    878                 mUserIntentReceiver, UserHandle.ALL, intentFilter, null, null);
    879         mContext.registerReceiverAsUser(mUserPresentReceiver, UserHandle.SYSTEM,
    880                 new IntentFilter(Intent.ACTION_USER_PRESENT), null, null);
    881 
    882         try {
    883             mNetd.registerObserver(mTethering);
    884             mNetd.registerObserver(mDataActivityObserver);
    885         } catch (RemoteException e) {
    886             loge("Error registering observer :" + e);
    887         }
    888 
    889         mSettingsObserver = new SettingsObserver(mContext, mHandler);
    890         registerSettingsCallbacks();
    891 
    892         mDataConnectionStats = new DataConnectionStats(mContext);
    893         mDataConnectionStats.startMonitoring();
    894 
    895         mPacManager = new PacManager(mContext, mHandler, EVENT_PROXY_HAS_CHANGED);
    896 
    897         mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
    898 
    899         mKeepaliveTracker = new KeepaliveTracker(mHandler);
    900         mNotifier = new NetworkNotificationManager(mContext, mTelephonyManager,
    901                 mContext.getSystemService(NotificationManager.class));
    902 
    903         final int dailyLimit = Settings.Global.getInt(mContext.getContentResolver(),
    904                 Settings.Global.NETWORK_SWITCH_NOTIFICATION_DAILY_LIMIT,
    905                 LingerMonitor.DEFAULT_NOTIFICATION_DAILY_LIMIT);
    906         final long rateLimit = Settings.Global.getLong(mContext.getContentResolver(),
    907                 Settings.Global.NETWORK_SWITCH_NOTIFICATION_RATE_LIMIT_MILLIS,
    908                 LingerMonitor.DEFAULT_NOTIFICATION_RATE_LIMIT_MILLIS);
    909         mLingerMonitor = new LingerMonitor(mContext, mNotifier, dailyLimit, rateLimit);
    910 
    911         mMultinetworkPolicyTracker = createMultinetworkPolicyTracker(
    912                 mContext, mHandler, () -> rematchForAvoidBadWifiUpdate());
    913         mMultinetworkPolicyTracker.start();
    914 
    915         mMultipathPolicyTracker = new MultipathPolicyTracker(mContext, mHandler);
    916 
    917         mDnsManager = new DnsManager(mContext, mNetd, mSystemProperties);
    918         registerPrivateDnsSettingsCallbacks();
    919     }
    920 
    921     private Tethering makeTethering() {
    922         // TODO: Move other elements into @Overridden getters.
    923         final TetheringDependencies deps = new TetheringDependencies() {
    924             @Override
    925             public boolean isTetheringSupported() {
    926                 return ConnectivityService.this.isTetheringSupported();
    927             }
    928         };
    929         return new Tethering(mContext, mNetd, mStatsService, mPolicyManager,
    930                 IoThread.get().getLooper(), new MockableSystemProperties(),
    931                 deps);
    932     }
    933 
    934     private static NetworkCapabilities createDefaultNetworkCapabilitiesForUid(int uid) {
    935         final NetworkCapabilities netCap = new NetworkCapabilities();
    936         netCap.addCapability(NET_CAPABILITY_INTERNET);
    937         netCap.addCapability(NET_CAPABILITY_NOT_RESTRICTED);
    938         netCap.removeCapability(NET_CAPABILITY_NOT_VPN);
    939         netCap.setSingleUid(uid);
    940         return netCap;
    941     }
    942 
    943     private NetworkRequest createDefaultInternetRequestForTransport(
    944             int transportType, NetworkRequest.Type type) {
    945         NetworkCapabilities netCap = new NetworkCapabilities();
    946         netCap.addCapability(NET_CAPABILITY_INTERNET);
    947         netCap.addCapability(NET_CAPABILITY_NOT_RESTRICTED);
    948         if (transportType > -1) {
    949             netCap.addTransportType(transportType);
    950         }
    951         return new NetworkRequest(netCap, TYPE_NONE, nextNetworkRequestId(), type);
    952     }
    953 
    954     // Used only for testing.
    955     // TODO: Delete this and either:
    956     // 1. Give FakeSettingsProvider the ability to send settings change notifications (requires
    957     //    changing ContentResolver to make registerContentObserver non-final).
    958     // 2. Give FakeSettingsProvider an alternative notification mechanism and have the test use it
    959     //    by subclassing SettingsObserver.
    960     @VisibleForTesting
    961     void updateMobileDataAlwaysOn() {
    962         mHandler.sendEmptyMessage(EVENT_CONFIGURE_MOBILE_DATA_ALWAYS_ON);
    963     }
    964 
    965     // See FakeSettingsProvider comment above.
    966     @VisibleForTesting
    967     void updatePrivateDnsSettings() {
    968         mHandler.sendEmptyMessage(EVENT_PRIVATE_DNS_SETTINGS_CHANGED);
    969     }
    970 
    971     private void handleMobileDataAlwaysOn() {
    972         final boolean enable = toBool(Settings.Global.getInt(
    973                 mContext.getContentResolver(), Settings.Global.MOBILE_DATA_ALWAYS_ON, 1));
    974         final boolean isEnabled = (mNetworkRequests.get(mDefaultMobileDataRequest) != null);
    975         if (enable == isEnabled) {
    976             return;  // Nothing to do.
    977         }
    978 
    979         if (enable) {
    980             handleRegisterNetworkRequest(new NetworkRequestInfo(
    981                     null, mDefaultMobileDataRequest, new Binder()));
    982         } else {
    983             handleReleaseNetworkRequest(mDefaultMobileDataRequest, Process.SYSTEM_UID);
    984         }
    985     }
    986 
    987     private void registerSettingsCallbacks() {
    988         // Watch for global HTTP proxy changes.
    989         mSettingsObserver.observe(
    990                 Settings.Global.getUriFor(Settings.Global.HTTP_PROXY),
    991                 EVENT_APPLY_GLOBAL_HTTP_PROXY);
    992 
    993         // Watch for whether or not to keep mobile data always on.
    994         mSettingsObserver.observe(
    995                 Settings.Global.getUriFor(Settings.Global.MOBILE_DATA_ALWAYS_ON),
    996                 EVENT_CONFIGURE_MOBILE_DATA_ALWAYS_ON);
    997     }
    998 
    999     private void registerPrivateDnsSettingsCallbacks() {
   1000         for (Uri uri : DnsManager.getPrivateDnsSettingsUris()) {
   1001             mSettingsObserver.observe(uri, EVENT_PRIVATE_DNS_SETTINGS_CHANGED);
   1002         }
   1003     }
   1004 
   1005     private synchronized int nextNetworkRequestId() {
   1006         return mNextNetworkRequestId++;
   1007     }
   1008 
   1009     @VisibleForTesting
   1010     protected int reserveNetId() {
   1011         synchronized (mNetworkForNetId) {
   1012             for (int i = MIN_NET_ID; i <= MAX_NET_ID; i++) {
   1013                 int netId = mNextNetId;
   1014                 if (++mNextNetId > MAX_NET_ID) mNextNetId = MIN_NET_ID;
   1015                 // Make sure NetID unused.  http://b/16815182
   1016                 if (!mNetIdInUse.get(netId)) {
   1017                     mNetIdInUse.put(netId, true);
   1018                     return netId;
   1019                 }
   1020             }
   1021         }
   1022         throw new IllegalStateException("No free netIds");
   1023     }
   1024 
   1025     private NetworkState getFilteredNetworkState(int networkType, int uid, boolean ignoreBlocked) {
   1026         if (mLegacyTypeTracker.isTypeSupported(networkType)) {
   1027             final NetworkAgentInfo nai = mLegacyTypeTracker.getNetworkForType(networkType);
   1028             final NetworkState state;
   1029             if (nai != null) {
   1030                 state = nai.getNetworkState();
   1031                 state.networkInfo.setType(networkType);
   1032             } else {
   1033                 final NetworkInfo info = new NetworkInfo(networkType, 0,
   1034                         getNetworkTypeName(networkType), "");
   1035                 info.setDetailedState(NetworkInfo.DetailedState.DISCONNECTED, null, null);
   1036                 info.setIsAvailable(true);
   1037                 final NetworkCapabilities capabilities = new NetworkCapabilities();
   1038                 capabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING,
   1039                         !info.isRoaming());
   1040                 state = new NetworkState(info, new LinkProperties(), capabilities,
   1041                         null, null, null);
   1042             }
   1043             filterNetworkStateForUid(state, uid, ignoreBlocked);
   1044             return state;
   1045         } else {
   1046             return NetworkState.EMPTY;
   1047         }
   1048     }
   1049 
   1050     private NetworkAgentInfo getNetworkAgentInfoForNetwork(Network network) {
   1051         if (network == null) {
   1052             return null;
   1053         }
   1054         return getNetworkAgentInfoForNetId(network.netId);
   1055     }
   1056 
   1057     private NetworkAgentInfo getNetworkAgentInfoForNetId(int netId) {
   1058         synchronized (mNetworkForNetId) {
   1059             return mNetworkForNetId.get(netId);
   1060         }
   1061     }
   1062 
   1063     private Network[] getVpnUnderlyingNetworks(int uid) {
   1064         synchronized (mVpns) {
   1065             if (!mLockdownEnabled) {
   1066                 int user = UserHandle.getUserId(uid);
   1067                 Vpn vpn = mVpns.get(user);
   1068                 if (vpn != null && vpn.appliesToUid(uid)) {
   1069                     return vpn.getUnderlyingNetworks();
   1070                 }
   1071             }
   1072         }
   1073         return null;
   1074     }
   1075 
   1076     private NetworkState getUnfilteredActiveNetworkState(int uid) {
   1077         NetworkAgentInfo nai = getDefaultNetwork();
   1078 
   1079         final Network[] networks = getVpnUnderlyingNetworks(uid);
   1080         if (networks != null) {
   1081             // getUnderlyingNetworks() returns:
   1082             // null => there was no VPN, or the VPN didn't specify anything, so we use the default.
   1083             // empty array => the VPN explicitly said "no default network".
   1084             // non-empty array => the VPN specified one or more default networks; we use the
   1085             //                    first one.
   1086             if (networks.length > 0) {
   1087                 nai = getNetworkAgentInfoForNetwork(networks[0]);
   1088             } else {
   1089                 nai = null;
   1090             }
   1091         }
   1092 
   1093         if (nai != null) {
   1094             return nai.getNetworkState();
   1095         } else {
   1096             return NetworkState.EMPTY;
   1097         }
   1098     }
   1099 
   1100     /**
   1101      * Check if UID should be blocked from using the network with the given LinkProperties.
   1102      */
   1103     private boolean isNetworkWithLinkPropertiesBlocked(LinkProperties lp, int uid,
   1104             boolean ignoreBlocked) {
   1105         // Networks aren't blocked when ignoring blocked status
   1106         if (ignoreBlocked) {
   1107             return false;
   1108         }
   1109         // Networks are never blocked for system services
   1110         // TODO: consider moving this check to NetworkPolicyManagerInternal.isUidNetworkingBlocked.
   1111         if (isSystem(uid)) {
   1112             return false;
   1113         }
   1114         synchronized (mVpns) {
   1115             final Vpn vpn = mVpns.get(UserHandle.getUserId(uid));
   1116             if (vpn != null && vpn.isBlockingUid(uid)) {
   1117                 return true;
   1118             }
   1119         }
   1120         final String iface = (lp == null ? "" : lp.getInterfaceName());
   1121         return mPolicyManagerInternal.isUidNetworkingBlocked(uid, iface);
   1122     }
   1123 
   1124     private void maybeLogBlockedNetworkInfo(NetworkInfo ni, int uid) {
   1125         if (ni == null || !LOGD_BLOCKED_NETWORKINFO) {
   1126             return;
   1127         }
   1128         final boolean blocked;
   1129         synchronized (mBlockedAppUids) {
   1130             if (ni.getDetailedState() == DetailedState.BLOCKED && mBlockedAppUids.add(uid)) {
   1131                 blocked = true;
   1132             } else if (ni.isConnected() && mBlockedAppUids.remove(uid)) {
   1133                 blocked = false;
   1134             } else {
   1135                 return;
   1136             }
   1137         }
   1138         String action = blocked ? "BLOCKED" : "UNBLOCKED";
   1139         log(String.format("Returning %s NetworkInfo to uid=%d", action, uid));
   1140         mNetworkInfoBlockingLogs.log(action + " " + uid);
   1141     }
   1142 
   1143     /**
   1144      * Apply any relevant filters to {@link NetworkState} for the given UID. For
   1145      * example, this may mark the network as {@link DetailedState#BLOCKED} based
   1146      * on {@link #isNetworkWithLinkPropertiesBlocked}.
   1147      */
   1148     private void filterNetworkStateForUid(NetworkState state, int uid, boolean ignoreBlocked) {
   1149         if (state == null || state.networkInfo == null || state.linkProperties == null) return;
   1150 
   1151         if (isNetworkWithLinkPropertiesBlocked(state.linkProperties, uid, ignoreBlocked)) {
   1152             state.networkInfo.setDetailedState(DetailedState.BLOCKED, null, null);
   1153         }
   1154         synchronized (mVpns) {
   1155             if (mLockdownTracker != null) {
   1156                 mLockdownTracker.augmentNetworkInfo(state.networkInfo);
   1157             }
   1158         }
   1159     }
   1160 
   1161     /**
   1162      * Return NetworkInfo for the active (i.e., connected) network interface.
   1163      * It is assumed that at most one network is active at a time. If more
   1164      * than one is active, it is indeterminate which will be returned.
   1165      * @return the info for the active network, or {@code null} if none is
   1166      * active
   1167      */
   1168     @Override
   1169     public NetworkInfo getActiveNetworkInfo() {
   1170         enforceAccessPermission();
   1171         final int uid = Binder.getCallingUid();
   1172         final NetworkState state = getUnfilteredActiveNetworkState(uid);
   1173         filterNetworkStateForUid(state, uid, false);
   1174         maybeLogBlockedNetworkInfo(state.networkInfo, uid);
   1175         return state.networkInfo;
   1176     }
   1177 
   1178     @Override
   1179     public Network getActiveNetwork() {
   1180         enforceAccessPermission();
   1181         return getActiveNetworkForUidInternal(Binder.getCallingUid(), false);
   1182     }
   1183 
   1184     @Override
   1185     public Network getActiveNetworkForUid(int uid, boolean ignoreBlocked) {
   1186         enforceConnectivityInternalPermission();
   1187         return getActiveNetworkForUidInternal(uid, ignoreBlocked);
   1188     }
   1189 
   1190     private Network getActiveNetworkForUidInternal(final int uid, boolean ignoreBlocked) {
   1191         final int user = UserHandle.getUserId(uid);
   1192         int vpnNetId = NETID_UNSET;
   1193         synchronized (mVpns) {
   1194             final Vpn vpn = mVpns.get(user);
   1195             // TODO : now that capabilities contain the UID, the appliesToUid test should
   1196             // be removed as the satisfying test below should be enough.
   1197             if (vpn != null && vpn.appliesToUid(uid)) vpnNetId = vpn.getNetId();
   1198         }
   1199         NetworkAgentInfo nai;
   1200         if (vpnNetId != NETID_UNSET) {
   1201             nai = getNetworkAgentInfoForNetId(vpnNetId);
   1202             if (nai != null) {
   1203                 final NetworkCapabilities requiredCaps =
   1204                     createDefaultNetworkCapabilitiesForUid(uid);
   1205                 if (requiredCaps.satisfiedByNetworkCapabilities(nai.networkCapabilities)) {
   1206                     return nai.network;
   1207                 }
   1208             }
   1209         }
   1210         nai = getDefaultNetwork();
   1211         if (nai != null
   1212                 && isNetworkWithLinkPropertiesBlocked(nai.linkProperties, uid, ignoreBlocked)) {
   1213             nai = null;
   1214         }
   1215         return nai != null ? nai.network : null;
   1216     }
   1217 
   1218     // Public because it's used by mLockdownTracker.
   1219     public NetworkInfo getActiveNetworkInfoUnfiltered() {
   1220         enforceAccessPermission();
   1221         final int uid = Binder.getCallingUid();
   1222         NetworkState state = getUnfilteredActiveNetworkState(uid);
   1223         return state.networkInfo;
   1224     }
   1225 
   1226     @Override
   1227     public NetworkInfo getActiveNetworkInfoForUid(int uid, boolean ignoreBlocked) {
   1228         enforceConnectivityInternalPermission();
   1229         final NetworkState state = getUnfilteredActiveNetworkState(uid);
   1230         filterNetworkStateForUid(state, uid, ignoreBlocked);
   1231         return state.networkInfo;
   1232     }
   1233 
   1234     @Override
   1235     public NetworkInfo getNetworkInfo(int networkType) {
   1236         enforceAccessPermission();
   1237         final int uid = Binder.getCallingUid();
   1238         if (getVpnUnderlyingNetworks(uid) != null) {
   1239             // A VPN is active, so we may need to return one of its underlying networks. This
   1240             // information is not available in LegacyTypeTracker, so we have to get it from
   1241             // getUnfilteredActiveNetworkState.
   1242             final NetworkState state = getUnfilteredActiveNetworkState(uid);
   1243             if (state.networkInfo != null && state.networkInfo.getType() == networkType) {
   1244                 filterNetworkStateForUid(state, uid, false);
   1245                 return state.networkInfo;
   1246             }
   1247         }
   1248         final NetworkState state = getFilteredNetworkState(networkType, uid, false);
   1249         return state.networkInfo;
   1250     }
   1251 
   1252     @Override
   1253     public NetworkInfo getNetworkInfoForUid(Network network, int uid, boolean ignoreBlocked) {
   1254         enforceAccessPermission();
   1255         final NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
   1256         if (nai != null) {
   1257             final NetworkState state = nai.getNetworkState();
   1258             filterNetworkStateForUid(state, uid, ignoreBlocked);
   1259             return state.networkInfo;
   1260         } else {
   1261             return null;
   1262         }
   1263     }
   1264 
   1265     @Override
   1266     public NetworkInfo[] getAllNetworkInfo() {
   1267         enforceAccessPermission();
   1268         final ArrayList<NetworkInfo> result = Lists.newArrayList();
   1269         for (int networkType = 0; networkType <= ConnectivityManager.MAX_NETWORK_TYPE;
   1270                 networkType++) {
   1271             NetworkInfo info = getNetworkInfo(networkType);
   1272             if (info != null) {
   1273                 result.add(info);
   1274             }
   1275         }
   1276         return result.toArray(new NetworkInfo[result.size()]);
   1277     }
   1278 
   1279     @Override
   1280     public Network getNetworkForType(int networkType) {
   1281         enforceAccessPermission();
   1282         final int uid = Binder.getCallingUid();
   1283         NetworkState state = getFilteredNetworkState(networkType, uid, false);
   1284         if (!isNetworkWithLinkPropertiesBlocked(state.linkProperties, uid, false)) {
   1285             return state.network;
   1286         }
   1287         return null;
   1288     }
   1289 
   1290     @Override
   1291     public Network[] getAllNetworks() {
   1292         enforceAccessPermission();
   1293         synchronized (mNetworkForNetId) {
   1294             final Network[] result = new Network[mNetworkForNetId.size()];
   1295             for (int i = 0; i < mNetworkForNetId.size(); i++) {
   1296                 result[i] = mNetworkForNetId.valueAt(i).network;
   1297             }
   1298             return result;
   1299         }
   1300     }
   1301 
   1302     @Override
   1303     public NetworkCapabilities[] getDefaultNetworkCapabilitiesForUser(int userId) {
   1304         // The basic principle is: if an app's traffic could possibly go over a
   1305         // network, without the app doing anything multinetwork-specific,
   1306         // (hence, by "default"), then include that network's capabilities in
   1307         // the array.
   1308         //
   1309         // In the normal case, app traffic only goes over the system's default
   1310         // network connection, so that's the only network returned.
   1311         //
   1312         // With a VPN in force, some app traffic may go into the VPN, and thus
   1313         // over whatever underlying networks the VPN specifies, while other app
   1314         // traffic may go over the system default network (e.g.: a split-tunnel
   1315         // VPN, or an app disallowed by the VPN), so the set of networks
   1316         // returned includes the VPN's underlying networks and the system
   1317         // default.
   1318         enforceAccessPermission();
   1319 
   1320         HashMap<Network, NetworkCapabilities> result = new HashMap<Network, NetworkCapabilities>();
   1321 
   1322         NetworkAgentInfo nai = getDefaultNetwork();
   1323         NetworkCapabilities nc = getNetworkCapabilitiesInternal(nai);
   1324         if (nc != null) {
   1325             result.put(nai.network, nc);
   1326         }
   1327 
   1328         synchronized (mVpns) {
   1329             if (!mLockdownEnabled) {
   1330                 Vpn vpn = mVpns.get(userId);
   1331                 if (vpn != null) {
   1332                     Network[] networks = vpn.getUnderlyingNetworks();
   1333                     if (networks != null) {
   1334                         for (Network network : networks) {
   1335                             nai = getNetworkAgentInfoForNetwork(network);
   1336                             nc = getNetworkCapabilitiesInternal(nai);
   1337                             if (nc != null) {
   1338                                 result.put(network, nc);
   1339                             }
   1340                         }
   1341                     }
   1342                 }
   1343             }
   1344         }
   1345 
   1346         NetworkCapabilities[] out = new NetworkCapabilities[result.size()];
   1347         out = result.values().toArray(out);
   1348         return out;
   1349     }
   1350 
   1351     @Override
   1352     public boolean isNetworkSupported(int networkType) {
   1353         enforceAccessPermission();
   1354         return mLegacyTypeTracker.isTypeSupported(networkType);
   1355     }
   1356 
   1357     /**
   1358      * Return LinkProperties for the active (i.e., connected) default
   1359      * network interface.  It is assumed that at most one default network
   1360      * is active at a time. If more than one is active, it is indeterminate
   1361      * which will be returned.
   1362      * @return the ip properties for the active network, or {@code null} if
   1363      * none is active
   1364      */
   1365     @Override
   1366     public LinkProperties getActiveLinkProperties() {
   1367         enforceAccessPermission();
   1368         final int uid = Binder.getCallingUid();
   1369         NetworkState state = getUnfilteredActiveNetworkState(uid);
   1370         return state.linkProperties;
   1371     }
   1372 
   1373     @Override
   1374     public LinkProperties getLinkPropertiesForType(int networkType) {
   1375         enforceAccessPermission();
   1376         NetworkAgentInfo nai = mLegacyTypeTracker.getNetworkForType(networkType);
   1377         if (nai != null) {
   1378             synchronized (nai) {
   1379                 return new LinkProperties(nai.linkProperties);
   1380             }
   1381         }
   1382         return null;
   1383     }
   1384 
   1385     // TODO - this should be ALL networks
   1386     @Override
   1387     public LinkProperties getLinkProperties(Network network) {
   1388         enforceAccessPermission();
   1389         return getLinkProperties(getNetworkAgentInfoForNetwork(network));
   1390     }
   1391 
   1392     private LinkProperties getLinkProperties(NetworkAgentInfo nai) {
   1393         if (nai == null) {
   1394             return null;
   1395         }
   1396         synchronized (nai) {
   1397             return new LinkProperties(nai.linkProperties);
   1398         }
   1399     }
   1400 
   1401     private NetworkCapabilities getNetworkCapabilitiesInternal(NetworkAgentInfo nai) {
   1402         if (nai != null) {
   1403             synchronized (nai) {
   1404                 if (nai.networkCapabilities != null) {
   1405                     return networkCapabilitiesRestrictedForCallerPermissions(
   1406                             nai.networkCapabilities,
   1407                             Binder.getCallingPid(), Binder.getCallingUid());
   1408                 }
   1409             }
   1410         }
   1411         return null;
   1412     }
   1413 
   1414     @Override
   1415     public NetworkCapabilities getNetworkCapabilities(Network network) {
   1416         enforceAccessPermission();
   1417         return getNetworkCapabilitiesInternal(getNetworkAgentInfoForNetwork(network));
   1418     }
   1419 
   1420     private NetworkCapabilities networkCapabilitiesRestrictedForCallerPermissions(
   1421             NetworkCapabilities nc, int callerPid, int callerUid) {
   1422         final NetworkCapabilities newNc = new NetworkCapabilities(nc);
   1423         if (!checkSettingsPermission(callerPid, callerUid)) {
   1424             newNc.setUids(null);
   1425             newNc.setSSID(null);
   1426         }
   1427         return newNc;
   1428     }
   1429 
   1430     private void restrictRequestUidsForCaller(NetworkCapabilities nc) {
   1431         if (!checkSettingsPermission()) {
   1432             nc.setSingleUid(Binder.getCallingUid());
   1433         }
   1434     }
   1435 
   1436     private void restrictBackgroundRequestForCaller(NetworkCapabilities nc) {
   1437         if (!mPermissionMonitor.hasUseBackgroundNetworksPermission(Binder.getCallingUid())) {
   1438             nc.addCapability(NET_CAPABILITY_FOREGROUND);
   1439         }
   1440     }
   1441 
   1442     @Override
   1443     public NetworkState[] getAllNetworkState() {
   1444         // Require internal since we're handing out IMSI details
   1445         enforceConnectivityInternalPermission();
   1446 
   1447         final ArrayList<NetworkState> result = Lists.newArrayList();
   1448         for (Network network : getAllNetworks()) {
   1449             final NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
   1450             if (nai != null) {
   1451                 // TODO (b/73321673) : NetworkState contains a copy of the
   1452                 // NetworkCapabilities, which may contain UIDs of apps to which the
   1453                 // network applies. Should the UIDs be cleared so as not to leak or
   1454                 // interfere ?
   1455                 result.add(nai.getNetworkState());
   1456             }
   1457         }
   1458         return result.toArray(new NetworkState[result.size()]);
   1459     }
   1460 
   1461     @Override
   1462     @Deprecated
   1463     public NetworkQuotaInfo getActiveNetworkQuotaInfo() {
   1464         Log.w(TAG, "Shame on UID " + Binder.getCallingUid()
   1465                 + " for calling the hidden API getNetworkQuotaInfo(). Shame!");
   1466         return new NetworkQuotaInfo();
   1467     }
   1468 
   1469     @Override
   1470     public boolean isActiveNetworkMetered() {
   1471         enforceAccessPermission();
   1472 
   1473         final int uid = Binder.getCallingUid();
   1474         final NetworkCapabilities caps = getUnfilteredActiveNetworkState(uid).networkCapabilities;
   1475         if (caps != null) {
   1476             return !caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
   1477         } else {
   1478             // Always return the most conservative value
   1479             return true;
   1480         }
   1481     }
   1482 
   1483     private INetworkManagementEventObserver mDataActivityObserver = new BaseNetworkObserver() {
   1484         @Override
   1485         public void interfaceClassDataActivityChanged(String label, boolean active, long tsNanos) {
   1486             int deviceType = Integer.parseInt(label);
   1487             sendDataActivityBroadcast(deviceType, active, tsNanos);
   1488         }
   1489     };
   1490 
   1491     /**
   1492      * Ensure that a network route exists to deliver traffic to the specified
   1493      * host via the specified network interface.
   1494      * @param networkType the type of the network over which traffic to the
   1495      * specified host is to be routed
   1496      * @param hostAddress the IP address of the host to which the route is
   1497      * desired
   1498      * @return {@code true} on success, {@code false} on failure
   1499      */
   1500     @Override
   1501     public boolean requestRouteToHostAddress(int networkType, byte[] hostAddress) {
   1502         enforceChangePermission();
   1503         if (mProtectedNetworks.contains(networkType)) {
   1504             enforceConnectivityInternalPermission();
   1505         }
   1506 
   1507         InetAddress addr;
   1508         try {
   1509             addr = InetAddress.getByAddress(hostAddress);
   1510         } catch (UnknownHostException e) {
   1511             if (DBG) log("requestRouteToHostAddress got " + e.toString());
   1512             return false;
   1513         }
   1514 
   1515         if (!ConnectivityManager.isNetworkTypeValid(networkType)) {
   1516             if (DBG) log("requestRouteToHostAddress on invalid network: " + networkType);
   1517             return false;
   1518         }
   1519 
   1520         NetworkAgentInfo nai = mLegacyTypeTracker.getNetworkForType(networkType);
   1521         if (nai == null) {
   1522             if (mLegacyTypeTracker.isTypeSupported(networkType) == false) {
   1523                 if (DBG) log("requestRouteToHostAddress on unsupported network: " + networkType);
   1524             } else {
   1525                 if (DBG) log("requestRouteToHostAddress on down network: " + networkType);
   1526             }
   1527             return false;
   1528         }
   1529 
   1530         DetailedState netState;
   1531         synchronized (nai) {
   1532             netState = nai.networkInfo.getDetailedState();
   1533         }
   1534 
   1535         if (netState != DetailedState.CONNECTED && netState != DetailedState.CAPTIVE_PORTAL_CHECK) {
   1536             if (VDBG) {
   1537                 log("requestRouteToHostAddress on down network "
   1538                         + "(" + networkType + ") - dropped"
   1539                         + " netState=" + netState);
   1540             }
   1541             return false;
   1542         }
   1543 
   1544         final int uid = Binder.getCallingUid();
   1545         final long token = Binder.clearCallingIdentity();
   1546         try {
   1547             LinkProperties lp;
   1548             int netId;
   1549             synchronized (nai) {
   1550                 lp = nai.linkProperties;
   1551                 netId = nai.network.netId;
   1552             }
   1553             boolean ok = addLegacyRouteToHost(lp, addr, netId, uid);
   1554             if (DBG) log("requestRouteToHostAddress ok=" + ok);
   1555             return ok;
   1556         } finally {
   1557             Binder.restoreCallingIdentity(token);
   1558         }
   1559     }
   1560 
   1561     private boolean addLegacyRouteToHost(LinkProperties lp, InetAddress addr, int netId, int uid) {
   1562         RouteInfo bestRoute = RouteInfo.selectBestRoute(lp.getAllRoutes(), addr);
   1563         if (bestRoute == null) {
   1564             bestRoute = RouteInfo.makeHostRoute(addr, lp.getInterfaceName());
   1565         } else {
   1566             String iface = bestRoute.getInterface();
   1567             if (bestRoute.getGateway().equals(addr)) {
   1568                 // if there is no better route, add the implied hostroute for our gateway
   1569                 bestRoute = RouteInfo.makeHostRoute(addr, iface);
   1570             } else {
   1571                 // if we will connect to this through another route, add a direct route
   1572                 // to it's gateway
   1573                 bestRoute = RouteInfo.makeHostRoute(addr, bestRoute.getGateway(), iface);
   1574             }
   1575         }
   1576         if (DBG) log("Adding legacy route " + bestRoute +
   1577                 " for UID/PID " + uid + "/" + Binder.getCallingPid());
   1578         try {
   1579             mNetd.addLegacyRouteForNetId(netId, bestRoute, uid);
   1580         } catch (Exception e) {
   1581             // never crash - catch them all
   1582             if (DBG) loge("Exception trying to add a route: " + e);
   1583             return false;
   1584         }
   1585         return true;
   1586     }
   1587 
   1588     @VisibleForTesting
   1589     protected final INetdEventCallback mNetdEventCallback = new BaseNetdEventCallback() {
   1590         @Override
   1591         public void onPrivateDnsValidationEvent(int netId, String ipAddress,
   1592                 String hostname, boolean validated) {
   1593             try {
   1594                 mHandler.sendMessage(mHandler.obtainMessage(
   1595                         EVENT_PRIVATE_DNS_VALIDATION_UPDATE,
   1596                         new PrivateDnsValidationUpdate(netId,
   1597                                 InetAddress.parseNumericAddress(ipAddress),
   1598                                 hostname, validated)));
   1599             } catch (IllegalArgumentException e) {
   1600                 loge("Error parsing ip address in validation event");
   1601             }
   1602         }
   1603     };
   1604 
   1605     @VisibleForTesting
   1606     protected void registerNetdEventCallback() {
   1607         mIpConnectivityMetrics =
   1608                 (IIpConnectivityMetrics) IIpConnectivityMetrics.Stub.asInterface(
   1609                 ServiceManager.getService(IpConnectivityLog.SERVICE_NAME));
   1610         if (mIpConnectivityMetrics == null) {
   1611             Slog.wtf(TAG, "Missing IIpConnectivityMetrics");
   1612         }
   1613 
   1614         try {
   1615             mIpConnectivityMetrics.addNetdEventCallback(
   1616                     INetdEventCallback.CALLBACK_CALLER_CONNECTIVITY_SERVICE,
   1617                     mNetdEventCallback);
   1618         } catch (Exception e) {
   1619             loge("Error registering netd callback: " + e);
   1620         }
   1621     }
   1622 
   1623     private final INetworkPolicyListener mPolicyListener = new NetworkPolicyManager.Listener() {
   1624         @Override
   1625         public void onUidRulesChanged(int uid, int uidRules) {
   1626             // TODO: notify UID when it has requested targeted updates
   1627         }
   1628         @Override
   1629         public void onRestrictBackgroundChanged(boolean restrictBackground) {
   1630             // TODO: relocate this specific callback in Tethering.
   1631             if (restrictBackground) {
   1632                 log("onRestrictBackgroundChanged(true): disabling tethering");
   1633                 mTethering.untetherAll();
   1634             }
   1635         }
   1636     };
   1637 
   1638     /**
   1639      * Require that the caller is either in the same user or has appropriate permission to interact
   1640      * across users.
   1641      *
   1642      * @param userId Target user for whatever operation the current IPC is supposed to perform.
   1643      */
   1644     private void enforceCrossUserPermission(int userId) {
   1645         if (userId == UserHandle.getCallingUserId()) {
   1646             // Not a cross-user call.
   1647             return;
   1648         }
   1649         mContext.enforceCallingOrSelfPermission(
   1650                 android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
   1651                 "ConnectivityService");
   1652     }
   1653 
   1654     private void enforceInternetPermission() {
   1655         mContext.enforceCallingOrSelfPermission(
   1656                 android.Manifest.permission.INTERNET,
   1657                 "ConnectivityService");
   1658     }
   1659 
   1660     private void enforceAccessPermission() {
   1661         mContext.enforceCallingOrSelfPermission(
   1662                 android.Manifest.permission.ACCESS_NETWORK_STATE,
   1663                 "ConnectivityService");
   1664     }
   1665 
   1666     private void enforceChangePermission() {
   1667         ConnectivityManager.enforceChangePermission(mContext);
   1668     }
   1669 
   1670     private void enforceSettingsPermission() {
   1671         mContext.enforceCallingOrSelfPermission(
   1672                 android.Manifest.permission.NETWORK_SETTINGS,
   1673                 "ConnectivityService");
   1674     }
   1675 
   1676     private boolean checkSettingsPermission() {
   1677         return PERMISSION_GRANTED == mContext.checkCallingOrSelfPermission(
   1678                 android.Manifest.permission.NETWORK_SETTINGS);
   1679     }
   1680 
   1681     private boolean checkSettingsPermission(int pid, int uid) {
   1682         return PERMISSION_GRANTED == mContext.checkPermission(
   1683                 android.Manifest.permission.NETWORK_SETTINGS, pid, uid);
   1684     }
   1685 
   1686     private void enforceTetherAccessPermission() {
   1687         mContext.enforceCallingOrSelfPermission(
   1688                 android.Manifest.permission.ACCESS_NETWORK_STATE,
   1689                 "ConnectivityService");
   1690     }
   1691 
   1692     private void enforceConnectivityInternalPermission() {
   1693         mContext.enforceCallingOrSelfPermission(
   1694                 android.Manifest.permission.CONNECTIVITY_INTERNAL,
   1695                 "ConnectivityService");
   1696     }
   1697 
   1698     private void enforceConnectivityRestrictedNetworksPermission() {
   1699         try {
   1700             mContext.enforceCallingOrSelfPermission(
   1701                     android.Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS,
   1702                     "ConnectivityService");
   1703             return;
   1704         } catch (SecurityException e) { /* fallback to ConnectivityInternalPermission */ }
   1705         enforceConnectivityInternalPermission();
   1706     }
   1707 
   1708     private void enforceKeepalivePermission() {
   1709         mContext.enforceCallingOrSelfPermission(KeepaliveTracker.PERMISSION, "ConnectivityService");
   1710     }
   1711 
   1712     // Public because it's used by mLockdownTracker.
   1713     public void sendConnectedBroadcast(NetworkInfo info) {
   1714         enforceConnectivityInternalPermission();
   1715         sendGeneralBroadcast(info, CONNECTIVITY_ACTION);
   1716     }
   1717 
   1718     private void sendInetConditionBroadcast(NetworkInfo info) {
   1719         sendGeneralBroadcast(info, ConnectivityManager.INET_CONDITION_ACTION);
   1720     }
   1721 
   1722     private Intent makeGeneralIntent(NetworkInfo info, String bcastType) {
   1723         synchronized (mVpns) {
   1724             if (mLockdownTracker != null) {
   1725                 info = new NetworkInfo(info);
   1726                 mLockdownTracker.augmentNetworkInfo(info);
   1727             }
   1728         }
   1729 
   1730         Intent intent = new Intent(bcastType);
   1731         intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, new NetworkInfo(info));
   1732         intent.putExtra(ConnectivityManager.EXTRA_NETWORK_TYPE, info.getType());
   1733         if (info.isFailover()) {
   1734             intent.putExtra(ConnectivityManager.EXTRA_IS_FAILOVER, true);
   1735             info.setFailover(false);
   1736         }
   1737         if (info.getReason() != null) {
   1738             intent.putExtra(ConnectivityManager.EXTRA_REASON, info.getReason());
   1739         }
   1740         if (info.getExtraInfo() != null) {
   1741             intent.putExtra(ConnectivityManager.EXTRA_EXTRA_INFO,
   1742                     info.getExtraInfo());
   1743         }
   1744         intent.putExtra(ConnectivityManager.EXTRA_INET_CONDITION, mDefaultInetConditionPublished);
   1745         return intent;
   1746     }
   1747 
   1748     private void sendGeneralBroadcast(NetworkInfo info, String bcastType) {
   1749         sendStickyBroadcast(makeGeneralIntent(info, bcastType));
   1750     }
   1751 
   1752     private void sendDataActivityBroadcast(int deviceType, boolean active, long tsNanos) {
   1753         Intent intent = new Intent(ConnectivityManager.ACTION_DATA_ACTIVITY_CHANGE);
   1754         intent.putExtra(ConnectivityManager.EXTRA_DEVICE_TYPE, deviceType);
   1755         intent.putExtra(ConnectivityManager.EXTRA_IS_ACTIVE, active);
   1756         intent.putExtra(ConnectivityManager.EXTRA_REALTIME_NS, tsNanos);
   1757         final long ident = Binder.clearCallingIdentity();
   1758         try {
   1759             mContext.sendOrderedBroadcastAsUser(intent, UserHandle.ALL,
   1760                     RECEIVE_DATA_ACTIVITY_CHANGE, null, null, 0, null, null);
   1761         } finally {
   1762             Binder.restoreCallingIdentity(ident);
   1763         }
   1764     }
   1765 
   1766     private void sendStickyBroadcast(Intent intent) {
   1767         synchronized (this) {
   1768             if (!mSystemReady) {
   1769                 mInitialBroadcast = new Intent(intent);
   1770             }
   1771             intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
   1772             if (VDBG) {
   1773                 log("sendStickyBroadcast: action=" + intent.getAction());
   1774             }
   1775 
   1776             Bundle options = null;
   1777             final long ident = Binder.clearCallingIdentity();
   1778             if (ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction())) {
   1779                 final NetworkInfo ni = intent.getParcelableExtra(
   1780                         ConnectivityManager.EXTRA_NETWORK_INFO);
   1781                 if (ni.getType() == ConnectivityManager.TYPE_MOBILE_SUPL) {
   1782                     intent.setAction(ConnectivityManager.CONNECTIVITY_ACTION_SUPL);
   1783                     intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
   1784                 } else {
   1785                     BroadcastOptions opts = BroadcastOptions.makeBasic();
   1786                     opts.setMaxManifestReceiverApiLevel(Build.VERSION_CODES.M);
   1787                     options = opts.toBundle();
   1788                 }
   1789                 final IBatteryStats bs = BatteryStatsService.getService();
   1790                 try {
   1791                     bs.noteConnectivityChanged(intent.getIntExtra(
   1792                             ConnectivityManager.EXTRA_NETWORK_TYPE, ConnectivityManager.TYPE_NONE),
   1793                             ni != null ? ni.getState().toString() : "?");
   1794                 } catch (RemoteException e) {
   1795                 }
   1796                 intent.addFlags(Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS);
   1797             }
   1798             try {
   1799                 mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL, options);
   1800             } finally {
   1801                 Binder.restoreCallingIdentity(ident);
   1802             }
   1803         }
   1804     }
   1805 
   1806     void systemReady() {
   1807         loadGlobalProxy();
   1808         registerNetdEventCallback();
   1809 
   1810         synchronized (this) {
   1811             mSystemReady = true;
   1812             if (mInitialBroadcast != null) {
   1813                 mContext.sendStickyBroadcastAsUser(mInitialBroadcast, UserHandle.ALL);
   1814                 mInitialBroadcast = null;
   1815             }
   1816         }
   1817         // load the global proxy at startup
   1818         mHandler.sendMessage(mHandler.obtainMessage(EVENT_APPLY_GLOBAL_HTTP_PROXY));
   1819 
   1820         // Try bringing up tracker, but KeyStore won't be ready yet for secondary users so wait
   1821         // for user to unlock device too.
   1822         updateLockdownVpn();
   1823 
   1824         // Configure whether mobile data is always on.
   1825         mHandler.sendMessage(mHandler.obtainMessage(EVENT_CONFIGURE_MOBILE_DATA_ALWAYS_ON));
   1826 
   1827         mHandler.sendMessage(mHandler.obtainMessage(EVENT_SYSTEM_READY));
   1828 
   1829         mPermissionMonitor.startMonitoring();
   1830     }
   1831 
   1832     /**
   1833      * Setup data activity tracking for the given network.
   1834      *
   1835      * Every {@code setupDataActivityTracking} should be paired with a
   1836      * {@link #removeDataActivityTracking} for cleanup.
   1837      */
   1838     private void setupDataActivityTracking(NetworkAgentInfo networkAgent) {
   1839         final String iface = networkAgent.linkProperties.getInterfaceName();
   1840 
   1841         final int timeout;
   1842         int type = ConnectivityManager.TYPE_NONE;
   1843 
   1844         if (networkAgent.networkCapabilities.hasTransport(
   1845                 NetworkCapabilities.TRANSPORT_CELLULAR)) {
   1846             timeout = Settings.Global.getInt(mContext.getContentResolver(),
   1847                                              Settings.Global.DATA_ACTIVITY_TIMEOUT_MOBILE,
   1848                                              10);
   1849             type = ConnectivityManager.TYPE_MOBILE;
   1850         } else if (networkAgent.networkCapabilities.hasTransport(
   1851                 NetworkCapabilities.TRANSPORT_WIFI)) {
   1852             timeout = Settings.Global.getInt(mContext.getContentResolver(),
   1853                                              Settings.Global.DATA_ACTIVITY_TIMEOUT_WIFI,
   1854                                              15);
   1855             type = ConnectivityManager.TYPE_WIFI;
   1856         } else {
   1857             // do not track any other networks
   1858             timeout = 0;
   1859         }
   1860 
   1861         if (timeout > 0 && iface != null && type != ConnectivityManager.TYPE_NONE) {
   1862             try {
   1863                 mNetd.addIdleTimer(iface, timeout, type);
   1864             } catch (Exception e) {
   1865                 // You shall not crash!
   1866                 loge("Exception in setupDataActivityTracking " + e);
   1867             }
   1868         }
   1869     }
   1870 
   1871     /**
   1872      * Remove data activity tracking when network disconnects.
   1873      */
   1874     private void removeDataActivityTracking(NetworkAgentInfo networkAgent) {
   1875         final String iface = networkAgent.linkProperties.getInterfaceName();
   1876         final NetworkCapabilities caps = networkAgent.networkCapabilities;
   1877 
   1878         if (iface != null && (caps.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) ||
   1879                               caps.hasTransport(NetworkCapabilities.TRANSPORT_WIFI))) {
   1880             try {
   1881                 // the call fails silently if no idletimer setup for this interface
   1882                 mNetd.removeIdleTimer(iface);
   1883             } catch (Exception e) {
   1884                 loge("Exception in removeDataActivityTracking " + e);
   1885             }
   1886         }
   1887     }
   1888 
   1889     /**
   1890      * Reads the network specific MTU size from reources.
   1891      * and set it on it's iface.
   1892      */
   1893     private void updateMtu(LinkProperties newLp, LinkProperties oldLp) {
   1894         final String iface = newLp.getInterfaceName();
   1895         final int mtu = newLp.getMtu();
   1896         if (oldLp == null && mtu == 0) {
   1897             // Silently ignore unset MTU value.
   1898             return;
   1899         }
   1900         if (oldLp != null && newLp.isIdenticalMtu(oldLp)) {
   1901             if (VDBG) log("identical MTU - not setting");
   1902             return;
   1903         }
   1904         if (LinkProperties.isValidMtu(mtu, newLp.hasGlobalIPv6Address()) == false) {
   1905             if (mtu != 0) loge("Unexpected mtu value: " + mtu + ", " + iface);
   1906             return;
   1907         }
   1908 
   1909         // Cannot set MTU without interface name
   1910         if (TextUtils.isEmpty(iface)) {
   1911             loge("Setting MTU size with null iface.");
   1912             return;
   1913         }
   1914 
   1915         try {
   1916             if (VDBG) log("Setting MTU size: " + iface + ", " + mtu);
   1917             mNetd.setMtu(iface, mtu);
   1918         } catch (Exception e) {
   1919             Slog.e(TAG, "exception in setMtu()" + e);
   1920         }
   1921     }
   1922 
   1923     private static final String DEFAULT_TCP_BUFFER_SIZES = "4096,87380,110208,4096,16384,110208";
   1924     private static final String DEFAULT_TCP_RWND_KEY = "net.tcp.default_init_rwnd";
   1925 
   1926     // Overridden for testing purposes to avoid writing to SystemProperties.
   1927     @VisibleForTesting
   1928     protected MockableSystemProperties getSystemProperties() {
   1929         return new MockableSystemProperties();
   1930     }
   1931 
   1932     private void updateTcpBufferSizes(NetworkAgentInfo nai) {
   1933         if (isDefaultNetwork(nai) == false) {
   1934             return;
   1935         }
   1936 
   1937         String tcpBufferSizes = nai.linkProperties.getTcpBufferSizes();
   1938         String[] values = null;
   1939         if (tcpBufferSizes != null) {
   1940             values = tcpBufferSizes.split(",");
   1941         }
   1942 
   1943         if (values == null || values.length != 6) {
   1944             if (DBG) log("Invalid tcpBufferSizes string: " + tcpBufferSizes +", using defaults");
   1945             tcpBufferSizes = DEFAULT_TCP_BUFFER_SIZES;
   1946             values = tcpBufferSizes.split(",");
   1947         }
   1948 
   1949         if (tcpBufferSizes.equals(mCurrentTcpBufferSizes)) return;
   1950 
   1951         try {
   1952             if (VDBG) Slog.d(TAG, "Setting tx/rx TCP buffers to " + tcpBufferSizes);
   1953 
   1954             final String prefix = "/sys/kernel/ipv4/tcp_";
   1955             FileUtils.stringToFile(prefix + "rmem_min", values[0]);
   1956             FileUtils.stringToFile(prefix + "rmem_def", values[1]);
   1957             FileUtils.stringToFile(prefix + "rmem_max", values[2]);
   1958             FileUtils.stringToFile(prefix + "wmem_min", values[3]);
   1959             FileUtils.stringToFile(prefix + "wmem_def", values[4]);
   1960             FileUtils.stringToFile(prefix + "wmem_max", values[5]);
   1961             mCurrentTcpBufferSizes = tcpBufferSizes;
   1962         } catch (IOException e) {
   1963             loge("Can't set TCP buffer sizes:" + e);
   1964         }
   1965 
   1966         Integer rwndValue = Settings.Global.getInt(mContext.getContentResolver(),
   1967             Settings.Global.TCP_DEFAULT_INIT_RWND,
   1968                     mSystemProperties.getInt("net.tcp.default_init_rwnd", 0));
   1969         final String sysctlKey = "sys.sysctl.tcp_def_init_rwnd";
   1970         if (rwndValue != 0) {
   1971             mSystemProperties.set(sysctlKey, rwndValue.toString());
   1972         }
   1973     }
   1974 
   1975     @Override
   1976     public int getRestoreDefaultNetworkDelay(int networkType) {
   1977         String restoreDefaultNetworkDelayStr = mSystemProperties.get(
   1978                 NETWORK_RESTORE_DELAY_PROP_NAME);
   1979         if(restoreDefaultNetworkDelayStr != null &&
   1980                 restoreDefaultNetworkDelayStr.length() != 0) {
   1981             try {
   1982                 return Integer.parseInt(restoreDefaultNetworkDelayStr);
   1983             } catch (NumberFormatException e) {
   1984             }
   1985         }
   1986         // if the system property isn't set, use the value for the apn type
   1987         int ret = RESTORE_DEFAULT_NETWORK_DELAY;
   1988 
   1989         if ((networkType <= ConnectivityManager.MAX_NETWORK_TYPE) &&
   1990                 (mNetConfigs[networkType] != null)) {
   1991             ret = mNetConfigs[networkType].restoreTime;
   1992         }
   1993         return ret;
   1994     }
   1995 
   1996     private void dumpNetworkDiagnostics(IndentingPrintWriter pw) {
   1997         final List<NetworkDiagnostics> netDiags = new ArrayList<NetworkDiagnostics>();
   1998         final long DIAG_TIME_MS = 5000;
   1999         for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
   2000             // Start gathering diagnostic information.
   2001             netDiags.add(new NetworkDiagnostics(
   2002                     nai.network,
   2003                     new LinkProperties(nai.linkProperties),  // Must be a copy.
   2004                     DIAG_TIME_MS));
   2005         }
   2006 
   2007         for (NetworkDiagnostics netDiag : netDiags) {
   2008             pw.println();
   2009             netDiag.waitForMeasurements();
   2010             netDiag.dump(pw);
   2011         }
   2012     }
   2013 
   2014     @Override
   2015     protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
   2016         PriorityDump.dump(mPriorityDumper, fd, writer, args);
   2017     }
   2018 
   2019     private void doDump(FileDescriptor fd, PrintWriter writer, String[] args, boolean asProto) {
   2020         final IndentingPrintWriter pw = new IndentingPrintWriter(writer, "  ");
   2021         if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
   2022         if (asProto) return;
   2023 
   2024         if (ArrayUtils.contains(args, DIAG_ARG)) {
   2025             dumpNetworkDiagnostics(pw);
   2026             return;
   2027         } else if (ArrayUtils.contains(args, TETHERING_ARG)) {
   2028             mTethering.dump(fd, pw, args);
   2029             return;
   2030         }
   2031 
   2032         pw.print("NetworkFactories for:");
   2033         for (NetworkFactoryInfo nfi : mNetworkFactoryInfos.values()) {
   2034             pw.print(" " + nfi.name);
   2035         }
   2036         pw.println();
   2037         pw.println();
   2038 
   2039         final NetworkAgentInfo defaultNai = getDefaultNetwork();
   2040         pw.print("Active default network: ");
   2041         if (defaultNai == null) {
   2042             pw.println("none");
   2043         } else {
   2044             pw.println(defaultNai.network.netId);
   2045         }
   2046         pw.println();
   2047 
   2048         pw.println("Current Networks:");
   2049         pw.increaseIndent();
   2050         for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
   2051             pw.println(nai.toString());
   2052             pw.increaseIndent();
   2053             pw.println(String.format(
   2054                     "Requests: REQUEST:%d LISTEN:%d BACKGROUND_REQUEST:%d total:%d",
   2055                     nai.numForegroundNetworkRequests(),
   2056                     nai.numNetworkRequests() - nai.numRequestNetworkRequests(),
   2057                     nai.numBackgroundNetworkRequests(),
   2058                     nai.numNetworkRequests()));
   2059             pw.increaseIndent();
   2060             for (int i = 0; i < nai.numNetworkRequests(); i++) {
   2061                 pw.println(nai.requestAt(i).toString());
   2062             }
   2063             pw.decreaseIndent();
   2064             pw.println("Lingered:");
   2065             pw.increaseIndent();
   2066             nai.dumpLingerTimers(pw);
   2067             pw.decreaseIndent();
   2068             pw.decreaseIndent();
   2069         }
   2070         pw.decreaseIndent();
   2071         pw.println();
   2072 
   2073         pw.println("Network Requests:");
   2074         pw.increaseIndent();
   2075         for (NetworkRequestInfo nri : mNetworkRequests.values()) {
   2076             pw.println(nri.toString());
   2077         }
   2078         pw.println();
   2079         pw.decreaseIndent();
   2080 
   2081         mLegacyTypeTracker.dump(pw);
   2082 
   2083         pw.println();
   2084         mTethering.dump(fd, pw, args);
   2085 
   2086         pw.println();
   2087         mKeepaliveTracker.dump(pw);
   2088 
   2089         pw.println();
   2090         dumpAvoidBadWifiSettings(pw);
   2091 
   2092         pw.println();
   2093         mMultipathPolicyTracker.dump(pw);
   2094 
   2095         if (ArrayUtils.contains(args, SHORT_ARG) == false) {
   2096             pw.println();
   2097             synchronized (mValidationLogs) {
   2098                 pw.println("mValidationLogs (most recent first):");
   2099                 for (ValidationLog p : mValidationLogs) {
   2100                     pw.println(p.mNetwork + " - " + p.mName);
   2101                     pw.increaseIndent();
   2102                     p.mLog.dump(fd, pw, args);
   2103                     pw.decreaseIndent();
   2104                 }
   2105             }
   2106 
   2107             pw.println();
   2108             pw.println("mNetworkRequestInfoLogs (most recent first):");
   2109             pw.increaseIndent();
   2110             mNetworkRequestInfoLogs.reverseDump(fd, pw, args);
   2111             pw.decreaseIndent();
   2112 
   2113             pw.println();
   2114             pw.println("mNetworkInfoBlockingLogs (most recent first):");
   2115             pw.increaseIndent();
   2116             mNetworkInfoBlockingLogs.reverseDump(fd, pw, args);
   2117             pw.decreaseIndent();
   2118 
   2119             pw.println();
   2120             pw.println("NetTransition WakeLock activity (most recent first):");
   2121             pw.increaseIndent();
   2122             pw.println("total acquisitions: " + mTotalWakelockAcquisitions);
   2123             pw.println("total releases: " + mTotalWakelockReleases);
   2124             pw.println("cumulative duration: " + (mTotalWakelockDurationMs / 1000) + "s");
   2125             pw.println("longest duration: " + (mMaxWakelockDurationMs / 1000) + "s");
   2126             if (mTotalWakelockAcquisitions > mTotalWakelockReleases) {
   2127                 long duration = SystemClock.elapsedRealtime() - mLastWakeLockAcquireTimestamp;
   2128                 pw.println("currently holding WakeLock for: " + (duration / 1000) + "s");
   2129             }
   2130             mWakelockLogs.reverseDump(fd, pw, args);
   2131             pw.decreaseIndent();
   2132         }
   2133     }
   2134 
   2135     private boolean isLiveNetworkAgent(NetworkAgentInfo nai, int what) {
   2136         if (nai.network == null) return false;
   2137         final NetworkAgentInfo officialNai = getNetworkAgentInfoForNetwork(nai.network);
   2138         if (officialNai != null && officialNai.equals(nai)) return true;
   2139         if (officialNai != null || VDBG) {
   2140             loge(eventName(what) + " - isLiveNetworkAgent found mismatched netId: " + officialNai +
   2141                 " - " + nai);
   2142         }
   2143         return false;
   2144     }
   2145 
   2146     // must be stateless - things change under us.
   2147     private class NetworkStateTrackerHandler extends Handler {
   2148         public NetworkStateTrackerHandler(Looper looper) {
   2149             super(looper);
   2150         }
   2151 
   2152         private boolean maybeHandleAsyncChannelMessage(Message msg) {
   2153             switch (msg.what) {
   2154                 default:
   2155                     return false;
   2156                 case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: {
   2157                     handleAsyncChannelHalfConnect(msg);
   2158                     break;
   2159                 }
   2160                 case AsyncChannel.CMD_CHANNEL_DISCONNECT: {
   2161                     NetworkAgentInfo nai = mNetworkAgentInfos.get(msg.replyTo);
   2162                     if (nai != null) nai.asyncChannel.disconnect();
   2163                     break;
   2164                 }
   2165                 case AsyncChannel.CMD_CHANNEL_DISCONNECTED: {
   2166                     handleAsyncChannelDisconnected(msg);
   2167                     break;
   2168                 }
   2169             }
   2170             return true;
   2171         }
   2172 
   2173         private void maybeHandleNetworkAgentMessage(Message msg) {
   2174             NetworkAgentInfo nai = mNetworkAgentInfos.get(msg.replyTo);
   2175             if (nai == null) {
   2176                 if (VDBG) {
   2177                     log(String.format("%s from unknown NetworkAgent", eventName(msg.what)));
   2178                 }
   2179                 return;
   2180             }
   2181 
   2182             switch (msg.what) {
   2183                 case NetworkAgent.EVENT_NETWORK_CAPABILITIES_CHANGED: {
   2184                     final NetworkCapabilities networkCapabilities = (NetworkCapabilities) msg.obj;
   2185                     if (networkCapabilities.hasCapability(NET_CAPABILITY_CAPTIVE_PORTAL) ||
   2186                             networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED) ||
   2187                             networkCapabilities.hasCapability(NET_CAPABILITY_FOREGROUND)) {
   2188                         Slog.wtf(TAG, "BUG: " + nai + " has CS-managed capability.");
   2189                     }
   2190                     updateCapabilities(nai.getCurrentScore(), nai, networkCapabilities);
   2191                     break;
   2192                 }
   2193                 case NetworkAgent.EVENT_NETWORK_PROPERTIES_CHANGED: {
   2194                     handleUpdateLinkProperties(nai, (LinkProperties) msg.obj);
   2195                     break;
   2196                 }
   2197                 case NetworkAgent.EVENT_NETWORK_INFO_CHANGED: {
   2198                     NetworkInfo info = (NetworkInfo) msg.obj;
   2199                     updateNetworkInfo(nai, info);
   2200                     break;
   2201                 }
   2202                 case NetworkAgent.EVENT_NETWORK_SCORE_CHANGED: {
   2203                     Integer score = (Integer) msg.obj;
   2204                     if (score != null) updateNetworkScore(nai, score.intValue());
   2205                     break;
   2206                 }
   2207                 case NetworkAgent.EVENT_SET_EXPLICITLY_SELECTED: {
   2208                     if (nai.everConnected && !nai.networkMisc.explicitlySelected) {
   2209                         loge("ERROR: already-connected network explicitly selected.");
   2210                     }
   2211                     nai.networkMisc.explicitlySelected = true;
   2212                     nai.networkMisc.acceptUnvalidated = (boolean) msg.obj;
   2213                     break;
   2214                 }
   2215                 case NetworkAgent.EVENT_PACKET_KEEPALIVE: {
   2216                     mKeepaliveTracker.handleEventPacketKeepalive(nai, msg);
   2217                     break;
   2218                 }
   2219             }
   2220         }
   2221 
   2222         private boolean maybeHandleNetworkMonitorMessage(Message msg) {
   2223             switch (msg.what) {
   2224                 default:
   2225                     return false;
   2226                 case NetworkMonitor.EVENT_NETWORK_TESTED: {
   2227                     final NetworkAgentInfo nai = getNetworkAgentInfoForNetId(msg.arg2);
   2228                     if (nai == null) break;
   2229 
   2230                     final boolean valid = (msg.arg1 == NetworkMonitor.NETWORK_TEST_RESULT_VALID);
   2231                     final boolean wasValidated = nai.lastValidated;
   2232                     final boolean wasDefault = isDefaultNetwork(nai);
   2233 
   2234                     final String redirectUrl = (msg.obj instanceof String) ? (String) msg.obj : "";
   2235 
   2236                     if (DBG) {
   2237                         final String logMsg = !TextUtils.isEmpty(redirectUrl)
   2238                                  ? " with redirect to " + redirectUrl
   2239                                  : "";
   2240                         log(nai.name() + " validation " + (valid ? "passed" : "failed") + logMsg);
   2241                     }
   2242                     if (valid != nai.lastValidated) {
   2243                         if (wasDefault) {
   2244                             metricsLogger().defaultNetworkMetrics().logDefaultNetworkValidity(
   2245                                     SystemClock.elapsedRealtime(), valid);
   2246                         }
   2247                         final int oldScore = nai.getCurrentScore();
   2248                         nai.lastValidated = valid;
   2249                         nai.everValidated |= valid;
   2250                         updateCapabilities(oldScore, nai, nai.networkCapabilities);
   2251                         // If score has changed, rebroadcast to NetworkFactories. b/17726566
   2252                         if (oldScore != nai.getCurrentScore()) sendUpdatedScoreToFactories(nai);
   2253                     }
   2254                     updateInetCondition(nai);
   2255                     // Let the NetworkAgent know the state of its network
   2256                     Bundle redirectUrlBundle = new Bundle();
   2257                     redirectUrlBundle.putString(NetworkAgent.REDIRECT_URL_KEY, redirectUrl);
   2258                     nai.asyncChannel.sendMessage(
   2259                             NetworkAgent.CMD_REPORT_NETWORK_STATUS,
   2260                             (valid ? NetworkAgent.VALID_NETWORK : NetworkAgent.INVALID_NETWORK),
   2261                             0, redirectUrlBundle);
   2262                     if (wasValidated && !nai.lastValidated) {
   2263                         handleNetworkUnvalidated(nai);
   2264                     }
   2265                     break;
   2266                 }
   2267                 case NetworkMonitor.EVENT_PROVISIONING_NOTIFICATION: {
   2268                     final int netId = msg.arg2;
   2269                     final boolean visible = toBool(msg.arg1);
   2270                     final NetworkAgentInfo nai = getNetworkAgentInfoForNetId(netId);
   2271                     // If captive portal status has changed, update capabilities or disconnect.
   2272                     if (nai != null && (visible != nai.lastCaptivePortalDetected)) {
   2273                         final int oldScore = nai.getCurrentScore();
   2274                         nai.lastCaptivePortalDetected = visible;
   2275                         nai.everCaptivePortalDetected |= visible;
   2276                         if (nai.lastCaptivePortalDetected &&
   2277                             Settings.Global.CAPTIVE_PORTAL_MODE_AVOID == getCaptivePortalMode()) {
   2278                             if (DBG) log("Avoiding captive portal network: " + nai.name());
   2279                             nai.asyncChannel.sendMessage(
   2280                                     NetworkAgent.CMD_PREVENT_AUTOMATIC_RECONNECT);
   2281                             teardownUnneededNetwork(nai);
   2282                             break;
   2283                         }
   2284                         updateCapabilities(oldScore, nai, nai.networkCapabilities);
   2285                     }
   2286                     if (!visible) {
   2287                         mNotifier.clearNotification(netId);
   2288                     } else {
   2289                         if (nai == null) {
   2290                             loge("EVENT_PROVISIONING_NOTIFICATION from unknown NetworkMonitor");
   2291                             break;
   2292                         }
   2293                         if (!nai.networkMisc.provisioningNotificationDisabled) {
   2294                             mNotifier.showNotification(netId, NotificationType.SIGN_IN, nai, null,
   2295                                     (PendingIntent) msg.obj, nai.networkMisc.explicitlySelected);
   2296                         }
   2297                     }
   2298                     break;
   2299                 }
   2300                 case NetworkMonitor.EVENT_PRIVATE_DNS_CONFIG_RESOLVED: {
   2301                     final NetworkAgentInfo nai = getNetworkAgentInfoForNetId(msg.arg2);
   2302                     if (nai == null) break;
   2303 
   2304                     updatePrivateDns(nai, (PrivateDnsConfig) msg.obj);
   2305                     break;
   2306                 }
   2307             }
   2308             return true;
   2309         }
   2310 
   2311         private int getCaptivePortalMode() {
   2312             return Settings.Global.getInt(mContext.getContentResolver(),
   2313                     Settings.Global.CAPTIVE_PORTAL_MODE,
   2314                     Settings.Global.CAPTIVE_PORTAL_MODE_PROMPT);
   2315         }
   2316 
   2317         private boolean maybeHandleNetworkAgentInfoMessage(Message msg) {
   2318             switch (msg.what) {
   2319                 default:
   2320                     return false;
   2321                 case NetworkAgentInfo.EVENT_NETWORK_LINGER_COMPLETE: {
   2322                     NetworkAgentInfo nai = (NetworkAgentInfo) msg.obj;
   2323                     if (nai != null && isLiveNetworkAgent(nai, msg.what)) {
   2324                         handleLingerComplete(nai);
   2325                     }
   2326                     break;
   2327                 }
   2328             }
   2329             return true;
   2330         }
   2331 
   2332         @Override
   2333         public void handleMessage(Message msg) {
   2334             if (!maybeHandleAsyncChannelMessage(msg) &&
   2335                     !maybeHandleNetworkMonitorMessage(msg) &&
   2336                     !maybeHandleNetworkAgentInfoMessage(msg)) {
   2337                 maybeHandleNetworkAgentMessage(msg);
   2338             }
   2339         }
   2340     }
   2341 
   2342     private boolean networkRequiresValidation(NetworkAgentInfo nai) {
   2343         return NetworkMonitor.isValidationRequired(
   2344                 mDefaultRequest.networkCapabilities, nai.networkCapabilities);
   2345     }
   2346 
   2347     private void handlePrivateDnsSettingsChanged() {
   2348         final PrivateDnsConfig cfg = mDnsManager.getPrivateDnsConfig();
   2349 
   2350         for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
   2351             handlePerNetworkPrivateDnsConfig(nai, cfg);
   2352             if (networkRequiresValidation(nai)) {
   2353                 handleUpdateLinkProperties(nai, new LinkProperties(nai.linkProperties));
   2354             }
   2355         }
   2356     }
   2357 
   2358     private void handlePerNetworkPrivateDnsConfig(NetworkAgentInfo nai, PrivateDnsConfig cfg) {
   2359         // Private DNS only ever applies to networks that might provide
   2360         // Internet access and therefore also require validation.
   2361         if (!networkRequiresValidation(nai)) return;
   2362 
   2363         // Notify the NetworkMonitor thread in case it needs to cancel or
   2364         // schedule DNS resolutions. If a DNS resolution is required the
   2365         // result will be sent back to us.
   2366         nai.networkMonitor.notifyPrivateDnsSettingsChanged(cfg);
   2367 
   2368         // With Private DNS bypass support, we can proceed to update the
   2369         // Private DNS config immediately, even if we're in strict mode
   2370         // and have not yet resolved the provider name into a set of IPs.
   2371         updatePrivateDns(nai, cfg);
   2372     }
   2373 
   2374     private void updatePrivateDns(NetworkAgentInfo nai, PrivateDnsConfig newCfg) {
   2375         mDnsManager.updatePrivateDns(nai.network, newCfg);
   2376         updateDnses(nai.linkProperties, null, nai.network.netId);
   2377     }
   2378 
   2379     private void handlePrivateDnsValidationUpdate(PrivateDnsValidationUpdate update) {
   2380         NetworkAgentInfo nai = getNetworkAgentInfoForNetId(update.netId);
   2381         if (nai == null) {
   2382             return;
   2383         }
   2384         mDnsManager.updatePrivateDnsValidation(update);
   2385         handleUpdateLinkProperties(nai, new LinkProperties(nai.linkProperties));
   2386     }
   2387 
   2388     private void updateLingerState(NetworkAgentInfo nai, long now) {
   2389         // 1. Update the linger timer. If it's changed, reschedule or cancel the alarm.
   2390         // 2. If the network was lingering and there are now requests, unlinger it.
   2391         // 3. If this network is unneeded (which implies it is not lingering), and there is at least
   2392         //    one lingered request, start lingering.
   2393         nai.updateLingerTimer();
   2394         if (nai.isLingering() && nai.numForegroundNetworkRequests() > 0) {
   2395             if (DBG) log("Unlingering " + nai.name());
   2396             nai.unlinger();
   2397             logNetworkEvent(nai, NetworkEvent.NETWORK_UNLINGER);
   2398         } else if (unneeded(nai, UnneededFor.LINGER) && nai.getLingerExpiry() > 0) {
   2399             int lingerTime = (int) (nai.getLingerExpiry() - now);
   2400             if (DBG) log("Lingering " + nai.name() + " for " + lingerTime + "ms");
   2401             nai.linger();
   2402             logNetworkEvent(nai, NetworkEvent.NETWORK_LINGER);
   2403             notifyNetworkCallbacks(nai, ConnectivityManager.CALLBACK_LOSING, lingerTime);
   2404         }
   2405     }
   2406 
   2407     private void handleAsyncChannelHalfConnect(Message msg) {
   2408         AsyncChannel ac = (AsyncChannel) msg.obj;
   2409         if (mNetworkFactoryInfos.containsKey(msg.replyTo)) {
   2410             if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
   2411                 if (VDBG) log("NetworkFactory connected");
   2412                 // A network factory has connected.  Send it all current NetworkRequests.
   2413                 for (NetworkRequestInfo nri : mNetworkRequests.values()) {
   2414                     if (nri.request.isListen()) continue;
   2415                     NetworkAgentInfo nai = getNetworkForRequest(nri.request.requestId);
   2416                     ac.sendMessage(android.net.NetworkFactory.CMD_REQUEST_NETWORK,
   2417                             (nai != null ? nai.getCurrentScore() : 0), 0, nri.request);
   2418                 }
   2419             } else {
   2420                 loge("Error connecting NetworkFactory");
   2421                 mNetworkFactoryInfos.remove(msg.obj);
   2422             }
   2423         } else if (mNetworkAgentInfos.containsKey(msg.replyTo)) {
   2424             if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
   2425                 if (VDBG) log("NetworkAgent connected");
   2426                 // A network agent has requested a connection.  Establish the connection.
   2427                 mNetworkAgentInfos.get(msg.replyTo).asyncChannel.
   2428                         sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION);
   2429             } else {
   2430                 loge("Error connecting NetworkAgent");
   2431                 NetworkAgentInfo nai = mNetworkAgentInfos.remove(msg.replyTo);
   2432                 if (nai != null) {
   2433                     final boolean wasDefault = isDefaultNetwork(nai);
   2434                     synchronized (mNetworkForNetId) {
   2435                         mNetworkForNetId.remove(nai.network.netId);
   2436                         mNetIdInUse.delete(nai.network.netId);
   2437                     }
   2438                     // Just in case.
   2439                     mLegacyTypeTracker.remove(nai, wasDefault);
   2440                 }
   2441             }
   2442         }
   2443     }
   2444 
   2445     // This is a no-op if it's called with a message designating a network that has
   2446     // already been destroyed, because its reference will not be found in the relevant
   2447     // maps.
   2448     private void handleAsyncChannelDisconnected(Message msg) {
   2449         NetworkAgentInfo nai = mNetworkAgentInfos.get(msg.replyTo);
   2450         if (nai != null) {
   2451             disconnectAndDestroyNetwork(nai);
   2452         } else {
   2453             NetworkFactoryInfo nfi = mNetworkFactoryInfos.remove(msg.replyTo);
   2454             if (DBG && nfi != null) log("unregisterNetworkFactory for " + nfi.name);
   2455         }
   2456     }
   2457 
   2458     // Destroys a network, remove references to it from the internal state managed by
   2459     // ConnectivityService, free its interfaces and clean up.
   2460     // Must be called on the Handler thread.
   2461     private void disconnectAndDestroyNetwork(NetworkAgentInfo nai) {
   2462         if (DBG) {
   2463             log(nai.name() + " got DISCONNECTED, was satisfying " + nai.numNetworkRequests());
   2464         }
   2465         // A network agent has disconnected.
   2466         // TODO - if we move the logic to the network agent (have them disconnect
   2467         // because they lost all their requests or because their score isn't good)
   2468         // then they would disconnect organically, report their new state and then
   2469         // disconnect the channel.
   2470         if (nai.networkInfo.isConnected()) {
   2471             nai.networkInfo.setDetailedState(NetworkInfo.DetailedState.DISCONNECTED,
   2472                     null, null);
   2473         }
   2474         final boolean wasDefault = isDefaultNetwork(nai);
   2475         if (wasDefault) {
   2476             mDefaultInetConditionPublished = 0;
   2477             // Log default network disconnection before required book-keeping.
   2478             // Let rematchAllNetworksAndRequests() below record a new default network event
   2479             // if there is a fallback. Taken together, the two form a X -> 0, 0 -> Y sequence
   2480             // whose timestamps tell how long it takes to recover a default network.
   2481             long now = SystemClock.elapsedRealtime();
   2482             metricsLogger().defaultNetworkMetrics().logDefaultNetworkEvent(now, null, nai);
   2483         }
   2484         notifyIfacesChangedForNetworkStats();
   2485         // TODO - we shouldn't send CALLBACK_LOST to requests that can be satisfied
   2486         // by other networks that are already connected. Perhaps that can be done by
   2487         // sending all CALLBACK_LOST messages (for requests, not listens) at the end
   2488         // of rematchAllNetworksAndRequests
   2489         notifyNetworkCallbacks(nai, ConnectivityManager.CALLBACK_LOST);
   2490         mKeepaliveTracker.handleStopAllKeepalives(nai,
   2491                 ConnectivityManager.PacketKeepalive.ERROR_INVALID_NETWORK);
   2492         for (String iface : nai.linkProperties.getAllInterfaceNames()) {
   2493             // Disable wakeup packet monitoring for each interface.
   2494             wakeupModifyInterface(iface, nai.networkCapabilities, false);
   2495         }
   2496         nai.networkMonitor.sendMessage(NetworkMonitor.CMD_NETWORK_DISCONNECTED);
   2497         mNetworkAgentInfos.remove(nai.messenger);
   2498         nai.maybeStopClat();
   2499         synchronized (mNetworkForNetId) {
   2500             // Remove the NetworkAgent, but don't mark the netId as
   2501             // available until we've told netd to delete it below.
   2502             mNetworkForNetId.remove(nai.network.netId);
   2503         }
   2504         // Remove all previously satisfied requests.
   2505         for (int i = 0; i < nai.numNetworkRequests(); i++) {
   2506             NetworkRequest request = nai.requestAt(i);
   2507             NetworkAgentInfo currentNetwork = getNetworkForRequest(request.requestId);
   2508             if (currentNetwork != null && currentNetwork.network.netId == nai.network.netId) {
   2509                 clearNetworkForRequest(request.requestId);
   2510                 sendUpdatedScoreToFactories(request, 0);
   2511             }
   2512         }
   2513         nai.clearLingerState();
   2514         if (nai.isSatisfyingRequest(mDefaultRequest.requestId)) {
   2515             removeDataActivityTracking(nai);
   2516             notifyLockdownVpn(nai);
   2517             ensureNetworkTransitionWakelock(nai.name());
   2518         }
   2519         mLegacyTypeTracker.remove(nai, wasDefault);
   2520         if (!nai.networkCapabilities.hasTransport(TRANSPORT_VPN)) {
   2521             updateAllVpnsCapabilities();
   2522         }
   2523         rematchAllNetworksAndRequests(null, 0);
   2524         mLingerMonitor.noteDisconnect(nai);
   2525         if (nai.created) {
   2526             // Tell netd to clean up the configuration for this network
   2527             // (routing rules, DNS, etc).
   2528             // This may be slow as it requires a lot of netd shelling out to ip and
   2529             // ip[6]tables to flush routes and remove the incoming packet mark rule, so do it
   2530             // after we've rematched networks with requests which should make a potential
   2531             // fallback network the default or requested a new network from the
   2532             // NetworkFactories, so network traffic isn't interrupted for an unnecessarily
   2533             // long time.
   2534             try {
   2535                 mNetd.removeNetwork(nai.network.netId);
   2536             } catch (Exception e) {
   2537                 loge("Exception removing network: " + e);
   2538             }
   2539             mDnsManager.removeNetwork(nai.network);
   2540         }
   2541         synchronized (mNetworkForNetId) {
   2542             mNetIdInUse.delete(nai.network.netId);
   2543         }
   2544     }
   2545 
   2546     // If this method proves to be too slow then we can maintain a separate
   2547     // pendingIntent => NetworkRequestInfo map.
   2548     // This method assumes that every non-null PendingIntent maps to exactly 1 NetworkRequestInfo.
   2549     private NetworkRequestInfo findExistingNetworkRequestInfo(PendingIntent pendingIntent) {
   2550         Intent intent = pendingIntent.getIntent();
   2551         for (Map.Entry<NetworkRequest, NetworkRequestInfo> entry : mNetworkRequests.entrySet()) {
   2552             PendingIntent existingPendingIntent = entry.getValue().mPendingIntent;
   2553             if (existingPendingIntent != null &&
   2554                     existingPendingIntent.getIntent().filterEquals(intent)) {
   2555                 return entry.getValue();
   2556             }
   2557         }
   2558         return null;
   2559     }
   2560 
   2561     private void handleRegisterNetworkRequestWithIntent(Message msg) {
   2562         final NetworkRequestInfo nri = (NetworkRequestInfo) (msg.obj);
   2563 
   2564         NetworkRequestInfo existingRequest = findExistingNetworkRequestInfo(nri.mPendingIntent);
   2565         if (existingRequest != null) { // remove the existing request.
   2566             if (DBG) log("Replacing " + existingRequest.request + " with "
   2567                     + nri.request + " because their intents matched.");
   2568             handleReleaseNetworkRequest(existingRequest.request, getCallingUid());
   2569         }
   2570         handleRegisterNetworkRequest(nri);
   2571     }
   2572 
   2573     private void handleRegisterNetworkRequest(NetworkRequestInfo nri) {
   2574         mNetworkRequests.put(nri.request, nri);
   2575         mNetworkRequestInfoLogs.log("REGISTER " + nri);
   2576         if (nri.request.isListen()) {
   2577             for (NetworkAgentInfo network : mNetworkAgentInfos.values()) {
   2578                 if (nri.request.networkCapabilities.hasSignalStrength() &&
   2579                         network.satisfiesImmutableCapabilitiesOf(nri.request)) {
   2580                     updateSignalStrengthThresholds(network, "REGISTER", nri.request);
   2581                 }
   2582             }
   2583         }
   2584         rematchAllNetworksAndRequests(null, 0);
   2585         if (nri.request.isRequest() && getNetworkForRequest(nri.request.requestId) == null) {
   2586             sendUpdatedScoreToFactories(nri.request, 0);
   2587         }
   2588     }
   2589 
   2590     private void handleReleaseNetworkRequestWithIntent(PendingIntent pendingIntent,
   2591             int callingUid) {
   2592         NetworkRequestInfo nri = findExistingNetworkRequestInfo(pendingIntent);
   2593         if (nri != null) {
   2594             handleReleaseNetworkRequest(nri.request, callingUid);
   2595         }
   2596     }
   2597 
   2598     // Determines whether the network is the best (or could become the best, if it validated), for
   2599     // none of a particular type of NetworkRequests. The type of NetworkRequests considered depends
   2600     // on the value of reason:
   2601     //
   2602     // - UnneededFor.TEARDOWN: non-listen NetworkRequests. If a network is unneeded for this reason,
   2603     //   then it should be torn down.
   2604     // - UnneededFor.LINGER: foreground NetworkRequests. If a network is unneeded for this reason,
   2605     //   then it should be lingered.
   2606     private boolean unneeded(NetworkAgentInfo nai, UnneededFor reason) {
   2607         final int numRequests;
   2608         switch (reason) {
   2609             case TEARDOWN:
   2610                 numRequests = nai.numRequestNetworkRequests();
   2611                 break;
   2612             case LINGER:
   2613                 numRequests = nai.numForegroundNetworkRequests();
   2614                 break;
   2615             default:
   2616                 Slog.wtf(TAG, "Invalid reason. Cannot happen.");
   2617                 return true;
   2618         }
   2619 
   2620         if (!nai.everConnected || nai.isVPN() || nai.isLingering() || numRequests > 0) {
   2621             return false;
   2622         }
   2623         for (NetworkRequestInfo nri : mNetworkRequests.values()) {
   2624             if (reason == UnneededFor.LINGER && nri.request.isBackgroundRequest()) {
   2625                 // Background requests don't affect lingering.
   2626                 continue;
   2627             }
   2628 
   2629             // If this Network is already the highest scoring Network for a request, or if
   2630             // there is hope for it to become one if it validated, then it is needed.
   2631             if (nri.request.isRequest() && nai.satisfies(nri.request) &&
   2632                     (nai.isSatisfyingRequest(nri.request.requestId) ||
   2633                     // Note that this catches two important cases:
   2634                     // 1. Unvalidated cellular will not be reaped when unvalidated WiFi
   2635                     //    is currently satisfying the request.  This is desirable when
   2636                     //    cellular ends up validating but WiFi does not.
   2637                     // 2. Unvalidated WiFi will not be reaped when validated cellular
   2638                     //    is currently satisfying the request.  This is desirable when
   2639                     //    WiFi ends up validating and out scoring cellular.
   2640                     getNetworkForRequest(nri.request.requestId).getCurrentScore() <
   2641                             nai.getCurrentScoreAsValidated())) {
   2642                 return false;
   2643             }
   2644         }
   2645         return true;
   2646     }
   2647 
   2648     private NetworkRequestInfo getNriForAppRequest(
   2649             NetworkRequest request, int callingUid, String requestedOperation) {
   2650         final NetworkRequestInfo nri = mNetworkRequests.get(request);
   2651 
   2652         if (nri != null) {
   2653             if (Process.SYSTEM_UID != callingUid && nri.mUid != callingUid) {
   2654                 log(String.format("UID %d attempted to %s for unowned request %s",
   2655                         callingUid, requestedOperation, nri));
   2656                 return null;
   2657             }
   2658         }
   2659 
   2660         return nri;
   2661     }
   2662 
   2663     private void handleTimedOutNetworkRequest(final NetworkRequestInfo nri) {
   2664         if (mNetworkRequests.get(nri.request) == null) {
   2665             return;
   2666         }
   2667         if (getNetworkForRequest(nri.request.requestId) != null) {
   2668             return;
   2669         }
   2670         if (VDBG || (DBG && nri.request.isRequest())) {
   2671             log("releasing " + nri.request + " (timeout)");
   2672         }
   2673         handleRemoveNetworkRequest(nri);
   2674         callCallbackForRequest(nri, null, ConnectivityManager.CALLBACK_UNAVAIL, 0);
   2675     }
   2676 
   2677     private void handleReleaseNetworkRequest(NetworkRequest request, int callingUid) {
   2678         final NetworkRequestInfo nri =
   2679                 getNriForAppRequest(request, callingUid, "release NetworkRequest");
   2680         if (nri == null) {
   2681             return;
   2682         }
   2683         if (VDBG || (DBG && nri.request.isRequest())) {
   2684             log("releasing " + nri.request + " (release request)");
   2685         }
   2686         handleRemoveNetworkRequest(nri);
   2687     }
   2688 
   2689     private void handleRemoveNetworkRequest(final NetworkRequestInfo nri) {
   2690         nri.unlinkDeathRecipient();
   2691         mNetworkRequests.remove(nri.request);
   2692 
   2693         synchronized (mUidToNetworkRequestCount) {
   2694             int requests = mUidToNetworkRequestCount.get(nri.mUid, 0);
   2695             if (requests < 1) {
   2696                 Slog.wtf(TAG, "BUG: too small request count " + requests + " for UID " +
   2697                         nri.mUid);
   2698             } else if (requests == 1) {
   2699                 mUidToNetworkRequestCount.removeAt(
   2700                         mUidToNetworkRequestCount.indexOfKey(nri.mUid));
   2701             } else {
   2702                 mUidToNetworkRequestCount.put(nri.mUid, requests - 1);
   2703             }
   2704         }
   2705 
   2706         mNetworkRequestInfoLogs.log("RELEASE " + nri);
   2707         if (nri.request.isRequest()) {
   2708             boolean wasKept = false;
   2709             NetworkAgentInfo nai = getNetworkForRequest(nri.request.requestId);
   2710             if (nai != null) {
   2711                 boolean wasBackgroundNetwork = nai.isBackgroundNetwork();
   2712                 nai.removeRequest(nri.request.requestId);
   2713                 if (VDBG) {
   2714                     log(" Removing from current network " + nai.name() +
   2715                             ", leaving " + nai.numNetworkRequests() + " requests.");
   2716                 }
   2717                 // If there are still lingered requests on this network, don't tear it down,
   2718                 // but resume lingering instead.
   2719                 updateLingerState(nai, SystemClock.elapsedRealtime());
   2720                 if (unneeded(nai, UnneededFor.TEARDOWN)) {
   2721                     if (DBG) log("no live requests for " + nai.name() + "; disconnecting");
   2722                     teardownUnneededNetwork(nai);
   2723                 } else {
   2724                     wasKept = true;
   2725                 }
   2726                 clearNetworkForRequest(nri.request.requestId);
   2727                 if (!wasBackgroundNetwork && nai.isBackgroundNetwork()) {
   2728                     // Went from foreground to background.
   2729                     updateCapabilities(nai.getCurrentScore(), nai, nai.networkCapabilities);
   2730                 }
   2731             }
   2732 
   2733             // TODO: remove this code once we know that the Slog.wtf is never hit.
   2734             //
   2735             // Find all networks that are satisfying this request and remove the request
   2736             // from their request lists.
   2737             // TODO - it's my understanding that for a request there is only a single
   2738             // network satisfying it, so this loop is wasteful
   2739             for (NetworkAgentInfo otherNai : mNetworkAgentInfos.values()) {
   2740                 if (otherNai.isSatisfyingRequest(nri.request.requestId) && otherNai != nai) {
   2741                     Slog.wtf(TAG, "Request " + nri.request + " satisfied by " +
   2742                             otherNai.name() + ", but mNetworkAgentInfos says " +
   2743                             (nai != null ? nai.name() : "null"));
   2744                 }
   2745             }
   2746 
   2747             // Maintain the illusion.  When this request arrived, we might have pretended
   2748             // that a network connected to serve it, even though the network was already
   2749             // connected.  Now that this request has gone away, we might have to pretend
   2750             // that the network disconnected.  LegacyTypeTracker will generate that
   2751             // phantom disconnect for this type.
   2752             if (nri.request.legacyType != TYPE_NONE && nai != null) {
   2753                 boolean doRemove = true;
   2754                 if (wasKept) {
   2755                     // check if any of the remaining requests for this network are for the
   2756                     // same legacy type - if so, don't remove the nai
   2757                     for (int i = 0; i < nai.numNetworkRequests(); i++) {
   2758                         NetworkRequest otherRequest = nai.requestAt(i);
   2759                         if (otherRequest.legacyType == nri.request.legacyType &&
   2760                                 otherRequest.isRequest()) {
   2761                             if (DBG) log(" still have other legacy request - leaving");
   2762                             doRemove = false;
   2763                         }
   2764                     }
   2765                 }
   2766 
   2767                 if (doRemove) {
   2768                     mLegacyTypeTracker.remove(nri.request.legacyType, nai, false);
   2769                 }
   2770             }
   2771 
   2772             for (NetworkFactoryInfo nfi : mNetworkFactoryInfos.values()) {
   2773                 nfi.asyncChannel.sendMessage(android.net.NetworkFactory.CMD_CANCEL_REQUEST,
   2774                         nri.request);
   2775             }
   2776         } else {
   2777             // listens don't have a singular affectedNetwork.  Check all networks to see
   2778             // if this listen request applies and remove it.
   2779             for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
   2780                 nai.removeRequest(nri.request.requestId);
   2781                 if (nri.request.networkCapabilities.hasSignalStrength() &&
   2782                         nai.satisfiesImmutableCapabilitiesOf(nri.request)) {
   2783                     updateSignalStrengthThresholds(nai, "RELEASE", nri.request);
   2784                 }
   2785             }
   2786         }
   2787     }
   2788 
   2789     @Override
   2790     public void setAcceptUnvalidated(Network network, boolean accept, boolean always) {
   2791         enforceConnectivityInternalPermission();
   2792         mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_ACCEPT_UNVALIDATED,
   2793                 encodeBool(accept), encodeBool(always), network));
   2794     }
   2795 
   2796     @Override
   2797     public void setAvoidUnvalidated(Network network) {
   2798         enforceConnectivityInternalPermission();
   2799         mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_AVOID_UNVALIDATED, network));
   2800     }
   2801 
   2802     private void handleSetAcceptUnvalidated(Network network, boolean accept, boolean always) {
   2803         if (DBG) log("handleSetAcceptUnvalidated network=" + network +
   2804                 " accept=" + accept + " always=" + always);
   2805 
   2806         NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
   2807         if (nai == null) {
   2808             // Nothing to do.
   2809             return;
   2810         }
   2811 
   2812         if (nai.everValidated) {
   2813             // The network validated while the dialog box was up. Take no action.
   2814             return;
   2815         }
   2816 
   2817         if (!nai.networkMisc.explicitlySelected) {
   2818             Slog.wtf(TAG, "BUG: setAcceptUnvalidated non non-explicitly selected network");
   2819         }
   2820 
   2821         if (accept != nai.networkMisc.acceptUnvalidated) {
   2822             int oldScore = nai.getCurrentScore();
   2823             nai.networkMisc.acceptUnvalidated = accept;
   2824             rematchAllNetworksAndRequests(nai, oldScore);
   2825             sendUpdatedScoreToFactories(nai);
   2826         }
   2827 
   2828         if (always) {
   2829             nai.asyncChannel.sendMessage(
   2830                     NetworkAgent.CMD_SAVE_ACCEPT_UNVALIDATED, encodeBool(accept));
   2831         }
   2832 
   2833         if (!accept) {
   2834             // Tell the NetworkAgent to not automatically reconnect to the network.
   2835             nai.asyncChannel.sendMessage(NetworkAgent.CMD_PREVENT_AUTOMATIC_RECONNECT);
   2836             // Teardown the nework.
   2837             teardownUnneededNetwork(nai);
   2838         }
   2839 
   2840     }
   2841 
   2842     private void handleSetAvoidUnvalidated(Network network) {
   2843         NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
   2844         if (nai == null || nai.lastValidated) {
   2845             // Nothing to do. The network either disconnected or revalidated.
   2846             return;
   2847         }
   2848         if (!nai.avoidUnvalidated) {
   2849             int oldScore = nai.getCurrentScore();
   2850             nai.avoidUnvalidated = true;
   2851             rematchAllNetworksAndRequests(nai, oldScore);
   2852             sendUpdatedScoreToFactories(nai);
   2853         }
   2854     }
   2855 
   2856     private void scheduleUnvalidatedPrompt(NetworkAgentInfo nai) {
   2857         if (VDBG) log("scheduleUnvalidatedPrompt " + nai.network);
   2858         mHandler.sendMessageDelayed(
   2859                 mHandler.obtainMessage(EVENT_PROMPT_UNVALIDATED, nai.network),
   2860                 PROMPT_UNVALIDATED_DELAY_MS);
   2861     }
   2862 
   2863     @Override
   2864     public void startCaptivePortalApp(Network network) {
   2865         enforceConnectivityInternalPermission();
   2866         mHandler.post(() -> {
   2867             NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
   2868             if (nai == null) return;
   2869             if (!nai.networkCapabilities.hasCapability(NET_CAPABILITY_CAPTIVE_PORTAL)) return;
   2870             nai.networkMonitor.sendMessage(NetworkMonitor.CMD_LAUNCH_CAPTIVE_PORTAL_APP);
   2871         });
   2872     }
   2873 
   2874     public boolean avoidBadWifi() {
   2875         return mMultinetworkPolicyTracker.getAvoidBadWifi();
   2876     }
   2877 
   2878     private void rematchForAvoidBadWifiUpdate() {
   2879         rematchAllNetworksAndRequests(null, 0);
   2880         for (NetworkAgentInfo nai: mNetworkAgentInfos.values()) {
   2881             if (nai.networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
   2882                 sendUpdatedScoreToFactories(nai);
   2883             }
   2884         }
   2885     }
   2886 
   2887     // TODO: Evaluate whether this is of interest to other consumers of
   2888     // MultinetworkPolicyTracker and worth moving out of here.
   2889     private void dumpAvoidBadWifiSettings(IndentingPrintWriter pw) {
   2890         final boolean configRestrict = mMultinetworkPolicyTracker.configRestrictsAvoidBadWifi();
   2891         if (!configRestrict) {
   2892             pw.println("Bad Wi-Fi avoidance: unrestricted");
   2893             return;
   2894         }
   2895 
   2896         pw.println("Bad Wi-Fi avoidance: " + avoidBadWifi());
   2897         pw.increaseIndent();
   2898         pw.println("Config restrict:   " + configRestrict);
   2899 
   2900         final String value = mMultinetworkPolicyTracker.getAvoidBadWifiSetting();
   2901         String description;
   2902         // Can't use a switch statement because strings are legal case labels, but null is not.
   2903         if ("0".equals(value)) {
   2904             description = "get stuck";
   2905         } else if (value == null) {
   2906             description = "prompt";
   2907         } else if ("1".equals(value)) {
   2908             description = "avoid";
   2909         } else {
   2910             description = value + " (?)";
   2911         }
   2912         pw.println("User setting:      " + description);
   2913         pw.println("Network overrides:");
   2914         pw.increaseIndent();
   2915         for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
   2916             if (nai.avoidUnvalidated) {
   2917                 pw.println(nai.name());
   2918             }
   2919         }
   2920         pw.decreaseIndent();
   2921         pw.decreaseIndent();
   2922     }
   2923 
   2924     private void showValidationNotification(NetworkAgentInfo nai, NotificationType type) {
   2925         final String action;
   2926         switch (type) {
   2927             case NO_INTERNET:
   2928                 action = ConnectivityManager.ACTION_PROMPT_UNVALIDATED;
   2929                 break;
   2930             case LOST_INTERNET:
   2931                 action = ConnectivityManager.ACTION_PROMPT_LOST_VALIDATION;
   2932                 break;
   2933             default:
   2934                 Slog.wtf(TAG, "Unknown notification type " + type);
   2935                 return;
   2936         }
   2937 
   2938         Intent intent = new Intent(action);
   2939         intent.setData(Uri.fromParts("netId", Integer.toString(nai.network.netId), null));
   2940         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
   2941         intent.setClassName("com.android.settings",
   2942                 "com.android.settings.wifi.WifiNoInternetDialog");
   2943 
   2944         PendingIntent pendingIntent = PendingIntent.getActivityAsUser(
   2945                 mContext, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT, null, UserHandle.CURRENT);
   2946         mNotifier.showNotification(nai.network.netId, type, nai, null, pendingIntent, true);
   2947     }
   2948 
   2949     private void handlePromptUnvalidated(Network network) {
   2950         if (VDBG) log("handlePromptUnvalidated " + network);
   2951         NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
   2952 
   2953         // Only prompt if the network is unvalidated and was explicitly selected by the user, and if
   2954         // we haven't already been told to switch to it regardless of whether it validated or not.
   2955         // Also don't prompt on captive portals because we're already prompting the user to sign in.
   2956         if (nai == null || nai.everValidated || nai.everCaptivePortalDetected ||
   2957                 !nai.networkMisc.explicitlySelected || nai.networkMisc.acceptUnvalidated) {
   2958             return;
   2959         }
   2960         showValidationNotification(nai, NotificationType.NO_INTERNET);
   2961     }
   2962 
   2963     private void handleNetworkUnvalidated(NetworkAgentInfo nai) {
   2964         NetworkCapabilities nc = nai.networkCapabilities;
   2965         if (DBG) log("handleNetworkUnvalidated " + nai.name() + " cap=" + nc);
   2966 
   2967         if (nc.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) &&
   2968             mMultinetworkPolicyTracker.shouldNotifyWifiUnvalidated()) {
   2969             showValidationNotification(nai, NotificationType.LOST_INTERNET);
   2970         }
   2971     }
   2972 
   2973     @Override
   2974     public int getMultipathPreference(Network network) {
   2975         enforceAccessPermission();
   2976 
   2977         NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
   2978         if (nai != null && nai.networkCapabilities
   2979                 .hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED)) {
   2980             return ConnectivityManager.MULTIPATH_PREFERENCE_UNMETERED;
   2981         }
   2982 
   2983         Integer networkPreference = mMultipathPolicyTracker.getMultipathPreference(network);
   2984         if (networkPreference != null) {
   2985             return networkPreference;
   2986         }
   2987 
   2988         return mMultinetworkPolicyTracker.getMeteredMultipathPreference();
   2989     }
   2990 
   2991     private class InternalHandler extends Handler {
   2992         public InternalHandler(Looper looper) {
   2993             super(looper);
   2994         }
   2995 
   2996         @Override
   2997         public void handleMessage(Message msg) {
   2998             switch (msg.what) {
   2999                 case EVENT_EXPIRE_NET_TRANSITION_WAKELOCK:
   3000                 case EVENT_CLEAR_NET_TRANSITION_WAKELOCK: {
   3001                     handleReleaseNetworkTransitionWakelock(msg.what);
   3002                     break;
   3003                 }
   3004                 case EVENT_APPLY_GLOBAL_HTTP_PROXY: {
   3005                     handleDeprecatedGlobalHttpProxy();
   3006                     break;
   3007                 }
   3008                 case EVENT_PROXY_HAS_CHANGED: {
   3009                     handleApplyDefaultProxy((ProxyInfo)msg.obj);
   3010                     break;
   3011                 }
   3012                 case EVENT_REGISTER_NETWORK_FACTORY: {
   3013                     handleRegisterNetworkFactory((NetworkFactoryInfo)msg.obj);
   3014                     break;
   3015                 }
   3016                 case EVENT_UNREGISTER_NETWORK_FACTORY: {
   3017                     handleUnregisterNetworkFactory((Messenger)msg.obj);
   3018                     break;
   3019                 }
   3020                 case EVENT_REGISTER_NETWORK_AGENT: {
   3021                     handleRegisterNetworkAgent((NetworkAgentInfo)msg.obj);
   3022                     break;
   3023                 }
   3024                 case EVENT_REGISTER_NETWORK_REQUEST:
   3025                 case EVENT_REGISTER_NETWORK_LISTENER: {
   3026                     handleRegisterNetworkRequest((NetworkRequestInfo) msg.obj);
   3027                     break;
   3028                 }
   3029                 case EVENT_REGISTER_NETWORK_REQUEST_WITH_INTENT:
   3030                 case EVENT_REGISTER_NETWORK_LISTENER_WITH_INTENT: {
   3031                     handleRegisterNetworkRequestWithIntent(msg);
   3032                     break;
   3033                 }
   3034                 case EVENT_TIMEOUT_NETWORK_REQUEST: {
   3035                     NetworkRequestInfo nri = (NetworkRequestInfo) msg.obj;
   3036                     handleTimedOutNetworkRequest(nri);
   3037                     break;
   3038                 }
   3039                 case EVENT_RELEASE_NETWORK_REQUEST_WITH_INTENT: {
   3040                     handleReleaseNetworkRequestWithIntent((PendingIntent) msg.obj, msg.arg1);
   3041                     break;
   3042                 }
   3043                 case EVENT_RELEASE_NETWORK_REQUEST: {
   3044                     handleReleaseNetworkRequest((NetworkRequest) msg.obj, msg.arg1);
   3045                     break;
   3046                 }
   3047                 case EVENT_SET_ACCEPT_UNVALIDATED: {
   3048                     Network network = (Network) msg.obj;
   3049                     handleSetAcceptUnvalidated(network, toBool(msg.arg1), toBool(msg.arg2));
   3050                     break;
   3051                 }
   3052                 case EVENT_SET_AVOID_UNVALIDATED: {
   3053                     handleSetAvoidUnvalidated((Network) msg.obj);
   3054                     break;
   3055                 }
   3056                 case EVENT_PROMPT_UNVALIDATED: {
   3057                     handlePromptUnvalidated((Network) msg.obj);
   3058                     break;
   3059                 }
   3060                 case EVENT_CONFIGURE_MOBILE_DATA_ALWAYS_ON: {
   3061                     handleMobileDataAlwaysOn();
   3062                     break;
   3063                 }
   3064                 // Sent by KeepaliveTracker to process an app request on the state machine thread.
   3065                 case NetworkAgent.CMD_START_PACKET_KEEPALIVE: {
   3066                     mKeepaliveTracker.handleStartKeepalive(msg);
   3067                     break;
   3068                 }
   3069                 // Sent by KeepaliveTracker to process an app request on the state machine thread.
   3070                 case NetworkAgent.CMD_STOP_PACKET_KEEPALIVE: {
   3071                     NetworkAgentInfo nai = getNetworkAgentInfoForNetwork((Network) msg.obj);
   3072                     int slot = msg.arg1;
   3073                     int reason = msg.arg2;
   3074                     mKeepaliveTracker.handleStopKeepalive(nai, slot, reason);
   3075                     break;
   3076                 }
   3077                 case EVENT_SYSTEM_READY: {
   3078                     for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
   3079                         nai.networkMonitor.systemReady = true;
   3080                     }
   3081                     mMultipathPolicyTracker.start();
   3082                     break;
   3083                 }
   3084                 case EVENT_REVALIDATE_NETWORK: {
   3085                     handleReportNetworkConnectivity((Network) msg.obj, msg.arg1, toBool(msg.arg2));
   3086                     break;
   3087                 }
   3088                 case EVENT_PRIVATE_DNS_SETTINGS_CHANGED:
   3089                     handlePrivateDnsSettingsChanged();
   3090                     break;
   3091                 case EVENT_PRIVATE_DNS_VALIDATION_UPDATE:
   3092                     handlePrivateDnsValidationUpdate(
   3093                             (PrivateDnsValidationUpdate) msg.obj);
   3094                     break;
   3095             }
   3096         }
   3097     }
   3098 
   3099     // javadoc from interface
   3100     @Override
   3101     public int tether(String iface, String callerPkg) {
   3102         ConnectivityManager.enforceTetherChangePermission(mContext, callerPkg);
   3103         if (isTetheringSupported()) {
   3104             final int status = mTethering.tether(iface);
   3105             return status;
   3106         } else {
   3107             return ConnectivityManager.TETHER_ERROR_UNSUPPORTED;
   3108         }
   3109     }
   3110 
   3111     // javadoc from interface
   3112     @Override
   3113     public int untether(String iface, String callerPkg) {
   3114         ConnectivityManager.enforceTetherChangePermission(mContext, callerPkg);
   3115 
   3116         if (isTetheringSupported()) {
   3117             final int status = mTethering.untether(iface);
   3118             return status;
   3119         } else {
   3120             return ConnectivityManager.TETHER_ERROR_UNSUPPORTED;
   3121         }
   3122     }
   3123 
   3124     // javadoc from interface
   3125     @Override
   3126     public int getLastTetherError(String iface) {
   3127         enforceTetherAccessPermission();
   3128 
   3129         if (isTetheringSupported()) {
   3130             return mTethering.getLastTetherError(iface);
   3131         } else {
   3132             return ConnectivityManager.TETHER_ERROR_UNSUPPORTED;
   3133         }
   3134     }
   3135 
   3136     // TODO - proper iface API for selection by property, inspection, etc
   3137     @Override
   3138     public String[] getTetherableUsbRegexs() {
   3139         enforceTetherAccessPermission();
   3140         if (isTetheringSupported()) {
   3141             return mTethering.getTetherableUsbRegexs();
   3142         } else {
   3143             return new String[0];
   3144         }
   3145     }
   3146 
   3147     @Override
   3148     public String[] getTetherableWifiRegexs() {
   3149         enforceTetherAccessPermission();
   3150         if (isTetheringSupported()) {
   3151             return mTethering.getTetherableWifiRegexs();
   3152         } else {
   3153             return new String[0];
   3154         }
   3155     }
   3156 
   3157     @Override
   3158     public String[] getTetherableBluetoothRegexs() {
   3159         enforceTetherAccessPermission();
   3160         if (isTetheringSupported()) {
   3161             return mTethering.getTetherableBluetoothRegexs();
   3162         } else {
   3163             return new String[0];
   3164         }
   3165     }
   3166 
   3167     @Override
   3168     public int setUsbTethering(boolean enable, String callerPkg) {
   3169         ConnectivityManager.enforceTetherChangePermission(mContext, callerPkg);
   3170         if (isTetheringSupported()) {
   3171             return mTethering.setUsbTethering(enable);
   3172         } else {
   3173             return ConnectivityManager.TETHER_ERROR_UNSUPPORTED;
   3174         }
   3175     }
   3176 
   3177     // TODO - move iface listing, queries, etc to new module
   3178     // javadoc from interface
   3179     @Override
   3180     public String[] getTetherableIfaces() {
   3181         enforceTetherAccessPermission();
   3182         return mTethering.getTetherableIfaces();
   3183     }
   3184 
   3185     @Override
   3186     public String[] getTetheredIfaces() {
   3187         enforceTetherAccessPermission();
   3188         return mTethering.getTetheredIfaces();
   3189     }
   3190 
   3191     @Override
   3192     public String[] getTetheringErroredIfaces() {
   3193         enforceTetherAccessPermission();
   3194         return mTethering.getErroredIfaces();
   3195     }
   3196 
   3197     @Override
   3198     public String[] getTetheredDhcpRanges() {
   3199         enforceConnectivityInternalPermission();
   3200         return mTethering.getTetheredDhcpRanges();
   3201     }
   3202 
   3203     @Override
   3204     public boolean isTetheringSupported(String callerPkg) {
   3205         ConnectivityManager.enforceTetherChangePermission(mContext, callerPkg);
   3206         return isTetheringSupported();
   3207     }
   3208 
   3209     // if ro.tether.denied = true we default to no tethering
   3210     // gservices could set the secure setting to 1 though to enable it on a build where it
   3211     // had previously been turned off.
   3212     private boolean isTetheringSupported() {
   3213         int defaultVal = encodeBool(!mSystemProperties.get("ro.tether.denied").equals("true"));
   3214         boolean tetherSupported = toBool(Settings.Global.getInt(mContext.getContentResolver(),
   3215                 Settings.Global.TETHER_SUPPORTED, defaultVal));
   3216         boolean tetherEnabledInSettings = tetherSupported
   3217                 && !mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_TETHERING);
   3218 
   3219         // Elevate to system UID to avoid caller requiring MANAGE_USERS permission.
   3220         boolean adminUser = false;
   3221         final long token = Binder.clearCallingIdentity();
   3222         try {
   3223             adminUser = mUserManager.isAdminUser();
   3224         } finally {
   3225             Binder.restoreCallingIdentity(token);
   3226         }
   3227 
   3228         return tetherEnabledInSettings && adminUser && mTethering.hasTetherableConfiguration();
   3229     }
   3230 
   3231     @Override
   3232     public void startTethering(int type, ResultReceiver receiver, boolean showProvisioningUi,
   3233             String callerPkg) {
   3234         ConnectivityManager.enforceTetherChangePermission(mContext, callerPkg);
   3235         if (!isTetheringSupported()) {
   3236             receiver.send(ConnectivityManager.TETHER_ERROR_UNSUPPORTED, null);
   3237             return;
   3238         }
   3239         mTethering.startTethering(type, receiver, showProvisioningUi);
   3240     }
   3241 
   3242     @Override
   3243     public void stopTethering(int type, String callerPkg) {
   3244         ConnectivityManager.enforceTetherChangePermission(mContext, callerPkg);
   3245         mTethering.stopTethering(type);
   3246     }
   3247 
   3248     // Called when we lose the default network and have no replacement yet.
   3249     // This will automatically be cleared after X seconds or a new default network
   3250     // becomes CONNECTED, whichever happens first.  The timer is started by the
   3251     // first caller and not restarted by subsequent callers.
   3252     private void ensureNetworkTransitionWakelock(String forWhom) {
   3253         synchronized (this) {
   3254             if (mNetTransitionWakeLock.isHeld()) {
   3255                 return;
   3256             }
   3257             mNetTransitionWakeLock.acquire();
   3258             mLastWakeLockAcquireTimestamp = SystemClock.elapsedRealtime();
   3259             mTotalWakelockAcquisitions++;
   3260         }
   3261         mWakelockLogs.log("ACQUIRE for " + forWhom);
   3262         Message msg = mHandler.obtainMessage(EVENT_EXPIRE_NET_TRANSITION_WAKELOCK);
   3263         mHandler.sendMessageDelayed(msg, mNetTransitionWakeLockTimeout);
   3264     }
   3265 
   3266     // Called when we gain a new default network to release the network transition wakelock in a
   3267     // second, to allow a grace period for apps to reconnect over the new network. Pending expiry
   3268     // message is cancelled.
   3269     private void scheduleReleaseNetworkTransitionWakelock() {
   3270         synchronized (this) {
   3271             if (!mNetTransitionWakeLock.isHeld()) {
   3272                 return; // expiry message released the lock first.
   3273             }
   3274         }
   3275         // Cancel self timeout on wakelock hold.
   3276         mHandler.removeMessages(EVENT_EXPIRE_NET_TRANSITION_WAKELOCK);
   3277         Message msg = mHandler.obtainMessage(EVENT_CLEAR_NET_TRANSITION_WAKELOCK);
   3278         mHandler.sendMessageDelayed(msg, 1000);
   3279     }
   3280 
   3281     // Called when either message of ensureNetworkTransitionWakelock or
   3282     // scheduleReleaseNetworkTransitionWakelock is processed.
   3283     private void handleReleaseNetworkTransitionWakelock(int eventId) {
   3284         String event = eventName(eventId);
   3285         synchronized (this) {
   3286             if (!mNetTransitionWakeLock.isHeld()) {
   3287                 mWakelockLogs.log(String.format("RELEASE: already released (%s)", event));
   3288                 Slog.w(TAG, "expected Net Transition WakeLock to be held");
   3289                 return;
   3290             }
   3291             mNetTransitionWakeLock.release();
   3292             long lockDuration = SystemClock.elapsedRealtime() - mLastWakeLockAcquireTimestamp;
   3293             mTotalWakelockDurationMs += lockDuration;
   3294             mMaxWakelockDurationMs = Math.max(mMaxWakelockDurationMs, lockDuration);
   3295             mTotalWakelockReleases++;
   3296         }
   3297         mWakelockLogs.log(String.format("RELEASE (%s)", event));
   3298     }
   3299 
   3300     // 100 percent is full good, 0 is full bad.
   3301     @Override
   3302     public void reportInetCondition(int networkType, int percentage) {
   3303         NetworkAgentInfo nai = mLegacyTypeTracker.getNetworkForType(networkType);
   3304         if (nai == null) return;
   3305         reportNetworkConnectivity(nai.network, percentage > 50);
   3306     }
   3307 
   3308     @Override
   3309     public void reportNetworkConnectivity(Network network, boolean hasConnectivity) {
   3310         enforceAccessPermission();
   3311         enforceInternetPermission();
   3312         final int uid = Binder.getCallingUid();
   3313         final int connectivityInfo = encodeBool(hasConnectivity);
   3314         mHandler.sendMessage(
   3315                 mHandler.obtainMessage(EVENT_REVALIDATE_NETWORK, uid, connectivityInfo, network));
   3316     }
   3317 
   3318     private void handleReportNetworkConnectivity(
   3319             Network network, int uid, boolean hasConnectivity) {
   3320         final NetworkAgentInfo nai;
   3321         if (network == null) {
   3322             nai = getDefaultNetwork();
   3323         } else {
   3324             nai = getNetworkAgentInfoForNetwork(network);
   3325         }
   3326         if (nai == null || nai.networkInfo.getState() == NetworkInfo.State.DISCONNECTING ||
   3327             nai.networkInfo.getState() == NetworkInfo.State.DISCONNECTED) {
   3328             return;
   3329         }
   3330         // Revalidate if the app report does not match our current validated state.
   3331         if (hasConnectivity == nai.lastValidated) {
   3332             return;
   3333         }
   3334         if (DBG) {
   3335             int netid = nai.network.netId;
   3336             log("reportNetworkConnectivity(" + netid + ", " + hasConnectivity + ") by " + uid);
   3337         }
   3338         // Validating a network that has not yet connected could result in a call to
   3339         // rematchNetworkAndRequests() which is not meant to work on such networks.
   3340         if (!nai.everConnected) {
   3341             return;
   3342         }
   3343         LinkProperties lp = getLinkProperties(nai);
   3344         if (isNetworkWithLinkPropertiesBlocked(lp, uid, false)) {
   3345             return;
   3346         }
   3347         nai.networkMonitor.forceReevaluation(uid);
   3348     }
   3349 
   3350     private ProxyInfo getDefaultProxy() {
   3351         // this information is already available as a world read/writable jvm property
   3352         // so this API change wouldn't have a benifit.  It also breaks the passing
   3353         // of proxy info to all the JVMs.
   3354         // enforceAccessPermission();
   3355         synchronized (mProxyLock) {
   3356             ProxyInfo ret = mGlobalProxy;
   3357             if ((ret == null) && !mDefaultProxyDisabled) ret = mDefaultProxy;
   3358             return ret;
   3359         }
   3360     }
   3361 
   3362     @Override
   3363     public ProxyInfo getProxyForNetwork(Network network) {
   3364         if (network == null) return getDefaultProxy();
   3365         final ProxyInfo globalProxy = getGlobalProxy();
   3366         if (globalProxy != null) return globalProxy;
   3367         if (!NetworkUtils.queryUserAccess(Binder.getCallingUid(), network.netId)) return null;
   3368         // Don't call getLinkProperties() as it requires ACCESS_NETWORK_STATE permission, which
   3369         // caller may not have.
   3370         final NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
   3371         if (nai == null) return null;
   3372         synchronized (nai) {
   3373             final ProxyInfo proxyInfo = nai.linkProperties.getHttpProxy();
   3374             if (proxyInfo == null) return null;
   3375             return new ProxyInfo(proxyInfo);
   3376         }
   3377     }
   3378 
   3379     // Convert empty ProxyInfo's to null as null-checks are used to determine if proxies are present
   3380     // (e.g. if mGlobalProxy==null fall back to network-specific proxy, if network-specific
   3381     // proxy is null then there is no proxy in place).
   3382     private ProxyInfo canonicalizeProxyInfo(ProxyInfo proxy) {
   3383         if (proxy != null && TextUtils.isEmpty(proxy.getHost())
   3384                 && (proxy.getPacFileUrl() == null || Uri.EMPTY.equals(proxy.getPacFileUrl()))) {
   3385             proxy = null;
   3386         }
   3387         return proxy;
   3388     }
   3389 
   3390     // ProxyInfo equality function with a couple modifications over ProxyInfo.equals() to make it
   3391     // better for determining if a new proxy broadcast is necessary:
   3392     // 1. Canonicalize empty ProxyInfos to null so an empty proxy compares equal to null so as to
   3393     //    avoid unnecessary broadcasts.
   3394     // 2. Make sure all parts of the ProxyInfo's compare true, including the host when a PAC URL
   3395     //    is in place.  This is important so legacy PAC resolver (see com.android.proxyhandler)
   3396     //    changes aren't missed.  The legacy PAC resolver pretends to be a simple HTTP proxy but
   3397     //    actually uses the PAC to resolve; this results in ProxyInfo's with PAC URL, host and port
   3398     //    all set.
   3399     private boolean proxyInfoEqual(ProxyInfo a, ProxyInfo b) {
   3400         a = canonicalizeProxyInfo(a);
   3401         b = canonicalizeProxyInfo(b);
   3402         // ProxyInfo.equals() doesn't check hosts when PAC URLs are present, but we need to check
   3403         // hosts even when PAC URLs are present to account for the legacy PAC resolver.
   3404         return Objects.equals(a, b) && (a == null || Objects.equals(a.getHost(), b.getHost()));
   3405     }
   3406 
   3407     public void setGlobalProxy(ProxyInfo proxyProperties) {
   3408         enforceConnectivityInternalPermission();
   3409 
   3410         synchronized (mProxyLock) {
   3411             if (proxyProperties == mGlobalProxy) return;
   3412             if (proxyProperties != null && proxyProperties.equals(mGlobalProxy)) return;
   3413             if (mGlobalProxy != null && mGlobalProxy.equals(proxyProperties)) return;
   3414 
   3415             String host = "";
   3416             int port = 0;
   3417             String exclList = "";
   3418             String pacFileUrl = "";
   3419             if (proxyProperties != null && (!TextUtils.isEmpty(proxyProperties.getHost()) ||
   3420                     !Uri.EMPTY.equals(proxyProperties.getPacFileUrl()))) {
   3421                 if (!proxyProperties.isValid()) {
   3422                     if (DBG)
   3423                         log("Invalid proxy properties, ignoring: " + proxyProperties.toString());
   3424                     return;
   3425                 }
   3426                 mGlobalProxy = new ProxyInfo(proxyProperties);
   3427                 host = mGlobalProxy.getHost();
   3428                 port = mGlobalProxy.getPort();
   3429                 exclList = mGlobalProxy.getExclusionListAsString();
   3430                 if (!Uri.EMPTY.equals(proxyProperties.getPacFileUrl())) {
   3431                     pacFileUrl = proxyProperties.getPacFileUrl().toString();
   3432                 }
   3433             } else {
   3434                 mGlobalProxy = null;
   3435             }
   3436             ContentResolver res = mContext.getContentResolver();
   3437             final long token = Binder.clearCallingIdentity();
   3438             try {
   3439                 Settings.Global.putString(res, Settings.Global.GLOBAL_HTTP_PROXY_HOST, host);
   3440                 Settings.Global.putInt(res, Settings.Global.GLOBAL_HTTP_PROXY_PORT, port);
   3441                 Settings.Global.putString(res, Settings.Global.GLOBAL_HTTP_PROXY_EXCLUSION_LIST,
   3442                         exclList);
   3443                 Settings.Global.putString(res, Settings.Global.GLOBAL_HTTP_PROXY_PAC, pacFileUrl);
   3444             } finally {
   3445                 Binder.restoreCallingIdentity(token);
   3446             }
   3447 
   3448             if (mGlobalProxy == null) {
   3449                 proxyProperties = mDefaultProxy;
   3450             }
   3451             sendProxyBroadcast(proxyProperties);
   3452         }
   3453     }
   3454 
   3455     private void loadGlobalProxy() {
   3456         ContentResolver res = mContext.getContentResolver();
   3457         String host = Settings.Global.getString(res, Settings.Global.GLOBAL_HTTP_PROXY_HOST);
   3458         int port = Settings.Global.getInt(res, Settings.Global.GLOBAL_HTTP_PROXY_PORT, 0);
   3459         String exclList = Settings.Global.getString(res,
   3460                 Settings.Global.GLOBAL_HTTP_PROXY_EXCLUSION_LIST);
   3461         String pacFileUrl = Settings.Global.getString(res, Settings.Global.GLOBAL_HTTP_PROXY_PAC);
   3462         if (!TextUtils.isEmpty(host) || !TextUtils.isEmpty(pacFileUrl)) {
   3463             ProxyInfo proxyProperties;
   3464             if (!TextUtils.isEmpty(pacFileUrl)) {
   3465                 proxyProperties = new ProxyInfo(pacFileUrl);
   3466             } else {
   3467                 proxyProperties = new ProxyInfo(host, port, exclList);
   3468             }
   3469             if (!proxyProperties.isValid()) {
   3470                 if (DBG) log("Invalid proxy properties, ignoring: " + proxyProperties.toString());
   3471                 return;
   3472             }
   3473 
   3474             synchronized (mProxyLock) {
   3475                 mGlobalProxy = proxyProperties;
   3476             }
   3477         }
   3478     }
   3479 
   3480     public ProxyInfo getGlobalProxy() {
   3481         // this information is already available as a world read/writable jvm property
   3482         // so this API change wouldn't have a benifit.  It also breaks the passing
   3483         // of proxy info to all the JVMs.
   3484         // enforceAccessPermission();
   3485         synchronized (mProxyLock) {
   3486             return mGlobalProxy;
   3487         }
   3488     }
   3489 
   3490     private void handleApplyDefaultProxy(ProxyInfo proxy) {
   3491         if (proxy != null && TextUtils.isEmpty(proxy.getHost())
   3492                 && Uri.EMPTY.equals(proxy.getPacFileUrl())) {
   3493             proxy = null;
   3494         }
   3495         synchronized (mProxyLock) {
   3496             if (mDefaultProxy != null && mDefaultProxy.equals(proxy)) return;
   3497             if (mDefaultProxy == proxy) return; // catches repeated nulls
   3498             if (proxy != null &&  !proxy.isValid()) {
   3499                 if (DBG) log("Invalid proxy properties, ignoring: " + proxy.toString());
   3500                 return;
   3501             }
   3502 
   3503             // This call could be coming from the PacManager, containing the port of the local
   3504             // proxy.  If this new proxy matches the global proxy then copy this proxy to the
   3505             // global (to get the correct local port), and send a broadcast.
   3506             // TODO: Switch PacManager to have its own message to send back rather than
   3507             // reusing EVENT_HAS_CHANGED_PROXY and this call to handleApplyDefaultProxy.
   3508             if ((mGlobalProxy != null) && (proxy != null)
   3509                     && (!Uri.EMPTY.equals(proxy.getPacFileUrl()))
   3510                     && proxy.getPacFileUrl().equals(mGlobalProxy.getPacFileUrl())) {
   3511                 mGlobalProxy = proxy;
   3512                 sendProxyBroadcast(mGlobalProxy);
   3513                 return;
   3514             }
   3515             mDefaultProxy = proxy;
   3516 
   3517             if (mGlobalProxy != null) return;
   3518             if (!mDefaultProxyDisabled) {
   3519                 sendProxyBroadcast(proxy);
   3520             }
   3521         }
   3522     }
   3523 
   3524     // If the proxy has changed from oldLp to newLp, resend proxy broadcast with default proxy.
   3525     // This method gets called when any network changes proxy, but the broadcast only ever contains
   3526     // the default proxy (even if it hasn't changed).
   3527     // TODO: Deprecate the broadcast extras as they aren't necessarily applicable in a multi-network
   3528     // world where an app might be bound to a non-default network.
   3529     private void updateProxy(LinkProperties newLp, LinkProperties oldLp, NetworkAgentInfo nai) {
   3530         ProxyInfo newProxyInfo = newLp == null ? null : newLp.getHttpProxy();
   3531         ProxyInfo oldProxyInfo = oldLp == null ? null : oldLp.getHttpProxy();
   3532 
   3533         if (!proxyInfoEqual(newProxyInfo, oldProxyInfo)) {
   3534             sendProxyBroadcast(getDefaultProxy());
   3535         }
   3536     }
   3537 
   3538     private void handleDeprecatedGlobalHttpProxy() {
   3539         String proxy = Settings.Global.getString(mContext.getContentResolver(),
   3540                 Settings.Global.HTTP_PROXY);
   3541         if (!TextUtils.isEmpty(proxy)) {
   3542             String data[] = proxy.split(":");
   3543             if (data.length == 0) {
   3544                 return;
   3545             }
   3546 
   3547             String proxyHost =  data[0];
   3548             int proxyPort = 8080;
   3549             if (data.length > 1) {
   3550                 try {
   3551                     proxyPort = Integer.parseInt(data[1]);
   3552                 } catch (NumberFormatException e) {
   3553                     return;
   3554                 }
   3555             }
   3556             ProxyInfo p = new ProxyInfo(data[0], proxyPort, "");
   3557             setGlobalProxy(p);
   3558         }
   3559     }
   3560 
   3561     private void sendProxyBroadcast(ProxyInfo proxy) {
   3562         if (proxy == null) proxy = new ProxyInfo("", 0, "");
   3563         if (mPacManager.setCurrentProxyScriptUrl(proxy)) return;
   3564         if (DBG) log("sending Proxy Broadcast for " + proxy);
   3565         Intent intent = new Intent(Proxy.PROXY_CHANGE_ACTION);
   3566         intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING |
   3567             Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
   3568         intent.putExtra(Proxy.EXTRA_PROXY_INFO, proxy);
   3569         final long ident = Binder.clearCallingIdentity();
   3570         try {
   3571             mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
   3572         } finally {
   3573             Binder.restoreCallingIdentity(ident);
   3574         }
   3575     }
   3576 
   3577     private static class SettingsObserver extends ContentObserver {
   3578         final private HashMap<Uri, Integer> mUriEventMap;
   3579         final private Context mContext;
   3580         final private Handler mHandler;
   3581 
   3582         SettingsObserver(Context context, Handler handler) {
   3583             super(null);
   3584             mUriEventMap = new HashMap<Uri, Integer>();
   3585             mContext = context;
   3586             mHandler = handler;
   3587         }
   3588 
   3589         void observe(Uri uri, int what) {
   3590             mUriEventMap.put(uri, what);
   3591             final ContentResolver resolver = mContext.getContentResolver();
   3592             resolver.registerContentObserver(uri, false, this);
   3593         }
   3594 
   3595         @Override
   3596         public void onChange(boolean selfChange) {
   3597             Slog.wtf(TAG, "Should never be reached.");
   3598         }
   3599 
   3600         @Override
   3601         public void onChange(boolean selfChange, Uri uri) {
   3602             final Integer what = mUriEventMap.get(uri);
   3603             if (what != null) {
   3604                 mHandler.obtainMessage(what.intValue()).sendToTarget();
   3605             } else {
   3606                 loge("No matching event to send for URI=" + uri);
   3607             }
   3608         }
   3609     }
   3610 
   3611     private static void log(String s) {
   3612         Slog.d(TAG, s);
   3613     }
   3614 
   3615     private static void loge(String s) {
   3616         Slog.e(TAG, s);
   3617     }
   3618 
   3619     private static void loge(String s, Throwable t) {
   3620         Slog.e(TAG, s, t);
   3621     }
   3622 
   3623     /**
   3624      * Prepare for a VPN application.
   3625      * VPN permissions are checked in the {@link Vpn} class. If the caller is not {@code userId},
   3626      * {@link android.Manifest.permission.INTERACT_ACROSS_USERS_FULL} permission is required.
   3627      *
   3628      * @param oldPackage Package name of the application which currently controls VPN, which will
   3629      *                   be replaced. If there is no such application, this should should either be
   3630      *                   {@code null} or {@link VpnConfig.LEGACY_VPN}.
   3631      * @param newPackage Package name of the application which should gain control of VPN, or
   3632      *                   {@code null} to disable.
   3633      * @param userId User for whom to prepare the new VPN.
   3634      *
   3635      * @hide
   3636      */
   3637     @Override
   3638     public boolean prepareVpn(@Nullable String oldPackage, @Nullable String newPackage,
   3639             int userId) {
   3640         enforceCrossUserPermission(userId);
   3641 
   3642         synchronized (mVpns) {
   3643             throwIfLockdownEnabled();
   3644             Vpn vpn = mVpns.get(userId);
   3645             if (vpn != null) {
   3646                 return vpn.prepare(oldPackage, newPackage);
   3647             } else {
   3648                 return false;
   3649             }
   3650         }
   3651     }
   3652 
   3653     /**
   3654      * Set whether the VPN package has the ability to launch VPNs without user intervention.
   3655      * This method is used by system-privileged apps.
   3656      * VPN permissions are checked in the {@link Vpn} class. If the caller is not {@code userId},
   3657      * {@link android.Manifest.permission.INTERACT_ACROSS_USERS_FULL} permission is required.
   3658      *
   3659      * @param packageName The package for which authorization state should change.
   3660      * @param userId User for whom {@code packageName} is installed.
   3661      * @param authorized {@code true} if this app should be able to start a VPN connection without
   3662      *                   explicit user approval, {@code false} if not.
   3663      *
   3664      * @hide
   3665      */
   3666     @Override
   3667     public void setVpnPackageAuthorization(String packageName, int userId, boolean authorized) {
   3668         enforceCrossUserPermission(userId);
   3669 
   3670         synchronized (mVpns) {
   3671             Vpn vpn = mVpns.get(userId);
   3672             if (vpn != null) {
   3673                 vpn.setPackageAuthorization(packageName, authorized);
   3674             }
   3675         }
   3676     }
   3677 
   3678     /**
   3679      * Configure a TUN interface and return its file descriptor. Parameters
   3680      * are encoded and opaque to this class. This method is used by VpnBuilder
   3681      * and not available in ConnectivityManager. Permissions are checked in
   3682      * Vpn class.
   3683      * @hide
   3684      */
   3685     @Override
   3686     public ParcelFileDescriptor establishVpn(VpnConfig config) {
   3687         int user = UserHandle.getUserId(Binder.getCallingUid());
   3688         synchronized (mVpns) {
   3689             throwIfLockdownEnabled();
   3690             return mVpns.get(user).establish(config);
   3691         }
   3692     }
   3693 
   3694     /**
   3695      * Start legacy VPN, controlling native daemons as needed. Creates a
   3696      * secondary thread to perform connection work, returning quickly.
   3697      */
   3698     @Override
   3699     public void startLegacyVpn(VpnProfile profile) {
   3700         int user = UserHandle.getUserId(Binder.getCallingUid());
   3701         final LinkProperties egress = getActiveLinkProperties();
   3702         if (egress == null) {
   3703             throw new IllegalStateException("Missing active network connection");
   3704         }
   3705         synchronized (mVpns) {
   3706             throwIfLockdownEnabled();
   3707             mVpns.get(user).startLegacyVpn(profile, mKeyStore, egress);
   3708         }
   3709     }
   3710 
   3711     /**
   3712      * Return the information of the ongoing legacy VPN. This method is used
   3713      * by VpnSettings and not available in ConnectivityManager. Permissions
   3714      * are checked in Vpn class.
   3715      */
   3716     @Override
   3717     public LegacyVpnInfo getLegacyVpnInfo(int userId) {
   3718         enforceCrossUserPermission(userId);
   3719 
   3720         synchronized (mVpns) {
   3721             return mVpns.get(userId).getLegacyVpnInfo();
   3722         }
   3723     }
   3724 
   3725     /**
   3726      * Return the information of all ongoing VPNs. This method is used by NetworkStatsService
   3727      * and not available in ConnectivityManager.
   3728      */
   3729     @Override
   3730     public VpnInfo[] getAllVpnInfo() {
   3731         enforceConnectivityInternalPermission();
   3732         synchronized (mVpns) {
   3733             if (mLockdownEnabled) {
   3734                 return new VpnInfo[0];
   3735             }
   3736 
   3737             List<VpnInfo> infoList = new ArrayList<>();
   3738             for (int i = 0; i < mVpns.size(); i++) {
   3739                 VpnInfo info = createVpnInfo(mVpns.valueAt(i));
   3740                 if (info != null) {
   3741                     infoList.add(info);
   3742                 }
   3743             }
   3744             return infoList.toArray(new VpnInfo[infoList.size()]);
   3745         }
   3746     }
   3747 
   3748     /**
   3749      * @return VPN information for accounting, or null if we can't retrieve all required
   3750      *         information, e.g primary underlying iface.
   3751      */
   3752     @Nullable
   3753     private VpnInfo createVpnInfo(Vpn vpn) {
   3754         VpnInfo info = vpn.getVpnInfo();
   3755         if (info == null) {
   3756             return null;
   3757         }
   3758         Network[] underlyingNetworks = vpn.getUnderlyingNetworks();
   3759         // see VpnService.setUnderlyingNetworks()'s javadoc about how to interpret
   3760         // the underlyingNetworks list.
   3761         if (underlyingNetworks == null) {
   3762             NetworkAgentInfo defaultNetwork = getDefaultNetwork();
   3763             if (defaultNetwork != null && defaultNetwork.linkProperties != null) {
   3764                 info.primaryUnderlyingIface = getDefaultNetwork().linkProperties.getInterfaceName();
   3765             }
   3766         } else if (underlyingNetworks.length > 0) {
   3767             LinkProperties linkProperties = getLinkProperties(underlyingNetworks[0]);
   3768             if (linkProperties != null) {
   3769                 info.primaryUnderlyingIface = linkProperties.getInterfaceName();
   3770             }
   3771         }
   3772         return info.primaryUnderlyingIface == null ? null : info;
   3773     }
   3774 
   3775     /**
   3776      * Returns the information of the ongoing VPN for {@code userId}. This method is used by
   3777      * VpnDialogs and not available in ConnectivityManager.
   3778      * Permissions are checked in Vpn class.
   3779      * @hide
   3780      */
   3781     @Override
   3782     public VpnConfig getVpnConfig(int userId) {
   3783         enforceCrossUserPermission(userId);
   3784         synchronized (mVpns) {
   3785             Vpn vpn = mVpns.get(userId);
   3786             if (vpn != null) {
   3787                 return vpn.getVpnConfig();
   3788             } else {
   3789                 return null;
   3790             }
   3791         }
   3792     }
   3793 
   3794     /**
   3795      * Ask all VPN objects to recompute and update their capabilities.
   3796      *
   3797      * When underlying networks change, VPNs may have to update capabilities to reflect things
   3798      * like the metered bit, their transports, and so on. This asks the VPN objects to update
   3799      * their capabilities, and as this will cause them to send messages to the ConnectivityService
   3800      * handler thread through their agent, this is asynchronous. When the capabilities objects
   3801      * are computed they will be up-to-date as they are computed synchronously from here and
   3802      * this is running on the ConnectivityService thread.
   3803      * TODO : Fix this and call updateCapabilities inline to remove out-of-order events.
   3804      */
   3805     private void updateAllVpnsCapabilities() {
   3806         synchronized (mVpns) {
   3807             for (int i = 0; i < mVpns.size(); i++) {
   3808                 final Vpn vpn = mVpns.valueAt(i);
   3809                 vpn.updateCapabilities();
   3810             }
   3811         }
   3812     }
   3813 
   3814     @Override
   3815     public boolean updateLockdownVpn() {
   3816         if (Binder.getCallingUid() != Process.SYSTEM_UID) {
   3817             Slog.w(TAG, "Lockdown VPN only available to AID_SYSTEM");
   3818             return false;
   3819         }
   3820 
   3821         synchronized (mVpns) {
   3822             // Tear down existing lockdown if profile was removed
   3823             mLockdownEnabled = LockdownVpnTracker.isEnabled();
   3824             if (mLockdownEnabled) {
   3825                 byte[] profileTag = mKeyStore.get(Credentials.LOCKDOWN_VPN);
   3826                 if (profileTag == null) {
   3827                     Slog.e(TAG, "Lockdown VPN configured but cannot be read from keystore");
   3828                     return false;
   3829                 }
   3830                 String profileName = new String(profileTag);
   3831                 final VpnProfile profile = VpnProfile.decode(
   3832                         profileName, mKeyStore.get(Credentials.VPN + profileName));
   3833                 if (profile == null) {
   3834                     Slog.e(TAG, "Lockdown VPN configured invalid profile " + profileName);
   3835                     setLockdownTracker(null);
   3836                     return true;
   3837                 }
   3838                 int user = UserHandle.getUserId(Binder.getCallingUid());
   3839                 Vpn vpn = mVpns.get(user);
   3840                 if (vpn == null) {
   3841                     Slog.w(TAG, "VPN for user " + user + " not ready yet. Skipping lockdown");
   3842                     return false;
   3843                 }
   3844                 setLockdownTracker(new LockdownVpnTracker(mContext, mNetd, this, vpn, profile));
   3845             } else {
   3846                 setLockdownTracker(null);
   3847             }
   3848         }
   3849 
   3850         return true;
   3851     }
   3852 
   3853     /**
   3854      * Internally set new {@link LockdownVpnTracker}, shutting down any existing
   3855      * {@link LockdownVpnTracker}. Can be {@code null} to disable lockdown.
   3856      */
   3857     @GuardedBy("mVpns")
   3858     private void setLockdownTracker(LockdownVpnTracker tracker) {
   3859         // Shutdown any existing tracker
   3860         final LockdownVpnTracker existing = mLockdownTracker;
   3861         mLockdownTracker = null;
   3862         if (existing != null) {
   3863             existing.shutdown();
   3864         }
   3865 
   3866         if (tracker != null) {
   3867             mLockdownTracker = tracker;
   3868             mLockdownTracker.init();
   3869         }
   3870     }
   3871 
   3872     @GuardedBy("mVpns")
   3873     private void throwIfLockdownEnabled() {
   3874         if (mLockdownEnabled) {
   3875             throw new IllegalStateException("Unavailable in lockdown mode");
   3876         }
   3877     }
   3878 
   3879     /**
   3880      * Starts the always-on VPN {@link VpnService} for user {@param userId}, which should perform
   3881      * some setup and then call {@code establish()} to connect.
   3882      *
   3883      * @return {@code true} if the service was started, the service was already connected, or there
   3884      *         was no always-on VPN to start. {@code false} otherwise.
   3885      */
   3886     private boolean startAlwaysOnVpn(int userId) {
   3887         synchronized (mVpns) {
   3888             Vpn vpn = mVpns.get(userId);
   3889             if (vpn == null) {
   3890                 // Shouldn't happen as all codepaths that point here should have checked the Vpn
   3891                 // exists already.
   3892                 Slog.wtf(TAG, "User " + userId + " has no Vpn configuration");
   3893                 return false;
   3894             }
   3895 
   3896             return vpn.startAlwaysOnVpn();
   3897         }
   3898     }
   3899 
   3900     @Override
   3901     public boolean isAlwaysOnVpnPackageSupported(int userId, String packageName) {
   3902         enforceSettingsPermission();
   3903         enforceCrossUserPermission(userId);
   3904 
   3905         synchronized (mVpns) {
   3906             Vpn vpn = mVpns.get(userId);
   3907             if (vpn == null) {
   3908                 Slog.w(TAG, "User " + userId + " has no Vpn configuration");
   3909                 return false;
   3910             }
   3911             return vpn.isAlwaysOnPackageSupported(packageName);
   3912         }
   3913     }
   3914 
   3915     @Override
   3916     public boolean setAlwaysOnVpnPackage(int userId, String packageName, boolean lockdown) {
   3917         enforceConnectivityInternalPermission();
   3918         enforceCrossUserPermission(userId);
   3919 
   3920         synchronized (mVpns) {
   3921             // Can't set always-on VPN if legacy VPN is already in lockdown mode.
   3922             if (LockdownVpnTracker.isEnabled()) {
   3923                 return false;
   3924             }
   3925 
   3926             Vpn vpn = mVpns.get(userId);
   3927             if (vpn == null) {
   3928                 Slog.w(TAG, "User " + userId + " has no Vpn configuration");
   3929                 return false;
   3930             }
   3931             if (!vpn.setAlwaysOnPackage(packageName, lockdown)) {
   3932                 return false;
   3933             }
   3934             if (!startAlwaysOnVpn(userId)) {
   3935                 vpn.setAlwaysOnPackage(null, false);
   3936                 return false;
   3937             }
   3938         }
   3939         return true;
   3940     }
   3941 
   3942     @Override
   3943     public String getAlwaysOnVpnPackage(int userId) {
   3944         enforceConnectivityInternalPermission();
   3945         enforceCrossUserPermission(userId);
   3946 
   3947         synchronized (mVpns) {
   3948             Vpn vpn = mVpns.get(userId);
   3949             if (vpn == null) {
   3950                 Slog.w(TAG, "User " + userId + " has no Vpn configuration");
   3951                 return null;
   3952             }
   3953             return vpn.getAlwaysOnPackage();
   3954         }
   3955     }
   3956 
   3957     @Override
   3958     public int checkMobileProvisioning(int suggestedTimeOutMs) {
   3959         // TODO: Remove?  Any reason to trigger a provisioning check?
   3960         return -1;
   3961     }
   3962 
   3963     /** Location to an updatable file listing carrier provisioning urls.
   3964      *  An example:
   3965      *
   3966      * <?xml version="1.0" encoding="utf-8"?>
   3967      *  <provisioningUrls>
   3968      *   <provisioningUrl mcc="310" mnc="4">http://myserver.com/foo?mdn=%3$s&iccid=%1$s&imei=%2$s</provisioningUrl>
   3969      *  </provisioningUrls>
   3970      */
   3971     private static final String PROVISIONING_URL_PATH =
   3972             "/data/misc/radio/provisioning_urls.xml";
   3973     private final File mProvisioningUrlFile = new File(PROVISIONING_URL_PATH);
   3974 
   3975     /** XML tag for root element. */
   3976     private static final String TAG_PROVISIONING_URLS = "provisioningUrls";
   3977     /** XML tag for individual url */
   3978     private static final String TAG_PROVISIONING_URL = "provisioningUrl";
   3979     /** XML attribute for mcc */
   3980     private static final String ATTR_MCC = "mcc";
   3981     /** XML attribute for mnc */
   3982     private static final String ATTR_MNC = "mnc";
   3983 
   3984     private String getProvisioningUrlBaseFromFile() {
   3985         FileReader fileReader = null;
   3986         XmlPullParser parser = null;
   3987         Configuration config = mContext.getResources().getConfiguration();
   3988 
   3989         try {
   3990             fileReader = new FileReader(mProvisioningUrlFile);
   3991             parser = Xml.newPullParser();
   3992             parser.setInput(fileReader);
   3993             XmlUtils.beginDocument(parser, TAG_PROVISIONING_URLS);
   3994 
   3995             while (true) {
   3996                 XmlUtils.nextElement(parser);
   3997 
   3998                 String element = parser.getName();
   3999                 if (element == null) break;
   4000 
   4001                 if (element.equals(TAG_PROVISIONING_URL)) {
   4002                     String mcc = parser.getAttributeValue(null, ATTR_MCC);
   4003                     try {
   4004                         if (mcc != null && Integer.parseInt(mcc) == config.mcc) {
   4005                             String mnc = parser.getAttributeValue(null, ATTR_MNC);
   4006                             if (mnc != null && Integer.parseInt(mnc) == config.mnc) {
   4007                                 parser.next();
   4008                                 if (parser.getEventType() == XmlPullParser.TEXT) {
   4009                                     return parser.getText();
   4010                                 }
   4011                             }
   4012                         }
   4013                     } catch (NumberFormatException e) {
   4014                         loge("NumberFormatException in getProvisioningUrlBaseFromFile: " + e);
   4015                     }
   4016                 }
   4017             }
   4018             return null;
   4019         } catch (FileNotFoundException e) {
   4020             loge("Carrier Provisioning Urls file not found");
   4021         } catch (XmlPullParserException e) {
   4022             loge("Xml parser exception reading Carrier Provisioning Urls file: " + e);
   4023         } catch (IOException e) {
   4024             loge("I/O exception reading Carrier Provisioning Urls file: " + e);
   4025         } finally {
   4026             if (fileReader != null) {
   4027                 try {
   4028                     fileReader.close();
   4029                 } catch (IOException e) {}
   4030             }
   4031         }
   4032         return null;
   4033     }
   4034 
   4035     @Override
   4036     public String getMobileProvisioningUrl() {
   4037         enforceConnectivityInternalPermission();
   4038         String url = getProvisioningUrlBaseFromFile();
   4039         if (TextUtils.isEmpty(url)) {
   4040             url = mContext.getResources().getString(R.string.mobile_provisioning_url);
   4041             log("getMobileProvisioningUrl: mobile_provisioining_url from resource =" + url);
   4042         } else {
   4043             log("getMobileProvisioningUrl: mobile_provisioning_url from File =" + url);
   4044         }
   4045         // populate the iccid, imei and phone number in the provisioning url.
   4046         if (!TextUtils.isEmpty(url)) {
   4047             String phoneNumber = mTelephonyManager.getLine1Number();
   4048             if (TextUtils.isEmpty(phoneNumber)) {
   4049                 phoneNumber = "0000000000";
   4050             }
   4051             url = String.format(url,
   4052                     mTelephonyManager.getSimSerialNumber() /* ICCID */,
   4053                     mTelephonyManager.getDeviceId() /* IMEI */,
   4054                     phoneNumber /* Phone numer */);
   4055         }
   4056 
   4057         return url;
   4058     }
   4059 
   4060     @Override
   4061     public void setProvisioningNotificationVisible(boolean visible, int networkType,
   4062             String action) {
   4063         enforceConnectivityInternalPermission();
   4064         if (!ConnectivityManager.isNetworkTypeValid(networkType)) {
   4065             return;
   4066         }
   4067         final long ident = Binder.clearCallingIdentity();
   4068         try {
   4069             // Concatenate the range of types onto the range of NetIDs.
   4070             int id = MAX_NET_ID + 1 + (networkType - ConnectivityManager.TYPE_NONE);
   4071             mNotifier.setProvNotificationVisible(visible, id, action);
   4072         } finally {
   4073             Binder.restoreCallingIdentity(ident);
   4074         }
   4075     }
   4076 
   4077     @Override
   4078     public void setAirplaneMode(boolean enable) {
   4079         enforceConnectivityInternalPermission();
   4080         final long ident = Binder.clearCallingIdentity();
   4081         try {
   4082             final ContentResolver cr = mContext.getContentResolver();
   4083             Settings.Global.putInt(cr, Settings.Global.AIRPLANE_MODE_ON, encodeBool(enable));
   4084             Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
   4085             intent.putExtra("state", enable);
   4086             mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
   4087         } finally {
   4088             Binder.restoreCallingIdentity(ident);
   4089         }
   4090     }
   4091 
   4092     private void onUserStart(int userId) {
   4093         synchronized (mVpns) {
   4094             Vpn userVpn = mVpns.get(userId);
   4095             if (userVpn != null) {
   4096                 loge("Starting user already has a VPN");
   4097                 return;
   4098             }
   4099             userVpn = new Vpn(mHandler.getLooper(), mContext, mNetd, userId);
   4100             mVpns.put(userId, userVpn);
   4101             if (mUserManager.getUserInfo(userId).isPrimary() && LockdownVpnTracker.isEnabled()) {
   4102                 updateLockdownVpn();
   4103             }
   4104         }
   4105     }
   4106 
   4107     private void onUserStop(int userId) {
   4108         synchronized (mVpns) {
   4109             Vpn userVpn = mVpns.get(userId);
   4110             if (userVpn == null) {
   4111                 loge("Stopped user has no VPN");
   4112                 return;
   4113             }
   4114             userVpn.onUserStopped();
   4115             mVpns.delete(userId);
   4116         }
   4117     }
   4118 
   4119     private void onUserAdded(int userId) {
   4120         synchronized (mVpns) {
   4121             final int vpnsSize = mVpns.size();
   4122             for (int i = 0; i < vpnsSize; i++) {
   4123                 Vpn vpn = mVpns.valueAt(i);
   4124                 vpn.onUserAdded(userId);
   4125             }
   4126         }
   4127     }
   4128 
   4129     private void onUserRemoved(int userId) {
   4130         synchronized (mVpns) {
   4131             final int vpnsSize = mVpns.size();
   4132             for (int i = 0; i < vpnsSize; i++) {
   4133                 Vpn vpn = mVpns.valueAt(i);
   4134                 vpn.onUserRemoved(userId);
   4135             }
   4136         }
   4137     }
   4138 
   4139     private void onUserUnlocked(int userId) {
   4140         synchronized (mVpns) {
   4141             // User present may be sent because of an unlock, which might mean an unlocked keystore.
   4142             if (mUserManager.getUserInfo(userId).isPrimary() && LockdownVpnTracker.isEnabled()) {
   4143                 updateLockdownVpn();
   4144             } else {
   4145                 startAlwaysOnVpn(userId);
   4146             }
   4147         }
   4148     }
   4149 
   4150     private BroadcastReceiver mUserIntentReceiver = new BroadcastReceiver() {
   4151         @Override
   4152         public void onReceive(Context context, Intent intent) {
   4153             final String action = intent.getAction();
   4154             final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
   4155             if (userId == UserHandle.USER_NULL) return;
   4156 
   4157             if (Intent.ACTION_USER_STARTED.equals(action)) {
   4158                 onUserStart(userId);
   4159             } else if (Intent.ACTION_USER_STOPPED.equals(action)) {
   4160                 onUserStop(userId);
   4161             } else if (Intent.ACTION_USER_ADDED.equals(action)) {
   4162                 onUserAdded(userId);
   4163             } else if (Intent.ACTION_USER_REMOVED.equals(action)) {
   4164                 onUserRemoved(userId);
   4165             } else if (Intent.ACTION_USER_UNLOCKED.equals(action)) {
   4166                 onUserUnlocked(userId);
   4167             }
   4168         }
   4169     };
   4170 
   4171     private BroadcastReceiver mUserPresentReceiver = new BroadcastReceiver() {
   4172         @Override
   4173         public void onReceive(Context context, Intent intent) {
   4174             // Try creating lockdown tracker, since user present usually means
   4175             // unlocked keystore.
   4176             updateLockdownVpn();
   4177             mContext.unregisterReceiver(this);
   4178         }
   4179     };
   4180 
   4181     private final HashMap<Messenger, NetworkFactoryInfo> mNetworkFactoryInfos =
   4182             new HashMap<Messenger, NetworkFactoryInfo>();
   4183     private final HashMap<NetworkRequest, NetworkRequestInfo> mNetworkRequests =
   4184             new HashMap<NetworkRequest, NetworkRequestInfo>();
   4185 
   4186     private static final int MAX_NETWORK_REQUESTS_PER_UID = 100;
   4187     // Map from UID to number of NetworkRequests that UID has filed.
   4188     @GuardedBy("mUidToNetworkRequestCount")
   4189     private final SparseIntArray mUidToNetworkRequestCount = new SparseIntArray();
   4190 
   4191     private static class NetworkFactoryInfo {
   4192         public final String name;
   4193         public final Messenger messenger;
   4194         public final AsyncChannel asyncChannel;
   4195 
   4196         public NetworkFactoryInfo(String name, Messenger messenger, AsyncChannel asyncChannel) {
   4197             this.name = name;
   4198             this.messenger = messenger;
   4199             this.asyncChannel = asyncChannel;
   4200         }
   4201     }
   4202 
   4203     private void ensureNetworkRequestHasType(NetworkRequest request) {
   4204         if (request.type == NetworkRequest.Type.NONE) {
   4205             throw new IllegalArgumentException(
   4206                     "All NetworkRequests in ConnectivityService must have a type");
   4207         }
   4208     }
   4209 
   4210     /**
   4211      * Tracks info about the requester.
   4212      * Also used to notice when the calling process dies so we can self-expire
   4213      */
   4214     private class NetworkRequestInfo implements IBinder.DeathRecipient {
   4215         final NetworkRequest request;
   4216         final PendingIntent mPendingIntent;
   4217         boolean mPendingIntentSent;
   4218         private final IBinder mBinder;
   4219         final int mPid;
   4220         final int mUid;
   4221         final Messenger messenger;
   4222 
   4223         NetworkRequestInfo(NetworkRequest r, PendingIntent pi) {
   4224             request = r;
   4225             ensureNetworkRequestHasType(request);
   4226             mPendingIntent = pi;
   4227             messenger = null;
   4228             mBinder = null;
   4229             mPid = getCallingPid();
   4230             mUid = getCallingUid();
   4231             enforceRequestCountLimit();
   4232         }
   4233 
   4234         NetworkRequestInfo(Messenger m, NetworkRequest r, IBinder binder) {
   4235             super();
   4236             messenger = m;
   4237             request = r;
   4238             ensureNetworkRequestHasType(request);
   4239             mBinder = binder;
   4240             mPid = getCallingPid();
   4241             mUid = getCallingUid();
   4242             mPendingIntent = null;
   4243             enforceRequestCountLimit();
   4244 
   4245             try {
   4246                 mBinder.linkToDeath(this, 0);
   4247             } catch (RemoteException e) {
   4248                 binderDied();
   4249             }
   4250         }
   4251 
   4252         private void enforceRequestCountLimit() {
   4253             synchronized (mUidToNetworkRequestCount) {
   4254                 int networkRequests = mUidToNetworkRequestCount.get(mUid, 0) + 1;
   4255                 if (networkRequests >= MAX_NETWORK_REQUESTS_PER_UID) {
   4256                     throw new ServiceSpecificException(
   4257                             ConnectivityManager.Errors.TOO_MANY_REQUESTS);
   4258                 }
   4259                 mUidToNetworkRequestCount.put(mUid, networkRequests);
   4260             }
   4261         }
   4262 
   4263         void unlinkDeathRecipient() {
   4264             if (mBinder != null) {
   4265                 mBinder.unlinkToDeath(this, 0);
   4266             }
   4267         }
   4268 
   4269         public void binderDied() {
   4270             log("ConnectivityService NetworkRequestInfo binderDied(" +
   4271                     request + ", " + mBinder + ")");
   4272             releaseNetworkRequest(request);
   4273         }
   4274 
   4275         public String toString() {
   4276             return "uid/pid:" + mUid + "/" + mPid + " " + request +
   4277                     (mPendingIntent == null ? "" : " to trigger " + mPendingIntent);
   4278         }
   4279     }
   4280 
   4281     private void ensureRequestableCapabilities(NetworkCapabilities networkCapabilities) {
   4282         final String badCapability = networkCapabilities.describeFirstNonRequestableCapability();
   4283         if (badCapability != null) {
   4284             throw new IllegalArgumentException("Cannot request network with " + badCapability);
   4285         }
   4286     }
   4287 
   4288     // This checks that the passed capabilities either do not request a specific SSID, or the
   4289     // calling app has permission to do so.
   4290     private void ensureSufficientPermissionsForRequest(NetworkCapabilities nc,
   4291             int callerPid, int callerUid) {
   4292         if (null != nc.getSSID() && !checkSettingsPermission(callerPid, callerUid)) {
   4293             throw new SecurityException("Insufficient permissions to request a specific SSID");
   4294         }
   4295     }
   4296 
   4297     private ArrayList<Integer> getSignalStrengthThresholds(NetworkAgentInfo nai) {
   4298         final SortedSet<Integer> thresholds = new TreeSet();
   4299         synchronized (nai) {
   4300             for (NetworkRequestInfo nri : mNetworkRequests.values()) {
   4301                 if (nri.request.networkCapabilities.hasSignalStrength() &&
   4302                         nai.satisfiesImmutableCapabilitiesOf(nri.request)) {
   4303                     thresholds.add(nri.request.networkCapabilities.getSignalStrength());
   4304                 }
   4305             }
   4306         }
   4307         return new ArrayList<Integer>(thresholds);
   4308     }
   4309 
   4310     private void updateSignalStrengthThresholds(
   4311             NetworkAgentInfo nai, String reason, NetworkRequest request) {
   4312         ArrayList<Integer> thresholdsArray = getSignalStrengthThresholds(nai);
   4313         Bundle thresholds = new Bundle();
   4314         thresholds.putIntegerArrayList("thresholds", thresholdsArray);
   4315 
   4316         if (VDBG || (DBG && !"CONNECT".equals(reason))) {
   4317             String detail;
   4318             if (request != null && request.networkCapabilities.hasSignalStrength()) {
   4319                 detail = reason + " " + request.networkCapabilities.getSignalStrength();
   4320             } else {
   4321                 detail = reason;
   4322             }
   4323             log(String.format("updateSignalStrengthThresholds: %s, sending %s to %s",
   4324                     detail, Arrays.toString(thresholdsArray.toArray()), nai.name()));
   4325         }
   4326 
   4327         nai.asyncChannel.sendMessage(
   4328                 android.net.NetworkAgent.CMD_SET_SIGNAL_STRENGTH_THRESHOLDS,
   4329                 0, 0, thresholds);
   4330     }
   4331 
   4332     private void ensureValidNetworkSpecifier(NetworkCapabilities nc) {
   4333         if (nc == null) {
   4334             return;
   4335         }
   4336         NetworkSpecifier ns = nc.getNetworkSpecifier();
   4337         if (ns == null) {
   4338             return;
   4339         }
   4340         MatchAllNetworkSpecifier.checkNotMatchAllNetworkSpecifier(ns);
   4341         ns.assertValidFromUid(Binder.getCallingUid());
   4342     }
   4343 
   4344     @Override
   4345     public NetworkRequest requestNetwork(NetworkCapabilities networkCapabilities,
   4346             Messenger messenger, int timeoutMs, IBinder binder, int legacyType) {
   4347         final NetworkRequest.Type type = (networkCapabilities == null)
   4348                 ? NetworkRequest.Type.TRACK_DEFAULT
   4349                 : NetworkRequest.Type.REQUEST;
   4350         // If the requested networkCapabilities is null, take them instead from
   4351         // the default network request. This allows callers to keep track of
   4352         // the system default network.
   4353         if (type == NetworkRequest.Type.TRACK_DEFAULT) {
   4354             networkCapabilities = createDefaultNetworkCapabilitiesForUid(Binder.getCallingUid());
   4355             enforceAccessPermission();
   4356         } else {
   4357             networkCapabilities = new NetworkCapabilities(networkCapabilities);
   4358             enforceNetworkRequestPermissions(networkCapabilities);
   4359             // TODO: this is incorrect. We mark the request as metered or not depending on the state
   4360             // of the app when the request is filed, but we never change the request if the app
   4361             // changes network state. http://b/29964605
   4362             enforceMeteredApnPolicy(networkCapabilities);
   4363         }
   4364         ensureRequestableCapabilities(networkCapabilities);
   4365         ensureSufficientPermissionsForRequest(networkCapabilities,
   4366                 Binder.getCallingPid(), Binder.getCallingUid());
   4367         // Set the UID range for this request to the single UID of the requester, or to an empty
   4368         // set of UIDs if the caller has the appropriate permission and UIDs have not been set.
   4369         // This will overwrite any allowed UIDs in the requested capabilities. Though there
   4370         // are no visible methods to set the UIDs, an app could use reflection to try and get
   4371         // networks for other apps so it's essential that the UIDs are overwritten.
   4372         restrictRequestUidsForCaller(networkCapabilities);
   4373 
   4374         if (timeoutMs < 0) {
   4375             throw new IllegalArgumentException("Bad timeout specified");
   4376         }
   4377         ensureValidNetworkSpecifier(networkCapabilities);
   4378 
   4379         NetworkRequest networkRequest = new NetworkRequest(networkCapabilities, legacyType,
   4380                 nextNetworkRequestId(), type);
   4381         NetworkRequestInfo nri = new NetworkRequestInfo(messenger, networkRequest, binder);
   4382         if (DBG) log("requestNetwork for " + nri);
   4383 
   4384         mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_REQUEST, nri));
   4385         if (timeoutMs > 0) {
   4386             mHandler.sendMessageDelayed(mHandler.obtainMessage(EVENT_TIMEOUT_NETWORK_REQUEST,
   4387                     nri), timeoutMs);
   4388         }
   4389         return networkRequest;
   4390     }
   4391 
   4392     private void enforceNetworkRequestPermissions(NetworkCapabilities networkCapabilities) {
   4393         if (networkCapabilities.hasCapability(NET_CAPABILITY_NOT_RESTRICTED) == false) {
   4394             enforceConnectivityRestrictedNetworksPermission();
   4395         } else {
   4396             enforceChangePermission();
   4397         }
   4398     }
   4399 
   4400     @Override
   4401     public boolean requestBandwidthUpdate(Network network) {
   4402         enforceAccessPermission();
   4403         NetworkAgentInfo nai = null;
   4404         if (network == null) {
   4405             return false;
   4406         }
   4407         synchronized (mNetworkForNetId) {
   4408             nai = mNetworkForNetId.get(network.netId);
   4409         }
   4410         if (nai != null) {
   4411             nai.asyncChannel.sendMessage(android.net.NetworkAgent.CMD_REQUEST_BANDWIDTH_UPDATE);
   4412             return true;
   4413         }
   4414         return false;
   4415     }
   4416 
   4417     private boolean isSystem(int uid) {
   4418         return uid < Process.FIRST_APPLICATION_UID;
   4419     }
   4420 
   4421     private void enforceMeteredApnPolicy(NetworkCapabilities networkCapabilities) {
   4422         final int uid = Binder.getCallingUid();
   4423         if (isSystem(uid)) {
   4424             // Exemption for system uid.
   4425             return;
   4426         }
   4427         if (networkCapabilities.hasCapability(NET_CAPABILITY_NOT_METERED)) {
   4428             // Policy already enforced.
   4429             return;
   4430         }
   4431         if (mPolicyManagerInternal.isUidRestrictedOnMeteredNetworks(uid)) {
   4432             // If UID is restricted, don't allow them to bring up metered APNs.
   4433             networkCapabilities.addCapability(NET_CAPABILITY_NOT_METERED);
   4434         }
   4435     }
   4436 
   4437     @Override
   4438     public NetworkRequest pendingRequestForNetwork(NetworkCapabilities networkCapabilities,
   4439             PendingIntent operation) {
   4440         checkNotNull(operation, "PendingIntent cannot be null.");
   4441         networkCapabilities = new NetworkCapabilities(networkCapabilities);
   4442         enforceNetworkRequestPermissions(networkCapabilities);
   4443         enforceMeteredApnPolicy(networkCapabilities);
   4444         ensureRequestableCapabilities(networkCapabilities);
   4445         ensureSufficientPermissionsForRequest(networkCapabilities,
   4446                 Binder.getCallingPid(), Binder.getCallingUid());
   4447         ensureValidNetworkSpecifier(networkCapabilities);
   4448         restrictRequestUidsForCaller(networkCapabilities);
   4449 
   4450         NetworkRequest networkRequest = new NetworkRequest(networkCapabilities, TYPE_NONE,
   4451                 nextNetworkRequestId(), NetworkRequest.Type.REQUEST);
   4452         NetworkRequestInfo nri = new NetworkRequestInfo(networkRequest, operation);
   4453         if (DBG) log("pendingRequest for " + nri);
   4454         mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_REQUEST_WITH_INTENT,
   4455                 nri));
   4456         return networkRequest;
   4457     }
   4458 
   4459     private void releasePendingNetworkRequestWithDelay(PendingIntent operation) {
   4460         mHandler.sendMessageDelayed(
   4461                 mHandler.obtainMessage(EVENT_RELEASE_NETWORK_REQUEST_WITH_INTENT,
   4462                 getCallingUid(), 0, operation), mReleasePendingIntentDelayMs);
   4463     }
   4464 
   4465     @Override
   4466     public void releasePendingNetworkRequest(PendingIntent operation) {
   4467         checkNotNull(operation, "PendingIntent cannot be null.");
   4468         mHandler.sendMessage(mHandler.obtainMessage(EVENT_RELEASE_NETWORK_REQUEST_WITH_INTENT,
   4469                 getCallingUid(), 0, operation));
   4470     }
   4471 
   4472     // In order to implement the compatibility measure for pre-M apps that call
   4473     // WifiManager.enableNetwork(..., true) without also binding to that network explicitly,
   4474     // WifiManager registers a network listen for the purpose of calling setProcessDefaultNetwork.
   4475     // This ensures it has permission to do so.
   4476     private boolean hasWifiNetworkListenPermission(NetworkCapabilities nc) {
   4477         if (nc == null) {
   4478             return false;
   4479         }
   4480         int[] transportTypes = nc.getTransportTypes();
   4481         if (transportTypes.length != 1 || transportTypes[0] != NetworkCapabilities.TRANSPORT_WIFI) {
   4482             return false;
   4483         }
   4484         try {
   4485             mContext.enforceCallingOrSelfPermission(
   4486                     android.Manifest.permission.ACCESS_WIFI_STATE,
   4487                     "ConnectivityService");
   4488         } catch (SecurityException e) {
   4489             return false;
   4490         }
   4491         return true;
   4492     }
   4493 
   4494     @Override
   4495     public NetworkRequest listenForNetwork(NetworkCapabilities networkCapabilities,
   4496             Messenger messenger, IBinder binder) {
   4497         if (!hasWifiNetworkListenPermission(networkCapabilities)) {
   4498             enforceAccessPermission();
   4499         }
   4500 
   4501         NetworkCapabilities nc = new NetworkCapabilities(networkCapabilities);
   4502         ensureSufficientPermissionsForRequest(networkCapabilities,
   4503                 Binder.getCallingPid(), Binder.getCallingUid());
   4504         restrictRequestUidsForCaller(nc);
   4505         // Apps without the CHANGE_NETWORK_STATE permission can't use background networks, so
   4506         // make all their listens include NET_CAPABILITY_FOREGROUND. That way, they will get
   4507         // onLost and onAvailable callbacks when networks move in and out of the background.
   4508         // There is no need to do this for requests because an app without CHANGE_NETWORK_STATE
   4509         // can't request networks.
   4510         restrictBackgroundRequestForCaller(nc);
   4511         ensureValidNetworkSpecifier(nc);
   4512 
   4513         NetworkRequest networkRequest = new NetworkRequest(nc, TYPE_NONE, nextNetworkRequestId(),
   4514                 NetworkRequest.Type.LISTEN);
   4515         NetworkRequestInfo nri = new NetworkRequestInfo(messenger, networkRequest, binder);
   4516         if (VDBG) log("listenForNetwork for " + nri);
   4517 
   4518         mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_LISTENER, nri));
   4519         return networkRequest;
   4520     }
   4521 
   4522     @Override
   4523     public void pendingListenForNetwork(NetworkCapabilities networkCapabilities,
   4524             PendingIntent operation) {
   4525         checkNotNull(operation, "PendingIntent cannot be null.");
   4526         if (!hasWifiNetworkListenPermission(networkCapabilities)) {
   4527             enforceAccessPermission();
   4528         }
   4529         ensureValidNetworkSpecifier(networkCapabilities);
   4530         ensureSufficientPermissionsForRequest(networkCapabilities,
   4531                 Binder.getCallingPid(), Binder.getCallingUid());
   4532 
   4533         final NetworkCapabilities nc = new NetworkCapabilities(networkCapabilities);
   4534         restrictRequestUidsForCaller(nc);
   4535 
   4536         NetworkRequest networkRequest = new NetworkRequest(nc, TYPE_NONE, nextNetworkRequestId(),
   4537                 NetworkRequest.Type.LISTEN);
   4538         NetworkRequestInfo nri = new NetworkRequestInfo(networkRequest, operation);
   4539         if (VDBG) log("pendingListenForNetwork for " + nri);
   4540 
   4541         mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_LISTENER, nri));
   4542     }
   4543 
   4544     @Override
   4545     public void releaseNetworkRequest(NetworkRequest networkRequest) {
   4546         ensureNetworkRequestHasType(networkRequest);
   4547         mHandler.sendMessage(mHandler.obtainMessage(
   4548                 EVENT_RELEASE_NETWORK_REQUEST, getCallingUid(), 0, networkRequest));
   4549     }
   4550 
   4551     @Override
   4552     public void registerNetworkFactory(Messenger messenger, String name) {
   4553         enforceConnectivityInternalPermission();
   4554         NetworkFactoryInfo nfi = new NetworkFactoryInfo(name, messenger, new AsyncChannel());
   4555         mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_FACTORY, nfi));
   4556     }
   4557 
   4558     private void handleRegisterNetworkFactory(NetworkFactoryInfo nfi) {
   4559         if (DBG) log("Got NetworkFactory Messenger for " + nfi.name);
   4560         mNetworkFactoryInfos.put(nfi.messenger, nfi);
   4561         nfi.asyncChannel.connect(mContext, mTrackerHandler, nfi.messenger);
   4562     }
   4563 
   4564     @Override
   4565     public void unregisterNetworkFactory(Messenger messenger) {
   4566         enforceConnectivityInternalPermission();
   4567         mHandler.sendMessage(mHandler.obtainMessage(EVENT_UNREGISTER_NETWORK_FACTORY, messenger));
   4568     }
   4569 
   4570     private void handleUnregisterNetworkFactory(Messenger messenger) {
   4571         NetworkFactoryInfo nfi = mNetworkFactoryInfos.remove(messenger);
   4572         if (nfi == null) {
   4573             loge("Failed to find Messenger in unregisterNetworkFactory");
   4574             return;
   4575         }
   4576         if (DBG) log("unregisterNetworkFactory for " + nfi.name);
   4577     }
   4578 
   4579     /**
   4580      * NetworkAgentInfo supporting a request by requestId.
   4581      * These have already been vetted (their Capabilities satisfy the request)
   4582      * and the are the highest scored network available.
   4583      * the are keyed off the Requests requestId.
   4584      */
   4585     // NOTE: Accessed on multiple threads, must be synchronized on itself.
   4586     @GuardedBy("mNetworkForRequestId")
   4587     private final SparseArray<NetworkAgentInfo> mNetworkForRequestId =
   4588             new SparseArray<NetworkAgentInfo>();
   4589 
   4590     // NOTE: Accessed on multiple threads, must be synchronized on itself.
   4591     @GuardedBy("mNetworkForNetId")
   4592     private final SparseArray<NetworkAgentInfo> mNetworkForNetId =
   4593             new SparseArray<NetworkAgentInfo>();
   4594     // NOTE: Accessed on multiple threads, synchronized with mNetworkForNetId.
   4595     // An entry is first added to mNetIdInUse, prior to mNetworkForNetId, so
   4596     // there may not be a strict 1:1 correlation between the two.
   4597     @GuardedBy("mNetworkForNetId")
   4598     private final SparseBooleanArray mNetIdInUse = new SparseBooleanArray();
   4599 
   4600     // NetworkAgentInfo keyed off its connecting messenger
   4601     // TODO - eval if we can reduce the number of lists/hashmaps/sparsearrays
   4602     // NOTE: Only should be accessed on ConnectivityServiceThread, except dump().
   4603     private final HashMap<Messenger, NetworkAgentInfo> mNetworkAgentInfos =
   4604             new HashMap<Messenger, NetworkAgentInfo>();
   4605 
   4606     @GuardedBy("mBlockedAppUids")
   4607     private final HashSet<Integer> mBlockedAppUids = new HashSet();
   4608 
   4609     // Note: if mDefaultRequest is changed, NetworkMonitor needs to be updated.
   4610     private final NetworkRequest mDefaultRequest;
   4611 
   4612     // Request used to optionally keep mobile data active even when higher
   4613     // priority networks like Wi-Fi are active.
   4614     private final NetworkRequest mDefaultMobileDataRequest;
   4615 
   4616     private NetworkAgentInfo getNetworkForRequest(int requestId) {
   4617         synchronized (mNetworkForRequestId) {
   4618             return mNetworkForRequestId.get(requestId);
   4619         }
   4620     }
   4621 
   4622     private void clearNetworkForRequest(int requestId) {
   4623         synchronized (mNetworkForRequestId) {
   4624             mNetworkForRequestId.remove(requestId);
   4625         }
   4626     }
   4627 
   4628     private void setNetworkForRequest(int requestId, NetworkAgentInfo nai) {
   4629         synchronized (mNetworkForRequestId) {
   4630             mNetworkForRequestId.put(requestId, nai);
   4631         }
   4632     }
   4633 
   4634     private NetworkAgentInfo getDefaultNetwork() {
   4635         return getNetworkForRequest(mDefaultRequest.requestId);
   4636     }
   4637 
   4638     private boolean isDefaultNetwork(NetworkAgentInfo nai) {
   4639         return nai == getDefaultNetwork();
   4640     }
   4641 
   4642     private boolean isDefaultRequest(NetworkRequestInfo nri) {
   4643         return nri.request.requestId == mDefaultRequest.requestId;
   4644     }
   4645 
   4646     public int registerNetworkAgent(Messenger messenger, NetworkInfo networkInfo,
   4647             LinkProperties linkProperties, NetworkCapabilities networkCapabilities,
   4648             int currentScore, NetworkMisc networkMisc) {
   4649         enforceConnectivityInternalPermission();
   4650 
   4651         LinkProperties lp = new LinkProperties(linkProperties);
   4652         lp.ensureDirectlyConnectedRoutes();
   4653         // TODO: Instead of passing mDefaultRequest, provide an API to determine whether a Network
   4654         // satisfies mDefaultRequest.
   4655         final NetworkCapabilities nc = new NetworkCapabilities(networkCapabilities);
   4656         final NetworkAgentInfo nai = new NetworkAgentInfo(messenger, new AsyncChannel(),
   4657                 new Network(reserveNetId()), new NetworkInfo(networkInfo), lp, nc, currentScore,
   4658                 mContext, mTrackerHandler, new NetworkMisc(networkMisc), mDefaultRequest, this);
   4659         // Make sure the network capabilities reflect what the agent info says.
   4660         nai.networkCapabilities = mixInCapabilities(nai, nc);
   4661         synchronized (this) {
   4662             nai.networkMonitor.systemReady = mSystemReady;
   4663         }
   4664         final String extraInfo = networkInfo.getExtraInfo();
   4665         final String name = TextUtils.isEmpty(extraInfo)
   4666                 ? nai.networkCapabilities.getSSID() : extraInfo;
   4667         addValidationLogs(nai.networkMonitor.getValidationLogs(), nai.network, name);
   4668         if (DBG) log("registerNetworkAgent " + nai);
   4669         mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_AGENT, nai));
   4670         return nai.network.netId;
   4671     }
   4672 
   4673     private void handleRegisterNetworkAgent(NetworkAgentInfo nai) {
   4674         if (VDBG) log("Got NetworkAgent Messenger");
   4675         mNetworkAgentInfos.put(nai.messenger, nai);
   4676         synchronized (mNetworkForNetId) {
   4677             mNetworkForNetId.put(nai.network.netId, nai);
   4678         }
   4679         nai.asyncChannel.connect(mContext, mTrackerHandler, nai.messenger);
   4680         NetworkInfo networkInfo = nai.networkInfo;
   4681         nai.networkInfo = null;
   4682         updateNetworkInfo(nai, networkInfo);
   4683         updateUids(nai, null, nai.networkCapabilities);
   4684     }
   4685 
   4686     private void updateLinkProperties(NetworkAgentInfo networkAgent, LinkProperties oldLp) {
   4687         LinkProperties newLp = new LinkProperties(networkAgent.linkProperties);
   4688         int netId = networkAgent.network.netId;
   4689 
   4690         // The NetworkAgentInfo does not know whether clatd is running on its network or not. Before
   4691         // we do anything else, make sure its LinkProperties are accurate.
   4692         if (networkAgent.clatd != null) {
   4693             networkAgent.clatd.fixupLinkProperties(oldLp, newLp);
   4694         }
   4695 
   4696         updateInterfaces(newLp, oldLp, netId, networkAgent.networkCapabilities);
   4697         updateMtu(newLp, oldLp);
   4698         // TODO - figure out what to do for clat
   4699 //        for (LinkProperties lp : newLp.getStackedLinks()) {
   4700 //            updateMtu(lp, null);
   4701 //        }
   4702         updateTcpBufferSizes(networkAgent);
   4703 
   4704         updateRoutes(newLp, oldLp, netId);
   4705         updateDnses(newLp, oldLp, netId);
   4706         // Make sure LinkProperties represents the latest private DNS status.
   4707         // This does not need to be done before updateDnses because the
   4708         // LinkProperties are not the source of the private DNS configuration.
   4709         // updateDnses will fetch the private DNS configuration from DnsManager.
   4710         mDnsManager.updatePrivateDnsStatus(netId, newLp);
   4711 
   4712         // Start or stop clat accordingly to network state.
   4713         networkAgent.updateClat(mNetd);
   4714         if (isDefaultNetwork(networkAgent)) {
   4715             handleApplyDefaultProxy(newLp.getHttpProxy());
   4716         } else {
   4717             updateProxy(newLp, oldLp, networkAgent);
   4718         }
   4719         // TODO - move this check to cover the whole function
   4720         if (!Objects.equals(newLp, oldLp)) {
   4721             synchronized (networkAgent) {
   4722                 networkAgent.linkProperties = newLp;
   4723             }
   4724             notifyIfacesChangedForNetworkStats();
   4725             notifyNetworkCallbacks(networkAgent, ConnectivityManager.CALLBACK_IP_CHANGED);
   4726         }
   4727 
   4728         mKeepaliveTracker.handleCheckKeepalivesStillValid(networkAgent);
   4729     }
   4730 
   4731     private void wakeupModifyInterface(String iface, NetworkCapabilities caps, boolean add) {
   4732         // Marks are only available on WiFi interaces. Checking for
   4733         // marks on unsupported interfaces is harmless.
   4734         if (!caps.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
   4735             return;
   4736         }
   4737 
   4738         int mark = mContext.getResources().getInteger(
   4739             com.android.internal.R.integer.config_networkWakeupPacketMark);
   4740         int mask = mContext.getResources().getInteger(
   4741             com.android.internal.R.integer.config_networkWakeupPacketMask);
   4742 
   4743         // Mask/mark of zero will not detect anything interesting.
   4744         // Don't install rules unless both values are nonzero.
   4745         if (mark == 0 || mask == 0) {
   4746             return;
   4747         }
   4748 
   4749         final String prefix = "iface:" + iface;
   4750         try {
   4751             if (add) {
   4752                 mNetd.getNetdService().wakeupAddInterface(iface, prefix, mark, mask);
   4753             } else {
   4754                 mNetd.getNetdService().wakeupDelInterface(iface, prefix, mark, mask);
   4755             }
   4756         } catch (Exception e) {
   4757             loge("Exception modifying wakeup packet monitoring: " + e);
   4758         }
   4759 
   4760     }
   4761 
   4762     private void updateInterfaces(LinkProperties newLp, LinkProperties oldLp, int netId,
   4763                                   NetworkCapabilities caps) {
   4764         CompareResult<String> interfaceDiff = new CompareResult<String>(
   4765                 oldLp != null ? oldLp.getAllInterfaceNames() : null,
   4766                 newLp != null ? newLp.getAllInterfaceNames() : null);
   4767         for (String iface : interfaceDiff.added) {
   4768             try {
   4769                 if (DBG) log("Adding iface " + iface + " to network " + netId);
   4770                 mNetd.addInterfaceToNetwork(iface, netId);
   4771                 wakeupModifyInterface(iface, caps, true);
   4772             } catch (Exception e) {
   4773                 loge("Exception adding interface: " + e);
   4774             }
   4775         }
   4776         for (String iface : interfaceDiff.removed) {
   4777             try {
   4778                 if (DBG) log("Removing iface " + iface + " from network " + netId);
   4779                 wakeupModifyInterface(iface, caps, false);
   4780                 mNetd.removeInterfaceFromNetwork(iface, netId);
   4781             } catch (Exception e) {
   4782                 loge("Exception removing interface: " + e);
   4783             }
   4784         }
   4785     }
   4786 
   4787     /**
   4788      * Have netd update routes from oldLp to newLp.
   4789      * @return true if routes changed between oldLp and newLp
   4790      */
   4791     private boolean updateRoutes(LinkProperties newLp, LinkProperties oldLp, int netId) {
   4792         // Compare the route diff to determine which routes should be added and removed.
   4793         CompareResult<RouteInfo> routeDiff = new CompareResult<RouteInfo>(
   4794                 oldLp != null ? oldLp.getAllRoutes() : null,
   4795                 newLp != null ? newLp.getAllRoutes() : null);
   4796 
   4797         // add routes before removing old in case it helps with continuous connectivity
   4798 
   4799         // do this twice, adding non-nexthop routes first, then routes they are dependent on
   4800         for (RouteInfo route : routeDiff.added) {
   4801             if (route.hasGateway()) continue;
   4802             if (VDBG) log("Adding Route [" + route + "] to network " + netId);
   4803             try {
   4804                 mNetd.addRoute(netId, route);
   4805             } catch (Exception e) {
   4806                 if ((route.getDestination().getAddress() instanceof Inet4Address) || VDBG) {
   4807                     loge("Exception in addRoute for non-gateway: " + e);
   4808                 }
   4809             }
   4810         }
   4811         for (RouteInfo route : routeDiff.added) {
   4812             if (route.hasGateway() == false) continue;
   4813             if (VDBG) log("Adding Route [" + route + "] to network " + netId);
   4814             try {
   4815                 mNetd.addRoute(netId, route);
   4816             } catch (Exception e) {
   4817                 if ((route.getGateway() instanceof Inet4Address) || VDBG) {
   4818                     loge("Exception in addRoute for gateway: " + e);
   4819                 }
   4820             }
   4821         }
   4822 
   4823         for (RouteInfo route : routeDiff.removed) {
   4824             if (VDBG) log("Removing Route [" + route + "] from network " + netId);
   4825             try {
   4826                 mNetd.removeRoute(netId, route);
   4827             } catch (Exception e) {
   4828                 loge("Exception in removeRoute: " + e);
   4829             }
   4830         }
   4831         return !routeDiff.added.isEmpty() || !routeDiff.removed.isEmpty();
   4832     }
   4833 
   4834     private void updateDnses(LinkProperties newLp, LinkProperties oldLp, int netId) {
   4835         if (oldLp != null && newLp.isIdenticalDnses(oldLp)) {
   4836             return;  // no updating necessary
   4837         }
   4838 
   4839         final NetworkAgentInfo defaultNai = getDefaultNetwork();
   4840         final boolean isDefaultNetwork = (defaultNai != null && defaultNai.network.netId == netId);
   4841 
   4842         if (DBG) {
   4843             final Collection<InetAddress> dnses = newLp.getDnsServers();
   4844             log("Setting DNS servers for network " + netId + " to " + dnses);
   4845         }
   4846         try {
   4847             mDnsManager.setDnsConfigurationForNetwork(netId, newLp, isDefaultNetwork);
   4848         } catch (Exception e) {
   4849             loge("Exception in setDnsConfigurationForNetwork: " + e);
   4850         }
   4851     }
   4852 
   4853     private String getNetworkPermission(NetworkCapabilities nc) {
   4854         // TODO: make these permission strings AIDL constants instead.
   4855         if (!nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)) {
   4856             return NetworkManagementService.PERMISSION_SYSTEM;
   4857         }
   4858         if (!nc.hasCapability(NET_CAPABILITY_FOREGROUND)) {
   4859             return NetworkManagementService.PERMISSION_NETWORK;
   4860         }
   4861         return null;
   4862     }
   4863 
   4864     /**
   4865      * Augments the NetworkCapabilities passed in by a NetworkAgent with capabilities that are
   4866      * maintained here that the NetworkAgent is not aware of (e.g., validated, captive portal,
   4867      * and foreground status).
   4868      */
   4869     private NetworkCapabilities mixInCapabilities(NetworkAgentInfo nai, NetworkCapabilities nc) {
   4870         // Once a NetworkAgent is connected, complain if some immutable capabilities are removed.
   4871          // Don't complain for VPNs since they're not driven by requests and there is no risk of
   4872          // causing a connect/teardown loop.
   4873          // TODO: remove this altogether and make it the responsibility of the NetworkFactories to
   4874          // avoid connect/teardown loops.
   4875         if (nai.everConnected &&
   4876                 !nai.isVPN() &&
   4877                 !nai.networkCapabilities.satisfiedByImmutableNetworkCapabilities(nc)) {
   4878             // TODO: consider not complaining when a network agent degrades its capabilities if this
   4879             // does not cause any request (that is not a listen) currently matching that agent to
   4880             // stop being matched by the updated agent.
   4881             String diff = nai.networkCapabilities.describeImmutableDifferences(nc);
   4882             if (!TextUtils.isEmpty(diff)) {
   4883                 Slog.wtf(TAG, "BUG: " + nai + " lost immutable capabilities:" + diff);
   4884             }
   4885         }
   4886 
   4887         // Don't modify caller's NetworkCapabilities.
   4888         NetworkCapabilities newNc = new NetworkCapabilities(nc);
   4889         if (nai.lastValidated) {
   4890             newNc.addCapability(NET_CAPABILITY_VALIDATED);
   4891         } else {
   4892             newNc.removeCapability(NET_CAPABILITY_VALIDATED);
   4893         }
   4894         if (nai.lastCaptivePortalDetected) {
   4895             newNc.addCapability(NET_CAPABILITY_CAPTIVE_PORTAL);
   4896         } else {
   4897             newNc.removeCapability(NET_CAPABILITY_CAPTIVE_PORTAL);
   4898         }
   4899         if (nai.isBackgroundNetwork()) {
   4900             newNc.removeCapability(NET_CAPABILITY_FOREGROUND);
   4901         } else {
   4902             newNc.addCapability(NET_CAPABILITY_FOREGROUND);
   4903         }
   4904         if (nai.isSuspended()) {
   4905             newNc.removeCapability(NET_CAPABILITY_NOT_SUSPENDED);
   4906         } else {
   4907             newNc.addCapability(NET_CAPABILITY_NOT_SUSPENDED);
   4908         }
   4909 
   4910         return newNc;
   4911     }
   4912 
   4913     /**
   4914      * Update the NetworkCapabilities for {@code nai} to {@code nc}. Specifically:
   4915      *
   4916      * 1. Calls mixInCapabilities to merge the passed-in NetworkCapabilities {@code nc} with the
   4917      *    capabilities we manage and store in {@code nai}, such as validated status and captive
   4918      *    portal status)
   4919      * 2. Takes action on the result: changes network permissions, sends CAP_CHANGED callbacks, and
   4920      *    potentially triggers rematches.
   4921      * 3. Directly informs other network stack components (NetworkStatsService, VPNs, etc. of the
   4922      *    change.)
   4923      *
   4924      * @param oldScore score of the network before any of the changes that prompted us
   4925      *                 to call this function.
   4926      * @param nai the network having its capabilities updated.
   4927      * @param nc the new network capabilities.
   4928      */
   4929     private void updateCapabilities(int oldScore, NetworkAgentInfo nai, NetworkCapabilities nc) {
   4930         NetworkCapabilities newNc = mixInCapabilities(nai, nc);
   4931 
   4932         if (Objects.equals(nai.networkCapabilities, newNc)) return;
   4933 
   4934         final String oldPermission = getNetworkPermission(nai.networkCapabilities);
   4935         final String newPermission = getNetworkPermission(newNc);
   4936         if (!Objects.equals(oldPermission, newPermission) && nai.created && !nai.isVPN()) {
   4937             try {
   4938                 mNetd.setNetworkPermission(nai.network.netId, newPermission);
   4939             } catch (RemoteException e) {
   4940                 loge("Exception in setNetworkPermission: " + e);
   4941             }
   4942         }
   4943 
   4944         final NetworkCapabilities prevNc;
   4945         synchronized (nai) {
   4946             prevNc = nai.networkCapabilities;
   4947             nai.networkCapabilities = newNc;
   4948         }
   4949 
   4950         updateUids(nai, prevNc, newNc);
   4951 
   4952         if (nai.getCurrentScore() == oldScore && newNc.equalRequestableCapabilities(prevNc)) {
   4953             // If the requestable capabilities haven't changed, and the score hasn't changed, then
   4954             // the change we're processing can't affect any requests, it can only affect the listens
   4955             // on this network. We might have been called by rematchNetworkAndRequests when a
   4956             // network changed foreground state.
   4957             processListenRequests(nai, true);
   4958         } else {
   4959             // If the requestable capabilities have changed or the score changed, we can't have been
   4960             // called by rematchNetworkAndRequests, so it's safe to start a rematch.
   4961             rematchAllNetworksAndRequests(nai, oldScore);
   4962             notifyNetworkCallbacks(nai, ConnectivityManager.CALLBACK_CAP_CHANGED);
   4963         }
   4964 
   4965         // Report changes that are interesting for network statistics tracking.
   4966         if (prevNc != null) {
   4967             final boolean meteredChanged = prevNc.hasCapability(NET_CAPABILITY_NOT_METERED) !=
   4968                     newNc.hasCapability(NET_CAPABILITY_NOT_METERED);
   4969             final boolean roamingChanged = prevNc.hasCapability(NET_CAPABILITY_NOT_ROAMING) !=
   4970                     newNc.hasCapability(NET_CAPABILITY_NOT_ROAMING);
   4971             if (meteredChanged || roamingChanged) {
   4972                 notifyIfacesChangedForNetworkStats();
   4973             }
   4974         }
   4975 
   4976         if (!newNc.hasTransport(TRANSPORT_VPN)) {
   4977             // Tell VPNs about updated capabilities, since they may need to
   4978             // bubble those changes through.
   4979             updateAllVpnsCapabilities();
   4980         }
   4981     }
   4982 
   4983     private void updateUids(NetworkAgentInfo nai, NetworkCapabilities prevNc,
   4984             NetworkCapabilities newNc) {
   4985         Set<UidRange> prevRanges = null == prevNc ? null : prevNc.getUids();
   4986         Set<UidRange> newRanges = null == newNc ? null : newNc.getUids();
   4987         if (null == prevRanges) prevRanges = new ArraySet<>();
   4988         if (null == newRanges) newRanges = new ArraySet<>();
   4989         final Set<UidRange> prevRangesCopy = new ArraySet<>(prevRanges);
   4990 
   4991         prevRanges.removeAll(newRanges);
   4992         newRanges.removeAll(prevRangesCopy);
   4993 
   4994         try {
   4995             if (!newRanges.isEmpty()) {
   4996                 final UidRange[] addedRangesArray = new UidRange[newRanges.size()];
   4997                 newRanges.toArray(addedRangesArray);
   4998                 mNetd.addVpnUidRanges(nai.network.netId, addedRangesArray);
   4999             }
   5000             if (!prevRanges.isEmpty()) {
   5001                 final UidRange[] removedRangesArray = new UidRange[prevRanges.size()];
   5002                 prevRanges.toArray(removedRangesArray);
   5003                 mNetd.removeVpnUidRanges(nai.network.netId, removedRangesArray);
   5004             }
   5005         } catch (Exception e) {
   5006             // Never crash!
   5007             loge("Exception in updateUids: " + e);
   5008         }
   5009     }
   5010 
   5011     public void handleUpdateLinkProperties(NetworkAgentInfo nai, LinkProperties newLp) {
   5012         if (getNetworkAgentInfoForNetId(nai.network.netId) != nai) {
   5013             // Ignore updates for disconnected networks
   5014             return;
   5015         }
   5016         // newLp is already a defensive copy.
   5017         newLp.ensureDirectlyConnectedRoutes();
   5018         if (VDBG) {
   5019             log("Update of LinkProperties for " + nai.name() +
   5020                     "; created=" + nai.created +
   5021                     "; everConnected=" + nai.everConnected);
   5022         }
   5023         LinkProperties oldLp = nai.linkProperties;
   5024         synchronized (nai) {
   5025             nai.linkProperties = newLp;
   5026         }
   5027         if (nai.everConnected) {
   5028             updateLinkProperties(nai, oldLp);
   5029         }
   5030     }
   5031 
   5032     private void sendUpdatedScoreToFactories(NetworkAgentInfo nai) {
   5033         for (int i = 0; i < nai.numNetworkRequests(); i++) {
   5034             NetworkRequest nr = nai.requestAt(i);
   5035             // Don't send listening requests to factories. b/17393458
   5036             if (nr.isListen()) continue;
   5037             sendUpdatedScoreToFactories(nr, nai.getCurrentScore());
   5038         }
   5039     }
   5040 
   5041     private void sendUpdatedScoreToFactories(NetworkRequest networkRequest, int score) {
   5042         if (VDBG) log("sending new Min Network Score(" + score + "): " + networkRequest.toString());
   5043         for (NetworkFactoryInfo nfi : mNetworkFactoryInfos.values()) {
   5044             nfi.asyncChannel.sendMessage(android.net.NetworkFactory.CMD_REQUEST_NETWORK, score, 0,
   5045                     networkRequest);
   5046         }
   5047     }
   5048 
   5049     private void sendPendingIntentForRequest(NetworkRequestInfo nri, NetworkAgentInfo networkAgent,
   5050             int notificationType) {
   5051         if (notificationType == ConnectivityManager.CALLBACK_AVAILABLE && !nri.mPendingIntentSent) {
   5052             Intent intent = new Intent();
   5053             intent.putExtra(ConnectivityManager.EXTRA_NETWORK, networkAgent.network);
   5054             intent.putExtra(ConnectivityManager.EXTRA_NETWORK_REQUEST, nri.request);
   5055             nri.mPendingIntentSent = true;
   5056             sendIntent(nri.mPendingIntent, intent);
   5057         }
   5058         // else not handled
   5059     }
   5060 
   5061     private void sendIntent(PendingIntent pendingIntent, Intent intent) {
   5062         mPendingIntentWakeLock.acquire();
   5063         try {
   5064             if (DBG) log("Sending " + pendingIntent);
   5065             pendingIntent.send(mContext, 0, intent, this /* onFinished */, null /* Handler */);
   5066         } catch (PendingIntent.CanceledException e) {
   5067             if (DBG) log(pendingIntent + " was not sent, it had been canceled.");
   5068             mPendingIntentWakeLock.release();
   5069             releasePendingNetworkRequest(pendingIntent);
   5070         }
   5071         // ...otherwise, mPendingIntentWakeLock.release() gets called by onSendFinished()
   5072     }
   5073 
   5074     @Override
   5075     public void onSendFinished(PendingIntent pendingIntent, Intent intent, int resultCode,
   5076             String resultData, Bundle resultExtras) {
   5077         if (DBG) log("Finished sending " + pendingIntent);
   5078         mPendingIntentWakeLock.release();
   5079         // Release with a delay so the receiving client has an opportunity to put in its
   5080         // own request.
   5081         releasePendingNetworkRequestWithDelay(pendingIntent);
   5082     }
   5083 
   5084     private void callCallbackForRequest(NetworkRequestInfo nri,
   5085             NetworkAgentInfo networkAgent, int notificationType, int arg1) {
   5086         if (nri.messenger == null) {
   5087             return;  // Default request has no msgr
   5088         }
   5089         Bundle bundle = new Bundle();
   5090         // TODO: check if defensive copies of data is needed.
   5091         putParcelable(bundle, new NetworkRequest(nri.request));
   5092         Message msg = Message.obtain();
   5093         if (notificationType != ConnectivityManager.CALLBACK_UNAVAIL) {
   5094             putParcelable(bundle, networkAgent.network);
   5095         }
   5096         switch (notificationType) {
   5097             case ConnectivityManager.CALLBACK_AVAILABLE: {
   5098                 putParcelable(bundle, new NetworkCapabilities(networkAgent.networkCapabilities));
   5099                 putParcelable(bundle, new LinkProperties(networkAgent.linkProperties));
   5100                 break;
   5101             }
   5102             case ConnectivityManager.CALLBACK_LOSING: {
   5103                 msg.arg1 = arg1;
   5104                 break;
   5105             }
   5106             case ConnectivityManager.CALLBACK_CAP_CHANGED: {
   5107                 // networkAgent can't be null as it has been accessed a few lines above.
   5108                 final NetworkCapabilities nc = networkCapabilitiesRestrictedForCallerPermissions(
   5109                         networkAgent.networkCapabilities, nri.mPid, nri.mUid);
   5110                 putParcelable(bundle, nc);
   5111                 break;
   5112             }
   5113             case ConnectivityManager.CALLBACK_IP_CHANGED: {
   5114                 putParcelable(bundle, new LinkProperties(networkAgent.linkProperties));
   5115                 break;
   5116             }
   5117         }
   5118         msg.what = notificationType;
   5119         msg.setData(bundle);
   5120         try {
   5121             if (VDBG) {
   5122                 String notification = ConnectivityManager.getCallbackName(notificationType);
   5123                 log("sending notification " + notification + " for " + nri.request);
   5124             }
   5125             nri.messenger.send(msg);
   5126         } catch (RemoteException e) {
   5127             // may occur naturally in the race of binder death.
   5128             loge("RemoteException caught trying to send a callback msg for " + nri.request);
   5129         }
   5130     }
   5131 
   5132     private static <T extends Parcelable> void putParcelable(Bundle bundle, T t) {
   5133         bundle.putParcelable(t.getClass().getSimpleName(), t);
   5134     }
   5135 
   5136     private void teardownUnneededNetwork(NetworkAgentInfo nai) {
   5137         if (nai.numRequestNetworkRequests() != 0) {
   5138             for (int i = 0; i < nai.numNetworkRequests(); i++) {
   5139                 NetworkRequest nr = nai.requestAt(i);
   5140                 // Ignore listening requests.
   5141                 if (nr.isListen()) continue;
   5142                 loge("Dead network still had at least " + nr);
   5143                 break;
   5144             }
   5145         }
   5146         nai.asyncChannel.disconnect();
   5147     }
   5148 
   5149     private void handleLingerComplete(NetworkAgentInfo oldNetwork) {
   5150         if (oldNetwork == null) {
   5151             loge("Unknown NetworkAgentInfo in handleLingerComplete");
   5152             return;
   5153         }
   5154         if (DBG) log("handleLingerComplete for " + oldNetwork.name());
   5155 
   5156         // If we get here it means that the last linger timeout for this network expired. So there
   5157         // must be no other active linger timers, and we must stop lingering.
   5158         oldNetwork.clearLingerState();
   5159 
   5160         if (unneeded(oldNetwork, UnneededFor.TEARDOWN)) {
   5161             // Tear the network down.
   5162             teardownUnneededNetwork(oldNetwork);
   5163         } else {
   5164             // Put the network in the background.
   5165             updateCapabilities(oldNetwork.getCurrentScore(), oldNetwork,
   5166                     oldNetwork.networkCapabilities);
   5167         }
   5168     }
   5169 
   5170     private void makeDefault(NetworkAgentInfo newNetwork) {
   5171         if (DBG) log("Switching to new default network: " + newNetwork);
   5172         setupDataActivityTracking(newNetwork);
   5173         try {
   5174             mNetd.setDefaultNetId(newNetwork.network.netId);
   5175         } catch (Exception e) {
   5176             loge("Exception setting default network :" + e);
   5177         }
   5178 
   5179         notifyLockdownVpn(newNetwork);
   5180         handleApplyDefaultProxy(newNetwork.linkProperties.getHttpProxy());
   5181         updateTcpBufferSizes(newNetwork);
   5182         mDnsManager.setDefaultDnsSystemProperties(newNetwork.linkProperties.getDnsServers());
   5183         notifyIfacesChangedForNetworkStats();
   5184     }
   5185 
   5186     private void processListenRequests(NetworkAgentInfo nai, boolean capabilitiesChanged) {
   5187         // For consistency with previous behaviour, send onLost callbacks before onAvailable.
   5188         for (NetworkRequestInfo nri : mNetworkRequests.values()) {
   5189             NetworkRequest nr = nri.request;
   5190             if (!nr.isListen()) continue;
   5191             if (nai.isSatisfyingRequest(nr.requestId) && !nai.satisfies(nr)) {
   5192                 nai.removeRequest(nri.request.requestId);
   5193                 callCallbackForRequest(nri, nai, ConnectivityManager.CALLBACK_LOST, 0);
   5194             }
   5195         }
   5196 
   5197         if (capabilitiesChanged) {
   5198             notifyNetworkCallbacks(nai, ConnectivityManager.CALLBACK_CAP_CHANGED);
   5199         }
   5200 
   5201         for (NetworkRequestInfo nri : mNetworkRequests.values()) {
   5202             NetworkRequest nr = nri.request;
   5203             if (!nr.isListen()) continue;
   5204             if (nai.satisfies(nr) && !nai.isSatisfyingRequest(nr.requestId)) {
   5205                 nai.addRequest(nr);
   5206                 notifyNetworkAvailable(nai, nri);
   5207             }
   5208         }
   5209     }
   5210 
   5211     // Handles a network appearing or improving its score.
   5212     //
   5213     // - Evaluates all current NetworkRequests that can be
   5214     //   satisfied by newNetwork, and reassigns to newNetwork
   5215     //   any such requests for which newNetwork is the best.
   5216     //
   5217     // - Lingers any validated Networks that as a result are no longer
   5218     //   needed. A network is needed if it is the best network for
   5219     //   one or more NetworkRequests, or if it is a VPN.
   5220     //
   5221     // - Tears down newNetwork if it just became validated
   5222     //   but turns out to be unneeded.
   5223     //
   5224     // - If reapUnvalidatedNetworks==REAP, tears down unvalidated
   5225     //   networks that have no chance (i.e. even if validated)
   5226     //   of becoming the highest scoring network.
   5227     //
   5228     // NOTE: This function only adds NetworkRequests that "newNetwork" could satisfy,
   5229     // it does not remove NetworkRequests that other Networks could better satisfy.
   5230     // If you need to handle decreases in score, use {@link rematchAllNetworksAndRequests}.
   5231     // This function should be used when possible instead of {@code rematchAllNetworksAndRequests}
   5232     // as it performs better by a factor of the number of Networks.
   5233     //
   5234     // @param newNetwork is the network to be matched against NetworkRequests.
   5235     // @param reapUnvalidatedNetworks indicates if an additional pass over all networks should be
   5236     //               performed to tear down unvalidated networks that have no chance (i.e. even if
   5237     //               validated) of becoming the highest scoring network.
   5238     private void rematchNetworkAndRequests(NetworkAgentInfo newNetwork,
   5239             ReapUnvalidatedNetworks reapUnvalidatedNetworks, long now) {
   5240         if (!newNetwork.everConnected) return;
   5241         boolean keep = newNetwork.isVPN();
   5242         boolean isNewDefault = false;
   5243         NetworkAgentInfo oldDefaultNetwork = null;
   5244 
   5245         final boolean wasBackgroundNetwork = newNetwork.isBackgroundNetwork();
   5246         final int score = newNetwork.getCurrentScore();
   5247 
   5248         if (VDBG) log("rematching " + newNetwork.name());
   5249 
   5250         // Find and migrate to this Network any NetworkRequests for
   5251         // which this network is now the best.
   5252         ArrayList<NetworkAgentInfo> affectedNetworks = new ArrayList<NetworkAgentInfo>();
   5253         ArrayList<NetworkRequestInfo> addedRequests = new ArrayList<NetworkRequestInfo>();
   5254         NetworkCapabilities nc = newNetwork.networkCapabilities;
   5255         if (VDBG) log(" network has: " + nc);
   5256         for (NetworkRequestInfo nri : mNetworkRequests.values()) {
   5257             // Process requests in the first pass and listens in the second pass. This allows us to
   5258             // change a network's capabilities depending on which requests it has. This is only
   5259             // correct if the change in capabilities doesn't affect whether the network satisfies
   5260             // requests or not, and doesn't affect the network's score.
   5261             if (nri.request.isListen()) continue;
   5262 
   5263             final NetworkAgentInfo currentNetwork = getNetworkForRequest(nri.request.requestId);
   5264             final boolean satisfies = newNetwork.satisfies(nri.request);
   5265             if (newNetwork == currentNetwork && satisfies) {
   5266                 if (VDBG) {
   5267                     log("Network " + newNetwork.name() + " was already satisfying" +
   5268                             " request " + nri.request.requestId + ". No change.");
   5269                 }
   5270                 keep = true;
   5271                 continue;
   5272             }
   5273 
   5274             // check if it satisfies the NetworkCapabilities
   5275             if (VDBG) log("  checking if request is satisfied: " + nri.request);
   5276             if (satisfies) {
   5277                 // next check if it's better than any current network we're using for
   5278                 // this request
   5279                 if (VDBG) {
   5280                     log("currentScore = " +
   5281                             (currentNetwork != null ? currentNetwork.getCurrentScore() : 0) +
   5282                             ", newScore = " + score);
   5283                 }
   5284                 if (currentNetwork == null || currentNetwork.getCurrentScore() < score) {
   5285                     if (VDBG) log("rematch for " + newNetwork.name());
   5286                     if (currentNetwork != null) {
   5287                         if (VDBG) log("   accepting network in place of " + currentNetwork.name());
   5288                         currentNetwork.removeRequest(nri.request.requestId);
   5289                         currentNetwork.lingerRequest(nri.request, now, mLingerDelayMs);
   5290                         affectedNetworks.add(currentNetwork);
   5291                     } else {
   5292                         if (VDBG) log("   accepting network in place of null");
   5293                     }
   5294                     newNetwork.unlingerRequest(nri.request);
   5295                     setNetworkForRequest(nri.request.requestId, newNetwork);
   5296                     if (!newNetwork.addRequest(nri.request)) {
   5297                         Slog.wtf(TAG, "BUG: " + newNetwork.name() + " already has " + nri.request);
   5298                     }
   5299                     addedRequests.add(nri);
   5300                     keep = true;
   5301                     // Tell NetworkFactories about the new score, so they can stop
   5302                     // trying to connect if they know they cannot match it.
   5303                     // TODO - this could get expensive if we have alot of requests for this
   5304                     // network.  Think about if there is a way to reduce this.  Push
   5305                     // netid->request mapping to each factory?
   5306                     sendUpdatedScoreToFactories(nri.request, score);
   5307                     if (isDefaultRequest(nri)) {
   5308                         isNewDefault = true;
   5309                         oldDefaultNetwork = currentNetwork;
   5310                         if (currentNetwork != null) {
   5311                             mLingerMonitor.noteLingerDefaultNetwork(currentNetwork, newNetwork);
   5312                         }
   5313                     }
   5314                 }
   5315             } else if (newNetwork.isSatisfyingRequest(nri.request.requestId)) {
   5316                 // If "newNetwork" is listed as satisfying "nri" but no longer satisfies "nri",
   5317                 // mark it as no longer satisfying "nri".  Because networks are processed by
   5318                 // rematchAllNetworksAndRequests() in descending score order, "currentNetwork" will
   5319                 // match "newNetwork" before this loop will encounter a "currentNetwork" with higher
   5320                 // score than "newNetwork" and where "currentNetwork" no longer satisfies "nri".
   5321                 // This means this code doesn't have to handle the case where "currentNetwork" no
   5322                 // longer satisfies "nri" when "currentNetwork" does not equal "newNetwork".
   5323                 if (DBG) {
   5324                     log("Network " + newNetwork.name() + " stopped satisfying" +
   5325                             " request " + nri.request.requestId);
   5326                 }
   5327                 newNetwork.removeRequest(nri.request.requestId);
   5328                 if (currentNetwork == newNetwork) {
   5329                     clearNetworkForRequest(nri.request.requestId);
   5330                     sendUpdatedScoreToFactories(nri.request, 0);
   5331                 } else {
   5332                     Slog.wtf(TAG, "BUG: Removing request " + nri.request.requestId + " from " +
   5333                             newNetwork.name() +
   5334                             " without updating mNetworkForRequestId or factories!");
   5335                 }
   5336                 // TODO: Technically, sending CALLBACK_LOST here is
   5337                 // incorrect if there is a replacement network currently
   5338                 // connected that can satisfy nri, which is a request
   5339                 // (not a listen). However, the only capability that can both
   5340                 // a) be requested and b) change is NET_CAPABILITY_TRUSTED,
   5341                 // so this code is only incorrect for a network that loses
   5342                 // the TRUSTED capability, which is a rare case.
   5343                 callCallbackForRequest(nri, newNetwork, ConnectivityManager.CALLBACK_LOST, 0);
   5344             }
   5345         }
   5346         if (isNewDefault) {
   5347             // Notify system services that this network is up.
   5348             makeDefault(newNetwork);
   5349             // Log 0 -> X and Y -> X default network transitions, where X is the new default.
   5350             metricsLogger().defaultNetworkMetrics().logDefaultNetworkEvent(
   5351                     now, newNetwork, oldDefaultNetwork);
   5352             // Have a new default network, release the transition wakelock in
   5353             scheduleReleaseNetworkTransitionWakelock();
   5354         }
   5355 
   5356         if (!newNetwork.networkCapabilities.equalRequestableCapabilities(nc)) {
   5357             Slog.wtf(TAG, String.format(
   5358                     "BUG: %s changed requestable capabilities during rematch: %s -> %s",
   5359                     newNetwork.name(), nc, newNetwork.networkCapabilities));
   5360         }
   5361         if (newNetwork.getCurrentScore() != score) {
   5362             Slog.wtf(TAG, String.format(
   5363                     "BUG: %s changed score during rematch: %d -> %d",
   5364                    newNetwork.name(), score, newNetwork.getCurrentScore()));
   5365         }
   5366 
   5367         // Second pass: process all listens.
   5368         if (wasBackgroundNetwork != newNetwork.isBackgroundNetwork()) {
   5369             // If the network went from background to foreground or vice versa, we need to update
   5370             // its foreground state. It is safe to do this after rematching the requests because
   5371             // NET_CAPABILITY_FOREGROUND does not affect requests, as is not a requestable
   5372             // capability and does not affect the network's score (see the Slog.wtf call above).
   5373             updateCapabilities(score, newNetwork, newNetwork.networkCapabilities);
   5374         } else {
   5375             processListenRequests(newNetwork, false);
   5376         }
   5377 
   5378         // do this after the default net is switched, but
   5379         // before LegacyTypeTracker sends legacy broadcasts
   5380         for (NetworkRequestInfo nri : addedRequests) notifyNetworkAvailable(newNetwork, nri);
   5381 
   5382         // Linger any networks that are no longer needed. This should be done after sending the
   5383         // available callback for newNetwork.
   5384         for (NetworkAgentInfo nai : affectedNetworks) {
   5385             updateLingerState(nai, now);
   5386         }
   5387         // Possibly unlinger newNetwork. Unlingering a network does not send any callbacks so it
   5388         // does not need to be done in any particular order.
   5389         updateLingerState(newNetwork, now);
   5390 
   5391         if (isNewDefault) {
   5392             // Maintain the illusion: since the legacy API only
   5393             // understands one network at a time, we must pretend
   5394             // that the current default network disconnected before
   5395             // the new one connected.
   5396             if (oldDefaultNetwork != null) {
   5397                 mLegacyTypeTracker.remove(oldDefaultNetwork.networkInfo.getType(),
   5398                                           oldDefaultNetwork, true);
   5399             }
   5400             mDefaultInetConditionPublished = newNetwork.lastValidated ? 100 : 0;
   5401             mLegacyTypeTracker.add(newNetwork.networkInfo.getType(), newNetwork);
   5402             notifyLockdownVpn(newNetwork);
   5403         }
   5404 
   5405         if (keep) {
   5406             // Notify battery stats service about this network, both the normal
   5407             // interface and any stacked links.
   5408             // TODO: Avoid redoing this; this must only be done once when a network comes online.
   5409             try {
   5410                 final IBatteryStats bs = BatteryStatsService.getService();
   5411                 final int type = newNetwork.networkInfo.getType();
   5412 
   5413                 final String baseIface = newNetwork.linkProperties.getInterfaceName();
   5414                 bs.noteNetworkInterfaceType(baseIface, type);
   5415                 for (LinkProperties stacked : newNetwork.linkProperties.getStackedLinks()) {
   5416                     final String stackedIface = stacked.getInterfaceName();
   5417                     bs.noteNetworkInterfaceType(stackedIface, type);
   5418                 }
   5419             } catch (RemoteException ignored) {
   5420             }
   5421 
   5422             // This has to happen after the notifyNetworkCallbacks as that tickles each
   5423             // ConnectivityManager instance so that legacy requests correctly bind dns
   5424             // requests to this network.  The legacy users are listening for this bcast
   5425             // and will generally do a dns request so they can ensureRouteToHost and if
   5426             // they do that before the callbacks happen they'll use the default network.
   5427             //
   5428             // TODO: Is there still a race here? We send the broadcast
   5429             // after sending the callback, but if the app can receive the
   5430             // broadcast before the callback, it might still break.
   5431             //
   5432             // This *does* introduce a race where if the user uses the new api
   5433             // (notification callbacks) and then uses the old api (getNetworkInfo(type))
   5434             // they may get old info.  Reverse this after the old startUsing api is removed.
   5435             // This is on top of the multiple intent sequencing referenced in the todo above.
   5436             for (int i = 0; i < newNetwork.numNetworkRequests(); i++) {
   5437                 NetworkRequest nr = newNetwork.requestAt(i);
   5438                 if (nr.legacyType != TYPE_NONE && nr.isRequest()) {
   5439                     // legacy type tracker filters out repeat adds
   5440                     mLegacyTypeTracker.add(nr.legacyType, newNetwork);
   5441                 }
   5442             }
   5443 
   5444             // A VPN generally won't get added to the legacy tracker in the "for (nri)" loop above,
   5445             // because usually there are no NetworkRequests it satisfies (e.g., mDefaultRequest
   5446             // wants the NOT_VPN capability, so it will never be satisfied by a VPN). So, add the
   5447             // newNetwork to the tracker explicitly (it's a no-op if it has already been added).
   5448             if (newNetwork.isVPN()) {
   5449                 mLegacyTypeTracker.add(TYPE_VPN, newNetwork);
   5450             }
   5451         }
   5452         if (reapUnvalidatedNetworks == ReapUnvalidatedNetworks.REAP) {
   5453             for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
   5454                 if (unneeded(nai, UnneededFor.TEARDOWN)) {
   5455                     if (nai.getLingerExpiry() > 0) {
   5456                         // This network has active linger timers and no requests, but is not
   5457                         // lingering. Linger it.
   5458                         //
   5459                         // One way (the only way?) this can happen if this network is unvalidated
   5460                         // and became unneeded due to another network improving its score to the
   5461                         // point where this network will no longer be able to satisfy any requests
   5462                         // even if it validates.
   5463                         updateLingerState(nai, now);
   5464                     } else {
   5465                         if (DBG) log("Reaping " + nai.name());
   5466                         teardownUnneededNetwork(nai);
   5467                     }
   5468                 }
   5469             }
   5470         }
   5471     }
   5472 
   5473     /**
   5474      * Attempt to rematch all Networks with NetworkRequests.  This may result in Networks
   5475      * being disconnected.
   5476      * @param changed If only one Network's score or capabilities have been modified since the last
   5477      *         time this function was called, pass this Network in this argument, otherwise pass
   5478      *         null.
   5479      * @param oldScore If only one Network has been changed but its NetworkCapabilities have not
   5480      *         changed, pass in the Network's score (from getCurrentScore()) prior to the change via
   5481      *         this argument, otherwise pass {@code changed.getCurrentScore()} or 0 if
   5482      *         {@code changed} is {@code null}. This is because NetworkCapabilities influence a
   5483      *         network's score.
   5484      */
   5485     private void rematchAllNetworksAndRequests(NetworkAgentInfo changed, int oldScore) {
   5486         // TODO: This may get slow.  The "changed" parameter is provided for future optimization
   5487         // to avoid the slowness.  It is not simply enough to process just "changed", for
   5488         // example in the case where "changed"'s score decreases and another network should begin
   5489         // satifying a NetworkRequest that "changed" currently satisfies.
   5490 
   5491         // Optimization: Only reprocess "changed" if its score improved.  This is safe because it
   5492         // can only add more NetworkRequests satisfied by "changed", and this is exactly what
   5493         // rematchNetworkAndRequests() handles.
   5494         final long now = SystemClock.elapsedRealtime();
   5495         if (changed != null && oldScore < changed.getCurrentScore()) {
   5496             rematchNetworkAndRequests(changed, ReapUnvalidatedNetworks.REAP, now);
   5497         } else {
   5498             final NetworkAgentInfo[] nais = mNetworkAgentInfos.values().toArray(
   5499                     new NetworkAgentInfo[mNetworkAgentInfos.size()]);
   5500             // Rematch higher scoring networks first to prevent requests first matching a lower
   5501             // scoring network and then a higher scoring network, which could produce multiple
   5502             // callbacks and inadvertently unlinger networks.
   5503             Arrays.sort(nais);
   5504             for (NetworkAgentInfo nai : nais) {
   5505                 rematchNetworkAndRequests(nai,
   5506                         // Only reap the last time through the loop.  Reaping before all rematching
   5507                         // is complete could incorrectly teardown a network that hasn't yet been
   5508                         // rematched.
   5509                         (nai != nais[nais.length-1]) ? ReapUnvalidatedNetworks.DONT_REAP
   5510                                 : ReapUnvalidatedNetworks.REAP,
   5511                         now);
   5512             }
   5513         }
   5514     }
   5515 
   5516     private void updateInetCondition(NetworkAgentInfo nai) {
   5517         // Don't bother updating until we've graduated to validated at least once.
   5518         if (!nai.everValidated) return;
   5519         // For now only update icons for default connection.
   5520         // TODO: Update WiFi and cellular icons separately. b/17237507
   5521         if (!isDefaultNetwork(nai)) return;
   5522 
   5523         int newInetCondition = nai.lastValidated ? 100 : 0;
   5524         // Don't repeat publish.
   5525         if (newInetCondition == mDefaultInetConditionPublished) return;
   5526 
   5527         mDefaultInetConditionPublished = newInetCondition;
   5528         sendInetConditionBroadcast(nai.networkInfo);
   5529     }
   5530 
   5531     private void notifyLockdownVpn(NetworkAgentInfo nai) {
   5532         synchronized (mVpns) {
   5533             if (mLockdownTracker != null) {
   5534                 if (nai != null && nai.isVPN()) {
   5535                     mLockdownTracker.onVpnStateChanged(nai.networkInfo);
   5536                 } else {
   5537                     mLockdownTracker.onNetworkInfoChanged();
   5538                 }
   5539             }
   5540         }
   5541     }
   5542 
   5543     private void updateNetworkInfo(NetworkAgentInfo networkAgent, NetworkInfo newInfo) {
   5544         final NetworkInfo.State state = newInfo.getState();
   5545         NetworkInfo oldInfo = null;
   5546         final int oldScore = networkAgent.getCurrentScore();
   5547         synchronized (networkAgent) {
   5548             oldInfo = networkAgent.networkInfo;
   5549             networkAgent.networkInfo = newInfo;
   5550         }
   5551         notifyLockdownVpn(networkAgent);
   5552 
   5553         if (DBG) {
   5554             log(networkAgent.name() + " EVENT_NETWORK_INFO_CHANGED, going from " +
   5555                     (oldInfo == null ? "null" : oldInfo.getState()) +
   5556                     " to " + state);
   5557         }
   5558 
   5559         if (!networkAgent.created
   5560                 && (state == NetworkInfo.State.CONNECTED
   5561                 || (state == NetworkInfo.State.CONNECTING && networkAgent.isVPN()))) {
   5562 
   5563             // A network that has just connected has zero requests and is thus a foreground network.
   5564             networkAgent.networkCapabilities.addCapability(NET_CAPABILITY_FOREGROUND);
   5565 
   5566             try {
   5567                 // This should never fail.  Specifying an already in use NetID will cause failure.
   5568                 if (networkAgent.isVPN()) {
   5569                     mNetd.createVirtualNetwork(networkAgent.network.netId,
   5570                             !networkAgent.linkProperties.getDnsServers().isEmpty(),
   5571                             (networkAgent.networkMisc == null ||
   5572                                 !networkAgent.networkMisc.allowBypass));
   5573                 } else {
   5574                     mNetd.createPhysicalNetwork(networkAgent.network.netId,
   5575                             getNetworkPermission(networkAgent.networkCapabilities));
   5576                 }
   5577             } catch (Exception e) {
   5578                 loge("Error creating network " + networkAgent.network.netId + ": "
   5579                         + e.getMessage());
   5580                 return;
   5581             }
   5582             networkAgent.created = true;
   5583         }
   5584 
   5585         if (!networkAgent.everConnected && state == NetworkInfo.State.CONNECTED) {
   5586             networkAgent.everConnected = true;
   5587 
   5588             handlePerNetworkPrivateDnsConfig(networkAgent, mDnsManager.getPrivateDnsConfig());
   5589             updateLinkProperties(networkAgent, null);
   5590             notifyIfacesChangedForNetworkStats();
   5591 
   5592             networkAgent.networkMonitor.sendMessage(NetworkMonitor.CMD_NETWORK_CONNECTED);
   5593             scheduleUnvalidatedPrompt(networkAgent);
   5594 
   5595             if (networkAgent.isVPN()) {
   5596                 // Temporarily disable the default proxy (not global).
   5597                 synchronized (mProxyLock) {
   5598                     if (!mDefaultProxyDisabled) {
   5599                         mDefaultProxyDisabled = true;
   5600                         if (mGlobalProxy == null && mDefaultProxy != null) {
   5601                             sendProxyBroadcast(null);
   5602                         }
   5603                     }
   5604                 }
   5605                 // TODO: support proxy per network.
   5606             }
   5607 
   5608             // Whether a particular NetworkRequest listen should cause signal strength thresholds to
   5609             // be communicated to a particular NetworkAgent depends only on the network's immutable,
   5610             // capabilities, so it only needs to be done once on initial connect, not every time the
   5611             // network's capabilities change. Note that we do this before rematching the network,
   5612             // so we could decide to tear it down immediately afterwards. That's fine though - on
   5613             // disconnection NetworkAgents should stop any signal strength monitoring they have been
   5614             // doing.
   5615             updateSignalStrengthThresholds(networkAgent, "CONNECT", null);
   5616 
   5617             // Consider network even though it is not yet validated.
   5618             final long now = SystemClock.elapsedRealtime();
   5619             rematchNetworkAndRequests(networkAgent, ReapUnvalidatedNetworks.REAP, now);
   5620 
   5621             // This has to happen after matching the requests, because callbacks are just requests.
   5622             notifyNetworkCallbacks(networkAgent, ConnectivityManager.CALLBACK_PRECHECK);
   5623         } else if (state == NetworkInfo.State.DISCONNECTED) {
   5624             networkAgent.asyncChannel.disconnect();
   5625             if (networkAgent.isVPN()) {
   5626                 synchronized (mProxyLock) {
   5627                     if (mDefaultProxyDisabled) {
   5628                         mDefaultProxyDisabled = false;
   5629                         if (mGlobalProxy == null && mDefaultProxy != null) {
   5630                             sendProxyBroadcast(mDefaultProxy);
   5631                         }
   5632                     }
   5633                 }
   5634                 updateUids(networkAgent, networkAgent.networkCapabilities, null);
   5635             }
   5636             disconnectAndDestroyNetwork(networkAgent);
   5637         } else if ((oldInfo != null && oldInfo.getState() == NetworkInfo.State.SUSPENDED) ||
   5638                 state == NetworkInfo.State.SUSPENDED) {
   5639             // going into or coming out of SUSPEND: rescore and notify
   5640             if (networkAgent.getCurrentScore() != oldScore) {
   5641                 rematchAllNetworksAndRequests(networkAgent, oldScore);
   5642             }
   5643             updateCapabilities(networkAgent.getCurrentScore(), networkAgent,
   5644                     networkAgent.networkCapabilities);
   5645             // TODO (b/73132094) : remove this call once the few users of onSuspended and
   5646             // onResumed have been removed.
   5647             notifyNetworkCallbacks(networkAgent, (state == NetworkInfo.State.SUSPENDED ?
   5648                     ConnectivityManager.CALLBACK_SUSPENDED :
   5649                     ConnectivityManager.CALLBACK_RESUMED));
   5650             mLegacyTypeTracker.update(networkAgent);
   5651         }
   5652     }
   5653 
   5654     private void updateNetworkScore(NetworkAgentInfo nai, int score) {
   5655         if (VDBG) log("updateNetworkScore for " + nai.name() + " to " + score);
   5656         if (score < 0) {
   5657             loge("updateNetworkScore for " + nai.name() + " got a negative score (" + score +
   5658                     ").  Bumping score to min of 0");
   5659             score = 0;
   5660         }
   5661 
   5662         final int oldScore = nai.getCurrentScore();
   5663         nai.setCurrentScore(score);
   5664 
   5665         rematchAllNetworksAndRequests(nai, oldScore);
   5666 
   5667         sendUpdatedScoreToFactories(nai);
   5668     }
   5669 
   5670     // Notify only this one new request of the current state. Transfer all the
   5671     // current state by calling NetworkCapabilities and LinkProperties callbacks
   5672     // so that callers can be guaranteed to have as close to atomicity in state
   5673     // transfer as can be supported by this current API.
   5674     protected void notifyNetworkAvailable(NetworkAgentInfo nai, NetworkRequestInfo nri) {
   5675         mHandler.removeMessages(EVENT_TIMEOUT_NETWORK_REQUEST, nri);
   5676         if (nri.mPendingIntent != null) {
   5677             sendPendingIntentForRequest(nri, nai, ConnectivityManager.CALLBACK_AVAILABLE);
   5678             // Attempt no subsequent state pushes where intents are involved.
   5679             return;
   5680         }
   5681 
   5682         callCallbackForRequest(nri, nai, ConnectivityManager.CALLBACK_AVAILABLE, 0);
   5683     }
   5684 
   5685     private void sendLegacyNetworkBroadcast(NetworkAgentInfo nai, DetailedState state, int type) {
   5686         // The NetworkInfo we actually send out has no bearing on the real
   5687         // state of affairs. For example, if the default connection is mobile,
   5688         // and a request for HIPRI has just gone away, we need to pretend that
   5689         // HIPRI has just disconnected. So we need to set the type to HIPRI and
   5690         // the state to DISCONNECTED, even though the network is of type MOBILE
   5691         // and is still connected.
   5692         NetworkInfo info = new NetworkInfo(nai.networkInfo);
   5693         info.setType(type);
   5694         if (state != DetailedState.DISCONNECTED) {
   5695             info.setDetailedState(state, null, info.getExtraInfo());
   5696             sendConnectedBroadcast(info);
   5697         } else {
   5698             info.setDetailedState(state, info.getReason(), info.getExtraInfo());
   5699             Intent intent = new Intent(ConnectivityManager.CONNECTIVITY_ACTION);
   5700             intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, info);
   5701             intent.putExtra(ConnectivityManager.EXTRA_NETWORK_TYPE, info.getType());
   5702             if (info.isFailover()) {
   5703                 intent.putExtra(ConnectivityManager.EXTRA_IS_FAILOVER, true);
   5704                 nai.networkInfo.setFailover(false);
   5705             }
   5706             if (info.getReason() != null) {
   5707                 intent.putExtra(ConnectivityManager.EXTRA_REASON, info.getReason());
   5708             }
   5709             if (info.getExtraInfo() != null) {
   5710                 intent.putExtra(ConnectivityManager.EXTRA_EXTRA_INFO, info.getExtraInfo());
   5711             }
   5712             NetworkAgentInfo newDefaultAgent = null;
   5713             if (nai.isSatisfyingRequest(mDefaultRequest.requestId)) {
   5714                 newDefaultAgent = getDefaultNetwork();
   5715                 if (newDefaultAgent != null) {
   5716                     intent.putExtra(ConnectivityManager.EXTRA_OTHER_NETWORK_INFO,
   5717                             newDefaultAgent.networkInfo);
   5718                 } else {
   5719                     intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, true);
   5720                 }
   5721             }
   5722             intent.putExtra(ConnectivityManager.EXTRA_INET_CONDITION,
   5723                     mDefaultInetConditionPublished);
   5724             sendStickyBroadcast(intent);
   5725             if (newDefaultAgent != null) {
   5726                 sendConnectedBroadcast(newDefaultAgent.networkInfo);
   5727             }
   5728         }
   5729     }
   5730 
   5731     protected void notifyNetworkCallbacks(NetworkAgentInfo networkAgent, int notifyType, int arg1) {
   5732         if (VDBG) {
   5733             String notification = ConnectivityManager.getCallbackName(notifyType);
   5734             log("notifyType " + notification + " for " + networkAgent.name());
   5735         }
   5736         for (int i = 0; i < networkAgent.numNetworkRequests(); i++) {
   5737             NetworkRequest nr = networkAgent.requestAt(i);
   5738             NetworkRequestInfo nri = mNetworkRequests.get(nr);
   5739             if (VDBG) log(" sending notification for " + nr);
   5740             // TODO: if we're in the middle of a rematch, can we send a CAP_CHANGED callback for
   5741             // a network that no longer satisfies the listen?
   5742             if (nri.mPendingIntent == null) {
   5743                 callCallbackForRequest(nri, networkAgent, notifyType, arg1);
   5744             } else {
   5745                 sendPendingIntentForRequest(nri, networkAgent, notifyType);
   5746             }
   5747         }
   5748     }
   5749 
   5750     protected void notifyNetworkCallbacks(NetworkAgentInfo networkAgent, int notifyType) {
   5751         notifyNetworkCallbacks(networkAgent, notifyType, 0);
   5752     }
   5753 
   5754     /**
   5755      * Returns the list of all interfaces that could be used by network traffic that does not
   5756      * explicitly specify a network. This includes the default network, but also all VPNs that are
   5757      * currently connected.
   5758      *
   5759      * Must be called on the handler thread.
   5760      */
   5761     private Network[] getDefaultNetworks() {
   5762         ArrayList<Network> defaultNetworks = new ArrayList<>();
   5763         NetworkAgentInfo defaultNetwork = getDefaultNetwork();
   5764         for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
   5765             if (nai.everConnected && (nai == defaultNetwork || nai.isVPN())) {
   5766                 defaultNetworks.add(nai.network);
   5767             }
   5768         }
   5769         return defaultNetworks.toArray(new Network[0]);
   5770     }
   5771 
   5772     /**
   5773      * Notify NetworkStatsService that the set of active ifaces has changed, or that one of the
   5774      * properties tracked by NetworkStatsService on an active iface has changed.
   5775      */
   5776     private void notifyIfacesChangedForNetworkStats() {
   5777         try {
   5778             mStatsService.forceUpdateIfaces(getDefaultNetworks());
   5779         } catch (Exception ignored) {
   5780         }
   5781     }
   5782 
   5783     @Override
   5784     public boolean addVpnAddress(String address, int prefixLength) {
   5785         int user = UserHandle.getUserId(Binder.getCallingUid());
   5786         synchronized (mVpns) {
   5787             throwIfLockdownEnabled();
   5788             return mVpns.get(user).addAddress(address, prefixLength);
   5789         }
   5790     }
   5791 
   5792     @Override
   5793     public boolean removeVpnAddress(String address, int prefixLength) {
   5794         int user = UserHandle.getUserId(Binder.getCallingUid());
   5795         synchronized (mVpns) {
   5796             throwIfLockdownEnabled();
   5797             return mVpns.get(user).removeAddress(address, prefixLength);
   5798         }
   5799     }
   5800 
   5801     @Override
   5802     public boolean setUnderlyingNetworksForVpn(Network[] networks) {
   5803         int user = UserHandle.getUserId(Binder.getCallingUid());
   5804         final boolean success;
   5805         synchronized (mVpns) {
   5806             throwIfLockdownEnabled();
   5807             success = mVpns.get(user).setUnderlyingNetworks(networks);
   5808         }
   5809         if (success) {
   5810             mHandler.post(() -> notifyIfacesChangedForNetworkStats());
   5811         }
   5812         return success;
   5813     }
   5814 
   5815     @Override
   5816     public String getCaptivePortalServerUrl() {
   5817         enforceConnectivityInternalPermission();
   5818         return NetworkMonitor.getCaptivePortalServerHttpUrl(mContext);
   5819     }
   5820 
   5821     @Override
   5822     public void startNattKeepalive(Network network, int intervalSeconds, Messenger messenger,
   5823             IBinder binder, String srcAddr, int srcPort, String dstAddr) {
   5824         enforceKeepalivePermission();
   5825         mKeepaliveTracker.startNattKeepalive(
   5826                 getNetworkAgentInfoForNetwork(network),
   5827                 intervalSeconds, messenger, binder,
   5828                 srcAddr, srcPort, dstAddr, ConnectivityManager.PacketKeepalive.NATT_PORT);
   5829     }
   5830 
   5831     @Override
   5832     public void stopKeepalive(Network network, int slot) {
   5833         mHandler.sendMessage(mHandler.obtainMessage(
   5834                 NetworkAgent.CMD_STOP_PACKET_KEEPALIVE, slot, PacketKeepalive.SUCCESS, network));
   5835     }
   5836 
   5837     @Override
   5838     public void factoryReset() {
   5839         enforceConnectivityInternalPermission();
   5840 
   5841         if (mUserManager.hasUserRestriction(UserManager.DISALLOW_NETWORK_RESET)) {
   5842             return;
   5843         }
   5844 
   5845         final int userId = UserHandle.getCallingUserId();
   5846 
   5847         // Turn airplane mode off
   5848         setAirplaneMode(false);
   5849 
   5850         if (!mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_TETHERING)) {
   5851             // Untether
   5852             String pkgName = mContext.getOpPackageName();
   5853             for (String tether : getTetheredIfaces()) {
   5854                 untether(tether, pkgName);
   5855             }
   5856         }
   5857 
   5858         if (!mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_VPN)) {
   5859             // Remove always-on package
   5860             synchronized (mVpns) {
   5861                 final String alwaysOnPackage = getAlwaysOnVpnPackage(userId);
   5862                 if (alwaysOnPackage != null) {
   5863                     setAlwaysOnVpnPackage(userId, null, false);
   5864                     setVpnPackageAuthorization(alwaysOnPackage, userId, false);
   5865                 }
   5866 
   5867                 // Turn Always-on VPN off
   5868                 if (mLockdownEnabled && userId == UserHandle.USER_SYSTEM) {
   5869                     final long ident = Binder.clearCallingIdentity();
   5870                     try {
   5871                         mKeyStore.delete(Credentials.LOCKDOWN_VPN);
   5872                         mLockdownEnabled = false;
   5873                         setLockdownTracker(null);
   5874                     } finally {
   5875                         Binder.restoreCallingIdentity(ident);
   5876                     }
   5877                 }
   5878 
   5879                 // Turn VPN off
   5880                 VpnConfig vpnConfig = getVpnConfig(userId);
   5881                 if (vpnConfig != null) {
   5882                     if (vpnConfig.legacy) {
   5883                         prepareVpn(VpnConfig.LEGACY_VPN, VpnConfig.LEGACY_VPN, userId);
   5884                     } else {
   5885                         // Prevent this app (packagename = vpnConfig.user) from initiating
   5886                         // VPN connections in the future without user intervention.
   5887                         setVpnPackageAuthorization(vpnConfig.user, userId, false);
   5888 
   5889                         prepareVpn(null, VpnConfig.LEGACY_VPN, userId);
   5890                     }
   5891                 }
   5892             }
   5893         }
   5894 
   5895         Settings.Global.putString(mContext.getContentResolver(),
   5896                 Settings.Global.NETWORK_AVOID_BAD_WIFI, null);
   5897     }
   5898 
   5899     @Override
   5900     public byte[] getNetworkWatchlistConfigHash() {
   5901         NetworkWatchlistManager nwm = mContext.getSystemService(NetworkWatchlistManager.class);
   5902         if (nwm == null) {
   5903             loge("Unable to get NetworkWatchlistManager");
   5904             return null;
   5905         }
   5906         // Redirect it to network watchlist service to access watchlist file and calculate hash.
   5907         return nwm.getWatchlistConfigHash();
   5908     }
   5909 
   5910     @VisibleForTesting
   5911     public NetworkMonitor createNetworkMonitor(Context context, Handler handler,
   5912             NetworkAgentInfo nai, NetworkRequest defaultRequest) {
   5913         return new NetworkMonitor(context, handler, nai, defaultRequest);
   5914     }
   5915 
   5916     @VisibleForTesting
   5917     MultinetworkPolicyTracker createMultinetworkPolicyTracker(Context c, Handler h, Runnable r) {
   5918         return new MultinetworkPolicyTracker(c, h, r);
   5919     }
   5920 
   5921     @VisibleForTesting
   5922     public WakeupMessage makeWakeupMessage(Context c, Handler h, String s, int cmd, Object obj) {
   5923         return new WakeupMessage(c, h, s, cmd, 0, 0, obj);
   5924     }
   5925 
   5926     @VisibleForTesting
   5927     public boolean hasService(String name) {
   5928         return ServiceManager.checkService(name) != null;
   5929     }
   5930 
   5931     @VisibleForTesting
   5932     protected IpConnectivityMetrics.Logger metricsLogger() {
   5933         return checkNotNull(LocalServices.getService(IpConnectivityMetrics.Logger.class),
   5934                 "no IpConnectivityMetrics service");
   5935     }
   5936 
   5937     private void logNetworkEvent(NetworkAgentInfo nai, int evtype) {
   5938         int[] transports = nai.networkCapabilities.getTransportTypes();
   5939         mMetricsLog.log(nai.network.netId, transports, new NetworkEvent(evtype));
   5940     }
   5941 
   5942     private static boolean toBool(int encodedBoolean) {
   5943         return encodedBoolean != 0; // Only 0 means false.
   5944     }
   5945 
   5946     private static int encodeBool(boolean b) {
   5947         return b ? 1 : 0;
   5948     }
   5949 
   5950     @Override
   5951     public void onShellCommand(FileDescriptor in, FileDescriptor out,
   5952             FileDescriptor err, String[] args, ShellCallback callback,
   5953             ResultReceiver resultReceiver) {
   5954         (new ShellCmd()).exec(this, in, out, err, args, callback, resultReceiver);
   5955     }
   5956 
   5957     private class ShellCmd extends ShellCommand {
   5958 
   5959         @Override
   5960         public int onCommand(String cmd) {
   5961             if (cmd == null) {
   5962                 return handleDefaultCommands(cmd);
   5963             }
   5964             final PrintWriter pw = getOutPrintWriter();
   5965             try {
   5966                 switch (cmd) {
   5967                     case "airplane-mode":
   5968                         final String action = getNextArg();
   5969                         if ("enable".equals(action)) {
   5970                             setAirplaneMode(true);
   5971                             return 0;
   5972                         } else if ("disable".equals(action)) {
   5973                             setAirplaneMode(false);
   5974                             return 0;
   5975                         } else if (action == null) {
   5976                             final ContentResolver cr = mContext.getContentResolver();
   5977                             final int enabled = Settings.Global.getInt(cr,
   5978                                     Settings.Global.AIRPLANE_MODE_ON);
   5979                             pw.println(enabled == 0 ? "disabled" : "enabled");
   5980                             return 0;
   5981                         } else {
   5982                             onHelp();
   5983                             return -1;
   5984                         }
   5985                     default:
   5986                         return handleDefaultCommands(cmd);
   5987                 }
   5988             } catch (Exception e) {
   5989                 pw.println(e);
   5990             }
   5991             return -1;
   5992         }
   5993 
   5994         @Override
   5995         public void onHelp() {
   5996             PrintWriter pw = getOutPrintWriter();
   5997             pw.println("Connectivity service commands:");
   5998             pw.println("  help");
   5999             pw.println("    Print this help text.");
   6000             pw.println("  airplane-mode [enable|disable]");
   6001             pw.println("    Turn airplane mode on or off.");
   6002             pw.println("  airplane-mode");
   6003             pw.println("    Get airplane mode.");
   6004         }
   6005     }
   6006 }
   6007