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