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