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