Home | History | Annotate | Download | only in server
      1 /*
      2  * Copyright (C) 2007 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.CONNECTIVITY_INTERNAL;
     20 import static android.Manifest.permission.DUMP;
     21 import static android.Manifest.permission.SHUTDOWN;
     22 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_DOZABLE;
     23 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_DOZABLE;
     24 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_NONE;
     25 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_POWERSAVE;
     26 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_STANDBY;
     27 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NONE;
     28 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_POWERSAVE;
     29 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_STANDBY;
     30 import static android.net.NetworkPolicyManager.FIREWALL_RULE_ALLOW;
     31 import static android.net.NetworkPolicyManager.FIREWALL_RULE_DEFAULT;
     32 import static android.net.NetworkPolicyManager.FIREWALL_RULE_DENY;
     33 import static android.net.NetworkPolicyManager.FIREWALL_TYPE_BLACKLIST;
     34 import static android.net.NetworkPolicyManager.FIREWALL_TYPE_WHITELIST;
     35 import static android.net.NetworkStats.SET_DEFAULT;
     36 import static android.net.NetworkStats.TAG_ALL;
     37 import static android.net.NetworkStats.TAG_NONE;
     38 import static android.net.NetworkStats.UID_ALL;
     39 import static android.net.TrafficStats.UID_TETHERING;
     40 import static com.android.server.NetworkManagementService.NetdResponseCode.ClatdStatusResult;
     41 import static com.android.server.NetworkManagementService.NetdResponseCode.InterfaceGetCfgResult;
     42 import static com.android.server.NetworkManagementService.NetdResponseCode.InterfaceListResult;
     43 import static com.android.server.NetworkManagementService.NetdResponseCode.IpFwdStatusResult;
     44 import static com.android.server.NetworkManagementService.NetdResponseCode.TetherDnsFwdTgtListResult;
     45 import static com.android.server.NetworkManagementService.NetdResponseCode.TetherInterfaceListResult;
     46 import static com.android.server.NetworkManagementService.NetdResponseCode.TetherStatusResult;
     47 import static com.android.server.NetworkManagementService.NetdResponseCode.TetheringStatsListResult;
     48 import static com.android.server.NetworkManagementService.NetdResponseCode.TtyListResult;
     49 import static com.android.server.NetworkManagementSocketTagger.PROP_QTAGUID_ENABLED;
     50 
     51 import android.annotation.NonNull;
     52 import android.app.ActivityManager;
     53 import android.content.ContentResolver;
     54 import android.content.Context;
     55 import android.net.ConnectivityManager;
     56 import android.net.INetd;
     57 import android.net.INetworkManagementEventObserver;
     58 import android.net.InterfaceConfiguration;
     59 import android.net.IpPrefix;
     60 import android.net.LinkAddress;
     61 import android.net.Network;
     62 import android.net.NetworkPolicyManager;
     63 import android.net.NetworkStats;
     64 import android.net.NetworkUtils;
     65 import android.net.RouteInfo;
     66 import android.net.UidRange;
     67 import android.net.wifi.WifiConfiguration;
     68 import android.net.wifi.WifiConfiguration.KeyMgmt;
     69 import android.os.BatteryStats;
     70 import android.os.Binder;
     71 import android.os.Handler;
     72 import android.os.INetworkActivityListener;
     73 import android.os.INetworkManagementService;
     74 import android.os.PowerManager;
     75 import android.os.Process;
     76 import android.os.RemoteCallbackList;
     77 import android.os.RemoteException;
     78 import android.os.ServiceManager;
     79 import android.os.ServiceSpecificException;
     80 import android.os.StrictMode;
     81 import android.os.SystemClock;
     82 import android.os.SystemProperties;
     83 import android.os.Trace;
     84 import android.provider.Settings;
     85 import android.telephony.DataConnectionRealTimeInfo;
     86 import android.telephony.PhoneStateListener;
     87 import android.telephony.SubscriptionManager;
     88 import android.telephony.TelephonyManager;
     89 import android.util.Log;
     90 import android.util.Slog;
     91 import android.util.SparseBooleanArray;
     92 import android.util.SparseIntArray;
     93 
     94 import com.android.internal.annotations.GuardedBy;
     95 import com.android.internal.annotations.VisibleForTesting;
     96 import com.android.internal.app.IBatteryStats;
     97 import com.android.internal.net.NetworkStatsFactory;
     98 import com.android.internal.util.DumpUtils;
     99 import com.android.internal.util.HexDump;
    100 import com.android.internal.util.Preconditions;
    101 import com.android.server.NativeDaemonConnector.Command;
    102 import com.android.server.NativeDaemonConnector.SensitiveArg;
    103 import com.android.server.net.LockdownVpnTracker;
    104 import com.google.android.collect.Maps;
    105 
    106 import java.io.BufferedReader;
    107 import java.io.DataInputStream;
    108 import java.io.File;
    109 import java.io.FileDescriptor;
    110 import java.io.FileInputStream;
    111 import java.io.IOException;
    112 import java.io.InputStreamReader;
    113 import java.io.PrintWriter;
    114 import java.net.InetAddress;
    115 import java.net.InterfaceAddress;
    116 import java.net.NetworkInterface;
    117 import java.net.SocketException;
    118 import java.util.ArrayList;
    119 import java.util.Arrays;
    120 import java.util.HashMap;
    121 import java.util.List;
    122 import java.util.Map;
    123 import java.util.NoSuchElementException;
    124 import java.util.StringTokenizer;
    125 import java.util.concurrent.CountDownLatch;
    126 
    127 /**
    128  * @hide
    129  */
    130 public class NetworkManagementService extends INetworkManagementService.Stub
    131         implements Watchdog.Monitor {
    132     private static final String TAG = "NetworkManagement";
    133     private static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG);
    134     private static final String NETD_TAG = "NetdConnector";
    135     private static final String NETD_SERVICE_NAME = "netd";
    136 
    137     private static final int MAX_UID_RANGES_PER_COMMAND = 10;
    138 
    139     /**
    140      * Name representing {@link #setGlobalAlert(long)} limit when delivered to
    141      * {@link INetworkManagementEventObserver#limitReached(String, String)}.
    142      */
    143     public static final String LIMIT_GLOBAL_ALERT = "globalAlert";
    144 
    145     /**
    146      * String to pass to netd to indicate that a network is only accessible
    147      * to apps that have the CHANGE_NETWORK_STATE permission.
    148      */
    149     public static final String PERMISSION_NETWORK = "NETWORK";
    150 
    151     /**
    152      * String to pass to netd to indicate that a network is only
    153      * accessible to system apps and those with the CONNECTIVITY_INTERNAL
    154      * permission.
    155      */
    156     public static final String PERMISSION_SYSTEM = "SYSTEM";
    157 
    158     class NetdResponseCode {
    159         /* Keep in sync with system/netd/server/ResponseCode.h */
    160         public static final int InterfaceListResult       = 110;
    161         public static final int TetherInterfaceListResult = 111;
    162         public static final int TetherDnsFwdTgtListResult = 112;
    163         public static final int TtyListResult             = 113;
    164         public static final int TetheringStatsListResult  = 114;
    165 
    166         public static final int TetherStatusResult        = 210;
    167         public static final int IpFwdStatusResult         = 211;
    168         public static final int InterfaceGetCfgResult     = 213;
    169         public static final int SoftapStatusResult        = 214;
    170         public static final int InterfaceRxCounterResult  = 216;
    171         public static final int InterfaceTxCounterResult  = 217;
    172         public static final int QuotaCounterResult        = 220;
    173         public static final int TetheringStatsResult      = 221;
    174         public static final int DnsProxyQueryResult       = 222;
    175         public static final int ClatdStatusResult         = 223;
    176 
    177         public static final int InterfaceChange           = 600;
    178         public static final int BandwidthControl          = 601;
    179         public static final int InterfaceClassActivity    = 613;
    180         public static final int InterfaceAddressChange    = 614;
    181         public static final int InterfaceDnsServerInfo    = 615;
    182         public static final int RouteChange               = 616;
    183         public static final int StrictCleartext           = 617;
    184     }
    185 
    186     /* Defaults for resolver parameters. */
    187     public static final int DNS_RESOLVER_DEFAULT_SAMPLE_VALIDITY_SECONDS = 1800;
    188     public static final int DNS_RESOLVER_DEFAULT_SUCCESS_THRESHOLD_PERCENT = 25;
    189     public static final int DNS_RESOLVER_DEFAULT_MIN_SAMPLES = 8;
    190     public static final int DNS_RESOLVER_DEFAULT_MAX_SAMPLES = 64;
    191 
    192     /**
    193      * String indicating a softap command.
    194      */
    195     static final String SOFT_AP_COMMAND = "softap";
    196 
    197     /**
    198      * String passed back to netd connector indicating softap command success.
    199      */
    200     static final String SOFT_AP_COMMAND_SUCCESS = "Ok";
    201 
    202     static final int DAEMON_MSG_MOBILE_CONN_REAL_TIME_INFO = 1;
    203 
    204     /**
    205      * Binder context for this service
    206      */
    207     private final Context mContext;
    208 
    209     /**
    210      * connector object for communicating with netd
    211      */
    212     private final NativeDaemonConnector mConnector;
    213 
    214     private final Handler mFgHandler;
    215     private final Handler mDaemonHandler;
    216 
    217     private INetd mNetdService;
    218 
    219     private IBatteryStats mBatteryStats;
    220 
    221     private final Thread mThread;
    222     private CountDownLatch mConnectedSignal = new CountDownLatch(1);
    223 
    224     private final RemoteCallbackList<INetworkManagementEventObserver> mObservers =
    225             new RemoteCallbackList<>();
    226 
    227     private final NetworkStatsFactory mStatsFactory = new NetworkStatsFactory();
    228 
    229     /**
    230      * If both locks need to be held, then they should be obtained in the order:
    231      * first {@link #mQuotaLock} and then {@link #mRulesLock}.
    232      */
    233     private Object mQuotaLock = new Object();
    234     private Object mRulesLock = new Object();
    235 
    236     /** Set of interfaces with active quotas. */
    237     @GuardedBy("mQuotaLock")
    238     private HashMap<String, Long> mActiveQuotas = Maps.newHashMap();
    239     /** Set of interfaces with active alerts. */
    240     @GuardedBy("mQuotaLock")
    241     private HashMap<String, Long> mActiveAlerts = Maps.newHashMap();
    242     /** Set of UIDs blacklisted on metered networks. */
    243     @GuardedBy("mRulesLock")
    244     private SparseBooleanArray mUidRejectOnMetered = new SparseBooleanArray();
    245     /** Set of UIDs whitelisted on metered networks. */
    246     @GuardedBy("mRulesLock")
    247     private SparseBooleanArray mUidAllowOnMetered = new SparseBooleanArray();
    248     /** Set of UIDs with cleartext penalties. */
    249     @GuardedBy("mQuotaLock")
    250     private SparseIntArray mUidCleartextPolicy = new SparseIntArray();
    251     /** Set of UIDs that are to be blocked/allowed by firewall controller. */
    252     @GuardedBy("mRulesLock")
    253     private SparseIntArray mUidFirewallRules = new SparseIntArray();
    254     /**
    255      * Set of UIDs that are to be blocked/allowed by firewall controller.  This set of Ids matches
    256      * to application idles.
    257      */
    258     @GuardedBy("mRulesLock")
    259     private SparseIntArray mUidFirewallStandbyRules = new SparseIntArray();
    260     /**
    261      * Set of UIDs that are to be blocked/allowed by firewall controller.  This set of Ids matches
    262      * to device idles.
    263      */
    264     @GuardedBy("mRulesLock")
    265     private SparseIntArray mUidFirewallDozableRules = new SparseIntArray();
    266     /**
    267      * Set of UIDs that are to be blocked/allowed by firewall controller.  This set of Ids matches
    268      * to device on power-save mode.
    269      */
    270     @GuardedBy("mRulesLock")
    271     private SparseIntArray mUidFirewallPowerSaveRules = new SparseIntArray();
    272     /** Set of states for the child firewall chains. True if the chain is active. */
    273     @GuardedBy("mRulesLock")
    274     final SparseBooleanArray mFirewallChainStates = new SparseBooleanArray();
    275 
    276     @GuardedBy("mQuotaLock")
    277     private volatile boolean mDataSaverMode;
    278 
    279     private Object mIdleTimerLock = new Object();
    280     /** Set of interfaces with active idle timers. */
    281     private static class IdleTimerParams {
    282         public final int timeout;
    283         public final int type;
    284         public int networkCount;
    285 
    286         IdleTimerParams(int timeout, int type) {
    287             this.timeout = timeout;
    288             this.type = type;
    289             this.networkCount = 1;
    290         }
    291     }
    292     private HashMap<String, IdleTimerParams> mActiveIdleTimers = Maps.newHashMap();
    293 
    294     private volatile boolean mBandwidthControlEnabled;
    295     private volatile boolean mFirewallEnabled;
    296     private volatile boolean mStrictEnabled;
    297 
    298     private boolean mMobileActivityFromRadio = false;
    299     private int mLastPowerStateFromRadio = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
    300     private int mLastPowerStateFromWifi = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
    301 
    302     private final RemoteCallbackList<INetworkActivityListener> mNetworkActivityListeners =
    303             new RemoteCallbackList<>();
    304     private boolean mNetworkActive;
    305 
    306     /**
    307      * Constructs a new NetworkManagementService instance
    308      *
    309      * @param context  Binder context for this service
    310      */
    311     private NetworkManagementService(Context context, String socket) {
    312         mContext = context;
    313 
    314         // make sure this is on the same looper as our NativeDaemonConnector for sync purposes
    315         mFgHandler = new Handler(FgThread.get().getLooper());
    316 
    317         // Don't need this wake lock, since we now have a time stamp for when
    318         // the network actually went inactive.  (It might be nice to still do this,
    319         // but I don't want to do it through the power manager because that pollutes the
    320         // battery stats history with pointless noise.)
    321         //PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
    322         PowerManager.WakeLock wl = null; //pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, NETD_TAG);
    323 
    324         mConnector = new NativeDaemonConnector(
    325                 new NetdCallbackReceiver(), socket, 10, NETD_TAG, 160, wl,
    326                 FgThread.get().getLooper());
    327         mThread = new Thread(mConnector, NETD_TAG);
    328 
    329         mDaemonHandler = new Handler(FgThread.get().getLooper());
    330 
    331         // Add ourself to the Watchdog monitors.
    332         Watchdog.getInstance().addMonitor(this);
    333 
    334         LocalServices.addService(NetworkManagementInternal.class, new LocalService());
    335     }
    336 
    337     @VisibleForTesting
    338     NetworkManagementService() {
    339         mConnector = null;
    340         mContext = null;
    341         mDaemonHandler = null;
    342         mFgHandler = null;
    343         mThread = null;
    344     }
    345 
    346     static NetworkManagementService create(Context context, String socket)
    347             throws InterruptedException {
    348         final NetworkManagementService service = new NetworkManagementService(context, socket);
    349         final CountDownLatch connectedSignal = service.mConnectedSignal;
    350         if (DBG) Slog.d(TAG, "Creating NetworkManagementService");
    351         service.mThread.start();
    352         if (DBG) Slog.d(TAG, "Awaiting socket connection");
    353         connectedSignal.await();
    354         if (DBG) Slog.d(TAG, "Connected");
    355         service.connectNativeNetdService();
    356         return service;
    357     }
    358 
    359     public static NetworkManagementService create(Context context) throws InterruptedException {
    360         return create(context, NETD_SERVICE_NAME);
    361     }
    362 
    363     public void systemReady() {
    364         if (DBG) {
    365             final long start = System.currentTimeMillis();
    366             prepareNativeDaemon();
    367             final long delta = System.currentTimeMillis() - start;
    368             Slog.d(TAG, "Prepared in " + delta + "ms");
    369             return;
    370         } else {
    371             prepareNativeDaemon();
    372         }
    373     }
    374 
    375     private IBatteryStats getBatteryStats() {
    376         synchronized (this) {
    377             if (mBatteryStats != null) {
    378                 return mBatteryStats;
    379             }
    380             mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService(
    381                     BatteryStats.SERVICE_NAME));
    382             return mBatteryStats;
    383         }
    384     }
    385 
    386     @Override
    387     public void registerObserver(INetworkManagementEventObserver observer) {
    388         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
    389         mObservers.register(observer);
    390     }
    391 
    392     @Override
    393     public void unregisterObserver(INetworkManagementEventObserver observer) {
    394         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
    395         mObservers.unregister(observer);
    396     }
    397 
    398     @FunctionalInterface
    399     private interface NetworkManagementEventCallback {
    400         public void sendCallback(INetworkManagementEventObserver o) throws RemoteException;
    401     }
    402 
    403     private void invokeForAllObservers(NetworkManagementEventCallback eventCallback) {
    404         final int length = mObservers.beginBroadcast();
    405         try {
    406             for (int i = 0; i < length; i++) {
    407                 try {
    408                     eventCallback.sendCallback(mObservers.getBroadcastItem(i));
    409                 } catch (RemoteException | RuntimeException e) {
    410                 }
    411             }
    412         } finally {
    413             mObservers.finishBroadcast();
    414         }
    415     }
    416 
    417     /**
    418      * Notify our observers of an interface status change
    419      */
    420     private void notifyInterfaceStatusChanged(String iface, boolean up) {
    421         invokeForAllObservers(o -> o.interfaceStatusChanged(iface, up));
    422     }
    423 
    424     /**
    425      * Notify our observers of an interface link state change
    426      * (typically, an Ethernet cable has been plugged-in or unplugged).
    427      */
    428     private void notifyInterfaceLinkStateChanged(String iface, boolean up) {
    429         invokeForAllObservers(o -> o.interfaceLinkStateChanged(iface, up));
    430     }
    431 
    432     /**
    433      * Notify our observers of an interface addition.
    434      */
    435     private void notifyInterfaceAdded(String iface) {
    436         invokeForAllObservers(o -> o.interfaceAdded(iface));
    437     }
    438 
    439     /**
    440      * Notify our observers of an interface removal.
    441      */
    442     private void notifyInterfaceRemoved(String iface) {
    443         // netd already clears out quota and alerts for removed ifaces; update
    444         // our sanity-checking state.
    445         mActiveAlerts.remove(iface);
    446         mActiveQuotas.remove(iface);
    447 
    448         invokeForAllObservers(o -> o.interfaceRemoved(iface));
    449     }
    450 
    451     /**
    452      * Notify our observers of a limit reached.
    453      */
    454     private void notifyLimitReached(String limitName, String iface) {
    455         invokeForAllObservers(o -> o.limitReached(limitName, iface));
    456     }
    457 
    458     /**
    459      * Notify our observers of a change in the data activity state of the interface
    460      */
    461     private void notifyInterfaceClassActivity(int type, int powerState, long tsNanos,
    462             int uid, boolean fromRadio) {
    463         final boolean isMobile = ConnectivityManager.isNetworkTypeMobile(type);
    464         if (isMobile) {
    465             if (!fromRadio) {
    466                 if (mMobileActivityFromRadio) {
    467                     // If this call is not coming from a report from the radio itself, but we
    468                     // have previously received reports from the radio, then we will take the
    469                     // power state to just be whatever the radio last reported.
    470                     powerState = mLastPowerStateFromRadio;
    471                 }
    472             } else {
    473                 mMobileActivityFromRadio = true;
    474             }
    475             if (mLastPowerStateFromRadio != powerState) {
    476                 mLastPowerStateFromRadio = powerState;
    477                 try {
    478                     getBatteryStats().noteMobileRadioPowerState(powerState, tsNanos, uid);
    479                 } catch (RemoteException e) {
    480                 }
    481             }
    482         }
    483 
    484         if (ConnectivityManager.isNetworkTypeWifi(type)) {
    485             if (mLastPowerStateFromWifi != powerState) {
    486                 mLastPowerStateFromWifi = powerState;
    487                 try {
    488                     getBatteryStats().noteWifiRadioPowerState(powerState, tsNanos, uid);
    489                 } catch (RemoteException e) {
    490                 }
    491             }
    492         }
    493 
    494         boolean isActive = powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_MEDIUM
    495                 || powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH;
    496 
    497         if (!isMobile || fromRadio || !mMobileActivityFromRadio) {
    498             // Report the change in data activity.  We don't do this if this is a change
    499             // on the mobile network, that is not coming from the radio itself, and we
    500             // have previously seen change reports from the radio.  In that case only
    501             // the radio is the authority for the current state.
    502             final boolean active = isActive;
    503             invokeForAllObservers(o -> o.interfaceClassDataActivityChanged(
    504                     Integer.toString(type), active, tsNanos));
    505         }
    506 
    507         boolean report = false;
    508         synchronized (mIdleTimerLock) {
    509             if (mActiveIdleTimers.isEmpty()) {
    510                 // If there are no idle timers, we are not monitoring activity, so we
    511                 // are always considered active.
    512                 isActive = true;
    513             }
    514             if (mNetworkActive != isActive) {
    515                 mNetworkActive = isActive;
    516                 report = isActive;
    517             }
    518         }
    519         if (report) {
    520             reportNetworkActive();
    521         }
    522     }
    523 
    524     // Sync the state of the given chain with the native daemon.
    525     private void syncFirewallChainLocked(int chain, String name) {
    526         SparseIntArray rules;
    527         synchronized (mRulesLock) {
    528             final SparseIntArray uidFirewallRules = getUidFirewallRulesLR(chain);
    529             // Make a copy of the current rules, and then clear them. This is because
    530             // setFirewallUidRuleInternal only pushes down rules to the native daemon if they
    531             // are different from the current rules stored in the mUidFirewall*Rules array for
    532             // the specified chain. If we don't clear the rules, setFirewallUidRuleInternal
    533             // will do nothing.
    534             rules = uidFirewallRules.clone();
    535             uidFirewallRules.clear();
    536         }
    537         if (rules.size() > 0) {
    538             // Now push the rules. setFirewallUidRuleInternal will push each of these down to the
    539             // native daemon, and also add them to the mUidFirewall*Rules array for the specified
    540             // chain.
    541             if (DBG) Slog.d(TAG, "Pushing " + rules.size() + " active firewall "
    542                     + name + "UID rules");
    543             for (int i = 0; i < rules.size(); i++) {
    544                 setFirewallUidRuleLocked(chain, rules.keyAt(i), rules.valueAt(i));
    545             }
    546         }
    547     }
    548 
    549     private void connectNativeNetdService() {
    550         boolean nativeServiceAvailable = false;
    551         try {
    552             mNetdService = INetd.Stub.asInterface(ServiceManager.getService(NETD_SERVICE_NAME));
    553             nativeServiceAvailable = mNetdService.isAlive();
    554         } catch (RemoteException e) {}
    555         if (!nativeServiceAvailable) {
    556             Slog.wtf(TAG, "Can't connect to NativeNetdService " + NETD_SERVICE_NAME);
    557         }
    558     }
    559 
    560     /**
    561      * Prepare native daemon once connected, enabling modules and pushing any
    562      * existing in-memory rules.
    563      */
    564     private void prepareNativeDaemon() {
    565 
    566         mBandwidthControlEnabled = false;
    567 
    568         // only enable bandwidth control when support exists
    569         final boolean hasKernelSupport = new File("/proc/net/xt_qtaguid/ctrl").exists();
    570         if (hasKernelSupport) {
    571             Slog.d(TAG, "enabling bandwidth control");
    572             try {
    573                 mConnector.execute("bandwidth", "enable");
    574                 mBandwidthControlEnabled = true;
    575             } catch (NativeDaemonConnectorException e) {
    576                 Log.wtf(TAG, "problem enabling bandwidth controls", e);
    577             }
    578         } else {
    579             Slog.i(TAG, "not enabling bandwidth control");
    580         }
    581 
    582         SystemProperties.set(PROP_QTAGUID_ENABLED, mBandwidthControlEnabled ? "1" : "0");
    583 
    584         if (mBandwidthControlEnabled) {
    585             try {
    586                 getBatteryStats().noteNetworkStatsEnabled();
    587             } catch (RemoteException e) {
    588             }
    589         }
    590 
    591         try {
    592             mConnector.execute("strict", "enable");
    593             mStrictEnabled = true;
    594         } catch (NativeDaemonConnectorException e) {
    595             Log.wtf(TAG, "Failed strict enable", e);
    596         }
    597 
    598         // push any existing quota or UID rules
    599         synchronized (mQuotaLock) {
    600 
    601             setDataSaverModeEnabled(mDataSaverMode);
    602 
    603             int size = mActiveQuotas.size();
    604             if (size > 0) {
    605                 if (DBG) Slog.d(TAG, "Pushing " + size + " active quota rules");
    606                 final HashMap<String, Long> activeQuotas = mActiveQuotas;
    607                 mActiveQuotas = Maps.newHashMap();
    608                 for (Map.Entry<String, Long> entry : activeQuotas.entrySet()) {
    609                     setInterfaceQuota(entry.getKey(), entry.getValue());
    610                 }
    611             }
    612 
    613             size = mActiveAlerts.size();
    614             if (size > 0) {
    615                 if (DBG) Slog.d(TAG, "Pushing " + size + " active alert rules");
    616                 final HashMap<String, Long> activeAlerts = mActiveAlerts;
    617                 mActiveAlerts = Maps.newHashMap();
    618                 for (Map.Entry<String, Long> entry : activeAlerts.entrySet()) {
    619                     setInterfaceAlert(entry.getKey(), entry.getValue());
    620                 }
    621             }
    622 
    623             SparseBooleanArray uidRejectOnQuota = null;
    624             SparseBooleanArray uidAcceptOnQuota = null;
    625             synchronized (mRulesLock) {
    626                 size = mUidRejectOnMetered.size();
    627                 if (size > 0) {
    628                     if (DBG) Slog.d(TAG, "Pushing " + size + " UIDs to metered blacklist rules");
    629                     uidRejectOnQuota = mUidRejectOnMetered;
    630                     mUidRejectOnMetered = new SparseBooleanArray();
    631                 }
    632 
    633                 size = mUidAllowOnMetered.size();
    634                 if (size > 0) {
    635                     if (DBG) Slog.d(TAG, "Pushing " + size + " UIDs to metered whitelist rules");
    636                     uidAcceptOnQuota = mUidAllowOnMetered;
    637                     mUidAllowOnMetered = new SparseBooleanArray();
    638                 }
    639             }
    640             if (uidRejectOnQuota != null) {
    641                 for (int i = 0; i < uidRejectOnQuota.size(); i++) {
    642                     setUidMeteredNetworkBlacklist(uidRejectOnQuota.keyAt(i),
    643                             uidRejectOnQuota.valueAt(i));
    644                 }
    645             }
    646             if (uidAcceptOnQuota != null) {
    647                 for (int i = 0; i < uidAcceptOnQuota.size(); i++) {
    648                     setUidMeteredNetworkWhitelist(uidAcceptOnQuota.keyAt(i),
    649                             uidAcceptOnQuota.valueAt(i));
    650                 }
    651             }
    652 
    653             size = mUidCleartextPolicy.size();
    654             if (size > 0) {
    655                 if (DBG) Slog.d(TAG, "Pushing " + size + " active UID cleartext policies");
    656                 final SparseIntArray local = mUidCleartextPolicy;
    657                 mUidCleartextPolicy = new SparseIntArray();
    658                 for (int i = 0; i < local.size(); i++) {
    659                     setUidCleartextNetworkPolicy(local.keyAt(i), local.valueAt(i));
    660                 }
    661             }
    662 
    663             setFirewallEnabled(mFirewallEnabled || LockdownVpnTracker.isEnabled());
    664 
    665             syncFirewallChainLocked(FIREWALL_CHAIN_NONE, "");
    666             syncFirewallChainLocked(FIREWALL_CHAIN_STANDBY, "standby ");
    667             syncFirewallChainLocked(FIREWALL_CHAIN_DOZABLE, "dozable ");
    668             syncFirewallChainLocked(FIREWALL_CHAIN_POWERSAVE, "powersave ");
    669 
    670             final int[] chains =
    671                     {FIREWALL_CHAIN_STANDBY, FIREWALL_CHAIN_DOZABLE, FIREWALL_CHAIN_POWERSAVE};
    672             for (int chain : chains) {
    673                 if (getFirewallChainState(chain)) {
    674                     setFirewallChainEnabled(chain, true);
    675                 }
    676             }
    677         }
    678     }
    679 
    680     /**
    681      * Notify our observers of a new or updated interface address.
    682      */
    683     private void notifyAddressUpdated(String iface, LinkAddress address) {
    684         invokeForAllObservers(o -> o.addressUpdated(iface, address));
    685     }
    686 
    687     /**
    688      * Notify our observers of a deleted interface address.
    689      */
    690     private void notifyAddressRemoved(String iface, LinkAddress address) {
    691         invokeForAllObservers(o -> o.addressRemoved(iface, address));
    692     }
    693 
    694     /**
    695      * Notify our observers of DNS server information received.
    696      */
    697     private void notifyInterfaceDnsServerInfo(String iface, long lifetime, String[] addresses) {
    698         invokeForAllObservers(o -> o.interfaceDnsServerInfo(iface, lifetime, addresses));
    699     }
    700 
    701     /**
    702      * Notify our observers of a route change.
    703      */
    704     private void notifyRouteChange(String action, RouteInfo route) {
    705         if (action.equals("updated")) {
    706             invokeForAllObservers(o -> o.routeUpdated(route));
    707         } else {
    708             invokeForAllObservers(o -> o.routeRemoved(route));
    709         }
    710     }
    711 
    712     //
    713     // Netd Callback handling
    714     //
    715 
    716     private class NetdCallbackReceiver implements INativeDaemonConnectorCallbacks {
    717         @Override
    718         public void onDaemonConnected() {
    719             Slog.i(TAG, "onDaemonConnected()");
    720             // event is dispatched from internal NDC thread, so we prepare the
    721             // daemon back on main thread.
    722             if (mConnectedSignal != null) {
    723                 // The system is booting and we're connecting to netd for the first time.
    724                 mConnectedSignal.countDown();
    725                 mConnectedSignal = null;
    726             } else {
    727                 // We're reconnecting to netd after the socket connection
    728                 // was interrupted (e.g., if it crashed).
    729                 mFgHandler.post(new Runnable() {
    730                     @Override
    731                     public void run() {
    732                         connectNativeNetdService();
    733                         prepareNativeDaemon();
    734                     }
    735                 });
    736             }
    737         }
    738 
    739         @Override
    740         public boolean onCheckHoldWakeLock(int code) {
    741             return code == NetdResponseCode.InterfaceClassActivity;
    742         }
    743 
    744         @Override
    745         public boolean onEvent(int code, String raw, String[] cooked) {
    746             String errorMessage = String.format("Invalid event from daemon (%s)", raw);
    747             switch (code) {
    748             case NetdResponseCode.InterfaceChange:
    749                     /*
    750                      * a network interface change occured
    751                      * Format: "NNN Iface added <name>"
    752                      *         "NNN Iface removed <name>"
    753                      *         "NNN Iface changed <name> <up/down>"
    754                      *         "NNN Iface linkstatus <name> <up/down>"
    755                      */
    756                     if (cooked.length < 4 || !cooked[1].equals("Iface")) {
    757                         throw new IllegalStateException(errorMessage);
    758                     }
    759                     if (cooked[2].equals("added")) {
    760                         notifyInterfaceAdded(cooked[3]);
    761                         return true;
    762                     } else if (cooked[2].equals("removed")) {
    763                         notifyInterfaceRemoved(cooked[3]);
    764                         return true;
    765                     } else if (cooked[2].equals("changed") && cooked.length == 5) {
    766                         notifyInterfaceStatusChanged(cooked[3], cooked[4].equals("up"));
    767                         return true;
    768                     } else if (cooked[2].equals("linkstate") && cooked.length == 5) {
    769                         notifyInterfaceLinkStateChanged(cooked[3], cooked[4].equals("up"));
    770                         return true;
    771                     }
    772                     throw new IllegalStateException(errorMessage);
    773                     // break;
    774             case NetdResponseCode.BandwidthControl:
    775                     /*
    776                      * Bandwidth control needs some attention
    777                      * Format: "NNN limit alert <alertName> <ifaceName>"
    778                      */
    779                     if (cooked.length < 5 || !cooked[1].equals("limit")) {
    780                         throw new IllegalStateException(errorMessage);
    781                     }
    782                     if (cooked[2].equals("alert")) {
    783                         notifyLimitReached(cooked[3], cooked[4]);
    784                         return true;
    785                     }
    786                     throw new IllegalStateException(errorMessage);
    787                     // break;
    788             case NetdResponseCode.InterfaceClassActivity:
    789                     /*
    790                      * An network interface class state changed (active/idle)
    791                      * Format: "NNN IfaceClass <active/idle> <label>"
    792                      */
    793                     if (cooked.length < 4 || !cooked[1].equals("IfaceClass")) {
    794                         throw new IllegalStateException(errorMessage);
    795                     }
    796                     long timestampNanos = 0;
    797                     int processUid = -1;
    798                     if (cooked.length >= 5) {
    799                         try {
    800                             timestampNanos = Long.parseLong(cooked[4]);
    801                             if (cooked.length == 6) {
    802                                 processUid = Integer.parseInt(cooked[5]);
    803                             }
    804                         } catch(NumberFormatException ne) {}
    805                     } else {
    806                         timestampNanos = SystemClock.elapsedRealtimeNanos();
    807                     }
    808                     boolean isActive = cooked[2].equals("active");
    809                     notifyInterfaceClassActivity(Integer.parseInt(cooked[3]),
    810                             isActive ? DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH
    811                             : DataConnectionRealTimeInfo.DC_POWER_STATE_LOW,
    812                             timestampNanos, processUid, false);
    813                     return true;
    814                     // break;
    815             case NetdResponseCode.InterfaceAddressChange:
    816                     /*
    817                      * A network address change occurred
    818                      * Format: "NNN Address updated <addr> <iface> <flags> <scope>"
    819                      *         "NNN Address removed <addr> <iface> <flags> <scope>"
    820                      */
    821                     if (cooked.length < 7 || !cooked[1].equals("Address")) {
    822                         throw new IllegalStateException(errorMessage);
    823                     }
    824 
    825                     String iface = cooked[4];
    826                     LinkAddress address;
    827                     try {
    828                         int flags = Integer.parseInt(cooked[5]);
    829                         int scope = Integer.parseInt(cooked[6]);
    830                         address = new LinkAddress(cooked[3], flags, scope);
    831                     } catch(NumberFormatException e) {     // Non-numeric lifetime or scope.
    832                         throw new IllegalStateException(errorMessage, e);
    833                     } catch(IllegalArgumentException e) {  // Malformed/invalid IP address.
    834                         throw new IllegalStateException(errorMessage, e);
    835                     }
    836 
    837                     if (cooked[2].equals("updated")) {
    838                         notifyAddressUpdated(iface, address);
    839                     } else {
    840                         notifyAddressRemoved(iface, address);
    841                     }
    842                     return true;
    843                     // break;
    844             case NetdResponseCode.InterfaceDnsServerInfo:
    845                     /*
    846                      * Information about available DNS servers has been received.
    847                      * Format: "NNN DnsInfo servers <interface> <lifetime> <servers>"
    848                      */
    849                     long lifetime;  // Actually a 32-bit unsigned integer.
    850 
    851                     if (cooked.length == 6 &&
    852                         cooked[1].equals("DnsInfo") &&
    853                         cooked[2].equals("servers")) {
    854                         try {
    855                             lifetime = Long.parseLong(cooked[4]);
    856                         } catch (NumberFormatException e) {
    857                             throw new IllegalStateException(errorMessage);
    858                         }
    859                         String[] servers = cooked[5].split(",");
    860                         notifyInterfaceDnsServerInfo(cooked[3], lifetime, servers);
    861                     }
    862                     return true;
    863                     // break;
    864             case NetdResponseCode.RouteChange:
    865                     /*
    866                      * A route has been updated or removed.
    867                      * Format: "NNN Route <updated|removed> <dst> [via <gateway] [dev <iface>]"
    868                      */
    869                     if (!cooked[1].equals("Route") || cooked.length < 6) {
    870                         throw new IllegalStateException(errorMessage);
    871                     }
    872 
    873                     String via = null;
    874                     String dev = null;
    875                     boolean valid = true;
    876                     for (int i = 4; (i + 1) < cooked.length && valid; i += 2) {
    877                         if (cooked[i].equals("dev")) {
    878                             if (dev == null) {
    879                                 dev = cooked[i+1];
    880                             } else {
    881                                 valid = false;  // Duplicate interface.
    882                             }
    883                         } else if (cooked[i].equals("via")) {
    884                             if (via == null) {
    885                                 via = cooked[i+1];
    886                             } else {
    887                                 valid = false;  // Duplicate gateway.
    888                             }
    889                         } else {
    890                             valid = false;      // Unknown syntax.
    891                         }
    892                     }
    893                     if (valid) {
    894                         try {
    895                             // InetAddress.parseNumericAddress(null) inexplicably returns ::1.
    896                             InetAddress gateway = null;
    897                             if (via != null) gateway = InetAddress.parseNumericAddress(via);
    898                             RouteInfo route = new RouteInfo(new IpPrefix(cooked[3]), gateway, dev);
    899                             notifyRouteChange(cooked[2], route);
    900                             return true;
    901                         } catch (IllegalArgumentException e) {}
    902                     }
    903                     throw new IllegalStateException(errorMessage);
    904                     // break;
    905             case NetdResponseCode.StrictCleartext:
    906                 final int uid = Integer.parseInt(cooked[1]);
    907                 final byte[] firstPacket = HexDump.hexStringToByteArray(cooked[2]);
    908                 try {
    909                     ActivityManager.getService().notifyCleartextNetwork(uid, firstPacket);
    910                 } catch (RemoteException ignored) {
    911                 }
    912                 break;
    913             default: break;
    914             }
    915             return false;
    916         }
    917     }
    918 
    919 
    920     //
    921     // INetworkManagementService members
    922     //
    923     @Override
    924     public INetd getNetdService() throws RemoteException {
    925         final CountDownLatch connectedSignal = mConnectedSignal;
    926         if (connectedSignal != null) {
    927             try {
    928                 connectedSignal.await();
    929             } catch (InterruptedException ignored) {}
    930         }
    931 
    932         return mNetdService;
    933     }
    934 
    935     @Override
    936     public String[] listInterfaces() {
    937         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
    938         try {
    939             return NativeDaemonEvent.filterMessageList(
    940                     mConnector.executeForList("interface", "list"), InterfaceListResult);
    941         } catch (NativeDaemonConnectorException e) {
    942             throw e.rethrowAsParcelableException();
    943         }
    944     }
    945 
    946     @Override
    947     public InterfaceConfiguration getInterfaceConfig(String iface) {
    948         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
    949 
    950         final NativeDaemonEvent event;
    951         try {
    952             event = mConnector.execute("interface", "getcfg", iface);
    953         } catch (NativeDaemonConnectorException e) {
    954             throw e.rethrowAsParcelableException();
    955         }
    956 
    957         event.checkCode(InterfaceGetCfgResult);
    958 
    959         // Rsp: 213 xx:xx:xx:xx:xx:xx yyy.yyy.yyy.yyy zzz flag1 flag2 flag3
    960         final StringTokenizer st = new StringTokenizer(event.getMessage());
    961 
    962         InterfaceConfiguration cfg;
    963         try {
    964             cfg = new InterfaceConfiguration();
    965             cfg.setHardwareAddress(st.nextToken(" "));
    966             InetAddress addr = null;
    967             int prefixLength = 0;
    968             try {
    969                 addr = NetworkUtils.numericToInetAddress(st.nextToken());
    970             } catch (IllegalArgumentException iae) {
    971                 Slog.e(TAG, "Failed to parse ipaddr", iae);
    972             }
    973 
    974             try {
    975                 prefixLength = Integer.parseInt(st.nextToken());
    976             } catch (NumberFormatException nfe) {
    977                 Slog.e(TAG, "Failed to parse prefixLength", nfe);
    978             }
    979 
    980             cfg.setLinkAddress(new LinkAddress(addr, prefixLength));
    981             while (st.hasMoreTokens()) {
    982                 cfg.setFlag(st.nextToken());
    983             }
    984         } catch (NoSuchElementException nsee) {
    985             throw new IllegalStateException("Invalid response from daemon: " + event);
    986         }
    987         return cfg;
    988     }
    989 
    990     @Override
    991     public void setInterfaceConfig(String iface, InterfaceConfiguration cfg) {
    992         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
    993         LinkAddress linkAddr = cfg.getLinkAddress();
    994         if (linkAddr == null || linkAddr.getAddress() == null) {
    995             throw new IllegalStateException("Null LinkAddress given");
    996         }
    997 
    998         final Command cmd = new Command("interface", "setcfg", iface,
    999                 linkAddr.getAddress().getHostAddress(),
   1000                 linkAddr.getPrefixLength());
   1001         for (String flag : cfg.getFlags()) {
   1002             cmd.appendArg(flag);
   1003         }
   1004 
   1005         try {
   1006             mConnector.execute(cmd);
   1007         } catch (NativeDaemonConnectorException e) {
   1008             throw e.rethrowAsParcelableException();
   1009         }
   1010     }
   1011 
   1012     @Override
   1013     public void setInterfaceDown(String iface) {
   1014         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
   1015         final InterfaceConfiguration ifcg = getInterfaceConfig(iface);
   1016         ifcg.setInterfaceDown();
   1017         setInterfaceConfig(iface, ifcg);
   1018     }
   1019 
   1020     @Override
   1021     public void setInterfaceUp(String iface) {
   1022         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
   1023         final InterfaceConfiguration ifcg = getInterfaceConfig(iface);
   1024         ifcg.setInterfaceUp();
   1025         setInterfaceConfig(iface, ifcg);
   1026     }
   1027 
   1028     @Override
   1029     public void setInterfaceIpv6PrivacyExtensions(String iface, boolean enable) {
   1030         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
   1031         try {
   1032             mConnector.execute(
   1033                     "interface", "ipv6privacyextensions", iface, enable ? "enable" : "disable");
   1034         } catch (NativeDaemonConnectorException e) {
   1035             throw e.rethrowAsParcelableException();
   1036         }
   1037     }
   1038 
   1039     /* TODO: This is right now a IPv4 only function. Works for wifi which loses its
   1040        IPv6 addresses on interface down, but we need to do full clean up here */
   1041     @Override
   1042     public void clearInterfaceAddresses(String iface) {
   1043         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
   1044         try {
   1045             mConnector.execute("interface", "clearaddrs", iface);
   1046         } catch (NativeDaemonConnectorException e) {
   1047             throw e.rethrowAsParcelableException();
   1048         }
   1049     }
   1050 
   1051     @Override
   1052     public void enableIpv6(String iface) {
   1053         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
   1054         try {
   1055             mConnector.execute("interface", "ipv6", iface, "enable");
   1056         } catch (NativeDaemonConnectorException e) {
   1057             throw e.rethrowAsParcelableException();
   1058         }
   1059     }
   1060 
   1061     @Override
   1062     public void disableIpv6(String iface) {
   1063         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
   1064         try {
   1065             mConnector.execute("interface", "ipv6", iface, "disable");
   1066         } catch (NativeDaemonConnectorException e) {
   1067             throw e.rethrowAsParcelableException();
   1068         }
   1069     }
   1070 
   1071     @Override
   1072     public void setInterfaceIpv6NdOffload(String iface, boolean enable) {
   1073         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
   1074         try {
   1075             mConnector.execute(
   1076                     "interface", "ipv6ndoffload", iface, (enable ? "enable" : "disable"));
   1077         } catch (NativeDaemonConnectorException e) {
   1078             throw e.rethrowAsParcelableException();
   1079         }
   1080     }
   1081 
   1082     @Override
   1083     public void addRoute(int netId, RouteInfo route) {
   1084         modifyRoute("add", "" + netId, route);
   1085     }
   1086 
   1087     @Override
   1088     public void removeRoute(int netId, RouteInfo route) {
   1089         modifyRoute("remove", "" + netId, route);
   1090     }
   1091 
   1092     private void modifyRoute(String action, String netId, RouteInfo route) {
   1093         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
   1094 
   1095         final Command cmd = new Command("network", "route", action, netId);
   1096 
   1097         // create triplet: interface dest-ip-addr/prefixlength gateway-ip-addr
   1098         cmd.appendArg(route.getInterface());
   1099         cmd.appendArg(route.getDestination().toString());
   1100 
   1101         switch (route.getType()) {
   1102             case RouteInfo.RTN_UNICAST:
   1103                 if (route.hasGateway()) {
   1104                     cmd.appendArg(route.getGateway().getHostAddress());
   1105                 }
   1106                 break;
   1107             case RouteInfo.RTN_UNREACHABLE:
   1108                 cmd.appendArg("unreachable");
   1109                 break;
   1110             case RouteInfo.RTN_THROW:
   1111                 cmd.appendArg("throw");
   1112                 break;
   1113         }
   1114 
   1115         try {
   1116             mConnector.execute(cmd);
   1117         } catch (NativeDaemonConnectorException e) {
   1118             throw e.rethrowAsParcelableException();
   1119         }
   1120     }
   1121 
   1122     private ArrayList<String> readRouteList(String filename) {
   1123         FileInputStream fstream = null;
   1124         ArrayList<String> list = new ArrayList<>();
   1125 
   1126         try {
   1127             fstream = new FileInputStream(filename);
   1128             DataInputStream in = new DataInputStream(fstream);
   1129             BufferedReader br = new BufferedReader(new InputStreamReader(in));
   1130             String s;
   1131 
   1132             // throw away the title line
   1133 
   1134             while (((s = br.readLine()) != null) && (s.length() != 0)) {
   1135                 list.add(s);
   1136             }
   1137         } catch (IOException ex) {
   1138             // return current list, possibly empty
   1139         } finally {
   1140             if (fstream != null) {
   1141                 try {
   1142                     fstream.close();
   1143                 } catch (IOException ex) {}
   1144             }
   1145         }
   1146 
   1147         return list;
   1148     }
   1149 
   1150     @Override
   1151     public void setMtu(String iface, int mtu) {
   1152         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
   1153 
   1154         final NativeDaemonEvent event;
   1155         try {
   1156             event = mConnector.execute("interface", "setmtu", iface, mtu);
   1157         } catch (NativeDaemonConnectorException e) {
   1158             throw e.rethrowAsParcelableException();
   1159         }
   1160     }
   1161 
   1162     @Override
   1163     public void shutdown() {
   1164         // TODO: remove from aidl if nobody calls externally
   1165         mContext.enforceCallingOrSelfPermission(SHUTDOWN, TAG);
   1166 
   1167         Slog.i(TAG, "Shutting down");
   1168     }
   1169 
   1170     @Override
   1171     public boolean getIpForwardingEnabled() throws IllegalStateException{
   1172         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
   1173 
   1174         final NativeDaemonEvent event;
   1175         try {
   1176             event = mConnector.execute("ipfwd", "status");
   1177         } catch (NativeDaemonConnectorException e) {
   1178             throw e.rethrowAsParcelableException();
   1179         }
   1180 
   1181         // 211 Forwarding enabled
   1182         event.checkCode(IpFwdStatusResult);
   1183         return event.getMessage().endsWith("enabled");
   1184     }
   1185 
   1186     @Override
   1187     public void setIpForwardingEnabled(boolean enable) {
   1188         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
   1189         try {
   1190             mConnector.execute("ipfwd", enable ? "enable" : "disable", "tethering");
   1191         } catch (NativeDaemonConnectorException e) {
   1192             throw e.rethrowAsParcelableException();
   1193         }
   1194     }
   1195 
   1196     @Override
   1197     public void startTethering(String[] dhcpRange) {
   1198         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
   1199         // cmd is "tether start first_start first_stop second_start second_stop ..."
   1200         // an odd number of addrs will fail
   1201 
   1202         final Command cmd = new Command("tether", "start");
   1203         for (String d : dhcpRange) {
   1204             cmd.appendArg(d);
   1205         }
   1206 
   1207         try {
   1208             mConnector.execute(cmd);
   1209         } catch (NativeDaemonConnectorException e) {
   1210             throw e.rethrowAsParcelableException();
   1211         }
   1212     }
   1213 
   1214     @Override
   1215     public void stopTethering() {
   1216         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
   1217         try {
   1218             mConnector.execute("tether", "stop");
   1219         } catch (NativeDaemonConnectorException e) {
   1220             throw e.rethrowAsParcelableException();
   1221         }
   1222     }
   1223 
   1224     @Override
   1225     public boolean isTetheringStarted() {
   1226         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
   1227 
   1228         final NativeDaemonEvent event;
   1229         try {
   1230             event = mConnector.execute("tether", "status");
   1231         } catch (NativeDaemonConnectorException e) {
   1232             throw e.rethrowAsParcelableException();
   1233         }
   1234 
   1235         // 210 Tethering services started
   1236         event.checkCode(TetherStatusResult);
   1237         return event.getMessage().endsWith("started");
   1238     }
   1239 
   1240     @Override
   1241     public void tetherInterface(String iface) {
   1242         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
   1243         try {
   1244             mConnector.execute("tether", "interface", "add", iface);
   1245         } catch (NativeDaemonConnectorException e) {
   1246             throw e.rethrowAsParcelableException();
   1247         }
   1248         List<RouteInfo> routes = new ArrayList<>();
   1249         // The RouteInfo constructor truncates the LinkAddress to a network prefix, thus making it
   1250         // suitable to use as a route destination.
   1251         routes.add(new RouteInfo(getInterfaceConfig(iface).getLinkAddress(), null, iface));
   1252         addInterfaceToLocalNetwork(iface, routes);
   1253     }
   1254 
   1255     @Override
   1256     public void untetherInterface(String iface) {
   1257         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
   1258         try {
   1259             mConnector.execute("tether", "interface", "remove", iface);
   1260         } catch (NativeDaemonConnectorException e) {
   1261             throw e.rethrowAsParcelableException();
   1262         } finally {
   1263             removeInterfaceFromLocalNetwork(iface);
   1264         }
   1265     }
   1266 
   1267     @Override
   1268     public String[] listTetheredInterfaces() {
   1269         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
   1270         try {
   1271             return NativeDaemonEvent.filterMessageList(
   1272                     mConnector.executeForList("tether", "interface", "list"),
   1273                     TetherInterfaceListResult);
   1274         } catch (NativeDaemonConnectorException e) {
   1275             throw e.rethrowAsParcelableException();
   1276         }
   1277     }
   1278 
   1279     @Override
   1280     public void setDnsForwarders(Network network, String[] dns) {
   1281         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
   1282 
   1283         int netId = (network != null) ? network.netId : ConnectivityManager.NETID_UNSET;
   1284         final Command cmd = new Command("tether", "dns", "set", netId);
   1285 
   1286         for (String s : dns) {
   1287             cmd.appendArg(NetworkUtils.numericToInetAddress(s).getHostAddress());
   1288         }
   1289 
   1290         try {
   1291             mConnector.execute(cmd);
   1292         } catch (NativeDaemonConnectorException e) {
   1293             throw e.rethrowAsParcelableException();
   1294         }
   1295     }
   1296 
   1297     @Override
   1298     public String[] getDnsForwarders() {
   1299         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
   1300         try {
   1301             return NativeDaemonEvent.filterMessageList(
   1302                     mConnector.executeForList("tether", "dns", "list"), TetherDnsFwdTgtListResult);
   1303         } catch (NativeDaemonConnectorException e) {
   1304             throw e.rethrowAsParcelableException();
   1305         }
   1306     }
   1307 
   1308     private List<InterfaceAddress> excludeLinkLocal(List<InterfaceAddress> addresses) {
   1309         ArrayList<InterfaceAddress> filtered = new ArrayList<>(addresses.size());
   1310         for (InterfaceAddress ia : addresses) {
   1311             if (!ia.getAddress().isLinkLocalAddress())
   1312                 filtered.add(ia);
   1313         }
   1314         return filtered;
   1315     }
   1316 
   1317     private void modifyInterfaceForward(boolean add, String fromIface, String toIface) {
   1318         final Command cmd = new Command("ipfwd", add ? "add" : "remove", fromIface, toIface);
   1319         try {
   1320             mConnector.execute(cmd);
   1321         } catch (NativeDaemonConnectorException e) {
   1322             throw e.rethrowAsParcelableException();
   1323         }
   1324     }
   1325 
   1326     @Override
   1327     public void startInterfaceForwarding(String fromIface, String toIface) {
   1328         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
   1329         modifyInterfaceForward(true, fromIface, toIface);
   1330     }
   1331 
   1332     @Override
   1333     public void stopInterfaceForwarding(String fromIface, String toIface) {
   1334         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
   1335         modifyInterfaceForward(false, fromIface, toIface);
   1336     }
   1337 
   1338     private void modifyNat(String action, String internalInterface, String externalInterface)
   1339             throws SocketException {
   1340         final Command cmd = new Command("nat", action, internalInterface, externalInterface);
   1341 
   1342         final NetworkInterface internalNetworkInterface = NetworkInterface.getByName(
   1343                 internalInterface);
   1344         if (internalNetworkInterface == null) {
   1345             cmd.appendArg("0");
   1346         } else {
   1347             // Don't touch link-local routes, as link-local addresses aren't routable,
   1348             // kernel creates link-local routes on all interfaces automatically
   1349             List<InterfaceAddress> interfaceAddresses = excludeLinkLocal(
   1350                     internalNetworkInterface.getInterfaceAddresses());
   1351             cmd.appendArg(interfaceAddresses.size());
   1352             for (InterfaceAddress ia : interfaceAddresses) {
   1353                 InetAddress addr = NetworkUtils.getNetworkPart(
   1354                         ia.getAddress(), ia.getNetworkPrefixLength());
   1355                 cmd.appendArg(addr.getHostAddress() + "/" + ia.getNetworkPrefixLength());
   1356             }
   1357         }
   1358 
   1359         try {
   1360             mConnector.execute(cmd);
   1361         } catch (NativeDaemonConnectorException e) {
   1362             throw e.rethrowAsParcelableException();
   1363         }
   1364     }
   1365 
   1366     @Override
   1367     public void enableNat(String internalInterface, String externalInterface) {
   1368         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
   1369         try {
   1370             modifyNat("enable", internalInterface, externalInterface);
   1371         } catch (SocketException e) {
   1372             throw new IllegalStateException(e);
   1373         }
   1374     }
   1375 
   1376     @Override
   1377     public void disableNat(String internalInterface, String externalInterface) {
   1378         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
   1379         try {
   1380             modifyNat("disable", internalInterface, externalInterface);
   1381         } catch (SocketException e) {
   1382             throw new IllegalStateException(e);
   1383         }
   1384     }
   1385 
   1386     @Override
   1387     public String[] listTtys() {
   1388         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
   1389         try {
   1390             return NativeDaemonEvent.filterMessageList(
   1391                     mConnector.executeForList("list_ttys"), TtyListResult);
   1392         } catch (NativeDaemonConnectorException e) {
   1393             throw e.rethrowAsParcelableException();
   1394         }
   1395     }
   1396 
   1397     @Override
   1398     public void attachPppd(
   1399             String tty, String localAddr, String remoteAddr, String dns1Addr, String dns2Addr) {
   1400         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
   1401         try {
   1402             mConnector.execute("pppd", "attach", tty,
   1403                     NetworkUtils.numericToInetAddress(localAddr).getHostAddress(),
   1404                     NetworkUtils.numericToInetAddress(remoteAddr).getHostAddress(),
   1405                     NetworkUtils.numericToInetAddress(dns1Addr).getHostAddress(),
   1406                     NetworkUtils.numericToInetAddress(dns2Addr).getHostAddress());
   1407         } catch (NativeDaemonConnectorException e) {
   1408             throw e.rethrowAsParcelableException();
   1409         }
   1410     }
   1411 
   1412     @Override
   1413     public void detachPppd(String tty) {
   1414         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
   1415         try {
   1416             mConnector.execute("pppd", "detach", tty);
   1417         } catch (NativeDaemonConnectorException e) {
   1418             throw e.rethrowAsParcelableException();
   1419         }
   1420     }
   1421 
   1422     @Override
   1423     public void addIdleTimer(String iface, int timeout, final int type) {
   1424         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
   1425 
   1426         if (DBG) Slog.d(TAG, "Adding idletimer");
   1427 
   1428         synchronized (mIdleTimerLock) {
   1429             IdleTimerParams params = mActiveIdleTimers.get(iface);
   1430             if (params != null) {
   1431                 // the interface already has idletimer, update network count
   1432                 params.networkCount++;
   1433                 return;
   1434             }
   1435 
   1436             try {
   1437                 mConnector.execute("idletimer", "add", iface, Integer.toString(timeout),
   1438                         Integer.toString(type));
   1439             } catch (NativeDaemonConnectorException e) {
   1440                 throw e.rethrowAsParcelableException();
   1441             }
   1442             mActiveIdleTimers.put(iface, new IdleTimerParams(timeout, type));
   1443 
   1444             // Networks start up.
   1445             if (ConnectivityManager.isNetworkTypeMobile(type)) {
   1446                 mNetworkActive = false;
   1447             }
   1448             mDaemonHandler.post(new Runnable() {
   1449                 @Override public void run() {
   1450                     notifyInterfaceClassActivity(type,
   1451                             DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH,
   1452                             SystemClock.elapsedRealtimeNanos(), -1, false);
   1453                 }
   1454             });
   1455         }
   1456     }
   1457 
   1458     @Override
   1459     public void removeIdleTimer(String iface) {
   1460         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
   1461 
   1462         if (DBG) Slog.d(TAG, "Removing idletimer");
   1463 
   1464         synchronized (mIdleTimerLock) {
   1465             final IdleTimerParams params = mActiveIdleTimers.get(iface);
   1466             if (params == null || --(params.networkCount) > 0) {
   1467                 return;
   1468             }
   1469 
   1470             try {
   1471                 mConnector.execute("idletimer", "remove", iface,
   1472                         Integer.toString(params.timeout), Integer.toString(params.type));
   1473             } catch (NativeDaemonConnectorException e) {
   1474                 throw e.rethrowAsParcelableException();
   1475             }
   1476             mActiveIdleTimers.remove(iface);
   1477             mDaemonHandler.post(new Runnable() {
   1478                 @Override public void run() {
   1479                     notifyInterfaceClassActivity(params.type,
   1480                             DataConnectionRealTimeInfo.DC_POWER_STATE_LOW,
   1481                             SystemClock.elapsedRealtimeNanos(), -1, false);
   1482                 }
   1483             });
   1484         }
   1485     }
   1486 
   1487     @Override
   1488     public NetworkStats getNetworkStatsSummaryDev() {
   1489         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
   1490         try {
   1491             return mStatsFactory.readNetworkStatsSummaryDev();
   1492         } catch (IOException e) {
   1493             throw new IllegalStateException(e);
   1494         }
   1495     }
   1496 
   1497     @Override
   1498     public NetworkStats getNetworkStatsSummaryXt() {
   1499         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
   1500         try {
   1501             return mStatsFactory.readNetworkStatsSummaryXt();
   1502         } catch (IOException e) {
   1503             throw new IllegalStateException(e);
   1504         }
   1505     }
   1506 
   1507     @Override
   1508     public NetworkStats getNetworkStatsDetail() {
   1509         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
   1510         try {
   1511             return mStatsFactory.readNetworkStatsDetail(UID_ALL, null, TAG_ALL, null);
   1512         } catch (IOException e) {
   1513             throw new IllegalStateException(e);
   1514         }
   1515     }
   1516 
   1517     @Override
   1518     public void setInterfaceQuota(String iface, long quotaBytes) {
   1519         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
   1520 
   1521         // silently discard when control disabled
   1522         // TODO: eventually migrate to be always enabled
   1523         if (!mBandwidthControlEnabled) return;
   1524 
   1525         synchronized (mQuotaLock) {
   1526             if (mActiveQuotas.containsKey(iface)) {
   1527                 throw new IllegalStateException("iface " + iface + " already has quota");
   1528             }
   1529 
   1530             try {
   1531                 // TODO: support quota shared across interfaces
   1532                 mConnector.execute("bandwidth", "setiquota", iface, quotaBytes);
   1533                 mActiveQuotas.put(iface, quotaBytes);
   1534             } catch (NativeDaemonConnectorException e) {
   1535                 throw e.rethrowAsParcelableException();
   1536             }
   1537         }
   1538     }
   1539 
   1540     @Override
   1541     public void removeInterfaceQuota(String iface) {
   1542         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
   1543 
   1544         // silently discard when control disabled
   1545         // TODO: eventually migrate to be always enabled
   1546         if (!mBandwidthControlEnabled) return;
   1547 
   1548         synchronized (mQuotaLock) {
   1549             if (!mActiveQuotas.containsKey(iface)) {
   1550                 // TODO: eventually consider throwing
   1551                 return;
   1552             }
   1553 
   1554             mActiveQuotas.remove(iface);
   1555             mActiveAlerts.remove(iface);
   1556 
   1557             try {
   1558                 // TODO: support quota shared across interfaces
   1559                 mConnector.execute("bandwidth", "removeiquota", iface);
   1560             } catch (NativeDaemonConnectorException e) {
   1561                 throw e.rethrowAsParcelableException();
   1562             }
   1563         }
   1564     }
   1565 
   1566     @Override
   1567     public void setInterfaceAlert(String iface, long alertBytes) {
   1568         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
   1569 
   1570         // silently discard when control disabled
   1571         // TODO: eventually migrate to be always enabled
   1572         if (!mBandwidthControlEnabled) return;
   1573 
   1574         // quick sanity check
   1575         if (!mActiveQuotas.containsKey(iface)) {
   1576             throw new IllegalStateException("setting alert requires existing quota on iface");
   1577         }
   1578 
   1579         synchronized (mQuotaLock) {
   1580             if (mActiveAlerts.containsKey(iface)) {
   1581                 throw new IllegalStateException("iface " + iface + " already has alert");
   1582             }
   1583 
   1584             try {
   1585                 // TODO: support alert shared across interfaces
   1586                 mConnector.execute("bandwidth", "setinterfacealert", iface, alertBytes);
   1587                 mActiveAlerts.put(iface, alertBytes);
   1588             } catch (NativeDaemonConnectorException e) {
   1589                 throw e.rethrowAsParcelableException();
   1590             }
   1591         }
   1592     }
   1593 
   1594     @Override
   1595     public void removeInterfaceAlert(String iface) {
   1596         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
   1597 
   1598         // silently discard when control disabled
   1599         // TODO: eventually migrate to be always enabled
   1600         if (!mBandwidthControlEnabled) return;
   1601 
   1602         synchronized (mQuotaLock) {
   1603             if (!mActiveAlerts.containsKey(iface)) {
   1604                 // TODO: eventually consider throwing
   1605                 return;
   1606             }
   1607 
   1608             try {
   1609                 // TODO: support alert shared across interfaces
   1610                 mConnector.execute("bandwidth", "removeinterfacealert", iface);
   1611                 mActiveAlerts.remove(iface);
   1612             } catch (NativeDaemonConnectorException e) {
   1613                 throw e.rethrowAsParcelableException();
   1614             }
   1615         }
   1616     }
   1617 
   1618     @Override
   1619     public void setGlobalAlert(long alertBytes) {
   1620         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
   1621 
   1622         // silently discard when control disabled
   1623         // TODO: eventually migrate to be always enabled
   1624         if (!mBandwidthControlEnabled) return;
   1625 
   1626         try {
   1627             mConnector.execute("bandwidth", "setglobalalert", alertBytes);
   1628         } catch (NativeDaemonConnectorException e) {
   1629             throw e.rethrowAsParcelableException();
   1630         }
   1631     }
   1632 
   1633     private void setUidOnMeteredNetworkList(int uid, boolean blacklist, boolean enable) {
   1634         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
   1635 
   1636         // silently discard when control disabled
   1637         // TODO: eventually migrate to be always enabled
   1638         if (!mBandwidthControlEnabled) return;
   1639 
   1640         final String chain = blacklist ? "naughtyapps" : "niceapps";
   1641         final String suffix = enable ? "add" : "remove";
   1642 
   1643         synchronized (mQuotaLock) {
   1644             boolean oldEnable;
   1645             SparseBooleanArray quotaList;
   1646             synchronized (mRulesLock) {
   1647                 quotaList = blacklist ? mUidRejectOnMetered : mUidAllowOnMetered;
   1648                 oldEnable = quotaList.get(uid, false);
   1649             }
   1650             if (oldEnable == enable) {
   1651                 // TODO: eventually consider throwing
   1652                 return;
   1653             }
   1654 
   1655             Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "inetd bandwidth");
   1656             try {
   1657                 mConnector.execute("bandwidth", suffix + chain, uid);
   1658                 synchronized (mRulesLock) {
   1659                     if (enable) {
   1660                         quotaList.put(uid, true);
   1661                     } else {
   1662                         quotaList.delete(uid);
   1663                     }
   1664                 }
   1665             } catch (NativeDaemonConnectorException e) {
   1666                 throw e.rethrowAsParcelableException();
   1667             } finally {
   1668                 Trace.traceEnd(Trace.TRACE_TAG_NETWORK);
   1669             }
   1670         }
   1671     }
   1672 
   1673     @Override
   1674     public void setUidMeteredNetworkBlacklist(int uid, boolean enable) {
   1675         setUidOnMeteredNetworkList(uid, true, enable);
   1676     }
   1677 
   1678     @Override
   1679     public void setUidMeteredNetworkWhitelist(int uid, boolean enable) {
   1680         setUidOnMeteredNetworkList(uid, false, enable);
   1681     }
   1682 
   1683     @Override
   1684     public boolean setDataSaverModeEnabled(boolean enable) {
   1685         if (DBG) Log.d(TAG, "setDataSaverMode: " + enable);
   1686         synchronized (mQuotaLock) {
   1687             if (mDataSaverMode == enable) {
   1688                 Log.w(TAG, "setDataSaverMode(): already " + mDataSaverMode);
   1689                 return true;
   1690             }
   1691             Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "bandwidthEnableDataSaver");
   1692             try {
   1693                 final boolean changed = mNetdService.bandwidthEnableDataSaver(enable);
   1694                 if (changed) {
   1695                     mDataSaverMode = enable;
   1696                 } else {
   1697                     Log.w(TAG, "setDataSaverMode(" + enable + "): netd command silently failed");
   1698                 }
   1699                 return changed;
   1700             } catch (RemoteException e) {
   1701                 Log.w(TAG, "setDataSaverMode(" + enable + "): netd command failed", e);
   1702                 return false;
   1703             } finally {
   1704                 Trace.traceEnd(Trace.TRACE_TAG_NETWORK);
   1705             }
   1706         }
   1707     }
   1708 
   1709     @Override
   1710     public void setAllowOnlyVpnForUids(boolean add, UidRange[] uidRanges)
   1711             throws ServiceSpecificException {
   1712         try {
   1713             mNetdService.networkRejectNonSecureVpn(add, uidRanges);
   1714         } catch (ServiceSpecificException e) {
   1715             Log.w(TAG, "setAllowOnlyVpnForUids(" + add + ", " + Arrays.toString(uidRanges) + ")"
   1716                     + ": netd command failed", e);
   1717             throw e;
   1718         } catch (RemoteException e) {
   1719             Log.w(TAG, "setAllowOnlyVpnForUids(" + add + ", " + Arrays.toString(uidRanges) + ")"
   1720                     + ": netd command failed", e);
   1721             throw e.rethrowAsRuntimeException();
   1722         }
   1723     }
   1724 
   1725     @Override
   1726     public void setUidCleartextNetworkPolicy(int uid, int policy) {
   1727         if (Binder.getCallingUid() != uid) {
   1728             mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
   1729         }
   1730 
   1731         synchronized (mQuotaLock) {
   1732             final int oldPolicy = mUidCleartextPolicy.get(uid, StrictMode.NETWORK_POLICY_ACCEPT);
   1733             if (oldPolicy == policy) {
   1734                 return;
   1735             }
   1736 
   1737             if (!mStrictEnabled) {
   1738                 // Module isn't enabled yet; stash the requested policy away to
   1739                 // apply later once the daemon is connected.
   1740                 mUidCleartextPolicy.put(uid, policy);
   1741                 return;
   1742             }
   1743 
   1744             final String policyString;
   1745             switch (policy) {
   1746                 case StrictMode.NETWORK_POLICY_ACCEPT:
   1747                     policyString = "accept";
   1748                     break;
   1749                 case StrictMode.NETWORK_POLICY_LOG:
   1750                     policyString = "log";
   1751                     break;
   1752                 case StrictMode.NETWORK_POLICY_REJECT:
   1753                     policyString = "reject";
   1754                     break;
   1755                 default:
   1756                     throw new IllegalArgumentException("Unknown policy " + policy);
   1757             }
   1758 
   1759             try {
   1760                 mConnector.execute("strict", "set_uid_cleartext_policy", uid, policyString);
   1761                 mUidCleartextPolicy.put(uid, policy);
   1762             } catch (NativeDaemonConnectorException e) {
   1763                 throw e.rethrowAsParcelableException();
   1764             }
   1765         }
   1766     }
   1767 
   1768     @Override
   1769     public boolean isBandwidthControlEnabled() {
   1770         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
   1771         return mBandwidthControlEnabled;
   1772     }
   1773 
   1774     @Override
   1775     public NetworkStats getNetworkStatsUidDetail(int uid) {
   1776         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
   1777         try {
   1778             return mStatsFactory.readNetworkStatsDetail(uid, null, TAG_ALL, null);
   1779         } catch (IOException e) {
   1780             throw new IllegalStateException(e);
   1781         }
   1782     }
   1783 
   1784     @Override
   1785     public NetworkStats getNetworkStatsTethering() {
   1786         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
   1787 
   1788         final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 1);
   1789         try {
   1790             final NativeDaemonEvent[] events = mConnector.executeForList(
   1791                     "bandwidth", "gettetherstats");
   1792             for (NativeDaemonEvent event : events) {
   1793                 if (event.getCode() != TetheringStatsListResult) continue;
   1794 
   1795                 // 114 ifaceIn ifaceOut rx_bytes rx_packets tx_bytes tx_packets
   1796                 final StringTokenizer tok = new StringTokenizer(event.getMessage());
   1797                 try {
   1798                     final String ifaceIn = tok.nextToken();
   1799                     final String ifaceOut = tok.nextToken();
   1800 
   1801                     final NetworkStats.Entry entry = new NetworkStats.Entry();
   1802                     entry.iface = ifaceOut;
   1803                     entry.uid = UID_TETHERING;
   1804                     entry.set = SET_DEFAULT;
   1805                     entry.tag = TAG_NONE;
   1806                     entry.rxBytes = Long.parseLong(tok.nextToken());
   1807                     entry.rxPackets = Long.parseLong(tok.nextToken());
   1808                     entry.txBytes = Long.parseLong(tok.nextToken());
   1809                     entry.txPackets = Long.parseLong(tok.nextToken());
   1810                     stats.combineValues(entry);
   1811                 } catch (NoSuchElementException e) {
   1812                     throw new IllegalStateException("problem parsing tethering stats: " + event);
   1813                 } catch (NumberFormatException e) {
   1814                     throw new IllegalStateException("problem parsing tethering stats: " + event);
   1815                 }
   1816             }
   1817         } catch (NativeDaemonConnectorException e) {
   1818             throw e.rethrowAsParcelableException();
   1819         }
   1820         return stats;
   1821     }
   1822 
   1823     @Override
   1824     public void setDnsConfigurationForNetwork(int netId, String[] servers, String domains) {
   1825         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
   1826 
   1827         ContentResolver resolver = mContext.getContentResolver();
   1828 
   1829         int sampleValidity = Settings.Global.getInt(resolver,
   1830                 Settings.Global.DNS_RESOLVER_SAMPLE_VALIDITY_SECONDS,
   1831                 DNS_RESOLVER_DEFAULT_SAMPLE_VALIDITY_SECONDS);
   1832         if (sampleValidity < 0 || sampleValidity > 65535) {
   1833             Slog.w(TAG, "Invalid sampleValidity=" + sampleValidity + ", using default=" +
   1834                     DNS_RESOLVER_DEFAULT_SAMPLE_VALIDITY_SECONDS);
   1835             sampleValidity = DNS_RESOLVER_DEFAULT_SAMPLE_VALIDITY_SECONDS;
   1836         }
   1837 
   1838         int successThreshold = Settings.Global.getInt(resolver,
   1839                 Settings.Global.DNS_RESOLVER_SUCCESS_THRESHOLD_PERCENT,
   1840                 DNS_RESOLVER_DEFAULT_SUCCESS_THRESHOLD_PERCENT);
   1841         if (successThreshold < 0 || successThreshold > 100) {
   1842             Slog.w(TAG, "Invalid successThreshold=" + successThreshold + ", using default=" +
   1843                     DNS_RESOLVER_DEFAULT_SUCCESS_THRESHOLD_PERCENT);
   1844             successThreshold = DNS_RESOLVER_DEFAULT_SUCCESS_THRESHOLD_PERCENT;
   1845         }
   1846 
   1847         int minSamples = Settings.Global.getInt(resolver,
   1848                 Settings.Global.DNS_RESOLVER_MIN_SAMPLES, DNS_RESOLVER_DEFAULT_MIN_SAMPLES);
   1849         int maxSamples = Settings.Global.getInt(resolver,
   1850                 Settings.Global.DNS_RESOLVER_MAX_SAMPLES, DNS_RESOLVER_DEFAULT_MAX_SAMPLES);
   1851         if (minSamples < 0 || minSamples > maxSamples || maxSamples > 64) {
   1852             Slog.w(TAG, "Invalid sample count (min, max)=(" + minSamples + ", " + maxSamples +
   1853                     "), using default=(" + DNS_RESOLVER_DEFAULT_MIN_SAMPLES + ", " +
   1854                     DNS_RESOLVER_DEFAULT_MAX_SAMPLES + ")");
   1855             minSamples = DNS_RESOLVER_DEFAULT_MIN_SAMPLES;
   1856             maxSamples = DNS_RESOLVER_DEFAULT_MAX_SAMPLES;
   1857         }
   1858 
   1859         final String[] domainStrs = domains == null ? new String[0] : domains.split(" ");
   1860         final int[] params = { sampleValidity, successThreshold, minSamples, maxSamples };
   1861         try {
   1862             mNetdService.setResolverConfiguration(netId, servers, domainStrs, params);
   1863         } catch (RemoteException e) {
   1864             throw new RuntimeException(e);
   1865         }
   1866     }
   1867 
   1868     @Override
   1869     public void addVpnUidRanges(int netId, UidRange[] ranges) {
   1870         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
   1871         Object[] argv = new Object[3 + MAX_UID_RANGES_PER_COMMAND];
   1872         argv[0] = "users";
   1873         argv[1] = "add";
   1874         argv[2] = netId;
   1875         int argc = 3;
   1876         // Avoid overly long commands by limiting number of UID ranges per command.
   1877         for (int i = 0; i < ranges.length; i++) {
   1878             argv[argc++] = ranges[i].toString();
   1879             if (i == (ranges.length - 1) || argc == argv.length) {
   1880                 try {
   1881                     mConnector.execute("network", Arrays.copyOf(argv, argc));
   1882                 } catch (NativeDaemonConnectorException e) {
   1883                     throw e.rethrowAsParcelableException();
   1884                 }
   1885                 argc = 3;
   1886             }
   1887         }
   1888     }
   1889 
   1890     @Override
   1891     public void removeVpnUidRanges(int netId, UidRange[] ranges) {
   1892         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
   1893         Object[] argv = new Object[3 + MAX_UID_RANGES_PER_COMMAND];
   1894         argv[0] = "users";
   1895         argv[1] = "remove";
   1896         argv[2] = netId;
   1897         int argc = 3;
   1898         // Avoid overly long commands by limiting number of UID ranges per command.
   1899         for (int i = 0; i < ranges.length; i++) {
   1900             argv[argc++] = ranges[i].toString();
   1901             if (i == (ranges.length - 1) || argc == argv.length) {
   1902                 try {
   1903                     mConnector.execute("network", Arrays.copyOf(argv, argc));
   1904                 } catch (NativeDaemonConnectorException e) {
   1905                     throw e.rethrowAsParcelableException();
   1906                 }
   1907                 argc = 3;
   1908             }
   1909         }
   1910     }
   1911 
   1912     @Override
   1913     public void setFirewallEnabled(boolean enabled) {
   1914         enforceSystemUid();
   1915         try {
   1916             mConnector.execute("firewall", "enable", enabled ? "whitelist" : "blacklist");
   1917             mFirewallEnabled = enabled;
   1918         } catch (NativeDaemonConnectorException e) {
   1919             throw e.rethrowAsParcelableException();
   1920         }
   1921     }
   1922 
   1923     @Override
   1924     public boolean isFirewallEnabled() {
   1925         enforceSystemUid();
   1926         return mFirewallEnabled;
   1927     }
   1928 
   1929     @Override
   1930     public void setFirewallInterfaceRule(String iface, boolean allow) {
   1931         enforceSystemUid();
   1932         Preconditions.checkState(mFirewallEnabled);
   1933         final String rule = allow ? "allow" : "deny";
   1934         try {
   1935             mConnector.execute("firewall", "set_interface_rule", iface, rule);
   1936         } catch (NativeDaemonConnectorException e) {
   1937             throw e.rethrowAsParcelableException();
   1938         }
   1939     }
   1940 
   1941     @Override
   1942     public void setFirewallEgressSourceRule(String addr, boolean allow) {
   1943         enforceSystemUid();
   1944         Preconditions.checkState(mFirewallEnabled);
   1945         final String rule = allow ? "allow" : "deny";
   1946         try {
   1947             mConnector.execute("firewall", "set_egress_source_rule", addr, rule);
   1948         } catch (NativeDaemonConnectorException e) {
   1949             throw e.rethrowAsParcelableException();
   1950         }
   1951     }
   1952 
   1953     @Override
   1954     public void setFirewallEgressDestRule(String addr, int port, boolean allow) {
   1955         enforceSystemUid();
   1956         Preconditions.checkState(mFirewallEnabled);
   1957         final String rule = allow ? "allow" : "deny";
   1958         try {
   1959             mConnector.execute("firewall", "set_egress_dest_rule", addr, port, rule);
   1960         } catch (NativeDaemonConnectorException e) {
   1961             throw e.rethrowAsParcelableException();
   1962         }
   1963     }
   1964 
   1965     private void closeSocketsForFirewallChainLocked(int chain, String chainName) {
   1966         // UID ranges to close sockets on.
   1967         UidRange[] ranges;
   1968         // UID ranges whose sockets we won't touch.
   1969         int[] exemptUids;
   1970 
   1971         int numUids = 0;
   1972 
   1973         if (getFirewallType(chain) == FIREWALL_TYPE_WHITELIST) {
   1974             // Close all sockets on all non-system UIDs...
   1975             ranges = new UidRange[] {
   1976                 // TODO: is there a better way of finding all existing users? If so, we could
   1977                 // specify their ranges here.
   1978                 new UidRange(Process.FIRST_APPLICATION_UID, Integer.MAX_VALUE),
   1979             };
   1980             // ... except for the UIDs that have allow rules.
   1981             synchronized (mRulesLock) {
   1982                 final SparseIntArray rules = getUidFirewallRulesLR(chain);
   1983                 exemptUids = new int[rules.size()];
   1984                 for (int i = 0; i < exemptUids.length; i++) {
   1985                     if (rules.valueAt(i) == NetworkPolicyManager.FIREWALL_RULE_ALLOW) {
   1986                         exemptUids[numUids] = rules.keyAt(i);
   1987                         numUids++;
   1988                     }
   1989                 }
   1990             }
   1991             // Normally, whitelist chains only contain deny rules, so numUids == exemptUids.length.
   1992             // But the code does not guarantee this in any way, and at least in one case - if we add
   1993             // a UID rule to the firewall, and then disable the firewall - the chains can contain
   1994             // the wrong type of rule. In this case, don't close connections that we shouldn't.
   1995             //
   1996             // TODO: tighten up this code by ensuring we never set the wrong type of rule, and
   1997             // fix setFirewallEnabled to grab mQuotaLock and clear rules.
   1998             if (numUids != exemptUids.length) {
   1999                 exemptUids = Arrays.copyOf(exemptUids, numUids);
   2000             }
   2001         } else {
   2002             // Close sockets for every UID that has a deny rule...
   2003             synchronized (mRulesLock) {
   2004                 final SparseIntArray rules = getUidFirewallRulesLR(chain);
   2005                 ranges = new UidRange[rules.size()];
   2006                 for (int i = 0; i < ranges.length; i++) {
   2007                     if (rules.valueAt(i) == NetworkPolicyManager.FIREWALL_RULE_DENY) {
   2008                         int uid = rules.keyAt(i);
   2009                         ranges[numUids] = new UidRange(uid, uid);
   2010                         numUids++;
   2011                     }
   2012                 }
   2013             }
   2014             // As above; usually numUids == ranges.length, but not always.
   2015             if (numUids != ranges.length) {
   2016                 ranges = Arrays.copyOf(ranges, numUids);
   2017             }
   2018             // ... with no exceptions.
   2019             exemptUids = new int[0];
   2020         }
   2021 
   2022         try {
   2023             mNetdService.socketDestroy(ranges, exemptUids);
   2024         } catch(RemoteException | ServiceSpecificException e) {
   2025             Slog.e(TAG, "Error closing sockets after enabling chain " + chainName + ": " + e);
   2026         }
   2027     }
   2028 
   2029     @Override
   2030     public void setFirewallChainEnabled(int chain, boolean enable) {
   2031         enforceSystemUid();
   2032         synchronized (mQuotaLock) {
   2033             synchronized (mRulesLock) {
   2034                 if (getFirewallChainState(chain) == enable) {
   2035                     // All is the same, nothing to do.  This relies on the fact that netd has child
   2036                     // chains default detached.
   2037                     return;
   2038                 }
   2039                 setFirewallChainState(chain, enable);
   2040             }
   2041 
   2042             final String operation = enable ? "enable_chain" : "disable_chain";
   2043             final String chainName;
   2044             switch(chain) {
   2045                 case FIREWALL_CHAIN_STANDBY:
   2046                     chainName = FIREWALL_CHAIN_NAME_STANDBY;
   2047                     break;
   2048                 case FIREWALL_CHAIN_DOZABLE:
   2049                     chainName = FIREWALL_CHAIN_NAME_DOZABLE;
   2050                     break;
   2051                 case FIREWALL_CHAIN_POWERSAVE:
   2052                     chainName = FIREWALL_CHAIN_NAME_POWERSAVE;
   2053                     break;
   2054                 default:
   2055                     throw new IllegalArgumentException("Bad child chain: " + chain);
   2056             }
   2057 
   2058             try {
   2059                 mConnector.execute("firewall", operation, chainName);
   2060             } catch (NativeDaemonConnectorException e) {
   2061                 throw e.rethrowAsParcelableException();
   2062             }
   2063 
   2064             // Close any sockets that were opened by the affected UIDs. This has to be done after
   2065             // disabling network connectivity, in case they react to the socket close by reopening
   2066             // the connection and race with the iptables commands that enable the firewall. All
   2067             // whitelist and blacklist chains allow RSTs through.
   2068             if (enable) {
   2069                 if (DBG) Slog.d(TAG, "Closing sockets after enabling chain " + chainName);
   2070                 closeSocketsForFirewallChainLocked(chain, chainName);
   2071             }
   2072         }
   2073     }
   2074 
   2075     private int getFirewallType(int chain) {
   2076         switch (chain) {
   2077             case FIREWALL_CHAIN_STANDBY:
   2078                 return FIREWALL_TYPE_BLACKLIST;
   2079             case FIREWALL_CHAIN_DOZABLE:
   2080                 return FIREWALL_TYPE_WHITELIST;
   2081             case FIREWALL_CHAIN_POWERSAVE:
   2082                 return FIREWALL_TYPE_WHITELIST;
   2083             default:
   2084                 return isFirewallEnabled() ? FIREWALL_TYPE_WHITELIST : FIREWALL_TYPE_BLACKLIST;
   2085         }
   2086     }
   2087 
   2088     @Override
   2089     public void setFirewallUidRules(int chain, int[] uids, int[] rules) {
   2090         enforceSystemUid();
   2091         synchronized (mQuotaLock) {
   2092             synchronized (mRulesLock) {
   2093                 SparseIntArray uidFirewallRules = getUidFirewallRulesLR(chain);
   2094                 SparseIntArray newRules = new SparseIntArray();
   2095                 // apply new set of rules
   2096                 for (int index = uids.length - 1; index >= 0; --index) {
   2097                     int uid = uids[index];
   2098                     int rule = rules[index];
   2099                     updateFirewallUidRuleLocked(chain, uid, rule);
   2100                     newRules.put(uid, rule);
   2101                 }
   2102                 // collect the rules to remove.
   2103                 SparseIntArray rulesToRemove = new SparseIntArray();
   2104                 for (int index = uidFirewallRules.size() - 1; index >= 0; --index) {
   2105                     int uid = uidFirewallRules.keyAt(index);
   2106                     if (newRules.indexOfKey(uid) < 0) {
   2107                         rulesToRemove.put(uid, FIREWALL_RULE_DEFAULT);
   2108                     }
   2109                 }
   2110                 // remove dead rules
   2111                 for (int index = rulesToRemove.size() - 1; index >= 0; --index) {
   2112                     int uid = rulesToRemove.keyAt(index);
   2113                     updateFirewallUidRuleLocked(chain, uid, FIREWALL_RULE_DEFAULT);
   2114                 }
   2115             }
   2116             try {
   2117                 switch (chain) {
   2118                     case FIREWALL_CHAIN_DOZABLE:
   2119                         mNetdService.firewallReplaceUidChain("fw_dozable", true, uids);
   2120                         break;
   2121                     case FIREWALL_CHAIN_STANDBY:
   2122                         mNetdService.firewallReplaceUidChain("fw_standby", false, uids);
   2123                         break;
   2124                     case FIREWALL_CHAIN_POWERSAVE:
   2125                         mNetdService.firewallReplaceUidChain("fw_powersave", true, uids);
   2126                         break;
   2127                     case FIREWALL_CHAIN_NONE:
   2128                     default:
   2129                         Slog.d(TAG, "setFirewallUidRules() called on invalid chain: " + chain);
   2130                 }
   2131             } catch (RemoteException e) {
   2132                 Slog.w(TAG, "Error flushing firewall chain " + chain, e);
   2133             }
   2134         }
   2135     }
   2136 
   2137     @Override
   2138     public void setFirewallUidRule(int chain, int uid, int rule) {
   2139         enforceSystemUid();
   2140         synchronized (mQuotaLock) {
   2141             setFirewallUidRuleLocked(chain, uid, rule);
   2142         }
   2143     }
   2144 
   2145     private void setFirewallUidRuleLocked(int chain, int uid, int rule) {
   2146         if (updateFirewallUidRuleLocked(chain, uid, rule)) {
   2147             try {
   2148                 mConnector.execute("firewall", "set_uid_rule", getFirewallChainName(chain), uid,
   2149                         getFirewallRuleName(chain, rule));
   2150             } catch (NativeDaemonConnectorException e) {
   2151                 throw e.rethrowAsParcelableException();
   2152             }
   2153         }
   2154     }
   2155 
   2156     // TODO: now that netd supports batching, NMS should not keep these data structures anymore...
   2157     private boolean updateFirewallUidRuleLocked(int chain, int uid, int rule) {
   2158         synchronized (mRulesLock) {
   2159             SparseIntArray uidFirewallRules = getUidFirewallRulesLR(chain);
   2160 
   2161             final int oldUidFirewallRule = uidFirewallRules.get(uid, FIREWALL_RULE_DEFAULT);
   2162             if (DBG) {
   2163                 Slog.d(TAG, "oldRule = " + oldUidFirewallRule
   2164                         + ", newRule=" + rule + " for uid=" + uid + " on chain " + chain);
   2165             }
   2166             if (oldUidFirewallRule == rule) {
   2167                 if (DBG) Slog.d(TAG, "!!!!! Skipping change");
   2168                 // TODO: eventually consider throwing
   2169                 return false;
   2170             }
   2171 
   2172             String ruleName = getFirewallRuleName(chain, rule);
   2173             String oldRuleName = getFirewallRuleName(chain, oldUidFirewallRule);
   2174 
   2175             if (rule == NetworkPolicyManager.FIREWALL_RULE_DEFAULT) {
   2176                 uidFirewallRules.delete(uid);
   2177             } else {
   2178                 uidFirewallRules.put(uid, rule);
   2179             }
   2180             return !ruleName.equals(oldRuleName);
   2181         }
   2182     }
   2183 
   2184     private @NonNull String getFirewallRuleName(int chain, int rule) {
   2185         String ruleName;
   2186         if (getFirewallType(chain) == FIREWALL_TYPE_WHITELIST) {
   2187             if (rule == NetworkPolicyManager.FIREWALL_RULE_ALLOW) {
   2188                 ruleName = "allow";
   2189             } else {
   2190                 ruleName = "deny";
   2191             }
   2192         } else { // Blacklist mode
   2193             if (rule == NetworkPolicyManager.FIREWALL_RULE_DENY) {
   2194                 ruleName = "deny";
   2195             } else {
   2196                 ruleName = "allow";
   2197             }
   2198         }
   2199         return ruleName;
   2200     }
   2201 
   2202     private @NonNull SparseIntArray getUidFirewallRulesLR(int chain) {
   2203         switch (chain) {
   2204             case FIREWALL_CHAIN_STANDBY:
   2205                 return mUidFirewallStandbyRules;
   2206             case FIREWALL_CHAIN_DOZABLE:
   2207                 return mUidFirewallDozableRules;
   2208             case FIREWALL_CHAIN_POWERSAVE:
   2209                 return mUidFirewallPowerSaveRules;
   2210             case FIREWALL_CHAIN_NONE:
   2211                 return mUidFirewallRules;
   2212             default:
   2213                 throw new IllegalArgumentException("Unknown chain:" + chain);
   2214         }
   2215     }
   2216 
   2217     public @NonNull String getFirewallChainName(int chain) {
   2218         switch (chain) {
   2219             case FIREWALL_CHAIN_STANDBY:
   2220                 return FIREWALL_CHAIN_NAME_STANDBY;
   2221             case FIREWALL_CHAIN_DOZABLE:
   2222                 return FIREWALL_CHAIN_NAME_DOZABLE;
   2223             case FIREWALL_CHAIN_POWERSAVE:
   2224                 return FIREWALL_CHAIN_NAME_POWERSAVE;
   2225             case FIREWALL_CHAIN_NONE:
   2226                 return FIREWALL_CHAIN_NAME_NONE;
   2227             default:
   2228                 throw new IllegalArgumentException("Unknown chain:" + chain);
   2229         }
   2230     }
   2231 
   2232     private static void enforceSystemUid() {
   2233         final int uid = Binder.getCallingUid();
   2234         if (uid != Process.SYSTEM_UID) {
   2235             throw new SecurityException("Only available to AID_SYSTEM");
   2236         }
   2237     }
   2238 
   2239     @Override
   2240     public void startClatd(String interfaceName) throws IllegalStateException {
   2241         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
   2242 
   2243         try {
   2244             mConnector.execute("clatd", "start", interfaceName);
   2245         } catch (NativeDaemonConnectorException e) {
   2246             throw e.rethrowAsParcelableException();
   2247         }
   2248     }
   2249 
   2250     @Override
   2251     public void stopClatd(String interfaceName) throws IllegalStateException {
   2252         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
   2253 
   2254         try {
   2255             mConnector.execute("clatd", "stop", interfaceName);
   2256         } catch (NativeDaemonConnectorException e) {
   2257             throw e.rethrowAsParcelableException();
   2258         }
   2259     }
   2260 
   2261     @Override
   2262     public boolean isClatdStarted(String interfaceName) {
   2263         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
   2264 
   2265         final NativeDaemonEvent event;
   2266         try {
   2267             event = mConnector.execute("clatd", "status", interfaceName);
   2268         } catch (NativeDaemonConnectorException e) {
   2269             throw e.rethrowAsParcelableException();
   2270         }
   2271 
   2272         event.checkCode(ClatdStatusResult);
   2273         return event.getMessage().endsWith("started");
   2274     }
   2275 
   2276     @Override
   2277     public void registerNetworkActivityListener(INetworkActivityListener listener) {
   2278         mNetworkActivityListeners.register(listener);
   2279     }
   2280 
   2281     @Override
   2282     public void unregisterNetworkActivityListener(INetworkActivityListener listener) {
   2283         mNetworkActivityListeners.unregister(listener);
   2284     }
   2285 
   2286     @Override
   2287     public boolean isNetworkActive() {
   2288         synchronized (mNetworkActivityListeners) {
   2289             return mNetworkActive || mActiveIdleTimers.isEmpty();
   2290         }
   2291     }
   2292 
   2293     private void reportNetworkActive() {
   2294         final int length = mNetworkActivityListeners.beginBroadcast();
   2295         try {
   2296             for (int i = 0; i < length; i++) {
   2297                 try {
   2298                     mNetworkActivityListeners.getBroadcastItem(i).onNetworkActive();
   2299                 } catch (RemoteException | RuntimeException e) {
   2300                 }
   2301             }
   2302         } finally {
   2303             mNetworkActivityListeners.finishBroadcast();
   2304         }
   2305     }
   2306 
   2307     /** {@inheritDoc} */
   2308     @Override
   2309     public void monitor() {
   2310         if (mConnector != null) {
   2311             mConnector.monitor();
   2312         }
   2313     }
   2314 
   2315     @Override
   2316     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
   2317         if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
   2318 
   2319         pw.println("NetworkManagementService NativeDaemonConnector Log:");
   2320         mConnector.dump(fd, pw, args);
   2321         pw.println();
   2322 
   2323         pw.print("Bandwidth control enabled: "); pw.println(mBandwidthControlEnabled);
   2324         pw.print("mMobileActivityFromRadio="); pw.print(mMobileActivityFromRadio);
   2325                 pw.print(" mLastPowerStateFromRadio="); pw.println(mLastPowerStateFromRadio);
   2326         pw.print("mNetworkActive="); pw.println(mNetworkActive);
   2327 
   2328         synchronized (mQuotaLock) {
   2329             pw.print("Active quota ifaces: "); pw.println(mActiveQuotas.toString());
   2330             pw.print("Active alert ifaces: "); pw.println(mActiveAlerts.toString());
   2331             pw.print("Data saver mode: "); pw.println(mDataSaverMode);
   2332             synchronized (mRulesLock) {
   2333                 dumpUidRuleOnQuotaLocked(pw, "blacklist", mUidRejectOnMetered);
   2334                 dumpUidRuleOnQuotaLocked(pw, "whitelist", mUidAllowOnMetered);
   2335             }
   2336         }
   2337 
   2338         synchronized (mRulesLock) {
   2339             dumpUidFirewallRule(pw, "", mUidFirewallRules);
   2340 
   2341             pw.print("UID firewall standby chain enabled: "); pw.println(
   2342                     getFirewallChainState(FIREWALL_CHAIN_STANDBY));
   2343             dumpUidFirewallRule(pw, FIREWALL_CHAIN_NAME_STANDBY, mUidFirewallStandbyRules);
   2344 
   2345             pw.print("UID firewall dozable chain enabled: "); pw.println(
   2346                     getFirewallChainState(FIREWALL_CHAIN_DOZABLE));
   2347             dumpUidFirewallRule(pw, FIREWALL_CHAIN_NAME_DOZABLE, mUidFirewallDozableRules);
   2348 
   2349             pw.println("UID firewall powersave chain enabled: " +
   2350                     getFirewallChainState(FIREWALL_CHAIN_POWERSAVE));
   2351             dumpUidFirewallRule(pw, FIREWALL_CHAIN_NAME_POWERSAVE, mUidFirewallPowerSaveRules);
   2352         }
   2353 
   2354         synchronized (mIdleTimerLock) {
   2355             pw.println("Idle timers:");
   2356             for (HashMap.Entry<String, IdleTimerParams> ent : mActiveIdleTimers.entrySet()) {
   2357                 pw.print("  "); pw.print(ent.getKey()); pw.println(":");
   2358                 IdleTimerParams params = ent.getValue();
   2359                 pw.print("    timeout="); pw.print(params.timeout);
   2360                 pw.print(" type="); pw.print(params.type);
   2361                 pw.print(" networkCount="); pw.println(params.networkCount);
   2362             }
   2363         }
   2364 
   2365         pw.print("Firewall enabled: "); pw.println(mFirewallEnabled);
   2366         pw.print("Netd service status: " );
   2367         if (mNetdService == null) {
   2368             pw.println("disconnected");
   2369         } else {
   2370             try {
   2371                 final boolean alive = mNetdService.isAlive();
   2372                 pw.println(alive ? "alive": "dead");
   2373             } catch (RemoteException e) {
   2374                 pw.println("unreachable");
   2375             }
   2376         }
   2377     }
   2378 
   2379     private void dumpUidRuleOnQuotaLocked(PrintWriter pw, String name, SparseBooleanArray list) {
   2380         pw.print("UID bandwith control ");
   2381         pw.print(name);
   2382         pw.print(" rule: [");
   2383         final int size = list.size();
   2384         for (int i = 0; i < size; i++) {
   2385             pw.print(list.keyAt(i));
   2386             if (i < size - 1) pw.print(",");
   2387         }
   2388         pw.println("]");
   2389     }
   2390 
   2391     private void dumpUidFirewallRule(PrintWriter pw, String name, SparseIntArray rules) {
   2392         pw.print("UID firewall ");
   2393         pw.print(name);
   2394         pw.print(" rule: [");
   2395         final int size = rules.size();
   2396         for (int i = 0; i < size; i++) {
   2397             pw.print(rules.keyAt(i));
   2398             pw.print(":");
   2399             pw.print(rules.valueAt(i));
   2400             if (i < size - 1) pw.print(",");
   2401         }
   2402         pw.println("]");
   2403     }
   2404 
   2405     @Override
   2406     public void createPhysicalNetwork(int netId, String permission) {
   2407         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
   2408 
   2409         try {
   2410             if (permission != null) {
   2411                 mConnector.execute("network", "create", netId, permission);
   2412             } else {
   2413                 mConnector.execute("network", "create", netId);
   2414             }
   2415         } catch (NativeDaemonConnectorException e) {
   2416             throw e.rethrowAsParcelableException();
   2417         }
   2418     }
   2419 
   2420     @Override
   2421     public void createVirtualNetwork(int netId, boolean hasDNS, boolean secure) {
   2422         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
   2423 
   2424         try {
   2425             mConnector.execute("network", "create", netId, "vpn", hasDNS ? "1" : "0",
   2426                     secure ? "1" : "0");
   2427         } catch (NativeDaemonConnectorException e) {
   2428             throw e.rethrowAsParcelableException();
   2429         }
   2430     }
   2431 
   2432     @Override
   2433     public void removeNetwork(int netId) {
   2434         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
   2435 
   2436         try {
   2437             mConnector.execute("network", "destroy", netId);
   2438         } catch (NativeDaemonConnectorException e) {
   2439             throw e.rethrowAsParcelableException();
   2440         }
   2441     }
   2442 
   2443     @Override
   2444     public void addInterfaceToNetwork(String iface, int netId) {
   2445         modifyInterfaceInNetwork("add", "" + netId, iface);
   2446     }
   2447 
   2448     @Override
   2449     public void removeInterfaceFromNetwork(String iface, int netId) {
   2450         modifyInterfaceInNetwork("remove", "" + netId, iface);
   2451     }
   2452 
   2453     private void modifyInterfaceInNetwork(String action, String netId, String iface) {
   2454         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
   2455         try {
   2456             mConnector.execute("network", "interface", action, netId, iface);
   2457         } catch (NativeDaemonConnectorException e) {
   2458             throw e.rethrowAsParcelableException();
   2459         }
   2460     }
   2461 
   2462     @Override
   2463     public void addLegacyRouteForNetId(int netId, RouteInfo routeInfo, int uid) {
   2464         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
   2465 
   2466         final Command cmd = new Command("network", "route", "legacy", uid, "add", netId);
   2467 
   2468         // create triplet: interface dest-ip-addr/prefixlength gateway-ip-addr
   2469         final LinkAddress la = routeInfo.getDestinationLinkAddress();
   2470         cmd.appendArg(routeInfo.getInterface());
   2471         cmd.appendArg(la.getAddress().getHostAddress() + "/" + la.getPrefixLength());
   2472         if (routeInfo.hasGateway()) {
   2473             cmd.appendArg(routeInfo.getGateway().getHostAddress());
   2474         }
   2475 
   2476         try {
   2477             mConnector.execute(cmd);
   2478         } catch (NativeDaemonConnectorException e) {
   2479             throw e.rethrowAsParcelableException();
   2480         }
   2481     }
   2482 
   2483     @Override
   2484     public void setDefaultNetId(int netId) {
   2485         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
   2486 
   2487         try {
   2488             mConnector.execute("network", "default", "set", netId);
   2489         } catch (NativeDaemonConnectorException e) {
   2490             throw e.rethrowAsParcelableException();
   2491         }
   2492     }
   2493 
   2494     @Override
   2495     public void clearDefaultNetId() {
   2496         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
   2497 
   2498         try {
   2499             mConnector.execute("network", "default", "clear");
   2500         } catch (NativeDaemonConnectorException e) {
   2501             throw e.rethrowAsParcelableException();
   2502         }
   2503     }
   2504 
   2505     @Override
   2506     public void setNetworkPermission(int netId, String permission) {
   2507         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
   2508 
   2509         try {
   2510             if (permission != null) {
   2511                 mConnector.execute("network", "permission", "network", "set", permission, netId);
   2512             } else {
   2513                 mConnector.execute("network", "permission", "network", "clear", netId);
   2514             }
   2515         } catch (NativeDaemonConnectorException e) {
   2516             throw e.rethrowAsParcelableException();
   2517         }
   2518     }
   2519 
   2520 
   2521     @Override
   2522     public void setPermission(String permission, int[] uids) {
   2523         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
   2524 
   2525         Object[] argv = new Object[4 + MAX_UID_RANGES_PER_COMMAND];
   2526         argv[0] = "permission";
   2527         argv[1] = "user";
   2528         argv[2] = "set";
   2529         argv[3] = permission;
   2530         int argc = 4;
   2531         // Avoid overly long commands by limiting number of UIDs per command.
   2532         for (int i = 0; i < uids.length; ++i) {
   2533             argv[argc++] = uids[i];
   2534             if (i == uids.length - 1 || argc == argv.length) {
   2535                 try {
   2536                     mConnector.execute("network", Arrays.copyOf(argv, argc));
   2537                 } catch (NativeDaemonConnectorException e) {
   2538                     throw e.rethrowAsParcelableException();
   2539                 }
   2540                 argc = 4;
   2541             }
   2542         }
   2543     }
   2544 
   2545     @Override
   2546     public void clearPermission(int[] uids) {
   2547         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
   2548 
   2549         Object[] argv = new Object[3 + MAX_UID_RANGES_PER_COMMAND];
   2550         argv[0] = "permission";
   2551         argv[1] = "user";
   2552         argv[2] = "clear";
   2553         int argc = 3;
   2554         // Avoid overly long commands by limiting number of UIDs per command.
   2555         for (int i = 0; i < uids.length; ++i) {
   2556             argv[argc++] = uids[i];
   2557             if (i == uids.length - 1 || argc == argv.length) {
   2558                 try {
   2559                     mConnector.execute("network", Arrays.copyOf(argv, argc));
   2560                 } catch (NativeDaemonConnectorException e) {
   2561                     throw e.rethrowAsParcelableException();
   2562                 }
   2563                 argc = 3;
   2564             }
   2565         }
   2566     }
   2567 
   2568     @Override
   2569     public void allowProtect(int uid) {
   2570         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
   2571 
   2572         try {
   2573             mConnector.execute("network", "protect", "allow", uid);
   2574         } catch (NativeDaemonConnectorException e) {
   2575             throw e.rethrowAsParcelableException();
   2576         }
   2577     }
   2578 
   2579     @Override
   2580     public void denyProtect(int uid) {
   2581         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
   2582 
   2583         try {
   2584             mConnector.execute("network", "protect", "deny", uid);
   2585         } catch (NativeDaemonConnectorException e) {
   2586             throw e.rethrowAsParcelableException();
   2587         }
   2588     }
   2589 
   2590     @Override
   2591     public void addInterfaceToLocalNetwork(String iface, List<RouteInfo> routes) {
   2592         modifyInterfaceInNetwork("add", "local", iface);
   2593 
   2594         for (RouteInfo route : routes) {
   2595             if (!route.isDefaultRoute()) {
   2596                 modifyRoute("add", "local", route);
   2597             }
   2598         }
   2599     }
   2600 
   2601     @Override
   2602     public void removeInterfaceFromLocalNetwork(String iface) {
   2603         modifyInterfaceInNetwork("remove", "local", iface);
   2604     }
   2605 
   2606     @Override
   2607     public int removeRoutesFromLocalNetwork(List<RouteInfo> routes) {
   2608         int failures = 0;
   2609 
   2610         for (RouteInfo route : routes) {
   2611             try {
   2612                 modifyRoute("remove", "local", route);
   2613             } catch (IllegalStateException e) {
   2614                 failures++;
   2615             }
   2616         }
   2617 
   2618         return failures;
   2619     }
   2620 
   2621     private void setFirewallChainState(int chain, boolean state) {
   2622         synchronized (mRulesLock) {
   2623             mFirewallChainStates.put(chain, state);
   2624         }
   2625     }
   2626 
   2627     private boolean getFirewallChainState(int chain) {
   2628         synchronized (mRulesLock) {
   2629             return mFirewallChainStates.get(chain);
   2630         }
   2631     }
   2632 
   2633     @VisibleForTesting
   2634     class LocalService extends NetworkManagementInternal {
   2635         @Override
   2636         public boolean isNetworkRestrictedForUid(int uid) {
   2637             synchronized (mRulesLock) {
   2638                 if (getFirewallChainState(FIREWALL_CHAIN_STANDBY)
   2639                         && mUidFirewallStandbyRules.get(uid) == FIREWALL_RULE_DENY) {
   2640                     if (DBG) Slog.d(TAG, "Uid " + uid + " restricted because of app standby mode");
   2641                     return true;
   2642                 }
   2643                 if (getFirewallChainState(FIREWALL_CHAIN_DOZABLE)
   2644                         && mUidFirewallDozableRules.get(uid) != FIREWALL_RULE_ALLOW) {
   2645                     if (DBG) Slog.d(TAG, "Uid " + uid + " restricted because of device idle mode");
   2646                     return true;
   2647                 }
   2648                 if (getFirewallChainState(FIREWALL_CHAIN_POWERSAVE)
   2649                         && mUidFirewallPowerSaveRules.get(uid) != FIREWALL_RULE_ALLOW) {
   2650                     if (DBG) Slog.d(TAG, "Uid " + uid + " restricted because of power saver mode");
   2651                     return true;
   2652                 }
   2653                 if (mUidRejectOnMetered.get(uid)) {
   2654                     if (DBG) Slog.d(TAG, "Uid " + uid + " restricted because of no metered data"
   2655                             + " in the background");
   2656                     return true;
   2657                 }
   2658                 if (mDataSaverMode && !mUidAllowOnMetered.get(uid)) {
   2659                     if (DBG) Slog.d(TAG, "Uid " + uid + " restricted because of data saver mode");
   2660                     return true;
   2661                 }
   2662                 return false;
   2663             }
   2664         }
   2665     }
   2666 
   2667     @VisibleForTesting
   2668     Injector getInjector() {
   2669         return new Injector();
   2670     }
   2671 
   2672     @VisibleForTesting
   2673     class Injector {
   2674         void setDataSaverMode(boolean dataSaverMode) {
   2675             mDataSaverMode = dataSaverMode;
   2676         }
   2677 
   2678         void setFirewallChainState(int chain, boolean state) {
   2679             NetworkManagementService.this.setFirewallChainState(chain, state);
   2680         }
   2681 
   2682         void setFirewallRule(int chain, int uid, int rule) {
   2683             synchronized (mRulesLock) {
   2684                 getUidFirewallRulesLR(chain).put(uid, rule);
   2685             }
   2686         }
   2687 
   2688         void setUidOnMeteredNetworkList(boolean blacklist, int uid, boolean enable) {
   2689             synchronized (mRulesLock) {
   2690                 if (blacklist) {
   2691                     mUidRejectOnMetered.put(uid, enable);
   2692                 } else {
   2693                     mUidAllowOnMetered.put(uid, enable);
   2694                 }
   2695             }
   2696         }
   2697 
   2698         void reset() {
   2699             synchronized (mRulesLock) {
   2700                 setDataSaverMode(false);
   2701                 final int[] chains = {
   2702                         FIREWALL_CHAIN_DOZABLE,
   2703                         FIREWALL_CHAIN_STANDBY,
   2704                         FIREWALL_CHAIN_POWERSAVE
   2705                 };
   2706                 for (int chain : chains) {
   2707                     setFirewallChainState(chain, false);
   2708                     getUidFirewallRulesLR(chain).clear();
   2709                 }
   2710                 mUidAllowOnMetered.clear();
   2711                 mUidRejectOnMetered.clear();
   2712             }
   2713         }
   2714     }
   2715 }
   2716