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