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