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