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