OSDN Git Service

Merge "docs: Add documentation for equals() method" into qt-dev am: 732a127636
[android-x86/frameworks-base.git] / services / core / java / com / android / server / NetworkManagementService.java
1 /*
2  * Copyright (C) 2007 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package com.android.server;
18
19 import static android.Manifest.permission.CONNECTIVITY_INTERNAL;
20 import static android.Manifest.permission.NETWORK_SETTINGS;
21 import static android.Manifest.permission.NETWORK_STACK;
22 import static android.Manifest.permission.SHUTDOWN;
23 import static android.net.INetd.FIREWALL_BLACKLIST;
24 import static android.net.INetd.FIREWALL_CHAIN_DOZABLE;
25 import static android.net.INetd.FIREWALL_CHAIN_NONE;
26 import static android.net.INetd.FIREWALL_CHAIN_POWERSAVE;
27 import static android.net.INetd.FIREWALL_CHAIN_STANDBY;
28 import static android.net.INetd.FIREWALL_RULE_ALLOW;
29 import static android.net.INetd.FIREWALL_RULE_DENY;
30 import static android.net.INetd.FIREWALL_WHITELIST;
31 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_DOZABLE;
32 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_POWERSAVE;
33 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_STANDBY;
34 import static android.net.NetworkPolicyManager.FIREWALL_RULE_DEFAULT;
35 import static android.net.NetworkStats.SET_DEFAULT;
36 import static android.net.NetworkStats.STATS_PER_UID;
37 import static android.net.NetworkStats.TAG_ALL;
38 import static android.net.NetworkStats.TAG_NONE;
39 import static android.net.TrafficStats.UID_TETHERING;
40
41 import static com.android.server.NetworkManagementSocketTagger.PROP_QTAGUID_ENABLED;
42
43 import android.annotation.NonNull;
44 import android.app.ActivityManager;
45 import android.content.Context;
46 import android.net.ConnectivityManager;
47 import android.net.INetd;
48 import android.net.INetdUnsolicitedEventListener;
49 import android.net.INetworkManagementEventObserver;
50 import android.net.ITetheringStatsProvider;
51 import android.net.InetAddresses;
52 import android.net.InterfaceConfiguration;
53 import android.net.InterfaceConfigurationParcel;
54 import android.net.IpPrefix;
55 import android.net.LinkAddress;
56 import android.net.Network;
57 import android.net.NetworkPolicyManager;
58 import android.net.NetworkStats;
59 import android.net.NetworkUtils;
60 import android.net.RouteInfo;
61 import android.net.TetherStatsParcel;
62 import android.net.UidRange;
63 import android.net.UidRangeParcel;
64 import android.net.util.NetdService;
65 import android.os.BatteryStats;
66 import android.os.Binder;
67 import android.os.Handler;
68 import android.os.IBinder;
69 import android.os.INetworkActivityListener;
70 import android.os.INetworkManagementService;
71 import android.os.Process;
72 import android.os.RemoteCallbackList;
73 import android.os.RemoteException;
74 import android.os.ServiceManager;
75 import android.os.ServiceSpecificException;
76 import android.os.StrictMode;
77 import android.os.SystemClock;
78 import android.os.SystemProperties;
79 import android.os.Trace;
80 import android.telephony.DataConnectionRealTimeInfo;
81 import android.text.TextUtils;
82 import android.util.Log;
83 import android.util.Slog;
84 import android.util.SparseBooleanArray;
85 import android.util.SparseIntArray;
86 import android.util.StatsLog;
87
88 import com.android.internal.annotations.GuardedBy;
89 import com.android.internal.annotations.VisibleForTesting;
90 import com.android.internal.app.IBatteryStats;
91 import com.android.internal.util.DumpUtils;
92 import com.android.internal.util.HexDump;
93 import com.android.internal.util.Preconditions;
94 import com.android.server.net.NetworkStatsFactory;
95
96 import com.google.android.collect.Maps;
97
98 import java.io.BufferedReader;
99 import java.io.DataInputStream;
100 import java.io.FileDescriptor;
101 import java.io.FileInputStream;
102 import java.io.IOException;
103 import java.io.InputStreamReader;
104 import java.io.PrintWriter;
105 import java.net.InetAddress;
106 import java.net.InterfaceAddress;
107 import java.util.ArrayList;
108 import java.util.Arrays;
109 import java.util.HashMap;
110 import java.util.List;
111 import java.util.Map;
112
113 /**
114  * @hide
115  */
116 public class NetworkManagementService extends INetworkManagementService.Stub {
117
118     /**
119      * Helper class that encapsulates NetworkManagementService dependencies and makes them
120      * easier to mock in unit tests.
121      */
122     static class SystemServices {
123         public IBinder getService(String name) {
124             return ServiceManager.getService(name);
125         }
126         public void registerLocalService(NetworkManagementInternal nmi) {
127             LocalServices.addService(NetworkManagementInternal.class, nmi);
128         }
129         public INetd getNetd() {
130             return NetdService.get();
131         }
132     }
133
134     private static final String TAG = "NetworkManagement";
135     private static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG);
136
137     private static final int MAX_UID_RANGES_PER_COMMAND = 10;
138
139     /**
140      * Name representing {@link #setGlobalAlert(long)} limit when delivered to
141      * {@link INetworkManagementEventObserver#limitReached(String, String)}.
142      */
143     public static final String LIMIT_GLOBAL_ALERT = "globalAlert";
144
145     static final int DAEMON_MSG_MOBILE_CONN_REAL_TIME_INFO = 1;
146
147     static final boolean MODIFY_OPERATION_ADD = true;
148     static final boolean MODIFY_OPERATION_REMOVE = false;
149
150     /**
151      * Binder context for this service
152      */
153     private final Context mContext;
154
155     private final Handler mDaemonHandler;
156
157     private final SystemServices mServices;
158
159     private INetd mNetdService;
160
161     private final NetdUnsolicitedEventListener mNetdUnsolicitedEventListener;
162
163     private IBatteryStats mBatteryStats;
164
165     private final RemoteCallbackList<INetworkManagementEventObserver> mObservers =
166             new RemoteCallbackList<>();
167
168     private final NetworkStatsFactory mStatsFactory = new NetworkStatsFactory();
169
170     @GuardedBy("mTetheringStatsProviders")
171     private final HashMap<ITetheringStatsProvider, String>
172             mTetheringStatsProviders = Maps.newHashMap();
173
174     /**
175      * If both locks need to be held, then they should be obtained in the order:
176      * first {@link #mQuotaLock} and then {@link #mRulesLock}.
177      */
178     private final Object mQuotaLock = new Object();
179     private final Object mRulesLock = new Object();
180
181     /** Set of interfaces with active quotas. */
182     @GuardedBy("mQuotaLock")
183     private HashMap<String, Long> mActiveQuotas = Maps.newHashMap();
184     /** Set of interfaces with active alerts. */
185     @GuardedBy("mQuotaLock")
186     private HashMap<String, Long> mActiveAlerts = Maps.newHashMap();
187     /** Set of UIDs blacklisted on metered networks. */
188     @GuardedBy("mRulesLock")
189     private SparseBooleanArray mUidRejectOnMetered = new SparseBooleanArray();
190     /** Set of UIDs whitelisted on metered networks. */
191     @GuardedBy("mRulesLock")
192     private SparseBooleanArray mUidAllowOnMetered = new SparseBooleanArray();
193     /** Set of UIDs with cleartext penalties. */
194     @GuardedBy("mQuotaLock")
195     private SparseIntArray mUidCleartextPolicy = new SparseIntArray();
196     /** Set of UIDs that are to be blocked/allowed by firewall controller. */
197     @GuardedBy("mRulesLock")
198     private SparseIntArray mUidFirewallRules = new SparseIntArray();
199     /**
200      * Set of UIDs that are to be blocked/allowed by firewall controller.  This set of Ids matches
201      * to application idles.
202      */
203     @GuardedBy("mRulesLock")
204     private SparseIntArray mUidFirewallStandbyRules = new SparseIntArray();
205     /**
206      * Set of UIDs that are to be blocked/allowed by firewall controller.  This set of Ids matches
207      * to device idles.
208      */
209     @GuardedBy("mRulesLock")
210     private SparseIntArray mUidFirewallDozableRules = new SparseIntArray();
211     /**
212      * Set of UIDs that are to be blocked/allowed by firewall controller.  This set of Ids matches
213      * to device on power-save mode.
214      */
215     @GuardedBy("mRulesLock")
216     private SparseIntArray mUidFirewallPowerSaveRules = new SparseIntArray();
217     /** Set of states for the child firewall chains. True if the chain is active. */
218     @GuardedBy("mRulesLock")
219     final SparseBooleanArray mFirewallChainStates = new SparseBooleanArray();
220
221     @GuardedBy("mQuotaLock")
222     private volatile boolean mDataSaverMode;
223
224     private final Object mIdleTimerLock = new Object();
225     /** Set of interfaces with active idle timers. */
226     private static class IdleTimerParams {
227         public final int timeout;
228         public final int type;
229         public int networkCount;
230
231         IdleTimerParams(int timeout, int type) {
232             this.timeout = timeout;
233             this.type = type;
234             this.networkCount = 1;
235         }
236     }
237     private HashMap<String, IdleTimerParams> mActiveIdleTimers = Maps.newHashMap();
238
239     private volatile boolean mFirewallEnabled;
240     private volatile boolean mStrictEnabled;
241
242     private boolean mMobileActivityFromRadio = false;
243     private int mLastPowerStateFromRadio = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
244     private int mLastPowerStateFromWifi = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
245
246     private final RemoteCallbackList<INetworkActivityListener> mNetworkActivityListeners =
247             new RemoteCallbackList<>();
248     private boolean mNetworkActive;
249
250     /**
251      * Constructs a new NetworkManagementService instance
252      *
253      * @param context  Binder context for this service
254      */
255     private NetworkManagementService(
256             Context context, SystemServices services) {
257         mContext = context;
258         mServices = services;
259
260         mDaemonHandler = new Handler(FgThread.get().getLooper());
261
262         mNetdUnsolicitedEventListener = new NetdUnsolicitedEventListener();
263
264         mServices.registerLocalService(new LocalService());
265
266         synchronized (mTetheringStatsProviders) {
267             mTetheringStatsProviders.put(new NetdTetheringStatsProvider(), "netd");
268         }
269     }
270
271     @VisibleForTesting
272     NetworkManagementService() {
273         mContext = null;
274         mDaemonHandler = null;
275         mServices = null;
276         mNetdUnsolicitedEventListener = null;
277     }
278
279     static NetworkManagementService create(Context context, SystemServices services)
280             throws InterruptedException {
281         final NetworkManagementService service =
282                 new NetworkManagementService(context, services);
283         if (DBG) Slog.d(TAG, "Creating NetworkManagementService");
284         if (DBG) Slog.d(TAG, "Connecting native netd service");
285         service.connectNativeNetdService();
286         if (DBG) Slog.d(TAG, "Connected");
287         return service;
288     }
289
290     public static NetworkManagementService create(Context context) throws InterruptedException {
291         return create(context, new SystemServices());
292     }
293
294     public void systemReady() {
295         if (DBG) {
296             final long start = System.currentTimeMillis();
297             prepareNativeDaemon();
298             final long delta = System.currentTimeMillis() - start;
299             Slog.d(TAG, "Prepared in " + delta + "ms");
300             return;
301         } else {
302             prepareNativeDaemon();
303         }
304     }
305
306     private IBatteryStats getBatteryStats() {
307         synchronized (this) {
308             if (mBatteryStats != null) {
309                 return mBatteryStats;
310             }
311             mBatteryStats =
312                     IBatteryStats.Stub.asInterface(mServices.getService(BatteryStats.SERVICE_NAME));
313             return mBatteryStats;
314         }
315     }
316
317     @Override
318     public void registerObserver(INetworkManagementEventObserver observer) {
319         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
320         mObservers.register(observer);
321     }
322
323     @Override
324     public void unregisterObserver(INetworkManagementEventObserver observer) {
325         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
326         mObservers.unregister(observer);
327     }
328
329     @FunctionalInterface
330     private interface NetworkManagementEventCallback {
331         public void sendCallback(INetworkManagementEventObserver o) throws RemoteException;
332     }
333
334     private void invokeForAllObservers(NetworkManagementEventCallback eventCallback) {
335         final int length = mObservers.beginBroadcast();
336         try {
337             for (int i = 0; i < length; i++) {
338                 try {
339                     eventCallback.sendCallback(mObservers.getBroadcastItem(i));
340                 } catch (RemoteException | RuntimeException e) {
341                 }
342             }
343         } finally {
344             mObservers.finishBroadcast();
345         }
346     }
347
348     /**
349      * Notify our observers of an interface status change
350      */
351     private void notifyInterfaceStatusChanged(String iface, boolean up) {
352         invokeForAllObservers(o -> o.interfaceStatusChanged(iface, up));
353     }
354
355     /**
356      * Notify our observers of an interface link state change
357      * (typically, an Ethernet cable has been plugged-in or unplugged).
358      */
359     private void notifyInterfaceLinkStateChanged(String iface, boolean up) {
360         invokeForAllObservers(o -> o.interfaceLinkStateChanged(iface, up));
361     }
362
363     /**
364      * Notify our observers of an interface addition.
365      */
366     private void notifyInterfaceAdded(String iface) {
367         invokeForAllObservers(o -> o.interfaceAdded(iface));
368     }
369
370     /**
371      * Notify our observers of an interface removal.
372      */
373     private void notifyInterfaceRemoved(String iface) {
374         // netd already clears out quota and alerts for removed ifaces; update
375         // our sanity-checking state.
376         mActiveAlerts.remove(iface);
377         mActiveQuotas.remove(iface);
378         invokeForAllObservers(o -> o.interfaceRemoved(iface));
379     }
380
381     /**
382      * Notify our observers of a limit reached.
383      */
384     private void notifyLimitReached(String limitName, String iface) {
385         invokeForAllObservers(o -> o.limitReached(limitName, iface));
386     }
387
388     /**
389      * Notify our observers of a change in the data activity state of the interface
390      */
391     private void notifyInterfaceClassActivity(int type, boolean isActive, long tsNanos,
392             int uid, boolean fromRadio) {
393         final boolean isMobile = ConnectivityManager.isNetworkTypeMobile(type);
394         int powerState = isActive
395                 ? DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH
396                 : DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
397         if (isMobile) {
398             if (!fromRadio) {
399                 if (mMobileActivityFromRadio) {
400                     // If this call is not coming from a report from the radio itself, but we
401                     // have previously received reports from the radio, then we will take the
402                     // power state to just be whatever the radio last reported.
403                     powerState = mLastPowerStateFromRadio;
404                 }
405             } else {
406                 mMobileActivityFromRadio = true;
407             }
408             if (mLastPowerStateFromRadio != powerState) {
409                 mLastPowerStateFromRadio = powerState;
410                 try {
411                     getBatteryStats().noteMobileRadioPowerState(powerState, tsNanos, uid);
412                 } catch (RemoteException e) {
413                 }
414                 StatsLog.write_non_chained(StatsLog.MOBILE_RADIO_POWER_STATE_CHANGED, uid, null,
415                         powerState);
416             }
417         }
418
419         if (ConnectivityManager.isNetworkTypeWifi(type)) {
420             if (mLastPowerStateFromWifi != powerState) {
421                 mLastPowerStateFromWifi = powerState;
422                 try {
423                     getBatteryStats().noteWifiRadioPowerState(powerState, tsNanos, uid);
424                 } catch (RemoteException e) {
425                 }
426                 StatsLog.write_non_chained(StatsLog.WIFI_RADIO_POWER_STATE_CHANGED, uid, null,
427                         powerState);
428             }
429         }
430
431         if (!isMobile || fromRadio || !mMobileActivityFromRadio) {
432             // Report the change in data activity.  We don't do this if this is a change
433             // on the mobile network, that is not coming from the radio itself, and we
434             // have previously seen change reports from the radio.  In that case only
435             // the radio is the authority for the current state.
436             final boolean active = isActive;
437             invokeForAllObservers(o -> o.interfaceClassDataActivityChanged(
438                     Integer.toString(type), active, tsNanos));
439         }
440
441         boolean report = false;
442         synchronized (mIdleTimerLock) {
443             if (mActiveIdleTimers.isEmpty()) {
444                 // If there are no idle timers, we are not monitoring activity, so we
445                 // are always considered active.
446                 isActive = true;
447             }
448             if (mNetworkActive != isActive) {
449                 mNetworkActive = isActive;
450                 report = isActive;
451             }
452         }
453         if (report) {
454             reportNetworkActive();
455         }
456     }
457
458     @Override
459     public void registerTetheringStatsProvider(ITetheringStatsProvider provider, String name) {
460         mContext.enforceCallingOrSelfPermission(NETWORK_STACK, TAG);
461         Preconditions.checkNotNull(provider);
462         synchronized(mTetheringStatsProviders) {
463             mTetheringStatsProviders.put(provider, name);
464         }
465     }
466
467     @Override
468     public void unregisterTetheringStatsProvider(ITetheringStatsProvider provider) {
469         mContext.enforceCallingOrSelfPermission(NETWORK_STACK, TAG);
470         synchronized(mTetheringStatsProviders) {
471             mTetheringStatsProviders.remove(provider);
472         }
473     }
474
475     @Override
476     public void tetherLimitReached(ITetheringStatsProvider provider) {
477         mContext.enforceCallingOrSelfPermission(NETWORK_STACK, TAG);
478         synchronized(mTetheringStatsProviders) {
479             if (!mTetheringStatsProviders.containsKey(provider)) {
480                 return;
481             }
482             // No current code examines the interface parameter in a global alert. Just pass null.
483             mDaemonHandler.post(() -> notifyLimitReached(LIMIT_GLOBAL_ALERT, null));
484         }
485     }
486
487     // Sync the state of the given chain with the native daemon.
488     private void syncFirewallChainLocked(int chain, String name) {
489         SparseIntArray rules;
490         synchronized (mRulesLock) {
491             final SparseIntArray uidFirewallRules = getUidFirewallRulesLR(chain);
492             // Make a copy of the current rules, and then clear them. This is because
493             // setFirewallUidRuleInternal only pushes down rules to the native daemon if they
494             // are different from the current rules stored in the mUidFirewall*Rules array for
495             // the specified chain. If we don't clear the rules, setFirewallUidRuleInternal
496             // will do nothing.
497             rules = uidFirewallRules.clone();
498             uidFirewallRules.clear();
499         }
500         if (rules.size() > 0) {
501             // Now push the rules. setFirewallUidRuleInternal will push each of these down to the
502             // native daemon, and also add them to the mUidFirewall*Rules array for the specified
503             // chain.
504             if (DBG) Slog.d(TAG, "Pushing " + rules.size() + " active firewall "
505                     + name + "UID rules");
506             for (int i = 0; i < rules.size(); i++) {
507                 setFirewallUidRuleLocked(chain, rules.keyAt(i), rules.valueAt(i));
508             }
509         }
510     }
511
512     private void connectNativeNetdService() {
513         mNetdService = mServices.getNetd();
514         try {
515             mNetdService.registerUnsolicitedEventListener(mNetdUnsolicitedEventListener);
516             if (DBG) Slog.d(TAG, "Register unsolicited event listener");
517         } catch (RemoteException | ServiceSpecificException e) {
518             Slog.e(TAG, "Failed to set Netd unsolicited event listener " + e);
519         }
520     }
521
522     /**
523      * Prepare native daemon once connected, enabling modules and pushing any
524      * existing in-memory rules.
525      */
526     private void prepareNativeDaemon() {
527
528         // push any existing quota or UID rules
529         synchronized (mQuotaLock) {
530
531             // Netd unconditionally enable bandwidth control
532             SystemProperties.set(PROP_QTAGUID_ENABLED, "1");
533
534             mStrictEnabled = true;
535
536             setDataSaverModeEnabled(mDataSaverMode);
537
538             int size = mActiveQuotas.size();
539             if (size > 0) {
540                 if (DBG) Slog.d(TAG, "Pushing " + size + " active quota rules");
541                 final HashMap<String, Long> activeQuotas = mActiveQuotas;
542                 mActiveQuotas = Maps.newHashMap();
543                 for (Map.Entry<String, Long> entry : activeQuotas.entrySet()) {
544                     setInterfaceQuota(entry.getKey(), entry.getValue());
545                 }
546             }
547
548             size = mActiveAlerts.size();
549             if (size > 0) {
550                 if (DBG) Slog.d(TAG, "Pushing " + size + " active alert rules");
551                 final HashMap<String, Long> activeAlerts = mActiveAlerts;
552                 mActiveAlerts = Maps.newHashMap();
553                 for (Map.Entry<String, Long> entry : activeAlerts.entrySet()) {
554                     setInterfaceAlert(entry.getKey(), entry.getValue());
555                 }
556             }
557
558             SparseBooleanArray uidRejectOnQuota = null;
559             SparseBooleanArray uidAcceptOnQuota = null;
560             synchronized (mRulesLock) {
561                 size = mUidRejectOnMetered.size();
562                 if (size > 0) {
563                     if (DBG) Slog.d(TAG, "Pushing " + size + " UIDs to metered blacklist rules");
564                     uidRejectOnQuota = mUidRejectOnMetered;
565                     mUidRejectOnMetered = new SparseBooleanArray();
566                 }
567
568                 size = mUidAllowOnMetered.size();
569                 if (size > 0) {
570                     if (DBG) Slog.d(TAG, "Pushing " + size + " UIDs to metered whitelist rules");
571                     uidAcceptOnQuota = mUidAllowOnMetered;
572                     mUidAllowOnMetered = new SparseBooleanArray();
573                 }
574             }
575             if (uidRejectOnQuota != null) {
576                 for (int i = 0; i < uidRejectOnQuota.size(); i++) {
577                     setUidMeteredNetworkBlacklist(uidRejectOnQuota.keyAt(i),
578                             uidRejectOnQuota.valueAt(i));
579                 }
580             }
581             if (uidAcceptOnQuota != null) {
582                 for (int i = 0; i < uidAcceptOnQuota.size(); i++) {
583                     setUidMeteredNetworkWhitelist(uidAcceptOnQuota.keyAt(i),
584                             uidAcceptOnQuota.valueAt(i));
585                 }
586             }
587
588             size = mUidCleartextPolicy.size();
589             if (size > 0) {
590                 if (DBG) Slog.d(TAG, "Pushing " + size + " active UID cleartext policies");
591                 final SparseIntArray local = mUidCleartextPolicy;
592                 mUidCleartextPolicy = new SparseIntArray();
593                 for (int i = 0; i < local.size(); i++) {
594                     setUidCleartextNetworkPolicy(local.keyAt(i), local.valueAt(i));
595                 }
596             }
597
598             setFirewallEnabled(mFirewallEnabled);
599
600             syncFirewallChainLocked(FIREWALL_CHAIN_NONE, "");
601             syncFirewallChainLocked(FIREWALL_CHAIN_STANDBY, "standby ");
602             syncFirewallChainLocked(FIREWALL_CHAIN_DOZABLE, "dozable ");
603             syncFirewallChainLocked(FIREWALL_CHAIN_POWERSAVE, "powersave ");
604
605             final int[] chains =
606                     {FIREWALL_CHAIN_STANDBY, FIREWALL_CHAIN_DOZABLE, FIREWALL_CHAIN_POWERSAVE};
607             for (int chain : chains) {
608                 if (getFirewallChainState(chain)) {
609                     setFirewallChainEnabled(chain, true);
610                 }
611             }
612         }
613
614
615         try {
616             getBatteryStats().noteNetworkStatsEnabled();
617         } catch (RemoteException e) {
618         }
619
620     }
621
622     /**
623      * Notify our observers of a new or updated interface address.
624      */
625     private void notifyAddressUpdated(String iface, LinkAddress address) {
626         invokeForAllObservers(o -> o.addressUpdated(iface, address));
627     }
628
629     /**
630      * Notify our observers of a deleted interface address.
631      */
632     private void notifyAddressRemoved(String iface, LinkAddress address) {
633         invokeForAllObservers(o -> o.addressRemoved(iface, address));
634     }
635
636     /**
637      * Notify our observers of DNS server information received.
638      */
639     private void notifyInterfaceDnsServerInfo(String iface, long lifetime, String[] addresses) {
640         invokeForAllObservers(o -> o.interfaceDnsServerInfo(iface, lifetime, addresses));
641     }
642
643     /**
644      * Notify our observers of a route change.
645      */
646     private void notifyRouteChange(boolean updated, RouteInfo route) {
647         if (updated) {
648             invokeForAllObservers(o -> o.routeUpdated(route));
649         } else {
650             invokeForAllObservers(o -> o.routeRemoved(route));
651         }
652     }
653
654     private class NetdUnsolicitedEventListener extends INetdUnsolicitedEventListener.Stub {
655         @Override
656         public void onInterfaceClassActivityChanged(boolean isActive,
657                 int label, long timestamp, int uid) throws RemoteException {
658             final long timestampNanos;
659             if (timestamp <= 0) {
660                 timestampNanos = SystemClock.elapsedRealtimeNanos();
661             } else {
662                 timestampNanos = timestamp;
663             }
664             mDaemonHandler.post(() ->
665                     notifyInterfaceClassActivity(label, isActive, timestampNanos, uid, false));
666         }
667
668         @Override
669         public void onQuotaLimitReached(String alertName, String ifName)
670                 throws RemoteException {
671             mDaemonHandler.post(() -> notifyLimitReached(alertName, ifName));
672         }
673
674         @Override
675         public void onInterfaceDnsServerInfo(String ifName,
676                 long lifetime, String[] servers) throws RemoteException {
677             mDaemonHandler.post(() -> notifyInterfaceDnsServerInfo(ifName, lifetime, servers));
678         }
679
680         @Override
681         public void onInterfaceAddressUpdated(String addr,
682                 String ifName, int flags, int scope) throws RemoteException {
683             final LinkAddress address = new LinkAddress(addr, flags, scope);
684             mDaemonHandler.post(() -> notifyAddressUpdated(ifName, address));
685         }
686
687         @Override
688         public void onInterfaceAddressRemoved(String addr,
689                 String ifName, int flags, int scope) throws RemoteException {
690             final LinkAddress address = new LinkAddress(addr, flags, scope);
691             mDaemonHandler.post(() -> notifyAddressRemoved(ifName, address));
692         }
693
694         @Override
695         public void onInterfaceAdded(String ifName) throws RemoteException {
696             mDaemonHandler.post(() -> notifyInterfaceAdded(ifName));
697         }
698
699         @Override
700         public void onInterfaceRemoved(String ifName) throws RemoteException {
701             mDaemonHandler.post(() -> notifyInterfaceRemoved(ifName));
702         }
703
704         @Override
705         public void onInterfaceChanged(String ifName, boolean up)
706                 throws RemoteException {
707             mDaemonHandler.post(() -> notifyInterfaceStatusChanged(ifName, up));
708         }
709
710         @Override
711         public void onInterfaceLinkStateChanged(String ifName, boolean up)
712                 throws RemoteException {
713             mDaemonHandler.post(() -> notifyInterfaceLinkStateChanged(ifName, up));
714         }
715
716         @Override
717         public void onRouteChanged(boolean updated,
718                 String route, String gateway, String ifName) throws RemoteException {
719             final RouteInfo processRoute = new RouteInfo(new IpPrefix(route),
720                     ("".equals(gateway)) ? null : InetAddresses.parseNumericAddress(gateway),
721                     ifName);
722             mDaemonHandler.post(() -> notifyRouteChange(updated, processRoute));
723         }
724
725         @Override
726         public void onStrictCleartextDetected(int uid, String hex) throws RemoteException {
727             // Don't need to post to mDaemonHandler because the only thing
728             // that notifyCleartextNetwork does is post to a handler
729             ActivityManager.getService().notifyCleartextNetwork(uid,
730                     HexDump.hexStringToByteArray(hex));
731         }
732
733         @Override
734         public int getInterfaceVersion() {
735             return INetdUnsolicitedEventListener.VERSION;
736         }
737     }
738
739     //
740     // INetworkManagementService members
741     //
742     @Override
743     public String[] listInterfaces() {
744         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
745         try {
746             return mNetdService.interfaceGetList();
747         } catch (RemoteException | ServiceSpecificException e) {
748             throw new IllegalStateException(e);
749         }
750     }
751
752     /**
753      * Convert InterfaceConfiguration to InterfaceConfigurationParcel with given ifname.
754      */
755     private static InterfaceConfigurationParcel toStableParcel(InterfaceConfiguration cfg,
756             String iface) {
757         InterfaceConfigurationParcel cfgParcel = new InterfaceConfigurationParcel();
758         cfgParcel.ifName = iface;
759         String hwAddr = cfg.getHardwareAddress();
760         if (!TextUtils.isEmpty(hwAddr)) {
761             cfgParcel.hwAddr = hwAddr;
762         } else {
763             cfgParcel.hwAddr = "";
764         }
765         cfgParcel.ipv4Addr = cfg.getLinkAddress().getAddress().getHostAddress();
766         cfgParcel.prefixLength = cfg.getLinkAddress().getPrefixLength();
767         ArrayList<String> flags = new ArrayList<>();
768         for (String flag : cfg.getFlags()) {
769             flags.add(flag);
770         }
771         cfgParcel.flags = flags.toArray(new String[0]);
772
773         return cfgParcel;
774     }
775
776     /**
777      * Construct InterfaceConfiguration from InterfaceConfigurationParcel.
778      */
779     public static InterfaceConfiguration fromStableParcel(InterfaceConfigurationParcel p) {
780         InterfaceConfiguration cfg = new InterfaceConfiguration();
781         cfg.setHardwareAddress(p.hwAddr);
782
783         final InetAddress addr = NetworkUtils.numericToInetAddress(p.ipv4Addr);
784         cfg.setLinkAddress(new LinkAddress(addr, p.prefixLength));
785         for (String flag : p.flags) {
786             cfg.setFlag(flag);
787         }
788
789         return cfg;
790     }
791
792     @Override
793     public InterfaceConfiguration getInterfaceConfig(String iface) {
794         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
795         final InterfaceConfigurationParcel result;
796         try {
797             result = mNetdService.interfaceGetCfg(iface);
798         } catch (RemoteException | ServiceSpecificException e) {
799             throw new IllegalStateException(e);
800         }
801
802         try {
803             final InterfaceConfiguration cfg = fromStableParcel(result);
804             return cfg;
805         } catch (IllegalArgumentException iae) {
806             throw new IllegalStateException("Invalid InterfaceConfigurationParcel", iae);
807         }
808     }
809
810     @Override
811     public void setInterfaceConfig(String iface, InterfaceConfiguration cfg) {
812         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
813         LinkAddress linkAddr = cfg.getLinkAddress();
814         if (linkAddr == null || linkAddr.getAddress() == null) {
815             throw new IllegalStateException("Null LinkAddress given");
816         }
817
818         final InterfaceConfigurationParcel cfgParcel = toStableParcel(cfg, iface);
819
820         try {
821             mNetdService.interfaceSetCfg(cfgParcel);
822         } catch (RemoteException | ServiceSpecificException e) {
823             throw new IllegalStateException(e);
824         }
825     }
826
827     @Override
828     public void setInterfaceDown(String iface) {
829         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
830         final InterfaceConfiguration ifcg = getInterfaceConfig(iface);
831         ifcg.setInterfaceDown();
832         setInterfaceConfig(iface, ifcg);
833     }
834
835     @Override
836     public void setInterfaceUp(String iface) {
837         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
838         final InterfaceConfiguration ifcg = getInterfaceConfig(iface);
839         ifcg.setInterfaceUp();
840         setInterfaceConfig(iface, ifcg);
841     }
842
843     @Override
844     public void setInterfaceIpv6PrivacyExtensions(String iface, boolean enable) {
845         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
846         try {
847             mNetdService.interfaceSetIPv6PrivacyExtensions(iface, enable);
848         } catch (RemoteException | ServiceSpecificException e) {
849             throw new IllegalStateException(e);
850         }
851     }
852
853     /* TODO: This is right now a IPv4 only function. Works for wifi which loses its
854        IPv6 addresses on interface down, but we need to do full clean up here */
855     @Override
856     public void clearInterfaceAddresses(String iface) {
857         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
858         try {
859             mNetdService.interfaceClearAddrs(iface);
860         } catch (RemoteException | ServiceSpecificException e) {
861             throw new IllegalStateException(e);
862         }
863     }
864
865     @Override
866     public void enableIpv6(String iface) {
867         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
868         try {
869             mNetdService.interfaceSetEnableIPv6(iface, true);
870         } catch (RemoteException | ServiceSpecificException e) {
871             throw new IllegalStateException(e);
872         }
873     }
874
875     @Override
876     public void setIPv6AddrGenMode(String iface, int mode) throws ServiceSpecificException {
877         try {
878             mNetdService.setIPv6AddrGenMode(iface, mode);
879         } catch (RemoteException e) {
880             throw e.rethrowAsRuntimeException();
881         }
882     }
883
884     @Override
885     public void disableIpv6(String iface) {
886         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
887         try {
888             mNetdService.interfaceSetEnableIPv6(iface, false);
889         } catch (RemoteException | ServiceSpecificException e) {
890             throw new IllegalStateException(e);
891         }
892     }
893
894     @Override
895     public void addRoute(int netId, RouteInfo route) {
896         modifyRoute(MODIFY_OPERATION_ADD, netId, route);
897     }
898
899     @Override
900     public void removeRoute(int netId, RouteInfo route) {
901         modifyRoute(MODIFY_OPERATION_REMOVE, netId, route);
902     }
903
904     private void modifyRoute(boolean add, int netId, RouteInfo route) {
905         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
906
907         final String ifName = route.getInterface();
908         final String dst = route.getDestination().toString();
909         final String nextHop;
910
911         switch (route.getType()) {
912             case RouteInfo.RTN_UNICAST:
913                 if (route.hasGateway()) {
914                     nextHop = route.getGateway().getHostAddress();
915                 } else {
916                     nextHop = INetd.NEXTHOP_NONE;
917                 }
918                 break;
919             case RouteInfo.RTN_UNREACHABLE:
920                 nextHop = INetd.NEXTHOP_UNREACHABLE;
921                 break;
922             case RouteInfo.RTN_THROW:
923                 nextHop = INetd.NEXTHOP_THROW;
924                 break;
925             default:
926                 nextHop = INetd.NEXTHOP_NONE;
927                 break;
928         }
929         try {
930             if (add) {
931                 mNetdService.networkAddRoute(netId, ifName, dst, nextHop);
932             } else {
933                 mNetdService.networkRemoveRoute(netId, ifName, dst, nextHop);
934             }
935         } catch (RemoteException | ServiceSpecificException e) {
936             throw new IllegalStateException(e);
937         }
938     }
939
940     private ArrayList<String> readRouteList(String filename) {
941         FileInputStream fstream = null;
942         ArrayList<String> list = new ArrayList<>();
943
944         try {
945             fstream = new FileInputStream(filename);
946             DataInputStream in = new DataInputStream(fstream);
947             BufferedReader br = new BufferedReader(new InputStreamReader(in));
948             String s;
949
950             // throw away the title line
951
952             while (((s = br.readLine()) != null) && (s.length() != 0)) {
953                 list.add(s);
954             }
955         } catch (IOException ex) {
956             // return current list, possibly empty
957         } finally {
958             if (fstream != null) {
959                 try {
960                     fstream.close();
961                 } catch (IOException ex) {}
962             }
963         }
964
965         return list;
966     }
967
968     @Override
969     public void setMtu(String iface, int mtu) {
970         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
971
972         try {
973             mNetdService.interfaceSetMtu(iface, mtu);
974         } catch (RemoteException | ServiceSpecificException e) {
975             throw new IllegalStateException(e);
976         }
977     }
978
979     @Override
980     public void shutdown() {
981         // TODO: remove from aidl if nobody calls externally
982         mContext.enforceCallingOrSelfPermission(SHUTDOWN, TAG);
983
984         Slog.i(TAG, "Shutting down");
985     }
986
987     @Override
988     public boolean getIpForwardingEnabled() throws IllegalStateException{
989         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
990
991         try {
992             final boolean isEnabled = mNetdService.ipfwdEnabled();
993             return isEnabled;
994         } catch (RemoteException | ServiceSpecificException e) {
995             throw new IllegalStateException(e);
996         }
997     }
998
999     @Override
1000     public void setIpForwardingEnabled(boolean enable) {
1001         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1002         try {
1003             if (enable) {
1004                 mNetdService.ipfwdEnableForwarding("tethering");
1005             } else {
1006                 mNetdService.ipfwdDisableForwarding("tethering");
1007             }
1008         } catch (RemoteException | ServiceSpecificException e) {
1009             throw new IllegalStateException(e);
1010         }
1011     }
1012
1013     @Override
1014     public void startTethering(String[] dhcpRange) {
1015         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1016         // an odd number of addrs will fail
1017
1018         try {
1019             mNetdService.tetherStart(dhcpRange);
1020         } catch (RemoteException | ServiceSpecificException e) {
1021             throw new IllegalStateException(e);
1022         }
1023     }
1024
1025     @Override
1026     public void stopTethering() {
1027         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1028         try {
1029             mNetdService.tetherStop();
1030         } catch (RemoteException | ServiceSpecificException e) {
1031             throw new IllegalStateException(e);
1032         }
1033     }
1034
1035     @Override
1036     public boolean isTetheringStarted() {
1037         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1038
1039         try {
1040             final boolean isEnabled = mNetdService.tetherIsEnabled();
1041             return isEnabled;
1042         } catch (RemoteException | ServiceSpecificException e) {
1043             throw new IllegalStateException(e);
1044         }
1045     }
1046
1047     @Override
1048     public void tetherInterface(String iface) {
1049         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1050         try {
1051             mNetdService.tetherInterfaceAdd(iface);
1052         } catch (RemoteException | ServiceSpecificException e) {
1053             throw new IllegalStateException(e);
1054         }
1055         List<RouteInfo> routes = new ArrayList<>();
1056         // The RouteInfo constructor truncates the LinkAddress to a network prefix, thus making it
1057         // suitable to use as a route destination.
1058         routes.add(new RouteInfo(getInterfaceConfig(iface).getLinkAddress(), null, iface));
1059         addInterfaceToLocalNetwork(iface, routes);
1060     }
1061
1062     @Override
1063     public void untetherInterface(String iface) {
1064         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1065         try {
1066             mNetdService.tetherInterfaceRemove(iface);
1067         } catch (RemoteException | ServiceSpecificException e) {
1068             throw new IllegalStateException(e);
1069         } finally {
1070             removeInterfaceFromLocalNetwork(iface);
1071         }
1072     }
1073
1074     @Override
1075     public String[] listTetheredInterfaces() {
1076         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1077         try {
1078             return mNetdService.tetherInterfaceList();
1079         } catch (RemoteException | ServiceSpecificException e) {
1080             throw new IllegalStateException(e);
1081         }
1082     }
1083
1084     @Override
1085     public void setDnsForwarders(Network network, String[] dns) {
1086         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1087
1088         int netId = (network != null) ? network.netId : ConnectivityManager.NETID_UNSET;
1089
1090         try {
1091             mNetdService.tetherDnsSet(netId, dns);
1092         } catch (RemoteException | ServiceSpecificException e) {
1093             throw new IllegalStateException(e);
1094         }
1095     }
1096
1097     @Override
1098     public String[] getDnsForwarders() {
1099         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1100         try {
1101             return mNetdService.tetherDnsList();
1102         } catch (RemoteException | ServiceSpecificException e) {
1103             throw new IllegalStateException(e);
1104         }
1105     }
1106
1107     private List<InterfaceAddress> excludeLinkLocal(List<InterfaceAddress> addresses) {
1108         ArrayList<InterfaceAddress> filtered = new ArrayList<>(addresses.size());
1109         for (InterfaceAddress ia : addresses) {
1110             if (!ia.getAddress().isLinkLocalAddress())
1111                 filtered.add(ia);
1112         }
1113         return filtered;
1114     }
1115
1116     private void modifyInterfaceForward(boolean add, String fromIface, String toIface) {
1117         try {
1118             if (add) {
1119                 mNetdService.ipfwdAddInterfaceForward(fromIface, toIface);
1120             } else {
1121                 mNetdService.ipfwdRemoveInterfaceForward(fromIface, toIface);
1122             }
1123         } catch (RemoteException | ServiceSpecificException e) {
1124             throw new IllegalStateException(e);
1125         }
1126     }
1127
1128     @Override
1129     public void startInterfaceForwarding(String fromIface, String toIface) {
1130         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1131         modifyInterfaceForward(true, fromIface, toIface);
1132     }
1133
1134     @Override
1135     public void stopInterfaceForwarding(String fromIface, String toIface) {
1136         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1137         modifyInterfaceForward(false, fromIface, toIface);
1138     }
1139
1140     @Override
1141     public void enableNat(String internalInterface, String externalInterface) {
1142         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1143         try {
1144             mNetdService.tetherAddForward(internalInterface, externalInterface);
1145         } catch (RemoteException | ServiceSpecificException e) {
1146             throw new IllegalStateException(e);
1147         }
1148     }
1149
1150     @Override
1151     public void disableNat(String internalInterface, String externalInterface) {
1152         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1153         try {
1154             mNetdService.tetherRemoveForward(internalInterface, externalInterface);
1155         } catch (RemoteException | ServiceSpecificException e) {
1156             throw new IllegalStateException(e);
1157         }
1158     }
1159
1160     @Override
1161     public void addIdleTimer(String iface, int timeout, final int type) {
1162         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1163
1164         if (DBG) Slog.d(TAG, "Adding idletimer");
1165
1166         synchronized (mIdleTimerLock) {
1167             IdleTimerParams params = mActiveIdleTimers.get(iface);
1168             if (params != null) {
1169                 // the interface already has idletimer, update network count
1170                 params.networkCount++;
1171                 return;
1172             }
1173
1174             try {
1175                 mNetdService.idletimerAddInterface(iface, timeout, Integer.toString(type));
1176             } catch (RemoteException | ServiceSpecificException e) {
1177                 throw new IllegalStateException(e);
1178             }
1179             mActiveIdleTimers.put(iface, new IdleTimerParams(timeout, type));
1180
1181             // Networks start up.
1182             if (ConnectivityManager.isNetworkTypeMobile(type)) {
1183                 mNetworkActive = false;
1184             }
1185             mDaemonHandler.post(() -> notifyInterfaceClassActivity(type, true,
1186                     SystemClock.elapsedRealtimeNanos(), -1, false));
1187         }
1188     }
1189
1190     @Override
1191     public void removeIdleTimer(String iface) {
1192         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1193
1194         if (DBG) Slog.d(TAG, "Removing idletimer");
1195
1196         synchronized (mIdleTimerLock) {
1197             final IdleTimerParams params = mActiveIdleTimers.get(iface);
1198             if (params == null || --(params.networkCount) > 0) {
1199                 return;
1200             }
1201
1202             try {
1203                 mNetdService.idletimerRemoveInterface(iface,
1204                         params.timeout, Integer.toString(params.type));
1205             } catch (RemoteException | ServiceSpecificException e) {
1206                 throw new IllegalStateException(e);
1207             }
1208             mActiveIdleTimers.remove(iface);
1209             mDaemonHandler.post(() -> notifyInterfaceClassActivity(params.type, false,
1210                     SystemClock.elapsedRealtimeNanos(), -1, false));
1211         }
1212     }
1213
1214     @Override
1215     public NetworkStats getNetworkStatsSummaryDev() {
1216         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1217         try {
1218             return mStatsFactory.readNetworkStatsSummaryDev();
1219         } catch (IOException e) {
1220             throw new IllegalStateException(e);
1221         }
1222     }
1223
1224     @Override
1225     public NetworkStats getNetworkStatsSummaryXt() {
1226         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1227         try {
1228             return mStatsFactory.readNetworkStatsSummaryXt();
1229         } catch (IOException e) {
1230             throw new IllegalStateException(e);
1231         }
1232     }
1233
1234     @Override
1235     public NetworkStats getNetworkStatsDetail() {
1236         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1237         try {
1238             return mStatsFactory.readNetworkStatsDetail();
1239         } catch (IOException e) {
1240             throw new IllegalStateException(e);
1241         }
1242     }
1243
1244     @Override
1245     public void setInterfaceQuota(String iface, long quotaBytes) {
1246         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1247
1248         synchronized (mQuotaLock) {
1249             if (mActiveQuotas.containsKey(iface)) {
1250                 throw new IllegalStateException("iface " + iface + " already has quota");
1251             }
1252
1253             try {
1254                 // TODO: support quota shared across interfaces
1255                 mNetdService.bandwidthSetInterfaceQuota(iface, quotaBytes);
1256
1257                 mActiveQuotas.put(iface, quotaBytes);
1258             } catch (RemoteException | ServiceSpecificException e) {
1259                 throw new IllegalStateException(e);
1260             }
1261
1262             synchronized (mTetheringStatsProviders) {
1263                 for (ITetheringStatsProvider provider : mTetheringStatsProviders.keySet()) {
1264                     try {
1265                         provider.setInterfaceQuota(iface, quotaBytes);
1266                     } catch (RemoteException e) {
1267                         Log.e(TAG, "Problem setting tethering data limit on provider " +
1268                                 mTetheringStatsProviders.get(provider) + ": " + e);
1269                     }
1270                 }
1271             }
1272         }
1273     }
1274
1275     @Override
1276     public void removeInterfaceQuota(String iface) {
1277         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1278
1279         synchronized (mQuotaLock) {
1280             if (!mActiveQuotas.containsKey(iface)) {
1281                 // TODO: eventually consider throwing
1282                 return;
1283             }
1284
1285             mActiveQuotas.remove(iface);
1286             mActiveAlerts.remove(iface);
1287
1288             try {
1289                 // TODO: support quota shared across interfaces
1290                 mNetdService.bandwidthRemoveInterfaceQuota(iface);
1291             } catch (RemoteException | ServiceSpecificException e) {
1292                 throw new IllegalStateException(e);
1293             }
1294
1295             synchronized (mTetheringStatsProviders) {
1296                 for (ITetheringStatsProvider provider : mTetheringStatsProviders.keySet()) {
1297                     try {
1298                         provider.setInterfaceQuota(iface, ITetheringStatsProvider.QUOTA_UNLIMITED);
1299                     } catch (RemoteException e) {
1300                         Log.e(TAG, "Problem removing tethering data limit on provider " +
1301                                 mTetheringStatsProviders.get(provider) + ": " + e);
1302                     }
1303                 }
1304             }
1305         }
1306     }
1307
1308     @Override
1309     public void setInterfaceAlert(String iface, long alertBytes) {
1310         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1311
1312         // quick sanity check
1313         if (!mActiveQuotas.containsKey(iface)) {
1314             throw new IllegalStateException("setting alert requires existing quota on iface");
1315         }
1316
1317         synchronized (mQuotaLock) {
1318             if (mActiveAlerts.containsKey(iface)) {
1319                 throw new IllegalStateException("iface " + iface + " already has alert");
1320             }
1321
1322             try {
1323                 // TODO: support alert shared across interfaces
1324                 mNetdService.bandwidthSetInterfaceAlert(iface, alertBytes);
1325                 mActiveAlerts.put(iface, alertBytes);
1326             } catch (RemoteException | ServiceSpecificException e) {
1327                 throw new IllegalStateException(e);
1328             }
1329         }
1330     }
1331
1332     @Override
1333     public void removeInterfaceAlert(String iface) {
1334         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1335
1336         synchronized (mQuotaLock) {
1337             if (!mActiveAlerts.containsKey(iface)) {
1338                 // TODO: eventually consider throwing
1339                 return;
1340             }
1341
1342             try {
1343                 // TODO: support alert shared across interfaces
1344                 mNetdService.bandwidthRemoveInterfaceAlert(iface);
1345                 mActiveAlerts.remove(iface);
1346             } catch (RemoteException | ServiceSpecificException e) {
1347                 throw new IllegalStateException(e);
1348             }
1349         }
1350     }
1351
1352     @Override
1353     public void setGlobalAlert(long alertBytes) {
1354         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1355
1356         try {
1357             mNetdService.bandwidthSetGlobalAlert(alertBytes);
1358         } catch (RemoteException | ServiceSpecificException e) {
1359             throw new IllegalStateException(e);
1360         }
1361     }
1362
1363     private void setUidOnMeteredNetworkList(int uid, boolean blacklist, boolean enable) {
1364         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1365
1366         synchronized (mQuotaLock) {
1367             boolean oldEnable;
1368             SparseBooleanArray quotaList;
1369             synchronized (mRulesLock) {
1370                 quotaList = blacklist ? mUidRejectOnMetered : mUidAllowOnMetered;
1371                 oldEnable = quotaList.get(uid, false);
1372             }
1373             if (oldEnable == enable) {
1374                 // TODO: eventually consider throwing
1375                 return;
1376             }
1377
1378             Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "inetd bandwidth");
1379             try {
1380                 if (blacklist) {
1381                     if (enable) {
1382                         mNetdService.bandwidthAddNaughtyApp(uid);
1383                     } else {
1384                         mNetdService.bandwidthRemoveNaughtyApp(uid);
1385                     }
1386                 } else {
1387                     if (enable) {
1388                         mNetdService.bandwidthAddNiceApp(uid);
1389                     } else {
1390                         mNetdService.bandwidthRemoveNiceApp(uid);
1391                     }
1392                 }
1393                 synchronized (mRulesLock) {
1394                     if (enable) {
1395                         quotaList.put(uid, true);
1396                     } else {
1397                         quotaList.delete(uid);
1398                     }
1399                 }
1400             } catch (RemoteException | ServiceSpecificException e) {
1401                 throw new IllegalStateException(e);
1402             } finally {
1403                 Trace.traceEnd(Trace.TRACE_TAG_NETWORK);
1404             }
1405         }
1406     }
1407
1408     @Override
1409     public void setUidMeteredNetworkBlacklist(int uid, boolean enable) {
1410         setUidOnMeteredNetworkList(uid, true, enable);
1411     }
1412
1413     @Override
1414     public void setUidMeteredNetworkWhitelist(int uid, boolean enable) {
1415         setUidOnMeteredNetworkList(uid, false, enable);
1416     }
1417
1418     @Override
1419     public boolean setDataSaverModeEnabled(boolean enable) {
1420         mContext.enforceCallingOrSelfPermission(NETWORK_SETTINGS, TAG);
1421
1422         if (DBG) Log.d(TAG, "setDataSaverMode: " + enable);
1423         synchronized (mQuotaLock) {
1424             if (mDataSaverMode == enable) {
1425                 Log.w(TAG, "setDataSaverMode(): already " + mDataSaverMode);
1426                 return true;
1427             }
1428             Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "bandwidthEnableDataSaver");
1429             try {
1430                 final boolean changed = mNetdService.bandwidthEnableDataSaver(enable);
1431                 if (changed) {
1432                     mDataSaverMode = enable;
1433                 } else {
1434                     Log.w(TAG, "setDataSaverMode(" + enable + "): netd command silently failed");
1435                 }
1436                 return changed;
1437             } catch (RemoteException e) {
1438                 Log.w(TAG, "setDataSaverMode(" + enable + "): netd command failed", e);
1439                 return false;
1440             } finally {
1441                 Trace.traceEnd(Trace.TRACE_TAG_NETWORK);
1442             }
1443         }
1444     }
1445
1446     private static UidRangeParcel makeUidRangeParcel(int start, int stop) {
1447         UidRangeParcel range = new UidRangeParcel();
1448         range.start = start;
1449         range.stop = stop;
1450         return range;
1451     }
1452
1453     private static UidRangeParcel[] toStableParcels(UidRange[] ranges) {
1454         UidRangeParcel[] stableRanges = new UidRangeParcel[ranges.length];
1455         for (int i = 0; i < ranges.length; i++) {
1456             stableRanges[i] = makeUidRangeParcel(ranges[i].start, ranges[i].stop);
1457         }
1458         return stableRanges;
1459     }
1460
1461     @Override
1462     public void setAllowOnlyVpnForUids(boolean add, UidRange[] uidRanges)
1463             throws ServiceSpecificException {
1464         mContext.enforceCallingOrSelfPermission(NETWORK_STACK, TAG);
1465         try {
1466             mNetdService.networkRejectNonSecureVpn(add, toStableParcels(uidRanges));
1467         } catch (ServiceSpecificException e) {
1468             Log.w(TAG, "setAllowOnlyVpnForUids(" + add + ", " + Arrays.toString(uidRanges) + ")"
1469                     + ": netd command failed", e);
1470             throw e;
1471         } catch (RemoteException e) {
1472             Log.w(TAG, "setAllowOnlyVpnForUids(" + add + ", " + Arrays.toString(uidRanges) + ")"
1473                     + ": netd command failed", e);
1474             throw e.rethrowAsRuntimeException();
1475         }
1476     }
1477
1478     private void applyUidCleartextNetworkPolicy(int uid, int policy) {
1479         final int policyValue;
1480         switch (policy) {
1481             case StrictMode.NETWORK_POLICY_ACCEPT:
1482                 policyValue = INetd.PENALTY_POLICY_ACCEPT;
1483                 break;
1484             case StrictMode.NETWORK_POLICY_LOG:
1485                 policyValue = INetd.PENALTY_POLICY_LOG;
1486                 break;
1487             case StrictMode.NETWORK_POLICY_REJECT:
1488                 policyValue = INetd.PENALTY_POLICY_REJECT;
1489                 break;
1490             default:
1491                 throw new IllegalArgumentException("Unknown policy " + policy);
1492         }
1493
1494         try {
1495             mNetdService.strictUidCleartextPenalty(uid, policyValue);
1496             mUidCleartextPolicy.put(uid, policy);
1497         } catch (RemoteException | ServiceSpecificException e) {
1498             throw new IllegalStateException(e);
1499         }
1500     }
1501
1502     @Override
1503     public void setUidCleartextNetworkPolicy(int uid, int policy) {
1504         if (Binder.getCallingUid() != uid) {
1505             mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1506         }
1507
1508         synchronized (mQuotaLock) {
1509             final int oldPolicy = mUidCleartextPolicy.get(uid, StrictMode.NETWORK_POLICY_ACCEPT);
1510             if (oldPolicy == policy) {
1511                 // This also ensures we won't needlessly apply an ACCEPT policy if we've just
1512                 // enabled strict and the underlying iptables rules are empty.
1513                 return;
1514             }
1515
1516             // TODO: remove this code after removing prepareNativeDaemon()
1517             if (!mStrictEnabled) {
1518                 // Module isn't enabled yet; stash the requested policy away to
1519                 // apply later once the daemon is connected.
1520                 mUidCleartextPolicy.put(uid, policy);
1521                 return;
1522             }
1523
1524             // netd does not keep state on strict mode policies, and cannot replace a non-accept
1525             // policy without deleting it first. Rather than add state to netd, just always send
1526             // it an accept policy when switching between two non-accept policies.
1527             // TODO: consider keeping state in netd so we can simplify this code.
1528             if (oldPolicy != StrictMode.NETWORK_POLICY_ACCEPT &&
1529                     policy != StrictMode.NETWORK_POLICY_ACCEPT) {
1530                 applyUidCleartextNetworkPolicy(uid, StrictMode.NETWORK_POLICY_ACCEPT);
1531             }
1532
1533             applyUidCleartextNetworkPolicy(uid, policy);
1534         }
1535     }
1536
1537     @Override
1538     public boolean isBandwidthControlEnabled() {
1539         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1540         return true;
1541     }
1542
1543     @Override
1544     public NetworkStats getNetworkStatsUidDetail(int uid, String[] ifaces) {
1545         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1546         try {
1547             return mStatsFactory.readNetworkStatsDetail(uid, ifaces, TAG_ALL);
1548         } catch (IOException e) {
1549             throw new IllegalStateException(e);
1550         }
1551     }
1552
1553     private class NetdTetheringStatsProvider extends ITetheringStatsProvider.Stub {
1554         @Override
1555         public NetworkStats getTetherStats(int how) {
1556             // We only need to return per-UID stats. Per-device stats are already counted by
1557             // interface counters.
1558             if (how != STATS_PER_UID) {
1559                 return new NetworkStats(SystemClock.elapsedRealtime(), 0);
1560             }
1561
1562             final TetherStatsParcel[] tetherStatsVec;
1563             try {
1564                 tetherStatsVec = mNetdService.tetherGetStats();
1565             } catch (RemoteException | ServiceSpecificException e) {
1566                 throw new IllegalStateException("problem parsing tethering stats: ", e);
1567             }
1568
1569             final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(),
1570                 tetherStatsVec.length);
1571             final NetworkStats.Entry entry = new NetworkStats.Entry();
1572
1573             for (TetherStatsParcel tetherStats : tetherStatsVec) {
1574                 try {
1575                     entry.iface = tetherStats.iface;
1576                     entry.uid = UID_TETHERING;
1577                     entry.set = SET_DEFAULT;
1578                     entry.tag = TAG_NONE;
1579                     entry.rxBytes   = tetherStats.rxBytes;
1580                     entry.rxPackets = tetherStats.rxPackets;
1581                     entry.txBytes   = tetherStats.txBytes;
1582                     entry.txPackets = tetherStats.txPackets;
1583                     stats.combineValues(entry);
1584                 } catch (ArrayIndexOutOfBoundsException e) {
1585                     throw new IllegalStateException("invalid tethering stats " + e);
1586                 }
1587             }
1588
1589             return stats;
1590         }
1591
1592         @Override
1593         public void setInterfaceQuota(String iface, long quotaBytes) {
1594             // Do nothing. netd is already informed of quota changes in setInterfaceQuota.
1595         }
1596     }
1597
1598     @Override
1599     public NetworkStats getNetworkStatsTethering(int how) {
1600         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1601
1602         final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 1);
1603         synchronized (mTetheringStatsProviders) {
1604             for (ITetheringStatsProvider provider: mTetheringStatsProviders.keySet()) {
1605                 try {
1606                     stats.combineAllValues(provider.getTetherStats(how));
1607                 } catch (RemoteException e) {
1608                     Log.e(TAG, "Problem reading tethering stats from " +
1609                             mTetheringStatsProviders.get(provider) + ": " + e);
1610                 }
1611             }
1612         }
1613         return stats;
1614     }
1615
1616     @Override
1617     public void addVpnUidRanges(int netId, UidRange[] ranges) {
1618         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1619
1620         try {
1621             mNetdService.networkAddUidRanges(netId, toStableParcels(ranges));
1622         } catch (RemoteException | ServiceSpecificException e) {
1623             throw new IllegalStateException(e);
1624         }
1625     }
1626
1627     @Override
1628     public void removeVpnUidRanges(int netId, UidRange[] ranges) {
1629         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1630         try {
1631             mNetdService.networkRemoveUidRanges(netId, toStableParcels(ranges));
1632         } catch (RemoteException | ServiceSpecificException e) {
1633             throw new IllegalStateException(e);
1634         }
1635     }
1636
1637     @Override
1638     public void setFirewallEnabled(boolean enabled) {
1639         enforceSystemUid();
1640         try {
1641             mNetdService.firewallSetFirewallType(
1642                     enabled ? INetd.FIREWALL_WHITELIST : INetd.FIREWALL_BLACKLIST);
1643             mFirewallEnabled = enabled;
1644         } catch (RemoteException | ServiceSpecificException e) {
1645             throw new IllegalStateException(e);
1646         }
1647     }
1648
1649     @Override
1650     public boolean isFirewallEnabled() {
1651         enforceSystemUid();
1652         return mFirewallEnabled;
1653     }
1654
1655     @Override
1656     public void setFirewallInterfaceRule(String iface, boolean allow) {
1657         enforceSystemUid();
1658         Preconditions.checkState(mFirewallEnabled);
1659         try {
1660             mNetdService.firewallSetInterfaceRule(iface,
1661                     allow ? INetd.FIREWALL_RULE_ALLOW : INetd.FIREWALL_RULE_DENY);
1662         } catch (RemoteException | ServiceSpecificException e) {
1663             throw new IllegalStateException(e);
1664         }
1665     }
1666
1667     private void closeSocketsForFirewallChainLocked(int chain, String chainName) {
1668         // UID ranges to close sockets on.
1669         UidRangeParcel[] ranges;
1670         // UID ranges whose sockets we won't touch.
1671         int[] exemptUids;
1672
1673         int numUids = 0;
1674         if (DBG) Slog.d(TAG, "Closing sockets after enabling chain " + chainName);
1675         if (getFirewallType(chain) == FIREWALL_WHITELIST) {
1676             // Close all sockets on all non-system UIDs...
1677             ranges = new UidRangeParcel[] {
1678                 // TODO: is there a better way of finding all existing users? If so, we could
1679                 // specify their ranges here.
1680                 makeUidRangeParcel(Process.FIRST_APPLICATION_UID, Integer.MAX_VALUE),
1681             };
1682             // ... except for the UIDs that have allow rules.
1683             synchronized (mRulesLock) {
1684                 final SparseIntArray rules = getUidFirewallRulesLR(chain);
1685                 exemptUids = new int[rules.size()];
1686                 for (int i = 0; i < exemptUids.length; i++) {
1687                     if (rules.valueAt(i) == FIREWALL_RULE_ALLOW) {
1688                         exemptUids[numUids] = rules.keyAt(i);
1689                         numUids++;
1690                     }
1691                 }
1692             }
1693             // Normally, whitelist chains only contain deny rules, so numUids == exemptUids.length.
1694             // But the code does not guarantee this in any way, and at least in one case - if we add
1695             // a UID rule to the firewall, and then disable the firewall - the chains can contain
1696             // the wrong type of rule. In this case, don't close connections that we shouldn't.
1697             //
1698             // TODO: tighten up this code by ensuring we never set the wrong type of rule, and
1699             // fix setFirewallEnabled to grab mQuotaLock and clear rules.
1700             if (numUids != exemptUids.length) {
1701                 exemptUids = Arrays.copyOf(exemptUids, numUids);
1702             }
1703         } else {
1704             // Close sockets for every UID that has a deny rule...
1705             synchronized (mRulesLock) {
1706                 final SparseIntArray rules = getUidFirewallRulesLR(chain);
1707                 ranges = new UidRangeParcel[rules.size()];
1708                 for (int i = 0; i < ranges.length; i++) {
1709                     if (rules.valueAt(i) == FIREWALL_RULE_DENY) {
1710                         int uid = rules.keyAt(i);
1711                         ranges[numUids] = makeUidRangeParcel(uid, uid);
1712                         numUids++;
1713                     }
1714                 }
1715             }
1716             // As above; usually numUids == ranges.length, but not always.
1717             if (numUids != ranges.length) {
1718                 ranges = Arrays.copyOf(ranges, numUids);
1719             }
1720             // ... with no exceptions.
1721             exemptUids = new int[0];
1722         }
1723
1724         try {
1725             mNetdService.socketDestroy(ranges, exemptUids);
1726         } catch(RemoteException | ServiceSpecificException e) {
1727             Slog.e(TAG, "Error closing sockets after enabling chain " + chainName + ": " + e);
1728         }
1729     }
1730
1731     @Override
1732     public void setFirewallChainEnabled(int chain, boolean enable) {
1733         enforceSystemUid();
1734         synchronized (mQuotaLock) {
1735             synchronized (mRulesLock) {
1736                 if (getFirewallChainState(chain) == enable) {
1737                     // All is the same, nothing to do.  This relies on the fact that netd has child
1738                     // chains default detached.
1739                     return;
1740                 }
1741                 setFirewallChainState(chain, enable);
1742             }
1743
1744             final String chainName = getFirewallChainName(chain);
1745             if (chain == FIREWALL_CHAIN_NONE) {
1746                 throw new IllegalArgumentException("Bad child chain: " + chainName);
1747             }
1748
1749             try {
1750                 mNetdService.firewallEnableChildChain(chain, enable);
1751             } catch (RemoteException | ServiceSpecificException e) {
1752                 throw new IllegalStateException(e);
1753             }
1754
1755             // Close any sockets that were opened by the affected UIDs. This has to be done after
1756             // disabling network connectivity, in case they react to the socket close by reopening
1757             // the connection and race with the iptables commands that enable the firewall. All
1758             // whitelist and blacklist chains allow RSTs through.
1759             if (enable) {
1760                 closeSocketsForFirewallChainLocked(chain, chainName);
1761             }
1762         }
1763     }
1764
1765     private String getFirewallChainName(int chain) {
1766         switch (chain) {
1767             case FIREWALL_CHAIN_STANDBY:
1768                 return FIREWALL_CHAIN_NAME_STANDBY;
1769             case FIREWALL_CHAIN_DOZABLE:
1770                 return FIREWALL_CHAIN_NAME_DOZABLE;
1771             case FIREWALL_CHAIN_POWERSAVE:
1772                 return FIREWALL_CHAIN_NAME_POWERSAVE;
1773             default:
1774                 throw new IllegalArgumentException("Bad child chain: " + chain);
1775         }
1776     }
1777
1778     private int getFirewallType(int chain) {
1779         switch (chain) {
1780             case FIREWALL_CHAIN_STANDBY:
1781                 return FIREWALL_BLACKLIST;
1782             case FIREWALL_CHAIN_DOZABLE:
1783                 return FIREWALL_WHITELIST;
1784             case FIREWALL_CHAIN_POWERSAVE:
1785                 return FIREWALL_WHITELIST;
1786             default:
1787                 return isFirewallEnabled() ? FIREWALL_WHITELIST : FIREWALL_BLACKLIST;
1788         }
1789     }
1790
1791     @Override
1792     public void setFirewallUidRules(int chain, int[] uids, int[] rules) {
1793         enforceSystemUid();
1794         synchronized (mQuotaLock) {
1795             synchronized (mRulesLock) {
1796                 SparseIntArray uidFirewallRules = getUidFirewallRulesLR(chain);
1797                 SparseIntArray newRules = new SparseIntArray();
1798                 // apply new set of rules
1799                 for (int index = uids.length - 1; index >= 0; --index) {
1800                     int uid = uids[index];
1801                     int rule = rules[index];
1802                     updateFirewallUidRuleLocked(chain, uid, rule);
1803                     newRules.put(uid, rule);
1804                 }
1805                 // collect the rules to remove.
1806                 SparseIntArray rulesToRemove = new SparseIntArray();
1807                 for (int index = uidFirewallRules.size() - 1; index >= 0; --index) {
1808                     int uid = uidFirewallRules.keyAt(index);
1809                     if (newRules.indexOfKey(uid) < 0) {
1810                         rulesToRemove.put(uid, FIREWALL_RULE_DEFAULT);
1811                     }
1812                 }
1813                 // remove dead rules
1814                 for (int index = rulesToRemove.size() - 1; index >= 0; --index) {
1815                     int uid = rulesToRemove.keyAt(index);
1816                     updateFirewallUidRuleLocked(chain, uid, FIREWALL_RULE_DEFAULT);
1817                 }
1818             }
1819             try {
1820                 switch (chain) {
1821                     case FIREWALL_CHAIN_DOZABLE:
1822                         mNetdService.firewallReplaceUidChain("fw_dozable", true, uids);
1823                         break;
1824                     case FIREWALL_CHAIN_STANDBY:
1825                         mNetdService.firewallReplaceUidChain("fw_standby", false, uids);
1826                         break;
1827                     case FIREWALL_CHAIN_POWERSAVE:
1828                         mNetdService.firewallReplaceUidChain("fw_powersave", true, uids);
1829                         break;
1830                     case FIREWALL_CHAIN_NONE:
1831                     default:
1832                         Slog.d(TAG, "setFirewallUidRules() called on invalid chain: " + chain);
1833                 }
1834             } catch (RemoteException e) {
1835                 Slog.w(TAG, "Error flushing firewall chain " + chain, e);
1836             }
1837         }
1838     }
1839
1840     @Override
1841     public void setFirewallUidRule(int chain, int uid, int rule) {
1842         enforceSystemUid();
1843         synchronized (mQuotaLock) {
1844             setFirewallUidRuleLocked(chain, uid, rule);
1845         }
1846     }
1847
1848     private void setFirewallUidRuleLocked(int chain, int uid, int rule) {
1849         if (updateFirewallUidRuleLocked(chain, uid, rule)) {
1850             final int ruleType = getFirewallRuleType(chain, rule);
1851             try {
1852                 mNetdService.firewallSetUidRule(chain, uid, ruleType);
1853             } catch (RemoteException | ServiceSpecificException e) {
1854                 throw new IllegalStateException(e);
1855             }
1856         }
1857     }
1858
1859     // TODO: now that netd supports batching, NMS should not keep these data structures anymore...
1860     private boolean updateFirewallUidRuleLocked(int chain, int uid, int rule) {
1861         synchronized (mRulesLock) {
1862             SparseIntArray uidFirewallRules = getUidFirewallRulesLR(chain);
1863
1864             final int oldUidFirewallRule = uidFirewallRules.get(uid, FIREWALL_RULE_DEFAULT);
1865             if (DBG) {
1866                 Slog.d(TAG, "oldRule = " + oldUidFirewallRule
1867                         + ", newRule=" + rule + " for uid=" + uid + " on chain " + chain);
1868             }
1869             if (oldUidFirewallRule == rule) {
1870                 if (DBG) Slog.d(TAG, "!!!!! Skipping change");
1871                 // TODO: eventually consider throwing
1872                 return false;
1873             }
1874
1875             String ruleName = getFirewallRuleName(chain, rule);
1876             String oldRuleName = getFirewallRuleName(chain, oldUidFirewallRule);
1877
1878             if (rule == NetworkPolicyManager.FIREWALL_RULE_DEFAULT) {
1879                 uidFirewallRules.delete(uid);
1880             } else {
1881                 uidFirewallRules.put(uid, rule);
1882             }
1883             return !ruleName.equals(oldRuleName);
1884         }
1885     }
1886
1887     private @NonNull String getFirewallRuleName(int chain, int rule) {
1888         String ruleName;
1889         if (getFirewallType(chain) == FIREWALL_WHITELIST) {
1890             if (rule == FIREWALL_RULE_ALLOW) {
1891                 ruleName = "allow";
1892             } else {
1893                 ruleName = "deny";
1894             }
1895         } else { // Blacklist mode
1896             if (rule == FIREWALL_RULE_DENY) {
1897                 ruleName = "deny";
1898             } else {
1899                 ruleName = "allow";
1900             }
1901         }
1902         return ruleName;
1903     }
1904
1905     @GuardedBy("mRulesLock")
1906     private @NonNull SparseIntArray getUidFirewallRulesLR(int chain) {
1907         switch (chain) {
1908             case FIREWALL_CHAIN_STANDBY:
1909                 return mUidFirewallStandbyRules;
1910             case FIREWALL_CHAIN_DOZABLE:
1911                 return mUidFirewallDozableRules;
1912             case FIREWALL_CHAIN_POWERSAVE:
1913                 return mUidFirewallPowerSaveRules;
1914             case FIREWALL_CHAIN_NONE:
1915                 return mUidFirewallRules;
1916             default:
1917                 throw new IllegalArgumentException("Unknown chain:" + chain);
1918         }
1919     }
1920
1921     private int getFirewallRuleType(int chain, int rule) {
1922         if (rule == NetworkPolicyManager.FIREWALL_RULE_DEFAULT) {
1923             return getFirewallType(chain) == FIREWALL_WHITELIST
1924                     ? INetd.FIREWALL_RULE_DENY : INetd.FIREWALL_RULE_ALLOW;
1925         }
1926         return rule;
1927     }
1928
1929     private static void enforceSystemUid() {
1930         final int uid = Binder.getCallingUid();
1931         if (uid != Process.SYSTEM_UID) {
1932             throw new SecurityException("Only available to AID_SYSTEM");
1933         }
1934     }
1935
1936     @Override
1937     public void registerNetworkActivityListener(INetworkActivityListener listener) {
1938         mNetworkActivityListeners.register(listener);
1939     }
1940
1941     @Override
1942     public void unregisterNetworkActivityListener(INetworkActivityListener listener) {
1943         mNetworkActivityListeners.unregister(listener);
1944     }
1945
1946     @Override
1947     public boolean isNetworkActive() {
1948         synchronized (mNetworkActivityListeners) {
1949             return mNetworkActive || mActiveIdleTimers.isEmpty();
1950         }
1951     }
1952
1953     private void reportNetworkActive() {
1954         final int length = mNetworkActivityListeners.beginBroadcast();
1955         try {
1956             for (int i = 0; i < length; i++) {
1957                 try {
1958                     mNetworkActivityListeners.getBroadcastItem(i).onNetworkActive();
1959                 } catch (RemoteException | RuntimeException e) {
1960                 }
1961             }
1962         } finally {
1963             mNetworkActivityListeners.finishBroadcast();
1964         }
1965     }
1966
1967     @Override
1968     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1969         if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
1970
1971         pw.print("mMobileActivityFromRadio="); pw.print(mMobileActivityFromRadio);
1972                 pw.print(" mLastPowerStateFromRadio="); pw.println(mLastPowerStateFromRadio);
1973         pw.print("mNetworkActive="); pw.println(mNetworkActive);
1974
1975         synchronized (mQuotaLock) {
1976             pw.print("Active quota ifaces: "); pw.println(mActiveQuotas.toString());
1977             pw.print("Active alert ifaces: "); pw.println(mActiveAlerts.toString());
1978             pw.print("Data saver mode: "); pw.println(mDataSaverMode);
1979             synchronized (mRulesLock) {
1980                 dumpUidRuleOnQuotaLocked(pw, "blacklist", mUidRejectOnMetered);
1981                 dumpUidRuleOnQuotaLocked(pw, "whitelist", mUidAllowOnMetered);
1982             }
1983         }
1984
1985         synchronized (mRulesLock) {
1986             dumpUidFirewallRule(pw, "", mUidFirewallRules);
1987
1988             pw.print("UID firewall standby chain enabled: "); pw.println(
1989                     getFirewallChainState(FIREWALL_CHAIN_STANDBY));
1990             dumpUidFirewallRule(pw, FIREWALL_CHAIN_NAME_STANDBY, mUidFirewallStandbyRules);
1991
1992             pw.print("UID firewall dozable chain enabled: "); pw.println(
1993                     getFirewallChainState(FIREWALL_CHAIN_DOZABLE));
1994             dumpUidFirewallRule(pw, FIREWALL_CHAIN_NAME_DOZABLE, mUidFirewallDozableRules);
1995
1996             pw.println("UID firewall powersave chain enabled: " +
1997                     getFirewallChainState(FIREWALL_CHAIN_POWERSAVE));
1998             dumpUidFirewallRule(pw, FIREWALL_CHAIN_NAME_POWERSAVE, mUidFirewallPowerSaveRules);
1999         }
2000
2001         synchronized (mIdleTimerLock) {
2002             pw.println("Idle timers:");
2003             for (HashMap.Entry<String, IdleTimerParams> ent : mActiveIdleTimers.entrySet()) {
2004                 pw.print("  "); pw.print(ent.getKey()); pw.println(":");
2005                 IdleTimerParams params = ent.getValue();
2006                 pw.print("    timeout="); pw.print(params.timeout);
2007                 pw.print(" type="); pw.print(params.type);
2008                 pw.print(" networkCount="); pw.println(params.networkCount);
2009             }
2010         }
2011
2012         pw.print("Firewall enabled: "); pw.println(mFirewallEnabled);
2013         pw.print("Netd service status: " );
2014         if (mNetdService == null) {
2015             pw.println("disconnected");
2016         } else {
2017             try {
2018                 final boolean alive = mNetdService.isAlive();
2019                 pw.println(alive ? "alive": "dead");
2020             } catch (RemoteException e) {
2021                 pw.println("unreachable");
2022             }
2023         }
2024     }
2025
2026     private void dumpUidRuleOnQuotaLocked(PrintWriter pw, String name, SparseBooleanArray list) {
2027         pw.print("UID bandwith control ");
2028         pw.print(name);
2029         pw.print(" rule: [");
2030         final int size = list.size();
2031         for (int i = 0; i < size; i++) {
2032             pw.print(list.keyAt(i));
2033             if (i < size - 1) pw.print(",");
2034         }
2035         pw.println("]");
2036     }
2037
2038     private void dumpUidFirewallRule(PrintWriter pw, String name, SparseIntArray rules) {
2039         pw.print("UID firewall ");
2040         pw.print(name);
2041         pw.print(" rule: [");
2042         final int size = rules.size();
2043         for (int i = 0; i < size; i++) {
2044             pw.print(rules.keyAt(i));
2045             pw.print(":");
2046             pw.print(rules.valueAt(i));
2047             if (i < size - 1) pw.print(",");
2048         }
2049         pw.println("]");
2050     }
2051
2052     @Override
2053     public void addInterfaceToNetwork(String iface, int netId) {
2054         modifyInterfaceInNetwork(MODIFY_OPERATION_ADD, netId, iface);
2055     }
2056
2057     @Override
2058     public void removeInterfaceFromNetwork(String iface, int netId) {
2059         modifyInterfaceInNetwork(MODIFY_OPERATION_REMOVE, netId, iface);
2060     }
2061
2062     private void modifyInterfaceInNetwork(boolean add, int netId, String iface) {
2063         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
2064         try {
2065             if (add) {
2066                 mNetdService.networkAddInterface(netId, iface);
2067             } else {
2068                 mNetdService.networkRemoveInterface(netId, iface);
2069             }
2070         } catch (RemoteException | ServiceSpecificException e) {
2071             throw new IllegalStateException(e);
2072         }
2073     }
2074
2075     @Override
2076     public void addLegacyRouteForNetId(int netId, RouteInfo routeInfo, int uid) {
2077         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
2078
2079         final LinkAddress la = routeInfo.getDestinationLinkAddress();
2080         final String ifName = routeInfo.getInterface();
2081         final String dst = la.toString();
2082         final String nextHop;
2083
2084         if (routeInfo.hasGateway()) {
2085             nextHop = routeInfo.getGateway().getHostAddress();
2086         } else {
2087             nextHop = "";
2088         }
2089         try {
2090             mNetdService.networkAddLegacyRoute(netId, ifName, dst, nextHop, uid);
2091         } catch (RemoteException | ServiceSpecificException e) {
2092             throw new IllegalStateException(e);
2093         }
2094     }
2095
2096     @Override
2097     public void setDefaultNetId(int netId) {
2098         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
2099
2100         try {
2101             mNetdService.networkSetDefault(netId);
2102         } catch (RemoteException | ServiceSpecificException e) {
2103             throw new IllegalStateException(e);
2104         }
2105     }
2106
2107     @Override
2108     public void clearDefaultNetId() {
2109         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
2110
2111         try {
2112             mNetdService.networkClearDefault();
2113         } catch (RemoteException | ServiceSpecificException e) {
2114             throw new IllegalStateException(e);
2115         }
2116     }
2117
2118     @Override
2119     public void setNetworkPermission(int netId, int permission) {
2120         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
2121
2122         try {
2123             mNetdService.networkSetPermissionForNetwork(netId, permission);
2124         } catch (RemoteException | ServiceSpecificException e) {
2125             throw new IllegalStateException(e);
2126         }
2127     }
2128
2129     @Override
2130     public void allowProtect(int uid) {
2131         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
2132
2133         try {
2134             mNetdService.networkSetProtectAllow(uid);
2135         } catch (RemoteException | ServiceSpecificException e) {
2136             throw new IllegalStateException(e);
2137         }
2138     }
2139
2140     @Override
2141     public void denyProtect(int uid) {
2142         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
2143
2144         try {
2145             mNetdService.networkSetProtectDeny(uid);
2146         } catch (RemoteException | ServiceSpecificException e) {
2147             throw new IllegalStateException(e);
2148         }
2149     }
2150
2151     @Override
2152     public void addInterfaceToLocalNetwork(String iface, List<RouteInfo> routes) {
2153         modifyInterfaceInNetwork(MODIFY_OPERATION_ADD, INetd.LOCAL_NET_ID, iface);
2154
2155         for (RouteInfo route : routes) {
2156             if (!route.isDefaultRoute()) {
2157                 modifyRoute(MODIFY_OPERATION_ADD, INetd.LOCAL_NET_ID, route);
2158             }
2159         }
2160
2161         // IPv6 link local should be activated always.
2162         modifyRoute(MODIFY_OPERATION_ADD, INetd.LOCAL_NET_ID,
2163                 new RouteInfo(new IpPrefix("fe80::/64"), null, iface));
2164     }
2165
2166     @Override
2167     public void removeInterfaceFromLocalNetwork(String iface) {
2168         modifyInterfaceInNetwork(MODIFY_OPERATION_REMOVE, INetd.LOCAL_NET_ID, iface);
2169     }
2170
2171     @Override
2172     public int removeRoutesFromLocalNetwork(List<RouteInfo> routes) {
2173         int failures = 0;
2174
2175         for (RouteInfo route : routes) {
2176             try {
2177                 modifyRoute(MODIFY_OPERATION_REMOVE, INetd.LOCAL_NET_ID, route);
2178             } catch (IllegalStateException e) {
2179                 failures++;
2180             }
2181         }
2182
2183         return failures;
2184     }
2185
2186     @Override
2187     public boolean isNetworkRestricted(int uid) {
2188         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
2189         return isNetworkRestrictedInternal(uid);
2190     }
2191
2192     private boolean isNetworkRestrictedInternal(int uid) {
2193         synchronized (mRulesLock) {
2194             if (getFirewallChainState(FIREWALL_CHAIN_STANDBY)
2195                     && mUidFirewallStandbyRules.get(uid) == FIREWALL_RULE_DENY) {
2196                 if (DBG) Slog.d(TAG, "Uid " + uid + " restricted because of app standby mode");
2197                 return true;
2198             }
2199             if (getFirewallChainState(FIREWALL_CHAIN_DOZABLE)
2200                     && mUidFirewallDozableRules.get(uid) != FIREWALL_RULE_ALLOW) {
2201                 if (DBG) Slog.d(TAG, "Uid " + uid + " restricted because of device idle mode");
2202                 return true;
2203             }
2204             if (getFirewallChainState(FIREWALL_CHAIN_POWERSAVE)
2205                     && mUidFirewallPowerSaveRules.get(uid) != FIREWALL_RULE_ALLOW) {
2206                 if (DBG) Slog.d(TAG, "Uid " + uid + " restricted because of power saver mode");
2207                 return true;
2208             }
2209             if (mUidRejectOnMetered.get(uid)) {
2210                 if (DBG) Slog.d(TAG, "Uid " + uid + " restricted because of no metered data"
2211                         + " in the background");
2212                 return true;
2213             }
2214             if (mDataSaverMode && !mUidAllowOnMetered.get(uid)) {
2215                 if (DBG) Slog.d(TAG, "Uid " + uid + " restricted because of data saver mode");
2216                 return true;
2217             }
2218             return false;
2219         }
2220     }
2221
2222     private void setFirewallChainState(int chain, boolean state) {
2223         synchronized (mRulesLock) {
2224             mFirewallChainStates.put(chain, state);
2225         }
2226     }
2227
2228     private boolean getFirewallChainState(int chain) {
2229         synchronized (mRulesLock) {
2230             return mFirewallChainStates.get(chain);
2231         }
2232     }
2233
2234     @VisibleForTesting
2235     class LocalService extends NetworkManagementInternal {
2236         @Override
2237         public boolean isNetworkRestrictedForUid(int uid) {
2238             return isNetworkRestrictedInternal(uid);
2239         }
2240     }
2241
2242     @VisibleForTesting
2243     Injector getInjector() {
2244         return new Injector();
2245     }
2246
2247     @VisibleForTesting
2248     class Injector {
2249         void setDataSaverMode(boolean dataSaverMode) {
2250             mDataSaverMode = dataSaverMode;
2251         }
2252
2253         void setFirewallChainState(int chain, boolean state) {
2254             NetworkManagementService.this.setFirewallChainState(chain, state);
2255         }
2256
2257         void setFirewallRule(int chain, int uid, int rule) {
2258             synchronized (mRulesLock) {
2259                 getUidFirewallRulesLR(chain).put(uid, rule);
2260             }
2261         }
2262
2263         void setUidOnMeteredNetworkList(boolean blacklist, int uid, boolean enable) {
2264             synchronized (mRulesLock) {
2265                 if (blacklist) {
2266                     mUidRejectOnMetered.put(uid, enable);
2267                 } else {
2268                     mUidAllowOnMetered.put(uid, enable);
2269                 }
2270             }
2271         }
2272
2273         void reset() {
2274             synchronized (mRulesLock) {
2275                 setDataSaverMode(false);
2276                 final int[] chains = {
2277                         FIREWALL_CHAIN_DOZABLE,
2278                         FIREWALL_CHAIN_STANDBY,
2279                         FIREWALL_CHAIN_POWERSAVE
2280                 };
2281                 for (int chain : chains) {
2282                     setFirewallChainState(chain, false);
2283                     getUidFirewallRulesLR(chain).clear();
2284                 }
2285                 mUidAllowOnMetered.clear();
2286                 mUidRejectOnMetered.clear();
2287             }
2288         }
2289     }
2290 }