• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.net;
18 
19 import static android.Manifest.permission.CONNECTIVITY_INTERNAL;
20 import static android.net.ConnectivityManager.FIREWALL_CHAIN_DOZABLE;
21 import static android.net.ConnectivityManager.FIREWALL_CHAIN_LOW_POWER_STANDBY;
22 import static android.net.ConnectivityManager.FIREWALL_CHAIN_POWERSAVE;
23 import static android.net.ConnectivityManager.FIREWALL_CHAIN_RESTRICTED;
24 import static android.net.ConnectivityManager.FIREWALL_CHAIN_STANDBY;
25 import static android.net.INetd.FIREWALL_ALLOWLIST;
26 import static android.net.INetd.FIREWALL_CHAIN_NONE;
27 import static android.net.INetd.FIREWALL_DENYLIST;
28 import static android.net.INetd.FIREWALL_RULE_ALLOW;
29 import static android.net.INetd.FIREWALL_RULE_DENY;
30 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_DOZABLE;
31 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_LOW_POWER_STANDBY;
32 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_POWERSAVE;
33 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_RESTRICTED;
34 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_STANDBY;
35 import static android.net.NetworkPolicyManager.FIREWALL_RULE_DEFAULT;
36 
37 import static com.android.net.module.util.NetworkStatsUtils.LIMIT_GLOBAL_ALERT;
38 
39 import android.annotation.NonNull;
40 import android.app.ActivityManager;
41 import android.content.Context;
42 import android.net.ConnectivityManager;
43 import android.net.INetd;
44 import android.net.INetdUnsolicitedEventListener;
45 import android.net.INetworkManagementEventObserver;
46 import android.net.ITetheringStatsProvider;
47 import android.net.InetAddresses;
48 import android.net.InterfaceConfiguration;
49 import android.net.InterfaceConfigurationParcel;
50 import android.net.IpPrefix;
51 import android.net.LinkAddress;
52 import android.net.NetworkPolicyManager;
53 import android.net.NetworkStack;
54 import android.net.NetworkStats;
55 import android.net.RouteInfo;
56 import android.net.util.NetdService;
57 import android.os.BatteryStats;
58 import android.os.Binder;
59 import android.os.Handler;
60 import android.os.IBinder;
61 import android.os.INetworkManagementService;
62 import android.os.PermissionEnforcer;
63 import android.os.Process;
64 import android.os.RemoteCallbackList;
65 import android.os.RemoteException;
66 import android.os.ServiceManager;
67 import android.os.ServiceSpecificException;
68 import android.os.StrictMode;
69 import android.os.SystemClock;
70 import android.os.Trace;
71 import android.text.TextUtils;
72 import android.util.Log;
73 import android.util.Slog;
74 import android.util.SparseBooleanArray;
75 import android.util.SparseIntArray;
76 
77 import com.android.internal.annotations.GuardedBy;
78 import com.android.internal.app.IBatteryStats;
79 import com.android.internal.util.DumpUtils;
80 import com.android.internal.util.HexDump;
81 import com.android.internal.util.Preconditions;
82 import com.android.net.module.util.NetdUtils;
83 import com.android.net.module.util.NetdUtils.ModifyOperation;
84 import com.android.server.FgThread;
85 import com.android.server.LocalServices;
86 
87 import com.google.android.collect.Maps;
88 
89 import java.io.BufferedReader;
90 import java.io.DataInputStream;
91 import java.io.FileDescriptor;
92 import java.io.FileInputStream;
93 import java.io.IOException;
94 import java.io.InputStreamReader;
95 import java.io.PrintWriter;
96 import java.net.InetAddress;
97 import java.net.InterfaceAddress;
98 import java.util.ArrayList;
99 import java.util.HashMap;
100 import java.util.List;
101 import java.util.Map;
102 import java.util.Objects;
103 
104 /**
105  * @hide
106  */
107 public class NetworkManagementService extends INetworkManagementService.Stub {
108 
109     /**
110      * Helper class that encapsulates NetworkManagementService dependencies and makes them
111      * easier to mock in unit tests.
112      */
113     static class Dependencies {
getService(String name)114         public IBinder getService(String name) {
115             return ServiceManager.getService(name);
116         }
registerLocalService(NetworkManagementInternal nmi)117         public void registerLocalService(NetworkManagementInternal nmi) {
118             LocalServices.addService(NetworkManagementInternal.class, nmi);
119         }
getNetd()120         public INetd getNetd() {
121             return NetdService.get();
122         }
123 
getCallingUid()124         public int getCallingUid() {
125             return Binder.getCallingUid();
126         }
127     }
128 
129     private static final String TAG = "NetworkManagement";
130     private static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG);
131 
132     private static final int MAX_UID_RANGES_PER_COMMAND = 10;
133 
134     static final int DAEMON_MSG_MOBILE_CONN_REAL_TIME_INFO = 1;
135 
136     static final boolean MODIFY_OPERATION_ADD = true;
137     static final boolean MODIFY_OPERATION_REMOVE = false;
138 
139     /**
140      * Binder context for this service
141      */
142     private final Context mContext;
143 
144     private final Handler mDaemonHandler;
145 
146     private final Dependencies mDeps;
147 
148     private INetd mNetdService;
149 
150     private final NetdUnsolicitedEventListener mNetdUnsolicitedEventListener;
151 
152     private IBatteryStats mBatteryStats;
153 
154     private final RemoteCallbackList<INetworkManagementEventObserver> mObservers =
155             new RemoteCallbackList<>();
156 
157     @GuardedBy("mTetheringStatsProviders")
158     private final HashMap<ITetheringStatsProvider, String>
159             mTetheringStatsProviders = Maps.newHashMap();
160 
161     /**
162      * If both locks need to be held, then they should be obtained in the order:
163      * first {@link #mQuotaLock} and then {@link #mRulesLock}.
164      */
165     private final Object mQuotaLock = new Object();
166     private final Object mRulesLock = new Object();
167 
168     /** Set of interfaces with active quotas. */
169     @GuardedBy("mQuotaLock")
170     private HashMap<String, Long> mActiveQuotas = Maps.newHashMap();
171     /** Set of interfaces with active alerts. */
172     @GuardedBy("mQuotaLock")
173     private HashMap<String, Long> mActiveAlerts = Maps.newHashMap();
174     /** Set of UIDs denied on metered networks. */
175     @GuardedBy("mRulesLock")
176     private SparseBooleanArray mUidRejectOnMetered = new SparseBooleanArray();
177     /** Set of UIDs allowed on metered networks. */
178     @GuardedBy("mRulesLock")
179     private SparseBooleanArray mUidAllowOnMetered = new SparseBooleanArray();
180     /** Set of UIDs with cleartext penalties. */
181     @GuardedBy("mQuotaLock")
182     private SparseIntArray mUidCleartextPolicy = new SparseIntArray();
183     /** Set of UIDs that are to be blocked/allowed by firewall controller. */
184     @GuardedBy("mRulesLock")
185     private SparseIntArray mUidFirewallRules = new SparseIntArray();
186     /**
187      * Set of UIDs that are to be blocked/allowed by firewall controller.  This set of Ids matches
188      * to application idles.
189      */
190     @GuardedBy("mRulesLock")
191     private SparseIntArray mUidFirewallStandbyRules = new SparseIntArray();
192     /**
193      * Set of UIDs that are to be blocked/allowed by firewall controller.  This set of Ids matches
194      * to device idles.
195      */
196     @GuardedBy("mRulesLock")
197     private SparseIntArray mUidFirewallDozableRules = new SparseIntArray();
198     /**
199      * Set of UIDs that are to be blocked/allowed by firewall controller.  This set of Ids matches
200      * to device on power-save mode.
201      */
202     @GuardedBy("mRulesLock")
203     private SparseIntArray mUidFirewallPowerSaveRules = new SparseIntArray();
204     /**
205      * Contains the per-UID firewall rules that are used when Restricted Networking Mode is enabled.
206      */
207     @GuardedBy("mRulesLock")
208     private SparseIntArray mUidFirewallRestrictedRules = new SparseIntArray();
209     /**
210      * Contains the per-UID firewall rules that are used when Low Power Standby is enabled.
211      */
212     @GuardedBy("mRulesLock")
213     private SparseIntArray mUidFirewallLowPowerStandbyRules = new SparseIntArray();
214     /** Set of states for the child firewall chains. True if the chain is active. */
215     @GuardedBy("mRulesLock")
216     final SparseBooleanArray mFirewallChainStates = new SparseBooleanArray();
217 
218     @GuardedBy("mQuotaLock")
219     private volatile boolean mDataSaverMode;
220 
221     private volatile boolean mFirewallEnabled;
222     private volatile boolean mStrictEnabled;
223 
224     /**
225      * Constructs a new NetworkManagementService instance
226      *
227      * @param context  Binder context for this service
228      */
NetworkManagementService( Context context, Dependencies deps)229     private NetworkManagementService(
230             Context context, Dependencies deps) {
231         super(PermissionEnforcer.fromContext(context));
232         mContext = context;
233         mDeps = deps;
234 
235         mDaemonHandler = new Handler(FgThread.get().getLooper());
236 
237         mNetdUnsolicitedEventListener = new NetdUnsolicitedEventListener();
238 
239         mDeps.registerLocalService(new LocalService());
240 
241         synchronized (mTetheringStatsProviders) {
242             mTetheringStatsProviders.put(new NetdTetheringStatsProvider(), "netd");
243         }
244     }
245 
NetworkManagementService()246     private NetworkManagementService() {
247         mContext = null;
248         mDaemonHandler = null;
249         mDeps = null;
250         mNetdUnsolicitedEventListener = null;
251     }
252 
create(Context context, Dependencies deps)253     static NetworkManagementService create(Context context, Dependencies deps)
254             throws InterruptedException {
255         final NetworkManagementService service =
256                 new NetworkManagementService(context, deps);
257         if (DBG) Slog.d(TAG, "Creating NetworkManagementService");
258         if (DBG) Slog.d(TAG, "Connecting native netd service");
259         service.connectNativeNetdService();
260         if (DBG) Slog.d(TAG, "Connected");
261         return service;
262     }
263 
create(Context context)264     public static NetworkManagementService create(Context context) throws InterruptedException {
265         return create(context, new Dependencies());
266     }
267 
systemReady()268     public void systemReady() {
269         if (DBG) {
270             final long start = System.currentTimeMillis();
271             prepareNativeDaemon();
272             final long delta = System.currentTimeMillis() - start;
273             Slog.d(TAG, "Prepared in " + delta + "ms");
274             return;
275         } else {
276             prepareNativeDaemon();
277         }
278     }
279 
getBatteryStats()280     private IBatteryStats getBatteryStats() {
281         synchronized (this) {
282             if (mBatteryStats != null) {
283                 return mBatteryStats;
284             }
285             mBatteryStats =
286                     IBatteryStats.Stub.asInterface(mDeps.getService(BatteryStats.SERVICE_NAME));
287             return mBatteryStats;
288         }
289     }
290 
291     @Override
registerObserver(INetworkManagementEventObserver observer)292     public void registerObserver(INetworkManagementEventObserver observer) {
293         NetworkStack.checkNetworkStackPermission(mContext);
294         mObservers.register(observer);
295     }
296 
297     @Override
unregisterObserver(INetworkManagementEventObserver observer)298     public void unregisterObserver(INetworkManagementEventObserver observer) {
299         NetworkStack.checkNetworkStackPermission(mContext);
300         mObservers.unregister(observer);
301     }
302 
303     @FunctionalInterface
304     private interface NetworkManagementEventCallback {
sendCallback(INetworkManagementEventObserver o)305         public void sendCallback(INetworkManagementEventObserver o) throws RemoteException;
306     }
307 
invokeForAllObservers(NetworkManagementEventCallback eventCallback)308     private void invokeForAllObservers(NetworkManagementEventCallback eventCallback) {
309         final int length = mObservers.beginBroadcast();
310         try {
311             for (int i = 0; i < length; i++) {
312                 try {
313                     eventCallback.sendCallback(mObservers.getBroadcastItem(i));
314                 } catch (RemoteException | RuntimeException e) {
315                 }
316             }
317         } finally {
318             mObservers.finishBroadcast();
319         }
320     }
321 
322     /**
323      * Notify our observers of an interface status change
324      */
notifyInterfaceStatusChanged(String iface, boolean up)325     private void notifyInterfaceStatusChanged(String iface, boolean up) {
326         invokeForAllObservers(o -> o.interfaceStatusChanged(iface, up));
327     }
328 
329     /**
330      * Notify our observers of an interface link state change
331      * (typically, an Ethernet cable has been plugged-in or unplugged).
332      */
notifyInterfaceLinkStateChanged(String iface, boolean up)333     private void notifyInterfaceLinkStateChanged(String iface, boolean up) {
334         invokeForAllObservers(o -> o.interfaceLinkStateChanged(iface, up));
335     }
336 
337     /**
338      * Notify our observers of an interface addition.
339      */
notifyInterfaceAdded(String iface)340     private void notifyInterfaceAdded(String iface) {
341         invokeForAllObservers(o -> o.interfaceAdded(iface));
342     }
343 
344     /**
345      * Notify our observers of an interface removal.
346      */
notifyInterfaceRemoved(String iface)347     private void notifyInterfaceRemoved(String iface) {
348         // netd already clears out quota and alerts for removed ifaces; update
349         // our validity-checking state.
350         mActiveAlerts.remove(iface);
351         mActiveQuotas.remove(iface);
352         invokeForAllObservers(o -> o.interfaceRemoved(iface));
353     }
354 
355     /**
356      * Notify our observers of a limit reached.
357      */
notifyLimitReached(String limitName, String iface)358     private void notifyLimitReached(String limitName, String iface) {
359         invokeForAllObservers(o -> o.limitReached(limitName, iface));
360     }
361 
362     /**
363      * Notify our observers of a change in the data activity state of the interface
364      */
notifyInterfaceClassActivity(int type, boolean isActive, long tsNanos, int uid)365     private void notifyInterfaceClassActivity(int type, boolean isActive, long tsNanos,
366             int uid) {
367         invokeForAllObservers(o -> o.interfaceClassDataActivityChanged(
368                 type, isActive, tsNanos, uid));
369     }
370 
371     @Override
registerTetheringStatsProvider(ITetheringStatsProvider provider, String name)372     public void registerTetheringStatsProvider(ITetheringStatsProvider provider, String name) {
373         NetworkStack.checkNetworkStackPermission(mContext);
374         Objects.requireNonNull(provider);
375         synchronized(mTetheringStatsProviders) {
376             mTetheringStatsProviders.put(provider, name);
377         }
378     }
379 
380     @Override
unregisterTetheringStatsProvider(ITetheringStatsProvider provider)381     public void unregisterTetheringStatsProvider(ITetheringStatsProvider provider) {
382         NetworkStack.checkNetworkStackPermission(mContext);
383         synchronized(mTetheringStatsProviders) {
384             mTetheringStatsProviders.remove(provider);
385         }
386     }
387 
388     @Override
tetherLimitReached(ITetheringStatsProvider provider)389     public void tetherLimitReached(ITetheringStatsProvider provider) {
390         NetworkStack.checkNetworkStackPermission(mContext);
391         synchronized(mTetheringStatsProviders) {
392             if (!mTetheringStatsProviders.containsKey(provider)) {
393                 return;
394             }
395             // No current code examines the interface parameter in a global alert. Just pass null.
396             mDaemonHandler.post(() -> notifyLimitReached(LIMIT_GLOBAL_ALERT, null));
397         }
398     }
399 
400     // Sync the state of the given chain with the native daemon.
syncFirewallChainLocked(int chain, String name)401     private void syncFirewallChainLocked(int chain, String name) {
402         SparseIntArray rules;
403         synchronized (mRulesLock) {
404             final SparseIntArray uidFirewallRules = getUidFirewallRulesLR(chain);
405             // Make a copy of the current rules, and then clear them. This is because
406             // setFirewallUidRuleInternal only pushes down rules to the native daemon if they
407             // are different from the current rules stored in the mUidFirewall*Rules array for
408             // the specified chain. If we don't clear the rules, setFirewallUidRuleInternal
409             // will do nothing.
410             rules = uidFirewallRules.clone();
411             uidFirewallRules.clear();
412         }
413         if (rules.size() > 0) {
414             // Now push the rules. setFirewallUidRuleInternal will push each of these down to the
415             // native daemon, and also add them to the mUidFirewall*Rules array for the specified
416             // chain.
417             if (DBG) Slog.d(TAG, "Pushing " + rules.size() + " active firewall "
418                     + name + "UID rules");
419             for (int i = 0; i < rules.size(); i++) {
420                 setFirewallUidRuleLocked(chain, rules.keyAt(i), rules.valueAt(i));
421             }
422         }
423     }
424 
connectNativeNetdService()425     private void connectNativeNetdService() {
426         mNetdService = mDeps.getNetd();
427         try {
428             mNetdService.registerUnsolicitedEventListener(mNetdUnsolicitedEventListener);
429             if (DBG) Slog.d(TAG, "Register unsolicited event listener");
430         } catch (RemoteException | ServiceSpecificException e) {
431             Slog.e(TAG, "Failed to set Netd unsolicited event listener " + e);
432         }
433     }
434 
435     /**
436      * Prepare native daemon once connected, enabling modules and pushing any
437      * existing in-memory rules.
438      */
prepareNativeDaemon()439     private void prepareNativeDaemon() {
440 
441         // push any existing quota or UID rules
442         synchronized (mQuotaLock) {
443 
444             mStrictEnabled = true;
445 
446             setDataSaverModeEnabled(mDataSaverMode);
447 
448             int size = mActiveQuotas.size();
449             if (size > 0) {
450                 if (DBG) Slog.d(TAG, "Pushing " + size + " active quota rules");
451                 final HashMap<String, Long> activeQuotas = mActiveQuotas;
452                 mActiveQuotas = Maps.newHashMap();
453                 for (Map.Entry<String, Long> entry : activeQuotas.entrySet()) {
454                     setInterfaceQuota(entry.getKey(), entry.getValue());
455                 }
456             }
457 
458             size = mActiveAlerts.size();
459             if (size > 0) {
460                 if (DBG) Slog.d(TAG, "Pushing " + size + " active alert rules");
461                 final HashMap<String, Long> activeAlerts = mActiveAlerts;
462                 mActiveAlerts = Maps.newHashMap();
463                 for (Map.Entry<String, Long> entry : activeAlerts.entrySet()) {
464                     setInterfaceAlert(entry.getKey(), entry.getValue());
465                 }
466             }
467 
468             SparseBooleanArray uidRejectOnQuota = null;
469             SparseBooleanArray uidAcceptOnQuota = null;
470             synchronized (mRulesLock) {
471                 size = mUidRejectOnMetered.size();
472                 if (size > 0) {
473                     if (DBG) Slog.d(TAG, "Pushing " + size + " UIDs to metered denylist rules");
474                     uidRejectOnQuota = mUidRejectOnMetered;
475                     mUidRejectOnMetered = new SparseBooleanArray();
476                 }
477 
478                 size = mUidAllowOnMetered.size();
479                 if (size > 0) {
480                     if (DBG) Slog.d(TAG, "Pushing " + size + " UIDs to metered allowlist rules");
481                     uidAcceptOnQuota = mUidAllowOnMetered;
482                     mUidAllowOnMetered = new SparseBooleanArray();
483                 }
484             }
485             if (uidRejectOnQuota != null) {
486                 for (int i = 0; i < uidRejectOnQuota.size(); i++) {
487                     setUidOnMeteredNetworkDenylist(uidRejectOnQuota.keyAt(i),
488                             uidRejectOnQuota.valueAt(i));
489                 }
490             }
491             if (uidAcceptOnQuota != null) {
492                 for (int i = 0; i < uidAcceptOnQuota.size(); i++) {
493                     setUidOnMeteredNetworkAllowlist(uidAcceptOnQuota.keyAt(i),
494                             uidAcceptOnQuota.valueAt(i));
495                 }
496             }
497 
498             size = mUidCleartextPolicy.size();
499             if (size > 0) {
500                 if (DBG) Slog.d(TAG, "Pushing " + size + " active UID cleartext policies");
501                 final SparseIntArray local = mUidCleartextPolicy;
502                 mUidCleartextPolicy = new SparseIntArray();
503                 for (int i = 0; i < local.size(); i++) {
504                     setUidCleartextNetworkPolicy(local.keyAt(i), local.valueAt(i));
505                 }
506             }
507 
508             setFirewallEnabled(mFirewallEnabled);
509 
510             syncFirewallChainLocked(FIREWALL_CHAIN_NONE, "");
511             syncFirewallChainLocked(FIREWALL_CHAIN_STANDBY, "standby ");
512             syncFirewallChainLocked(FIREWALL_CHAIN_DOZABLE, "dozable ");
513             syncFirewallChainLocked(FIREWALL_CHAIN_POWERSAVE, "powersave ");
514             syncFirewallChainLocked(FIREWALL_CHAIN_RESTRICTED, "restricted ");
515             syncFirewallChainLocked(FIREWALL_CHAIN_LOW_POWER_STANDBY, "low power standby ");
516 
517             final int[] chains = {
518                     FIREWALL_CHAIN_STANDBY,
519                     FIREWALL_CHAIN_DOZABLE,
520                     FIREWALL_CHAIN_POWERSAVE,
521                     FIREWALL_CHAIN_RESTRICTED,
522                     FIREWALL_CHAIN_LOW_POWER_STANDBY
523             };
524 
525             for (int chain : chains) {
526                 if (getFirewallChainState(chain)) {
527                     setFirewallChainEnabled(chain, true);
528                 }
529             }
530         }
531 
532 
533         try {
534             getBatteryStats().noteNetworkStatsEnabled();
535         } catch (RemoteException e) {
536         }
537 
538     }
539 
540     /**
541      * Notify our observers of a new or updated interface address.
542      */
notifyAddressUpdated(String iface, LinkAddress address)543     private void notifyAddressUpdated(String iface, LinkAddress address) {
544         invokeForAllObservers(o -> o.addressUpdated(iface, address));
545     }
546 
547     /**
548      * Notify our observers of a deleted interface address.
549      */
notifyAddressRemoved(String iface, LinkAddress address)550     private void notifyAddressRemoved(String iface, LinkAddress address) {
551         invokeForAllObservers(o -> o.addressRemoved(iface, address));
552     }
553 
554     /**
555      * Notify our observers of DNS server information received.
556      */
notifyInterfaceDnsServerInfo(String iface, long lifetime, String[] addresses)557     private void notifyInterfaceDnsServerInfo(String iface, long lifetime, String[] addresses) {
558         invokeForAllObservers(o -> o.interfaceDnsServerInfo(iface, lifetime, addresses));
559     }
560 
561     /**
562      * Notify our observers of a route change.
563      */
notifyRouteChange(boolean updated, RouteInfo route)564     private void notifyRouteChange(boolean updated, RouteInfo route) {
565         if (updated) {
566             invokeForAllObservers(o -> o.routeUpdated(route));
567         } else {
568             invokeForAllObservers(o -> o.routeRemoved(route));
569         }
570     }
571 
572     private class NetdUnsolicitedEventListener extends INetdUnsolicitedEventListener.Stub {
573         @Override
onInterfaceClassActivityChanged(boolean isActive, int label, long timestamp, int uid)574         public void onInterfaceClassActivityChanged(boolean isActive,
575                 int label, long timestamp, int uid) throws RemoteException {
576             final long timestampNanos;
577             if (timestamp <= 0) {
578                 timestampNanos = SystemClock.elapsedRealtimeNanos();
579             } else {
580                 timestampNanos = timestamp;
581             }
582             mDaemonHandler.post(() ->
583                     notifyInterfaceClassActivity(label, isActive, timestampNanos, uid));
584         }
585 
586         @Override
onQuotaLimitReached(String alertName, String ifName)587         public void onQuotaLimitReached(String alertName, String ifName)
588                 throws RemoteException {
589             mDaemonHandler.post(() -> notifyLimitReached(alertName, ifName));
590         }
591 
592         @Override
onInterfaceDnsServerInfo(String ifName, long lifetime, String[] servers)593         public void onInterfaceDnsServerInfo(String ifName,
594                 long lifetime, String[] servers) throws RemoteException {
595             mDaemonHandler.post(() -> notifyInterfaceDnsServerInfo(ifName, lifetime, servers));
596         }
597 
598         @Override
onInterfaceAddressUpdated(String addr, String ifName, int flags, int scope)599         public void onInterfaceAddressUpdated(String addr,
600                 String ifName, int flags, int scope) throws RemoteException {
601             final LinkAddress address = new LinkAddress(addr, flags, scope);
602             mDaemonHandler.post(() -> notifyAddressUpdated(ifName, address));
603         }
604 
605         @Override
onInterfaceAddressRemoved(String addr, String ifName, int flags, int scope)606         public void onInterfaceAddressRemoved(String addr,
607                 String ifName, int flags, int scope) throws RemoteException {
608             final LinkAddress address = new LinkAddress(addr, flags, scope);
609             mDaemonHandler.post(() -> notifyAddressRemoved(ifName, address));
610         }
611 
612         @Override
onInterfaceAdded(String ifName)613         public void onInterfaceAdded(String ifName) throws RemoteException {
614             mDaemonHandler.post(() -> notifyInterfaceAdded(ifName));
615         }
616 
617         @Override
onInterfaceRemoved(String ifName)618         public void onInterfaceRemoved(String ifName) throws RemoteException {
619             mDaemonHandler.post(() -> notifyInterfaceRemoved(ifName));
620         }
621 
622         @Override
onInterfaceChanged(String ifName, boolean up)623         public void onInterfaceChanged(String ifName, boolean up)
624                 throws RemoteException {
625             mDaemonHandler.post(() -> notifyInterfaceStatusChanged(ifName, up));
626         }
627 
628         @Override
onInterfaceLinkStateChanged(String ifName, boolean up)629         public void onInterfaceLinkStateChanged(String ifName, boolean up)
630                 throws RemoteException {
631             mDaemonHandler.post(() -> notifyInterfaceLinkStateChanged(ifName, up));
632         }
633 
634         @Override
onRouteChanged(boolean updated, String route, String gateway, String ifName)635         public void onRouteChanged(boolean updated,
636                 String route, String gateway, String ifName) throws RemoteException {
637             final RouteInfo processRoute = new RouteInfo(new IpPrefix(route),
638                     ("".equals(gateway)) ? null : InetAddresses.parseNumericAddress(gateway),
639                     ifName, RouteInfo.RTN_UNICAST);
640             mDaemonHandler.post(() -> notifyRouteChange(updated, processRoute));
641         }
642 
643         @Override
onStrictCleartextDetected(int uid, String hex)644         public void onStrictCleartextDetected(int uid, String hex) throws RemoteException {
645             // Don't need to post to mDaemonHandler because the only thing
646             // that notifyCleartextNetwork does is post to a handler
647             ActivityManager.getService().notifyCleartextNetwork(uid,
648                     HexDump.hexStringToByteArray(hex));
649         }
650 
651         @Override
getInterfaceVersion()652         public int getInterfaceVersion() {
653             return INetdUnsolicitedEventListener.VERSION;
654         }
655 
656         @Override
getInterfaceHash()657         public String getInterfaceHash() {
658             return INetdUnsolicitedEventListener.HASH;
659         }
660     }
661 
662     //
663     // INetworkManagementService members
664     //
665     @Override
listInterfaces()666     public String[] listInterfaces() {
667         // TODO: Remove CONNECTIVITY_INTERNAL after bluetooth tethering has no longer called these
668         //  APIs.
669         NetworkStack.checkNetworkStackPermissionOr(mContext, CONNECTIVITY_INTERNAL);
670         try {
671             return mNetdService.interfaceGetList();
672         } catch (RemoteException | ServiceSpecificException e) {
673             throw new IllegalStateException(e);
674         }
675     }
676 
677     /**
678      * Convert InterfaceConfiguration to InterfaceConfigurationParcel with given ifname.
679      */
toStableParcel(InterfaceConfiguration cfg, String iface)680     private static InterfaceConfigurationParcel toStableParcel(InterfaceConfiguration cfg,
681             String iface) {
682         InterfaceConfigurationParcel cfgParcel = new InterfaceConfigurationParcel();
683         cfgParcel.ifName = iface;
684         String hwAddr = cfg.getHardwareAddress();
685         if (!TextUtils.isEmpty(hwAddr)) {
686             cfgParcel.hwAddr = hwAddr;
687         } else {
688             cfgParcel.hwAddr = "";
689         }
690         cfgParcel.ipv4Addr = cfg.getLinkAddress().getAddress().getHostAddress();
691         cfgParcel.prefixLength = cfg.getLinkAddress().getPrefixLength();
692         ArrayList<String> flags = new ArrayList<>();
693         for (String flag : cfg.getFlags()) {
694             flags.add(flag);
695         }
696         cfgParcel.flags = flags.toArray(new String[0]);
697 
698         return cfgParcel;
699     }
700 
701     /**
702      * Construct InterfaceConfiguration from InterfaceConfigurationParcel.
703      */
fromStableParcel(InterfaceConfigurationParcel p)704     public static InterfaceConfiguration fromStableParcel(InterfaceConfigurationParcel p) {
705         InterfaceConfiguration cfg = new InterfaceConfiguration();
706         cfg.setHardwareAddress(p.hwAddr);
707 
708         final InetAddress addr = InetAddresses.parseNumericAddress(p.ipv4Addr);
709         cfg.setLinkAddress(new LinkAddress(addr, p.prefixLength));
710         for (String flag : p.flags) {
711             cfg.setFlag(flag);
712         }
713 
714         return cfg;
715     }
716 
717     @Override
getInterfaceConfig(String iface)718     public InterfaceConfiguration getInterfaceConfig(String iface) {
719         // TODO: Remove CONNECTIVITY_INTERNAL after bluetooth tethering has no longer called these
720         //  APIs.
721         NetworkStack.checkNetworkStackPermissionOr(mContext, CONNECTIVITY_INTERNAL);
722         final InterfaceConfigurationParcel result;
723         try {
724             result = mNetdService.interfaceGetCfg(iface);
725         } catch (RemoteException | ServiceSpecificException e) {
726             throw new IllegalStateException(e);
727         }
728 
729         try {
730             final InterfaceConfiguration cfg = fromStableParcel(result);
731             return cfg;
732         } catch (IllegalArgumentException iae) {
733             throw new IllegalStateException("Invalid InterfaceConfigurationParcel", iae);
734         }
735     }
736 
737     @Override
setInterfaceConfig(String iface, InterfaceConfiguration cfg)738     public void setInterfaceConfig(String iface, InterfaceConfiguration cfg) {
739         // TODO: Remove CONNECTIVITY_INTERNAL after bluetooth tethering has no longer called these
740         //  APIs.
741         NetworkStack.checkNetworkStackPermissionOr(mContext, CONNECTIVITY_INTERNAL);
742         LinkAddress linkAddr = cfg.getLinkAddress();
743         if (linkAddr == null || linkAddr.getAddress() == null) {
744             throw new IllegalStateException("Null LinkAddress given");
745         }
746 
747         final InterfaceConfigurationParcel cfgParcel = toStableParcel(cfg, iface);
748 
749         try {
750             mNetdService.interfaceSetCfg(cfgParcel);
751         } catch (RemoteException | ServiceSpecificException e) {
752             throw new IllegalStateException(e);
753         }
754     }
755 
756     @Override
setInterfaceDown(String iface)757     public void setInterfaceDown(String iface) {
758         NetworkStack.checkNetworkStackPermission(mContext);
759         final InterfaceConfiguration ifcg = getInterfaceConfig(iface);
760         ifcg.setInterfaceDown();
761         setInterfaceConfig(iface, ifcg);
762     }
763 
764     @Override
setInterfaceUp(String iface)765     public void setInterfaceUp(String iface) {
766         NetworkStack.checkNetworkStackPermission(mContext);
767         final InterfaceConfiguration ifcg = getInterfaceConfig(iface);
768         ifcg.setInterfaceUp();
769         setInterfaceConfig(iface, ifcg);
770     }
771 
772     @Override
setInterfaceIpv6PrivacyExtensions(String iface, boolean enable)773     public void setInterfaceIpv6PrivacyExtensions(String iface, boolean enable) {
774         NetworkStack.checkNetworkStackPermission(mContext);
775         try {
776             mNetdService.interfaceSetIPv6PrivacyExtensions(iface, enable);
777         } catch (RemoteException | ServiceSpecificException e) {
778             throw new IllegalStateException(e);
779         }
780     }
781 
782     /* TODO: This is right now a IPv4 only function. Works for wifi which loses its
783        IPv6 addresses on interface down, but we need to do full clean up here */
784     @Override
clearInterfaceAddresses(String iface)785     public void clearInterfaceAddresses(String iface) {
786         NetworkStack.checkNetworkStackPermission(mContext);
787         try {
788             mNetdService.interfaceClearAddrs(iface);
789         } catch (RemoteException | ServiceSpecificException e) {
790             throw new IllegalStateException(e);
791         }
792     }
793 
794     @Override
enableIpv6(String iface)795     public void enableIpv6(String iface) {
796         NetworkStack.checkNetworkStackPermission(mContext);
797         try {
798             mNetdService.interfaceSetEnableIPv6(iface, true);
799         } catch (RemoteException | ServiceSpecificException e) {
800             throw new IllegalStateException(e);
801         }
802     }
803 
804     @Override
setIPv6AddrGenMode(String iface, int mode)805     public void setIPv6AddrGenMode(String iface, int mode) throws ServiceSpecificException {
806         NetworkStack.checkNetworkStackPermission(mContext);
807         try {
808             mNetdService.setIPv6AddrGenMode(iface, mode);
809         } catch (RemoteException e) {
810             throw e.rethrowAsRuntimeException();
811         }
812     }
813 
814     @Override
disableIpv6(String iface)815     public void disableIpv6(String iface) {
816         NetworkStack.checkNetworkStackPermission(mContext);
817         try {
818             mNetdService.interfaceSetEnableIPv6(iface, false);
819         } catch (RemoteException | ServiceSpecificException e) {
820             throw new IllegalStateException(e);
821         }
822     }
823 
824     @Override
addRoute(int netId, RouteInfo route)825     public void addRoute(int netId, RouteInfo route) {
826         NetworkStack.checkNetworkStackPermission(mContext);
827         NetdUtils.modifyRoute(mNetdService, ModifyOperation.ADD, netId, route);
828     }
829 
830     @Override
removeRoute(int netId, RouteInfo route)831     public void removeRoute(int netId, RouteInfo route) {
832         NetworkStack.checkNetworkStackPermission(mContext);
833         NetdUtils.modifyRoute(mNetdService, ModifyOperation.REMOVE, netId, route);
834     }
835 
readRouteList(String filename)836     private ArrayList<String> readRouteList(String filename) {
837         FileInputStream fstream = null;
838         ArrayList<String> list = new ArrayList<>();
839 
840         try {
841             fstream = new FileInputStream(filename);
842             DataInputStream in = new DataInputStream(fstream);
843             BufferedReader br = new BufferedReader(new InputStreamReader(in));
844             String s;
845 
846             // throw away the title line
847 
848             while (((s = br.readLine()) != null) && (s.length() != 0)) {
849                 list.add(s);
850             }
851         } catch (IOException ex) {
852             // return current list, possibly empty
853         } finally {
854             if (fstream != null) {
855                 try {
856                     fstream.close();
857                 } catch (IOException ex) {}
858             }
859         }
860 
861         return list;
862     }
863 
864     @android.annotation.EnforcePermission(android.Manifest.permission.SHUTDOWN)
865     @Override
shutdown()866     public void shutdown() {
867         // TODO: remove from aidl if nobody calls externally
868 
869         super.shutdown_enforcePermission();
870 
871         Slog.i(TAG, "Shutting down");
872     }
873 
874     @Override
getIpForwardingEnabled()875     public boolean getIpForwardingEnabled() throws IllegalStateException{
876         NetworkStack.checkNetworkStackPermission(mContext);
877 
878         try {
879             final boolean isEnabled = mNetdService.ipfwdEnabled();
880             return isEnabled;
881         } catch (RemoteException | ServiceSpecificException e) {
882             throw new IllegalStateException(e);
883         }
884     }
885 
886     @Override
setIpForwardingEnabled(boolean enable)887     public void setIpForwardingEnabled(boolean enable) {
888         NetworkStack.checkNetworkStackPermission(mContext);
889         try {
890             if (enable) {
891                 mNetdService.ipfwdEnableForwarding("tethering");
892             } else {
893                 mNetdService.ipfwdDisableForwarding("tethering");
894             }
895         } catch (RemoteException | ServiceSpecificException e) {
896             throw new IllegalStateException(e);
897         }
898     }
899 
900     @Override
startTethering(String[] dhcpRange)901     public void startTethering(String[] dhcpRange) {
902         startTetheringWithConfiguration(true, dhcpRange);
903     }
904 
905     @Override
startTetheringWithConfiguration(boolean usingLegacyDnsProxy, String[] dhcpRange)906     public void startTetheringWithConfiguration(boolean usingLegacyDnsProxy, String[] dhcpRange) {
907         NetworkStack.checkNetworkStackPermission(mContext);
908         try {
909             NetdUtils.tetherStart(mNetdService, usingLegacyDnsProxy, dhcpRange);
910         } catch (RemoteException | ServiceSpecificException e) {
911             throw new IllegalStateException(e);
912         }
913     }
914 
915     @Override
stopTethering()916     public void stopTethering() {
917         NetworkStack.checkNetworkStackPermission(mContext);
918         try {
919             mNetdService.tetherStop();
920         } catch (RemoteException | ServiceSpecificException e) {
921             throw new IllegalStateException(e);
922         }
923     }
924 
925     @Override
isTetheringStarted()926     public boolean isTetheringStarted() {
927         NetworkStack.checkNetworkStackPermission(mContext);
928 
929         try {
930             final boolean isEnabled = mNetdService.tetherIsEnabled();
931             return isEnabled;
932         } catch (RemoteException | ServiceSpecificException e) {
933             throw new IllegalStateException(e);
934         }
935     }
936 
937     @Override
tetherInterface(String iface)938     public void tetherInterface(String iface) {
939         NetworkStack.checkNetworkStackPermission(mContext);
940         try {
941             final LinkAddress addr = getInterfaceConfig(iface).getLinkAddress();
942             final IpPrefix dest = new IpPrefix(addr.getAddress(), addr.getPrefixLength());
943             NetdUtils.tetherInterface(mNetdService, iface, dest);
944         } catch (RemoteException | ServiceSpecificException e) {
945             throw new IllegalStateException(e);
946         }
947     }
948 
949     @Override
untetherInterface(String iface)950     public void untetherInterface(String iface) {
951         NetworkStack.checkNetworkStackPermission(mContext);
952         try {
953             NetdUtils.untetherInterface(mNetdService, iface);
954         } catch (RemoteException | ServiceSpecificException e) {
955             throw new IllegalStateException(e);
956         }
957     }
958 
959     @Override
listTetheredInterfaces()960     public String[] listTetheredInterfaces() {
961         NetworkStack.checkNetworkStackPermission(mContext);
962         try {
963             return mNetdService.tetherInterfaceList();
964         } catch (RemoteException | ServiceSpecificException e) {
965             throw new IllegalStateException(e);
966         }
967     }
968 
969     @Override
getDnsForwarders()970     public String[] getDnsForwarders() {
971         NetworkStack.checkNetworkStackPermission(mContext);
972         try {
973             return mNetdService.tetherDnsList();
974         } catch (RemoteException | ServiceSpecificException e) {
975             throw new IllegalStateException(e);
976         }
977     }
978 
excludeLinkLocal(List<InterfaceAddress> addresses)979     private List<InterfaceAddress> excludeLinkLocal(List<InterfaceAddress> addresses) {
980         ArrayList<InterfaceAddress> filtered = new ArrayList<>(addresses.size());
981         for (InterfaceAddress ia : addresses) {
982             if (!ia.getAddress().isLinkLocalAddress())
983                 filtered.add(ia);
984         }
985         return filtered;
986     }
987 
modifyInterfaceForward(boolean add, String fromIface, String toIface)988     private void modifyInterfaceForward(boolean add, String fromIface, String toIface) {
989         try {
990             if (add) {
991                 mNetdService.ipfwdAddInterfaceForward(fromIface, toIface);
992             } else {
993                 mNetdService.ipfwdRemoveInterfaceForward(fromIface, toIface);
994             }
995         } catch (RemoteException | ServiceSpecificException e) {
996             throw new IllegalStateException(e);
997         }
998     }
999 
1000     @Override
startInterfaceForwarding(String fromIface, String toIface)1001     public void startInterfaceForwarding(String fromIface, String toIface) {
1002         NetworkStack.checkNetworkStackPermission(mContext);
1003         modifyInterfaceForward(true, fromIface, toIface);
1004     }
1005 
1006     @Override
stopInterfaceForwarding(String fromIface, String toIface)1007     public void stopInterfaceForwarding(String fromIface, String toIface) {
1008         NetworkStack.checkNetworkStackPermission(mContext);
1009         modifyInterfaceForward(false, fromIface, toIface);
1010     }
1011 
1012     @Override
enableNat(String internalInterface, String externalInterface)1013     public void enableNat(String internalInterface, String externalInterface) {
1014         NetworkStack.checkNetworkStackPermission(mContext);
1015         try {
1016             mNetdService.tetherAddForward(internalInterface, externalInterface);
1017         } catch (RemoteException | ServiceSpecificException e) {
1018             throw new IllegalStateException(e);
1019         }
1020     }
1021 
1022     @Override
disableNat(String internalInterface, String externalInterface)1023     public void disableNat(String internalInterface, String externalInterface) {
1024         NetworkStack.checkNetworkStackPermission(mContext);
1025         try {
1026             mNetdService.tetherRemoveForward(internalInterface, externalInterface);
1027         } catch (RemoteException | ServiceSpecificException e) {
1028             throw new IllegalStateException(e);
1029         }
1030     }
1031 
1032     @Override
setInterfaceQuota(String iface, long quotaBytes)1033     public void setInterfaceQuota(String iface, long quotaBytes) {
1034         NetworkStack.checkNetworkStackPermission(mContext);
1035 
1036         synchronized (mQuotaLock) {
1037             if (mActiveQuotas.containsKey(iface)) {
1038                 throw new IllegalStateException("iface " + iface + " already has quota");
1039             }
1040 
1041             try {
1042                 // TODO: support quota shared across interfaces
1043                 mNetdService.bandwidthSetInterfaceQuota(iface, quotaBytes);
1044 
1045                 mActiveQuotas.put(iface, quotaBytes);
1046             } catch (RemoteException | ServiceSpecificException e) {
1047                 throw new IllegalStateException(e);
1048             }
1049 
1050             synchronized (mTetheringStatsProviders) {
1051                 for (ITetheringStatsProvider provider : mTetheringStatsProviders.keySet()) {
1052                     try {
1053                         provider.setInterfaceQuota(iface, quotaBytes);
1054                     } catch (RemoteException e) {
1055                         Log.e(TAG, "Problem setting tethering data limit on provider " +
1056                                 mTetheringStatsProviders.get(provider) + ": " + e);
1057                     }
1058                 }
1059             }
1060         }
1061     }
1062 
1063     @Override
removeInterfaceQuota(String iface)1064     public void removeInterfaceQuota(String iface) {
1065         NetworkStack.checkNetworkStackPermission(mContext);
1066 
1067         synchronized (mQuotaLock) {
1068             if (!mActiveQuotas.containsKey(iface)) {
1069                 // TODO: eventually consider throwing
1070                 return;
1071             }
1072 
1073             mActiveQuotas.remove(iface);
1074             mActiveAlerts.remove(iface);
1075 
1076             try {
1077                 // TODO: support quota shared across interfaces
1078                 mNetdService.bandwidthRemoveInterfaceQuota(iface);
1079             } catch (RemoteException | ServiceSpecificException e) {
1080                 throw new IllegalStateException(e);
1081             }
1082 
1083             synchronized (mTetheringStatsProviders) {
1084                 for (ITetheringStatsProvider provider : mTetheringStatsProviders.keySet()) {
1085                     try {
1086                         provider.setInterfaceQuota(iface, ITetheringStatsProvider.QUOTA_UNLIMITED);
1087                     } catch (RemoteException e) {
1088                         Log.e(TAG, "Problem removing tethering data limit on provider " +
1089                                 mTetheringStatsProviders.get(provider) + ": " + e);
1090                     }
1091                 }
1092             }
1093         }
1094     }
1095 
1096     @Override
setInterfaceAlert(String iface, long alertBytes)1097     public void setInterfaceAlert(String iface, long alertBytes) {
1098         NetworkStack.checkNetworkStackPermission(mContext);
1099 
1100         // quick validity check
1101         if (!mActiveQuotas.containsKey(iface)) {
1102             throw new IllegalStateException("setting alert requires existing quota on iface");
1103         }
1104 
1105         synchronized (mQuotaLock) {
1106             if (mActiveAlerts.containsKey(iface)) {
1107                 throw new IllegalStateException("iface " + iface + " already has alert");
1108             }
1109 
1110             try {
1111                 // TODO: support alert shared across interfaces
1112                 mNetdService.bandwidthSetInterfaceAlert(iface, alertBytes);
1113                 mActiveAlerts.put(iface, alertBytes);
1114             } catch (RemoteException | ServiceSpecificException e) {
1115                 throw new IllegalStateException(e);
1116             }
1117         }
1118     }
1119 
1120     @Override
removeInterfaceAlert(String iface)1121     public void removeInterfaceAlert(String iface) {
1122         NetworkStack.checkNetworkStackPermission(mContext);
1123 
1124         synchronized (mQuotaLock) {
1125             if (!mActiveAlerts.containsKey(iface)) {
1126                 // TODO: eventually consider throwing
1127                 return;
1128             }
1129 
1130             try {
1131                 // TODO: support alert shared across interfaces
1132                 mNetdService.bandwidthRemoveInterfaceAlert(iface);
1133                 mActiveAlerts.remove(iface);
1134             } catch (RemoteException | ServiceSpecificException e) {
1135                 throw new IllegalStateException(e);
1136             }
1137         }
1138     }
1139 
1140     @Override
setGlobalAlert(long alertBytes)1141     public void setGlobalAlert(long alertBytes) {
1142         NetworkStack.checkNetworkStackPermission(mContext);
1143 
1144         try {
1145             mNetdService.bandwidthSetGlobalAlert(alertBytes);
1146         } catch (RemoteException | ServiceSpecificException e) {
1147             throw new IllegalStateException(e);
1148         }
1149     }
1150 
setUidOnMeteredNetworkList(int uid, boolean allowlist, boolean enable)1151     private void setUidOnMeteredNetworkList(int uid, boolean allowlist, boolean enable) {
1152         NetworkStack.checkNetworkStackPermission(mContext);
1153 
1154         synchronized (mQuotaLock) {
1155             boolean oldEnable;
1156             SparseBooleanArray quotaList;
1157             synchronized (mRulesLock) {
1158                 quotaList = allowlist ?  mUidAllowOnMetered : mUidRejectOnMetered;
1159                 oldEnable = quotaList.get(uid, false);
1160             }
1161             if (oldEnable == enable) {
1162                 // TODO: eventually consider throwing
1163                 return;
1164             }
1165 
1166             Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "inetd bandwidth");
1167             final ConnectivityManager cm = mContext.getSystemService(ConnectivityManager.class);
1168             try {
1169                 if (allowlist) {
1170                     if (enable) {
1171                         cm.addUidToMeteredNetworkAllowList(uid);
1172                     } else {
1173                         cm.removeUidFromMeteredNetworkAllowList(uid);
1174                     }
1175                 } else {
1176                     if (enable) {
1177                         cm.addUidToMeteredNetworkDenyList(uid);
1178                     } else {
1179                         cm.removeUidFromMeteredNetworkDenyList(uid);
1180                     }
1181                 }
1182                 synchronized (mRulesLock) {
1183                     if (enable) {
1184                         quotaList.put(uid, true);
1185                     } else {
1186                         quotaList.delete(uid);
1187                     }
1188                 }
1189             } catch (RuntimeException e) {
1190                 throw new IllegalStateException(e);
1191             } finally {
1192                 Trace.traceEnd(Trace.TRACE_TAG_NETWORK);
1193             }
1194         }
1195     }
1196 
1197     @Override
setUidOnMeteredNetworkDenylist(int uid, boolean enable)1198     public void setUidOnMeteredNetworkDenylist(int uid, boolean enable) {
1199         setUidOnMeteredNetworkList(uid, false, enable);
1200     }
1201 
1202     @Override
setUidOnMeteredNetworkAllowlist(int uid, boolean enable)1203     public void setUidOnMeteredNetworkAllowlist(int uid, boolean enable) {
1204         setUidOnMeteredNetworkList(uid, true, enable);
1205     }
1206 
1207     @android.annotation.EnforcePermission(android.Manifest.permission.NETWORK_SETTINGS)
1208     @Override
setDataSaverModeEnabled(boolean enable)1209     public boolean setDataSaverModeEnabled(boolean enable) {
1210 
1211         super.setDataSaverModeEnabled_enforcePermission();
1212 
1213         if (DBG) Log.d(TAG, "setDataSaverMode: " + enable);
1214         synchronized (mQuotaLock) {
1215             if (mDataSaverMode == enable) {
1216                 Log.w(TAG, "setDataSaverMode(): already " + mDataSaverMode);
1217                 return true;
1218             }
1219             Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "bandwidthEnableDataSaver");
1220             try {
1221                 final boolean changed = mNetdService.bandwidthEnableDataSaver(enable);
1222                 if (changed) {
1223                     mDataSaverMode = enable;
1224                 } else {
1225                     Log.w(TAG, "setDataSaverMode(" + enable + "): netd command silently failed");
1226                 }
1227                 return changed;
1228             } catch (RemoteException e) {
1229                 Log.w(TAG, "setDataSaverMode(" + enable + "): netd command failed", e);
1230                 return false;
1231             } finally {
1232                 Trace.traceEnd(Trace.TRACE_TAG_NETWORK);
1233             }
1234         }
1235     }
1236 
applyUidCleartextNetworkPolicy(int uid, int policy)1237     private void applyUidCleartextNetworkPolicy(int uid, int policy) {
1238         final int policyValue;
1239         switch (policy) {
1240             case StrictMode.NETWORK_POLICY_ACCEPT:
1241                 policyValue = INetd.PENALTY_POLICY_ACCEPT;
1242                 break;
1243             case StrictMode.NETWORK_POLICY_LOG:
1244                 policyValue = INetd.PENALTY_POLICY_LOG;
1245                 break;
1246             case StrictMode.NETWORK_POLICY_REJECT:
1247                 policyValue = INetd.PENALTY_POLICY_REJECT;
1248                 break;
1249             default:
1250                 throw new IllegalArgumentException("Unknown policy " + policy);
1251         }
1252 
1253         try {
1254             mNetdService.strictUidCleartextPenalty(uid, policyValue);
1255             mUidCleartextPolicy.put(uid, policy);
1256         } catch (RemoteException | ServiceSpecificException e) {
1257             throw new IllegalStateException(e);
1258         }
1259     }
1260 
1261     @Override
setUidCleartextNetworkPolicy(int uid, int policy)1262     public void setUidCleartextNetworkPolicy(int uid, int policy) {
1263         if (mDeps.getCallingUid() != uid) {
1264             NetworkStack.checkNetworkStackPermission(mContext);
1265         }
1266 
1267         synchronized (mQuotaLock) {
1268             final int oldPolicy = mUidCleartextPolicy.get(uid, StrictMode.NETWORK_POLICY_ACCEPT);
1269             if (oldPolicy == policy) {
1270                 // This also ensures we won't needlessly apply an ACCEPT policy if we've just
1271                 // enabled strict and the underlying iptables rules are empty.
1272                 return;
1273             }
1274 
1275             // TODO: remove this code after removing prepareNativeDaemon()
1276             if (!mStrictEnabled) {
1277                 // Module isn't enabled yet; stash the requested policy away to
1278                 // apply later once the daemon is connected.
1279                 mUidCleartextPolicy.put(uid, policy);
1280                 return;
1281             }
1282 
1283             // netd does not keep state on strict mode policies, and cannot replace a non-accept
1284             // policy without deleting it first. Rather than add state to netd, just always send
1285             // it an accept policy when switching between two non-accept policies.
1286             // TODO: consider keeping state in netd so we can simplify this code.
1287             if (oldPolicy != StrictMode.NETWORK_POLICY_ACCEPT &&
1288                     policy != StrictMode.NETWORK_POLICY_ACCEPT) {
1289                 applyUidCleartextNetworkPolicy(uid, StrictMode.NETWORK_POLICY_ACCEPT);
1290             }
1291 
1292             applyUidCleartextNetworkPolicy(uid, policy);
1293         }
1294     }
1295 
1296     @Override
isBandwidthControlEnabled()1297     public boolean isBandwidthControlEnabled() {
1298         return true;
1299     }
1300 
1301     private class NetdTetheringStatsProvider extends ITetheringStatsProvider.Stub {
1302         @Override
getTetherStats(int how)1303         public NetworkStats getTetherStats(int how) {
1304             // Remove the implementation of NetdTetheringStatsProvider#getTetherStats
1305             // since all callers are migrated to use INetd#tetherGetStats directly.
1306             throw new UnsupportedOperationException();
1307         }
1308 
1309         @Override
setInterfaceQuota(String iface, long quotaBytes)1310         public void setInterfaceQuota(String iface, long quotaBytes) {
1311             // Do nothing. netd is already informed of quota changes in setInterfaceQuota.
1312         }
1313     }
1314 
1315     @Override
getNetworkStatsTethering(int how)1316     public NetworkStats getNetworkStatsTethering(int how) {
1317         // Remove the implementation of getNetworkStatsTethering since all callers are migrated
1318         // to use INetd#tetherGetStats directly.
1319         throw new UnsupportedOperationException();
1320     }
1321 
1322     @Override
setFirewallEnabled(boolean enabled)1323     public void setFirewallEnabled(boolean enabled) {
1324         enforceSystemUid();
1325         try {
1326             mNetdService.firewallSetFirewallType(
1327                     enabled ? INetd.FIREWALL_ALLOWLIST : INetd.FIREWALL_DENYLIST);
1328             mFirewallEnabled = enabled;
1329         } catch (RemoteException | ServiceSpecificException e) {
1330             throw new IllegalStateException(e);
1331         }
1332     }
1333 
1334     @Override
isFirewallEnabled()1335     public boolean isFirewallEnabled() {
1336         enforceSystemUid();
1337         return mFirewallEnabled;
1338     }
1339 
1340     @Override
setFirewallInterfaceRule(String iface, boolean allow)1341     public void setFirewallInterfaceRule(String iface, boolean allow) {
1342         enforceSystemUid();
1343         Preconditions.checkState(mFirewallEnabled);
1344         try {
1345             mNetdService.firewallSetInterfaceRule(iface,
1346                     allow ? INetd.FIREWALL_RULE_ALLOW : INetd.FIREWALL_RULE_DENY);
1347         } catch (RemoteException | ServiceSpecificException e) {
1348             throw new IllegalStateException(e);
1349         }
1350     }
1351 
1352     @Override
setFirewallChainEnabled(int chain, boolean enable)1353     public void setFirewallChainEnabled(int chain, boolean enable) {
1354         enforceSystemUid();
1355         synchronized (mQuotaLock) {
1356             synchronized (mRulesLock) {
1357                 if (getFirewallChainState(chain) == enable) {
1358                     // All is the same, nothing to do.  This relies on the fact that netd has child
1359                     // chains default detached.
1360                     return;
1361                 }
1362                 setFirewallChainState(chain, enable);
1363             }
1364 
1365             final String chainName = getFirewallChainName(chain);
1366             if (chain == FIREWALL_CHAIN_NONE) {
1367                 throw new IllegalArgumentException("Bad child chain: " + chainName);
1368             }
1369 
1370             final ConnectivityManager cm = mContext.getSystemService(ConnectivityManager.class);
1371             try {
1372                 cm.setFirewallChainEnabled(chain, enable);
1373             } catch (RuntimeException e) {
1374                 throw new IllegalStateException(e);
1375             }
1376         }
1377     }
1378 
getFirewallChainName(int chain)1379     private String getFirewallChainName(int chain) {
1380         switch (chain) {
1381             case FIREWALL_CHAIN_STANDBY:
1382                 return FIREWALL_CHAIN_NAME_STANDBY;
1383             case FIREWALL_CHAIN_DOZABLE:
1384                 return FIREWALL_CHAIN_NAME_DOZABLE;
1385             case FIREWALL_CHAIN_POWERSAVE:
1386                 return FIREWALL_CHAIN_NAME_POWERSAVE;
1387             case FIREWALL_CHAIN_RESTRICTED:
1388                 return FIREWALL_CHAIN_NAME_RESTRICTED;
1389             case FIREWALL_CHAIN_LOW_POWER_STANDBY:
1390                 return FIREWALL_CHAIN_NAME_LOW_POWER_STANDBY;
1391             default:
1392                 throw new IllegalArgumentException("Bad child chain: " + chain);
1393         }
1394     }
1395 
getFirewallType(int chain)1396     private int getFirewallType(int chain) {
1397         switch (chain) {
1398             case FIREWALL_CHAIN_STANDBY:
1399                 return FIREWALL_DENYLIST;
1400             case FIREWALL_CHAIN_DOZABLE:
1401                 return FIREWALL_ALLOWLIST;
1402             case FIREWALL_CHAIN_POWERSAVE:
1403                 return FIREWALL_ALLOWLIST;
1404             case FIREWALL_CHAIN_RESTRICTED:
1405                 return FIREWALL_ALLOWLIST;
1406             case FIREWALL_CHAIN_LOW_POWER_STANDBY:
1407                 return FIREWALL_ALLOWLIST;
1408             default:
1409                 return isFirewallEnabled() ? FIREWALL_ALLOWLIST : FIREWALL_DENYLIST;
1410         }
1411     }
1412 
1413     @Override
setFirewallUidRules(int chain, int[] uids, int[] rules)1414     public void setFirewallUidRules(int chain, int[] uids, int[] rules) {
1415         enforceSystemUid();
1416         synchronized (mQuotaLock) {
1417             synchronized (mRulesLock) {
1418                 SparseIntArray uidFirewallRules = getUidFirewallRulesLR(chain);
1419                 SparseIntArray newRules = new SparseIntArray();
1420                 // apply new set of rules
1421                 for (int index = uids.length - 1; index >= 0; --index) {
1422                     int uid = uids[index];
1423                     int rule = rules[index];
1424                     updateFirewallUidRuleLocked(chain, uid, rule);
1425                     newRules.put(uid, rule);
1426                 }
1427                 // collect the rules to remove.
1428                 SparseIntArray rulesToRemove = new SparseIntArray();
1429                 for (int index = uidFirewallRules.size() - 1; index >= 0; --index) {
1430                     int uid = uidFirewallRules.keyAt(index);
1431                     if (newRules.indexOfKey(uid) < 0) {
1432                         rulesToRemove.put(uid, FIREWALL_RULE_DEFAULT);
1433                     }
1434                 }
1435                 // remove dead rules
1436                 for (int index = rulesToRemove.size() - 1; index >= 0; --index) {
1437                     int uid = rulesToRemove.keyAt(index);
1438                     updateFirewallUidRuleLocked(chain, uid, FIREWALL_RULE_DEFAULT);
1439                 }
1440             }
1441             final ConnectivityManager cm = mContext.getSystemService(ConnectivityManager.class);
1442             try {
1443                 cm.replaceFirewallChain(chain, uids);
1444             } catch (RuntimeException e) {
1445                 Slog.w(TAG, "Error flushing firewall chain " + chain, e);
1446             }
1447         }
1448     }
1449 
1450     @Override
setFirewallUidRule(int chain, int uid, int rule)1451     public void setFirewallUidRule(int chain, int uid, int rule) {
1452         enforceSystemUid();
1453         synchronized (mQuotaLock) {
1454             setFirewallUidRuleLocked(chain, uid, rule);
1455         }
1456     }
1457 
setFirewallUidRuleLocked(int chain, int uid, int rule)1458     private void setFirewallUidRuleLocked(int chain, int uid, int rule) {
1459         if (updateFirewallUidRuleLocked(chain, uid, rule)) {
1460             final ConnectivityManager cm = mContext.getSystemService(ConnectivityManager.class);
1461             try {
1462                 cm.setUidFirewallRule(chain, uid, rule);
1463             } catch (RuntimeException e) {
1464                 throw new IllegalStateException(e);
1465             }
1466         }
1467     }
1468 
1469     // TODO: now that netd supports batching, NMS should not keep these data structures anymore...
updateFirewallUidRuleLocked(int chain, int uid, int rule)1470     private boolean updateFirewallUidRuleLocked(int chain, int uid, int rule) {
1471         synchronized (mRulesLock) {
1472             SparseIntArray uidFirewallRules = getUidFirewallRulesLR(chain);
1473 
1474             final int oldUidFirewallRule = uidFirewallRules.get(uid, FIREWALL_RULE_DEFAULT);
1475             if (DBG) {
1476                 Slog.d(TAG, "oldRule = " + oldUidFirewallRule
1477                         + ", newRule=" + rule + " for uid=" + uid + " on chain " + chain);
1478             }
1479             if (oldUidFirewallRule == rule) {
1480                 if (DBG) Slog.d(TAG, "!!!!! Skipping change");
1481                 // TODO: eventually consider throwing
1482                 return false;
1483             }
1484 
1485             String ruleName = getFirewallRuleName(chain, rule);
1486             String oldRuleName = getFirewallRuleName(chain, oldUidFirewallRule);
1487 
1488             if (rule == NetworkPolicyManager.FIREWALL_RULE_DEFAULT) {
1489                 uidFirewallRules.delete(uid);
1490             } else {
1491                 uidFirewallRules.put(uid, rule);
1492             }
1493             return !ruleName.equals(oldRuleName);
1494         }
1495     }
1496 
getFirewallRuleName(int chain, int rule)1497     private @NonNull String getFirewallRuleName(int chain, int rule) {
1498         String ruleName;
1499         if (getFirewallType(chain) == FIREWALL_ALLOWLIST) {
1500             if (rule == FIREWALL_RULE_ALLOW) {
1501                 ruleName = "allow";
1502             } else {
1503                 ruleName = "deny";
1504             }
1505         } else { // Deny mode
1506             if (rule == FIREWALL_RULE_DENY) {
1507                 ruleName = "deny";
1508             } else {
1509                 ruleName = "allow";
1510             }
1511         }
1512         return ruleName;
1513     }
1514 
1515     @GuardedBy("mRulesLock")
getUidFirewallRulesLR(int chain)1516     private @NonNull SparseIntArray getUidFirewallRulesLR(int chain) {
1517         switch (chain) {
1518             case FIREWALL_CHAIN_STANDBY:
1519                 return mUidFirewallStandbyRules;
1520             case FIREWALL_CHAIN_DOZABLE:
1521                 return mUidFirewallDozableRules;
1522             case FIREWALL_CHAIN_POWERSAVE:
1523                 return mUidFirewallPowerSaveRules;
1524             case FIREWALL_CHAIN_RESTRICTED:
1525                 return mUidFirewallRestrictedRules;
1526             case FIREWALL_CHAIN_LOW_POWER_STANDBY:
1527                 return mUidFirewallLowPowerStandbyRules;
1528             case FIREWALL_CHAIN_NONE:
1529                 return mUidFirewallRules;
1530             default:
1531                 throw new IllegalArgumentException("Unknown chain:" + chain);
1532         }
1533     }
1534 
enforceSystemUid()1535     private void enforceSystemUid() {
1536         final int uid = mDeps.getCallingUid();
1537         if (uid != Process.SYSTEM_UID) {
1538             throw new SecurityException("Only available to AID_SYSTEM");
1539         }
1540     }
1541 
1542     @Override
dump(FileDescriptor fd, PrintWriter pw, String[] args)1543     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1544         if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
1545 
1546         synchronized (mQuotaLock) {
1547             pw.print("Active quota ifaces: "); pw.println(mActiveQuotas.toString());
1548             pw.print("Active alert ifaces: "); pw.println(mActiveAlerts.toString());
1549             pw.print("Data saver mode: "); pw.println(mDataSaverMode);
1550             synchronized (mRulesLock) {
1551                 dumpUidRuleOnQuotaLocked(pw, "denied UIDs", mUidRejectOnMetered);
1552                 dumpUidRuleOnQuotaLocked(pw, "allowed UIDs", mUidAllowOnMetered);
1553             }
1554         }
1555 
1556         synchronized (mRulesLock) {
1557             dumpUidFirewallRule(pw, "", mUidFirewallRules);
1558 
1559             pw.print("UID firewall standby chain enabled: ");
1560             pw.println(getFirewallChainState(FIREWALL_CHAIN_STANDBY));
1561             dumpUidFirewallRule(pw, FIREWALL_CHAIN_NAME_STANDBY, mUidFirewallStandbyRules);
1562 
1563             pw.print("UID firewall dozable chain enabled: ");
1564             pw.println(getFirewallChainState(FIREWALL_CHAIN_DOZABLE));
1565             dumpUidFirewallRule(pw, FIREWALL_CHAIN_NAME_DOZABLE, mUidFirewallDozableRules);
1566 
1567             pw.print("UID firewall powersave chain enabled: ");
1568             pw.println(getFirewallChainState(FIREWALL_CHAIN_POWERSAVE));
1569             dumpUidFirewallRule(pw, FIREWALL_CHAIN_NAME_POWERSAVE, mUidFirewallPowerSaveRules);
1570 
1571             pw.print("UID firewall restricted mode chain enabled: ");
1572             pw.println(getFirewallChainState(FIREWALL_CHAIN_RESTRICTED));
1573             dumpUidFirewallRule(pw, FIREWALL_CHAIN_NAME_RESTRICTED,
1574                     mUidFirewallRestrictedRules);
1575 
1576             pw.print("UID firewall low power standby chain enabled: ");
1577             pw.println(getFirewallChainState(FIREWALL_CHAIN_LOW_POWER_STANDBY));
1578             dumpUidFirewallRule(pw, FIREWALL_CHAIN_NAME_LOW_POWER_STANDBY,
1579                     mUidFirewallLowPowerStandbyRules);
1580         }
1581 
1582         pw.print("Firewall enabled: "); pw.println(mFirewallEnabled);
1583         pw.print("Netd service status: " );
1584         if (mNetdService == null) {
1585             pw.println("disconnected");
1586         } else {
1587             try {
1588                 final boolean alive = mNetdService.isAlive();
1589                 pw.println(alive ? "alive": "dead");
1590             } catch (RemoteException e) {
1591                 pw.println("unreachable");
1592             }
1593         }
1594     }
1595 
dumpUidRuleOnQuotaLocked(PrintWriter pw, String name, SparseBooleanArray list)1596     private void dumpUidRuleOnQuotaLocked(PrintWriter pw, String name, SparseBooleanArray list) {
1597         pw.print("UID bandwith control ");
1598         pw.print(name);
1599         pw.print(": [");
1600         final int size = list.size();
1601         for (int i = 0; i < size; i++) {
1602             pw.print(list.keyAt(i));
1603             if (i < size - 1) pw.print(",");
1604         }
1605         pw.println("]");
1606     }
1607 
dumpUidFirewallRule(PrintWriter pw, String name, SparseIntArray rules)1608     private void dumpUidFirewallRule(PrintWriter pw, String name, SparseIntArray rules) {
1609         pw.print("UID firewall ");
1610         pw.print(name);
1611         pw.print(" rule: [");
1612         final int size = rules.size();
1613         for (int i = 0; i < size; i++) {
1614             pw.print(rules.keyAt(i));
1615             pw.print(":");
1616             pw.print(rules.valueAt(i));
1617             if (i < size - 1) pw.print(",");
1618         }
1619         pw.println("]");
1620     }
1621 
modifyInterfaceInNetwork(boolean add, int netId, String iface)1622     private void modifyInterfaceInNetwork(boolean add, int netId, String iface) {
1623         NetworkStack.checkNetworkStackPermission(mContext);
1624         try {
1625             if (add) {
1626                 mNetdService.networkAddInterface(netId, iface);
1627             } else {
1628                 mNetdService.networkRemoveInterface(netId, iface);
1629             }
1630         } catch (RemoteException | ServiceSpecificException e) {
1631             throw new IllegalStateException(e);
1632         }
1633     }
1634 
1635     @Override
allowProtect(int uid)1636     public void allowProtect(int uid) {
1637         NetworkStack.checkNetworkStackPermission(mContext);
1638 
1639         try {
1640             mNetdService.networkSetProtectAllow(uid);
1641         } catch (RemoteException | ServiceSpecificException e) {
1642             throw new IllegalStateException(e);
1643         }
1644     }
1645 
1646     @Override
denyProtect(int uid)1647     public void denyProtect(int uid) {
1648         NetworkStack.checkNetworkStackPermission(mContext);
1649 
1650         try {
1651             mNetdService.networkSetProtectDeny(uid);
1652         } catch (RemoteException | ServiceSpecificException e) {
1653             throw new IllegalStateException(e);
1654         }
1655     }
1656 
1657     @Override
addInterfaceToLocalNetwork(String iface, List<RouteInfo> routes)1658     public void addInterfaceToLocalNetwork(String iface, List<RouteInfo> routes) {
1659         modifyInterfaceInNetwork(MODIFY_OPERATION_ADD, INetd.LOCAL_NET_ID, iface);
1660         // modifyInterfaceInNetwork already check calling permission.
1661         NetdUtils.addRoutesToLocalNetwork(mNetdService, iface, routes);
1662     }
1663 
1664     @Override
removeInterfaceFromLocalNetwork(String iface)1665     public void removeInterfaceFromLocalNetwork(String iface) {
1666         modifyInterfaceInNetwork(MODIFY_OPERATION_REMOVE, INetd.LOCAL_NET_ID, iface);
1667     }
1668 
1669     @Override
removeRoutesFromLocalNetwork(List<RouteInfo> routes)1670     public int removeRoutesFromLocalNetwork(List<RouteInfo> routes) {
1671         NetworkStack.checkNetworkStackPermission(mContext);
1672         return NetdUtils.removeRoutesFromLocalNetwork(mNetdService, routes);
1673     }
1674 
1675     @android.annotation.EnforcePermission(android.Manifest.permission.OBSERVE_NETWORK_POLICY)
1676     @Override
isNetworkRestricted(int uid)1677     public boolean isNetworkRestricted(int uid) {
1678         super.isNetworkRestricted_enforcePermission();
1679 
1680         return isNetworkRestrictedInternal(uid);
1681     }
1682 
isNetworkRestrictedInternal(int uid)1683     private boolean isNetworkRestrictedInternal(int uid) {
1684         synchronized (mRulesLock) {
1685             if (getFirewallChainState(FIREWALL_CHAIN_STANDBY)
1686                     && mUidFirewallStandbyRules.get(uid) == FIREWALL_RULE_DENY) {
1687                 if (DBG) Slog.d(TAG, "Uid " + uid + " restricted because of app standby mode");
1688                 return true;
1689             }
1690             if (getFirewallChainState(FIREWALL_CHAIN_DOZABLE)
1691                     && mUidFirewallDozableRules.get(uid) != FIREWALL_RULE_ALLOW) {
1692                 if (DBG) Slog.d(TAG, "Uid " + uid + " restricted because of device idle mode");
1693                 return true;
1694             }
1695             if (getFirewallChainState(FIREWALL_CHAIN_POWERSAVE)
1696                     && mUidFirewallPowerSaveRules.get(uid) != FIREWALL_RULE_ALLOW) {
1697                 if (DBG) Slog.d(TAG, "Uid " + uid + " restricted because of power saver mode");
1698                 return true;
1699             }
1700             if (getFirewallChainState(FIREWALL_CHAIN_RESTRICTED)
1701                     && mUidFirewallRestrictedRules.get(uid) != FIREWALL_RULE_ALLOW) {
1702                 if (DBG) Slog.d(TAG, "Uid " + uid + " restricted because of restricted mode");
1703                 return true;
1704             }
1705             if (getFirewallChainState(FIREWALL_CHAIN_LOW_POWER_STANDBY)
1706                     && mUidFirewallLowPowerStandbyRules.get(uid) != FIREWALL_RULE_ALLOW) {
1707                 if (DBG) Slog.d(TAG, "Uid " + uid + " restricted because of low power standby");
1708                 return true;
1709             }
1710             if (mUidRejectOnMetered.get(uid)) {
1711                 if (DBG) Slog.d(TAG, "Uid " + uid + " restricted because of no metered data"
1712                         + " in the background");
1713                 return true;
1714             }
1715             if (mDataSaverMode && !mUidAllowOnMetered.get(uid)) {
1716                 if (DBG) Slog.d(TAG, "Uid " + uid + " restricted because of data saver mode");
1717                 return true;
1718             }
1719             return false;
1720         }
1721     }
1722 
setFirewallChainState(int chain, boolean state)1723     private void setFirewallChainState(int chain, boolean state) {
1724         synchronized (mRulesLock) {
1725             mFirewallChainStates.put(chain, state);
1726         }
1727     }
1728 
getFirewallChainState(int chain)1729     private boolean getFirewallChainState(int chain) {
1730         synchronized (mRulesLock) {
1731             return mFirewallChainStates.get(chain);
1732         }
1733     }
1734 
1735     private class LocalService extends NetworkManagementInternal {
1736         @Override
isNetworkRestrictedForUid(int uid)1737         public boolean isNetworkRestrictedForUid(int uid) {
1738             return isNetworkRestrictedInternal(uid);
1739         }
1740     }
1741 }
1742