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